velloo 0.8.0 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (117) hide show
  1. package/BUN-LICENSE.md +4 -3
  2. package/README.md +112 -128
  3. package/THIRD-PARTY-NOTICES.md +61 -61
  4. package/canvas/assets/InitWizard-C1CkcS7C.js +3 -0
  5. package/canvas/assets/index-CZPX0col.css +2 -0
  6. package/canvas/assets/index-D7gy-ZUv.js +49 -0
  7. package/canvas/assets/lucide-all-B49qZ9YE.js +1 -0
  8. package/canvas/assets/radix-CuVEihKE.js +41 -0
  9. package/canvas/assets/react-C1iE8mnY.js +9 -0
  10. package/canvas/assets/rolldown-runtime-XKyaHtl9.js +1 -0
  11. package/canvas/assets/vendor-DXkvBgGY.js +58 -0
  12. package/canvas/assets/wand-sparkles-BxGgFkAt.js +1 -0
  13. package/canvas/index.html +6 -6
  14. package/{chunk-32cq4wpr.js → chunk-0rvdh1j3.js} +1 -1
  15. package/chunk-12pgt83m.js +8 -0
  16. package/chunk-12vc3f1h.js +3 -0
  17. package/{chunk-majd3gx9.js → chunk-28mhcvw2.js} +1 -1
  18. package/{chunk-ez720ked.js → chunk-3zm7ydna.js} +1 -1
  19. package/chunk-457fm9yy.js +7 -0
  20. package/chunk-46jg9aqy.js +40 -0
  21. package/chunk-5gwh0zpn.js +3 -0
  22. package/{chunk-q7wwqn03.js → chunk-5hb1e233.js} +1 -1
  23. package/{chunk-w30zfv3m.js → chunk-5ts4fvd9.js} +1 -1
  24. package/{chunk-rg86bhtb.js → chunk-62amy8bj.js} +1 -1
  25. package/{chunk-nrxqr4v5.js → chunk-6p8zwxxx.js} +1 -1
  26. package/{chunk-45wv1fs5.js → chunk-75gfv9g4.js} +11 -12
  27. package/chunk-84qjmqmz.js +2 -0
  28. package/{chunk-esg0x95a.js → chunk-85m9p67t.js} +2 -2
  29. package/chunk-91qesxwh.js +2 -0
  30. package/{chunk-hsk91jms.js → chunk-976rm76x.js} +1 -1
  31. package/chunk-99ccjbaa.js +4 -0
  32. package/{chunk-asqpx5v7.js → chunk-9hc7m55p.js} +3 -4
  33. package/{chunk-h3ser37q.js → chunk-a7xka0bj.js} +1 -1
  34. package/chunk-ak57bgnh.js +2 -0
  35. package/chunk-bf5808x5.js +2 -0
  36. package/{chunk-mqtnj8ws.js → chunk-bj47gjs9.js} +1 -1
  37. package/chunk-d0m56cjx.js +2 -0
  38. package/chunk-d6a6198y.js +3 -0
  39. package/{chunk-aefn23tr.js → chunk-etv7qsw7.js} +1 -1
  40. package/chunk-f2793pj6.js +85 -0
  41. package/{chunk-3612470d.js → chunk-fnv123mm.js} +1 -1
  42. package/{chunk-pjtg3wnm.js → chunk-fzevxpdz.js} +1 -1
  43. package/chunk-ghwy99py.js +68 -0
  44. package/chunk-gtt1qww8.js +2 -0
  45. package/chunk-hhkjqvww.js +1501 -0
  46. package/{chunk-d19ttv1a.js → chunk-hrvqwp8z.js} +1 -1
  47. package/{chunk-v6ks5v53.js → chunk-hxk0wkt3.js} +1 -1
  48. package/{chunk-qgbat4fv.js → chunk-jc95phff.js} +2 -2
  49. package/chunk-kwym0g80.js +11 -0
  50. package/chunk-kxcjme3n.js +6 -0
  51. package/{chunk-dy7qwj3t.js → chunk-mkctjrrz.js} +2 -2
  52. package/{chunk-z6r6wxm6.js → chunk-mknhfnkn.js} +1 -1
  53. package/chunk-mseawt58.js +849 -0
  54. package/{chunk-cg0sjdqt.js → chunk-nccfyeyy.js} +1 -1
  55. package/{chunk-c4164x55.js → chunk-npnxs0fy.js} +1 -1
  56. package/{chunk-ffm2jpxp.js → chunk-p9p2vbat.js} +2 -2
  57. package/chunk-pqc7dbhc.js +2 -0
  58. package/{chunk-g3k8k6fq.js → chunk-qc7c328q.js} +1 -1
  59. package/chunk-qe6pp4p6.js +72 -0
  60. package/{chunk-zgwvkgsz.js → chunk-qwy0jba8.js} +1 -1
  61. package/{chunk-mqx96m2g.js → chunk-s26bgjqz.js} +1 -1
  62. package/{chunk-8n07n0cr.js → chunk-s8pqbr4n.js} +2 -2
  63. package/{chunk-p93x4pn2.js → chunk-tjy12q19.js} +1 -1
  64. package/{chunk-cq2q36d1.js → chunk-v1by80c5.js} +1 -1
  65. package/chunk-vdy4ave9.js +2 -0
  66. package/chunk-vwhee991.js +3 -0
  67. package/chunk-wf7r45wh.js +12 -0
  68. package/chunk-x4jsr5et.js +17 -0
  69. package/{chunk-8qf0ne1p.js → chunk-x9gk2n9v.js} +1 -1
  70. package/chunk-xxjevh62.js +2 -0
  71. package/{chunk-s1cwck4c.js → chunk-y2y1b3zm.js} +1 -1
  72. package/chunk-y6jq6y8t.js +2 -0
  73. package/cli.js +1 -1
  74. package/package.json +11 -11
  75. package/pkgs/helpers/src/icon-data.ts +868 -172
  76. package/pkgs/schema/src/index.ts +1 -0
  77. package/pkgs/schema/src/snippet-resolve.ts +43 -0
  78. package/pkgs/shadcn-snapshot/dist/manifest.json +348 -0
  79. package/pkgs/shadcn-snapshot/src/components/canvas-portal.tsx +3 -3
  80. package/plugins/claude/velloo/.claude-plugin/plugin.json +5 -2
  81. package/plugins/gemini/gemini-extension.json +7 -2
  82. package/canvas/assets/index-CcPwhD7W.js +0 -31
  83. package/canvas/assets/index-CkVteRZ9.css +0 -2
  84. package/canvas/assets/lucide-all-Cezxn40A.js +0 -1
  85. package/canvas/assets/radix-gmpYzWRH.js +0 -41
  86. package/canvas/assets/react-D0Ec-185.js +0 -9
  87. package/canvas/assets/rolldown-runtime-hePW80VL.js +0 -1
  88. package/canvas/assets/vendor-CKmQ-Zst.js +0 -53
  89. package/chunk-07fxzrx2.js +0 -40
  90. package/chunk-4g4c9h7k.js +0 -2
  91. package/chunk-6w42sr61.js +0 -6
  92. package/chunk-80fjfyha.js +0 -86
  93. package/chunk-8ztgcajz.js +0 -8
  94. package/chunk-9g45c5md.js +0 -815
  95. package/chunk-b4hny6hw.js +0 -3
  96. package/chunk-bntsn3wj.js +0 -2
  97. package/chunk-djwvt6jx.js +0 -2
  98. package/chunk-dqqpbmxt.js +0 -22
  99. package/chunk-ejpccmcj.js +0 -18
  100. package/chunk-emty5315.js +0 -2
  101. package/chunk-jxgwdz2r.js +0 -5
  102. package/chunk-kvq7pcph.js +0 -2
  103. package/chunk-m0v3d581.js +0 -2
  104. package/chunk-nx0ex7qw.js +0 -2
  105. package/chunk-qqagacne.js +0 -4
  106. package/chunk-qx83fdv2.js +0 -85
  107. package/chunk-r5y1sh4f.js +0 -12
  108. package/chunk-rhfzy9c0.js +0 -2
  109. package/chunk-rrrn1mkq.js +0 -3
  110. package/chunk-sjxp2bx3.js +0 -2
  111. package/chunk-t08391mh.js +0 -3
  112. package/chunk-t61vyqpd.js +0 -2
  113. package/chunk-vbk1qhdz.js +0 -3
  114. package/chunk-x84qrz4q.js +0 -6
  115. package/chunk-xg49s85z.js +0 -1491
  116. package/chunk-xxw67jpk.js +0 -63
  117. package/chunk-yjwtdm71.js +0 -2
