velloo 0.2.0 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (88) hide show
  1. package/README.md +1 -1
  2. package/canvas/assets/index-DZFrkC4P.js +29 -0
  3. package/canvas/assets/index-gB0StCrx.css +2 -0
  4. package/canvas/assets/lucide-all-Bu8-9UDF.js +1 -0
  5. package/canvas/assets/{radix-C3HaOB-d.js → radix-gmpYzWRH.js} +1 -1
  6. package/canvas/index.html +3 -3
  7. package/chunk-0s6drs3n.js +2 -0
  8. package/chunk-0zen7bzb.js +3 -0
  9. package/{chunk-er1fxb7d.js → chunk-1xb88e07.js} +1 -1
  10. package/{chunk-jv0xggh0.js → chunk-2e3nd4tz.js} +1 -1
  11. package/{chunk-08sv3k41.js → chunk-2fgfex9b.js} +1 -1
  12. package/{chunk-a84n72m2.js → chunk-2p37rp3j.js} +1 -1
  13. package/{chunk-ydhwv29b.js → chunk-2zbn6641.js} +2 -2
  14. package/{chunk-6w6ch4ce.js → chunk-3px2d1j1.js} +1 -1
  15. package/{chunk-2c7jbx46.js → chunk-4e9jh482.js} +1 -1
  16. package/{chunk-dgwjpbp9.js → chunk-4g250157.js} +1 -1
  17. package/{chunk-sjgqnykd.js → chunk-4ma2wnqw.js} +1 -1
  18. package/{chunk-x4f4k9pp.js → chunk-59zas5y2.js} +7 -7
  19. package/{chunk-0fe83yzt.js → chunk-5wv5a52y.js} +1 -1
  20. package/{chunk-bwnvcncx.js → chunk-6zz9kfbd.js} +1 -1
  21. package/{chunk-mh2pr7cq.js → chunk-7cvhnp9h.js} +1 -1
  22. package/{chunk-1h55s5he.js → chunk-7s8frnag.js} +1 -1
  23. package/chunk-7t13w87m.js +2 -0
  24. package/{chunk-zb6hc1y0.js → chunk-7yaafw73.js} +1 -1
  25. package/chunk-88eqqdk1.js +688 -0
  26. package/{chunk-ampmdzz4.js → chunk-8z3ykvcs.js} +1 -1
  27. package/{chunk-r22epxz2.js → chunk-98vvrj0c.js} +1 -1
  28. package/{chunk-vdkrbzh1.js → chunk-9cdwhrkh.js} +1 -1
  29. package/{chunk-xt5ayg7g.js → chunk-9p1dk5cb.js} +1 -1
  30. package/{chunk-dg6z4vdd.js → chunk-9psr8atb.js} +1 -1
  31. package/{chunk-4fj5tahv.js → chunk-9ydc34wc.js} +1 -1
  32. package/{chunk-pp86v6m6.js → chunk-as08hzp3.js} +1 -1
  33. package/chunk-asbajsmd.js +5 -0
  34. package/{chunk-vgmr98cv.js → chunk-avkfsc3p.js} +1 -1
  35. package/{chunk-ngnymg2q.js → chunk-bhx8k09w.js} +1 -1
  36. package/{chunk-3e8vez4d.js → chunk-c4fym47a.js} +63 -19
  37. package/{chunk-jb21jkp1.js → chunk-c6hywdvq.js} +1 -1
  38. package/{chunk-rpwpeph5.js → chunk-f0vsjfpc.js} +1 -1
  39. package/{chunk-ek71z2fv.js → chunk-g71v35gd.js} +1 -1
  40. package/{chunk-80r93t2e.js → chunk-hfzg98c8.js} +1 -1
  41. package/{chunk-jfx9xjmr.js → chunk-js6mz7h1.js} +1 -1
  42. package/{chunk-4dn75m6t.js → chunk-mfbxfb9b.js} +1 -1
  43. package/{chunk-mnapdp1y.js → chunk-mt8ds8zj.js} +1 -1
  44. package/chunk-n9t36h0q.js +2 -0
  45. package/{chunk-fsbsksga.js → chunk-nev5mv85.js} +1 -1
  46. package/{chunk-40xgcth8.js → chunk-nte0t7v3.js} +2 -2
  47. package/{chunk-hcb68zt7.js → chunk-p62fygqz.js} +1 -1
  48. package/{chunk-ayrb3qnm.js → chunk-p6e1eg76.js} +1 -1
  49. package/{chunk-7eq7nx37.js → chunk-ph2jfg1x.js} +1 -1
  50. package/{chunk-n9gs6yx9.js → chunk-pve2mmnr.js} +1 -1
  51. package/{chunk-avns4dbf.js → chunk-sn9vg42q.js} +1 -1
  52. package/{chunk-dy41n60j.js → chunk-t2w8a591.js} +5 -5
  53. package/{chunk-735ezz23.js → chunk-t5m5mznb.js} +2 -2
  54. package/{chunk-6nqghjda.js → chunk-t947mxr1.js} +1 -1
  55. package/chunk-tt7fys2w.js +2 -0
  56. package/chunk-wafb2xm9.js +6 -0
  57. package/{chunk-sn3x2m0m.js → chunk-whw3epmr.js} +1 -1
  58. package/{chunk-j11fyeqh.js → chunk-wndntr7s.js} +1 -1
  59. package/{chunk-7eyb8yrf.js → chunk-wnwgqvtd.js} +1 -1
  60. package/{chunk-v40fn08f.js → chunk-wp123630.js} +2 -2
  61. package/{chunk-ccszg02q.js → chunk-wvs939t5.js} +1 -1
  62. package/{chunk-jr0ss0mm.js → chunk-z21hg6j3.js} +2 -2
  63. package/cli.js +1 -1
  64. package/package.json +1 -1
  65. package/pkgs/helpers/src/descriptors.ts +7 -1
  66. package/pkgs/provider-antd/src/index.ts +1 -0
  67. package/pkgs/provider-chakra/src/index.ts +1 -0
  68. package/pkgs/provider-mui/src/index.ts +1 -0
  69. package/pkgs/provider-none/src/index.ts +42 -1
  70. package/pkgs/provider-none/src/intro.ts +2 -2
  71. package/pkgs/schema/src/config.ts +19 -0
  72. package/pkgs/schema/src/extension.ts +26 -0
  73. package/pkgs/schema/src/index.ts +10 -0
  74. package/pkgs/schema/src/node.ts +99 -0
  75. package/pkgs/schema/src/screen.ts +7 -0
  76. package/pkgs/shadcn-snapshot/dist/manifest.json +9 -1
  77. package/skills/velloo-setup/SKILL.md +70 -48
  78. package/canvas/assets/index-BCvDZiBo.css +0 -2
  79. package/canvas/assets/index-ClaBqcaS.js +0 -28
  80. package/canvas/assets/lucide-all-iIF-pmzN.js +0 -1
  81. package/chunk-308ynsxd.js +0 -2
  82. package/chunk-9vg3yafz.js +0 -3
  83. package/chunk-eyr8hrzf.js +0 -2
  84. package/chunk-k17gfwq3.js +0 -2
  85. package/chunk-rgasy862.js +0 -5
  86. package/chunk-t448rrfr.js +0 -2
  87. package/chunk-tdsk5wxa.js +0 -451
  88. package/chunk-vsv8z729.js +0 -6
@@ -1,5 +1,5 @@
1
1
  // @bun
