vcvm
Version:
One-command path to fresh, isolated Linux micro-VMs on Vercel
29 lines (26 loc) • 52.8 kB
JavaScript
#!/usr/bin/env node
var Kt=(e=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(e,{get:(t,o)=>(typeof require<"u"?require:t)[o]}):e)(function(e){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+e+'" is not supported')});import{render as ts}from"ink";import os from"meow";import{Box as zo,Text as Qn}from"ink";import{createContext as tr,useContext as or,useState as le,useEffect as rr}from"react";import{existsSync as xe,readFileSync as he}from"fs";import{join as Se}from"path";import Zo from"xdg-app-paths";import{spawn as er}from"child_process";var De=!1;function Ut(e){De=e}function C(...e){De&&console.error("[DEBUG]",new Date().toISOString(),...e)}function M(e,t){De&&(console.error("[DEBUG ERROR]",e),t instanceof Error?(console.error(" Message:",t.message),console.error(" Stack:",t.stack)):console.error(" Error:",t),t.response&&(console.error(" Response status:",t.response.status),console.error(" Response data:",JSON.stringify(t.response.data,null,2))))}function ke(e,t,o){De&&(console.error("[DEBUG REQUEST]",e,t),o&&console.error(" Body:",JSON.stringify(o,null,2)))}async function qt(){let e=Zo("com.vercel.cli.test").dataDirs();for(let t of e){let o=Se(t,"auth.json");if(xe(o))try{let r=JSON.parse(he(o,"utf-8"));if(r.token)return r.token}catch{continue}}return null}async function Gt(){return new Promise(e=>{let t=er("vc",["login"],{stdio:"inherit",shell:!0});t.on("close",o=>{e(o===0)}),t.on("error",()=>{e(!1)})})}async function Jt(e,t){try{let o=await fetch("https://api.vercel.com/v2/user",{headers:{Authorization:`Bearer ${e}`}});if(!o.ok)throw new Error("Failed to fetch user info");let r=await o.json(),s={user:{username:r.user.username,email:r.user.email,name:r.user.name}};if(t){let l=await fetch("https://api.vercel.com/v2/teams",{headers:{Authorization:`Bearer ${e}`}});if(l.ok){let i=await l.json();if(i.teams&&i.teams.length>0){let a=i.teams.find(c=>c.id===t);s.team={id:a.id,name:a.name,slug:a.slug}}}}return s}catch{return{}}}async function Yt(e,t,o){try{let r=t?`https://api.vercel.com/v9/projects/${o}?teamId=${t}`:`https://api.vercel.com/v9/projects/${o}`;C("Fetching project info from:",r);let s=await fetch(r,{headers:{Authorization:`Bearer ${e}`}});if(!s.ok)return M("Failed to fetch project info",{status:s.status}),null;let l=await s.json();return{id:l.id,name:l.name}}catch(r){return M("Error fetching project info",r),null}}async function zt(e,t){try{let o=`https://api.vercel.com/v2/teams/${t}`;C("Fetching team info from:",o);let r=await fetch(o,{headers:{Authorization:`Bearer ${e}`}});if(!r.ok)return M("Failed to fetch team info",{status:r.status}),null;let s=await r.json();return{id:s.id,name:s.name,slug:s.slug}}catch(o){return M("Error fetching team info",o),null}}async function j(){if(C("auth() checking environment variables"),process.env.VERCEL_TOKEN&&process.env.VERCEL_TEAM_ID&&process.env.VERCEL_PROJECT_ID)return C("Using environment variables for auth"),{token:process.env.VERCEL_TOKEN,teamId:process.env.VERCEL_TEAM_ID,projectId:process.env.VERCEL_PROJECT_ID};let e=await qt();if(C("Got token from Vercel CLI:",!!e),e){let o=Se(process.cwd(),".vercel","project.json");if(C("Checking for project.json at:",o),xe(o))try{let r=JSON.parse(he(o,"utf-8"));return C("Found project data:",{hasOrgId:!!r.orgId,hasProjectId:!!r.projectId,orgId:r.orgId,projectId:r.projectId}),{token:e,teamId:r.orgId||null,projectId:r.projectId||null}}catch(r){return M("Failed to read project.json",r),{token:e,teamId:null,projectId:null}}return C("No project.json found, returning token only"),{token:e,teamId:null,projectId:null}}let t=Se(process.cwd(),".env.local");if(xe(t)){let r=he(t,"utf-8").split(`
`),s={};for(let l of r){let[i,...a]=l.split("=");i&&a.length>0&&(s[i.trim()]=a.join("=").trim())}if(s.VERCEL_OIDC_TOKEN){let l=Se(process.cwd(),".vercel","project.json");if(xe(l)){let i=JSON.parse(he(l,"utf-8"));return{token:s.VERCEL_OIDC_TOKEN,teamId:i.orgId||null,projectId:i.projectId||null}}}return{token:s.VERCEL_TOKEN||null,teamId:s.VERCEL_TEAM_ID||null,projectId:s.VERCEL_PROJECT_ID||null}}return{token:null,teamId:null,projectId:null}}async function Xt(){if(await qt())return{success:!0};if(process.env.VERCEL_OIDC_TOKEN)return{success:!0};if(process.env.VERCEL_TOKEN&&process.env.VERCEL_TEAM_ID&&process.env.VERCEL_PROJECT_ID)return{success:!0};let t=Se(process.cwd(),".env.local");return xe(t)&&he(t,"utf-8").includes("VERCEL_OIDC_TOKEN")?{success:!0}:{success:!1,error:`Authentication required. Please run:
1. Sign in to Vercel: vc login
2. Link to a Vercel project: vercel link
Or set up access token authentication:
- VERCEL_TOKEN
- VERCEL_TEAM_ID
- VERCEL_PROJECT_ID`}}import{jsx as nr}from"react/jsx-runtime";var Wt=tr(null);function Ae(){let e=or(Wt);if(!e)throw new Error("useAuth must be used within an AuthProvider");return e}function Qt({children:e}){let[t,o]=le(null),[r,s]=le(null),[l,i]=le(null),[a,c]=le(null),[u,m]=le(!0),[S,p]=le(null),v=async()=>{try{if(m(!0),p(null),!(await Xt()).success&&!await Gt()){p("Authentication failed. Please run 'vc login' manually."),m(!1);return}let I=await j();if(!I.token){p("Failed to get authentication token"),m(!1);return}o(I.token),s(I.teamId),i(I.projectId);let B=await Jt(I.token,I.teamId);c(B),m(!1)}catch(y){p(y instanceof Error?y.message:"Authentication failed"),m(!1)}};return rr(()=>{v()},[]),nr(Wt.Provider,{value:{token:t,teamId:r,projectId:l,userInfo:a,isLoading:u,error:S,refreshAuth:v},children:e})}var w={colors:{primary:"white",secondary:"gray",muted:"gray",success:"white",error:"white",warning:"white",background:"black",accent:"white"},spacing:{xs:0,sm:1,md:2,lg:3},symbols:{arrow:"\u2192",bullet:"\u2022",check:"\u2713",cross:"\xD7",dash:"\u2014",ellipsis:"...",chevron:"\u203A"}},be=e=>e<1e3?`${e}ms`:e<6e4?`${(e/1e3).toFixed(1)}s`:`${Math.floor(e/6e4)}m ${Math.floor(e%6e4/1e3)}s`,ct=(e,t)=>e.length<=t?e:e.slice(0,t-3)+"...";import{ThemeProvider as Zn}from"@inkjs/ui";import{extendTheme as sr,defaultTheme as ir}from"@inkjs/ui";var Zt=sr(ir,{components:{Spinner:{styles:{frame:()=>({color:"gray"}),label:()=>({color:"white"})}},Select:{styles:{container:()=>({flexDirection:"column",width:"100%",height:"100%"}),option:({isHighlighted:e,isSelected:t})=>({color:e?"white":"gray",inverse:e,bold:t}),highlightedOption:()=>({color:"white",inverse:!0}),scrollIndicator:()=>({color:"gray"})}},Badge:{styles:{root:({color:e})=>({color:e==="green"||e==="blue"?"white":"gray",inverse:e==="green"||e==="blue"})}},StatusMessage:{styles:{container:()=>({paddingY:1}),icon:({variant:e})=>({color:e==="success"||e==="info"?"white":"gray"}),message:()=>({color:"white"})}},Alert:{styles:{container:({variant:e})=>({borderStyle:"single",borderColor:e==="success"||e==="info"?"white":"gray",paddingX:2,paddingY:1,marginY:1}),icon:({variant:e})=>({color:e==="success"||e==="info"?"white":"gray"}),title:()=>({bold:!0,color:"white"}),body:()=>({color:"gray"})}},ProgressBar:{styles:{container:()=>({width:"100%"}),bar:()=>({color:"white"}),track:()=>({color:"gray"}),percentage:()=>({color:"gray"})}}}});import{useState as qe,useEffect as jr}from"react";import{Sandbox as Rr}from"@vercel/sandbox";import go from"ms";import{existsSync as lt,mkdirSync as ar,readFileSync as je,writeFileSync as eo,chmodSync as Re}from"fs";import{homedir as cr}from"os";import{join as mt}from"path";import{execSync as lr}from"child_process";var Le=mt(cr(),".vm"),ne=mt(Le,"id_rsa"),me=mt(Le,"id_rsa.pub");function mr(){lt(Le)||ar(Le,{recursive:!0})}function ve(){if(mr(),lt(ne)&<(me))return{privateKey:je(ne,"utf-8"),publicKey:je(me,"utf-8")};try{return lr(`ssh-keygen -t rsa -b 4096 -f "${ne}" -N "" -C "vm@localhost"`,{stdio:"pipe"}),Re(ne,384),Re(me,420),{privateKey:je(ne,"utf-8"),publicKey:je(me,"utf-8")}}catch{let t=ur();return eo(ne,t.privateKey),eo(me,t.publicKey),Re(ne,384),Re(me,420),t}}function ur(){let e=Kt("crypto"),{generateKeyPairSync:t}=e,{publicKey:o,privateKey:r}=t("rsa",{modulusLength:4096,publicKeyEncoding:{type:"spki",format:"pem"},privateKeyEncoding:{type:"pkcs8",format:"pem"}}),s=dr(o);return{privateKey:r,publicKey:s}}function dr(e){return`ssh-rsa ${e.replace(/-----BEGIN PUBLIC KEY-----/,"").replace(/-----END PUBLIC KEY-----/,"").replace(/\s/g,"")} vm@localhost`}function to(){return ve().publicKey}async function Ve(e,t){try{C("Setting up SSH server for sandbox:",e.sandboxId),C("Installing openssh-server...");let o=await e.runCommand({cmd:"dnf",args:["install","-y","openssh-server"],sudo:!0});if(o.exitCode!==0)return C("SSH server installation failed:",{exitCode:o.exitCode,stdout:o.stdout,stderr:o.stderr}),{success:!1,error:"Failed to install SSH server"};C("SSH server installed successfully"),t?.("configuring-ssh"),await e.runCommand({cmd:"ssh-keygen",args:["-A"],sudo:!0}),await e.runCommand({cmd:"mkdir",args:["-p","/home/vercel-sandbox/.ssh"],sudo:!0}),await e.runCommand({cmd:"chown",args:["-R","vercel-sandbox:vercel-sandbox","/home/vercel-sandbox/.ssh"],sudo:!0}),await e.runCommand({cmd:"chmod",args:["700","/home/vercel-sandbox/.ssh"],sudo:!0}),t?.("generating-keys");let r=to();await e.runCommand({cmd:"sh",args:["-c",`echo '${r}' | sudo tee /home/vercel-sandbox/.ssh/authorized_keys`]}),await e.runCommand({cmd:"chmod",args:["600","/home/vercel-sandbox/.ssh/authorized_keys"],sudo:!0}),await e.runCommand({cmd:"chown",args:["vercel-sandbox:vercel-sandbox","/home/vercel-sandbox/.ssh/authorized_keys"],sudo:!0}),await e.runCommand({cmd:"sh",args:["-c",`echo '
Port 2222
PermitRootLogin no
PasswordAuthentication no
PermitEmptyPasswords no
PubkeyAuthentication yes
AuthorizedKeysFile .ssh/authorized_keys
ChallengeResponseAuthentication no
UsePAM no
' | sudo tee /etc/ssh/sshd_config`]}),await e.runCommand({cmd:"pkill",args:["-f","sshd"],sudo:!0});let l=await e.runCommand({cmd:"/usr/sbin/sshd",args:["-f","/etc/ssh/sshd_config"],sudo:!0});if(l.exitCode!==0){let i=await e.runCommand({cmd:"/usr/bin/sshd",args:["-f","/etc/ssh/sshd_config"],sudo:!0});if(i.exitCode!==0)return{success:!1,error:`Failed to start SSH daemon: ${l.stderr||i.stderr}`}}return{success:!0,port:2222}}catch(o){return{success:!1,error:o instanceof Error?o.message:"Unknown SSH setup error"}}}import{useState as pr,useEffect as fr}from"react";import{Box as ut}from"ink";import{Spinner as gr,ProgressBar as xr}from"@inkjs/ui";import{jsx as _e,jsxs as hr}from"react/jsx-runtime";function oo({status:e}){let[t,o]=pr(0);return fr(()=>{let r=setInterval(()=>{o(s=>s>=90?s:s+Math.random()*10)},500);return()=>clearInterval(r)},[]),hr(ut,{flexDirection:"column",gap:1,children:[_e(ut,{children:_e(gr,{label:e||"Starting sandbox"})}),_e(ut,{width:40,children:_e(xr,{value:Math.floor(t)})})]})}import{useState as Sr,useEffect as br}from"react";import{Box as V,Text as K,useInput as vr,useApp as wr}from"ink";import{StatusMessage as ro,Badge as no}from"@inkjs/ui";import{spawn as yr}from"child_process";import{jsx as R,jsxs as O}from"react/jsx-runtime";function Me({sandboxId:e,domain:t,port:o,runtime:r,timeout:s,userInfo:l}){let[i,a]=Sr(!0),{exit:c}=wr();vr(m=>{(m==="s"||m==="S")&&u()}),br(()=>{let m=setTimeout(()=>{a(!1)},1500);return()=>clearTimeout(m)},[]);let u=()=>{yr(process.argv[0],[process.argv[1],"ssh",e],{stdio:"inherit"}),c()};return i?R(V,{flexDirection:"column",paddingY:2,children:R(ro,{variant:"success",children:"Sandbox created successfully"})}):O(V,{flexDirection:"column",gap:2,children:[O(V,{flexDirection:"column",gap:1,children:[O(V,{alignItems:"center",gap:2,children:[R(K,{bold:!0,children:"Sandbox Ready"}),R(no,{color:"green",children:"Active"})]}),l&&O(K,{dimColor:!0,children:[l.user?`${l.user.username}`:"",l.team?` ${w.symbols.bullet} ${l.team.name}`:""]})]}),O(V,{flexDirection:"column",gap:1,children:[O(V,{gap:2,children:[R(V,{width:10,children:R(K,{dimColor:!0,children:"ID"})}),R(K,{children:e})]}),O(V,{gap:2,children:[R(V,{width:10,children:R(K,{dimColor:!0,children:"SSH"})}),O(K,{bold:!0,children:["vm ssh ",e]})]}),O(V,{gap:2,children:[R(V,{width:10,children:R(K,{dimColor:!0,children:"Web"})}),O(K,{children:[t.includes("://")?t.split("://")[1].split(":")[0]:t.split(":")[0],":3000"]})]}),O(V,{gap:2,children:[R(V,{width:10,children:R(K,{dimColor:!0,children:"Runtime"})}),R(no,{color:"blue",children:r})]}),O(V,{gap:2,children:[R(V,{width:10,children:R(K,{dimColor:!0,children:"Timeout"})}),R(K,{children:s})]})]}),O(V,{flexDirection:"column",gap:1,children:[R(ro,{variant:"info",children:"Press 's' to SSH into the sandbox"}),O(K,{dimColor:!0,children:["Or use: vm ssh ",e.slice(0,8),"..."]})]})]})}import{Alert as xo}from"@inkjs/ui";import{existsSync as so,readFileSync as Ir,writeFileSync as Pr,mkdirSync as Tr}from"fs";import{homedir as Cr}from"os";import{join as io}from"path";import{Sandbox as Er}from"@vercel/sandbox";var dt=io(Cr(),".vercelvm"),pt=io(dt,"sandboxes.json");function ao(){so(dt)||Tr(dt,{recursive:!0})}function we(){if(ao(),!so(pt))return[];try{let e=Ir(pt,"utf-8");return JSON.parse(e)}catch{return[]}}function co(e){ao(),Pr(pt,JSON.stringify(e,null,2))}function Ne(e){let t=we(),o=t.findIndex(r=>r.id===e.id);o>=0?t[o]=e:t.push(e),co(t)}function ue(e){return we().find(o=>o.id===e)||null}function se(){let e=we(),t=new Date().getTime();return e.map(o=>{let r=new Date(o.expiresAt).getTime();return t>r&&o.status==="active"&&(o.status="expired"),o}).filter(o=>o.status!=="stopped")}async function ie(e,t){let o=we(),r=o.find(s=>s.id===e);r&&(r.status=t,t==="active"&&(r.lastPingAt=new Date().toISOString()),co(o))}async function Oe(e,t){try{return await(await Er.get({sandboxId:e,token:t.token,teamId:t.teamId,projectId:t.projectId})).stop(),await ie(e,"stopped"),{success:!0}}catch(o){return console.error("Failed to stop sandbox:",o),{success:!1,error:o instanceof Error?o.message:"Unknown error"}}}var $e={getSandboxes:()=>{let e=we(),t={};for(let o of e)t[o.id]={id:o.id,host:o.domains[o.sshPort]||"unknown",port:o.sshPort};return t}};import{existsSync as lo,readFileSync as Br,writeFileSync as Dr,mkdirSync as kr}from"fs";import{homedir as Ar}from"os";import{join as mo}from"path";var gt=mo(Ar(),".vmvm"),xt=mo(gt,"presets.json"),ft=[{id:"quick-node",name:"Quick Node.js",description:"Fast Node.js environment for quick experiments",runtime:"node22",timeout:"15m",isDefault:!0,createdAt:new Date().toISOString()},{id:"long-node",name:"Long Node.js",description:"Node.js with extended 45-minute timeout",runtime:"node22",timeout:"45m",createdAt:new Date().toISOString()},{id:"python",name:"Python",description:"Python environment",runtime:"python3.13",timeout:"30m",ports:[8888],createdAt:new Date().toISOString()},{id:"web-dev",name:"Web Development",description:"Node.js with port 3000 exposed",runtime:"node22",timeout:"30m",ports:[3e3],createdAt:new Date().toISOString()}];function uo(){lo(gt)||kr(gt,{recursive:!0})}function ye(){if(uo(),!lo(xt))return ht(ft),ft;try{let e=Br(xt,"utf-8");return JSON.parse(e)}catch{return ft}}function ht(e){uo(),Dr(xt,JSON.stringify(e,null,2))}function Fe(){return ye()}function He(e){return ye().find(o=>o.id===e)||null}function Ke(){let e=ye();return e.find(t=>t.isDefault)||e[0]||null}function po(e){let o=ye().filter(r=>r.id!==e);ht(o)}function fo(e){let t=ye();t.forEach(r=>r.isDefault=!1);let o=t.find(r=>r.id===e);o&&(o.isDefault=!0,ht(t))}function Ue(e){let t={};return e.runtime&&(t.runtime=e.runtime),e.timeout&&(t.timeout=e.timeout),e.ports&&(t.ports=e.ports.split(",").map(o=>parseInt(o.trim())).filter(o=>!isNaN(o))),t}import{jsx as Ge}from"react/jsx-runtime";function ho({flags:e}){let{token:t,teamId:o,projectId:r,userInfo:s,isLoading:l,error:i}=Ae(),[a,c]=qe("waiting"),[u,m]=qe(null),[S,p]=qe(null),[v,y]=qe(null);jr(()=>{!l&&t&&I()},[l,t]);let I=async()=>{try{if(C("Starting sandbox with auth:",{hasToken:!!t,teamId:o,projectId:r}),!t||!o||!r){p("Missing authentication credentials. Please run 'vercel link' in this directory."),c("error");return}c("creating"),ve();let B=null;if(e.preset){if(B=He(e.preset),!B){p(`Preset '${e.preset}' not found`),c("error");return}}else!e.runtime&&!e.timeout&&!e.ports&&(B=Ke());let D=Ue(e),n=B?{...B,...D}:D,x=n.ports||e.ports?.split(",").map(f=>Number.parseInt(f.trim()))||[2222],h={runtime:n.runtime||e.runtime||"node22",ports:x,timeout:go(n.timeout||e.timeout||"30m"),resources:{vcpus:2},token:t,teamId:o,projectId:r};C("Creating sandbox with config:",h),ke("POST","Sandbox.create",h);let g=await Rr.create(h);C("Sandbox created successfully:",{sandboxId:g.sandboxId}),m(g),c("configuring");let P=await Ve(g);if(!P.success){p(P.error||"SSH setup failed"),c("error");return}y(P.port||2222);let L=go(e.timeout||"30m");Ne({id:g.sandboxId,runtime:e.runtime||"node22",domains:x.reduce((f,T)=>(f[T]=g.domain(T),f),{}),sshPort:P.port||2222,createdAt:new Date().toISOString(),timeout:L,expiresAt:new Date(Date.now()+L).toISOString(),status:"active"}),c("ready")}catch(B){M("Sandbox creation failed",B);let D="Unknown error occurred";B instanceof Error&&(D=B.message),B.response?.status===400&&(D=`Bad Request (400): ${B.response?.data?.error||B.response?.data?.message||D}`,C("400 Error details:",B.response?.data)),p(D),c("error")}};return i?Ge(xo,{variant:"error",title:"Authentication Error",children:i}):a==="error"?Ge(xo,{variant:"error",title:"Error",children:S}):a==="ready"&&u&&v?Ge(Me,{sandboxId:u.sandboxId,domain:u.domain(v),port:v,runtime:e.runtime||"node22",timeout:e.timeout||"30m",userInfo:s}):Ge(oo,{status:l?"Checking authentication...":a==="waiting"?"Preparing...":a==="creating"?"Creating sandbox environment...":a==="configuring"?"Setting up SSH server...":""})}import{useState as Ie,useEffect as Or}from"react";import{Box as z,Text as Z,useInput as $r,useApp as Fr}from"ink";import{Badge as Hr,Alert as wo,ConfirmInput as Kr}from"@inkjs/ui";import{Sandbox as Lr}from"@vercel/sandbox";async function Vr(e,t){try{return C("Pinging sandbox:",e),await(await Lr.get({sandboxId:e,token:t.token,teamId:t.teamId,projectId:t.projectId})).runCommand({cmd:"echo",args:["ping"]}),C("Sandbox ping successful:",e),await ie(e,"active"),!0}catch(o){M("Sandbox ping failed",o);let r=o?.response?.status;return(r===404||r===403)&&await ie(e,"stopped"),!1}}async function Je(e){let o=se().filter(r=>r.status==="active");C(`Pinging ${o.length} active sandboxes`),await Promise.all(o.map(r=>Vr(r.id,e)))}function _r(e){let t=new Date().getTime(),o=new Date(e.expiresAt).getTime();return t>o}async function Ye(){let e=se();for(let t of e)t.status==="active"&&_r(t)&&await ie(t.id,"expired")}import{spawn as Ur}from"child_process";import Mr from"react";import{Box as So,Text as bo}from"ink";import{jsx as Nr,jsxs as St}from"react/jsx-runtime";function vo({children:e,maxHeight:t,overflowDirection:o="bottom"}){let r=Mr.Children.toArray(e),s=r.length,l=Math.max(0,s-t);if(l===0)return Nr(So,{flexDirection:"column",children:e});let i=o==="top"?r.slice(l):r.slice(0,t);return St(So,{flexDirection:"column",children:[l>0&&o==="top"&&St(bo,{dimColor:!0,children:[w.symbols.ellipsis," ",l," more item",l===1?"":"s"," above"]}),i,l>0&&o==="bottom"&&St(bo,{dimColor:!0,children:[w.symbols.ellipsis," ",l," more item",l===1?"":"s"," below"]})]})}import{jsx as U,jsxs as G}from"react/jsx-runtime";function ze({prefetchedData:e}){let[t,o]=Ie([]),[r,s]=Ie(null),[l,i]=Ie(!1),[a,c]=Ie(null),[u,m]=Ie(Date.now()),{exit:S}=Fr();Or(()=>{if(e&&e.length>0){let h=e.map(g=>{let P=new Date(g.createdAt),L=new Date,f=L.getTime()-P.getTime(),_=new Date(g.expiresAt).getTime()-L.getTime(),H=_>0?be(_):"Expired";return{...g,age:be(f),timeRemaining:H}});o(h),!r&&h.length>0&&s(h[0].id)}else y();let n=setInterval(()=>{m(Date.now())},1e3),x=setInterval(()=>{y()},3e4);return()=>{clearInterval(n),clearInterval(x)}},[e]),$r((n,x)=>{if(!l)if(x.upArrow||n==="k"){let h=t.findIndex(P=>P.id===r),g=h>0?h-1:t.length-1;t[g]&&s(t[g].id)}else if(x.downArrow||n==="j"){let h=t.findIndex(P=>P.id===r),g=h<t.length-1?h+1:0;t[g]&&s(t[g].id)}else if(n==="s"&&r){let h=t.find(g=>g.id===r);h&&p(h)}else if(n==="d"&&r){let h=t.find(g=>g.id===r);h&&(c(h),i(!0))}else n==="r"?y():n==="q"&&S()});let p=n=>{Ur(process.argv[0],[process.argv[1],"ssh",n.id],{stdio:"inherit"}),S()},v=()=>{i(!1),c(null)},y=async()=>{await Ye();let n=await j();n.token&&n.teamId&&n.projectId&&await Je({token:n.token,teamId:n.teamId,projectId:n.projectId});let h=se().map(g=>{let P=new Date(g.createdAt),L=new Date,f=L.getTime()-P.getTime(),_=new Date(g.expiresAt).getTime()-L.getTime(),H=_>0?be(_):"Expired";return{...g,age:be(f),timeRemaining:H}});o(h),!r&&h.length>0?s(h[0].id):r&&!h.find(g=>g.id===r)&&s(h.length>0?h[0].id:null)},I=async()=>{if(a){let n=await j();if(n.token&&n.teamId&&n.projectId){let x=await Oe(a.id,{token:n.token,teamId:n.teamId,projectId:n.projectId});x.success||console.error("Failed to stop sandbox:",x.error)}else await ie(a.id,"stopped");await y()}i(!1),c(null)};if(l&&a)return G(z,{flexDirection:"column",height:"100%",justifyContent:"center",alignItems:"center",children:[U(wo,{variant:"warning",title:"Delete Sandbox?",children:`Delete sandbox ${ct(a.id,12)}?`}),U(z,{marginTop:2,children:U(Kr,{onConfirm:I,onCancel:v})})]});if(t.length===0)return U(z,{flexDirection:"column",height:"100%",justifyContent:"center",alignItems:"center",children:U(wo,{variant:"info",title:"No Active Sandboxes",children:"Run 'vm start' to create one"})});let B=n=>{let h=new Date(n).getTime()-u;if(h<=0)return"Expired";let g=Math.floor(h/6e4),P=Math.floor(g/60);return P>0?`${P}h ${g%60}m remaining`:`${g}m remaining`},D=n=>{switch(n){case"active":return"\u25CF";case"expired":return"\u25CB";case"stopped":return"\xD7";default:return"?"}};return G(z,{flexDirection:"column",height:"100%",children:[G(z,{flexDirection:"column",marginBottom:2,children:[G(z,{alignItems:"center",gap:2,children:[U(Z,{bold:!0,children:"Active Sandboxes"}),U(Hr,{color:"blue",children:t.length})]}),G(Z,{dimColor:!0,children:["s: SSH ",w.symbols.bullet," d: Delete ",w.symbols.bullet," r: Refresh ",w.symbols.bullet," ESC: Back ",w.symbols.bullet," q: Quit"]})]}),U(z,{flexDirection:"column",flexGrow:1,children:U(vo,{maxHeight:20,overflowDirection:"top",children:t.map(n=>{let x=n.id===r,h=B(n.expiresAt);return G(z,{flexDirection:"column",marginBottom:x?1:0,children:[U(z,{paddingLeft:1,children:G(Z,{color:n.status==="active"?x?"greenBright":"green":n.status==="expired"?"red":"gray",bold:x,children:[x?w.symbols.arrow:" "," ",D(n.status)," ",ct(n.id,12)," ",w.symbols.bullet," ",U(Z,{dimColor:!0,children:n.runtime})," ",w.symbols.bullet," ",U(Z,{dimColor:!x,children:h})]})}),x&&G(z,{paddingLeft:4,flexDirection:"column",gap:0,children:[G(Z,{dimColor:!0,children:["Created: ",new Date(n.createdAt).toLocaleString()]}),G(Z,{dimColor:!0,children:["SSH: vm ssh ",n.id]}),(()=>{let g=n.domains[n.sshPort],P=g;return g.includes("://")&&(P=g.split("://")[1]),P.includes(":")&&(P=P.split(":")[0]),G(Z,{dimColor:!0,children:["Host: ",P,":",n.sshPort]})})()]})]},n.id)})})})]})}import{useState as yo,useEffect as Jr}from"react";import{Box as Yr}from"ink";import{Alert as zr}from"@inkjs/ui";import{useState as Vi,useEffect as _i}from"react";import{Text as Ni}from"ink";import{Spinner as qr}from"@inkjs/ui";import{jsx as Gr,jsxs as Fi}from"react/jsx-runtime";function ee({label:e}){return Gr(qr,{label:e})}import{spawn as Xr}from"child_process";import{useApp as Wr}from"ink";import{writeFileSync as Qr,mkdirSync as Zr,existsSync as en,readFileSync as tn}from"fs";import{join as bt,dirname as on}from"path";import{homedir as rn}from"os";import{fileURLToPath as nn}from"url";import{jsx as vt}from"react/jsx-runtime";function Io({sandboxId:e}){let[t,o]=yo("connecting"),[r,s]=yo(null),{exit:l}=Wr();Jr(()=>{i()},[e]);let i=async()=>{try{if(!e){s("Sandbox ID is required"),o("error");return}if(!ue(e)){s('Sandbox not found. Use "vm list" to see active sandboxes.'),o("error");return}let c=await j();if(!c.token||!c.teamId||!c.projectId){s("Authentication required. Please run 'vm link' first."),o("error");return}o("connected");let u=bt(rn(),".vm","scripts");en(u)||Zr(u,{recursive:!0});let m=bt(u,`sandbox-shell-${e}.js`),S=on(nn(import.meta.url)),p=bt(S,"sandbox-shell.js"),v=tn(p,"utf-8");v=v.replace(/__SANDBOX_ID__/g,e).replace(/__TOKEN__/g,c.token).replace(/__TEAM_ID__/g,c.teamId).replace(/__PROJECT_ID__/g,c.projectId),Qr(m,v);let y=Xr("node",[m],{stdio:"inherit",env:{...process.env,NODE_NO_WARNINGS:"1"}});y.on("close",()=>{try{Kt("fs").unlinkSync(m)}catch{}l()}),y.on("error",I=>{M("Failed to spawn shell process:",I),s("Failed to start shell session"),o("error")})}catch(a){M("Connection error:",a),s(a instanceof Error?a.message:"Failed to connect"),o("error")}};return t==="error"?vt(zr,{variant:"error",title:"Connection Failed",children:r}):t==="connecting"?vt(Yr,{paddingY:1,children:vt(ee,{label:`Connecting to sandbox ${e}`})}):null}import{useState as wt,useEffect as sn}from"react";import{Box as an,Text as J}from"ink";import{jsx as Xe,jsxs as te}from"react/jsx-runtime";function Po({sandboxId:e}){let[t,o]=wt(null),[r,s]=wt(!0),[l,i]=wt(null);sn(()=>{a()},[e]);let a=async()=>{try{if(!e){i("Sandbox ID is required"),s(!1);return}let c=await ue(e);c?o(c):i("Sandbox not found")}catch(c){i(c instanceof Error?c.message:"Failed to load status")}finally{s(!1)}};return r?Xe(J,{color:"gray",children:"Loading sandbox status..."}):l?te(J,{color:"red",children:["Error: ",l]}):te(an,{flexDirection:"column",padding:1,children:[Xe(J,{color:"cyan",bold:!0,children:"Sandbox Status"}),Xe(J,{color:"gray",children:"\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"}),te(J,{color:"white",children:["ID: ",t.id]}),te(J,{color:"white",children:["Runtime: ",t.runtime]}),te(J,{color:"white",children:["Status: ",Xe(J,{color:"green",children:"Running"})]}),te(J,{color:"white",children:["SSH: ",t.domain,":",t.sshPort]}),te(J,{color:"white",children:["Web: ",t.domain,":3000"]}),te(J,{color:"white",children:["Created: ",new Date(t.createdAt).toLocaleString()]})]})}import{useState as To,useEffect as cn}from"react";import{Box as yt,Text as It}from"ink";import{jsx as Tt,jsxs as Pt}from"react/jsx-runtime";function Co({sandboxId:e}){let[t,o]=To("stopping"),[r,s]=To(null);cn(()=>{l()},[e]);let l=async()=>{try{if(!e){s("Sandbox ID is required"),o("error");return}if(!ue(e)){s("Sandbox not found"),o("error");return}let a=await j();if(!a.token||!a.teamId||!a.projectId){s("Authentication required. Please run 'vm link' first."),o("error");return}let c=await Oe(e,{token:a.token,teamId:a.teamId,projectId:a.projectId});c.success?o("stopped"):(s(c.error||"Failed to stop sandbox"),o("error"))}catch(i){s(i instanceof Error?i.message:"Failed to stop sandbox"),o("error")}};return t==="error"?Tt(yt,{children:Pt(It,{color:"red",children:["\u274C Error: ",r]})}):t==="stopped"?Tt(yt,{children:Pt(It,{color:"green",children:["\u2705 Sandbox ",e," stopped successfully"]})}):Tt(yt,{children:Pt(It,{color:"yellow",children:["\u{1F6D1} Stopping sandbox ",e,"..."]})})}import{useState as We,useEffect as ln}from"react";import{Box as Eo,Text as Ct}from"ink";import{Vercel as mn}from"@vercel/sdk";import Et from"inquirer";import{existsSync as un,mkdirSync as dn,writeFileSync as Bo,readFileSync as pn}from"fs";import{join as Pe}from"path";import{jsx as Bt,jsxs as Dt}from"react/jsx-runtime";function Qe({flags:e}){let[t,o]=We(!0),[r,s]=We(null),[l,i]=We(!1),[a,c]=We("");ln(()=>{u()},[]);async function u(){try{let m=await j();if(!m.token||!m.teamId||!m.projectId)throw new Error("Authentication required. Please run 'vercel link' first.");let S=new mn({bearerToken:m.token}),p=process.cwd(),v=Pe(p,".vercel");if(un(Pe(v,"project.json"))&&!e.project){let D=JSON.parse(pn(Pe(v,"project.json"),"utf-8"));c(D.projectId||D.name),i(!0),o(!1);return}let y=e.project,I=e.team||m.teamId;if(!y){let{action:D}=await Et.prompt([{type:"list",name:"action",message:"What would you like to do?",choices:[{name:"Link to existing project",value:"existing"},{name:"Create new project",value:"new"}]}]);if(D==="existing"){let n=await S.projects.getProjects({teamId:I});if(!n.projects||n.projects.length===0)throw new Error("No projects found. Please create a project first.");let{selectedProject:x}=await Et.prompt([{type:"list",name:"selectedProject",message:"Select a project to link:",choices:n.projects.map(g=>({name:g.name,value:g.id}))}]);y=x;let h=n.projects.find(g=>g.id===x);c(h?.name||x)}else{let{newProjectName:n}=await Et.prompt([{type:"input",name:"newProjectName",message:"Enter project name:",validate:h=>h?/^[a-z0-9-]+$/.test(h)?!0:"Project name must contain only lowercase letters, numbers, and hyphens":"Project name is required"}]),x=await S.projects.createProject({requestBody:{name:n,framework:void 0},teamId:I});y=x.id,c(x.name)}}dn(v,{recursive:!0});let B={projectId:y,orgId:I,settings:{createdAt:Date.now(),framework:void 0,devCommand:null,installCommand:null,buildCommand:null}};Bo(Pe(v,"project.json"),JSON.stringify(B,null,2)),Bo(Pe(v,".gitignore"),`*
`),i(!0),o(!1)}catch(m){s(m instanceof Error?m.message:"An error occurred"),o(!1)}}return t?Bt(ee,{label:"Linking project..."}):r?Bt(Eo,{flexDirection:"column",children:Dt(Ct,{color:"red",children:["\u274C Error: ",r]})}):l?Dt(Eo,{flexDirection:"column",children:[Dt(Ct,{color:"green",children:["\u2705 Successfully linked to project: ",a]}),Bt(Ct,{color:"gray",children:"You can now use 'vm start' to create a sandbox"})]}):null}import{useState as X,useEffect as fn}from"react";import{Box as N,Text as F,useInput as gn}from"ink";import{Spinner as xn,Alert as Do,StatusMessage as hn,UnorderedList as ko,Select as Sn,TextInput as Ao,Badge as jo}from"@inkjs/ui";import{Vercel as kt}from"@vercel/sdk";import{jsx as E,jsxs as q}from"react/jsx-runtime";function Ze({action:e,args:t,flags:o}){let[r,s]=X(!1),[l,i]=X(null),[a,c]=X([]),[u,m]=X(null),[S,p]=X("list"),[v,y]=X(null),[I,B]=X(""),[D,n]=X(""),[x,h]=X(!0);fn(()=>{g()},[]),gn((f,T)=>{S==="list"?f==="a"?(p("add"),B(""),n(""),h(!0)):f==="r"&&a.length>0?p("remove"):f==="f"&&g():S==="menu"?T.escape&&p("list"):(S==="add"||S==="remove")&&T.escape&&(p("list"),i(null),m(null))});async function g(){try{s(!0),i(null);let f=await j();if(!f.token||!f.teamId||!f.projectId)throw new Error("Authentication required. Please run 'vm link' first.");y(f);let H=await new kt({bearerToken:f.token}).projects.filterProjectEnvs({idOrName:f.projectId}),Qo=Array.isArray(H)?H:H.envs||[];c(Qo),s(!1)}catch(f){i(f instanceof Error?f.message:"An error occurred"),s(!1)}}async function P(){if(!I||!D){i("Both key and value are required");return}try{s(!0);let f=new kt({bearerToken:v.token}),T=[];o.prod&&T.push("production"),o.preview&&T.push("preview"),o.development&&T.push("development"),T.length===0&&T.push("development"),await f.projects.createProjectEnv({idOrName:v.projectId,upsert:"true",requestBody:[{key:I,value:D,target:T,type:"encrypted"}]}),m(`Added ${I}`),p("list"),await g()}catch(f){i(f instanceof Error?f.message:"Failed to add environment variable"),s(!1)}}async function L(f){try{s(!0),await new kt({bearerToken:v.token}).projects.removeProjectEnv({idOrName:v.projectId,id:f});let _=a.find(H=>H.id===f);m(`Removed ${_?.key}`),p("list"),await g()}catch(T){i(T instanceof Error?T.message:"Failed to remove environment variable"),s(!1)}}if(r)return E(xn,{label:"Loading environment variables..."});if(l)return E(Do,{variant:"error",title:"Error",children:l});if(S==="add")return q(N,{flexDirection:"column",gap:2,children:[q(N,{flexDirection:"column",gap:1,children:[E(F,{bold:!0,children:"Add Environment Variable"}),E(F,{dimColor:!0,children:"ESC to cancel"})]}),q(N,{flexDirection:"column",gap:1,children:[E(F,{children:"Key:"}),x?E(Ao,{defaultValue:I,onSubmit:f=>{B(f),f&&h(!1)},placeholder:"Enter variable name..."}):E(F,{color:"green",children:I})]}),!x&&q(N,{flexDirection:"column",gap:1,children:[E(F,{children:"Value:"}),E(Ao,{defaultValue:D,onSubmit:f=>{n(f),P()},placeholder:"Enter value..."})]}),E(N,{marginTop:1,children:q(F,{dimColor:!0,children:["Target:"," ",o.prod?"production":o.preview?"preview":"development"]})})]});if(S==="remove"){let f=a.map(T=>({label:`${T.key} (${T.target?.join(", ")||"all"})`,value:T.id}));return q(N,{flexDirection:"column",gap:2,children:[q(N,{flexDirection:"column",gap:1,children:[E(F,{bold:!0,children:"Remove Environment Variable"}),E(F,{dimColor:!0,children:"Select a variable to remove \u2022 ESC to cancel"})]}),E(N,{flexGrow:1,children:E(Sn,{options:f,onChange:T=>L(T)})})]})}return q(N,{flexDirection:"column",height:"100%",children:[q(N,{flexDirection:"column",marginBottom:2,children:[q(N,{alignItems:"center",gap:2,children:[E(F,{bold:!0,children:"Environment Variables"}),E(jo,{color:a.length>0?"blue":"gray",children:a.length})]}),q(F,{dimColor:!0,children:["a: Add ",w.symbols.bullet," r: Remove ",w.symbols.bullet," f: Refresh ",w.symbols.bullet," ESC: Back"]})]}),u&&E(N,{marginBottom:2,children:E(hn,{variant:"success",children:u})}),E(N,{flexGrow:1,children:a.length===0?E(N,{justifyContent:"center",alignItems:"center",height:"100%",children:E(Do,{variant:"info",title:"No Environment Variables",children:"Press 'a' to add one"})}):E(ko,{children:a.map(f=>E(ko.Item,{children:q(N,{gap:1,children:[E(F,{bold:!0,children:f.key}),E(F,{dimColor:!0,children:"="}),E(F,{dimColor:!0,children:f.type==="encrypted"?"\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022":f.value}),E(jo,{color:"gray",children:f.target?.join(", ")||"all"})]})},f.id))})})]})}import{useState as At,useEffect as bn}from"react";import{Box as Te,Text as et}from"ink";import{NodeSSH as vn}from"node-ssh";import{readFileSync as wn,existsSync as yn}from"fs";import{join as In}from"path";import{homedir as Pn}from"os";import{jsx as ae,jsxs as jt}from"react/jsx-runtime";function Ro({sandboxId:e,command:t}){let[o,r]=At(!0),[s,l]=At(null),[i,a]=At(null);bn(()=>{c()},[]);async function c(){try{if(!e)throw new Error("Please provide a sandbox ID");if(!t||t.length===0)throw new Error("Please provide a command to execute");let m=$e.getSandboxes()[e];if(!m)throw new Error(`Sandbox ${e} not found. Run 'vm list' to see active sandboxes.`);let S=new vn,p=In(Pn(),".vm","id_rsa");if(!yn(p))throw new Error("SSH key not found. Please run 'vm start' to generate SSH keys.");let v=wn(p,"utf-8");await S.connect({host:m.host,port:m.port,username:"user",privateKey:v,readyTimeout:3e4,algorithms:{serverHostKey:["ssh-rsa","rsa-sha2-256","rsa-sha2-512"]}});let y=t.join(" "),I=await S.execCommand(y);a({stdout:I.stdout,stderr:I.stderr,exitCode:I.code||0}),S.dispose(),r(!1)}catch(u){l(u instanceof Error?u.message:"An error occurred"),r(!1)}}return o?ae(ee,{label:"Executing command..."}):s?ae(Te,{flexDirection:"column",children:jt(et,{color:"red",children:["\u274C Error: ",s]})}):i?(process.env.VM_JSON_OUTPUT&&(console.log(JSON.stringify(i)),process.exit(i.exitCode)),jt(Te,{flexDirection:"column",children:[i.stdout&&ae(Te,{flexDirection:"column",children:ae(et,{children:i.stdout})}),i.stderr&&ae(Te,{flexDirection:"column",children:ae(et,{color:"red",children:i.stderr})}),i.exitCode!==0&&ae(Te,{marginTop:1,children:jt(et,{color:"yellow",children:["Exit code: ",i.exitCode]})})]})):null}import{useState as Rt,useEffect as Tn}from"react";import{Box as Lt,Text as Vt}from"ink";import{jsx as tt,jsxs as _t}from"react/jsx-runtime";function Lo({sandboxId:e}){let[t,o]=Rt(!0),[r,s]=Rt(null),[l,i]=Rt("");Tn(()=>{a()},[]);async function a(){try{if(!e)throw new Error("Please provide a sandbox ID");if(!$e.getSandboxes()[e])throw new Error(`Sandbox ${e} not found. Run 'vm list' to see active sandboxes.`);let m=await j();if(!m.token||!m.teamId)throw new Error("Authentication required. Please run 'vm link' first.");i("Logs feature coming soon. Sandbox logs will be displayed here."),o(!1)}catch(c){s(c instanceof Error?c.message:"An error occurred"),o(!1)}}return t?tt(ee,{label:"Fetching logs..."}):r?tt(Lt,{flexDirection:"column",children:_t(Vt,{color:"red",children:["\u274C Error: ",r]})}):_t(Lt,{flexDirection:"column",children:[_t(Vt,{color:"cyan",bold:!0,children:["Sandbox Logs (",e,"):"]}),tt(Lt,{marginTop:1,children:tt(Vt,{children:l||"No logs available"})})]})}import{useState as ge,useEffect as Gn}from"react";import{Box as b,Text as k,useInput as Jn,useApp as Yn,useStdout as zn}from"ink";import{Badge as Xn}from"@inkjs/ui";import{useState as Ee,useEffect as An}from"react";import{Sandbox as jn}from"@vercel/sandbox";import _o from"ms";import{useState as Cn,useEffect as En}from"react";import{Box as de,Text as pe}from"ink";import{Spinner as Bn,StatusMessage as Dn}from"@inkjs/ui";import{jsx as W,jsxs as Ce}from"react/jsx-runtime";var kn={auth:"Authenticating with Vercel",preparing:"Preparing environment",allocating:"Allocating resources",creating:"Creating sandbox instance","installing-ssh":"Installing SSH server","configuring-ssh":"Configuring SSH access","generating-keys":"Setting up SSH keys","starting-services":"Starting services",ready:"Sandbox ready"},Mt=["auth","preparing","allocating","creating","installing-ssh","configuring-ssh","generating-keys","starting-services","ready"];function Vo({currentStep:e,error:t}){let[o,r]=Cn(0);En(()=>{let i=setInterval(()=>{r(a=>a+1)},1e3);return()=>clearInterval(i)},[]);let s=i=>{let a=Mt.indexOf(e),c=Mt.indexOf(i);return c<a?"complete":c===a?"active":"pending"},l=i=>{if(i<60)return`${i}s`;let a=Math.floor(i/60),c=i%60;return`${a}m ${c}s`};return t?W(de,{flexDirection:"column",gap:1,children:W(Dn,{variant:"error",children:t})}):Ce(de,{flexDirection:"column",gap:1,children:[Ce(de,{marginBottom:1,children:[W(pe,{bold:!0,children:"Creating Sandbox"}),Ce(pe,{dimColor:!0,children:[" (",l(o),")"]})]}),Mt.map(i=>{let a=s(i),c=kn[i];return Ce(de,{gap:1,children:[Ce(de,{width:3,children:[a==="complete"&&W(pe,{color:"green",children:w.symbols.check}),a==="active"&&W(Bn,{}),a==="pending"&&W(pe,{dimColor:!0,children:w.symbols.bullet})]}),W(pe,{color:a==="complete"?"green":a==="active"?void 0:"gray",dimColor:a==="pending",children:c})]},i)}),e!=="ready"&&W(de,{marginTop:1,children:W(pe,{dimColor:!0,italic:!0,children:"This may take a few moments..."})})]})}import{Alert as Mo}from"@inkjs/ui";import{jsx as ot}from"react/jsx-runtime";function No({flags:e}){let{token:t,teamId:o,projectId:r,userInfo:s,isLoading:l,error:i}=Ae(),[a,c]=Ee("waiting"),[u,m]=Ee("auth"),[S,p]=Ee(null),[v,y]=Ee(null),[I,B]=Ee(null);An(()=>{!l&&t&&D()},[l,t]);let D=async()=>{try{if(m("auth"),C("Starting sandbox with auth:",{hasToken:!!t,teamId:o,projectId:r}),!t||!o||!r){y("Missing authentication credentials. Please run 'vercel link' in this directory."),c("error");return}m("preparing"),c("creating"),ve();let n=null;if(e.preset){if(n=He(e.preset),!n){y(`Preset '${e.preset}' not found`),c("error");return}}else!e.runtime&&!e.timeout&&!e.ports&&(n=Ke());let x=Ue(e),h=n?{...n,...x}:x,g=h.ports||e.ports?.split(",").map(_=>Number.parseInt(_.trim()))||[2222],P={runtime:h.runtime||e.runtime||"node22",ports:g,timeout:_o(h.timeout||e.timeout||"30m"),resources:{vcpus:2},token:t,teamId:o,projectId:r};m("allocating"),C("Creating sandbox with config:",P),ke("POST","Sandbox.create",P),m("creating");let L=await jn.create(P);C("Sandbox created successfully:",{sandboxId:L.sandboxId,sshDomain:L.domain(2222)}),p(L),c("configuring"),m("installing-ssh");let f=await Ve(L,_=>m(_));if(!f.success){y(f.error||"SSH setup failed"),c("error");return}m("starting-services"),B(f.port||2222);let T=_o(e.timeout||"30m");Ne({id:L.sandboxId,runtime:e.runtime||"node22",domains:g.reduce((_,H)=>(_[H]=L.domain(H),_),{}),sshPort:f.port||2222,createdAt:new Date().toISOString(),timeout:T,expiresAt:new Date(Date.now()+T).toISOString(),status:"active"}),m("ready"),c("ready")}catch(n){M("Sandbox creation failed",n);let x="Unknown error occurred";n instanceof Error&&(x=n.message),n.response?.status===400&&(x=`Bad Request (400): ${n.response?.data?.error||n.response?.data?.message||x}`,C("400 Error details:",n.response?.data)),y(x),c("error")}};return i?ot(Mo,{variant:"error",title:"Authentication Error",children:i}):a==="error"?ot(Mo,{variant:"error",title:"Error",children:v}):a==="ready"&&S&&I?ot(Me,{sandboxId:S.sandboxId,domain:S.domain(I),port:I,runtime:e.runtime||"node22",timeout:e.timeout||"30m",userInfo:s}):ot(Vo,{currentStep:u,error:v||void 0})}import{useState as Ho,useEffect as Vn}from"react";import{Box as fe,Text as Ht}from"ink";import Rn from"react";import{Box as Nt,Text as Ot,useInput as Ln}from"ink";import{jsx as rt,jsxs as Oo}from"react/jsx-runtime";function nt({items:e,value:t,onChange:o,onSubmit:r,isFocused:s=!0}){let[l,i]=Rn.useState(()=>{if(t){let a=e.findIndex(c=>c.value===t);return a>=0?a:0}return 0});return Ln((a,c)=>{if(s)if(c.upArrow||a==="k"){let u=l>0?l-1:e.length-1;i(u),o?.(e[u].value)}else if(c.downArrow||a==="j"){let u=l<e.length-1?l+1:0;i(u),o?.(e[u].value)}else c.return&&!e[l].disabled&&r?.(e[l].value)}),rt(Nt,{flexDirection:"column",children:e.map((a,c)=>{let u=c===l,m=u?"\u25CF":"\u25CB",S=a.disabled?"gray":u?"green":void 0;return Oo(Nt,{gap:1,children:[rt(Ot,{color:S,children:m}),Oo(Nt,{flexDirection:"column",flexGrow:1,children:[rt(Ot,{color:S,wrap:"truncate",children:a.label}),u&&a.description&&rt(Ot,{dimColor:!0,wrap:"wrap",children:a.description})]})]},c)})})}import{Box as $t,Text as Ft}from"ink";import{jsx as st,jsxs as Fo}from"react/jsx-runtime";function it({label:e,value:t,width:o=20,dimLabel:r=!1}){return Fo($t,{children:[st($t,{width:o,children:st(Ft,{dimColor:r,children:e})}),st(Ft,{children:t})]})}function $o({title:e,children:t}){return Fo($t,{flexDirection:"column",borderStyle:"single",borderColor:"gray",paddingX:1,children:[st(Ft,{bold:!0,children:e}),t]})}import{jsx as Q,jsxs as Be}from"react/jsx-runtime";function Ko({onSelect:e,onCancel:t}){let[o,r]=Ho([]),[s,l]=Ho("custom");Vn(()=>{let u=Fe();r(u);let m=u.find(S=>S.isDefault);m&&l(m.id)},[]);let i=[...o.map(u=>({label:`${u.name}${u.isDefault?" (default)":""}`,value:u.id,description:u.description})),{label:"Custom Configuration",value:"custom",description:"Configure VM settings manually"}],a=u=>{if(u==="custom")t();else{let m=o.find(S=>S.id===u);m&&e(m)}},c=o.find(u=>u.id===s);return Be(fe,{flexDirection:"column",height:"100%",padding:1,children:[Be(fe,{flexDirection:"column",marginBottom:2,children:[Q(Ht,{bold:!0,children:"Select VM Preset"}),Q(Ht,{dimColor:!0,children:"Choose a preset configuration or create custom"})]}),Be(fe,{flexDirection:"row",gap:4,flexGrow:1,children:[Q(fe,{flexDirection:"column",flexGrow:1,children:Q(nt,{items:i,value:s,onChange:l,onSubmit:a})}),c&&Q(fe,{width:30,children:Be($o,{title:"Preset Details",children:[Q(it,{label:"Runtime",value:c.runtime}),Q(it,{label:"Timeout",value:c.timeout}),c.ports&&c.ports.length>0&&Q(it,{label:"Ports",value:c.ports.join(", ")})]})})]}),Q(fe,{marginTop:2,children:Be(Ht,{dimColor:!0,children:[w.symbols.arrow," Navigate ",w.symbols.bullet," Enter to select"," ",w.symbols.bullet," ESC for menu"]})})]})}import{useState as at,useEffect as _n}from"react";import{Box as oe,Text as ce,useInput as Mn}from"ink";import{Select as Nn,Badge as On,Alert as $n,ConfirmInput as Fn}from"@inkjs/ui";import{jsx as re,jsxs as Y}from"react/jsx-runtime";function Uo(){let[e,t]=at([]),[o,r]=at(null),[s,l]=at("list"),[i,a]=at(null);_n(()=>{c()},[]);let c=()=>{let p=Fe();t(p),!o&&p.length>0&&r(p[0].id)};Mn(p=>{if(s!=="delete-confirm")if(p==="d"&&o){let v=e.find(y=>y.id===o);v&&!["quick-node","long-node","python","web-dev"].includes(v.id)&&(a(v),l("delete-confirm"))}else p==="s"&&o?(fo(o),c()):p==="r"&&c()});let u=async()=>{i&&(await po(i.id),c()),l("list"),a(null)},m=()=>{l("list"),a(null)};if(s==="delete-confirm"&&i)return Y(oe,{flexDirection:"column",height:"100%",justifyContent:"center",alignItems:"center",children:[Y($n,{variant:"warning",title:"Delete Preset?",children:['Delete preset "',i.name,'"?']}),re(oe,{marginTop:2,children:re(Fn,{onConfirm:u,onCancel:m})})]});let S=e.map(p=>({label:`${p.name}${p.isDefault?" (default)":""}`,value:p.id}));return Y(oe,{flexDirection:"column",height:"100%",children:[Y(oe,{flexDirection:"column",marginBottom:2,children:[Y(oe,{alignItems:"center",gap:2,children:[re(ce,{bold:!0,children:"VM Presets"}),re(On,{color:"blue",children:e.length})]}),Y(ce,{dimColor:!0,children:["s: Set as default ",w.symbols.bullet," d: Delete ",w.symbols.bullet," r: Refresh ",w.symbols.bullet," ESC: Back"]})]}),re(oe,{flexGrow:1,children:re(Nn,{options:S,onChange:r,defaultValue:o||void 0})}),o&&(()=>{let p=e.find(v=>v.id===o);return p?Y(oe,{flexDirection:"column",marginTop:2,gap:1,children:[re(ce,{dimColor:!0,children:p.description}),Y(oe,{gap:2,children:[Y(ce,{dimColor:!0,children:["Runtime: ",p.runtime]}),Y(ce,{dimColor:!0,children:["Timeout: ",p.timeout]}),p.ports&&Y(ce,{dimColor:!0,children:["Ports: ",p.ports.join(", ")]})]}),["quick-node","long-node","python","web-dev"].includes(o)&&re(ce,{dimColor:!0,italic:!0,children:"Built-in preset (cannot be deleted)"})]}):null})()]})}import{Box as Hn,Text as qo}from"ink";import{jsx as Go,jsxs as qn}from"react/jsx-runtime";var Kn=`
\u2588\u2588\u2557 \u2588\u2588\u2557\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2557
\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2551
\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2554\u2588\u2588\u2588\u2588\u2554\u2588\u2588\u2551
\u255A\u2588\u2588\u2557 \u2588\u2588\u2554\u255D\u2588\u2588\u2551\u255A\u2588\u2588\u2554\u255D\u2588\u2588\u2551
\u255A\u2588\u2588\u2588\u2588\u2554\u255D \u2588\u2588\u2551 \u255A\u2550\u255D \u2588\u2588\u2551
\u255A\u2550\u2550\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u255D
`,Un="VM";function Jo({terminalWidth:e=80,subtitle:t}){let r=e<40?Un:Kn.trim();return qn(Hn,{flexDirection:"column",marginBottom:1,children:[Go(qo,{bold:!0,children:r}),t&&Go(qo,{dimColor:!0,children:t})]})}import{jsx as d,jsxs as A}from"react/jsx-runtime";var Wn=e=>[{label:"Start New Sandbox",value:"start",description:"Launch a fresh development environment"},{label:"List Sandboxes",value:"list",description:"View all active sandboxes"},{label:`Link Project${e?` ${w.symbols.check}`:""}`,value:"link",description:"Connect to a Vercel project"},{label:"Environment Variables",value:"env",description:"Manage project environment variables"},{label:"VM Presets",value:"presets",description:"Manage VM configuration presets"},{label:"Help",value:"help",description:"View commands and shortcuts"}];function Yo(){let[e,t]=ge("menu"),[o,r]=ge(0),[s,l]=ge([]),[i,a]=ge(!1),[c,u]=ge({teamId:null,projectId:null,projectName:null,teamName:null}),[m,S]=ge(null),{exit:p}=Yn(),{stdout:v}=zn();Gn(()=>{y(),I();let n=setInterval(()=>{y()},3e4);return()=>clearInterval(n)},[e]);let y=async()=>{await Ye();let n=await j();n.token&&n.teamId&&n.projectId&&await Je({token:n.token,teamId:n.teamId,projectId:n.projectId});let x=se();l(x),r(x.length)},I=async()=>{let n=await j();a(!!n.projectId&&!!n.teamId);let x=null,h=null;n.token&&n.teamId&&n.projectId&&(x=(await Yt(n.token,n.teamId,n.projectId))?.name||null,h=(await zt(n.token,n.teamId))?.name||null),u({teamId:n.teamId,projectId:n.projectId,projectName:x,teamName:h})};Jn((n,x)=>{if(e!=="menu"){x.escape&&t("menu");return}(n==="q"||x.ctrl&&n==="c")&&p()});let B=n=>{t(n==="start"?"preset-selector":n)};if(e==="preset-selector")return d(Ko,{onSelect:n=>{S(n),t("start")},onCancel:()=>{S(null),t("start")}});if(e==="start")return A(b,{flexDirection:"column",height:"100%",paddingX:1,paddingY:1,children:[d(b,{marginBottom:1,children:d(k,{dimColor:!0,children:"ESC to return to menu"})}),d(b,{flexGrow:1,children:d(No,{flags:m?{preset:m.id}:{runtime:"node22",timeout:"30m",ports:"2222"}})})]});if(e==="list")return A(b,{flexDirection:"column",height:"100%",paddingX:2,paddingY:1,children:[d(b,{marginBottom:1,children:d(k,{dimColor:!0,children:"ESC to return to menu"})}),d(b,{flexGrow:1,children:d(ze,{prefetchedData:s})})]});if(e==="link")return A(b,{flexDirection:"column",height:"100%",paddingX:2,paddingY:1,children:[d(b,{marginBottom:1,children:d(k,{dimColor:!0,children:"ESC to return to menu"})}),d(b,{flexGrow:1,children:d(Qe,{flags:{}})})]});if(e==="env")return A(b,{flexDirection:"column",height:"100%",paddingX:2,paddingY:1,children:[d(b,{marginBottom:1,children:d(k,{dimColor:!0,children:"ESC to return to menu"})}),d(b,{flexGrow:1,children:d(Ze,{action:"list",args:[],flags:{}})})]});if(e==="presets")return A(b,{flexDirection:"column",height:"100%",paddingX:2,paddingY:1,children:[d(b,{marginBottom:1,children:d(k,{dimColor:!0,children:"ESC to return to menu"})}),d(b,{flexGrow:1,children:d(Uo,{})})]});if(e==="help")return A(b,{flexDirection:"column",height:"100%",paddingX:2,paddingY:1,children:[A(b,{flexDirection:"column",children:[d(k,{bold:!0,children:"Keyboard Shortcuts"}),A(b,{marginTop:1,flexDirection:"column",gap:1,children:[A(b,{children:[d(b,{width:12,children:d(k,{dimColor:!0,children:"\u2191/\u2193 or j/k"})}),d(k,{children:"Navigate menu"})]}),A(b,{children:[d(b,{width:12,children:d(k,{dimColor:!0,children:"Enter"})}),d(k,{children:"Select option"})]}),A(b,{children:[d(b,{width:12,children:d(k,{dimColor:!0,children:"1-5"})}),d(k,{children:"Quick select"})]}),A(b,{children:[d(b,{width:12,children:d(k,{dimColor:!0,children:"ESC"})}),d(k,{children:"Back to menu"})]}),A(b,{children:[d(b,{width:12,children:d(k,{dimColor:!0,children:"q"})}),d(k,{children:"Quit"})]})]})]}),d(b,{flexGrow:1}),d(b,{children:d(k,{dimColor:!0,children:"ESC to return to menu"})})]});let D=Wn(i);return A(b,{flexDirection:"column",height:"100%",paddingX:2,paddingY:1,children:[d(Jo,{terminalWidth:v?.columns,subtitle:"Ephemeral VMs on Vercel"}),d(b,{flexDirection:"column",marginBottom:2,children:A(b,{gap:3,children:[A(b,{children:[d(k,{dimColor:!0,children:"Active Sandboxes: "}),d(Xn,{color:o>0?"blue":"gray",children:o})]}),i&&A(b,{children:[d(k,{dimColor:!0,children:"Project: "}),d(k,{children:c.projectName||c.projectId?.slice(0,8)+"..."})]}),c.teamName&&A(b,{children:[d(k,{dimColor:!0,children:"Team: "}),d(k,{children:c.teamName})]})]})}),d(b,{flexDirection:"column",flexGrow:1,children:d(nt,{items:D,onSubmit:B})}),d(b,{marginTop:1,children:A(k,{dimColor:!0,children:[w.symbols.arrow," Navigate ",w.sym