@@ -1,5 +1,5 @@
1
1
  // @bun
2
- import{isCancel,confirm,select}from"./chunk-80fjfyha.js";import{capturesDir,sessionStatePath,captureDir,listCaptures,deleteCapture,isSafeCaptureId,HeadedBrowserMissingError,startCaptureSession}from"./chunk-xg49s85z.js";import"./chunk-xxw67jpk.js";import{loadDesignFolder}from"./chunk-9g45c5md.js";import"./chunk-bntsn3wj.js";import{fail}from"./chunk-s23gtejf.js";import{installChromiumInteractive}from"./chunk-dy7qwj3t.js";import{openUrl}from"./chunk-hggap8fq.js";import{DESIGN_ARG_DESCRIPTION,resolveDesign}from"./chunk-6w42sr61.js";import{withSubcommands}from"./chunk-94vx1yb0.js";import{require_picocolors}from"./chunk-jrsknzjt.js";import{__toESM,defineCommand}from"./chunk-2smsg2ct.js";import{join}from"path";var import_picocolors=__toESM(require_picocolors(),1);var CTRL_C=3,LOOPBACK=/^(localhost|127\.0\.0\.1|\[::1\]|::1)(:\d+)?$/i;function normalizeCaptureUrl(input){let raw=input.trim();if(raw==="")return null;let hasScheme=/^[a-z][a-z0-9+.-]*:\/\//i.test(raw),host=raw.split(/[/?#]/,1)[0]??"",candidate=hasScheme?raw:`${LOOPBACK.test(host)?"http":"https"}://${raw}`;try{let url=new URL(candidate);if(url.protocol!=="http:"&&url.protocol!=="https:")return null;if(url.hostname==="")return null;return url.toString()}catch{return null}}function bindKeys(handlers){let stdin=process.stdin;if(!stdin.isTTY)return()=>{};stdin.setRawMode(!0),stdin.resume(),stdin.setEncoding("utf8");let onData=(key)=>{if(key==="c")handlers.page();else if(key==="t")handlers.theme();else if(key==="l")handlers.list();else if(key==="q"||key.charCodeAt(0)===CTRL_C)handlers.quit()};return stdin.on("data",onData),()=>{if(stdin.off("data",onData),stdin.isTTY)stdin.setRawMode(!1);stdin.pause()}}function when(iso){let d=new Date(iso);if(Number.isNaN(d.getTime()))return iso;return d.toLocaleString(void 0,{month:"short",day:"numeric",hour:"2-digit",minute:"2-digit"})}function describe(m){let what=m.themeOnly?"theme only":`${m.nodeCount} nodes, ${m.assetCount} assets`;return`${m.title||m.finalUrl||m.url} ${import_picocolors.default.dim(`\u2014 ${what}, ${when(m.capturedAt)}`)}`}function printCaptures(captures,dir){if(console.log(""),captures.length===0){console.log(import_picocolors.default.dim(" No captures yet. Run `velloo capture <url>` to make one.")),console.log("");return}console.log(` ${import_picocolors.default.bold(`${captures.length} capture${captures.length===1?"":"s"}`)}`),console.log(import_picocolors.default.dim(` ${dir}`)),console.log("");for(let m of captures)console.log(` ${import_picocolors.default.cyan(m.id)} ${describe(m)}`),console.log(import_picocolors.default.dim(` ${m.finalUrl||m.url}`));console.log("")}async function browseCaptures(root,folderId){let dir=capturesDir(root,folderId),captures=listCaptures(root,folderId);if(!process.stdin.isTTY||captures.length===0){printCaptures(captures,dir);return}for(;;){if(captures=listCaptures(root,folderId),captures.length===0){console.log(import_picocolors.default.dim(`
2
+ import{isCancel,confirm,select,DESIGN_ARG_DESCRIPTION,resolveDesign}from"./chunk-qe6pp4p6.js";import{capturesDir,sessionStatePath,captureDir,listCaptures,deleteCapture,isSafeCaptureId,HeadedBrowserMissingError,startCaptureSession}from"./chunk-hhkjqvww.js";import"./chunk-ghwy99py.js";import{loadDesignFolder}from"./chunk-mseawt58.js";import"./chunk-ak57bgnh.js";import{fail}from"./chunk-s23gtejf.js";import{installChromiumInteractive}from"./chunk-mkctjrrz.js";import{openUrl}from"./chunk-hggap8fq.js";import{withSubcommands}from"./chunk-94vx1yb0.js";import{require_picocolors}from"./chunk-jrsknzjt.js";import{__toESM,defineCommand}from"./chunk-2smsg2ct.js";import{join}from"path";var import_picocolors=__toESM(require_picocolors(),1);var CTRL_C=3,LOOPBACK=/^(localhost|127\.0\.0\.1|\[::1\]|::1)(:\d+)?$/i;function normalizeCaptureUrl(input){let raw=input.trim();if(raw==="")return null;let hasScheme=/^[a-z][a-z0-9+.-]*:\/\//i.test(raw),host=raw.split(/[/?#]/,1)[0]??"",candidate=hasScheme?raw:`${LOOPBACK.test(host)?"http":"https"}://${raw}`;try{let url=new URL(candidate);if(url.protocol!=="http:"&&url.protocol!=="https:")return null;if(url.hostname==="")return null;return url.toString()}catch{return null}}function bindKeys(handlers){let stdin=process.stdin;if(!stdin.isTTY)return()=>{};stdin.setRawMode(!0),stdin.resume(),stdin.setEncoding("utf8");let onData=(key)=>{if(key==="c")handlers.page();else if(key==="t")handlers.theme();else if(key==="l")handlers.list();else if(key==="q"||key.charCodeAt(0)===CTRL_C)handlers.quit()};return stdin.on("data",onData),()=>{if(stdin.off("data",onData),stdin.isTTY)stdin.setRawMode(!1);stdin.pause()}}function when(iso){let d=new Date(iso);if(Number.isNaN(d.getTime()))return iso;return d.toLocaleString(void 0,{month:"short",day:"numeric",hour:"2-digit",minute:"2-digit"})}function describe(m){let what=m.themeOnly?"theme only":`${m.nodeCount} nodes, ${m.assetCount} assets`;return`${m.title||m.finalUrl||m.url} ${import_picocolors.default.dim(`\u2014 ${what}, ${when(m.capturedAt)}`)}`}function printCaptures(captures,dir){if(console.log(""),captures.length===0){console.log(import_picocolors.default.dim(" No captures yet. Run `velloo capture <url>` to make one.")),console.log("");return}console.log(` ${import_picocolors.default.bold(`${captures.length} capture${captures.length===1?"":"s"}`)}`),console.log(import_picocolors.default.dim(` ${dir}`)),console.log("");for(let m of captures)console.log(` ${import_picocolors.default.cyan(m.id)} ${describe(m)}`),console.log(import_picocolors.default.dim(` ${m.finalUrl||m.url}`));console.log("")}async function browseCaptures(root,folderId){let dir=capturesDir(root,folderId),captures=listCaptures(root,folderId);if(!process.stdin.isTTY||captures.length===0){printCaptures(captures,dir);return}for(;;){if(captures=listCaptures(root,folderId),captures.length===0){console.log(import_picocolors.default.dim(`
3
3
  No captures left.
4
4
  `));return}let picked=await select({message:`${captures.length} capture${captures.length===1?"":"s"} for this folder`,options:[...captures.map((m)=>({value:m.id,label:describe(m),hint:m.finalUrl||m.url})),{value:"__done",label:import_picocolors.default.dim("Done")}]});if(isCancel(picked)||picked==="__done")return;let manifest=captures.find((m)=>m.id===picked);if(!manifest)continue;let action=await select({message:manifest.title||manifest.id,options:[...manifest.files.includes("page.png")?[{value:"open",label:"Open the screenshot"}]:[],{value:"details",label:"Show what it contains"},{value:"delete",label:import_picocolors.default.red("Delete this capture")},{value:"back",label:import_picocolors.default.dim("Back")}]});if(isCancel(action)||action==="back")continue;if(action==="open"){await openUrl(`file://${join(captureDir(root,manifest.id,folderId),"page.png")}`);continue}if(action==="details"){console.log(""),console.log(` ${import_picocolors.default.bold(manifest.id)}`),console.log(` url ${manifest.finalUrl||manifest.url}`),console.log(` captured ${when(manifest.capturedAt)}`),console.log(` viewport ${manifest.viewport.w}\xD7${manifest.viewport.h}`),console.log(` nodes ${manifest.nodeCount}`),console.log(` assets ${manifest.assetCount}`),console.log(` files ${manifest.files.join(", ")}`),console.log(import_picocolors.default.dim(` ${captureDir(root,manifest.id,folderId)}`)),console.log(""),console.log(import_picocolors.default.dim(` verify a screen against it: compare_to_url { captureId: "${manifest.id}" }`)),console.log("");continue}if(action==="delete"){let sure=await confirm({message:`Delete ${manifest.title||manifest.id}? This can't be undone.`,initialValue:!1});if(isCancel(sure)||!sure)continue;deleteCapture(root,manifest.id,folderId),console.log(import_picocolors.default.dim(` deleted ${manifest.id}`))}}}var DESIGN_FLAG={type:"string",description:DESIGN_ARG_DESCRIPTION};async function captureDesign(arg,command){let design=await loadDesignFolder(await resolveDesign(arg,command,{designFlag:"--design"}));return{root:design.root,folderId:design.config.folderId}}var list=defineCommand({meta:{name:"list",description:"Browse stored captures (interactive on a TTY)"},args:{design:DESIGN_FLAG},async run({args}){let{root,folderId}=await captureDesign(args.design,"capture list");await browseCaptures(root,folderId)}}),remove=defineCommand({meta:{name:"delete",description:"Delete a stored capture, or every capture for the design"},args:{id:{type:"positional",required:!0,description:"The capture id, or `all`"},design:DESIGN_FLAG},async run({args}){let{root,folderId}=await captureDesign(args.design,"capture delete"),id=args.id.trim();if(id==="all"){let all=listCaptures(root,folderId);if(all.length===0){console.log(import_picocolors.default.dim("velloo capture: no captures to delete."));return}if(process.stdin.isTTY){let sure=await confirm({message:`Delete all ${all.length} captures for this design? This can't be undone.`,initialValue:!1});if(isCancel(sure)||!sure){console.log(import_picocolors.default.dim(" nothing deleted."));return}}for(let m of all)deleteCapture(root,m.id,folderId);console.log(`velloo capture: deleted ${all.length} captures.`);return}if(!isSafeCaptureId(id))fail("capture delete",`not a capture id: ${args.id}`);if(!deleteCapture(root,id,folderId))fail("capture delete",`no capture "${id}" for this design \u2014 run \`velloo capture list\`.`);console.log(`velloo capture: deleted ${id}.`)}}),capture=defineCommand({meta:{name:"capture",description:"open a browser, log in, and capture pages as evidence for the agent"},args:{url:{type:"positional",required:!1,description:"Page to open the browser on, e.g. http://localhost:3000/dashboard"},design:DESIGN_FLAG},async run({args}){let{root,folderId}=await captureDesign(args.design,"capture"),url;if(args.url!==void 0){let normalized=normalizeCaptureUrl(args.url);if(normalized===null)fail("capture",`not a page that can be captured: ${args.url} (expected an http(s) URL)`);url=normalized}let statePath=url?sessionStatePath(root,new URL(url).origin,folderId):void 0;console.log(""),console.log(` ${import_picocolors.default.bold("velloo capture")}`),console.log(import_picocolors.default.dim(` A browser window opens. Log in and navigate wherever you need \u2014 then use the
5
5
  `+" velloo toolbar in the page (or the keys below) to capture what the agent should see.")),console.log(""),console.log(import_picocolors.default.dim(` ${import_picocolors.default.cyan("c")} capture page ${import_picocolors.default.cyan("t")} capture theme ${import_picocolors.default.cyan("l")} list ${import_picocolors.default.cyan("q")} done`)),console.log("");let made=[],onCapture=(m)=>{made.push(m);let what=m.themeOnly?"theme":`${m.nodeCount} nodes, ${m.assetCount} assets`;console.log(` ${import_picocolors.default.green("\u2713")} ${m.title||m.url} ${import_picocolors.default.dim(`(${what}) \u2192 ${m.id}`)}`)},start=async()=>startCaptureSession({folderRoot:root,...folderId?{folderId}:{},...url?{url}:{},...statePath?{sessionStatePath:statePath}:{},onCapture,onStatus:(message)=>console.log(import_picocolors.default.dim(` ${message}`))}),session;try{session=await start()}catch(err){if(!(err instanceof HeadedBrowserMissingError))throw err;if(!process.stdin.isTTY)fail("capture",err.message);console.log(""),console.log(` ${import_picocolors.default.yellow("\u26A0")} ${err.message}`);let proceed=await confirm({message:"Download the full browser now? (~300MB, one-time)",initialValue:!0});if(isCancel(proceed)||!proceed)fail("capture","no browser available for a capture session.");if(!await installChromiumInteractive())fail("capture","the browser isn't usable yet \u2014 see the output above.");session=await start()}let report=(e)=>{console.log(import_picocolors.default.red(` capture failed: ${e instanceof Error?e.message:String(e)}`))},unbind=bindKeys({page:()=>{session.capturePage().catch(report)},theme:()=>{session.captureTheme().catch(report)},list:()=>{if(console.log(import_picocolors.default.dim(` on: ${session.currentUrl()||"(no page)"}`)),made.length===0)console.log(import_picocolors.default.dim(" nothing captured yet"));for(let m of made)console.log(import_picocolors.default.dim(` ${m.id} ${m.title||m.url}`))},quit:()=>{session.close()}});if(await session.finished,unbind(),console.log(""),made.length===0)console.log(` ${import_picocolors.default.dim("No captures made.")}`);else console.log(` ${import_picocolors.default.green("\u2713")} ${made.length} capture${made.length===1?"":"s"} saved`),console.log(import_picocolors.default.dim(` ${capturesDir(root,folderId)}`)),console.log(""),console.log(import_picocolors.default.dim(" The agent can read these with list_captures / get_capture,")),console.log(import_picocolors.default.dim(" and verify a screen against one with compare_to_url { captureId }."));if(statePath)console.log(""),console.log(import_picocolors.default.dim(" Session cookies for this app were saved to:")),console.log(import_picocolors.default.dim(` ${statePath}`)),console.log(import_picocolors.default.dim(` Scoped to that site only (third-party sign-in cookies are dropped), outside your
@@ -0,0 +1,2 @@
1
+ // @bun
2
+ import{recordedDesignName}from"./chunk-mseawt58.js";import"./chunk-ghwy99py.js";import"./chunk-hhkjqvww.js";import"./chunk-ak57bgnh.js";import"./chunk-d6a6198y.js";import{assertLoopbackHost,daemonRoot,isLive,ensureDaemon,stopDaemon}from"./chunk-jc95phff.js";import{findDesigns,DESIGN_ARG_DESCRIPTION,resolveDesign}from"./chunk-qe6pp4p6.js";import{fail}from"./chunk-s23gtejf.js";import"./chunk-tjy12q19.js";import"./chunk-75gfv9g4.js";import{openUrl}from"./chunk-hggap8fq.js";import{createProgress}from"./chunk-fzevxpdz.js";import{designWithFolder}from"./chunk-v1by80c5.js";import"./chunk-mknhfnkn.js";import"./chunk-5ts4fvd9.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};
package/cli.js CHANGED
@@ -1,3 +1,3 @@
1
1
  #!/usr/bin/env bun
2
2
  // @bun
3
- import"./chunk-s23gtejf.js";import{COMMANDS}from"./chunk-32cq4wpr.js";import{TOOL_VERSION}from"./chunk-rrrn1mkq.js";import{maybeNotifyAboutUpdate}from"./chunk-d19ttv1a.js";import{defineCommand,runMain}from"./chunk-2smsg2ct.js";var main=defineCommand({meta:{name:"velloo",version:TOOL_VERSION,description:"Open-source, local-first canvas for agent-driven design."},subCommands:COMMANDS});await runMain(main);var command=process.argv[2];if(!["mcp","__daemon","__update_check","run","upgrade"].includes(command??""))await maybeNotifyAboutUpdate();
3
+ import"./chunk-s23gtejf.js";import{COMMANDS}from"./chunk-0rvdh1j3.js";import{TOOL_VERSION}from"./chunk-d6a6198y.js";import{maybeNotifyAboutUpdate}from"./chunk-hrvqwp8z.js";import{defineCommand,runMain}from"./chunk-2smsg2ct.js";var main=defineCommand({meta:{name:"velloo",version:TOOL_VERSION,description:"Open-source, local-first canvas for agent-driven design."},subCommands:COMMANDS});await runMain(main);var command=process.argv[2];if(!["mcp","__daemon","__update_check","run","upgrade"].includes(command??""))await maybeNotifyAboutUpdate();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "velloo",
3
- "version": "0.8.0",
3
+ "version": "0.10.0",
4
4
  "type": "module",
5
5
  "description": "Local-first, code-shaped design canvas — your AI agent designs with your real components, in your repo",
6
6
  "license": "Apache-2.0",
@@ -48,19 +48,19 @@
48
48
  "@tailwindcss/node": "4.3.3",
49
49
  "@tailwindcss/oxide": "4.3.3",
50
50
  "clsx": "2.1.1",
51
- "playwright-core": "1.62.1",
52
- "tailwind-merge": "3.6.0",
51
+ "playwright-core": "1.64.1",
52
+ "tailwind-merge": "3.7.0",
53
53
  "tailwindcss": "4.3.3",
54
54
  "tw-animate-css": "1.4.0"
55
55
  },
56
56
  "optionalDependencies": {
57
- "@oven/bun-darwin-aarch64": "1.4.2",
58
- "@oven/bun-darwin-x64-baseline": "1.4.2",
59
- "@oven/bun-linux-aarch64": "1.4.2",
60
- "@oven/bun-linux-aarch64-musl": "1.4.2",
61
- "@oven/bun-linux-x64-baseline": "1.4.2",
62
- "@oven/bun-linux-x64-musl-baseline": "1.4.2",
63
- "@oven/bun-windows-aarch64": "1.4.2",
64
- "@oven/bun-windows-x64-baseline": "1.4.2"
57
+ "@oven/bun-darwin-aarch64": "1.4.3",
58
+ "@oven/bun-darwin-x64-baseline": "1.4.3",
59
+ "@oven/bun-linux-aarch64": "1.4.3",
60
+ "@oven/bun-linux-aarch64-musl": "1.4.3",
61
+ "@oven/bun-linux-x64-baseline": "1.4.3",
62
+ "@oven/bun-linux-x64-musl-baseline": "1.4.3",
63
+ "@oven/bun-windows-aarch64": "1.4.3",
64
+ "@oven/bun-windows-x64-baseline": "1.4.3"
65
65
  }
66
66
  }