2
- import{ScreenSchema}from"./chunk-40xgcth8.js";import{detectTailwindMajor,emitCode,moduleTarget,v3ClassIssues,classNamesInJsx,styleChannelOf,loadDesignFolder,hostAppRootFrom,resolveProviders}from"./chunk-tdsk5wxa.js";import"./chunk-t448rrfr.js";import"./chunk-3e8vez4d.js";import"./chunk-80fjfyha.js";import{fail}from"./chunk-s23gtejf.js";import{findDesignConfig}from"./chunk-ngnymg2q.js";import{createProgress}from"./chunk-pjtg3wnm.js";import{DESIGN_ARG_DESCRIPTION,resolveDesign,pickScreen}from"./chunk-vsv8z729.js";import{defineCommand}from"./chunk-2smsg2ct.js";import{readFile,writeFile}from"fs/promises";import{isAbsolute,resolve}from"path";import{stdout}from"process";async function folderEmitContext(screenPath,screen){let found=await findDesignConfig(screenPath);if(!found)return{};let design=await loadDesignFolder(found.folder),{providers,defaultProvider}=await resolveProviders(design.config,found.folder),provider=screen.library&&providers[screen.library]||defaultProvider,adapter=provider,target;if(adapter.codegenModule){let manifest=await provider.loadManifest();target=moduleTarget(manifest.filter((c)=>c.source!=="velloo").map((c)=>c.id),adapter.codegenModule)}let inlineStyle=styleChannelOf(provider,design.config.styling?.framework).kind==="style";return{snippets:design.snippets,...design.config.extensions?{extensions:design.config.extensions}:{},...target?{target}:{},...inlineStyle?{inlineStyle:!0}:{}}}var emit_default=defineCommand({meta:{name:"emit",description:"Print or write agent-consumed IR for a screen."},args:{screen:{type:"positional",required:!1,description:"Screen id, or a path to a screen JSON. Omit to pick interactively."},design:{type:"string",description:DESIGN_ARG_DESCRIPTION},to:{type:"string",description:"Write IR as JSON to this path. Omit to print the JSX body to stdout (agent-friendly when piped)."},"components-alias":{type:"string",description:'Override the import prefix the IR mentions in snippet identifiers. Defaults to .design/config.json#codegen.componentsAlias, else "@/components/ui".'}},async run({args}){let interactive=Boolean(process.stdin.isTTY),screenArg=args.screen,screenPath=!!screenArg&&(screenArg.includes("/")||screenArg.endsWith(".json"))?resolve(screenArg):(await pickScreen(await resolveDesign(args.design,"emit",{designFlag:"--design"}),screenArg,interactive,"emit")).path,screenJson=JSON.parse(await readFile(screenPath,"utf8")),screen=ScreenSchema.parse(screenJson),progress=createProgress();progress.start("preparing code");try{let componentsAlias=args["components-alias"]??await readConfigAlias(screenPath),context=await folderEmitContext(screenPath,screen);progress.step("generating code");let result=await emitCode(screen,{...componentsAlias?{componentsAlias}:{},...context});if(!result.ok){progress.fail("code generation failed");let e=result.error;if(e.kind==="UnknownComponent")fail("emit",`unknown component: ${JSON.stringify(e.ref)}`);else if(e.kind==="SnippetNotFound")fail("emit",`snippet not found: ${JSON.stringify(e.snippetId)}`);else fail("emit",`screen not found: ${JSON.stringify(e.screenId)}`)}let found=await findDesignConfig(screenPath),tailwindV3Compat=found&&!context?.target&&!context?.inlineStyle?detectTailwindMajor(hostAppRootFrom(found.folder,found.config.hostApp))===3?v3ClassIssues([...result.value.classesUsed,...result.value.snippetsUsed.flatMap((s)=>classNamesInJsx(s.jsx))]):[]:[];if(args.to){progress.step("writing code");let outPath=isAbsolute(args.to)?args.to:resolve(args.to),ir=tailwindV3Compat.length>0?{...result.value,tailwindV3Compat}:result.value;await writeFile(outPath,JSON.stringify(ir,null,2),"utf8"),progress.succeed("generated code"),console.log(`velloo emit: wrote ${outPath}`);return}if(progress.succeed("generated code"),stdout.write(`// screen: ${result.value.screen.id} (${result.value.screen.name})
2
+ import{ScreenSchema}from"./chunk-nte0t7v3.js";import{detectTailwindMajor,emitCode,moduleTarget,v3ClassIssues,classNamesInJsx,styleChannelOf,loadDesignFolder,hostAppRootFrom,resolveProviders}from"./chunk-88eqqdk1.js";import"./chunk-n9t36h0q.js";import"./chunk-c4fym47a.js";import"./chunk-80fjfyha.js";import{fail}from"./chunk-s23gtejf.js";import{findDesignConfig}from"./chunk-bhx8k09w.js";import{createProgress}from"./chunk-pjtg3wnm.js";import{DESIGN_ARG_DESCRIPTION,resolveDesign,pickScreen}from"./chunk-wafb2xm9.js";import{defineCommand}from"./chunk-2smsg2ct.js";import{readFile,writeFile}from"fs/promises";import{isAbsolute,resolve}from"path";import{stdout}from"process";async function folderEmitContext(screenPath,screen){let found=await findDesignConfig(screenPath);if(!found)return{};let design=await loadDesignFolder(found.folder),{providers,defaultProvider}=await resolveProviders(design.config,found.folder),provider=screen.library&&providers[screen.library]||defaultProvider,adapter=provider,target;if(adapter.codegenModule){let manifest=await provider.loadManifest();target=moduleTarget(manifest.filter((c)=>c.source!=="velloo").map((c)=>c.id),adapter.codegenModule)}let inlineStyle=styleChannelOf(provider,design.config.styling?.framework).kind==="style";return{snippets:design.snippets,...design.config.extensions?{extensions:design.config.extensions}:{},...target?{target}:{},...inlineStyle?{inlineStyle:!0}:{}}}var emit_default=defineCommand({meta:{name:"emit",description:"Print or write agent-consumed IR for a screen."},args:{screen:{type:"positional",required:!1,description:"Screen id, or a path to a screen JSON. Omit to pick interactively."},design:{type:"string",description:DESIGN_ARG_DESCRIPTION},to:{type:"string",description:"Write IR as JSON to this path. Omit to print the JSX body to stdout (agent-friendly when piped)."},"components-alias":{type:"string",description:'Override the import prefix the IR mentions in snippet identifiers. Defaults to .design/config.json#codegen.componentsAlias, else "@/components/ui".'}},async run({args}){let interactive=Boolean(process.stdin.isTTY),screenArg=args.screen,screenPath=!!screenArg&&(screenArg.includes("/")||screenArg.endsWith(".json"))?resolve(screenArg):(await pickScreen(await resolveDesign(args.design,"emit",{designFlag:"--design"}),screenArg,interactive,"emit")).path,screenJson=JSON.parse(await readFile(screenPath,"utf8")),screen=ScreenSchema.parse(screenJson),progress=createProgress();progress.start("preparing code");try{let componentsAlias=args["components-alias"]??await readConfigAlias(screenPath),context=await folderEmitContext(screenPath,screen);progress.step("generating code");let result=await emitCode(screen,{...componentsAlias?{componentsAlias}:{},...context});if(!result.ok){progress.fail("code generation failed");let e=result.error;if(e.kind==="UnknownComponent")fail("emit",`unknown component: ${JSON.stringify(e.ref)}`);else if(e.kind==="SnippetNotFound")fail("emit",`snippet not found: ${JSON.stringify(e.snippetId)}`);else fail("emit",`screen not found: ${JSON.stringify(e.screenId)}`)}let found=await findDesignConfig(screenPath),tailwindV3Compat=found&&!context?.target&&!context?.inlineStyle?detectTailwindMajor(hostAppRootFrom(found.folder,found.config.hostApp))===3?v3ClassIssues([...result.value.classesUsed,...result.value.snippetsUsed.flatMap((s)=>classNamesInJsx(s.jsx))]):[]:[];if(args.to){progress.step("writing code");let outPath=isAbsolute(args.to)?args.to:resolve(args.to),ir=tailwindV3Compat.length>0?{...result.value,tailwindV3Compat}:result.value;await writeFile(outPath,JSON.stringify(ir,null,2),"utf8"),progress.succeed("generated code"),console.log(`velloo emit: wrote ${outPath}`);return}if(progress.succeed("generated code"),stdout.write(`// screen: ${result.value.screen.id} (${result.value.screen.name})
3
3
  `),stdout.write(`// components: ${result.value.componentsUsed.join(", ")||"(none)"}
4
4
  `),result.value.iconsUsed.length>0)stdout.write(`// icons (lucide): ${result.value.iconsUsed.join(", ")}
5
5
  `);if(result.value.snippetsUsed.length>0)stdout.write(`// snippets: ${result.value.snippetsUsed.map((s)=>`${s.componentName}(${s.id})`).join(", ")}
@@ -1,3 +1,3 @@
1
1
  // @bun
2
- import{isCancel,select}from"./chunk-80fjfyha.js";import"./chunk-40xgcth8.js";import"./chunk-tdsk5wxa.js";import"./chunk-t448rrfr.js";import"./chunk-3e8vez4d.js";import"./chunk-dg6z4vdd.js";import{daemonRoot,listDaemons,stopDaemon}from"./chunk-sjgqnykd.js";import{fail}from"./chunk-s23gtejf.js";import"./chunk-08sv3k41.js";import"./chunk-4fj5tahv.js";import"./chunk-cvn689d5.js";import"./chunk-dy41n60j.js";import{designWithFolder}from"./chunk-dgwjpbp9.js";import{DESIGN_ARG_DESCRIPTION,resolveDesign}from"./chunk-vsv8z729.js";import"./chunk-735ezz23.js";import"./chunk-pp86v6m6.js";import{require_picocolors}from"./chunk-jrsknzjt.js";import{__toESM,defineCommand}from"./chunk-2smsg2ct.js";import{resolve}from"path";var import_picocolors=__toESM(require_picocolors(),1);var ALL="__all__",canvasLine=(d)=>`${designWithFolder(d.root,void 0,{absolute:!0})} \u2014 ${d.canvasUrl}`;async function stopEach(daemons){for(let d of daemons)await stopDaemon(d.root),console.log(`velloo: stopped ${canvasLine(d)}`)}async function designHere(){try{return await resolveDesign(void 0,"stop",{onFail:()=>{throw Error("no design here")}})}catch{return}}function runningFor(daemons,folder){if(!folder)return;let root=resolve(daemonRoot(folder));return daemons.find((d)=>resolve(d.root)===root)?.root}var stop_default=defineCommand({meta:{name:"stop",description:"Stop a running canvas (picks from the running ones when none is named)"},args:{design:{type:"positional",required:!1,description:DESIGN_ARG_DESCRIPTION},all:{type:"boolean",default:!1,description:"Stop every running velloo canvas on this machine"}},async run({args}){if(args.all){let daemons=await listDaemons();if(daemons.length===0)console.log("velloo: no canvas daemons running.");else await stopEach(daemons);return}if(!args.design&&process.stdin.isTTY){let daemons=await listDaemons();if(daemons.length===0){console.log("velloo: no canvas daemons running.");return}if(daemons.length===1){await stopEach(daemons);return}let here=runningFor(daemons,await designHere()),ordered=[...daemons].sort((a,b)=>a.root===here?-1:b.root===here?1:0),chosen=await select({message:"Stop which canvas?",options:[...ordered.map((d)=>({value:d.root,label:designWithFolder(d.root,void 0,{absolute:!0}),hint:d.root===here?`${d.canvasUrl} \xB7 this directory`:d.canvasUrl})),{value:ALL,label:`All ${daemons.length} canvases`}],...here?{initialValue:here}:{}});if(isCancel(chosen))fail("stop","cancelled.");await stopEach(chosen===ALL?daemons:daemons.filter((d)=>d.root===chosen));return}if(!args.design&&!await designHere()){let daemons=await listDaemons();if(daemons.length===0){console.log("velloo: no canvas daemons running.");return}fail("stop",[`there is no design in this directory. ${daemons.length} canvas${daemons.length===1?" is":"es are"} running \u2014 stop one by its design folder, or all of them with \`velloo stop --all\`:`,...daemons.map((d)=>` ${canvasLine(d)}`)].join(`
2
+ import{isCancel,select}from"./chunk-80fjfyha.js";import"./chunk-nte0t7v3.js";import"./chunk-88eqqdk1.js";import"./chunk-n9t36h0q.js";import"./chunk-c4fym47a.js";import"./chunk-9psr8atb.js";import{daemonRoot,listDaemons,stopDaemon}from"./chunk-4ma2wnqw.js";import{fail}from"./chunk-s23gtejf.js";import"./chunk-2fgfex9b.js";import"./chunk-9ydc34wc.js";import"./chunk-cvn689d5.js";import"./chunk-t2w8a591.js";import{designWithFolder}from"./chunk-4g250157.js";import{DESIGN_ARG_DESCRIPTION,resolveDesign}from"./chunk-wafb2xm9.js";import"./chunk-t5m5mznb.js";import"./chunk-as08hzp3.js";import{require_picocolors}from"./chunk-jrsknzjt.js";import{__toESM,defineCommand}from"./chunk-2smsg2ct.js";import{resolve}from"path";var import_picocolors=__toESM(require_picocolors(),1);var ALL="__all__",canvasLine=(d)=>`${designWithFolder(d.root,void 0,{absolute:!0})} \u2014 ${d.canvasUrl}`;async function stopEach(daemons){for(let d of daemons)await stopDaemon(d.root),console.log(`velloo: stopped ${canvasLine(d)}`)}async function designHere(){try{return await resolveDesign(void 0,"stop",{onFail:()=>{throw Error("no design here")}})}catch{return}}function runningFor(daemons,folder){if(!folder)return;let root=resolve(daemonRoot(folder));return daemons.find((d)=>resolve(d.root)===root)?.root}var stop_default=defineCommand({meta:{name:"stop",description:"Stop a running canvas (picks from the running ones when none is named)"},args:{design:{type:"positional",required:!1,description:DESIGN_ARG_DESCRIPTION},all:{type:"boolean",default:!1,description:"Stop every running velloo canvas on this machine"}},async run({args}){if(args.all){let daemons=await listDaemons();if(daemons.length===0)console.log("velloo: no canvas daemons running.");else await stopEach(daemons);return}if(!args.design&&process.stdin.isTTY){let daemons=await listDaemons();if(daemons.length===0){console.log("velloo: no canvas daemons running.");return}if(daemons.length===1){await stopEach(daemons);return}let here=runningFor(daemons,await designHere()),ordered=[...daemons].sort((a,b)=>a.root===here?-1:b.root===here?1:0),chosen=await select({message:"Stop which canvas?",options:[...ordered.map((d)=>({value:d.root,label:designWithFolder(d.root,void 0,{absolute:!0}),hint:d.root===here?`${d.canvasUrl} \xB7 this directory`:d.canvasUrl})),{value:ALL,label:`All ${daemons.length} canvases`}],...here?{initialValue:here}:{}});if(isCancel(chosen))fail("stop","cancelled.");await stopEach(chosen===ALL?daemons:daemons.filter((d)=>d.root===chosen));return}if(!args.design&&!await designHere()){let daemons=await listDaemons();if(daemons.length===0){console.log("velloo: no canvas daemons running.");return}fail("stop",[`there is no design in this directory. ${daemons.length} canvas${daemons.length===1?" is":"es are"} running \u2014 stop one by its design folder, or all of them with \`velloo stop --all\`:`,...daemons.map((d)=>` ${canvasLine(d)}`)].join(`
3
3
  `))}let folder=await resolveDesign(args.design,"stop"),root=daemonRoot(folder);if(await stopDaemon(root)){console.log(`velloo: stopped ${designWithFolder(folder)}`);return}console.log(`velloo: no canvas running for ${designWithFolder(folder)}`);let others=await listDaemons();if(others.length===0)return;console.log(import_picocolors.default.dim(` ${others.length} canvas${others.length===1?"":"es"} running elsewhere \u2014 run \`velloo stop\` to pick, or \`velloo stop --all\`:`));for(let d of others)console.log(import_picocolors.default.dim(` ${canvasLine(d)}`))}});export{stop_default as default};
@@ -1,2 +1,2 @@
1
1
  // @bun
2
- import"./chunk-40xgcth8.js";import{recordedDesignName}from"./chunk-tdsk5wxa.js";import"./chunk-t448rrfr.js";import"./chunk-3e8vez4d.js";import"./chunk-dg6z4vdd.js";import{assertLoopbackHost,daemonRoot,isLive,ensureDaemon,stopDaemon}from"./chunk-sjgqnykd.js";import"./chunk-80fjfyha.js";import{fail}from"./chunk-s23gtejf.js";import"./chunk-08sv3k41.js";import"./chunk-4fj5tahv.js";import"./chunk-cvn689d5.js";import"./chunk-dy41n60j.js";import{createProgress}from"./chunk-pjtg3wnm.js";import{designWithFolder}from"./chunk-dgwjpbp9.js";import{findDesigns,DESIGN_ARG_DESCRIPTION,resolveDesign}from"./chunk-vsv8z729.js";import{openUrl}from"./chunk-hggap8fq.js";import"./chunk-735ezz23.js";import"./chunk-pp86v6m6.js";import{traceEnabled}from"./chunk-6tx68d90.js";import{require_picocolors}from"./chunk-jrsknzjt.js";import{__toESM,defineCommand}from"./chunk-2smsg2ct.js";import{basename,join}from"path";var import_picocolors=__toESM(require_picocolors(),1);function actionForRunKey(key,targetCount=1){if(key==="b")return{kind:"background"};if(key==="q"||key==="\x03")return{kind:"stop"};if(targetCount<=1)return key==="o"?{kind:"open"}:null;if(key==="a"||key==="o")return{kind:"open"};if(/^[1-9]$/.test(key)){let index=Number(key);return index<=targetCount?{kind:"open",index}:null}return null}function shouldStayForeground(opts){return!opts.background&&opts.stdinIsTTY}function bindRunKeys(onKey){let stdin=process.stdin;if(!stdin.isTTY)return()=>{};stdin.setRawMode(!0),stdin.resume(),stdin.setEncoding("utf8");let onData=(chunk)=>{onKey(chunk)};return stdin.on("data",onData),()=>{if(stdin.off("data",onData),stdin.isTTY)stdin.setRawMode(!1);stdin.pause()}}var LIVE_POLL_MS=2000;async function waitInForeground(opts){return await new Promise((resolve)=>{let settled=!1,unbind=()=>{},timer,finish=(outcome)=>{if(settled)return;if(settled=!0,unbind(),timer!==void 0)clearInterval(timer);process.off("SIGINT",onStop),process.off("SIGTERM",onStop),resolve(outcome)},onStop=()=>finish("stop");unbind=bindRunKeys((key)=>{let action=actionForRunKey(key,opts.targetCount??1);if(!action)return;if(action.kind==="open")opts.onOpen(action.index);else finish(action.kind)}),process.on("SIGINT",onStop),process.on("SIGTERM",onStop),timer=setInterval(()=>{opts.isLive().then((live)=>{if(!live)finish("died")})},LIVE_POLL_MS)})}import{resolve}from"path";async function resolveRunTargets(arg,opts={}){let cwd=resolve(opts.cwd??"."),single=async()=>{let folder=await resolveDesign(arg,"run",{interactive:!0,requireConfig:!0,cwd});return[{name:recordedDesignName(folder)??void 0,folder}]};if(arg)return single();let found;try{found=await findDesigns(cwd)}catch{return single()}if(!found||found.designs.length<2)return single();let targets=[];for(let design of found.designs)if(design.exists&&!design.outsideRepo)targets.push({name:design.name,folder:design.root});if(targets.length===0)return single();if(targets.length===1)return targets;let defaultDesign=found.defaultDesign;if(defaultDesign)targets.sort((a,b)=>a.name===defaultDesign?-1:b.name===defaultDesign?1:0);return targets}function label(target){return recordedDesignName(target.folder)??target.name??basename(target.folder)}function printKeys(attached){if(console.log(""),attached.length>1)attached.forEach(({target},i)=>{console.log(` ${import_picocolors.default.cyan(String(i+1))} open ${label(target)}`)}),console.log(` ${import_picocolors.default.cyan("a")} open all`);else console.log(` ${import_picocolors.default.cyan("o")} open the browser`);console.log(` ${import_picocolors.default.cyan("b")} run in the background`),console.log(` ${import_picocolors.default.cyan("q")} stop`),console.log("")}function printBackgroundStay(designArg){console.log(`velloo: it keeps running in the background \u2014 awake while the canvas is open or an agent is connected. Stop it anytime with \`velloo stop${designArg}\`.`)}var run_default=defineCommand({meta:{name:"run",description:"Open the canvas for a design folder and stay in the foreground (starts a persistent canvas if none is running)"},args:{design:{type:"positional",required:!1,description:DESIGN_ARG_DESCRIPTION},port:{type:"string",description:"Preferred canvas port when starting fresh (default: the port this folder ran on last, else 7300)"},host:{type:"string",description:"Loopback bind hostname: 127.0.0.1 (default), localhost or ::1"},open:{type:"boolean",default:!1,description:"Open the canvas in your browser"},background:{type:"boolean",default:!1,description:"Leave the canvas running and return to the shell (the default when stdin is not a TTY)"}},async run({args}){assertLoopbackHost(args.host??"127.0.0.1");let targets=await resolveRunTargets(args.design,{}),preferredPort=args.port?Number(args.port):void 0;if(preferredPort!==void 0&&(!Number.isFinite(preferredPort)||preferredPort<0))fail("run",`invalid --port ${JSON.stringify(args.port)}`);let progress=createProgress();progress.start(targets.length>1?"starting canvases":"starting canvas");let spawned=0,running=[];try{for(let[index,target]of targets.entries()){if(targets.length>1)progress.step(`starting ${label(target)}`);let rec=await ensureDaemon(target.folder,{...preferredPort!==void 0&&index===0?{preferredPort}:{},host:args.host,onSpawn:()=>{spawned++,progress.step(`waiting for ${label(target)}`)}});running.push({target,rec})}progress.succeed(spawned===0?targets.length>1?"connected to running canvases":"connected to running canvas":targets.length>1?`started ${targets.length} canvases`:"started canvas")}catch(error){throw progress.fail("could not start canvas"),error}let designArg=args.design?` ${args.design}`:"",first=running[0];if(running.length===1)console.log(`velloo: design ${designWithFolder(first.target.folder,first.target.name)}`),console.log(`velloo: canvas at ${first.rec.canvasUrl}`);else{console.log("velloo: canvases");let rows=running.map(({target,rec})=>({design:designWithFolder(target.folder,target.name),url:rec.canvasUrl})),width=Math.max(...rows.map((row)=>row.design.length));for(let row of rows)console.log(` ${import_picocolors.default.bold(row.design.padEnd(width))} ${row.url}`)}if(traceEnabled())if(spawned>0)console.log(`velloo: \u29BF trace recording ON \u2014 agent MCP calls tape to ${join(first.target.folder,".velloo","trace")} (view with \`velloo trace\`)`);else console.log(`velloo: VELLOO_TRACE is set, but a canvas was already running \u2014 recording is NOT active on it. Run \`velloo stop${designArg}\`, then re-run to record. The agent must also connect through this same (trace-enabled) velloo.`);let foreground=shouldStayForeground({background:Boolean(args.background),stdinIsTTY:Boolean(process.stdin.isTTY)});if(foreground)printKeys(running);else printBackgroundStay(designArg);let attached=running,openTarget=(index)=>{let picked=index===void 0?attached:[attached[index-1]];for(let entry of picked)if(entry)openUrl(entry.rec.canvasUrl)};if(args.open)openTarget(running.length>1?void 0:1);if(!foreground)return;for(;;){let outcome=await waitInForeground({isLive:async()=>{for(let{rec}of attached)if(!await isLive(rec))return!1;return!0},onOpen:openTarget,targetCount:attached.length});if(outcome==="background"){printBackgroundStay(designArg);return}if(outcome==="died"){let alive=[];for(let entry of attached)if(await isLive(entry.rec))alive.push(entry);else console.log(`velloo: the canvas for "${label(entry.target)}" stopped.`);if(attached=alive,attached.length===0){console.log(`velloo: no canvases left. Start again with \`velloo run${designArg}\`.`);return}console.log(import_picocolors.default.dim(` Still running: ${attached.map(({target})=>label(target)).join(", ")}.`)),printKeys(attached);continue}for(let{target}of attached){let stopped=await stopDaemon(daemonRoot(target.folder));console.log(stopped?`velloo: stopped ${designWithFolder(target.folder)}`:`velloo: no canvas running for ${designWithFolder(target.folder)}`)}return}}});export{run_default as default};
2
+ import"./chunk-nte0t7v3.js";import{recordedDesignName}from"./chunk-88eqqdk1.js";import"./chunk-n9t36h0q.js";import"./chunk-c4fym47a.js";import"./chunk-9psr8atb.js";import{assertLoopbackHost,daemonRoot,isLive,ensureDaemon,stopDaemon}from"./chunk-4ma2wnqw.js";import"./chunk-80fjfyha.js";import{fail}from"./chunk-s23gtejf.js";import"./chunk-2fgfex9b.js";import"./chunk-9ydc34wc.js";import"./chunk-cvn689d5.js";import"./chunk-t2w8a591.js";import{createProgress}from"./chunk-pjtg3wnm.js";import{designWithFolder}from"./chunk-4g250157.js";import{findDesigns,DESIGN_ARG_DESCRIPTION,resolveDesign}from"./chunk-wafb2xm9.js";import{openUrl}from"./chunk-hggap8fq.js";import"./chunk-t5m5mznb.js";import"./chunk-as08hzp3.js";import{traceEnabled}from"./chunk-6tx68d90.js";import{require_picocolors}from"./chunk-jrsknzjt.js";import{__toESM,defineCommand}from"./chunk-2smsg2ct.js";import{basename,join}from"path";var import_picocolors=__toESM(require_picocolors(),1);function actionForRunKey(key,targetCount=1){if(key==="b")return{kind:"background"};if(key==="q"||key==="\x03")return{kind:"stop"};if(targetCount<=1)return key==="o"?{kind:"open"}:null;if(key==="a"||key==="o")return{kind:"open"};if(/^[1-9]$/.test(key)){let index=Number(key);return index<=targetCount?{kind:"open",index}:null}return null}function shouldStayForeground(opts){return!opts.background&&opts.stdinIsTTY}function bindRunKeys(onKey){let stdin=process.stdin;if(!stdin.isTTY)return()=>{};stdin.setRawMode(!0),stdin.resume(),stdin.setEncoding("utf8");let onData=(chunk)=>{onKey(chunk)};return stdin.on("data",onData),()=>{if(stdin.off("data",onData),stdin.isTTY)stdin.setRawMode(!1);stdin.pause()}}var LIVE_POLL_MS=2000;async function waitInForeground(opts){return await new Promise((resolve)=>{let settled=!1,unbind=()=>{},timer,finish=(outcome)=>{if(settled)return;if(settled=!0,unbind(),timer!==void 0)clearInterval(timer);process.off("SIGINT",onStop),process.off("SIGTERM",onStop),resolve(outcome)},onStop=()=>finish("stop");unbind=bindRunKeys((key)=>{let action=actionForRunKey(key,opts.targetCount??1);if(!action)return;if(action.kind==="open")opts.onOpen(action.index);else finish(action.kind)}),process.on("SIGINT",onStop),process.on("SIGTERM",onStop),timer=setInterval(()=>{opts.isLive().then((live)=>{if(!live)finish("died")})},LIVE_POLL_MS)})}import{resolve}from"path";async function resolveRunTargets(arg,opts={}){let cwd=resolve(opts.cwd??"."),single=async()=>{let folder=await resolveDesign(arg,"run",{interactive:!0,requireConfig:!0,cwd});return[{name:recordedDesignName(folder)??void 0,folder}]};if(arg)return single();let found;try{found=await findDesigns(cwd)}catch{return single()}if(!found||found.designs.length<2)return single();let targets=[];for(let design of found.designs)if(design.exists&&!design.outsideRepo)targets.push({name:design.name,folder:design.root});if(targets.length===0)return single();if(targets.length===1)return targets;let defaultDesign=found.defaultDesign;if(defaultDesign)targets.sort((a,b)=>a.name===defaultDesign?-1:b.name===defaultDesign?1:0);return targets}function label(target){return recordedDesignName(target.folder)??target.name??basename(target.folder)}function printKeys(attached){if(console.log(""),attached.length>1)attached.forEach(({target},i)=>{console.log(` ${import_picocolors.default.cyan(String(i+1))} open ${label(target)}`)}),console.log(` ${import_picocolors.default.cyan("a")} open all`);else console.log(` ${import_picocolors.default.cyan("o")} open the browser`);console.log(` ${import_picocolors.default.cyan("b")} run in the background`),console.log(` ${import_picocolors.default.cyan("q")} stop`),console.log("")}function printBackgroundStay(designArg){console.log(`velloo: it keeps running in the background \u2014 awake while the canvas is open or an agent is connected. Stop it anytime with \`velloo stop${designArg}\`.`)}var run_default=defineCommand({meta:{name:"run",description:"Open the canvas for a design folder and stay in the foreground (starts a persistent canvas if none is running)"},args:{design:{type:"positional",required:!1,description:DESIGN_ARG_DESCRIPTION},port:{type:"string",description:"Preferred canvas port when starting fresh (default: the port this folder ran on last, else 7300)"},host:{type:"string",description:"Loopback bind hostname: 127.0.0.1 (default), localhost or ::1"},open:{type:"boolean",default:!1,description:"Open the canvas in your browser"},background:{type:"boolean",default:!1,description:"Leave the canvas running and return to the shell (the default when stdin is not a TTY)"}},async run({args}){assertLoopbackHost(args.host??"127.0.0.1");let targets=await resolveRunTargets(args.design,{}),preferredPort=args.port?Number(args.port):void 0;if(preferredPort!==void 0&&(!Number.isFinite(preferredPort)||preferredPort<0))fail("run",`invalid --port ${JSON.stringify(args.port)}`);let progress=createProgress();progress.start(targets.length>1?"starting canvases":"starting canvas");let spawned=0,running=[];try{for(let[index,target]of targets.entries()){if(targets.length>1)progress.step(`starting ${label(target)}`);let rec=await ensureDaemon(target.folder,{...preferredPort!==void 0&&index===0?{preferredPort}:{},host:args.host,onSpawn:()=>{spawned++,progress.step(`waiting for ${label(target)}`)}});running.push({target,rec})}progress.succeed(spawned===0?targets.length>1?"connected to running canvases":"connected to running canvas":targets.length>1?`started ${targets.length} canvases`:"started canvas")}catch(error){throw progress.fail("could not start canvas"),error}let designArg=args.design?` ${args.design}`:"",first=running[0];if(running.length===1)console.log(`velloo: design ${designWithFolder(first.target.folder,first.target.name)}`),console.log(`velloo: canvas at ${first.rec.canvasUrl}`);else{console.log("velloo: canvases");let rows=running.map(({target,rec})=>({design:designWithFolder(target.folder,target.name),url:rec.canvasUrl})),width=Math.max(...rows.map((row)=>row.design.length));for(let row of rows)console.log(` ${import_picocolors.default.bold(row.design.padEnd(width))} ${row.url}`)}if(traceEnabled())if(spawned>0)console.log(`velloo: \u29BF trace recording ON \u2014 agent MCP calls tape to ${join(first.target.folder,".velloo","trace")} (view with \`velloo trace\`)`);else console.log(`velloo: VELLOO_TRACE is set, but a canvas was already running \u2014 recording is NOT active on it. Run \`velloo stop${designArg}\`, then re-run to record. The agent must also connect through this same (trace-enabled) velloo.`);let foreground=shouldStayForeground({background:Boolean(args.background),stdinIsTTY:Boolean(process.stdin.isTTY)});if(foreground)printKeys(running);else printBackgroundStay(designArg);let attached=running,openTarget=(index)=>{let picked=index===void 0?attached:[attached[index-1]];for(let entry of picked)if(entry)openUrl(entry.rec.canvasUrl)};if(args.open)openTarget(running.length>1?void 0:1);if(!foreground)return;for(;;){let outcome=await waitInForeground({isLive:async()=>{for(let{rec}of attached)if(!await isLive(rec))return!1;return!0},onOpen:openTarget,targetCount:attached.length});if(outcome==="background"){printBackgroundStay(designArg);return}if(outcome==="died"){let alive=[];for(let entry of attached)if(await isLive(entry.rec))alive.push(entry);else console.log(`velloo: the canvas for "${label(entry.target)}" stopped.`);if(attached=alive,attached.length===0){console.log(`velloo: no canvases left. Start again with \`velloo run${designArg}\`.`);return}console.log(import_picocolors.default.dim(` Still running: ${attached.map(({target})=>label(target)).join(", ")}.`)),printKeys(attached);continue}for(let{target}of attached){let stopped=await stopDaemon(daemonRoot(target.folder));console.log(stopped?`velloo: stopped ${designWithFolder(target.folder)}`:`velloo: no canvas running for ${designWithFolder(target.folder)}`)}return}}});export{run_default as default};
@@ -1,4 +1,4 @@
1
1
  // @bun
2
- import{PACKAGE_VERSION,TOOL_VERSION,BUILD_TIME_MS}from"./chunk-dg6z4vdd.js";import{require_picocolors}from"./chunk-jrsknzjt.js";import{__toESM}from"./chunk-2smsg2ct.js";import{existsSync,realpathSync}from"fs";import{readFile}from"fs/promises";import{homedir}from"os";import{dirname,join}from"path";var DEFAULT_DOWNLOAD_BASE={stable:"https://get.velloo.design",dev:"https://get.dev.velloo.design"},NPM_LATEST_URL="https://registry.npmjs.org/velloo/latest";function localReleasePath(){return process.env.VELLOO_LOCAL_RELEASE??join(homedir(),".velloo","local-release.json")}async function readLocalRelease(){try{let raw=JSON.parse(await readFile(localReleasePath(),"utf8"));if(typeof raw!=="object"||raw===null)return null;let value=raw;if(typeof value.builtAt!=="number"||typeof value.tarball!=="string")return null;return{version:typeof value.version==="string"?value.version:PACKAGE_VERSION,build:typeof value.build==="string"?value.build:value.version??PACKAGE_VERSION,builtAt:value.builtAt,tarball:value.tarball,repo:typeof value.repo==="string"?value.repo:dirname(value.tarball)}}catch{return null}}function looksLikeHomebrew(env){let entry=env.VELLOO_LAUNCHER_PATH??Bun.main;if(!entry)return!1;try{return/[/\\]Cellar[/\\]velloo[/\\]/.test(realpathSync(entry))}catch{return/[/\\]Cellar[/\\]velloo[/\\]/.test(entry)}}var EXPLICIT=["npm","direct","homebrew","local","source"];function installMethod(env=process.env){let declared=env.VELLOO_INSTALL_METHOD;if(declared&&EXPLICIT.includes(declared)){if(declared==="npm"&&looksLikeHomebrew(env))return"homebrew";return declared}if(looksLikeHomebrew(env))return"homebrew";return"unknown"}function selfUpgradable(method){return method==="npm"||method==="direct"||method==="homebrew"||method==="local"}function releaseChannel(env=process.env){let declared=env.VELLOO_RELEASE_CHANNEL??bakedChannel();return declared==="dev"||declared==="local"?declared:"stable"}function bakedChannel(){return"stable"}function downloadBase(env=process.env){let explicit=env.VELLOO_DOWNLOAD_BASE;if(explicit)return explicit.replace(/\/+$/,"");let channel=releaseChannel(env);return DEFAULT_DOWNLOAD_BASE[channel==="local"?"stable":channel]}function installerUrl(env=process.env){return env.VELLOO_INSTALLER_URL??`${downloadBase(env)}/install.sh`}function latestVersionUrl(env=process.env){if(env.VELLOO_UPDATE_URL)return env.VELLOO_UPDATE_URL;if(releaseChannel(env)==="stable"&&installMethod(env)==="npm")return NPM_LATEST_URL;return`${downloadBase(env)}/latest.json`}function runningRelease(){return{version:PACKAGE_VERSION,build:TOOL_VERSION,...BUILD_TIME_MS===void 0?{}:{builtAt:BUILD_TIME_MS}}}function compareVersions(left,right){let parse=(value)=>{let match=/^v?(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z.-]+))?(?:\+[0-9A-Za-z.-]+)?$/.exec(value);if(!match)return null;return{core:[Number(match[1]),Number(match[2]),Number(match[3])],prerelease:match[4]??null}},a=parse(left),b=parse(right);if(!a||!b)return 0;for(let index=0;index<3;index++){let delta=(a.core[index]??0)-(b.core[index]??0);if(delta!==0)return Math.sign(delta)}if(a.prerelease===b.prerelease)return 0;if(a.prerelease===null)return 1;if(b.prerelease===null)return-1;return a.prerelease.localeCompare(b.prerelease,void 0,{numeric:!0})}function isNewerRelease(candidate,running=runningRelease()){let byVersion=compareVersions(candidate.version,running.version);if(byVersion!==0)return byVersion>0;if(typeof candidate.builtAt!=="number")return!1;if(typeof running.builtAt!=="number")return!0;return candidate.builtAt>running.builtAt}function releaseLabel(info){return info.build??info.version}var FETCH_TIMEOUT_MS=2000;async function fetchLatestRelease(env=process.env){if(releaseChannel(env)==="local"&&!env.VELLOO_UPDATE_URL){let local=await readLocalRelease();if(!local)return null;return{version:local.version,build:local.build,builtAt:local.builtAt}}let response=await fetch(latestVersionUrl(env),{headers:{accept:"application/json","user-agent":`velloo/${PACKAGE_VERSION}`},signal:AbortSignal.timeout(FETCH_TIMEOUT_MS)});if(!response.ok)throw Error(`release check returned HTTP ${response.status}`);let body=await response.json();if(typeof body.version!=="string"||!/^\d+\.\d+\.\d+/.test(body.version))throw Error("release check returned an invalid version");return{version:body.version,...typeof body.build==="string"?{build:body.build}:{},...typeof body.builtAt==="number"?{builtAt:body.builtAt}:{}}}function installedVellooBin(env=process.env){let candidates=[],method=installMethod(env);if(method==="direct")candidates.push(join(env.VELLOO_BIN_DIR??join(homedir(),".local","bin"),"velloo"));if(method==="homebrew"){let prefix=env.HOMEBREW_PREFIX??(process.platform==="darwin"?"/opt/homebrew":null);if(prefix)candidates.push(join(prefix,"bin","velloo"));candidates.push("/usr/local/bin/velloo")}if(method==="npm"||method==="local"){let node=env.VELLOO_NODE_EXECUTABLE;if(node)candidates.push(join(dirname(node),"velloo"));let prefix=npmGlobalPrefix(env);if(prefix)candidates.push(process.platform==="win32"?join(prefix,"velloo.cmd"):join(prefix,"bin","velloo"))}return candidates.find((path)=>existsSync(path))??null}function npmGlobalPrefix(env){try{let result=Bun.spawnSync([npmExecutable(env),"prefix","-g"],{env}),out=result.stdout.toString().trim();return result.success&&out?out:null}catch{return null}}function npmExecutable(env=process.env){let node=env.VELLOO_NODE_EXECUTABLE;if(node){let adjacent=join(dirname(node),process.platform==="win32"?"npm.cmd":"npm");if(existsSync(adjacent))return adjacent}return process.platform==="win32"?"npm.cmd":"npm"}var import_picocolors=__toESM(require_picocolors(),1);import{existsSync as existsSync2}from"fs";import{mkdir,mkdtemp,readFile as readFile2,rename,rm,writeFile}from"fs/promises";import{homedir as homedir2,tmpdir}from"os";import{dirname as dirname2,join as join2}from"path";var CHECK_INTERVAL_MS=86400000,LOCAL_CHECK_INTERVAL_MS=1e4;function releaseSource(){return releaseChannel()==="local"&&!process.env.VELLOO_UPDATE_URL?`file:${localReleasePath()}`:latestVersionUrl()}function cachePath(){return process.env.VELLOO_UPDATE_CACHE??join2(homedir2(),".velloo","update-check.json")}async function readCacheFile(){try{let value=JSON.parse(await readFile2(cachePath(),"utf8"));if(typeof value!=="object"||value===null)return{};return Object.fromEntries(Object.entries(value).filter(([,entry])=>typeof entry==="object"&&entry!==null))}catch{return{}}}async function readCache(){let entry=(await readCacheFile())[releaseSource()];if(typeof entry?.checkedAt!=="number"||typeof entry.latest!=="string")return null;return entry}async function writeCache(value){let path=cachePath(),file={...await readCacheFile(),[releaseSource()]:value};await mkdir(dirname2(path),{recursive:!0});let temporary=`${path}.${process.pid}.tmp`;await writeFile(temporary,`${JSON.stringify(file,null,2)}
2
+ import{PACKAGE_VERSION,TOOL_VERSION,BUILD_TIME_MS}from"./chunk-9psr8atb.js";import{require_picocolors}from"./chunk-jrsknzjt.js";import{__toESM}from"./chunk-2smsg2ct.js";import{existsSync,realpathSync}from"fs";import{readFile}from"fs/promises";import{homedir}from"os";import{dirname,join}from"path";var DEFAULT_DOWNLOAD_BASE={stable:"https://get.velloo.design",dev:"https://get.dev.velloo.design"},NPM_LATEST_URL="https://registry.npmjs.org/velloo/latest";function localReleasePath(){return process.env.VELLOO_LOCAL_RELEASE??join(homedir(),".velloo","local-release.json")}async function readLocalRelease(){try{let raw=JSON.parse(await readFile(localReleasePath(),"utf8"));if(typeof raw!=="object"||raw===null)return null;let value=raw;if(typeof value.builtAt!=="number"||typeof value.tarball!=="string")return null;return{version:typeof value.version==="string"?value.version:PACKAGE_VERSION,build:typeof value.build==="string"?value.build:value.version??PACKAGE_VERSION,builtAt:value.builtAt,tarball:value.tarball,repo:typeof value.repo==="string"?value.repo:dirname(value.tarball)}}catch{return null}}function looksLikeHomebrew(env){let entry=env.VELLOO_LAUNCHER_PATH??Bun.main;if(!entry)return!1;try{return/[/\\]Cellar[/\\]velloo[/\\]/.test(realpathSync(entry))}catch{return/[/\\]Cellar[/\\]velloo[/\\]/.test(entry)}}var EXPLICIT=["npm","direct","homebrew","local","source"];function installMethod(env=process.env){let declared=env.VELLOO_INSTALL_METHOD;if(declared&&EXPLICIT.includes(declared)){if(declared==="npm"&&looksLikeHomebrew(env))return"homebrew";return declared}if(looksLikeHomebrew(env))return"homebrew";return"unknown"}function selfUpgradable(method){return method==="npm"||method==="direct"||method==="homebrew"||method==="local"}function releaseChannel(env=process.env){let declared=env.VELLOO_RELEASE_CHANNEL??bakedChannel();return declared==="dev"||declared==="local"?declared:"stable"}function bakedChannel(){return"stable"}function downloadBase(env=process.env){let explicit=env.VELLOO_DOWNLOAD_BASE;if(explicit)return explicit.replace(/\/+$/,"");let channel=releaseChannel(env);return DEFAULT_DOWNLOAD_BASE[channel==="local"?"stable":channel]}function installerUrl(env=process.env){return env.VELLOO_INSTALLER_URL??`${downloadBase(env)}/install.sh`}function latestVersionUrl(env=process.env){if(env.VELLOO_UPDATE_URL)return env.VELLOO_UPDATE_URL;if(releaseChannel(env)==="stable"&&installMethod(env)==="npm")return NPM_LATEST_URL;return`${downloadBase(env)}/latest.json`}function runningRelease(){return{version:PACKAGE_VERSION,build:TOOL_VERSION,...BUILD_TIME_MS===void 0?{}:{builtAt:BUILD_TIME_MS}}}function compareVersions(left,right){let parse=(value)=>{let match=/^v?(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z.-]+))?(?:\+[0-9A-Za-z.-]+)?$/.exec(value);if(!match)return null;return{core:[Number(match[1]),Number(match[2]),Number(match[3])],prerelease:match[4]??null}},a=parse(left),b=parse(right);if(!a||!b)return 0;for(let index=0;index<3;index++){let delta=(a.core[index]??0)-(b.core[index]??0);if(delta!==0)return Math.sign(delta)}if(a.prerelease===b.prerelease)return 0;if(a.prerelease===null)return 1;if(b.prerelease===null)return-1;return a.prerelease.localeCompare(b.prerelease,void 0,{numeric:!0})}function isNewerRelease(candidate,running=runningRelease()){let byVersion=compareVersions(candidate.version,running.version);if(byVersion!==0)return byVersion>0;if(typeof candidate.builtAt!=="number")return!1;if(typeof running.builtAt!=="number")return!0;return candidate.builtAt>running.builtAt}function releaseLabel(info){return info.build??info.version}var FETCH_TIMEOUT_MS=2000;async function fetchLatestRelease(env=process.env){if(releaseChannel(env)==="local"&&!env.VELLOO_UPDATE_URL){let local=await readLocalRelease();if(!local)return null;return{version:local.version,build:local.build,builtAt:local.builtAt}}let response=await fetch(latestVersionUrl(env),{headers:{accept:"application/json","user-agent":`velloo/${PACKAGE_VERSION}`},signal:AbortSignal.timeout(FETCH_TIMEOUT_MS)});if(!response.ok)throw Error(`release check returned HTTP ${response.status}`);let body=await response.json();if(typeof body.version!=="string"||!/^\d+\.\d+\.\d+/.test(body.version))throw Error("release check returned an invalid version");return{version:body.version,...typeof body.build==="string"?{build:body.build}:{},...typeof body.builtAt==="number"?{builtAt:body.builtAt}:{}}}function installedVellooBin(env=process.env){let candidates=[],method=installMethod(env);if(method==="direct")candidates.push(join(env.VELLOO_BIN_DIR??join(homedir(),".local","bin"),"velloo"));if(method==="homebrew"){let prefix=env.HOMEBREW_PREFIX??(process.platform==="darwin"?"/opt/homebrew":null);if(prefix)candidates.push(join(prefix,"bin","velloo"));candidates.push("/usr/local/bin/velloo")}if(method==="npm"||method==="local"){let node=env.VELLOO_NODE_EXECUTABLE;if(node)candidates.push(join(dirname(node),"velloo"));let prefix=npmGlobalPrefix(env);if(prefix)candidates.push(process.platform==="win32"?join(prefix,"velloo.cmd"):join(prefix,"bin","velloo"))}return candidates.find((path)=>existsSync(path))??null}function npmGlobalPrefix(env){try{let result=Bun.spawnSync([npmExecutable(env),"prefix","-g"],{env}),out=result.stdout.toString().trim();return result.success&&out?out:null}catch{return null}}function npmExecutable(env=process.env){let node=env.VELLOO_NODE_EXECUTABLE;if(node){let adjacent=join(dirname(node),process.platform==="win32"?"npm.cmd":"npm");if(existsSync(adjacent))return adjacent}return process.platform==="win32"?"npm.cmd":"npm"}var import_picocolors=__toESM(require_picocolors(),1);import{existsSync as existsSync2}from"fs";import{mkdir,mkdtemp,readFile as readFile2,rename,rm,writeFile}from"fs/promises";import{homedir as homedir2,tmpdir}from"os";import{dirname as dirname2,join as join2}from"path";var CHECK_INTERVAL_MS=86400000,LOCAL_CHECK_INTERVAL_MS=1e4;function releaseSource(){return releaseChannel()==="local"&&!process.env.VELLOO_UPDATE_URL?`file:${localReleasePath()}`:latestVersionUrl()}function cachePath(){return process.env.VELLOO_UPDATE_CACHE??join2(homedir2(),".velloo","update-check.json")}async function readCacheFile(){try{let value=JSON.parse(await readFile2(cachePath(),"utf8"));if(typeof value!=="object"||value===null)return{};return Object.fromEntries(Object.entries(value).filter(([,entry])=>typeof entry==="object"&&entry!==null))}catch{return{}}}async function readCache(){let entry=(await readCacheFile())[releaseSource()];if(typeof entry?.checkedAt!=="number"||typeof entry.latest!=="string")return null;return entry}async function writeCache(value){let path=cachePath(),file={...await readCacheFile(),[releaseSource()]:value};await mkdir(dirname2(path),{recursive:!0});let temporary=`${path}.${process.pid}.tmp`;await writeFile(temporary,`${JSON.stringify(file,null,2)}
3
3
  `);try{await rename(temporary,path)}catch(error){if(process.platform!=="win32")throw error;await rm(path,{force:!0}),await rename(temporary,path)}}function cachedRelease(cache){return{version:cache.latest,...cache.latestBuild===void 0?{}:{build:cache.latestBuild},...cache.latestBuiltAt===void 0?{}:{builtAt:cache.latestBuiltAt}}}async function refreshUpdateCache(){try{let previous=await readCache(),latest=await fetchLatestRelease();if(!latest)return;await writeCache({checkedAt:Date.now(),latest:latest.version,...latest.build===void 0?{}:{latestBuild:latest.build},...latest.builtAt===void 0?{}:{latestBuiltAt:latest.builtAt},...previous?.notifiedAt?{notifiedAt:previous.notifiedAt}:{},...previous?.notifiedVersion?{notifiedVersion:previous.notifiedVersion}:{}})}catch{}}function spawnUpdateCheck(){let entry=Bun.main,argv=existsSync2(entry)?[process.execPath,entry,"__update_check"]:[process.execPath,"__update_check"];try{Bun.spawn(argv,{stdin:"ignore",stdout:"ignore",stderr:"ignore",env:{...process.env,VELLOO_UPDATE_CHECK_CHILD:"1"}}).unref()}catch{}}function checkIntervalMs(){return releaseChannel()==="local"?LOCAL_CHECK_INTERVAL_MS:CHECK_INTERVAL_MS}function checkSuppressed(){return process.env.VELLOO_DISABLE_UPDATE_CHECK==="1"||process.env.VELLOO_UPDATE_CHECK_CHILD==="1"||!selfUpgradable(installMethod())}async function maybeNotifyAboutUpdate(options={}){if(checkSuppressed()||!(options.isTTY??process.stderr.isTTY))return;let now=options.now??Date.now(),cached=await readCache(),latest=(releaseChannel()==="local"?await fetchLatestRelease().catch(()=>null):null)??(cached?cachedRelease(cached):null);if(latest&&isNewerRelease(latest)){if(!(cached?.notifiedVersion===releaseLabel(latest)&&typeof cached?.notifiedAt==="number"&&now-cached.notifiedAt<checkIntervalMs())){let running=runningRelease();console.error(""),console.error(`${import_picocolors.default.yellow("Update available:")} ${releaseLabel(running)} \u2192 ${releaseLabel(latest)}. Run ${import_picocolors.default.cyan("velloo upgrade")}.`),await writeCache({checkedAt:cached?.checkedAt??now,latest:latest.version,...latest.build===void 0?{}:{latestBuild:latest.build},...latest.builtAt===void 0?{}:{latestBuiltAt:latest.builtAt},notifiedAt:now,notifiedVersion:releaseLabel(latest)}).catch(()=>{})}}if(!cached||now-cached.checkedAt>=checkIntervalMs())spawnUpdateCheck()}async function runInherited(command,env=process.env){let code=await Bun.spawn(command,{stdin:"inherit",stdout:"inherit",stderr:"inherit",env}).exited;if(code!==0)throw Error(`\`${command.join(" ")}\` exited with status ${code}`)}async function updateStatus(opts={}){let method=installMethod(),channel=releaseChannel(),running=runningRelease(),base={method,channel,current:releaseLabel(running),latest:null,available:!1,upgradable:selfUpgradable(method),...selfUpgradable(method)?{}:{reason:unsupportedReason(method)}};if(!selfUpgradable(method))return base;let release=null;if(opts.refresh)try{if(release=await fetchLatestRelease(),release)await writeCache({checkedAt:Date.now(),latest:release.version,...release.build===void 0?{}:{latestBuild:release.build},...release.builtAt===void 0?{}:{latestBuiltAt:release.builtAt}}).catch(()=>{})}catch(error){return{...base,reason:error instanceof Error?error.message:String(error)}}else{let cached=await readCache();if(cached)release=cachedRelease(cached);if(!cached||Date.now()-cached.checkedAt>=checkIntervalMs())spawnUpdateCheck()}if(!release)return base;return{...base,latest:releaseLabel(release),available:isNewerRelease(release,running)}}function unsupportedReason(method){return method==="source"?"this Velloo is running from source; update the checkout with your Git workflow":"could not identify this installation. Reinstall with `npm install -g velloo@latest` or the installer at https://get.velloo.design/install.sh"}async function upgradeInstalledVelloo(options={}){let method=installMethod(),channel=releaseChannel(),running=runningRelease();if(!selfUpgradable(method))throw Error(unsupportedReason(method));let latest=await fetchLatestRelease();if(!latest)throw Error(channel==="local"?`no local build found at ${localReleasePath()} \u2014 run \`bun run cli:build\` in the velloo checkout first`:"this channel has no published release");let done=(upgraded)=>({upgraded,from:releaseLabel(running),to:releaseLabel(latest),method,channel});if(!isNewerRelease(latest,running))return console.log(`velloo: ${releaseLabel(running)} is already the latest ${channel} build.`),done(!1);if(options.checkOnly)return console.log(`velloo: ${releaseLabel(running)} \u2192 ${releaseLabel(latest)} is available (${method} installation, ${channel} channel).`),done(!1);if(method==="homebrew")await runInherited(["brew","upgrade",process.env.VELLOO_BREW_FORMULA??"velloo"]);else if(channel==="local")await upgradeFromLocalBuild();else if(method==="npm"){let packageName=process.env.VELLOO_NPM_PACKAGE??"velloo",spec=channel==="dev"?`${downloadBase()}/velloo.tgz`:`${packageName}@${latest.version}`;await runInherited([npmExecutable(),"install","-g",spec])}else{let response=await fetch(installerUrl(),{signal:AbortSignal.timeout(1e4)});if(!response.ok)throw Error(`installer download returned HTTP ${response.status}`);let directory=await mkdtemp(join2(tmpdir(),"velloo-upgrade-")),installer=join2(directory,"install.sh");try{await writeFile(installer,await response.text(),{mode:448}),await runInherited(["bash",installer],{...process.env,VELLOO_VERSION:latest.version,VELLOO_DOWNLOAD_BASE:downloadBase()})}finally{await rm(directory,{recursive:!0,force:!0})}}return console.log(`velloo: upgraded ${releaseLabel(running)} \u2192 ${releaseLabel(latest)} via ${method}.`),done(!0)}async function upgradeFromLocalBuild(){let local=await readLocalRelease();if(!local)throw Error("no local build recorded \u2014 run `bun run cli:build` first");if(!existsSync2(local.tarball))throw Error(`the recorded local build is gone (${local.tarball}) \u2014 run \`bun run cli:build\` in ${local.repo} again`);await runInherited([npmExecutable(),"install","-g","--include=optional",local.tarball])}
4
4
  export{installedVellooBin,refreshUpdateCache,maybeNotifyAboutUpdate,updateStatus,upgradeInstalledVelloo};
@@ -1,3 +1,3 @@
1
1
  // @bun
2
- var package_default={name:"@velloo/cli",version:"0.2.0",license:"Apache-2.0",private:!0,type:"module",description:"Velloo CLI",bin:{velloo:"./src/cli.ts"},exports:{".":"./src/cli.ts"},engines:{bun:">=1.4.0"},scripts:{build:"bun run build.ts"},dependencies:{"@clack/prompts":"1.7.0","@velloo/canvas":"workspace:*","@velloo/codegen":"workspace:*","@velloo/protocol":"workspace:*","@velloo/provider":"workspace:*","@velloo/provider-antd":"workspace:*","@velloo/provider-chakra":"workspace:*","@velloo/provider-mui":"workspace:*","@velloo/provider-none":"workspace:*","@velloo/renderer":"workspace:*","@velloo/result":"workspace:*","@velloo/schema":"workspace:*","@velloo/server":"workspace:*","@velloo/shadcn-snapshot":"workspace:*",citty:"0.2.2",picocolors:"1.1.1",zod:"4.5.4"}};var PACKAGE_VERSION=package_default.version,TOOL_VERSION="0.2.0",BUILD_TIME_MS=1789624987317;
2
+ var package_default={name:"@velloo/cli",version:"0.3.1",license:"Apache-2.0",private:!0,type:"module",description:"Velloo CLI",bin:{velloo:"./src/cli.ts"},exports:{".":"./src/cli.ts"},engines:{bun:">=1.4.0"},scripts:{build:"bun run build.ts"},dependencies:{"@clack/prompts":"1.7.0","@velloo/canvas":"workspace:*","@velloo/codegen":"workspace:*","@velloo/protocol":"workspace:*","@velloo/provider":"workspace:*","@velloo/provider-antd":"workspace:*","@velloo/provider-chakra":"workspace:*","@velloo/provider-mui":"workspace:*","@velloo/provider-none":"workspace:*","@velloo/renderer":"workspace:*","@velloo/result":"workspace:*","@velloo/schema":"workspace:*","@velloo/server":"workspace:*","@velloo/shadcn-snapshot":"workspace:*",citty:"0.2.2",picocolors:"1.1.1",zod:"4.5.4"}};var PACKAGE_VERSION=package_default.version,TOOL_VERSION="0.3.1",BUILD_TIME_MS=1790007117267;
3
3
  export{PACKAGE_VERSION,TOOL_VERSION,BUILD_TIME_MS};
@@ -1,3 +1,3 @@
1
1
  // @bun
2
- import{fail,failWithError}from"./chunk-s23gtejf.js";import{firstPositional}from"./chunk-94vx1yb0.js";import{traceEnabled}from"./chunk-6tx68d90.js";var TOLERATED={upgrade:["folder-only"]},BUILTIN_FLAGS=["help","h","version","v"],camel=(name)=>name.replace(/-([a-z0-9])/g,(_,c)=>c.toUpperCase()),kebab=(name)=>name.replace(/[A-Z]/g,(c)=>`-${c.toLowerCase()}`);async function knownFlags(args){let defs=(typeof args==="function"?await args():await args)??{},known=new Set(BUILTIN_FLAGS);for(let[name,def]of Object.entries(defs)){if(def.type==="positional")continue;let alias="alias"in def?def.alias:void 0;for(let spelling of[name,...alias===void 0?[]:[alias].flat()])known.add(spelling),known.add(camel(spelling)),known.add(kebab(spelling))}return known}function flagsIn(rawArgs){let flags=[];for(let token of rawArgs){if(token==="--")break;if(!token.startsWith("-")||token==="-"||/^-\d/.test(token))continue;if(token.startsWith("--")){let name=token.slice(2).split("=")[0]??"";flags.push(name.startsWith("no-")?name.slice(3):name)}else flags.push(...token.slice(1).split("=")[0]?.split("")??[])}return flags}function strictFlags(name,cmd){let subCommands=cmd.subCommands,table=async()=>typeof subCommands==="function"?await subCommands():await subCommands,checked=subCommands?{...cmd,subCommands:async()=>Object.fromEntries(Object.entries(await table()??{}).map(([child,load])=>[child,async()=>{let def=typeof load==="function"?await load():await load;return strictFlags(`${name} ${child}`,def)}]))}:cmd;if(subCommands&&!cmd.run)return checked;let setup=cmd.setup;return{...checked,async setup(context){if(subCommands){let child=await firstPositional(context.rawArgs,cmd.args);if(child!==void 0&&Object.hasOwn(await table()??{},child)){await setup?.(context);return}}let known=await knownFlags(cmd.args),tolerated=TOLERATED[name]??[],unknown=flagsIn(context.rawArgs).filter((flag)=>flag!==""&&!known.has(flag)&&!tolerated.includes(flag));if(unknown.length>0){let listed=[...known].filter((f)=>f.length>1&&!BUILTIN_FLAGS.includes(f)&&f===kebab(f)),hint=listed.length>0?` (it takes ${listed.map((f)=>`--${f}`).join(", ")})`:"";fail(name,`unknown option ${unknown.map((f)=>f.length===1?`-${f}`:`--${f}`).join(", ")}${hint}`)}await setup?.(context)}}}var LOADERS={init:()=>import("./chunk-k17gfwq3.js").then((m)=>m.default),login:()=>import("./chunk-rpwpeph5.js").then((m)=>m.default),logout:()=>import("./chunk-0fe83yzt.js").then((m)=>m.default),connect:()=>import("./chunk-6nqghjda.js").then((m)=>m.default),run:()=>import("./chunk-vdkrbzh1.js").then((m)=>m.default),design:()=>import("./chunk-7eyb8yrf.js").then((m)=>m.default),mcp:()=>import("./chunk-j11fyeqh.js").then((m)=>m.default),stop:()=>import("./chunk-r22epxz2.js").then((m)=>m.default),status:()=>import("./chunk-jv0xggh0.js").then((m)=>m.default),__daemon:()=>import("./chunk-1h55s5he.js").then((m)=>m.default),__update_check:()=>import("./chunk-6w6ch4ce.js").then((m)=>m.default),render:()=>import("./chunk-n9gs6yx9.js").then((m)=>m.default),capture:()=>import("./chunk-sn3x2m0m.js").then((m)=>m.default),browser:()=>import("./chunk-avns4dbf.js").then((m)=>m.default),export:()=>import("./chunk-mnapdp1y.js").then((m)=>m.default),upgrade:()=>import("./chunk-308ynsxd.js").then((m)=>m.default),publish:()=>import("./chunk-mh2pr7cq.js").then((m)=>m.default),emit:()=>import("./chunk-ampmdzz4.js").then((m)=>m.default),theme:()=>import("./chunk-ccszg02q.js").then((m)=>m.default),completions:()=>import("./chunk-er1fxb7d.js").then((m)=>m.default),...traceEnabled()?{trace:()=>import("./chunk-ek71z2fv.js").then((m)=>m.default)}:{}};function guarded(name,load){return async()=>{let cmd=strictFlags(name,await load()),run=cmd.run;if(!run)return cmd;return{...cmd,async run(ctx){try{await run(ctx)}catch(err){failWithError(name,err)}}}}}var COMMANDS=Object.fromEntries(Object.entries(LOADERS).map(([name,load])=>[name,guarded(name,load)]));
2
+ import{fail,failWithError}from"./chunk-s23gtejf.js";import{firstPositional}from"./chunk-94vx1yb0.js";import{traceEnabled}from"./chunk-6tx68d90.js";var TOLERATED={upgrade:["folder-only"]},BUILTIN_FLAGS=["help","h","version","v"],camel=(name)=>name.replace(/-([a-z0-9])/g,(_,c)=>c.toUpperCase()),kebab=(name)=>name.replace(/[A-Z]/g,(c)=>`-${c.toLowerCase()}`);async function knownFlags(args){let defs=(typeof args==="function"?await args():await args)??{},known=new Set(BUILTIN_FLAGS);for(let[name,def]of Object.entries(defs)){if(def.type==="positional")continue;let alias="alias"in def?def.alias:void 0;for(let spelling of[name,...alias===void 0?[]:[alias].flat()])known.add(spelling),known.add(camel(spelling)),known.add(kebab(spelling))}return known}function flagsIn(rawArgs){let flags=[];for(let token of rawArgs){if(token==="--")break;if(!token.startsWith("-")||token==="-"||/^-\d/.test(token))continue;if(token.startsWith("--")){let name=token.slice(2).split("=")[0]??"";flags.push(name.startsWith("no-")?name.slice(3):name)}else flags.push(...token.slice(1).split("=")[0]?.split("")??[])}return flags}function strictFlags(name,cmd){let subCommands=cmd.subCommands,table=async()=>typeof subCommands==="function"?await subCommands():await subCommands,checked=subCommands?{...cmd,subCommands:async()=>Object.fromEntries(Object.entries(await table()??{}).map(([child,load])=>[child,async()=>{let def=typeof load==="function"?await load():await load;return strictFlags(`${name} ${child}`,def)}]))}:cmd;if(subCommands&&!cmd.run)return checked;let setup=cmd.setup;return{...checked,async setup(context){if(subCommands){let child=await firstPositional(context.rawArgs,cmd.args);if(child!==void 0&&Object.hasOwn(await table()??{},child)){await setup?.(context);return}}let known=await knownFlags(cmd.args),tolerated=TOLERATED[name]??[],unknown=flagsIn(context.rawArgs).filter((flag)=>flag!==""&&!known.has(flag)&&!tolerated.includes(flag));if(unknown.length>0){let listed=[...known].filter((f)=>f.length>1&&!BUILTIN_FLAGS.includes(f)&&f===kebab(f)),hint=listed.length>0?` (it takes ${listed.map((f)=>`--${f}`).join(", ")})`:"";fail(name,`unknown option ${unknown.map((f)=>f.length===1?`-${f}`:`--${f}`).join(", ")}${hint}`)}await setup?.(context)}}}var LOADERS={init:()=>import("./chunk-0s6drs3n.js").then((m)=>m.default),login:()=>import("./chunk-f0vsjfpc.js").then((m)=>m.default),logout:()=>import("./chunk-5wv5a52y.js").then((m)=>m.default),connect:()=>import("./chunk-t947mxr1.js").then((m)=>m.default),run:()=>import("./chunk-9cdwhrkh.js").then((m)=>m.default),design:()=>import("./chunk-wnwgqvtd.js").then((m)=>m.default),mcp:()=>import("./chunk-wndntr7s.js").then((m)=>m.default),stop:()=>import("./chunk-98vvrj0c.js").then((m)=>m.default),status:()=>import("./chunk-2e3nd4tz.js").then((m)=>m.default),__daemon:()=>import("./chunk-7s8frnag.js").then((m)=>m.default),__update_check:()=>import("./chunk-3px2d1j1.js").then((m)=>m.default),render:()=>import("./chunk-pve2mmnr.js").then((m)=>m.default),capture:()=>import("./chunk-whw3epmr.js").then((m)=>m.default),browser:()=>import("./chunk-sn9vg42q.js").then((m)=>m.default),export:()=>import("./chunk-mt8ds8zj.js").then((m)=>m.default),upgrade:()=>import("./chunk-7t13w87m.js").then((m)=>m.default),publish:()=>import("./chunk-7cvhnp9h.js").then((m)=>m.default),emit:()=>import("./chunk-8z3ykvcs.js").then((m)=>m.default),theme:()=>import("./chunk-wvs939t5.js").then((m)=>m.default),completions:()=>import("./chunk-1xb88e07.js").then((m)=>m.default),...traceEnabled()?{trace:()=>import("./chunk-g71v35gd.js").then((m)=>m.default)}:{}};function guarded(name,load){return async()=>{let cmd=strictFlags(name,await load()),run=cmd.run;if(!run)return cmd;return{...cmd,async run(ctx){try{await run(ctx)}catch(err){failWithError(name,err)}}}}}var COMMANDS=Object.fromEntries(Object.entries(LOADERS).map(([name,load])=>[name,guarded(name,load)]));
3
3
  export{COMMANDS};
@@ -1,3 +1,3 @@
1
1
  // @bun
2
- import{AuthConfigResponseSchema,HealthResponseSchema,cloudJson}from"./chunk-t448rrfr.js";var BUILT_DEFAULT="https://api.velloo.ai";function defaultCloudUrl(){return(process.env.VELLOO_CLOUD_URL??BUILT_DEFAULT).replace(/\/+$/,"")}var CONFIG_TIMEOUT_MS=5000;function cloudOrigin(baseUrl){return new URL(baseUrl).origin}async function fetchCloudAppUrl(baseUrl,timeoutMs=CONFIG_TIMEOUT_MS){let fallback=cloudOrigin(baseUrl),res;try{res=await fetch(`${fallback}/v1/auth/config`,{signal:AbortSignal.timeout(timeoutMs)})}catch{return fallback}if(!res.ok)return fallback;let config=await cloudJson(res,AuthConfigResponseSchema,"reading the cloud's config");if(!config.ok||config.value.appUrl===void 0)return fallback;try{let advertised=new URL(config.value.appUrl).origin;return isSecureCloudUrl(advertised)?advertised:fallback}catch{return fallback}}async function publishedBoardsUrl(baseUrl){return`${await fetchCloudAppUrl(baseUrl)}/boards`}async function billingPageUrl(baseUrl){return`${await fetchCloudAppUrl(baseUrl)}/billing`}var LOOPBACK=new Set(["localhost","127.0.0.1","::1","[::1]"]);function isSecureCloudUrl(cloudUrl){try{let u=new URL(cloudUrl);if(u.protocol==="https:")return!0;return u.protocol==="http:"&&LOOPBACK.has(u.hostname)}catch{return!1}}function assertSecureCloudUrl(cloudUrl){if(!isSecureCloudUrl(cloudUrl))throw Error(`refusing to send credentials to a non-HTTPS cloud URL: ${cloudUrl} (use https:// or a loopback host)`)}async function checkCloudHealth(baseUrl){let res;try{res=await fetch(`${baseUrl}/health`,{signal:AbortSignal.timeout(8000)})}catch(error){return{status:"unreachable",reason:error instanceof Error?error.message:String(error)}}let health=await cloudJson(res,HealthResponseSchema,"reading the cloud's health");if(!health.ok||health.value.ok!==!1)return{status:"ok"};let down=[health.value.db?.ok===!1?"database":null,health.value.blob?.ok===!1?"storage backend":null].filter((part)=>part!==null);return{status:"unhealthy",detail:`the cloud's ${down.length>0?down.join(" and "):"a dependency"} is unavailable \u2014 publishes and share links are down; try again later.`}}
2
+ import{AuthConfigResponseSchema,HealthResponseSchema,cloudJson}from"./chunk-n9t36h0q.js";var BUILT_DEFAULT="https://api.velloo.ai";function defaultCloudUrl(){return(process.env.VELLOO_CLOUD_URL??BUILT_DEFAULT).replace(/\/+$/,"")}var CONFIG_TIMEOUT_MS=5000;function cloudOrigin(baseUrl){return new URL(baseUrl).origin}async function fetchCloudAppUrl(baseUrl,timeoutMs=CONFIG_TIMEOUT_MS){let fallback=cloudOrigin(baseUrl),res;try{res=await fetch(`${fallback}/v1/auth/config`,{signal:AbortSignal.timeout(timeoutMs)})}catch{return fallback}if(!res.ok)return fallback;let config=await cloudJson(res,AuthConfigResponseSchema,"reading the cloud's config");if(!config.ok||config.value.appUrl===void 0)return fallback;try{let advertised=new URL(config.value.appUrl).origin;return isSecureCloudUrl(advertised)?advertised:fallback}catch{return fallback}}async function publishedBoardsUrl(baseUrl){return`${await fetchCloudAppUrl(baseUrl)}/boards`}async function billingPageUrl(baseUrl){return`${await fetchCloudAppUrl(baseUrl)}/billing`}var LOOPBACK=new Set(["localhost","127.0.0.1","::1","[::1]"]);function isSecureCloudUrl(cloudUrl){try{let u=new URL(cloudUrl);if(u.protocol==="https:")return!0;return u.protocol==="http:"&&LOOPBACK.has(u.hostname)}catch{return!1}}function assertSecureCloudUrl(cloudUrl){if(!isSecureCloudUrl(cloudUrl))throw Error(`refusing to send credentials to a non-HTTPS cloud URL: ${cloudUrl} (use https:// or a loopback host)`)}async function checkCloudHealth(baseUrl){let res;try{res=await fetch(`${baseUrl}/health`,{signal:AbortSignal.timeout(8000)})}catch(error){return{status:"unreachable",reason:error instanceof Error?error.message:String(error)}}let health=await cloudJson(res,HealthResponseSchema,"reading the cloud's health");if(!health.ok||health.value.ok!==!1)return{status:"ok"};let down=[health.value.db?.ok===!1?"database":null,health.value.blob?.ok===!1?"storage backend":null].filter((part)=>part!==null);return{status:"unhealthy",detail:`the cloud's ${down.length>0?down.join(" and "):"a dependency"} is unavailable \u2014 publishes and share links are down; try again later.`}}
3
3
  export{defaultCloudUrl,fetchCloudAppUrl,publishedBoardsUrl,billingPageUrl,isSecureCloudUrl,assertSecureCloudUrl,checkCloudHealth};
@@ -0,0 +1,5 @@
1
+ // @bun
2
+ import{ok,err,PRICING_URL,PROTECTED_SHARES_UNAVAILABLE,PublishDestinationsResponseSchema,LinkResponseSchema,LinkAccessResponseSchema,VersionUploadResponseSchema,PublishedDesignsResponseSchema,TeamsResponseSchema,unreachable,protocolViolation,uploadRaceLost,readFailure,cloudFailure,httpFailureFrom,boardLimitFrom,describeBoardLimit,describeCloudError,cloudJson,cloudFetch}from"./chunk-n9t36h0q.js";import{prettifyError,string,number,boolean,array,object,strictObject,record,literal,AnnotationSchema,CanvasNoteSchema,BoardSchema,ExtensionSchema,ViewportPresetSchema,LibrarySchema,ScreenSchema,SnippetSchema,sanitizeSvgMarkup,ThemeSchema,ViewportSchema}from"./chunk-nte0t7v3.js";import{buildBoardComposite,MAX_CONCURRENT_RENDERS,renderScreen,captureScreenshot}from"./chunk-c4fym47a.js";import{writeJsonAtomic,managedDesignId,localDesignOf,recordedDesignName,orderedBoards,activeBoards,registryForScreen,renderPassForScreen,liveExtensions,LiveBundler,createPublishMount}from"./chunk-88eqqdk1.js";import{withAssetServer}from"./chunk-0zen7bzb.js";import{checkCloudHealth}from"./chunk-as08hzp3.js";var VERSION_UPLOAD_TIMEOUT_MS=60000,VERSION_UPLOAD_RETRIES=1;async function listPublishDestinations(opts){let query=new URLSearchParams({folderId:opts.folderId});if(opts.teamId)query.set("teamId",opts.teamId);return cloudFetch(`${opts.baseUrl}/v1/publish-destinations?${query}`,PublishDestinationsResponseSchema,{operation:"listing publish destinations",token:opts.token})}async function uploadLinkBundle(opts){let{baseUrl,token,form}=opts,authorized={authorization:`Bearer ${token}`},createRes=await fetch(`${baseUrl}/v1/links`,{method:"POST",headers:authorized,body:JSON.stringify(opts.link)}).catch((error)=>error);if(!(createRes instanceof Response))return err(unreachable(createRes,{url:baseUrl}));if(createRes.status!==200&&createRes.status!==201)return err(await httpFailureFrom("link creation",createRes));let created=createRes.status===201,createdLink=await cloudJson(createRes,LinkResponseSchema,"link creation");if(!createdLink.ok)return createdLink;let link=createdLink.value;if(opts.link.publishMode==="new"&&!created)return err(protocolViolation("the cloud reused a link even though a new publish destination was requested"));if(opts.link.publishMode==="update"&&created)return await fetch(`${baseUrl}/v1/links/${link.slug}`,{method:"DELETE",headers:authorized}).catch(()=>{}),err(protocolViolation("the cloud created a link even though an existing destination was selected"));if(!created){let accessRes=await fetch(`${baseUrl}/v1/links/${link.slug}/access`,{method:"PUT",headers:{...authorized,"content-type":"application/json"},body:JSON.stringify({visibility:opts.link.visibility,password:opts.link.password??null,passwordExpiresAt:opts.link.password?opts.link.passwordExpiresAt??null:null,expectedVersionId:opts.link.expectedVersionId??null})});if(!accessRes.ok)return err(await httpFailureFrom("privacy update",accessRes));let access=await cloudJson(accessRes,LinkAccessResponseSchema,"privacy update");if(!access.ok)return access;link={...link,...access.value}}if(form.append("publishMode",opts.link.publishMode),opts.link.expectedVersionId)form.append("expectedVersionId",opts.link.expectedVersionId);let attempt=await uploadVersionWithRetry({url:`${baseUrl}/v1/links/${link.slug}/versions`,headers:authorized,form,timeoutMs:opts.uploadTimeoutMs??VERSION_UPLOAD_TIMEOUT_MS,retries:opts.uploadRetries??VERSION_UPLOAD_RETRIES});if(!attempt.ok)return attempt;let upload=attempt.value,uploadRes=upload.response;if(uploadRes.status!==201){let{detail,code}=await readFailure(uploadRes);if(upload.transientFailures>0&&uploadRes.status===409&&/slot changed|already has a version/i.test(detail))return err(uploadRaceLost());if(created)await fetch(`${baseUrl}/v1/links/${link.slug}`,{method:"DELETE",headers:authorized}).catch(()=>{});return err(cloudFailure("upload",uploadRes.status,detail,code))}let parsed=await cloudJson(uploadRes,VersionUploadResponseSchema,"upload");if(!parsed.ok)return parsed;let uploaded=parsed.value;return ok({link:{slug:link.slug,visibility:link.visibility??opts.link.visibility,passwordProtected:link.passwordProtected??opts.link.password!=null},created,files:uploaded.files,bytes:uploaded.bytes,shareUrl:uploaded.url.startsWith("http")?uploaded.url:`${baseUrl}${uploaded.url}`,...uploaded.tier!==void 0?{tier:uploaded.tier}:{},...uploaded.history!==void 0?{history:uploaded.history}:{}})}async function uploadVersionWithRetry(opts){let attempts=Math.max(1,Math.floor(opts.retries)+1),transientFailures=0,lastNetworkError="unknown network error",lastTimedOut=!1;for(let attempt=1;attempt<=attempts;attempt+=1){let controller=new AbortController,timedOut=!1,timer=setTimeout(()=>{timedOut=!0,controller.abort()},Math.max(1,opts.timeoutMs));try{let response=await fetch(opts.url,{method:"POST",headers:opts.headers,body:opts.form,signal:controller.signal});if(response.status<500||attempt===attempts)return ok({response,transientFailures});transientFailures+=1,await response.body?.cancel().catch(()=>{})}catch(error){if(transientFailures+=1,lastTimedOut=timedOut,lastNetworkError=error instanceof Error?error.message:String(error),attempt===attempts){let retried=attempts>1?` after ${attempts} attempts`:"";return err(timedOut?unreachable(`timed out after ${formatDuration(opts.timeoutMs)}${retried}`,{url:opts.url,timedOut:!0}):unreachable(`version upload${retried}: ${lastNetworkError}`,{url:opts.url}))}}finally{clearTimeout(timer)}}return err(lastTimedOut?unreachable(`timed out after ${formatDuration(opts.timeoutMs)}`,{url:opts.url,timedOut:!0}):unreachable(`version upload: ${lastNetworkError}`,{url:opts.url}))}function formatDuration(ms){return ms>=1000?`${Math.round(ms/1000)}s`:`${Math.max(1,Math.round(ms))}ms`}var cloudUnhealthy=(detail)=>({kind:"CloudUnhealthy",detail}),noScreens=(root)=>({kind:"NoScreens",root}),noBoardScreens=()=>({kind:"NoBoardScreens"}),bundleInvalid=(detail)=>({kind:"BundleInvalid",detail}),teamNotFound=(requested)=>({kind:"TeamNotFound",requested}),teamAmbiguous=(requested)=>({kind:"TeamAmbiguous",requested});function describePublishError(error){switch(error.kind){case"CloudUnhealthy":return error.detail;case"NoScreens":return`no screens found in ${error.root} \u2014 is this a velloo design folder?`;case"NoBoardScreens":return"the selected boards have no screens.";case"BundleInvalid":return`velloo built an invalid design bundle and did not upload it: ${error.detail}. This is a bug \u2014 please report it.`;case"TeamNotFound":return`no team named or identified by '${error.requested}'`;case"TeamAmbiguous":return`more than one team is named '${error.requested}'; pass its UUID`;case"HttpFailure":{if(error.status===403&&/protected shares/i.test(error.detail))return`${PROTECTED_SHARES_UNAVAILABLE}. Publish publicly, or upgrade at ${PRICING_URL}`;let limit=boardLimitFrom(error);if(limit)return`${describeBoardLimit(limit)}. Run \`velloo publish list\` to see them, or upgrade at ${PRICING_URL}`;return describeCloudError(error)}default:return describeCloudError(error)}}import{execFileSync}from"child_process";import{readFile}from"fs/promises";import{join}from"path";var DESIGN_BUNDLE_FORMAT=1,BundleScreenshotsSchema=object({cover:string().optional(),screens:record(string(),string()).optional(),boards:record(string(),string()).optional()}),DesignBundleMetaSchema=object({formatVersion:number().int().positive().optional(),title:string().optional(),screens:array(object({id:string(),name:string().optional()})).optional(),boards:array(object({id:string()})).optional(),screenshots:BundleScreenshotsSchema.optional()});var DesignBundleSchema=strictObject({formatVersion:literal(DESIGN_BUNDLE_FORMAT),title:string(),viewport:ViewportSchema,defaultLibrary:string(),libraries:record(string(),LibrarySchema),extensions:record(string(),ExtensionSchema),viewportPresets:array(ViewportPresetSchema),theme:ThemeSchema,themes:record(string(),ThemeSchema),customCss:string(),snippets:array(SnippetSchema),screens:array(ScreenSchema),boards:array(BoardSchema),annotations:record(string(),array(AnnotationSchema)),notes:record(string(),array(CanvasNoteSchema)),live:boolean(),snapshotCssPath:string(),bundlePath:string().optional(),screenshots:object({cover:string(),screens:record(string(),string()),boards:record(string(),string())}).optional()});import{homedir}from"os";import{delimiter,dirname,resolve}from"path";function designGitEnv(folder){let ceilings=[homedir()];if(managedDesignId(folder)||localDesignOf(folder))ceilings.push(dirname(resolve(folder)));let inherited=process.env.GIT_CEILING_DIRECTORIES;if(inherited)ceilings.push(inherited);return{...process.env,GIT_CEILING_DIRECTORIES:ceilings.join(delimiter)}}var MAX_SCREENSHOT_BYTES=4194304,MAX_SCREENSHOT_COUNT=120,DOWNSCALE_WIDTH=1280;function isBrowserMissing(err){return err instanceof Error&&err.name==="BrowserMissingError"}async function captureBundleScreenshots(opts){let{screens,boards,viewport,renderHtml,capture,warn,progress}=opts,selectedScreens=opts.screenIds?screens.filter((screen)=>opts.screenIds?.has(screen.id)):screens,selectedBoards=opts.boardIds?boards.filter((board)=>opts.boardIds?.has(board.id)):boards,manifest={cover:"",screens:{},boards:{}},total=selectedScreens.length+selectedBoards.filter((board)=>board.frames.length>0).length,done=0,advance=()=>{done+=1,progress?.(done,total)},shoot=async(html,vp,fullPage)=>{let png=await capture({html,viewport:vp,fullPage,deviceScaleFactor:1});if(png.byteLength>MAX_SCREENSHOT_BYTES&&DOWNSCALE_WIDTH<vp.w)png=await capture({html,viewport:vp,fullPage,deviceScaleFactor:DOWNSCALE_WIDTH/vp.w});return png.byteLength<=MAX_SCREENSHOT_BYTES?png:null},jobs=[];for(let screen of selectedScreens)jobs.push({run:async()=>{try{let png=await shoot(await renderHtml(screen),viewport,!0);if(!png)return warn(`screenshot of screen "${screen.id}" exceeds 4MB even downscaled \u2014 skipped`),null;return{kind:"screen",id:screen.id,path:`screenshots/${screen.id}.png`,bytes:png}}catch(err){if(isBrowserMissing(err))throw err;return warn(`screenshot of screen "${screen.id}" failed \u2014 skipped (${message(err)})`),null}finally{advance()}}});let screenById=new Map(screens.map((screen)=>[screen.id,screen]));for(let board of selectedBoards){if(board.frames.length===0)continue;jobs.push({run:async()=>{try{let framed=(await Promise.all(board.frames.map(async(frame)=>{let screen=screenById.get(frame.screen);return screen?{frame,html:await renderHtml(screen,board.theme,frame.scheme??"light")}:null}))).filter((entry)=>entry!==null);if(framed.length===0)return null;let composite=buildBoardComposite(framed),png=await shoot(composite.html,composite.viewport,!1);if(!png)return warn(`screenshot of board "${board.id}" exceeds 4MB even downscaled \u2014 skipped`),null;return{kind:"board",id:board.id,path:`screenshots/${board.id}.png`,bytes:png}}catch(err){if(isBrowserMissing(err))throw err;return warn(`screenshot of board "${board.id}" failed \u2014 skipped (${message(err)})`),null}finally{advance()}}})}let shotLimit=MAX_SCREENSHOT_COUNT-1,results=Array.from({length:jobs.length},()=>null),nextJob=0,completedShots=0,reservedShots=0,browserMissing=!1,worker=async()=>{while(!browserMissing&&nextJob<jobs.length&&completedShots+reservedShots<shotLimit){let index=nextJob++;reservedShots+=1;try{let shot=await jobs[index]?.run();if(shot)results[index]=shot,completedShots+=1}catch(err){if(isBrowserMissing(err))browserMissing=!0;else throw err}finally{reservedShots-=1}}},concurrency=Math.max(1,Math.min(MAX_CONCURRENT_RENDERS,Math.floor(opts.concurrency??MAX_CONCURRENT_RENDERS)));if(await Promise.all(Array.from({length:Math.min(concurrency,jobs.length)},worker)),browserMissing)return warn("no headless browser available \u2014 publishing without screenshots"),null;if(nextJob<jobs.length)warn(`screenshot limit (${MAX_SCREENSHOT_COUNT}) reached \u2014 remaining shots skipped`);let files=[];for(let shot of results){if(!shot)continue;if(files.push({path:shot.path,bytes:shot.bytes}),shot.kind==="screen")manifest.screens[shot.id]=shot.path;else manifest.boards[shot.id]=shot.path}let coverSource=selectedBoards.map((b)=>manifest.boards[b.id]).find((p)=>p!==void 0)??selectedScreens.map((s)=>manifest.screens[s.id]).find((p)=>p!==void 0);if(!coverSource)return null;let source=files.find((f)=>f.path===coverSource);if(!source)return null;return manifest.cover="screenshots/cover.png",files.push({path:manifest.cover,bytes:source.bytes}),{manifest,files}}function message(err){let msg=err instanceof Error?err.message:String(err);return msg.split(`
3
+ `)[0]??msg}var normalizedBoardIds=(boardIds)=>[...new Set(boardIds)].sort();function publishSlotMismatches(slot,current){let mismatches=[];if(!slot.context.contextKnown)mismatches.push("older publish has no board-selection context");if(slot.teamId!==current.teamId)mismatches.push("team differs");if(JSON.stringify(normalizedBoardIds(slot.context.boardIds))!==JSON.stringify(normalizedBoardIds(current.boardIds)))mismatches.push("board selection differs");if(slot.context.repo!==current.repo)mismatches.push("repository differs");else if(current.repo!==null){if(!slot.context.branch||!current.branch)mismatches.push("branch is unavailable");else if(slot.context.branch!==current.branch)mismatches.push("branch differs")}return mismatches}function recommendedPublishSlot(slots,current){return exactPublishSlots(slots,current)[0]??null}function exactPublishSlots(slots,current){return slots.filter((slot)=>publishSlotMismatches(slot,current).length===0).sort((left,right)=>publishedAt(right.lastPublishedAt)-publishedAt(left.lastPublishedAt))}var publishedAt=(value)=>{let parsed=value?Date.parse(value):Number.NaN;return Number.isFinite(parsed)?parsed:Number.NEGATIVE_INFINITY},PUBLISH_VIEWPORT={w:1440,h:900};function defaultPublishTitle(folderRoot){return`${recordedDesignName(folderRoot)??folderRoot.split("/").filter(Boolean).pop()} designs`}async function ensureFolderId(folder,existing,report){if(existing)return existing;let path=join(folder,".design","config.json"),raw=JSON.parse(await readFile(path,"utf8")),folderId=crypto.randomUUID();return await writeJsonAtomic(path,{...raw,folderId}),report({kind:"note",message:"assigned this folder a cloud id (.design/config.json folderId) \u2014 commit it so every clone finds the folder's share links."}),folderId}function reportProvenance(git,report){if(git.repo){report({kind:"info",message:git.branch?`source: ${git.repo} on ${git.branch}`:`source: ${git.repo} (detached HEAD \u2014 no branch recorded)`});return}report({kind:"info",message:git.branch?`source: branch ${git.branch} \u2014 no git remote, publishing without a repository`:"source: not a git repository \u2014 publishing without repository or branch"})}function gitProbe(folder){return{encoding:"utf8",stdio:["ignore","pipe","ignore"],env:designGitEnv(folder)}}function gitCommitSha(folder){try{let probe=gitProbe(folder);if(execFileSync("git",["-C",folder,"status","--porcelain"],probe).trim().length>0)return null;return execFileSync("git",["-C",folder,"rev-parse","HEAD"],probe).trim()}catch{return null}}function normalizeRemote(url){let rest=url.trim().replace(/\.git\/?$/,"");if(/^[./~]/.test(rest)||/^[a-z]:[\\/]/i.test(rest)||rest.startsWith("file://"))return null;let scp=/^(?:[\w.-]+@)?([\w.-]+):(?!\/\/)(.+)$/.exec(rest);if(scp?.[1]&&scp[2])return`${scp[1]}/${scp[2].replace(/^\/+/,"")}`;try{let parsed=new URL(rest.includes("://")?rest:`https://${rest}`);if(!parsed.hostname||!parsed.pathname||parsed.pathname==="/")return null;return`${parsed.hostname}${parsed.pathname.replace(/\/+$/,"")}`}catch{return null}}function gitContext(folder){let probe=gitProbe(folder),run=(args)=>{try{return execFileSync("git",["-C",folder,...args],probe).trim()||null}catch{return null}},branchRaw=run(["rev-parse","--abbrev-ref","HEAD"]),remote=run(["remote","get-url","origin"]);return{repo:remote?normalizeRemote(remote):null,branch:branchRaw==="HEAD"?null:branchRaw}}async function resolveTeam(baseUrl,token,requested){if(!requested)return ok(void 0);let listed=await listTeams(baseUrl,token);if(!listed.ok)return listed;let exact=listed.value.filter((team)=>team.id===requested||team.name.toLowerCase()===requested.toLowerCase());if(exact.length===0)return err(teamNotFound(requested));if(exact.length>1)return err(teamAmbiguous(requested));return ok(exact[0]?.id)}async function listTeams(baseUrl,token){let body=await cloudFetch(`${baseUrl}/v1/teams/mine`,TeamsResponseSchema,{operation:"listing teams",token});return body.ok?ok(body.value.teams):body}function selectBoards(design,boardIds){if(!boardIds||boardIds.length===0)return activeBoards(design).map(([,board])=>board);let wanted=new Set(boardIds);return orderedBoards(design).map(([,board])=>board).filter((board)=>wanted.has(board.id))}async function publishDesign(cloud,pipeline,request,report=()=>{}){let{folder:design}=pipeline,{root,config}=design;report({kind:"step",step:"check",message:"checking the cloud"});let health=await checkCloudHealth(cloud.baseUrl);if(health.status==="unreachable")return err(unreachable(health.reason,{url:cloud.baseUrl}));if(health.status==="unhealthy")return err(cloudUnhealthy(health.detail));if(design.screens.size===0)return err(noScreens(root));report({kind:"step",step:"select",message:"collecting boards"});let boards=selectBoards(design,request.boardIds),screenIds=Boolean(request.boardIds&&request.boardIds.length>0)?new Set(boards.flatMap((b)=>b.frames.map((f)=>f.screen))):null,screens=screenIds?[...design.screens.values()].filter((s)=>screenIds.has(s.id)):[...design.screens.values()];if(screens.length===0)return err(noBoardScreens());let viewport=request.viewport??PUBLISH_VIEWPORT,title=request.title?.trim()||defaultPublishTitle(root),form=new FormData,bundleFiles=0,bundleBytes=0,addFile=(path,data,type)=>{if(typeof data==="string"?data.length===0:data.byteLength===0)return report({kind:"warn",message:`skipped empty file: ${path}`}),!1;return form.append("file",new File([data],path,type?{type}:void 0)),bundleFiles+=1,bundleBytes+=typeof data==="string"?new TextEncoder().encode(data).byteLength:data.byteLength,!0},liveExt=liveExtensions(config.extensions),bundler=Object.keys(liveExt).length>0?pipeline.liveBundler??createPublishBundler(root,config):null;report({kind:"step",step:"styles",message:"compiling styles"});let snapshotCss=await pipeline.snapshotCss(),live=!1,liveCode=null;if(bundler){report({kind:"step",step:"bundle",message:"bundling live components"});let bundle=await bundler.build();for(let e of bundle.errors)report({kind:"warn",message:`live-island: ${e.message}`});if(addFile("bundle.js",bundle.code,"text/javascript"))liveCode=bundle.code,live=!0}report({kind:"step",step:"capture",message:"capturing previews"});let mount=createPublishMount(pipeline.folder,pipeline.providers,pipeline.defaultProvider),shots=await withAssetServer(root,liveCode,(baseHref)=>{let htmlCache=new Map,renderHtml=async(screen,themeName,scheme="light")=>{let theme=(themeName?design.themes.get(themeName):void 0)??design.theme,key=`${screen.id}\x00${theme.name}\x00${scheme}`,cached=htmlCache.get(key);if(cached)return cached;let canvasBundle=await mount.forScreen(screen,theme,scheme==="dark"),rendering=renderScreen(screen,theme,{viewport,snapshotCss,registry:registryForScreen(screen,pipeline.providers,pipeline.defaultProvider,config.extensions??{}),renderPass:renderPassForScreen(screen,pipeline.providers,pipeline.defaultProvider,theme),snippets:design.snippets,customCss:design.customCss,dark:scheme==="dark",baseHref,...live?{liveBundleUrl:"/live/bundle.js"}:{},...canvasBundle?{canvasBundle}:{}}).then(({html})=>html);return htmlCache.set(key,rendering),rendering};return captureBundleScreenshots({screens,boards,...request.screenshotSelection?{screenIds:request.screenshotSelection.screenIds,boardIds:request.screenshotSelection.boardIds}:{},viewport,renderHtml,capture:async(req)=>(await captureScreenshot({html:req.html,viewport:req.viewport,fullPage:req.fullPage,deviceScaleFactor:req.deviceScaleFactor})).png,warn:(message)=>report({kind:"warn",message}),progress:(done,total)=>report({kind:"capture",done,total})})},mount.serve);for(let f of shots?.files??[])addFile(f.path,f.bytes,"image/png");let annotations=Object.fromEntries([...design.annotations].filter(([screenId,list])=>list.length>0&&screens.some((s)=>s.id===screenId))),notes=Object.fromEntries([...design.notes].filter(([boardId,list])=>list.length>0&&boards.some((b)=>b.id===boardId))),designDoc={formatVersion:DESIGN_BUNDLE_FORMAT,title,viewport,defaultLibrary:config.defaultLibrary,libraries:config.libraries,extensions:config.extensions??{},viewportPresets:config.viewportPresets??[],theme:design.theme,themes:Object.fromEntries(design.themes),customCss:design.customCss,snippets:[...design.snippets.values()],screens,boards,annotations,notes,live,snapshotCssPath:"snapshot.css",...live?{bundlePath:"bundle.js"}:{},...shots?{screenshots:shots.manifest}:{}},validated=DesignBundleSchema.safeParse(designDoc);if(!validated.success)return err(bundleInvalid(prettifyError(validated.error)));addFile("design.json",JSON.stringify(designDoc),"application/json"),addFile("snapshot.css",snapshotCss||`/* this folder uses no CSS framework */
4
+ `,"text/css");let assetRefs=new Set,assetRe=/\/assets\/[A-Za-z0-9._@\-/]+/g;for(let source of[...screens,...design.snippets.values()])for(let m of JSON.stringify(source).matchAll(assetRe))assetRefs.add(m[0]);for(let ref of assetRefs){let rel=ref.replace(/^\//,"");try{let bytes=await readFile(join(root,rel));addFile(rel,/\.svg$/i.test(rel)?Buffer.from(sanitizeSvgMarkup(bytes.toString("utf8")),"utf8"):bytes)}catch{report({kind:"warn",message:`asset not found: ${rel}`})}}let commitSha=gitCommitSha(root);if(commitSha)form.append("commitSha",commitSha);let git=request.provenance??gitContext(root);if(reportProvenance(git,report),git.repo)form.append("gitRepo",git.repo);if(git.branch)form.append("gitBranch",git.branch);let folderId=await ensureFolderId(root,config.folderId,report);report({kind:"step",step:"upload",message:`uploading ${bundleFiles} file${bundleFiles===1?"":"s"} (${formatBytes(bundleBytes)})`});let uploaded=await uploadLinkBundle({baseUrl:cloud.baseUrl,token:cloud.token,link:{...request.destination.slug?{slug:request.destination.slug}:{},folderId,publishMode:request.destination.mode,...request.destination.mode==="update"?{expectedVersionId:request.destination.expectedVersionId}:{},title,visibility:request.visibility,...request.teamId?{teamId:request.teamId}:{},...request.password?{password:request.password}:{},...request.passwordExpiresAt?{passwordExpiresAt:request.passwordExpiresAt}:{}},form});if(!uploaded.ok)return uploaded;let upload=uploaded.value;return ok({shareUrl:upload.shareUrl,visibility:upload.link.visibility,passwordProtected:upload.link.passwordProtected,files:upload.files,bytes:upload.bytes,screenshots:shots?.files.length??0,boards:boards.length,screens:screens.length,commitSha,created:upload.created,...upload.tier!==void 0?{tier:upload.tier}:{},...upload.history!==void 0?{history:upload.history}:{}})}function formatBytes(bytes){if(bytes>=1048576)return`${(bytes/1048576).toFixed(1)} MB`;if(bytes>=1024)return`${Math.round(bytes/1024)} KB`;return`${bytes} B`}function createPublishBundler(root,config){return new LiveBundler(root,()=>config,()=>liveExtensions(config.extensions),!0,!0)}function publishedDesignSubtitle(design){let published=design.lastPublishedAt?`Published ${design.lastPublishedAt}`:"Publish time unavailable",publisher=design.ownerEmail?.trim()?`by ${design.ownerEmail.trim()}`:"publisher unavailable",repo=design.git?.repo?.trim(),branch=design.git?.branch?.trim(),source=repo?`repo ${repo}${branch?` (${branch})`:""}`:"repository unavailable";return`${published} \xB7 ${publisher} \xB7 ${source}`}async function listPublishedDesigns(opts){let body=await cloudFetch(`${opts.baseUrl}/v1/links`,PublishedDesignsResponseSchema,{operation:"listing published designs",token:opts.token});if(!body.ok)return body;return ok((body.value.links??[]).filter((link)=>link.published).map((link)=>({...link,url:link.url.startsWith("http")?link.url:`${opts.baseUrl}${link.url}`})))}async function unpublishDesign(opts){let res=await fetch(`${opts.baseUrl}/v1/links/${encodeURIComponent(opts.slug)}`,{method:"DELETE",headers:{authorization:`Bearer ${opts.token}`}}).catch((error)=>error);if(!(res instanceof Response))return err(unreachable(res,{url:opts.baseUrl}));if(!res.ok)return err(await httpFailureFrom("unpublishing the design",res));return ok(void 0)}
5
+ export{publishedDesignSubtitle,listPublishedDesigns,unpublishDesign,listPublishDestinations,designGitEnv,describePublishError,recommendedPublishSlot,exactPublishSlots,PUBLISH_VIEWPORT,gitContext,resolveTeam,listTeams,publishDesign,createPublishBundler};
@@ -1,5 +1,5 @@
1
1
  // @bun
2
- import{localDesignOf}from"./chunk-tdsk5wxa.js";import{TOOL_VERSION}from"./chunk-dg6z4vdd.js";import{isCancel,multiselect,log,select}from"./chunk-80fjfyha.js";import{manifestListing,findDesigns}from"./chunk-vsv8z729.js";import{require_picocolors}from"./chunk-jrsknzjt.js";import{__toESM}from"./chunk-2smsg2ct.js";import{existsSync}from"fs";import{homedir}from"os";import{dirname,join}from"path";var claudeEntry=(conn)=>conn.transport==="http"?{type:"http",url:conn.url}:{command:conn.command,args:conn.args},cursorEntry=(conn)=>conn.transport==="http"?{url:conn.url}:{command:conn.command,args:conn.args},codexEntry=cursorEntry,continueEntry=(conn)=>conn.transport==="http"?{name:"velloo",type:"streamable-http",url:conn.url}:{name:"velloo",type:"stdio",command:conn.command,args:conn.args},droidEntry=(conn)=>conn.transport==="http"?{type:"http",url:conn.url}:{type:"stdio",command:conn.command,args:conn.args,disabled:!1},geminiEntry=(conn)=>conn.transport==="http"?{httpUrl:conn.url}:{command:conn.command,args:conn.args},opencodeEntry=(conn)=>conn.transport==="http"?{type:"remote",url:conn.url,enabled:!0}:{type:"local",command:[conn.command,...conn.args],enabled:!0},vscodeEntry=(conn)=>conn.transport==="http"?{type:"http",url:conn.url}:{type:"stdio",command:conn.command,args:conn.args};function claudeDesktopConfigPath(homeDir){if(process.platform==="win32")return join(homeDir,"AppData","Roaming","Claude","claude_desktop_config.json");if(process.platform==="darwin")return join(homeDir,"Library","Application Support","Claude","claude_desktop_config.json");return join(homeDir,".config","Claude","claude_desktop_config.json")}var AGENTS={"claude-code":{id:"claude-code",label:"Claude Code (project)",scope:"project",format:"json",family:"claude-code",path:(root)=>join(root,".mcp.json"),entry:claudeEntry},cursor:{id:"cursor",label:"Cursor (project)",scope:"project",format:"json",family:"cursor",path:(root)=>join(root,".cursor","mcp.json"),entry:cursorEntry},codex:{id:"codex",label:"Codex CLI (project)",scope:"project",format:"codex-toml",path:(root)=>join(root,".codex","config.toml"),entry:codexEntry},continue:{id:"continue",label:"Continue (project)",scope:"project",format:"continue-block",path:(root)=>join(root,".continue","mcpServers","velloo.yaml"),entry:continueEntry},"claude-code-global":{id:"claude-code-global",label:"Claude Code (global)",scope:"global",format:"json",family:"claude-code",path:(_root,home)=>join(home,".claude.json"),entry:claudeEntry},"cursor-global":{id:"cursor-global",label:"Cursor (global)",scope:"global",format:"json",family:"cursor",path:(_root,home)=>join(home,".cursor","mcp.json"),entry:cursorEntry},"codex-global":{id:"codex-global",label:"Codex CLI (global)",scope:"global",format:"codex-toml",path:(_root,home)=>join(home,".codex","config.toml"),entry:codexEntry},"continue-global":{id:"continue-global",label:"Continue (global)",scope:"global",format:"continue-config",path:(_root,home)=>join(home,".continue","config.yaml"),entry:continueEntry},"claude-desktop":{id:"claude-desktop",label:"Claude Desktop",scope:"global",format:"json",gui:!0,path:(_root,home)=>claudeDesktopConfigPath(home),entry:claudeEntry},opencode:{id:"opencode",label:"opencode (project)",scope:"project",format:"opencode-json",path:(root)=>join(root,"opencode.json"),entry:opencodeEntry},"opencode-global":{id:"opencode-global",label:"opencode (global)",scope:"global",format:"opencode-json",path:(_root,home)=>join(home,".config","opencode","opencode.json"),entry:opencodeEntry},"droid-global":{id:"droid-global",label:"Droid (global)",scope:"global",format:"json",path:(_root,home)=>join(home,".factory","mcp.json"),entry:droidEntry},"cline-global":{id:"cline-global",label:"Cline (global)",scope:"global",format:"json",path:(_root,home)=>join(home,".cline","data","settings","cline_mcp_settings.json"),entry:cursorEntry},gemini:{id:"gemini",label:"Gemini CLI (project)",scope:"project",format:"json",path:(root)=>join(root,".gemini","settings.json"),entry:geminiEntry},"gemini-global":{id:"gemini-global",label:"Gemini CLI (global)",scope:"global",format:"json",path:(_root,home)=>join(home,".gemini","settings.json"),entry:geminiEntry},"windsurf-global":{id:"windsurf-global",label:"Windsurf (global)",scope:"global",format:"json",path:(_root,home)=>join(home,".codeium","windsurf","mcp_config.json"),entry:cursorEntry},vscode:{id:"vscode",label:"VS Code / Copilot (project)",scope:"project",format:"vscode-json",path:(root)=>join(root,".vscode","mcp.json"),entry:vscodeEntry}},AGENT_IDS=Object.keys(AGENTS),PROJECT_AGENT_IDS=["claude-code","cursor"],GLOBAL_AGENT_IDS=["claude-code-global","cursor-global"];function detectInstalledAgents(homeDir=homedir()){let has=(rel)=>existsSync(join(homeDir,rel)),found=[];if(Bun.which("claude")||has(".claude.json")||has(".claude"))found.push("claude-code-global");if(Bun.which("cursor-agent")||Bun.which("cursor")||has(".cursor"))found.push("cursor-global");if(Bun.which("codex")||has(".codex"))found.push("codex-global");if(has(".continue"))found.push("continue-global");if(existsSync(dirname(claudeDesktopConfigPath(homeDir))))found.push("claude-desktop");if(Bun.which("opencode")||has(join(".config","opencode")))found.push("opencode-global");if(Bun.which("droid")||has(".factory"))found.push("droid-global");if(Bun.which("cline")||has(".cline"))found.push("cline-global");if(Bun.which("gemini")||has(join(".gemini","settings.json")))found.push("gemini-global");if(has(join(".codeium","windsurf")))found.push("windsurf-global");return found}import{existsSync as existsSync2,realpathSync}from"fs";import{access}from"fs/promises";import{dirname as dirname2,join as join2,parse,relative,resolve}from"path";async function resolveProjectRoot(designFolder,override){if(override)return override;let local=localDesignOf(designFolder);if(local)return local.root;let registered=await registeringManifest(designFolder);if(registered)return registered.dir;return nearestPackageRoot(designFolder)}async function designArgumentFor(projectRoot,designFolder){let set=await findDesigns(projectRoot).catch(()=>null),target=realOr(designFolder);if(set?.designs.some((d)=>!d.outsideRepo&&realOr(d.root)===target))return null;return relative(projectRoot,designFolder)||"."}function realOr(path){return existsSync2(path)?realpathSync(path):resolve(path)}async function agentRootCandidates(designFolder){if(localDesignOf(designFolder))return[];let roots=[await resolveProjectRoot(designFolder)];return roots.push(await nearestPackageRoot(designFolder)),[...new Set(roots)]}async function registeringManifest(designFolder){let abs=resolve(designFolder),found;try{found=await manifestListing(abs)}catch{return null}if(!found)return null;let real=existsSync2(abs)?realpathSync(abs):abs;return found.folders.some((folder)=>folder===abs||existsSync2(folder)&&realpathSync(folder)===real)?found:null}async function nearestPackageRoot(designFolder){let fallback=dirname2(designFolder),dir=fallback,fsRoot=parse(dir).root;for(let i=0;i<8;i++){try{return await access(join2(dir,"package.json")),dir}catch{}if(dir===fsRoot)break;dir=dirname2(dir)}return fallback}import{existsSync as existsSync5}from"fs";import{homedir as homedir3}from"os";import{join as join6}from"path";import{mkdir,writeFile}from"fs/promises";import{dirname as dirname3,join as join3}from"path";async function installCursorRules(projectRoot,designFolder){let pinned=await designArgumentFor(projectRoot,designFolder),arg=pinned?` ${pinned}`:"",body=`---
2
+ import{localDesignOf}from"./chunk-88eqqdk1.js";import{TOOL_VERSION}from"./chunk-9psr8atb.js";import{isCancel,multiselect,log,select}from"./chunk-80fjfyha.js";import{manifestListing,findDesigns}from"./chunk-wafb2xm9.js";import{require_picocolors}from"./chunk-jrsknzjt.js";import{__toESM}from"./chunk-2smsg2ct.js";import{existsSync}from"fs";import{homedir}from"os";import{dirname,join}from"path";var claudeEntry=(conn)=>conn.transport==="http"?{type:"http",url:conn.url}:{command:conn.command,args:conn.args},cursorEntry=(conn)=>conn.transport==="http"?{url:conn.url}:{command:conn.command,args:conn.args},codexEntry=cursorEntry,continueEntry=(conn)=>conn.transport==="http"?{name:"velloo",type:"streamable-http",url:conn.url}:{name:"velloo",type:"stdio",command:conn.command,args:conn.args},droidEntry=(conn)=>conn.transport==="http"?{type:"http",url:conn.url}:{type:"stdio",command:conn.command,args:conn.args,disabled:!1},geminiEntry=(conn)=>conn.transport==="http"?{httpUrl:conn.url}:{command:conn.command,args:conn.args},opencodeEntry=(conn)=>conn.transport==="http"?{type:"remote",url:conn.url,enabled:!0}:{type:"local",command:[conn.command,...conn.args],enabled:!0},vscodeEntry=(conn)=>conn.transport==="http"?{type:"http",url:conn.url}:{type:"stdio",command:conn.command,args:conn.args};function claudeDesktopConfigPath(homeDir){if(process.platform==="win32")return join(homeDir,"AppData","Roaming","Claude","claude_desktop_config.json");if(process.platform==="darwin")return join(homeDir,"Library","Application Support","Claude","claude_desktop_config.json");return join(homeDir,".config","Claude","claude_desktop_config.json")}var AGENTS={"claude-code":{id:"claude-code",label:"Claude Code (project)",scope:"project",format:"json",family:"claude-code",path:(root)=>join(root,".mcp.json"),entry:claudeEntry},cursor:{id:"cursor",label:"Cursor (project)",scope:"project",format:"json",family:"cursor",path:(root)=>join(root,".cursor","mcp.json"),entry:cursorEntry},codex:{id:"codex",label:"Codex CLI (project)",scope:"project",format:"codex-toml",path:(root)=>join(root,".codex","config.toml"),entry:codexEntry},continue:{id:"continue",label:"Continue (project)",scope:"project",format:"continue-block",path:(root)=>join(root,".continue","mcpServers","velloo.yaml"),entry:continueEntry},"claude-code-global":{id:"claude-code-global",label:"Claude Code (global)",scope:"global",format:"json",family:"claude-code",path:(_root,home)=>join(home,".claude.json"),entry:claudeEntry},"cursor-global":{id:"cursor-global",label:"Cursor (global)",scope:"global",format:"json",family:"cursor",path:(_root,home)=>join(home,".cursor","mcp.json"),entry:cursorEntry},"codex-global":{id:"codex-global",label:"Codex CLI (global)",scope:"global",format:"codex-toml",path:(_root,home)=>join(home,".codex","config.toml"),entry:codexEntry},"continue-global":{id:"continue-global",label:"Continue (global)",scope:"global",format:"continue-config",path:(_root,home)=>join(home,".continue","config.yaml"),entry:continueEntry},"claude-desktop":{id:"claude-desktop",label:"Claude Desktop",scope:"global",format:"json",gui:!0,path:(_root,home)=>claudeDesktopConfigPath(home),entry:claudeEntry},opencode:{id:"opencode",label:"opencode (project)",scope:"project",format:"opencode-json",path:(root)=>join(root,"opencode.json"),entry:opencodeEntry},"opencode-global":{id:"opencode-global",label:"opencode (global)",scope:"global",format:"opencode-json",path:(_root,home)=>join(home,".config","opencode","opencode.json"),entry:opencodeEntry},"droid-global":{id:"droid-global",label:"Droid (global)",scope:"global",format:"json",path:(_root,home)=>join(home,".factory","mcp.json"),entry:droidEntry},"cline-global":{id:"cline-global",label:"Cline (global)",scope:"global",format:"json",path:(_root,home)=>join(home,".cline","data","settings","cline_mcp_settings.json"),entry:cursorEntry},gemini:{id:"gemini",label:"Gemini CLI (project)",scope:"project",format:"json",path:(root)=>join(root,".gemini","settings.json"),entry:geminiEntry},"gemini-global":{id:"gemini-global",label:"Gemini CLI (global)",scope:"global",format:"json",path:(_root,home)=>join(home,".gemini","settings.json"),entry:geminiEntry},"windsurf-global":{id:"windsurf-global",label:"Windsurf (global)",scope:"global",format:"json",path:(_root,home)=>join(home,".codeium","windsurf","mcp_config.json"),entry:cursorEntry},vscode:{id:"vscode",label:"VS Code / Copilot (project)",scope:"project",format:"vscode-json",path:(root)=>join(root,".vscode","mcp.json"),entry:vscodeEntry}},AGENT_IDS=Object.keys(AGENTS),PROJECT_AGENT_IDS=["claude-code","cursor"],GLOBAL_AGENT_IDS=["claude-code-global","cursor-global"];function detectInstalledAgents(homeDir=homedir()){let has=(rel)=>existsSync(join(homeDir,rel)),found=[];if(Bun.which("claude")||has(".claude.json")||has(".claude"))found.push("claude-code-global");if(Bun.which("cursor-agent")||Bun.which("cursor")||has(".cursor"))found.push("cursor-global");if(Bun.which("codex")||has(".codex"))found.push("codex-global");if(has(".continue"))found.push("continue-global");if(existsSync(dirname(claudeDesktopConfigPath(homeDir))))found.push("claude-desktop");if(Bun.which("opencode")||has(join(".config","opencode")))found.push("opencode-global");if(Bun.which("droid")||has(".factory"))found.push("droid-global");if(Bun.which("cline")||has(".cline"))found.push("cline-global");if(Bun.which("gemini")||has(join(".gemini","settings.json")))found.push("gemini-global");if(has(join(".codeium","windsurf")))found.push("windsurf-global");return found}import{existsSync as existsSync2,realpathSync}from"fs";import{access}from"fs/promises";import{dirname as dirname2,join as join2,parse,relative,resolve,sep}from"path";async function resolveProjectRoot(designFolder,override){if(override)return override;let local=localDesignOf(designFolder);if(local)return local.root;let registered=await registeringManifest(designFolder);if(registered)return registered.dir;return nearestPackageRoot(designFolder)}async function designArgumentFor(projectRoot,designFolder){let set=await findDesigns(projectRoot).catch(()=>null),target=realOr(designFolder);if(set?.designs.some((d)=>!d.outsideRepo&&realOr(d.root)===target))return null;return relative(projectRoot,designFolder).split(sep).join("/")||"."}function realOr(path){return existsSync2(path)?realpathSync(path):resolve(path)}async function agentRootCandidates(designFolder){if(localDesignOf(designFolder))return[];let roots=[await resolveProjectRoot(designFolder)];return roots.push(await nearestPackageRoot(designFolder)),[...new Set(roots)]}async function registeringManifest(designFolder){let abs=resolve(designFolder),found;try{found=await manifestListing(abs)}catch{return null}if(!found)return null;let real=existsSync2(abs)?realpathSync(abs):abs;return found.folders.some((folder)=>folder===abs||existsSync2(folder)&&realpathSync(folder)===real)?found:null}async function nearestPackageRoot(designFolder){let fallback=dirname2(designFolder),dir=fallback,fsRoot=parse(dir).root;for(let i=0;i<8;i++){try{return await access(join2(dir,"package.json")),dir}catch{}if(dir===fsRoot)break;dir=dirname2(dir)}return fallback}import{existsSync as existsSync5}from"fs";import{homedir as homedir3}from"os";import{join as join6}from"path";import{mkdir,writeFile}from"fs/promises";import{dirname as dirname3,join as join3}from"path";async function installCursorRules(projectRoot,designFolder){let pinned=await designArgumentFor(projectRoot,designFolder),arg=pinned?` ${pinned}`:"",body=`---
3
3
  description: Drive UI design through the Velloo MCP server (a local design canvas backed by this project's shadcn components).
4
4
  alwaysApply: false
5
5
  ---
@@ -1,3 +1,3 @@
1
1
  // @bun
2
- import{ConfigSchema}from"./chunk-40xgcth8.js";import{readFile}from"fs/promises";import{dirname,join,resolve}from"path";async function findDesignConfig(startPath){let dir=resolve(startPath);if(!dir.endsWith("/"))dir=dirname(dir);while(!0){let candidate=join(dir,".design","config.json");try{let raw=await readFile(candidate,"utf8"),config=ConfigSchema.parse(JSON.parse(raw));return{folder:dir,config}}catch(err){if(err.code!=="ENOENT")throw err}let parent=dirname(dir);if(parent===dir)return null;dir=parent}}
2
+ import{ConfigSchema}from"./chunk-nte0t7v3.js";import{readFile}from"fs/promises";import{dirname,join,resolve}from"path";async function findDesignConfig(startPath){let dir=resolve(startPath);if(!dir.endsWith("/"))dir=dirname(dir);while(!0){let candidate=join(dir,".design","config.json");try{let raw=await readFile(candidate,"utf8"),config=ConfigSchema.parse(JSON.parse(raw));return{folder:dir,config}}catch(err){if(err.code!=="ENOENT")throw err}let parent=dirname(dir);if(parent===dir)return null;dir=parent}}
3
3
  export{findDesignConfig};