vibespot 1.6.5 → 1.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +24 -3
- package/assets/whats-new.json +27 -0
- package/dist/index.js +579 -681
- package/dist/index.js.map +1 -1
- package/package.json +8 -5
- package/ui/chat.js +671 -9
- package/ui/dashboard.js +53 -12
- package/ui/docs/index.html +57 -2
- package/ui/email-preview.js +1 -5
- package/ui/escape-html.js +14 -0
- package/ui/field-editor.js +6 -12
- package/ui/field-save.js +82 -0
- package/ui/index.html +10 -4
- package/ui/inline-edit.js +116 -570
- package/ui/plan.js +22 -13
- package/ui/preview-agent.js +1050 -0
- package/ui/preview.js +248 -265
- package/ui/section-controls.js +16 -622
- package/ui/setup.js +73 -20
- package/ui/styles.css +424 -0
- package/ui/upload-panel.js +7 -8
- package/ui/whats-new.js +249 -0
- package/assets/readme/00-hero-banner.png +0 -0
- package/assets/readme/00-hero-banner.svg +0 -59
- package/assets/readme/01-vibe-coding-hero.png +0 -0
- package/assets/readme/02-plan-mode.png +0 -0
- package/assets/readme/03-figma-import.png +0 -0
- package/assets/readme/04-multi-page-sites.png +0 -0
- package/assets/readme/05-inline-wysiwyg.png +0 -0
- package/assets/readme/06-hubspot-upload.png +0 -0
- package/ui/docs/screenshots/brand-kit-preview.png +0 -0
- package/ui/docs/screenshots/content-type-dropdown.png +0 -0
- package/ui/docs/screenshots/editor-full-layout.png +0 -0
- package/ui/docs/screenshots/inline-wysiwyg-editing.png +0 -0
- package/ui/docs/screenshots/module-overview-slideout.png +0 -0
- package/ui/docs/screenshots/multi-page-tree.png +0 -0
- package/ui/docs/screenshots/onboarding-walkthrough.png +0 -0
- package/ui/docs/screenshots/split-pane-view.png +0 -0
- package/ui/docs/screenshots/visual-controls-toolbar.png +0 -0
- package/ui/docs/screenshots/workspace-tabs.png +0 -0
package/dist/index.js
CHANGED
|
@@ -1,12 +1,5 @@
|
|
|
1
|
-
var dg=Object.defineProperty;var N=(e,t)=>()=>(e&&(t=e(e=0)),t);var Ge=(e,t)=>{for(var n in t)dg(e,n,{get:t[n],enumerable:!0})};import Av from"path";import{fileURLToPath as $v}from"url";var y=N(()=>{"use strict"});import fn from"chalk";function At(e){return Ha?fn:fn.hex(e)}var pt,Ha,I,gt=N(()=>{"use strict";y();pt={accent:"#FF7A59",accentBright:"#FF9A7A",success:"#00BDA5",info:"#0066FF",warn:"#FFB020",error:"#E23D2D",muted:"#8B8D91",vibes:"#00BDD6"},Ha=!!process.env.NO_COLOR;I={accent:At(pt.accent),accentBright:At(pt.accentBright),success:At(pt.success),info:At(pt.info),warn:At(pt.warn),error:At(pt.error),muted:At(pt.muted),vibes:At(pt.vibes),heading:Ha?fn.bold:fn.bold.hex(pt.accent),command:At(pt.accentBright),dim:fn.dim,bold:fn.bold}});import{readFileSync as Pi,writeFileSync as ug,mkdirSync as Ua,existsSync as Vs}from"fs";import{dirname as Ga,join as _t}from"path";import{fileURLToPath as mg}from"url";function P(e){return Pi(e,"utf-8")}function B(e,t){Ua(Ga(e),{recursive:!0}),ug(e,t,"utf-8")}function x(e){return Vs(e)}function Re(e){Ua(e,{recursive:!0})}function bn(e){let t=[_t(yn,"../../assets",e),_t(yn,"../assets",e),_t(process.cwd(),"assets",e)];for(let n of t)if(Vs(n))return n;throw new Error(`Asset not found: ${e}`)}function Sn(){if(hn)return hn;let e=[_t(yn,"../../package.json"),_t(yn,"../package.json"),_t(process.cwd(),"package.json")];for(let t of e)if(Vs(t))try{let n=JSON.parse(Pi(t,"utf-8"));if(n.name==="vibespot"&&n.version)return hn=n.version,hn}catch{}return hn="dev",hn}function Wa(){if(Ks)return Ks;let e=[_t(yn,"../../CHANGELOG.md"),_t(yn,"../CHANGELOG.md"),_t(process.cwd(),"CHANGELOG.md")];for(let t of e)if(Vs(t))try{return Ks=Pi(t,"utf-8"),Ks}catch{}return""}var yn,hn,Ks,oe=N(()=>{"use strict";y();yn=Ga(mg(import.meta.url));hn="";Ks=""});import{execSync as Ka,execFileSync as pg}from"child_process";function ie(e,t={}){try{return{stdout:Ka(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 Z(e,t={}){try{return{stdout:pg("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 Va(e,t={}){try{return Ka(e,{stdio:"inherit",timeout:3e5,...t}),!0}catch{return!1}}var Qt=N(()=>{"use strict";y()});var qa={};Ge(qa,{addHubSpotAccount:()=>Xn,getActiveHubSpotAccount:()=>Ht,getApiKeyForEngine:()=>Fe,getConfigDir:()=>hg,getHubSpotPak:()=>Le,isCliToolEnabled:()=>st,loadConfig:()=>R,maskApiKey:()=>Ys,removeHubSpotAccount:()=>Ni,saveConfig:()=>Y,setActiveHubSpotAccount:()=>Ri,setCliToolEnabled:()=>Oi});import{join as za}from"path";import{homedir as gg}from"os";import{chmodSync as fg}from"fs";function R(){let e={};if(x(zs))try{e=JSON.parse(P(zs)),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 Ys(e){return e.length<=12?"***":e.slice(0,7)+"..."+e.slice(-4)}function Y(e){let n={...R(),...e};if(B(zs,JSON.stringify(n,null,2)),process.platform!=="win32")try{fg(zs,384)}catch{}}function hg(){return Ya}function Ht(){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 Xn(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 Ni(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 Ri(e){Y({activeHubSpotAccount:e})}function Le(){return Ht()?.personalAccessKey||process.env.HUBSPOT_PERSONAL_ACCESS_KEY||null}function st(e){return R().enabledCLITools?.includes(e)??!1}function Oi(e,t){let n=R(),s=new Set(n.enabledCLITools||[]);t?s.add(e):s.delete(e),Y({enabledCLITools:[...s]})}var Ya,zs,ee=N(()=>{"use strict";y();oe();Ya=za(gg(),".vibespot"),zs=za(Ya,"config.json")});var ji={};Ge(ji,{OAUTH_EXTRA_HEADERS:()=>Zn,OAUTH_SYSTEM_PREFIX:()=>xn,clearOAuthTokens:()=>Zs,getOAuthTokenInfo:()=>en,getValidAccessToken:()=>Di,hasValidOAuthToken:()=>Ze,saveInitialToken:()=>Fi});import{join as yg}from"path";import{homedir as bg}from"os";import{chmodSync as Sg,unlinkSync as vg}from"fs";function Xs(){if(!x(vn))return null;try{return JSON.parse(P(vn))}catch{return null}}function Xa(e){if(B(vn,JSON.stringify(e,null,2)),process.platform!=="win32")try{Sg(vn,384)}catch{}}async function kg(e){let t=await fetch(wg,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({grant_type:"refresh_token",refresh_token:e,client_id:xg})});if(!t.ok)throw Zs(),new Error("Claude OAuth session expired. Please re-authenticate in Settings.");let n=await t.json();Xa({access_token:n.access_token,refresh_token:n.refresh_token||e,expires_at:Date.now()+(n.expires_in||28800)*1e3})}function Fi(e,t=""){Xa({access_token:e,refresh_token:t,expires_at:Date.now()+28800*1e3})}function Ze(){let e=Xs();return e?e.expires_at>Date.now():!1}async function Di(){let e=Xs();if(!e)return null;if(e.expires_at-Date.now()>Cg)return e.access_token;if(e.refresh_token){qs||(qs=kg(e.refresh_token).finally(()=>{qs=null}));try{await qs}catch{return null}return Xs()?.access_token??null}return e.access_token}function en(){let e=Xs();return e?{expiresAt:new Date(e.expires_at).toISOString()}:null}function Zs(){if(x(vn))try{vg(vn)}catch{}}var xg,wg,vn,Cg,Zn,xn,qs,$t=N(()=>{"use strict";y();oe();xg="9d1c250a-e61b-44d9-88ed-5944d1962f5e",wg="https://console.anthropic.com/v1/oauth/token",vn=yg(bg(),".vibespot","claude-oauth.json"),Cg=300*1e3,Zn={"user-agent":"claude-cli/2.1.75","x-app":"cli","anthropic-beta":"oauth-2025-04-20"},xn="You are Claude Code, Anthropic's official CLI for Claude.";qs=null});import{join as Qs}from"path";import{homedir as eo}from"os";import{readFileSync as Za,existsSync as to,readdirSync as Tg}from"fs";function Qn(){let e=ie("node --version");return{name:"Node.js",found:e.success,version:e.stdout.replace(/^v/,""),path:ie(`${tn} node`).stdout}}function es(){let e=ie("git --version");return{name:"Git",found:e.success,version:e.stdout.replace("git version ",""),path:ie(`${tn} git`).stdout}}function ft(){let e=ie("hs --version");return{name:"HubSpot CLI",found:e.success,version:e.stdout,path:ie(`${tn} hs`).stdout}}function kn(){let e=ie("claude --version");if(!e.success)return{name:"Claude Code",found:!1,version:"",path:"",authenticated:!1,authDetail:"Not installed"};let t=Qs(eo(),".claude"),n=!1,s="Not signed in \u2014 run `claude` to authenticate";try{if(to(t)){let o=Tg(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(`${tn} claude`).stdout,authenticated:n,authDetail:s}}function ts(e){try{let t=Qs(eo(),".hscli","config.yml");if(!to(t))return"na1";let n=Za(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:Qa});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
|
-
`)
|
|
3
|
-
`)[0]?.replace("gh version ","").split(" ")[0]||"",path:ie(`${tn} gh`).stdout}}function so(){let e=ie("gh auth status 2>&1",{timeout:Qa});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 el(){return!!process.env.ANTHROPIC_API_KEY}function oo(e){return parseInt(e.split(".")[0],10)>=18}function tl(e){let t=parseInt(e.split(".")[0],10);return!isNaN(t)&&t>=8}function Ag(){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=Ht();return{authenticated:!!o,portalName:o?.portalName||"",portalId:o?.portalId||"",dataCenter:o?o.dataCenter:"na1",accounts:s,uploadMode:t}}function wn(e,...t){if(e)return{configured:!0,masked:Ys(e),source:"config"};for(let n of t)if(process.env[n])return{configured:!0,masked:Ys(process.env[n]),source:"env"};return{configured:!1,masked:"",source:null}}function Li(e){return{anthropic:wn(e.anthropicApiKey,"ANTHROPIC_API_KEY"),openai:wn(e.openaiApiKey,"OPENAI_API_KEY"),gemini:wn(e.geminiApiKey,"GEMINI_API_KEY","GOOGLE_AI_API_KEY"),langdock:wn(e.langdockApiKey,"LANGDOCK_API_KEY"),langfusePublic:wn(e.langfusePublicKey,"LANGFUSE_PUBLIC_KEY"),langfuseSecret:wn(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 Bi(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?ts(s.portalId):"na1";return{...n,...s,dataCenter:o,uploadMode:"cli"}}return{name:"HubSpot API",found:!0,version:"v3",path:"",...Ag()}}function nl(){let e=R(),t=e.hubspotUploadMode||"api",n=Li(e),s={authenticated:Ze(),expiresAt:en()?.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:Bi(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 sl(){let e=R(),t=Li(e),n={authenticated:Ze(),expiresAt:en()?.expiresAt},s=st("claude-code")?kn():{...Cn,name:"Claude Code"},o=st("gemini-cli")?Tn():{...Cn,name:"Gemini CLI"},i=st("codex-cli")?An():{...Cn,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 ol(){let t=R().hubspotUploadMode||"api",n=no(),s=n.found?so():{authenticated:!1,username:""};return{github:{...n,...s},hubspot:Bi(t,!0)}}function io(){let e=R(),t=e.hubspotUploadMode||"api",n=Qn(),s=es(),o=Bi(t,!0),i=no(),r=i.found?so():{authenticated:!1,username:""},a={authenticated:Ze(),expiresAt:en()?.expiresAt},l=st("claude-code")?kn():{...Cn,name:"Claude Code"},c=st("gemini-cli")?Tn():{...Cn,name:"Gemini CLI"},d=st("codex-cli")?An():{...Cn,name:"OpenAI Codex CLI"},u=Li(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 tn,Qa,Cn,nn=N(()=>{"use strict";y();Qt();ee();$t();tn=process.platform==="win32"?"where":"which",Qa=4e3;Cn={name:"",found:!1,version:"",path:"",authenticated:!1,authDetail:"Disabled"}});import{readFileSync as _g}from"fs";import{basename as $g}from"path";async function rl(e){let t=il.get(e);if(t&&t.expiresAt-Date.now()>Ig)return t;let n=await fetch(`${Et}/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 il.set(e,o),o}async function _n(e){let{accessToken:t}=await rl(e);return{Authorization:`Bearer ${t}`}}function ro(e){return e.replace(/^\/+/,"").split("/").filter(Boolean).map(encodeURIComponent).join("/")}function Pg(e){return e.startsWith("pat-eu1-")?"eu1":e.startsWith("pat-na1-")?"na1":e.startsWith("CiRldTE")?"eu1":"na1"}function Ng(e){return new Promise(t=>setTimeout(t,e))}async function ns(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 ss(e,t,n=Eg){for(let s=0;s<=n;s++){let o=await fetch(e,t);if(o.status===429||o.status>=500&&s<n){let i=Mg*Math.pow(2,s);await Ng(i);continue}return o}return fetch(e,t)}async function ao(e){let t=await rl(e),n=`${Et}/account-info/v3/details`,s=await ss(n,{headers:await _n(e)});if(!s.ok){let a=await ns(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:Pg(e)}}async function al(e,t,n){let s=_g(n),o=$g(n),i=new FormData,r=new Blob([s]);i.append("file",r,o);let a=`${Et}/cms/v3/source-code/published/content/${ro(t)}`,l=await ss(a,{method:"PUT",headers:await _n(e),body:i});if(!l.ok){let c=await ns(l,t);return{success:!1,path:t,error:c}}return{success:!0,path:t}}async function Hi(e,t){let n=`${Et}/cms/v3/source-code/published/content/${ro(t)}`,s=await ss(n,{method:"DELETE",headers:await _n(e)});if(!s.ok&&s.status!==404){let o=await ns(s,t);throw new Error(`Failed to delete ${t}: ${o.message}`)}}async function ll(e,t){let n=`${Et}/cms/v3/source-code/published/content/${ro(t)}`,s=await ss(n,{method:"GET",headers:await _n(e)});if(!s.ok){let i=await ns(s,t);throw new Error(`Failed to download ${t}: ${i.message}`)}let o=await s.arrayBuffer();return Buffer.from(o)}async function lo(e,t){let n=`${Et}/cms/v3/source-code/published/metadata/${ro(t)}`,s=await ss(n,{method:"GET",headers:await _n(e)});if(s.status===404)return null;if(!s.ok){let o=await ns(s,t);throw new Error(`Failed to get metadata for ${t}: ${o.message}`)}return await s.json()}async function cl(e){let t=await _n(e),n=[`${Et}/cms/v3/source-code/published/metadata`,`${Et}/cms/v3/source-code/published/metadata/`,`${Et}/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 Et,Eg,Mg,Ig,il,sn=N(()=>{"use strict";y();Et="https://api.hubapi.com",Eg=3,Mg=1e3,Ig=300*1e3,il=new Map});import*as ae from"@clack/prompts";function Ui(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=e.validate,n=await ae.text({message:I.accent(e.message),placeholder:e.placeholder,defaultValue:e.defaultValue,validate:t?s=>t(s??""):void 0});return Ui(n),n}async function Me(e){let t=await ae.confirm({message:I.accent(e.message),initialValue:e.initialValue??!0});return Ui(t),t}async function Mt(e){let t=await ae.select({message:I.accent(e.message),options:e.options});return Ui(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 Gi,statSync as Rg}from"fs";import{join as he,basename as Wi,extname as Og}from"path";function dl(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 ul(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=Gi(s);for(let i of o){let r=he(s,i);if(!Rg(r).isFile())continue;let l=Og(i);if(![".tsx",".jsx"].includes(l))continue;let c=Wi(i,l);if(c.startsWith("ui")||c==="index")continue;let d=P(r),u=Fg(c,d);t.push({name:c,path:r,description:u})}}catch{}return t}function Fg(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 ml(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 pl(e){let t=[],n=he(e,"src/hooks");if(x(n))try{let o=Gi(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=Gi(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 gl(e){let t,n=!1;if(e.startsWith("http")||e.startsWith("git@")){if(!dl(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=Wi(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=ul(t),o=x(he(t,"tailwind.config.ts"))||x(he(t,"tailwind.config.js")),{varCount:i,fonts:r}=ml(t),a=pl(t);return{sourceDir:t,wasCloned:n,components:s,hasTailwind:o,cssVarCount:i,fonts:r,interactions:a}}async function uo(){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@")){dl(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=Wi(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=ul(t),i=x(he(t,"tailwind.config.ts"))||x(he(t,"tailwind.config.js")),{varCount:r,fonts:a}=ml(t),l=pl(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
|
-
|
|
6
|
-
CSS: ${d}
|
|
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 mo=N(()=>{"use strict";y();Qt();oe();Qe();gt()});var fl={};Ge(fl,{addEmailTemplateToTheme:()=>$n,createThemeScaffold:()=>is});import{mkdirSync as It,writeFileSync as os}from"fs";import{join as We}from"path";function is(e,t){It(e,{recursive:!0}),It(We(e,"templates"),{recursive:!0}),It(We(e,"modules"),{recursive:!0}),It(We(e,"css"),{recursive:!0}),It(We(e,"js"),{recursive:!0}),It(We(e,"images"),{recursive:!0}),It(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"}};os(We(e,"theme.json"),JSON.stringify(n,null,2)+`
|
|
9
|
-
`),os(We(e,"fields.json"),`[]
|
|
1
|
+
var Yf=Object.defineProperty;var j=(e,t)=>()=>(e&&(t=e(e=0)),t);var Ve=(e,t)=>{for(var n in t)Yf(e,n,{get:t[n],enumerable:!0})};import Ok from"path";import{fileURLToPath as Dk}from"url";var y=j(()=>{"use strict"});import{readFileSync as di,writeFileSync as Xf,mkdirSync as Il,existsSync as mo}from"fs";import{dirname as Ml,join as It}from"path";import{fileURLToPath as Zf}from"url";function I(e){return di(e,"utf-8")}function U(e,t){Il(Ml(e),{recursive:!0}),Xf(e,t,"utf-8")}function w(e){return mo(e)}function $e(e){Il(e,{recursive:!0})}function Kt(e){let t=[It(Pn,"../../assets",e),It(Pn,"../assets",e),It(process.cwd(),"assets",e)];for(let n of t)if(mo(n))return n;throw new Error(`Asset not found: ${e}`)}function Mt(){if(_n)return _n;let e=[It(Pn,"../../package.json"),It(Pn,"../package.json"),It(process.cwd(),"package.json")];for(let t of e)if(mo(t))try{let n=JSON.parse(di(t,"utf-8"));if(n.name==="vibespot"&&n.version)return _n=n.version,_n}catch{}return _n="dev",_n}function $l(){if(po)return po;let e=[It(Pn,"../../CHANGELOG.md"),It(Pn,"../CHANGELOG.md"),It(process.cwd(),"CHANGELOG.md")];for(let t of e)if(mo(t))try{return po=di(t,"utf-8"),po}catch{}return""}var Pn,_n,po,ae=j(()=>{"use strict";y();Pn=Ml(Zf(import.meta.url));_n="";po=""});import{execSync as Rl,execFileSync as Nl}from"child_process";function Se(e,t={}){try{return{stdout:Rl(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(),r=(s.stderr??"").toString().trim();return{stdout:o,stderr:r,success:!1}}}function ee(e,t={}){try{return{stdout:Nl("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(),r=(s.stderr??"").toString().trim();return{stdout:o,stderr:r,success:!1}}}function cs(e,t,n={}){try{return{stdout:Nl(e,t,{encoding:"utf-8",stdio:["pipe","pipe","pipe"],timeout:12e4,shell:process.platform==="win32",...n}).toString().trim(),stderr:"",success:!0}}catch(s){let o=s,r=(o.stdout??"").toString().trim(),i=(o.stderr??"").toString().trim();return{stdout:r,stderr:i,success:!1}}}function Ol(e,t={}){try{return Rl(e,{stdio:"inherit",timeout:3e5,...t}),!0}catch{return!1}}var on=j(()=>{"use strict";y()});var Dl={};Ve(Dl,{addHubSpotAccount:()=>us,getActiveHubSpotAccount:()=>Vt,getApiKeyForEngine:()=>De,getConfigDir:()=>sh,getHubSpotPak:()=>Je,isCliToolEnabled:()=>rt,loadConfig:()=>$,maskApiKey:()=>fo,removeHubSpotAccount:()=>fi,saveConfig:()=>Y,setActiveHubSpotAccount:()=>hi,setCliToolEnabled:()=>yi});import{join as gi}from"path";import{homedir as Qf}from"os";import{chmodSync as ui,mkdirSync as eh,renameSync as th,writeFileSync as nh}from"fs";function mi(){if(process.platform!=="win32"){try{ui(ds,Fl)}catch{}try{ui(go,pi)}catch{}}}function $(){let e={};if(w(go))try{mi(),e=JSON.parse(I(go)),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 De(e,t){let n=t||$();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 fo(e){return e.length<=12?"***":e.slice(0,7)+"..."+e.slice(-4)}function Y(e){let n={...$(),...e},s=JSON.stringify(n,null,2);eh(ds,{recursive:!0,mode:Fl}),mi();let o=gi(ds,`.config.json.${process.pid}.${Date.now()}.tmp`);if(nh(o,s,{encoding:"utf-8",mode:pi,flag:"w"}),process.platform!=="win32")try{ui(o,pi)}catch{}th(o,go),mi()}function sh(){return ds}function Vt(){let e=$();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 us(e,t,n,s){let r=$().hubspotAccounts||[],i=r.findIndex(l=>l.portalId===t),a={portalId:t,portalName:n,personalAccessKey:e,dataCenter:s,addedAt:new Date().toISOString()};i>=0?r[i]=a:r.push(a),Y({hubspotAccounts:r,activeHubSpotAccount:t})}function fi(e){let t=$(),n=(t.hubspotAccounts||[]).filter(o=>o.portalId!==e),s={hubspotAccounts:n};t.activeHubSpotAccount===e&&(s.activeHubSpotAccount=n[0]?.portalId||void 0),Y(s)}function hi(e){Y({activeHubSpotAccount:e})}function Je(){return Vt()?.personalAccessKey||process.env.HUBSPOT_PERSONAL_ACCESS_KEY||null}function rt(e){return $().enabledCLITools?.includes(e)??!1}function yi(e,t){let n=$(),s=new Set(n.enabledCLITools||[]);t?s.add(e):s.delete(e),Y({enabledCLITools:[...s]})}var ds,go,pi,Fl,te=j(()=>{"use strict";y();ae();ds=gi(Qf(),".vibespot"),go=gi(ds,"config.json"),pi=384,Fl=448});var Ci={};Ve(Ci,{OAUTH_EXTRA_HEADERS:()=>ms,OAUTH_SYSTEM_PREFIX:()=>In,clearOAuthTokens:()=>ps,getOAuthTokenInfo:()=>rn,getValidAccessToken:()=>ki,hasValidOAuthToken:()=>Qe,saveInitialToken:()=>wi});import{join as xi}from"path";import{homedir as oh}from"os";import{chmodSync as bi,mkdirSync as rh,renameSync as ih,unlinkSync as ah,writeFileSync as lh}from"fs";function vi(){if(process.platform!=="win32"){try{bi(yo,jl)}catch{}try{bi(En,Si)}catch{}}}function ph(e){if(!e||typeof e!="object")return null;let t=e;return typeof t.access_token!="string"||!t.access_token||typeof t.refresh_token!="string"||typeof t.expires_at!="number"||!Number.isFinite(t.expires_at)?null:{access_token:t.access_token,refresh_token:t.refresh_token,expires_at:t.expires_at}}function bo(){if(!w(En))return null;try{return vi(),ph(JSON.parse(I(En)))}catch{return null}}function Ll(e){rh(yo,{recursive:!0,mode:jl}),vi();let t=xi(yo,`.claude-oauth.json.${process.pid}.${Date.now()}.tmp`);if(lh(t,JSON.stringify(e,null,2),{encoding:"utf-8",mode:Si,flag:"w"}),process.platform!=="win32")try{bi(t,Si)}catch{}ih(t,En),vi()}async function mh(e){let t=await fetch(dh,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({grant_type:"refresh_token",refresh_token:e,client_id:ch})});if(!t.ok)throw ps(),new Error("Claude OAuth session expired. Please re-authenticate in Settings.");let n=await t.json();if(typeof n.access_token!="string"||!n.access_token)throw ps(),new Error("Claude OAuth refresh returned an invalid token payload. Please re-authenticate in Settings.");let s=typeof n.expires_in=="number"&&Number.isFinite(n.expires_in)?n.expires_in:28800;Ll({access_token:n.access_token,refresh_token:typeof n.refresh_token=="string"?n.refresh_token:e,expires_at:Date.now()+s*1e3})}function wi(e,t=""){Ll({access_token:e,refresh_token:t,expires_at:Date.now()+28800*1e3})}function Qe(){let e=bo();return e?e.expires_at>Date.now():!1}async function ki(){let e=bo();if(!e)return null;if(e.expires_at-Date.now()>uh)return e.access_token;if(e.refresh_token){ho||(ho=mh(e.refresh_token).finally(()=>{ho=null}));try{await ho}catch{return null}return bo()?.access_token??null}return e.access_token}function rn(){let e=bo();return e?{expiresAt:new Date(e.expires_at).toISOString()}:null}function ps(){if(w(En))try{ah(En)}catch{}}var ch,dh,yo,En,uh,Si,jl,ms,In,ho,$t=j(()=>{"use strict";y();ae();ch="9d1c250a-e61b-44d9-88ed-5944d1962f5e",dh="https://console.anthropic.com/v1/oauth/token",yo=xi(oh(),".vibespot"),En=xi(yo,"claude-oauth.json"),uh=300*1e3,Si=384,jl=448,ms={"user-agent":"claude-cli/2.1.75","x-app":"cli","anthropic-beta":"oauth-2025-04-20"},In="You are Claude Code, Anthropic's official CLI for Claude.";ho=null});import{readFileSync as hh}from"fs";import{basename as yh}from"path";import{createHash as bh}from"crypto";function wh(e){return bh("sha256").update(e).digest("hex")}function kh(e=Date.now()){for(let[t,n]of ln)n.expiresAt-e<=Vl&&ln.delete(t)}function Ch(){for(;ln.size>xh;){let e=ln.keys().next().value;if(!e)return;ln.delete(e)}}async function zl(e){kh();let t=wh(e),n=ln.get(t);if(n&&n.expiresAt-Date.now()>Vl)return n;let s=await fetch(`${Rt}/localdevauth/v1/auth/refresh`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({encodedOAuthRefreshToken:e})});if(!s.ok){let i=await s.text().catch(()=>"");throw new Error(s.status===401||s.status===403?"Invalid or expired Personal Access Key":`Token exchange failed (${s.status}): ${i.slice(0,200)}`)}let o=await s.json();if(typeof o.oauthAccessToken!="string"||!o.oauthAccessToken||typeof o.expiresAtMillis!="number"||!Number.isFinite(o.expiresAtMillis)||o.expiresAtMillis<=Date.now())throw new Error("Token exchange returned an invalid token payload");let r={accessToken:o.oauthAccessToken,expiresAt:o.expiresAtMillis,hubId:typeof o.hubId=="number"?o.hubId:Number(o.hubId||0),hubName:typeof o.hubName=="string"?o.hubName:""};return ln.set(t,r),Ch(),r}async function Fn(e){let{accessToken:t}=await zl(e);return{Authorization:`Bearer ${t}`}}function Ao(e){return e.replace(/^\/+/,"").split("/").filter(Boolean).map(encodeURIComponent).join("/")}function Th(e){return e.startsWith("pat-eu1-")?"eu1":e.startsWith("pat-na1-")?"na1":e.startsWith("CiRldTE")?"eu1":"na1"}function Ah(e){return new Promise(t=>setTimeout(t,e))}async function ys(e,t){let n=`HTTP ${e.status}`,s,o;try{let r=await e.json();if(r.message&&typeof r.message=="string"&&(n=r.message),r.category&&typeof r.category=="string"&&(s=r.category),r.errors&&Array.isArray(r.errors)&&r.errors.length>0){let i=r.errors[0];o=i.message||JSON.stringify(i)}}catch{try{let r=await e.text();r&&(n=r.slice(0,500))}catch{}}return{status:e.status,message:t?`${n} (${t})`:n,category:s,detail:o}}async function bs(e,t,n=Sh){for(let s=0;s<=n;s++){let o=await fetch(e,t);if(o.status===429||o.status>=500&&s<n){let r=vh*Math.pow(2,s);await Ah(r);continue}return o}return fetch(e,t)}async function _o(e){let t=await zl(e),n=`${Rt}/account-info/v3/details`,s=await bs(n,{headers:await Fn(e)});if(!s.ok){let a=await ys(s);throw new Error(`Failed to get account info: ${a.message}`)}let o=await s.json(),r=String(o.portalId||t.hubId||""),i=t.hubName||o.uiDomain||r;return{portalId:r,portalName:i,dataCenter:Th(e)}}async function ql(e,t,n){let s=hh(n),o=yh(n),r=new FormData,i=new Blob([s]);r.append("file",i,o);let a=`${Rt}/cms/v3/source-code/published/content/${Ao(t)}`,l=await bs(a,{method:"PUT",headers:await Fn(e),body:r});if(!l.ok){let c=await ys(l,t);return{success:!1,path:t,error:c}}return{success:!0,path:t}}async function Pi(e,t){let n=`${Rt}/cms/v3/source-code/published/content/${Ao(t)}`,s=await bs(n,{method:"DELETE",headers:await Fn(e)});if(!s.ok&&s.status!==404){let o=await ys(s,t);throw new Error(`Failed to delete ${t}: ${o.message}`)}}async function Yl(e,t){let n=`${Rt}/cms/v3/source-code/published/content/${Ao(t)}`,s=await bs(n,{method:"GET",headers:await Fn(e)});if(!s.ok){let r=await ys(s,t);throw new Error(`Failed to download ${t}: ${r.message}`)}let o=await s.arrayBuffer();return Buffer.from(o)}async function Po(e,t){let n=`${Rt}/cms/v3/source-code/published/metadata/${Ao(t)}`,s=await bs(n,{method:"GET",headers:await Fn(e)});if(s.status===404)return null;if(!s.ok){let o=await ys(s,t);throw new Error(`Failed to get metadata for ${t}: ${o.message}`)}return await s.json()}async function Xl(e){let t=await Fn(e),n=[`${Rt}/cms/v3/source-code/published/metadata`,`${Rt}/cms/v3/source-code/published/metadata/`,`${Rt}/designmanager/v1/portals/content/listing`];for(let s of n)try{let o=await fetch(s,{method:"GET",headers:t});if(o.ok){let r=await o.json(),i=r.children||r.objects||(Array.isArray(r)?r:null);if(i&&i.length>0)return i.filter(a=>a.folder)}}catch{}return[]}var Rt,Sh,vh,Vl,xh,ln,cn=j(()=>{"use strict";y();Rt="https://api.hubapi.com",Sh=3,vh=1e3,Vl=300*1e3,xh=25,ln=new Map});var sc={};Ve(sc,{addEmailTemplateToTheme:()=>jn,createThemeScaffold:()=>vs});import{mkdirSync as Ot,writeFileSync as Ss}from"fs";import{join as ze}from"path";function vs(e,t){Ot(e,{recursive:!0}),Ot(ze(e,"templates"),{recursive:!0}),Ot(ze(e,"modules"),{recursive:!0}),Ot(ze(e,"css"),{recursive:!0}),Ot(ze(e,"js"),{recursive:!0}),Ot(ze(e,"images"),{recursive:!0}),Ot(ze(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(ze(e,"theme.json"),JSON.stringify(n,null,2)+`
|
|
2
|
+
`),Ss(ze(e,"fields.json"),`[]
|
|
10
3
|
`);let s=`<!--
|
|
11
4
|
templateType: page
|
|
12
5
|
isAvailableForNewContent: false
|
|
@@ -22,7 +15,7 @@ var dg=Object.defineProperty;var N=(e,t)=>()=>(e&&(t=e(e=0)),t);var Ge=(e,t)=>{f
|
|
|
22
15
|
%}
|
|
23
16
|
{% end_dnd_area %}
|
|
24
17
|
{% endblock body %}
|
|
25
|
-
`;
|
|
18
|
+
`;Ss(ze(e,"templates","home.html"),s);let o=`<!--
|
|
26
19
|
templateType: none
|
|
27
20
|
isAvailableForNewContent: false
|
|
28
21
|
label: Base Layout
|
|
@@ -45,7 +38,7 @@ var dg=Object.defineProperty;var N=(e,t)=>()=>(e&&(t=e(e=0)),t);var Ge=(e,t)=>{f
|
|
|
45
38
|
{{ standard_footer_includes }}
|
|
46
39
|
</body>
|
|
47
40
|
</html>
|
|
48
|
-
`;
|
|
41
|
+
`;Ot(ze(e,"templates","layouts"),{recursive:!0}),Ss(ze(e,"templates","layouts","base.html"),o)}function jn(e,t){let n=`<!--
|
|
49
42
|
templateType: email
|
|
50
43
|
isAvailableForNewContent: true
|
|
51
44
|
label: ${t} Email Template
|
|
@@ -84,8 +77,8 @@ var dg=Object.defineProperty;var N=(e,t)=>()=>(e&&(t=e(e=0)),t);var Ge=(e,t)=>{f
|
|
|
84
77
|
{{ standard_footer_includes }}
|
|
85
78
|
</body>
|
|
86
79
|
</html>
|
|
87
|
-
`;
|
|
88
|
-
## `,o+s.length);return
|
|
80
|
+
`;Ot(ze(e,"templates"),{recursive:!0}),Ss(ze(e,"templates","email.html"),n)}var xs=j(()=>{"use strict";y()});import{join as Ih,resolve as Mo,dirname as Mh,sep as $h}from"path";function He(e){return String(e||"").trim().toLowerCase().replace(/['"]/g,"").replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")}function ws(e){return!e||e==="."||e===".."?!1:!/[/\\\0]/.test(e)}function dn(e,t){let n=Mo(e);if(!ws(`${t}.module`))throw new Error(`Unsafe module name rejected: ${JSON.stringify(t)}`);let s=Mo(n,`${t}.module`);if(Mh(s)!==n||!s.endsWith(".module"))throw new Error(`Unsafe module name rejected: ${JSON.stringify(t)}`);return s}function Ln(e,t){if(t.includes("\0"))throw new Error(`Unsafe path rejected: ${JSON.stringify(t)}`);let n=Ih(e,t),s=Mo(e),o=Mo(n);if(o!==s&&!o.startsWith(s+$h))throw new Error(`Path escapes target directory: ${JSON.stringify(t)}`);return n}var wt=j(()=>{"use strict";y()});var rc={};Ve(rc,{fetchTheme:()=>ks});import{mkdirSync as oc,writeFileSync as Rh}from"fs";import{dirname as Nh}from"path";async function $i(e,t){let n=await Po(e,t);if(!n)return[];if(!n.folder)return[n.path||t];let s=[],o=n.children||[];for(let r of o){let i=typeof r=="string"?r:r.name;if(!i)continue;let a=`${t}/${i}`;if(typeof r=="string")s.push(...await $i(e,a));else{let l=r;l.folder?s.push(...await $i(e,l.path||a)):s.push(l.path||a)}}return s}async function Oh(e,t,n){let s=0;async function o(){for(;s<e.length;){let i=s++;await n(e[i])}}let r=Array.from({length:Math.min(t,e.length)},()=>o());await Promise.all(r)}async function ks(e,t,n,s={}){let o=s.concurrency??5,r=await $i(e,t);if(r.length===0)throw new Error(`Theme "${t}" not found on HubSpot or is empty`);oc(n,{recursive:!0}),await Oh(r,o,async i=>{let a=i.startsWith(t+"/")?i.slice(t.length+1):i,l=Ln(n,a);oc(Nh(l),{recursive:!0});let c=await Yl(e,i);Rh(l,c),s.onFile?.(a)})}var $o=j(()=>{"use strict";y();wt();cn()});function zt(e){let t=ic.get(e);if(t!==void 0)return t;try{t=I(Kt(e))}catch{t=""}return ic.set(e,t),t}function Ce(){return zt("conversion-guide.md")||"Conversion guide not found. Using built-in rules."}function No(){return zt("design-guide.md")}function ac(){return zt("content-guide.md")}function et(){return zt("hubspot-rules.md")}function lc(){return zt("humanify-guide.md")}function cc(){return zt("email-rules.md")}function dc(){return zt("blog-rules.md")}function uc(e){let t=zt("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 r=t.indexOf(`
|
|
81
|
+
## `,o+s.length);return r>=0?t.slice(o,r).trim():t.slice(o).trim()}function pc(e){return`You are a HubSpot CMS expert converting React/Tailwind pages to native HubSpot modules.
|
|
89
82
|
|
|
90
83
|
## Rules
|
|
91
84
|
Follow the conversion guide below EXACTLY. Key rules:
|
|
@@ -102,10 +95,10 @@ Follow the conversion guide below EXACTLY. Key rules:
|
|
|
102
95
|
- Convert React hooks to vanilla JS (no React, no npm packages)
|
|
103
96
|
|
|
104
97
|
## HubSpot CMS Rules
|
|
105
|
-
${
|
|
98
|
+
${et()}
|
|
106
99
|
|
|
107
100
|
## Conversion Guide
|
|
108
|
-
${e}`}function
|
|
101
|
+
${e}`}function mc(e,t,n){return`Convert this React component to a HubSpot module named "${t}".
|
|
109
102
|
|
|
110
103
|
Return a JSON object with these keys:
|
|
111
104
|
- fieldsJson: complete fields.json content (as JSON string)
|
|
@@ -120,7 +113,7 @@ ${n}
|
|
|
120
113
|
React component source:
|
|
121
114
|
${e}
|
|
122
115
|
|
|
123
|
-
Return ONLY valid JSON, no markdown fences.`}function
|
|
116
|
+
Return ONLY valid JSON, no markdown fences.`}function gc(e,t,n){return`Create a shared CSS file for a HubSpot CMS landing page.
|
|
124
117
|
|
|
125
118
|
Extract the design system from the source CSS and Tailwind config below.
|
|
126
119
|
Use the class prefix ".${n}-" for all custom classes.
|
|
@@ -144,7 +137,7 @@ ${e}
|
|
|
144
137
|
Tailwind config:
|
|
145
138
|
${t}
|
|
146
139
|
|
|
147
|
-
Return ONLY the CSS content, no markdown fences.`}function
|
|
140
|
+
Return ONLY the CSS content, no markdown fences.`}function fc(e,t,n){return`Create a shared vanilla JS file for a HubSpot CMS landing page.
|
|
148
141
|
|
|
149
142
|
Convert the React hooks and interactive components below to plain JavaScript.
|
|
150
143
|
Use the class prefix "${n}-" to match the CSS.
|
|
@@ -162,7 +155,7 @@ ${e}
|
|
|
162
155
|
Interactive component sources:
|
|
163
156
|
${t}
|
|
164
157
|
|
|
165
|
-
Return ONLY the JavaScript content, no markdown fences.`}function
|
|
158
|
+
Return ONLY the JavaScript content, no markdown fences.`}function hc(e,t,n){return`Create a HubSpot page template that assembles these modules:
|
|
166
159
|
|
|
167
160
|
${e.map((s,o)=>`${o+1}. ${s}.module`).join(`
|
|
168
161
|
`)}
|
|
@@ -177,30 +170,27 @@ Template requirements:
|
|
|
177
170
|
- Each module in its own dnd_section with padding zeroed and full_width=true
|
|
178
171
|
- dnd_area label: "${t} Landing Page"
|
|
179
172
|
|
|
180
|
-
Return ONLY the template HTML content, no markdown fences.`}var
|
|
181
|
-
`)}catch{}}}var ho,qg,Xi,Zi,M,le=N(()=>{"use strict";y();ho=Qi(Yg(),".vibespot","logs"),qg=7,Xi=!1,Zi=!1;M={info(e,t,n){let s=n?`[${e}] ${t} ${JSON.stringify(n)}`:`[${e}] ${t}`;console.log(s),qi("INFO",s)},warn(e,t,n){let s=n?`[${e}] ${t} ${JSON.stringify(n)}`:`[${e}] ${t}`;console.warn(s),qi("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),qi("ERROR",o)}}});function nf(e){let t=(e||"").toLowerCase();return tf.find(n=>t.includes(n.match))}function ds(e,t){let n=nf(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 En(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 Mn(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 _l(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 tf,on=N(()=>{"use strict";y();tf=[{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 sf}from"async_hooks";function of(){return{inputTokens:0,outputTokens:0,cacheReadTokens:0,cacheCreationTokens:0,costUsd:0,calls:0,unpricedCalls:0}}function rf(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 er(e){let t=of();return{result:await $l.run(t,e),cost:rf(t)}}function El(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=ds(e,t);s?n.costUsd+=s.total:n.unpricedCalls+=1}var $l,tr=N(()=>{"use strict";y();on();$l=new sf});import{randomUUID as Pt}from"crypto";import{AsyncLocalStorage as af}from"async_hooks";function Pl(){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||lf).replace(/\/+$/,"");return{publicKey:t,secretKey:n,baseUrl:o}}function yo(){return Pl()!==null}function ms(e,t=cf){if(typeof e=="string")return e.length>t?e.slice(0,t)+`\u2026[+${e.length-t} chars]`:e;try{let n=JSON.stringify(e);if(n&&n.length>t)return n.slice(0,t)+`\u2026[+${n.length-t} chars]`}catch{return"[unserializable]"}return e}async function tt(e,t){if(!yo())return t();let n=Pt();Gt.push({id:Pt(),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:ms(e.input)}:{},...e.metadata?{metadata:e.metadata}:{},...e.tags?{tags:e.tags}:{}}});try{return await us.run({traceId:n,sessionId:e.sessionId},t)}finally{await Nl()}}function nr(e){if(!yo())return;let t=us.getStore();t?.traceId&&Gt.push({id:Pt(),type:"trace-create",timestamp:new Date().toISOString(),body:{id:t.traceId,timestamp:new Date().toISOString(),output:ms(e)}})}async function te(e,t,n){let s=us.getStore();if(!yo()||!s?.traceId)return t();let o=Pt(),i=s.spanId,r=new Date,a,l;try{return await us.run({...s,spanId:o},t)}catch(c){throw a="ERROR",l=c?.message,c}finally{Gt.push({id:Pt(),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:ms(n.input)}:{},...n?.metadata?{metadata:n.metadata}:{},...a?{level:a}:{},...l?{statusMessage:l}:{}}})}}async function df(e){if(yo())try{let t=us.getStore(),n=t?.traceId,s=n?t?.spanId:void 0,o=!1;n||(n=Pt(),o=!0,Gt.push({id:Pt(),type:"trace-create",timestamp:new Date().toISOString(),body:{id:n,name:e.name,timestamp:new Date().toISOString()}}));let i=e.usage?_l(e.usage):void 0,r=e.usage?ds(e.model,e.usage):void 0;Gt.push({id:Pt(),type:"generation-create",timestamp:new Date().toISOString(),body:{id:Pt(),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:ms(e.input,Ml)}:{},...e.output!==void 0?{output:ms(e.output,Ml)}:{},...i?{usageDetails:i}:{},...r?{costDetails:r}:{},...e.level?{level:e.level}:{},...e.statusMessage?{statusMessage:e.statusMessage}:{},...e.promptName?{promptName:e.promptName,...e.promptVersion!=null?{promptVersion:e.promptVersion}:{}}:{},metadata:{...e.engine?{engine:e.engine}:{},...e.metadata??{}}}}),o&&await Nl()}catch(t){M.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?ds(n,o):void 0;if(o&&M.info("agent-usage",`${t} ${s}`,{model:n,inputTokens:o.inputTokens,outputTokens:o.outputTokens,cacheReadTokens:o.cacheReadTokens,costUsd:l?.total,durationMs:a}),Il.size>0){let c={engine:t,model:n,name:s,usage:o,cost:l,startTime:i,endTime:r,durationMs:a};for(let d of Il)try{d(c)}catch{}}El(n,o),df({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,promptName:e.promptName,promptVersion:e.promptVersion})}async function Nl(){let e=Pl();if(!e||Gt.length===0)return;let t=Gt;Gt=[];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(()=>"");M.warn("langfuse",`ingestion HTTP ${s.status}: ${o.slice(0,300)}`)}else M.info("langfuse",`flushed ${t.length} event(s)`)}catch(n){M.warn("langfuse",`ingestion failed: ${n.message}`)}}var lf,cf,Ml,us,Gt,Il,Be=N(()=>{"use strict";y();ee();le();on();tr();lf="https://cloud.langfuse.com",cf=24e3,Ml=2e5,us=new af,Gt=[],Il=new Set});import{join as me}from"path";import{readdirSync as it,rmSync as wf}from"fs";function ko(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 To(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 Ao(e){let t=[];return Ll(e)&&t.push("textarea \u2192 text"),Jl(e)&&t.push("name \u2192 item_name"),Bl(e)&&t.push("now() \u2192 local_dt"),Hl(e)&&t.push("Removed HubDB templates"),Ul(e)&&t.push("Fixed link field defaults"),Gl(e)&&t.push("Fixed rgba/invalid color values \u2192 hex"),Cf(e)&&t.push("Stripped CDN @import statements"),Kl(e)&&t.push('dnd_area \u2192 "main" in email templates'),Vl(e)&&t.push("Added {{ dnd_area_stylesheet }} to email templates"),t}function jl(e,t){return t.message.includes("textarea")?Ll(e):t.message.includes("reserved field name")?Jl(e):t.message.includes("now()")?Bl(e):t.message.includes("HubDB")?Hl(e):t.message.includes("invalid default value")||t.message.includes("deserialization")?Ul(e):t.message.includes("invalid format")&&t.message.includes("color")?Gl(e):t.message.includes("dnd")||t.message.includes("Dnd area")?Kl(e):t.message.includes("dnd_area_stylesheet")?Vl(e):!1}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,"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 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,"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 Hl(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"))&&(wf(o),t=!0)}return t}function Ul(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));zl(i)&&(B(o,JSON.stringify(i,null,2)+`
|
|
182
|
-
`),
|
|
183
|
-
`),t=!0)}catch{}}return t}function Wl(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"&&!kf(i)){let r=Tf(i);r&&(o.color=r.hex,r.opacity!==void 0&&(o.opacity=r.opacity),t=!0)}}Array.isArray(s.children)&&Wl(s.children)&&(t=!0)}return t}function kf(e){return/^#[0-9a-fA-F]{6}$/.test(e)}function Tf(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 Kl(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 Vl(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 zl(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)&&zl(s.children)&&(t=!0)}return t}var _o=N(()=>{"use strict";y();oe()});import{readdirSync as Af}from"fs";import{join as _f,relative as $f}from"path";function Yl(e){let t=[];for(let n of Af(e,{withFileTypes:!0})){if(Ef.has(n.name)||n.name.startsWith(".")&&n.name!==".gitkeep")continue;let s=_f(e,n.name);n.isDirectory()?t.push(...Yl(s)):n.isFile()&&t.push(s)}return t}async function Mf(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=Yl(t),r=i.length,a=0,l=0,c=[];return await Mf(i,o,async d=>{let u=$f(t,d).replace(/\\/g,"/"),m=`${n}/${u}`;s.onFileStart?.(u);let g=await al(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 Ef,sr=N(()=>{"use strict";y();sn();sn();Ef=new Set([".git","node_modules",".vibespot",".DS_Store"])});var oc=N(()=>{"use strict";y()});import{existsSync as Nt,writeFileSync as Rf,mkdirSync as Of}from"fs";import{join as vt}from"path";function rc(e){return/^[0-9a-f]{4,40}$/i.test(e)}function ac(e){return Number.isInteger(e)&&e>0&&e<1e3}function rt(){return Eo!==null||(Eo=Z(["--version"]).success),Eo}function Mo(e){if(!rt())return!1;if(Nt(vt(e,".git")))return ic(e),!0;let t=Z(["init"],{cwd:e});return t.success?(Ff(e),ic(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 ic(e){let t=vt(e,".vibespot");Nt(t)||Of(t,{recursive:!0})}function Ff(e){let t=vt(e,".gitignore");Rf(t,[".vibespot/","node_modules/",""].join(`
|
|
185
|
-
`),"utf-8")}function rn(e,t){if(!rt()||!Nt(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 ir(e,t,n,s){if(!rt()||!Nt(vt(e,".git")))return null;for(let u of s){let m=vt(e,u);Nt(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 lc(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 cc(e,t=50){if(!rt())return[];if(!Nt(vt(e,".git")))return[];if(!ac(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()?[]:lc(n.stdout)}function dc(e,t,n=50){if(!rt())return[];if(!Nt(vt(e,".git")))return[];if(!ac(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()?[]:lc(o.stdout)}function uc(e,t){if(!rt())return{success:!1,error:"Git not available"};if(!Nt(vt(e,".git")))return{success:!1,error:"Not a git repo"};if(!rc(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 mc(e,t,n,s){if(!rt())return{success:!1,error:"Git not available"};if(!Nt(vt(e,".git")))return{success:!1,error:"Not a git repo"};if(!rc(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 Eo,Pn=N(()=>{"use strict";y();Qt();Eo=null});import{readFileSync as Df,existsSync as gc,writeFileSync as jf,mkdirSync as Lf,rmSync as Jf}from"fs";import{join as Io}from"path";function an(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=Rt("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(),Hf()}function fc(e){let t=C();t&&(t.assets||(t.assets=[]),t.assets.push(e),t.updatedAt=Date.now(),L())}function hc(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 pc(e){return e.toLowerCase().replace(/[\s\-_]+/g,"")}function Bf(e,t){let n=pc(e),s=pc(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=>Bf(r.moduleName,n.moduleName));i&&M.warn("session-state",`Module "${n.moduleName}" looks like a renamed variant of existing "${i.moduleName}" \u2014 adding as a new module. This usually indicates the Module Planner re-named an existing module. Check the prompt's "preserve existing names" rule.`),t.modules.push(n),t.moduleOrder.some(r=>r.toLowerCase()===s)||t.moduleOrder.push(n.moduleName)}}t.updatedAt=Date.now(),at()}}function Wt(e){let t=C();t&&(t.moduleOrder=e,t.updatedAt=Date.now(),at())}function yc(e){let t=C();if(t){t.modules=t.modules.filter(n=>n.moduleName!==e),t.moduleOrder=t.moduleOrder.filter(n=>n!==e);for(let n of t.templates)n.modules=n.modules.filter(s=>s.moduleName!==e),n.moduleOrder=n.moduleOrder.filter(s=>s!==e);if(t.themePath){let n=Io(t.themePath,"modules",`${e}.module`);gc(n)&&Jf(n,{recursive:!0,force:!0})}t.updatedAt=Date.now(),at()}}function bc(e){let t=C();t&&(t.moduleOrder=t.moduleOrder.filter(n=>n!==e),t.updatedAt=Date.now(),at())}function Sc(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);wc(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 Hf(){let e=C();if(e)try{let t=Io(e.themePath,".vibespot");Lf(t,{recursive:!0});let n={sessionId:e.id,themeName:e.themeName,messages:e.messages,updatedAt:Date.now()};jf(Io(t,"chat.json"),JSON.stringify(n,null,2),"utf-8")}catch{}}function vc(e){let t=Io(e,".vibespot","chat.json");if(!gc(t))return[];try{let n=JSON.parse(Df(t,"utf-8"));return Array.isArray(n.messages)?n.messages:[]}catch{return[]}}function xc(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=Rt(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&&fs(e.pages[0].templateId),t.updatedAt=Date.now()}}function wc(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&&wc(i.children,s.slice(1).join("."),n))}var gs=N(()=>{"use strict";y();hs();Kt();le()});import{existsSync as Po,rmSync as No}from"fs";import{join as Nn}from"path";function Ro(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 fs(e){let t=C();if(!t)return!1;let n=t.templates.find(s=>s.id===e);return n?(t.activeTemplateId=e,an(n),t.updatedAt=Date.now(),!0):!1}function Rt(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,an(l),s.updatedAt=Date.now(),l}function Cc(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,an(l),n.updatedAt=Date.now(),l}function kc(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 Tc(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 Ac(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=Nn(n.themePath,"templates"),r=`${o.id}.html`,a=Nn(i,r);if(Po(a)&&No(a,{force:!0}),o.pageType==="blog_post"){let l=Nn(i,`${o.id}-listing.html`);Po(l)&&No(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=Nn(n.themePath,"modules");for(let l of r){let c=Nn(a,`${l}.module`);Po(c)&&No(c,{recursive:!0,force:!0})}}}if(n.activeTemplateId===e&&(n.templates.length>0?fs(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=Nn(n.themePath,".vibespot","plan.md");Po(r)&&No(r,{force:!0})}return n.updatedAt=Date.now(),!0}function Ot(){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 Kt=N(()=>{"use strict";y();hs();gs()});import{readFileSync as xt,readdirSync as dr,existsSync as Ie,writeFileSync as ys,mkdirSync as Oo,rmSync as rr,renameSync as ar,cpSync as Uf}from"fs";import{join as pe,dirname as _c}from"path";import{homedir as Gf}from"os";function Fo(){if(Rn)return Rn;try{return Ie(lr)?(Rn=JSON.parse(xt(lr,"utf-8")),Rn):cr()}catch{return cr()}}function Do(e){Rn=e;try{Oo(de,{recursive:!0}),ys(lr,JSON.stringify(e),"utf-8")}catch{}}function cr(){if(!Ie(de))return[];let e=[];for(let t of dr(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 Rn=e,Do(e),e}function $c(e){let t=Fo(),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),Do(t)}function Wf(e){let t=Fo().filter(n=>n.id!==e);Do(t)}function Kf(e){let t=Fo().filter(n=>n.themeName!==e);Do(t)}function C(){return Ue}function Ec(){return`vibe-${Date.now().toString(36)}-${Math.random().toString(36).slice(2,8)}`}function On(e,t,n={}){let s={id:Ec(),themePath:e,themeName:t,isImported:!!n.isImported,templates:[],activeTemplateId:"",messages:[],modules:[],sharedCss:"",sharedJs:"",template:"",moduleOrder:[],createdAt:Date.now(),updatedAt:Date.now()};return Ue=s,Mo(e),s}function L(){if(!Ue)return;Oo(de,{recursive:!0});let e=pe(de,`${Ue.id}.json`);ys(e,JSON.stringify(Ue,null,2),"utf-8"),$c(Ue)}function jo(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=""),Ro(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 Fn(){return Ie(de)?Fo():[]}function Mc(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)&&rr(o.themePath,{recursive:!0,force:!0})}catch{}else try{s=JSON.parse(xt(n,"utf-8")).themeName||""}catch{}try{Ie(n)&&rr(n)}catch{}if(s&&Ie(de)){for(let o of dr(de).filter(i=>i.endsWith(".json")&&i!=="_index.json"))try{JSON.parse(xt(pe(de,o),"utf-8")).themeName===s&&rr(pe(de,o))}catch{}Kf(s)}else Wf(e);Ue?.id===e&&(Ue=null)}function Ic(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(_c(i),t);if(Ie(i)){if(Ie(r))return{ok:!1,error:"A project with that name already exists"};try{ar(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{ar(a,l)}catch{}let c=pe(r,"js",`${o}-animations.js`),d=pe(r,"js",`${t}-animations.js`);if(Ie(c))try{ar(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,ys(u,JSON.stringify(m,null,2),"utf-8")}catch{}}if(Ie(de))for(let a of dr(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(),ys(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()),cr(),{ok:!0}}function Pc(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=_c(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{Uf(n.themePath,a,{recursive:!0})}catch(d){return{ok:!1,error:`Failed to copy files: ${d instanceof Error?d.message:String(d)}`}}else Oo(a,{recursive:!0});let l=Ec(),c={...JSON.parse(JSON.stringify(n)),id:l,themeName:i,themePath:a,createdAt:Date.now(),updatedAt:Date.now(),messages:[]};return Oo(de,{recursive:!0}),ys(pe(de,`${l}.json`),JSON.stringify(c,null,2),"utf-8"),$c(c),{ok:!0,newName:i,newSessionId:l}}var de,lr,Rn,Ue,hs=N(()=>{"use strict";y();Pn();Kt();de=pe(Gf(),".vibespot","sessions"),lr=pe(de,"_index.json"),Rn=null;Ue=null});import{readFileSync as Vf,readdirSync as Oc,statSync as ur}from"fs";import{createHash as zf}from"crypto";import{join as be,relative as Yf}from"path";function Bo(e){let t=[];if(!x(e))return vh(e,[{severity:"error",rule:"theme.path.missing",message:`Theme directory not found: ${e}`}]);let n=Dn(e),s=hh(e),o=bh(e),i=Sh(e),r=eh(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 bs(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 {
|
|
173
|
+
Return ONLY the template HTML content, no markdown fences.`}var ic,tt=j(()=>{"use strict";y();ae();ic=new Map});import{appendFileSync as Bh,mkdirSync as Jh,readdirSync as Hh,unlinkSync as Uh}from"fs";import{join as Fi}from"path";import{homedir as Gh}from"os";function Kh(){if(!Ni)try{Jh(Fo,{recursive:!0}),Ni=!0}catch{}}function Vh(){if(!Oi){Oi=!0;try{let e=Date.now()-Wh*864e5;for(let t of Hh(Fo)){if(!t.startsWith("vibespot-")||!t.endsWith(".log"))continue;let n=t.slice(9,19),s=new Date(n).getTime();if(s&&s<e)try{Uh(Fi(Fo,t))}catch{}}}catch{}}}function zh(){let t=new Date().toISOString().slice(0,10);return Fi(Fo,`vibespot-${t}.log`)}function qh(){return new Date().toISOString().slice(11,23)}function Ri(e,t){if(Kh(),!!Ni){Oi||Vh();try{Bh(zh(),`${qh()} ${e} ${t}
|
|
174
|
+
`)}catch{}}}var Fo,Wh,Ni,Oi,A,re=j(()=>{"use strict";y();Fo=Fi(Gh(),".vibespot","logs"),Wh=7,Ni=!1,Oi=!1;A={info(e,t,n){let s=n?`[${e}] ${t} ${JSON.stringify(n)}`:`[${e}] ${t}`;console.log(s),Ri("INFO",s)},warn(e,t,n){let s=n?`[${e}] ${t} ${JSON.stringify(n)}`:`[${e}] ${t}`;console.warn(s),Ri("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),Ri("ERROR",o)}}});function Xh(e){let t=(e||"").toLowerCase();return Yh.find(n=>t.includes(n.match))}function Ts(e,t){let n=Xh(e);if(!n)return;let s=n.cacheReadPerM??n.inputPerM*.1,o=n.cacheWritePerM??n.inputPerM*1.25,r=(t.inputTokens??0)*n.inputPerM,i=(t.outputTokens??0)*n.outputPerM,a=(t.cacheReadTokens??0)*s,l=(t.cacheCreationTokens??0)*o,c={total:(r+i+a+l)/1e6};return t.inputTokens!=null&&(c.input=r/1e6),t.outputTokens!=null&&(c.output=i/1e6),t.cacheReadTokens&&(c.cache_read_input_tokens=a/1e6),t.cacheCreationTokens&&(c.cache_creation_input_tokens=l/1e6),c}function nt(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 Bn(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 Jn(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 bc(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 Yh,un=j(()=>{"use strict";y();Yh=[{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 Zh}from"async_hooks";function Qh(){return{inputTokens:0,outputTokens:0,cacheReadTokens:0,cacheCreationTokens:0,costUsd:0,calls:0,unpricedCalls:0}}function Sc(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 Do(e){let t=Qh();return{result:await Di.run(t,e),cost:Sc(t)}}function vc(e,t){if(!t)return;let n=Di.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=Ts(e,t);s?n.costUsd+=s.total:n.unpricedCalls+=1}function xc(){let e=Di.getStore();return e?Sc(e):null}var Di,jo=j(()=>{"use strict";y();un();Di=new Zh});import{randomUUID as Ft}from"crypto";import{AsyncLocalStorage as ey}from"async_hooks";function Cc(){let e=$(),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||ty).replace(/\/+$/,"");return{publicKey:t,secretKey:n,baseUrl:o}}function Lo(){return Cc()!==null}function _s(e,t=ny){if(typeof e=="string")return e.length>t?e.slice(0,t)+`\u2026[+${e.length-t} chars]`:e;try{let n=JSON.stringify(e);if(n&&n.length>t)return n.slice(0,t)+`\u2026[+${n.length-t} chars]`}catch{return"[unserializable]"}return e}async function qe(e,t){if(!Lo())return t();let n=Ft();qt.push({id:Ft(),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:_s(e.input)}:{},...e.metadata?{metadata:e.metadata}:{},...e.tags?{tags:e.tags}:{}}});try{return await As.run({traceId:n,sessionId:e.sessionId},t)}finally{Tc()}}function Bo(e){if(!Lo())return;let t=As.getStore();t?.traceId&&qt.push({id:Ft(),type:"trace-create",timestamp:new Date().toISOString(),body:{id:t.traceId,timestamp:new Date().toISOString(),output:_s(e)}})}async function ce(e,t,n){let s=As.getStore();if(!Lo()||!s?.traceId)return t();let o=Ft(),r=s.spanId,i=new Date,a,l;try{return await As.run({...s,spanId:o},t)}catch(c){throw a="ERROR",l=c?.message,c}finally{qt.push({id:Ft(),type:"span-create",timestamp:new Date().toISOString(),body:{id:o,traceId:s.traceId,name:e,startTime:i.toISOString(),endTime:new Date().toISOString(),...r?{parentObservationId:r}:{},...n?.input!==void 0?{input:_s(n.input)}:{},...n?.metadata?{metadata:n.metadata}:{},...a?{level:a}:{},...l?{statusMessage:l}:{}}})}}async function sy(e){if(Lo())try{let t=As.getStore(),n=t?.traceId,s=n?t?.spanId:void 0,o=!1;n||(n=Ft(),o=!0,qt.push({id:Ft(),type:"trace-create",timestamp:new Date().toISOString(),body:{id:n,name:e.name,timestamp:new Date().toISOString()}}));let r=e.usage?bc(e.usage):void 0,i=e.usage?Ts(e.model,e.usage):void 0;qt.push({id:Ft(),type:"generation-create",timestamp:new Date().toISOString(),body:{id:Ft(),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:_s(e.input,wc)}:{},...e.output!==void 0?{output:_s(e.output,wc)}:{},...r?{usageDetails:r}:{},...i?{costDetails:i}:{},...e.level?{level:e.level}:{},...e.statusMessage?{statusMessage:e.statusMessage}:{},...e.promptName?{promptName:e.promptName,...e.promptVersion!=null?{promptVersion:e.promptVersion}:{}}:{},metadata:{...e.engine?{engine:e.engine}:{},...e.metadata??{}}}}),o&&await Tc()}catch(t){A.warn("langfuse",`recordGeneration failed: ${t.message}`)}}function Ct(e){let{engine:t,model:n,name:s,usage:o,startTime:r,endTime:i}=e,a=i.getTime()-r.getTime(),l=o?Ts(n,o):void 0;if(o&&A.info("agent-usage",`${t} ${s}`,{model:n,inputTokens:o.inputTokens,outputTokens:o.outputTokens,cacheReadTokens:o.cacheReadTokens,costUsd:l?.total,durationMs:a}),kc.size>0){let c={engine:t,model:n,name:s,usage:o,cost:l,startTime:r,endTime:i,durationMs:a};for(let d of kc)try{d(c)}catch{}}vc(n,o),sy({name:s,model:n,engine:t,input:e.input,output:e.output,usage:o,startTime:r,endTime:i,level:e.level,statusMessage:e.statusMessage,metadata:e.metadata,promptName:e.promptName,promptVersion:e.promptVersion})}async function Tc(){let e=Cc();if(!e||qt.length===0)return;let t=qt;qt=[];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}),signal:AbortSignal.timeout(oy)});if(!s.ok&&s.status!==207){let o=await s.text().catch(()=>"");A.warn("langfuse",`ingestion HTTP ${s.status}: ${o.slice(0,300)}`)}else A.info("langfuse",`flushed ${t.length} event(s)`)}catch(n){A.warn("langfuse",`ingestion failed: ${n.message}`)}}var ty,ny,wc,As,qt,kc,oy,Ue=j(()=>{"use strict";y();te();re();un();jo();ty="https://cloud.langfuse.com",ny=24e3,wc=2e5,As=new ey,qt=[],kc=new Set;oy=1e4});var _c=j(()=>{"use strict";y()});import{existsSync as Dt,writeFileSync as ay,mkdirSync as ly}from"fs";import{join as Tt}from"path";function Ec(e){return/^[0-9a-f]{4,40}$/i.test(e)}function Ic(e){return Number.isInteger(e)&&e>0&&e<1e3}function at(){return Ho!==null||(Ho=ee(["--version"]).success),Ho}function Uo(e){if(!at())return!1;if(Dt(Tt(e,".git")))return Pc(e),!0;let t=ee(["init"],{cwd:e});return t.success?(cy(e),Pc(e),ee(["add","-A"],{cwd:e}),ee(["commit","-m","Initial theme"],{cwd:e}),!0):(console.warn(`[project-git] git init failed in ${e}: ${t.stderr}`),!1)}function Pc(e){let t=Tt(e,".vibespot");Dt(t)||ly(t,{recursive:!0})}function cy(e){let t=Tt(e,".gitignore");ay(t,[".vibespot/","node_modules/",""].join(`
|
|
175
|
+
`),"utf-8")}function pn(e,t){if(!at()||!Dt(Tt(e,".git"))||(ee(["add","-A"],{cwd:e}),ee(["diff","--cached","--quiet"],{cwd:e}).success))return null;let s=t.length>72?t.slice(0,69)+"...":t,o=ee(["commit","-m",s],{cwd:e});if(!o.success)return console.warn(`[project-git] commit failed: ${o.stderr}`),null;let r=ee(["rev-parse","--short","HEAD"],{cwd:e});return r.success?r.stdout:null}function ji(e,t,n,s){if(!at()||!Dt(Tt(e,".git")))return null;for(let u of s){let p=Tt(e,u);Dt(p)&&ee(["add","--",u],{cwd:e})}if(ee(["diff","--cached","--quiet"],{cwd:e}).success)return null;let r=`[${t}] `,i=72-r.length,a=n.length>i?n.slice(0,i-3)+"...":n,l=r+a,c=ee(["commit","-m",l],{cwd:e});if(!c.success)return console.warn(`[project-git] template commit failed: ${c.stderr}`),null;let d=ee(["rev-parse","--short","HEAD"],{cwd:e});return d.success?d.stdout:null}function Mc(e){let t=[],n=null;for(let s of e.split(`
|
|
176
|
+
`)){let o=s.trimEnd();if(o.startsWith("COMMIT|")){n&&t.push(n);let r=o.slice(7).split("|");if(r.length<4){n=null;continue}let i=parseInt(r[3],10)*1e3;n={hash:r[0],fullHash:r[1],message:r[2],timestamp:i,date:new Date(i).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 r of s.changedFiles){let i=r.match(/^modules\/([^/]+)\.module(?:\/|$)/);i&&o.add(i[1])}s.changedModules=[...o]}return t}function $c(e,t=50){if(!at())return[];if(!Dt(Tt(e,".git")))return[];if(!Ic(t))return[];let n=ee(["log","--name-only","--pretty=format:COMMIT|%h|%H|%s|%at","-n",String(t)],{cwd:e});return!n.success||!n.stdout.trim()?[]:Mc(n.stdout)}function Rc(e,t,n=50){if(!at())return[];if(!Dt(Tt(e,".git")))return[];if(!Ic(n))return[];let s=t.replace(/[\\.*+?^${}()|[\]/]/g,"\\$&"),o=ee(["log",`--grep=\\[${s}\\]`,"--name-only","--pretty=format:COMMIT|%h|%H|%s|%at","-n",String(n)],{cwd:e});return!o.success||!o.stdout.trim()?[]:Mc(o.stdout)}function Nc(e,t){if(!at())return{success:!1,error:"Git not available"};if(!Dt(Tt(e,".git")))return{success:!1,error:"Not a git repo"};if(!Ec(t))return{success:!1,error:"Invalid commit hash"};let n=ee(["cat-file","-t",t],{cwd:e});if(!n.success||n.stdout.trim()!=="commit")return{success:!1,error:`Commit ${t} not found`};let s=ee(["log","--format=%s","-1",t],{cwd:e}),o=s.success?s.stdout:t,r=ee(["checkout",t,"--","."],{cwd:e});if(!r.success)return{success:!1,error:`Checkout failed: ${r.stderr}`};let i=`Rollback to: ${o}`.slice(0,72);return ee(["commit","-m",i],{cwd:e}),{success:!0}}function Oc(e,t,n,s){if(!at())return{success:!1,error:"Git not available"};if(!Dt(Tt(e,".git")))return{success:!1,error:"Not a git repo"};if(!Ec(n))return{success:!1,error:"Invalid commit hash"};let o=ee(["cat-file","-t",n],{cwd:e});if(!o.success||o.stdout.trim()!=="commit")return{success:!1,error:`Commit ${n} not found`};let r=ee(["log","--format=%s","-1",n],{cwd:e}),i=r.success?r.stdout:n,a=0;for(let d of s)ee(["checkout",n,"--",d],{cwd:e}).success&&a++;if(a===0)return{success:!1,error:"No files could be restored from that commit"};ee(["add","-A"],{cwd:e});let c=`${`[${t}] `}Rollback to: ${i}`.slice(0,72);return ee(["commit","-m",c],{cwd:e}),{success:!0}}var Ho,Hn=j(()=>{"use strict";y();on();Ho=null});import{readFileSync as dy,existsSync as Dc,writeFileSync as uy,mkdirSync as py,rmSync as my}from"fs";import{join as Go}from"path";function mn(e){let t=x();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 lt(){let e=x();if(!e)return;let t=xe();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=jt("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 ct(e,t,n){let s=x();if(!s)return;let o={role:e,content:t,timestamp:Date.now()};n&&(o.pipeline=n),s.messages.push(o),s.updatedAt=Date.now(),lt(),fy()}function jc(e){let t=x();t&&(t.assets||(t.assets=[]),t.assets.push(e),t.updatedAt=Date.now(),D())}function Lc(e){let t=x();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 Fc(e){return e.toLowerCase().replace(/[\s\-_]+/g,"")}function gy(e,t){let n=Fc(e),s=Fc(t);if(n===s)return!0;if(n.length<4||s.length<4)return!1;let o=n.length<=s.length?n:s,r=n.length<=s.length?s:n;return r.includes(o)?o.length/r.length>=.8:!1}function Ge(e){let t=x();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(r=>r.moduleName.toLowerCase()===s);if(o>=0)t.modules[o]=n;else{let r=t.modules.find(i=>gy(i.moduleName,n.moduleName));r&&A.warn("session-state",`Module "${n.moduleName}" looks like a renamed variant of existing "${r.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(i=>i.toLowerCase()===s)||t.moduleOrder.push(n.moduleName)}}t.updatedAt=Date.now(),lt()}}function Yt(e){let t=x();t&&(t.moduleOrder=e,t.updatedAt=Date.now(),lt())}function Bc(e){let t=x();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)try{let n=dn(Go(t.themePath,"modules"),e);Dc(n)&&my(n,{recursive:!0,force:!0})}catch{A.warn("session-state","Refusing to delete module with unsafe name",{name:e})}t.updatedAt=Date.now(),lt()}}function Jc(e){let t=x();t&&(t.moduleOrder=t.moduleOrder.filter(n=>n!==e),t.updatedAt=Date.now(),lt())}function Hc(e,t,n){let s=x();if(!s)return;let o=s.modules.find(r=>r.moduleName===e);if(o)try{let r=JSON.parse(o.fieldsJson);Wc(r,t,n),o.fieldsJson=JSON.stringify(r,null,2),s.updatedAt=Date.now(),lt()}catch{}}function pe(){let e=x();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 fy(){let e=x();if(e)try{let t=Go(e.themePath,".vibespot");py(t,{recursive:!0});let n={sessionId:e.id,themeName:e.themeName,messages:e.messages,updatedAt:Date.now()};uy(Go(t,"chat.json"),JSON.stringify(n,null,2),"utf-8")}catch{}}function Uc(e){let t=Go(e,".vibespot","chat.json");if(!Dc(t))return[];try{let n=JSON.parse(dy(t,"utf-8"));return Array.isArray(n.messages)?n.messages:[]}catch{return[]}}function Gc(e){let t=x();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,r=s?.pageType||"website_page",i=t.templates.find(a=>a.id===n.templateId);i||(i=jt(r,o),i.id=n.templateId,i.templateFile=`templates/${n.templateId}.html`),i.modules=n.modules,i.moduleOrder=n.moduleOrder,i.sharedCss=e.sharedCss,i.sharedJs=e.sharedJs}e.pages.length>0&&Es(e.pages[0].templateId),t.updatedAt=Date.now()}}function Wc(e,t,n){let s=t.split("."),o=s[0],r=e.find(i=>i.name===o);r&&(s.length===1?r.default=n:r.children&&Wc(r.children,s.slice(1).join("."),n))}var Ps=j(()=>{"use strict";y();Is();Xt();re();wt()});import{existsSync as Wo,rmSync as Ko}from"fs";import{join as Ms}from"path";function Vo(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 xe(){let e=x();return!e||!e.activeTemplateId||!e.templates?.length?null:e.templates.find(t=>t.id===e.activeTemplateId)||null}function Es(e){let t=x();if(!t)return!1;let n=t.templates.find(s=>s.id===e);return n?(t.activeTemplateId=e,mn(n),t.updatedAt=Date.now(),!0):!1}function jt(e,t,n){let s=x();if(!s)throw new Error("No active session");let o=t.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-|-$/g,""),r=n==="email",a=`${r?"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:r?"templates/email.html":e==="module_only"?"":`templates/${a}.html`,modules:[],moduleOrder:[],sharedCss:"",sharedJs:"",template:"",messages:[]};return s.templates.push(l),s.activeTemplateId=a,mn(l),s.updatedAt=Date.now(),l}function Kc(e,t){let n=x();if(!n)return null;let s=n.templates.find(c=>c.id===e);if(!s)return null;let o=t||`${s.label} (Copy)`,r=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"}-${r}`,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,mn(l),n.updatedAt=Date.now(),l}function Vc(e){let t=x();if(!t||!Array.isArray(e)||e.length===0)return!1;let n=new Map(t.templates.map(r=>[r.id,r])),s=new Set,o=[];for(let r of e){let i=n.get(r);!i||s.has(r)||(o.push(i),s.add(r))}for(let r of t.templates)s.has(r.id)||o.push(r);return o.length!==t.templates.length?!1:(t.templates=o,t.updatedAt=Date.now(),!0)}function zc(e,t){let n=x();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 qc(e,t=!1){let n=x();if(!n)return!1;let s=n.templates.findIndex(r=>r.id===e);if(s<0)return!1;let o=n.templates.splice(s,1)[0];if(n.themePath){let r=Ms(n.themePath,"templates"),i=`${o.id}.html`,a=Ms(r,i);if(Wo(a)&&Ko(a,{force:!0}),o.pageType==="blog_post"){let l=Ms(r,`${o.id}-listing.html`);Wo(l)&&Ko(l,{force:!0})}}if(t&&o.modules.length>0){let r=new Set;for(let a of n.templates)for(let l of a.modules)r.add(l.moduleName);for(let a of n.modules)r.add(a.moduleName);let i=o.modules.map(a=>a.moduleName).filter(a=>!r.has(a));if(n.themePath&&i.length>0){let a=Ms(n.themePath,"modules");for(let l of i){let c;try{c=dn(a,l)}catch{continue}Wo(c)&&Ko(c,{recursive:!0,force:!0})}}}if(n.activeTemplateId===e&&(n.templates.length>0?Es(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(i=>!!i.plan)){let i=Ms(n.themePath,".vibespot","plan.md");Wo(i)&&Ko(i,{force:!0})}return n.updatedAt=Date.now(),!0}function Lt(){let e=x();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 Xt=j(()=>{"use strict";y();Is();Ps();wt()});import{readFileSync as dt,readdirSync as qo,existsSync as Te,writeFileSync as $s,mkdirSync as zo,rmSync as Li,renameSync as Bi,cpSync as hy}from"fs";import{join as ue,dirname as Xc,resolve as Yc}from"path";import{homedir as yy}from"os";function Yo(){if(Un)return Un;try{return Te(Ji)?(Un=JSON.parse(dt(Ji,"utf-8")),Un):Hi()}catch{return Hi()}}function Xo(e){Un=e;try{zo(oe,{recursive:!0}),$s(Ji,JSON.stringify(e),"utf-8")}catch{}}function Hi(){if(!Te(oe))return[];let e=[];for(let t of qo(oe).filter(n=>n.endsWith(".json")&&n!=="_index.json"))try{let n=JSON.parse(dt(ue(oe,t),"utf-8")),s=n.templates||[];e.push({id:n.id,themeName:n.themeName,updatedAt:n.updatedAt,moduleCount:s.reduce((o,r)=>o+(r.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 Un=e,Xo(e),e}function Zc(e){let t=Yo(),n=e.templates||[],s={id:e.id,themeName:e.themeName,updatedAt:e.updatedAt,moduleCount:n.reduce((r,i)=>r+(i.modules?.length||0),0),templateCount:n.length,pageCount:n.filter(r=>r.contentMode!=="email").length,emailCount:n.filter(r=>r.contentMode==="email").length,hasBrandAssets:!!(e.brandAssets&&(e.brandAssets.styleguide||e.brandAssets.brandvoice||e.brandAssets.brandKit)),isImported:!!e.isImported},o=t.findIndex(r=>r.id===e.id);o>=0?t[o]=s:t.push(s),Xo(t)}function by(e){let t=Yo().filter(n=>n.id!==e);Xo(t)}function Sy(e){let t=Yo().filter(n=>n.themeName!==e);Xo(t)}function x(){return We}function Qc(){return`vibe-${Date.now().toString(36)}-${Math.random().toString(36).slice(2,8)}`}function Gn(e,t,n={}){let s={id:Qc(),themePath:e,themeName:t,isImported:!!n.isImported,templates:[],activeTemplateId:"",messages:[],modules:[],sharedCss:"",sharedJs:"",template:"",moduleOrder:[],createdAt:Date.now(),updatedAt:Date.now()};return We=s,Uo(e),s}function D(){if(!We)return;zo(oe,{recursive:!0});let e=ue(oe,`${We.id}.json`);$s(e,JSON.stringify(We,null,2),"utf-8"),Zc(We)}function Rs(e){let t=ue(oe,e+".json");if(!Te(t))return null;try{let n=JSON.parse(dt(t,"utf-8"));if(n.templates||(n.templates=[]),n.activeTemplateId||(n.activeTemplateId=""),Vo(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 We=n,n}catch{return null}}function ed(e){if(!Te(oe))return null;let t=Yc(e),n=null,s=-1;for(let o of qo(oe).filter(r=>r.endsWith(".json")&&r!=="_index.json"))try{let r=JSON.parse(dt(ue(oe,o),"utf-8"));if(!r.id||!r.themePath||Yc(r.themePath)!==t)continue;let i=typeof r.updatedAt=="number"?r.updatedAt:0;i>s&&(s=i,n=r.id)}catch{}return n}function Wn(){return Te(oe)?Yo():[]}function td(e,t=!1){let n=ue(oe,e+".json"),s="";if(t)try{let o=JSON.parse(dt(n,"utf-8"));s=o.themeName||"",o.themePath&&Te(o.themePath)&&Li(o.themePath,{recursive:!0,force:!0})}catch{}else try{s=JSON.parse(dt(n,"utf-8")).themeName||""}catch{}try{Te(n)&&Li(n)}catch{}if(s&&Te(oe)){for(let o of qo(oe).filter(r=>r.endsWith(".json")&&r!=="_index.json"))try{JSON.parse(dt(ue(oe,o),"utf-8")).themeName===s&&Li(ue(oe,o))}catch{}Sy(s)}else by(e);We?.id===e&&(We=null)}function nd(e,t){let n=ue(oe,e+".json");if(!Te(n))return{ok:!1,error:"Session not found"};let s;try{s=JSON.parse(dt(n,"utf-8"))}catch{return{ok:!1,error:"Failed to read session"}}let o=s.themeName;if(o===t)return{ok:!0};let r=s.themePath,i=ue(Xc(r),t);if(Te(r)){if(Te(i))return{ok:!1,error:"A project with that name already exists"};try{Bi(r,i)}catch(p){return{ok:!1,error:`Failed to rename folder: ${p instanceof Error?p.message:String(p)}`}}let a=ue(i,"css",`${o}-theme.css`),l=ue(i,"css",`${t}-theme.css`);if(Te(a))try{Bi(a,l)}catch{}let c=ue(i,"js",`${o}-animations.js`),d=ue(i,"js",`${t}-animations.js`);if(Te(c))try{Bi(c,d)}catch{}let u=ue(i,"theme.json");if(Te(u))try{let p=JSON.parse(dt(u,"utf-8"));p.label=t,p.name=t,$s(u,JSON.stringify(p,null,2),"utf-8")}catch{}}if(Te(oe))for(let a of qo(oe).filter(l=>l.endsWith(".json")&&l!=="_index.json"))try{let l=JSON.parse(dt(ue(oe,a),"utf-8"));l.themeName===o&&(l.themeName=t,l.themePath=i,l.updatedAt=Date.now(),$s(ue(oe,a),JSON.stringify(l,null,2),"utf-8"))}catch{}return We&&We.themeName===o&&(We.themeName=t,We.themePath=i,We.updatedAt=Date.now()),Hi(),{ok:!0}}function sd(e){let t=ue(oe,e+".json");if(!Te(t))return{ok:!1,error:"Session not found"};let n;try{n=JSON.parse(dt(t,"utf-8"))}catch{return{ok:!1,error:"Failed to read session"}}let s=n.themeName.replace(/-copy(-\d+)?$/,""),o=Xc(n.themePath),r=`${s}-copy`,i=1;for(;Te(ue(o,r));)i++,r=`${s}-copy-${i}`;let a=ue(o,r);if(Te(n.themePath))try{hy(n.themePath,a,{recursive:!0})}catch(d){return{ok:!1,error:`Failed to copy files: ${d instanceof Error?d.message:String(d)}`}}else zo(a,{recursive:!0});let l=Qc(),c={...JSON.parse(JSON.stringify(n)),id:l,themeName:r,themePath:a,createdAt:Date.now(),updatedAt:Date.now(),messages:[]};return zo(oe,{recursive:!0}),$s(ue(oe,`${l}.json`),JSON.stringify(c,null,2),"utf-8"),Zc(c),{ok:!0,newName:r,newSessionId:l}}var oe,Ji,Un,We,Is=j(()=>{"use strict";y();Hn();Xt();oe=ue(yy(),".vibespot","sessions"),Ji=ue(oe,"_index.json"),Un=null;We=null});import{readFileSync as vy,readdirSync as id,statSync as Ui}from"fs";import{createHash as xy}from"crypto";import{join as be,relative as wy}from"path";function er(e){let t=[];if(!w(e))return Vy(e,[{severity:"error",rule:"theme.path.missing",message:`Theme directory not found: ${e}`}]);let n=Qt(e),s=Uy(e),o=Wy(e),r=Ky(e),i=_y(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 r)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."});i.hasSnapshot&&i.filesChanged>0&&t.push({severity:"info",rule:"roundtrip.snapshot.diff",message:`${i.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=r.filter(l=>l.pattern==="hubl.macro").length;return{themePath:e,designTokens:n,graph:s,fieldFlags:o,roundTripRisks:r,roundTripDiff:i,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:i.filesChanged}}}function gn(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
177
|
${t.join(`
|
|
188
178
|
`)}
|
|
189
179
|
}
|
|
190
|
-
`}function
|
|
191
|
-
`),s}function Fc(e){let t=Ss(e);return x(t)?null:mr(e)}function Qf(e){let t=Ss(e);if(!x(t))return null;try{let n=JSON.parse(P(t));return wh(n)?n:null}catch{return null}}function eh(e){let t=Ss(e),n=Qf(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=jc(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:Jo(d.text),afterLines:Jo(u.text)}):r.push({file:d.path,status:"deleted",beforeSha256:d.sha256,beforeSize:d.size,beforeLines:Jo(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:Jo(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 Dn(e){let t=fh(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(ch.source,"g");for(;(g=h.exec(m))!==null;){let f=g[1],b=new RegExp(dh.source,"g"),S;for(;(S=b.exec(f))!==null;){let v=S[1].trim(),w=S[2].trim();n[v]||(n[v]=w);let $=w.match(/#[0-9a-fA-F]{3,8}\b|rgba?\([^)]+\)|hsla?\([^)]+\)/);if($){let j=Nc($[0]);o.set(j,v)}}}for(let f of[th,nh,sh]){let b=new RegExp(f.source,"g"),S;for(;(S=b.exec(m))!==null;){let v=Nc(S[0]);v&&s.set(v,(s.get(v)??0)+1)}}Lo(m,oh,i,mh),Lo(m,ih,r,f=>f.trim()),uh(m,a),Lo(m,ah,l,f=>f.trim()),Lo(m,lh,c,f=>f.trim())}let d=[...s.entries()].filter(([u])=>!gh(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 Lo(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 uh(e,t){let n=new RegExp(rh.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 mh(e){return e.split(",")[0].trim().replace(/^["']|["']$/g,"")}function Nc(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 gh(e){return ph.has(e)}function fh(e){let t=[],n=be(e,"css");if(x(n))for(let o of Vt(n))o.endsWith(".css")&&t.push(be(n,o));let s=be(e,"modules");if(x(s))for(let o of Vt(s)){if(!o.endsWith(".module"))continue;let i=be(s,o,"module.css");x(i)&&t.push(i)}return t}function hh(e){let t=be(e,"modules"),n=be(e,"templates"),s=new Set,o=new Map;if(x(t))for(let c of Vt(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 Vt(n)){if(!c.endsWith(".html")||c==="home.html")continue;let d=be(n,c),u;try{u=ur(d)}catch{continue}if(!u.isFile())continue;let m;try{m=P(d)}catch{continue}let g=pr(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:Ch(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 pr(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 bh(e){let t=[],n=be(e,"modules");if(!x(n))return t;for(let s of Vt(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)&&Dc(r,o,t,0)}return t}function Dc(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&&!yh.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)&&Dc(i.children,t,n,s+1)}}function Sh(e){let t=[],n=be(e,"modules");if(x(n))for(let i of Vt(n)){if(!i.endsWith(".module"))continue;let r=i.replace(/\.module$/,""),a=be(n,i,"module.html");x(a)&&Rc(a,e,r,t);let l=be(n,i,"module.js");if(x(l))try{P(l).trim().length>0&&t.push({file:gr(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 Vt(s)){if(!i.endsWith(".html"))continue;let r=be(s,i);if(!x(r))continue;let a;try{a=ur(r)}catch{continue}a.isFile()&&Rc(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 Rc(e,t,n,s){let o;try{o=P(e)}catch{return}let i=gr(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 vh(e,t){let n={hasSnapshot:!1,snapshotPath:Ss(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 jc(e){let t=[];function n(s){for(let o of Vt(s)){if(o===".git"||o===".vibespot"||o==="node_modules")continue;let i=be(s,o),r;try{r=ur(i)}catch{continue}if(r.isDirectory()){n(i);continue}if(!r.isFile())continue;let a=gr(e,i),l=Vf(i),c={path:a,sha256:zf("sha256").update(l).digest("hex"),size:l.length};xh(a)&&(c.text=l.toString("utf8")),t.push(c)}}return n(e),t.sort((s,o)=>s.path.localeCompare(o.path))}function xh(e){let t=e.lastIndexOf(".");return t<0?!1:Xf.has(e.slice(t).toLowerCase())}function wh(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 Jo(e){if(e!==void 0)return e.length===0?0:e.split(/\r\n|\r|\n/).length}function Vt(e){try{return Oc(e)}catch{return[]}}function gr(e,t){return Yf(e,t).split("\\").join("/")}function Ch(e){return[...new Set(e)]}var qf,Xf,th,nh,sh,oh,ih,rh,ah,lh,ch,dh,ph,yh,Uo=N(()=>{"use strict";y();oe();qf=".vibespot/import-snapshot.json",Xf=new Set([".css",".html",".htm",".js",".json",".md",".txt",".svg",".yml",".yaml"]);th=/#(?:[0-9a-fA-F]{3,4}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})\b/g,nh=/\brgba?\([^)]+\)/g,sh=/\bhsla?\([^)]+\)/g,oh=/font-family\s*:\s*([^;}\n]+)/g,ih=/font-size\s*:\s*([^;}\n]+)/g,rh=/(?:padding|margin|gap)(?:-(?:top|right|bottom|left))?\s*:\s*([^;}\n]+)/g,ah=/border-radius\s*:\s*([^;}\n]+)/g,lh=/box-shadow\s*:\s*([^;}\n]+)/g,ch=/:root\s*\{([\s\S]*?)\}/g,dh=/(--[\w-]+)\s*:\s*([^;}\n]+)/g;ph=new Set(["#000000","#ffffff","transparent","currentcolor","inherit","initial"]);yh=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 fr,readdirSync as xs,existsSync as xe,writeFileSync as Ye,mkdirSync as vs,rmSync as Lc}from"fs";import{join as U}from"path";function we(e){try{return fr(e,"utf-8")}catch{return""}}function Bc(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 kh(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=pr(n);return{id:s,label:a,pageType:i,contentMode:r,moduleNames:c,templateContent:n,filename:t}}function Th(e,t,n,s,o){if(!xe(e))return[];let i=[],r=xs(e).filter(a=>a.endsWith(".html")&&a!=="home.html");for(let a of r){let l=U(e,a),c=kh(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 Go(e){let t=C();if(!t)return;let n=vc(e);n.length>0&&t.messages.length===0&&(t.messages=n),Mo(e),Fc(e);let s=U(e,"modules");if(!xe(s))return;let o=xs(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$/,""),$={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};$.fieldsJson&&$.moduleHtml&&(t.modules.push($),t.moduleOrder.push(w))}let i=U(e,"css"),r=U(e,"js"),a="",l="";if(xe(i)){let S=xs(i).filter(v=>v.endsWith("-theme.css"));S.length>0&&(a=we(U(i,S[0])),t.sharedCss=a)}if(xe(r)){let S=xs(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=Dn(e),v=bs(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=Th(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($=>v.has($));for(let $ of t.moduleOrder)w.includes($)||w.push($);t.moduleOrder=w}an(b[0])}else t.templates||(t.templates=[]),t.activeTemplateId||(t.activeTemplateId=""),Ro(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");vs(s,{recursive:!0});for(let l of n.values())vs(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");vs(l,{recursive:!0}),Ye(U(l,`${e.themeName}-theme.css`),e.sharedCss,"utf-8")}if(e.sharedJs){let l=U(t,"js");vs(l,{recursive:!0}),Ye(U(l,`${e.themeName}-animations.js`),e.sharedJs,"utf-8")}let o=U(t,"templates");vs(o,{recursive:!0});let i=U(o,"home.html");(e.templates.length>0||e.modules.length>0)&&xe(i)&&Lc(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=Eh(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||$h(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"&&(Mh(o,l),a.add(`${l.id}-listing.html`))}else if(e.modules.length>0){let l=e.template||Ih(),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 xs(o))l.startsWith("lp-")&&l.endsWith(".html")&&!a.has(l)&&Lc(U(o,l),{force:!0})}catch{}Ah(),_h()}function Hc(){let e=C();e&&(e.modules=[],e.moduleOrder=[],e.sharedCss="",e.sharedJs="",e.template="",Go(e.themePath),e.updatedAt=Date.now(),at())}function Uc(){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))}an(t),e.updatedAt=Date.now()}function Ah(){let e=C();if(!e)return;let t=U(e.themePath,"templates","layouts","base.html");if(xe(t))try{let n=fr(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+`
|
|
180
|
+
`}function tr(e,t){let n=be(e,"css");if(w(n))try{for(let i of id(n))if(i.endsWith("-theme.css"))return null}catch{}let s=Qt(e),o=gn(s);if(!o)return null;let r=be(n,`${t}-theme.css`);return U(r,o),r}function Ns(e){return be(e,ky)}function Ty(e,t=new Date().toISOString()){return{version:1,createdAt:t,files:cd(e)}}function Gi(e,t){let n=Ty(e,t),s=Ns(e);return U(s,JSON.stringify(n,null,2)+`
|
|
181
|
+
`),s}function ad(e){let t=Ns(e);return w(t)?null:Gi(e)}function Ay(e){let t=Ns(e);if(!w(t))return null;try{let n=JSON.parse(I(t));return qy(n)?n:null}catch{return null}}function _y(e){let t=Ns(e),n=Ay(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=cd(e),r=new Map(o.map(d=>[d.path,d])),i=[];for(let d of n.files){let u=r.get(d.path);u?u.sha256!==d.sha256&&i.push({file:d.path,status:"modified",beforeSha256:d.sha256,afterSha256:u.sha256,beforeSize:d.size,afterSize:u.size,beforeLines:Qo(d.text),afterLines:Qo(u.text)}):i.push({file:d.path,status:"deleted",beforeSha256:d.sha256,beforeSize:d.size,beforeLines:Qo(d.text)})}for(let d of o)s.has(d.path)||i.push({file:d.path,status:"added",afterSha256:d.sha256,afterSize:d.size,afterLines:Qo(d.text)});i.sort((d,u)=>d.file.localeCompare(u.file));let a=i.filter(d=>d.status==="added").length,l=i.filter(d=>d.status==="modified").length,c=i.filter(d=>d.status==="deleted").length;return{hasSnapshot:!0,snapshotPath:t,filesChanged:i.length,added:a,modified:l,deleted:c,files:i}}function Qt(e){let t=Hy(e),n={},s=new Map,o=new Map,r=new Set,i=new Set,a=new Set,l=new Set,c=new Set;for(let u of t){let p;try{p=I(u)}catch{continue}let g,f=new RegExp(Fy.source,"g");for(;(g=f.exec(p))!==null;){let h=g[1],b=new RegExp(Dy.source,"g"),S;for(;(S=b.exec(h))!==null;){let v=S[1].trim(),k=S[2].trim();n[v]||(n[v]=k);let _=k.match(/#[0-9a-fA-F]{3,8}\b|rgba?\([^)]+\)|hsla?\([^)]+\)/);if(_){let M=od(_[0]);o.set(M,v)}}}for(let h of[Py,Ey,Iy]){let b=new RegExp(h.source,"g"),S;for(;(S=b.exec(p))!==null;){let v=od(S[0]);v&&s.set(v,(s.get(v)??0)+1)}}Zo(p,My,r,Ly),Zo(p,$y,i,h=>h.trim()),jy(p,a),Zo(p,Ny,l,h=>h.trim()),Zo(p,Oy,c,h=>h.trim())}let d=[...s.entries()].filter(([u])=>!Jy(u)).sort((u,p)=>p[1]-u[1]).slice(0,12).map(([u,p])=>({value:u,count:p,varName:o.get(u)}));return{cssVariables:n,palette:d,fontFamilies:[...r].slice(0,8),fontSizes:[...i].slice(0,16),spacing:[...a].slice(0,16),radii:[...l].slice(0,8),shadows:[...c].slice(0,8)}}function Zo(e,t,n,s){let o=new RegExp(t.source,"g"),r;for(;(r=o.exec(e))!==null;){let i=s(r[1]);i&&!i.startsWith("var(")&&n.add(i)}}function jy(e,t){let n=new RegExp(Ry.source,"g"),s;for(;(s=n.exec(e))!==null;){let o=s[1].trim();if(!o.startsWith("var("))for(let r of o.split(/\s+/))/^-?\d+(\.\d+)?(rem|em|px|%)$/.test(r)&&t.add(r)}}function Ly(e){return e.split(",")[0].trim().replace(/^["']|["']$/g,"")}function od(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 Jy(e){return By.has(e)}function Hy(e){let t=[],n=be(e,"css");if(w(n))for(let o of Zt(n))o.endsWith(".css")&&t.push(be(n,o));let s=be(e,"modules");if(w(s))for(let o of Zt(s)){if(!o.endsWith(".module"))continue;let r=be(s,o,"module.css");w(r)&&t.push(r)}return t}function Uy(e){let t=be(e,"modules"),n=be(e,"templates"),s=new Set,o=new Map;if(w(t))for(let c of Zt(t)){if(!c.endsWith(".module"))continue;let d=c.replace(/\.module$/,"");s.add(d),o.set(d,w(be(t,c,"module.js")))}let r=[],i=new Map;if(w(n))for(let c of Zt(n)){if(!c.endsWith(".html")||c==="home.html")continue;let d=be(n,c),u;try{u=Ui(d)}catch{continue}if(!u.isFile())continue;let p;try{p=I(d)}catch{continue}let g=Wi(p);for(let h of g){let b=i.get(h)??new Set;b.add(c),i.set(h,b)}let f=c.replace(/\.html$/,"");r.push({id:f,file:`templates/${c}`,modules:Yy(g)})}let a=[...s].sort().map(c=>({name:c,templates:[...i.get(c)??[]].sort(),hasJs:o.get(c)??!1})),l=a.filter(c=>c.templates.length===0).map(c=>c.name);return{templates:r,modules:a,orphanModules:l}}function Wi(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 r=o[1].match(/(?:^|\/)modules\/(.+)$/);if(!r)continue;let i=r[1].replace(/\.module$/,"");i&&t.push(i)}return t}function Wy(e){let t=[],n=be(e,"modules");if(!w(n))return t;for(let s of Zt(n)){if(!s.endsWith(".module"))continue;let o=s.replace(/\.module$/,""),r=be(n,s,"fields.json");if(!w(r))continue;let i;try{i=JSON.parse(I(r))}catch{continue}Array.isArray(i)&&ld(i,o,t,0)}return t}function ld(e,t,n,s){for(let o of e){if(typeof o!="object"||o===null)continue;let r=o,i=typeof r.name=="string"?r.name:"(unnamed)",a=typeof r.type=="string"?r.type:"";if(a==="group"&&s>=1&&n.push({module:t,field:i,reason:"deeply nested group (>1 level)"}),(a==="group"||a==="module")&&r.occurrence){let l=r.occurrence;l.max!==void 0&&l.max!==1&&n.push({module:t,field:i,reason:"repeater (occurrence) field"})}(a==="hubdb_table"||a==="hubdbtable")&&n.push({module:t,field:i,reason:"HubDB-backed field"}),(a==="crm_object"||a==="crm_object_property")&&n.push({module:t,field:i,reason:"CRM object field"}),a==="embed"&&typeof r.embed=="object"&&n.push({module:t,field:i,reason:"rich embed field"}),a&&!Gy.has(a)&&a!=="module"&&n.push({module:t,field:i,reason:`field type "${a}" not in vibeSpot's generation set`}),r.visibility&&typeof r.visibility=="object"&&n.push({module:t,field:i,reason:"conditional visibility rule"}),Array.isArray(r.children)&&ld(r.children,t,n,s+1)}}function Ky(e){let t=[],n=be(e,"modules");if(w(n))for(let r of Zt(n)){if(!r.endsWith(".module"))continue;let i=r.replace(/\.module$/,""),a=be(n,r,"module.html");w(a)&&rd(a,e,i,t);let l=be(n,r,"module.js");if(w(l))try{I(l).trim().length>0&&t.push({file:Ki(e,l),pattern:"module.js.custom",detail:`${i}: module ships custom JS \u2014 preserve verbatim`})}catch{}}let s=be(e,"templates");if(w(s))for(let r of Zt(s)){if(!r.endsWith(".html"))continue;let i=be(s,r);if(!w(i))continue;let a;try{a=Ui(i)}catch{continue}a.isFile()&&rd(i,e,r,t)}let o=be(e,"import_modules.json");return w(o)&&t.push({file:"import_modules.json",pattern:"theme.import_modules",detail:"Theme declares import_modules.json \u2014 preserve to avoid breaking HubSpot pre-install"}),t}function rd(e,t,n,s){let o;try{o=I(e)}catch{return}let r=Ki(t,e);/{%\s*macro\s+\w+/.test(o)&&s.push({file:r,pattern:"hubl.macro",detail:`${n}: contains custom HubL {% macro %}`}),/{%\s*raw\s*%}/.test(o)&&s.push({file:r,pattern:"hubl.raw",detail:`${n}: contains {% raw %} block`});let i=/{%\s*include\s+["']([^"']+)["']/g,a;for(;(a=i.exec(o))!==null;){let l=a[1];!l.startsWith("../modules/")&&!l.startsWith("./modules/")&&!l.includes("/layouts/")&&s.push({file:r,pattern:"hubl.include",detail:`${n}: includes partial "${l}" outside modules/`})}}function Vy(e,t){let n={hasSnapshot:!1,snapshotPath:Ns(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 cd(e){let t=[];function n(s){for(let o of Zt(s)){if(o===".git"||o===".vibespot"||o==="node_modules")continue;let r=be(s,o),i;try{i=Ui(r)}catch{continue}if(i.isDirectory()){n(r);continue}if(!i.isFile())continue;let a=Ki(e,r),l=vy(r),c={path:a,sha256:xy("sha256").update(l).digest("hex"),size:l.length};zy(a)&&(c.text=l.toString("utf8")),t.push(c)}}return n(e),t.sort((s,o)=>s.path.localeCompare(o.path))}function zy(e){let t=e.lastIndexOf(".");return t<0?!1:Cy.has(e.slice(t).toLowerCase())}function qy(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 Qo(e){if(e!==void 0)return e.length===0?0:e.split(/\r\n|\r|\n/).length}function Zt(e){try{return id(e)}catch{return[]}}function Ki(e,t){return wy(e,t).split("\\").join("/")}function Yy(e){return[...new Set(e)]}var ky,Cy,Py,Ey,Iy,My,$y,Ry,Ny,Oy,Fy,Dy,By,Gy,Os=j(()=>{"use strict";y();ae();ky=".vibespot/import-snapshot.json",Cy=new Set([".css",".html",".htm",".js",".json",".md",".txt",".svg",".yml",".yaml"]);Py=/#(?:[0-9a-fA-F]{3,4}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})\b/g,Ey=/\brgba?\([^)]+\)/g,Iy=/\bhsla?\([^)]+\)/g,My=/font-family\s*:\s*([^;}\n]+)/g,$y=/font-size\s*:\s*([^;}\n]+)/g,Ry=/(?:padding|margin|gap)(?:-(?:top|right|bottom|left))?\s*:\s*([^;}\n]+)/g,Ny=/border-radius\s*:\s*([^;}\n]+)/g,Oy=/box-shadow\s*:\s*([^;}\n]+)/g,Fy=/:root\s*\{([\s\S]*?)\}/g,Dy=/(--[\w-]+)\s*:\s*([^;}\n]+)/g;By=new Set(["#000000","#ffffff","transparent","currentcolor","inherit","initial"]);Gy=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 Vi,readdirSync as Ds,existsSync as we,writeFileSync as Ye,mkdirSync as Fs,rmSync as dd}from"fs";import{join as q}from"path";function ke(e){try{return Vi(e,"utf-8")}catch{return""}}function nr(e,t){return ws(t)?q(e,t):(A.warn("session-disk","Skipping template with unsafe filename",{filename:t}),null)}function pd(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 Xy(e,t){let n=ke(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),r="landing_page",i;o?(r="module_only",i="email"):s.startsWith("bp-")||/templateType:\s*blog_post\b/i.test(n)?r="blog_post":s.startsWith("wp-")?r="website_page":s.startsWith("mo-")&&(r="module_only");let a=s,l=n.match(/<!--[\s\S]*?label:\s*"?([^"\n]+)"?\s*[\s\S]*?-->/);l&&(a=l[1].trim());let c=Wi(n);return{id:s,label:a,pageType:r,contentMode:i,moduleNames:c,templateContent:n,filename:t}}function Zy(e,t,n,s,o){if(!we(e))return[];let r=[],i=Ds(e).filter(a=>a.endsWith(".html")&&a!=="home.html");for(let a of i){let l=q(e,a),c=Xy(l,a);if(!c||c.moduleNames.length===0&&r.length>0)continue;let d=[],u=[];for(let p of c.moduleNames){let g=t.get(p);g&&(d.push(g),u.push(p))}r.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:r.length===0?[...o]:[]})}return r}function sr(e){let t=x();if(!t)return;let n=Uc(e);n.length>0&&t.messages.length===0&&(t.messages=n),Uo(e),ad(e);let s=q(e,"modules");if(!we(s))return;let o=Ds(s,{withFileTypes:!0});for(let S of o){if(!S.isDirectory()||!S.name.endsWith(".module"))continue;let v=q(s,S.name),k=S.name.replace(/\.module$/,""),_={moduleName:k,fieldsJson:ke(q(v,"fields.json")),metaJson:ke(q(v,"meta.json")),moduleHtml:ke(q(v,"module.html")),moduleCss:ke(q(v,"module.css")),moduleJs:ke(q(v,"module.js"))||void 0};_.fieldsJson&&_.moduleHtml&&(t.modules.push(_),t.moduleOrder.push(k))}let r=q(e,"css"),i=q(e,"js"),a="",l="";if(we(r)){let S=Ds(r).filter(v=>v.endsWith("-theme.css"));S.length>0&&(a=ke(q(r,S[0])),t.sharedCss=a)}if(we(i)){let S=Ds(i).filter(v=>v.endsWith("-animations.js"));S.length>0&&(l=ke(q(i,S[0])),t.sharedJs=l)}if(!a&&t.modules.length>0){let S=Qt(e),v=gn(S);v&&(t.sharedCss=v,a=v)}let c=q(e,".vibespot","styleguide.md"),d=q(e,".vibespot","brandvoice.md"),u=q(e,".vibespot","theme-context.md"),p=q(e,".vibespot","plan.md"),g=q(e,".vibespot","brand-kit.json");if((we(c)||we(d)||we(u)||we(p)||we(g))&&(t.brandAssets||(t.brandAssets={}),we(c)&&(t.brandAssets.styleguide=ke(c)),we(d)&&(t.brandAssets.brandvoice=ke(d)),we(u)&&(t.brandAssets.themeContext=ke(u)),we(p)&&(t.brandAssets.plan=ke(p)),we(g)))try{t.brandAssets.brandKit=JSON.parse(ke(g))}catch{}let f=q(e,"templates"),h=new Map(t.modules.map(S=>[S.moduleName,S])),b=Zy(f,h,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),k=S.filter(_=>v.has(_));for(let _ of t.moduleOrder)k.includes(_)||k.push(_);t.moduleOrder=k}mn(b[0])}else t.templates||(t.templates=[]),t.activeTemplateId||(t.activeTemplateId=""),Vo(t)}function Ae(){let e=x();if(!e)return;let t=e.themePath,n=new Map;if(e.templates.length>0)for(let c of e.templates)for(let d of c.modules)n.set(d.moduleName,d);for(let c of e.modules)n.set(c.moduleName,c);let s=q(t,"modules"),o=[];for(let c of n.values())try{o.push({mod:c,modDir:dn(s,c.moduleName)})}catch{A.warn("session-disk","Skipping module with unsafe name",{name:c.moduleName})}Fs(s,{recursive:!0});for(let{modDir:c}of o)Fs(c,{recursive:!0});for(let{mod:c,modDir:d}of o)Ye(q(d,"fields.json"),c.fieldsJson,"utf-8"),Ye(q(d,"meta.json"),c.metaJson,"utf-8"),Ye(q(d,"module.html"),c.moduleHtml,"utf-8"),Ye(q(d,"module.css"),c.moduleCss,"utf-8"),c.moduleJs&&Ye(q(d,"module.js"),c.moduleJs,"utf-8");if(e.sharedCss){let c=q(t,"css");Fs(c,{recursive:!0}),Ye(q(c,`${e.themeName}-theme.css`),e.sharedCss,"utf-8")}if(e.sharedJs){let c=q(t,"js");Fs(c,{recursive:!0}),Ye(q(c,`${e.themeName}-animations.js`),e.sharedJs,"utf-8")}let r=q(t,"templates");Fs(r,{recursive:!0});let i=q(r,"home.html");(e.templates.length>0||e.modules.length>0)&&we(i)&&dd(i,{force:!0});let l=new Set;if(e.templates.length>0)for(let c of e.templates){if(c.contentMode==="email"){if(c.modules.length===0)continue;let f=nb(c),h=c.templateFile?c.templateFile.replace("templates/",""):"email.html",b=nr(r,h);if(!b)continue;Ye(b,f,"utf-8"),l.add(h);continue}if(c.pageType==="module_only"||c.modules.length===0)continue;let d=c.template||tb(c),u=ud(d,c.label,c.pageType),p=`${c.id}.html`,g=nr(r,p);g&&(Ye(g,u,"utf-8"),l.add(p),c.pageType==="blog_post"&&(sb(r,c),l.add(`${c.id}-listing.html`)))}else if(e.modules.length>0){let c=e.template||ob(),d=ud(c,`${e.themeName} Landing Page`),u=`lp-${e.themeName}.html`,p=nr(r,u);p&&(Ye(p,d,"utf-8"),l.add(u))}try{for(let c of Ds(r))c.startsWith("lp-")&&c.endsWith(".html")&&!l.has(c)&&dd(q(r,c),{force:!0})}catch{}Qy(),eb()}function md(){let e=x();e&&(e.modules=[],e.moduleOrder=[],e.sharedCss="",e.sharedJs="",e.template="",sr(e.themePath),e.updatedAt=Date.now(),lt())}function gd(){let e=x();if(!e)return;let t=xe();if(!t)return;let n=e.themePath,s=q(n,"modules");t.modules=[];for(let o of t.moduleOrder){let r;try{r=dn(s,o)}catch{A.warn("session-disk","Skipping module with unsafe name",{name:o});continue}if(!we(r))continue;let i={moduleName:o,fieldsJson:ke(q(r,"fields.json")),metaJson:ke(q(r,"meta.json")),moduleHtml:ke(q(r,"module.html")),moduleCss:ke(q(r,"module.css")),moduleJs:ke(q(r,"module.js"))||void 0};i.fieldsJson&&i.moduleHtml&&t.modules.push(i)}if(t.templateFile)try{let o=Ln(n,t.templateFile);we(o)&&(t.template=ke(o))}catch{A.warn("session-disk","Skipping template file outside theme",{templateFile:t.templateFile})}mn(t),e.updatedAt=Date.now()}function Qy(){let e=x();if(!e)return;let t=q(e.themePath,"templates","layouts","base.html");if(we(t))try{let n=Vi(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
182
|
{% if template_js %}
|
|
193
183
|
{{ require_js(get_asset_url(template_js)) }}
|
|
194
184
|
{% endif %}`):n=n.replace("{{ standard_footer_includes }}",`{% if template_js %}
|
|
195
185
|
{{ require_js(get_asset_url(template_js)) }}
|
|
196
186
|
{% endif %}
|
|
197
|
-
{{ standard_footer_includes }}`),Ye(t,n,"utf-8")}catch{}}function
|
|
187
|
+
{{ standard_footer_includes }}`),Ye(t,n,"utf-8")}catch{}}function eb(){let e=x();if(!e)return;let t=q(e.themePath,"theme.json");if(we(t))try{let n=JSON.parse(Vi(t,"utf-8"));n.label=e.themeName,n.name=e.themeName,Ye(t,JSON.stringify(n,null,2),"utf-8")}catch{}}function ud(e,t,n="landing_page"){return e.includes("templateType")?e:`<!--
|
|
198
188
|
templateType: ${n==="blog_post"?"blog_post":"page"}
|
|
199
189
|
isAvailableForNewContent: true
|
|
200
190
|
label: "${t}"
|
|
201
191
|
-->
|
|
202
|
-
`+e}function
|
|
203
|
-
{% dnd_module path="../modules/${
|
|
192
|
+
`+e}function tb(e){if(e.modules.length===0)return"";let n=x().themeName,o=pd(e).map(i=>` {% dnd_section padding={"top":"0","bottom":"0","left":"0","right":"0"}, full_width=true %}
|
|
193
|
+
{% dnd_module path="../modules/${i.moduleName}.module" %}
|
|
204
194
|
{% end_dnd_module %}
|
|
205
195
|
{% end_dnd_section %}`).join(`
|
|
206
196
|
|
|
@@ -230,7 +220,7 @@ ${o}
|
|
|
230
220
|
|
|
231
221
|
{% block footer %}
|
|
232
222
|
{% endblock footer %}
|
|
233
|
-
`}function
|
|
223
|
+
`}function nb(e){let n=pd(e).map(s=>` {% dnd_section %}
|
|
234
224
|
{% dnd_module path="../modules/${s.moduleName}.module" %}
|
|
235
225
|
{% end_dnd_module %}
|
|
236
226
|
{% end_dnd_section %}`).join(`
|
|
@@ -277,7 +267,7 @@ ${n}
|
|
|
277
267
|
{{ standard_footer_includes }}
|
|
278
268
|
</body>
|
|
279
269
|
</html>
|
|
280
|
-
`}function
|
|
270
|
+
`}function sb(e,t){let n=`<!--
|
|
281
271
|
templateType: blog_listing
|
|
282
272
|
isAvailableForNewContent: true
|
|
283
273
|
label: "${t.label} - Listing"
|
|
@@ -302,7 +292,7 @@ ${n}
|
|
|
302
292
|
{% endif %}
|
|
303
293
|
</div>
|
|
304
294
|
{% endblock body %}
|
|
305
|
-
|
|
295
|
+
`,s=nr(e,`${t.id}-listing.html`);s&&Ye(s,n,"utf-8")}function ob(){let e=x();if(!e||e.modules.length===0)return"";let t=e.themeName,s=pe().map(o=>` {% dnd_section padding={"top":"0","bottom":"0","left":"0","right":"0"}, full_width=true %}
|
|
306
296
|
{% dnd_module path="../modules/${o.moduleName}.module" %}
|
|
307
297
|
{% end_dnd_module %}
|
|
308
298
|
{% end_dnd_section %}`).join(`
|
|
@@ -333,163 +323,11 @@ ${s}
|
|
|
333
323
|
|
|
334
324
|
{% block footer %}
|
|
335
325
|
{% endblock footer %}
|
|
336
|
-
`}var
|
|
337
|
-
|
|
338
|
-
`),s=e.renderedModules.join(`
|
|
339
|
-
`);return`<!DOCTYPE html>
|
|
340
|
-
<html lang="en">
|
|
341
|
-
<head>
|
|
342
|
-
<meta charset="utf-8">
|
|
343
|
-
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
344
|
-
${t}
|
|
345
|
-
<style>
|
|
346
|
-
html{scroll-behavior:smooth}
|
|
347
|
-
.vsp-img-wrap{position:relative;display:inline-block}
|
|
348
|
-
.vsp-img-badge{position:absolute;top:8px;right:8px;background:rgba(0,0,0,.75);color:#fff;font:500 11px/1 -apple-system,sans-serif;padding:5px 8px;border-radius:4px;pointer-events:none;opacity:.85;white-space:nowrap;z-index:10}
|
|
349
|
-
</style>
|
|
350
|
-
</head>
|
|
351
|
-
<body>
|
|
352
|
-
${s}
|
|
353
|
-
${n}
|
|
354
|
-
<script>
|
|
355
|
-
// Anchor link handler \u2014 smooth scroll to module sections
|
|
356
|
-
document.addEventListener('click',function(e){
|
|
357
|
-
var a=e.target.closest('a[href^="#"]');
|
|
358
|
-
if(!a)return;
|
|
359
|
-
var id=a.getAttribute('href').slice(1);
|
|
360
|
-
if(!id)return;
|
|
361
|
-
var el=document.getElementById(id);
|
|
362
|
-
if(el){
|
|
363
|
-
e.preventDefault();
|
|
364
|
-
el.scrollIntoView({behavior:'smooth',block:'start'});
|
|
365
|
-
}
|
|
366
|
-
});
|
|
367
|
-
// Placeholder image badges
|
|
368
|
-
document.querySelectorAll('img').forEach(function(img){
|
|
369
|
-
var src=img.src||img.getAttribute('src')||'';
|
|
370
|
-
if(src.indexOf('placehold')!==-1){
|
|
371
|
-
var w=document.createElement('span');
|
|
372
|
-
w.className='vsp-img-wrap';
|
|
373
|
-
img.parentNode.insertBefore(w,img);
|
|
374
|
-
w.appendChild(img);
|
|
375
|
-
var b=document.createElement('span');
|
|
376
|
-
b.className='vsp-img-badge';
|
|
377
|
-
b.textContent='Placeholder \u2014 replace in HubSpot';
|
|
378
|
-
w.appendChild(b);
|
|
379
|
-
}
|
|
380
|
-
});
|
|
381
|
-
</script>
|
|
382
|
-
</body>
|
|
383
|
-
</html>`}function Jh(e){return e=e.replace(Ph,""),e=e.replace(Nh,""),e=e.replace(Rh,""),Wc.lastIndex=0,e=e.replace(Wc,(t,n)=>`/theme-assets/${n}`),Kc.lastIndex=0,e=e.replace(Kc,""),e=e.replace(Oh,""),e=e.replace(Fh,""),e=e.replace(Dh,""),e=e.replace(jh,""),e=e.replace(Lh,""),e}function zc(e,t){let n=e,s=0;for(;s<30;){s++;let o=Bh(n);if(!o)break;let{varName:i,iterExpr:r,body:a,start:l,end:c}=o,d=Uh(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=zc(a,h);return f=Yc(f,h),f=qc(f,h),f}).join("")),n=n.slice(0,l)+u+n.slice(c)}return n}function Bh(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 Yc(e,t){let n=e,s=0;for(;yr.test(n)&&s<50;)s++,n=n.replace(yr,(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(jn(i,t))return d[0];for(let u=1;u<d.length;u+=2){let m=d[u],g=d[u+1]||"";if(jn(m,t))return g}return c}return jn(i,t)?l:c}),yr.lastIndex=0;return n}function qc(e,t){return e.replace(/\{\{[-\s]*(.*?)[-\s]*\}\}/g,(n,s)=>{let i=s.trim().split("|"),r=i[0].trim(),a=Gh(t,r);for(let c=1;c<i.length;c++)a=Zc(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 Hh(e){return e=e.replace(/\{%.*?%\}/gs,""),e=e.replace(/\{\{.*?\}\}/gs,""),e}function Uh(e,t){let n=e.match(/^range\(\s*(.+?)\s*,\s*(.+?)\s*\)$/);if(n){let o=Vc(n[1],t),i=Vc(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=zt(t,s[1].trim());return typeof o=="string"?o.split(s[2]):[]}return zt(t,e)}function Vc(e,t){let s=e.trim().split("|"),o=s[0].trim();if(!isNaN(Number(o)))return Number(o);let i=zt(t,o);for(let r=1;r<s.length;r++)i=Zc(i,s[r].trim());return Number(i)||0}function zt(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 Gh(e,t){let n=t.match(/^(.+?)\s*([*/])\s*([\d.]+)$/);if(n){let s=zt(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 zt(e,t)}function jn(e,t){let n=e.trim();if(n.startsWith("not "))return!jn(n.slice(4),t);if(n.includes(" and "))return n.split(" and ").every(i=>jn(i,t));if(n.includes(" or "))return n.split(" or ").some(i=>jn(i,t));let s=n.match(/^(.+?)\s*(==|!=|>=|<=|>|<)\s*(.+)$/);if(s){let i=zt(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=zt(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=zt(t,n);return Xc(o)}function Xc(e){return!(e==null||e===""||e===0||e===!1||Array.isArray(e)&&e.length===0)}function Zc(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 Xc(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=br(e);return r?Kh(r):""}default:return e}}function br(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?Wh(t[1]):null}if(typeof e=="object"){let t=e;if(typeof t.color=="string")return br(t.color);if(typeof t.hex=="string")return br(t.hex)}return null}function Wh(e){let t=e.toLowerCase();return t.length===3?t.split("").map(n=>n+n).join(""):t}function Kh(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 Ph,Nh,Rh,Wc,Kc,Oh,Fh,Dh,jh,Lh,yr,vr=N(()=>{"use strict";y();Ph=/\{%[-\s]*require_(css|js)\b.*?%\}/gs,Nh=/\{%[-\s]*end_require_(css|js)\s*%\}/gs,Rh=/\{\{[-\s]*require_(css|js)\(.*?\)\s*\}\}/gs,Wc=/\{\{[-\s]*get_asset_url\(["'](?:[^"'\/]+\/)?assets\/(.*?)["']\)\s*\}\}/gs,Kc=/\{\{[-\s]*get_asset_url\(.*?\)\s*\}\}/gs,Oh=/\{%[-\s]*(end_)?(dnd_area|dnd_section|dnd_column|dnd_row|dnd_module)\b.*?%\}/gs,Fh=/\{%[-\s]*module\b.*?%\}/gs,Dh=/\{%[-\s]*(extends|block|endblock|set)\b.*?%\}/gs,jh=/\{#.*?#\}/gs,Lh=/\{\{[-\s]*content\.\w+.*?\}\}/gs,yr=/\{%[-\s]*if\s+(.*?)\s*-?%\}((?:(?!\{%[-\s]*if\s)[\s\S])*?)\{%[-\s]*endif\s*-?%\}/g});var Wo={};Ge(Wo,{buildModulePreviewHtml:()=>Cr,buildPreviewHtml:()=>wr});function Vh(e){if(Jn()==="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 zh(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 xr(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 wr(){let e=C();if(!e)return Qc();let t=ve(),n=e.moduleOrder||[];if(t.length===0&&n.length===0)return Qc();if(Vh(t))return Yh(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:ln(u)}}catch{d={module:{}}}let m=xr(c.moduleHtml,u),g=Ln(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=zh(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
|
-
<div class="vibespot-placeholder">
|
|
385
|
-
<div class="vibespot-placeholder__name">${c}</div>
|
|
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 Sr({renderedModules:s,sharedCss:e.sharedCss,moduleCssArray:[l,...o],sharedJs:e.sharedJs,moduleJsArray:i})}function Qc(){return`<!DOCTYPE html>
|
|
388
|
-
<html lang="en">
|
|
389
|
-
<head>
|
|
390
|
-
<meta charset="utf-8">
|
|
391
|
-
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
392
|
-
<style>
|
|
393
|
-
* { margin: 0; padding: 0; box-sizing: border-box; }
|
|
394
|
-
body {
|
|
395
|
-
min-height: 100vh;
|
|
396
|
-
display: flex;
|
|
397
|
-
align-items: center;
|
|
398
|
-
justify-content: center;
|
|
399
|
-
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
|
|
400
|
-
background: #0f0f14;
|
|
401
|
-
color: #888;
|
|
402
|
-
}
|
|
403
|
-
.welcome {
|
|
404
|
-
text-align: center;
|
|
405
|
-
padding: 2rem;
|
|
406
|
-
}
|
|
407
|
-
.welcome__wave {
|
|
408
|
-
font-size: 4rem;
|
|
409
|
-
margin-bottom: 1.2rem;
|
|
410
|
-
opacity: 0.4;
|
|
411
|
-
animation: float 3s ease-in-out infinite;
|
|
412
|
-
}
|
|
413
|
-
@keyframes float {
|
|
414
|
-
0%, 100% { transform: translateY(0); }
|
|
415
|
-
50% { transform: translateY(-6px); }
|
|
416
|
-
}
|
|
417
|
-
.welcome__title {
|
|
418
|
-
font-size: 1.4rem;
|
|
419
|
-
font-weight: 600;
|
|
420
|
-
color: #bbb;
|
|
421
|
-
letter-spacing: 0.5px;
|
|
422
|
-
margin-bottom: 0.4rem;
|
|
423
|
-
}
|
|
424
|
-
.welcome__sub {
|
|
425
|
-
font-size: 1rem;
|
|
426
|
-
color: #666;
|
|
427
|
-
font-weight: 300;
|
|
428
|
-
}
|
|
429
|
-
</style>
|
|
430
|
-
</head>
|
|
431
|
-
<body>
|
|
432
|
-
<div class="welcome">
|
|
433
|
-
<div class="welcome__wave">\u224B</div>
|
|
434
|
-
<div class="welcome__title">vibeSpot</div>
|
|
435
|
-
<div class="welcome__sub">Build Something Great</div>
|
|
436
|
-
</div>
|
|
437
|
-
</body>
|
|
438
|
-
</html>`}function Cr(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:ln(o)}}catch{s={module:{}}}let i=xr(n.moduleHtml,o),r=Ln(i,s);return Sr({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 Yh(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:ln(a)}}catch{r={module:{}}}let l=xr(i.moduleHtml,a),c=Ln(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
|
-
<table role="presentation" cellpadding="0" cellspacing="0" border="0" width="100%" style="max-width:600px;margin:0 auto;">
|
|
440
|
-
<tr><td style="padding:40px 30px;text-align:center;background-color:#ffffff;border:1px dashed #ddd;">
|
|
441
|
-
<p style="font-family:Arial,Helvetica,sans-serif;font-size:14px;color:#999;">${i}</p>
|
|
442
|
-
</td></tr>
|
|
443
|
-
</table>
|
|
444
|
-
</div>`)}return`<!DOCTYPE html>
|
|
445
|
-
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
|
|
446
|
-
<head>
|
|
447
|
-
<meta charset="utf-8">
|
|
448
|
-
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
449
|
-
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
|
450
|
-
<title>Email Preview</title>
|
|
451
|
-
<style>
|
|
452
|
-
html, body { margin: 0; padding: 0; overflow-x: hidden; }
|
|
453
|
-
body {
|
|
454
|
-
background-color: #e8e8e8;
|
|
455
|
-
font-family: Arial, Helvetica, sans-serif;
|
|
456
|
-
-webkit-font-smoothing: antialiased;
|
|
457
|
-
}
|
|
458
|
-
.vibespot-email-wrapper {
|
|
459
|
-
padding: 30px 20px;
|
|
460
|
-
background-color: #e8e8e8;
|
|
461
|
-
min-height: 100vh;
|
|
462
|
-
}
|
|
463
|
-
.vibespot-module { margin: 0 auto; max-width: 600px; }
|
|
464
|
-
.vibespot-module--pending table { opacity: 0.6; }
|
|
465
|
-
html { scroll-behavior: smooth; }
|
|
466
|
-
img { max-width: 100% !important; height: auto !important; }
|
|
467
|
-
table { max-width: 100% !important; }
|
|
468
|
-
td { word-break: break-word; }
|
|
469
|
-
@media screen and (max-width: 620px) {
|
|
470
|
-
.vibespot-email-wrapper { padding: 10px 8px; }
|
|
471
|
-
table[width] { width: 100% !important; }
|
|
472
|
-
img[width] { width: 100% !important; height: auto !important; }
|
|
473
|
-
}
|
|
474
|
-
</style>
|
|
475
|
-
</head>
|
|
476
|
-
<body>
|
|
477
|
-
<div class="vibespot-email-wrapper">
|
|
478
|
-
${n.join(`
|
|
479
|
-
`)}
|
|
480
|
-
</div>
|
|
481
|
-
<script>
|
|
482
|
-
document.addEventListener('click', function(e) {
|
|
483
|
-
var a = e.target.closest('a[href^="#"]');
|
|
484
|
-
if (a) { e.preventDefault(); var t = document.querySelector(a.getAttribute('href')); if (t) t.scrollIntoView({ behavior: 'smooth' }); }
|
|
485
|
-
});
|
|
486
|
-
</script>
|
|
487
|
-
</body>
|
|
488
|
-
</html>`}var ws=N(()=>{"use strict";y();vr();Ce();Cs()});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 ks(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 kr(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 ed(e,t){let n=!1,s,o=/```vibespot-modules\s*\n?([\s\S]*?)```/g;for(;(s=o.exec(e))!==null;)try{M.info("parse","Found vibespot-modules block",{length:s[1].length});let i=ct(s[1]);if(!i||typeof i!="object")throw M.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=>kr(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){M.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=>kr(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){M.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"')){M.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=ks(a);if(l){let c=l;c.modules&&Array.isArray(c.modules)&&c.modules.length>0&&(M.info("parse","Salvaged modules from truncated response",{count:c.modules.length}),He({modules:c.modules.map(d=>kr(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){M.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.";M.warn("parse",a),t&&t(a)}}}var Ko=N(()=>{"use strict";y();Ce();le()});function Hn(){let e=C();return e?{pageType:ke()?.pageType,brandAssets:e.brandAssets}:{}}function nd(e,t,n=!1,s,o){let r=[{type:"text",text:Xh(t,n)}];if(n){let l=`## HubSpot CMS Rules
|
|
489
|
-
${Je()}
|
|
326
|
+
`}var zi=j(()=>{"use strict";y();Is();Ps();Xt();Hn();re();wt();Os()});var fd=j(()=>{"use strict";y();_c();Is();Ps();zi();Xt()});var me=j(()=>{"use strict";y();fd()});function Vn(){let e=x();return e?{pageType:xe()?.pageType,brandAssets:e.brandAssets}:{}}function qi(e,t,n=!1,s,o){let i=[{type:"text",text:ib(t,n)}];if(n){let l=`## HubSpot CMS Rules
|
|
327
|
+
${et()}
|
|
490
328
|
|
|
491
329
|
## Conversion Guide Reference
|
|
492
|
-
${e}`;
|
|
330
|
+
${e}`;i.push({type:"text",text:l,cache_control:{type:"ephemeral"}})}else{let l=`## Design Quality
|
|
493
331
|
- Use modern, clean design with proper spacing and typography
|
|
494
332
|
- Include responsive CSS (mobile breakpoint at 767px)
|
|
495
333
|
- Add scroll animation classes where appropriate
|
|
@@ -512,22 +350,22 @@ When using scroll-animate classes (opacity: 0 \u2192 visible), you MUST include
|
|
|
512
350
|
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
351
|
|
|
514
352
|
## Design Guide
|
|
515
|
-
${
|
|
353
|
+
${No()}
|
|
516
354
|
|
|
517
355
|
## Content & Copywriting Guide
|
|
518
|
-
${
|
|
356
|
+
${ac()}
|
|
519
357
|
|
|
520
358
|
## HubSpot CMS Rules
|
|
521
|
-
${
|
|
359
|
+
${et()}
|
|
522
360
|
|
|
523
361
|
## Conversion Guide Reference
|
|
524
|
-
${e}`;
|
|
362
|
+
${e}`;i.push({type:"text",text:l,cache_control:{type:"ephemeral"}})}let a=rb(s,o);return a&&i.push({type:"text",text:a}),i.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."}),i}function rb(e,t){let n=[];if(e){let s=uc(e);s&&n.push(`## Page Type Context
|
|
525
363
|
${s}`)}if(t?.styleguide&&n.push(`## Brand Style Guide
|
|
526
364
|
${t.styleguide}`),t?.brandvoice&&n.push(`## Brand Voice
|
|
527
|
-
${t.brandvoice}`),t?.humanify!==!1){let s=
|
|
365
|
+
${t.brandvoice}`),t?.humanify!==!1){let s=lc();s&&n.push(`## Anti-AI Copy Rules (Humanify)
|
|
528
366
|
${s}`)}return n.join(`
|
|
529
367
|
|
|
530
|
-
`)}function
|
|
368
|
+
`)}function ib(e,t){return`You are vibeSpot, an AI that builds HubSpot CMS landing pages from natural language descriptions.
|
|
531
369
|
|
|
532
370
|
## Your Role
|
|
533
371
|
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,241 +444,265 @@ The current template's modules are listed in page order in the user message. Thi
|
|
|
606
444
|
- **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
445
|
- **Remove**: When the user asks to remove a section, omit it from the output.
|
|
608
446
|
- **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
|
|
610
|
-
|
|
611
|
-
## Your Role
|
|
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.
|
|
613
|
-
|
|
614
|
-
## Output Format \u2014 CRITICAL
|
|
615
|
-
You MUST include a \`\`\`vibespot-modules code block with ALL module data as JSON. This is the ONLY way modules get created. A text summary, table, or description of modules does NOT work \u2014 you must output the actual JSON.
|
|
616
|
-
|
|
617
|
-
\`\`\`vibespot-modules
|
|
618
|
-
{
|
|
619
|
-
"modules": [
|
|
620
|
-
{
|
|
621
|
-
"moduleName": "Hero",
|
|
622
|
-
"fieldsJson": "...",
|
|
623
|
-
"metaJson": "...",
|
|
624
|
-
"moduleHtml": "...",
|
|
625
|
-
"moduleCss": "...",
|
|
626
|
-
"moduleJs": null
|
|
627
|
-
}
|
|
628
|
-
],
|
|
629
|
-
"sharedCss": "...",
|
|
630
|
-
"sharedJs": "..."
|
|
631
|
-
}
|
|
632
|
-
\`\`\`
|
|
633
|
-
|
|
634
|
-
NEVER respond with only a text summary. The vibespot-modules JSON block is mandatory.
|
|
635
|
-
|
|
636
|
-
## Rules
|
|
637
|
-
- fieldsJson, metaJson must be valid JSON strings
|
|
638
|
-
- moduleHtml uses HubL template syntax ({{ module.field_name }})
|
|
639
|
-
- moduleCss is vanilla CSS (no Tailwind, no Sass)
|
|
640
|
-
- moduleJs is optional vanilla JS (wrapped in IIFE)
|
|
641
|
-
- NEVER use CDN imports (@import url(), <link> to external CDNs like Google Fonts, cdnjs, unpkg, jsdelivr)
|
|
642
|
-
- For fonts, use system font stacks with good fallbacks. Define them as CSS custom properties in sharedCss:
|
|
643
|
-
--font-heading: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
|
|
644
|
-
--font-body: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
|
|
645
|
-
--font-mono: 'SF Mono', SFMono-Regular, Consolas, monospace;
|
|
646
|
-
- All assets must be self-contained \u2014 no external HTTP requests in CSS or HTML
|
|
647
|
-
- Use "type": "text" (NEVER "textarea" \u2014 it's deprecated)
|
|
648
|
-
- NEVER use "name": "name" (reserved) \u2014 use "item_name" instead
|
|
649
|
-
- NEVER put literal \\n newline sequences in field default values \u2014 use plain text without line breaks
|
|
650
|
-
- Wrap style fields in a "styles" group with "tab": "STYLE"
|
|
651
|
-
- All CSS classes must use a unique prefix "${t}-" to avoid theme conflicts
|
|
652
|
-
- Use BEM naming: ${t}-module__element--modifier
|
|
653
|
-
- metaJson must include: host_template_types: ["PAGE"], is_available_for_new_content: true
|
|
654
|
-
- For repeater groups, use "occurrence": { "min": 0, "max": 100 } and iterate with {% for %}
|
|
655
|
-
- Color fields: type "color", default { "color": "#hex", "opacity": 100 }
|
|
656
|
-
- Link fields: type "link", default { "url": { "href": "#", "type": "EXTERNAL" }, "open_in_new_tab": false, "no_follow": false }
|
|
657
|
-
- Image fields: type "image", default { "src": "https://placehold.co/800x600/1a1a2e/ffffff?text=Replace+in+HubSpot", "alt": "Placeholder image", "width": 800, "height": 600 }
|
|
658
|
-
|
|
659
|
-
## Images & Media
|
|
660
|
-
- Users can upload images that get placed in the theme's assets/ folder automatically
|
|
661
|
-
- When the user uploads an image and wants it on the page, reference it with: {{ get_asset_url("${t}/assets/filename.ext") }}
|
|
662
|
-
- IMPORTANT: get_asset_url() paths must include the theme name prefix "${t}/" because HubSpot resolves from the Design Manager root
|
|
663
|
-
- For background images with uploaded assets: style="background-image: url('{{ get_asset_url(\\"${t}/assets/filename.ext\\") }}')"
|
|
664
|
-
- For images without an uploaded asset, use image fields (type "image") with placehold.co defaults
|
|
665
|
-
- ALWAYS use image fields (type "image") so users can swap images in the page editor
|
|
666
|
-
- Use placehold.co URLs as defaults so the preview looks complete (e.g. https://placehold.co/800x600/1a1a2e/ffffff?text=Hero+Image)
|
|
667
|
-
- In module.html, render images with: <img src="{{ module.field_name.src }}" alt="{{ module.field_name.alt }}" width="{{ module.field_name.width }}" height="{{ module.field_name.height }}">
|
|
668
|
-
- For background images in CSS, use inline styles: style="background-image: url('{{ module.field_name.src }}')"
|
|
669
|
-
- Size placeholders appropriately for their context (hero: 1920x800, cards: 600x400, icons: 200x200, avatars: 150x150)
|
|
670
|
-
- If the user's intent is ambiguous (design reference vs page asset), ask them to clarify
|
|
671
|
-
|
|
672
|
-
## Navigation & Anchor Links
|
|
673
|
-
- For anchor links, add an id attribute directly on the module's root element in module.html:
|
|
674
|
-
<section id="pricing" class="..."> (NOT on an external wrapper \u2014 HubSpot's dnd system strips those)
|
|
675
|
-
- The id should be the moduleName lowercased with spaces replaced by hyphens (e.g. "Pricing Cards" \u2192 id="pricing-cards")
|
|
676
|
-
- For navigation/menu modules, use anchor links that match these ids: e.g. href="#features"
|
|
677
|
-
- Always include smooth scrolling behavior in navigation link clicks
|
|
678
|
-
- For nav modules, make menu items editable via a repeater group with "label" (text) and "anchor" (text) fields
|
|
679
|
-
|
|
680
|
-
## When modifying existing modules
|
|
681
|
-
The current template's modules are listed in page order in the user message. This sequence forms the page narrative.
|
|
682
|
-
|
|
683
|
-
- **Modify**: When the user references an existing module by name or describes changes to existing content, update that module's code. Keep the moduleName unchanged.
|
|
684
|
-
- **Add**: When the user asks for a new section, create a new module and insert it at the narratively correct position. Consider the page flow: navigation \u2192 hero \u2192 content sections \u2192 social proof \u2192 CTA \u2192 footer.
|
|
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
|
-
- **Remove**: When the user asks to remove a section, omit it from the output.
|
|
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?Yi(s):"",a=r?`
|
|
689
|
-
|
|
690
|
-
## Page Type Context
|
|
691
|
-
${r}`:"",l="";if(o?.styleguide&&(l+=`
|
|
692
|
-
|
|
693
|
-
## Brand Style Guide
|
|
694
|
-
${o.styleguide}`),o?.brandvoice&&(l+=`
|
|
695
|
-
|
|
696
|
-
## Brand Voice
|
|
697
|
-
${o.brandvoice}`),o?.humanify!==!1){let d=zi();d&&(l+=`
|
|
698
|
-
|
|
699
|
-
## Anti-AI Copy Rules (Humanify)
|
|
700
|
-
${d}`)}let c="\n\n## REMINDER \u2014 Output Format (CRITICAL)\nYour response MUST contain a ```vibespot-modules code block with the full JSON. Without this block, no modules will be created. Do NOT respond with only text, tables, or descriptions. The JSON block is mandatory.";return n?i+a+l+`
|
|
701
|
-
|
|
702
|
-
## HubSpot CMS Rules
|
|
703
|
-
${Je()}
|
|
704
|
-
|
|
705
|
-
## Conversion Guide Reference
|
|
706
|
-
${e}`+c:i+a+l+`
|
|
707
|
-
|
|
708
|
-
## Design Quality
|
|
709
|
-
- Use modern, clean design with proper spacing and typography
|
|
710
|
-
- Include responsive CSS (mobile breakpoint at 767px)
|
|
711
|
-
- Add scroll animation classes where appropriate
|
|
712
|
-
- Use CSS custom properties for the design system
|
|
713
|
-
- Make content editable through fields.json (headlines, text, colors, images, links)
|
|
714
|
-
|
|
715
|
-
## Scroll Animation CSS Fallback (IMPORTANT)
|
|
716
|
-
When using scroll-animate classes (opacity: 0 \u2192 visible), you MUST include a CSS-only fallback animation in sharedCss that auto-reveals elements after a delay. This ensures content is visible even if the JS file fails to load:
|
|
717
|
-
\`\`\`css
|
|
718
|
-
@keyframes scroll-animate-fallback {
|
|
719
|
-
to { opacity: 1; transform: none; }
|
|
720
|
-
}
|
|
721
|
-
.scroll-animate {
|
|
722
|
-
animation: scroll-animate-fallback 0.1s 3s forwards;
|
|
723
|
-
}
|
|
724
|
-
.scroll-animate.visible {
|
|
725
|
-
animation: none;
|
|
726
|
-
}
|
|
727
|
-
\`\`\`
|
|
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.
|
|
447
|
+
- **Design consistency**: Match the existing theme's design language \u2014 reuse the same CSS custom properties, class naming prefix, spacing scale, and typography.`:"")}function js(e,t,n=!1,s,o){return qi(e,t,n,s,o).map(r=>r.text).join(`
|
|
729
448
|
|
|
730
|
-
|
|
731
|
-
${
|
|
732
|
-
|
|
733
|
-
## Content & Copywriting Guide
|
|
734
|
-
${Vi()}
|
|
735
|
-
|
|
736
|
-
## HubSpot CMS Rules
|
|
737
|
-
${Je()}
|
|
738
|
-
|
|
739
|
-
## Conversion Guide Reference
|
|
740
|
-
${e}`+c}function Bn(e,t){return e.length<=t?e:e.slice(0,t)+`
|
|
741
|
-
/* \u2026truncated ${e.length-t} chars to fit the context budget\u2026 */`}function As(){let e=C(),t=[],n=e.modules,s=n.length;if(s>0){t.push(`
|
|
449
|
+
`)}function Kn(e,t){return e.length<=t?e:e.slice(0,t)+`
|
|
450
|
+
/* \u2026truncated ${e.length-t} chars to fit the context budget\u2026 */`}function Ls(){let e=x(),t=[],n=e.modules,s=n.length;if(s>0){t.push(`
|
|
742
451
|
|
|
743
452
|
## Page Narrative (module sequence)
|
|
744
453
|
`),t.push(`This template has ${s} module${s===1?"":"s"} in this order:
|
|
745
|
-
`);for(let
|
|
454
|
+
`);for(let g=0;g<s;g++)t.push(`${g+1}. ${n[g].moduleName}
|
|
746
455
|
`);t.push(`
|
|
747
456
|
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.
|
|
748
457
|
`),t.push(`
|
|
749
458
|
## Current Module State
|
|
750
|
-
`);let a=0,l=!1,
|
|
751
|
-
### ${
|
|
752
|
-
`);continue}let
|
|
753
|
-
### ${
|
|
459
|
+
`);let a=0,l=!1,u=Math.max(s,1)*4+2,p=Math.max(2e3,Math.floor(hd/u));for(let g=0;g<s;g++){let f=n[g];if(l){t.push(`
|
|
460
|
+
### ${g+1}/${s}: ${f.moduleName}.module \u2014 (source omitted to fit context budget; ask to edit it specifically to load its source)
|
|
461
|
+
`);continue}let h=`
|
|
462
|
+
### ${g+1}/${s}: ${f.moduleName}.module
|
|
754
463
|
**fields.json:**
|
|
755
464
|
\`\`\`json
|
|
756
|
-
${
|
|
465
|
+
${Kn(f.fieldsJson,p)}
|
|
757
466
|
\`\`\`
|
|
758
467
|
**module.html:**
|
|
759
468
|
\`\`\`html
|
|
760
|
-
${
|
|
469
|
+
${Kn(f.moduleHtml,p)}
|
|
761
470
|
\`\`\`
|
|
762
471
|
**module.css:**
|
|
763
472
|
\`\`\`css
|
|
764
|
-
${
|
|
473
|
+
${Kn(f.moduleCss,p)}
|
|
765
474
|
\`\`\`
|
|
766
|
-
`+(
|
|
475
|
+
`+(f.moduleJs?`**module.js:**
|
|
767
476
|
\`\`\`js
|
|
768
|
-
${
|
|
477
|
+
${Kn(f.moduleJs,p)}
|
|
769
478
|
\`\`\`
|
|
770
|
-
`:"");a+=
|
|
479
|
+
`:"");a+=h.length,t.push(h),a>hd&&(l=!0)}e.sharedCss&&t.push(`
|
|
771
480
|
### Shared CSS
|
|
772
481
|
\`\`\`css
|
|
773
|
-
${
|
|
482
|
+
${Kn(e.sharedCss,p)}
|
|
774
483
|
\`\`\`
|
|
775
484
|
`),e.sharedJs&&t.push(`
|
|
776
485
|
### Shared JS
|
|
777
486
|
\`\`\`js
|
|
778
|
-
${
|
|
487
|
+
${Kn(e.sharedJs,p)}
|
|
779
488
|
\`\`\`
|
|
780
|
-
`)}let o=
|
|
489
|
+
`)}let o=Lt(),r=new Set(e.modules.map(a=>a.moduleName)),i=o.filter(a=>!r.has(a.module.moduleName));if(i.length>0){t.push(`
|
|
781
490
|
|
|
782
491
|
## Available modules in this theme (reusable)
|
|
783
|
-
`);for(let a of
|
|
492
|
+
`);for(let a of i)t.push(`- ${a.module.moduleName} (used in: ${a.usedIn.join(", ")})
|
|
784
493
|
`);t.push(`
|
|
785
494
|
The user can ask to reuse any of these modules by name.
|
|
786
|
-
`)}return t.join("")}function
|
|
495
|
+
`)}return t.join("")}function Yi(e,t){let n=x(),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})),r=Ls(),i="";if(n.assets?.length){let d=n.assets.filter(u=>u.type==="image"&&u.usage==="asset");d.length>0&&(i=`
|
|
787
496
|
|
|
788
497
|
## Available Theme Assets
|
|
789
498
|
These images are in the theme's assets/ folder. Reference them with get_asset_url("${n.themeName}/assets/filename"):
|
|
790
499
|
${d.map(u=>`- ${u.filename} (${u.originalName}) \u2192 get_asset_url("${n.themeName}/assets/${u.filename}")`).join(`
|
|
791
|
-
`)}`)}let a=e;
|
|
500
|
+
`)}`)}let a=e;r&&(a+=`
|
|
792
501
|
|
|
793
502
|
---
|
|
794
|
-
${
|
|
503
|
+
${r}`),i&&(a+=i),a+="\n\n---\nRemember: respond with a ```vibespot-modules JSON block containing ALL modules. No text-only responses.";let l=t&&t.length>0;if(l)for(let d of t)d.type==="document"&&d.extractedText&&(a+=`
|
|
795
504
|
|
|
796
505
|
---
|
|
797
506
|
[Attached document: ${d.originalName}]
|
|
798
507
|
${d.extractedText}`),d.type==="image"&&d.usage==="asset"&&d.assetPath&&(a+=`
|
|
799
508
|
|
|
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
|
|
509
|
+
[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 hd,yd=j(()=>{"use strict";y();tt();me();hd=2e5});import{spawn as Sd}from"child_process";import{mkdtempSync as ab}from"fs";import{tmpdir as bd}from"os";import{join as lb}from"path";async function vd(){return Xi||(Xi=(await import("@anthropic-ai/sdk")).default),Xi}function pb(e){for(let[t,n]of ub)if(t.test(e))return Math.min(cb,n);return db}function xd(e){if(!e?.length)return"";let t=[];for(let n of e)n.type==="image"&&n.usage==="asset"&&n.assetPath&&t.push(`
|
|
801
510
|
[Uploaded image: ${n.originalName} \u2192 use get_asset_url("${n.assetPath}")]`),n.type==="document"&&n.extractedText&&t.push(`
|
|
802
511
|
|
|
803
512
|
---
|
|
804
513
|
[Attached document: ${n.originalName}]
|
|
805
|
-
${n.extractedText}`);return t.join("")}async function
|
|
806
|
-
`);
|
|
514
|
+
${n.extractedText}`);return t.join("")}async function wd(e,t,n,s,o,r,i,a="anthropic-api"){for(let l=0;;l++){let c=new Date;try{let d="",u=0,p=r||(()=>{});p(Le[0]);let g=setInterval(()=>{u++,p(Le[Math.min(u,Le.length-1)])},6e3),f=e.messages.stream({model:s,max_tokens:48e3,system:t,messages:n});try{for await(let b of f)if(b.type==="content_block_delta"&&b.delta.type==="text_delta"){let S=b.delta.text;d+=S,o(S)}}finally{clearInterval(g)}let h;try{h=nt((await f.finalMessage()).usage)}catch{}Ct({engine:a,model:s,name:"vibe-chat",input:{system:t,messages:n},output:d,usage:h,startTime:c,endTime:new Date}),i&&i(d);return}catch(d){let u=d.status,p=d.error?.type;if(!(u===429||p==="rate_limit_error"||d instanceof Error&&d.message.includes("429"))||l>=Zi.length)throw d;let f=Zi[l];A.warn("ai-engine",`Rate limited (429), attempt ${l+1}/${Zi.length} \u2014 waiting ${f}s`),r&&r(`Rate limited by Anthropic API \u2014 retrying in ${f}s...`),await new Promise(h=>setTimeout(h,f*1e3)),r&&r("Retrying...")}}}function kd(e,t,n){let s=Ce(),r=x().modules.length>0,i=Yi(e,n),a=Vn(),l=qi(s,t,r,a.pageType,a.brandAssets);return{messages:i,systemBlocks:l,conversionGuide:s,editMode:r}}async function Qi(e,t,n,s,o,r,i,a,l){let c=await vd(),d=new c({apiKey:t,...l?{baseURL:l}:{}}),{messages:u,systemBlocks:p}=kd(e,n,a);A.info("anthropic","API call",{model:s,systemBlockCount:p.length,cachedBlocks:p.filter(g=>g.cache_control).length,messageCount:u.length}),await wd(d,p,u,s,o,r,i)}async function Cd(e,t,n,s,o,r,i){let a=await ki();if(!a)throw new Error("Claude OAuth session expired. Please re-authenticate in Settings.");let l=await vd(),c=new l({authToken:a,defaultHeaders:ms}),{messages:d,systemBlocks:u}=kd(e,t,i),p=[{type:"text",text:In},...u];A.info("anthropic-oauth","API call",{model:n,systemBlockCount:p.length,cachedBlocks:p.filter(g=>g.cache_control).length,messageCount:d.length}),await wd(c,p,d,n,s,o,r,"claude-oauth")}async function ea(e,t,n,s,o,r,i,a,l){let c=Ce(),d=x().modules.length>0,u=Yi(e,a),p=Vn(),g=u.map(P=>typeof P.content=="string"?P:{role:P.role,content:P.content.map(F=>F.type==="text"?{type:"text",text:F.text}:{type:"image_url",image_url:{url:`data:${F.source.media_type};base64,${F.source.data}`}})}),f=js(c,n,d,p.pageType,p.brandAssets),h=l||"https://api.openai.com/v1/chat/completions",b=!/\/mistral(\/|$|\?)/.test(h),S=new Date,v=await fetch(h,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${t}`},body:JSON.stringify({model:s,max_tokens:pb(s),stream:!0,...b?{stream_options:{include_usage:!0}}:{},messages:[{role:"system",content:f},...g]})});if(!v.ok){let P=await v.text();throw new Error(`API error (${v.status}): ${P}`)}let k=0,_=r||(()=>{});_(Le[0]);let M=setInterval(()=>{k++,_(Le[Math.min(k,Le.length-1)])},6e3),R="",J,O=v.body.getReader(),V=new TextDecoder,H="";try{for(;;){let{done:P,value:F}=await O.read();if(P)break;H+=V.decode(F,{stream:!0});let z=H.split(`
|
|
515
|
+
`);H=z.pop()||"";for(let L of z){if(!L.startsWith("data: "))continue;let W=L.slice(6).trim();if(W==="[DONE]")break;try{let _e=JSON.parse(W),Be=_e.choices?.[0]?.delta?.content;Be&&(R+=Be,o(Be)),_e.usage&&(J=_e.usage)}catch{}}}}finally{clearInterval(M)}Ct({engine:"openai-api",model:s,name:"vibe-chat",input:{system:f,messages:g},output:R,usage:Bn(J),startTime:S,endTime:new Date}),i&&i(R)}async function ta(e,t,n,s,o,r,i,a,l){let c=Ce(),d=x(),u=d.modules.length>0,p=Ls(),g=Vn(),f=[];for(let W of d.messages.slice(-20))f.push({role:W.role==="assistant"?"model":"user",parts:[{text:W.content}]});let h=p?`${e}
|
|
807
516
|
|
|
808
517
|
---
|
|
809
|
-
${
|
|
518
|
+
${p}`:e;if(i?.length)for(let W of i)W.type==="document"&&W.extractedText&&(h+=`
|
|
810
519
|
|
|
811
520
|
---
|
|
812
|
-
[Attached document: ${
|
|
813
|
-
${
|
|
814
|
-
|
|
815
|
-
[Uploaded image: ${
|
|
816
|
-
`);
|
|
817
|
-
`))>=0;){let
|
|
818
|
-
${
|
|
819
|
-
`+(c?`Stderr: ${c.slice(0,500)}
|
|
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.
|
|
821
|
-
`+(c?`Stderr: ${c.slice(0,500)}
|
|
822
|
-
`:"")+`Partial output (${l.length} chars): ${l.slice(0,500)}`)))},b);a.on("close",()=>clearTimeout(v))})}function Nr(e,t,n,s,o){return new Promise((i,r)=>{let a={...process.env};delete a.CLAUDECODE;let l=id(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}.
|
|
521
|
+
[Attached document: ${W.originalName}]
|
|
522
|
+
${W.extractedText}`),W.type==="image"&&W.usage==="asset"&&W.assetPath&&(h+=`
|
|
523
|
+
|
|
524
|
+
[Uploaded image: ${W.originalName} \u2192 available as get_asset_url("${W.assetPath}")]`);let b=[];if(i?.length)for(let W of i)W.type==="image"&&W.base64&&b.push({inlineData:{mimeType:W.mimeType,data:W.base64}});b.push({text:h}),f.push({role:"user",parts:b});let S=l||"gemini-2.5-flash",v=!!a,k=a||`https://generativelanguage.googleapis.com/v1beta/models/${S}:streamGenerateContent?alt=sse&key=${t}`,_=js(c,n,u,g.pageType,g.brandAssets),M=new Date,R=await fetch(k,{method:"POST",headers:{"Content-Type":"application/json",...v?{Authorization:`Bearer ${t}`}:{}},body:JSON.stringify({systemInstruction:{parts:[{text:_}]},contents:f,generationConfig:{maxOutputTokens:48e3}})});if(!R.ok){let W=await R.text();throw new Error(`Gemini API error (${R.status}): ${W}`)}let J=0,O=o||(()=>{});O(Le[0]);let V=setInterval(()=>{J++,O(Le[Math.min(J,Le.length-1)])},6e3),H="",P,F=R.body.getReader(),z=new TextDecoder,L="";try{for(;;){let{done:W,value:_e}=await F.read();if(W)break;L+=z.decode(_e,{stream:!0});let Be=L.split(`
|
|
525
|
+
`);L=Be.pop()||"";for(let yt of Be){if(!yt.startsWith("data: "))continue;let ot=yt.slice(6).trim();try{let ie=JSON.parse(ot),Tn=ie.candidates?.[0]?.content?.parts?.[0]?.text;Tn&&(H+=Tn,s(Tn)),ie.usageMetadata&&(P=ie.usageMetadata)}catch{}}}}finally{clearInterval(V)}Ct({engine:"gemini-api",model:S,name:"vibe-chat",input:{system:_,contents:f},output:H,usage:Jn(P),startTime:M,endTime:new Date}),r&&r(H)}function mb(){if(Bs)return Bs;try{Bs=ab(lb(bd(),"vibespot-claude-"))}catch{Bs=bd()}return Bs}function gb(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 sa(e,t,n={},s,o){return new Promise((r,i)=>{if(o?.aborted){i(or("claude"));return}let a={...process.env};delete a.CLAUDECODE;let l=Sd("claude",e,{stdio:["pipe","pipe","pipe"],env:a,cwd:mb()}),c="",d="",u="",p=!1,g=null,f=M=>{p||(p=!0,M())},h=M=>{try{if(M.type==="assistant"&&M.message?.content){for(let R of M.message.content)if(R.type==="text"&&typeof R.text=="string"){let J=R.text;c+=J,n.onChunk&&n.onChunk(J)}else if(R.type==="tool_use"){let J=R;J.name&&n.onToolUse&&n.onToolUse(J.name,J.input)}}M.type==="result"&&(g=M,!c&&typeof M.result=="string"&&(c=M.result,n.onChunk&&n.onChunk(M.result))),n.onEvent&&n.onEvent(M)}catch{}};l.stdout.on("data",M=>{u+=M.toString();let R;for(;(R=u.indexOf(`
|
|
526
|
+
`))>=0;){let J=u.slice(0,R).trim();if(u=u.slice(R+1),!!J)try{h(JSON.parse(J))}catch{}}}),l.stderr.on("data",M=>{d+=M.toString()}),l.on("error",M=>f(()=>i(new Error(`claude failed to start: ${M.message}`)))),l.on("close",M=>{if(u.trim()){try{h(JSON.parse(u.trim()))}catch{}u=""}f(()=>{if(M!==0||g&&g.is_error){let J=`${d}
|
|
527
|
+
${c}`,O=gb(J);i(O!==J?new Error(O):new Error(`claude exited with code ${M}.
|
|
823
528
|
`+(d?`Stderr: ${d.slice(0,500)}
|
|
824
|
-
`:"")+(c?`Output: ${c.slice(0,500)}`:"No output")))
|
|
529
|
+
`:"")+(c?`Output: ${c.slice(0,500)}`:"No output")))}else r(c)})}),l.stdin.on("error",()=>{}),l.stdin.write(t)?l.stdin.end():l.stdin.once("drain",()=>l.stdin.end());let S=s||6e5,v=Math.round(S/6e4),k=setTimeout(()=>{l.kill(),f(()=>i(new Error(`claude (stream-json) timed out after ${v} minutes.
|
|
825
530
|
`+(d?`Stderr: ${d.slice(0,500)}
|
|
826
|
-
`:"")+`Partial output (${c.length} chars): ${c.slice(0,500)}`)))},
|
|
531
|
+
`:"")+`Partial output (${c.length} chars): ${c.slice(0,500)}`)))},S),_=()=>{l.kill(),f(()=>i(or("claude")))};o?.addEventListener("abort",_,{once:!0}),l.on("close",()=>{clearTimeout(k),o?.removeEventListener("abort",_)})})}function or(e){let t=new Error(`${e} aborted (generation cancelled)`);return t.name="AbortError",t}function Js(e,t,n,s,o,r,i){return new Promise((a,l)=>{if(r?.aborted){l(or(e));return}let c={...process.env};delete c.CLAUDECODE;let d=Sd(e,t,{stdio:["pipe","pipe","pipe"],env:c,...i?.cwd?{cwd:i.cwd}:{},...i?.shell?{shell:!0}:{}}),u="",p="",g=!1,f=_=>{g||(g=!0,_())};d.stdout.on("data",_=>{let M=_.toString();u+=M,s&&s(M)}),d.stderr.on("data",_=>{p+=_.toString()}),d.on("error",_=>f(()=>l(new Error(`${e} failed to start: ${_.message}`)))),d.on("close",_=>{f(()=>{_!==0?l(new Error(`${e} exited with code ${_}.
|
|
532
|
+
`+(p?`Stderr: ${p.slice(0,500)}
|
|
533
|
+
`:"")+(u?`Output: ${u.slice(0,500)}`:"No output"))):a(u)})}),d.stdin.on("error",()=>{}),d.stdin.write(n)?d.stdin.end():d.stdin.once("drain",()=>d.stdin.end());let b=o||6e5,S=Math.round(b/6e4),v=setTimeout(()=>{d.kill(),f(()=>l(new Error(`${e} timed out after ${S} minutes.
|
|
534
|
+
`+(p?`Stderr: ${p.slice(0,500)}
|
|
535
|
+
`:"")+`Partial output (${u.length} chars): ${u.slice(0,500)}`)))},b),k=()=>{d.kill(),f(()=>l(or(e)))};r?.addEventListener("abort",k,{once:!0}),d.on("close",()=>{clearTimeout(v),r?.removeEventListener("abort",k)})})}async function Td(e,t,n,s,o,r){let i=Ce(),a=$(),l=x().modules.length>0,c=Vn(),d=js(i,t,l,c.pageType,c.brandAssets);d+=`
|
|
827
536
|
|
|
828
537
|
## User Request
|
|
829
|
-
`+e,d+=
|
|
538
|
+
`+e,d+=Ls(),d+=xd(r),d+="\n\n---\nRemember: respond with a ```vibespot-modules JSON block containing ALL modules. No text-only responses.";let u=["--print",...na];a.claudeCodeModel&&u.push("--model",a.claudeCodeModel),a.webSearch&&u.push("--allowedTools=WebSearch"),u.push("--output-format","stream-json","--include-partial-messages","--verbose");let p=0,g=s||(()=>{});g(Le[0]);let f=setInterval(()=>{p++;let h=Le[Math.min(p,Le.length-1)];g(h)},6e3);try{let h=await sa(u,d,{onChunk:b=>n(b),onToolUse:(b,S)=>{g(fb(b,S))}});o&&o(h)}finally{clearInterval(f)}}function fb(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 oa(e,t,n,s,o,r,i){let a=Ce(),l=x().modules.length>0,c=Vn(),d=js(a,n,l,c.pageType,c.brandAssets);d+=`
|
|
830
539
|
|
|
831
540
|
## User Request
|
|
832
|
-
`+t,d+=As(),d+=ad(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 Nr(u,m,d,S=>{s(S)});i&&i(b)}finally{clearInterval(f)}}var Ar,je,_r,Ir,_s,Or=N(()=>{"use strict";y();Ke();ee();$t();Ce();sd();le();Be();on();Ar=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..."],_r=[10,20,40,60,120];Ir=["--strict-mcp-config"],_s=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 sy,mkdirSync as md,existsSync as Fr,readFileSync as Dr}from"fs";import{join as cn,extname as oy}from"path";import{randomUUID as iy}from"crypto";import ry from"busboy";function dy(e,t){if(gd.has(t))return t;let n=e.slice(e.lastIndexOf(".")).toLowerCase();return cy[n]??t}function uy(e){return e.replace(/[^a-zA-Z0-9._-]/g,"_").replace(/_{2,}/g,"_").replace(/^_+|_+$/g,"").toLowerCase()}function my(e,t){if(!Fr(cn(e,t)))return t;let n=oy(t),s=t.slice(0,-n.length||void 0),o=1;for(;Fr(cn(e,`${s}-${o}${n}`));)o++;return`${s}-${o}${n}`}async function py(e){let{PDFParse:t}=await import("pdf-parse"),n=Dr(e),s=new t({data:n});try{return(await s.getText()).text}finally{await s.destroy()}}async function gy(e){return(await(await import("mammoth")).extractRawText({path:e})).value}function fy(e){return Dr(e,"utf-8")}function fd(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=ry({headers:e.headers,limits:{fileSize:ay,files:10}});l.on("file",(c,d,u)=>{let{filename:m,mimeType:g}=u;r++;let h=dy(m,g);if(!gd.has(h)){i.push(`Unsupported file type: ${m} (${g})`),d.resume();return}let f=pd.has(h),b=uy(m),S=iy(),v,w;f?(v=cn(n.themePath,"assets"),md(v,{recursive:!0}),w=my(v,b)):(v=cn(n.themePath,".vibespot","uploads"),md(v,{recursive:!0}),w=`${S}-${b}`);let $=cn(v,w),j=sy($),J=0,K=!1;d.on("data",H=>{J+=H.length}),d.on("limit",()=>{K=!0,i.push(`File too large (>10MB): ${m}`)}),d.pipe(j),a.push(new Promise(H=>{j.on("finish",()=>{if(!K){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),fc(X)}H()}),j.on("error",()=>{i.push(`Failed to write: ${m}`),H()})}))}),l.on("finish",async()=>{await Promise.all(a);for(let c of o)if(c.type==="document"){let d=cn(n.themePath,".vibespot","uploads",c.filename);try{c.mimeType==="application/pdf"?c.extractedText=await py(d):c.mimeType==="application/vnd.openxmlformats-officedocument.wordprocessingml.document"?c.extractedText=await gy(d):c.extractedText=fy(d),M.info("upload",`Extracted text from ${c.originalName} (${c.extractedText.length} chars)`)}catch(u){M.warn("upload",`Failed to extract text from ${c.originalName}: ${u}`),c.extractedText=`[Could not extract text from ${c.originalName}]`}}if(r===0){p(t,400,{error:"No files uploaded"});return}p(t,200,{files:o.map(c=>({id:c.id,filename:c.filename,originalName:c.originalName,type:c.type,usage:c.usage,size:c.size})),errors:i.length>0?i:void 0})}),l.on("error",c=>{M.error("upload",`Busboy error: ${c}`),p(t,500,{error:"Upload failed"})}),e.pipe(l)}function Vo(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=cn(t.themePath,"assets",s.filename);Fr(i)&&(o.base64=Dr(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 ay,pd,ly,gd,cy,jr=N(()=>{"use strict";y();Xe();Ce();le();ay=10*1024*1024,pd=new Set(["image/png","image/jpeg","image/jpg","image/svg+xml","image/webp","image/gif"]),ly=new Set(["application/pdf","application/vnd.openxmlformats-officedocument.wordprocessingml.document","text/markdown","text/plain"]),gd=new Set([...pd,...ly]),cy={".md":"text/markdown",".txt":"text/plain",".markdown":"text/markdown"}});var wd={};Ge(wd,{LANGDOCK_BASE_URLS:()=>$s,callAgent:()=>Pe,callAgentAPI:()=>xd,isAgenticCapable:()=>Ms,isCLIEngine:()=>Gn,resolveThinkingBudget:()=>Un});async function zo(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>=Lr.length)throw s;let a=Lr[n];M.warn("agent-adapter",`Rate limited (429), attempt ${n+1}/${Lr.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 Es(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 Sd(){return Jr||(Jr=(await import("@anthropic-ai/sdk")).default),Jr}async function hd(e,t,n,s,o,i){let r=await Sd(),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 zo(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:Es(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 zo(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 hy(e,t,n){let s=await Sd(),o=new s({authToken:e,defaultHeaders:Zn}),i=n.messages,r;if(n.systemBlocks?r=[{type:"text",text:xn},...n.systemBlocks]:r=[{type:"text",text:xn},{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 zo(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:Es(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 zo(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 Br(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"?Br(o):o;t.properties=n}return t.items&&typeof t.items=="object"&&(t.items=Br(t.items)),t}async function yd(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:Br(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=En(l.usage);if(n.structuredOutput)try{return{type:"structured",data:Es(JSON.parse(c)),usage:d}}catch{return M.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 bd(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=Mn(c.usageMetadata);if(n.structuredOutput)try{return{type:"structured",data:Es(JSON.parse(d)),usage:u}}catch{return M.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 yy(e,t,n){switch(e){case"claude-code":{let s=["--print",...Ir];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 by(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(`
|
|
541
|
+
`+t,d+=Ls(),d+=xd(i),d+="\n\n---\nRemember: respond with a ```vibespot-modules JSON block containing ALL modules. No text-only responses.";let u,p;e==="gemini"?(u="gemini",p=[]):(u="codex",p=["exec","--full-auto"]);let g=0,f=o||(()=>{});f(Le[0]);let h=setInterval(()=>{g++;let b=Le[Math.min(g,Le.length-1)];f(b)},6e3);try{let b=await Js(u,p,d,S=>{s(S)});r&&r(b)}finally{clearInterval(h)}}var Xi,cb,db,ub,Le,Zi,na,Bs,rr=j(()=>{"use strict";y();tt();te();$t();me();yd();re();Ue();un();Xi=null;cb=48e3,db=16384,ub=[[/^gpt-5/i,128e3],[/^(o1|o3|o4)/i,1e5],[/^gpt-4\.1/i,32768],[/^gpt-4o/i,16384],[/^(gpt-4-turbo|gpt-4-\d|gpt-3\.5)/i,4096]];Le=["Analyzing your request...","Reading the conversion guide...","Planning module structure...","Generating HTML templates...","Writing CSS styles...","Creating field definitions...","Building module metadata...","Assembling theme assets...","Polishing the output...","Almost there \u2014 hang tight..."],Zi=[10,20,40,60,120];na=["--strict-mcp-config"],Bs=null});function fn(e){let t={},n=new Map;for(let s of e)if(n.set(s.name,s.type),s.type==="group"&&s.occurrence&&Array.isArray(s.default))t[s.name]=s.children?Gb(s.default,s.children):s.default;else if(s.type==="group"&&s.children){let o=fn(s.children);Ub(n,s.name,o),t[s.name]=o}else t[s.name]=s.default??"";return eu(t,n),t}function Yn(e,t){let n=e;return n=Hb(n),n=su(n,t),n=ou(n,t),n=ru(n,t),n=Xb(n),n}function aa(e){let t=[e.sharedCss||"",...e.moduleCssArray].filter(Boolean).map(o=>`<style>${lu(o)}</style>`).join(`
|
|
542
|
+
`),n=[e.sharedJs||"",...e.moduleJsArray].filter(Boolean).map(o=>`<script>${cu(o)}</script>`).join(`
|
|
543
|
+
`),s=e.renderedModules.join(`
|
|
544
|
+
`);return`<!DOCTYPE html>
|
|
545
|
+
<html lang="en">
|
|
546
|
+
<head>
|
|
547
|
+
<meta charset="utf-8">
|
|
548
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
549
|
+
${t}
|
|
550
|
+
<style>
|
|
551
|
+
html{scroll-behavior:smooth}
|
|
552
|
+
.vsp-img-wrap{position:relative;display:inline-block}
|
|
553
|
+
.vsp-img-badge{position:absolute;top:8px;right:8px;background:rgba(0,0,0,.75);color:#fff;font:500 11px/1 -apple-system,sans-serif;padding:5px 8px;border-radius:4px;pointer-events:none;opacity:.85;white-space:nowrap;z-index:10}
|
|
554
|
+
</style>
|
|
555
|
+
</head>
|
|
556
|
+
<body>
|
|
557
|
+
${s}
|
|
558
|
+
${n}
|
|
559
|
+
<script>
|
|
560
|
+
// Anchor link handler \u2014 smooth scroll to module sections
|
|
561
|
+
document.addEventListener('click',function(e){
|
|
562
|
+
var a=e.target.closest('a[href^="#"]');
|
|
563
|
+
if(!a)return;
|
|
564
|
+
var id=a.getAttribute('href').slice(1);
|
|
565
|
+
if(!id)return;
|
|
566
|
+
var el=document.getElementById(id);
|
|
567
|
+
if(el){
|
|
568
|
+
e.preventDefault();
|
|
569
|
+
el.scrollIntoView({behavior:'smooth',block:'start'});
|
|
570
|
+
}
|
|
571
|
+
});
|
|
572
|
+
// Placeholder image badges
|
|
573
|
+
document.querySelectorAll('img').forEach(function(img){
|
|
574
|
+
var src=img.src||img.getAttribute('src')||'';
|
|
575
|
+
if(src.indexOf('placehold')!==-1){
|
|
576
|
+
var w=document.createElement('span');
|
|
577
|
+
w.className='vsp-img-wrap';
|
|
578
|
+
img.parentNode.insertBefore(w,img);
|
|
579
|
+
w.appendChild(img);
|
|
580
|
+
var b=document.createElement('span');
|
|
581
|
+
b.className='vsp-img-badge';
|
|
582
|
+
b.textContent='Placeholder \u2014 replace in HubSpot';
|
|
583
|
+
w.appendChild(b);
|
|
584
|
+
}
|
|
585
|
+
});
|
|
586
|
+
</script>
|
|
587
|
+
</body>
|
|
588
|
+
</html>`}function Hb(e){return e=e.replace(Nb,""),e=e.replace(Ob,""),e=e.replace(Fb,""),qd.lastIndex=0,e=e.replace(qd,(t,n)=>`/theme-assets/${n}`),Yd.lastIndex=0,e=e.replace(Yd,""),e=e.replace(Db,""),e=e.replace(jb,""),e=e.replace(Lb,""),e=e.replace(Bb,""),e=e.replace(Jb,""),e}function eu(e,t){Object.defineProperty(e,Qd,{value:t,enumerable:!1,configurable:!1})}function Ub(e,t,n){let s=nu(n);if(s)for(let[o,r]of s)e.set(`${t}.${o}`,r)}function Gb(e,t){return e.map(n=>{if(n===null||typeof n!="object"||Array.isArray(n))return n;let s={...n},o=tu(t);return eu(s,o),s})}function tu(e,t=""){let n=new Map;for(let s of e){let o=t?`${t}.${s.name}`:s.name;if(n.set(o,s.type),s.type==="group"&&s.children){let r=tu(s.children,o);for(let[i,a]of r)n.set(i,a)}}return n}function nu(e){if(!(e===null||typeof e!="object"))return e[Qd]}function su(e,t){let n=e,s=0;for(;s<30;){s++;let o=Wb(n);if(!o)break;let{varName:r,iterExpr:i,body:a,start:l,end:c}=o,d=Zb(i,t),u="";Array.isArray(d)&&(u=d.map((p,g)=>{let f={...t,[r]:p,loop:{index:g+1,index0:g,first:g===0,last:g===d.length-1,length:d.length}},h=su(a,f);return h=ou(h,f),h=ru(h,f),h}).join("")),n=n.slice(0,l)+u+n.slice(c)}return n}function Wb(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],r=s[2],i=s.index+s[0].length;n.lastIndex=i;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(i,l.index);return{varName:o,iterExpr:r,body:c,start:s.index,end:l.index+l[0].length}}return null}function ou(e,t){let n=e,s=0,o=Kb(e);for(;s<o;){s++;let r=Vb(n);if(!r)break;let i=zb(r.condition,r.body,t);n=n.slice(0,r.start)+i+n.slice(r.end)}return n}function Kb(e){let t=e.match(/\{%[-\s]*if\s+/g);return t?t.length:0}function Vb(e){let t=[];fr.lastIndex=0;let n;for(;(n=fr.exec(e))!==null;){let s=n[1].trim();if(s.startsWith("if "))t.push({condition:n[2].trim(),start:n.index,bodyStart:n.index+n[0].length});else if(s==="endif"&&t.length>0){let o=t.pop();return{condition:o.condition,body:e.slice(o.bodyStart,n.index),start:o.start,end:n.index+n[0].length}}}return null}function zb(e,t,n){let s=[],o=e,r=0,i=0;fr.lastIndex=0;let a;for(;(a=fr.exec(t))!==null;){let l=a[1].trim();if(l.startsWith("if ")){i++;continue}if(l==="endif"){i=Math.max(0,i-1);continue}i>0||(l.startsWith("elif ")||l==="else")&&(s.push({condition:o,body:t.slice(r,a.index)}),o=l==="else"?null:a[3].trim(),r=a.index+a[0].length)}s.push({condition:o,body:t.slice(r)});for(let l of s)if(l.condition===null||gr(l.condition,n))return l.body;return""}function ru(e,t){return e.replace(/\{\{[-\s]*(.*?)[-\s]*\}\}/g,(n,s,o)=>{let r=s.trim(),i=qb(e,o),a=r.split("|"),l=a[0].trim(),c=Qb(t,l),d=!1,u=!1;for(let g=1;g<a.length;g++){let f=a[g].trim(),h=eS(f);c=au(c,f),h==="escape"||h==="e"?d=!0:h==="safe"&&(u=!0)}if(c==null)return"";typeof c=="object"&&(c=JSON.stringify(c));let p=String(c);return p=p.replace(/\\n/g," ").replace(/\n/g," "),d?p:i==="style"?lu(p):i==="script"?tS(p):i==="htmlText"&&(u||Yb(t,l))?lS(p):la(p)})}function qb(e,t){let n=e.slice(0,t),s=n.toLowerCase().lastIndexOf("<script"),o=n.toLowerCase().lastIndexOf("</script");if(s>o)return"script";let r=n.toLowerCase().lastIndexOf("<style"),i=n.toLowerCase().lastIndexOf("</style");if(r>i)return"style";let a=n.lastIndexOf("<"),l=n.lastIndexOf(">");return a>l?"htmlTag":"htmlText"}function Yb(e,t){let n=t.split(".");if(n.length<2)return!1;let s=e,o="";for(let r=0;r<n.length;r++){if(s===null||typeof s!="object")return!1;let i=nu(s);if(i){o=n.slice(r).join(".");let a=i.get(o);return a==="richtext"||a==="html"}s=s[n[r]]}return!1}function Xb(e){return e=e.replace(/\{%.*?%\}/gs,""),e=e.replace(/\{\{.*?\}\}/gs,""),e}function Zb(e,t){let n=e.match(/^range\(\s*(.+?)\s*,\s*(.+?)\s*\)$/);if(n){let o=Xd(n[1],t),r=Xd(n[2],t),i=[];for(let a=o;a<r;a++)i.push(a);return i}let s=e.match(/^(.+?)\|split\(['"](.+?)['"]\)$/);if(s){let o=en(t,s[1].trim());return typeof o=="string"?o.split(s[2]):[]}return en(t,e)}function Xd(e,t){let s=e.trim().split("|"),o=s[0].trim();if(!isNaN(Number(o)))return Number(o);let r=en(t,o);for(let i=1;i<s.length;i++)r=au(r,s[i].trim());return Number(r)||0}function en(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 Qb(e,t){let n=t.match(/^(.+?)\s*([*/])\s*([\d.]+)$/);if(n){let s=en(e,n[1].trim());if(s==null||s==="")return"";let o=Number(s);if(Number.isNaN(o))return"";let r=Number(n[3]);return n[2]==="/"?r===0?"":o/r:o*r}return en(e,t)}function gr(e,t){let n=e.trim();if(n.startsWith("not "))return!gr(n.slice(4),t);if(n.includes(" and "))return n.split(" and ").every(r=>gr(r,t));if(n.includes(" or "))return n.split(" or ").some(r=>gr(r,t));let s=n.match(/^(.+?)\s*(==|!=|>=|<=|>|<)\s*(.+)$/);if(s){let r=en(t,s[1].trim()),i=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=en(t,a):a=Number(a),i){case"==":return r==a;case"!=":return r!=a;case">":return Number(r)>Number(a);case"<":return Number(r)<Number(a);case">=":return Number(r)>=Number(a);case"<=":return Number(r)<=Number(a)}}let o=en(t,n);return iu(o)}function iu(e){return!(e==null||e===""||e===0||e===!1||Array.isArray(e)&&e.length===0)}function au(e,t){let n=e==null?"":String(e),s=t.match(/^(\w+)\((.*)\)$/),o=s?s[1]:t,r=s?s[2].replace(/^["']|["']$/g,""):void 0;switch(o){case"escape":case"e":return la(n);case"safe":return e;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(r){let i=parseInt(r,10);return n.length>i?n.slice(0,i)+"...":n}return n;case"default":return iu(e)?e:r??"";case"length":return Array.isArray(e)?e.length:n.length;case"join":return Array.isArray(e)?e.join(r??", "):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 i=ia(e);return i?yS(i):""}default:return e}}function eS(e){let t=e.match(/^(\w+)(?:\(.*\))?$/);return t?t[1]:e}function la(e){return e.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")}function lu(e){return e.replace(/<\/style/gi,"<\\/style")}function cu(e){return e.replace(/<\/script/gi,"<\\/script")}function tS(e){return cu(e).replace(/\\/g,"\\\\").replace(/"/g,'\\"').replace(/'/g,"\\'").replace(/\r/g,"\\r").replace(/\n/g,"\\n").replace(/\u2028/g,"\\u2028").replace(/\u2029/g,"\\u2029")}function lS(e){let t="",n=0,s=null;for(;n<e.length;){let o=e.indexOf("<",n);if(o===-1){s||(t+=e.slice(n));break}s||(t+=e.slice(n,o));let r=cS(e,o);if(r===-1){s||(t+="<"),n=o+1;continue}let i=e.slice(o,r+1),a=dS(i);if(n=r+1,!!a){if(s){a.closing&&a.tagName===s&&(s=null);continue}if(nS.has(a.tagName)){a.closing||(s=a.tagName);continue}if(sS.has(a.tagName)){if(a.closing){aS.has(a.tagName)||(t+=`</${a.tagName}>`);continue}t+=pS(a)}}}return t.replace(/<\/style/gi,"<\\/style").replace(/<\/script/gi,"<\\/script")}function cS(e,t){let n=null;for(let s=t+1;s<e.length;s++){let o=e[s];if(n){o===n&&(n=null);continue}if(o==='"'||o==="'"){n=o;continue}if(o===">")return s}return-1}function dS(e){if(e.startsWith("<!--"))return null;let t=e.slice(1,-1).trim();if(!t||t.startsWith("!")||t.startsWith("?"))return null;let n=t.startsWith("/");n&&(t=t.slice(1).trimStart());let s=t.match(/^([A-Za-z][A-Za-z0-9:-]*)/);if(!s)return null;let o=s[1].toLowerCase(),r=n?[]:uS(t.slice(s[0].length));return{tagName:o,closing:n,attrs:r}}function uS(e){let t=[],n=0;for(;n<e.length;){for(;n<e.length&&/[\s/]/.test(e[n]);)n++;if(n>=e.length)break;let s=n;for(;n<e.length&&!/[\s/=]/.test(e[n]);)n++;let o=e.slice(s,n);if(!o){n++;continue}for(;n<e.length&&/\s/.test(e[n]);)n++;let r=null;if(e[n]==="="){for(n++;n<e.length&&/\s/.test(e[n]);)n++;let i=e[n];if(i==='"'||i==="'"){n++;let a=n;for(;n<e.length&&e[n]!==i;)n++;r=e.slice(a,n),e[n]===i&&n++}else{let a=n;for(;n<e.length&&!/\s/.test(e[n]);)n++;r=e.slice(a,n)}}t.push({name:o.toLowerCase(),value:r})}return t}function pS(e){let t=e.attrs.map(n=>mS(e.tagName,n)).filter(n=>!!n).map(n=>n.value===null?n.name:`${n.name}="${la(n.value)}"`).join(" ");return t?`<${e.tagName} ${t}>`:`<${e.tagName}>`}function mS(e,t){let n=t.name;if(!n||n.startsWith("on")||n==="style")return null;let s=rS[e];return oS.has(n)||n.startsWith("aria-")||n.startsWith("data-")||!!s?.has(n)?iS.has(n)&&t.value!==null&&!gS(t.value)?{name:n,value:"#"}:e==="a"&&n==="target"&&t.value==="_blank"?t:n==="target"?null:t:null}function gS(e){let n=fS(e).trim().replace(/[\u0000-\u001F\u007F\s]+/g,"").toLowerCase();if(n.startsWith("#")||n.startsWith("/")||n.startsWith("./")||n.startsWith("../"))return!0;if(n.startsWith("data:"))return/^data:image\/(?:gif|jpe?g|png|webp);/i.test(n);let s=n.match(/^([a-z][a-z0-9+.-]*):/);return s?["http","https","mailto","tel"].includes(s[1]):!0}function fS(e){let t={amp:"&",colon:":",gt:">",lt:"<",newline:`
|
|
589
|
+
`,quot:'"',tab:" "};return e.replace(/&(#x[\da-f]+|#\d+|[a-z]+);?/gi,(n,s)=>{let o=s.toLowerCase();if(o.startsWith("#x")){let r=parseInt(o.slice(2),16);return Zd(r)?String.fromCodePoint(r):n}if(o.startsWith("#")){let r=parseInt(o.slice(1),10);return Zd(r)?String.fromCodePoint(r):n}return t[o]??n})}function Zd(e){return Number.isInteger(e)&&e>=0&&e<=1114111}function ia(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?hS(t[1]):null}if(typeof e=="object"){let t=e;if(typeof t.color=="string")return ia(t.color);if(typeof t.hex=="string")return ia(t.hex)}return null}function hS(e){let t=e.toLowerCase();return t.length===3?t.split("").map(n=>n+n).join(""):t}function yS(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 Qd,Nb,Ob,Fb,qd,Yd,Db,jb,Lb,Bb,Jb,fr,nS,sS,oS,rS,iS,aS,ca=j(()=>{"use strict";y();Qd=Symbol("hublFieldTypes");Nb=/\{%[-\s]*require_(css|js)\b.*?%\}/gs,Ob=/\{%[-\s]*end_require_(css|js)\s*%\}/gs,Fb=/\{\{[-\s]*require_(css|js)\(.*?\)\s*\}\}/gs,qd=/\{\{[-\s]*get_asset_url\(["'](?:[^"'\/]+\/)?assets\/(.*?)["']\)\s*\}\}/gs,Yd=/\{\{[-\s]*get_asset_url\(.*?\)\s*\}\}/gs,Db=/\{%[-\s]*(end_)?(dnd_area|dnd_section|dnd_column|dnd_row|dnd_module)\b.*?%\}/gs,jb=/\{%[-\s]*module\b.*?%\}/gs,Lb=/\{%[-\s]*(extends|block|endblock|set)\b.*?%\}/gs,Bb=/\{#.*?#\}/gs,Jb=/\{\{[-\s]*content\.\w+.*?\}\}/gs,fr=/\{%[-\s]*(if\s+([\s\S]*?)|elif\s+([\s\S]*?)|else|endif)\s*-?%\}/g;nS=new Set(["script","style","iframe","object","embed"]),sS=new Set(["a","abbr","b","blockquote","br","cite","code","dd","del","details","div","dl","dt","em","figcaption","figure","h1","h2","h3","h4","h5","h6","hr","i","img","ins","li","mark","ol","p","pre","q","s","small","span","strong","sub","summary","sup","table","tbody","td","tfoot","th","thead","tr","u","ul"]),oS=new Set(["class","dir","id","lang","role","title"]),rS={a:new Set(["href","name","rel","target"]),blockquote:new Set(["cite"]),del:new Set(["cite","datetime"]),details:new Set(["open"]),img:new Set(["alt","decoding","height","loading","src","title","width"]),ins:new Set(["cite","datetime"]),q:new Set(["cite"]),td:new Set(["colspan","headers","rowspan"]),th:new Set(["colspan","headers","rowspan","scope"])},iS=new Set(["cite","href","src"]),aS=new Set(["br","hr","img"])});function tn(){return du}function uu(e){du=e}function pu(){return hr}function mu(e){hr=e}function gu(e){hr===e&&(hr=null)}var du,hr,hn=j(()=>{"use strict";y();du="page";hr=null});var yr={};Ve(yr,{buildModulePreviewHtml:()=>ua,buildPreviewHtml:()=>Us});function bS(e){if(tn()==="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 SS(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"),r=t(["--text-muted","--text-secondary","--muted","--color-text-muted"],"#666"),i=t(["--border","--border-color","--color-border"],"#333");return{bg:n,surface:s,text:o,textMuted:r,border:i}}function da(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,r,i,a,l,c,d)=>{if(r.includes("data-vs-field"))return o;let u=n.get(c)||"text";return`${r.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,r,i,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,r,i,a)=>o.includes("data-vs-link")?o:o.replace("<a",`<a data-vs-link="${a}"`)),s}function Us(){let e=x();if(!e)return fu();let t=pe(),n=e.moduleOrder||[];if(t.length===0&&n.length===0)return fu();if(bS(t))return vS(t,n);let s=[],o=[],r=[],i=new Set;for(let c of t){if(c.moduleHtml.includes("dnd_area")||c.moduleHtml.includes("extends "))continue;let d,u=[];try{let h=JSON.parse(c.fieldsJson);u=Array.isArray(h)?h:[],d={module:fn(u)}}catch{d={module:{}}}let p=da(c.moduleHtml,u),g=Yn(p,d),f=c.moduleName.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-|-$/g,"");s.push(`<div class="vibespot-module" id="${f}" data-module="${c.moduleName}">${g}</div>`),i.add(c.moduleName),c.moduleCss&&o.push(c.moduleCss),c.moduleJs&&r.push(c.moduleJs)}let a=SS(e.sharedCss);for(let c of n)if(!i.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}">
|
|
590
|
+
<div class="vibespot-placeholder">
|
|
591
|
+
<div class="vibespot-placeholder__name">${c}</div>
|
|
592
|
+
</div>
|
|
593
|
+
</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 aa({renderedModules:s,sharedCss:e.sharedCss,moduleCssArray:[l,...o],sharedJs:e.sharedJs,moduleJsArray:r})}function fu(){return`<!DOCTYPE html>
|
|
594
|
+
<html lang="en">
|
|
595
|
+
<head>
|
|
596
|
+
<meta charset="utf-8">
|
|
597
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
598
|
+
<style>
|
|
599
|
+
* { margin: 0; padding: 0; box-sizing: border-box; }
|
|
600
|
+
body {
|
|
601
|
+
min-height: 100vh;
|
|
602
|
+
display: flex;
|
|
603
|
+
align-items: center;
|
|
604
|
+
justify-content: center;
|
|
605
|
+
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
|
|
606
|
+
background: #0f0f14;
|
|
607
|
+
color: #888;
|
|
608
|
+
}
|
|
609
|
+
.welcome {
|
|
610
|
+
text-align: center;
|
|
611
|
+
padding: 2rem;
|
|
612
|
+
}
|
|
613
|
+
.welcome__wave {
|
|
614
|
+
font-size: 4rem;
|
|
615
|
+
margin-bottom: 1.2rem;
|
|
616
|
+
opacity: 0.4;
|
|
617
|
+
animation: float 3s ease-in-out infinite;
|
|
618
|
+
}
|
|
619
|
+
@keyframes float {
|
|
620
|
+
0%, 100% { transform: translateY(0); }
|
|
621
|
+
50% { transform: translateY(-6px); }
|
|
622
|
+
}
|
|
623
|
+
.welcome__title {
|
|
624
|
+
font-size: 1.4rem;
|
|
625
|
+
font-weight: 600;
|
|
626
|
+
color: #bbb;
|
|
627
|
+
letter-spacing: 0.5px;
|
|
628
|
+
margin-bottom: 0.4rem;
|
|
629
|
+
}
|
|
630
|
+
.welcome__sub {
|
|
631
|
+
font-size: 1rem;
|
|
632
|
+
color: #666;
|
|
633
|
+
font-weight: 300;
|
|
634
|
+
}
|
|
635
|
+
</style>
|
|
636
|
+
</head>
|
|
637
|
+
<body>
|
|
638
|
+
<div class="welcome">
|
|
639
|
+
<div class="welcome__wave">\u224B</div>
|
|
640
|
+
<div class="welcome__title">vibeSpot</div>
|
|
641
|
+
<div class="welcome__sub">Build Something Great</div>
|
|
642
|
+
</div>
|
|
643
|
+
</body>
|
|
644
|
+
</html>`}function ua(e){let t=x();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:fn(o)}}catch{s={module:{}}}let r=da(n.moduleHtml,o),i=Yn(r,s);return aa({renderedModules:[`<div class="vibespot-module" data-module="${n.moduleName}">${i}</div>`],sharedCss:t.sharedCss,moduleCssArray:n.moduleCss?[n.moduleCss]:[],sharedJs:t.sharedJs,moduleJsArray:n.moduleJs?[n.moduleJs]:[]})}function vS(e,t){let n=[],s=new Set;for(let r of e){let i,a=[];try{let u=JSON.parse(r.fieldsJson);a=Array.isArray(u)?u:[],i={module:fn(a)}}catch{i={module:{}}}let l=da(r.moduleHtml,a),c=Yn(l,i),d=r.moduleName.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-|-$/g,"");n.push(`<div class="vibespot-module" id="${d}" data-module="${r.moduleName}">${c}</div>`),s.add(r.moduleName)}for(let r of t)if(!s.has(r)){let i=r.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-|-$/g,"");n.push(`<div class="vibespot-module vibespot-module--pending" id="${i}" data-module="${r}">
|
|
645
|
+
<table role="presentation" cellpadding="0" cellspacing="0" border="0" width="100%" style="max-width:600px;margin:0 auto;">
|
|
646
|
+
<tr><td style="padding:40px 30px;text-align:center;background-color:#ffffff;border:1px dashed #ddd;">
|
|
647
|
+
<p style="font-family:Arial,Helvetica,sans-serif;font-size:14px;color:#999;">${r}</p>
|
|
648
|
+
</td></tr>
|
|
649
|
+
</table>
|
|
650
|
+
</div>`)}return`<!DOCTYPE html>
|
|
651
|
+
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
|
|
652
|
+
<head>
|
|
653
|
+
<meta charset="utf-8">
|
|
654
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
655
|
+
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
|
656
|
+
<title>Email Preview</title>
|
|
657
|
+
<style>
|
|
658
|
+
html, body { margin: 0; padding: 0; overflow-x: hidden; }
|
|
659
|
+
body {
|
|
660
|
+
background-color: #e8e8e8;
|
|
661
|
+
font-family: Arial, Helvetica, sans-serif;
|
|
662
|
+
-webkit-font-smoothing: antialiased;
|
|
663
|
+
}
|
|
664
|
+
.vibespot-email-wrapper {
|
|
665
|
+
padding: 30px 20px;
|
|
666
|
+
background-color: #e8e8e8;
|
|
667
|
+
min-height: 100vh;
|
|
668
|
+
}
|
|
669
|
+
.vibespot-module { margin: 0 auto; max-width: 600px; }
|
|
670
|
+
.vibespot-module--pending table { opacity: 0.6; }
|
|
671
|
+
html { scroll-behavior: smooth; }
|
|
672
|
+
img { max-width: 100% !important; height: auto !important; }
|
|
673
|
+
table { max-width: 100% !important; }
|
|
674
|
+
td { word-break: break-word; }
|
|
675
|
+
@media screen and (max-width: 620px) {
|
|
676
|
+
.vibespot-email-wrapper { padding: 10px 8px; }
|
|
677
|
+
table[width] { width: 100% !important; }
|
|
678
|
+
img[width] { width: 100% !important; height: auto !important; }
|
|
679
|
+
}
|
|
680
|
+
</style>
|
|
681
|
+
</head>
|
|
682
|
+
<body>
|
|
683
|
+
<div class="vibespot-email-wrapper">
|
|
684
|
+
${n.join(`
|
|
685
|
+
`)}
|
|
686
|
+
</div>
|
|
687
|
+
<script>
|
|
688
|
+
document.addEventListener('click', function(e) {
|
|
689
|
+
var a = e.target.closest('a[href^="#"]');
|
|
690
|
+
if (a) { e.preventDefault(); var t = document.querySelector(a.getAttribute('href')); if (t) t.scrollIntoView({ behavior: 'smooth' }); }
|
|
691
|
+
});
|
|
692
|
+
</script>
|
|
693
|
+
</body>
|
|
694
|
+
</html>`}var Xn=j(()=>{"use strict";y();ca();me();hn()});function m(e,t,n){e.writeHead(t,{"Content-Type":"application/json"}),e.end(JSON.stringify(n))}function G(e,t,n={}){let s=n.maxBytes??xS,o=[],r=0,i=!1;e.on("data",a=>{if(!i){if(r+=a.length,r>s){i=!0,o.length=0,n.res&&!n.res.headersSent?(e.pause(),n.res.writeHead(413,{"Content-Type":"application/json",Connection:"close"}),n.res.end(JSON.stringify({error:"Request body too large"}))):e.destroy();return}o.push(a)}}),e.on("end",()=>{i||t(Buffer.concat(o).toString("utf-8"))})}function Ze(e,t,n){G(e,s=>{try{n(JSON.parse(s||"{}"))}catch{m(t,400,{error:"Invalid JSON in request body"})}},{res:t})}var xS,Re=j(()=>{"use strict";y();xS=5*1024*1024});import{homedir as BS}from"os";function N(e){return(e instanceof Error?e.message:String(e)).split(BS()).join("~").replace(JS,"~")}var JS,At=j(()=>{"use strict";y();JS=/(?:\/(?:home|Users)\/|[A-Za-z]:\\Users\\)[^\s/\\'")\]]+/g});function pt(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 r=/position (\d+)/.exec(o.message);if(!r)return null;let i=parseInt(r[1],10);if(i<=n)return null;n=i;let a=Math.max(0,i-5),c=t.slice(a,i+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 Gs(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,r=!1,i=!1;for(let d=n+1;d<e.length;d++){let u=e[d];if(i){i=!1;continue}if(u==="\\"){i=!0;continue}if(u==='"'){r=!r;continue}r||(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 pt(c)}function Au(e){return typeof e=="string"?e.trim()?e:null:e==null?null:JSON.stringify(e,null,2)}function HS(e){let t=typeof e.moduleName=="string"?e.moduleName.trim():"",n=Au(e.fieldsJson),s=Au(e.metaJson);return!t||n===null||s===null?null:{moduleName:t,fieldsJson:n,metaJson:s,moduleHtml:String(e.moduleHtml||""),moduleCss:String(e.moduleCss||""),moduleJs:e.moduleJs?String(e.moduleJs):void 0}}function ya(e,t){let n=[],s=0;for(let o of e){let r=o&&typeof o=="object"?HS(o):null;if(r)n.push(r);else{s++;let i=o&&typeof o=="object"?o.moduleName:void 0;A.warn("parse","Dropping malformed module (missing name/fieldsJson/metaJson)",{moduleName:i})}}return s>0&&t&&t(`${s} module(s) in the AI response were incomplete and skipped. Try sending your request again.`),n}function _u(e,t){let n=!1,s,o=/```vibespot-modules\s*\n?([\s\S]*?)```/g;for(;(s=o.exec(e))!==null;)try{A.info("parse","Found vibespot-modules block",{length:s[1].length});let r=pt(s[1]);if(!r||typeof r!="object")throw A.warn("parse","tryParseJSON returned non-object",{result:typeof r}),new Error("Invalid JSON after repair");let i=r;if(i.modules&&Array.isArray(i.modules)){let a=ya(i.modules,t);a.length>0&&(Ge({modules:a,sharedCss:i.sharedCss!==void 0?String(i.sharedCss):void 0,sharedJs:i.sharedJs!==void 0?String(i.sharedJs):void 0}),n=!0)}}catch(r){A.warn("parse","Failed to parse vibespot-modules block",{error:r instanceof Error?r.message:String(r)})}if(!n){let r=/```(?:json)?\s*\n([\s\S]*?)```/g;for(;(s=r.exec(e))!==null;)if(s[1].includes('"modules"'))try{let i=pt(s[1]);if(!i||typeof i!="object")throw new Error("Invalid JSON after repair");let a=i;if(a.modules&&Array.isArray(a.modules)){let l=ya(a.modules,t);l.length>0&&(Ge({modules:l,sharedCss:a.sharedCss!==void 0?String(a.sharedCss):void 0,sharedJs:a.sharedJs!==void 0?String(a.sharedJs):void 0}),n=!0)}}catch(i){A.warn("parse","Failed to parse JSON module block",{error:i instanceof Error?i.message:String(i)})}}if(!n&&(e.match(/```/g)||[]).length%2!==0&&e.includes('"modules"')){A.info("parse","Detected truncated response (odd fence count), attempting salvage");let i=e.lastIndexOf("```"),a=e.slice(i+3);a=a.replace(/^[\w-]*\s*\n?/,"");let l=Gs(a);if(l){let c=l;if(c.modules&&Array.isArray(c.modules)&&c.modules.length>0){let d=ya(c.modules,t);d.length>0&&(A.info("parse","Salvaged modules from truncated response",{count:d.length}),Ge({modules: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){A.info("parse","No modules applied",{responseLength:e.length,hasVibespot:e.includes("vibespot-modules"),hasModules:e.includes('"modules"'),fenceCount:(e.match(/```/g)||[]).length});let r=e.includes("vibespot-modules")||e.includes('"modules"'),i=/\bmodule|modul/i.test(e)&&(/\bcreated?\b|\berstellt\b|\bgenerat/i.test(e)||/\|.*\|.*\|/m.test(e));if(r||i){let a=r?"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.";A.warn("parse",a),t&&t(a)}}}var Sr=j(()=>{"use strict";y();me();re()});import{createWriteStream as US,mkdirSync as Pu,existsSync as ba,readFileSync as Sa}from"fs";import{join as yn,extname as GS}from"path";import{randomUUID as WS}from"crypto";import KS from"busboy";function YS(e,t){if(Iu.has(t))return t;let n=e.slice(e.lastIndexOf(".")).toLowerCase();return qS[n]??t}function XS(e){return e.replace(/[^a-zA-Z0-9._-]/g,"_").replace(/_{2,}/g,"_").replace(/^_+|_+$/g,"").toLowerCase()}function ZS(e,t){if(!ba(yn(e,t)))return t;let n=GS(t),s=t.slice(0,-n.length||void 0),o=1;for(;ba(yn(e,`${s}-${o}${n}`));)o++;return`${s}-${o}${n}`}async function QS(e){let{PDFParse:t}=await import("pdf-parse"),n=Sa(e),s=new t({data:n});try{return(await s.getText()).text}finally{await s.destroy()}}async function ev(e){return(await(await import("mammoth")).extractRawText({path:e})).value}function tv(e){return Sa(e,"utf-8")}function Mu(e,t){let n=x();if(!n){m(t,400,{error:"No active session"});return}if(!(e.headers["content-type"]||"").includes("multipart/form-data")){m(t,400,{error:"Expected multipart/form-data"});return}let o=[],r=[],i=0,a=[],l=KS({headers:e.headers,limits:{fileSize:VS,files:10}});l.on("file",(c,d,u)=>{let{filename:p,mimeType:g}=u;i++;let f=YS(p,g);if(!Iu.has(f)){r.push(`Unsupported file type: ${p} (${g})`),d.resume();return}let h=Eu.has(f),b=XS(p),S=WS(),v,k;h?(v=yn(n.themePath,"assets"),Pu(v,{recursive:!0}),k=ZS(v,b)):(v=yn(n.themePath,".vibespot","uploads"),Pu(v,{recursive:!0}),k=`${S}-${b}`);let _=yn(v,k),M=US(_),R=0,J=!1;d.on("data",O=>{R+=O.length}),d.on("limit",()=>{J=!0,r.push(`File too large (>10MB): ${p}`)}),d.pipe(M),a.push(new Promise(O=>{M.on("finish",()=>{if(!J){let V={id:S,filename:k,originalName:p,type:h?"image":"document",usage:h?"asset":"context",mimeType:f,size:R,addedAt:new Date().toISOString()};o.push(V),jc(V)}O()}),M.on("error",()=>{r.push(`Failed to write: ${p}`),O()})}))}),l.on("finish",async()=>{await Promise.all(a);for(let c of o)if(c.type==="document"){let d=yn(n.themePath,".vibespot","uploads",c.filename);try{c.mimeType==="application/pdf"?c.extractedText=await QS(d):c.mimeType==="application/vnd.openxmlformats-officedocument.wordprocessingml.document"?c.extractedText=await ev(d):c.extractedText=tv(d),A.info("upload",`Extracted text from ${c.originalName} (${c.extractedText.length} chars)`)}catch(u){A.warn("upload",`Failed to extract text from ${c.originalName}: ${u}`),c.extractedText=`[Could not extract text from ${c.originalName}]`}}if(i===0){m(t,400,{error:"No files uploaded"});return}m(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:r.length>0?r:void 0})}),l.on("error",c=>{A.error("upload",`Busboy error: ${c}`),m(t,500,{error:"Upload failed"})}),e.pipe(l)}function vr(e){let t=x();return t?.assets?e.map(n=>{let s=t.assets.find(r=>r.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 r=yn(t.themePath,"assets",s.filename);ba(r)&&(o.base64=Sa(r).toString("base64")),o.assetPath=`${t.themeName}/assets/${s.filename}`}else s.type==="document"&&(o.extractedText=s.extractedText);return o}).filter(n=>n!==null):[]}var VS,Eu,zS,Iu,qS,va=j(()=>{"use strict";y();Re();me();re();VS=10*1024*1024,Eu=new Set(["image/png","image/jpeg","image/jpg","image/svg+xml","image/webp","image/gif"]),zS=new Set(["application/pdf","application/vnd.openxmlformats-officedocument.wordprocessingml.document","text/markdown","text/plain"]),Iu=new Set([...Eu,...zS]),qS={".md":"text/markdown",".txt":"text/plain",".markdown":"text/markdown"}});function Ws(e){if(e instanceof Ie)return!0;let t=e?.name;if(t==="AbortError"||t==="APIUserAbortError")return!0;let n=e instanceof Error?e.message:"";return/\baborted\b/i.test(n)}function xr(e,t){let n=0,s=[];return t&&t.addEventListener("abort",()=>{for(;s.length>0;)s.shift().reject(new Ie)},{once:!0}),async function(r){if(t?.aborted)throw new Ie;if(n>=e&&(await new Promise((i,a)=>s.push({resolve:i,reject:a})),t?.aborted))throw new Ie;n++;try{return await r()}finally{n--,s.length>0&&s.shift().resolve()}}}var Ie,Qn=j(()=>{"use strict";y();Ie=class extends Error{aborted=!0;constructor(t="Pipeline aborted"){super(t),this.name="PipelineAbortError"}}});var ju={};Ve(ju,{LANGDOCK_BASE_URLS:()=>Ks,callAgent:()=>Ne,callAgentAPI:()=>Du,isAgenticCapable:()=>zs,isCLIEngine:()=>ns,resolveThinkingBudget:()=>ts});function nv(e,t){return new Promise(n=>{let s=setTimeout(()=>{t?.removeEventListener("abort",o),n()},e),o=()=>{clearTimeout(s),n()};t?.addEventListener("abort",o,{once:!0})})}async function es(e,t,n){for(let s=0;;s++)try{return await e()}catch(o){let r=o.status,i=o.error?.type;if(!(r===429||i==="rate_limit_error"||o instanceof Error&&o.message.includes("429"))||s>=xa.length)throw o;let l=xa[s];if(A.warn("agent-adapter",`Rate limited (429), attempt ${s+1}/${xa.length} \u2014 waiting ${l}s`),t&&t(`Rate limited \u2014 retrying in ${l}s...`),await nv(l*1e3,n),n?.aborted)throw new Ie;t&&t("Retrying...")}}function Vs(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 Ou(){return wa||(wa=(await import("@anthropic-ai/sdk")).default),wa}async function $u(e,t,n,s,o,r){let i=await Ou(),a=new i({apiKey:e,...s?{defaultHeaders:s}:{},...r?{baseURL:r}:{}}),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 es(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}}:{}},{signal:n.signal}),p=nt(u.usage);for(let f of u.content)if(f.type==="tool_use")return{type:"structured",data:Vs(f.input),usage:p};return{type:"text",text:u.content.filter(f=>f.type==="text").map(f=>f.text).join(""),usage:p}},n.onStatus,n.signal)}return es(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}}:{}},{signal:n.signal});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 p;try{p=nt((await u.finalMessage()).usage)}catch{}return{type:"text",text:d,usage:p}},n.onStatus,n.signal)}async function sv(e,t,n){let s=await Ou(),o=new s({authToken:e,defaultHeaders:ms}),r=n.messages,i;if(n.systemBlocks?i=[{type:"text",text:In},...n.systemBlocks]:i=[{type:"text",text:In},{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 es(async()=>{let l=await o.messages.create({model:t,max_tokens:n.maxTokens||16e3,system:i,messages:r,tools:[a],tool_choice:{type:"tool",name:n.structuredOutput.name},...n.thinkingBudgetTokens?{thinking:{type:"enabled",budget_tokens:n.thinkingBudgetTokens}}:{}},{signal:n.signal}),c=nt(l.usage);for(let u of l.content)if(u.type==="tool_use")return{type:"structured",data:Vs(u.input),usage:c};return{type:"text",text:l.content.filter(u=>u.type==="text").map(u=>u.text).join(""),usage:c}},n.onStatus,n.signal)}return es(async()=>{let a="",l=o.messages.stream({model:t,max_tokens:n.maxTokens||16e3,system:i,messages:r,...n.enableWebSearch?{tools:[{type:"web_search_20250305",name:"web_search"}]}:{},...n.thinkingBudgetTokens?{thinking:{type:"enabled",budget_tokens:n.thinkingBudgetTokens}}:{}},{signal:n.signal});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=nt((await l.finalMessage()).usage)}catch{}return{type:"text",text:a,usage:c}},n.onStatus,n.signal)}function ka(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"?ka(o):o;t.properties=n}return t.items&&typeof t.items=="object"&&(t.items=ka(t.items)),t}async function Ru(e,t,n,s){let o=[{role:"system",content:n.systemPrompt},...n.messages.map(a=>({role:a.role,content:typeof a.content=="string"?a.content:a.content.map(l=>({type:"text",text:l.text}))}))],r={model:t,max_completion_tokens:n.maxTokens||16e3,messages:o};n.structuredOutput&&(r.response_format={type:"json_schema",json_schema:{name:n.structuredOutput.name,strict:!1,schema:ka(n.structuredOutput.schema)}});let i=s||"https://api.openai.com/v1/chat/completions";return es(async()=>{let a=await fetch(i,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${e}`},body:JSON.stringify(r),signal:n.signal});if(!a.ok){let u=await a.text(),p=a.status;if(p===429){let g=new Error(`OpenAI rate limit: ${u}`);throw g.status=429,g}throw new Error(`OpenAI API error (${p}): ${u}`)}let l=await a.json(),c=l.choices?.[0]?.message?.content||"",d=Bn(l.usage);if(n.structuredOutput)try{return{type:"structured",data:Vs(JSON.parse(c)),usage:d}}catch{return A.warn("agent-adapter","OpenAI structured output parse failed, returning raw text"),{type:"text",text:c,usage:d}}return{type:"text",text:c,usage:d}},n.onStatus,n.signal)}async function Nu(e,t,n,s){let o=t||"gemini-2.5-flash",r=n.messages.map(c=>({role:c.role==="assistant"?"model":"user",parts:typeof c.content=="string"?[{text:c.content}]:c.content.map(d=>({text:d.text}))})),i={systemInstruction:{parts:[{text:n.systemPrompt}]},contents:r,generationConfig:{maxOutputTokens:n.maxTokens||16e3,...n.structuredOutput?{responseMimeType:"application/json",responseSchema:n.structuredOutput.schema}:{}}},a=!!s,l=s||`https://generativelanguage.googleapis.com/v1beta/models/${o}:generateContent?key=${e}`;return es(async()=>{let c=await fetch(l,{method:"POST",headers:{"Content-Type":"application/json",...a?{Authorization:`Bearer ${e}`}:{}},body:JSON.stringify(i),signal:n.signal});if(!c.ok){let g=await c.text(),f=c.status;if(f===429){let h=new Error(`Gemini rate limit: ${g}`);throw h.status=429,h}throw new Error(`Gemini API error (${f}): ${g}`)}let d=await c.json(),u=d.candidates?.[0]?.content?.parts?.[0]?.text||"",p=Jn(d.usageMetadata);if(n.structuredOutput)try{return{type:"structured",data:Vs(JSON.parse(u)),usage:p}}catch{return A.warn("agent-adapter","Gemini structured output parse failed, returning raw text"),{type:"text",text:u,usage:p}}return{type:"text",text:u,usage:p}},n.onStatus,n.signal)}function ov(e,t,n){switch(e){case"claude-code":{let s=["--print",...na];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 rv(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(r=>r.text).join(`
|
|
833
695
|
`);t.push(`
|
|
834
696
|
|
|
835
697
|
## ${s}
|
|
836
|
-
${o}`)}if(e.structuredOutput){let n=
|
|
698
|
+
${o}`)}if(e.structuredOutput){let n=Fu(e.structuredOutput.schema);t.push(`
|
|
837
699
|
|
|
838
700
|
## Output Format \u2014 CRITICAL
|
|
839
701
|
Respond with a JSON code block. Wrap your JSON in \`\`\`json fences. No prose or explanation before or after the code block.
|
|
840
702
|
|
|
841
703
|
The JSON must match this structure:
|
|
842
|
-
${n}`)}return t.join("")}function
|
|
843
|
-
`)}function
|
|
704
|
+
${n}`)}return t.join("")}function Fu(e,t=0){let n=" ".repeat(t),s=e.properties,o=e.required||[];if(!s)return`${n}${JSON.stringify(e)}`;let r=["{"];for(let[i,a]of Object.entries(s)){let l=o.includes(i)?" (required)":"",c=a.type||"any",d=a.description?` \u2014 ${a.description}`:"",u=a.enum?` [${a.enum.join(", ")}]`:"";if(c==="array"&&a.items){let p=a.items.type||"object";r.push(`${n} "${i}": ${c}<${p}>${l}${d}${u}`)}else c==="object"&&a.properties?r.push(`${n} "${i}": ${Fu(a,t+1)}${l}${d}`):r.push(`${n} "${i}": ${c}${l}${d}${u}`)}return r.push(`${n}}`),r.join(`
|
|
705
|
+
`)}function iv(e){let t=e.trim(),n=pt(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=pt(a);if(l&&typeof l=="object")return l;let c=Gs(a);if(c&&typeof c=="object")return c}let o=t.indexOf("{"),r=t.lastIndexOf("}");if(o!==-1&&r>o){let a=t.slice(o,r+1),l=pt(a);if(l&&typeof l=="object")return l;let c=Gs(a);if(c&&typeof c=="object")return c}let i=Gs(t);return i&&typeof i=="object"?i:null}async function av(e,t,n){let{bin:s,args:o}=ov(e,t,n),r=rv(n),i;if(e==="claude-code"){let l=[...o,"--output-format","stream-json","--include-partial-messages","--verbose"];i=await sa(l,r,{onChunk:n.onChunk,onToolUse:(c,d)=>{if(!n.onStatus)return;let u=lv(c,d);n.onStatus(u)}},void 0,n.signal)}else i=await Js(s,o,r,n.onChunk,void 0,n.signal);if(!n.structuredOutput)return{type:"text",text:i};let a=iv(i);return a?{type:"structured",data:Vs(a)}:(A.warn("agent-cli",`${e}: failed to parse structured output, returning text`,{outputPreview:i.slice(0,500),outputLength:i.length}),{type:"text",text:i})}function lv(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 Du(e,t,n,s){A.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,r=await(async()=>{switch(e){case"anthropic-api":return $u(t,n,s);case"claude-oauth":{let{getValidAccessToken:i}=await Promise.resolve().then(()=>($t(),Ci)),a=await i();if(!a)throw new Error("Claude OAuth session expired. Please re-authenticate in Settings.");return sv(a,n,s)}case"openai-api":return Ru(t,n,s);case"gemini-api":return Nu(t,n,s);case"langdock-api":{let i=$(),a=i.langdockProvider||"anthropic",l=i.langdockBaseUrl;switch(a){case"openai":case"mistral":{let c=l||Ks[a];return Ru(t,n,s,`${c}/v1/chat/completions`)}case"google":{let c=l||Ks.google;return Nu(t,n,s,`${c}/v1beta/models/${n}:generateContent`)}default:{let c=l||Ks.anthropic;return $u(t,n,s,void 0,void 0,c)}}}default:throw new Error(`Unsupported API engine: ${e}`)}})();return dv(e,n,s,r,o,new Date),r}function dv(e,t,n,s,o,r){Ct({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:r,metadata:{structured:!!n.structuredOutput,systemPromptLength:n.systemPrompt.length,...n.prompt?.source?{promptSource:n.prompt.source}:{}},...n.prompt?{promptName:n.prompt.name,promptVersion:n.prompt.version}:{}})}async function Ne(e,t,n,s){if(s.signal?.aborted)throw new Ie;return cv.has(e)?Du(e,t,n,s):(A.info("agent-adapter",`${e} CLI call`,{structured:!!s.structuredOutput,schemaName:s.structuredOutput?.name,systemPromptLength:s.systemPrompt.length,messageCount:s.messages.length}),av(e,n,s))}function ts(e){if(e==="langdock-api"){if(($().langdockProvider||"anthropic")!=="anthropic")return 0}else if(e!=="anthropic-api"&&e!=="claude-oauth")return 0;let t=$();if(!t.extendedThinking)return 0;switch(t.extendedThinkingBudget){case"high":return 32e3;case"low":return 4e3;default:return 16e3}}function zs(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 ns(e){return e==="claude-code"||e==="gemini-cli"||e==="codex-cli"}var Ks,jP,xa,wa,cv,mt=j(()=>{"use strict";y();rr();Sr();te();$t();re();un();Ue();Qn();Ks={anthropic:"https://api.langdock.com/anthropic",openai:"https://api.langdock.com/openai",google:"https://api.langdock.com/google",mistral:"https://api.langdock.com/mistral"},jP=Ks.anthropic,xa=[10,20,40,60,120];wa=null;cv=new Set(["anthropic-api","claude-oauth","openai-api","gemini-api","langdock-api"])});var Ca,Lu=j(()=>{"use strict";y();Ca={"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.
|
|
844
706
|
|
|
845
707
|
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.
|
|
846
708
|
|
|
@@ -1176,9 +1038,9 @@ Every style/color field you reference in CSS must ship a complete default value.
|
|
|
1176
1038
|
- Include smooth scroll behavior in nav click handlers, and respect prefers-reduced-motion
|
|
1177
1039
|
|
|
1178
1040
|
## metaJson Template
|
|
1179
|
-
{ "host_template_types": ["PAGE"], "is_available_for_new_content": true }`}}});function
|
|
1041
|
+
{ "host_template_types": ["PAGE"], "is_available_for_new_content": true }`}}});function mv(){if(Bu!==void 0)return Bu;if(qs!==void 0)return qs;try{let e=JSON.parse(I(Kt(pv)));qs=e&&typeof e=="object"&&e.prompts?e:null}catch{qs=null}return qs}function gv(e){let t=new Set;for(let n of e.matchAll(Ju))t.add(n[1]);return[...t]}function Hu(e){let t=Ca[e],n=mv()?.prompts?.[e];if(n&&n.version===t.version&&typeof n.template=="string"){let s=new Set(t.placeholders);if(gv(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 fv(e,t,n){let s=new Set(Ca[e].placeholders);return t.replace(Ju,(o,r)=>s.has(r)?n[r]??"":o)}function Bt(e){let t=Hu(e);return{name:`${uv}${e}`,version:t.version,source:t.source}}function Jt(e,t){return fv(e,Hu(e).template,t)}var uv,pv,Ju,qs,Bu,Ht=j(()=>{"use strict";y();ae();Lu();uv="vibespot-stage-",pv="prompts.bundle.json",Ju=/\{\{\s*([a-zA-Z][\w]*)\s*\}\}/g});function Uu(e,t,n,s,o){let r=t.length>0?`Current template modules (in page order):
|
|
1180
1042
|
${t.map((d,u)=>`${u+1}. ${d}`).join(`
|
|
1181
|
-
`)}`:"No modules yet (new page).",
|
|
1043
|
+
`)}`:"No modules yet (new page).",i=n.length>0?`
|
|
1182
1044
|
|
|
1183
1045
|
Module library (reusable from other templates):
|
|
1184
1046
|
${n.map(d=>`- ${d.name} (used in: ${d.usedIn.join(", ")})`).join(`
|
|
@@ -1193,16 +1055,16 @@ All pages:
|
|
|
1193
1055
|
${o.pages.map(d=>`- ${d.label} (${d.id}, ${d.moduleCount} modules)`).join(`
|
|
1194
1056
|
`)}
|
|
1195
1057
|
|
|
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=`${
|
|
1058
|
+
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=`${r}${i}${a}${l}`;return Jt("intent-analyzer",{themeName:e,contextData:c})}var Gu,Wu=j(()=>{"use strict";y();Ht();Gu={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 Ku(e,t,n,s,o,r,i,a){r({type:"agent_step",step:"analyzing",label:"Analyzing your request..."});let l=t.modules.map(f=>f.moduleName),c=Uu(t.themeName,l,i,t.brandAssets?.themeContext,t.sitePages?{activePageLabel:t.activePageLabel,pages:t.sitePages.map(f=>({id:f.id,label:f.label,moduleCount:f.moduleCount}))}:void 0),d=[],u=t.messages.slice(-6);for(let f of u)if(f.role==="user"||f.role==="assistant"){let h=f.role==="assistant"&&f.content.length>300?f.content.slice(0,300)+"...":f.content;d.push({role:f.role,content:h})}d.push({role:"user",content:e});let p=await ce("intent-analyzer",()=>Ne(n,s,o,{systemPrompt:c,messages:d,structuredOutput:{schema:Gu,name:"pipeline_plan"},maxTokens:2e3,prompt:Bt("intent-analyzer"),signal:a}));if(p.type!=="structured"){A.warn("intent-analyzer","Did not get structured output, falling back");let f=t.modules.length===0;return{intent:f?"create":"modify",affectedModules:f?[]:l,unchangedModules:[],newModules:[],guidesNeeded:["design","content","conversion","hubspot_rules","humanify"],designSystemChanges:f}}let g=p.data;return g.affectedModules=g.affectedModules||[],g.unchangedModules=g.unchangedModules||[],g.newModules=g.newModules||[],g.newModules=g.newModules.map(f=>({...f,name:He(String(f.name??""))})).filter(f=>f.name.length>0),g.pages&&(g.pages=g.pages.map(f=>({...f,id:He(String(f.id??"")),slug:He(String(f.slug??""))})).filter(f=>f.id.length>0)),g.sharedModules&&(g.sharedModules=g.sharedModules.map(f=>He(String(f??""))).filter(f=>f.length>0)),g.guidesNeeded=g.guidesNeeded||[],t.contentMode==="email"||t.contentMode==="blog"?g.contentType=t.contentMode:g.contentType=g.contentType==="email"||g.contentType==="blog"?g.contentType:"page",A.info("intent-analyzer","Plan",{intent:g.intent,affected:g.affectedModules.length,unchanged:g.unchangedModules.length,new:g.newModules.length,reuse:g.reuseModules?.length||0,designSystem:g.designSystemChanges}),r({type:"agent_decision",step:"analyzing",decision:hv(g)}),g}function hv(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 Vu=j(()=>{"use strict";y();mt();Wu();Ht();re();Ue();wt()});function Ta(e,t){let n=[];n.push(Jt("design-system",{themeName:e})),n.push(`
|
|
1197
1059
|
|
|
1198
1060
|
## Design Guide
|
|
1199
|
-
${
|
|
1061
|
+
${ep()}`),t?.styleguide&&n.push(`
|
|
1200
1062
|
|
|
1201
1063
|
## Brand Style Guide
|
|
1202
1064
|
${t.styleguide}`),t?.themeContext&&n.push(`
|
|
1203
1065
|
|
|
1204
1066
|
## Product Context
|
|
1205
|
-
${t.themeContext}`);let s=t?.brandKit&&(t.brandKit.colors?.primary||t.brandKit.colors?.secondary||t.brandKit.colors?.accent||t.brandKit.fonts?.heading||t.brandKit.fonts?.body);if(s){let o=[],
|
|
1067
|
+
${t.themeContext}`);let s=t?.brandKit&&(t.brandKit.colors?.primary||t.brandKit.colors?.secondary||t.brandKit.colors?.accent||t.brandKit.fonts?.heading||t.brandKit.fonts?.body);if(s){let o=[],r=t.brandKit;r.colors?.primary&&o.push(`- Primary color: ${r.colors.primary}`),r.colors?.secondary&&o.push(`- Secondary color: ${r.colors.secondary}`),r.colors?.accent&&o.push(`- Accent color: ${r.colors.accent}`),r.fonts?.heading&&o.push(`- Heading font: ${r.fonts.heading}`),r.fonts?.body&&o.push(`- Body font: ${r.fonts.body}`),r.logoUrl&&o.push(`- Logo URL: ${r.logoUrl}`),o.length>0&&n.push(`
|
|
1206
1068
|
|
|
1207
1069
|
## Brand Kit \u2014 MANDATORY Design Constraints
|
|
1208
1070
|
The following brand identity values MUST be used. Do NOT substitute or override them:
|
|
@@ -1212,11 +1074,11 @@ ${o.join(`
|
|
|
1212
1074
|
## No Brand Provided \u2014 Follow the Generation Recipe
|
|
1213
1075
|
No brand colors, fonts, or styleguide have been set. You MUST follow these rules to create a unique design:
|
|
1214
1076
|
|
|
1215
|
-
${
|
|
1077
|
+
${Qu()}`),n.join("")}function qu(e,t){let n=Ta(e),o=n.indexOf(`
|
|
1216
1078
|
|
|
1217
1079
|
## Design Guide
|
|
1218
|
-
`);if(o===-1)return[{type:"text",text:n}];let
|
|
1219
|
-
${
|
|
1080
|
+
`);if(o===-1)return[{type:"text",text:n}];let r=n.slice(0,o),i=`## Design Guide
|
|
1081
|
+
${ep()}`,a=[{type:"text",text:r},{type:"text",text:i,cache_control:{type:"ephemeral"}}],l=[];t?.styleguide&&l.push(`## Brand Style Guide
|
|
1220
1082
|
${t.styleguide}`),t?.themeContext&&l.push(`## Product Context
|
|
1221
1083
|
${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
|
|
1222
1084
|
The following brand identity values MUST be used. Do NOT substitute or override them:
|
|
@@ -1224,13 +1086,13 @@ ${d.join(`
|
|
|
1224
1086
|
`)}`)}return!c&&!t?.styleguide&&l.push(`## No Brand Provided \u2014 Follow the Generation Recipe
|
|
1225
1087
|
No brand colors, fonts, or styleguide have been set. You MUST follow these rules to create a unique design:
|
|
1226
1088
|
|
|
1227
|
-
${
|
|
1089
|
+
${Qu()}`),l.length>0&&a.push({type:"text",text:l.join(`
|
|
1228
1090
|
|
|
1229
|
-
`)}),a}function
|
|
1230
|
-
`)}function
|
|
1091
|
+
`)}),a}function yv(e){let t=[...new Set([...e.matchAll(/\.([a-zA-Z][\w-]*)/g)].map(r=>`.${r[1]}`))],n=[...new Set([...e.matchAll(/(--[\w-]+)\s*:/g)].map(r=>r[1]))],s=[...new Set([...e.matchAll(/@media\s*\([^)]+\)/g)].map(r=>r[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(`
|
|
1092
|
+
`)}function Xu(e,t,n,s){let o=[],r=yv(t);return o.push(Jt("module-planner",{themeName:e,cssSummary:r})),(!s||s.includes("content"))&&o.push(`
|
|
1231
1093
|
|
|
1232
1094
|
## Content & Copywriting Guide
|
|
1233
|
-
${
|
|
1095
|
+
${bv()}`),n?.brandvoice&&o.push(`
|
|
1234
1096
|
|
|
1235
1097
|
## Brand Voice
|
|
1236
1098
|
${n.brandvoice}`),n?.themeContext&&o.push(`
|
|
@@ -1239,7 +1101,7 @@ ${n.brandvoice}`),n?.themeContext&&o.push(`
|
|
|
1239
1101
|
${n.themeContext}`),n?.humanify!==!1&&s?.includes("humanify")&&o.push(`
|
|
1240
1102
|
|
|
1241
1103
|
## Anti-AI Copy Rules
|
|
1242
|
-
${
|
|
1104
|
+
${Sv()}`),o.join("")}function Qu(){let e=No(),t=zu(e,"## 4. Color System","## 5."),n=zu(e,"### Recommended Font Pairings","### Typography Scale"),s=[];return s.push(`### Step 1: Derive the aesthetic from the content
|
|
1243
1105
|
Read the user's request carefully. What industry? What audience? What mood?
|
|
1244
1106
|
Map it to ONE of these aesthetic directions \u2014 then commit fully:
|
|
1245
1107
|
|
|
@@ -1295,7 +1157,7 @@ Before finalizing, ask yourself:
|
|
|
1295
1157
|
|
|
1296
1158
|
If any answer is "no," go bolder. The user wants personality, not safety.`),s.join(`
|
|
1297
1159
|
|
|
1298
|
-
`)}function
|
|
1160
|
+
`)}function zu(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 ep(){return`### Design Philosophy
|
|
1299
1161
|
You are a senior UI designer. Every page must look professionally designed, not like AI output.
|
|
1300
1162
|
Avoid "AI slop": purple gradients on white, cookie-cutter card grids, no personality.
|
|
1301
1163
|
|
|
@@ -1402,7 +1264,7 @@ Include these in shared CSS:
|
|
|
1402
1264
|
| All animations same speed | Stagger with increasing delays |
|
|
1403
1265
|
| Skip hover/focus states | Every interactive element needs feedback |
|
|
1404
1266
|
| Use \`<br>\` tags for spacing | Use proper margin/padding |
|
|
1405
|
-
| Put everything in a shadowed card | Vary: full-bleed, contained, floating |`}function
|
|
1267
|
+
| Put everything in a shadowed card | Vary: full-bleed, contained, floating |`}function bv(){return`### Mandatory Page Sections (generate all)
|
|
1406
1268
|
1. **Navigation Bar** \u2014 Logo, 4-5 nav links, CTA button, sticky on scroll
|
|
1407
1269
|
2. **Hero** \u2014 Badge/pill, primary headline, subheadline, primary + secondary CTA, trust signals, visual element
|
|
1408
1270
|
3. **Social Proof Bar** \u2014 Logo strip of 4-6 clients OR stats bar (compact, py-8)
|
|
@@ -1490,7 +1352,7 @@ Alternate backgrounds every 2-3 sections to create visual "chapters." Sprinkle t
|
|
|
1490
1352
|
- Invent plausible specifics: neighborhood names, "48 hours" not "quickly", "\u20AC49" not "affordable"
|
|
1491
1353
|
- Keep paragraphs to 2-3 sentences max
|
|
1492
1354
|
- Aim for 6th-grade reading level
|
|
1493
|
-
- Include section labels (UPPERCASE, letter-spacing 0.1em, accent color, 2-3 words) above every headline`}function
|
|
1355
|
+
- Include section labels (UPPERCASE, letter-spacing 0.1em, accent color, 2-3 words) above every headline`}function Sv(){return`### Banned Punctuation
|
|
1494
1356
|
- **Em dashes (\u2014)**: NEVER use. Biggest AI tell. Replace with periods, commas, or parentheses.
|
|
1495
1357
|
- **Semicolons**: Feel academic, not conversational. Use periods instead.
|
|
1496
1358
|
- **Exclamation marks**: One per page maximum. Zero is ideal for B2B.
|
|
@@ -1520,12 +1382,12 @@ seamless, cutting-edge, groundbreaking, game-changer, revolutionary, transformat
|
|
|
1520
1382
|
- Use plain short words: use > utilize, start > commence, help > facilitate
|
|
1521
1383
|
- Vary sentence length aggressively: mix 3-word, 12-word, and 25-word sentences
|
|
1522
1384
|
- Front-load the benefit in the first 5 words
|
|
1523
|
-
- Write like you'd explain it in a bar \u2014 if you wouldn't say it holding a beer, rewrite it`}var
|
|
1385
|
+
- Write like you'd explain it in a bar \u2014 if you wouldn't say it holding a beer, rewrite it`}var Yu,Zu,tp=j(()=>{"use strict";y();tt();Ht();Yu={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"]};Zu={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 Aa(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?"":`
|
|
1524
1386
|
|
|
1525
1387
|
## Brand Kit \u2014 MANDATORY Design Constraints
|
|
1526
1388
|
The following brand identity values MUST be used. Do NOT substitute or override them:
|
|
1527
1389
|
${t.join(`
|
|
1528
|
-
`)}`}function
|
|
1390
|
+
`)}`}function _a(e,t){let n=[];n.push(`You are the Email Design Token Architect for vibeSpot, a HubSpot email template builder.
|
|
1529
1391
|
|
|
1530
1392
|
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.
|
|
1531
1393
|
|
|
@@ -1614,25 +1476,25 @@ Do NOT use: system-ui, -apple-system, Segoe UI, Inter, or any Google Fonts.
|
|
|
1614
1476
|
- No external font imports`),n.push(`
|
|
1615
1477
|
|
|
1616
1478
|
## Email Design Guide
|
|
1617
|
-
${
|
|
1479
|
+
${rp()}`),t?.styleguide&&n.push(`
|
|
1618
1480
|
|
|
1619
1481
|
## Brand Style Guide
|
|
1620
1482
|
${t.styleguide}`),t?.themeContext&&n.push(`
|
|
1621
1483
|
|
|
1622
1484
|
## Product Context
|
|
1623
|
-
${t.themeContext}`);let s=
|
|
1485
|
+
${t.themeContext}`);let s=Aa(t?.brandKit);return s?n.push(s):t?.styleguide||n.push(`
|
|
1624
1486
|
|
|
1625
1487
|
## No Brand Provided \u2014 Be Creative
|
|
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
|
|
1488
|
+
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 np(e,t){let n=_a(e),o=n.indexOf(`
|
|
1627
1489
|
|
|
1628
1490
|
## Email Design Guide
|
|
1629
|
-
`);if(o===-1)return[{type:"text",text:n}];let
|
|
1630
|
-
${
|
|
1491
|
+
`);if(o===-1)return[{type:"text",text:n}];let r=n.slice(0,o),i=`## Email Design Guide
|
|
1492
|
+
${rp()}`,a=[{type:"text",text:r},{type:"text",text:i,cache_control:{type:"ephemeral"}}],l=[];t?.styleguide&&l.push(`## Brand Style Guide
|
|
1631
1493
|
${t.styleguide}`),t?.themeContext&&l.push(`## Product Context
|
|
1632
|
-
${t.themeContext}`);let c=
|
|
1494
|
+
${t.themeContext}`);let c=Aa(t?.brandKit);return c?l.push(c):t?.styleguide||l.push(`## No Brand Provided \u2014 Be Creative
|
|
1633
1495
|
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(`
|
|
1634
1496
|
|
|
1635
|
-
`)}),a}function
|
|
1497
|
+
`)}),a}function op(e,t,n,s){let o=[],r=Object.entries(t).map(([a,l])=>` ${a}: ${l}`).join(`
|
|
1636
1498
|
`);o.push(`You are the Email Module Planner for vibeSpot, a HubSpot email template builder.
|
|
1637
1499
|
|
|
1638
1500
|
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.
|
|
@@ -1644,7 +1506,7 @@ The Design Tokens have already been created. Your module plans MUST reference th
|
|
|
1644
1506
|
## Design Tokens
|
|
1645
1507
|
These literal values will be used in inline styles by module developers:
|
|
1646
1508
|
|
|
1647
|
-
${
|
|
1509
|
+
${r}
|
|
1648
1510
|
|
|
1649
1511
|
## Email Structure Rules
|
|
1650
1512
|
|
|
@@ -1691,7 +1553,7 @@ List all module names in display order (top to bottom)
|
|
|
1691
1553
|
One sentence describing the email's purpose and flow`),(!s||s.includes("content"))&&o.push(`
|
|
1692
1554
|
|
|
1693
1555
|
## Email Content Guide
|
|
1694
|
-
${
|
|
1556
|
+
${vv()}`),n?.brandvoice&&o.push(`
|
|
1695
1557
|
|
|
1696
1558
|
## Brand Voice
|
|
1697
1559
|
${n.brandvoice}`),n?.themeContext&&o.push(`
|
|
@@ -1700,7 +1562,7 @@ ${n.brandvoice}`),n?.themeContext&&o.push(`
|
|
|
1700
1562
|
${n.themeContext}`),n?.humanify!==!1&&s?.includes("humanify")&&o.push(`
|
|
1701
1563
|
|
|
1702
1564
|
## Anti-AI Copy Rules
|
|
1703
|
-
${
|
|
1565
|
+
${xv()}`);let i=Aa(n?.brandKit);return i&&o.push(i),o.join("")}function rp(){return`### Email Design Philosophy
|
|
1704
1566
|
Design for the inbox, not the browser. Email templates must look clean and professional in Gmail, Outlook, Apple Mail, and Yahoo Mail simultaneously.
|
|
1705
1567
|
|
|
1706
1568
|
### Color Strategy
|
|
@@ -1733,7 +1595,7 @@ Design for the inbox, not the browser. Email templates must look clean and profe
|
|
|
1733
1595
|
- Hero images: 600px wide, 2:1 to 3:1 aspect ratio
|
|
1734
1596
|
- Always include alt text (images blocked by default in many clients)
|
|
1735
1597
|
- Use display:block to prevent gaps in Outlook
|
|
1736
|
-
- Product images: consistent sizing within a row`}function
|
|
1598
|
+
- Product images: consistent sizing within a row`}function vv(){return`### Email Types and Structure
|
|
1737
1599
|
|
|
1738
1600
|
**Welcome / Onboarding Email**
|
|
1739
1601
|
- Warm greeting with first-name personalization
|
|
@@ -1779,7 +1641,7 @@ Design for the inbox, not the browser. Email templates must look clean and profe
|
|
|
1779
1641
|
- One idea per paragraph, 2-3 sentences max
|
|
1780
1642
|
- Use "you" more than "we"
|
|
1781
1643
|
- Specific > vague: "saves 3 hours/week" beats "saves time"
|
|
1782
|
-
- CTA copy = verb + benefit: "Start Your Trial", "See the Results"`}function
|
|
1644
|
+
- CTA copy = verb + benefit: "Start Your Trial", "See the Results"`}function xv(){return`### Email-Specific Anti-AI Rules
|
|
1783
1645
|
- No em dashes (\u2014) in email copy. Period.
|
|
1784
1646
|
- No "I hope this email finds you well"
|
|
1785
1647
|
- No "In today's fast-paced world"
|
|
@@ -1788,61 +1650,49 @@ Design for the inbox, not the browser. Email templates must look clean and profe
|
|
|
1788
1650
|
- One exclamation mark per email maximum
|
|
1789
1651
|
- Avoid tricolon structures ("Fast, reliable, secure")
|
|
1790
1652
|
- Write like a colleague, not a press release
|
|
1791
|
-
- Every sentence must earn its place \u2014 if removing it doesn't hurt, remove it`}var
|
|
1792
|
-
${e}`;n.modules.length>0&&t.designSystemChanges&&(
|
|
1793
|
-
|
|
1794
|
-
## Current Shared CSS (update this)
|
|
1795
|
-
\`\`\`css
|
|
1796
|
-
${n.sharedCss}
|
|
1797
|
-
\`\`\``);let m=Un(s),g=a?Vr:Gr,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}:{},...a?{}:{prompt:wt("design-system")}})),f;h.type!=="structured"?(M.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,M.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(`
|
|
1799
|
-
`)}
|
|
1800
|
-
}
|
|
1801
|
-
|
|
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(`
|
|
1803
|
-
`)}),r({type:"design_system_ready",sharedCss:b,sharedJs:f.sharedJs||"",aesthetic:f.aesthetic||""}),{...f,sharedCss:b}}async function Hd(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?qo(n.themeName,n.brandAssets):Yo(n.themeName,n.brandAssets),d=l?a?Kr(n.themeName,n.brandAssets):Ur(n.themeName,n.brandAssets):void 0,u=`## User Request
|
|
1804
|
-
${e}`;n.modules.length>0&&t.designSystemChanges&&(u+=`
|
|
1653
|
+
- Every sentence must earn its place \u2014 if removing it doesn't hurt, remove it`}var sp,ip=j(()=>{"use strict";y();sp={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"]}});function wv(e,t){let n=r=>{let i=String(r??"");return t.has(i)&&ws(i)?i:He(i)},s=e.modules.map(r=>({...r,name:n(r.name)})).filter(r=>r.name.length>0),o=(e.moduleOrder||[]).map(r=>n(r)).filter(r=>r.length>0);return{...e,modules:s,moduleOrder:o}}async function ss(e,t,n,s,o,r,i,a){let l=t.contentType==="email";i({type:"agent_step",step:"designing",label:l?"Creating email design tokens...":"Creating design system..."});let c=s==="anthropic-api"||s==="claude-oauth",d=l?_a(n.themeName,n.brandAssets):Ta(n.themeName,n.brandAssets),u=c?l?np(n.themeName,n.brandAssets):qu(n.themeName,n.brandAssets):void 0,p=`## User Request
|
|
1654
|
+
${e}`;n.modules.length>0&&t.designSystemChanges&&(p+=`
|
|
1805
1655
|
|
|
1806
1656
|
## Current Shared CSS (update this)
|
|
1807
1657
|
\`\`\`css
|
|
1808
1658
|
${n.sharedCss}
|
|
1809
|
-
\`\`\``);let
|
|
1810
|
-
${Object.entries(
|
|
1659
|
+
\`\`\``);let g=ts(s),f=l?sp:Yu,h=await ce("design-system",()=>Ne(s,o,r,{systemPrompt:d,systemBlocks:u,messages:[{role:"user",content:p}],structuredOutput:{schema:f,name:"design_system"},maxTokens:16e3,...g>0?{thinkingBudgetTokens:g}:{},...l?{}:{prompt:Bt("design-system")},signal:a})),b;h.type!=="structured"?(A.warn("page-architect","Design system: did not get structured output, using fallback"),b={cssVariables:{},sharedCss:n.sharedCss||"",sharedJs:n.sharedJs||"",aesthetic:"default"}):(b=h.data,A.info("page-architect","Design system created",{aesthetic:b.aesthetic,varCount:Object.keys(b.cssVariables||{}).length,cssLength:b.sharedCss?.length||0}));let S=l?"":b.sharedCss||"",v=b.cssVariables;!l&&v&&typeof v=="object"&&Object.keys(v).length>0&&(S.includes(":root")||(S=`:root {
|
|
1660
|
+
${Object.entries(v).map(([V,H])=>` ${V.startsWith("--")?V:`--${V}`}: ${H};`).join(`
|
|
1811
1661
|
`)}
|
|
1812
1662
|
}
|
|
1813
1663
|
|
|
1814
|
-
${
|
|
1815
|
-
`)}),
|
|
1816
|
-
${e}`;if(t.newModules.length>0&&(
|
|
1664
|
+
${S}`));let k=[],_=/\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(_)||[]).map(O=>O.trim()))];if(M.length>0){let O=M.filter(H=>S.toLowerCase().includes(H.toLowerCase())),V=M.filter(H=>!O.includes(H));V.length>0&&k.push(`Note: ${V.join(", ")} not available \u2014 HubSpot modules use system font stacks (no external font imports allowed)`)}let R=Object.keys(v||{}).length,J=l?[`Email design tokens: ${b.aesthetic||"created"} | ${R} tokens`]:[`Design system: ${b.aesthetic||"created"} | ${R} variables, ${S.length} chars CSS`,...k];return i({type:"agent_decision",step:"designing",decision:J.join(`
|
|
1665
|
+
`)}),i({type:"design_system_ready",sharedCss:S,sharedJs:b.sharedJs||"",aesthetic:b.aesthetic||""}),{...b,sharedCss:S}}async function ap(e,t,n,s,o,r,i,a){let l=await ss(e,t,n,s,o,r,i,a);return wr(e,t,n,l,l.sharedCss,s,o,r,i,a)}async function wr(e,t,n,s,o,r,i,a,l,c){let d=t.contentType==="email",u=s.cssVariables,p=ts(r);l({type:"agent_step",step:"designing",label:"Planning modules..."});let g=d?op(n.themeName,u||{},n.brandAssets,t.guidesNeeded):Xu(n.themeName,o,n.brandAssets,t.guidesNeeded),f=`## User Request
|
|
1666
|
+
${e}`;if(t.newModules.length>0&&(f+=`
|
|
1817
1667
|
|
|
1818
1668
|
## Planned Modules
|
|
1819
|
-
${t.newModules.map((k
|
|
1820
|
-
`)}`),n.modules.length>0){let
|
|
1669
|
+
${t.newModules.map((v,k)=>`${k+1}. **${v.name}** \u2014 ${v.description}`).join(`
|
|
1670
|
+
`)}`),n.modules.length>0){let v=new Set(t.affectedModules),k=n.modules.filter(M=>v.has(M.moduleName)),_=n.modules.filter(M=>!v.has(M.moduleName));k.length>0&&(f+=`
|
|
1821
1671
|
|
|
1822
1672
|
## Existing Modules to Re-plan (PRESERVE THESE EXACT NAMES)
|
|
1823
1673
|
These already exist and are being regenerated. Your output's module names MUST match these exactly \u2014 do NOT rename, retitle-case, or "improve" them. Their content/layout may change; their identifier must not.
|
|
1824
|
-
`+
|
|
1825
|
-
`)),
|
|
1674
|
+
`+k.map(M=>`- \`${M.moduleName}\``).join(`
|
|
1675
|
+
`)),_.length>0&&(f+=`
|
|
1826
1676
|
|
|
1827
1677
|
## Existing Modules to Keep (do not re-plan)
|
|
1828
1678
|
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).
|
|
1829
|
-
`+
|
|
1830
|
-
`))}let
|
|
1831
|
-
`)}function
|
|
1679
|
+
`+_.map(M=>`- \`${M.moduleName}\``).join(`
|
|
1680
|
+
`))}let h=await ce("module-planner",()=>Ne(r,i,a,{systemPrompt:g,messages:[{role:"user",content:f}],structuredOutput:{schema:Zu,name:"module_plan"},maxTokens:8e3,...p>0?{thinkingBudgetTokens:p}:{},...d?{}:{prompt:Bt("module-planner")},signal:c})),b,S={modules:t.newModules.map(v=>({name:v.name,description:v.description,contentBrief:"Generate appropriate content",layoutNotes:"Use responsive layout"})),moduleOrder:t.newModules.map(v=>v.name),narrative:"Page generated from user request"};if(h.type!=="structured")A.warn("page-architect","Module planner: did not get structured output, using fallback"),b=S;else{let v=h.data;Array.isArray(v?.modules)&&v.modules.length>0?(b=v,b.moduleOrder=b.moduleOrder||b.modules.map(k=>k.name),b.narrative=b.narrative||"Page generated from user request"):(A.warn("page-architect","Module planner: structured output missing 'modules' array, using fallback",{keys:v?Object.keys(v):[]}),b=S),A.info("page-architect","Module plan",{moduleCount:b.modules.length})}return b=wv(b,new Set(n.modules.map(v=>v.moduleName))),l({type:"agent_decision",step:"designing",decision:`Page: ${b.narrative} | ${b.modules.length} modules planned`}),{designSystem:{cssVariables:s.cssVariables||{},sharedCss:o,sharedJs:s.sharedJs},modules:b.modules,moduleOrder:b.moduleOrder,narrative:b.narrative}}var lp=j(()=>{"use strict";y();mt();tp();ip();Ht();re();Ue();wt()});function kv(e){let t=[...new Set([...e.matchAll(/\.([a-zA-Z][\w-]*)/g)].map(r=>`.${r[1]}`))],n=[...new Set([...e.matchAll(/(--[\w-]+)\s*:/g)].map(r=>r[1]))],s=[...new Set([...e.matchAll(/@media\s*\([^)]+\)/g)].map(r=>r[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(`
|
|
1681
|
+
`)}function cp(e,t,n,s,o){let r=kv(s),i=t.map(d=>`- **${d.label}** (${d.pageType}, slug: "${d.slug}"): ${d.purpose}`).join(`
|
|
1832
1682
|
`),a=n.map(d=>`- **${d}**`).join(`
|
|
1833
1683
|
`),l=[],c=t.map(d=>` - "${d.label}" \u2192 href="/${d.slug}"`).join(`
|
|
1834
|
-
`);return l.push(
|
|
1684
|
+
`);return l.push(Jt("site-module-planner",{themeName:e,siteMap:i,sharedList:a,cssSummary:r,navHrefs:c,sharedModuleNamesCsv:n.join(", ")})),o?.brandvoice&&l.push(`
|
|
1835
1685
|
|
|
1836
1686
|
## Brand Voice
|
|
1837
1687
|
${o.brandvoice}`),o?.themeContext&&l.push(`
|
|
1838
1688
|
|
|
1839
1689
|
## Product Context
|
|
1840
|
-
${o.themeContext}`),l.join("")}var
|
|
1690
|
+
${o.themeContext}`),l.join("")}var dp,up=j(()=>{"use strict";y();Ht();dp={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 mp(e,t,n,s,o,r,i,a,l){a({type:"agent_step",step:"planning_site",label:`Planning modules for ${t.pages?.length||0} pages...`});let c=t.pages||[],d=t.sharedModules||["site-header","site-footer"],u=cp(n.themeName,c,d,s,n.brandAssets),p=`## User Request
|
|
1841
1691
|
${e}
|
|
1842
1692
|
|
|
1843
1693
|
## Site Map
|
|
1844
|
-
${
|
|
1845
|
-
`)}`,
|
|
1694
|
+
${c.map(k=>`- ${k.label} (${k.slug}): ${k.purpose}`).join(`
|
|
1695
|
+
`)}`,g=ts(o),f=await ce("site-module-planner",()=>Ne(o,r,i,{systemPrompt:u,messages:[{role:"user",content:p}],structuredOutput:{schema:dp,name:"site_module_plan"},maxTokens:16e3,...g>0?{thinkingBudgetTokens:g}:{},prompt:Bt("site-module-planner"),signal:l}));if(f.type!=="structured")return A.warn("site-planner","Did not get structured output, building fallback"),pp(t,d,s);let h=f.data;if(!Array.isArray(h?.pages)||!Array.isArray(h?.sharedModules))return A.warn("site-planner","Structured output missing expected fields",{keys:h?Object.keys(h):[]}),pp(t,d,s);let b=h.sharedModules.map(k=>({name:He(String(k.name??"")),description:k.description,contentBrief:k.contentBrief,layoutNotes:k.layoutNotes})).filter(k=>k.name.length>0),S=h.pages.map(k=>({pageId:He(String(k.pageId??"")),modules:(k.modules||[]).map(_=>({name:He(String(_.name??"")),description:_.description,contentBrief:_.contentBrief,layoutNotes:_.layoutNotes})).filter(_=>_.name.length>0),moduleOrder:(k.moduleOrder||[]).map(_=>He(String(_??""))).filter(_=>_.length>0)})),v=b.length+S.reduce((k,_)=>k+_.modules.length,0);return A.info("site-planner","Site plan complete",{pages:S.length,sharedModules:b.length,totalModules:v}),a({type:"agent_decision",step:"planning_site",decision:`${S.length} pages planned, ${b.length} shared modules, ${v} total modules`}),a({type:"site_blueprint_ready",pages:S.map(k=>{let _=c.find(M=>M.id===k.pageId);return{pageId:k.pageId,label:_?.label||k.pageId,moduleCount:k.modules.length}}),sharedModuleCount:b.length}),{designSystem:{cssVariables:{},sharedCss:s},pages:S,sharedModules:b,narrative:h.narrative||"Multi-page site generated from user request"}}function pp(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 gp=j(()=>{"use strict";y();mt();up();Ht();re();Ue();wt()});function Ys(e,t,n,s){let o=[];return o.push(Jt("module-developer",{themeName:e})),t&&o.push(`
|
|
1846
1696
|
|
|
1847
1697
|
## Theme Shared CSS (use these custom properties)
|
|
1848
1698
|
\`\`\`css
|
|
@@ -1850,29 +1700,29 @@ ${t}
|
|
|
1850
1700
|
\`\`\``),(!n||n.includes("hubspot_rules"))&&o.push(`
|
|
1851
1701
|
|
|
1852
1702
|
## HubSpot CMS Rules
|
|
1853
|
-
${
|
|
1703
|
+
${et()}`),(!n||n.includes("conversion"))&&o.push(`
|
|
1854
1704
|
|
|
1855
1705
|
## Conversion Guide
|
|
1856
|
-
${
|
|
1706
|
+
${Ce()}`),s?.themeContext&&o.push(`
|
|
1857
1707
|
|
|
1858
1708
|
## Product Context
|
|
1859
1709
|
${s.themeContext}`),s?.humanify!==!1&&n?.includes("humanify")&&o.push(`
|
|
1860
1710
|
|
|
1861
1711
|
## Anti-AI Copy Rules
|
|
1862
|
-
${
|
|
1712
|
+
${fp()}`),o.join("")}function kr(e,t,n,s){let o=[],r=Ys(e,"",[],s?{...s,humanify:!1}:void 0);t&&(r+=`
|
|
1863
1713
|
|
|
1864
1714
|
## Theme Shared CSS (use these custom properties)
|
|
1865
1715
|
\`\`\`css
|
|
1866
1716
|
${t}
|
|
1867
|
-
\`\`\``),o.push({type:"text",text:
|
|
1868
|
-
${
|
|
1869
|
-
${
|
|
1717
|
+
\`\`\``),o.push({type:"text",text:r});let i=[];(!n||n.includes("hubspot_rules"))&&i.push(`## HubSpot CMS Rules
|
|
1718
|
+
${et()}`),(!n||n.includes("conversion"))&&i.push(`## Conversion Guide
|
|
1719
|
+
${Ce()}`),i.length>0&&o.push({type:"text",text:i.join(`
|
|
1870
1720
|
|
|
1871
1721
|
`),cache_control:{type:"ephemeral"}});let a=[];return s?.themeContext&&a.push(`## Product Context
|
|
1872
1722
|
${s.themeContext}`),s?.humanify!==!1&&n?.includes("humanify")&&a.push(`## Anti-AI Copy Rules
|
|
1873
|
-
${
|
|
1723
|
+
${fp()}`),a.length>0&&o.push({type:"text",text:a.join(`
|
|
1874
1724
|
|
|
1875
|
-
`)}),o}function
|
|
1725
|
+
`)}),o}function fp(){return`### Banned Punctuation
|
|
1876
1726
|
- **Em dashes (\u2014)**: NEVER use. Replace with periods, commas, or parentheses. Hyphens for compounds fine.
|
|
1877
1727
|
- **Semicolons**: Use periods instead in marketing copy.
|
|
1878
1728
|
- **Exclamation marks**: One per page max. Zero ideal for B2B.
|
|
@@ -1911,7 +1761,7 @@ Never end with: "The future of [X] is here", "Your journey starts here", "Join t
|
|
|
1911
1761
|
- Keep slightly imperfect (fragments OK, mild hedging like "honestly didn't think")
|
|
1912
1762
|
- Full names, specific roles (not "John D., CEO")
|
|
1913
1763
|
- Never start with "This product is..." \u2014 start with the person's situation
|
|
1914
|
-
- Vary length and voice across testimonials`}function
|
|
1764
|
+
- Vary length and voice across testimonials`}function hp(e,t,n){let s=[];return s.push(`## User Request
|
|
1915
1765
|
${e}`),s.push(`
|
|
1916
1766
|
|
|
1917
1767
|
## Module Specification
|
|
@@ -1938,7 +1788,7 @@ ${n.moduleCss}
|
|
|
1938
1788
|
**module.js:**
|
|
1939
1789
|
\`\`\`js
|
|
1940
1790
|
${n.moduleJs}
|
|
1941
|
-
\`\`\``)),s.join("")}var
|
|
1791
|
+
\`\`\``)),s.join("")}var Xs,Pa=j(()=>{"use strict";y();tt();Ht();Xs={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 Ea(e,t){let n=[];if(n.push(`You are an Email Module Developer for vibeSpot, a HubSpot CMS builder.
|
|
1942
1792
|
|
|
1943
1793
|
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.
|
|
1944
1794
|
|
|
@@ -2096,17 +1946,17 @@ Modules that serve as email footers MUST include:
|
|
|
2096
1946
|
${t.themeContext}`),t?.humanify!==!1&&n.push(`
|
|
2097
1947
|
|
|
2098
1948
|
## Anti-AI Copy Rules
|
|
2099
|
-
${
|
|
1949
|
+
${bp()}`),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(`
|
|
2100
1950
|
|
|
2101
1951
|
## Brand Kit \u2014 MANDATORY Design Constraints
|
|
2102
1952
|
The following brand identity values MUST be used. Do NOT substitute or override them:
|
|
2103
1953
|
${s.join(`
|
|
2104
|
-
`)}`)}return n.join("")}function
|
|
2105
|
-
${o}`,cache_control:{type:"ephemeral"}});let
|
|
2106
|
-
${t.themeContext}`),t?.humanify!==!1&&
|
|
2107
|
-
${
|
|
1954
|
+
`)}`)}return n.join("")}function yp(e,t){let n=[],s=Ea(e,{...t,humanify:!1});n.push({type:"text",text:s});let o;try{o=cc()}catch{o=""}o&&n.push({type:"text",text:`## Email Template Rules Reference
|
|
1955
|
+
${o}`,cache_control:{type:"ephemeral"}});let r=[];return t?.themeContext&&r.push(`## Product Context
|
|
1956
|
+
${t.themeContext}`),t?.humanify!==!1&&r.push(`## Anti-AI Copy Rules
|
|
1957
|
+
${bp()}`),r.length>0&&n.push({type:"text",text:r.join(`
|
|
2108
1958
|
|
|
2109
|
-
`)}),n}function
|
|
1959
|
+
`)}),n}function bp(){return`### Banned Punctuation
|
|
2110
1960
|
- **Em dashes (\u2014)**: NEVER use. Replace with periods, commas, or parentheses.
|
|
2111
1961
|
- **Semicolons**: Use periods instead.
|
|
2112
1962
|
- **Exclamation marks**: One per email max. Zero ideal for B2B.
|
|
@@ -2125,7 +1975,7 @@ Never start with: "In today's", "In an era", "Whether you're", "Imagine a world"
|
|
|
2125
1975
|
- Be concrete: "42 minutes" not "fast", "\u20AC29/month" not "affordable"
|
|
2126
1976
|
- Use plain words: use > utilize, start > commence, help > facilitate
|
|
2127
1977
|
- Front-load the benefit in the first 5 words
|
|
2128
|
-
- Email subject lines: specific, benefit-first, under 50 chars`}function
|
|
1978
|
+
- Email subject lines: specific, benefit-first, under 50 chars`}function Sp(e,t,n){let s=[];return s.push(`## User Request
|
|
2129
1979
|
${e}`),s.push(`
|
|
2130
1980
|
|
|
2131
1981
|
## Email Module Specification
|
|
@@ -2145,7 +1995,7 @@ ${n.fieldsJson}
|
|
|
2145
1995
|
**module.html:**
|
|
2146
1996
|
\`\`\`html
|
|
2147
1997
|
${n.moduleHtml}
|
|
2148
|
-
\`\`\``),s.join("")}var
|
|
1998
|
+
\`\`\``),s.join("")}var vp,xp=j(()=>{"use strict";y();tt();vp={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 Ia(e,t,n,s){let o=[];o.push(`You are a Blog Module Developer for vibeSpot, a HubSpot CMS builder.
|
|
2149
1999
|
|
|
2150
2000
|
Your job: generate ONE HubSpot CMS blog module. You receive a module specification and must produce the complete module code optimized for blog templates.
|
|
2151
2001
|
|
|
@@ -2330,22 +2180,22 @@ The blog post body module wraps \`{{ content.post_body }}\` with reading-optimiz
|
|
|
2330
2180
|
${s.themeContext}`),s?.humanify!==!1&&o.push(`
|
|
2331
2181
|
|
|
2332
2182
|
## Anti-AI Copy Rules
|
|
2333
|
-
${
|
|
2334
|
-
${
|
|
2335
|
-
${
|
|
2183
|
+
${kp()}`);let r=[];if(n?.includes("conversion"))try{let i=Ce();i&&r.push(`## Conversion Guide
|
|
2184
|
+
${i}`)}catch{}if(n?.includes("hubspot_rules"))try{let i=et();i&&r.push(`## HubSpot Rules
|
|
2185
|
+
${i}`)}catch{}return r.length>0&&o.push(`
|
|
2336
2186
|
|
|
2337
|
-
${
|
|
2187
|
+
${r.join(`
|
|
2338
2188
|
|
|
2339
|
-
`)}`),o.join("")}function
|
|
2340
|
-
${
|
|
2341
|
-
${c}`)}catch{}if(n?.includes("hubspot_rules"))try{let c=
|
|
2189
|
+
`)}`),o.join("")}function wp(e,t,n,s){let o=[],r=Ia(e,t,void 0,{...s,humanify:!1});o.push({type:"text",text:r});let i;try{i=dc()}catch{i=""}i&&o.push({type:"text",text:`## Blog Template Rules Reference
|
|
2190
|
+
${i}`,cache_control:{type:"ephemeral"}});let a=[];if(n?.includes("conversion"))try{let c=Ce();c&&a.push(`## Conversion Guide
|
|
2191
|
+
${c}`)}catch{}if(n?.includes("hubspot_rules"))try{let c=et();c&&a.push(`## HubSpot Rules
|
|
2342
2192
|
${c}`)}catch{}a.length>0&&o.push({type:"text",text:a.join(`
|
|
2343
2193
|
|
|
2344
2194
|
`),cache_control:{type:"ephemeral"}});let l=[];return s?.themeContext&&l.push(`## Product Context
|
|
2345
2195
|
${s.themeContext}`),s?.humanify!==!1&&l.push(`## Anti-AI Copy Rules
|
|
2346
|
-
${
|
|
2196
|
+
${kp()}`),l.length>0&&o.push({type:"text",text:l.join(`
|
|
2347
2197
|
|
|
2348
|
-
`)}),o}function
|
|
2198
|
+
`)}),o}function kp(){return`### Banned Punctuation
|
|
2349
2199
|
- **Em dashes (\u2014)**: NEVER use. Replace with periods, commas, or parentheses.
|
|
2350
2200
|
- **Semicolons**: Use periods instead.
|
|
2351
2201
|
- **Exclamation marks**: Maximum one per page. Zero ideal for B2B.
|
|
@@ -2364,7 +2214,7 @@ Never start with: "In today's", "In an era", "Whether you're", "Imagine a world"
|
|
|
2364
2214
|
- Be concrete: "42 minutes" not "fast", "\u20AC29/month" not "affordable"
|
|
2365
2215
|
- Use plain words: use > utilize, start > commence, help > facilitate
|
|
2366
2216
|
- Front-load the benefit in the first 5 words
|
|
2367
|
-
- Blog headlines: specific, benefit-first, no clickbait`}function
|
|
2217
|
+
- Blog headlines: specific, benefit-first, no clickbait`}function Cp(e,t,n){let s=[];return s.push(`## User Request
|
|
2368
2218
|
${e}`),s.push(`
|
|
2369
2219
|
|
|
2370
2220
|
## Blog Module Specification
|
|
@@ -2389,36 +2239,142 @@ ${n.moduleHtml}
|
|
|
2389
2239
|
**module.css:**
|
|
2390
2240
|
\`\`\`css
|
|
2391
2241
|
${n.moduleCss}
|
|
2392
|
-
\`\`\``),s.join("")}var
|
|
2242
|
+
\`\`\``),s.join("")}var Tp,Ap=j(()=>{"use strict";y();tt();tt();Tp={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 Ma(e,t,n,s,o,r,i,a,l,c,d,u,p){let g=u==="email",f=u==="blog",h=g?"email module":f?"blog module":"module";l({type:"agent_step",step:"developing",label:`Generating ${t.length} ${h}${t.length===1?"":"s"}...`});let b=o==="anthropic-api"||o==="claude-oauth",S=g?Ea(s,d):f?Ia(s,n,c,d):Ys(s,n,c,d),v=b?g?yp(s,d):f?wp(s,n,c,d):kr(s,n,c,d):void 0,k=xr(a,p),_=t.length,M=g?vp:f?Tp:Xs,R=g||f?void 0:Bt("module-developer"),J=t.map((V,H)=>k(async()=>{l({type:"module_progress",module:V.name,status:"generating",current:H+1,total:_});let P="";for(let F=0;F<2;F++){if(p?.aborted)throw new Ie;try{F>0&&(A.warn("module-developer",`${V.name}: retrying after failure (attempt ${F+1})`),l({type:"module_progress",module:V.name,status:"retrying",current:H+1,total:_}));let z=await _p(e,V,S,o,r,i,0,v,g,M,f,R,p);return l({type:"module_progress",module:V.name,status:"complete",current:H+1,total:_,moduleFiles:z}),{moduleName:V.name,module:z}}catch(z){if(Ws(z))throw z instanceof Ie?z:new Ie;P=z instanceof Error?z.message:typeof z=="object"&&z!==null?JSON.stringify(z):String(z),A.error("module-developer",`Failed: ${V.name} (attempt ${F+1})`,{error:P})}}return l({type:"module_progress",module:V.name,status:"failed",current:H+1,total:_}),{moduleName:V.name,error:P}})),O=await Promise.allSettled(J);if(p?.aborted)throw new Ie;return O.map((V,H)=>V.status==="fulfilled"?V.value:{moduleName:t[H].name,error:V.reason instanceof Error?V.reason.message:String(V.reason)})}async function _p(e,t,n,s,o,r,i=0,a,l=!1,c=Xs,d=!1,u,p){let g=l?Sp(e,t,t.existingCode):d?Cp(e,t,t.existingCode):hp(e,t,t.existingCode),f=await Ne(s,o,r,{systemPrompt:n,systemBlocks:a,messages:[{role:"user",content:g}],structuredOutput:{schema:c,name:"module_output"},maxTokens:16e3,...u?{prompt:u}:{},signal:p});if(f.type!=="structured"){if(i<2)return A.warn("module-developer",`${t.name}: no structured output, retry ${i+1}`),_p(e,t,n,s,o,r,i+1,a,l,c,d,u,p);throw new Error(`Module "${t.name}" failed to produce structured output after ${i+1} attempts`)}let h=f.data,b=typeof h.fieldsJson=="string"?h.fieldsJson:JSON.stringify(h.fieldsJson,null,2),S=typeof h.metaJson=="string"?h.metaJson:JSON.stringify(h.metaJson,null,2);return{moduleName:t.name,fieldsJson:b,metaJson:S,moduleHtml:String(h.moduleHtml||""),moduleCss:l?"":String(h.moduleCss||""),moduleJs:l?void 0:h.moduleJs?String(h.moduleJs):void 0}}var Pp=j(()=>{"use strict";y();mt();Qn();Pa();xp();Ap();Ht();re()});function Zs(e,t,n,s,o){let r=s==="email",i=s==="blog";return n({type:"agent_step",step:"quality_check",label:r?"Email quality check...":i?"Blog quality check...":"Quality check..."}),e.map(a=>{let l=[],c={...a};c.fieldsJson=Ep(c.fieldsJson,c.moduleName,"fieldsJson",l,r),c.metaJson=Ep(c.metaJson,c.moduleName,"metaJson",l,r,i);let d={};c.fieldsJson=Tv(c.fieldsJson,c.moduleName,l,d),c.moduleHtml=Av(c.moduleHtml,d),c.fieldsJson=_v(c.fieldsJson,c.moduleName,l),r?c=jv(c,l):(c.moduleCss=Pv(c.moduleCss,c.moduleName,"moduleCss",l),c.moduleCss=Iv(c.moduleCss,c.moduleName,t,l),c.moduleHtml=Mv(c.moduleHtml,c.moduleName,t,l),i&&(c=Lv(c,l))),c.moduleHtml=Rv(c.moduleHtml,c.moduleName,l),r||Nv(c,l),c.metaJson=Ov(c.metaJson,c.moduleName,l,r,i),o&&Dv(c,o,l);let u=l.every(p=>p.autoFixed);return l.length>0&&A.info("validator",`${c.moduleName}: ${l.length} issues`,{autoFixed:l.filter(p=>p.autoFixed).length,unfixed:l.filter(p=>!p.autoFixed).length}),{module:c,issues:l,valid:u}})}function Ep(e,t,n,s,o=!1,r=!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":r?"BLOG_POST":"PAGE"],is_available_for_new_content:!0}):e):pt(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":r?"BLOG_POST":"PAGE"],is_available_for_new_content:!0})):e}function Tv(e,t,n,s){let o=e;for(let[r,i]of Cv)new RegExp(`"name"\\s*:\\s*"${r}"`,"g").test(o)&&(n.push({module:t,field:"fieldsJson",message:`"${r}" is a reserved field name \u2192 renamed to "${i}"`,autoFixed:!0}),o=o.replace(new RegExp(`"name"\\s*:\\s*"${r}"`,"g"),`"name": "${i}"`),s[r]=i);return o}function Av(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 _v(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 Pv(e,t,n,s){if(!e)return e;let o=e,r=/@import\s+url\([^)]*(?:fonts\.googleapis|cdnjs|unpkg|jsdelivr)[^)]*\)\s*;?/gi;return r.test(o)&&(s.push({module:t,field:n,message:"CDN @import removed (external imports not allowed)",autoFixed:!0}),o=o.replace(r,"/* CDN import removed */")),o}function Mp(e){return Ev.has(e)||e.startsWith("body-wrapper")||e.startsWith("dnd-")||e.startsWith("row-")||e.startsWith("hs-")||e.startsWith("hs_")}function Iv(e,t,n,s){if(!e)return e;let o=n+"-",r=/\.([a-zA-Z][\w-]*)/g,i=new Set,a;for(;(a=r.exec(e))!==null;){let c=a[1];!c.startsWith(o)&&!Mp(c)&&i.add(c)}if(i.size<=3)return e;let l=e;for(let c of i){let d=new RegExp(`\\.${$v(c)}(?=[\\s,{:+~>\\[\\]])`,"g");l=l.replace(d,`.${o}${c}`)}return l!==e&&s.push({module:t,field:"moduleCss",message:`${i.size} CSS classes auto-prefixed with "${o}"`,autoFixed:!0}),l}function Mv(e,t,n,s){if(!e)return e;let o=n+"-",r=/class="([^"]*)"/g,i=!1,a=e.replace(r,(l,c)=>{let d=/(\{%[-~]?[\s\S]*?[-~]?%\}|\{\{[\s\S]*?\}\})/g,u=c.split(d),p=!1,g=u.map((f,h)=>h%2===1?f:f.split(/(\s+)/).map(b=>/^\s*$/.test(b)?b:b&&!b.startsWith(o)&&!Mp(b)&&/^[a-zA-Z][\w-]*$/.test(b)?(p=!0,o+b):b).join("")).join("");return p?(i=!0,`class="${g}"`):l});return i&&s.push({module:t,field:"moduleHtml",message:`HTML class references auto-prefixed with "${o}"`,autoFixed:!0}),a}function $v(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function Rv(e,t,n){if(!e)return e;let s=e,r=["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("|"),i=new RegExp(`\\b[a-zA-Z][\\w-]*-(${r})\\b(?!-)`,"g"),a=/(\{%[-~]?[\s\S]*?[-~]?%\})/g,l=!1;s=s.replace(a,f=>f.replace(i,(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 f=u[1],h=!f.startsWith("end"),b=h?f:f.replace("end","");d.push({tag:f,isOpen:h,baseTag:b,start:u.index,end:u.index+u[0].length})}let p=[],g=[];for(let f=0;f<d.length;f++)if(d[f].isOpen)p.push(f);else{let h=-1;for(let b=p.length-1;b>=0;b--)if(d[p[b]].baseTag===d[f].baseTag){h=b;break}h!==-1?p.splice(h,1):g.push(f)}if(g.length>0){for(let f=g.length-1;f>=0;f--){let h=d[g[f]];s=s.slice(0,h.start)+`<!-- removed orphan {% ${h.tag} %} -->`+s.slice(h.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(p.length>0){let f=p.map(b=>d[b].baseTag),h=f.reverse().map(b=>`{% end${b} %}`).join(`
|
|
2393
2243
|
`);s=`${s}
|
|
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 uu(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 Ky(e,t){let n=ct(e.fieldsJson),s=Array.isArray(n)?ln(n):{},o=e.moduleHtml||"";try{o=Ln(e.moduleHtml||"",{module:s})}catch{}let i=[...uu(o),...uu(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 Vy(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 pu(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 Yy(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(zy))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 qy(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 Xy(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 Fy,By,zy,Zr=N(()=>{"use strict";y();Ko();le();vr();Fy=[["name","item_name"],["label","section_label"],["body","body_text"]];By=new Set(["visible","active","scroll-animate","hidden","open","closed","fade-in","fade-out","is-active","is-open","is-visible"]);zy=/#[0-9a-fA-F]{6}\b/g});import{execSync as Zy}from"child_process";async function gu(e,t,n,s,o,i,r,a){let l=Date.now(),c=i;if(Gn(n)){let T={"claude-code":"claude","gemini-cli":"gemini","codex-cli":"codex"}[n];if(T)try{Zy(`command -v ${T}`,{stdio:"ignore"})}catch{throw new Error(`CLI engine "${n}" requires "${T}" to be installed and on your PATH.`)}}let d=await Md(e,t,n,s,o,r,a);if(d.intent==="question"&&d.answer){let F=Date.now()-l;return r({type:"pipeline_complete",modulesGenerated:0,modulesUnchanged:t.modules.length,durationMs:F,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:F}}}if(d.intent==="create_site"&&d.pages&&d.pages.length>0)return Qy(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 Hd(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 F of u.modules)f.push({name:F.name,description:F.description,contentBrief:F.contentBrief,layoutNotes:F.layoutNotes});else{for(let F of d.newModules)f.push({name:F.name,description:F.description,contentBrief:"Generate appropriate content based on the user request",layoutNotes:"Use responsive layout matching the existing design system"});for(let F of d.affectedModules){let T=t.modules.find(k=>k.moduleName===F);T&&f.push({name:F,description:`Modify existing module: ${F}`,contentBrief:"Apply the user's requested changes",layoutNotes:"Preserve existing layout unless changes are requested",existingCode:T})}}let b=[],S=[];if(f.length>0){let F=await te("module-development",()=>Rs(e,f,m,t.themeName,n,s,o,c,r,d.guidesNeeded,t.brandAssets,d.contentType),{metadata:{moduleCount:f.length}});for(let T of F)T.module?b.push(T.module):S.push(T.moduleName)}let v=null;if(b.length>0){v=dn(b,t.themeName,r,d.contentType,t.brandAssets?.brandKit);let F=v.filter(k=>k.issues.some(E=>E.field==="fieldsJson"&&E.message.includes("reset to empty"))).map(k=>k.module.moduleName);if(F.length>0){let k=F.map(E=>f.find(O=>O.name===E)).filter(E=>E!=null);if(k.length>0){M.info("pipeline",`Retrying ${k.length} module(s) with broken fieldsJson: ${k.map(O=>O.name).join(", ")}`),r({type:"agent_decision",step:"quality_check",decision:`Regenerating ${k.length} module(s) with invalid fields JSON...`});let E=await te("module-development-retry",()=>Rs(e,k,m,t.themeName,n,s,o,c,r,d.guidesNeeded,t.brandAssets,d.contentType),{metadata:{moduleCount:k.length}});for(let O of E)if(O.module){let re=b.findIndex(_e=>_e.moduleName===O.moduleName);re>=0&&(b[re]=O.module)}v=dn(b,t.themeName,r,d.contentType,t.brandAssets?.brandKit)}}b=v.map(k=>k.module);let T=v.reduce((k,E)=>k+E.issues.length,0);if(T>0){let k=v.reduce((O,re)=>O+re.issues.filter(_e=>_e.autoFixed).length,0);M.info("pipeline",`Quality check: ${T} issues, ${k} auto-fixed`);let E=v.flatMap(O=>O.issues).map(O=>`${O.autoFixed?"\u2713":"\u26A0"} ${O.module}: ${O.message}`).join(`
|
|
2395
|
-
|
|
2396
|
-
|
|
2397
|
-
|
|
2244
|
+
${h}`,n.push({module:t,field:"moduleHtml",message:`Added ${f.length} missing closing tag${f.length===1?"":"s"}: ${f.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 Ip(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(r=>r.trim()===""))&&t.push(s[0].trim())}return t}function Nv(e,t){let n=pt(e.fieldsJson),s=Array.isArray(n)?fn(n):{},o=e.moduleHtml||"";try{o=Yn(e.moduleHtml||"",{module:s})}catch{}let r=[...Ip(o),...Ip(e.moduleCss||"")];if(r.length===0)return;let i=r[0].length>60?r[0].slice(0,57)+"\u2026":r[0];t.push({module:e.moduleName,field:"moduleCss",message:`${r.length} invalid CSS color value${r.length===1?"":"s"} (e.g. \`${i}\`) \u2014 renders unstyled. A style field with no default is likely fed into rgba()/hsla().`,autoFixed:!1,code:"invalid-css"})}function Ov(e,t,n,s=!1,o=!1){let r=pt(e);if(!r||typeof r!="object")return e;let i=r,a=!1;if(i.host_template_types){if(s)i.host_template_types.includes("EMAIL")||(i.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=i.host_template_types;l.includes("BLOG_POST")||l.includes("BLOG_LISTING")||(i.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";i.host_template_types=[l],a=!0}return i.is_available_for_new_content===void 0&&(i.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(i,null,2)):e}function $p(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 r=/href=["'](\/?[a-z0-9][a-z0-9-]*(?:\/[a-z0-9-]*)*)["']/gi,i,a=[];for(;(i=r.exec(o.moduleHtml))!==null;){let l=i[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 Dv(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 r=new Set;for(let a of o.matchAll(Fv))r.add(a[0].toLowerCase());let i=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 r)if(!i.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 r=[];t.fonts.heading&&r.push(t.fonts.heading.toLowerCase()),t.fonts.body&&r.push(t.fonts.body.toLowerCase());let i=/font-family:\s*([^;}"]+)/gi;for(let a of o.matchAll(i)){let l=a[1].toLowerCase().trim();if(!r.some(c=>l.includes(c))){n.push({module:e.moduleName,field:"moduleHtml",message:`Off-brand font "${a[1].trim()}" (brand fonts: ${r.join(", ")})`,autoFixed:!1});break}}}}function jv(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 r=/<link[^>]*href="https?:\/\/[^"]*(?:fonts\.googleapis|cdnjs|unpkg|jsdelivr)[^"]*"[^>]*\/?>/gi;return r.test(s)&&(s=s.replace(r,""),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 Lv(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 Cv,Ev,Fv,$a=j(()=>{"use strict";y();Sr();re();ca();Cv=[["name","item_name"],["label","section_label"],["body","body_text"]];Ev=new Set(["visible","active","scroll-animate","hidden","open","closed","fade-in","fade-out","is-active","is-open","is-visible"]);Fv=/#[0-9a-fA-F]{6}\b/g});function Bv(e){return e.replace(/^--/,"").replace(/[-_]/g," ").replace(/\b\w/g,t=>t.toUpperCase()).trim()}function Cr(e,t,n){for(let s of t)for(let[o,r]of Object.entries(e))if(o.toLowerCase().includes(s)&&Np.test(String(r).trim()))return String(r).trim();return n}function Rp(e,t,n){for(let s of t)for(let[o,r]of Object.entries(e)){let i=o.toLowerCase();if(i.includes("font")&&i.includes(s)&&String(r).trim())return String(r).trim()}for(let[s,o]of Object.entries(e))if(s.toLowerCase().includes("font")&&String(o).trim())return String(o).trim();return n}function Jv(e){let t=[],n=new Set;for(let[s,o]of Object.entries(e)){let r=String(o).trim();if(!(!Np.test(r)||r.startsWith("var("))&&!n.has(r.toLowerCase())&&(n.add(r.toLowerCase()),t.push({label:Bv(s),value:r}),t.length>=6))break}return t}function bn(e){return e.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">")}function Hv(e,t,n){let s=Cr(e,["background","bg","surface","dark"],"#0f1115"),o=Cr(e,["text","foreground","fg","ink","light"],"#f5f5f7"),r=Cr(e,["primary","brand","accent","cta"],"#e8613a"),i=Cr(e,["on-primary","button-text","light","background"],"#ffffff");return`<!doctype html><html><head><meta charset="utf-8"><style>
|
|
2245
|
+
*{margin:0;box-sizing:border-box}
|
|
2246
|
+
body{font-family:${bn(n)};background:${bn(s)};color:${bn(o)}}
|
|
2247
|
+
.hero{padding:48px 40px;display:flex;flex-direction:column;gap:18px;align-items:flex-start}
|
|
2248
|
+
.eyebrow{font-size:12px;letter-spacing:.12em;text-transform:uppercase;opacity:.7}
|
|
2249
|
+
h1{font-family:${bn(t)};font-size:38px;line-height:1.08;font-weight:700;max-width:14ch}
|
|
2250
|
+
p{font-size:16px;line-height:1.55;opacity:.85;max-width:46ch}
|
|
2251
|
+
.btn{margin-top:6px;display:inline-block;padding:13px 26px;border-radius:8px;
|
|
2252
|
+
background:${bn(r)};color:${bn(i)};font-family:${bn(t)};
|
|
2253
|
+
font-weight:600;font-size:15px;text-decoration:none}
|
|
2254
|
+
</style></head><body>
|
|
2255
|
+
<section class="hero">
|
|
2256
|
+
<span class="eyebrow">Preview</span>
|
|
2257
|
+
<h1>Build pages that feel like your brand.</h1>
|
|
2258
|
+
<p>This is a sample hero rendered from the design system above \u2014 same palette, type, and button style your real modules will use.</p>
|
|
2259
|
+
<a class="btn" href="#">Get started</a>
|
|
2260
|
+
</section>
|
|
2261
|
+
</body></html>`}function Op(e){let t=e.cssVariables||{},n=Jv(t),s=Rp(t,["head","display","title","serif"],"Space Grotesk, system-ui, sans-serif"),o=Rp(t,["body","text","base","sans"],"DM Sans, system-ui, sans-serif"),r=Hv(t,s,o);return{kind:"design",headline:"Here's the look \u2014 approve before I build the page",data:{aesthetic:e.aesthetic||"custom",palette:n,typography:{heading:s,body:o},heroHtml:r}}}function Fp(){return{kind:"brand_intake",headline:"Want me to match your brand, or should I surprise you?",data:{surpriseLabel:"Surprise me",surpriseHint:"I'll invent a design system that fits your request.",bringLabel:"Bring your brand",bringHint:"Paste colors, code, a tone of voice, or point me at a site/theme.",channels:[{key:"colors",label:"Brand colors",placeholder:`Primary #e8613a
|
|
2262
|
+
Ink #0f1115
|
|
2263
|
+
Surface #ffffff`,multiline:!0},{key:"code",label:"Paste CSS or HTML",placeholder:":root { --brand: #e8613a } \u2026",multiline:!0},{key:"voice",label:"Tone of voice",placeholder:"Direct, specific, no buzzword soup",multiline:!0},{key:"siteUrl",label:"Site URL",placeholder:"https://yourbrand.com",multiline:!1},{key:"themePath",label:"HubSpot theme path",placeholder:"/path/to/theme",multiline:!1}]}}}var Np,Dp=j(()=>{"use strict";y();Np=/^(#|rgb|hsl|var\()/i});function Ra(e){return[...new Set(e.map(t=>t.trim()).filter(Boolean))]}function Na(){return{cssVariables:{},palette:[],fontFamilies:[],fontSizes:[],spacing:[],radii:[],shadows:[]}}function jp(e){let t=Na(),n,s=new RegExp(Uv.source,"g");for(;(n=s.exec(e))!==null;){let d=new RegExp(Gv.source,"g"),u;for(;(u=d.exec(n[1]))!==null;){let p=u[1].trim(),g=u[2].trim();p&&g&&!t.cssVariables[p]&&(t.cssVariables[p]=g)}}let o=new Map,r,i=new RegExp(Bp.source,"g");for(;(r=i.exec(e))!==null;){let d=r[0].trim().toLowerCase();["#fff","#ffffff","#000","#000000"].includes(d)||o.set(d,(o.get(d)??0)+1)}t.palette=[...o.entries()].sort((d,u)=>u[1]-d[1]).slice(0,12).map(([d,u])=>({value:d,count:u}));let a=[],l,c=new RegExp(Wv.source,"gi");for(;(l=c.exec(e))!==null;){let d=l[1].split(",")[0].trim().replace(/^["']|["']$/g,"");d&&!d.startsWith("var(")&&a.push(d)}return t.fontFamilies=Ra(a).slice(0,8),t}function Kv(e){let t=Na(),n=e.split(/[\n,]/).map(o=>o.trim()).filter(Boolean),s=0;for(let o of n){let i=new RegExp(Bp.source,"g").exec(o);if(!i)continue;let a=i[0].trim(),l=o.slice(0,i.index).replace(/[:\-–—]+\s*$/,"").trim(),c=l?l.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,""):"",d=c?`--color-${c}`:s===0?"--color-primary":s===1?"--color-secondary":`--color-accent-${s-1}`;t.cssVariables[d]||(t.cssVariables[d]=a,t.palette.push({value:a.toLowerCase(),count:1}),s++)}return t}async function Vv(e){let t=/^https?:\/\//i.test(e)?e:`https://${e}`,n=new AbortController,s=setTimeout(()=>n.abort(),1e4);try{let o=await fetch(t,{signal:n.signal,redirect:"follow",headers:Lp});if(!o.ok)return A.warn("brand-intake",`site fetch ${t} \u2192 HTTP ${o.status}`),"";let r=await o.text(),i="";for(let l of r.matchAll(/<style[^>]*>([\s\S]*?)<\/style>/gi))i+=`
|
|
2264
|
+
${l[1]}`;for(let l of r.matchAll(/<meta[^>]+name=["']theme-color["'][^>]*>/gi)){let c=/content=["']([^"']+)["']/i.exec(l[0])?.[1];c&&(i+=`
|
|
2265
|
+
--theme-color: ${c};`)}for(let l of r.matchAll(/style=["']([^"']+)["']/gi))i+=`
|
|
2266
|
+
.inline{${l[1]}}`;let a=[];for(let l of r.matchAll(/<link\b[^>]*>/gi)){let c=l[0];if(!/rel=["'][^"']*stylesheet[^"']*["']/i.test(c))continue;let d=/href=["']([^"']+)["']/i.exec(c)?.[1];d&&a.push(d)}for(let l of a.slice(0,6))try{let c=new URL(l.startsWith("//")?`https:${l}`:l,t).toString(),d=await fetch(c,{signal:n.signal,redirect:"follow",headers:Lp});d.ok&&(i+=`
|
|
2267
|
+
${await d.text()}`)}catch{}return i.trim()||(i=r),i}catch(o){return A.warn("brand-intake",`site fetch failed for ${t}: ${o instanceof Error?o.message:String(o)}`),""}finally{clearTimeout(s)}}function Tr(e,t,n,s){for(let[o,r]of Object.entries(s.cssVariables))e[o]||(e[o]=r);t.push(...s.palette.map(o=>o.value)),n.push(...s.fontFamilies)}async function Jp(e){let t={},n=[],s=[],o=[],r=[];if(e.colors?.trim()){let d=Kv(e.colors);Object.keys(d.cssVariables).length>0&&(Tr(t,n,s,d),o.push("colors"),r.push(`### Brand colors (provided)
|
|
2268
|
+
${Object.entries(d.cssVariables).map(([u,p])=>`- ${u}: ${p}`).join(`
|
|
2269
|
+
`)}`))}if(e.code?.trim()){let d=jp(e.code);(Object.keys(d.cssVariables).length>0||d.palette.length>0||d.fontFamilies.length>0)&&(Tr(t,n,s,d),o.push("code"),r.push(`### From pasted code
|
|
2270
|
+
- Variables: ${Object.keys(d.cssVariables).length}
|
|
2271
|
+
- Colors: ${d.palette.slice(0,6).map(u=>u.value).join(", ")||"none"}
|
|
2272
|
+
- Fonts: ${d.fontFamilies.join(", ")||"none"}`))}if(e.themePath?.trim())try{let d=Qt(e.themePath.trim());(Object.keys(d.cssVariables).length>0||d.palette.length>0||d.fontFamilies.length>0)&&(Tr(t,n,s,d),o.push("theme"),r.push(`### From imported theme
|
|
2273
|
+
- Variables: ${Object.keys(d.cssVariables).length}
|
|
2274
|
+
- Colors: ${d.palette.slice(0,6).map(u=>u.value).join(", ")||"none"}
|
|
2275
|
+
- Fonts: ${d.fontFamilies.join(", ")||"none"}`))}catch(d){A.warn("brand-intake",`theme token extraction failed: ${d instanceof Error?d.message:String(d)}`)}if(e.siteUrl?.trim()){let d=await Vv(e.siteUrl.trim());if(d){let u=jp(d);(Object.keys(u.cssVariables).length>0||u.palette.length>0||u.fontFamilies.length>0)&&(Tr(t,n,s,u),o.push("site"),r.push(`### From site (${e.siteUrl.trim()})
|
|
2276
|
+
- Colors: ${u.palette.slice(0,6).map(p=>p.value).join(", ")||"none"}
|
|
2277
|
+
- Fonts: ${u.fontFamilies.join(", ")||"none"}`))}}Object.keys(t).length===0&&Ra(n).slice(0,6).forEach((d,u)=>{let p=u===0?"primary":u===1?"secondary":`accent-${u-1}`;t[`--color-${p}`]=d});let i=Ra(s);i[0]&&!Object.keys(t).some(d=>d.includes("font")&&d.includes("head"))&&(t["--font-heading"]=i[0]),i[1]&&!Object.keys(t).some(d=>d.includes("font")&&d.includes("body"))&&(t["--font-body"]=i[1]||i[0]);let a=Object.keys(t).length?gn({...Na(),cssVariables:t}):"",l=e.voice?.trim()||void 0;l&&o.push("voice");let c;if(r.length>0||l){let d=["# Brand intake (user-provided)","Use these EXACT brand tokens as the foundation of the design system. Map the colors and fonts into `:root` variables and build every component style around them \u2014 do not invent a different palette."];r.length&&d.push(r.join(`
|
|
2278
|
+
|
|
2279
|
+
`)),l&&d.push(`### Tone of voice
|
|
2280
|
+
${l}`),c=d.join(`
|
|
2281
|
+
|
|
2282
|
+
`)}return{cssVariables:t,rootCss:a,styleguide:c,brandvoice:l,channels:o}}var Bp,Uv,Gv,Wv,Lp,Hp=j(()=>{"use strict";y();Os();re();Bp=/#[0-9a-fA-F]{3,8}\b|rgba?\([^)]+\)|hsla?\([^)]+\)/g,Uv=/:root\s*\{([^}]*)\}/g,Gv=/(--[A-Za-z0-9-_]+)\s*:\s*([^;]+?)\s*(?:;|$)/g,Wv=/font-family\s*:\s*([^;}]+)[;}]/gi;Lp={"User-Agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0 Safari/537.36",Accept:"text/html,application/xhtml+xml,text/css,*/*;q=0.8","Accept-Language":"en-US,en;q=0.9"}});function Up(e){let t=new Map;e.modules.forEach((r,i)=>{t.has(r.name)||t.set(r.name,i)});let n=[],s=new Set;for(let r of e.moduleOrder||[]){let i=t.get(r);if(i==null||s.has(i))continue;s.add(i);let a=e.modules[i];n.push({name:a.name,description:a.description||"",sourceIndex:i})}return e.modules.forEach((r,i)=>{s.has(i)||n.push({name:r.name,description:r.description||"",sourceIndex:i})}),{kind:"structure",headline:"Here's the structure \u2014 reorder, cut, or add sections before I build",data:{narrative:e.narrative||"",modules:n}}}function Gp(e,t){if(!t||t.length===0)return e;let n=[],s=new Set;for(let o of t){let r=o.sourceIndex!=null?e.modules[o.sourceIndex]:void 0,i=He(o.name)||r?.name;i&&(s.has(i)||(s.add(i),r?n.push({name:i,description:o.description??r.description,contentBrief:r.contentBrief,layoutNotes:r.layoutNotes}):n.push({name:i,description:o.description||`User-added section: ${i}`,contentBrief:"Generate appropriate content based on the user request",layoutNotes:"Use a responsive layout matching the existing design system"})))}return n.length===0?e:{...e,modules:n,moduleOrder:n.map(o=>o.name)}}var Wp=j(()=>{"use strict";y();wt()});import{execSync as zv}from"child_process";function Vp(){return`cp_${Date.now().toString(36)}_${Math.random().toString(36).slice(2,10)}`}function Sn(e){Qs.delete(e)}function zp(){let e=xc();if(!(!e||e.costUsd<=0))return Math.round(e.costUsd*qv*100)/100}async function qp(e,t,n,s,o,r,i,a,l=!1,c){let d=Date.now(),u=r;if(ns(n)){let v={"claude-code":"claude","gemini-cli":"gemini","codex-cli":"codex"}[n];if(v)try{zv(`command -v ${v}`,{stdio:"ignore"})}catch{throw new Error(`CLI engine "${n}" requires "${v}" to be installed and on your PATH.`)}}let p=await Ku(e,t,n,s,o,i,a,c);if(c?.aborted)throw new Ie;if(p.intent==="question"&&p.answer){let S=Date.now()-d;return i({type:"pipeline_complete",modulesGenerated:0,modulesUnchanged:t.modules.length,durationMs:S,answer:p.answer}),{modules:[...t.modules],moduleOrder:t.moduleOrder,sharedCss:t.sharedCss,sharedJs:t.sharedJs,assistantMessage:p.answer,stats:{modulesGenerated:0,modulesUnchanged:t.modules.length,modulesFailed:0,durationMs:S}}}if(p.intent==="create_site"&&p.pages&&p.pages.length>0)return Qv(e,p,t,n,s,o,r,i,d,c);let g=null,f=t.sharedCss,h=t.sharedJs;if(p.intent==="create"||p.designSystemChanges){if(l&&p.contentType!=="email"){if(p.intent==="create"&&!Yv(t))return Xv({kind:"brand_intake",userMessage:e,plan:p,sharedCss:f,sharedJs:h,startTime:d,libraryModules:a},t,i);let S=await ss(e,p,t,n,s,o,i,c);return Fa({kind:"design",userMessage:e,plan:p,designSystem:S,sharedCss:S.sharedCss,sharedJs:S.sharedJs||h,startTime:d,libraryModules:a},t,i)}g=await ap(e,p,t,n,s,o,i,c),p.contentType!=="email"&&(f=g.designSystem.sharedCss||f,h=g.designSystem.sharedJs||h),i({type:"blueprint_ready",moduleOrder:g.moduleOrder,sharedCss:f,sharedJs:h})}if(c?.aborted)throw new Ie;return Oa(e,p,t,g,f,h,n,s,o,u,i,a,d,c)}function Yp(e,t,n,s,o){let r=Vp();Qs.set(r,t);let i=zp();return o({type:"checkpoint_requested",kind:e,preview:n,...i!=null?{estCostNext:i}:{}}),{modules:[...s.modules],moduleOrder:s.moduleOrder,sharedCss:t.sharedCss,sharedJs:t.sharedJs,assistantMessage:"",contentType:t.plan.contentType,stats:{modulesGenerated:0,modulesUnchanged:s.modules.length,modulesFailed:0,durationMs:Date.now()-t.startTime},pendingCheckpoint:{kind:e,resumeToken:r,preview:n,createdAt:new Date().toISOString(),resumeState:t}}}function Fa(e,t,n){if(!e.designSystem)throw new Error("Cannot park at the design checkpoint without a design system.");return Yp("design",e,Op(e.designSystem),t,n)}function Kp(e,t,n){return Yp("structure",e,Up(e.blueprint),t,n)}function Yv(e){return!!(e.brandAssets?.styleguide&&e.brandAssets.styleguide.trim()||e.sharedCss&&e.sharedCss.includes(":root"))}function Xv(e,t,n){let s=Vp();Qs.set(s,e);let o=Fp(),r=zp();return n({type:"checkpoint_requested",kind:"brand_intake",preview:o,...r!=null?{estCostNext:r}:{}}),{modules:[...t.modules],moduleOrder:t.moduleOrder,sharedCss:e.sharedCss,sharedJs:e.sharedJs,assistantMessage:"",contentType:e.plan.contentType,stats:{modulesGenerated:0,modulesUnchanged:t.modules.length,modulesFailed:0,durationMs:Date.now()-e.startTime},pendingCheckpoint:{kind:"brand_intake",resumeToken:s,preview:o,createdAt:new Date().toISOString(),resumeState:e}}}async function Zv(e,t,n,s,o,r,i,a,l){Sn(e);let c=n.action==="approve"?n.brandIntake:void 0,d=s,u,p=null;if(c)if(p=await Jp(c),p.channels.length>0){let h=[s.brandAssets?.styleguide,p.styleguide].filter(b=>b&&b.trim()).join(`
|
|
2283
|
+
|
|
2284
|
+
`);u={...h?{styleguide:h}:{},...p.brandvoice?{brandvoice:p.brandvoice}:{}},d={...s,brandAssets:{...s.brandAssets,...h?{styleguide:h}:{},...p.brandvoice?{brandvoice:p.brandvoice}:{}},sharedCss:p.rootCss||s.sharedCss},a({type:"agent_decision",step:"designing",decision:`Brand intake: using ${p.channels.join(", ")} \u2192 ${Object.keys(p.cssVariables).length} brand token(s)`})}else a({type:"agent_decision",step:"designing",decision:"Brand intake: couldn't extract usable design tokens from what you provided \u2014 generating a design system instead. Try pasting your brand colors or CSS directly."});let g=await ss(t.userMessage,t.plan,d,o,r,i,a,l);p&&Object.keys(p.cssVariables).length>0&&(g.cssVariables={...g.cssVariables||{},...p.cssVariables},p.rootCss&&!g.sharedCss.includes(p.rootCss.trim())&&(g.sharedCss=`${g.sharedCss}
|
|
2285
|
+
|
|
2286
|
+
/* Brand intake overrides (VIB-1878) */
|
|
2287
|
+
${p.rootCss}`));let f=Fa({kind:"design",userMessage:t.userMessage,plan:t.plan,designSystem:g,sharedCss:g.sharedCss,sharedJs:g.sharedJs||t.sharedJs,startTime:t.startTime,libraryModules:t.libraryModules},s,a);return u&&(f.brandAssetsUpdate=u),f}async function Xp(e,t,n,s,o,r,i,a,l,c){let d=Qs.get(e);if(!d&&c&&(d=c,Qs.set(e,d)),!d)throw new Error("This checkpoint has expired (the server may have restarted). Send your request again to start over.");if(t.action==="cancel")return Sn(e),{modules:[...n.modules],moduleOrder:n.moduleOrder,sharedCss:n.sharedCss,sharedJs:n.sharedJs,assistantMessage:"Cancelled \u2014 nothing was built.",canceled:!0,stats:{modulesGenerated:0,modulesUnchanged:n.modules.length,modulesFailed:0,durationMs:0}};if(d.kind==="brand_intake")return Zv(e,d,t,n,s,o,r,a,l);if(d.kind==="structure"){if(Sn(e),t.action==="steer"){let h=(t.note||"").trim(),b=h?`${d.userMessage}
|
|
2288
|
+
|
|
2289
|
+
## Structure steer (revise the module plan to honor this)
|
|
2290
|
+
${h}`:d.userMessage,S=await wr(b,d.plan,n,d.designSystem,d.sharedCss,s,o,r,a,l);return Kp({...d,userMessage:b,blueprint:S},n,a)}let f=Gp(d.blueprint,t.outline);return a({type:"blueprint_ready",moduleOrder:f.moduleOrder,sharedCss:d.sharedCss,sharedJs:d.sharedJs}),Oa(d.userMessage,d.plan,n,f,d.sharedCss,d.sharedJs??"",s,o,r,i,a,d.libraryModules,d.startTime,l)}if(t.action==="steer"){Sn(e);let f=(t.note||"").trim(),h=f?`${d.userMessage}
|
|
2291
|
+
|
|
2292
|
+
## Design steer (revise the design system to honor this)
|
|
2293
|
+
${f}`:d.userMessage,b=await ss(h,d.plan,n,s,o,r,a,l);return Fa({...d,userMessage:h,designSystem:b,sharedCss:b.sharedCss,sharedJs:b.sharedJs||d.sharedJs},n,a)}if(Sn(e),!d.designSystem)throw new Error("Checkpoint resume state is missing its design system. Send your request again to start over.");let u=await wr(d.userMessage,d.plan,n,d.designSystem,d.sharedCss,s,o,r,a,l),p=d.plan.contentType!=="email"&&u.designSystem.sharedCss||d.sharedCss,g=d.plan.contentType!=="email"&&u.designSystem.sharedJs||d.sharedJs;return t.action!=="skip"?Kp({kind:"structure",userMessage:d.userMessage,plan:d.plan,designSystem:d.designSystem,blueprint:u,sharedCss:p,sharedJs:g??"",startTime:d.startTime,libraryModules:d.libraryModules},n,a):(a({type:"blueprint_ready",moduleOrder:u.moduleOrder,sharedCss:p,sharedJs:g}),Oa(d.userMessage,d.plan,n,u,p,g??"",s,o,r,i,a,d.libraryModules,d.startTime,l))}async function Zp(e,t,n,s,o,r,i,a,l,c,d){let u=[],p=[];if(t.length>0){let f=await ce("module-development",()=>Ma(e,t,n,o.themeName,r,i,a,l,c,s.guidesNeeded,o.brandAssets,s.contentType,d),{metadata:{moduleCount:t.length}});for(let h of f)h.module?u.push(h.module):p.push(h.moduleName)}let g=null;if(u.length>0){g=Zs(u,o.themeName,c,s.contentType,o.brandAssets?.brandKit);let f=g.filter(h=>h.issues.some(b=>b.field==="fieldsJson"&&b.message.includes("reset to empty"))).map(h=>h.module.moduleName);if(f.length>0){let h=f.map(b=>t.find(S=>S.name===b)).filter(b=>b!=null);if(h.length>0){A.info("pipeline",`Retrying ${h.length} module(s) with broken fieldsJson: ${h.map(S=>S.name).join(", ")}`),c({type:"agent_decision",step:"quality_check",decision:`Regenerating ${h.length} module(s) with invalid fields JSON...`});let b=await ce("module-development-retry",()=>Ma(e,h,n,o.themeName,r,i,a,l,c,s.guidesNeeded,o.brandAssets,s.contentType,d),{metadata:{moduleCount:h.length}});for(let S of b)if(S.module){let v=u.findIndex(k=>k.moduleName===S.moduleName);v>=0&&(u[v]=S.module)}g=Zs(u,o.themeName,c,s.contentType,o.brandAssets?.brandKit)}}}return{generatedModules:u,failedModules:p,validationResults:g}}async function Oa(e,t,n,s,o,r,i,a,l,c,d,u,p,g){let f=[];if(s)for(let H of s.modules)f.push({name:H.name,description:H.description,contentBrief:H.contentBrief,layoutNotes:H.layoutNotes});else{for(let H of t.newModules)f.push({name:H.name,description:H.description,contentBrief:"Generate appropriate content based on the user request",layoutNotes:"Use responsive layout matching the existing design system"});for(let H of t.affectedModules){let P=n.modules.find(F=>F.moduleName===H);P&&f.push({name:H,description:`Modify existing module: ${H}`,contentBrief:"Apply the user's requested changes",layoutNotes:"Preserve existing layout unless changes are requested",existingCode:P})}}let h=await Zp(e,f,o,t,n,i,a,l,c,d,g),b=h.generatedModules,S=h.failedModules,v=h.validationResults;if(v){b=v.map(P=>P.module);let H=v.reduce((P,F)=>P+F.issues.length,0);if(H>0){let P=v.reduce((z,L)=>z+L.issues.filter(W=>W.autoFixed).length,0);A.info("pipeline",`Quality check: ${H} issues, ${P} auto-fixed`);let F=v.flatMap(z=>z.issues).map(z=>`${z.autoFixed?"\u2713":"\u26A0"} ${z.module}: ${z.message}`).join(`
|
|
2294
|
+
`);d({type:"agent_decision",step:"quality_check",decision:`${H} issues found, ${P} auto-fixed
|
|
2295
|
+
${F}`})}else d({type:"agent_decision",step:"quality_check",decision:"All modules passed quality checks"})}let k=tx(n,t,b,s,u),_=nx(n,t,s,k);if(s?.moduleOrder?.length){let H=new Set(s.moduleOrder),P=k.filter(F=>!H.has(F.moduleName)).map(F=>F.moduleName);P.length>0&&d({type:"agent_decision",step:"quality_check",decision:`\u26A0 ${P.length} module${P.length===1?"":"s"} missing from page order \u2014 auto-inserted: ${P.join(", ")}`})}let M=Date.now()-p,R=b.length,J=t.unchangedModules.length,O=v?v.flatMap(H=>H.issues):[],V=sx(t,R,J,S,M,s,O);return S.length>0?d({type:"pipeline_partial",succeeded:b.map(H=>H.moduleName),failed:S,durationMs:M}):d({type:"pipeline_complete",modulesGenerated:R,modulesUnchanged:J,durationMs:M,assistantMessage:V}),{modules:k,moduleOrder:_,sharedCss:o,sharedJs:r,assistantMessage:V,contentType:t.contentType,stats:{modulesGenerated:R,modulesUnchanged:J,modulesFailed:S.length,durationMs:M}}}async function Qv(e,t,n,s,o,r,i,a,l,c){let d=t.pages,u=t.sharedModules||["site-header","site-footer"],p=await ss(e,t,n,s,o,r,a,c),g=p.sharedCss||n.sharedCss,f=p.sharedJs||n.sharedJs;a({type:"blueprint_ready",moduleOrder:u,sharedCss:g,sharedJs:f});let h=await mp(e,t,n,g,s,o,r,a,c);a({type:"agent_step",step:"developing",label:`Generating modules for ${d.length} pages...`});let b=[];for(let L of h.sharedModules)b.push({...L});for(let L of h.pages)for(let W of L.modules)b.push({name:W.name,description:W.description,contentBrief:W.contentBrief,layoutNotes:W.layoutNotes});let S=d.map(L=>`- "${L.label}" \u2192 /${L.slug}`).join(`
|
|
2296
|
+
`);for(let L of b)(L.name.includes("header")||L.name.includes("nav"))&&(L.layoutNotes+=`
|
|
2398
2297
|
|
|
2399
2298
|
## Site Navigation
|
|
2400
2299
|
This is a multi-page site. Include navigation links to all pages:
|
|
2401
|
-
${
|
|
2402
|
-
Use relative href paths. Add CSS class "${n.themeName}-nav__link--active" on the current page's link.`);let
|
|
2300
|
+
${S}
|
|
2301
|
+
Use relative href paths. Add CSS class "${n.themeName}-nav__link--active" on the current page's link.`);let v=await Zp(e,b,g,t,n,s,o,r,i,a,c),k=v.generatedModules,_=v.failedModules,M=k,R=[];if(v.validationResults){M=v.validationResults.map(_e=>_e.module),R=v.validationResults.flatMap(_e=>_e.issues);let L=$p(M,d.map(_e=>_e.slug));R.push(...L);let W=R.length;if(W>0){let _e=R.filter(Be=>Be.autoFixed).length;a({type:"agent_decision",step:"quality_check",decision:`${W} issues found, ${_e} auto-fixed`})}else a({type:"agent_decision",step:"quality_check",decision:"All modules passed quality checks"})}let J=new Map(M.map(L=>[L.moduleName,L])),O=h.sharedModules.map(L=>J.get(L.name)).filter(L=>!!L),V=new Map(d.map(L=>[L.id,L])),H=h.pages.map(L=>{let W=L.modules.map(ie=>J.get(ie.name)).filter(ie=>!!ie),_e=u.filter(ie=>ie.includes("header")||ie.includes("nav")),Be=u.filter(ie=>ie.includes("footer")),yt=[..._e,...L.moduleOrder,...Be],ot=V.get(L.pageId);return{pageId:L.pageId,templateId:L.pageId,label:ot?.label||L.pageId,pageType:ot?.pageType||"website_page",modules:[...O,...W],moduleOrder:yt}}),P=Date.now()-l,F=ex(d,k.length,_,P,h.narrative,R);return _.length>0?a({type:"pipeline_partial",succeeded:k.map(L=>L.moduleName),failed:_,durationMs:P}):a({type:"pipeline_complete",modulesGenerated:k.length,modulesUnchanged:0,durationMs:P,assistantMessage:F}),{modules:M,moduleOrder:M.map(L=>L.moduleName),sharedCss:g,sharedJs:f||"",assistantMessage:F,stats:{modulesGenerated:k.length,modulesUnchanged:0,modulesFailed:_.length,durationMs:P},multiPage:{pages:H,sharedModules:O,sharedCss:g,sharedJs:f||"",assistantMessage:F,stats:{pagesGenerated:d.length,modulesGenerated:k.length,modulesFailed:_.length,durationMs:P}}}}function ex(e,t,n,s,o,r){let i=Math.round(s/1e3),a=[];a.push(`Created ${e.length}-page site with ${t} modules in ${i}s.`),a.push(`
|
|
2403
2302
|
|
|
2404
2303
|
**Pages:** ${e.map(d=>d.label).join(", ")}`),o&&a.push(`
|
|
2405
2304
|
|
|
2406
2305
|
${o}`),n.length>0&&a.push(`
|
|
2407
2306
|
|
|
2408
|
-
**Failed:** ${n.join(", ")}. You can retry these individually.`);let l=
|
|
2307
|
+
**Failed:** ${n.join(", ")}. You can retry these individually.`);let l=r.filter(d=>!d.autoFixed),c=r.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(`
|
|
2409
2308
|
|
|
2410
2309
|
${d.join(`
|
|
2411
|
-
`)}`)}return a.join("")}function
|
|
2310
|
+
`)}`)}return a.join("")}function tx(e,t,n,s,o){let r=[],i=new Set;for(let a of n)r.push(a),i.add(a.moduleName);for(let a of t.unchangedModules){if(i.has(a))continue;let l=e.modules.find(c=>c.moduleName===a);l&&(r.push(l),i.add(a))}if(t.reuseModules)for(let a of t.reuseModules){if(i.has(a.name))continue;let l=o.find(c=>c.name===a.name&&c.module);l?.module?(r.push(l.module),i.add(a.name)):A.warn("pipeline",`Reuse of "${a.name}" requested but no library payload found \u2014 skipping`)}return r}function nx(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),A.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],r=[...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 r){let l=Math.min(a.position,o.length);o.splice(l,0,a.name)}let i=new Set(s.map(a=>a.moduleName));return o.filter(a=>i.has(a))}function sx(e,t,n,s,o,r,i){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(p=>p.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.`);r?.narrative&&l.push(`
|
|
2412
2311
|
|
|
2413
|
-
${
|
|
2312
|
+
${r.narrative}`),s.length>0&&l.push(`
|
|
2414
2313
|
|
|
2415
|
-
**Failed:** ${s.join(", ")}. You can retry these individually.`);let c=
|
|
2314
|
+
**Failed:** ${s.join(", ")}. You can retry these individually.`);let c=i.filter(u=>!u.autoFixed),d=i.filter(u=>u.autoFixed);if(d.length>0||c.length>0){let u=[];d.length>0&&u.push(`**Auto-fixed:** ${d.map(p=>`${p.module}: ${p.message}`).join(", ")}`),c.length>0&&u.push(`**Warnings:** ${c.map(p=>`${p.module}: ${p.message}`).join(", ")}`),l.push(`
|
|
2416
2315
|
|
|
2417
2316
|
${u.join(`
|
|
2418
|
-
`)}`)}return l.join("")}var
|
|
2317
|
+
`)}`)}return l.join("")}var qv,Qs,Da=j(()=>{"use strict";y();mt();Qn();Vu();lp();gp();Pp();$a();Dp();Hp();Wp();jo();re();Ue();mt();qv=6,Qs=new Map});var to={};Ve(to,{collectThemeFiles:()=>em,extractDesignContext:()=>lx});import{existsSync as Ar,readdirSync as _r,readFileSync as ox}from"fs";import{join as _t}from"path";import{spawn as rx}from"child_process";async function Qp(){return ja||(ja=(await import("@anthropic-ai/sdk")).default),ja}function eo(e){try{return ox(e,"utf-8")}catch{return""}}function em(e){let t=[],n=0;function s(a,l){if(!l.trim())return!0;let c=`
|
|
2318
|
+
### ${a}
|
|
2319
|
+
\`\`\`
|
|
2320
|
+
${l}
|
|
2321
|
+
\`\`\`
|
|
2322
|
+
`;return n+c.length>ix?!1:(t.push(c),n+=c.length,!0)}let o=eo(_t(e,"theme.json"));o&&s("theme.json",o);let r=_t(e,"css");if(Ar(r)){for(let a of _r(r).filter(l=>l.endsWith(".css")))if(!s(`css/${a}`,eo(_t(r,a))))break}let i=_t(e,"modules");if(Ar(i))for(let a of _r(i).filter(l=>l.endsWith(".module"))){let l=_t(i,a),c=eo(_t(l,"module.css"));if(c&&!s(`modules/${a}/module.css`,c))break}if(Ar(i))for(let a of _r(i).filter(l=>l.endsWith(".module"))){let l=_t(i,a),c=eo(_t(l,"module.html"));if(c&&!s(`modules/${a}/module.html`,c))break}if(Ar(i))for(let a of _r(i).filter(l=>l.endsWith(".module"))){let l=_t(i,a),c=eo(_t(l,"fields.json"));if(c&&!s(`modules/${a}/fields.json`,c))break}return t.join("")}function ax(){if(!Pr)try{Pr=I(Kt("extraction-prompt.md"))}catch{Pr=""}return Pr}function La(e,t,n){return new Promise((s,o)=>{let r={...process.env};delete r.CLAUDECODE;let i=rx(e,t,{stdio:["pipe","pipe","pipe"],env:r,shell:process.platform==="win32"}),a="",l="";i.stdout.on("data",c=>{a+=c.toString()}),i.stderr.on("data",c=>{l+=c.toString()}),i.on("error",c=>o(new Error(`${e} failed to start: ${c.message}`))),i.on("close",c=>{c===0||a.trim()?s(a.trim()):o(new Error(`${e} exited with code ${c}: ${l.trim()}`))}),i.stdin.write(n),i.stdin.end()})}async function lx(e,t){t?.({status:"Collecting theme files..."});let n=em(e);if(!n.trim())throw new Error("No CSS, HTML, or fields.json files found in theme.");let s=ax();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:
|
|
2323
|
+
${n}`;t?.({status:"Analyzing design patterns..."});let r=$(),i=r.aiEngine||"anthropic-api",a="",l=new Date,c,d="";switch(i){case"anthropic-api":case"api":{let u=De("anthropic-api");if(!u)throw new Error("Anthropic API key not configured. Open Settings to add one.");let p=await Qp(),g=new p({apiKey:u});d=r.anthropicApiModel||"claude-sonnet-4-6";let f=await g.messages.create({model:d,max_tokens:8e3,system:[{type:"text",text:s,cache_control:{type:"ephemeral"}}],messages:[{role:"user",content:o}]});a=f.content.map(h=>h.type==="text"?h.text:"").join(""),c=nt(f.usage);break}case"claude-oauth":{let{getValidAccessToken:u,OAUTH_EXTRA_HEADERS:p,OAUTH_SYSTEM_PREFIX:g}=await Promise.resolve().then(()=>($t(),Ci)),f=await u();if(!f)throw new Error("Claude OAuth session expired. Please re-authenticate in Settings.");let h=await Qp(),b=new h({authToken:f,defaultHeaders:p});d=r.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=nt(S.usage);break}case"openai-api":{let u=De("openai-api");if(!u)throw new Error("OpenAI API key not configured. Open Settings to add one.");d=r.openaiApiModel||"gpt-4o";let p=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(!p.ok)throw new Error(`OpenAI API error: ${p.status} ${await p.text()}`);let g=await p.json();a=g.choices?.[0]?.message?.content||"",c=Bn(g.usage);break}case"gemini-api":{let u=De("gemini-api");if(!u)throw new Error("Gemini API key not configured. Open Settings to add one.");d=r.geminiApiModel||"gemini-2.5-flash";let p=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(!p.ok)throw new Error(`Gemini API error: ${p.status} ${await p.text()}`);let g=await p.json();a=g.candidates?.[0]?.content?.parts?.map(f=>f.text).join("")||"",c=Jn(g.usageMetadata);break}case"claude-code":{let u=`${s}
|
|
2324
|
+
|
|
2325
|
+
## User Request
|
|
2326
|
+
${o}`,p=["--print"];r.claudeCodeModel&&p.push("--model",r.claudeCodeModel),a=await La("claude",p,u);break}case"gemini-cli":{let u=`${s}
|
|
2327
|
+
|
|
2328
|
+
## User Request
|
|
2329
|
+
${o}`;a=await La("gemini",[],u);break}case"codex-cli":{let u=`${s}
|
|
2330
|
+
|
|
2331
|
+
## User Request
|
|
2332
|
+
${o}`;a=await La("codex",[],u);break}default:throw new Error(`Unknown AI engine: ${i}. Open Settings to configure one.`)}if(!a.trim())throw new Error("AI returned empty response.");return d&&Ct({engine:i,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 ja,ix,Pr,no=j(()=>{"use strict";y();ae();te();Ue();un();ja=null;ix=8e4;Pr=""});var Ba={};Ve(Ba,{extractBrandvoice:()=>cx});async function cx(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.
|
|
2333
|
+
|
|
2334
|
+
Return a markdown document with these sections (skip any section where the content provides no signal):
|
|
2335
|
+
|
|
2336
|
+
## Tone
|
|
2337
|
+
Overall communication style (e.g., confident but approachable, technical but clear, playful, authoritative).
|
|
2338
|
+
|
|
2339
|
+
## Voice Characteristics
|
|
2340
|
+
3-5 bullet points describing how this brand "sounds" (e.g., "Uses short, punchy sentences", "Addresses reader directly with 'you'").
|
|
2341
|
+
|
|
2342
|
+
## Vocabulary
|
|
2343
|
+
- **Preferred words**: Terms used repeatedly or intentionally
|
|
2344
|
+
- **Avoided patterns**: Any notable absences or anti-patterns
|
|
2345
|
+
|
|
2346
|
+
## Sentence Style
|
|
2347
|
+
Typical sentence length, structure, use of questions, imperatives, etc.
|
|
2348
|
+
|
|
2349
|
+
## Dos and Don'ts
|
|
2350
|
+
3-4 practical rules for writing in this voice (e.g., "Do: Lead with benefits, not features", "Don't: Use jargon without context").
|
|
2351
|
+
|
|
2352
|
+
Keep it actionable \u2014 this guide will be fed to AI to maintain consistent copy across pages.`;try{let r=await Ne(t,n,s,{systemPrompt:o,messages:[{role:"user",content:e}],maxTokens:1e3}),i=r.type==="text"?r.text:JSON.stringify(r.data);return!i||i.trim().length<20?null:(A.info("brandvoice-extractor",`Extracted brand voice (${i.length} chars)`),i.trim())}catch(r){let i=r instanceof Error?r.message:String(r);return A.warn("brandvoice-extractor",`Brand voice extraction failed: ${i}`),null}}var Ja=j(()=>{"use strict";y();mt();re()});var Er={};Ve(Er,{extractThemeContext:()=>dx});async function dx(e,t,n,s,o){if(!e||e.length<50)return null;let i=`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.
|
|
2353
|
+
|
|
2354
|
+
Return a markdown document with these sections (skip any section where the content provides no information):
|
|
2355
|
+
|
|
2356
|
+
## Product / Company
|
|
2357
|
+
Name, one-line description, and what it does.
|
|
2358
|
+
|
|
2359
|
+
## Value Propositions
|
|
2360
|
+
Key benefits or features (bulleted list).
|
|
2361
|
+
|
|
2362
|
+
## Target Audience
|
|
2363
|
+
Who this product/service is for.
|
|
2364
|
+
|
|
2365
|
+
## Tone & Voice
|
|
2366
|
+
Communication style (e.g., professional, casual, technical, friendly).
|
|
2367
|
+
|
|
2368
|
+
## Key Terminology
|
|
2369
|
+
Specific terms, product names, or branded language used consistently.
|
|
2370
|
+
|
|
2371
|
+
Keep it concise \u2014 this brief is used as context for AI-generated content on other pages in the same theme.${t?`
|
|
2372
|
+
|
|
2373
|
+
Existing product context (update if the new content adds info, keep what's still accurate):
|
|
2374
|
+
${t}`:""}`;try{let a=await Ne(n,s,o,{systemPrompt:i,messages:[{role:"user",content:e}],maxTokens:1e3}),l=a.type==="text"?a.text:JSON.stringify(a.data);return!l||l.trim().length<20?null:(A.info("context-extractor",`Extracted theme context (${l.length} chars)`),l.trim())}catch(a){let l=a instanceof Error?a.message:String(a);return A.warn("context-extractor",`Theme context extraction failed: ${l}`),null}}var Ir=j(()=>{"use strict";y();mt();re()});import{join as tm}from"path";function ux(e){let t=[];return e.brandAssets?.styleguide||t.push("styleguide"),e.brandAssets?.brandvoice||t.push("brandvoice"),e.brandAssets?.themeContext||t.push("themeContext"),t}function Mr(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=tm(e.themePath,".vibespot");$e(o),U(tm(o,s),n)}async function nm(e,t){let n=ux(e),s={attempted:[],extracted:[],skipped:[],errors:[]};return n.length===0?s:qe({name:"brand_enrichment",sessionId:e.themeName,metadata:{missing:n},tags:["vibespot","brand-enrichment"]},()=>px(e,t,n,s))}async function px(e,t,n,s){let o=mx(t)?t:{...await gx(e),...t??{}};n.includes("styleguide")&&await Ha(e,"styleguide",s,()=>ce("extract-styleguide",()=>o.extractStyleguide(e)));let r=n.filter(a=>a==="brandvoice"||a==="themeContext");if(r.length===0)return s;let i="";try{i=o.buildPreviewHtml()}catch(a){let l=a instanceof Error?a.message:String(a);for(let c of r)s.skipped.push(c),s.errors.push({asset:c,message:`Could not render preview HTML: ${l}`});return s}if(!i||i.length<50){for(let a of r)s.skipped.push(a);return s}return n.includes("brandvoice")&&await Ha(e,"brandvoice",s,()=>ce("extract-brandvoice",()=>o.extractBrandvoice(e,i))),n.includes("themeContext")&&await Ha(e,"themeContext",s,()=>ce("extract-theme-context",()=>o.extractThemeContext(e,i))),s}async function Ha(e,t,n,s){n.attempted.push(t);try{let o=await s();if(!o){n.skipped.push(t);return}Mr(e,t,o),n.extracted.push(t)}catch(o){let r=o instanceof Error?o.message:String(o);n.skipped.push(t),n.errors.push({asset:t,message:r}),A.warn("brand-enrichment",`${t} enrichment skipped: ${r}`)}}function mx(e){return!!e?.extractStyleguide&&!!e.extractBrandvoice&&!!e.extractThemeContext&&!!e.buildPreviewHtml}async function gx(e){let{extractDesignContext:t}=await Promise.resolve().then(()=>(no(),to)),{buildPreviewHtml:n}=await Promise.resolve().then(()=>(Xn(),yr)),{resolveAgenticEngine:s}=await Promise.resolve().then(()=>(os(),Ga)),{extractBrandvoice:o}=await Promise.resolve().then(()=>(Ja(),Ba)),{extractThemeContext:r}=await Promise.resolve().then(()=>(Ir(),Er)),i=$();return{extractStyleguide:()=>t(e.themePath),buildPreviewHtml:n,extractBrandvoice:async(a,l)=>{let{engine:c,apiKey:d,model:u}=s(i);return o(l,c,d,u)},extractThemeContext:async(a,l)=>{let{engine:c,apiKey:d,model:u}=s(i);return r(l,a.brandAssets?.themeContext,c,d,u)}}}var Ua=j(()=>{"use strict";y();ae();te();re();Ue()});var am={};Ve(am,{runFigmaConversion:()=>fx});import{basename as rm}from"path";async function fx(e,t,n,s,o,r,i,a,l){let c=Date.now();i({type:"agent_step",step:"designing",label:"Building design system from Figma tokens..."});let{sharedCss:d,sharedJs:u}=hx(e.designTokens,t);i({type:"design_system_ready",sharedCss:d,sharedJs:u,aesthetic:"Figma import"}),i({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:p,moduleOrder:g}=bx(e.sections,e.assets,t);i({type:"blueprint_ready",moduleOrder:g,sharedCss:d,sharedJs:u}),i({type:"agent_decision",step:"designing",decision:`Mapped ${p.length} Figma sections to modules: ${g.join(", ")}`}),i({type:"agent_step",step:"developing",label:`Converting ${p.length} modules...`});let f=n==="anthropic-api"||n==="claude-oauth",h=Ys(t,d,["hubspot_rules","conversion"],a),b=f?kr(t,d,["hubspot_rules","conversion"],a):void 0,S=xr(r),v=p.length,_=(await ce("module-development",()=>{let F=p.map((z,L)=>{let W=e.sections[L];return S(async()=>{i({type:"module_progress",module:z.name,status:"generating",current:L+1,total:v});let _e=xx(W,z,e.assets,t,l!==!1),Be="";for(let yt=0;yt<2;yt++)try{yt>0&&(A.warn("figma-pipeline",`${z.name}: retrying (attempt ${yt+1})`),i({type:"module_progress",module:z.name,status:"retrying",current:L+1,total:v}));let ot=await Ne(n,s,o,{systemPrompt:h,systemBlocks:b,messages:[{role:"user",content:_e}],structuredOutput:{schema:Xs,name:"module_output"},maxTokens:16e3});if(ot.type!=="structured")throw new Error("No structured output returned");let ie=ot.data,Tn={moduleName:z.name,fieldsJson:typeof ie.fieldsJson=="string"?ie.fieldsJson:JSON.stringify(ie.fieldsJson,null,2),metaJson:typeof ie.metaJson=="string"?ie.metaJson:JSON.stringify(ie.metaJson,null,2),moduleHtml:String(ie.moduleHtml||""),moduleCss:String(ie.moduleCss||""),moduleJs:ie.moduleJs?String(ie.moduleJs):void 0};return i({type:"module_progress",module:z.name,status:"complete",current:L+1,total:v,moduleFiles:Tn}),{moduleName:z.name,module:Tn}}catch(ot){Be=ot instanceof Error?ot.message:String(ot),A.error("figma-pipeline",`Failed: ${z.name} (attempt ${yt+1}): ${Be}`)}return i({type:"module_progress",module:z.name,status:"failed",current:L+1,total:v}),{moduleName:z.name,error:Be}})});return Promise.allSettled(F)},{metadata:{moduleCount:v}})).map(F=>F.status==="fulfilled"?F.value:{moduleName:"unknown",error:String(F.reason)}),M=_.filter(F=>F.module).map(F=>F.module),R=_.filter(F=>F.error).map(F=>F.moduleName),O=Zs(M,t,i).map(F=>F.module),V=Date.now()-c,H=Math.round(V/1e3),P=`Imported ${O.length} modules from Figma design "${e.fileName}" in ${H}s.`;return R.length>0?i({type:"pipeline_partial",succeeded:O.map(F=>F.moduleName),failed:R,durationMs:V}):i({type:"pipeline_complete",modulesGenerated:O.length,modulesUnchanged:0,durationMs:V,assistantMessage:P}),{modules:O,moduleOrder:g,sharedCss:d,sharedJs:u,assistantMessage:P,stats:{modulesGenerated:O.length,modulesUnchanged:0,modulesFailed:R.length,durationMs:V}}}function $r(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),r=Math.min(t,n,s),i=(o+r)/2;if(o===r)return{h:0,s:0,l:i};let a=o-r,l=i>.5?a/(2-o-r):a/(o+r),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:i}}function hx(e,t){let n=[],s=t,o=[...e.colors].sort((P,F)=>F.occurrences-P.occurrences),r=o.filter(P=>P.usage==="background"||P.usage==="fill"),i=o.filter(P=>P.usage==="text"),a=r[0]||o[0],l=a?$r(a.hex).l<.4:!1;a&&n.push(` --${s}-color-bg: ${a.hex}`);let c=i[0]||(l?o.find(P=>$r(P.hex).l>.7):o.find(P=>$r(P.hex).l<.3));c&&n.push(` --${s}-color-text: ${c.hex}`);let d=new Set([a?.hex,c?.hex].filter(Boolean)),u=o.filter(P=>!d.has(P.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(P=>!d.has(P.hex)).slice(0,6).forEach((P,F)=>n.push(` --${s}-color-${F+1}: ${P.hex}`)),a){let P=$r(a.hex).l;n.push(` --${s}-color-surface: ${l?sm(a.hex,.05):om(a.hex,.03)}`),n.push(` --${s}-color-border: ${l?sm(a.hex,.15):om(a.hex,.12)}`)}let g=e.typography.filter(P=>P.role==="heading"||P.role==="subheading"),f=e.typography.filter(P=>P.role==="body"||P.role==="label"||P.role==="caption"),h=g[0]?.fontFamily||f[0]?.fontFamily||"system-ui",b=f[0]?.fontFamily||h;n.push(` --${s}-font-display: "${h}", system-ui, sans-serif`),n.push(` --${s}-font-body: "${b}", system-ui, sans-serif`);let S=g.sort((P,F)=>F.fontSize-P.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=f.sort((P,F)=>F.occurrences-P.occurrences)[0];v&&n.push(` --${s}-size-body: ${v.fontSize}px`);let k=[...new Set(e.spacing.map(P=>P.value))].sort((P,F)=>P-F),_=["xs","sm","md","lg","xl","2xl","section"];k.slice(0,_.length).forEach((P,F)=>{n.push(` --${s}-space-${_[F]}: ${P}px`)});let M=e.effects.filter(P=>P.type==="shadow"),R=e.effects.filter(P=>P.type==="radius");M[0]&&n.push(` --${s}-shadow: ${M[0].cssValue}`),R.sort((P,F)=>parseFloat(P.cssValue)-parseFloat(F.cssValue)),R[0]&&n.push(` --${s}-radius: ${R[0].cssValue}`),R[1]&&n.push(` --${s}-radius-lg: ${R[1].cssValue}`);let J=`:root {
|
|
2419
2375
|
${n.join(`;
|
|
2420
2376
|
`)};
|
|
2421
|
-
}`,
|
|
2377
|
+
}`,O=`
|
|
2422
2378
|
/* Reset */
|
|
2423
2379
|
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
|
|
2424
2380
|
|
|
@@ -2502,8 +2458,8 @@ body {
|
|
|
2502
2458
|
h1 { font-size: 2rem; }
|
|
2503
2459
|
h2 { font-size: 1.5rem; }
|
|
2504
2460
|
h3 { font-size: 1.25rem; }
|
|
2505
|
-
}`;return{sharedCss:
|
|
2506
|
-
`+
|
|
2461
|
+
}`;return{sharedCss:J+`
|
|
2462
|
+
`+O,sharedJs:`(function() {
|
|
2507
2463
|
var observer = new IntersectionObserver(function(entries) {
|
|
2508
2464
|
entries.forEach(function(entry) {
|
|
2509
2465
|
if (entry.isIntersecting) {
|
|
@@ -2513,11 +2469,11 @@ body {
|
|
|
2513
2469
|
});
|
|
2514
2470
|
}, { threshold: 0.1 });
|
|
2515
2471
|
document.querySelectorAll('[data-animate]').forEach(function(el) { observer.observe(el); });
|
|
2516
|
-
})();`}}function
|
|
2517
|
-
`)}function
|
|
2518
|
-
Children (${e.children.length}):`);for(let o of e.children){let
|
|
2519
|
-
Available image assets:`);for(let o of t){let
|
|
2520
|
-
`)}function
|
|
2472
|
+
})();`}}function sm(e,t){return im(e,t)}function om(e,t){return im(e,-t)}function im(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 yx(e){return e.replace(/([a-z])([A-Z])/g,"$1-$2").replace(/[^a-zA-Z0-9]+/g,"-").replace(/(^-|-$)/g,"").toLowerCase()}function bx(e,t,n){let s=new Set,o=[];for(let r of e){let i=yx(r.name);if(s.has(i)){let d=2;for(;s.has(`${i}-${d}`);)d++;i=`${i}-${d}`}s.add(i);let a=Sx(r.textContent),l=vx(r,t,n),c=`Figma section "${r.name}" \u2014 ${r.width}x${r.height}px, ${r.textContent.length} text elements, ${r.children.length} children`;o.push({name:i,description:c,contentBrief:a,layoutNotes:l})}return{specs:o,moduleOrder:o.map(r=>r.name)}}function Sx(e){let t={};for(let o of e){let r=o.role;t[r]||(t[r]=[]),t[r].push(o.text)}let n=[],s=["headline","subheadline","body","cta","label","caption"];for(let o of s)if(t[o])for(let r of t[o])n.push(`**${o}** (use as field default): "${r}"`);return n.join(`
|
|
2473
|
+
`)}function vx(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(`
|
|
2474
|
+
Children (${e.children.length}):`);for(let o of e.children){let r=` - ${o.type} "${o.name}" (${o.width}x${o.height})`;o.layoutMode&&(r+=` [${o.layoutMode}]`),o.childCount>0&&(r+=` [${o.childCount} children]`),o.characters&&(r+=` text: "${o.characters.slice(0,60)}"`),s.push(r)}}if(t.length>0){s.push(`
|
|
2475
|
+
Available image assets:`);for(let o of t){let r=rm(o.localPath);s.push(` - get_asset_url("${n}/assets/${r}") \u2014 ${o.name}`)}}return s.join(`
|
|
2476
|
+
`)}function xx(e,t,n,s,o){let r=[];if(r.push(`## Figma Design Translation
|
|
2521
2477
|
|
|
2522
2478
|
TRANSLATE this Figma section into a HubSpot CMS module. This is a CONVERSION, not creation.
|
|
2523
2479
|
- Use the EXACT text content from the design as field default values
|
|
@@ -2537,17 +2493,17 @@ The Figma design shows the DESKTOP layout. You MUST add responsive CSS:
|
|
|
2537
2493
|
- Hide purely decorative elements if they break mobile layout
|
|
2538
2494
|
- Add a \`@media (max-width: 1023px)\` block for tablet if the layout has 3+ columns
|
|
2539
2495
|
|
|
2540
|
-
## Section: "${e.name}" (${e.width}x${e.height}px)`),e.backgroundColor&&
|
|
2541
|
-
### Layout`),e.layoutMode&&
|
|
2542
|
-
### Text Content \u2014 USE THESE AS FIELD DEFAULTS`);for(let
|
|
2543
|
-
### Structure (${e.children.length} children)`);for(let
|
|
2544
|
-
text: "${
|
|
2545
|
-
### Available Image Assets \u2014 USE get_asset_url()`),
|
|
2546
|
-
### Images \u2014 USE IMAGE FIELDS WITH PLACEHOLDERS`),
|
|
2496
|
+
## Section: "${e.name}" (${e.width}x${e.height}px)`),e.backgroundColor&&r.push(`Background: ${e.backgroundColor}`),(e.layoutMode||e.itemSpacing||e.paddingTop)&&(r.push(`
|
|
2497
|
+
### Layout`),e.layoutMode&&r.push(`Direction: ${e.layoutMode}`),e.itemSpacing&&r.push(`Gap: ${e.itemSpacing}px`),(e.paddingTop||e.paddingRight||e.paddingBottom||e.paddingLeft)&&r.push(`Padding: ${e.paddingTop||0}px ${e.paddingRight||0}px ${e.paddingBottom||0}px ${e.paddingLeft||0}px`)),e.textContent.length>0){r.push(`
|
|
2498
|
+
### Text Content \u2014 USE THESE AS FIELD DEFAULTS`);for(let i of e.textContent)r.push(`- **${i.role}** (${i.fontSize}px, weight ${i.fontWeight}): "${i.text}"`)}if(e.children.length>0){r.push(`
|
|
2499
|
+
### Structure (${e.children.length} children)`);for(let i of e.children){let a=`- ${i.type} "${i.name}" (${i.width}x${i.height})`;i.layoutMode&&(a+=` layout: ${i.layoutMode}`),i.childCount>0&&(a+=`, ${i.childCount} children`),i.characters&&(a+=`
|
|
2500
|
+
text: "${i.characters.slice(0,100)}"`),r.push(a)}}if(n.length>0)if(o){r.push(`
|
|
2501
|
+
### Available Image Assets \u2014 USE get_asset_url()`),r.push("Images are uploaded as theme assets. Reference them with get_asset_url():");for(let i of n){let a=rm(i.localPath);r.push(`- \`get_asset_url("${s}/assets/${a}")\` \u2014 ${i.name}`)}}else{r.push(`
|
|
2502
|
+
### Images \u2014 USE IMAGE FIELDS WITH PLACEHOLDERS`),r.push('Do NOT use get_asset_url(). Instead, create "image" type fields in fields.json for each image.'),r.push('Set a descriptive default.src (e.g. "https://placehold.co/600x400?text=Hero+Image") and default.alt text.'),r.push("In the module HTML, use: {{ module.field_name.src }} and {{ module.field_name.alt }}"),r.push("This gives content editors full control to replace images in HubSpot.");for(let i of n)r.push(`- "${i.name}" \u2014 create an image field for this`)}return r.push(`
|
|
2547
2503
|
## Module Specification
|
|
2548
2504
|
- **Name**: ${t.name}
|
|
2549
|
-
- **Description**: ${t.description}`),
|
|
2550
|
-
`)}var
|
|
2505
|
+
- **Description**: ${t.description}`),r.join(`
|
|
2506
|
+
`)}var lm=j(()=>{"use strict";y();mt();Qn();Pa();$a();re();Ue()});var cm={};Ve(cm,{buildPlanModePrompt:()=>wx});function wx(e,t,n,s,o){let r=kx(o,!!t?.plan),i=[];return i.push(`You are vibeSpot's plan-mode assistant for the theme "${e}".
|
|
2551
2507
|
|
|
2552
2508
|
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.
|
|
2553
2509
|
|
|
@@ -2611,208 +2567,117 @@ Drive toward filling these gaps in priority order:
|
|
|
2611
2567
|
4. **Sections / modules** \u2014 high-level page structure (hero, features, testimonials, pricing, FAQ, footer, etc.)
|
|
2612
2568
|
5. **Content** \u2014 actual copy, value props, social proof, key messages
|
|
2613
2569
|
6. **Brand voice and visual style** \u2014 formal/casual, palette preferences, reference sites
|
|
2614
|
-
7. **Constraints** \u2014 must-haves, must-avoids, integrations needed`),t?.styleguide&&
|
|
2570
|
+
7. **Constraints** \u2014 must-haves, must-avoids, integrations needed`),t?.styleguide&&i.push(`## Available styleguide
|
|
2615
2571
|
|
|
2616
2572
|
The theme already has a styleguide. Reference its colors, typography, and tokens in the plan rather than asking about them again.
|
|
2617
2573
|
|
|
2618
2574
|
\`\`\`
|
|
2619
|
-
${
|
|
2620
|
-
\`\`\``),t?.brandvoice&&
|
|
2575
|
+
${Wa(t.styleguide,1500)}
|
|
2576
|
+
\`\`\``),t?.brandvoice&&i.push(`## Available brand voice
|
|
2621
2577
|
|
|
2622
2578
|
\`\`\`
|
|
2623
|
-
${
|
|
2624
|
-
\`\`\``),t?.themeContext&&
|
|
2579
|
+
${Wa(t.brandvoice,1e3)}
|
|
2580
|
+
\`\`\``),t?.themeContext&&i.push(`## Theme context
|
|
2625
2581
|
|
|
2626
2582
|
\`\`\`
|
|
2627
|
-
${
|
|
2628
|
-
\`\`\``),n.length>0&&
|
|
2583
|
+
${Wa(t.themeContext,1e3)}
|
|
2584
|
+
\`\`\``),n.length>0&&i.push(`## Existing modules in this theme
|
|
2629
2585
|
|
|
2630
2586
|
These already exist on the page \u2014 you can keep, modify, or remove them in the plan, or reference them as reusable:
|
|
2631
2587
|
|
|
2632
2588
|
${n.map(a=>`- ${a}`).join(`
|
|
2633
|
-
`)}`),s.length>0&&
|
|
2589
|
+
`)}`),s.length>0&&i.push(`## Module library (reusable across templates)
|
|
2634
2590
|
|
|
2635
2591
|
These modules exist in other templates and could be reused here. Reference them by name in the plan if appropriate.
|
|
2636
2592
|
|
|
2637
2593
|
${s.map(a=>`- **${a.name}** (used in: ${a.usedIn.join(", ")})`).join(`
|
|
2638
|
-
`)}`),t?.plan&&
|
|
2594
|
+
`)}`),t?.plan&&i.push(`## Current plan (continue refining)
|
|
2639
2595
|
|
|
2640
2596
|
The plan in progress so far. Build on it \u2014 preserve what's there, only update sections that are changing based on the user's latest message.
|
|
2641
2597
|
|
|
2642
2598
|
\`\`\`markdown
|
|
2643
2599
|
${t.plan}
|
|
2644
|
-
\`\`\``),
|
|
2600
|
+
\`\`\``),i.push(`## Phase guidance for this turn
|
|
2645
2601
|
|
|
2646
|
-
${
|
|
2602
|
+
${r}`),i.join(`
|
|
2647
2603
|
|
|
2648
|
-
`)}function
|
|
2604
|
+
`)}function kx(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:
|
|
2649
2605
|
- Briefly acknowledge the template and that you'll work from this structure (1\u20132 sentences in chat).
|
|
2650
2606
|
- 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.
|
|
2651
2607
|
- 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.
|
|
2652
2608
|
- 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.
|
|
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
|
|
2654
|
-
... [truncated]`}var
|
|
2609
|
+
- 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 Wa(e,t){return e.length<=t?e:e.slice(0,t)+`
|
|
2610
|
+
... [truncated]`}var dm=j(()=>{"use strict";y()});var Ga={};Ve(Ga,{applyPipelineResult:()=>xn,cancelActiveGeneration:()=>Ya,handleAgenticGenerate:()=>Fr,handleAgenticResume:()=>Qa,handleFigmaImport:()=>ro,handleGenerate:()=>Tx,handleGenerateStream:()=>oo,handlePlanModeStream:()=>el,isGenerating:()=>Gt,isPlanModeActive:()=>tl,resolveAgenticEngine:()=>vn,setParseWarningCallback:()=>za,shouldUseAgenticMode:()=>nl});import{execSync as Ka}from"child_process";function za(e){Va=e}function Gt(){return Ut.size>0}async function Or(e){let t=Rr.get(e)||Promise.resolve(),n,s=new Promise(r=>{n=r}),o=t.then(()=>s);return Rr.set(e,o),await t,()=>{n(),Rr.get(e)===o&&Rr.delete(e)}}function um(){let e={abort:new AbortController};return qa.add(e),{run:e,signal:e.abort.signal}}function pm(e){qa.delete(e)}function Ya(){let e=!1;for(let t of qa)t.abort.abort(),e=!0;return e}function Cx(e,t){let n=x();if(!n||n.id!==e){A.warn("ai-handler","Session changed during generation \u2014 discarding AI output");return}ct("assistant",t),_u(t,Va||void 0),D()}async function oo(e,t,n,s){let o=x();if(!o)throw new Error("No active session");let r=o.id,i=await Or(r);Ut.add(r);let a=c=>Cx(r,c),l=s?.length?vr(s):void 0;try{let c=$(),d=c.aiEngine||Xa();switch(d){case"anthropic-api":case"api":{let u=De("anthropic-api",c);if(!u)throw new Error("Anthropic API key not configured. Open Settings to add one.");await Qi(e,u,o.themeName,c.anthropicApiModel||"claude-sonnet-4-6",t,n,a,l);break}case"claude-oauth":{await Cd(e,o.themeName,c.anthropicApiModel||"claude-sonnet-4-6",t,n,a,l);break}case"openai-api":{let u=De("openai-api",c);if(!u)throw new Error("OpenAI API key not configured. Open Settings to add one.");await ea(e,u,o.themeName,c.openaiApiModel||"gpt-4o",t,n,a,l);break}case"gemini-api":{let u=De("gemini-api",c);if(!u)throw new Error("Gemini API key not configured. Open Settings to add one.");await ta(e,u,o.themeName,t,n,a,l);break}case"claude-code":await Td(e,o.themeName,t,n,a,l);break;case"gemini-cli":await oa("gemini",e,o.themeName,t,n,a,l);break;case"codex-cli":await oa("codex",e,o.themeName,t,n,a,l);break;case"langdock-api":{let u=De("langdock-api",c);if(!u)throw new Error("Langdock API key not configured. Open Settings to add one.");let p=c.langdockProvider||"anthropic",g={anthropic:"https://api.langdock.com/anthropic",openai:"https://api.langdock.com/openai",google:"https://api.langdock.com/google",mistral:"https://api.langdock.com/mistral"},f=c.langdockBaseUrl||g[p],h=c.langdockApiModel;switch(p){case"openai":case"mistral":await ea(e,u,o.themeName,h||"gpt-4.1",t,n,a,l,`${f}/v1/chat/completions`);break;case"google":await ta(e,u,o.themeName,t,n,a,l,`${f}/v1beta/models/${h||"gemini-2.5-flash"}:streamGenerateContent?alt=sse`,h);break;default:await Qi(e,u,o.themeName,h||"claude-sonnet-4-6",t,n,a,l,f);break}break}default:throw new Error(`Unknown AI engine: ${d}. Open Settings to configure one.`)}}finally{Ut.delete(r),Va=null,i()}}function Xa(){let e=$();if(Qe())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 Ka("claude --version",{stdio:"pipe"}),"claude-code"}catch{}try{return Ka("gemini --version",{stdio:"pipe"}),"gemini-cli"}catch{}try{return Ka("codex --version",{stdio:"pipe"}),"codex-cli"}catch{}throw new Error("No AI engine available. Open Settings to configure one.")}async function Tx(e){let t="";return await oo(e,n=>{t+=n}),t}function so(){let e=x(),t=xe(),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(r=>({id:r.id,label:r.label,pageType:r.pageType,moduleCount:r.modules.length}))),o}function vn(e){let t=e.aiEngine||Xa();if(!zs(t))throw new Error("Agentic pipeline is not available for this engine.");if(ns(t)){let o="";return t==="claude-code"&&(o=e.claudeCodeModel||""),{engine:t,apiKey:"",model:o}}let n;if(t==="claude-oauth"){if(!Qe())throw new Error("Claude OAuth session expired. Please re-authenticate in Settings.");n="oauth"}else n=De(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}}function Za(e){let t=e.multiPage;return{modules:e.modules.map(n=>n.moduleName),moduleCount:e.modules.length,moduleOrder:e.moduleOrder,stats:e.stats,...t?{pages:t.pages.map(n=>n.pageId)}:{},assistantMessage:e.assistantMessage}}async function Fr(e,t,n,s=!1){let o=x();if(!o)throw new Error("No active session");let r=o.id,{run:i,signal:a}=um(),l=await Or(r);try{if(a.aborted)return A.info("ai-handler","Agentic run cancelled before start (barge-in)"),Nr(so());Ut.add(r);let c=$(),{engine:d,apiKey:u,model:p}=vn(c),g=c.agenticConcurrency||20,f=so(),h=f.brandAssets?.plan,b=e;h&&h.trim()&&(b=`## Approved plan
|
|
2655
2611
|
|
|
2656
2612
|
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.
|
|
2657
2613
|
|
|
2658
|
-
${
|
|
2614
|
+
${h}
|
|
2659
2615
|
|
|
2660
2616
|
---
|
|
2661
2617
|
|
|
2662
2618
|
## User message
|
|
2663
2619
|
|
|
2664
|
-
${e}`);let
|
|
2620
|
+
${e}`);let S=n?.length?vr(n):void 0;if(S?.length)for(let O of S)O.type==="document"&&O.extractedText&&(b+=`
|
|
2665
2621
|
|
|
2666
2622
|
---
|
|
2667
|
-
[Attached document: ${
|
|
2668
|
-
${
|
|
2623
|
+
[Attached document: ${O.originalName}]
|
|
2624
|
+
${O.extractedText}`),O.type==="image"&&O.usage==="asset"&&O.assetPath&&(b+=`
|
|
2669
2625
|
|
|
2670
|
-
[Uploaded image: ${
|
|
2626
|
+
[Uploaded image: ${O.originalName} \u2192 available as get_asset_url("${O.assetPath}")]`);let v=Lt(),k=new Set(f.modules.map(O=>O.moduleName)),_=v.filter(O=>!k.has(O.module.moduleName)).map(O=>({name:O.module.moduleName,usedIn:O.usedIn,module:O.module})),{result:M,cost:R}=await Do(()=>qe({name:"agent_pipeline",sessionId:f.themeName,input:e,metadata:{engine:d,model:p,concurrency:g},tags:["vibespot","agentic-pipeline"]},async()=>{let O=await qp(b,f,d,u,p,g,t,_,s,a);return Bo(Za(O)),O})).catch(O=>{if(Ws(O))return A.info("ai-handler","Agentic run cancelled (barge-in)"),{result:Nr(f),cost:void 0};throw O});if(M.cost=R,M.canceled)return M;let J=x();if(!J||J.id!==r)throw A.warn("ai-handler","Session changed during agentic generation \u2014 discarding output"),new Error("Session changed during generation");return M}finally{Ut.delete(r),pm(i),l()}}function Nr(e){return{modules:[...e.modules],moduleOrder:e.moduleOrder,sharedCss:e.sharedCss,sharedJs:e.sharedJs,assistantMessage:"",canceled:!0,stats:{modulesGenerated:0,modulesUnchanged:e.modules.length,modulesFailed:0,durationMs:0}}}async function Qa(e,t,n,s){let o=x();if(!o)throw new Error("No active session");let r=o.id,{run:i,signal:a}=um(),l=await Or(r);try{if(a.aborted)return A.info("ai-handler","Checkpoint resume cancelled before start (barge-in)"),Nr(so());Ut.add(r);let c=$(),{engine:d,apiKey:u,model:p}=vn(c),g=c.agenticConcurrency||20,f=so(),{result:h,cost:b}=await Do(()=>qe({name:"agent_pipeline_resume",sessionId:f.themeName,input:{action:t.action,kind:t.kind},metadata:{engine:d,model:p,concurrency:g},tags:["vibespot","agentic-pipeline","checkpoint-resume"]},async()=>{let v=await Xp(e,t,f,d,u,p,g,n,a,s);return Bo(Za(v)),v})).catch(v=>{if(Ws(v))return A.info("ai-handler","Checkpoint resume cancelled (barge-in)"),{result:Nr(f),cost:void 0};throw v});if(h.cost=b,h.canceled)return h;let S=x();if(!S||S.id!==r)throw A.warn("ai-handler","Session changed during checkpoint resume \u2014 discarding output"),new Error("Session changed during generation");return h.brandAssetsUpdate&&(h.brandAssetsUpdate.styleguide&&Mr(S,"styleguide",h.brandAssetsUpdate.styleguide),h.brandAssetsUpdate.brandvoice&&Mr(S,"brandvoice",h.brandAssetsUpdate.brandvoice),D()),h}finally{Ut.delete(r),pm(i),l()}}async function ro(e,t,n,s){let o=x();if(!o)throw new Error("No active session");let r=o.id,i=await Or(r);Ut.add(r);try{let{runFigmaConversion:a}=await Promise.resolve().then(()=>(lm(),am)),l=$(),{engine:c,apiKey:d,model:u}=vn(l),p=l.agenticConcurrency||20,g=so(),{result:f,cost:h}=await Do(()=>qe({name:"figma_import",sessionId:t,input:{fileName:e.fileName,sections:e.sections.length},metadata:{engine:c,model:u,concurrency:p},tags:["vibespot","figma-import"]},async()=>{let S=await a(e,t,c,d,u,p,n,g.brandAssets,s?.useAssets);return Bo(Za(S)),S}));f.cost=h;let b=x();if(!b||b.id!==r)throw A.warn("ai-handler","Session changed during Figma import \u2014 discarding output"),new Error("Session changed during generation");return f}finally{Ut.delete(r),i()}}function xn(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"});Gc({pages:n.pages,sharedModules:n.sharedModules,sharedCss:n.sharedCss,sharedJs:n.sharedJs,pageLabels:s})}else{Ge({modules:e.modules,sharedCss:e.sharedCss,sharedJs:e.sharedJs}),Yt(e.moduleOrder);let s=e.contentType;if(s==="email"){let o=xe();o&&!o.contentMode&&(o.contentMode="email")}else if(s==="blog"){let o=xe();o&&(o.contentMode||(o.contentMode="blog"),o.pageType!=="blog_post"&&(o.pageType="blog_post"))}}t?.cost&&Lc(t.cost),ct("assistant",e.assistantMessage,t),D()}async function el(e,t,n){let s=x();if(!s)throw new Error("No active session");let o=$(),{engine:r,apiKey:i,model:a}=vn(o),[{buildPlanModePrompt:l},{callAgent:c}]=await Promise.all([Promise.resolve().then(()=>(dm(),cm)),Promise.resolve().then(()=>(mt(),ju))]),d=s.messages.filter(k=>k.role==="assistant").length,u=s.modules.map(k=>k.moduleName),p=Lt(),g=new Set(u),f=p.filter(k=>!g.has(k.module.moduleName)).map(k=>({name:k.module.moduleName,usedIn:k.usedIn})),h=l(s.themeName,s.brandAssets,u,f,d),b=n?.length?vr(n):void 0,S=e;if(b?.length)for(let k of b)k.type==="document"&&k.extractedText&&(S+=`
|
|
2671
2627
|
|
|
2672
2628
|
---
|
|
2673
|
-
[Attached document: ${
|
|
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 ia(){return!!R().planMode}function ra(){let e=R(),t=e.aiEngine||sa();return Ms(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 ta,jt,Kn=N(()=>{"use strict";y();ee();Ce();Ko();le();tr();Or();$t();jr();fu();Be();ta=null;jt=null});import{readFileSync as gb,readdirSync as fb,existsSync as hb}from"fs";import{dirname as yb,join as ti}from"path";import{fileURLToPath as bb}from"url";function vb(e){let t=e.match(Sb);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 xb(e){let t=vb(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 wb(){let e=[ti(Au,"../../assets/plan-templates"),ti(Au,"../assets/plan-templates"),ti(process.cwd(),"assets/plan-templates")];for(let t of e)if(hb(t))return t;return null}function _u(){if(qt)return qt;let e=wb();if(!e)return qt=[],qt;let t=[],n=[];try{n=fb(e)}catch{return qt=[],qt}for(let s of n)if(s.endsWith(".md"))try{let o=gb(ti(e,s),"utf-8"),i=xb(o);i&&t.push(i)}catch{}return t.sort((s,o)=>s.order!==o.order?s.order-o.order:s.label.localeCompare(o.label)),qt=t,qt}function $u(e){return _u().find(t=>t.id===e)??null}function Eu(){return _u().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 Au,Sb,qt,Mu=N(()=>{"use strict";y();Au=yb(bb(import.meta.url)),Sb=/^---\r?\n([\s\S]*?)\r?\n---\r?\n([\s\S]*)$/;qt=null});import{existsSync as Iu,mkdirSync as Cb,writeFileSync as kb,rmSync as Tb}from"fs";import{join as Pu}from"path";function Nu(e){return Pu(e,".vibespot",Ab)}function ni(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=Pu(t.themePath,".vibespot");Iu(s)||Cb(s,{recursive:!0}),kb(Nu(t.themePath),e,"utf-8")}catch(s){M.warn("plan",`Failed to write plan.md: ${s instanceof Error?s.message:String(s)}`)}return L(),e}function la(){let e=C();if(!e)return;e.brandAssets&&delete e.brandAssets.plan;let t=ke();t&&delete t.plan;try{let n=Nu(e.themePath);Iu(n)&&Tb(n)}catch(n){M.warn("plan",`Failed to remove plan.md: ${n instanceof Error?n.message:String(n)}`)}L()}function Ru(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}ni(o),p(t,200,{ok:!0,plan:o})})}function Ou(e,t){qe(e,t,()=>{la(),Y({planMode:!1}),p(t,200,{ok:!0})})}function Fu(e,t){p(t,200,{templates:Eu()})}function Du(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=$u(o);if(!i){p(t,404,{error:`Unknown plan template: ${o}`});return}ni(i.body),Y({planMode:!0}),p(t,200,{ok:!0,templateId:i.id,label:i.label,plan:i.body})})}var Ab,ju=N(()=>{"use strict";y();Xe();Ce();Kt();ee();le();Mu();Ab="plan.md"});function Lu(e){let t,n,s;for(ca.lastIndex=0;(s=ca.exec(e))!==null;)t=s[1].trim();let o;for(da.lastIndex=0;(o=da.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(ca,"").replace(da,"").replace(/\n{3,}/g,`
|
|
2676
|
-
|
|
2677
|
-
`).trim(),plan:t,choices:n}}var ca,da,Ju=N(()=>{"use strict";y();ca=/```vibespot-plan\s*\n([\s\S]*?)```/g,da=/```vibespot-choices\s*\n([\s\S]*?)```/g});import{spawn as ua}from"child_process";function Bu(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+=`
|
|
2678
|
-
Process error: ${o.message}`,t.completedAt=Date.now()}),setTimeout(()=>{t.status==="running"&&(e.kill(),t.status="failed",t.output+=`
|
|
2679
|
-
Process timed out`,t.completedAt=Date.now())},n||3e5)}function Ds(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};Xt.set(o,i);let r=ua(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()),Bu(r,i,s?.timeout),o}function mn(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};Xt.set(s,o);let i=e.split(" "),r=ua(i[0],i.slice(1),{cwd:n?.cwd,stdio:["ignore","pipe","pipe"],env:{...process.env,...n?.env},shell:!0});return Bu(r,o,n?.timeout),s}function si(e){return Xt.get(e)}function _b(){let e=Date.now()-18e5;for(let[t,n]of Xt)n.completedAt&&n.completedAt<e&&Xt.delete(t)}function oi(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};Xt.set(s,o);let i=e.split(" "),r=ua(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+=`
|
|
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+=`
|
|
2681
|
-
Process timed out`,o.completedAt=Date.now(),o.listeners.clear())},l),s}function Hu(e,t){let n=Xt.get(e);if(!n||!("listeners"in n))return;let s=n;if(s.output)try{t(s.output)}catch{}s.listeners.add(t)}function Uu(e,t){let n=Xt.get(e);!n||!("listeners"in n)||n.listeners.delete(t)}var Xt,ii=N(()=>{"use strict";y();Xt=new Map;setInterval(_b,600*1e3)});import{readFileSync as $b,readdirSync as Eb,existsSync as Mb}from"fs";import{dirname as Ib,join as ri}from"path";import{fileURLToPath as Pb}from"url";function Nb(){let e=[ri(Gu,"../../starters"),ri(Gu,"../starters"),ri(process.cwd(),"starters")];for(let t of e)if(Mb(t))return t;return null}function Wu(){if(Vn!==null)return Vn;let e=Nb();if(!e)return Vn=[],Vn;let t=[];for(let n of Eb(e).filter(s=>s.endsWith(".json")).sort())try{let s=JSON.parse($b(ri(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 Vn=t,Vn}function Ku(){return Wu().map(e=>({id:e.id,name:e.name,description:e.description,category:e.category,contentType:e.contentType,moduleCount:e.modules.length}))}function ma(e){return Wu().find(t=>t.id===e)||null}var Gu,Vn,Vu=N(()=>{"use strict";y();Gu=Ib(Pb(import.meta.url)),Vn=null});var Ls={};Ge(Ls,{collectThemeFiles:()=>Yu,extractDesignContext:()=>jb});import{existsSync as ai,readdirSync as li,readFileSync as Rb}from"fs";import{join as kt}from"path";import{spawn as Ob}from"child_process";async function zu(){return pa||(pa=(await import("@anthropic-ai/sdk")).default),pa}function js(e){try{return Rb(e,"utf-8")}catch{return""}}function Yu(e){let t=[],n=0;function s(a,l){if(!l.trim())return!0;let c=`
|
|
2682
|
-
### ${a}
|
|
2683
|
-
\`\`\`
|
|
2684
|
-
${l}
|
|
2685
|
-
\`\`\`
|
|
2686
|
-
`;return n+c.length>Fb?!1:(t.push(c),n+=c.length,!0)}let o=js(kt(e,"theme.json"));o&&s("theme.json",o);let i=kt(e,"css");if(ai(i)){for(let a of li(i).filter(l=>l.endsWith(".css")))if(!s(`css/${a}`,js(kt(i,a))))break}let r=kt(e,"modules");if(ai(r))for(let a of li(r).filter(l=>l.endsWith(".module"))){let l=kt(r,a),c=js(kt(l,"module.css"));if(c&&!s(`modules/${a}/module.css`,c))break}if(ai(r))for(let a of li(r).filter(l=>l.endsWith(".module"))){let l=kt(r,a),c=js(kt(l,"module.html"));if(c&&!s(`modules/${a}/module.html`,c))break}if(ai(r))for(let a of li(r).filter(l=>l.endsWith(".module"))){let l=kt(r,a),c=js(kt(l,"fields.json"));if(c&&!s(`modules/${a}/fields.json`,c))break}return t.join("")}function Db(){if(!ci)try{ci=P(bn("extraction-prompt.md"))}catch{ci=""}return ci}function ga(e,t,n){return new Promise((s,o)=>{let i={...process.env};delete i.CLAUDECODE;let r=Ob(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 jb(e,t){t?.({status:"Collecting theme files..."});let n=Yu(e);if(!n.trim())throw new Error("No CSS, HTML, or fields.json files found in theme.");let s=Db();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 zu(),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(),ji)),h=await u();if(!h)throw new Error("Claude OAuth session expired. Please re-authenticate in Settings.");let f=await zu(),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=En(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=Mn(g.usageMetadata);break}case"claude-code":{let u=`${s}
|
|
2688
|
-
|
|
2689
|
-
## User Request
|
|
2690
|
-
${o}`,m=["--print"];i.claudeCodeModel&&m.push("--model",i.claudeCodeModel),a=await ga("claude",m,u);break}case"gemini-cli":{let u=`${s}
|
|
2691
|
-
|
|
2692
|
-
## User Request
|
|
2693
|
-
${o}`;a=await ga("gemini",[],u);break}case"codex-cli":{let u=`${s}
|
|
2694
|
-
|
|
2695
|
-
## User Request
|
|
2696
|
-
${o}`;a=await ga("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 pa,Fb,ci,Js=N(()=>{"use strict";y();oe();ee();Be();on();pa=null;Fb=8e4;ci=""});var fa={};Ge(fa,{extractBrandvoice:()=>Lb});async function Lb(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.
|
|
2697
|
-
|
|
2698
|
-
Return a markdown document with these sections (skip any section where the content provides no signal):
|
|
2699
|
-
|
|
2700
|
-
## Tone
|
|
2701
|
-
Overall communication style (e.g., confident but approachable, technical but clear, playful, authoritative).
|
|
2702
|
-
|
|
2703
|
-
## Voice Characteristics
|
|
2704
|
-
3-5 bullet points describing how this brand "sounds" (e.g., "Uses short, punchy sentences", "Addresses reader directly with 'you'").
|
|
2705
|
-
|
|
2706
|
-
## Vocabulary
|
|
2707
|
-
- **Preferred words**: Terms used repeatedly or intentionally
|
|
2708
|
-
- **Avoided patterns**: Any notable absences or anti-patterns
|
|
2709
|
-
|
|
2710
|
-
## Sentence Style
|
|
2711
|
-
Typical sentence length, structure, use of questions, imperatives, etc.
|
|
2712
|
-
|
|
2713
|
-
## Dos and Don'ts
|
|
2714
|
-
3-4 practical rules for writing in this voice (e.g., "Do: Lead with benefits, not features", "Don't: Use jargon without context").
|
|
2715
|
-
|
|
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:(M.info("brandvoice-extractor",`Extracted brand voice (${r.length} chars)`),r.trim())}catch(i){let r=i instanceof Error?i.message:String(i);return M.warn("brandvoice-extractor",`Brand voice extraction failed: ${r}`),null}}var ha=N(()=>{"use strict";y();dt();le()});var di={};Ge(di,{extractThemeContext:()=>Jb});async function Jb(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.
|
|
2717
|
-
|
|
2718
|
-
Return a markdown document with these sections (skip any section where the content provides no information):
|
|
2719
|
-
|
|
2720
|
-
## Product / Company
|
|
2721
|
-
Name, one-line description, and what it does.
|
|
2722
|
-
|
|
2723
|
-
## Value Propositions
|
|
2724
|
-
Key benefits or features (bulleted list).
|
|
2725
|
-
|
|
2726
|
-
## Target Audience
|
|
2727
|
-
Who this product/service is for.
|
|
2728
|
-
|
|
2729
|
-
## Tone & Voice
|
|
2730
|
-
Communication style (e.g., professional, casual, technical, friendly).
|
|
2731
|
-
|
|
2732
|
-
## Key Terminology
|
|
2733
|
-
Specific terms, product names, or branded language used consistently.
|
|
2734
|
-
|
|
2735
|
-
Keep it concise \u2014 this brief is used as context for AI-generated content on other pages in the same theme.${t?`
|
|
2736
|
-
|
|
2737
|
-
Existing product context (update if the new content adds info, keep what's still accurate):
|
|
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:(M.info("context-extractor",`Extracted theme context (${l.length} chars)`),l.trim())}catch(a){let l=a instanceof Error?a.message:String(a);return M.warn("context-extractor",`Theme context extraction failed: ${l}`),null}}var ui=N(()=>{"use strict";y();dt();le()});import{join as qu}from"path";function Bb(e){let t=[];return e.brandAssets?.styleguide||t.push("styleguide"),e.brandAssets?.brandvoice||t.push("brandvoice"),e.brandAssets?.themeContext||t.push("themeContext"),t}function Hb(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=qu(e.themePath,".vibespot");Re(o),B(qu(o,s),n)}async function Xu(e,t){let n=Bb(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"]},()=>Ub(e,t,n,s))}async function Ub(e,t,n,s){let o=Gb(t)?t:{...await Wb(e),...t??{}};n.includes("styleguide")&&await ya(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 ya(e,"brandvoice",s,()=>te("extract-brandvoice",()=>o.extractBrandvoice(e,r))),n.includes("themeContext")&&await ya(e,"themeContext",s,()=>te("extract-theme-context",()=>o.extractThemeContext(e,r))),s}async function ya(e,t,n,s){n.attempted.push(t);try{let o=await s();if(!o){n.skipped.push(t);return}Hb(e,t,o),n.extracted.push(t)}catch(o){let i=o instanceof Error?o.message:String(o);n.skipped.push(t),n.errors.push({asset:t,message:i}),M.warn("brand-enrichment",`${t} enrichment skipped: ${i}`)}}function Gb(e){return!!e?.extractStyleguide&&!!e.extractBrandvoice&&!!e.extractThemeContext&&!!e.buildPreviewHtml}async function Wb(e){let{extractDesignContext:t}=await Promise.resolve().then(()=>(Js(),Ls)),{buildPreviewHtml:n}=await Promise.resolve().then(()=>(ws(),Wo)),{resolveAgenticEngine:s}=await Promise.resolve().then(()=>(Kn(),aa)),{extractBrandvoice:o}=await Promise.resolve().then(()=>(ha(),fa)),{extractThemeContext:i}=await Promise.resolve().then(()=>(ui(),di)),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 zn,readdirSync as Qu,rmSync as Kb,writeFileSync as pn,mkdirSync as mi}from"fs";import{join as Ne,basename as Vb}from"path";import{homedir as zb}from"os";import{execFileSync as tm}from"child_process";function gi(){if(pi&&Date.now()-pi.ts<Yb)return pi.data;let e=[];if(zn(ut))try{for(let t of Qu(ut,{withFileTypes:!0}))if(t.isDirectory()){let n=Ne(ut,t.name,"theme.json");if(zn(n)){let s=0,o=Ne(ut,t.name,"modules");if(zn(o))try{s=Qu(o,{withFileTypes:!0}).filter(i=>i.isDirectory()).length}catch{}e.push({name:t.name,moduleCount:s})}}}catch{}return pi={data:e,ts:Date.now()},e}function sm(e){let t=C(),n=io(),s=!1;try{tm("hs",["--version"],{encoding:"utf-8",stdio:"pipe",...nm}),s=!0}catch{}let o=Fn().sort((r,a)=>a.updatedAt-r.updatedAt),i=gi();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:Jn()})}function om(e,t){W(e,n=>{try{if(Yt()){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),zn(a)&&Kb(a,{recursive:!0,force:!0}),o&&typeof o=="string"&&!ma(o)){p(t,400,{error:`Starter template "${o}" not found`});return}is(a,r),On(a,r),o&&typeof o=="string"?(qb(a,r,o),Te()):i==="email"&&(Rt("module_only","Email","email"),$n(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 qb(e,t,n){let s=ma(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&&$n(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");mi(d,{recursive:!0});for(let u of s.modules){let m=Ne(d,`${u.moduleName}.module`);mi(m,{recursive:!0}),pn(Ne(m,"fields.json"),u.fieldsJson,"utf-8"),pn(Ne(m,"meta.json"),u.metaJson,"utf-8"),pn(Ne(m,"module.html"),u.moduleHtml,"utf-8"),pn(Ne(m,"module.css"),u.moduleCss,"utf-8"),u.moduleJs&&pn(Ne(m,"module.js"),u.moduleJs,"utf-8")}if(s.sharedCss){let u=Ne(e,"css");mi(u,{recursive:!0}),pn(Ne(u,`${t}-theme.css`),s.sharedCss,"utf-8")}if(s.sharedJs){let u=Ne(e,"js");mi(u,{recursive:!0}),pn(Ne(u,`${t}-animations.js`),s.sharedJs,"utf-8")}}function im(e){p(e,200,{starters:Ku()})}function rm(e,t){W(e,n=>{try{if(Yt()){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()=>{tm("hs",["cms","fetch",o,l],{encoding:"utf-8",stdio:"pipe",...nm});let c=await em(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)})}):as(i,o,l).then(async()=>{let c=await em(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 em(e,t){On(e,t,{isImported:!0}),Go(e),L();let n=C(),s={attempted:[],extracted:[],skipped:[],errors:[]};return n&&(s=await Xu(n),L()),{moduleCount:n?.modules.length||0,brandEnrichment:s}}function am(e,t){W(e,n=>{try{if(Yt()){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(zn(o)||(o=Ne(ut,s)),!zn(o)){p(t,400,{error:`Theme folder not found: ${s}`});return}let i=Vb(o);On(o,i),Go(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 lm(e,t){W(e,n=>{try{if(Yt()){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=jo(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 cm(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 dm(e){let t=Le();if(!t){p(e,200,{themes:[],error:"No HubSpot account connected"});return}(async()=>{let n=await cl(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 lo(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=gi(),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 nm,ut,pi,Yb,fi=N(()=>{"use strict";y();Xe();ee();rs();po();sn();Ce();Kt();Kn();nn();ee();oe();Vu();Cs();Zu();nm=process.platform==="win32"?{shell:!0}:{},ut=Ne(zb(),"vibespot-themes"),pi=null,Yb=5e3});import{existsSync as Xb,readFileSync as Zb,appendFileSync as Qb}from"fs";import{join as um}from"path";import{homedir as mm}from"os";function nS(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 Sa(e,t={},n=ym){let s=new AbortController,o=setTimeout(()=>s.abort(),n);try{return await fetch(e,{...t,signal:s.signal})}finally{clearTimeout(o)}}async function sS(e){let t=await Sa("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 oS(e){let t=await Sa("https://api.openai.com/v1/models",{headers:{Authorization:`Bearer ${e}`}});return t.ok?(await t.json()).data.map(s=>s.id):[]}function gm(e,t){return e.filter(n=>t.test(n)).sort((n,s)=>n.localeCompare(s)).map(n=>({id:n,label:nS(n)}))}async function iS(e){let t=await Sa(`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 rS(e=!1){if(!e&&Date.now()-Yn.ts<eS&&Object.keys(Yn.data).length>0)return Yn.data;let t=R(),n={...ba},s=[],o=Fe("anthropic-api",t);o&&s.push(sS(o).then(c=>{c.length&&(n["anthropic-api"]=c,n["claude-oauth"]=c,n["claude-code"]=c)}).catch(()=>{}));let i=Fe("openai-api",t);i&&s.push(oS(i).then(c=>{if(!c.length)return;let d=gm(c,hm);d.length&&(n["openai-api"]=d);let u=gm(c,tS);u.length&&(n["codex-cli"]=u)}).catch(()=>{}));let r=Fe("gemini-api",t);r&&s.push(iS(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,ym+500))]);let l=t.langdockProvider||"anthropic";return n["langdock-api"]=pm[l]||pm.anthropic,a&&(Yn.data=n,Yn.ts=Date.now()),n}function bm(e){let t=nl(),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:Sn(),environment:t,config:s,models:ba,sessionCount:Fn().length,localThemeCount:gi().length})}function Sm(e,t){let n=/[?&]refresh=1\b/.test(e.url||"");rS(n).then(s=>p(t,200,{models:s})).catch(()=>p(t,200,{models:ba}))}function vm(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=fm[o];if(!i&&Date.now()-r.ts<aS&&Object.keys(r.data).length>0){p(t,200,{...r.data,group:o,cached:!0});return}let a;if(o==="ai"){let l=sl();a={tools:{claudeCode:l.claudeCode,geminiCli:l.geminiCli,codexCli:l.codexCli,claudeOAuth:l.claudeOAuth},availableEngines:l.availableEngines}}else if(o==="platform")a={tools:ol()};else{let l=io();a={tools:l.tools,availableEngines:l.availableEngines}}fm[o]={data:a,ts:Date.now()},p(t,200,{...a,group:o,cached:!1})}function xm(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 wm(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 Cm(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=mn(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 km(e,t){W(e,n=>{try{let s=JSON.parse(n||"{}"),o=R(),i=o.hubspotUploadMode||"api";if(s.personalAccessKey)if(i==="api"){ao(s.personalAccessKey).then(r=>{Xn(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=Ds("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 Tm(e,t){W(e,n=>{try{let s=JSON.parse(n||"{}");if(!no().found){p(t,400,{error:"GitHub CLI not installed",needsInstall:!0});return}let i=so();if(i.authenticated&&!s.force){p(t,200,{ok:!0,alreadyAuthenticated:!0,username:i.username});return}if(s.token){let a=Ds("gh",["auth","login","--with-token"],"Authenticating with GitHub",{timeout:3e4,stdin:s.token});p(t,200,{ok:!0,jobId:a});return}let r=mn("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 Am(e,t){W(e,n=>{try{let{portalId:s,action:o}=JSON.parse(n);if((R().hubspotUploadMode||"api")==="api"){if(o==="remove"&&s){Ni(s),p(t,200,{ok:!0});return}if(s){Ri(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=Ds("hs",["accounts","remove",l],`Removing HubSpot account ${l}`,{timeout:15e3});p(t,200,{ok:!0,jobId:c});return}if(l){let c=Ds("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 _m(e){let t=mn("gh auth logout --hostname github.com -y","Logging out of GitHub",{timeout:15e3});p(e,200,{ok:!0,jobId:t})}function $m(e,t){W(e,n=>{try{let{cli:s,apiKey:o}=JSON.parse(n||"{}");switch(s){case"claude":{let i=mn("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=mn("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")?um(mm(),".zshrc"):um(mm(),".bashrc");try{(Xb(l)?Zb(l,"utf-8"):"").includes("OPENAI_API_KEY")||Qb(l,`
|
|
2739
|
-
# Added by vibeSpot
|
|
2740
|
-
${a}
|
|
2741
|
-
`)}catch{}}}p(t,200,{ok:!0,message:"API key saved"})}else{let i=mn("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 Em(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 Mm(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}Oi(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 Im(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]||"",Yn.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 Pm(e,t){let n=e.replace("/api/settings/job/","");if(!n){p(t,400,{error:"Job ID required"});return}let s=si(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 Yn,eS,ba,pm,hm,tS,ym,aS,fm,Nm=N(()=>{"use strict";y();Xe();ee();Ce();fi();nn();sn();oe();ii();Yn={data:{},ts:0},eS=600*1e3,ba={"claude-code":[{id:"claude-opus-4-8",label:"Claude Opus 4.8"},{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-8",label:"Claude Opus 4.8"},{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-8",label:"Claude Opus 4.8"},{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"}]},pm={anthropic:[{id:"claude-sonnet-4-6",label:"Claude Sonnet 4.6 (default)"},{id:"claude-opus-4-8",label:"Claude Opus 4.8"},{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"}]},hm=/^(gpt-[45](\.\d+)?(-[a-z0-9-]+)?|o[1-4](-(mini|pro|nano)(-high)?)?|codex(-[a-z0-9-]+)?)$/,tS=hm;ym=2500;aS=60*1e3,fm={ai:{data:{},ts:0},platform:{data:{},ts:0},all:{data:{},ts:0}}});function Rm(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}Fi(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 Om(e,t){let n=Ze(),s=en();p(t,200,{authenticated:n,expiresAt:s?.expiresAt||null})}function Fm(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 Dm=N(()=>{"use strict";y();Xe();ee();$t()});import{existsSync as lS,rmSync as cS}from"fs";import{join as dS}from"path";function jm(e,t,n){if(e==="GET"){let s=C(),o=Fn().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);Mc(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 Lm(e,t){W(e,n=>{try{let{sessionId:s}=JSON.parse(n),o=jo(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 Jm(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=dS(ut,s);if(!lS(o)){p(t,404,{error:"Theme not found on disk"});return}cS(o,{recursive:!0,force:!0}),p(t,200,{ok:!0})}catch(s){p(t,500,{error:s instanceof Error?s.message:String(s)})}})}function Bm(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=Ic(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 Hm(e,t){W(e,n=>{try{let{sessionId:s}=JSON.parse(n);if(!s){p(t,400,{error:"sessionId is required"});return}let o=Pc(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 Um=N(()=>{"use strict";y();Xe();Ce();fi()});import{existsSync as hi,readFileSync as uS,readdirSync as mS,rmSync as zm}from"fs";import{join as Oe,basename as pS,relative as gS,sep as fS}from"path";import hS from"jszip";function Ym(e){let t=C();if(!t){p(e,404,{error:"No active session"});return}let n=Ot();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 qm(e,t=[]){for(let n of mS(e,{withFileTypes:!0}))if(n.isDirectory()){if(yS.has(n.name))continue;qm(Oe(e,n.name),t)}else n.isFile()&&t.push(Oe(e,n.name));return t}async function Xm(e){let t=C();if(!t){p(e,404,{error:"No active session"});return}let n=t.themePath;if(!hi(n)){p(e,404,{error:"Theme directory not found"});return}let s=t.themeName||"theme",o=pS(n);try{let i=new hS;for(let a of qm(n)){let l=Oe(o,gS(n,a)).split(fS).join("/");i.file(l,uS(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){M.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=Rt(l?"module_only":i,r,l?"email":void 0);l&&s.themePath&&$n(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(!Ac(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 Qm(e,t){W(e,n=>{try{let{templateId:s}=JSON.parse(n);if(!s){p(t,400,{error:"templateId is required"});return}if(!fs(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 ep(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(!Tc(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 tp(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(!kc(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 np(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=Cc(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 sp(e){let t=Ot();p(e,200,{modules:t.map(n=>({moduleName:n.module.moduleName,usedIn:n.usedIn,fieldsJson:n.module.fieldsJson}))})}function op(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=Ot().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 ip(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=va(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);hi(l)&&zm(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 ap(e,t){p(t,200,rp)}function SS(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(bS);if(l)for(let c of l)t.includes(c.toLowerCase())||t.push(c.toLowerCase())}if(i){let l=Gm.exec(a);if(Gm.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 va(e,t){let{colors:n,fonts:s}=SS(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=rp.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 lp(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"&&vS.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");hi(o)&&zm(o),L(),p(n,200,{ok:!0});return}p(n,405,{error:"Method not allowed"})}function Wm(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 Km(e){return e==="themeContext"?"extract-theme-context":`extract-${e}`}async function Vm(e,t,n){if(t==="styleguide"){let{extractDesignContext:m}=await Promise.resolve().then(()=>(Js(),Ls));return m(n||e.themePath)}let{resolveAgenticEngine:s}=await Promise.resolve().then(()=>(Kn(),aa)),{loadConfig:o}=await Promise.resolve().then(()=>(ee(),qa)),i=o(),{engine:r,apiKey:a,model:l}=s(i),{buildPreviewHtml:c}=await Promise.resolve().then(()=>(ws(),Wo)),d=c();if(!d||d.length<50)return null;if(t==="brandvoice"){let{extractBrandvoice:m}=await Promise.resolve().then(()=>(ha(),fa));return m(d,r,a,l)}let{extractThemeContext:u}=await Promise.resolve().then(()=>(ui(),di));return u(d,e.brandAssets?.themeContext,r,a,l)}function cp(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(Km(g),()=>Vm(n,g,r))))),u={};for(let g=0;g<c.length;g++){let h=d[g],f=h.status==="fulfilled"?h.value:null;f&&Wm(n,c[g],f),u[c[g]]=f}let m=null;u.styleguide&&(m=va(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(Km(i),()=>Vm(n,i,r)));if(!a){p(t,200,{ok:!1,type:i,error:"No content to extract from"});return}Wm(n,i,a);let l=null;i==="styleguide"&&(l=va(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 dp(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(()=>(po(),yl));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(!hi(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(),Ls)),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 yS,rp,bS,Gm,vS,up=N(()=>{"use strict";y();Xe();le();Be();ee();rs();Ce();oe();yS=new Set([".git",".vibespot","node_modules"]);rp=[{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"}];bS=/#[0-9a-fA-F]{6}\b/g,Gm=/font[- ]?famil(?:y|ies)\s*[:=]\s*([^\n]+)/gi;vS=/^#[0-9a-fA-F]{6}$/});import{join as xS}from"path";function mp(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 pp(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?yc(o.moduleName):bc(o.moduleName),L(),p(n,200,{ok:!0})});return}p(n,405,{error:"Method not allowed"})}function gp(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 fp(e,t){qe(e,t,n=>{Array.isArray(n.order)?(Wt(n.order),L(),p(t,200,{ok:!0})):p(t,400,{error:"order must be an array"})})}async function hp(e){let t=C();if(!t){p(e,404,{error:"No active session"});return}try{Te();let n=Ao(t.themePath),s=oi(`hs cms upload "${t.themePath}" "${t.themeName}"`,"Uploading to HubSpot",{cwd:xS(t.themePath,".."),timeout:18e4});p(e,200,{ok:!0,jobId:s,fixes:n})}catch(n){p(e,500,{error:String(n)})}}function yp(e,t){W(e,n=>{try{let{moduleName:s,fieldPath:o,value:i}=JSON.parse(n);Sc(s,o,i),L(),p(t,200,{ok:!0})}catch(s){p(t,400,{error:String(s)})}})}function bp(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=gl(s),i=o.components.map(a=>`- ${a.name}: ${a.description}`).join(`
|
|
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.
|
|
2744
|
-
|
|
2745
|
-
Source analysis found ${o.components.length} components:
|
|
2746
|
-
${i}
|
|
2747
|
-
|
|
2748
|
-
Design system: ${o.hasTailwind?"Tailwind CSS":"Custom CSS"}, ${o.cssVarCount} CSS variables
|
|
2749
|
-
Fonts: ${o.fonts.length>0?o.fonts.join(", "):"System fonts"}
|
|
2750
|
-
Interactions: ${o.interactions.join(", ")}
|
|
2751
|
-
|
|
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 Sp(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?dc(n.themePath,o,50):cc(n.themePath,50);p(t,200,{available:!0,commits:i,filtered:!!o})}function vp(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=mc(s.themePath,i,o,a);if(!l.success){p(t,500,{error:l.error||"Rollback failed"});return}Uc()}else{let r=uc(s.themePath,o);if(!r.success){p(t,500,{error:r.error||"Rollback failed"});return}Hc()}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 xp=N(()=>{"use strict";y();Xe();Ce();_o();ii();mo();Pn()});import{writeFileSync as wS,mkdirSync as Cp}from"fs";import{join as yi}from"path";import{randomUUID as CS}from"crypto";function kp(e){let t=e.match(kS);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 Si(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 wa(e,t){for(let n=0;;n++)try{return await e()}catch(s){if(!(s.status===429)||n>=wp.length)throw s;let r=wp[n];M.warn("figma",`Rate limited (429), attempt ${n+1} \u2014 waiting ${r}s`),t&&t(`Figma rate limited \u2014 retrying in ${r}s...`),await new Promise(a=>setTimeout(a,r*1e3))}}function gn(e,t,n=0){if(t(e,n),e.children)for(let s of e.children)gn(s,t,n+1)}function Tp(e,t){if(e.id===t)return e;if(e.children)for(let n of e.children){let s=Tp(n,t);if(s)return s}return null}function AS(e,t){if(t){let s=Tp(e,t);if(!s)return[];if(s.type==="FRAME"||s.type==="COMPONENT"||s.type==="COMPONENT_SET"){let o=(s.children||[]).filter(i=>xa.has(i.type));return o.length>0?o:[s]}return s.children?s.children.filter(o=>xa.has(o.type)):[]}let n=e.children?.[0];return n?.children?n.children.filter(s=>xa.has(s.type)):[]}function bi(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 _S(e){let t=new Map;for(let n of e)gn(n,s=>{if(s.fills){for(let o of s.fills)if(o.type==="SOLID"&&o.color){let i=bi(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=bi(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 $S(e){let t=new Map;for(let n of e)gn(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 ES(e){let t=[],n=new Set;for(let s of e)gn(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 MS(e){let t=[],n=new Set;for(let s of e)gn(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 IS(e,t){let n=[];return gn(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 PS(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 NS(e){if(e.fills){for(let t of e.fills)if(t.type==="SOLID"&&t.color)return bi(t.color)}if(e.backgroundColor)return bi(e.backgroundColor)}function RS(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:IS(t,t.name),children:(t.children||[]).slice(0,20).map(PS),backgroundColor:NS(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 OS(e){let t=[];for(let n of e)gn(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 Ap(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());wS(t,s)}async function FS(e,t,n,s,o){if(t.length===0)return new Map;Cp(s,{recursive:!0});let r=t.map(c=>c.id).join(",");o&&o("Exporting frame screenshots...");let a=await wa(()=>Si(`/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=yi(s,`frame-${u}.png`);try{await Ap(d,m),l.set(c,m),M.info("figma",`Downloaded frame screenshot: ${m}`)}catch(g){M.warn("figma",`Failed to download frame ${c}: ${g}`)}}return l}async function DS(e,t,n,s,o){if(t.length===0)return[];Cp(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 wa(()=>Si(`/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()}-${CS().slice(0,6)}.png`,f=yi(s,h);try{await Ap(m,f),r.push({name:u.name,localPath:f,nodeId:u.nodeId,format:"png"}),M.info("figma",`Downloaded asset: ${h}`)}catch(b){M.warn("figma",`Failed to download image ${u.name}: ${b}`)}}}return r}async function _p(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 wa(()=>Si(i,n),o);M.info("figma",`Fetched file: ${r.name}`);let a=AS(r.document,t);if(a.length===0)throw new Error("No frames found in the Figma file. The file may be empty or structured differently.");M.info("figma",`Found ${a.length} top-level frames`),o&&o(`Found ${a.length} sections. Extracting design tokens...`);let l={colors:_S(a),typography:$S(a),spacing:ES(a),effects:MS(a)};M.info("figma","Design tokens extracted",{colors:l.colors.length,typography:l.typography.length,spacing:l.spacing.length,effects:l.effects.length}),o&&o("Mapping page structure...");let c=RS(a),d=yi(s,".vibespot","figma-frames"),u=await FS(e,a,n,d,o),m=c.map(b=>({...b,frameImagePath:u.get(b.nodeId)||""}));o&&o("Extracting image assets...");let g=OS(a),h=yi(s,"assets"),f=await DS(e,g,n,h,o);return M.info("figma",`Extraction complete: ${m.length} sections, ${f.length} assets`),{fileName:r.name,fileUrl:`https://www.figma.com/design/${e}`,designTokens:l,sections:m,assets:f}}function $p(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 Ep(e){return await Si("/v1/me",e)}var kS,TS,wp,xa,Mp=N(()=>{"use strict";y();le();kS=/figma\.com\/(?:design|file|proto)\/([a-zA-Z0-9]+)(?:\/([^?]*))?/;TS="https://api.figma.com",wp=[10,20,40,60,120];xa=new Set(["FRAME","COMPONENT","COMPONENT_SET","SECTION"])});var Fp={};Ge(Fp,{getCachedExtraction:()=>Op,handleFigmaExtractRoute:()=>ka,handleFigmaGenerateRoute:()=>Ta,handleFigmaTestTokenRoute:()=>Ca});import{randomUUID as Ip}from"crypto";import{existsSync as Pp,mkdirSync as Np,writeFileSync as jS,copyFileSync as LS}from"fs";import{join as vi,basename as JS}from"path";function Rp(){let e=Date.now();for(let[t,n]of Bs)n.expires<e&&Bs.delete(t)}function Op(e){Rp();let t=Bs.get(e);return t?(Bs.delete(e),t.extraction):null}function Ca(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 Ep(s);p(t,200,{ok:!0,user:o})}catch(o){let i=o instanceof Error?o.message:String(o);M.warn("figma",`Token test failed: ${i}`),p(t,200,{ok:!1,error:"Invalid or expired Figma token"})}})}function ka(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=kp(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-${Ip().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)}
|
|
2753
|
-
|
|
2754
|
-
`)};try{let c=await _p(i.fileKey,i.nodeId,o,a,m=>l({type:"progress",message:m})),d=Ip();Rp(),Bs.set(d,{extraction:c,expires:Date.now()+BS});let u=$p(c);l({type:"complete",ok:!0,extractionId:d,summary:u})}catch(c){let d=c instanceof Error?c.message:String(c);M.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 HS(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.occurrences-a.occurrences),i=o[0],r=o[1];i&&s.push(`- **Primary:** \`${i.hex}\` (${i.variableName||"dominant color"})`),r&&s.push(`- **Secondary:** \`${r.hex}\` (${r.variableName||"accent color"})`),s.push(""),s.push("### Full palette","");for(let a of o.slice(0,15)){let l=a.variableName?`${a.variableName}`:`${a.occurrences}\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.type}** (${i.context}): ${i.value}px`);s.push("")}if(t.effects.length>0){s.push("## Effects","");for(let o of t.effects)o.type==="shadow"?s.push(`- **Box shadow** (${o.context}): \`${o.cssValue}\``):o.type==="radius"?s.push(`- **Border radius** (${o.context}): ${o.cssValue}`):o.type==="blur"&&s.push(`- **Blur** (${o.context}): ${o.cssValue}`);s.push("")}return s.join(`
|
|
2755
|
-
`)}function Ta(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=Op(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)}
|
|
2756
|
-
|
|
2757
|
-
`)};try{l({type:"progress",message:"Generating styleguide from design tokens..."});let c=HS(r),d=vi(a.themePath,".vibespot");if(Pp(d)||Np(d,{recursive:!0}),jS(vi(d,"styleguide.md"),c),a.brandAssets||(a.brandAssets={}),a.brandAssets.styleguide=c,L(),l({type:"progress",message:"Styleguide saved."}),a.templates.length===0)Rt("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=vi(a.themePath,"assets");Np(f,{recursive:!0});let b=0;for(let S of r.assets)if(Pp(S.localPath)){let v=vi(f,JS(S.localPath));try{LS(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 Fs(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}),Wt(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});un(g,{steps:u,modules:m,stats:g.stats}),Te(),rn(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);M.error("figma",`Generate failed: ${d}`),l({type:"complete",ok:!1,error:d})}t.end()})}var Bs,BS,Aa=N(()=>{"use strict";y();Xe();ee();le();Mp();Ce();gs();hr();Pn();Kn();Kt();Bs=new Map,BS=1800*1e3});import{readdirSync as Ea,statSync as US}from"fs";import{join as q,relative as GS}from"path";function qn(e){let t=q(e,Lt);if(!x(t))return null;try{return JSON.parse(P(t))}catch{return null}}function wi(e,t){let n=q(e,Lt);B(n,JSON.stringify(t,null,2)+`
|
|
2758
|
-
`)}function Hs(e){let t=[];if(!x(e))return t.push({severity:"error",rule:"theme.path.missing",message:`Theme directory not found: ${e}`}),_a(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."}),_a(e,t,qn(e));VS(e,n,t),zS(e,n,t),YS(e,t),XS(e,t),ZS(e,t),QS(e,t);let s=qn(e);return ev(s,t),_a(e,t,s)}function _a(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 VS(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 WS)Tt(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 KS)(!(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.'}):(Tt(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."}),Tt(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."}),Tt(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=Jp(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 zS(e,t,n){let s=t.screenshot_path;if(typeof s!="string"||s.length===0)return;let o=Jp(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 YS(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=Ea(n)}catch{return}for(let i of o){if(!i.endsWith(".module"))continue;s++;let r=q(n,i);qS(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 qS(e,t,n,s){let o=$a(q(t,"meta.json")),i=mt(e,q(t,"meta.json"));o?(Tt(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)?jp(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 jp(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)";Tt(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}),!Tt(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)&&jp(i.children,t,n,s)}}function XS(e,t){let n=[],s=q(e,"css");xi(s,".css").forEach(i=>{Dp(i,n,e)});let o=q(e,"modules");if(x(o))for(let i of Us(o)){if(!i.endsWith(".module"))continue;let r=q(o,i);["module.css","module.html"].forEach(a=>{let l=q(r,a);x(l)&&Dp(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 Dp(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 ZS(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");xi(o,".css").forEach(a=>s.push(a));let i=q(e,"js");xi(i,".js").forEach(a=>s.push(a));let r=q(e,"modules");if(x(r))for(let a of Us(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 QS(e,t){let n=q(e,"modules");if(x(n))for(let s of Us(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 ev(e,t){if(!e){t.push({severity:"warning",rule:"marketplace.json.missing",file:Lt,message:"marketplace.json sidecar not found",fix:"Run `vibespot marketplace edit` (CLI) or open the Marketplace panel in the editor to fill in listing details."});return}e.category?Zt.includes(e.category)||t.push({severity:"warning",rule:"marketplace.json.category.unknown",file:Lt,message:`marketplace.json category "${e.category}" is not a recognized HubSpot Marketplace category`,fix:`Use one of: ${Zt.join(", ")}.`}):t.push({severity:"warning",rule:"marketplace.json.category.missing",file:Lt,message:"marketplace.json has no category",fix:`Pick one of: ${Zt.join(", ")}.`}),(!e.description||e.description.trim().length<40)&&t.push({severity:"warning",rule:"marketplace.json.description.short",file:Lt,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:Lt,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:Lt,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:Lt,message:`marketplace.json has ${n} features but HubSpot allows at most 5`,fix:"Trim the features list to 5 or fewer entries."})}function Ci(e){let t=[],n=[],s=q(e,"modules");if(x(s))for(let i of Us(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));Tt(d,"label")||(d.label=Bp(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=Lp(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=tv(e);for(let i of o)t.push(`${i}: stripped external CDN reference(s)`);return{applied:t,skipped:n}}function tv(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)))}xi(q(e,"css"),".css").forEach(r);let l=q(e,"modules");if(x(l))for(let c of Us(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 Lp(e){let t=0;for(let n of e){if(typeof n!="object"||n===null)continue;let s=n;!Tt(s,"label")&&Tt(s,"name")&&(s.label=Bp(String(s.name)),t++),Array.isArray(s.children)&&(t+=Lp(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 Tt(e,t){let n=e[t];return typeof n=="string"?n.trim().length>0:Array.isArray(n)?n.length>0:n!=null&&n!==""}function Jp(e,t){let n=t.replace(/^\.?\//,"");return q(e,n)}function mt(e,t){return GS(e,t).split("\\").join("/")}function Us(e){try{return Ea(e)}catch{return[]}}function xi(e,t){if(!x(e))return[];try{let n=[];for(let s of Ea(e)){let o=q(e,s);US(o).isFile()&&s.endsWith(t)&&n.push(o)}return n}catch{return[]}}function Bp(e){return e.replace(/[-_]+/g," ").split(" ").filter(Boolean).map(t=>t.charAt(0).toUpperCase()+t.slice(1)).join(" ")}var Zt,WS,KS,Lt,Ma=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"],WS=["label","preview_path","screenshot_path","version","documentation_url","license","example_url"],KS=["enable_domain_stylesheets","is_available_for_new_content"],Lt="marketplace.json"});function Ia(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 Hp(e,t){let n=Ia(t);if(!n)return;let s=Hs(n);p(t,200,{report:s,categories:Zt})}function Up(e,t){let n=Ia(t);if(!n)return;let s=Ci(n),o=Hs(n);p(t,200,{fix:s,report:o})}function Gp(e,t,n){let s=Ia(n);if(s){if(e==="GET"){p(n,200,{metadata:qn(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};wi(s,i),p(n,200,{ok:!0,metadata:i})});return}p(n,405,{error:"Method not allowed"})}}var Wp=N(()=>{"use strict";y();Xe();Ce();Ma()});function nv(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 Kp(e,t){let n=nv(t);if(!n)return;let s=Bo(n);p(t,200,{report:s})}function Vp(e,t){let n=C();if(!n){p(t,400,{error:"No active theme. Open or fetch a theme first."});return}let s=Dn(n.themePath),o=bs(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=Ho(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 zp=N(()=>{"use strict";y();Xe();Ce();Uo()});import{createServer as sv}from"http";import{readFileSync as Ra,existsSync as Gs}from"fs";import{join as Bt,extname as qp}from"path";import{WebSocketServer as ov,WebSocket as iv}from"ws";function Ae(e){Ti&&Ti.readyState===iv.OPEN&&Ti.send(JSON.stringify(e))}function ki(e){Ai.push(e),Ae(e)}function Jt(){Ai=[]}function Pa(e,t){return n=>{if(n.type==="module_progress"&&n.moduleFiles){let{moduleFiles:s,...o}=n;ki(o)}else ki(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}),Wt(n.moduleOrder),ki({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}]}),ki({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 Na(e){let t=e.cost;if(!t||t.calls===0)return;let n=C();Ae({type:"generation_cost",cost:t,projectTotal:n?.costTotal})}function Jn(){return Zp}function _i(e){let{port:t,uiDir:n}=e;Zp=e.contentMode||"page";let s=sv((i,r)=>rv(i,r,n)),o=new ov({server:s});return o.on("connection",i=>lv(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 rv(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/")){av(o,s.pathname,e,t);return}if(s.pathname==="/preview"){let i=wr();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=Cr(i);t.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),t.end(r||"<!-- module not found -->");return}if(s.pathname.startsWith("/theme-assets/")){cv(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";Yp(i,Bt(n,"docs"),e,t);return}Yp(s.pathname,n,e,t)}function av(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":mp(e,s);break;case"/api/modules":pp(e,n,s);break;case"/api/modules/reorder":fp(n,s);break;case"/api/modules/code":gp(n,s);break;case"/api/upload":hp(s);break;case"/api/upload-files":e==="POST"?fd(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/field":yp(n,s);break;case"/api/import":bp(n,s);break;case"/api/setup":sm(s);break;case"/api/setup/create":om(n,s);break;case"/api/setup/fetch":rm(n,s);break;case"/api/setup/open":am(n,s);break;case"/api/setup/resume":lm(n,s);break;case"/api/setup/apikey":cm(n,s);break;case"/api/setup/remote-themes":e==="GET"?dm(s):p(s,405,{error:"Method not allowed"});break;case"/api/starters":e==="GET"?im(s):p(s,405,{error:"Method not allowed"});break;case"/api/settings/status":e==="GET"?bm(s):p(s,405,{error:"Method not allowed"});break;case"/api/settings/models":e==="GET"?Sm(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/settings/tools":e==="GET"?vm(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/settings/engine":e==="POST"?xm(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/settings/apikey":e==="POST"?wm(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/settings/install":e==="POST"?Cm(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/settings/hs-auth":e==="POST"?km(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/settings/gh-auth":e==="POST"?Tm(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/settings/hs-switch":e==="POST"?Am(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/settings/gh-logout":e==="POST"?_m(s):p(s,405,{error:"Method not allowed"});break;case"/api/settings/cli-auth":e==="POST"?$m(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/settings/hs-mode":e==="POST"?Em(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/settings/cli-toggle":e==="POST"?Mm(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/settings/claude-oauth/save":e==="POST"?Rm(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/settings/claude-oauth/status":e==="GET"?Om(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/settings/claude-oauth/logout":e==="POST"?Fm(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/settings":e==="POST"?Im(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/changelog":e==="GET"?p(s,200,{changelog:Wa()}):p(s,405,{error:"Method not allowed"});break;case"/api/themes":jm(e,n,s);break;case"/api/themes/switch":e==="POST"?Lm(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/themes/delete-local":e==="POST"?Jm(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/themes/rename":e==="POST"?Bm(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/themes/duplicate":e==="POST"?Hm(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/history":e==="GET"?Sp(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/rollback":e==="POST"?vp(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/dashboard":e==="GET"?Ym(s):p(s,405,{error:"Method not allowed"});break;case"/api/templates":Zm(e,n,s);break;case"/api/templates/activate":e==="POST"?Qm(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/templates/rename":e==="POST"?ep(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/templates/clone":e==="POST"?np(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/templates/reorder":e==="POST"?tp(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/module-library":e==="GET"?sp(s):p(s,405,{error:"Method not allowed"});break;case"/api/brand-assets":ip(e,n,s);break;case"/api/brand-kit":lp(e,n,s);break;case"/api/fonts":e==="GET"?ap(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/brand-assets/extract":e==="POST"?cp(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/brand-assets/import-reference":e==="POST"?dp(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/download-zip":e==="GET"?Xm(s):p(s,405,{error:"Method not allowed"});break;case"/api/figma/test-token":e==="POST"?Ca(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/figma/extract":e==="POST"?ka(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/figma/generate":e==="POST"?Ta(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/plan/edit":e==="POST"?Ru(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/plan/discard":e==="POST"?Ou(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/plan/templates":e==="GET"?Fu(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/plan/template":e==="POST"?Du(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/marketplace/check":e==="GET"?Hp(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/marketplace/fix":e==="POST"?Up(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/marketplace/listing":Gp(e,n,s);break;case"/api/inverse/analyze":e==="GET"?Kp(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/inverse/apply-tokens":e==="POST"?Vp(n,s):p(s,405,{error:"Method not allowed"});break;default:t.startsWith("/api/settings/job/")&&e==="GET"?Pm(t,s):t.match(/^\/api\/templates\/[^/]+\/add-module$/)&&e==="POST"?op(t,n,s):p(s,404,{error:"Not found"})}}function lv(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(ia()){lt("user",o),L();try{e.send(JSON.stringify({type:"stream_status",content:"Planning..."}));let a="",l=await oa(o,d=>{a+=d,e.send(JSON.stringify({type:"stream",content:d}))},i),c=Lu(l||a);c.plan&&(ni(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=ra();r.needsPrompt&&e.send(JSON.stringify({type:"agentic_prompt"}));try{if(r.useAgentic){Jt();let l=[],c=[],d=await ei(o,Pa(l,c),i);un(d,{steps:l,modules:c,stats:d.stats,cost:d.cost}),Na(d)}else na(l=>{Ae({type:"parse_warning",message:l})}),await Os(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=ir(a.themePath,l.id,o,d)}else c=rn(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}))})}Jt();{let l=C();l&&r.useAgentic&&!l.brandAssets?.styleguide&&!l.brandAssets?.brandvoice&&!l.brandAssets?.themeContext&&Ae({type:"suggest_brand_extraction"})}}catch(a){Jt(),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(()=>(Aa(),Fp)),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(()=>(rs(),fl)),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),On(S,i),L()}Ae({type:"figma_import_started",fileName:a.fileName}),Jt();let c=[],d=[],u=await Fs(a,i,Pa(c,d));un(u,{steps:c,modules:d,stats:u.stats,cost:u.cost}),Na(u),Te(),rn(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}))})}Jt()}catch(l){Jt(),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}=Wn(i),{buildPreviewHtml:c}=await Promise.resolve().then(()=>(ws(),Wo)),d=c();if(!d||d.length<50)return;let{extractThemeContext:u}=await Promise.resolve().then(()=>(ui(),di)),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=Bt(o.themePath,".vibespot");Gs(f)||g(f,{recursive:!0}),h(Bt(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(),Ls)),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=Bt(o.themePath,".vibespot");Gs(S)||g(S,{recursive:!0}),h(Bt(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=Ao(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}
|
|
2761
|
-
`}))},onFileComplete:d=>{e.send(JSON.stringify({type:"upload_output",chunk:` \u2713 ${d}
|
|
2762
|
-
`}))},onFileError:(d,u)=>{e.send(JSON.stringify({type:"upload_output",chunk:` \u2717 ${d}: ${u.message}
|
|
2763
|
-
`}))},onProgress:(d,u)=>{e.send(JSON.stringify({type:"upload_progress",completed:d,total:u}))}});if(c.success){let d=Ht();e.send(JSON.stringify({type:"upload_complete",output:`Uploaded ${c.uploaded} files`,portalId:d?.portalId||"",dataCenter:d?.dataCenter||"na1",themeName:o.themeName,contentMode:Jn()}))}else{let d=ko(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=oi(`hs cms upload "${o.themePath}" "${o.themeName}"`,"Uploading to HubSpot",{cwd:Bt(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}))};Hu(l,c);let d=setInterval(()=>{let u=si(l);if(!(!u||u.status==="running"))if(clearInterval(d),Uu(l,c),u.status==="completed"){let m=ht(),g=m.portalId?ts(m.portalId):"na1";e.send(JSON.stringify({type:"upload_complete",output:u.output,portalId:m.portalId||"",dataCenter:g,themeName:o.themeName,contentMode:Jn()}))}else{let m=To(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.
|
|
2765
|
-
|
|
2766
|
-
IMPORTANT: Be verbose in your response. For each error:
|
|
2767
|
-
1. State exactly which file has the problem and what the error is
|
|
2768
|
-
2. Explain WHY this error occurs (e.g. "HubSpot doesn't support textarea field type" or "field name 'name' is reserved in HubSpot modules")
|
|
2769
|
-
3. Describe the specific fix you're applying (e.g. "Changing field type from textarea to text" or "Renaming field from 'name' to 'item_name'")
|
|
2770
|
-
4. Apply the fix to the module files
|
|
2771
|
-
|
|
2772
|
-
CRITICAL: After fixing the reported errors, scan ALL other module files in the theme for the same issues. For example, if you fix "name" \u2192 "item_name" in one module, check every other module's fields.json for the same problem. Fix all occurrences, not just the ones in the error log.
|
|
2629
|
+
[Attached document: ${k.originalName}]
|
|
2630
|
+
${k.extractedText}`);let v=await c(r,i,a,{systemPrompt:h,messages:[{role:"user",content:S}],maxTokens:8e3,onChunk:t,enableWebSearch:!!o.webSearch});return v.type==="text"?v.text:JSON.stringify(v.data)}function tl(){return!!$().planMode}function nl(){let e=$(),t=e.aiEngine||Xa();return zs(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 Va,Ut,Rr,qa,os=j(()=>{"use strict";y();te();me();Sr();re();jo();rr();$t();va();Da();Ua();Qn();Ue();Va=null;Ut=new Set;Rr=new Map;qa=new Set});import{writeFileSync as fw,mkdirSync as Gg}from"fs";import{join as Wr}from"path";import{randomUUID as hw}from"crypto";function Wg(e){let t;try{t=new URL(e)}catch{return null}if(t.protocol!=="https:"||!bw.has(t.hostname.toLowerCase()))return null;let n=t.pathname.match(yw);if(!n)return null;let s=n[1],o=n[2]?decodeURIComponent(n[2].replace(/-/g," ")):void 0,r,i=t.searchParams.get("node-id");return i&&(r=i.replace(/-/g,":"),!/^[a-zA-Z0-9:]+$/.test(r))?null:{fileKey:s,nodeId:r,fileName:o}}function Kg(e){return e.map(t=>encodeURIComponent(t)).join(",")}async function Vr(e,t){let n=await fetch(`${vw}${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 ll(e,t){for(let n=0;;n++)try{return await e()}catch(s){if(!(s.status===429)||n>=Ug.length)throw s;let i=Ug[n];A.warn("figma",`Rate limited (429), attempt ${n+1} \u2014 waiting ${i}s`),t&&t(`Figma rate limited \u2014 retrying in ${i}s...`),await new Promise(a=>setTimeout(a,i*1e3))}}function Cn(e,t,n=0){if(t(e,n),e.children)for(let s of e.children)Cn(s,t,n+1)}function Vg(e,t){if(e.id===t)return e;if(e.children)for(let n of e.children){let s=Vg(n,t);if(s)return s}return null}function xw(e,t){if(t){let s=Vg(e,t);if(!s)return[];if(s.type==="FRAME"||s.type==="COMPONENT"||s.type==="COMPONENT_SET"){let o=(s.children||[]).filter(r=>al.has(r.type));return o.length>0?o:[s]}return s.children?s.children.filter(o=>al.has(o.type)):[]}let n=e.children?.[0];return n?.children?n.children.filter(s=>al.has(s.type)):[]}function Kr(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 ww(e){let t=new Map;for(let n of e)Cn(n,s=>{if(s.fills){for(let o of s.fills)if(o.type==="SOLID"&&o.color){let r=Kr(o.color),i=t.get(r),a=s.type==="TEXT",l=a?"text":"fill";i?(i.occurrences++,a&&i.usage!=="text"&&(i.usage="text")):t.set(r,{hex:r,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 r=Kr(o.color),i=t.get(r);i?i.occurrences++:t.set(r,{hex:r,opacity:1,occurrences:1,usage:"border"})}}});return[...t.values()].sort((n,s)=>s.occurrences-n.occurrences)}function kw(e){let t=new Map;for(let n of e)Cn(n,s=>{if(s.type!=="TEXT"||!s.style)return;let o=s.style,r=o.fontSize||16,i=o.fontWeight||400,a=o.lineHeightPx?Math.round(o.lineHeightPx/r*100)/100:1.5,l=o.letterSpacing||0,c=o.fontFamily||"sans-serif",d="body";r>=32?d="heading":r>=20?d="subheading":r<=12?d="caption":i>=600&&r<=14&&(d="label");let u=`${c}-${r}-${i}`,p=t.get(u);p?p.occurrences++:t.set(u,{fontFamily:c,fontSize:r,fontWeight:i,lineHeight:a,letterSpacing:l,role:d,occurrences:1})});return[...t.values()].sort((n,s)=>s.fontSize-n.fontSize)}function Cw(e){let t=[],n=new Set;for(let s of e)Cn(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 r=o.paddingTop||0,i=o.paddingRight||0,a=o.paddingBottom||0,l=o.paddingLeft||0;if(r>0||i>0||a>0||l>0){let c=`pad-${r}-${i}-${a}-${l}-${o.name}`;if(!n.has(c)){n.add(c);let d=r===a&&l===i&&r===l?r:Math.max(r,i,a,l);t.push({context:`${o.name} padding`,value:d,type:"padding"})}}});return t}function Tw(e){let t=[],n=new Set;for(let s of e)Cn(s,o=>{if(o.effects){for(let r of o.effects)if(r.type==="DROP_SHADOW"&&r.color&&r.offset){let{r:i,g:a,b:l,a:c}=r.color,d=`${r.offset.x}px ${r.offset.y}px ${r.radius||0}px rgba(${Math.round(i*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 r=`${o.cornerRadius}px`;n.has(`radius-${r}`)||(n.add(`radius-${r}`),t.push({type:"radius",cssValue:r,context:o.name}))}});return t}function Aw(e,t){let n=[];return Cn(e,s=>{if(s.type!=="TEXT"||!s.characters?.trim())return;let o=s.style?.fontSize||16,r=s.style?.fontWeight||400,i="body";o>=32?i="headline":o>=20?i="subheadline":o<=12?i="caption":r>=600&&o<=16&&(i="label"),r>=600&&s.characters.length<40&&o>=14&&o<32&&(i="cta"),n.push({text:s.characters,fontSize:o,fontWeight:r,role:i,sectionName:t})}),n}function _w(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 Pw(e){if(e.fills){for(let t of e.fills)if(t.type==="SOLID"&&t.color)return Kr(t.color)}if(e.backgroundColor)return Kr(e.backgroundColor)}function Ew(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:Aw(t,t.name),children:(t.children||[]).slice(0,20).map(_w),backgroundColor:Pw(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 Iw(e){let t=[];for(let n of e)Cn(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}function Mw(e){let t;try{t=new URL(e)}catch{return!1}return t.protocol==="https:"&&Sw.has(t.hostname.toLowerCase())}async function zg(e,t){if(!Mw(e))throw new Error("Figma image download URL is not on the allowed Figma CDN host list");let n=await fetch(e,{redirect:"manual"});if(!n.ok)throw new Error(`Failed to download image: ${n.status}`);let s=Number(n.headers.get("content-length")||"0");if(Number.isFinite(s)&&s>Gr)throw new Error(`Figma image download exceeds ${Gr} bytes`);let o=n.headers.get("content-type")||"";if(!o.toLowerCase().startsWith("image/"))throw new Error(`Figma image download returned non-image content: ${o||"unknown"}`);let r=Buffer.from(await n.arrayBuffer());if(r.byteLength>Gr)throw new Error(`Figma image download exceeds ${Gr} bytes`);fw(t,r)}async function $w(e,t,n,s,o){if(t.length===0)return new Map;Gg(s,{recursive:!0});let r=t.map(c=>c.id),i=Kg(r);o&&o("Exporting frame screenshots...");let a=await ll(()=>Vr(`/v1/images/${e}?ids=${i}&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,"-"),p=Wr(s,`frame-${u}.png`);try{await zg(d,p),l.set(c,p),A.info("figma",`Downloaded frame screenshot: ${p}`)}catch(g){A.warn("figma",`Failed to download frame ${c}: ${g}`)}}return l}async function Rw(e,t,n,s,o){if(t.length===0)return[];Gg(s,{recursive:!0});let r=50,i=[];for(let a=0;a<t.length;a+=r){let l=t.slice(a,a+r),c=Kg(l.map(u=>u.nodeId));o&&o(`Exporting images (${a+1}-${Math.min(a+r,t.length)} of ${t.length})...`);let d=await ll(()=>Vr(`/v1/images/${e}?ids=${c}&format=png&scale=2`,n),o);for(let u of l){let p=d.images[u.nodeId];if(!p)continue;let f=`${u.name.replace(/[^a-zA-Z0-9-_]/g,"-").toLowerCase()}-${hw().slice(0,6)}.png`,h=Wr(s,f);try{await zg(p,h),i.push({name:u.name,localPath:h,nodeId:u.nodeId,format:"png"}),A.info("figma",`Downloaded asset: ${f}`)}catch(b){A.warn("figma",`Failed to download image ${u.name}: ${b}`)}}}return i}async function qg(e,t,n,s,o){o&&o("Fetching Figma file...");let r=t?`/v1/files/${e}?ids=${encodeURIComponent(t)}&geometry=paths`:`/v1/files/${e}?geometry=paths`,i=await ll(()=>Vr(r,n),o);A.info("figma",`Fetched file: ${i.name}`);let a=xw(i.document,t);if(a.length===0)throw new Error("No frames found in the Figma file. The file may be empty or structured differently.");A.info("figma",`Found ${a.length} top-level frames`),o&&o(`Found ${a.length} sections. Extracting design tokens...`);let l={colors:ww(a),typography:kw(a),spacing:Cw(a),effects:Tw(a)};A.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=Ew(a),d=Wr(s,".vibespot","figma-frames"),u=await $w(e,a,n,d,o),p=c.map(b=>({...b,frameImagePath:u.get(b.nodeId)||""}));o&&o("Extracting image assets...");let g=Iw(a),f=Wr(s,"assets"),h=await Rw(e,g,n,f,o);return A.info("figma",`Extraction complete: ${p.length} sections, ${h.length} assets`),{fileName:i.name,fileUrl:`https://www.figma.com/design/${e}`,designTokens:l,sections:p,assets:h}}function Yg(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 Xg(e){return await Vr("/v1/me",e)}var yw,bw,Sw,Gr,vw,Ug,al,Zg=j(()=>{"use strict";y();re();yw=/^\/(?:design|file|proto)\/([a-zA-Z0-9]+)(?:\/([^?]*))?/,bw=new Set(["figma.com","www.figma.com"]),Sw=new Set(["s3-alpha.figma.com","s3-alpha-sig.figma.com","figma-alpha-api.s3.amazonaws.com","figma-alpha-api.s3.us-west-2.amazonaws.com"]),Gr=25*1024*1024;vw="https://api.figma.com",Ug=[10,20,40,60,120];al=new Set(["FRAME","COMPONENT","COMPONENT_SET","SECTION"])});var of={};Ve(of,{getCachedExtraction:()=>sf,handleFigmaExtractRoute:()=>dl,handleFigmaGenerateRoute:()=>ul,handleFigmaTestTokenRoute:()=>cl});import{randomUUID as Qg}from"crypto";import{existsSync as ef,mkdirSync as tf,writeFileSync as Nw,copyFileSync as Ow}from"fs";import{join as zr,basename as Fw}from"path";function nf(){let e=Date.now();for(let[t,n]of io)n.expires<e&&io.delete(t)}function sf(e){nf();let t=io.get(e);return t?(io.delete(e),t.extraction):null}function cl(e,t){Ze(e,t,async n=>{let s=n.token||$().figmaToken;if(!s){m(t,400,{ok:!1,error:"No Figma token provided"});return}try{let o=await Xg(s);m(t,200,{ok:!0,user:o})}catch(o){let r=N(o);A.warn("figma",`Token test failed: ${r}`),m(t,200,{ok:!1,error:"Invalid or expired Figma token"})}})}function dl(e,t){Ze(e,t,async n=>{let s=n.url;if(!s){m(t,400,{error:"Missing 'url' field"});return}let o=n.token||$().figmaToken;if(!o){m(t,400,{error:"No Figma token configured. Add one in Settings."});return}let r=Wg(s);if(!r){m(t,400,{error:"Not a valid Figma URL. Expected: figma.com/design/<key>/..."});return}let a=x()?.themePath||`/tmp/vibespot-figma-${Qg().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)}
|
|
2773
2631
|
|
|
2774
|
-
|
|
2632
|
+
`)};try{let c=await qg(r.fileKey,r.nodeId,o,a,p=>l({type:"progress",message:p})),d=Qg();nf(),io.set(d,{extraction:c,expires:Date.now()+Dw});let u=Yg(c);l({type:"complete",ok:!0,extractionId:d,summary:u})}catch(c){let d=N(c);A.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 jw(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.occurrences-a.occurrences),r=o[0],i=o[1];r&&s.push(`- **Primary:** \`${r.hex}\` (${r.variableName||"dominant color"})`),i&&s.push(`- **Secondary:** \`${i.hex}\` (${i.variableName||"accent color"})`),s.push(""),s.push("### Full palette","");for(let a of o.slice(0,15)){let l=a.variableName?`${a.variableName}`:`${a.occurrences}\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(i=>i.fontFamily))];s.push(`**Font families:** ${o.join(", ")}`,""),s.push("| Role | Family | Size | Weight |"),s.push("|------|--------|------|--------|");let r=new Set;for(let i of t.typography){let a=`${i.role}-${i.fontSize}-${i.fontWeight}`;r.has(a)||(r.add(a),s.push(`| ${i.role} | ${i.fontFamily} | ${i.fontSize}px | ${i.fontWeight} |`))}s.push("")}if(t.spacing.length>0){s.push("## Spacing","");let o=[...new Set(t.spacing.map(r=>r.value))].sort((r,i)=>r-i);s.push(`**Scale:** ${o.join("px, ")}px`,"");for(let r of t.spacing)s.push(`- **${r.type}** (${r.context}): ${r.value}px`);s.push("")}if(t.effects.length>0){s.push("## Effects","");for(let o of t.effects)o.type==="shadow"?s.push(`- **Box shadow** (${o.context}): \`${o.cssValue}\``):o.type==="radius"?s.push(`- **Border radius** (${o.context}): ${o.cssValue}`):o.type==="blur"&&s.push(`- **Blur** (${o.context}): ${o.cssValue}`);s.push("")}return s.join(`
|
|
2633
|
+
`)}function ul(e,t){Ze(e,t,async n=>{let s=n.extractionId,o=n.themeName,r=n.useAssets!==!1;if(!s||!o){m(t,400,{error:"Missing extractionId or themeName"});return}let i=sf(s);if(!i){m(t,400,{error:"Extraction expired or not found. Please re-extract."});return}let a=x();if(!a){m(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)}
|
|
2775
2634
|
|
|
2776
|
-
|
|
2777
|
-
|
|
2635
|
+
`)};try{l({type:"progress",message:"Generating styleguide from design tokens..."});let c=jw(i),d=zr(a.themePath,".vibespot");if(ef(d)||tf(d,{recursive:!0}),Nw(zr(d,"styleguide.md"),c),a.brandAssets||(a.brandAssets={}),a.brandAssets.styleguide=c,D(),l({type:"progress",message:"Styleguide saved."}),a.templates.length===0)jt("landing_page","Landing Page");else{a.modules=[],a.moduleOrder=[],a.sharedCss="",a.sharedJs="";let h=a.templates.find(b=>b.id===a.activeTemplateId);h&&(h.modules=[],h.moduleOrder=[],h.sharedCss="",h.sharedJs="")}if(D(),r&&i.assets.length>0){let h=zr(a.themePath,"assets");tf(h,{recursive:!0});let b=0;for(let S of i.assets)if(ef(S.localPath)){let v=zr(h,Fw(S.localPath));try{Ow(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=[],p=[],g=await ro(i,o,h=>{if(h.type==="agent_step")u.push({step:h.step,label:h.label}),l({type:"progress",message:`${h.label}...`});else if(h.type==="agent_decision"){let b=u[u.length-1];b&&(b.decisions||(b.decisions=[]),b.decisions.push(h.decision)),l({type:"progress",message:` ${h.decision}`})}else h.type==="design_system_ready"?Ge({sharedCss:h.sharedCss,sharedJs:h.sharedJs}):h.type==="blueprint_ready"?(Ge({sharedCss:h.sharedCss,sharedJs:h.sharedJs}),Yt(h.moduleOrder),l({type:"progress",message:`Planned ${h.moduleOrder.length} modules`})):h.type==="module_progress"&&(h.status==="generating"?l({type:"progress",message:`Generating module: ${h.module}`}):h.status==="complete"&&h.moduleFiles?(Ge({modules:[{moduleName:h.module,fieldsJson:h.moduleFiles.fieldsJson,metaJson:h.moduleFiles.metaJson,moduleHtml:h.moduleFiles.moduleHtml,moduleCss:h.moduleFiles.moduleCss,moduleJs:h.moduleFiles.moduleJs}]}),p.push({name:h.module,status:"complete"}),l({type:"progress",message:`Module complete: ${h.module}`})):h.status==="failed"&&(p.push({name:h.module,status:"failed"}),l({type:"progress",message:`Module failed: ${h.module}`})))},{useAssets:r});xn(g,{steps:u,modules:p,stats:g.stats}),Ae(),pn(a.themePath,`Figma import: ${i.fileName}`);let f=pe().map(h=>h.moduleName);l({type:"progress",message:`Conversion complete \u2014 ${f.length} modules generated`}),l({type:"complete",ok:!0,modules:f})}catch(c){let d=N(c);A.error("figma",`Generate failed: ${d}`),l({type:"complete",ok:!1,error:d})}t.end()})}var io,Dw,pl=j(()=>{"use strict";y();At();Re();te();re();Zg();me();Ps();zi();Hn();os();Xt();io=new Map,Dw=1800*1e3});y();y();import{Command as Mk}from"commander";y();y();y();import An from"chalk";var bt={accent:"#FF7A59",accentBright:"#FF9A7A",success:"#00BDA5",info:"#0066FF",warn:"#FFB020",error:"#E23D2D",muted:"#8B8D91",vibes:"#00BDD6"},El=!!process.env.NO_COLOR;function Et(e){return El?An:An.hex(e)}var E={accent:Et(bt.accent),accentBright:Et(bt.accentBright),success:Et(bt.success),info:Et(bt.info),warn:Et(bt.warn),error:Et(bt.error),muted:Et(bt.muted),vibes:Et(bt.vibes),heading:El?An.bold:An.bold.hex(bt.accent),command:Et(bt.accentBright),dim:An.dim,bold:An.bold};ae();function Pe(){let e=E.vibes,t=E.accent,n=E.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")} ${E.dim(`v${Mt()}`)}`),console.log()}y();y();on();te();$t();import{join as So}from"path";import{homedir as vo}from"os";import{readFileSync as Bl,existsSync as xo,readdirSync as gh}from"fs";var an=process.platform==="win32"?"where":"which",Jl=4e3;function gs(){let e=Se("node --version");return{name:"Node.js",found:e.success,version:e.stdout.replace(/^v/,""),path:Se(`${an} node`).stdout}}function fs(){let e=Se("git --version");return{name:"Git",found:e.success,version:e.stdout.replace("git version ",""),path:Se(`${an} git`).stdout}}function St(){let e=Se("hs --version");return{name:"HubSpot CLI",found:e.success,version:e.stdout,path:Se(`${an} hs`).stdout}}function Rn(){let e=Se("claude --version");if(!e.success)return{name:"Claude Code",found:!1,version:"",path:"",authenticated:!1,authDetail:"Not installed"};let t=So(vo(),".claude"),n=!1,s="Not signed in \u2014 run `claude` to authenticate";try{if(xo(t)){let o=gh(t);(o.some(i=>i.includes("credentials")||i.includes("auth")||i.includes("token")||i===".credentials.json")||o.length>2)&&(n=!0,s="Authenticated")}}catch{}return{name:"Claude Code",found:!0,version:e.stdout,path:Se(`${an} claude`).stdout,authenticated:n,authDetail:s}}function hs(e){try{let t=So(vo(),".hscli","config.yml");if(!xo(t))return"na1";let n=Bl(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 i=n.slice(o,o+300).match(/personalAccessKey:[\s>-]*\n\s+(\S+)/);if(!i)return"na1";if(i[1].startsWith("CiRldTE"))return"eu1"}catch{}return"na1"}function vt(){let e=Se("hs accounts list",{timeout:Jl});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 r=e.stdout.split(`
|
|
2636
|
+
`);for(let i of r){let a=i.match(/^\s*(.+?)\s+(\d{5,})\s+(.*)/);if(a&&!/Account ID/i.test(i)&&!/^-+$/.test(i.trim())&&!/^Name\s/i.test(i.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 Nn(){let e=Se("gemini --version");if(!e.success)return{name:"Gemini CLI",found:!1,version:"",path:"",authenticated:!1,authDetail:"Not installed"};let t=So(vo(),".config","gcloud","application_default_credentials.json"),n=xo(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:Se(`${an} gemini`).stdout,authenticated:o,authDetail:o?"Authenticated":"Run `gemini` to sign in with Google"}}function On(){let e=Se("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 r=So(vo(),".codex","auth.json");xo(r)&&(n=Bl(r,"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:Se(`${an} codex`).stdout,authenticated:s,authDetail:o}}function wo(){let e=Se("gh --version");return{name:"GitHub CLI",found:e.success,version:e.stdout.split(`
|
|
2637
|
+
`)[0]?.replace("gh version ","").split(" ")[0]||"",path:Se(`${an} gh`).stdout}}function ko(){let e=Se("gh auth status 2>&1",{timeout:Jl});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 Hl(){return!!process.env.ANTHROPIC_API_KEY}function Co(e){return parseInt(e.split(".")[0],10)>=18}function Ul(e){let t=parseInt(e.split(".")[0],10);return!isNaN(t)&&t>=8}function fh(){let e=$(),t=e.hubspotUploadMode||"api",n=e.hubspotAccounts||[],s=n.map(r=>({name:r.portalName,portalId:r.portalId,authType:"personalaccesskey",isDefault:r.portalId===(e.activeHubSpotAccount||n[0]?.portalId)})),o=Vt();return{authenticated:!!o,portalName:o?.portalName||"",portalId:o?.portalId||"",dataCenter:o?o.dataCenter:"na1",accounts:s,uploadMode:t}}var $n={name:"",found:!1,version:"",path:"",authenticated:!1,authDetail:"Disabled"};function Mn(e,...t){if(e)return{configured:!0,masked:fo(e),source:"config"};for(let n of t)if(process.env[n])return{configured:!0,masked:fo(process.env[n]),source:"env"};return{configured:!1,masked:"",source:null}}function Ti(e){return{anthropic:Mn(e.anthropicApiKey,"ANTHROPIC_API_KEY"),openai:Mn(e.openaiApiKey,"OPENAI_API_KEY"),gemini:Mn(e.geminiApiKey,"GEMINI_API_KEY","GOOGLE_AI_API_KEY"),langdock:Mn(e.langdockApiKey,"LANGDOCK_API_KEY"),langfusePublic:Mn(e.langfusePublicKey,"LANGFUSE_PUBLIC_KEY"),langfuseSecret:Mn(e.langfuseSecretKey,"LANGFUSE_SECRET_KEY")}}function Ai(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 _i(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=St(),s=n.found?vt():{authenticated:!1,portalName:"",portalId:"",accounts:[]},o=s.portalId?hs(s.portalId):"na1";return{...n,...s,dataCenter:o,uploadMode:"cli"}}return{name:"HubSpot API",found:!0,version:"v3",path:"",...fh()}}function Gl(){let e=$(),t=e.hubspotUploadMode||"api",n=Ti(e),s={authenticated:Qe(),expiresAt:rn()?.expiresAt},o=i=>({name:i,found:!1,version:"",path:"",authenticated:!1,authDetail:"Not scanned"}),r=i=>({name:i,found:!1,version:"",path:""});return{tools:{node:r("Node.js"),git:r("Git"),hubspot:_i(t,!1),github:{...r("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:Ai({apiKeys:n,claudeOAuth:s.authenticated,claudeCode:rt("claude-code"),geminiCli:rt("gemini-cli"),codexCli:rt("codex-cli")}),enabledCLITools:e.enabledCLITools||[],scanned:!1}}function Wl(){let e=$(),t=Ti(e),n={authenticated:Qe(),expiresAt:rn()?.expiresAt},s=rt("claude-code")?Rn():{...$n,name:"Claude Code"},o=rt("gemini-cli")?Nn():{...$n,name:"Gemini CLI"},r=rt("codex-cli")?On():{...$n,name:"OpenAI Codex CLI"};return{claudeCode:s,geminiCli:o,codexCli:r,claudeOAuth:n,availableEngines:Ai({apiKeys:t,claudeOAuth:n.authenticated,claudeCode:s.found&&s.authenticated,geminiCli:o.found&&o.authenticated,codexCli:r.found&&r.authenticated})}}function Kl(){let t=$().hubspotUploadMode||"api",n=wo(),s=n.found?ko():{authenticated:!1,username:""};return{github:{...n,...s},hubspot:_i(t,!0)}}function To(){let e=$(),t=e.hubspotUploadMode||"api",n=gs(),s=fs(),o=_i(t,!0),r=wo(),i=r.found?ko():{authenticated:!1,username:""},a={authenticated:Qe(),expiresAt:rn()?.expiresAt},l=rt("claude-code")?Rn():{...$n,name:"Claude Code"},c=rt("gemini-cli")?Nn():{...$n,name:"Gemini CLI"},d=rt("codex-cli")?On():{...$n,name:"OpenAI Codex CLI"},u=Ti(e);return{tools:{node:n,git:s,hubspot:o,github:{...r,...i},claudeCode:l,claudeOAuth:a,geminiCli:c,codexCli:d},apiKeys:u,activeEngine:e.aiEngine||null,availableEngines:Ai({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}}$t();on();te();cn();y();import*as le from"@clack/prompts";function Ei(e){le.isCancel(e)&&(le.cancel(E.muted("Operation cancelled.")),process.exit(0))}async function fe(e){le.intro(E.heading(e))}async function he(e){le.outro(E.success(e))}async function xt(e,t){le.note(e,t?E.heading(t):void 0)}async function ve(e){let t=e.validate,n=await le.text({message:E.accent(e.message),placeholder:e.placeholder,defaultValue:e.defaultValue,validate:t?s=>t(s??""):void 0});return Ei(n),n}async function Ee(e){let t=await le.confirm({message:E.accent(e.message),initialValue:e.initialValue??!0});return Ei(t),t}async function Nt(e){let t=await le.select({message:E.accent(e.message),options:e.options});return Ei(t),t}async function je(){let e=le.spinner();return{start:t=>e.start(E.muted(t)),stop:t=>e.stop(E.success(t)),message:t=>e.message(E.muted(t))}}function B(e){le.log.info(e)}function K(e){le.log.success(E.success(e))}function se(e){le.log.warn(E.warn(e))}function Z(e){le.log.error(E.error(e))}async function Eo(){await fe("Checking your environment");let e=gs();e.found||(Z("Node.js not found. Install it from https://nodejs.org"),process.exit(1)),Co(e.version)||(Z(`Node.js ${e.version} is too old. Version 18+ required. Update at https://nodejs.org`),process.exit(1)),K(`Node.js v${e.version}`);let t=fs();t.found||(Z("Git not found. Install it from https://git-scm.com"),process.exit(1)),K(`Git ${t.version}`);let n=$(),s=n.hubspotUploadMode!=="cli",o="",r="";if(s){let b=Je(),S=Vt();if(b)o=S?.portalId||"",r=S?.portalName||"",K(`HubSpot${r?`: ${r}`:""}${o?` (${o})`:""} \u2014 API mode`);else{se("No HubSpot account connected"),await xt(`You need a Personal Access Key to deploy themes.
|
|
2778
2638
|
Create one at: https://app.hubspot.com/l/personal-access-key
|
|
2779
|
-
Make sure the Content scope is enabled.`,"HubSpot connection required");let v=await
|
|
2639
|
+
Make sure the Content scope is enabled.`,"HubSpot connection required");let v=await ve({message:"Paste your Personal Access Key:",placeholder:"pat-na1-...",validate:_=>_.trim()?void 0:"Key is required"}),k=await je();k.start("Validating key...");try{let _=await _o(v);us(v,_.portalId,_.portalName,_.dataCenter),b=v,o=_.portalId,r=_.portalName,k.stop(`Connected to ${_.portalName} (${_.portalId})`)}catch(_){k.stop("Validation failed"),Z(`Invalid key: ${_ instanceof Error?_.message:String(_)}`),process.exit(1)}}}else{let b=St();if(b.found)K(`HubSpot CLI v${b.version}`);else{se("HubSpot CLI not found"),await Ee({message:"Install HubSpot CLI globally?"})||(Z("HubSpot CLI is required in CLI mode. Install: npm install -g @hubspot/cli"),process.exit(1));let k=await je();k.start("Installing HubSpot CLI..."),Se("npm install -g @hubspot/cli").success||(k.stop("Failed"),Z("Try: npm install -g @hubspot/cli"),process.exit(1)),b=St(),k.stop(`HubSpot CLI v${b.version} installed`)}let S=vt();if(S.authenticated)K(`HubSpot portal${S.portalName?`: ${S.portalName}`:""} (ID: ${S.portalId})`);else{se("HubSpot not authenticated"),await Ee({message:"Run `hs init` now?"})||(Z("Run `hs init` manually."),process.exit(1));let k=await je();k.start("Waiting for HubSpot authentication..."),Ol("hs init")||(k.stop("Authentication failed"),process.exit(1)),S=vt(),k.stop(`Connected to portal${S.portalName?`: ${S.portalName}`:""} (ID: ${S.portalId})`)}o=S.portalId,r=S.portalName}let i=Rn(),a=Nn(),l=On(),c=Hl(),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=Qe(),p,g=n.aiEngine,f=[];if(i.found&&f.push({value:"claude-code",label:"Claude Code",hint:g==="claude-code"?"last used \u2014 recommended":"uses your existing Claude subscription \u2014 recommended"}),u&&f.push({value:"claude-oauth",label:"Claude (OAuth)",hint:g==="claude-oauth"?"last used":"uses your Claude Pro/Max subscription via OAuth"}),a.found&&f.push({value:"gemini-cli",label:"Gemini CLI",hint:g==="gemini-cli"?"last used":"uses your existing Gemini setup"}),l.found&&f.push({value:"codex-cli",label:"OpenAI Codex",hint:g==="codex-cli"?"last used":"uses your existing OpenAI setup"}),c&&f.push({value:"api",label:"Anthropic API",hint:g==="api"?"last used":"uses your API key"}),g&&f.sort((b,S)=>b.value===g?-1:S.value===g?1:0),f.length===1)p=f[0].value,K(`AI engine: ${d[p]} (auto-detected)`);else if(f.length>1)p=await Nt({message:"Choose your AI engine:",options:f});else if(await xt(`You need an AI coding assistant to power the conversion.
|
|
2780
2640
|
|
|
2781
|
-
${
|
|
2641
|
+
${E.bold("Option 1:")} Install Claude Code ${E.muted("(recommended)")}
|
|
2782
2642
|
https://claude.ai/code
|
|
2783
2643
|
|
|
2784
|
-
${
|
|
2644
|
+
${E.bold("Option 2:")} Install Gemini CLI
|
|
2785
2645
|
https://github.com/google-gemini/gemini-cli
|
|
2786
2646
|
|
|
2787
|
-
${
|
|
2647
|
+
${E.bold("Option 3:")} Install OpenAI Codex
|
|
2788
2648
|
https://github.com/openai/codex
|
|
2789
2649
|
|
|
2790
|
-
${
|
|
2650
|
+
${E.bold("Option 4:")} Set an Anthropic API key
|
|
2791
2651
|
export ANTHROPIC_API_KEY=sk-ant-...
|
|
2792
|
-
(get one at https://console.anthropic.com)`,"AI engine required"),
|
|
2793
|
-
`,
|
|
2794
|
-
|
|
2652
|
+
(get one at https://console.anthropic.com)`,"AI engine required"),p=await Nt({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"}]}),p==="api"){let b=await ve({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 h;return p==="claude-code"&&(h=await Nt({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:p}),await he("Environment ready!"),{aiEngine:p,model:h,portalId:o,portalName:r}}y();on();ae();import{readdirSync as Ii,statSync as _h}from"fs";import{join as ye,basename as Mi,extname as Ph}from"path";function Zl(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 Ql(e){let t=[],n=[ye(e,"src/components/landing"),ye(e,"src/components/sections"),ye(e,"src/components"),ye(e,"src/pages"),ye(e,"app/components"),ye(e,"components")];for(let s of n)if(w(s))try{let o=Ii(s);for(let r of o){let i=ye(s,r);if(!_h(i).isFile())continue;let l=Ph(r);if(![".tsx",".jsx"].includes(l))continue;let c=Mi(r,l);if(c.startsWith("ui")||c==="index")continue;let d=I(i),u=Eh(c,d);t.push({name:c,path:i,description:u})}}catch{}return t}function Eh(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 ec(e){let t=[ye(e,"src/index.css"),ye(e,"src/globals.css"),ye(e,"src/app/globals.css"),ye(e,"app/globals.css")],n=0,s=[];for(let o of t){if(!w(o))continue;let r=I(o),i=r.match(/--[\w-]+:/g);i&&(n+=i.length);let a=r.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=r.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 tc(e){let t=[],n=ye(e,"src/hooks");if(w(n))try{let o=Ii(n);for(let r of o)/scroll/i.test(r)&&t.push("Scroll animations"),/intersection/i.test(r)&&t.push("Scroll animations")}catch{}let s=ye(e,"src/components/landing");if(w(s))try{let o=Ii(s);for(let r of o){if(!r.endsWith(".tsx")&&!r.endsWith(".jsx"))continue;let i=I(ye(s,r));/carousel|embla|swiper/i.test(i)&&!t.includes("Carousel")&&t.push("Carousel"),/accordion|collapsible/i.test(i)&&!t.includes("Accordion")&&t.push("Accordion"),/typing|typewriter/i.test(i)&&!t.includes("Typing animation")&&t.push("Typing animation"),/parallax|requestAnimationFrame/i.test(i)&&!t.includes("Parallax")&&t.push("Parallax")}}catch{}return t.length===0&&t.push("Scroll animations"),t}function nc(e){let t,n=!1;if(e.startsWith("http")||e.startsWith("git@")){if(!Zl(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=Mi(e.replace(/\.git$/,""))||"react-source";if(t=ye(process.cwd(),"workspace",l),!w(t)){let c=ee(["clone","--depth","1","--",e,t]);if(!c.success)throw new Error(`Failed to clone ${e}: ${c.stderr}`)}}else if(t=e,!w(t))throw new Error(`Directory not found: ${t}`);let s=Ql(t),o=w(ye(t,"tailwind.config.ts"))||w(ye(t,"tailwind.config.js")),{varCount:r,fonts:i}=ec(t),a=tc(t);return{sourceDir:t,wasCloned:n,components:s,hasTailwind:o,cssVarCount:r,fonts:i,interactions:a}}async function Io(){await fe("Source Project");let e=await ve({message:"GitHub URL or local path to your React project:",placeholder:"https://github.com/user/my-lovable-page",validate:f=>{if(!f.trim())return"Please enter a URL or path"}}),t,n=!1;if(e.startsWith("http")||e.startsWith("git@")){Zl(e)||(Z("Refusing to clone unsafe source URL. Only http(s):// and git@host:path URLs without shell metacharacters are allowed."),process.exit(1)),n=!0;let f=Mi(e.replace(/\.git$/,""))||"react-source";if(t=ye(process.cwd(),"workspace",f),w(t))K(`Using existing clone: ${E.dim(t)}`);else{let h=await je();h.start("Cloning repository..."),ee(["clone","--depth","1","--",e,t]).success||(h.stop("Clone failed"),Z(`Failed to clone ${e}. Check the URL and your access permissions.`),process.exit(1)),h.stop(`Cloned to ${E.dim(t)}`)}}else t=e,w(t)||(Z(`Directory not found: ${t}`),process.exit(1)),K(`Using local source: ${E.dim(t)}`);let s=await je();s.start("Analyzing project structure...");let o=Ql(t),r=w(ye(t,"tailwind.config.ts"))||w(ye(t,"tailwind.config.js")),{varCount:i,fonts:a}=ec(t),l=tc(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((f,h)=>` ${E.dim(`${h+1}.`)} ${E.bold(f.name)} ${E.muted(`\u2014 ${f.description}`)}`).join(`
|
|
2653
|
+
`),d=r?`Tailwind + custom CSS (${i} variables)`:`Custom CSS (${i} variables)`,u=a.length>0?a.join(", "):"System fonts",p=l.join(", ");return await xt(`${c}
|
|
2654
|
+
|
|
2655
|
+
CSS: ${d}
|
|
2656
|
+
JS: ${p}
|
|
2657
|
+
Font: ${u}`,`${o.length} components detected`),await Ee({message:"Does this look right?"})||(Z("Please adjust your source directory and try again."),process.exit(0)),await he("Source analyzed!"),{sourceDir:t,wasCloned:n,components:o,hasTailwind:r,cssVarCount:i,fonts:a,interactions:l}}y();on();import{join as Cs}from"path";y();function Dn(e){return typeof e=="string"&&e.length>0&&e.length<=200&&/^[A-Za-z0-9][A-Za-z0-9 ._-]*$/.test(e)&&!e.includes("..")}ae();te();xs();$o();async function Ro(){await fe("HubSpot Theme Setup");let e=await Nt({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=Cs(process.cwd(),"workspace");if($e(s),e==="fetch"){t=await ve({message:"What's your theme name in HubSpot?",placeholder:"My-Company-Theme",validate:u=>{if(!u.trim())return"Theme name is required";if(!Dn(u.trim()))return"Use only letters, numbers, spaces, dots, underscores, and hyphens"}}),t=t.trim(),n=Cs(s,t);let l=await je();l.start("Fetching theme from HubSpot...");let c=$(),d=Je();if(c.hubspotUploadMode==="cli"||!d)cs("hs",["cms","fetch",t,n]).success||(l.stop("Fetch failed"),Z(`Could not fetch theme "${t}". Check the name in HubSpot Design Manager.`),process.exit(1));else try{await ks(d,t,n)}catch(u){l.stop("Fetch failed"),Z(`Could not fetch theme "${t}": ${u instanceof Error?u.message:String(u)}`),process.exit(1)}l.stop(`Theme fetched: ${E.dim(n)}`)}else{t=await ve({message:"Name for your new theme:",placeholder:"my-theme",defaultValue:"my-theme"}),n=Cs(s,t);let l=await je();l.start("Creating theme...");try{vs(n,t)}catch(c){l.stop("Creation failed"),Z(`Could not create theme "${t}": ${c instanceof Error?c.message:String(c)}`),process.exit(1)}l.stop(`Theme created: ${E.dim(n)}`)}await fe("Checking theme compatibility");let o=Cs(n,"templates/layouts/base.html");w(o)||(Z(`base.html not found at ${o}. Your theme may have a different structure.`),process.exit(1)),K("base.html found");let r=I(o),i=!1;if(r.includes("template_css"))K("template_css support");else{se("Missing template_css support in base.html");let l=r.indexOf("theme-overrides.css")!==-1?r.indexOf("{{",r.lastIndexOf(`
|
|
2658
|
+
`,r.indexOf("theme-overrides.css"))):r.lastIndexOf("require_css");if(l>0){let c=r.lastIndexOf(`
|
|
2659
|
+
`,l);r=r.slice(0,c)+`
|
|
2795
2660
|
{% if template_css %}
|
|
2796
2661
|
{{ require_css(get_asset_url(template_css)) }}
|
|
2797
|
-
{% endif %}`+
|
|
2798
|
-
`,l),d=
|
|
2662
|
+
{% endif %}`+r.slice(c),i=!0}}if(r.includes("template_js"))K("template_js support");else{se("Missing template_js support in base.html");let l=r.indexOf("require_js");if(l>0){let c=r.indexOf(`
|
|
2663
|
+
`,l),d=r.indexOf(`
|
|
2799
2664
|
`,c+1),u=`
|
|
2800
2665
|
{% if template_js %}
|
|
2801
2666
|
{{ require_js(get_asset_url(template_js)) }}
|
|
2802
|
-
{% endif %}`,
|
|
2803
|
-
`)+1;
|
|
2804
|
-
`,
|
|
2805
|
-
`,
|
|
2667
|
+
{% endif %}`,p=r.indexOf("}}",l)+2+r.slice(r.indexOf("}}",l)+2).indexOf(`
|
|
2668
|
+
`)+1;r=r.slice(0,r.indexOf(`
|
|
2669
|
+
`,r.indexOf("}}",l)+2))+u+r.slice(r.indexOf(`
|
|
2670
|
+
`,r.indexOf("}}",l)+2)),i=!0}}if(i){let l=await je();l.start("Patching base.html..."),U(o,r),l.stop("base.html patched with template_css/template_js support")}let a=Cs(n,".hsignore");if(w(a)){let l=I(a);l.includes("docs/")||(U(a,l+`
|
|
2806
2671
|
docs/
|
|
2807
|
-
`),
|
|
2672
|
+
`),K("Added docs/ to .hsignore"))}else U(a,`docs/
|
|
2808
2673
|
*.md
|
|
2809
2674
|
node_modules/
|
|
2810
2675
|
.git
|
|
2811
|
-
`),
|
|
2676
|
+
`),K("Created .hsignore");return await he("Theme ready!"),{themePath:n,themeName:t}}y();import{join as st}from"path";import{readdirSync as Hs,rmSync as Ad}from"fs";y();tt();ae();import{spawn as Fh}from"child_process";import{join as ne,basename as Dh}from"path";import{readdirSync as kt,statSync as yc,writeFileSync as jh}from"fs";var Lh=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"]),Oo=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,r=t.conversionGuide||Ce();this.reported.clear(),this.moduleCount=0,this.expectedModules=0;let i=this.countSourceComponents(n),a=this.listModules(s),l=this.listDir(ne(s,"css")),c=this.listDir(ne(s,"js")),d=this.listDir(ne(s,"templates")),u=this.buildFullPrompt(n,s,r);o("convert",`Starting Claude Code (${i} source components found)...`);let p="",g="",f=setInterval(()=>{this.reportProgress(s,a,l,c,d,o)},3e3);try{await new Promise((v,k)=>{let _={...process.env};delete _.CLAUDECODE;let M=["--print","--max-turns","50","--allowedTools","Read,Glob,Grep,Write,Edit,Bash"];this.model&&M.push("--model",this.model);let R=Fh("claude",M,{cwd:s,stdio:["pipe","pipe","pipe"],env:_,shell:process.platform==="win32"});R.stdout.on("data",J=>{p+=J.toString()}),R.stderr.on("data",J=>{g+=J.toString()}),R.on("error",J=>k(new Error(`Claude Code failed to start: ${J.message}`))),R.on("close",J=>{J!==0?k(new Error(`Claude Code exited with code ${J}.
|
|
2812
2677
|
`+(g?`Stderr: ${g.slice(0,500)}
|
|
2813
|
-
`:"")+(
|
|
2814
|
-
... (truncated, full guide follows)`,"","=== CLAUDE CODE STDOUT ===",
|
|
2815
|
-
`);
|
|
2678
|
+
`:"")+(p?`Output: ${p.slice(0,500)}`:"No output"))):v()}),R.stdin.on("error",()=>{}),R.stdin.write(u),R.stdin.end(),setTimeout(()=>{R.kill(),k(new Error("Claude Code timed out after 30 minutes"))},18e5)})}finally{clearInterval(f)}let h=ne(s,"..","vibespot-conversion.log");try{let k=["=== vibeSpot Conversion Log ===",`Timestamp: ${new Date().toISOString()}`,`Source: ${n}`,`Theme: ${s}`,`Model: ${this.model||"default"}`,"","=== PROMPT SENT ===",u.slice(0,500)+`
|
|
2679
|
+
... (truncated, full guide follows)`,"","=== CLAUDE CODE STDOUT ===",p||"(empty)","","=== CLAUDE CODE STDERR ===",g||"(empty)",""].join(`
|
|
2680
|
+
`);jh(h,k,"utf-8"),o("status",`Log written to ${Dh(h)}`)}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=p.slice(0,1500)||"(no output)",k=g.slice(0,500);throw new Error(`Claude Code did not create any new module files.
|
|
2816
2681
|
|
|
2817
2682
|
This usually means the model described the conversion instead of using Write tool to create files.
|
|
2818
2683
|
|
|
@@ -2823,12 +2688,12 @@ Possible causes:
|
|
|
2823
2688
|
|
|
2824
2689
|
Source: ${t.sourceDir}
|
|
2825
2690
|
Theme: ${s}
|
|
2826
|
-
`+(
|
|
2691
|
+
`+(k?`
|
|
2827
2692
|
Stderr:
|
|
2828
|
-
${
|
|
2693
|
+
${k}
|
|
2829
2694
|
`:"")+`
|
|
2830
2695
|
Claude output:
|
|
2831
|
-
${v}`)}return b}reportProgress(t,n,s,o,i
|
|
2696
|
+
${v}`)}return b}reportProgress(t,n,s,o,r,i){let a=0,l=this.listDir(ne(t,"css"));for(let p of l){if(s.has(p)||!p.endsWith(".css"))continue;let g=`css:${p}`;this.reported.has(g)||(this.reported.add(g),i("created",`Shared CSS (${p})`),a++)}let c=this.listDir(ne(t,"js"));for(let p of c){if(o.has(p)||!p.endsWith(".js"))continue;let g=`js:${p}`;this.reported.has(g)||(this.reported.add(g),i("created",`Shared JS (${p})`),a++)}this.expectedModules===0&&(this.expectedModules=this.detectExpectedModules(t,r));let d=this.listModules(t);for(let p of d){if(n.has(p))continue;let g=`module:${p}`;if(!this.reported.has(g)){this.reported.add(g),this.moduleCount++;let f=this.expectedModules>0?`[${this.moduleCount}/${this.expectedModules}]`:`[${this.moduleCount}]`;i("created",`Module ${f}: ${p.replace(".module","")}`),a++}}let u=this.listDir(ne(t,"templates"));for(let p of u){if(r.has(p)||!p.endsWith(".html"))continue;let g=`template:${p}`;this.reported.has(g)||(this.reported.add(g),i("created",`Page template (${p})`),a++)}if(a===0)if(this.moduleCount>0){let p=this.expectedModules>0?`/${this.expectedModules}`:"";i("status",`${this.moduleCount}${p} modules created, conversion continuing...`)}else this.reported.size>0?i("status","Shared assets created, building modules..."):i("status","Claude Code is analyzing source files...")}buildFullPrompt(t,n,s){return`You are converting a React landing page to native HubSpot CMS modules.
|
|
2832
2697
|
|
|
2833
2698
|
SOURCE DIRECTORY: ${t}
|
|
2834
2699
|
THEME DIRECTORY: ${n}
|
|
@@ -2871,31 +2736,16 @@ CSS QUALITY: The converted page must visually match the original React page. Eve
|
|
|
2871
2736
|
Do NOT run hs upload \u2014 I will handle that separately.
|
|
2872
2737
|
|
|
2873
2738
|
HUBSPOT CMS RULES:
|
|
2874
|
-
${
|
|
2739
|
+
${et()}
|
|
2875
2740
|
|
|
2876
2741
|
CONVERSION GUIDE:
|
|
2877
|
-
${s}`}scanGeneratedFiles(t){let n={sharedCss:"",sharedJs:"",template:"",modules:[]},s=
|
|
2878
|
-
${
|
|
2879
|
-
|
|
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}
|
|
2881
|
-
${i}`)}return s.join(`
|
|
2882
|
-
|
|
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 Rl(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 pf}from"child_process";import{join as Ve}from"path";import{readdirSync as So,statSync as gf}from"fs";var vo=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=pf("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}.
|
|
2884
|
-
|
|
2885
|
-
INSTRUCTIONS:
|
|
2886
|
-
1. Analyze all .tsx/.jsx components in the React source
|
|
2887
|
-
2. Create a shared CSS file in css/ with design system variables, utilities, and theme-override countermeasures
|
|
2888
|
-
3. Create a shared JS file in js/ for scroll animations and interactive features
|
|
2889
|
-
4. For each visual section, create a HubSpot module in modules/ with fields.json, meta.json, module.html, module.css
|
|
2890
|
-
5. Add a styles group with "tab": "STYLE" and color pickers to each module
|
|
2891
|
-
6. Create a page template in templates/ that assembles all modules
|
|
2892
|
-
7. Make sure base.html supports template_css and template_js variables
|
|
2742
|
+
${s}`}scanGeneratedFiles(t){let n={sharedCss:"",sharedJs:"",template:"",modules:[]},s=ne(t,"css");if(w(s)){for(let a of kt(s))if(a.endsWith(".css")&&a!=="theme-overrides.css"&&a!=="main.css"&&a!=="style.css"){n.sharedCss=I(ne(s,a));break}}let o=ne(t,"js");if(w(o)){for(let a of kt(o))if(a.endsWith(".js")&&a!=="main.js"){n.sharedJs=I(ne(o,a));break}}let r=ne(t,"templates");if(w(r)){for(let a of kt(r))if(a.startsWith("lp-")&&a.endsWith(".html")){n.template=I(ne(r,a));break}if(!n.template){for(let a of kt(r))if(a.endsWith(".html")&&!Lh.has(a)&&!a.startsWith("system")){let l=I(ne(r,a));if(l.includes("dnd_area")){n.template=l;break}}}if(!n.template){for(let a of kt(r))if(a.endsWith(".html")&&!a.startsWith("system")&&a!=="base.html"){let l=I(ne(r,a));if(l.includes("dnd_area")){n.template=l;break}}}}let i=ne(t,"modules");if(w(i))for(let a of kt(i)){if(!a.endsWith(".module"))continue;let l=ne(i,a);if(!yc(l).isDirectory())continue;let c={moduleName:a.replace(".module",""),fieldsJson:"",metaJson:"",moduleHtml:"",moduleCss:""},d=ne(l,"fields.json");w(d)&&(c.fieldsJson=I(d));let u=ne(l,"meta.json");w(u)&&(c.metaJson=I(u));let p=ne(l,"module.html");w(p)&&(c.moduleHtml=I(p));let g=ne(l,"module.css");w(g)&&(c.moduleCss=I(g));let f=ne(l,"module.js");w(f)&&(c.moduleJs=I(f)),c.fieldsJson&&c.moduleHtml&&n.modules.push(c)}return n}listModules(t){let n=ne(t,"modules");return w(n)?new Set(kt(n).filter(s=>s.endsWith(".module"))):new Set}listDir(t){return w(t)?new Set(kt(t)):new Set}detectExpectedModules(t,n){let s=ne(t,"templates");if(!w(s))return 0;for(let o of kt(s))if(!n.has(o)&&!(!o.endsWith(".html")||o==="base.html"||o.startsWith("system")))try{let r=I(ne(s,o));if(r.includes("dnd_area")){let i=r.match(/dnd_module/g);return i?i.length:0}}catch{}return 0}countSourceComponents(t){let n=ne(t,"src");return w(n)?this.countComponentsRecursive(n):0}countComponentsRecursive(t){let n=0;for(let s of kt(t)){let o=ne(t,s);try{yc(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();tt();ae();Ue();un();import ry from"@anthropic-ai/sdk";import{join as de,basename as iy}from"path";import{readdirSync as Ac}from"fs";var Jo=class{client;model="claude-sonnet-4-6";constructor(t){this.client=new ry({apiKey:t||process.env.ANTHROPIC_API_KEY})}async convert(t){let{sourceDir:n,themePath:s,conversionGuide:o,onProgress:r}=t,i=pc(o),a=iy(n)||"page",l=a.toLowerCase().replace(/[^a-z0-9]/g,"-").replace(/-+/g,"-").replace(/^-|-$/g,"").slice(0,15);r("css","Analyzing design system...");let c=this.findAndReadCSS(n),d=this.findAndReadTailwind(n),u=await this.complete(i,gc(c,d,l)),p=de(s,"css",`${l}-theme.css`);U(p,u),r("css-done",`Created css/${l}-theme.css`),r("js","Creating shared JavaScript...");let g=this.findAndReadHooks(n),f=this.findInteractiveComponents(n),h=await this.complete(i,fc(g,f,l)),b=de(s,"js",`${l}-animations.js`);U(b,h),r("js-done",`Created js/${l}-animations.js`),r("modules","Building modules...");let S=this.findComponents(n),v=[];for(let R=0;R<S.length;R++){let J=S[R],O=J.name.replace(/Section$/,"").replace(/([A-Z])/g," $1").trim();r("module",`Building ${O}.module (${R+1}/${S.length})...`);let V=I(J.path),H=await this.complete(i,mc(V,O,`See css/${l}-theme.css`));try{let P=JSON.parse(H),F=typeof P.fieldsJson=="string"?P.fieldsJson:P.fieldsJson!=null?JSON.stringify(P.fieldsJson,null,2):null,z=typeof P.metaJson=="string"?P.metaJson:P.metaJson!=null?JSON.stringify(P.metaJson,null,2):null;if(!F||!z)throw new Error("Response is missing fieldsJson or metaJson");let L={moduleName:O,fieldsJson:F,metaJson:z,moduleHtml:P.moduleHtml||"",moduleCss:P.moduleCss||"",moduleJs:P.moduleJs||void 0},W=de(s,"modules",`${O}.module`);$e(W),U(de(W,"fields.json"),L.fieldsJson),U(de(W,"meta.json"),L.metaJson),U(de(W,"module.html"),L.moduleHtml),U(de(W,"module.css"),L.moduleCss),L.moduleJs&&U(de(W,"module.js"),L.moduleJs),v.push(L),r("module-done",`${O}.module (${this.countFiles(L)} files)`)}catch{r("module-error",`Failed to parse ${O} \u2014 skipping`)}}r("template","Creating page template...");let k=v.map(R=>R.moduleName),_=await this.complete(i,hc(k,a,l)),M=de(s,"templates",`lp-${l}.html`);return U(M,_),r("template-done",`Created templates/lp-${l}.html`),{sharedCss:u,sharedJs:h,template:_,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}]}),i=o.content.find(a=>a.type==="text")?.text||"";return Ct({engine:"anthropic-api",model:this.model,name:"react-conversion",input:{system:t,messages:[{role:"user",content:n}]},output:i,usage:nt(o.usage),startTime:s,endTime:new Date}),i}findAndReadCSS(t){let n=[de(t,"src/index.css"),de(t,"src/globals.css"),de(t,"src/app/globals.css"),de(t,"app/globals.css")];for(let s of n)if(w(s))return I(s);return""}findAndReadTailwind(t){let n=[de(t,"tailwind.config.ts"),de(t,"tailwind.config.js"),de(t,"tailwind.config.mjs")];for(let s of n)if(w(s))return I(s);return""}findAndReadHooks(t){let n=de(t,"src/hooks");if(!w(n))return"";try{return Ac(n).filter(s=>s.endsWith(".ts")||s.endsWith(".tsx")).map(s=>`// ${s}
|
|
2743
|
+
${I(de(n,s))}`).join(`
|
|
2893
2744
|
|
|
2894
|
-
|
|
2895
|
-
${s
|
|
2745
|
+
`)}catch{return""}}findInteractiveComponents(t){let n=this.findComponents(t),s=[];for(let o of n){let r=I(o.path);/carousel|accordion|typing|parallax|embla|swiper|collapsible/i.test(r)&&s.push(`// ${o.name}
|
|
2746
|
+
${r}`)}return s.join(`
|
|
2896
2747
|
|
|
2897
|
-
|
|
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 So(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 So(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 So(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 So(r)){if(!a.endsWith(".module"))continue;let l=Ve(r,a);if(!gf(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 ff}from"child_process";import{join as ze}from"path";import{readdirSync as xo,statSync as hf}from"fs";var wo=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=ff("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}.
|
|
2748
|
+
`)}findComponents(t){let n=[de(t,"src/components/landing"),de(t,"src/components/sections"),de(t,"src/components")];for(let s of n)if(w(s))try{return Ac(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:de(s,o)}))}catch{continue}return[]}countFiles(t){let n=3;return t.moduleCss&&n++,t.moduleJs&&n++,n}};y();y();tt();ae();rr();import{join as Xe}from"path";import{readdirSync as ir,statSync as hb}from"fs";var zn=class{constructor(t){this.config=t}async convert(t){let{sourceDir:n,themePath:s,onProgress:o}=t,r=t.conversionGuide||Ce(),i=this.buildFullPrompt(n,s,r);return o("convert",this.config.progressMessage),await Js(this.config.binary,this.config.args,i,void 0,this.config.timeoutMs,void 0,{cwd:s,shell:process.platform==="win32"}),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}.
|
|
2899
2749
|
|
|
2900
2750
|
INSTRUCTIONS:
|
|
2901
2751
|
1. Analyze all .tsx/.jsx components in the React source
|
|
@@ -2910,47 +2760,95 @@ CONVERSION GUIDE:
|
|
|
2910
2760
|
${s}
|
|
2911
2761
|
|
|
2912
2762
|
Do NOT run hs upload \u2014 I will handle that separately.
|
|
2913
|
-
Create all files directly in the theme directory.`}scanGeneratedFiles(t){let n={sharedCss:"",sharedJs:"",template:"",modules:[]},s=
|
|
2914
|
-
HubSpot-native modules. This takes 2-5 minutes.`,"AI Conversion");let t=
|
|
2915
|
-
${d}/${l.length} checks passed`),await
|
|
2916
|
-
`),"Conversion Checklist");let u=l.filter(
|
|
2917
|
-
`+u.map(
|
|
2918
|
-
`)),!await
|
|
2919
|
-
`+
|
|
2920
|
-
`));let g=
|
|
2921
|
-
`,l=!0)}catch{t.push(`${
|
|
2922
|
-
templateType: page`),
|
|
2763
|
+
Create all files directly in the theme directory.`}scanGeneratedFiles(t){let n={sharedCss:"",sharedJs:"",template:"",modules:[]},s=Xe(t,"css");if(w(s)){for(let a of ir(s))if((a.includes("theme")||a.includes("page"))&&a.endsWith(".css")&&a!=="theme-overrides.css"&&a!=="main.css"&&a!=="style.css"){n.sharedCss=I(Xe(s,a));break}}let o=Xe(t,"js");if(w(o)){for(let a of ir(o))if((a.includes("animation")||a.includes("page"))&&a.endsWith(".js")&&a!=="main.js"){n.sharedJs=I(Xe(o,a));break}}let r=Xe(t,"templates");if(w(r)){for(let a of ir(r))if(a.endsWith(".html")&&!a.startsWith("system")&&a!=="base.html"){let l=I(Xe(r,a));if(l.includes("dnd_area")){n.template=l;break}}}let i=Xe(t,"modules");if(w(i))for(let a of ir(i)){if(!a.endsWith(".module"))continue;let l=Xe(i,a);if(!hb(l).isDirectory())continue;let c={moduleName:a.replace(".module",""),fieldsJson:"",metaJson:"",moduleHtml:"",moduleCss:""},d=Xe(l,"fields.json");w(d)&&(c.fieldsJson=I(d));let u=Xe(l,"meta.json");w(u)&&(c.metaJson=I(u));let p=Xe(l,"module.html");w(p)&&(c.moduleHtml=I(p));let g=Xe(l,"module.css");w(g)&&(c.moduleCss=I(g));let f=Xe(l,"module.js");w(f)&&(c.moduleJs=I(f)),c.fieldsJson&&c.moduleHtml&&n.modules.push(c)}return n}};var ar=class extends zn{constructor(){super({binary:"gemini",args:[],progressMessage:"Running Gemini CLI (this may take a few minutes)...",timeoutMs:6e5})}};y();var lr=class extends zn{constructor(){super({binary:"codex",args:["exec","--full-auto"],progressMessage:"Running OpenAI Codex (this may take a few minutes)...",timeoutMs:6e5})}};tt();ae();function yb(e,t){switch(e){case"claude-code":return new Oo(t);case"gemini-cli":return new ar;case"codex-cli":return new lr;case"api":case"anthropic-api":case"claude-oauth":return new Jo;default:throw new Error(`The wizard does not support the "${e}" engine. Use claude-code, gemini-cli, codex-cli, or the Anthropic API.`)}}async function cr(e){await fe("Converting React to HubSpot Modules"),await xt(`AI will now analyze your React code and create
|
|
2764
|
+
HubSpot-native modules. This takes 2-5 minutes.`,"AI Conversion");let t=yb(e.aiEngine,e.model),n=Ce(),s=await je();s.start("Starting AI conversion...");let o=Date.now(),r=await t.convert({sourceDir:e.sourceDir,themePath:e.themePath,conversionGuide:n,onProgress:(f,h)=>{f==="created"?K(h):s.message(h)}}),i=((Date.now()-o)/1e3).toFixed(0);s.stop(`AI conversion complete (${i}s)`);let a=bb(e.themePath);for(let f of a)K(`Auto-fixed: ${f}`);let l=Sb(e.themePath,r),c=[];for(let f of l){let h=f.passed?"\u2705":"\u274C",b=f.passed?"":f.critical?" (CRITICAL)":" (cosmetic)";c.push(`${h} ${f.label}${b}`)}let d=l.filter(f=>f.passed).length;c.push(`
|
|
2765
|
+
${d}/${l.length} checks passed`),await xt(c.join(`
|
|
2766
|
+
`),"Conversion Checklist");let u=l.filter(f=>!f.passed&&f.critical),p=l.filter(f=>!f.passed&&!f.critical);if(u.length>0){if(Z(`${u.length} critical issue(s) \u2014 upload will likely fail:
|
|
2767
|
+
`+u.map(h=>` - ${h.label}`).join(`
|
|
2768
|
+
`)),!await Ee({message:"Continue with upload anyway?",initialValue:!1}))throw new Error("Conversion aborted due to critical checklist failures.")}else p.length>0&&se(`${p.length} non-critical issue(s) \u2014 page will work but may look incomplete:
|
|
2769
|
+
`+p.map(f=>` - ${f.label}`).join(`
|
|
2770
|
+
`));let g=st(e.themePath,"..","vibespot-conversion.log");return w(g)&&(await Ee({message:"Keep conversion log file for debugging?",initialValue:!1})?K(`Log saved: ${g}`):Ad(g)),await he("Files ready for upload!"),r}function bb(e){let t=[];vb(e),xb(e);let n=st(e,"modules");if(w(n))for(let o of Hs(n)){if(!o.endsWith(".module"))continue;let r=st(n,o,"fields.json");if(!w(r))continue;let i=o.replace(".module",""),a=I(r),l=!1;a.includes('"textarea"')&&(a=a.replace(/"textarea"/g,'"text"'),l=!0,t.push(`${i}: "textarea" \u2192 "text"`)),/"name":\s*"name"/.test(a)&&(a=a.replace(/"name":\s*"name"/g,'"name": "item_name"'),l=!0,t.push(`${i}: reserved field name "name" \u2192 "item_name"`));try{let d=JSON.parse(a),u=!1;_d(d)&&(u=!0,t.push(`${i}: fixed choice field format`)),Pd(d)&&(u=!0,t.push(`${i}: fixed link field default value`)),u&&(a=JSON.stringify(d,null,2)+`
|
|
2771
|
+
`,l=!0)}catch{t.push(`${i}: fields.json has invalid JSON \u2014 manual fix needed`)}l&&U(r,a);let c=st(n,o,"module.html");if(w(c)){let d=I(c);d.includes("now()")&&(d=d.replace(/now\(\)/g,"local_dt"),U(c,d),t.push(`${i}: now() \u2192 local_dt`))}}let s=st(e,"templates");if(w(s))for(let o of Hs(s)){if(!o.endsWith(".html"))continue;let r=st(s,o),i=I(r);(i.includes("hubdb_table")||i.includes("hubdb_table_rows"))&&(Ad(r),t.push(`Removed ${o} (HubDB requires CMS Hub Pro/Enterprise)`))}return t}function _d(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(r=>typeof r=="string")&&(s.choices=s.choices.map(r=>{if(typeof r=="string"){let i=r.charAt(0).toUpperCase()+r.slice(1);return[r,i]}return r}),t=!0),Array.isArray(s.children)&&_d(s.children)&&(t=!0)}return t}function Pd(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 i=typeof o=="string"?o:"";s.default={url:{href:i,type:"EXTERNAL"},open_in_new_tab:!1,no_follow:!1},t=!0}}Array.isArray(s.children)&&Pd(s.children)&&(t=!0)}return t}function Sb(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 r=t.modules.every(u=>u.moduleHtml.length>0);n.push({label:"module.html created for each module",passed:s>0&&r,critical:!0});let i=t.modules.filter(u=>!u.moduleCss).map(u=>u.moduleName),a=i.length===0;n.push({label:a?"module.css created for each module":`module.css missing for: ${i.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=st(e,"templates"),d=!1;if(w(c))for(let u of Hs(c)){if(!u.endsWith(".html")||u==="base.html"||u.startsWith("system"))continue;let p=I(st(c,u));if(p.includes("dnd_area")&&/templateType\s*:\s*page/i.test(p)){d=!0;break}}return n.push({label:"Template annotations (templateType: page)",passed:d,critical:!0}),n}function vb(e){let t=st(e,"templates");if(w(t))for(let n of Hs(t)){if(!n.endsWith(".html")||n==="base.html"||n.startsWith("system"))continue;let s=st(t,n),o=I(s);if(!o.includes("dnd_area")&&!o.includes("extends"))continue;let r=/templateType\s*:\s*page/i.test(o),i=/isAvailableForNewContent\s*:\s*true/i.test(o);if(r&&i)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);r||(c+=`
|
|
2772
|
+
templateType: page`),i||(c+=`
|
|
2923
2773
|
isAvailableForNewContent: true`),/label\s*:/i.test(c)||(c+=`
|
|
2924
2774
|
label: ${a}`),o=c+o.slice(l)}else o=`<!--
|
|
2925
2775
|
templateType: page
|
|
2926
2776
|
isAvailableForNewContent: true
|
|
2927
2777
|
label: ${a}
|
|
2928
2778
|
-->
|
|
2929
|
-
`+o;
|
|
2930
|
-
`)}catch{}}}y();
|
|
2931
|
-
`);
|
|
2932
|
-
|
|
2933
|
-
|
|
2779
|
+
`+o;U(s,o),K(`Template "${n}" \u2014 annotations verified`)}}function xb(e){let t=st(e,"modules");if(w(t))for(let n of Hs(t)){if(!n.endsWith(".module"))continue;let s=st(t,n,"meta.json");if(w(s))try{let o=JSON.parse(I(s)),r=!1;(!o.host_template_types||!o.host_template_types.includes("PAGE"))&&(o.host_template_types=["PAGE"],r=!0),o.is_available_for_new_content||(o.is_available_for_new_content=!0,r=!0),r&&U(s,JSON.stringify(o,null,2)+`
|
|
2780
|
+
`)}catch{}}}y();on();import{join as Jd,basename as Mb}from"path";y();ae();import{join as ge}from"path";import{readdirSync as ut,rmSync as wb}from"fs";function dr(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 ur(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 pr(e){let t=[];return Id(e)&&t.push("textarea \u2192 text"),Md(e)&&t.push("name \u2192 item_name"),$d(e)&&t.push("now() \u2192 local_dt"),Rd(e)&&t.push("Removed HubDB templates"),Nd(e)&&t.push("Fixed link field defaults"),Od(e)&&t.push("Fixed rgba/invalid color values \u2192 hex"),kb(e)&&t.push("Stripped CDN @import statements"),Dd(e)&&t.push('dnd_area \u2192 "main" in email templates'),jd(e)&&t.push("Added {{ dnd_area_stylesheet }} to email templates"),t}function Ed(e,t){let n=t.message.toLowerCase();return n.includes("textarea")?Id(e):n.includes("reserved field name")?Md(e):n.includes("now()")?$d(e):n.includes("hubdb")?Rd(e):n.includes("invalid default value")||n.includes("deserialization")?Nd(e):n.includes("color")&&n.includes("invalid")?Od(e):n.includes("dnd_area_stylesheet")?jd(e):n.includes("dnd")?Dd(e):!1}function Id(e){let t=!1,n=ge(e,"modules");if(!w(n))return!1;for(let s of ut(n)){if(!s.endsWith(".module"))continue;let o=ge(n,s,"fields.json");if(!w(o))continue;let r=I(o);r.includes('"textarea"')&&(r=r.replace(/"textarea"/g,'"text"'),U(o,r),t=!0)}return t}function Md(e){let t=!1,n=ge(e,"modules");if(!w(n))return!1;for(let s of ut(n)){if(!s.endsWith(".module"))continue;let o=ge(n,s,"fields.json");if(!w(o))continue;let r=I(o);/"name":\s*"name"/g.test(r)&&(r=r.replace(/"name":\s*"name"/g,'"name": "item_name"'),U(o,r),t=!0)}return t}function $d(e){let t=!1,n=ge(e,"modules");if(!w(n))return!1;for(let s of ut(n)){if(!s.endsWith(".module"))continue;let o=ge(n,s,"module.html");if(!w(o))continue;let r=I(o);r.includes("now()")&&(r=r.replace(/now\(\)/g,"local_dt"),U(o,r),t=!0)}return t}function Rd(e){let t=!1,n=ge(e,"templates");if(!w(n))return!1;for(let s of ut(n)){if(!s.endsWith(".html"))continue;let o=ge(n,s),r=I(o);(r.includes("hubdb_table")||r.includes("hubdb_table_rows"))&&(wb(o),t=!0)}return t}function Nd(e){let t=!1,n=ge(e,"modules");if(!w(n))return!1;for(let s of ut(n)){if(!s.endsWith(".module"))continue;let o=ge(n,s,"fields.json");if(w(o))try{let r=JSON.parse(I(o));Ld(r)&&(U(o,JSON.stringify(r,null,2)+`
|
|
2781
|
+
`),t=!0)}catch{}}return t}function kb(e){let t=!1,n=ge(e,"css");if(w(n))for(let o of ut(n)){if(!o.endsWith(".css"))continue;let r=ge(n,o),i=I(r),a=i.replace(/@import\s+url\(['"]?https?:\/\/[^)]+['"]?\)\s*;?/gi,"");a!==i&&(U(r,a),t=!0)}let s=ge(e,"modules");if(w(s))for(let o of ut(s)){if(!o.endsWith(".module"))continue;let r=ge(s,o,"module.css");if(!w(r))continue;let i=I(r),a=i.replace(/@import\s+url\(['"]?https?:\/\/[^)]+['"]?\)\s*;?/gi,"");a!==i&&(U(r,a),t=!0)}if(w(s))for(let o of ut(s)){if(!o.endsWith(".module"))continue;let r=ge(s,o,"module.html");if(!w(r))continue;let i=I(r),a=i.replace(/<link[^>]+href=['"]https?:\/\/[^'"]+['"][^>]*>/gi,"");a!==i&&(U(r,a),t=!0)}return t}function Od(e){let t=!1,n=ge(e,"modules");if(!w(n))return!1;for(let s of ut(n)){if(!s.endsWith(".module"))continue;let o=ge(n,s,"fields.json");if(w(o))try{let r=JSON.parse(I(o));Fd(r)&&(U(o,JSON.stringify(r,null,2)+`
|
|
2782
|
+
`),t=!0)}catch{}}return t}function Fd(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,r=o.color;if(typeof r=="string"&&!Cb(r)){let i=Tb(r);i&&(o.color=i.hex,i.opacity!==void 0&&(o.opacity=i.opacity),t=!0)}}Array.isArray(s.children)&&Fd(s.children)&&(t=!0)}return t}function Cb(e){return/^#[0-9a-fA-F]{6}$/.test(e)}function Tb(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 r=Math.min(255,parseInt(n[1])),i=Math.min(255,parseInt(n[2])),a=Math.min(255,parseInt(n[3])),l=`#${r.toString(16).padStart(2,"0")}${i.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 Dd(e){let t=!1,n=ge(e,"templates");if(!w(n))return!1;for(let s of ut(n)){if(!s.endsWith(".html"))continue;let o=ge(n,s),r=I(o);if(!/templateType:\s*email/i.test(r))continue;let i=r.replace(/\{%\s*dnd_area\s+"(?!main")([^"]+)"/g,'{% dnd_area "main"');i!==r&&(U(o,i),t=!0)}return t}function jd(e){let t=!1,n=ge(e,"templates");if(!w(n))return!1;for(let s of ut(n)){if(!s.endsWith(".html"))continue;let o=ge(n,s),r=I(o);if(!/templateType:\s*email/i.test(r)||r.includes("dnd_area_stylesheet"))continue;let i=r.replace(/(\{\{\s*standard_header_includes\s*\}\})/,`$1
|
|
2783
|
+
{{ dnd_area_stylesheet }}`);i!==r&&(U(o,i),t=!0)}return t}function Ld(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 i=typeof o=="string"?o:"";s.default={url:{href:i,type:"EXTERNAL"},open_in_new_tab:!1,no_follow:!1},t=!0}}Array.isArray(s.children)&&Ld(s.children)&&(t=!0)}return t}te();y();cn();cn();import{readdirSync as Ab}from"fs";import{join as _b,relative as Pb}from"path";var Eb=new Set([".git","node_modules",".vibespot",".DS_Store"]);function Bd(e){let t=[];for(let n of Ab(e,{withFileTypes:!0})){if(Eb.has(n.name)||n.name.startsWith(".")&&n.name!==".gitkeep")continue;let s=_b(e,n.name);n.isDirectory()?t.push(...Bd(s)):n.isFile()&&t.push(s)}return t}async function Ib(e,t,n){let s=0;async function o(){for(;s<e.length;){let i=s++;await n(e[i])}}let r=Array.from({length:Math.min(t,e.length)},()=>o());await Promise.all(r)}async function mr(e,t,n,s={}){let o=s.concurrency??5,r=Bd(t),i=r.length,a=0,l=0,c=[];return await Ib(r,o,async d=>{let u=Pb(t,d).replace(/\\/g,"/"),p=`${n}/${u}`;s.onFileStart?.(u);let g=await ql(e,p,d);if(g.success)a++,s.onFileComplete?.(u);else{l++;let f={file:u,status:g.error?.status||0,message:g.error?.message||"Unknown error",category:g.error?.category,detail:g.error?.detail};c.push(f),s.onFileError?.(u,f)}s.onProgress?.(a+l,i)}),{success:l===0,uploaded:a,failed:l,total:i,errors:c}}function $b(e){return(e.match(/^Uploaded file /gm)||[]).length}async function qn(e){await fe("Uploading to HubSpot");let t=Mb(e)||e,n=$(),s=Je(),o=n.hubspotUploadMode!=="cli"&&!!s,r=await je(),i=3;for(let a=1;a<=i;a++){r.start(a===1?"Uploading theme...":`Retrying upload (attempt ${a}/${i})...`);let l=[],c=0,d=!1;if(o){let p=await mr(s,e,t,{onFileComplete:()=>{c++}});d=p.success,d?c=p.uploaded:l=dr(p.errors)}else{let p=cs("hs",["cms","upload",e,t],{cwd:Jd(e,"..")}),g=[p.stdout,p.stderr].filter(Boolean).join(`
|
|
2784
|
+
`);c=$b(g),d=p.success,d||(l=ur(g))}if(d)return r.stop(`All files uploaded! (${c} files)`),await he("Upload complete!"),!0;if(c>0?r.stop(`${c} files uploaded, but some errors occurred`):r.stop("Upload failed"),l.length===0){if(Z("Upload failed with unknown error."),c>0&&(se(`Most files uploaded successfully. The theme may already be usable in HubSpot.
|
|
2785
|
+
You can check your HubSpot Design Manager to verify.`),await Ee({message:"Continue anyway (theme is likely uploaded)?",initialValue:!0})))return!0;if(a<i){if(!await Ee({message:"Try uploading again?"}))break;continue}break}let u=!1;for(let p of l)p.fixable?Ed(e,p)?(K(`Auto-fixed: ${p.message}`),u=!0):se(`Could not auto-fix: ${p.message}`):Z(p.message);if(!(u&&a<i)){if(c>0&&(se(`${c} files uploaded successfully despite errors.
|
|
2786
|
+
The theme may work \u2014 check HubSpot Design Manager.`),await Ee({message:"Continue anyway?",initialValue:!0})))return!0;if(!u){if(r.start("Cleaning up stuck modules..."),o)try{await Pi(s,`${t}/modules`)}catch{}else cs("hs",["cms","delete",`${t}/modules`],{cwd:Jd(e,"..")});r.stop("Cleaned up modules, retrying...")}}}return Z("Upload failed after multiple attempts."),!1}y();import{execFileSync as ra}from"child_process";import{rmSync as Rb}from"fs";import{basename as Hd}from"path";ae();async function Ud(e){let{portalId:t,sourceDir:n,themePath:s,wasCloned:o}=e;await fe("You're all set!");let i=hs(t)==="eu1"?"app-eu1.hubspot.com":"app.hubspot.com";if(await xt(`Your React page has been converted and uploaded to HubSpot.
|
|
2934
2787
|
The theme and modules are now in your account, but you still
|
|
2935
|
-
need to ${
|
|
2788
|
+
need to ${E.bold("create a new landing page")} that uses them.
|
|
2936
2789
|
|
|
2937
2790
|
Next steps:
|
|
2938
2791
|
|
|
2939
|
-
${
|
|
2940
|
-
${
|
|
2941
|
-
${
|
|
2942
|
-
${
|
|
2943
|
-
${
|
|
2944
|
-
${
|
|
2945
|
-
${
|
|
2946
|
-
|
|
2947
|
-
|
|
2948
|
-
|
|
2949
|
-
`)),a(),setTimeout(()=>process.exit(0),500)})})}catch(o){console.error(Ei.red(` Failed to start: ${o instanceof Error?o.message:String(o)}`)),process.exit(1)}}function gv(){let e=[$i(Qp,"../../ui"),$i(Qp,"../ui"),$i(process.cwd(),"ui")];for(let t of e)if(uv($i(t,"index.html")))return t;return null}y();import{resolve as tg}from"path";import{existsSync as Fa}from"fs";gt();Qe();ee();Ma();async function ng(e={}){let t=await og(e.path);if(e.fix){let o=Ci(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=Hs(t);if(e.json){process.stdout.write(JSON.stringify(n,null,2)+`
|
|
2950
|
-
|
|
2951
|
-
|
|
2952
|
-
|
|
2953
|
-
`));try{process.platform==="darwin"?Ba("open",[i],{stdio:"ignore"}):process.platform==="win32"?Ba("cmd",["/c","start","",i],{stdio:"ignore"}):Ba("xdg-open",[i],{stdio:"ignore"})}catch{}await new Promise(r=>{process.on("SIGINT",()=>{console.log(t(`
|
|
2954
|
-
|
|
2955
|
-
|
|
2792
|
+
${E.bold("1.")} Go to HubSpot ${E.muted("\u2192")} Content ${E.muted("\u2192")} Landing Pages ${E.muted("\u2192")} Create
|
|
2793
|
+
${E.bold("2.")} Choose your uploaded theme from the theme picker
|
|
2794
|
+
${E.bold("3.")} Select the landing page template that was just created
|
|
2795
|
+
${E.bold("4.")} Your converted modules will appear \u2014 drag them onto the page
|
|
2796
|
+
${E.bold("5.")} Click each section to edit text, images, and colors
|
|
2797
|
+
${E.bold("6.")} Upload images via File Manager ${E.muted("(Settings \u2192 Files)")}
|
|
2798
|
+
${E.bold("7.")} Preview and publish!`,"What's next"),await Ee({message:"Open HubSpot Landing Pages in your browser?"})){let c=t?`https://${i}/page-ui/${t}/management/pages/landing`:`https://${i}`;try{let d=process.platform;d==="darwin"?ra("open",[c],{stdio:"ignore"}):d==="win32"?ra("cmd",["/c","start","",c],{stdio:"ignore"}):ra("xdg-open",[c],{stdio:"ignore"}),K("Opening HubSpot Landing Pages...")}catch{B(`Open this URL in your browser: ${E.info(c)}`)}}let l=[];if(o&&w(n)&&l.push({path:n,label:`Cloned source (${Hd(n)})`}),w(s)&&l.push({path:s,label:`Theme directory (${Hd(s)})`}),l.length>0&&await Ee({message:"Clean up local working directories?"}))for(let d of l)try{Rb(d.path,{recursive:!0,force:!0}),K(`Removed ${d.label}`)}catch{se(`Could not remove ${d.label} \u2014 delete manually if needed.`)}await he(`Thanks for using hub${E.vibes("Vibes")}! ${E.vibes("~")}`)}te();async function Gd(){Pe();let e=await Eo(),t=await Io();Y({lastSourcePath:t.sourceDir});let n=await Ro();Y({lastThemePath:n.themePath}),await cr({aiEngine:e.aiEngine,model:e.model,sourceDir:t.sourceDir,themePath:n.themePath}),await qn(n.themePath),await Ud({portalId:e.portalId,sourceDir:t.sourceDir,themePath:n.themePath,wasCloned:t.wasCloned})}y();async function Wd(){Pe(),await Eo()}y();te();async function Kd(){Pe();let e=$();e.aiEngine||(Z("AI engine not configured. Run `vibespot init` first or use the full wizard with `vibespot`."),process.exit(1));let t=await Io(),n=await Ro();await cr({aiEngine:e.aiEngine,sourceDir:t.sourceDir,themePath:n.themePath})}y();te();async function Vd(){Pe();let e=$();if(e.lastThemePath)if(await Ee({message:`Upload from ${e.lastThemePath}?`}))await qn(e.lastThemePath);else{let n=await ve({message:"Path to your HubSpot theme directory:",placeholder:"./my-theme"});await qn(n)}else{let t=await ve({message:"Path to your HubSpot theme directory:",placeholder:"./my-theme",validate:n=>n.trim()?void 0:"Path is required"});await qn(t)}}y();te();async function zd(){Pe(),await fe("Environment Diagnostics");let e=0,t=gs();t.found?Co(t.version)?K(`Node.js v${t.version}`):(se(`Node.js v${t.version} \u2014 too old (need 18+)`),B(" Update at https://nodejs.org"),e++):(Z("Node.js \u2014 not installed"),B(" Install from https://nodejs.org"),e++);let n=fs();n.found?K(`Git ${n.version}`):(Z("Git \u2014 not installed"),B(" Install from https://git-scm.com"),e++);let s=St();if(!s.found)se("HubSpot CLI \u2014 not installed (only needed for deployment)"),B(" Install: npm install -g @hubspot/cli");else if(!Ul(s.version))se(`HubSpot CLI v${s.version} \u2014 too old (need v8+)`),B(" Update: npm install -g @hubspot/cli@latest"),e++;else{K(`HubSpot CLI v${s.version}`);let p=vt();p.authenticated?K(`HubSpot portal${p.portalName?`: ${p.portalName}`:""} (ID: ${p.portalId})`):(se("HubSpot \u2014 not authenticated"),B(" Run: hs init"))}let o=Rn();o.found?K(`Claude Code ${o.version} at ${o.path}`):B(E.muted("Claude Code \u2014 not installed"));let r=Nn();r.found?K(`Gemini CLI ${r.version} at ${r.path}`):B(E.muted("Gemini CLI \u2014 not installed"));let i=On();i.found?K(`OpenAI Codex ${i.version} at ${i.path}`):B(E.muted("OpenAI Codex \u2014 not installed"));let a=$(),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?K("Anthropic API key configured"):B(E.muted("Anthropic API key \u2014 not set")),c?K("OpenAI API key configured"):B(E.muted("OpenAI API key \u2014 not set")),d?K("Google AI API key configured"):B(E.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&&K(`AI engine: ${u[a.aiEngine]||a.aiEngine}`),a.lastThemePath&&B(E.muted(`Last theme: ${a.lastThemePath}`)),!o.found&&!r.found&&!i.found&&!l&&!c&&!d&&(se("No AI engine available"),B(" Fastest: Set an API key (ANTHROPIC_API_KEY, OPENAI_API_KEY, or GEMINI_API_KEY)"),B(" Or install: Claude Code \u2014 https://claude.ai/code"),B(" Gemini CLI \u2014 https://github.com/google-gemini/gemini-cli"),B(" Codex CLI \u2014 https://github.com/openai/codex"),e++),console.log(),e===0?await he("Everything looks good!"):await he(E.warn(`${e} issue${e>1?"s":""} found \u2014 see above`))}y();import{dirname as Sk,join as ii}from"path";import{existsSync as vk}from"fs";import{fileURLToPath as xk}from"url";import{execFileSync as wl}from"child_process";import ai from"chalk";y();me();Xn();Re();import{createServer as fk}from"http";import{readFileSync as vl,existsSync as xl}from"fs";import{join as oi,extname as Df}from"path";import{WebSocketServer as hk}from"ws";y();import{randomBytes as wS,timingSafeEqual as kS}from"crypto";var pa="vibespot_token";function hu(e){let t=(process.env[e]||"").toLowerCase();return t==="1"||t==="true"||t==="yes"}function yu(e){return e==="127.0.0.1"||e==="localhost"||e==="::1"||e==="[::1]"}function CS(e){return e?e==="127.0.0.1"||e==="::1"||e==="::ffff:127.0.0.1"||e.startsWith("127."):!1}function ma(e){let t=e||process.env.VIBESPOT_HOST||"127.0.0.1",n=hu("VIBESPOT_DISABLE_AUTH"),s=process.env.VIBESPOT_AUTH_TOKEN||null,o=!1;return n?{host:t,authToken:null,generatedToken:!1,authDisabled:n}:(!s&&!yu(t)&&(s=wS(24).toString("hex"),o=!0),{host:t,authToken:s,generatedToken:o,authDisabled:n})}function bu(e){return!e.authDisabled||yu(e.host)?{severity:"none",message:null}:hu("VIBESPOT_TRUST_PROXY")?{severity:"warn",message:` ! AUTH IS DISABLED on a non-loopback bind (VIBESPOT_DISABLE_AUTH=1 + VIBESPOT_TRUST_PROXY=1).
|
|
2799
|
+
! An authenticating proxy MUST be the only way to reach this server.
|
|
2800
|
+
! Never publish the app port directly (keep it expose-only, e.g. behind
|
|
2801
|
+
! the docker-compose.auth.yml Entra gate) \u2014 anyone who reaches it can
|
|
2802
|
+
! use your AI keys and HubSpot account.`}:{severity:"refuse",message:`VIBESPOT_DISABLE_AUTH=1 with a non-loopback bind (${e.host}) would serve a fully unauthenticated server \u2014 anyone who can reach the port could use your AI keys and HubSpot account. Refusing to start. If an authenticating proxy (e.g. the docker-compose.auth.yml Entra/oauth2-proxy gate) is the ONLY ingress to this port, set VIBESPOT_TRUST_PROXY=1 to acknowledge that and continue.`}}var Su=/^(localhost|127(?:\.\d+){3}|\[::1\]|::1|100\.\d+\.\d+\.\d+|192\.168\.\d+\.\d+|10\.\d+\.\d+\.\d+|172\.(?:1[6-9]|2\d|3[01])\.\d+\.\d+)$/;function TS(e){if(!e)return null;try{return new URL(`http://${e}`).hostname}catch{return null}}function AS(e,t){let n=TS(e);return n?Su.test(n)?!0:n===t.host:!1}function br(e,t){if(!e)return!0;let n;try{n=new URL(e)}catch{return!1}return n.protocol!=="http:"&&n.protocol!=="https:"?!1:t&&n.host===t?!0:Su.test(n.hostname)}function Zn(e,t){let n=Buffer.from(e),s=Buffer.from(t);return n.length===s.length&&kS(n,s)}function _S(e,t){let n=e.headers.cookie;if(!n)return null;for(let s of n.split(";")){let o=s.indexOf("=");if(o!==-1&&s.slice(0,o).trim()===t)return s.slice(o+1).trim()}return null}function ga(e,t){if(t.authDisabled)return{ok:!0,viaQueryToken:!1};if(t.authToken){let n=e.headers.authorization;if(n?.startsWith("Bearer ")&&Zn(n.slice(7).trim(),t.authToken))return{ok:!0,viaQueryToken:!1};let s=e.headers["x-vibespot-token"];if(typeof s=="string"&&Zn(s,t.authToken))return{ok:!0,viaQueryToken:!1};let o=_S(e,pa);if(o&&Zn(o,t.authToken))return{ok:!0,viaQueryToken:!1};try{let i=new URL(e.url||"/","http://localhost").searchParams.get("token");if(i&&Zn(i,t.authToken))return{ok:!0,viaQueryToken:!0}}catch{}}return CS(e.socket.remoteAddress)&&AS(e.headers.host,t)?{ok:!0,viaQueryToken:!1}:{ok:!1,viaQueryToken:!1}}y();import{createServer as PS}from"http";import{randomBytes as ES}from"crypto";import{existsSync as wu,readFileSync as ku}from"fs";import{extname as IS,join as Cu}from"path";Xn();me();wt();var fa="preview-agent.js",MS=10;function ha(e,t){let n=(e||"").trim();if(!n)return null;let s=r=>(console.warn(`Ignoring ${t||"public origin"} (${r}): ${n}`),null),o;try{o=new URL(n)}catch{return s("not an absolute URL")}return o.protocol!=="http:"&&o.protocol!=="https:"?s("must be http or https"):o.pathname!=="/"||o.search||o.hash?s("must not have a path, query, or fragment"):o.username||o.password?s("must not carry credentials"):o.origin}var $S={".png":"image/png",".jpg":"image/jpeg",".jpeg":"image/jpeg",".gif":"image/gif",".svg":"image/svg+xml",".webp":"image/webp",".avif":"image/avif",".ico":"image/x-icon",".css":"text/css; charset=utf-8",".js":"text/javascript; charset=utf-8",".woff":"font/woff",".woff2":"font/woff2",".ttf":"font/ttf",".otf":"font/otf",".mp4":"video/mp4",".webm":"video/webm"};function RS(){let e={};if(!x())return e;for(let n of pe())try{let s=JSON.parse(n.fieldsJson);Array.isArray(s)&&(e[n.moduleName]=s)}catch{}return e}function vu(e){return JSON.stringify(e).replace(/</g,"\\u003c")}function NS(e,t,n={}){let s=`<script id="vs-preview-config" type="application/json">${vu({v:1,token:t})}</script><script id="vs-preview-fields" type="application/json">${vu(n)}</script><script src="/${fa}"></script>`;return e.includes("<head>")?e.replace("<head>",`<head>${s}`):s+e}function OS(e,t){return e.replace(/(["'(])\/theme-assets\/([^"')?\s]+)/g,(n,s,o)=>`${s}/theme-assets/${o}?t=${t}`)}function xu(e,t,n){let s=e.searchParams.get("t");return s&&Zn(s,t)?!0:(n.writeHead(401,{"Content-Type":"text/plain; charset=utf-8"}),n.end("Preview access token required"),!1)}function FS(e,t){let n=Cu(e,fa);if(!wu(n)){t.writeHead(404,{"Content-Type":"text/plain; charset=utf-8"}),t.end("preview-agent.js not found");return}t.writeHead(200,{"Content-Type":"text/javascript; charset=utf-8","Cache-Control":"no-cache"}),t.end(ku(n))}function DS(e,t){let n=x();if(!n){t.writeHead(404,{"Content-Type":"text/plain; charset=utf-8"}),t.end("No session");return}let s;try{s=Ln(Cu(n.themePath,"assets"),decodeURIComponent(e))}catch{t.writeHead(404,{"Content-Type":"text/plain; charset=utf-8"}),t.end("Asset not found");return}if(!wu(s)){t.writeHead(404,{"Content-Type":"text/plain; charset=utf-8"}),t.end("Asset not found");return}t.writeHead(200,{"Content-Type":$S[IS(s).toLowerCase()]||"application/octet-stream","Cache-Control":"no-cache"}),t.end(ku(s))}function jS(e){return["default-src 'none'","script-src 'self' 'unsafe-inline'","style-src 'unsafe-inline'","img-src * data: blob:","font-src * data:","media-src * data: blob:","connect-src 'none'","base-uri 'none'","form-action 'none'",`frame-ancestors ${e.length?e.join(" "):"'none'"}`].join("; ")}function LS(e,t,n){let s=new URL(e.url||"/",`http://${e.headers.host||"localhost"}`),o=e.method||"GET";if(t.setHeader("X-Content-Type-Options","nosniff"),o!=="GET"&&o!=="HEAD"){t.writeHead(404,{"Content-Type":"text/plain; charset=utf-8"}),t.end("Not found");return}if(s.pathname===`/${fa}`){FS(n.uiDir,t);return}if(s.pathname==="/"){if(!xu(s,n.token,t))return;let r=OS(NS(Us(),n.token,RS()),n.token);t.writeHead(200,{"Content-Type":"text/html; charset=utf-8","Content-Security-Policy":n.csp,"Cache-Control":"no-store"}),t.end(r);return}if(s.pathname.startsWith("/theme-assets/")){if(!xu(s,n.token,t))return;DS(s.pathname.slice(14),t);return}t.writeHead(404,{"Content-Type":"text/plain; charset=utf-8"}),t.end("Not found")}function Tu(e){let t=e.token||ES(24).toString("hex"),n=jS(e.frameAncestors),s=PS((o,r)=>LS(o,r,{token:t,uiDir:e.uiDir,csp:n}));return new Promise((o,r)=>{let i=0,a=l=>{s.once("error",c=>{c.code==="EADDRINUSE"&&i<MS?(i+=1,a(l+1)):r(c)}),s.listen(l,e.host,()=>{s.removeAllListeners("error"),o({port:l,host:e.host,token:t,publicOrigin:e.publicOrigin||null,close:()=>s.close()})})};a(e.port)})}hn();y();Re();y();At();Re();te();xs();$o();cn();me();Xt();os();import{existsSync as is,readdirSync as hm,rmSync as $x,writeFileSync as wn,mkdirSync as jr}from"fs";import{join as Me,basename as Rx,resolve as ym}from"path";import{homedir as Nx}from"os";import{execFileSync as Sm}from"child_process";te();ae();y();import{readFileSync as Ax,readdirSync as _x,existsSync as Px}from"fs";import{dirname as Ex,join as Dr}from"path";import{fileURLToPath as Ix}from"url";var mm=Ex(Ix(import.meta.url)),rs=null;function Mx(){let e=[Dr(mm,"../../starters"),Dr(mm,"../starters"),Dr(process.cwd(),"starters")];for(let t of e)if(Px(t))return t;return null}function gm(){if(rs!==null)return rs;let e=Mx();if(!e)return rs=[],rs;let t=[];for(let n of _x(e).filter(s=>s.endsWith(".json")).sort())try{let s=JSON.parse(Ax(Dr(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 rs=t,rs}function fm(){return gm().map(e=>({id:e.id,name:e.name,description:e.description,category:e.category,contentType:e.contentType,moduleCount:e.modules.length}))}function sl(e){return gm().find(t=>t.id===e)||null}hn();Ua();var vm=process.platform==="win32"?{shell:!0}:{},gt=Me(Nx(),"vibespot-themes"),Lr=null,Ox=5e3;function Br(){if(Lr&&Date.now()-Lr.ts<Ox)return Lr.data;let e=[];if(is(gt))try{for(let t of hm(gt,{withFileTypes:!0}))if(t.isDirectory()){let n=Me(gt,t.name,"theme.json");if(is(n)){let s=0,o=Me(gt,t.name,"modules");if(is(o))try{s=hm(o,{withFileTypes:!0}).filter(r=>r.isDirectory()).length}catch{}e.push({name:t.name,moduleCount:s})}}}catch{}return Lr={data:e,ts:Date.now()},e}function xm(e){let t=x(),n=To(),s=!1;try{Sm("hs",["--version"],{encoding:"utf-8",stdio:"pipe",...vm}),s=!0}catch{}let o=Wn().sort((i,a)=>a.updatedAt-i.updatedAt),r=Br();m(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:r,contentMode:tn()})}function wm(e,t){G(e,n=>{try{if(Gt()){m(t,409,{error:"Cannot switch projects while AI is generating.",generating:!0});return}let{name:s,starterId:o,assetType:r}=JSON.parse(n);if(!s||typeof s!="string"){m(t,400,{error:"Theme name is required"});return}let i=s.toLowerCase().replace(/[^a-z0-9-]/g,"-").replace(/-+/g,"-").replace(/^-|-$/g,"");if(!i){m(t,400,{error:"Theme name must contain at least one alphanumeric character"});return}let a=Me(gt,i);if($e(gt),is(a)&&$x(a,{recursive:!0,force:!0}),o&&typeof o=="string"&&!sl(o)){m(t,400,{error:`Starter template "${o}" not found`});return}vs(a,i),Gn(a,i),o&&typeof o=="string"?(Fx(a,i,o),Ae()):r==="email"&&(jt("module_only","Email","email"),jn(a,i)),D(),m(t,200,{ok:!0,themeName:i,themePath:a,starterId:o||void 0})}catch(s){m(t,500,{error:N(s)})}})}function Fx(e,t,n){let s=sl(n);if(!s)return;let o=x();if(!o)return;let r=s.contentType==="email",i=s.modules.map(u=>({...u})),a=[...s.moduleOrder],l=r?`email-${t}`:`lp-${t}`,c={id:l,label:`${s.name}`,pageType:r?"module_only":"landing_page",contentMode:r?"email":void 0,templateFile:r?"templates/email.html":`templates/${l}.html`,modules:i,moduleOrder:a,sharedCss:s.sharedCss,sharedJs:s.sharedJs,template:"",messages:[]};r&&jn(e,t),o.templates=[c],o.activeTemplateId=l,o.modules=i,o.moduleOrder=a,o.sharedCss=s.sharedCss,o.sharedJs=s.sharedJs;let d=Me(e,"modules");jr(d,{recursive:!0});for(let u of s.modules){let p=Me(d,`${u.moduleName}.module`);jr(p,{recursive:!0}),wn(Me(p,"fields.json"),u.fieldsJson,"utf-8"),wn(Me(p,"meta.json"),u.metaJson,"utf-8"),wn(Me(p,"module.html"),u.moduleHtml,"utf-8"),wn(Me(p,"module.css"),u.moduleCss,"utf-8"),u.moduleJs&&wn(Me(p,"module.js"),u.moduleJs,"utf-8")}if(s.sharedCss){let u=Me(e,"css");jr(u,{recursive:!0}),wn(Me(u,`${t}-theme.css`),s.sharedCss,"utf-8")}if(s.sharedJs){let u=Me(e,"js");jr(u,{recursive:!0}),wn(Me(u,`${t}-animations.js`),s.sharedJs,"utf-8")}}function km(e){m(e,200,{starters:fm()})}function Cm(e,t){G(e,n=>{try{if(Gt()){m(t,409,{error:"Cannot switch projects while AI is generating.",generating:!0});return}let{name:s}=JSON.parse(n);if(!s||typeof s!="string"){m(t,400,{error:"Theme name is required"});return}let o=s.replace(/^\/+|\/+$/g,"");if(!o){m(t,400,{error:"Theme name is required"});return}let r=Je(),i=$(),a=o.includes("/")||o.includes("@")?o.replace(/[@/]/g,"_").replace(/_+/g,"_").replace(/^_|_$/g,""):o,l=Me(gt,a);$e(gt),i.hubspotUploadMode==="cli"||!r?(async()=>{Sm("hs",["cms","fetch",o,l],{encoding:"utf-8",stdio:"pipe",...vm});let c=await bm(l,a);m(t,200,{ok:!0,themeName:a,themePath:l,moduleCount:c.moduleCount,brandEnrichment:c.brandEnrichment})})().catch(c=>{m(t,500,{error:N(c)})}):ks(r,o,l).then(async()=>{let c=await bm(l,a);m(t,200,{ok:!0,themeName:a,themePath:l,moduleCount:c.moduleCount,brandEnrichment:c.brandEnrichment})}).catch(c=>{m(t,500,{error:N(c)})})}catch(s){m(t,500,{error:N(s)})}})}async function bm(e,t){Gn(e,t,{isImported:!0}),sr(e),D();let n=x(),s={attempted:[],extracted:[],skipped:[],errors:[]};return n&&(s=await nm(n),D()),{moduleCount:n?.modules.length||0,brandEnrichment:s}}function Tm(e,t){G(e,n=>{try{if(Gt()){m(t,409,{error:"Cannot switch projects while AI is generating.",generating:!0});return}let{path:s}=JSON.parse(n);if(!s||typeof s!="string"){m(t,400,{error:"Theme path is required"});return}let o=s;if(is(o)||(o=Me(gt,s)),!is(o)){m(t,400,{error:`Theme folder not found: ${s}`});return}let r=Rx(o),i=x();if(i&&ym(i.themePath)===ym(o)){m(t,200,{ok:!0,themeName:i.themeName,themePath:i.themePath,moduleCount:i.modules.length,resumed:!0});return}let a=ed(o),l=a?Rs(a):null;if(l){m(t,200,{ok:!0,themeName:l.themeName,themePath:l.themePath,moduleCount:l.modules.length,resumed:!0});return}Gn(o,r),sr(o),D(),m(t,200,{ok:!0,themeName:r,themePath:o,moduleCount:x()?.modules.length||0,resumed:!1})}catch(s){m(t,500,{error:N(s)})}})}function Am(e,t){G(e,n=>{try{if(Gt()){m(t,409,{error:"Cannot switch projects while AI is generating.",generating:!0});return}let{sessionId:s}=JSON.parse(n);if(!s||typeof s!="string"){m(t,400,{error:"Session ID is required"});return}let o=Rs(s);if(!o){m(t,404,{error:"Session not found"});return}m(t,200,{ok:!0,themeName:o.themeName,themePath:o.themePath,moduleCount:o.modules.length,messageCount:o.messages.length})}catch(s){m(t,500,{error:N(s)})}})}function _m(e,t){G(e,n=>{try{let{apiKey:s}=JSON.parse(n);if(!s||typeof s!="string"){m(t,400,{error:"API key is required"});return}Y({anthropicApiKey:s}),m(t,200,{ok:!0})}catch(s){m(t,400,{error:N(s)})}})}function Pm(e){let t=Je();if(!t){m(e,200,{themes:[],error:"No HubSpot account connected"});return}(async()=>{let n=await Xl(t);if(n.length===0){m(e,200,{themes:[]});return}let s=[],o=n.map(async a=>{let l=a.path||a.name;try{let c=await Po(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 r=Br(),i=new Set(r.map(a=>a.name));m(e,200,{themes:s.map(a=>({...a,existsLocally:i.has(a.name)}))})})().catch(n=>{m(e,200,{themes:[],error:N(n)})})}y();At();Re();te();me();import{existsSync as Lx,readFileSync as Bx,appendFileSync as Jx}from"fs";import{join as $m}from"path";import{homedir as Rm}from"os";cn();ae();y();import{spawn as Em}from"child_process";var kn=new Map;function Dx(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+=`
|
|
2803
|
+
Process error: ${o.message}`,t.completedAt=Date.now()}),setTimeout(()=>{t.status==="running"&&(e.kill(),t.status="failed",t.output+=`
|
|
2804
|
+
Process timed out`,t.completedAt=Date.now())},n||3e5).unref()}function ft(e,t,n,s){let o=`job-${Date.now().toString(36)}-${Math.random().toString(36).slice(2,6)}`,r={id:o,command:`${e} ${t.join(" ")}`,description:n,status:"running",output:"",exitCode:null,startedAt:Date.now(),completedAt:null};kn.set(o,r);let i=Em(e,t,{cwd:s?.cwd,stdio:[s?.stdin?"pipe":"ignore","pipe","pipe"],env:{...process.env,...s?.env},shell:process.platform==="win32"});return s?.stdin&&i.stdin&&(i.stdin.write(s.stdin),i.stdin.end()),Dx(i,r,s?.timeout),o}function Jr(e){return kn.get(e)}function jx(){let e=Date.now()-18e5;for(let[t,n]of kn)n.completedAt&&n.completedAt<e&&kn.delete(t)}setInterval(jx,600*1e3).unref();function Hr(e,t,n,s){let o=`job-${Date.now().toString(36)}-${Math.random().toString(36).slice(2,6)}`,r={id:o,command:`${e} ${t.join(" ")}`,description:n,status:"running",output:"",exitCode:null,startedAt:Date.now(),completedAt:null,listeners:new Set};kn.set(o,r);let i=Em(e,t,{cwd:s?.cwd,stdio:["ignore","pipe","pipe"],env:{...process.env,...s?.env},shell:process.platform==="win32"}),a=c=>{for(let d of r.listeners)try{d(c)}catch{}};i.stdout?.on("data",c=>{let d=c.toString();r.output+=d,a(d)}),i.stderr?.on("data",c=>{let d=c.toString();r.output+=d,a(d)}),i.on("close",c=>{r.status=c===0?"completed":"failed",r.exitCode=c,r.completedAt=Date.now(),r.listeners.clear()}),i.on("error",c=>{r.status="failed",r.output+=`
|
|
2805
|
+
Process error: ${c.message}`,r.completedAt=Date.now(),r.listeners.clear()});let l=s?.timeout||3e5;return setTimeout(()=>{r.status==="running"&&(i.kill(),r.status="failed",r.output+=`
|
|
2806
|
+
Process timed out`,r.completedAt=Date.now(),r.listeners.clear())},l).unref(),o}function Im(e,t){let n=kn.get(e);if(!n||!("listeners"in n))return;let s=n;if(s.output)try{t(s.output)}catch{}s.listeners.add(t)}function Mm(e,t){let n=kn.get(e);!n||!("listeners"in n)||n.listeners.delete(t)}var as={data:{},ts:0},Hx=600*1e3,ol={"claude-code":[{id:"claude-opus-4-8",label:"Claude Opus 4.8"},{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-8",label:"Claude Opus 4.8"},{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-8",label:"Claude Opus 4.8"},{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"}]},Nm={anthropic:[{id:"claude-sonnet-4-6",label:"Claude Sonnet 4.6 (default)"},{id:"claude-opus-4-8",label:"Claude Opus 4.8"},{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"}]},Dm=/^(gpt-[45](\.\d+)?(-[a-z0-9-]+)?|o[1-4](-(mini|pro|nano)(-high)?)?|codex(-[a-z0-9-]+)?)$/,Ux=Dm;function Gx(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,r=>r.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}var jm=2500;async function rl(e,t={},n=jm){let s=new AbortController,o=setTimeout(()=>s.abort(),n);try{return await fetch(e,{...t,signal:s.signal})}finally{clearTimeout(o)}}async function Wx(e){let t=await rl("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 Kx(e){let t=await rl("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:Gx(n)}))}async function Vx(e){let t=await rl(`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 zx(e=!1){if(!e&&Date.now()-as.ts<Hx&&Object.keys(as.data).length>0)return as.data;let t=$(),n={...ol},s=[],o=De("anthropic-api",t);o&&s.push(Wx(o).then(c=>{c.length&&(n["anthropic-api"]=c,n["claude-oauth"]=c,n["claude-code"]=c)}).catch(()=>{}));let r=De("openai-api",t);r&&s.push(Kx(r).then(c=>{if(!c.length)return;let d=Om(c,Dm);d.length&&(n["openai-api"]=d);let u=Om(c,Ux);u.length&&(n["codex-cli"]=u)}).catch(()=>{}));let i=De("gemini-api",t);i&&s.push(Vx(i).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,jm+500))]);let l=t.langdockProvider||"anthropic";return n["langdock-api"]=Nm[l]||Nm.anthropic,a&&(as.data=n,as.ts=Date.now()),n}function Lm(e){let t=Gl(),n=$(),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};m(e,200,{version:Mt(),environment:t,config:s,models:ol,sessionCount:Wn().length,localThemeCount:Br().length})}function Bm(e,t){let n=/[?&]refresh=1\b/.test(e.url||"");zx(n).then(s=>m(t,200,{models:s})).catch(()=>m(t,200,{models:ol}))}var qx=60*1e3,Fm={ai:{data:{},ts:0},platform:{data:{},ts:0},all:{data:{},ts:0}};function Jm(e,t){let n=new URL(e.url||"/","http://localhost"),s=n.searchParams.get("group")||"all",o=s==="ai"||s==="platform"?s:"all",r=n.searchParams.get("refresh")==="1",i=Fm[o];if(!r&&Date.now()-i.ts<qx&&Object.keys(i.data).length>0){m(t,200,{...i.data,group:o,cached:!0});return}let a;if(o==="ai"){let l=Wl();a={tools:{claudeCode:l.claudeCode,geminiCli:l.geminiCli,codexCli:l.codexCli,claudeOAuth:l.claudeOAuth},availableEngines:l.availableEngines}}else if(o==="platform")a={tools:Kl()};else{let l=To();a={tools:l.tools,availableEngines:l.availableEngines}}Fm[o]={data:a,ts:Date.now()},m(t,200,{...a,group:o,cached:!1})}function Hm(e,t){G(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)){m(t,400,{error:`Invalid engine: ${s}`});return}let i={aiEngine:s};if(o)switch(s){case"claude-code":i.claudeCodeModel=o;break;case"anthropic-api":case"claude-oauth":i.anthropicApiModel=o;break;case"openai-api":i.openaiApiModel=o;break;case"codex-cli":i.codexCliModel=o;break;case"gemini-cli":i.geminiCliModel=o;break;case"gemini-api":i.geminiApiModel=o;break;case"langdock-api":i.langdockApiModel=o;break}Y(i),m(t,200,{ok:!0,engine:s})}catch(s){m(t,400,{error:N(s)})}})}function Um(e,t){G(e,n=>{try{let{provider:s,apiKey:o}=JSON.parse(n);if(!s||typeof s!="string"){m(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:m(t,400,{error:`Unknown provider: ${s}`});return}Y(l),m(t,200,{ok:!0,provider:s,deleted:!0});return}let r={};switch(s){case"anthropic":r.anthropicApiKey=o;break;case"openai":r.openaiApiKey=o;break;case"gemini":r.geminiApiKey=o;break;case"langdock":r.langdockApiKey=o;break;case"figma":r.figmaToken=o;break;case"langfuse-public":r.langfusePublicKey=o;break;case"langfuse-secret":r.langfuseSecretKey=o;break;default:m(t,400,{error:`Unknown provider: ${s}`});return}Y(r);let i=null;if(!$().aiEngine){let c={anthropic:"anthropic-api",openai:"openai-api",gemini:"gemini-api",langdock:"langdock-api"}[s];c&&(Y({aiEngine:c}),i=c)}m(t,200,{ok:!0,provider:s,autoSelectedEngine:i})}catch(s){m(t,400,{error:N(s)})}})}function Gm(e,t){G(e,n=>{try{let{tool:s}=JSON.parse(n),o={hubspot:{cmd:"npm",args:["install","-g","@hubspot/cli"],desc:"Installing HubSpot CLI"},claude:{cmd:"npm",args:["install","-g","@anthropic-ai/claude-code"],desc:"Installing Claude Code"},gemini:{cmd:"npm",args:["install","-g","@google/gemini-cli"],desc:"Installing Gemini CLI"},codex:process.platform==="darwin"?{cmd:"brew",args:["install","--cask","codex"],desc:"Installing OpenAI Codex"}:{cmd:"npm",args:["install","-g","@openai/codex"],desc:"Installing OpenAI Codex"},gh:process.platform==="darwin"?{cmd:"brew",args:["install","gh"],desc:"Installing GitHub CLI"}:{cmd:"npm",args:["install","-g","@cli/gh"],desc:"Installing GitHub CLI"}},r=o[s];if(!r){m(t,400,{error:`Unknown tool: ${s}. Valid: ${Object.keys(o).join(", ")}`});return}let i=ft(r.cmd,r.args,r.desc,{timeout:12e4});m(t,200,{ok:!0,jobId:i})}catch(s){m(t,400,{error:N(s)})}})}function Wm(e,t){G(e,n=>{try{let s=JSON.parse(n||"{}"),o=$(),r=o.hubspotUploadMode||"api";if(s.personalAccessKey)if(r==="api"){_o(s.personalAccessKey).then(i=>{us(s.personalAccessKey,i.portalId,i.portalName,i.dataCenter),m(t,200,{ok:!0,portalName:i.portalName,portalId:i.portalId,dataCenter:i.dataCenter})}).catch(i=>{m(t,400,{error:N(i)})});return}else{if(!St().found){m(t,400,{error:"HubSpot CLI not installed",needsInstall:!0});return}let a=ft("hs",["auth",`--pak=${s.personalAccessKey}`],"Authenticating with HubSpot",{timeout:3e4});m(t,200,{ok:!0,jobId:a});return}if(r==="api"){let i=o.hubspotAccounts||[];if(i.length>0&&!s.force){let a=i.find(l=>l.portalId===o.activeHubSpotAccount)||i[0];m(t,200,{ok:!0,alreadyAuthenticated:!0,portalName:a.portalName,portalId:a.portalId});return}}else{if(!St().found){m(t,400,{error:"HubSpot CLI not installed",needsInstall:!0});return}let a=vt();if(a.authenticated&&!s.force){m(t,200,{ok:!0,alreadyAuthenticated:!0,portalName:a.portalName,portalId:a.portalId});return}}m(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){m(t,500,{error:N(s)})}})}function Km(e,t){G(e,n=>{try{let s=JSON.parse(n||"{}");if(!wo().found){m(t,400,{error:"GitHub CLI not installed",needsInstall:!0});return}let r=ko();if(r.authenticated&&!s.force){m(t,200,{ok:!0,alreadyAuthenticated:!0,username:r.username});return}if(s.token){let a=ft("gh",["auth","login","--with-token"],"Authenticating with GitHub",{timeout:3e4,stdin:s.token});m(t,200,{ok:!0,jobId:a});return}let i=ft("gh",["auth","login","--web","--git-protocol","https"],"GitHub authentication (check your browser)",{timeout:3e5});m(t,200,{ok:!0,jobId:i,browserAuthRequired:!0})}catch(s){m(t,500,{error:N(s)})}})}function Vm(e,t){G(e,n=>{try{let{portalId:s,action:o}=JSON.parse(n);if(($().hubspotUploadMode||"api")==="api"){if(o==="remove"&&s){fi(s),m(t,200,{ok:!0});return}if(s){hi(s),m(t,200,{ok:!0});return}}else{if(!St().found){m(t,400,{error:"HubSpot CLI not installed"});return}let l=String(s).replace(/[^0-9]/g,"");if(!l){m(t,400,{error:"Invalid portalId"});return}if(o==="remove"){let c=ft("hs",["accounts","remove",l],`Removing HubSpot account ${l}`,{timeout:15e3});m(t,200,{ok:!0,jobId:c});return}if(l){let c=ft("hs",["accounts","use",l],`Switching to HubSpot account ${l}`,{timeout:15e3});m(t,200,{ok:!0,jobId:c});return}}m(t,400,{error:"portalId required"})}catch(s){m(t,500,{error:N(s)})}})}function zm(e){let t=ft("gh",["auth","logout","--hostname","github.com","-y"],"Logging out of GitHub",{timeout:15e3});m(e,200,{ok:!0,jobId:t})}function qm(e,t){G(e,n=>{try{let{cli:s,apiKey:o}=JSON.parse(n||"{}");switch(s){case"claude":{let r=ft("claude",["--print","-p","reply OK"],"Authenticating Claude Code (check your browser if prompted)",{timeout:12e4,env:{CLAUDECODE:""}});m(t,200,{ok:!0,jobId:r,hint:"If Claude Code opens a browser window, complete the sign-in there."});break}case"gemini":{let r=ft("gemini",["-p","reply OK"],"Authenticating Gemini CLI (check your browser if prompted)",{timeout:12e4});m(t,200,{ok:!0,jobId:r,hint:"If Gemini opens a browser window, complete the sign-in there."});break}case"codex":{if(o&&o.trim()){let r=o.trim();if(process.env.OPENAI_API_KEY=r,Y({openaiApiKey:r}),process.platform!=="win32"){let i=/^[A-Za-z0-9_\-.:]+$/.test(r)?r:"";if(i){let a=`export OPENAI_API_KEY="${i}"`,l=process.env.SHELL?.includes("zsh")?$m(Rm(),".zshrc"):$m(Rm(),".bashrc");try{(Lx(l)?Bx(l,"utf-8"):"").includes("OPENAI_API_KEY")||Jx(l,`
|
|
2807
|
+
# Added by vibeSpot
|
|
2808
|
+
${a}
|
|
2809
|
+
`)}catch{}}}m(t,200,{ok:!0,message:"API key saved"})}else{let r=ft("codex",["login"],"Authenticating Codex CLI (check your browser if prompted)",{timeout:12e4});m(t,200,{ok:!0,jobId:r,hint:"Complete the sign-in in your browser."})}break}default:m(t,400,{error:`Unknown CLI: ${s}`})}}catch(s){m(t,400,{error:N(s)})}})}function Ym(e,t){G(e,n=>{try{let{mode:s}=JSON.parse(n);if(s!=="api"&&s!=="cli"){m(t,400,{error:`Invalid mode: ${s}. Must be "api" or "cli".`});return}Y({hubspotUploadMode:s}),m(t,200,{ok:!0,mode:s})}catch(s){m(t,400,{error:N(s)})}})}function Xm(e,t){G(e,n=>{try{let{toolId:s,enabled:o}=JSON.parse(n);if(!s||typeof o!="boolean"){m(t,400,{error:"toolId (string) and enabled (boolean) required"});return}yi(s,o),m(t,200,{ok:!0,toolId:s,enabled:o})}catch(s){m(t,400,{error:N(s)})}})}function Zm(e,t){G(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)){m(t,400,{error:"extendedThinkingBudget must be 'low' | 'medium' | 'high'"});return}if(s.langfuseEnabled!==void 0&&typeof s.langfuseEnabled!="boolean"){m(t,400,{error:"langfuseEnabled must be a boolean"});return}if(s.langfuseBaseUrl!==void 0&&typeof s.langfuseBaseUrl!="string"){m(t,400,{error:"langfuseBaseUrl must be a string"});return}if(s.langdockProvider!==void 0&&!["anthropic","openai","google","mistral"].includes(s.langdockProvider)){m(t,400,{error:"langdockProvider must be 'anthropic' | 'openai' | 'google' | 'mistral'"});return}let r={};for(let i of o)i in s&&(r[i]=s[i]);if(r.langdockProvider){let i={anthropic:"claude-sonnet-4-6",openai:"gpt-4.1",google:"gemini-2.5-pro",mistral:"mistral-large-latest"};r.langdockApiModel=i[r.langdockProvider]||"",as.ts=0}if(Object.keys(r).length===0){m(t,400,{error:"No valid settings fields provided"});return}Y(r),m(t,200,{ok:!0,updated:Object.keys(r)})}catch(s){m(t,400,{error:N(s)})}})}function Qm(e,t){let n=e.replace("/api/settings/job/","");if(!n){m(t,400,{error:"Job ID required"});return}let s=Jr(n);if(!s){m(t,404,{error:"Job not found"});return}m(t,200,{id:s.id,status:s.status,description:s.description,output:s.output,exitCode:s.exitCode,startedAt:s.startedAt,completedAt:s.completedAt})}y();ae();te();Re();import{readFileSync as Yx}from"fs";function Xx(){try{let e=Yx(Kt("whats-new.json"),"utf8"),t=JSON.parse(e);return!t||typeof t.version!="string"||!Array.isArray(t.highlights)?null:t}catch{return null}}function eg(e){let t=Xx(),n=Mt(),s=$().lastSeenVersion,o=!!t&&t.highlights.length>0&&t.version===n&&t.version!==s;m(e,200,{show:o,content:t||null,currentVersion:n})}function tg(e,t){G(e,n=>{let s=Mt();try{if(n){let o=JSON.parse(n);o&&typeof o.version=="string"&&o.version&&(s=o.version)}}catch{}Y({lastSeenVersion:s}),m(t,200,{ok:!0,lastSeenVersion:s})})}function ng(e){m(e,200,{changelog:$l()})}y();At();Re();te();$t();function sg(e,t){G(e,n=>{try{let{access_token:s,refresh_token:o}=JSON.parse(n);if(!s||typeof s!="string"){m(t,400,{error:"access_token is required"});return}wi(s.trim(),(o||"").trim());let r=$();(!r.aiEngine||r.aiEngine!=="claude-oauth")&&Y({aiEngine:"claude-oauth"}),m(t,200,{ok:!0})}catch(s){m(t,400,{error:N(s)})}})}function og(e,t){let n=Qe(),s=rn();m(t,200,{authenticated:n,expiresAt:s?.expiresAt||null})}function rg(e,t){try{ps(),$().aiEngine==="claude-oauth"&&Y({aiEngine:void 0}),m(t,200,{ok:!0})}catch(n){m(t,500,{error:N(n)})}}y();At();Re();me();import{existsSync as Zx,rmSync as Qx}from"fs";import{join as ew}from"path";function ig(e,t,n){if(e==="GET"){let s=x(),o=Wn().sort((r,i)=>i.updatedAt-r.updatedAt);m(n,200,{activeTheme:s?{id:s.id,themeName:s.themeName,isImported:!!s.isImported}:null,sessions:o});return}if(e==="DELETE"){G(t,s=>{try{let{sessionId:o,deleteFiles:r}=JSON.parse(s);td(o,r),m(n,200,{ok:!0})}catch(o){m(n,500,{error:N(o)})}});return}m(n,405,{error:"Method not allowed"})}function ag(e,t){G(e,n=>{try{let{sessionId:s}=JSON.parse(n),o=Rs(s);if(!o){m(t,404,{error:"Session not found"});return}m(t,200,{ok:!0,themeName:o.themeName,themePath:o.themePath})}catch(s){m(t,500,{error:N(s)})}})}function lg(e,t){G(e,n=>{try{let{themeName:s}=JSON.parse(n);if(!s||typeof s!="string"){m(t,400,{error:"Theme name is required"});return}if(/[\/\\]|\.\./.test(s)||s==="."||!s.replace(/[^a-z0-9]/gi,"")){m(t,400,{error:"Invalid theme name"});return}let o=ew(gt,s);if(!Zx(o)){m(t,404,{error:"Theme not found on disk"});return}Qx(o,{recursive:!0,force:!0}),m(t,200,{ok:!0})}catch(s){m(t,500,{error:N(s)})}})}function cg(e,t){G(e,n=>{try{let{sessionId:s,newName:o}=JSON.parse(n);if(!s||!o||typeof o!="string"){m(t,400,{error:"sessionId and newName are required"});return}let r=o.toLowerCase().replace(/[^a-z0-9-]/g,"-").replace(/^-|-$/g,"").replace(/-{2,}/g,"-");if(!r){m(t,400,{error:"Invalid name"});return}let i=nd(s,r);i.ok?m(t,200,{ok:!0,newName:r}):m(t,400,{error:i.error})}catch(s){m(t,500,{error:N(s)})}})}function dg(e,t){G(e,n=>{try{let{sessionId:s}=JSON.parse(n);if(!s){m(t,400,{error:"sessionId is required"});return}let o=sd(s);o.ok?m(t,200,{ok:!0,newName:o.newName,newSessionId:o.newSessionId}):m(t,400,{error:o.error})}catch(s){m(t,500,{error:N(s)})}})}y();At();Re();re();Ue();te();xs();me();ae();import{existsSync as Ur,readFileSync as tw,readdirSync as nw,rmSync as fg}from"fs";import{join as Oe,basename as sw,relative as ow,sep as rw}from"path";import iw from"jszip";import aw from"busboy";function hg(e){let t=x();if(!t){m(e,404,{error:"No active session"});return}let n=Lt();m(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}})}var lw=new Set([".git",".vibespot","node_modules"]);function yg(e,t=[]){for(let n of nw(e,{withFileTypes:!0}))if(n.isDirectory()){if(lw.has(n.name))continue;yg(Oe(e,n.name),t)}else n.isFile()&&t.push(Oe(e,n.name));return t}async function bg(e){let t=x();if(!t){m(e,404,{error:"No active session"});return}let n=t.themePath;if(!Ur(n)){m(e,404,{error:"Theme directory not found"});return}let s=t.themeName||"theme",o=sw(n);try{let r=new iw;for(let a of yg(n)){let l=Oe(o,ow(n,a)).split(rw).join("/");r.file(l,tw(a))}let i=await r.generateAsync({type:"nodebuffer",compression:"DEFLATE",compressionOptions:{level:6}});e.writeHead(200,{"Content-Type":"application/zip","Content-Disposition":`attachment; filename="${s}.zip"`,"Content-Length":i.length}),e.end(i)}catch(r){A.error("download-zip","Failed to create zip archive",r),m(e,500,{error:"Failed to create zip archive"})}}function Sg(e,t,n){let s=x();if(!s){m(n,404,{error:"No active session"});return}if(e==="GET"){m(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"){G(t,o=>{try{let{pageType:r,label:i}=JSON.parse(o);if(!r||!i){m(n,400,{error:"pageType and label are required"});return}if(!["landing_page","blog_post","website_page","module_only","email"].includes(r)){m(n,400,{error:`Invalid pageType: ${r}`});return}let l=r==="email",d=jt(l?"module_only":r,i,l?"email":void 0);l&&s.themePath&&jn(s.themePath,s.themeName),D(),m(n,200,{ok:!0,template:{id:d.id,label:d.label,pageType:d.pageType}})}catch(r){m(n,500,{error:N(r)})}});return}if(e==="DELETE"){G(t,o=>{try{let{templateId:r,deleteModules:i}=JSON.parse(o);if(!r){m(n,400,{error:"templateId is required"});return}if(!qc(r,!!i)){m(n,404,{error:"Template not found"});return}D(),m(n,200,{ok:!0})}catch(r){m(n,500,{error:N(r)})}});return}m(n,405,{error:"Method not allowed"})}function vg(e,t){G(e,n=>{try{let{templateId:s}=JSON.parse(n);if(!s){m(t,400,{error:"templateId is required"});return}if(!Es(s)){m(t,404,{error:"Template not found"});return}D();let r=x();m(t,200,{ok:!0,modules:pe().map(i=>i.moduleName),messageCount:r?.messages.length||0})}catch(s){m(t,500,{error:N(s)})}})}function xg(e,t){G(e,n=>{try{let{templateId:s,newLabel:o}=JSON.parse(n);if(!s||!o||typeof o!="string"){m(t,400,{error:"templateId and newLabel are required"});return}if(!zc(s,o.trim())){m(t,404,{error:"Template not found"});return}D(),m(t,200,{ok:!0,newLabel:o.trim()})}catch(s){m(t,500,{error:N(s)})}})}function wg(e,t){G(e,n=>{try{let{templateIds:s}=JSON.parse(n);if(!Array.isArray(s)||s.some(r=>typeof r!="string")){m(t,400,{error:"templateIds must be an array of strings"});return}if(!Vc(s)){m(t,400,{error:"Reorder rejected (length mismatch or no session)"});return}D(),m(t,200,{ok:!0})}catch(s){m(t,500,{error:N(s)})}})}function kg(e,t){G(e,n=>{try{let{templateId:s,label:o}=JSON.parse(n);if(!s){m(t,400,{error:"templateId is required"});return}let r=Kc(s,o);if(!r){m(t,404,{error:"Template not found"});return}D(),m(t,200,{ok:!0,template:{id:r.id,label:r.label,pageType:r.pageType,moduleCount:r.modules.length}})}catch(s){m(t,500,{error:N(s)})}})}function Cg(e){let t=Lt();m(e,200,{modules:t.map(n=>({moduleName:n.module.moduleName,usedIn:n.usedIn,fieldsJson:n.module.fieldsJson}))})}function Tg(e,t,n){let s=x();if(!s){m(n,404,{error:"No active session"});return}G(t,o=>{try{let{moduleName:r}=JSON.parse(o);if(!r){m(n,400,{error:"moduleName is required"});return}let a=Lt().find(d=>d.module.moduleName===r);if(!a){m(n,404,{error:`Module "${r}" not found in library`});return}let l={...a.module};s.modules.find(d=>d.moduleName===l.moduleName)||(s.modules.push(l),s.moduleOrder.push(l.moduleName),s.updatedAt=Date.now()),D(),m(n,200,{ok:!0})}catch(r){m(n,500,{error:N(r)})}})}function Ag(e,t,n){let s=x();if(!s){m(n,404,{error:"No active session"});return}if(e==="GET"){m(n,200,{styleguide:s.brandAssets?.styleguide||null,brandvoice:s.brandAssets?.brandvoice||null,themeContext:s.brandAssets?.themeContext||null});return}if(e==="POST"){if((t.headers["content-type"]||"").includes("multipart/form-data")){dw(s,t,n);return}G(t,r=>{try{let{type:i,content:a}=JSON.parse(r);if(!i){m(n,400,{error:"type is required"});return}if(i==="humanify"){s.brandAssets||(s.brandAssets={}),s.brandAssets.humanify=a==="on",s.updatedAt=Date.now(),D(),m(n,200,{ok:!0});return}if(!a){m(n,400,{error:"content is required"});return}if(!_g(i)){m(n,400,{error:`Invalid type: ${i}. Must be "styleguide", "brandvoice", or "themeContext"`});return}Pg(s,i,a,n)}catch(i){m(n,500,{error:N(i)})}});return}if(e==="DELETE"){G(t,o=>{try{let{type:r}=JSON.parse(o);if(r!=="styleguide"&&r!=="brandvoice"&&r!=="themeContext"){m(n,400,{error:`Invalid type: ${r}`});return}let i=r;s.brandAssets&&delete s.brandAssets[i],s.updatedAt=Date.now();let a=i==="themeContext"?"theme-context.md":`${i}.md`,l=Oe(s.themePath,".vibespot",a);Ur(l)&&fg(l),D(),m(n,200,{ok:!0})}catch(r){m(n,500,{error:N(r)})}});return}m(n,405,{error:"Method not allowed"})}var cw=1024*1024;function _g(e){return e==="styleguide"||e==="brandvoice"||e==="themeContext"}function Pg(e,t,n,s){e.brandAssets||(e.brandAssets={});let o=t==="themeContext"?"theme-context.md":`${t}.md`;e.brandAssets[t]=n,e.updatedAt=Date.now();let r=Oe(e.themePath,".vibespot");$e(r),U(Oe(r,o),n);let i=null;t==="styleguide"&&(i=il(e,n)),D(),m(s,200,{ok:!0,brandKit:i})}function dw(e,t,n){let s;try{s=aw({headers:t.headers,limits:{fileSize:cw,files:1,fields:5}})}catch{m(n,400,{error:"Malformed upload"});return}let o="",r=[],i=!1,a=!1,l=!1,c=(d,u)=>{l||(l=!0,m(n,d,{error:u}))};s.on("field",(d,u)=>{d==="type"&&(o=u)}),s.on("file",(d,u)=>{i=!0,u.on("data",p=>r.push(p)),u.on("limit",()=>{a=!0,u.resume()})}),s.on("finish",()=>{if(!l)try{if(!_g(o)){c(400,`Invalid type: ${o||"(missing)"}. Must be "styleguide", "brandvoice", or "themeContext"`);return}if(!i){c(400,"file is required");return}if(a){c(413,"File too large \u2014 brand assets are text files up to 1 MB.");return}let d=Buffer.concat(r);if(d.length===0){c(400,"content is required");return}if(d.includes(0)){c(400,"File doesn't look like plain text. Please upload a UTF-8 .md or .txt file.");return}let u;try{u=new TextDecoder("utf-8",{fatal:!0}).decode(d)}catch{c(400,"File is not valid UTF-8 text. Please upload a UTF-8 .md or .txt file.");return}l=!0,Pg(e,o,u,n)}catch(d){c(500,N(d))}}),s.on("error",()=>c(400,"Upload failed")),t.pipe(s)}var Eg=[{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"}];function Ig(e,t){m(t,200,Eg)}var uw=/#[0-9a-fA-F]{6}\b/g,ug=/font[- ]?famil(?:y|ies)\s*[:=]\s*([^\n]+)/gi;function pw(e){let t=[],n=[],s=e.split(`
|
|
2810
|
+
`),o=!1,r=!1;for(let i of s){let a=i.trim();if(/^##\s+color/i.test(a)){o=!0,r=!1;continue}if(/^##\s+typography/i.test(a)){r=!0,o=!1;continue}if(/^##\s+/.test(a)&&!(/color/i.test(a)||/typography/i.test(a))){o=!1,r=!1;continue}if(o){let l=a.match(uw);if(l)for(let c of l)t.includes(c.toLowerCase())||t.push(c.toLowerCase())}if(r){let l=ug.exec(a);if(ug.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 il(e,t){let{colors:n,fonts:s}=pw(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 i=a=>{let l=a.toLowerCase(),c=Eg.find(d=>d.name.toLowerCase()===l);return c?c.stack:a};s[0]&&(o.fonts.heading=i(s[0])),s[1]?o.fonts.body=i(s[1]):s[0]&&(o.fonts.body=i(s[0]))}e.brandAssets.brandKit=o;let r=Oe(e.themePath,".vibespot");return $e(r),U(Oe(r,"brand-kit.json"),JSON.stringify(o,null,2)),o}var mw=/^#[0-9a-fA-F]{6}$/;function Mg(e,t,n){let s=x();if(!s){m(n,404,{error:"No active session"});return}if(e==="GET"){m(n,200,s.brandAssets?.brandKit||{});return}if(e==="POST"){G(t,o=>{try{let r=JSON.parse(o);s.brandAssets||(s.brandAssets={});let i={};if(r.colors&&typeof r.colors=="object"){let l={};for(let c of["primary","secondary","accent"])typeof r.colors[c]=="string"&&mw.test(r.colors[c])&&(l[c]=r.colors[c]);Object.keys(l).length>0&&(i.colors=l)}if(r.fonts&&typeof r.fonts=="object"){let l={};for(let c of["heading","body"])typeof r.fonts[c]=="string"&&r.fonts[c].trim()&&(l[c]=r.fonts[c].trim());Object.keys(l).length>0&&(i.fonts=l)}typeof r.logoUrl=="string"&&r.logoUrl.trim()&&(i.logoUrl=r.logoUrl.trim()),s.brandAssets.brandKit=i,s.updatedAt=Date.now();let a=Oe(s.themePath,".vibespot");$e(a),U(Oe(a,"brand-kit.json"),JSON.stringify(i,null,2)),D(),m(n,200,{ok:!0,brandKit:i})}catch(r){m(n,500,{error:N(r)})}});return}if(e==="DELETE"){s.brandAssets&&delete s.brandAssets.brandKit,s.updatedAt=Date.now();let o=Oe(s.themePath,".vibespot","brand-kit.json");Ur(o)&&fg(o),D(),m(n,200,{ok:!0});return}m(n,405,{error:"Method not allowed"})}function pg(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");$e(o),U(Oe(o,s),n)}function mg(e){return e==="themeContext"?"extract-theme-context":`extract-${e}`}async function gg(e,t,n){if(t==="styleguide"){let{extractDesignContext:p}=await Promise.resolve().then(()=>(no(),to));return p(n||e.themePath)}let{resolveAgenticEngine:s}=await Promise.resolve().then(()=>(os(),Ga)),{loadConfig:o}=await Promise.resolve().then(()=>(te(),Dl)),r=o(),{engine:i,apiKey:a,model:l}=s(r),{buildPreviewHtml:c}=await Promise.resolve().then(()=>(Xn(),yr)),d=c();if(!d||d.length<50)return null;if(t==="brandvoice"){let{extractBrandvoice:p}=await Promise.resolve().then(()=>(Ja(),Ba));return p(d,i,a,l)}let{extractThemeContext:u}=await Promise.resolve().then(()=>(Ir(),Er));return u(d,e.brandAssets?.themeContext,i,a,l)}function $g(e,t){let n=x();if(!n){m(t,404,{error:"No active session"});return}G(e,s=>{(async()=>{try{let o=s?JSON.parse(s):{},r=o.type||"styleguide",i=o.sourcePath;if(r==="all"){let c=["styleguide","brandvoice","themeContext"],d=await qe({name:"brand_extract",sessionId:n.themeName,metadata:{type:"all"},tags:["vibespot","brand-extract"]},()=>Promise.allSettled(c.map(g=>ce(mg(g),()=>gg(n,g,i))))),u={};for(let g=0;g<c.length;g++){let f=d[g],h=f.status==="fulfilled"?f.value:null;h&&pg(n,c[g],h),u[c[g]]=h}let p=null;u.styleguide&&(p=il(n,u.styleguide)),D(),m(t,200,{ok:!0,type:"all",extracted:u,brandKit:p});return}if(r!=="styleguide"&&r!=="brandvoice"&&r!=="themeContext"){m(t,400,{error:`Invalid type: ${r}`});return}let a=await qe({name:"brand_extract",sessionId:n.themeName,metadata:{type:r},tags:["vibespot","brand-extract"]},()=>ce(mg(r),()=>gg(n,r,i)));if(!a){m(t,200,{ok:!1,type:r,error:"No content to extract from"});return}pg(n,r,a);let l=null;r==="styleguide"&&(l=il(n,a)),D(),m(t,200,{ok:!0,type:r,content:a,brandKit:l})}catch(o){m(t,500,{error:N(o)})}})()})}function Rg(e,t){let n=x();if(!n){m(t,404,{error:"No active session"});return}G(e,s=>{(async()=>{try{let{source:o,themeName:r,localPath:i}=JSON.parse(s),a;if(o==="hubspot"){if(!r){m(t,400,{error:"themeName is required for HubSpot import"});return}let u=Je();if(!u){m(t,400,{error:"No HubSpot account connected"});return}let p=r.replace(/^\/+|\/+$/g,"");if(!p){m(t,400,{error:"Invalid theme name"});return}let g=p.replace(/[@/]/g,"_").replace(/_+/g,"_"),{homedir:f}=await import("os"),h=Oe(f(),"vibespot-themes",".references",g);$e(h);let{fetchTheme:b}=await Promise.resolve().then(()=>($o(),rc));await b(u,p,h),a=h}else if(o==="local"){if(!i){m(t,400,{error:"localPath is required for local import"});return}if(!Ur(i)){m(t,400,{error:`Path not found: ${i}`});return}a=i}else{m(t,400,{error:"source must be 'hubspot' or 'local'"});return}let{extractDesignContext:l}=await Promise.resolve().then(()=>(no(),to)),c=await qe({name:"brand_extract",sessionId:n.themeName,metadata:{type:"styleguide",source:o},tags:["vibespot","brand-extract"]},()=>ce("extract-styleguide",()=>l(a)));n.brandAssets||(n.brandAssets={}),n.brandAssets.styleguide=c,n.updatedAt=Date.now();let d=Oe(n.themePath,".vibespot");$e(d),U(Oe(d,"styleguide.md"),c),D(),m(t,200,{ok:!0,styleguide:c,source:a})}catch(o){m(t,500,{error:N(o)})}})()})}y();At();Re();me();import{join as gw}from"path";Hn();function Ng(e,t){let n=x();if(!n){m(t,404,{error:"No active session"});return}m(t,200,{id:n.id,themeName:n.themeName,themePath:n.themePath,messageCount:n.messages.length,moduleCount:n.modules.length,moduleOrder:n.moduleOrder})}function Og(e,t,n){let s=x();if(!s){m(n,404,{error:"No active session"});return}if(e==="GET"){let o=pe();m(n,200,{modules:o.map(r=>({moduleName:r.moduleName,fieldsJson:r.fieldsJson,moduleHtml:r.moduleHtml,moduleCss:r.moduleCss,moduleJs:r.moduleJs||null})),sharedCss:s.sharedCss,sharedJs:s.sharedJs});return}if(e==="DELETE"){Ze(t,n,o=>{o.deleteEntirely?Bc(o.moduleName):Jc(o.moduleName),D(),m(n,200,{ok:!0})});return}m(n,405,{error:"Method not allowed"})}function Fg(e,t){let n=x();if(!n){m(t,404,{error:"No active session"});return}G(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{m(t,400,{error:"Invalid shared type"});return}let c=xe();c&&(o.shared==="css"?c.sharedCss=o.content:c.sharedJs=o.content),n.updatedAt=Date.now(),lt(),D(),Ae(),m(t,200,{ok:!0});return}let{moduleName:r,fileType:i,content:a}=o;if(!r||!i){m(t,400,{error:"moduleName and fileType required"});return}let l=n.modules.find(c=>c.moduleName===r);if(!l){m(t,404,{error:`Module "${r}" not found`});return}switch(i){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{m(t,400,{error:"Invalid JSON in fields.json"});return}l.fieldsJson=a;break;default:m(t,400,{error:`Invalid fileType: ${i}`});return}n.updatedAt=Date.now(),lt(),D(),Ae(),m(t,200,{ok:!0})}catch(o){m(t,400,{error:String(o)})}})}function Dg(e,t){Ze(e,t,n=>{Array.isArray(n.order)?(Yt(n.order),D(),m(t,200,{ok:!0})):m(t,400,{error:"order must be an array"})})}async function jg(e){let t=x();if(!t){m(e,404,{error:"No active session"});return}try{Ae();let n=pr(t.themePath);if(!Dn(t.themeName)){m(e,400,{error:"Theme name contains unsupported characters and cannot be uploaded via the HubSpot CLI."});return}let s=Hr("hs",["cms","upload",t.themePath,t.themeName],"Uploading to HubSpot",{cwd:gw(t.themePath,".."),timeout:18e4});m(e,200,{ok:!0,jobId:s,fixes:n})}catch(n){m(e,500,{error:String(n)})}}function Lg(e,t){G(e,n=>{try{let{moduleName:s,fieldPath:o,value:r}=JSON.parse(n);Hc(s,o,r),D(),m(t,200,{ok:!0})}catch(s){m(t,400,{error:String(s)})}})}function Bg(e,t){G(e,n=>{try{let{url:s}=JSON.parse(n);if(!s||typeof s!="string"){m(t,400,{error:"url is required"});return}let o=nc(s),r=o.components.map(a=>`- ${a.name}: ${a.description}`).join(`
|
|
2811
|
+
`),i={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.
|
|
2812
|
+
|
|
2813
|
+
Source analysis found ${o.components.length} components:
|
|
2814
|
+
${r}
|
|
2815
|
+
|
|
2816
|
+
Design system: ${o.hasTailwind?"Tailwind CSS":"Custom CSS"}, ${o.cssVarCount} CSS variables
|
|
2817
|
+
Fonts: ${o.fonts.length>0?o.fonts.join(", "):"System fonts"}
|
|
2818
|
+
Interactions: ${o.interactions.join(", ")}
|
|
2819
|
+
|
|
2820
|
+
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.`};m(t,200,i)}catch(s){m(t,500,{error:N(s)})}})}function Jg(e,t){let n=x();if(!n){m(t,404,{error:"No active session"});return}if(!at()){m(t,200,{available:!1,commits:[]});return}let o=new URL(e.url||"/","http://localhost").searchParams.get("templateId"),r=o?Rc(n.themePath,o,50):$c(n.themePath,50);m(t,200,{available:!0,commits:r,filtered:!!o})}function Hg(e,t){G(e,n=>{try{let s=x();if(!s){m(t,404,{error:"No active session"});return}let{hash:o,templateId:r}=JSON.parse(n);if(!o||typeof o!="string"){m(t,400,{error:"Commit hash is required"});return}if(ct("assistant",`Rolled back to version ${o.slice(0,7)}.`),r){let i=s.templates.find(c=>c.id===r);if(!i){m(t,404,{error:"Template not found"});return}let a=i.moduleOrder.map(c=>`modules/${c}.module`);i.templateFile&&a.push(i.templateFile);let l=Oc(s.themePath,r,o,a);if(!l.success){m(t,500,{error:l.error||"Rollback failed"});return}gd()}else{let i=Nc(s.themePath,o);if(!i.success){m(t,500,{error:i.error||"Rollback failed"});return}md()}D(),m(t,200,{ok:!0,modules:pe().map(i=>i.moduleName)})}catch(s){m(t,500,{error:N(s)})}})}va();pl();y();Re();me();y();ae();import{readdirSync as fl,statSync as Lw}from"fs";import{join as Q,relative as Bw}from"path";var nn=["Business Services","Education","Events","Health & Wellness","Hospitality","Marketing & SEO","Non-profit","Portfolio","Real Estate","Restaurant & Food","Retail & E-commerce","SaaS & Technology","Travel","Other"],Jw=["label","preview_path","screenshot_path","version","documentation_url","license","example_url"],Hw=["enable_domain_stylesheets","is_available_for_new_content"],Wt="marketplace.json";function ls(e){let t=Q(e,Wt);if(!w(t))return null;try{return JSON.parse(I(t))}catch{return null}}function Yr(e,t){let n=Q(e,Wt);U(n,JSON.stringify(t,null,2)+`
|
|
2821
|
+
`)}function ao(e){let t=[];if(!w(e))return t.push({severity:"error",rule:"theme.path.missing",message:`Theme directory not found: ${e}`}),ml(e,t,null);let n=gl(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."}),ml(e,t,ls(e));Uw(e,n,t),Gw(e,n,t),Ww(e,t),Vw(e,t),zw(e,t),qw(e,t);let s=ls(e);return Yw(s,t),ml(e,t,s)}function ml(e,t,n){let s=t.filter(i=>i.severity==="error").length,o=t.filter(i=>i.severity==="warning").length,r=t.filter(i=>i.severity==="info").length;return{themePath:e,passed:s===0,errorCount:s,warningCount:o,infoCount:r,findings:t,metadata:n}}function Uw(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 i of Jw)Pt(t,i)||n.push({severity:"error",rule:`theme.json.${i}.missing`,file:"theme.json",message:`theme.json is missing required field "${i}"`,fix:s[i]??`Add a "${i}" entry to theme.json.`});for(let i of Hw)(!(i in t)||typeof t[i]!="boolean")&&n.push({severity:"error",rule:`theme.json.${i}.missing`,file:"theme.json",message:`theme.json must declare boolean "${i}"`,fix:`Add "${i}": 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.'}):(Pt(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."}),Pt(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."}),Pt(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 r=t.preview_path;if(typeof r=="string"&&r.length>0){let i=cf(e,r);w(i)||n.push({severity:"error",rule:"theme.json.preview_path.invalid",file:"theme.json",message:`preview_path "${r}" does not point to an existing file`,fix:"Update preview_path to a real template, e.g. ./templates/home.html."})}}function Gw(e,t,n){let s=t.screenshot_path;if(typeof s!="string"||s.length===0)return;let o=cf(e,s);if(!w(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 Ww(e,t){let n=Q(e,"modules");if(!w(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=fl(n)}catch{return}for(let r of o){if(!r.endsWith(".module"))continue;s++;let i=Q(n,r);Kw(e,i,r,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 Kw(e,t,n,s){let o=gl(Q(t,"meta.json")),r=ht(e,Q(t,"meta.json"));o?(Pt(o,"label")||s.push({severity:"error",rule:"module.meta.label.missing",file:r,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:r,message:`${n}: is_available_for_new_content=false (won\u2019t be selectable in HubSpot UI)`})):s.push({severity:"error",rule:"module.meta.missing",file:r,message:`${n}: meta.json is missing or invalid`,fix:"Recreate the module so meta.json is generated."});let i=Q(t,"fields.json"),a=ht(e,i);if(!w(i))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=gl(i);Array.isArray(c)?af(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");w(l)||s.push({severity:"error",rule:"module.html.missing",file:ht(e,l),message:`${n}: module.html is missing`,fix:"Recreate the module so module.html is generated."})}function af(e,t,n,s){for(let o of e){if(typeof o!="object"||o===null)continue;let r=o,i=typeof r.name=="string"?r.name:"(unnamed)";Pt(r,"label")||s.push({severity:"error",rule:"module.field.label.missing",file:n,message:`${t}.${i}: field is missing "label"`,fix:`Add a human-readable "label" to the "${i}" field in fields.json.`,autoFixable:!0}),!Pt(r,"help_text")&&r.type!=="group"&&s.push({severity:"info",rule:"module.field.help_text.missing",file:n,message:`${t}.${i}: consider adding "help_text"`,fix:`Add a short "help_text" describing what "${i}" controls.`}),Array.isArray(r.children)&&af(r.children,t,n,s)}}function Vw(e,t){let n=[],s=Q(e,"css");qr(s,".css").forEach(r=>{rf(r,n,e)});let o=Q(e,"modules");if(w(o))for(let r of lo(o)){if(!r.endsWith(".module"))continue;let i=Q(o,r);["module.css","module.html"].forEach(a=>{let l=Q(i,a);w(l)&&rf(l,n,e)})}for(let r of n)t.push({severity:"error",rule:"asset.cdn-import",file:r.file,message:`External CDN reference found: ${r.match}`,fix:"Remove external @import / <link> URLs and bundle the asset locally.",autoFixable:!0})}function rf(e,t,n){let s;try{s=I(e)}catch{return}let o=s.match(/@import\s+url\(['"]?https?:\/\/[^)\s'"]+['"]?\)/i);o&&t.push({file:ht(n,e),match:o[0]});let r=s.match(/<link[^>]+href=['"]https?:\/\/[^'"]+['"][^>]*>/i);r&&t.push({file:ht(n,e),match:r[0]});let i=s.match(/<script[^>]+src=['"]https?:\/\/[^'"]+['"][^>]*>/i);i&&t.push({file:ht(n,e),match:i[0]})}function zw(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");qr(o,".css").forEach(a=>s.push(a));let r=Q(e,"js");qr(r,".js").forEach(a=>s.push(a));let i=Q(e,"modules");if(w(i))for(let a of lo(i))a.endsWith(".module")&&["module.html","module.css","module.js"].forEach(l=>{let c=Q(i,a,l);w(c)&&s.push(c)});for(let a of s){let l;try{l=I(a)}catch{continue}for(let c of n){let d=l.match(c.re);d&&t.push({severity:"error",rule:c.rule,file:ht(e,a),message:`${c.message}: ${d[0]}`,fix:"Replace portal-specific URLs with theme-relative paths or HubSpot tokens like get_asset_url."})}}}function qw(e,t){let n=Q(e,"modules");if(w(n))for(let s of lo(n)){if(!s.endsWith(".module"))continue;let o=Q(n,s,"module.html");if(!w(o))continue;let r;try{r=I(o)}catch{continue}let i=/<img\b([^>]*)>/gi,a;for(;a=i.exec(r);){let c=a[1];/\balt\s*=/.test(c)||t.push({severity:"warning",rule:"a11y.img.alt-missing",file:ht(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(r)||t.push({severity:"info",rule:"a11y.semantics.missing",file:ht(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 Yw(e,t){if(!e){t.push({severity:"warning",rule:"marketplace.json.missing",file:Wt,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?nn.includes(e.category)||t.push({severity:"warning",rule:"marketplace.json.category.unknown",file:Wt,message:`marketplace.json category "${e.category}" is not a recognized HubSpot Marketplace category`,fix:`Use one of: ${nn.join(", ")}.`}):t.push({severity:"warning",rule:"marketplace.json.category.missing",file:Wt,message:"marketplace.json has no category",fix:`Pick one of: ${nn.join(", ")}.`}),(!e.description||e.description.trim().length<40)&&t.push({severity:"warning",rule:"marketplace.json.description.short",file:Wt,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:Wt,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:Wt,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:Wt,message:`marketplace.json has ${n} features but HubSpot allows at most 5`,fix:"Trim the features list to 5 or fewer entries."})}function Xr(e){let t=[],n=[],s=Q(e,"modules");if(w(s))for(let r of lo(s)){if(!r.endsWith(".module"))continue;let i=Q(s,r),a=r.replace(/\.module$/,""),l=Q(i,"meta.json");if(w(l))try{let d=JSON.parse(I(l));Pt(d,"label")||(d.label=df(a),U(l,JSON.stringify(d,null,2)+`
|
|
2822
|
+
`),t.push(`${r}: filled meta.label = "${d.label}"`))}catch{n.push(`${r}: meta.json could not be parsed`)}let c=Q(i,"fields.json");if(w(c))try{let d=JSON.parse(I(c));if(Array.isArray(d)){let u=lf(d);u>0&&(U(c,JSON.stringify(d,null,2)+`
|
|
2823
|
+
`),t.push(`${r}: filled ${u} missing field label(s)`))}}catch{n.push(`${r}: fields.json could not be parsed`)}}let o=Xw(e);for(let r of o)t.push(`${r}: stripped external CDN reference(s)`);return{applied:t,skipped:n}}function Xw(e){let t=[],n=/@import\s+url\(['"]?https?:\/\/[^)]+['"]?\)\s*;?/gi,s=/<link[^>]+href=['"]https?:\/\/[^'"]+['"][^>]*>/gi,o=/<script[^>]+src=['"]https?:\/\/[^'"]+['"][^>]*><\/script>/gi,r=/<script[^>]+src=['"]https?:\/\/[^'"]+['"][^>]*\/>/gi;function i(c){let d;try{d=I(c)}catch{return}let u=d.replace(n,"");u!==d&&(U(c,u),t.push(ht(e,c)))}function a(c){let d;try{d=I(c)}catch{return}let u=d.replace(s,"");u=u.replace(o,""),u=u.replace(r,""),u=u.replace(n,""),u!==d&&(U(c,u),t.push(ht(e,c)))}qr(Q(e,"css"),".css").forEach(i);let l=Q(e,"modules");if(w(l))for(let c of lo(l)){if(!c.endsWith(".module"))continue;let d=Q(l,c),u=Q(d,"module.css"),p=Q(d,"module.html");w(u)&&i(u),w(p)&&a(p)}return t}function lf(e){let t=0;for(let n of e){if(typeof n!="object"||n===null)continue;let s=n;!Pt(s,"label")&&Pt(s,"name")&&(s.label=df(String(s.name)),t++),Array.isArray(s.children)&&(t+=lf(s.children))}return t}function gl(e){if(!w(e))return null;try{let t=JSON.parse(I(e));return t&&typeof t=="object"?t:null}catch{return null}}function Pt(e,t){let n=e[t];return typeof n=="string"?n.trim().length>0:Array.isArray(n)?n.length>0:n!=null&&n!==""}function cf(e,t){let n=t.replace(/^\.?\//,"");return Q(e,n)}function ht(e,t){return Bw(e,t).split("\\").join("/")}function lo(e){try{return fl(e)}catch{return[]}}function qr(e,t){if(!w(e))return[];try{let n=[];for(let s of fl(e)){let o=Q(e,s);Lw(o).isFile()&&s.endsWith(t)&&n.push(o)}return n}catch{return[]}}function df(e){return e.replace(/[-_]+/g," ").split(" ").filter(Boolean).map(t=>t.charAt(0).toUpperCase()+t.slice(1)).join(" ")}function hl(e){let t=x();if(!t)return m(e,400,{error:"No active theme. Open or create a theme first."}),null;try{Ae()}catch{}return t.themePath}function uf(e,t){let n=hl(t);if(!n)return;let s=ao(n);m(t,200,{report:s,categories:nn})}function pf(e,t){let n=hl(t);if(!n)return;let s=Xr(n),o=ao(n);m(t,200,{fix:s,report:o})}function mf(e,t,n){let s=hl(n);if(s){if(e==="GET"){m(n,200,{metadata:ls(s),categories:nn});return}if(e==="POST"){Ze(t,n,o=>{let r={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(i=>typeof i=="string"&&i.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(i=>typeof i=="string"):void 0};Yr(s,r),m(n,200,{ok:!0,metadata:r})});return}m(n,405,{error:"Method not allowed"})}}y();Re();me();Os();function Zw(e){let t=x();if(!t)return m(e,400,{error:"No active theme. Open or fetch a theme first."}),null;try{Ae()}catch{}return t.themePath}function gf(e,t){let n=Zw(t);if(!n)return;let s=er(n);m(t,200,{report:s})}function ff(e,t){let n=x();if(!n){m(t,400,{error:"No active theme. Open or fetch a theme first."});return}let s=Qt(n.themePath),o=gn(s);if(!o){m(t,200,{applied:!1,reason:"No tokens to apply."});return}if(!n.sharedCss||n.sharedCss.trim().length===0){n.sharedCss=o,n.updatedAt=Date.now(),D(),m(t,200,{applied:!0,written:"session.sharedCss",rootBlock:o});return}let r=tr(n.themePath,n.themeName);r?m(t,200,{applied:!0,written:r,rootBlock:o}):m(t,200,{applied:!1,reason:"Theme already has shared CSS."})}y();At();Re();me();Xt();te();re();import{existsSync as vf,mkdirSync as lk,writeFileSync as ck,rmSync as dk}from"fs";import{join as xf}from"path";y();import{readFileSync as Qw,readdirSync as ek,existsSync as tk}from"fs";import{dirname as nk,join as Zr}from"path";import{fileURLToPath as sk}from"url";var hf=nk(sk(import.meta.url)),ok=/^---\r?\n([\s\S]*?)\r?\n---\r?\n([\s\S]*)$/;function rk(e){let t=e.match(ok);if(!t)return null;let[,n,s]=t,o={};for(let r of n.split(/\r?\n/)){let i=r.indexOf(":");if(i===-1)continue;let a=r.slice(0,i).trim(),l=r.slice(i+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 ik(e){let t=rk(e);if(!t)return null;let{fields:n,body:s}=t,o=n.id,r=n.label,i=n.description??"";if(!o||!r)return null;let a=n.order?Number(n.order):NaN,l=n.contentType==="email"?"email":void 0;return{id:o,label:r,description:i,icon:n.icon||void 0,order:Number.isFinite(a)?a:9999,contentType:l,body:s.trimEnd()+`
|
|
2824
|
+
`}}var sn=null;function ak(){let e=[Zr(hf,"../../assets/plan-templates"),Zr(hf,"../assets/plan-templates"),Zr(process.cwd(),"assets/plan-templates")];for(let t of e)if(tk(t))return t;return null}function yf(){if(sn)return sn;let e=ak();if(!e)return sn=[],sn;let t=[],n=[];try{n=ek(e)}catch{return sn=[],sn}for(let s of n)if(s.endsWith(".md"))try{let o=Qw(Zr(e,s),"utf-8"),r=ik(o);r&&t.push(r)}catch{}return t.sort((s,o)=>s.order!==o.order?s.order-o.order:s.label.localeCompare(o.label)),sn=t,sn}function bf(e){return yf().find(t=>t.id===e)??null}function Sf(){return yf().map(({id:e,label:t,description:n,icon:s,order:o,contentType:r})=>({id:e,label:t,description:n,icon:s,order:o,contentType:r}))}var uk="plan.md";function wf(e){return xf(e,".vibespot",uk)}function Qr(e){let t=x();if(!t)return null;t.brandAssets||(t.brandAssets={}),t.brandAssets.plan=e;let n=xe();n&&(n.plan=e);try{let s=xf(t.themePath,".vibespot");vf(s)||lk(s,{recursive:!0}),ck(wf(t.themePath),e,"utf-8")}catch(s){A.warn("plan",`Failed to write plan.md: ${N(s)}`)}return D(),e}function yl(){let e=x();if(!e)return;e.brandAssets&&delete e.brandAssets.plan;let t=xe();t&&delete t.plan;try{let n=wf(e.themePath);vf(n)&&dk(n)}catch(n){A.warn("plan",`Failed to remove plan.md: ${N(n)}`)}D()}function kf(e,t){Ze(e,t,n=>{if(!x()){m(t,400,{error:"No active session"});return}let o=typeof n.markdown=="string"?n.markdown:"";if(!o.trim()){m(t,400,{error:"Plan content cannot be empty"});return}Qr(o),m(t,200,{ok:!0,plan:o})})}function Cf(e,t){Ze(e,t,()=>{yl(),Y({planMode:!1}),m(t,200,{ok:!0})})}function Tf(e,t){m(t,200,{templates:Sf()})}function Af(e,t){Ze(e,t,n=>{if(!x()){m(t,400,{error:"No active session"});return}let o=typeof n.templateId=="string"?n.templateId.trim():"";if(!o){m(t,400,{error:"templateId is required"});return}let r=bf(o);if(!r){m(t,404,{error:`Unknown plan template: ${o}`});return}Qr(r.body),Y({planMode:!0}),m(t,200,{ok:!0,templateId:r.id,label:r.label,plan:r.body})})}y();Re();hn();function _f(e,t){let n=pu();if(!n){m(t,200,{origin:null});return}if(n.publicOrigin){m(t,200,{origin:n.publicOrigin,token:n.token});return}let s=e.headers.host||`${n.host}:0`,o=s.startsWith("[")?s.slice(0,s.indexOf("]")+1):s.split(":")[0];m(t,200,{origin:`http://${o}:${n.port}`,token:n.token})}var pk={"/api/session":{handler:({method:e,res:t})=>Ng(e,t)},"/api/preview-origin":{handler:({req:e,res:t})=>_f(e,t)},"/api/modules":{handler:({method:e,req:t,res:n})=>Og(e,t,n)},"/api/modules/reorder":{handler:({req:e,res:t})=>Dg(e,t)},"/api/modules/code":{handler:({req:e,res:t})=>Fg(e,t)},"/api/upload":{handler:({res:e})=>jg(e)},"/api/upload-files":{methods:["POST"],handler:({req:e,res:t})=>Mu(e,t)},"/api/field":{handler:({req:e,res:t})=>Lg(e,t)},"/api/import":{handler:({req:e,res:t})=>Bg(e,t)},"/api/setup":{handler:({res:e})=>xm(e)},"/api/setup/create":{handler:({req:e,res:t})=>wm(e,t)},"/api/setup/fetch":{handler:({req:e,res:t})=>Cm(e,t)},"/api/setup/open":{handler:({req:e,res:t})=>Tm(e,t)},"/api/setup/resume":{handler:({req:e,res:t})=>Am(e,t)},"/api/setup/apikey":{handler:({req:e,res:t})=>_m(e,t)},"/api/setup/remote-themes":{methods:["GET"],handler:({res:e})=>Pm(e)},"/api/starters":{methods:["GET"],handler:({res:e})=>km(e)},"/api/whats-new":{methods:["GET"],handler:({res:e})=>eg(e)},"/api/whats-new/dismiss":{methods:["POST"],handler:({req:e,res:t})=>tg(e,t)},"/api/changelog":{methods:["GET"],handler:({res:e})=>ng(e)},"/api/settings/status":{methods:["GET"],handler:({res:e})=>Lm(e)},"/api/settings/models":{methods:["GET"],handler:({req:e,res:t})=>Bm(e,t)},"/api/settings/tools":{methods:["GET"],handler:({req:e,res:t})=>Jm(e,t)},"/api/settings/engine":{methods:["POST"],handler:({req:e,res:t})=>Hm(e,t)},"/api/settings/apikey":{methods:["POST"],handler:({req:e,res:t})=>Um(e,t)},"/api/settings/install":{methods:["POST"],handler:({req:e,res:t})=>Gm(e,t)},"/api/settings/hs-auth":{methods:["POST"],handler:({req:e,res:t})=>Wm(e,t)},"/api/settings/gh-auth":{methods:["POST"],handler:({req:e,res:t})=>Km(e,t)},"/api/settings/hs-switch":{methods:["POST"],handler:({req:e,res:t})=>Vm(e,t)},"/api/settings/gh-logout":{methods:["POST"],handler:({res:e})=>zm(e)},"/api/settings/cli-auth":{methods:["POST"],handler:({req:e,res:t})=>qm(e,t)},"/api/settings/hs-mode":{methods:["POST"],handler:({req:e,res:t})=>Ym(e,t)},"/api/settings/cli-toggle":{methods:["POST"],handler:({req:e,res:t})=>Xm(e,t)},"/api/settings/claude-oauth/save":{methods:["POST"],handler:({req:e,res:t})=>sg(e,t)},"/api/settings/claude-oauth/status":{methods:["GET"],handler:({req:e,res:t})=>og(e,t)},"/api/settings/claude-oauth/logout":{methods:["POST"],handler:({req:e,res:t})=>rg(e,t)},"/api/settings":{methods:["POST"],handler:({req:e,res:t})=>Zm(e,t)},"/api/themes":{handler:({method:e,req:t,res:n})=>ig(e,t,n)},"/api/themes/switch":{methods:["POST"],handler:({req:e,res:t})=>ag(e,t)},"/api/themes/delete-local":{methods:["POST"],handler:({req:e,res:t})=>lg(e,t)},"/api/themes/rename":{methods:["POST"],handler:({req:e,res:t})=>cg(e,t)},"/api/themes/duplicate":{methods:["POST"],handler:({req:e,res:t})=>dg(e,t)},"/api/history":{methods:["GET"],handler:({req:e,res:t})=>Jg(e,t)},"/api/rollback":{methods:["POST"],handler:({req:e,res:t})=>Hg(e,t)},"/api/dashboard":{methods:["GET"],handler:({res:e})=>hg(e)},"/api/templates":{handler:({method:e,req:t,res:n})=>Sg(e,t,n)},"/api/templates/activate":{methods:["POST"],handler:({req:e,res:t})=>vg(e,t)},"/api/templates/rename":{methods:["POST"],handler:({req:e,res:t})=>xg(e,t)},"/api/templates/clone":{methods:["POST"],handler:({req:e,res:t})=>kg(e,t)},"/api/templates/reorder":{methods:["POST"],handler:({req:e,res:t})=>wg(e,t)},"/api/module-library":{methods:["GET"],handler:({res:e})=>Cg(e)},"/api/brand-assets":{handler:({method:e,req:t,res:n})=>Ag(e,t,n)},"/api/brand-kit":{handler:({method:e,req:t,res:n})=>Mg(e,t,n)},"/api/fonts":{methods:["GET"],handler:({req:e,res:t})=>Ig(e,t)},"/api/brand-assets/extract":{methods:["POST"],handler:({req:e,res:t})=>$g(e,t)},"/api/brand-assets/import-reference":{methods:["POST"],handler:({req:e,res:t})=>Rg(e,t)},"/api/download-zip":{methods:["GET"],handler:({res:e})=>bg(e)},"/api/figma/test-token":{methods:["POST"],handler:({req:e,res:t})=>cl(e,t)},"/api/figma/extract":{methods:["POST"],handler:({req:e,res:t})=>dl(e,t)},"/api/figma/generate":{methods:["POST"],handler:({req:e,res:t})=>ul(e,t)},"/api/plan/edit":{methods:["POST"],handler:({req:e,res:t})=>kf(e,t)},"/api/plan/discard":{methods:["POST"],handler:({req:e,res:t})=>Cf(e,t)},"/api/plan/templates":{methods:["GET"],handler:({req:e,res:t})=>Tf(e,t)},"/api/plan/template":{methods:["POST"],handler:({req:e,res:t})=>Af(e,t)},"/api/marketplace/check":{methods:["GET"],handler:({req:e,res:t})=>uf(e,t)},"/api/marketplace/fix":{methods:["POST"],handler:({req:e,res:t})=>pf(e,t)},"/api/marketplace/listing":{handler:({method:e,req:t,res:n})=>mf(e,t,n)},"/api/inverse/analyze":{methods:["GET"],handler:({req:e,res:t})=>gf(e,t)},"/api/inverse/apply-tokens":{methods:["POST"],handler:({req:e,res:t})=>ff(e,t)}},mk=[{matches:e=>e.startsWith("/api/settings/job/"),method:"GET",handler:({path:e,res:t})=>Qm(e,t)},{matches:e=>/^\/api\/templates\/[^/]+\/add-module$/.test(e),method:"POST",handler:({path:e,req:t,res:n})=>Tg(e,t,n)}];function Pf(e,t,n,s){let o=n.headers.origin,r=br(o,n.headers.host);if(o&&r&&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, Authorization, X-Vibespot-Token"),e==="OPTIONS"){s.writeHead(204),s.end();return}if(o&&!r&&e!=="GET"&&e!=="HEAD"){m(s,403,{error:"Origin not allowed"});return}let i={method:e,path:t,req:n,res:s},a=pk[t];if(a){if(a.methods&&!a.methods.includes(e)){m(s,405,{error:"Method not allowed"});return}a.handler(i);return}for(let l of mk)if(l.method===e&&l.matches(t)){l.handler(i);return}m(s,404,{error:"Not found"})}y();me();Hn();os();Da();import{existsSync as If}from"fs";import{join as co}from"path";import{WebSocket as gk}from"ws";y();var bl=/```vibespot-plan\s*\n([\s\S]*?)```/g,Sl=/```vibespot-choices\s*\n([\s\S]*?)```/g;function Ef(e){let t,n,s;for(bl.lastIndex=0;(s=bl.exec(e))!==null;)t=s[1].trim();let o;for(Sl.lastIndex=0;(o=Sl.exec(e))!==null;)try{let i=JSON.parse(o[1].trim());i&&typeof i.question=="string"&&Array.isArray(i.options)&&i.options.every(a=>typeof a=="string")&&i.options.length>0&&(n={question:i.question,options:i.options})}catch{}return{cleanedContent:e.replace(bl,"").replace(Sl,"").replace(/\n{3,}/g,`
|
|
2825
|
+
|
|
2826
|
+
`).trim(),plan:t,choices:n}}te();At();Ue();hn();var ti=null,si=[];function X(e){ti&&ti.readyState===gk.OPEN&&ti.send(JSON.stringify(e))}function ei(e){si.push(e),X(e)}function Fe(){si=[]}function ni(e,t){return n=>{if(n.type==="module_progress"&&n.moduleFiles){let{moduleFiles:s,...o}=n;ei(o)}else ei(n);if(n.type==="agent_step")e.push({step:n.step,label:n.label});else if(n.type==="agent_decision"){let s=e[e.length-1];s&&(s.decisions||(s.decisions=[]),s.decisions.push(n.decision))}else n.type==="design_system_ready"?Ge({sharedCss:n.sharedCss,sharedJs:n.sharedJs}):n.type==="blueprint_ready"?(Ge({sharedCss:n.sharedCss,sharedJs:n.sharedJs}),Yt(n.moduleOrder),ei({type:"modules_updated",modules:pe().map(s=>s.moduleName)})):n.type==="module_progress"&&n.status==="complete"&&n.moduleFiles?(Ge({modules:[{moduleName:n.module,fieldsJson:n.moduleFiles.fieldsJson,metaJson:n.moduleFiles.metaJson,moduleHtml:n.moduleFiles.moduleHtml,moduleCss:n.moduleFiles.moduleCss,moduleJs:n.moduleFiles.moduleJs}]}),ei({type:"modules_updated",modules:pe().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 uo(e){let t=e.cost;if(!t||t.calls===0)return;let n=x();X({type:"generation_cost",cost:t,projectTotal:n?.costTotal})}function Nf(e,t){xn(e,{steps:t.steps,modules:t.modules,stats:e.stats,cost:e.cost}),uo(e);let n=x();if(n){Ae();let s=xe(),o=null;if(s){let r=s.moduleOrder.map(i=>`modules/${i}.module`);s.templateFile&&r.push(s.templateFile),s.sharedCss&&r.push(`css/${n.themeName}-theme.css`),s.sharedJs&&r.push(`js/${n.themeName}-animations.js`),o=ji(n.themePath,s.id,t.commitLabel,r)}else o=pn(n.themePath,t.commitLabel);o&&X({type:"version_created",hash:o})}X({type:"generation_complete"});{let s=x();X({type:"modules_updated",modules:pe().map(o=>o.moduleName),templateId:s?.activeTemplateId||null,templates:(s?.templates||[]).map(o=>({id:o.id,label:o.label,pageType:o.pageType,moduleCount:o.modules.length}))})}Fe()}async function Mf(e,t){ct("user",e),D();try{X({type:"stream_status",content:"Planning..."});let n="",s=await el(e,r=>{n+=r,X({type:"stream",content:r})},t),o=Ef(s||n);if(o.plan){Qr(o.plan),X({type:"plan_updated",plan:o.plan});let r=x();r&&(r.pendingCheckpoint={kind:"plan",resumeToken:"plan",preview:{kind:"plan",headline:"Plan ready for review",data:{plan:o.plan}},createdAt:new Date().toISOString()},D())}o.choices&&X({type:"plan_choices",question:o.choices.question,options:o.choices.options}),ct("assistant",o.cleanedContent),D(),X({type:"plan_complete",cleanedContent:o.cleanedContent}),X({type:"generation_complete"})}catch(n){X({type:"error",message:N(n)})}}async function $f(){let e=x();if(!e){X({type:"error",message:"No active session"});return}let t=e.brandAssets?.plan;if(!t||!t.trim()){X({type:"error",message:"No plan to approve. Send a chat message first."});return}Y({planMode:!1}),e.pendingCheckpoint?.kind==="plan"&&(e.pendingCheckpoint=void 0);let n="Implement the approved plan.";ct("user",n),D();try{Fe();let s=[],o=[],r=await Fr(n,ni(s,o));if(r.canceled){Fe();return}Nf(r,{steps:s,modules:o,commitLabel:"Approved plan: implementation"})}catch(s){Fe(),X({type:"error",message:N(s)})}}function Rf(){let e=x();e?.pendingCheckpoint?.kind==="plan"&&(e.pendingCheckpoint=void 0),yl(),Y({planMode:!1}),D(),X({type:"plan_discarded"})}function Of(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 r=Array.isArray(s.fileIds)?s.fileIds:void 0;Gt()&&Ya()&&X({type:"generation_superseded"});{let a=x();a?.pendingCheckpoint&&(Sn(a.pendingCheckpoint.resumeToken),a.pendingCheckpoint=void 0,D())}if(tl()){await Mf(o,r);break}ct("user",o),D();let i=nl();i.needsPrompt&&e.send(JSON.stringify({type:"agentic_prompt"}));try{if(i.useAgentic){Fe();let l=[],c=[],d=!s.oneShot,u=await Fr(o,ni(l,c),r,d);if(u.canceled){Fe();break}if(u.pendingCheckpoint){let p=x();p&&(p.pendingCheckpoint=u.pendingCheckpoint,D()),uo(u),Fe();break}xn(u,{steps:l,modules:c,stats:u.stats,cost:u.cost}),uo(u)}else za(l=>{X({type:"parse_warning",message:l})}),await oo(o,l=>{X({type:"stream",content:l})},l=>{X({type:"stream_status",content:l})},r);let a=x();if(a){Ae();let l=xe(),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=ji(a.themePath,l.id,o,d)}else c=pn(a.themePath,o);c&&X({type:"version_created",hash:c})}X({type:"generation_complete"});{let l=x();X({type:"modules_updated",modules:pe().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}))})}Fe();{let l=x();l&&i.useAgentic&&!l.brandAssets?.styleguide&&!l.brandAssets?.brandvoice&&!l.brandAssets?.themeContext&&X({type:"suggest_brand_extraction"})}}catch(a){Fe(),X({type:"error",message:N(a)})}break}case"figma_import":{let o=String(s.extractionId||""),r=String(s.themeName||"");if(!o||!r){e.send(JSON.stringify({type:"error",message:"Missing extractionId or themeName"}));break}let{getCachedExtraction:i}=await Promise.resolve().then(()=>(pl(),of)),a=i(o);if(!a){e.send(JSON.stringify({type:"error",message:"Extraction expired or not found. Please re-extract."}));break}try{let l=x();if(!l||l.themeName!==r){let{join:p}=await import("path"),{homedir:g}=await import("os"),{existsSync:f}=await import("fs"),{createThemeScaffold:h}=await Promise.resolve().then(()=>(xs(),sc)),b=p(g(),"vibespot-themes"),S=p(b,r);if(!f(b)){let{mkdirSync:v}=await import("fs");v(b,{recursive:!0})}f(S)||h(S,r),Gn(S,r),D()}X({type:"figma_import_started",fileName:a.fileName}),Fe();let c=[],d=[],u=await ro(a,r,ni(c,d));xn(u,{steps:c,modules:d,stats:u.stats,cost:u.cost}),uo(u),Ae(),pn(x().themePath,`Figma import: ${a.fileName}`),X({type:"generation_complete"});{let p=x();X({type:"modules_updated",modules:pe().map(g=>g.moduleName),templateId:p?.activeTemplateId||null,templates:(p?.templates||[]).map(g=>({id:g.id,label:g.label,pageType:g.pageType,moduleCount:g.modules.length}))})}Fe()}catch(l){Fe(),X({type:"error",message:N(l)})}break}case"extract_brand_assets":{let o=x();if(!o){e.send(JSON.stringify({type:"error",message:"No active session"}));break}(async()=>{try{let r=$(),{engine:i,apiKey:a,model:l}=vn(r),{buildPreviewHtml:c}=await Promise.resolve().then(()=>(Xn(),yr)),d=c();if(!d||d.length<50)return;let{extractThemeContext:u}=await Promise.resolve().then(()=>(Ir(),Er)),p=await qe({name:"brand_extract",sessionId:o.themeName,metadata:{type:"themeContext"},tags:["vibespot","brand-extract"]},()=>ce("extract-theme-context",()=>u(d,o.brandAssets?.themeContext,i,a,l))),{mkdirSync:g,writeFileSync:f}=await import("fs");if(p){o.brandAssets||(o.brandAssets={}),o.brandAssets.themeContext=p,o.updatedAt=Date.now();let h=co(o.themePath,".vibespot");If(h)||g(h,{recursive:!0}),f(co(h,"theme-context.md"),p),D(),e.send(JSON.stringify({type:"brand_asset_extracted",assetType:"themeContext"}))}if(!o.brandAssets?.styleguide)try{let{extractDesignContext:h}=await Promise.resolve().then(()=>(no(),to)),b=await qe({name:"brand_extract",sessionId:o.themeName,metadata:{type:"styleguide"},tags:["vibespot","brand-extract"]},()=>ce("extract-styleguide",()=>h(o.themePath)));if(b){o.brandAssets||(o.brandAssets={}),o.brandAssets.styleguide=b,o.updatedAt=Date.now();let S=co(o.themePath,".vibespot");If(S)||g(S,{recursive:!0}),f(co(S,"styleguide.md"),b),D(),e.send(JSON.stringify({type:"brand_asset_extracted",assetType:"styleguide"}))}}catch{}e.send(JSON.stringify({type:"brand_extraction_complete"}))}catch(r){e.send(JSON.stringify({type:"brand_extraction_error",message:N(r)}))}})();break}case"start_upload":{let o=x();if(!o){e.send(JSON.stringify({type:"error",message:"No active session"}));break}try{Ae();let r=pr(o.themePath);if(r.length>0&&e.send(JSON.stringify({type:"upload_status",phase:"autofix",fixes:r})),($().hubspotUploadMode||"api")==="api"){let l=Je();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 mr(l,o.themePath,o.themeName,{onFileStart:d=>{e.send(JSON.stringify({type:"upload_output",chunk:`Uploading ${d}
|
|
2827
|
+
`}))},onFileComplete:d=>{e.send(JSON.stringify({type:"upload_output",chunk:` \u2713 ${d}
|
|
2828
|
+
`}))},onFileError:(d,u)=>{e.send(JSON.stringify({type:"upload_output",chunk:` \u2717 ${d}: ${u.message}
|
|
2829
|
+
`}))},onProgress:(d,u)=>{e.send(JSON.stringify({type:"upload_progress",completed:d,total:u}))}});if(c.success){let d=Vt();e.send(JSON.stringify({type:"upload_complete",output:`Uploaded ${c.uploaded} files`,portalId:d?.portalId||"",dataCenter:d?.dataCenter||"na1",themeName:o.themeName,contentMode:tn()}))}else{let d=dr(c.errors);e.send(JSON.stringify({type:"upload_failed",output:c.errors.map(u=>`${u.file}: ${u.message}`).join(`
|
|
2830
|
+
`),errors:d}))}}else{if(!Dn(o.themeName)){e.send(JSON.stringify({type:"upload_failed",output:"Theme name contains unsupported characters and cannot be uploaded via the HubSpot CLI.",errors:[{file:"",message:"Unsafe theme name",fixable:!1}]}));break}let l=Hr("hs",["cms","upload",o.themePath,o.themeName],"Uploading to HubSpot",{cwd:co(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}))};Im(l,c);let d=setInterval(()=>{let u=Jr(l);if(!(!u||u.status==="running"))if(clearInterval(d),Mm(l,c),u.status==="completed"){let p=vt(),g=p.portalId?hs(p.portalId):"na1";e.send(JSON.stringify({type:"upload_complete",output:u.output,portalId:p.portalId||"",dataCenter:g,themeName:o.themeName,contentMode:tn()}))}else{let p=ur(u.output);e.send(JSON.stringify({type:"upload_failed",output:u.output,errors:p,exitCode:u.exitCode}))}},500)}}catch(r){e.send(JSON.stringify({type:"error",message:N(r)}))}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 r=`The HubSpot upload ("hs cms upload") failed. Below is the upload log output containing the errors.
|
|
2831
|
+
|
|
2832
|
+
IMPORTANT: Be verbose in your response. For each error:
|
|
2833
|
+
1. State exactly which file has the problem and what the error is
|
|
2834
|
+
2. Explain WHY this error occurs (e.g. "HubSpot doesn't support textarea field type" or "field name 'name' is reserved in HubSpot modules")
|
|
2835
|
+
3. Describe the specific fix you're applying (e.g. "Changing field type from textarea to text" or "Renaming field from 'name' to 'item_name'")
|
|
2836
|
+
4. Apply the fix to the module files
|
|
2837
|
+
|
|
2838
|
+
CRITICAL: After fixing the reported errors, scan ALL other module files in the theme for the same issues. For example, if you fix "name" \u2192 "item_name" in one module, check every other module's fields.json for the same problem. Fix all occurrences, not just the ones in the error log.
|
|
2839
|
+
|
|
2840
|
+
After fixing all errors, summarize the changes you made.
|
|
2841
|
+
|
|
2842
|
+
Upload log:
|
|
2843
|
+
${o}`;ct("user",r),D(),e.send(JSON.stringify({type:"upload_fix_started"}));try{await oo(r,a=>{e.send(JSON.stringify({type:"stream",content:a})),e.send(JSON.stringify({type:"upload_fix_stream",content:a}))});let i=x();if(i){Ae();let a=pn(i.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=x();e.send(JSON.stringify({type:"modules_updated",modules:pe().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(i){e.send(JSON.stringify({type:"upload_failed",output:N(i),errors:[{file:"AI fix",message:N(i),fixable:!1}]}))}break}case"ping":e.send(JSON.stringify({type:"pong"}));break;case"plan_approve":{await $f();break}case"plan_discard":{Rf();break}case"checkpoint_resolve":{let o=x();if(!o){e.send(JSON.stringify({type:"error",message:"No active session"}));break}let r=o.pendingCheckpoint;if(!r){e.send(JSON.stringify({type:"error",message:"No checkpoint is awaiting resolution."}));break}let i=String(s.action||"");if(!["approve","steer","skip","cancel"].includes(i)){e.send(JSON.stringify({type:"error",message:`Invalid checkpoint action: ${i}`}));break}let a=Array.isArray(s.outline)?s.outline.filter(d=>!!d&&typeof d.name=="string").map(d=>({name:String(d.name),description:typeof d.description=="string"?d.description:void 0,sourceIndex:Number.isInteger(d.sourceIndex)?d.sourceIndex:void 0})):void 0,l={kind:r.kind,action:i,note:typeof s.note=="string"?s.note:void 0,outline:a,...r.kind==="brand_intake"&&s.brandIntake&&typeof s.brandIntake=="object"?{brandIntake:s.brandIntake}:{}};if(r.kind==="plan"){o.pendingCheckpoint=void 0,D(),i==="cancel"?Rf():i==="steer"?await Mf(l.note?.trim()||"Refine the plan further."):await $f();break}let c=r.resumeToken;o.pendingCheckpoint=void 0,D();try{Fe();let d=[],u=[],p=await Qa(c,l,ni(d,u),r.resumeState);if(p.canceled){X({type:"checkpoint_cancelled"}),X({type:"generation_complete"}),Fe();break}if(p.pendingCheckpoint){let g=x();g&&(g.pendingCheckpoint=p.pendingCheckpoint,D()),uo(p),Fe();break}Nf(p,{steps:d,modules:u,commitLabel:"Checkpoint approved: implementation"})}catch(d){Fe(),X({type:"error",message:N(d)})}break}default:e.send(JSON.stringify({type:"error",message:`Unknown type: ${s.type}`}))}}),ti=e;let t=x();if(t){let n=$(),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=Gt(),r=xe();if(e.send(JSON.stringify({type:"init",sessionId:t.id,themeName:t.themeName,modules:pe().map(i=>i.moduleName),messageCount:t.messages.length,messages:t.messages,gitAvailable:at(),engine:n.aiEngine?s[n.aiEngine]||n.aiEngine:"",updatedAt:t.updatedAt,templateId:r?.id||null,pageType:r?.pageType||null,templates:(t.templates||[]).map(i=>({id:i.id,label:i.label,pageType:i.pageType,moduleCount:i.modules.length})),planMode:!!n.planMode,plan:t.brandAssets?.plan||"",isGenerating:o,pendingCheckpoint:t.pendingCheckpoint?{...t.pendingCheckpoint,resumeState:void 0}:null,costTotal:t.costTotal||null})),o&&si.length>0)for(let i of si)e.send(JSON.stringify(i))}else e.send(JSON.stringify({type:"needs_setup"}))}hn();var jf={".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"},Ke=ma();function ri(e){let{port:t,uiDir:n}=e;uu(e.contentMode||"page"),Ke=ma(e.host);let s=bu(Ke);if(s.severity==="refuse")throw new Error(s.message);s.severity==="warn"&&console.warn(s.message);let o=fk((a,l)=>yk(a,l,n)),r=new hk({server:o,verifyClient:a=>br(a.origin,a.req.headers.host)?ga(a.req,Ke).ok:!1});r.on("connection",a=>Of(a));let i=async a=>{let l=null;if(e.enablePreviewOrigin!==!1){let c=ha(process.env.VIBESPOT_PREVIEW_PUBLIC_ORIGIN,"VIBESPOT_PREVIEW_PUBLIC_ORIGIN"),d=ha(process.env.VIBESPOT_PUBLIC_ORIGIN,"VIBESPOT_PUBLIC_ORIGIN"),u=Ke.host==="127.0.0.1"||Ke.host==="localhost"||Ke.host==="::1",p=u?[`http://127.0.0.1:${a}`,`http://localhost:${a}`,...d?[d]:[]]:d?[d]:["*"];c&&!d&&!u&&console.warn("VIBESPOT_PREVIEW_PUBLIC_ORIGIN is set without VIBESPOT_PUBLIC_ORIGIN \u2014 the preview's frame-ancestors falls back to *; set VIBESPOT_PUBLIC_ORIGIN to pin embedding to your app origin."),l=await Tu({port:a+2,host:Ke.host,frameAncestors:p,uiDir:n,publicOrigin:c})}return mu(l),{port:a,host:Ke.host,authToken:Ke.authToken,previewOrigin:l,close:()=>{o.close(),r.close(),l?.close(),gu(l)}}};return new Promise((a,l)=>{o.on("error",c=>{c.code==="EADDRINUSE"?o.listen(t+1,Ke.host,()=>{i(t+1).then(a,l)}):l(c)}),o.listen(t,Ke.host,()=>{i(t).then(a,l)})})}function yk(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(o!=="OPTIONS"){let r=ga(e,Ke);if(!r.ok){s.pathname.startsWith("/api/")?m(t,401,{error:"Authentication required"}):(t.writeHead(401,{"Content-Type":"text/html; charset=utf-8"}),t.end('<!doctype html><title>vibeSpot</title><body style="font-family:system-ui;padding:2rem"><h1>Authentication required</h1><p>Open vibeSpot using the exact URL printed in the terminal where it was started (it includes a <code>?token=</code> secret).</p></body>'));return}if(r.viaQueryToken&&o==="GET"&&!s.pathname.startsWith("/api/")&&Ke.authToken){s.searchParams.delete("token"),t.writeHead(302,{"Set-Cookie":`${pa}=${Ke.authToken}; HttpOnly; SameSite=Strict; Path=/`,Location:s.pathname+s.search}),t.end();return}}if(s.pathname.startsWith("/api/")){Pf(o,s.pathname,e,t);return}if(s.pathname==="/preview"){let r=Us();t.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),t.end(r);return}if(s.pathname==="/module-preview"){let r=s.searchParams.get("module")||"",i=ua(r);t.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),t.end(i||"<!-- module not found -->");return}if(s.pathname.startsWith("/theme-assets/")){bk(s.pathname.slice(14),t);return}if(s.pathname==="/docs"){t.writeHead(301,{Location:"/docs/"}),t.end();return}if(s.pathname.startsWith("/docs/")){let r=s.pathname.slice(5)||"/index.html";Ff(r,oi(n,"docs"),e,t);return}Ff(s.pathname,n,e,t)}function bk(e,t){let n=x();if(!n){t.writeHead(404,{"Content-Type":"text/plain"}),t.end("No session");return}let s=oi(n.themePath,"assets",e);if(!xl(s)){t.writeHead(404,{"Content-Type":"text/plain"}),t.end("Asset not found");return}let o=Df(s),r=jf[o]||"application/octet-stream",i=vl(s);t.writeHead(200,{"Content-Type":r,"Cache-Control":"no-cache"}),t.end(i)}function Ff(e,t,n,s){let r=oi(t,e==="/"?"/index.html":e);if(!xl(r)){let c=oi(t,"index.html");if(xl(c)){let d=vl(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 i=Df(r),a=jf[i]||"application/octet-stream",l=i===".html";try{let c=vl(r);s.writeHead(200,{"Content-Type":a,"Cache-Control":"no-store"}),s.end(c)}catch{s.writeHead(500,{"Content-Type":"text/plain"}),s.end("Internal Server Error")}}me();var Lf=Sk(xk(import.meta.url)),wk=4200;async function Bf(){let e=ai.hex("#e8613a"),t=ai.dim;console.log(""),console.log(e(" v vibeSpot")),console.log(t(` Starting...
|
|
2844
|
+
`));let n=kk();n||(console.error(ai.red(" Could not find UI assets. Is the package installed correctly?")),process.exit(1));let s=parseInt(process.env.VIBESPOT_PORT||"",10)||wk;try{let{port:o,host:r,authToken:i,close:a}=await ri({port:s,uiDir:n}),c=`http://${r==="0.0.0.0"||r==="::"?"localhost":r}:${o}${i?`/?token=${i}`:""}`;if(console.log(e(` v ${c}`)),i&&console.log(t(" Access requires this exact URL \u2014 the token is your auth secret.")),console.log(t(` Press Ctrl+C to stop
|
|
2845
|
+
`)),!process.env.VIBESPOT_NO_OPEN)try{process.platform==="darwin"?wl("open",[c],{stdio:"ignore"}):process.platform==="win32"?wl("cmd",["/c","start","",c],{stdio:"ignore"}):wl("xdg-open",[c],{stdio:"ignore"})}catch{}await new Promise(d=>{process.on("SIGINT",()=>{console.log(t(`
|
|
2846
|
+
Saving session...`)),D(),a(),console.log(t(` Goodbye!
|
|
2847
|
+
`)),d(),setTimeout(()=>process.exit(0),500)})})}catch(o){console.error(ai.red(` Failed to start: ${o instanceof Error?o.message:String(o)}`)),process.exit(1)}}function kk(){let e=[ii(Lf,"../../ui"),ii(Lf,"../ui"),ii(process.cwd(),"ui")];for(let t of e)if(vk(ii(t,"index.html")))return t;return null}y();import{resolve as Jf}from"path";import{existsSync as kl}from"fs";te();async function Hf(e={}){let t=await Gf(e.path);if(e.fix){let o=Xr(t);if(o.applied.length>0){K(`Applied ${o.applied.length} auto-fix${o.applied.length===1?"":"es"}:`);for(let r of o.applied)B(` ${r}`)}else B(E.muted("No auto-fixable issues found."));if(o.skipped.length>0)for(let r of o.skipped)se(r)}let n=ao(t);if(e.json){process.stdout.write(JSON.stringify(n,null,2)+`
|
|
2848
|
+
`),n.passed||process.exit(1);return}Pe(),await fe("Marketplace check");let s=`${n.errorCount} error${Tl(n.errorCount)}, ${n.warningCount} warning${Tl(n.warningCount)}, ${n.infoCount} note${Tl(n.infoCount)}`;n.passed?K(`Theme passes Marketplace checks (${s}).`):Z(`Theme is not yet ready: ${s}.`),Cl("Errors",n.findings.filter(o=>o.severity==="error")),Cl("Warnings",n.findings.filter(o=>o.severity==="warning")),Cl("Notes",n.findings.filter(o=>o.severity==="info")),n.passed||(B(""),B(`Tip: run ${E.accent("vibespot marketplace check --fix")} to apply auto-fixable issues, then re-check.`),process.exit(1)),await he("Looks good! Submit the theme via your HubSpot Marketplace dashboard.")}async function Uf(e={}){let t=await Gf(e.path);Pe(),await fe("Marketplace listing details");let n=ls(t)??{},s=await Nt({message:"Category",options:nn.map(u=>({value:u,label:u}))}),o=await ve({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}),i=(await ve({message:"Key features (comma-separated, 2\u20135 items)",placeholder:"Hero, Pricing, Testimonials, Footer",defaultValue:(n.features??[]).join(", "),validate:u=>{let p=u.split(",").map(g=>g.trim()).filter(Boolean).length;if(p<2)return"Provide at least 2 features.";if(p>5)return"Provide at most 5 features."}})).split(",").map(u=>u.trim()).filter(Boolean),a=await ve({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 ve({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 Nt({message:"Pricing tier",options:[{value:"free",label:"Free"},{value:"paid",label:"Paid"}]}),d={category:s,description:o.trim(),features:i,supportUrl:a.trim()||void 0,documentationUrl:l.trim()||void 0,pricingTier:c,tags:n.tags};Yr(t,d),K("Saved marketplace.json"),await he(`Run ${E.accent("vibespot marketplace check")} to confirm the theme is ready to submit.`)}async function Gf(e){if(e){let o=Jf(e);if(!kl(o))throw new Error(`Theme not found: ${o}`);return o}let t=$();if(t.lastThemePath&&kl(t.lastThemePath))return t.lastThemePath;Pe();let n=await ve({message:"Path to your HubSpot theme directory:",placeholder:"./my-theme",validate:o=>o.trim()?void 0:"Path is required"}),s=Jf(n);if(!kl(s))throw new Error(`Theme not found: ${s}`);return s}function Cl(e,t){if(t.length!==0){B(""),B(E.heading(e));for(let n of t){let s=n.file?E.muted(`[${n.file}] `):"",o=n.severity==="error"?E.error("\u2717"):n.severity==="warning"?E.warn("!"):E.muted("\xB7");B(` ${o} ${s}${n.message}`),n.fix&&B(` ${E.muted("\u2192 "+n.fix)}`)}}}function Tl(e){return e===1?"":"s"}y();import{resolve as Wf}from"path";import{existsSync as Al}from"fs";import{basename as Ck}from"path";te();Os();async function Kf(e={}){let t=await Tk(e.path),n=Ck(t);if(e.applyTokens){let r=tr(t,n);r?K(`Wrote design tokens to ${r}`):B(E.muted("Skipped: theme already has shared CSS or no tokens were inferred."))}if(e.snapshot){let r=Gi(t);e.json||K(`Wrote imported theme snapshot to ${r}`)}let s=er(t);e.json&&(process.stdout.write(JSON.stringify(s,null,2)+`
|
|
2849
|
+
`),process.exit(0)),Pe(),await fe("Inverse pipeline analyzer");let o=s.summary;if(B(`${E.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){B(""),B(E.heading("Palette (top by frequency)"));for(let r of s.designTokens.palette.slice(0,6)){let i=r.varName?E.muted(` (${r.varName})`):"";B(` ${r.value} ${E.muted(`\xD7${r.count}`)}${i}`)}}if(s.designTokens.fontFamilies.length>0){B(""),B(E.heading("Typography"));for(let r of s.designTokens.fontFamilies.slice(0,4))B(` ${r}`)}if(s.graph.templates.length>0){B(""),B(E.heading("Template \u2192 modules"));for(let r of s.graph.templates)B(` ${r.id}: ${r.modules.length===0?E.muted("(empty)"):r.modules.join(", ")}`)}if(s.graph.orphanModules.length>0){B(""),B(E.heading("Orphan modules"));for(let r of s.graph.orphanModules)B(` ${r}`)}if(s.roundTripDiff.hasSnapshot){B(""),B(E.heading("Round-trip diff"));let r=s.roundTripDiff;if(r.filesChanged===0)B(` ${E.muted("No changes from imported snapshot.")}`);else{B(` ${r.filesChanged} changed file(s): ${r.added} added, ${r.modified} modified, ${r.deleted} deleted`);for(let i of r.files.slice(0,12))B(` ${i.status.padEnd(8)} ${i.file}`);r.files.length>12&&B(` ${E.muted(`...and ${r.files.length-12} more`)}`)}}_l("Errors",s.findings.filter(r=>r.severity==="error")),_l("Warnings",s.findings.filter(r=>r.severity==="warning")),_l("Notes",s.findings.filter(r=>r.severity==="info")),!e.applyTokens&&s.summary.cssVarCount===0&&s.designTokens.palette.length>0&&(B(""),B(`Tip: run ${E.accent("vibespot inverse --apply-tokens")} to seed a :root block from the inferred palette.`)),await he("Analysis complete."),process.exit(0)}async function Tk(e){if(e){let o=Wf(e);if(!Al(o))throw new Error(`Theme not found: ${o}`);return o}let t=$();if(t.lastThemePath&&Al(t.lastThemePath))return t.lastThemePath;Pe();let n=await ve({message:"Path to the imported HubSpot theme directory:",placeholder:"./my-theme",validate:o=>o.trim()?void 0:"Path is required"}),s=Wf(n);if(!Al(s))throw new Error(`Theme not found: ${s}`);return s}function _l(e,t){if(t.length!==0){B(""),B(E.heading(e));for(let n of t){let s=n.file?E.muted(`[${n.file}] `):"",o=n.severity==="error"?E.error("\u2717"):n.severity==="warning"?E.warn("!"):E.muted("\xB7");B(` ${o} ${s}${n.message}`),n.fix&&B(` ${E.muted("\u2192 "+n.fix)}`)}}}y();import{dirname as Ak,join as li}from"path";import{existsSync as _k}from"fs";import{fileURLToPath as Pk}from"url";import{execFileSync as Pl}from"child_process";import ci from"chalk";me();var Vf=Ak(Pk(import.meta.url)),Ek=4200;async function zf(){let e=ci.hex("#e8613a"),t=ci.dim;console.log(""),console.log(e(" v vibeSpot \u2014 Email Mode")),console.log(t(` Starting...
|
|
2850
|
+
`));let n=Ik();n||(console.error(ci.red(" Could not find UI assets. Is the package installed correctly?")),process.exit(1));try{let{port:s,host:o,authToken:r,close:i}=await ri({port:Ek,uiDir:n,contentMode:"email"}),l=`http://${o==="0.0.0.0"||o==="::"?"localhost":o}:${s}${r?`/?token=${r}`:""}`;console.log(e(` v ${l}`)),r&&console.log(t(" Access requires this exact URL \u2014 the token is your auth secret.")),console.log(t(` Email template mode \u2014 Press Ctrl+C to stop
|
|
2851
|
+
`));try{process.platform==="darwin"?Pl("open",[l],{stdio:"ignore"}):process.platform==="win32"?Pl("cmd",["/c","start","",l],{stdio:"ignore"}):Pl("xdg-open",[l],{stdio:"ignore"})}catch{}await new Promise(c=>{process.on("SIGINT",()=>{console.log(t(`
|
|
2852
|
+
Saving session...`)),D(),i(),console.log(t(` Goodbye!
|
|
2853
|
+
`)),c(),setTimeout(()=>process.exit(0),500)})})}catch(s){console.error(ci.red(` Failed to start: ${s instanceof Error?s.message:String(s)}`)),process.exit(1)}}function Ik(){let e=[li(Vf,"../../ui"),li(Vf,"../ui"),li(process.cwd(),"ui")];for(let t of e)if(_k(li(t,"index.html")))return t;return null}ae();function qf(){let e=new Mk;e.name("vibespot").description("AI-powered HubSpot CMS landing page builder").version(Mt()).action(Bf),e.command("wizard").description("Classic CLI wizard \u2014 step-by-step conversion flow").action(Gd),e.command("init").description("Check and install required tools").action(Wd),e.command("convert").description("Convert a React project to HubSpot modules").action(Kd),e.command("upload").description("Upload theme to HubSpot").action(Vd),e.command("doctor").description("Diagnose environment issues").action(zd);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=>Hf(n)),t.command("edit").description("Edit Marketplace listing metadata (marketplace.json)").option("-p, --path <path>","Path to the theme directory").action(n=>Uf(n)),e.command("email").description("Launch email template generation mode").action(zf),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=>Kf(n)),e}var $k=qf();$k.parseAsync(process.argv).catch(e=>{console.error(e),process.exit(1)});
|
|
2956
2854
|
//# sourceMappingURL=index.js.map
|