@zenovay/cli 0.1.7 → 0.1.8

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 (33) hide show
  1. package/dist/ai-BURm2MXB.js +11 -0
  2. package/dist/{analytical-screen-CS1ZL5Mo.js → analytical-screen-CdtZfbes.js} +1 -1
  3. package/dist/bin.js +1 -1
  4. package/dist/{companies-DjAmRDgx.js → companies-DerPI17Z.js} +1 -1
  5. package/dist/{deploys-CJVuTUqN.js → deploys-CfM6V_66.js} +1 -1
  6. package/dist/{doctor-CAFnE0Gm.js → doctor-WVkPGXJ7.js} +1 -1
  7. package/dist/{emit-DIRc7UzM.js → emit-0WJ_OGeT.js} +1 -1
  8. package/dist/{errors-DYLYIh2G.js → errors-BycEZviU.js} +1 -1
  9. package/dist/{events-tail-Bun9hEoz.js → events-tail-Bwgx_AgB.js} +1 -1
  10. package/dist/{funnel-KSMIsBXC.js → funnel-DkfVTEfJ.js} +1 -1
  11. package/dist/{health-CN35NYhE.js → health-BFF0dghf.js} +1 -1
  12. package/dist/{health-C6G6Mg6b.js → health-Dxmho1lB.js} +1 -1
  13. package/dist/init-CU_fEq2x.js +61 -0
  14. package/dist/init-DlfdHqEi.js +1 -0
  15. package/dist/{login-CxXnVN9s.js → login--p3mI2F6.js} +1 -1
  16. package/dist/login-DjYNTtGG.js +1 -0
  17. package/dist/{logout-2-GHLeZO.js → logout-Cf4_khj0.js} +1 -1
  18. package/dist/{projects-907FoPAg.js → projects-CSm0bMWz.js} +1 -1
  19. package/dist/{query-Bj9z5qK1.js → query-DrnUU6fc.js} +1 -1
  20. package/dist/{revenue-BdxoWU-f.js → revenue-y13ZDPfc.js} +1 -1
  21. package/dist/{sources-vI6GlYbS.js → sources-D_OWPKOb.js} +1 -1
  22. package/dist/{stats-BC2f1pG_.js → stats-CyWREh45.js} +1 -1
  23. package/dist/{update-BPa-ewQo.js → update-2SafBiSk.js} +1 -1
  24. package/dist/{vitals-C1c_KHq2.js → vitals-Bx1cVV2p.js} +1 -1
  25. package/dist/{watch-BMpFFzEj.js → watch-CFkeo8J8.js} +1 -1
  26. package/dist/wizard-bin.js +1 -1
  27. package/package.json +1 -1
  28. package/dist/ai-UzRL3dew.js +0 -11
  29. package/dist/init-B_nZyv9Q.js +0 -61
  30. package/dist/init-DPyKsF9Y.js +0 -1
  31. package/dist/login-CgIfUP2O.js +0 -1
  32. /package/dist/{client-Bc1xZcH_.js → client-DZ4Awt8u.js} +0 -0
  33. /package/dist/{formatter-DQ6l4sWM.js → formatter-45-fT1Hv.js} +0 -0
@@ -0,0 +1,11 @@
1
+ import{readConfig as e}from"./config-ZTGpKEWg.js";import{ApiClient as t,readToken as n}from"./api-D5XQeEDF.js";import{detectInstalled as r,initCommand as i}from"./init-CU_fEq2x.js";import{parseSseStream as a}from"./client-DZ4Awt8u.js";import"./formatter-45-fT1Hv.js";import{emit as o,isHeadless as s}from"./emit-0WJ_OGeT.js";import"./login--p3mI2F6.js";import{Panel as c}from"./panel-DglZ755S.js";import"./keybar-D2OI-8rx.js";import{Select as l}from"./prompt-hjzdzlyj.js";import"./sparkline-CR_bzxwB.js";import{Box as u,Text as d,render as f}from"ink";import p from"react";async function m(e){let t=await r(e.cwd),n;if(e.mode)n=e.mode;else if(!t.installed)n=`install`;else if(s(e))return o({type:`error`,code:`no_mode`,message:`Headless mode requires --mode chat|mcp|install`}),2;else n=await h(t);return n===`install`?i({cliVersion:e.cliVersion,cwd:e.cwd,json:e.json}):n===`chat`?g(e):_(e)}async function h(e){return new Promise(t=>{let n=[{label:`Chat with your analytics`,value:`chat`,description:`Ask natural-language questions about your data`},{label:`Manage via MCP`,value:`mcp`,description:`Create goals, funnels, sites, etc. in plain English`},{label:`Re-run install / repair`,value:`install`,description:`Run the install wizard again`}],{unmount:r}=f(p.createElement(u,{flexDirection:`column`},p.createElement(c,{title:`Zenovay detected${e.packageMarker?` (${e.packageMarker})`:``}`,state:`idle`},p.createElement(d,null,`What do you want to do?`)),p.createElement(l,{items:n,onSelect:e=>{r(),t(e)}})))})}async function g(r){let i=await e(),o=await n({strict:!1});if(!o)return process.stderr.write("Not logged in — run `zenovay login` first.\n"),2;let s=new t({config:i,cliVersion:r.cliVersion,token:o});process.stdout.write(`
2
+ Zenovay · chat mode — type your question then press Enter. Ctrl-C to exit.
3
+
4
+ > `);let c=await v();if(!c)return 0;let l=await s.openAiStream(`chat`,{messages:[{role:`user`,content:c}]});for await(let e of a(l)){if(e.type===`delta`&&process.stdout.write(e.content),e.type===`done`){process.stdout.write(`
5
+ `);break}if(e.type===`error`)return process.stderr.write(`\n[${e.code}] ${e.message}\n`),1}return 0}async function _(r){let i=await e(),o=await n({strict:!1});if(!o)return process.stderr.write("Not logged in — run `zenovay login` first.\n"),2;let s=new t({config:i,cliVersion:r.cliVersion,token:o});process.stdout.write(`
6
+ Zenovay · MCP mode — describe what you want to create or change. Ctrl-C to exit.
7
+
8
+ > `);let c=await v();if(!c)return 0;let l=await s.openAiStream(`mcp`,{messages:[{role:`user`,content:c}]});for await(let e of a(l)){if(e.type===`delta`&&process.stdout.write(e.content),e.type===`tool_start`&&process.stdout.write(`\n[tool: ${e.name}] `),e.type===`tool_result`&&process.stdout.write(`
9
+ [result]`),e.type===`done`){process.stdout.write(`
10
+ `);break}if(e.type===`error`)return process.stderr.write(`\n[${e.code}] ${e.message}\n`),1}return 0}function v(){return new Promise(e=>{let t=``,n=r=>{let i=r.toString(`utf8`);i.includes(`
11
+ `)||i.includes(`\r`)?(t+=i.replace(/[\r\n]/g,``),process.stdin.off(`data`,n),process.stdin.pause(),e(t)):t+=i};process.stdin.resume(),process.stdin.on(`data`,n)})}export{m as aiCommand};
@@ -1 +1 @@
1
- import{ApiError as e}from"./api-D5XQeEDF.js";import{formatEvent as t}from"./formatter-DQ6l4sWM.js";import{Panel as n}from"./panel-DglZ755S.js";import{Banner as r,Keybar as i}from"./keybar-D2OI-8rx.js";import{Box as a,Text as o,render as s,useApp as c,useInput as l}from"ink";import u,{useEffect as d,useMemo as f,useReducer as p,useRef as m}from"react";import h from"ink-spinner";function g(e,t){switch(t.type){case`set`:return{...e,data:t.data,status:`ready`,error:null};case`merge`:{let n=e.data?{...e.data,...t.partial}:t.partial;return{...e,data:n,status:`ready`,error:null}}case`error`:return{...e,status:`error`,error:{message:t.message,status:t.status,upgradeUrl:t.upgradeUrl}};case`refresh`:return{...e,refreshTick:e.refreshTick+1};case`focus`:return{...e,focusIndex:t.index};case`help-toggle`:return{...e,showHelp:!e.showHelp};default:return e}}async function _(e,n){let r=new AbortController,i=()=>r.abort();process.on(`SIGINT`,i);try{let i=await e.fetcher(r.signal);if(e.headlessEmit?e.headlessEmit(i,n):process.stdout.write(t(i,n)),e.streamer)for await(let i of e.streamer(r.signal))process.stdout.write(t(i,n));return 0}catch(e){if(e.name===`AbortError`)return 0;let t=e.message;return process.stderr.write(`${t}\n`),1}finally{process.off(`SIGINT`,i)}}const v=({cliVersion:e})=>u.createElement(a,{flexDirection:`column`},u.createElement(r,{version:e,subtitle:`login required`}),u.createElement(n,{title:`Not logged in`,state:`warn`},u.createElement(o,null,`You need to authenticate before running this command.`),u.createElement(o,null,` `),u.createElement(o,{color:`gray`},`Run `),u.createElement(o,{color:`cyan`},`zenovay login`),u.createElement(o,{color:`gray`},` to start the device-flow.`)));function y(t){let{exit:s}=c(),[_,v]=p(g,{data:null,status:`loading`,error:null,refreshTick:0,focusIndex:0,showHelp:!1}),y=m(v);y.current=v;let b=f(()=>({q:{label:`quit`,handler:()=>{s(),t.onExit(0)}},r:{label:`refresh`,handler:()=>y.current({type:`refresh`})},"?":{label:`help`,handler:()=>y.current({type:`help-toggle`})}}),[s,t]),x=f(()=>({...t.keybindings??{},...b}),[t.keybindings,b]);if(l((e,n)=>{if(n.tab&&n.shift){v({type:`focus`,index:(_.focusIndex-1+t.panels.length)%t.panels.length});return}if(n.tab){v({type:`focus`,index:(_.focusIndex+1)%t.panels.length});return}if(e>=`1`&&e<=`9`){let n=Number(e)-1;n<t.panels.length&&v({type:`focus`,index:n});return}let r=x[e];r&&r.handler()}),d(()=>{let n=new AbortController,r=!1,i=async()=>{try{let e=await t.fetcher(n.signal);r||y.current({type:`set`,data:e})}catch(t){if(r)return;if(t instanceof e){if(t.status===402){let e=t.body,n=typeof e==`object`&&e&&`upgradeUrl`in e?e.upgradeUrl:void 0;y.current({type:`error`,message:`This command requires a higher plan.`,status:402,upgradeUrl:n});return}y.current({type:`error`,message:t.message,status:t.status});return}if(t.name===`AbortError`)return;y.current({type:`error`,message:t.message})}};i();let a=null,o=t.refreshIntervalMs??15e3;return o>0&&!t.streamer&&(a=setInterval(i,o)),()=>{r=!0,n.abort(),a&&clearInterval(a)}},[t.fetcher,t.refreshIntervalMs,t.streamer,_.refreshTick]),d(()=>{if(!t.streamer)return;let e=new AbortController,n=!1;return(async()=>{try{for await(let r of t.streamer(e.signal)){if(n)return;y.current({type:`merge`,partial:r})}}catch(e){if(n||e.name===`AbortError`)return;y.current({type:`error`,message:e.message})}})(),()=>{n=!0,e.abort()}},[t.streamer]),_.status===`loading`&&_.data===null)return u.createElement(a,{flexDirection:`column`},u.createElement(r,{version:t.cliVersion,subtitle:t.title}),u.createElement(n,{title:`Loading`,state:`busy`},u.createElement(a,null,u.createElement(o,{color:`magenta`},u.createElement(h,{type:`dots`})),u.createElement(o,null,` Fetching `,t.commandName,`…`))),u.createElement(i,{items:[{key:`q`,label:`quit`}]}));if(_.status===`error`&&_.error){let e=_.error.status===402;return u.createElement(a,{flexDirection:`column`},u.createElement(r,{version:t.cliVersion,subtitle:t.title}),u.createElement(n,{title:e?`Upgrade required`:`Error`,state:e?`warn`:`err`},u.createElement(o,{color:e?`yellow`:`red`},_.error.message),e&&_.error.upgradeUrl?u.createElement(u.Fragment,null,u.createElement(o,null,` `),u.createElement(o,{color:`gray`},`Upgrade: `),u.createElement(o,{color:`cyan`},_.error.upgradeUrl)):null),u.createElement(i,{items:[{key:`r`,label:`retry`},{key:`q`,label:`quit`}]}))}let S=_.data,C=Object.entries(x).map(([e,t])=>({key:e,label:t.label})),w=Math.ceil(t.panels.length/2),T=t.panels.slice(0,w),E=t.panels.slice(w);return u.createElement(a,{flexDirection:`column`},u.createElement(r,{version:t.cliVersion,subtitle:t.title}),u.createElement(a,{flexDirection:`row`},T.map((e,t)=>{let r=_.focusIndex===t;return u.createElement(a,{key:e.id,flexDirection:`column`,marginRight:1,flexGrow:1},u.createElement(n,{title:e.title,state:r?`busy`:`idle`},e.render(S,r)))})),E.length>0?u.createElement(a,{flexDirection:`row`},E.map((e,t)=>{let r=t+w,i=_.focusIndex===r;return u.createElement(a,{key:e.id,flexDirection:`column`,marginRight:1,flexGrow:1},u.createElement(n,{title:e.title,state:i?`busy`:`idle`},e.render(S,i)))})):null,_.showHelp?u.createElement(n,{title:`Help`,state:`idle`},Object.entries(x).map(([e,t])=>u.createElement(o,{key:e},`[`,e,`] `,t.label)),u.createElement(o,{color:`gray`},`[tab/shift+tab] cycle focus [1-9] focus panel`)):null,u.createElement(i,{items:C}))}async function b(e){return e.authToken===null?e.format?(process.stderr.write("Not logged in — run `zenovay login` first.\n"),2):new Promise(t=>{let{unmount:n}=s(u.createElement(v,{cliVersion:e.cliVersion}));setTimeout(()=>{n(),t(2)},50)}):e.format?_(e,e.format):new Promise(t=>{let{unmount:n}=s(u.createElement(y,{...e,onExit:e=>{n(),t(e)}}))})}export{b as runAnalyticalScreen};
1
+ import{ApiError as e}from"./api-D5XQeEDF.js";import{formatEvent as t}from"./formatter-45-fT1Hv.js";import{Panel as n}from"./panel-DglZ755S.js";import{Banner as r,Keybar as i}from"./keybar-D2OI-8rx.js";import{Box as a,Text as o,render as s,useApp as c,useInput as l}from"ink";import u,{useEffect as d,useMemo as f,useReducer as p,useRef as m}from"react";import h from"ink-spinner";function g(e,t){switch(t.type){case`set`:return{...e,data:t.data,status:`ready`,error:null};case`merge`:{let n=e.data?{...e.data,...t.partial}:t.partial;return{...e,data:n,status:`ready`,error:null}}case`error`:return{...e,status:`error`,error:{message:t.message,status:t.status,upgradeUrl:t.upgradeUrl}};case`refresh`:return{...e,refreshTick:e.refreshTick+1};case`focus`:return{...e,focusIndex:t.index};case`help-toggle`:return{...e,showHelp:!e.showHelp};default:return e}}async function _(e,n){let r=new AbortController,i=()=>r.abort();process.on(`SIGINT`,i);try{let i=await e.fetcher(r.signal);if(e.headlessEmit?e.headlessEmit(i,n):process.stdout.write(t(i,n)),e.streamer)for await(let i of e.streamer(r.signal))process.stdout.write(t(i,n));return 0}catch(e){if(e.name===`AbortError`)return 0;let t=e.message;return process.stderr.write(`${t}\n`),1}finally{process.off(`SIGINT`,i)}}const v=({cliVersion:e})=>u.createElement(a,{flexDirection:`column`},u.createElement(r,{version:e,subtitle:`login required`}),u.createElement(n,{title:`Not logged in`,state:`warn`},u.createElement(o,null,`You need to authenticate before running this command.`),u.createElement(o,null,` `),u.createElement(o,{color:`gray`},`Run `),u.createElement(o,{color:`cyan`},`zenovay login`),u.createElement(o,{color:`gray`},` to start the device-flow.`)));function y(t){let{exit:s}=c(),[_,v]=p(g,{data:null,status:`loading`,error:null,refreshTick:0,focusIndex:0,showHelp:!1}),y=m(v);y.current=v;let b=f(()=>({q:{label:`quit`,handler:()=>{s(),t.onExit(0)}},r:{label:`refresh`,handler:()=>y.current({type:`refresh`})},"?":{label:`help`,handler:()=>y.current({type:`help-toggle`})}}),[s,t]),x=f(()=>({...t.keybindings??{},...b}),[t.keybindings,b]);if(l((e,n)=>{if(n.tab&&n.shift){v({type:`focus`,index:(_.focusIndex-1+t.panels.length)%t.panels.length});return}if(n.tab){v({type:`focus`,index:(_.focusIndex+1)%t.panels.length});return}if(e>=`1`&&e<=`9`){let n=Number(e)-1;n<t.panels.length&&v({type:`focus`,index:n});return}let r=x[e];r&&r.handler()}),d(()=>{let n=new AbortController,r=!1,i=async()=>{try{let e=await t.fetcher(n.signal);r||y.current({type:`set`,data:e})}catch(t){if(r)return;if(t instanceof e){if(t.status===402){let e=t.body,n=typeof e==`object`&&e&&`upgradeUrl`in e?e.upgradeUrl:void 0;y.current({type:`error`,message:`This command requires a higher plan.`,status:402,upgradeUrl:n});return}y.current({type:`error`,message:t.message,status:t.status});return}if(t.name===`AbortError`)return;y.current({type:`error`,message:t.message})}};i();let a=null,o=t.refreshIntervalMs??15e3;return o>0&&!t.streamer&&(a=setInterval(i,o)),()=>{r=!0,n.abort(),a&&clearInterval(a)}},[t.fetcher,t.refreshIntervalMs,t.streamer,_.refreshTick]),d(()=>{if(!t.streamer)return;let e=new AbortController,n=!1;return(async()=>{try{for await(let r of t.streamer(e.signal)){if(n)return;y.current({type:`merge`,partial:r})}}catch(e){if(n||e.name===`AbortError`)return;y.current({type:`error`,message:e.message})}})(),()=>{n=!0,e.abort()}},[t.streamer]),_.status===`loading`&&_.data===null)return u.createElement(a,{flexDirection:`column`},u.createElement(r,{version:t.cliVersion,subtitle:t.title}),u.createElement(n,{title:`Loading`,state:`busy`},u.createElement(a,null,u.createElement(o,{color:`magenta`},u.createElement(h,{type:`dots`})),u.createElement(o,null,` Fetching `,t.commandName,`…`))),u.createElement(i,{items:[{key:`q`,label:`quit`}]}));if(_.status===`error`&&_.error){let e=_.error.status===402;return u.createElement(a,{flexDirection:`column`},u.createElement(r,{version:t.cliVersion,subtitle:t.title}),u.createElement(n,{title:e?`Upgrade required`:`Error`,state:e?`warn`:`err`},u.createElement(o,{color:e?`yellow`:`red`},_.error.message),e&&_.error.upgradeUrl?u.createElement(u.Fragment,null,u.createElement(o,null,` `),u.createElement(o,{color:`gray`},`Upgrade: `),u.createElement(o,{color:`cyan`},_.error.upgradeUrl)):null),u.createElement(i,{items:[{key:`r`,label:`retry`},{key:`q`,label:`quit`}]}))}let S=_.data,C=Object.entries(x).map(([e,t])=>({key:e,label:t.label})),w=Math.ceil(t.panels.length/2),T=t.panels.slice(0,w),E=t.panels.slice(w);return u.createElement(a,{flexDirection:`column`},u.createElement(r,{version:t.cliVersion,subtitle:t.title}),u.createElement(a,{flexDirection:`row`},T.map((e,t)=>{let r=_.focusIndex===t;return u.createElement(a,{key:e.id,flexDirection:`column`,marginRight:1,flexGrow:1},u.createElement(n,{title:e.title,state:r?`busy`:`idle`},e.render(S,r)))})),E.length>0?u.createElement(a,{flexDirection:`row`},E.map((e,t)=>{let r=t+w,i=_.focusIndex===r;return u.createElement(a,{key:e.id,flexDirection:`column`,marginRight:1,flexGrow:1},u.createElement(n,{title:e.title,state:i?`busy`:`idle`},e.render(S,i)))})):null,_.showHelp?u.createElement(n,{title:`Help`,state:`idle`},Object.entries(x).map(([e,t])=>u.createElement(o,{key:e},`[`,e,`] `,t.label)),u.createElement(o,{color:`gray`},`[tab/shift+tab] cycle focus [1-9] focus panel`)):null,u.createElement(i,{items:C}))}async function b(e){return e.authToken===null?e.format?(process.stderr.write("Not logged in — run `zenovay login` first.\n"),2):new Promise(t=>{let{unmount:n}=s(u.createElement(v,{cliVersion:e.cliVersion}));setTimeout(()=>{n(),t(2)},50)}):e.format?_(e,e.format):new Promise(t=>{let{unmount:n}=s(u.createElement(y,{...e,onExit:e=>{n(),t(e)}}))})}export{b as runAnalyticalScreen};
package/dist/bin.js CHANGED
@@ -1,2 +1,2 @@
1
1
  #!/usr/bin/env node
2
- import{cac as e}from"cac";import{fork as t}from"node:child_process";import n from"node:path";import{fileURLToPath as r}from"node:url";import{readFileSync as i}from"node:fs";const a=n.dirname(r(import.meta.url)),o=n.join(a,`..`,`package.json`),s=JSON.parse(i(o,`utf8`)),c=s.version,l=process.argv[0]??`zenovay`;function u(){if(!(process.env.ZENOVAY_NO_UPDATE_CHECK===`1`||process.env.CI===`true`))try{let e=n.join(a,`lib`,`update`,`worker.js`),r=t(e,[],{detached:!0,stdio:`ignore`});r.unref()}catch{}}const d=e(`zenovay`);d.version(c),d.help(),d.command(`init`,`AI install wizard — add Zenovay tracking to your codebase`).option(`--json`,`Emit NDJSON events to stdout`).option(`--yes`,`Auto-approve all diffs (for CI)`).option(`--skip-mcp`,`Skip MCP client install`).option(`--skip-verify`,`Skip first-event verification`).action(async e=>{let{initCommand:t}=await import(`./init-DPyKsF9Y.js`),n=await t({cliVersion:c,cwd:process.cwd(),json:e.json,yes:e.yes,skipMcp:e.skipMcp,skipVerify:e.skipVerify});process.exitCode=n}),d.command(`login`,`Authenticate via OAuth device flow`).option(`--json`,`Emit NDJSON events`).option(`--no-browser`,`Skip opening the browser automatically`).action(async e=>{let{loginCommand:t}=await import(`./login-CgIfUP2O.js`);await t({cliVersion:c,json:e.json,openBrowser:e.browser!==!1,onCode:e=>{process.stdout.write(`\n Open this URL to authorize the CLI:\n ${e.verificationUriComplete??e.verificationUri}\n Or enter code: ${e.userCode}\n\n`)}})}),d.command(`logout`,`Revoke current session and delete local auth`).option(`--json`,``).action(async e=>{let{logoutCommand:t}=await import(`./logout-2-GHLeZO.js`);await t({cliVersion:c,json:e.json})}),d.command(`ai`,`3-mode AI assistant (install / chat / mcp)`).option(`--mode <mode>`,`install | chat | mcp`).option(`--json`,``).action(async e=>{let{aiCommand:t}=await import(`./ai-UzRL3dew.js`),n=await t({cliVersion:c,cwd:process.cwd(),mode:e.mode,json:e.json});process.exitCode=n}),d.command(`watch`,`Live TUI dashboard`).option(`--site-id <id>`,`Site ID`).option(`--interval <ms>`,`Poll interval ms`,{default:15e3}).option(`--json`,``).action(async e=>{let{watchCommand:t}=await import(`./watch-BMpFFzEj.js`),n=await t({cliVersion:c,siteId:e.siteId,intervalMs:Number(e.interval),json:e.json});process.exitCode=n}),d.command(`events tail`,`Stream live events`).option(`--site-id <id>`,`Site ID`,{default:``}).option(`--filter <expr>`,`Filter expression (e.g. 'type=pageview AND country=US')`).option(`--forward-to <url>`,`POST each event to a webhook with HMAC-SHA256 signature`).option(`--replay-24h`,`Replay the last 24h before going live`).option(`--set-forward-secret <hex>`,`Persist the HMAC secret used by --forward-to`).option(`--json`,``).action(async e=>{let{eventsTailCommand:t}=await import(`./events-tail-Bun9hEoz.js`),n=await t({cliVersion:c,siteId:e.siteId,json:e.json,filter:e.filter,forwardTo:e.forwardTo,replay24h:e.replay24h,setForwardSecret:e.setForwardSecret});process.exitCode=n}),d.command(`health`,`Run self-diagnostic checks`).option(`--json`,``).action(async e=>{let{healthCommand:t}=await import(`./health-CN35NYhE.js`),n=await t({cliVersion:c,binaryPath:l,json:e.json});process.exitCode=n}),d.command(`doctor`,`AI-assisted self-healing`).option(`--json`,``).action(async e=>{let{doctorCommand:t}=await import(`./doctor-CAFnE0Gm.js`),n=await t({cliVersion:c,binaryPath:l,json:e.json});process.exitCode=n}),d.command(`stats`,`One-shot dashboard summary (scriptable by default)`).option(`--site-id <id>`,`Site ID`).option(`--range <range>`,`Time range: 24h | 7d | 30d`,{default:`24h`}).option(`--watch`,`Auto-refresh every 60s`).option(`--json`,``).option(`--csv`,``).option(`--tsv`,``).option(`--ndjson`,``).action(async e=>{let{statsCommand:t}=await import(`./stats-BC2f1pG_.js`),n=await t({cliVersion:c,siteId:e.siteId,range:e.range,watch:e.watch,json:e.json,csv:e.csv,tsv:e.tsv,ndjson:e.ndjson});process.exitCode=n}),d.command(`sources`,`Traffic source breakdown with delta arrows`).option(`--site-id <id>`,`Site ID`).option(`--period <p>`,`Period: 7d | 30d | 90d | 1y`,{default:`30d`}).option(`--compare <c>`,`Comparison window (use "prev" for period-over-period)`).option(`--json`,``).option(`--csv`,``).option(`--tsv`,``).option(`--ndjson`,``).action(async e=>{let{sourcesCommand:t}=await import(`./sources-vI6GlYbS.js`),n=await t({cliVersion:c,siteId:e.siteId,period:e.period,compare:e.compare,json:e.json,csv:e.csv,tsv:e.tsv,ndjson:e.ndjson});process.exitCode=n}),d.command(`vitals`,`Core Web Vitals dashboard (LCP / INP / CLS / TTFB / FCP)`).option(`--site-id <id>`,`Site ID`).option(`--url <path>`,`Filter to a single URL`).option(`--device <type>`,`Filter by device: mobile | desktop`).option(`--window <w>`,`Time window: 24h | 7d | 30d | 90d`,{default:`7d`}).option(`--watch`,`Auto-refresh every 5 minutes`).option(`--json`,``).option(`--csv`,``).option(`--tsv`,``).option(`--ndjson`,``).action(async e=>{let{vitalsCommand:t}=await import(`./vitals-C1c_KHq2.js`),n=await t({cliVersion:c,siteId:e.siteId,url:e.url,device:e.device,window:e.window,watch:e.watch,json:e.json,csv:e.csv,tsv:e.tsv,ndjson:e.ndjson});process.exitCode=n}),d.command(`revenue`,`MRR / ARR / transaction series`).option(`--site-id <id>`,`Site ID`).option(`--range <r>`,`Time range: 24h | 7d | 30d | 1y`,{default:`30d`}).option(`--watch`,`Auto-refresh every 5 minutes`).option(`--json`,``).option(`--csv`,``).option(`--tsv`,``).option(`--ndjson`,``).action(async e=>{let{revenueCommand:t}=await import(`./revenue-BdxoWU-f.js`),n=await t({cliVersion:c,siteId:e.siteId,range:e.range,watch:e.watch,json:e.json,csv:e.csv,tsv:e.tsv,ndjson:e.ndjson});process.exitCode=n}),d.command(`funnels`,`List available funnels`).option(`--site-id <id>`,`Site ID`).option(`--json`,``).option(`--csv`,``).option(`--tsv`,``).option(`--ndjson`,``).action(async e=>{let{funnelCommand:t}=await import(`./funnel-KSMIsBXC.js`),n=await t({cliVersion:c,siteId:e.siteId,json:e.json,csv:e.csv,tsv:e.tsv,ndjson:e.ndjson});process.exitCode=n}),d.command(`themes`,`List available themes with colored swatches`).option(`--validate <path>`,`Validate a custom theme JSON file`).option(`--json`,`Emit themes JSON to stdout`).action(async e=>{let{themesCommand:t}=await import(`./themes-F-HUBXpr.js`),n=await t({cliVersion:c,validate:e.validate,json:e.json});process.exitCode=n}),d.command(`completions [shell]`,`Emit shell-completion script (bash | zsh | fish | nushell | pwsh)`).option(`--list`,`List supported shells`).action(async(e,t)=>{let{completionsCommand:n}=await import(`./completions-GDtTbG3B.js`),r=await n({shell:e,list:t.list});process.exitCode=r}),d.command(`query [sql]`,`Restricted SQL REPL over the analytics schema (Scale+)`).option(`--site-id <id>`,`Site ID`).option(`--max-rows <n>`,`Cap result row count`,{default:1e3}).option(`--json`,``).option(`--csv`,``).option(`--tsv`,``).option(`--ndjson`,``).action(async(e,t)=>{let{queryCommand:n}=await import(`./query-Bj9z5qK1.js`),r=await n({cliVersion:c,siteId:t.siteId,sql:e,maxRows:typeof t.maxRows==`string`?Number(t.maxRows):t.maxRows,json:t.json,csv:t.csv,tsv:t.tsv,ndjson:t.ndjson});process.exitCode=r}),d.command(`companies`,`B2B identification feed (Scale+)`).option(`--site-id <id>`,`Site ID`).option(`--window <w>`,`Time window: 24h | 7d | 30d | 90d`,{default:`24h`}).option(`--limit <n>`,`Max rows`,{default:100}).option(`--new-only`,`Show only newly identified companies (first-seen in last hour)`).option(`--watch`,`Auto-refresh every 30s`).option(`--json`,``).option(`--csv`,``).option(`--tsv`,``).option(`--ndjson`,``).action(async e=>{let{companiesCommand:t}=await import(`./companies-DjAmRDgx.js`),n=await t({cliVersion:c,siteId:e.siteId,window:e.window,limit:typeof e.limit==`string`?Number(e.limit):e.limit,newOnly:e.newOnly,watch:e.watch,json:e.json,csv:e.csv,tsv:e.tsv,ndjson:e.ndjson});process.exitCode=n}),d.command(`projects`,`List your tracked projects`).option(`--site-id <id>`,`Site ID`).option(`--json`,``).option(`--csv`,``).option(`--tsv`,``).option(`--ndjson`,``).action(async e=>{let{projectsCommand:t}=await import(`./projects-907FoPAg.js`),n=await t({cliVersion:c,siteId:e.siteId,json:e.json,csv:e.csv,tsv:e.tsv,ndjson:e.ndjson});process.exitCode=n}),d.command(`deploys`,`Recent GitHub commits overlaid on charts (Wave 4 W5)`).option(`--site-id <id>`,`Site ID`).option(`--branch <name>`,`Filter to a single branch (e.g. main, develop)`).option(`--since <iso>`,`Only commits after this ISO timestamp`).option(`--limit <n>`,`Max rows`,{default:50}).option(`--connect`,`Print the GitHub-integration deep link in app.zenovay.com`).option(`--json`,``).option(`--csv`,``).option(`--tsv`,``).option(`--ndjson`,``).action(async e=>{let{deploysCommand:t}=await import(`./deploys-CJVuTUqN.js`),n=await t({cliVersion:c,siteId:e.siteId,branch:e.branch,since:e.since,limit:typeof e.limit==`string`?Number(e.limit):e.limit,connect:e.connect,json:e.json,csv:e.csv,tsv:e.tsv,ndjson:e.ndjson});process.exitCode=n}),d.command(`webhooks forward`,`Forward webhook events to a local URL (stripe-listen-style; W3)`).option(`--to <url>`,`Local URL to POST events to (e.g. localhost:3000/webhook)`).option(`--site-id <id>`,`Site ID`).option(`--sign`,`HMAC-sign each forwarded request with X-Zenovay-Signature`).option(`--secret <hex>`,`HMAC secret (auto-derived from tunnel key if --sign without --secret)`).option(`--max-retries <n>`,`Per-request retry count`,{default:3}).action(async e=>{let{webhooksForwardCommand:t}=await import(`./webhooks-forward-But5AUF-.js`),n=await t({cliVersion:c,to:e.to,siteId:e.siteId,sign:e.sign,secret:e.secret,maxRetries:typeof e.maxRetries==`string`?Number(e.maxRetries):e.maxRetries});process.exitCode=n}),d.command(`errors`,`Recent error snapshot (Wave 2 lead-in; SSE coming in V2.1)`).option(`--site-id <id>`,`Site ID`).option(`--window <w>`,`Time window: 24h | 7d | 30d | 90d`,{default:`24h`}).option(`--limit <n>`,`Max errors to fetch`,{default:100}).option(`--search <q>`,`Filter by class or message substring`).option(`--watch`,`Auto-refresh every 30s`).option(`--json`,``).option(`--csv`,``).option(`--tsv`,``).option(`--ndjson`,``).action(async e=>{let{errorsCommand:t}=await import(`./errors-DYLYIh2G.js`),n=await t({cliVersion:c,siteId:e.siteId,window:e.window,limit:typeof e.limit==`string`?Number(e.limit):e.limit,search:e.search,watch:e.watch,json:e.json,csv:e.csv,tsv:e.tsv,ndjson:e.ndjson});process.exitCode=n}),d.command(`funnel <id>`,`Funnel drop-off chart for a specific funnel`).option(`--site-id <id>`,`Site ID`).option(`--window <w>`,`Time window: 7d | 30d`,{default:`30d`}).option(`--json`,``).option(`--csv`,``).option(`--tsv`,``).option(`--ndjson`,``).action(async(e,t)=>{let{funnelCommand:n}=await import(`./funnel-KSMIsBXC.js`),r=await n({cliVersion:c,siteId:t.siteId,funnelId:e,window:t.window,json:t.json,csv:t.csv,tsv:t.tsv,ndjson:t.ndjson});process.exitCode=r}),d.command(`update`,`Manually install the latest version`).option(`--check`,`Don't install — just print latest`).option(`--force-downgrade`,`Allow downgrading to an older version`).option(`--no-update-check`,`Disable auto-update for this invocation`).option(`--json`,``).action(async e=>{let{updateCommand:t}=await import(`./update-BPa-ewQo.js`);await t({cliVersion:c,binaryPath:l,check:e.check,forceDowngrade:e.forceDowngrade,json:e.json})}),d.parse(process.argv,{run:!1}),(async()=>{u();try{await d.runMatchedCommand()}catch(e){process.stderr.write(`\n✗ ${e.message}\n`),process.exit(1)}})();
2
+ import{cac as e}from"cac";import{fork as t}from"node:child_process";import n from"node:path";import{fileURLToPath as r}from"node:url";import{readFileSync as i}from"node:fs";const a=n.dirname(r(import.meta.url)),o=n.join(a,`..`,`package.json`),s=JSON.parse(i(o,`utf8`)),c=s.version,l=process.argv[0]??`zenovay`;function u(){if(!(process.env.ZENOVAY_NO_UPDATE_CHECK===`1`||process.env.CI===`true`))try{let e=n.join(a,`lib`,`update`,`worker.js`),r=t(e,[],{detached:!0,stdio:`ignore`});r.unref()}catch{}}const d=e(`zenovay`);d.version(c),d.help(),d.command(`init`,`AI install wizard — add Zenovay tracking to your codebase`).option(`--json`,`Emit NDJSON events to stdout`).option(`--yes`,`Auto-approve all diffs (for CI)`).option(`--skip-mcp`,`Skip MCP client install`).option(`--skip-verify`,`Skip first-event verification`).action(async e=>{let{initCommand:t}=await import(`./init-DlfdHqEi.js`),n=await t({cliVersion:c,cwd:process.cwd(),json:e.json,yes:e.yes,skipMcp:e.skipMcp,skipVerify:e.skipVerify});process.exitCode=n}),d.command(`login`,`Authenticate via OAuth device flow`).option(`--json`,`Emit NDJSON events`).option(`--no-browser`,`Skip opening the browser automatically`).action(async e=>{let{loginCommand:t}=await import(`./login-DjYNTtGG.js`);await t({cliVersion:c,json:e.json,openBrowser:e.browser!==!1,onCode:e=>{process.stdout.write(`\n Open this URL to authorize the CLI:\n ${e.verificationUriComplete??e.verificationUri}\n Or enter code: ${e.userCode}\n\n`)}})}),d.command(`logout`,`Revoke current session and delete local auth`).option(`--json`,``).action(async e=>{let{logoutCommand:t}=await import(`./logout-Cf4_khj0.js`);await t({cliVersion:c,json:e.json})}),d.command(`ai`,`3-mode AI assistant (install / chat / mcp)`).option(`--mode <mode>`,`install | chat | mcp`).option(`--json`,``).action(async e=>{let{aiCommand:t}=await import(`./ai-BURm2MXB.js`),n=await t({cliVersion:c,cwd:process.cwd(),mode:e.mode,json:e.json});process.exitCode=n}),d.command(`watch`,`Live TUI dashboard`).option(`--site-id <id>`,`Site ID`).option(`--interval <ms>`,`Poll interval ms`,{default:15e3}).option(`--json`,``).action(async e=>{let{watchCommand:t}=await import(`./watch-CFkeo8J8.js`),n=await t({cliVersion:c,siteId:e.siteId,intervalMs:Number(e.interval),json:e.json});process.exitCode=n}),d.command(`events tail`,`Stream live events`).option(`--site-id <id>`,`Site ID`,{default:``}).option(`--filter <expr>`,`Filter expression (e.g. 'type=pageview AND country=US')`).option(`--forward-to <url>`,`POST each event to a webhook with HMAC-SHA256 signature`).option(`--replay-24h`,`Replay the last 24h before going live`).option(`--set-forward-secret <hex>`,`Persist the HMAC secret used by --forward-to`).option(`--json`,``).action(async e=>{let{eventsTailCommand:t}=await import(`./events-tail-Bwgx_AgB.js`),n=await t({cliVersion:c,siteId:e.siteId,json:e.json,filter:e.filter,forwardTo:e.forwardTo,replay24h:e.replay24h,setForwardSecret:e.setForwardSecret});process.exitCode=n}),d.command(`health`,`Run self-diagnostic checks`).option(`--json`,``).action(async e=>{let{healthCommand:t}=await import(`./health-BFF0dghf.js`),n=await t({cliVersion:c,binaryPath:l,json:e.json});process.exitCode=n}),d.command(`doctor`,`AI-assisted self-healing`).option(`--json`,``).action(async e=>{let{doctorCommand:t}=await import(`./doctor-WVkPGXJ7.js`),n=await t({cliVersion:c,binaryPath:l,json:e.json});process.exitCode=n}),d.command(`stats`,`One-shot dashboard summary (scriptable by default)`).option(`--site-id <id>`,`Site ID`).option(`--range <range>`,`Time range: 24h | 7d | 30d`,{default:`24h`}).option(`--watch`,`Auto-refresh every 60s`).option(`--json`,``).option(`--csv`,``).option(`--tsv`,``).option(`--ndjson`,``).action(async e=>{let{statsCommand:t}=await import(`./stats-CyWREh45.js`),n=await t({cliVersion:c,siteId:e.siteId,range:e.range,watch:e.watch,json:e.json,csv:e.csv,tsv:e.tsv,ndjson:e.ndjson});process.exitCode=n}),d.command(`sources`,`Traffic source breakdown with delta arrows`).option(`--site-id <id>`,`Site ID`).option(`--period <p>`,`Period: 7d | 30d | 90d | 1y`,{default:`30d`}).option(`--compare <c>`,`Comparison window (use "prev" for period-over-period)`).option(`--json`,``).option(`--csv`,``).option(`--tsv`,``).option(`--ndjson`,``).action(async e=>{let{sourcesCommand:t}=await import(`./sources-D_OWPKOb.js`),n=await t({cliVersion:c,siteId:e.siteId,period:e.period,compare:e.compare,json:e.json,csv:e.csv,tsv:e.tsv,ndjson:e.ndjson});process.exitCode=n}),d.command(`vitals`,`Core Web Vitals dashboard (LCP / INP / CLS / TTFB / FCP)`).option(`--site-id <id>`,`Site ID`).option(`--url <path>`,`Filter to a single URL`).option(`--device <type>`,`Filter by device: mobile | desktop`).option(`--window <w>`,`Time window: 24h | 7d | 30d | 90d`,{default:`7d`}).option(`--watch`,`Auto-refresh every 5 minutes`).option(`--json`,``).option(`--csv`,``).option(`--tsv`,``).option(`--ndjson`,``).action(async e=>{let{vitalsCommand:t}=await import(`./vitals-Bx1cVV2p.js`),n=await t({cliVersion:c,siteId:e.siteId,url:e.url,device:e.device,window:e.window,watch:e.watch,json:e.json,csv:e.csv,tsv:e.tsv,ndjson:e.ndjson});process.exitCode=n}),d.command(`revenue`,`MRR / ARR / transaction series`).option(`--site-id <id>`,`Site ID`).option(`--range <r>`,`Time range: 24h | 7d | 30d | 1y`,{default:`30d`}).option(`--watch`,`Auto-refresh every 5 minutes`).option(`--json`,``).option(`--csv`,``).option(`--tsv`,``).option(`--ndjson`,``).action(async e=>{let{revenueCommand:t}=await import(`./revenue-y13ZDPfc.js`),n=await t({cliVersion:c,siteId:e.siteId,range:e.range,watch:e.watch,json:e.json,csv:e.csv,tsv:e.tsv,ndjson:e.ndjson});process.exitCode=n}),d.command(`funnels`,`List available funnels`).option(`--site-id <id>`,`Site ID`).option(`--json`,``).option(`--csv`,``).option(`--tsv`,``).option(`--ndjson`,``).action(async e=>{let{funnelCommand:t}=await import(`./funnel-DkfVTEfJ.js`),n=await t({cliVersion:c,siteId:e.siteId,json:e.json,csv:e.csv,tsv:e.tsv,ndjson:e.ndjson});process.exitCode=n}),d.command(`themes`,`List available themes with colored swatches`).option(`--validate <path>`,`Validate a custom theme JSON file`).option(`--json`,`Emit themes JSON to stdout`).action(async e=>{let{themesCommand:t}=await import(`./themes-F-HUBXpr.js`),n=await t({cliVersion:c,validate:e.validate,json:e.json});process.exitCode=n}),d.command(`completions [shell]`,`Emit shell-completion script (bash | zsh | fish | nushell | pwsh)`).option(`--list`,`List supported shells`).action(async(e,t)=>{let{completionsCommand:n}=await import(`./completions-GDtTbG3B.js`),r=await n({shell:e,list:t.list});process.exitCode=r}),d.command(`query [sql]`,`Restricted SQL REPL over the analytics schema (Scale+)`).option(`--site-id <id>`,`Site ID`).option(`--max-rows <n>`,`Cap result row count`,{default:1e3}).option(`--json`,``).option(`--csv`,``).option(`--tsv`,``).option(`--ndjson`,``).action(async(e,t)=>{let{queryCommand:n}=await import(`./query-DrnUU6fc.js`),r=await n({cliVersion:c,siteId:t.siteId,sql:e,maxRows:typeof t.maxRows==`string`?Number(t.maxRows):t.maxRows,json:t.json,csv:t.csv,tsv:t.tsv,ndjson:t.ndjson});process.exitCode=r}),d.command(`companies`,`B2B identification feed (Scale+)`).option(`--site-id <id>`,`Site ID`).option(`--window <w>`,`Time window: 24h | 7d | 30d | 90d`,{default:`24h`}).option(`--limit <n>`,`Max rows`,{default:100}).option(`--new-only`,`Show only newly identified companies (first-seen in last hour)`).option(`--watch`,`Auto-refresh every 30s`).option(`--json`,``).option(`--csv`,``).option(`--tsv`,``).option(`--ndjson`,``).action(async e=>{let{companiesCommand:t}=await import(`./companies-DerPI17Z.js`),n=await t({cliVersion:c,siteId:e.siteId,window:e.window,limit:typeof e.limit==`string`?Number(e.limit):e.limit,newOnly:e.newOnly,watch:e.watch,json:e.json,csv:e.csv,tsv:e.tsv,ndjson:e.ndjson});process.exitCode=n}),d.command(`projects`,`List your tracked projects`).option(`--site-id <id>`,`Site ID`).option(`--json`,``).option(`--csv`,``).option(`--tsv`,``).option(`--ndjson`,``).action(async e=>{let{projectsCommand:t}=await import(`./projects-CSm0bMWz.js`),n=await t({cliVersion:c,siteId:e.siteId,json:e.json,csv:e.csv,tsv:e.tsv,ndjson:e.ndjson});process.exitCode=n}),d.command(`deploys`,`Recent GitHub commits overlaid on charts (Wave 4 W5)`).option(`--site-id <id>`,`Site ID`).option(`--branch <name>`,`Filter to a single branch (e.g. main, develop)`).option(`--since <iso>`,`Only commits after this ISO timestamp`).option(`--limit <n>`,`Max rows`,{default:50}).option(`--connect`,`Print the GitHub-integration deep link in app.zenovay.com`).option(`--json`,``).option(`--csv`,``).option(`--tsv`,``).option(`--ndjson`,``).action(async e=>{let{deploysCommand:t}=await import(`./deploys-CfM6V_66.js`),n=await t({cliVersion:c,siteId:e.siteId,branch:e.branch,since:e.since,limit:typeof e.limit==`string`?Number(e.limit):e.limit,connect:e.connect,json:e.json,csv:e.csv,tsv:e.tsv,ndjson:e.ndjson});process.exitCode=n}),d.command(`webhooks forward`,`Forward webhook events to a local URL (stripe-listen-style; W3)`).option(`--to <url>`,`Local URL to POST events to (e.g. localhost:3000/webhook)`).option(`--site-id <id>`,`Site ID`).option(`--sign`,`HMAC-sign each forwarded request with X-Zenovay-Signature`).option(`--secret <hex>`,`HMAC secret (auto-derived from tunnel key if --sign without --secret)`).option(`--max-retries <n>`,`Per-request retry count`,{default:3}).action(async e=>{let{webhooksForwardCommand:t}=await import(`./webhooks-forward-But5AUF-.js`),n=await t({cliVersion:c,to:e.to,siteId:e.siteId,sign:e.sign,secret:e.secret,maxRetries:typeof e.maxRetries==`string`?Number(e.maxRetries):e.maxRetries});process.exitCode=n}),d.command(`errors`,`Recent error snapshot (Wave 2 lead-in; SSE coming in V2.1)`).option(`--site-id <id>`,`Site ID`).option(`--window <w>`,`Time window: 24h | 7d | 30d | 90d`,{default:`24h`}).option(`--limit <n>`,`Max errors to fetch`,{default:100}).option(`--search <q>`,`Filter by class or message substring`).option(`--watch`,`Auto-refresh every 30s`).option(`--json`,``).option(`--csv`,``).option(`--tsv`,``).option(`--ndjson`,``).action(async e=>{let{errorsCommand:t}=await import(`./errors-BycEZviU.js`),n=await t({cliVersion:c,siteId:e.siteId,window:e.window,limit:typeof e.limit==`string`?Number(e.limit):e.limit,search:e.search,watch:e.watch,json:e.json,csv:e.csv,tsv:e.tsv,ndjson:e.ndjson});process.exitCode=n}),d.command(`funnel <id>`,`Funnel drop-off chart for a specific funnel`).option(`--site-id <id>`,`Site ID`).option(`--window <w>`,`Time window: 7d | 30d`,{default:`30d`}).option(`--json`,``).option(`--csv`,``).option(`--tsv`,``).option(`--ndjson`,``).action(async(e,t)=>{let{funnelCommand:n}=await import(`./funnel-DkfVTEfJ.js`),r=await n({cliVersion:c,siteId:t.siteId,funnelId:e,window:t.window,json:t.json,csv:t.csv,tsv:t.tsv,ndjson:t.ndjson});process.exitCode=r}),d.command(`update`,`Manually install the latest version`).option(`--check`,`Don't install — just print latest`).option(`--force-downgrade`,`Allow downgrading to an older version`).option(`--no-update-check`,`Disable auto-update for this invocation`).option(`--json`,``).action(async e=>{let{updateCommand:t}=await import(`./update-2SafBiSk.js`);await t({cliVersion:c,binaryPath:l,check:e.check,forceDowngrade:e.forceDowngrade,json:e.json})}),d.parse(process.argv,{run:!1}),(async()=>{u();try{await d.runMatchedCommand()}catch(e){process.stderr.write(`\n✗ ${e.message}\n`),process.exit(1)}})();
@@ -1,3 +1,3 @@
1
- import{readConfig as e}from"./config-ZTGpKEWg.js";import{readToken as t}from"./api-D5XQeEDF.js";import{formatTabular as n,selectFormat as r}from"./formatter-DQ6l4sWM.js";import"./panel-DglZ755S.js";import"./keybar-D2OI-8rx.js";import"./prompt-hjzdzlyj.js";import"./sparkline-CR_bzxwB.js";import{runAnalyticalScreen as i}from"./analytical-screen-CS1ZL5Mo.js";import{Table as a}from"./ui-Bk5nl2yb.js";import{ApiV2Client as o}from"./api-v2-DP5YEHL_.js";import{Box as s,Text as c}from"ink";import l from"react";function u(e){let t=Math.max(0,Math.floor((Date.now()-new Date(e).getTime())/1e3));return t<60?`${t}s`:t<3600?`${Math.floor(t/60)}m`:t<86400?`${Math.floor(t/3600)}h`:`${Math.floor(t/86400)}d`}function d(e){return e==null?`—`:e>=500?`Enterprise`:e>=50?`Growth`:`SMB`}async function f(f){let p=await e(),m=await t({strict:!1}),h=f.siteId??m?.teamId??``;if(!h)return process.stderr.write(`No site selected — pass --site-id or set ZENOVAY_SITE.
1
+ import{readConfig as e}from"./config-ZTGpKEWg.js";import{readToken as t}from"./api-D5XQeEDF.js";import{formatTabular as n,selectFormat as r}from"./formatter-45-fT1Hv.js";import"./panel-DglZ755S.js";import"./keybar-D2OI-8rx.js";import"./prompt-hjzdzlyj.js";import"./sparkline-CR_bzxwB.js";import{runAnalyticalScreen as i}from"./analytical-screen-CdtZfbes.js";import{Table as a}from"./ui-Bk5nl2yb.js";import{ApiV2Client as o}from"./api-v2-DP5YEHL_.js";import{Box as s,Text as c}from"ink";import l from"react";function u(e){let t=Math.max(0,Math.floor((Date.now()-new Date(e).getTime())/1e3));return t<60?`${t}s`:t<3600?`${Math.floor(t/60)}m`:t<86400?`${Math.floor(t/3600)}h`:`${Math.floor(t/86400)}d`}function d(e){return e==null?`—`:e>=500?`Enterprise`:e>=50?`Growth`:`SMB`}async function f(f){let p=await e(),m=await t({strict:!1}),h=f.siteId??m?.teamId??``;if(!h)return process.stderr.write(`No site selected — pass --site-id or set ZENOVAY_SITE.
2
2
  `),2;let g=new o({config:p,cliVersion:f.cliVersion,token:m}),_=r(f),v=f.window??`24h`,y=f.limit??100,b=[{key:`lastSeenAt`,header:`when`,width:6,format:e=>u(String(e))},{key:`name`,header:`company`,width:24,format:e=>String(e).slice(0,24)},{key:`employeeCount`,header:`tier`,width:11,format:e=>d(typeof e==`number`?e:null)},{key:`industry`,header:`industry`,width:18,format:e=>String(e??`—`).slice(0,18)},{key:`visitCount`,header:`visits`,width:6,align:`right`},{key:`isNew`,header:``,width:5,format:e=>e?`NEW`:``}];return i({cliVersion:f.cliVersion,title:`companies · ${h} · ${v}`,commandName:`companies`,authToken:m?.accessToken??null,refreshIntervalMs:f.watch?3e4:0,fetcher:e=>g.getCompaniesSnapshot(h,{window:v,limit:y},e),format:_,headlessEmit:(e,t)=>{let r=f.newOnly?e.companies.filter(e=>e.isNew):e.companies;if(t===`json`||t===`ndjson`){if(t===`ndjson`)for(let e of r)process.stdout.write(JSON.stringify(e)+`
3
3
  `);else process.stdout.write(JSON.stringify({companies:r,total:r.length},null,2));return}process.stdout.write(n(r,[`name`,`domain`,`industry`,`employeeCount`,`visitCount`,`firstSeenAt`,`lastSeenAt`,`isNew`],t))},panels:[{id:`summary`,title:`Now`,render:e=>{let t=e.companies.filter(e=>e.isNew).length,n=e.companies.filter(e=>(e.employeeCount??0)>=500).length;return l.createElement(s,{flexDirection:`column`},l.createElement(c,null,l.createElement(c,{bold:!0},e.total),l.createElement(c,{color:`gray`},` companies in `,v)),l.createElement(c,{color:`gray`},l.createElement(c,{color:`green`},`● `,t,` new`),` · `,n,` enterprise`))}},{id:`feed`,title:`Feed`,render:e=>{let t=f.newOnly?e.companies.filter(e=>e.isNew):e.companies;return t.length===0?l.createElement(c,{color:`gray`},`— no `,f.newOnly?`new `:``,`companies in window —`):l.createElement(a,{data:t.slice(0,30),columns:b})}}]})}export{f as companiesCommand};
@@ -1,3 +1,3 @@
1
- import{readConfig as e}from"./config-ZTGpKEWg.js";import{readToken as t}from"./api-D5XQeEDF.js";import{formatTabular as n,selectFormat as r}from"./formatter-DQ6l4sWM.js";import"./panel-DglZ755S.js";import"./keybar-D2OI-8rx.js";import"./prompt-hjzdzlyj.js";import"./sparkline-CR_bzxwB.js";import{runAnalyticalScreen as i}from"./analytical-screen-CS1ZL5Mo.js";import{Table as a}from"./ui-Bk5nl2yb.js";import{ApiV2Client as o}from"./api-v2-DP5YEHL_.js";import{Box as s,Text as c}from"ink";import l from"react";function u(e){let t=Math.max(0,Math.floor((Date.now()-new Date(e).getTime())/1e3));return t<60?`${t}s`:t<3600?`${Math.floor(t/60)}m`:t<86400?`${Math.floor(t/3600)}h`:`${Math.floor(t/86400)}d`}async function d(d){if(d.connect){let t=await e(),n=t.apiBase.replace(`api.zenovay.com`,`app.zenovay.com`),r=`${n}/settings/integrations/github`;return process.stdout.write(`\n Connect GitHub to Zenovay:\n ${r}\n\n Open this URL in your browser. Zenovay re-uses the same GitHub\n OAuth app you already authorized for login (auth-zenovay), so\n no separate "Zenovay Deploys" app is needed. Pick the repos you\n want to track and deploys will appear here automatically.\n\n`),0}let f=await e(),p=await t({strict:!1}),m=d.siteId??p?.teamId??``;if(!m)return process.stderr.write(`No site selected — pass --site-id or set ZENOVAY_SITE.
1
+ import{readConfig as e}from"./config-ZTGpKEWg.js";import{readToken as t}from"./api-D5XQeEDF.js";import{formatTabular as n,selectFormat as r}from"./formatter-45-fT1Hv.js";import"./panel-DglZ755S.js";import"./keybar-D2OI-8rx.js";import"./prompt-hjzdzlyj.js";import"./sparkline-CR_bzxwB.js";import{runAnalyticalScreen as i}from"./analytical-screen-CdtZfbes.js";import{Table as a}from"./ui-Bk5nl2yb.js";import{ApiV2Client as o}from"./api-v2-DP5YEHL_.js";import{Box as s,Text as c}from"ink";import l from"react";function u(e){let t=Math.max(0,Math.floor((Date.now()-new Date(e).getTime())/1e3));return t<60?`${t}s`:t<3600?`${Math.floor(t/60)}m`:t<86400?`${Math.floor(t/3600)}h`:`${Math.floor(t/86400)}d`}async function d(d){if(d.connect){let t=await e(),n=t.apiBase.replace(`api.zenovay.com`,`app.zenovay.com`),r=`${n}/settings/integrations/github`;return process.stdout.write(`\n Connect GitHub to Zenovay:\n ${r}\n\n Open this URL in your browser. Zenovay re-uses the same GitHub\n OAuth app you already authorized for login (auth-zenovay), so\n no separate "Zenovay Deploys" app is needed. Pick the repos you\n want to track and deploys will appear here automatically.\n\n`),0}let f=await e(),p=await t({strict:!1}),m=d.siteId??p?.teamId??``;if(!m)return process.stderr.write(`No site selected — pass --site-id or set ZENOVAY_SITE.
2
2
  `),2;let h=new o({config:f,cliVersion:d.cliVersion,token:p}),g=r(d),_=d.limit??50,v=[{key:`pushed_at`,header:`when`,width:6,format:e=>u(String(e))},{key:`branch`,header:`branch`,width:14,format:e=>String(e??`—`).slice(0,14)},{key:`commit_sha`,header:`commit`,width:9,format:e=>String(e).slice(0,8)},{key:`commit_author`,header:`author`,width:16,format:e=>String(e??`—`).slice(0,16)},{key:`commit_message`,header:`message`,width:40,format:e=>String(e??`—`).slice(0,40)},{key:`show_on_chart`,header:`chart`,width:5,format:e=>e?`●`:`○`}];return i({cliVersion:d.cliVersion,title:`deploys · ${m}`,commandName:`deploys`,authToken:p?.accessToken??null,refreshIntervalMs:0,fetcher:e=>h.getDeploys(m,{branch:d.branch,since:d.since,limit:_},e),format:g,headlessEmit:(e,t)=>{if(t===`json`||t===`ndjson`){if(t===`ndjson`)for(let t of e.deploys)process.stdout.write(JSON.stringify(t)+`
3
3
  `);else process.stdout.write(JSON.stringify(e,null,2));return}process.stdout.write(n(e.deploys,[`pushed_at`,`branch`,`commit_sha`,`commit_author`,`commit_message`,`repository`,`commit_url`,`show_on_chart`],t))},panels:[{id:`summary`,title:`Summary`,render:e=>{let t=e.deploys.filter(e=>e.show_on_chart).length,n=new Set(e.deploys.map(e=>e.repository).filter(e=>!!e));return l.createElement(s,{flexDirection:`column`},l.createElement(c,null,l.createElement(c,{bold:!0},e.total),l.createElement(c,{color:`gray`},` commits`,d.branch?` · branch=${d.branch}`:``)),l.createElement(c,{color:`gray`},l.createElement(c,{color:`magenta`},`● `,t,` on chart`),l.createElement(c,null,` · `),l.createElement(c,null,n.size,` `,n.size===1?`repo`:`repos`)))}},{id:`list`,title:`Recent`,render:e=>e.deploys.length===0?l.createElement(s,{flexDirection:`column`},l.createElement(c,{color:`gray`},`— no commits yet —`),l.createElement(c,{color:`gray`},"Run `zenovay deploys --connect` to wire up the GitHub integration.")):l.createElement(a,{data:e.deploys.slice(0,30),columns:v})}]})}export{d as deploysCommand};
@@ -1,4 +1,4 @@
1
- import{readConfig as e}from"./config-ZTGpKEWg.js";import{ApiClient as t,readToken as n}from"./api-D5XQeEDF.js";import{parseSseStream as r}from"./client-Bc1xZcH_.js";import"./formatter-DQ6l4sWM.js";import{emit as i,isHeadless as a}from"./emit-DIRc7UzM.js";import"./panel-DglZ755S.js";import"./check-S0ACFIfq.js";import{runHealthChecks as o}from"./health-C6G6Mg6b.js";async function s(s){let c=await o({cliVersion:s.cliVersion,binaryPath:s.binaryPath}),l=c.filter(e=>e.status===`fail`);if(l.length===0)return a(s)||process.stdout.write(`All checks pass — no healing needed.
1
+ import{readConfig as e}from"./config-ZTGpKEWg.js";import{ApiClient as t,readToken as n}from"./api-D5XQeEDF.js";import{parseSseStream as r}from"./client-DZ4Awt8u.js";import"./formatter-45-fT1Hv.js";import{emit as i,isHeadless as a}from"./emit-0WJ_OGeT.js";import"./panel-DglZ755S.js";import"./check-S0ACFIfq.js";import{runHealthChecks as o}from"./health-Dxmho1lB.js";async function s(s){let c=await o({cliVersion:s.cliVersion,binaryPath:s.binaryPath}),l=c.filter(e=>e.status===`fail`);if(l.length===0)return a(s)||process.stdout.write(`All checks pass — no healing needed.
2
2
  `),0;let u=await e(),d=await n({strict:!1});if(!d){for(let e of l)process.stderr.write(`[${e.name}] ${e.detail}\n`);return process.stderr.write(`
3
3
  Log in with \`zenovay login\` for AI-assisted diagnosis.
4
4
  `),1}let f=new t({config:u,cliVersion:s.cliVersion,token:d}),p={platform:process.platform,arch:process.arch,node:process.version,cliVersion:s.cliVersion},m=`The Zenovay CLI failed the following health checks. Diagnose and propose a fix.
@@ -1 +1 @@
1
- import{formatEvent as e,formatTabular as t}from"./formatter-DQ6l4sWM.js";function n(e){return typeof e==`object`&&!!e&&Array.isArray(e._columns)&&Array.isArray(e._rows)}function r(){let e=process.argv;for(let t=0;t<e.length;t++){let n=e[t];if(n){if(n===`--json`)return`json`;if(n===`--csv`)return`csv`;if(n===`--tsv`)return`tsv`;if(n===`--ndjson`)return`ndjson`;if(n===`--format`&&t+1<e.length){let n=(e[t+1]??``).toLowerCase();if(n===`json`||n===`csv`||n===`tsv`||n===`ndjson`)return n}if(n.startsWith(`--format=`)){let e=n.slice(9).toLowerCase();if(e===`json`||e===`csv`||e===`tsv`||e===`ndjson`)return e}}}let t=(process.env.ZENOVAY_FORMAT??``).toLowerCase();return t===`json`||t===`csv`||t===`tsv`||t===`ndjson`?t:`ndjson`}function i(e={}){return e.json||e.csv||e.tsv||e.ndjson||process.env.CI===`true`||process.env.CI===`1`||process.env.ZENOVAY_FORMAT?!0:!process.stdout.isTTY}function a(i){let a=r();if(n(i)){process.stdout.write(t(i._rows,i._columns,a));return}if(a===`ndjson`){let e={ts:new Date().toISOString(),...i};process.stdout.write(`${JSON.stringify(e)}\n`);return}process.stdout.write(e({ts:new Date().toISOString(),...i},a))}export{a as emit,i as isHeadless};
1
+ import{formatEvent as e,formatTabular as t}from"./formatter-45-fT1Hv.js";function n(e){return typeof e==`object`&&!!e&&Array.isArray(e._columns)&&Array.isArray(e._rows)}function r(){let e=process.argv;for(let t=0;t<e.length;t++){let n=e[t];if(n){if(n===`--json`)return`json`;if(n===`--csv`)return`csv`;if(n===`--tsv`)return`tsv`;if(n===`--ndjson`)return`ndjson`;if(n===`--format`&&t+1<e.length){let n=(e[t+1]??``).toLowerCase();if(n===`json`||n===`csv`||n===`tsv`||n===`ndjson`)return n}if(n.startsWith(`--format=`)){let e=n.slice(9).toLowerCase();if(e===`json`||e===`csv`||e===`tsv`||e===`ndjson`)return e}}}let t=(process.env.ZENOVAY_FORMAT??``).toLowerCase();return t===`json`||t===`csv`||t===`tsv`||t===`ndjson`?t:`ndjson`}function i(e={}){return e.json||e.csv||e.tsv||e.ndjson||process.env.CI===`true`||process.env.CI===`1`||process.env.ZENOVAY_FORMAT?!0:!process.stdout.isTTY}function a(i){let a=r();if(n(i)){process.stdout.write(t(i._rows,i._columns,a));return}if(a===`ndjson`){let e={ts:new Date().toISOString(),...i};process.stdout.write(`${JSON.stringify(e)}\n`);return}process.stdout.write(e({ts:new Date().toISOString(),...i},a))}export{a as emit,i as isHeadless};
@@ -1,3 +1,3 @@
1
- import{readConfig as e}from"./config-ZTGpKEWg.js";import{readToken as t}from"./api-D5XQeEDF.js";import{formatTabular as n,selectFormat as r}from"./formatter-DQ6l4sWM.js";import"./panel-DglZ755S.js";import"./keybar-D2OI-8rx.js";import"./prompt-hjzdzlyj.js";import{spark as i}from"./sparkline-CR_bzxwB.js";import{runAnalyticalScreen as a}from"./analytical-screen-CS1ZL5Mo.js";import{Table as o}from"./ui-Bk5nl2yb.js";import{ApiV2Client as s}from"./api-v2-DP5YEHL_.js";import{Box as c,Text as l}from"ink";import u from"react";function d(e,t){return e.length<=t?e:e.slice(0,t-1)+`…`}function f(e){let t=Math.max(0,Math.floor((Date.now()-new Date(e).getTime())/1e3));return t<60?`${t}s`:t<3600?`${Math.floor(t/60)}m`:t<86400?`${Math.floor(t/3600)}h`:`${Math.floor(t/86400)}d`}async function p(p){let m=await e(),h=await t({strict:!1}),g=p.siteId??h?.teamId??``;if(!g)return process.stderr.write(`No site selected — pass --site-id or set ZENOVAY_SITE.
1
+ import{readConfig as e}from"./config-ZTGpKEWg.js";import{readToken as t}from"./api-D5XQeEDF.js";import{formatTabular as n,selectFormat as r}from"./formatter-45-fT1Hv.js";import"./panel-DglZ755S.js";import"./keybar-D2OI-8rx.js";import"./prompt-hjzdzlyj.js";import{spark as i}from"./sparkline-CR_bzxwB.js";import{runAnalyticalScreen as a}from"./analytical-screen-CdtZfbes.js";import{Table as o}from"./ui-Bk5nl2yb.js";import{ApiV2Client as s}from"./api-v2-DP5YEHL_.js";import{Box as c,Text as l}from"ink";import u from"react";function d(e,t){return e.length<=t?e:e.slice(0,t-1)+`…`}function f(e){let t=Math.max(0,Math.floor((Date.now()-new Date(e).getTime())/1e3));return t<60?`${t}s`:t<3600?`${Math.floor(t/60)}m`:t<86400?`${Math.floor(t/3600)}h`:`${Math.floor(t/86400)}d`}async function p(p){let m=await e(),h=await t({strict:!1}),g=p.siteId??h?.teamId??``;if(!g)return process.stderr.write(`No site selected — pass --site-id or set ZENOVAY_SITE.
2
2
  `),2;let _=new s({config:m,cliVersion:p.cliVersion,token:h}),v=r(p),y=p.window??`24h`,b=p.limit??100,x=[{key:`ts`,header:`when`,width:6,format:e=>f(String(e))},{key:`class`,header:`class`,width:18,format:e=>String(e)},{key:`message`,header:`message`,width:42,format:e=>d(String(e??``),42)},{key:`page`,header:`page`,width:24,format:e=>String(e??`—`)},{key:`device`,header:`device`,width:8,format:e=>String(e??`—`)}];return a({cliVersion:p.cliVersion,title:`errors · ${g} · ${y}`,commandName:`errors`,authToken:h?.accessToken??null,refreshIntervalMs:p.watch?3e4:0,fetcher:e=>_.getErrors(g,{window:y,limit:b},e),format:v,headlessEmit:(e,t)=>{let r=p.search?e.errors.filter(e=>e.class.toLowerCase().includes(p.search.toLowerCase())||e.message.toLowerCase().includes(p.search.toLowerCase())):e.errors;if(t===`json`||t===`ndjson`){if(t===`ndjson`)for(let e of r)process.stdout.write(JSON.stringify(e)+`
3
3
  `);else process.stdout.write(JSON.stringify({errors:r,total:r.length},null,2));return}process.stdout.write(n(r,[`ts`,`class`,`message`,`page`,`device`,`fingerprint`],t))},panels:[{id:`summary`,title:`Recent errors`,render:e=>{let t=p.search?e.errors.filter(e=>e.class.toLowerCase().includes(p.search.toLowerCase())||e.message.toLowerCase().includes(p.search.toLowerCase())):e.errors,n=new Map,r=Date.now(),a=60;for(let e of t){let t=new Date(e.ts).getTime(),i=Math.floor((r-t)/(60*1e3));if(i<0||i>=a)continue;let o=n.get(e.class)??Array(a).fill(0),s=a-1-i;o[s]+=1,n.set(e.class,o)}let o=[...n.entries()].sort((e,t)=>t[1].reduce((e,t)=>e+t,0)-e[1].reduce((e,t)=>e+t,0)).slice(0,6);return u.createElement(c,{flexDirection:`column`},u.createElement(l,null,u.createElement(l,{bold:!0},t.length),u.createElement(l,{color:`gray`},` errors in `,y)),o.length===0?null:u.createElement(c,{flexDirection:`column`,marginTop:1},o.map(([e,t])=>u.createElement(l,{key:e},u.createElement(l,{color:`red`},e.padEnd(20).slice(0,20)),` `,u.createElement(l,{color:`gray`},i(t,30))))))}},{id:`table`,title:`Detail`,render:e=>{let t=p.search?e.errors.filter(e=>e.class.toLowerCase().includes(p.search.toLowerCase())||e.message.toLowerCase().includes(p.search.toLowerCase())):e.errors;return t.length===0?u.createElement(l,{color:`gray`},`— no errors `,p.search?`matching "${p.search}"`:`in window`,` —`):u.createElement(o,{data:t.slice(0,30),columns:x})}}]})}export{p as errorsCommand};
@@ -1,4 +1,4 @@
1
- import{readConfig as e,updateConfig as t}from"./config-ZTGpKEWg.js";import{ApiClient as n,readToken as r}from"./api-D5XQeEDF.js";import{parseSseStream as i}from"./client-Bc1xZcH_.js";import"./formatter-DQ6l4sWM.js";import{isHeadless as a}from"./emit-DIRc7UzM.js";import{Panel as o}from"./panel-DglZ755S.js";import{Banner as s,Keybar as c}from"./keybar-D2OI-8rx.js";import{TextInput as l}from"./prompt-hjzdzlyj.js";import u from"node:path";import{promises as d}from"node:fs";import{Box as f,Static as p,Text as m,render as h,useApp as g,useInput as _}from"ink";import v,{useEffect as y,useRef as b,useState as x}from"react";import S from"node:os";import C from"node:crypto";const w=new Set([`type`,`page`,`country`,`device`,`user_id`,`sessionId`,`referrer`,`ts`,`url`,`method`,`status`]);function T(e){let t=[],n=0;for(;n<e.length;){let r=e[n];if(/\s/.test(r)){n+=1;continue}if(r===`(`){t.push({kind:`lparen`}),n+=1;continue}if(r===`)`){t.push({kind:`rparen`}),n+=1;continue}if(r===`"`||r===`'`){let i=r,a=n+1,o=``;for(;a<e.length&&e[a]!==i;)e[a]===`\\`&&a+1<e.length?(o+=e[a+1],a+=2):(o+=e[a],a+=1);if(a>=e.length)throw Error(`filter: unterminated string starting at column ${n+1}`);t.push({kind:`string`,value:o}),n=a+1;continue}if(r===`!`&&e[n+1]===`=`){t.push({kind:`op`,value:`!=`}),n+=2;continue}if(r===`!`&&e[n+1]===`~`){t.push({kind:`op`,value:`!~`}),n+=2;continue}if(r===`=`){t.push({kind:`op`,value:`=`}),n+=1;continue}if(r===`~`){t.push({kind:`op`,value:`~`}),n+=1;continue}let i=n;for(;n<e.length&&!/[\s()=!~]/.test(e[n])&&e[n]!==`"`&&e[n]!==`'`;)n+=1;let a=e.slice(i,n);if(a.length===0)throw Error(`filter: unexpected character at column ${i+1}`);let o=a.toUpperCase();o===`AND`?t.push({kind:`and`}):o===`OR`?t.push({kind:`or`}):t.push({kind:`ident`,value:a})}return t}function E(e){return e.replace(/[.*+?^${}()|[\]\\]/g,`\\$&`)}function D(e,t,n){let r=e==null?``:String(e);switch(t){case`=`:return r===n;case`!=`:return r!==n;case`~`:{let e=new RegExp(E(n),`i`);return e.test(r)}case`!~`:{let e=new RegExp(E(n),`i`);return!e.test(r)}}}function O(e){return e.tokens[e.pos]}function k(e){let t=e.tokens[e.pos];return e.pos+=1,t}function A(e){let t=O(e);if(!t)throw Error(`filter: unexpected end of expression`);if(t.kind===`lparen`){k(e);let t=j(e),n=k(e);if(!n||n.kind!==`rparen`)throw Error(`filter: missing closing ")"`);return t}if(t.kind!==`ident`)throw Error(`filter: expected key, got ${t.kind}`);k(e);let n=t.value;if(!w.has(n))throw Error(`filter: unknown key "${n}". Allowed: ${[...w].join(`, `)}`);let r=k(e);if(!r||r.kind!==`op`)throw Error(`filter: expected operator after "${n}"`);let i=k(e);if(!i||i.kind!==`ident`&&i.kind!==`string`)throw Error(`filter: expected value after operator "${r.value}"`);let a=r.value,o=i.value;return e=>D(e[n],a,o)}function j(e){let t=A(e);for(;;){let n=O(e);if(!n)break;if(n.kind===`and`){k(e);let n=A(e),r=t;t=e=>r(e)&&n(e);continue}if(n.kind===`or`){k(e);let n=A(e),r=t;t=e=>r(e)||n(e);continue}break}return t}function M(e){if(typeof e!=`string`||e.trim().length===0)throw Error(`filter: expression is empty`);let t=T(e);if(t.length===0)throw Error(`filter: expression is empty`);let n={tokens:t,pos:0},r=j(n);if(n.pos!==t.length){let e=n.tokens[n.pos];throw Error(`filter: unexpected trailing token "${N(e)}"`)}return r}function N(e){return e.kind===`ident`||e.kind===`string`||e.kind===`op`?e.value:e.kind}const P=10*1024*1024;var F=class{currentBytes=0;initialized=!1;writeQueue=Promise.resolve();constructor(e,t=P){this.filePath=e,this.maxBytes=t}async init(){if(!this.initialized){this.initialized=!0;try{await d.mkdir(u.dirname(this.filePath),{recursive:!0,mode:448})}catch{}try{let e=await d.stat(this.filePath);this.currentBytes=e.size}catch{this.currentBytes=0}}}append(e){let t=(async()=>{await this.init();let t=e.endsWith(`
1
+ import{readConfig as e,updateConfig as t}from"./config-ZTGpKEWg.js";import{ApiClient as n,readToken as r}from"./api-D5XQeEDF.js";import{parseSseStream as i}from"./client-DZ4Awt8u.js";import"./formatter-45-fT1Hv.js";import{isHeadless as a}from"./emit-0WJ_OGeT.js";import{Panel as o}from"./panel-DglZ755S.js";import{Banner as s,Keybar as c}from"./keybar-D2OI-8rx.js";import{TextInput as l}from"./prompt-hjzdzlyj.js";import u from"node:path";import{promises as d}from"node:fs";import{Box as f,Static as p,Text as m,render as h,useApp as g,useInput as _}from"ink";import v,{useEffect as y,useRef as b,useState as x}from"react";import S from"node:os";import C from"node:crypto";const w=new Set([`type`,`page`,`country`,`device`,`user_id`,`sessionId`,`referrer`,`ts`,`url`,`method`,`status`]);function T(e){let t=[],n=0;for(;n<e.length;){let r=e[n];if(/\s/.test(r)){n+=1;continue}if(r===`(`){t.push({kind:`lparen`}),n+=1;continue}if(r===`)`){t.push({kind:`rparen`}),n+=1;continue}if(r===`"`||r===`'`){let i=r,a=n+1,o=``;for(;a<e.length&&e[a]!==i;)e[a]===`\\`&&a+1<e.length?(o+=e[a+1],a+=2):(o+=e[a],a+=1);if(a>=e.length)throw Error(`filter: unterminated string starting at column ${n+1}`);t.push({kind:`string`,value:o}),n=a+1;continue}if(r===`!`&&e[n+1]===`=`){t.push({kind:`op`,value:`!=`}),n+=2;continue}if(r===`!`&&e[n+1]===`~`){t.push({kind:`op`,value:`!~`}),n+=2;continue}if(r===`=`){t.push({kind:`op`,value:`=`}),n+=1;continue}if(r===`~`){t.push({kind:`op`,value:`~`}),n+=1;continue}let i=n;for(;n<e.length&&!/[\s()=!~]/.test(e[n])&&e[n]!==`"`&&e[n]!==`'`;)n+=1;let a=e.slice(i,n);if(a.length===0)throw Error(`filter: unexpected character at column ${i+1}`);let o=a.toUpperCase();o===`AND`?t.push({kind:`and`}):o===`OR`?t.push({kind:`or`}):t.push({kind:`ident`,value:a})}return t}function E(e){return e.replace(/[.*+?^${}()|[\]\\]/g,`\\$&`)}function D(e,t,n){let r=e==null?``:String(e);switch(t){case`=`:return r===n;case`!=`:return r!==n;case`~`:{let e=new RegExp(E(n),`i`);return e.test(r)}case`!~`:{let e=new RegExp(E(n),`i`);return!e.test(r)}}}function O(e){return e.tokens[e.pos]}function k(e){let t=e.tokens[e.pos];return e.pos+=1,t}function A(e){let t=O(e);if(!t)throw Error(`filter: unexpected end of expression`);if(t.kind===`lparen`){k(e);let t=j(e),n=k(e);if(!n||n.kind!==`rparen`)throw Error(`filter: missing closing ")"`);return t}if(t.kind!==`ident`)throw Error(`filter: expected key, got ${t.kind}`);k(e);let n=t.value;if(!w.has(n))throw Error(`filter: unknown key "${n}". Allowed: ${[...w].join(`, `)}`);let r=k(e);if(!r||r.kind!==`op`)throw Error(`filter: expected operator after "${n}"`);let i=k(e);if(!i||i.kind!==`ident`&&i.kind!==`string`)throw Error(`filter: expected value after operator "${r.value}"`);let a=r.value,o=i.value;return e=>D(e[n],a,o)}function j(e){let t=A(e);for(;;){let n=O(e);if(!n)break;if(n.kind===`and`){k(e);let n=A(e),r=t;t=e=>r(e)&&n(e);continue}if(n.kind===`or`){k(e);let n=A(e),r=t;t=e=>r(e)||n(e);continue}break}return t}function M(e){if(typeof e!=`string`||e.trim().length===0)throw Error(`filter: expression is empty`);let t=T(e);if(t.length===0)throw Error(`filter: expression is empty`);let n={tokens:t,pos:0},r=j(n);if(n.pos!==t.length){let e=n.tokens[n.pos];throw Error(`filter: unexpected trailing token "${N(e)}"`)}return r}function N(e){return e.kind===`ident`||e.kind===`string`||e.kind===`op`?e.value:e.kind}const P=10*1024*1024;var F=class{currentBytes=0;initialized=!1;writeQueue=Promise.resolve();constructor(e,t=P){this.filePath=e,this.maxBytes=t}async init(){if(!this.initialized){this.initialized=!0;try{await d.mkdir(u.dirname(this.filePath),{recursive:!0,mode:448})}catch{}try{let e=await d.stat(this.filePath);this.currentBytes=e.size}catch{this.currentBytes=0}}}append(e){let t=(async()=>{await this.init();let t=e.endsWith(`
2
2
  `)?e:`${e}\n`,n=Buffer.byteLength(t,`utf8`);this.currentBytes+n>this.maxBytes&&await this.rotate();try{await d.appendFile(this.filePath,t,{mode:384}),this.currentBytes+=n}catch(e){process.stderr.write(`[scrollback] append failed: ${e.message}\n`)}})();return this.writeQueue=this.writeQueue.then(()=>t,()=>t),t}async rotate(){let e=e=>{if(e===0)return this.filePath;let t=u.parse(this.filePath);return u.join(t.dir,`${t.name}.${e}${t.ext}`)};try{await d.unlink(e(3))}catch{}for(let t=2;t>=0;--t)try{await d.rename(e(t),e(t+1))}catch(n){n.code!==`ENOENT`&&process.stderr.write(`[scrollback] rotate ${e(t)} failed: ${n.message}\n`)}this.currentBytes=0}async close(){await this.writeQueue}};const I=5e3,L=33,R=`─── replay end, live below ───`;async function z(i){if(i.setForwardSecret)return await t({forwardSecret:i.setForwardSecret}),process.stdout.write(`Forward secret saved.
3
3
  `),0;let o=await e(),s=await r({strict:!1});if(!s)return process.stderr.write("Not logged in — run `zenovay login` first.\n"),2;let c=new n({config:o,cliVersion:i.cliVersion,token:s}),l=null;if(i.filter)try{l=M(i.filter)}catch(e){return process.stderr.write(`Invalid --filter expression: ${e.message}\n`),2}if(a(i))return H(c,i,l,o.forwardSecret);let d=i.scrollbackPath??u.join(S.homedir(),`.zenovay`,`events-scrollback.log`);return new Promise(e=>{let{unmount:t}=h(v.createElement(U,{api:c,opts:i,predicate:l,forwardSecret:o.forwardSecret,scrollbackPath:d,onExit:n=>{t(),e(n)}}))})}function B(e){return{raw:JSON.stringify(e),parsed:e}}async function V(e,t,n){let r=JSON.stringify(n),i=C.createHmac(`sha256`,t).update(r).digest(`hex`);try{await fetch(e,{method:`POST`,headers:{"Content-Type":`application/json`,"X-Zenovay-Signature":`sha256=${i}`},body:r})}catch{}}async function H(e,t,n,r){let a=new AbortController;process.on(`SIGINT`,()=>a.abort());let o=()=>new Date().toISOString();try{let s=await e.openEventsStream(t.siteId,a.signal);for await(let e of i(s)){if(e.type===`error`)return process.stdout.write(`${JSON.stringify({ts:o(),type:`error`,code:e.code,message:e.message})}\n`),1;if(e.type===`done`)return 0;let i=e;if(n&&!n(i))continue;process.stdout.write(`${JSON.stringify({ts:o(),...i})}\n`),t.forwardTo&&r&&await V(t.forwardTo,r,{event:e,ts:o(),site_id:t.siteId})}return 0}catch(e){return process.stdout.write(`${JSON.stringify({ts:o(),type:`error`,code:`stream_failed`,message:e.message})}\n`),1}}const U=({api:e,opts:t,predicate:n,forwardSecret:r,scrollbackPath:a,onExit:u})=>{let{exit:h}=g(),S=b([]),C=b(null),[w,T]=x([]),[E,D]=x(null),[O,k]=x(!1),[A,j]=x(null);C.current||=new F(a),_(n=>{if(!O){if(E){D(null);return}if(n===`q`){h(),u(0);return}if(n===`f`){let e=S.current[S.current.length-1];e&&D(e);return}if(n===`w`){k(!0);return}if(n===`r`){G(e,t.siteId,S,j);return}}}),y(()=>{let e=setInterval(()=>{let e=S.current.slice(-100);T(e)},L);return()=>clearInterval(e)},[]),y(()=>{let a=new AbortController,o=!1;return(async()=>{t.replay24h&&await G(e,t.siteId,S,j);try{let s=await e.openEventsStream(t.siteId,a.signal);for await(let e of i(s)){if(o)break;if(e.type===`error`){let t={raw:`[ERR ${e.code}] ${e.message}`};W(S,t),C.current?.append(t.raw);continue}if(e.type===`done`)break;let i=e;if(n&&!n(i))continue;let a=B(e);W(S,a),C.current?.append(a.raw),t.forwardTo&&r&&V(t.forwardTo,r,{event:e,ts:new Date().toISOString(),site_id:t.siteId})}}catch(e){let t={raw:`[DISCONNECT] ${e.message}`};W(S,t)}})(),()=>{o=!0,a.abort(),C.current?.close()}},[e,t.siteId,t.replay24h,t.forwardTo,n,r]);let M=async e=>{let t=e.trim()||`events.ndjson`;try{let e=S.current.map(e=>e.raw).join(`
4
4
  `)+`
@@ -1,4 +1,4 @@
1
- import{readConfig as e}from"./config-ZTGpKEWg.js";import{readToken as t}from"./api-D5XQeEDF.js";import{formatTabular as n,selectFormat as r}from"./formatter-DQ6l4sWM.js";import"./panel-DglZ755S.js";import"./keybar-D2OI-8rx.js";import"./prompt-hjzdzlyj.js";import"./sparkline-CR_bzxwB.js";import{runAnalyticalScreen as i}from"./analytical-screen-CS1ZL5Mo.js";import{Table as a}from"./ui-Bk5nl2yb.js";import{ApiV2Client as o}from"./api-v2-DP5YEHL_.js";import{Box as s,Text as c}from"ink";import l from"react";function u(e,t){let n=Math.round(e*t);return`█`.repeat(Math.max(0,Math.min(t,n)))+`░`.repeat(Math.max(0,t-n))}async function d(d){let p=await e(),m=await t({strict:!1}),h=d.siteId??m?.teamId??``;if(!h)return process.stderr.write(`No site selected — pass --site-id or set ZENOVAY_SITE.
1
+ import{readConfig as e}from"./config-ZTGpKEWg.js";import{readToken as t}from"./api-D5XQeEDF.js";import{formatTabular as n,selectFormat as r}from"./formatter-45-fT1Hv.js";import"./panel-DglZ755S.js";import"./keybar-D2OI-8rx.js";import"./prompt-hjzdzlyj.js";import"./sparkline-CR_bzxwB.js";import{runAnalyticalScreen as i}from"./analytical-screen-CdtZfbes.js";import{Table as a}from"./ui-Bk5nl2yb.js";import{ApiV2Client as o}from"./api-v2-DP5YEHL_.js";import{Box as s,Text as c}from"ink";import l from"react";function u(e,t){let n=Math.round(e*t);return`█`.repeat(Math.max(0,Math.min(t,n)))+`░`.repeat(Math.max(0,t-n))}async function d(d){let p=await e(),m=await t({strict:!1}),h=d.siteId??m?.teamId??``;if(!h)return process.stderr.write(`No site selected — pass --site-id or set ZENOVAY_SITE.
2
2
  `),2;let g=new o({config:p,cliVersion:d.cliVersion,token:m}),_=r(d);if(!d.funnelId){let e=[{key:`name`,header:`name`,width:30},{key:`stepCount`,header:`steps`,width:6,align:`right`},{key:`id`,header:`id`,width:36,format:e=>String(e).slice(0,36)}];return i({cliVersion:d.cliVersion,title:`funnels · ${h}`,commandName:`funnels`,authToken:m?.accessToken??null,refreshIntervalMs:0,fetcher:e=>g.listFunnels(h,e),format:_,headlessEmit:(e,t)=>{if(t===`json`||t===`ndjson`){process.stdout.write(JSON.stringify(e,null,t===`json`?2:0)),t===`ndjson`&&process.stdout.write(`
3
3
  `);return}process.stdout.write(n(e.funnels,[`id`,`name`,`stepCount`],t))},panels:[{id:`funnels`,title:`Funnels`,render:t=>t.funnels.length===0?l.createElement(c,{color:`gray`},`— no funnels defined —`):l.createElement(a,{data:t.funnels,columns:e})},{id:`hint`,title:`Next`,render:()=>l.createElement(c,{color:`gray`},"Run `zenovay funnel <id>` for drop-off detail.")}]})}let v=d.window??`30d`;return i({cliVersion:d.cliVersion,title:`funnel · ${d.funnelId} · ${v}`,commandName:`funnel`,authToken:m?.accessToken??null,refreshIntervalMs:0,fetcher:e=>g.getFunnel(h,d.funnelId,v,e),format:_,headlessEmit:(e,t)=>{if(t===`json`||t===`ndjson`){process.stdout.write(JSON.stringify(e,null,t===`json`?2:0)),t===`ndjson`&&process.stdout.write(`
4
4
  `);return}process.stdout.write(n(e.steps,[`id`,`name`,`visitors`,`conversions`],t))},panels:[{id:`overview`,title:f(`Overview`),render:e=>l.createElement(s,{flexDirection:`column`},l.createElement(c,{bold:!0},e.name),l.createElement(c,{color:`gray`},e.totalEntries.toLocaleString(),` entries · `,e.totalCompletions.toLocaleString(),` completed (`,(e.conversionRate*100).toFixed(1),`%)`))},{id:`flow`,title:`Flow`,render:e=>{let t=e.totalEntries||1;return l.createElement(s,{flexDirection:`column`},e.steps.map((n,r)=>{let i=n.visitors/t,a=e.steps[r-1],o=a?a.visitors-n.visitors:0,d=a?o/Math.max(1,a.visitors)*100:0;return l.createElement(s,{key:n.id,flexDirection:`column`},a?l.createElement(c,{color:`red`},` `,`↓ drop `,o.toLocaleString(),` (`,d.toFixed(1),`%)`):null,l.createElement(c,null,l.createElement(c,{bold:!0},`${r+1}. ${n.name}`.padEnd(22).slice(0,22)),` `,l.createElement(c,{color:`magenta`},u(i,30)),` `,l.createElement(c,null,(i*100).toFixed(1).padStart(5),`% `),l.createElement(c,{color:`gray`},n.visitors.toLocaleString())))}))}}]})}function f(e){return e}export{d as funnelCommand};
@@ -1 +1 @@
1
- import"./config-ZTGpKEWg.js";import"./api-D5XQeEDF.js";import"./formatter-DQ6l4sWM.js";import"./emit-DIRc7UzM.js";import"./panel-DglZ755S.js";import"./check-S0ACFIfq.js";import{HealthReport as e,exitCodeFor as t,healthCommand as n,runHealthChecks as r}from"./health-C6G6Mg6b.js";export{n as healthCommand};
1
+ import"./config-ZTGpKEWg.js";import"./api-D5XQeEDF.js";import"./formatter-45-fT1Hv.js";import"./emit-0WJ_OGeT.js";import"./panel-DglZ755S.js";import"./check-S0ACFIfq.js";import{HealthReport as e,exitCodeFor as t,healthCommand as n,runHealthChecks as r}from"./health-Dxmho1lB.js";export{n as healthCommand};
@@ -1 +1 @@
1
- import{configPath as e,readConfig as t}from"./config-ZTGpKEWg.js";import{ApiClient as n,readToken as r}from"./api-D5XQeEDF.js";import{isHeadless as i}from"./emit-DIRc7UzM.js";import{Panel as a}from"./panel-DglZ755S.js";import{fetchManifest as o}from"./check-S0ACFIfq.js";import s from"node:path";import{promises as c}from"node:fs";import{Box as l,Text as u,render as d}from"ink";import f from"react";import p from"node:os";const m=6*60*60*1e3;function h(){return s.join(p.homedir(),`.zenovay`,`update.json`)}async function g(){try{let e=await c.readFile(h(),`utf8`);return JSON.parse(e)}catch{return null}}async function _(e){let t=h();await c.mkdir(s.dirname(t),{recursive:!0,mode:448}),await c.writeFile(t,JSON.stringify(e,null,2))}async function v(){let e=await t();if(e.noUpdateCheck||process.env.ZENOVAY_NO_UPDATE_CHECK===`1`||process.env.CI===`true`)return null;let n=await g();if(n&&Date.now()-n.fetchedAt<m)return n;try{let t=await o({cliBase:e.cliBase}),r={manifest:t,fetchedAt:Date.now(),lastNoticeAt:n?.lastNoticeAt};return await _(r),r}catch{return n}}async function y(){try{await v()}catch{}process.exit(0)}import.meta.url===`file://${process.argv[1]}`&&y();const b=2e3,x=5e3;async function S(e,t){let n=`${e}/mcp`,r=Date.now(),i=new AbortController,a=setTimeout(()=>i.abort(),b);try{let a=await t(n,{method:`GET`,signal:i.signal}),o=Date.now()-r;return a.ok?{name:`MCP server`,status:`pass`,detail:`${e}/mcp · ${o}ms`,latencyMs:o}:{name:`MCP server`,status:`fail`,detail:`HTTP ${a.status}`,latencyMs:o}}catch(e){return{name:`MCP server`,status:`fail`,detail:e.message}}finally{clearTimeout(a)}}async function C(){try{let t=await c.readFile(e(),`utf8`),n=JSON.parse(t),r=n.openaiApiKey;return typeof r==`string`&&r.trim().length>0?{name:`OpenAI key`,status:`pass`,detail:`configured`}:{name:`OpenAI key`,status:`warn`,detail:"not set (run `zenovay ai` to configure)"}}catch(e){return e.code===`ENOENT`?{name:`OpenAI key`,status:`warn`,detail:`no config file`}:{name:`OpenAI key`,status:`warn`,detail:`unreadable config`}}}async function w(){let e=p.homedir(),t=[s.join(e,`.zshrc`),s.join(e,`.bashrc`),s.join(e,`.config`,`fish`,`completions`,`zenovay.fish`)],n=[];for(let e of t)try{let t=await c.readFile(e,`utf8`);(/zenovay\s+(complet|--?complet)/i.test(t)||/_zenovay/.test(t)||/complete\s+-c\s+zenovay/.test(t))&&n.push(s.basename(e))}catch{}return n.length>0?{name:`Completions`,status:`pass`,detail:n.join(`, `)}:{name:`Completions`,status:`warn`,detail:"not installed (run `zenovay completions` after Wave 3)"}}async function T(e,t,n,r){if(!e||!t)return{name:`Events stream`,status:`skip`,detail:`not authenticated`};let i=new AbortController,a=setTimeout(()=>i.abort(),x),o=Date.now();try{let t=await e.openEventsStream(`probe`,i.signal),r=t.body?.getReader();if(r){let e=Promise.race([r.read().then(()=>`first`),new Promise(e=>setTimeout(()=>e(`timeout`),1500))]);await e;try{r.cancel()}catch{}}let a=Date.now()-o;return{name:`Events stream`,status:`pass`,detail:`${n}/v1/cli/events/tail · ${a}ms`,latencyMs:a}}catch(e){let t=e.message;return/40\d/.test(t)?{name:`Events stream`,status:`pass`,detail:`endpoint reachable (auth-gated)`}:{name:`Events stream`,status:`fail`,detail:t}}finally{clearTimeout(a)}}async function E(i){let a=i.fetchImpl??fetch,o=[],s=await t().catch(()=>null);o.push({name:`Binary`,status:`pass`,detail:`v${i.cliVersion} (${i.binaryPath})`}),o.push({name:`Config file`,status:s?`pass`:`warn`,detail:e()});let c=await r({strict:!1}).catch(()=>null);o.push({name:`Auth`,status:c?`pass`:`fail`,detail:c?`logged in${c.email?` as ${c.email}`:``}`:`not logged in`});let l=null;if(s)try{l=new n({config:s,cliVersion:i.cliVersion,token:c,fetchImpl:a});let e=await l.ping();o.push({name:`API connection`,status:`pass`,detail:`${s.apiBase.replace(/^https?:\/\//,``)} · ${e.latencyMs}ms`,latencyMs:e.latencyMs})}catch(e){o.push({name:`API connection`,status:`fail`,detail:`${e.message}`})}let u=await g().catch(()=>null);o.push({name:`Auto-update`,status:s?.noUpdateCheck?`warn`:`pass`,detail:s?.noUpdateCheck?`disabled`:u?`latest=${u.manifest.latest}`:`manifest not yet fetched`});let d=s?.apiBase??`https://api.zenovay.com`;return o.push(await S(d,a)),o.push(await C()),o.push(await w()),o.push(await T(l,!!c,d,a)),o}function D(e){return e.some(e=>e.status===`fail`)?1:0}async function O(e){let t=await E(e),n=D(t),r=n===0;return i({json:e.json})?(process.stdout.write(`${JSON.stringify({checks:t,passed:r})}\n`),n):new Promise(e=>{let{unmount:r}=d(f.createElement(k,{checks:t}),{exitOnCtrlC:!0});setImmediate(()=>{r(),e(n)})})}const k=({checks:e})=>f.createElement(a,{title:`Zenovay CLI health check`,state:`idle`},e.map(e=>f.createElement(l,{key:e.name},f.createElement(u,{color:j(e.status)},A(e.status)),f.createElement(u,null,` `),f.createElement(u,{bold:!0},e.name.padEnd(18)),f.createElement(u,{color:`gray`},e.detail))));function A(e){return e===`pass`?`✔`:e===`warn`?`⚠`:e===`skip`?`∼`:`✗`}function j(e){return e===`pass`?`green`:e===`warn`?`yellow`:e===`skip`?`gray`:`red`}export{k as HealthReport,D as exitCodeFor,O as healthCommand,E as runHealthChecks};
1
+ import{configPath as e,readConfig as t}from"./config-ZTGpKEWg.js";import{ApiClient as n,readToken as r}from"./api-D5XQeEDF.js";import{isHeadless as i}from"./emit-0WJ_OGeT.js";import{Panel as a}from"./panel-DglZ755S.js";import{fetchManifest as o}from"./check-S0ACFIfq.js";import s from"node:path";import{promises as c}from"node:fs";import{Box as l,Text as u,render as d}from"ink";import f from"react";import p from"node:os";const m=6*60*60*1e3;function h(){return s.join(p.homedir(),`.zenovay`,`update.json`)}async function g(){try{let e=await c.readFile(h(),`utf8`);return JSON.parse(e)}catch{return null}}async function _(e){let t=h();await c.mkdir(s.dirname(t),{recursive:!0,mode:448}),await c.writeFile(t,JSON.stringify(e,null,2))}async function v(){let e=await t();if(e.noUpdateCheck||process.env.ZENOVAY_NO_UPDATE_CHECK===`1`||process.env.CI===`true`)return null;let n=await g();if(n&&Date.now()-n.fetchedAt<m)return n;try{let t=await o({cliBase:e.cliBase}),r={manifest:t,fetchedAt:Date.now(),lastNoticeAt:n?.lastNoticeAt};return await _(r),r}catch{return n}}async function y(){try{await v()}catch{}process.exit(0)}import.meta.url===`file://${process.argv[1]}`&&y();const b=2e3,x=5e3;async function S(e,t){let n=`${e}/mcp`,r=Date.now(),i=new AbortController,a=setTimeout(()=>i.abort(),b);try{let a=await t(n,{method:`GET`,signal:i.signal}),o=Date.now()-r;return a.ok?{name:`MCP server`,status:`pass`,detail:`${e}/mcp · ${o}ms`,latencyMs:o}:{name:`MCP server`,status:`fail`,detail:`HTTP ${a.status}`,latencyMs:o}}catch(e){return{name:`MCP server`,status:`fail`,detail:e.message}}finally{clearTimeout(a)}}async function C(){try{let t=await c.readFile(e(),`utf8`),n=JSON.parse(t),r=n.openaiApiKey;return typeof r==`string`&&r.trim().length>0?{name:`OpenAI key`,status:`pass`,detail:`configured`}:{name:`OpenAI key`,status:`warn`,detail:"not set (run `zenovay ai` to configure)"}}catch(e){return e.code===`ENOENT`?{name:`OpenAI key`,status:`warn`,detail:`no config file`}:{name:`OpenAI key`,status:`warn`,detail:`unreadable config`}}}async function w(){let e=p.homedir(),t=[s.join(e,`.zshrc`),s.join(e,`.bashrc`),s.join(e,`.config`,`fish`,`completions`,`zenovay.fish`)],n=[];for(let e of t)try{let t=await c.readFile(e,`utf8`);(/zenovay\s+(complet|--?complet)/i.test(t)||/_zenovay/.test(t)||/complete\s+-c\s+zenovay/.test(t))&&n.push(s.basename(e))}catch{}return n.length>0?{name:`Completions`,status:`pass`,detail:n.join(`, `)}:{name:`Completions`,status:`warn`,detail:"not installed (run `zenovay completions` after Wave 3)"}}async function T(e,t,n,r){if(!e||!t)return{name:`Events stream`,status:`skip`,detail:`not authenticated`};let i=new AbortController,a=setTimeout(()=>i.abort(),x),o=Date.now();try{let t=await e.openEventsStream(`probe`,i.signal),r=t.body?.getReader();if(r){let e=Promise.race([r.read().then(()=>`first`),new Promise(e=>setTimeout(()=>e(`timeout`),1500))]);await e;try{r.cancel()}catch{}}let a=Date.now()-o;return{name:`Events stream`,status:`pass`,detail:`${n}/v1/cli/events/tail · ${a}ms`,latencyMs:a}}catch(e){let t=e.message;return/40\d/.test(t)?{name:`Events stream`,status:`pass`,detail:`endpoint reachable (auth-gated)`}:{name:`Events stream`,status:`fail`,detail:t}}finally{clearTimeout(a)}}async function E(i){let a=i.fetchImpl??fetch,o=[],s=await t().catch(()=>null);o.push({name:`Binary`,status:`pass`,detail:`v${i.cliVersion} (${i.binaryPath})`}),o.push({name:`Config file`,status:s?`pass`:`warn`,detail:e()});let c=await r({strict:!1}).catch(()=>null);o.push({name:`Auth`,status:c?`pass`:`fail`,detail:c?`logged in${c.email?` as ${c.email}`:``}`:`not logged in`});let l=null;if(s)try{l=new n({config:s,cliVersion:i.cliVersion,token:c,fetchImpl:a});let e=await l.ping();o.push({name:`API connection`,status:`pass`,detail:`${s.apiBase.replace(/^https?:\/\//,``)} · ${e.latencyMs}ms`,latencyMs:e.latencyMs})}catch(e){o.push({name:`API connection`,status:`fail`,detail:`${e.message}`})}let u=await g().catch(()=>null);o.push({name:`Auto-update`,status:s?.noUpdateCheck?`warn`:`pass`,detail:s?.noUpdateCheck?`disabled`:u?`latest=${u.manifest.latest}`:`manifest not yet fetched`});let d=s?.apiBase??`https://api.zenovay.com`;return o.push(await S(d,a)),o.push(await C()),o.push(await w()),o.push(await T(l,!!c,d,a)),o}function D(e){return e.some(e=>e.status===`fail`)?1:0}async function O(e){let t=await E(e),n=D(t),r=n===0;return i({json:e.json})?(process.stdout.write(`${JSON.stringify({checks:t,passed:r})}\n`),n):new Promise(e=>{let{unmount:r}=d(f.createElement(k,{checks:t}),{exitOnCtrlC:!0});setImmediate(()=>{r(),e(n)})})}const k=({checks:e})=>f.createElement(a,{title:`Zenovay CLI health check`,state:`idle`},e.map(e=>f.createElement(l,{key:e.name},f.createElement(u,{color:j(e.status)},A(e.status)),f.createElement(u,null,` `),f.createElement(u,{bold:!0},e.name.padEnd(18)),f.createElement(u,{color:`gray`},e.detail))));function A(e){return e===`pass`?`✔`:e===`warn`?`⚠`:e===`skip`?`∼`:`✗`}function j(e){return e===`pass`?`green`:e===`warn`?`yellow`:e===`skip`?`gray`:`red`}export{k as HealthReport,D as exitCodeFor,O as healthCommand,E as runHealthChecks};
@@ -0,0 +1,61 @@
1
+ import{readConfig as e}from"./config-ZTGpKEWg.js";import{ApiClient as t,readToken as n}from"./api-D5XQeEDF.js";import{parseSseStream as r}from"./client-DZ4Awt8u.js";import{emit as i,isHeadless as a}from"./emit-0WJ_OGeT.js";import{loginCommand as o}from"./login--p3mI2F6.js";import{Panel as s}from"./panel-DglZ755S.js";import{Banner as c,BrandGradient as l,Keybar as u}from"./keybar-D2OI-8rx.js";import{Select as d}from"./prompt-hjzdzlyj.js";import{spark as f}from"./sparkline-CR_bzxwB.js";import p from"node:path";import{promises as m}from"node:fs";import{Box as h,Text as g,render as _,useApp as v,useInput as y}from"ink";import b,{useEffect as x,useRef as ee,useState as S}from"react";import C from"node:os";import{z as w}from"zod";import{globby as T}from"globby";import E from"ink-spinner";import D from"node:crypto";import{ulid as O}from"ulid";import{applyPatch as k}from"diff";const A=[`@zenovay/tracker`,`@zenovay/next`,`@zenovay/nuxt`,`@zenovay/svelte`,`@zenovay/astro`,`@zenovay/remix`,`@zenovay/node`],j=[`zenovay.config.ts`,`zenovay.config.js`,`zenovay.config.mjs`,`zenovay.config.json`],M=/api\.zenovay\.com\/z\.js|cdn\.zenovay\.com\/t\.js/,N=/data-zenovay-site|data-id\s*=\s*"ZV_/;async function P(e){let t=[],n={installed:!1,reasons:t};try{let r=await m.readFile(p.join(e,`package.json`),`utf8`),i=JSON.parse(r),a={...i.dependencies,...i.devDependencies};for(let e of A)if(e in a){t.push(`dep:${e}`),n.packageMarker=e,n.installed=!0;break}}catch{}for(let r of j)try{await m.access(p.join(e,r)),t.push(`config:${r}`),n.configFile=r,n.installed=!0;break}catch{}try{let r=await T([`**/*.{html,htm,tsx,jsx,vue,svelte,astro,ts,js,mjs}`,`!node_modules/**`,`!.git/**`,`!dist/**`,`!.next/**`,`!.nuxt/**`,`!build/**`,`!.output/**`],{cwd:e,gitignore:!0,deep:4,absolute:!0});for(let i of r.slice(0,200))try{let r=await m.readFile(i,`utf8`);if(M.test(r)||N.test(r)){t.push(`script:${p.relative(e,i)}`),n.scriptFile=p.relative(e,i),n.installed=!0;break}}catch{}}catch{}return n}const F=[{name:`openai-proj`,regex:/\bsk-proj-[A-Za-z0-9_-]{20,}\b/g},{name:`anthropic`,regex:/\bsk-ant-[A-Za-z0-9_-]{20,}\b/g},{name:`openai-sk`,regex:/\bsk-[A-Za-z0-9]{20,}\b/g},{name:`github-pat-new`,regex:/\bgithub_pat_[A-Za-z0-9_]{82}\b/g},{name:`github-pat`,regex:/\bghp_[A-Za-z0-9]{36}\b/g},{name:`github-oauth`,regex:/\bgho_[A-Za-z0-9]{36}\b/g},{name:`aws-access-key`,regex:/\b(?:AKIA|ASIA)[A-Z0-9]{16}\b/g},{name:`stripe-live`,regex:/\b(?:sk|pk)_live_[A-Za-z0-9]{24,}\b/g},{name:`stripe-test`,regex:/\b(?:sk|pk)_test_[A-Za-z0-9]{24,}\b/g},{name:`stripe-restricted`,regex:/\brk_(?:live|test)_[A-Za-z0-9]{24,}\b/g},{name:`stripe-webhook`,regex:/\bwhsec_[A-Za-z0-9]{24,}\b/g},{name:`slack-bot`,regex:/\bxox[bpoa]-[A-Za-z0-9-]{10,}\b/g},{name:`google-api`,regex:/\bAIza[0-9A-Za-z_-]{35}\b/g},{name:`jwt`,regex:/\beyJ[A-Za-z0-9_-]+\.eyJ[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\b/g},{name:`private-key-rsa`,regex:/-----BEGIN (?:RSA|EC|OPENSSH|DSA|PGP) PRIVATE KEY(?: BLOCK)?-----/g},{name:`private-key-pkcs8`,regex:/-----BEGIN PRIVATE KEY-----/g}];function I(e){let t=e;for(let e of F){let n=new RegExp(e.regex.source,e.regex.flags);t=t.replace(n,`[REDACTED:${e.name}]`)}return t}const L=[/^package\.json$/,/^package-lock\.json$/,/^pnpm-lock\.yaml$/,/^yarn\.lock$/,/^bun\.lock$/,/^tsconfig.*\.json$/,/^(next|nuxt|vite|astro|remix|svelte|tailwind|postcss)\.config\.(ts|mts|cts|js|mjs|cjs)$/,/^app\/.*\.(tsx|ts|jsx|js|svelte|astro|vue)$/,/^pages\/.*\.(tsx|ts|jsx|js)$/,/^public\/index\.html$/,/^index\.html$/,/^src\/main\.(tsx|ts|jsx|js)$/,/^src\/App\.(tsx|ts|jsx|js|svelte|vue)$/,/^src\/routes\/\+layout\.(svelte|ts|js)$/,/^src\/routes\/root\..*$/,/^src\/layouts\/.*\.(astro|svelte|vue)$/,/^\.env\.example$/,/^README\.md$/,/^\.gitignore$/,/^nuxt\.config\.(ts|js|mjs)$/,/^plugins\/.*\.(ts|js)$/],te=[/(^|\/)\.env($|\.(?!example$)[^/]+$)/,/(^|\/)\.git(\/|$)/,/(^|\/)node_modules\//,/(^|\/)\.ssh\//,/(^|\/)\.aws\//,/\.pem$/,/\.key$/,/(^|\/)id_rsa($|\.)/,/(^|\/)\.npmrc$/,/(^|\/)credentials(\.|$)/],R=256*1024,z=50,B=20,V=40;var H=class extends Error{constructor(e,t){super(t),this.code=e,this.name=`SandboxError`}},U=class{sessionId;cwd;cwdReal;undoRoot;readCount=0;writeCount=0;roundCount=0;constructor(e){this.sessionId=e.sessionId??O(),this.cwd=e.cwd,this.cwdReal=m.realpath(e.cwd),this.undoRoot=e.undoRoot??p.join(C.homedir(),`.zenovay`,`undo`)}incrementRound(){if(this.roundCount++,this.roundCount>V)throw new H(`round-cap`,`Tool-call recursion cap (${V}) exceeded.`)}stats(){return{sessionId:this.sessionId,reads:this.readCount,writes:this.writeCount,rounds:this.roundCount}}async resolveForRead(e){return this.resolveSafe(e,`read`)}async resolveForWrite(e){return this.resolveSafe(e,`write`)}async resolveSafe(e,t){if(typeof e!=`string`||e.length===0)throw new H(`escape`,`Path must be a non-empty string.`);if(e.includes(`\0`))throw new H(`escape`,`Null byte in path.`);if(/^\\\\[?.]\\/.test(e)||/^\\\\[A-Za-z0-9]/.test(e))throw new H(`escape`,`Windows special path prefix: ${e}`);if(/%/.test(e))try{let t=decodeURIComponent(e);if(/%[0-9A-Fa-f]{2}/.test(t))throw new H(`escape`,`Double-encoded path: ${e}`);e=t}catch(t){throw t instanceof H?t:new H(`escape`,`Malformed percent-encoding: ${e}`)}if(e.includes(`\0`))throw new H(`escape`,`Null byte in decoded path.`);if(e.includes(`\\`))throw new H(`escape`,`Backslash in path (Windows-style separator not accepted): ${e}`);let n=await this.cwdReal,r=p.isAbsolute(e)?e:p.join(n,e),i=p.normalize(r),a=i;try{a=await m.realpath(i)}catch(e){if(e.code!==`ENOENT`)throw new H(`escape`,`realpath failed: ${e.message}`);let t=p.dirname(i);try{let e=await m.realpath(t);a=p.join(e,p.basename(i))}catch{}}if(!this.isWithin(a,n))throw new H(`escape`,`Path escapes cwd: ${e}`);let o=p.relative(n,a);for(let e of te)if(e.test(o)){if(t===`read`&&/(^|\/)node_modules\//.test(o))continue;throw new H(`blocklisted`,`Path is on the hard blocklist: ${o}`)}if(t===`write`){let e=L.some(e=>e.test(o));if(!e&&!/^\.env(\.local)?$/.test(o)&&!/^\.claude\//.test(o)&&!/^\.cursor\//.test(o))throw new H(`not-allowlisted`,`Write path not on allowlist: ${o}`)}return a}isWithin(e,t){let n=p.relative(t,e);return!n.startsWith(`..`)&&!p.isAbsolute(n)}async safeRead(e){if(this.readCount>=z)throw new H(`read-cap`,`Read cap (${z}) reached.`);let t=await this.resolveForRead(e),n=await m.stat(t);if(n.size>R)throw new H(`too-large`,`File exceeds ${R}B: ${e} (${n.size}B)`);let r=await m.readFile(t),i=r.subarray(0,Math.min(r.length,8192));if(i.includes(0))throw new H(`binary-rejected`,`Binary content in ${e}.`);return this.readCount++,r.toString(`utf8`)}async safeWrite(e,t){if(this.writeCount>=B)throw new H(`write-cap`,`Write cap (${B}) reached.`);if(t.length>R)throw new H(`too-large`,`Write exceeds ${R}B: ${e}`);let n=await this.resolveForWrite(e),r=await this.journalBackup(n);return await m.mkdir(p.dirname(n),{recursive:!0}),await m.writeFile(n,t,`utf8`),this.writeCount++,{backupPath:r}}async journalBackup(e){let t=await m.readFile(e).catch(e=>{if(e.code===`ENOENT`)return null;throw e}),n=p.join(this.undoRoot,this.sessionId);await m.mkdir(n,{recursive:!0,mode:448});let r=D.createHash(`sha256`).update(e).digest(`hex`).slice(0,16),i=p.join(n,`${r}.bak`),a=p.join(n,`manifest.jsonl`);t&&await m.writeFile(i,t,{mode:384});let o=JSON.stringify({abs:e,backupPath:t?i:null,ts:Date.now()});return await m.appendFile(a,o+`
2
+ `,{mode:384}),t?i:null}static wrapForModel(e,t){let n=D.createHash(`sha256`).update(t).digest(`hex`).slice(0,16),r=t.replaceAll(`&`,`&amp;`).replaceAll(`<`,`&lt;`).replaceAll(`>`,`&gt;`);return`<FILE path="${e}" sha256="${n}">\n${r}\n</FILE>`}static scrubSecrets(e){return I(e)}};const ne=[`astro.config.ts`,`astro.config.mjs`,`astro.config.js`];async function re(e){for(let t of ne)if(await e.exists(t))return{matched:!0,confidence:.95,reason:`Detected Astro via \`${t}\`.`};let t=await e.readFile(`package.json`);if(t)try{let e=JSON.parse(t);if(e.dependencies?.astro??e.devDependencies?.astro)return{matched:!0,confidence:.8,reason:"Detected Astro via `astro` dependency."}}catch{}return{matched:!1,confidence:0,reason:"No astro.config.* or `astro` dependency found."}}function ie(e){let t=e.trackingCode??e.siteId??``,n=`<script defer data-id="${t}" data-allow-localhost="true" src="https://api.zenovay.com/z.js" is:inline></script>`;return[{targetPath:`src/layouts/Layout.astro`,anchorKind:`head-tag`,code:n,description:`Inject the Zenovay tracker inside <head> of the primary layout.`},{targetPath:`src/layouts/BaseHead.astro`,anchorKind:`head-tag`,code:n,description:"Fallback target when the project uses a dedicated `BaseHead.astro`."}]}const ae={id:`astro`,displayName:`Astro`,detect:re,files:[{path:`src/layouts/Layout.astro`,kind:`mutate`,required:!1},{path:`src/layouts/BaseHead.astro`,kind:`mutate`,required:!1},{path:`.env`,kind:`create`,required:!0}],envVarName:`PUBLIC_ZENOVAY_SITE`,buildSnippets:ie},oe=[`app/layout.tsx`,`app/layout.ts`,`app/layout.jsx`,`app/layout.js`];async function se(e){for(let t of oe)if(await e.exists(t))return t;return null}async function ce(e){let t=await e.readFile(`package.json`);if(!t)return!1;try{let e=JSON.parse(t);return!!(e.dependencies?.next??e.devDependencies?.next)}catch{return!1}}async function le(e){let t=await ce(e),n=await e.exists(`app`),r=await se(e);return t?n?r?{matched:!0,confidence:.95,reason:`Detected Next.js App Router via \`next\` dep + \`${r}\`.`}:{matched:!1,confidence:.4,reason:"Found `app/` but no root layout file (layout.tsx/ts/jsx/js)."}:{matched:!1,confidence:0,reason:"No `app/` directory found — not an App Router project."}:{matched:!1,confidence:0,reason:"package.json does not list `next` as a dependency."}}function ue(e){let t=`app/layout.tsx`,n=e.trackingCode??e.siteId??``;return[{targetPath:t,anchorKind:`after-imports`,code:`import Script from 'next/script';`,description:`Import next/script to inject the Zenovay tracker.`},{targetPath:t,anchorKind:`wrap-children`,code:`<Script
3
+ defer
4
+ data-id="${n}"
5
+ data-allow-localhost="true"
6
+ src="https://api.zenovay.com/z.js"
7
+ strategy="afterInteractive"
8
+ />
9
+ {children}`,description:`Add the Zenovay tracker <Script> next to children in the root layout.`}]}const de={id:`next-app-router`,displayName:`Next.js (App Router)`,detect:le,files:[{path:`app/layout.tsx`,kind:`mutate`,required:!0}],envVarName:`NEXT_PUBLIC_ZENOVAY_SITE`,buildSnippets:ue},fe=[`pages/_app.tsx`,`pages/_app.ts`,`pages/_app.jsx`,`pages/_app.js`,`src/pages/_app.tsx`,`src/pages/_app.ts`,`src/pages/_app.jsx`,`src/pages/_app.js`];async function pe(e){for(let t of fe)if(await e.exists(t))return t;return null}async function me(e){let t=await e.readFile(`package.json`);if(!t)return!1;try{let e=JSON.parse(t);return!!(e.dependencies?.next??e.devDependencies?.next)}catch{return!1}}async function he(e){let t=await me(e);if(!t)return{matched:!1,confidence:0,reason:"package.json does not list `next` as a dependency."};let n=await pe(e);if(n)return{matched:!0,confidence:.9,reason:`Detected Next.js Pages Router via \`${n}\`.`};let r=await e.exists(`app`),i=await e.glob(`pages/**/*.{tsx,ts,jsx,js}`);return i.length>0&&!r?{matched:!0,confidence:.7,reason:"Found `pages/` directory with route files but no `_app` — will create one."}:{matched:!1,confidence:.2,reason:`Next.js detected, but no pages-router entry point found.`}}function ge(e){let t=`pages/_app.tsx`,n=e.trackingCode??e.siteId??``,r=`import type { AppProps } from 'next/app';
10
+ import Script from 'next/script';
11
+
12
+ export default function App({ Component, pageProps }: AppProps) {
13
+ return (
14
+ <>
15
+ <Script
16
+ defer
17
+ data-id="${n}"
18
+ data-allow-localhost="true"
19
+ src="https://api.zenovay.com/z.js"
20
+ strategy="afterInteractive"
21
+ />
22
+ <Component {...pageProps} />
23
+ </>
24
+ );
25
+ }
26
+ `;return[{targetPath:t,anchorKind:`after-imports`,code:`import Script from 'next/script';`,description:"Import next/script in `_app`."},{targetPath:t,anchorKind:`wrap-children`,code:`<><Script defer data-id="${n}" data-allow-localhost="true" src="https://api.zenovay.com/z.js" strategy="afterInteractive" /><Component {...pageProps} /></>`,description:`Render the Zenovay tracker alongside the page component.`},{targetPath:t,anchorKind:`replace-file`,code:r,description:"Full replacement when `_app` does not exist yet."}]}const _e={id:`next-pages-router`,displayName:`Next.js (Pages Router)`,detect:he,files:[{path:`pages/_app.tsx`,kind:`mutate`,required:!0}],envVarName:`NEXT_PUBLIC_ZENOVAY_SITE`,buildSnippets:ge},ve=w.object({modules:w.array(w.string()).optional(),runtimeConfig:w.object({public:w.record(w.string(),w.unknown()).optional()}).optional()}).passthrough();async function ye(e){let t=await e.readFile(`package.json`);if(!t)return{matched:!1,confidence:0,reason:`No package.json found.`};try{let e=JSON.parse(t),n=!!(e.dependencies?.nuxt??e.devDependencies?.nuxt??e.dependencies?.nuxt3??e.devDependencies?.nuxt3);if(n)return{matched:!0,confidence:.95,reason:"Detected Nuxt via `nuxt` / `nuxt3` dependency."}}catch{}let n=await e.exists(`nuxt.config.ts`)||await e.exists(`nuxt.config.js`)||await e.exists(`nuxt.config.mjs`);return n?{matched:!0,confidence:.6,reason:"Found `nuxt.config.*` but no explicit dependency listing."}:{matched:!1,confidence:0,reason:`No Nuxt dependency or config detected.`}}function be(e){let t=e.trackingCode??e.siteId??``,n=` app: {
27
+ head: {
28
+ script: [
29
+ {
30
+ defer: true,
31
+ src: 'https://api.zenovay.com/z.js',
32
+ 'data-id': '${t}',
33
+ 'data-allow-localhost': 'true',
34
+ },
35
+ ],
36
+ },
37
+ },`;return[{targetPath:`nuxt.config.ts`,anchorKind:`head-tag`,code:n,description:"Add the Zenovay tracker to Nuxt's `app.head.script` so every page loads it."}]}const xe={id:`nuxt`,displayName:`Nuxt`,detect:ye,files:[{path:`nuxt.config.ts`,kind:`mutate`,required:!0}],envVarName:`NUXT_PUBLIC_ZENOVAY_SITE`,buildSnippets:be},Se=[`index.html`,`public/index.html`,`dist/index.html`];async function Ce(e){for(let t of Se)if(await e.exists(t))return{matched:!0,confidence:.5,reason:`Detected plain HTML project via \`${t}\`.`};let t=await e.glob(`**/*.html`);return t.length>0?{matched:!0,confidence:.3,reason:`Found ${t.length} HTML file(s); plain-HTML adapter is usable as fallback.`}:{matched:!1,confidence:0,reason:`No HTML files found in the project.`}}function we(e){let t=e.siteId??``,n=`<script defer\n data-id="${t}"\n data-allow-localhost="true"\n src="https://api.zenovay.com/z.js">\n</script>`;return[{targetPath:`index.html`,anchorKind:`head-tag`,code:n,description:`Inject the Zenovay tracker inside <head>. Repeat for every HTML file that contains a <head>.`}]}const Te={id:`plain-html`,displayName:`Plain HTML`,detect:Ce,files:[{path:`index.html`,kind:`mutate`,required:!0}],envVarName:`PUBLIC_ZENOVAY_SITE`,buildSnippets:we};async function Ee(e){let t=await e.readFile(`package.json`);if(t)try{let e=JSON.parse(t),n={...e.dependencies??{},...e.devDependencies??{}},r=Object.keys(n).some(e=>e.startsWith(`@remix-run/`));if(r)return{matched:!0,confidence:.95,reason:"Detected Remix via `@remix-run/*` dependencies."}}catch{}return await e.exists(`remix.config.js`)||await e.exists(`remix.config.ts`)?{matched:!0,confidence:.8,reason:"Detected Remix via `remix.config.*`."}:{matched:!1,confidence:0,reason:`No Remix dependency or config detected.`}}function De(e){let t=e.trackingCode??e.siteId??``;return[{targetPath:`app/root.tsx`,anchorKind:`head-tag`,code:`<script defer data-id="${t}" data-allow-localhost="true" src="https://api.zenovay.com/z.js"></script>`,description:`Inline the Zenovay tracker <script> inside the document <head>.`}]}const Oe={id:`remix`,displayName:`Remix`,detect:Ee,files:[{path:`app/root.tsx`,kind:`mutate`,required:!0}],envVarName:`PUBLIC_ZENOVAY_SITE`,buildSnippets:De};async function ke(e){let t=await e.readFile(`package.json`);if(!t)return{matched:!1,confidence:0,reason:`No package.json found.`};try{let e=JSON.parse(t),n=!!(e.dependencies?.[`@sveltejs/kit`]??e.devDependencies?.[`@sveltejs/kit`]);return n?{matched:!0,confidence:.95,reason:"Detected SvelteKit via `@sveltejs/kit` dependency."}:{matched:!1,confidence:0,reason:"`@sveltejs/kit` not in dependencies."}}catch{return{matched:!1,confidence:0,reason:`package.json is not valid JSON.`}}}function Ae(e){let t=e.trackingCode??e.siteId??``,n=`<svelte:head>
38
+ <script defer data-id="${t}" data-allow-localhost="true" src="https://api.zenovay.com/z.js"></script>
39
+ </svelte:head>
40
+
41
+ <slot />
42
+ `;return[{targetPath:`src/routes/+layout.svelte`,anchorKind:`replace-file`,code:n,description:`Root layout that loads the Zenovay tracker in every route via <svelte:head>.`}]}const je={id:`sveltekit`,displayName:`SvelteKit`,detect:ke,files:[{path:`src/routes/+layout.svelte`,kind:`mutate`,required:!0}],envVarName:`PUBLIC_ZENOVAY_SITE`,buildSnippets:Ae},Me=[de,_e,xe,je,ae,Oe,Te];async function W(e){let t=[];for(let n of Me){let r=await n.detect(e);t.push({adapter:n,result:r})}let n=[...t].sort((e,t)=>t.result.confidence-e.result.confidence),r=n[0],i=r&&r.result.matched?r.adapter:null;return{adapter:i,ranked:n}}function G(e){let t=t=>p.resolve(e,t);return{cwd:e,async readFile(e){try{return await m.readFile(t(e),`utf8`)}catch(e){let t=e.code;if(t===`ENOENT`||t===`EISDIR`)return null;throw e}},async exists(e){try{return await m.access(t(e)),!0}catch{return!1}},async glob(t){return T(t,{cwd:e,dot:!1,gitignore:!0,onlyFiles:!0,followSymbolicLinks:!1})}}}async function K(e,t){let n=G(e),{adapter:r,ranked:i}=await W(n),a=i[0];return r&&a&&a.result.confidence>=.7?r:t?t.pickInteractively(i):r}function Ne(e,t){let n=/[\s"'#=]/.test(t)||t===``,r=n?`"${t.replace(/\\/g,`\\\\`).replace(/"/g,`\\"`)}"`:t;return`${e}=${r}`}function Pe(e){let t=new Set;for(let n of e.split(/\r?\n/)){let e=n.trim();if(!e||e.startsWith(`#`))continue;let r=e.indexOf(`=`);if(r<=0)continue;let i=e.slice(0,r).trim();/^[A-Za-z_][A-Za-z0-9_]*$/.test(i)&&t.add(i)}return t}async function q(e,t,n={}){let r=n.filename??`.env.local`,i=p.resolve(e,r),a=``,o=!0;try{a=await m.readFile(i,`utf8`)}catch(e){if(e.code===`ENOENT`)o=!1;else throw e}let s=o?Pe(a):new Set,c=[],l=[],u=[];for(let[e,n]of Object.entries(t)){if(s.has(e)){l.push(e);continue}u.push(Ne(e,n)),c.push(e)}if(c.length===0)return{created:!1,existing:o,addedKeys:c,skippedKeys:l};let d=`# Added by Zenovay CLI`,f;if(o){let e=a.length>0&&!a.endsWith(`
43
+ `);f=a+(e?`
44
+ `:``)+`
45
+ `+d+`
46
+ `+u.join(`
47
+ `)+`
48
+ `}else f=d+`
49
+ `+u.join(`
50
+ `)+`
51
+ `;if(o)await m.writeFile(i,f,`utf8`);else{let e=await m.open(i,`w`,384);try{await e.writeFile(f,`utf8`)}finally{await e.close()}}return{created:!o,existing:o,addedKeys:c,skippedKeys:l}}const Fe=`https://api.zenovay.com/mcp`,Ie=w.object({url:w.string().url(),headers:w.record(w.string(),w.string()).optional()}),Le=w.object({mcpServers:w.record(w.string(),Ie).optional()}).passthrough();function Re(e){return e.HOME??e.USERPROFILE??C.homedir()}function ze(e){return e.APPDATA??null}function Be(e,t){let n=Re(t),r=ze(t),i=[];return i.push({id:`cursor`,displayName:`Cursor`,configPath:p.join(n,`.cursor`,`mcp.json`)}),e===`win32`&&r&&i.push({id:`cursor`,displayName:`Cursor (AppData)`,configPath:p.join(r,`Cursor`,`User`,`globalStorage`,`cursor.mcp`,`mcp.json`)}),e===`darwin`?i.push({id:`claude-desktop`,displayName:`Claude Desktop`,configPath:p.join(n,`Library`,`Application Support`,`Claude`,`claude_desktop_config.json`)}):e===`win32`&&r?i.push({id:`claude-desktop`,displayName:`Claude Desktop`,configPath:p.join(r,`Claude`,`claude_desktop_config.json`)}):i.push({id:`claude-desktop`,displayName:`Claude Desktop`,configPath:p.join(n,`.config`,`Claude`,`claude_desktop_config.json`)}),i.push({id:`vscode`,displayName:`VS Code`,configPath:p.join(n,`.vscode`,`mcp.json`)}),i}async function Ve(e){try{return await m.access(e),!0}catch{return!1}}async function He(e){try{let t=await m.readFile(e,`utf8`);if(t.trim().length===0)return{};let n=JSON.parse(t),r=Le.safeParse(n);return r.success?r.data:n&&typeof n==`object`?n:{}}catch{return{}}}function Ue(e){return{url:Fe,headers:{Authorization:`Bearer ${e}`}}}async function J(e){let t=e.env??process.env,n=e.platform??process.platform,r=new Set(e.skip??[]),i=[],a=[],o=[],s=new Set,c=Ue(e.accessToken);for(let e of Be(n,t)){if(r.has(e.id)){a.push(e.displayName);continue}if(s.has(e.configPath))continue;s.add(e.configPath);try{let t=await Ve(e.configPath);if(!t){a.push(e.displayName);continue}let n=await He(e.configPath),r=`${e.configPath}.bak`;await m.copyFile(e.configPath,r);let o={...n,mcpServers:{...n.mcpServers??{},zenovay:c}};await m.mkdir(p.dirname(e.configPath),{recursive:!0}),await m.writeFile(e.configPath,JSON.stringify(o,null,2)+`
52
+ `,`utf8`),i.push(e.displayName)}catch(t){o.push({client:e.displayName,message:t instanceof Error?t.message:String(t)})}}return{installed:i,skipped:a,errors:o}}async function We(e,t,n){let r=n.timeoutMs??18e4,i=n.pollIntervalMs??2e3,a=n.now??(()=>Date.now()),o=n.sleep??(e=>new Promise(t=>setTimeout(t,e))),s=a(),c=s+r;for(n.onTick?.(0);;){let l=await n.api.getFirstEvent({siteId:e,since:t});if(l.received)return{received:!0,event:l.event};let u=a()-s;if(u>=r)return{received:!1};let d=c-a(),f=Math.min(i,Math.max(0,d));if(f<=0)return{received:!1};await o(f),n.onTick?.(a()-s)}}const Ge=w.object({path:w.string().min(1)}),Ke=w.object({path:w.string().min(1),content:w.string(),reason:w.string().min(1)}),qe=w.object({path:w.string().min(1),patch:w.string().min(1),reason:w.string().min(1)}),Je=w.object({}),Ye=w.object({question:w.string().min(1),choices:w.array(w.string()).optional()});async function Xe(e,t){let n=Ge.safeParse(t);if(!n.success)return{ok:!1,content:null,error:`invalid_args`};try{let t=await e.safeRead(n.data.path),r=U.scrubSecrets(t);return{ok:!0,content:U.wrapForModel(n.data.path,r)}}catch(e){return{ok:!1,content:null,error:e.message}}}async function Y(e,t,n){let r=Ke.safeParse(t);if(!r.success)return{ok:!1,content:null,error:`invalid_args`};let{path:i,content:a,reason:o}=r.data,s=``;try{s=await e.safeRead(i)}catch{s=``}let c=await n.approve({path:i,oldContent:s,newContent:a,reason:o});if(c===`n`)return{ok:!1,content:null,error:`skipped_by_user`};if(c===`e`)return{ok:!1,content:null,error:`deferred_to_user_edit`};try{let{backupPath:t}=await e.safeWrite(i,a);return{ok:!0,content:{path:i,backupPath:t}}}catch(e){return{ok:!1,content:null,error:e.message}}}async function Ze(e,t,n){let r=qe.safeParse(t);if(!r.success)return{ok:!1,content:null,error:`invalid_args`};let{path:i,patch:a,reason:o}=r.data,s;try{s=await e.safeRead(i)}catch(e){return{ok:!1,content:null,error:e.message}}let c=k(s,a);return c===!1||typeof c!=`string`?{ok:!1,content:null,error:`patch_did_not_apply_cleanly`}:Y(e,{path:i,content:c,reason:o},n)}async function Qe(e){try{let t=G(e),{adapter:n,ranked:r}=await W(t);return{ok:!0,content:{matched:n!==null,adapter:n?.id,displayName:n?.displayName,ranked:r.map(e=>({id:e.adapter.id,confidence:e.result.confidence,reason:e.result.reason}))}}}catch(e){return{ok:!1,content:null,error:e.message}}}async function $e(e,t){let n=Ye.safeParse(t);if(!n.success)return{ok:!1,content:null,error:`invalid_args`};try{let t=await e.ask(n.data);return{ok:!0,content:{answer:t}}}catch(e){return{ok:!1,content:null,error:e.message}}}async function et(e){let{api:t,sandbox:n,approval:i,prompter:a,handlers:o}=e,s=[...e.initialMessages],c=``,l=0;for(;l<V;){n.incrementRound(),l++;let e=await t.openAiStream(`install`,{messages:s,cwd_fingerprint:n.sessionId}),u=[],d=``;for await(let t of r(e))switch(t.type){case`delta`:d+=t.content,o?.onDelta?.(t.content);break;case`tool_start`:o?.onToolStart?.({id:t.id,name:t.name});break;case`tool_call`:{let e=await tt(t.name,t.arguments,{sandbox:n,cwd:n.cwd,approval:i,prompter:a});u.push({id:t.id,name:t.name,arguments:t.arguments,result:e}),o?.onToolResult?.({id:t.id,name:t.name,result:e});break}case`usage`:o?.onUsage?.(t);break;case`error`:throw o?.onError?.(t),Error(`[${t.code}] ${t.message}`);case`done`:break}if(d&&(c+=d),u.length===0){d&&s.push({role:`assistant`,content:d});break}s.push({role:`assistant`,content:d,toolCalls:u.map(e=>({id:e.id,type:`function`,function:{name:e.name,arguments:JSON.stringify(e.arguments)}}))});for(let e of u)s.push({role:`tool`,toolCallId:e.id,toolName:e.name,content:JSON.stringify(e.result)})}return{finalText:c,rounds:l}}async function tt(e,t,n){switch(e){case`read_file`:return Xe(n.sandbox,t);case`write_file`:return Y(n.sandbox,t,n.approval);case`patch_file`:return Ze(n.sandbox,t,n.approval);case`detect_framework`:return Qe(n.cwd);case`ask_user`:return $e(n.prompter,t);default:return{ok:!1,content:null,error:`unknown_tool:${e}`}}}function nt(){let e=[12,15,18,22,28,35,41,50,58,64,72,78],t=f(e,24);return[` ↑`,` ${t}`,` └────────────────────────`,` May Jun Jul Aug Sep`]}function rt(){return[` Landing page ████████████████████ 100%`,` ↓ -28%`,` Pricing ██████████████░░░░░░ 72%`,` ↓ -50%`,` Checkout ███████░░░░░░░░░░░░░ 36%`,` ↓ -64%`,` Purchased ███░░░░░░░░░░░░░░░░░ 13%`]}function it(){return[` ▇▇▇▇▇▇▇▇▇▎ 89 Sarah K. /pricing 🇺🇸`,` ▇▇▇▇▇▇░░░░ 61 anon /docs 🇩🇪`,` ▇▇▇░░░░░░░ 34 anon /changelog 🇯🇵`]}function at(){return[` LCP ● 2.1s good ████████████░░░░░░`,` INP ● 89ms good ██████████████████`,` CLS ⚠ 0.14 needs ████████████░░░░░░`,` TTFB ● 380ms good ███████████████░░░`]}const X=[{title:`Welcome`,body:[`The wizard is an agent — it handles the entire`,`Zenovay setup process on your behalf.`,``,`Reading your project, deciding where the tracker`,`belongs, and writing the snippet for you.`]},{title:`Events`,body:[`Events are the foundation of Zenovay analytics.`,``,`Every pageview, click, and custom action is an`,`event. Group them into Goals to track conversions.`]},{title:`Trends`,body:[`Use trends to measure growth.`,``,`See how visitors, signups, and revenue have`,`changed over the last week, month, or quarter.`],visual:nt},{title:`Funnels`,body:[`Funnels reveal where users drop off.`,``,`Define the steps you care about — landing,`,`pricing, checkout, purchase — and Zenovay shows`,`the per-step conversion rate.`],visual:rt},{title:`Live visitors`,body:[`Watch every visitor in real time, ranked by an`,`AI score that highlights high-intent traffic.`,``,"Use `zenovay visitors --live` after install."],visual:it},{title:`Core Web Vitals`,body:[`LCP, INP, CLS — Google's page-experience metrics,`,`collected automatically once the tracker is in.`,``,"Use `zenovay vitals` to see them per page + device."],visual:at},{title:`MCP integration`,body:[`Your CLI session can install Zenovay's MCP server`,`into Cursor / Claude Desktop / VS Code.`,``,`Then ask your AI: "what were my top pages today?"`,`and it queries Zenovay directly.`]},{title:`AI insights`,body:[`Zenovay watches your data and surfaces anomalies`,`automatically — traffic spikes, error bursts,`,`revenue drops — without you needing to ask.`,``,"Run `zenovay ai` after install to chat with them."]},{title:`Privacy-first`,body:[`No cookies required. No third-party trackers.`,`Cookieless mode is one toggle in your dashboard.`,``,`GDPR, CCPA, and PECR-compliant out of the box.`]}],ot=8e3,st=({width:e,height:t})=>{let[n,r]=S(0);x(()=>{let e=setInterval(()=>{r(e=>(e+1)%X.length)},ot);return()=>clearInterval(e)},[]);let i=X[n],a=i.visual?i.visual():[],o=X.map((e,t)=>t===n?`●`:`·`).join(` `);return b.createElement(h,{flexDirection:`column`,width:e,height:t,paddingX:2,paddingY:1},b.createElement(h,{marginBottom:1},b.createElement(g,{color:`magentaBright`,bold:!0},`Learn`)),b.createElement(h,{marginBottom:1},b.createElement(g,{bold:!0,color:`white`},i.title)),i.body.map((e,t)=>b.createElement(g,{key:t,color:`gray`},e||` `)),a.length>0&&b.createElement(h,{flexDirection:`column`,marginTop:1},a.map((e,t)=>b.createElement(g,{key:t,color:`cyan`},e))),b.createElement(h,{flexGrow:1}),b.createElement(h,{marginTop:1},b.createElement(g,{color:`gray`,dimColor:!0},o,` · `,n+1,` / `,X.length)))},ct={pending:`·`,active:`⠋`,done:`✓`,error:`✗`},lt={pending:`gray`,active:`magenta`,done:`green`,error:`red`},ut=({tasks:e,width:t,height:n,liveLine:r})=>{let i=e.filter(e=>e.status===`done`).length;return b.createElement(h,{flexDirection:`column`,width:t,height:n,paddingX:2,paddingY:1},b.createElement(h,{marginBottom:1},b.createElement(g,{color:`magentaBright`,bold:!0},`Tasks`)),e.map(e=>b.createElement(h,{key:e.id,flexDirection:`column`},b.createElement(h,null,e.status===`active`?b.createElement(g,{color:`magenta`},b.createElement(E,{type:`dots`})):b.createElement(g,{color:lt[e.status]},ct[e.status]),b.createElement(g,null,` `),b.createElement(g,{color:e.status===`pending`?`gray`:`white`},e.label)),e.detail&&b.createElement(h,{paddingLeft:2},b.createElement(g,{color:`gray`,dimColor:!0},e.detail)))),b.createElement(h,{flexGrow:1}),r&&b.createElement(h,{marginTop:1},b.createElement(g,{color:`cyan`},`◆ `),b.createElement(g,{color:`white`},r)),b.createElement(h,{marginTop:1},b.createElement(g,{color:`gray`,dimColor:!0},i,` / `,e.length)))};async function dt(e){return a(e)?ft(e):new Promise(t=>{let{unmount:n,waitUntilExit:r}=_(b.createElement(pt,{opts:e,onExit:e=>{n(),t(e)}}));r().catch(()=>t(1))})}async function ft(r){try{let a=await e(),o=await K(r.cwd);if(!o)return i({type:`error`,code:`no_framework`,message:`Could not detect framework (headless mode has no picker).`}),2;i({type:`framework.detected`,framework:o.id,confidence:1});let s=await n({strict:!1});if(!s&&!process.env.ZENOVAY_API_TOKEN)return i({type:`error`,code:`not_logged_in`,message:"Run `zenovay login` first (or set ZENOVAY_API_TOKEN)."}),2;let c=new t({config:a,cliVersion:r.cliVersion,token:s}),l=await c.getSites(),u=r.siteId?l.find(e=>e.id===r.siteId):l[0];if(!u&&r.siteId)return i({type:`error`,code:`site_not_found`,message:`Site ${r.siteId} not found.`}),2;if(!u)return i({type:`error`,code:`no_site`,message:`No sites exist; create one at app.zenovay.com or re-run interactively.`}),2;i({type:`info`,message:`Using site ${u.id} (${u.name}) trackingCode=${u.trackingCode??u.id}`});let d=await q(r.cwd,{[o.envVarName]:u.trackingCode??u.id});return i({type:`info`,message:`env vars added: ${d.addedKeys.join(`,`)}`}),i({type:`done`,command:`init`,exitCode:0}),0}catch(e){return i({type:`error`,code:`init_failed`,message:e.message}),1}}const pt=({opts:r,onExit:i})=>{let{exit:a}=v(),[l,d]=S(`intro`),[f,p]=S(null),[m,_]=S([]),[y,C]=S(null),[w,T]=S(null),[D,O]=S(null),[k,A]=S([]),[j,M]=S(void 0),[N,P]=S(null),[F,I]=S(0),L=ee(!1);return x(()=>(process.stdout.isTTY&&process.stdout.write(`\x1B[?1049h\x1B[H`),()=>{process.stdout.isTTY&&process.stdout.write(`\x1B[?1049l`)}),[]),x(()=>{L.current||(L.current=!0,(async()=>{try{d(`detecting`);let i=await K(r.cwd);if(!i){O(`Could not detect your framework. Supported: Next.js, Nuxt, SvelteKit, Astro, Remix, plain HTML.`),d(`error`);return}p(i);let a=await n({strict:!1});!process.env.ZENOVAY_API_TOKEN&&!a&&(d(`login`),await o({cliVersion:r.cliVersion})),d(`loading-sites`);let s=await e(),c=await n({strict:!1}),l=new t({config:s,cliVersion:r.cliVersion,token:c}),u=await l.getSites(),f=await Tt(r.cwd),m=Et(u,f);if(_(u),C(f),u.length===0){d(`create-site`);return}if(r.siteId){let e=u.find(e=>e.id===r.siteId);if(!e){O(`Site ${r.siteId} not found in your account.`),d(`error`);return}T(e),Z(e,i,r,{setPhase:d,setErrorMsg:O,setTasks:A,setLiveLine:M,setSandboxStats:P});return}if(r.yes&&m){T(m),Z(m,i,r,{setPhase:d,setErrorMsg:O,setTasks:A,setLiveLine:M,setSandboxStats:P});return}d(`site-picker`)}catch(e){O(e.message),d(`error`)}})())},[]),x(()=>{l===`success`&&setTimeout(()=>{a(),i(0)},1500),l===`error`&&setTimeout(()=>{a(),i(1)},8e3)},[l]),b.createElement(h,{flexDirection:`column`},b.createElement(c,{version:r.cliVersion,subtitle:`AI install wizard`}),l===`intro`&&b.createElement(mt,null),l===`detecting`&&b.createElement(s,{title:`Scanning`,state:`busy`},b.createElement(h,null,b.createElement(g,{color:`magenta`},b.createElement(E,{type:`dots`})),b.createElement(g,null,` Detecting framework…`))),l===`login`&&b.createElement(s,{title:`Authenticating`,state:`busy`},b.createElement(g,null,`Opening browser for login… (paste ZENOVAY_API_TOKEN env var to skip)`)),l===`loading-sites`&&b.createElement(s,{title:`Loading your sites`,state:`busy`},b.createElement(h,null,b.createElement(g,{color:`magenta`},b.createElement(E,{type:`dots`})),b.createElement(g,null,` Fetching your Zenovay sites…`))),l===`site-picker`&&f&&b.createElement(gt,{sites:m,preselectHint:y,onPick:e=>{if(e===`create-new`){d(`create-site`);return}T(e),Z(e,f,r,{setPhase:d,setErrorMsg:O,setTasks:A,setLiveLine:M,setSandboxStats:P})}}),l===`create-site`&&b.createElement(s,{title:`Create a new site`,state:`warn`},b.createElement(g,{color:`yellow`},"No site picked (or none exist yet). Visit https://app.zenovay.com/websites to create one, then re-run `zenovay init`."),b.createElement(g,{color:`gray`},`(Inline site creation from the CLI is scheduled for V1.1 — it requires a plan-limit check.)`)),l===`agent`&&f&&w&&b.createElement(ht,{adapter:f,site:w,tasks:k,liveLine:j}),l===`install-complete`&&f&&w&&b.createElement(vt,{adapter:f,site:w,stats:N,onCommit:()=>d(`commit-prompt`),onSkipCommit:()=>d(`deploy-prompt`)}),l===`commit-prompt`&&w&&b.createElement(yt,{cwd:r.cwd,onDone:e=>{e.committed&&M(`Pushed ${e.shortSha} to ${e.branch}`),d(`deploy-prompt`)},onError:e=>{O(e),d(`error`)}}),l===`deploy-prompt`&&w&&b.createElement(bt,{site:w,onDeployed:()=>d(`visit-prompt`),onSkip:()=>d(`verify`)}),l===`visit-prompt`&&w&&b.createElement(xt,{site:w,onContinue:()=>d(`verify`)}),l===`verify`&&w&&b.createElement(St,{site:w,elapsed:F,onTick:e=>I(e),onArrived:()=>d(`success`),onTimeout:()=>d(`success`)}),l===`success`&&f&&w&&b.createElement(_t,{adapter:f,site:w,stats:N}),l===`error`&&b.createElement(s,{title:`Install failed`,state:`err`},b.createElement(g,{color:`red`},D??`Unknown error`)),b.createElement(u,{items:[{key:`q`,label:`quit`},{key:`ctrl-c`,label:`abort`}]}))};async function Z(r,i,a,o){try{o.setPhase(`agent`);let s=await e(),c=await n({strict:!1}),l=new t({config:s,cliVersion:a.cliVersion,token:c}),u=new U({cwd:a.cwd}),d=r.trackingCode??r.id,f=await P(a.cwd);if(f.installed){o.setTasks(e=>e.map(e=>e.id===`detect`||e.id===`read`||e.id===`write`?{...e,status:`done`,detail:`already installed`}:e)),o.setLiveLine(`Tracker already present (${f.scriptFile??f.packageMarker??f.configFile??`detected`}) — skipping agent.`),o.setSandboxStats?.({reads:0,writes:0,rounds:0}),!a.skipMcp&&c&&await J({accessToken:c.accessToken}).catch(()=>void 0),o.setPhase(`install-complete`);return}let p=i.buildSnippets({trackingCode:d,siteId:r.id}),m=`Install Zenovay tracking into this ${i.displayName} project.\nSite: ${r.name} (trackingCode: ${d}).\n1. Call detect_framework to confirm the framework.\n2. Read the entry file(s) for this framework:\n`+i.files.map(e=>` - ${e.path}`).join(`
53
+ `)+`
54
+ 3. Insert the tracker using the snippet below.
55
+ 4. Confirm the change with a diff before writing.
56
+
57
+ Snippet reference (anchored by anchorKind — adapt to the actual file):
58
+ `+p.map(e=>` ${e.anchorKind} @ ${e.targetPath}:\n ${e.code.replace(/\n/g,`
59
+ `)}`).join(`
60
+
61
+ `);o.setTasks([{id:`detect`,label:`Detect framework`,status:`active`},{id:`read`,label:`Read project entry files`,status:`pending`},{id:`write`,label:`Insert tracker snippet`,status:`pending`},{id:`env`,label:`Write env vars (.env.local)`,status:`pending`},{id:`mcp`,label:`Install MCP clients (Cursor/Claude/VS Code)`,status:`pending`},{id:`verify`,label:`Wait for first event`,status:`pending`}]);let h=(e,t,n)=>{o.setTasks(r=>r.map(r=>r.id===e?{...r,status:t,detail:n??r.detail}:r))},g=null;try{await et({api:l,sandbox:u,approval:{async approve(){return`y`}},prompter:{async ask({question:e}){return e}},handlers:{onToolStart:({name:e})=>{e===`detect_framework`?(h(`detect`,`active`),o.setLiveLine(`Inspecting package.json + config files…`)):e===`read_file`?(h(`detect`,`done`),h(`read`,`active`)):(e===`write_file`||e===`patch_file`)&&(h(`read`,`done`),h(`write`,`active`))},onToolResult:({name:e,result:t})=>{let n=t?.ok!==!1,r=t?.content??{};e===`detect_framework`&&n&&(h(`detect`,`done`,i.displayName),o.setLiveLine(`Detected ${i.displayName}`)),e===`read_file`&&n&&r.path&&o.setLiveLine(`Read ${r.path}`),(e===`write_file`||e===`patch_file`)&&n&&r.path&&o.setLiveLine(`Wrote ${r.path}`)},onDelta:e=>{let t=e.replace(/\s+/g,` `).trim();t.length>4&&o.setLiveLine(t.slice(0,80))}},initialMessages:[{role:`user`,content:m}]})}catch(e){g=e}let _=u.stats();if(_.writes===0){let e=g?`Agent error: ${g.message}`:`Agent returned without writing any files (${_.reads} reads, ${_.rounds} rounds). The model may have refused or the AI Gateway may be misconfigured. Check api.zenovay.com logs.`;throw Error(e)}h(`write`,`done`),h(`env`,`active`),o.setLiveLine(`Adding env var to .env.local`);let v=await q(a.cwd,{[i.envVarName]:d});if(h(`env`,`done`,`${v.addedKeys.length} key(s) added`),!a.skipMcp&&c){h(`mcp`,`active`),o.setLiveLine(`Detecting Cursor / Claude Desktop / VS Code…`);let e=await J({accessToken:c.accessToken}).catch(()=>null);e&&e.installed.length>0?h(`mcp`,`done`,e.installed.join(`, `)):h(`mcp`,`done`,`none detected`)}else h(`mcp`,`done`,`skipped`);o.setTasks(e=>e.map(e=>e.id===`detect`||e.id===`read`||e.id===`write`?{...e,status:e.status===`pending`?`done`:e.status}:e)),o.setLiveLine(void 0),o.setSandboxStats?.(_),o.setPhase(`install-complete`)}catch(e){o.setErrorMsg(e.message),o.setPhase(`error`)}}const mt=()=>b.createElement(s,{title:`Zenovay wants to set up your project`,state:`idle`},b.createElement(g,null,`We'll use AI to analyze your codebase and add the Zenovay tracker.`),b.createElement(g,{color:`gray`},`.env* contents stay on your machine. Only framework metadata reaches api.zenovay.com.`)),ht=({adapter:e,site:t,tasks:n,liveLine:r})=>{let i=process.stdout.columns??100,a=(process.stdout.rows??30)-6,o=Math.floor(i/2)-1,s=Math.max(14,a);return b.createElement(h,{flexDirection:`column`},b.createElement(h,{flexDirection:`row`,height:s,borderStyle:`round`,borderColor:`gray`},b.createElement(h,{width:o,flexDirection:`column`},b.createElement(st,{width:o,height:s})),b.createElement(h,{width:1,flexDirection:`column`,height:s},b.createElement(g,{color:`gray`},`│`)),b.createElement(h,{width:o,flexDirection:`column`},b.createElement(ut,{tasks:n,liveLine:r,width:o,height:s}))),b.createElement(h,{marginTop:1},b.createElement(g,{color:`gray`},`Site: `,t.name,` · code: `,t.trackingCode??t.id,` · Framework: `,e.displayName)))},gt=({sites:e,preselectHint:t,onPick:n})=>{let r=Et(e,t),i=e.filter(e=>e.id!==r?.id),a=r?[r,...i]:i,o=[...a.map(e=>({label:wt(e,e.id===r?.id),value:e,description:e.trackingCode?`trackingCode: ${e.trackingCode}`:void 0})),{label:`+ Create new site on app.zenovay.com`,value:`create-new`,description:`Open the dashboard to add a new website`}];return b.createElement(s,{title:t?`Pick a site (best match: ${t})`:`Pick a site`,state:`idle`},b.createElement(d,{items:o,onSelect:n}))},_t=({adapter:e,site:t,stats:n})=>b.createElement(s,{title:`You're live on Zenovay`,state:`ok`},b.createElement(g,null,b.createElement(l,null,`✔ Installed successfully`)),b.createElement(g,null,`Framework: `,e.displayName),b.createElement(g,null,`Site: `,t.name,` (`,t.url,`)`),t.trackingCode?b.createElement(g,{color:`gray`},`Tracker code: `,t.trackingCode):null,n?b.createElement(g,{color:`gray`},n.writes,` file(s) modified across `,n.rounds,` agent round(s)`):null,b.createElement(g,{color:`gray`},`Dashboard: https://app.zenovay.com/sites/`,t.id),b.createElement(g,{color:`gray`},"Next: `zenovay watch` for a live TUI.")),vt=({adapter:e,site:t,stats:n,onCommit:r,onSkipCommit:i})=>(Q(e=>{e===`y`||e===`Y`||e===`\r`?r():(e===`n`||e===`N`||e===`s`||e===`S`)&&i()}),b.createElement(s,{title:`Tracker installed`,state:`ok`},b.createElement(g,null,b.createElement(l,null,`✔ `),`The Zenovay tracker is in your project.`),b.createElement(h,{marginTop:1},b.createElement(g,{color:`gray`},`Framework: `),b.createElement(g,null,e.displayName)),b.createElement(h,null,b.createElement(g,{color:`gray`},`Site: `),b.createElement(g,null,t.name,` (`,t.url,`)`)),n&&b.createElement(h,null,b.createElement(g,{color:`gray`},`Modified: `),b.createElement(g,null,n.writes,` file(s)`)),b.createElement(h,{marginTop:1},b.createElement(g,null,`Commit + push these changes to git? `),b.createElement(g,{color:`cyan`},`[Y/n]`)))),yt=({cwd:e,onDone:t,onError:n})=>{let[r,i]=S(`committing`),[a,o]=S(`Staging changes…`);return x(()=>{(async()=>{try{let n=await Ct(e,e=>o(e),e=>i(e));n.committed?o(`Pushed ${n.shortSha} to origin/${n.branch}`):o(`No changes to commit (already up-to-date).`),setTimeout(()=>t(n),800)}catch(e){n(e.message)}})()},[]),b.createElement(s,{title:`Committing to git`,state:`busy`},b.createElement(h,null,b.createElement(g,{color:`magenta`},b.createElement(E,{type:`dots`})),b.createElement(g,null,` `,r===`pushing`?`Pushing to origin`:`Committing`,`…`)),b.createElement(h,{marginTop:1},b.createElement(g,{color:`gray`},a)))},bt=({site:e,onDeployed:t,onSkip:n})=>(Q(e=>{e===`y`||e===`Y`||e===`\r`||e===`d`||e===`D`?t():(e===`n`||e===`N`||e===`s`||e===`S`)&&n()}),b.createElement(s,{title:`Ready to deploy?`,state:`idle`},b.createElement(g,null,`The tracker is installed locally. To capture events you need it on the live site:`),b.createElement(g,null,` `),b.createElement(h,null,b.createElement(g,{color:`cyan`},` → `),b.createElement(g,null,e.url)),b.createElement(g,null,` `),b.createElement(g,{color:`gray`},`Push the change through your normal deploy pipeline (Vercel auto-deploy, CI/CD, etc.).`),b.createElement(h,{marginTop:1},b.createElement(g,null,`Once it's deployed, press `),b.createElement(g,{color:`cyan`},`[Y]`),b.createElement(g,null,` to verify the tracker is firing. `),b.createElement(g,{color:`gray`},`[s] skip verification`)))),xt=({site:e,onContinue:t})=>(Q(()=>t()),b.createElement(s,{title:`Visit your site`,state:`idle`},b.createElement(g,null,`To send a test event, open any page on your site:`),b.createElement(g,null,` `),b.createElement(h,null,b.createElement(g,{color:`cyan`},` → `),b.createElement(g,null,e.url)),b.createElement(g,null,` `),b.createElement(g,{color:`gray`},`The tracker fires automatically on page load. We'll verify the next event arrives.`),b.createElement(h,{marginTop:1},b.createElement(g,null,`Press `),b.createElement(g,{color:`cyan`},`[any key]`),b.createElement(g,null,` when you've visited the page.`)))),St=({site:r,elapsed:i,onTick:a,onArrived:o,onTimeout:c})=>{x(()=>{let i=!1,s=Date.now();return(async()=>{try{let l=await e(),u=await n({strict:!1}),d=new t({config:l,cliVersion:`0`,token:u}),f=await We(r.id,s,{api:d,timeoutMs:18e4,pollIntervalMs:2500,onTick:e=>{i||a(e)}});if(i)return;f.received?o():c()}catch{i||c()}})(),()=>{i=!0}},[]);let l=Math.floor(i/1e3);return b.createElement(s,{title:`Waiting for first event`,state:`busy`},b.createElement(h,null,b.createElement(g,{color:`magenta`},b.createElement(E,{type:`dots`})),b.createElement(g,null,` Polling api.zenovay.com for the first hit on `),b.createElement(g,{color:`cyan`},r.url),b.createElement(g,null,` (`,l,`s elapsed)`)),b.createElement(h,{marginTop:1},b.createElement(g,{color:`gray`},`Reload the page if nothing arrives within ~30 seconds.`)))};function Q(e){y((t,n)=>{e(t,{return:n.return,escape:n.escape})},{isActive:!0})}async function Ct(e,t,n){let{execFile:r}=await import(`node:child_process`),{promisify:i}=await import(`node:util`),a=i(r),o=async(t,n)=>{let{stdout:r}=await a(t,n,{cwd:e,maxBuffer:4e6});return r.trim()};try{await o(`git`,[`rev-parse`,`--is-inside-work-tree`])}catch{return t(`Not a git repository — skipped.`),{committed:!1}}let s=await o(`git`,[`status`,`--porcelain`]);if(!s)return{committed:!1};t(`Staging tracker changes…`),await o(`git`,[`add`,`-A`]),t(`Creating commit…`),await o(`git`,[`commit`,`-m`,`chore(zenovay): install tracking script via @zenovay/cli`]);let c=await o(`git`,[`rev-parse`,`--short`,`HEAD`]),l=await o(`git`,[`rev-parse`,`--abbrev-ref`,`HEAD`]);n(`pushing`),t(`Pushing to origin/${l}…`);try{await o(`git`,[`push`,`origin`,l])}catch(e){return t(`Commit ${c} created locally; push failed (${e.message.slice(0,80)}). Push manually with: git push origin ${l}`),{committed:!0,shortSha:c,branch:l}}return n(`done`),{committed:!0,shortSha:c,branch:l}}function wt(e,t){let n=`${e.name}`.padEnd(30,` `).slice(0,30),r=e.url.replace(/^https?:\/\//,``).padEnd(28,` `).slice(0,28),i=t?` ← best match`:``;return`${n} ${r}${i}`}async function Tt(e){try{let t=await m.readFile(p.join(e,`package.json`),`utf8`),n=JSON.parse(t);if(n.name)return String(n.name).replace(/^@[^/]+\//,``)}catch{}try{let t=await m.readFile(p.join(e,`.git`,`config`),`utf8`),n=t.match(/url\s*=\s*.*[/:]([^/]+?)(?:\.git)?\s*$/m);if(n&&n[1])return n[1]}catch{}return p.basename(e)}function Et(e,t){if(!t||e.length===0)return e[0]??null;let n=$(t),r=e.find(e=>$(e.name)===n);if(r)return r;let i=e.find(e=>{let t=e.url.replace(/^https?:\/\//,``).replace(/\/.*$/,``),[r]=t.split(`.`);return $(r??``)===n});if(i)return i;let a=e.find(e=>$(e.name).includes(n)||$(e.url).includes(n));return a??e[0]??null}function $(e){return e.toLowerCase().replace(/[^a-z0-9]/g,``)}export{P as detectInstalled,dt as initCommand};
@@ -0,0 +1 @@
1
+ import"./config-ZTGpKEWg.js";import"./api-D5XQeEDF.js";import{initCommand as e}from"./init-CU_fEq2x.js";import"./client-DZ4Awt8u.js";import"./formatter-45-fT1Hv.js";import"./emit-0WJ_OGeT.js";import"./login--p3mI2F6.js";import"./panel-DglZ755S.js";import"./keybar-D2OI-8rx.js";import"./prompt-hjzdzlyj.js";import"./sparkline-CR_bzxwB.js";export{e as initCommand};
@@ -1 +1 @@
1
- import{readConfig as e}from"./config-ZTGpKEWg.js";import{ApiClient as t,pollDeviceToken as n,startDeviceAuthorization as r,writeToken as i}from"./api-D5XQeEDF.js";import{emit as a,isHeadless as o}from"./emit-DIRc7UzM.js";import s from"open";async function c(c){let l=await e(),u=o({json:c.json}),d=await r({apiBase:l.apiBase}),f=d.verification_uri_complete??d.verification_uri;u?a({type:`info`,message:`Open ${f} and enter code ${d.user_code}`}):c.onCode?c.onCode({userCode:d.user_code,verificationUri:d.verification_uri,verificationUriComplete:d.verification_uri_complete}):process.stdout.write(`\n Open this URL to authorize the CLI:\n ${f}\n Or enter code: ${d.user_code}\n\n`);let p=c.openBrowser??!u;if(p)try{await s(f)}catch{}let m=await n({apiBase:l.apiBase,deviceCode:d.device_code,interval:d.interval,expiresIn:d.expires_in});await i(m);let h=new t({config:l,cliVersion:c.cliVersion,token:m}),g=await h.me().catch(()=>null);if(g){let e={...m,userId:g.user.id,teamId:g.team?.id,email:g.user.email};await i(e)}return u&&a({type:`done`,command:`login`,exitCode:0}),{email:g?.user.email}}export{c as loginCommand};
1
+ import{readConfig as e}from"./config-ZTGpKEWg.js";import{ApiClient as t,pollDeviceToken as n,startDeviceAuthorization as r,writeToken as i}from"./api-D5XQeEDF.js";import{emit as a,isHeadless as o}from"./emit-0WJ_OGeT.js";import s from"open";async function c(c){let l=await e(),u=o({json:c.json}),d=await r({apiBase:l.apiBase}),f=d.verification_uri_complete??d.verification_uri;u?a({type:`info`,message:`Open ${f} and enter code ${d.user_code}`}):c.onCode?c.onCode({userCode:d.user_code,verificationUri:d.verification_uri,verificationUriComplete:d.verification_uri_complete}):process.stdout.write(`\n Open this URL to authorize the CLI:\n ${f}\n Or enter code: ${d.user_code}\n\n`);let p=c.openBrowser??!u;if(p)try{await s(f)}catch{}let m=await n({apiBase:l.apiBase,deviceCode:d.device_code,interval:d.interval,expiresIn:d.expires_in});await i(m);let h=new t({config:l,cliVersion:c.cliVersion,token:m}),g=await h.me().catch(()=>null);if(g){let e={...m,userId:g.user.id,teamId:g.team?.id,email:g.user.email};await i(e)}return u&&a({type:`done`,command:`login`,exitCode:0}),{email:g?.user.email}}export{c as loginCommand};
@@ -0,0 +1 @@
1
+ import"./config-ZTGpKEWg.js";import"./api-D5XQeEDF.js";import"./formatter-45-fT1Hv.js";import"./emit-0WJ_OGeT.js";import{loginCommand as e}from"./login--p3mI2F6.js";export{e as loginCommand};
@@ -1,2 +1,2 @@
1
- import{readConfig as e}from"./config-ZTGpKEWg.js";import{ApiClient as t,clearToken as n,readToken as r}from"./api-D5XQeEDF.js";import"./formatter-DQ6l4sWM.js";import{emit as i,isHeadless as a}from"./emit-DIRc7UzM.js";async function o(o){let s=await e(),c=await r({strict:!1}).catch(()=>null);if(c)try{let e=new t({config:s,cliVersion:o.cliVersion,token:c});await e.revokeCurrentToken()}catch{}await n(),a({json:o.json})?i({type:`done`,command:`logout`,exitCode:0}):process.stdout.write(`Logged out.
1
+ import{readConfig as e}from"./config-ZTGpKEWg.js";import{ApiClient as t,clearToken as n,readToken as r}from"./api-D5XQeEDF.js";import"./formatter-45-fT1Hv.js";import{emit as i,isHeadless as a}from"./emit-0WJ_OGeT.js";async function o(o){let s=await e(),c=await r({strict:!1}).catch(()=>null);if(c)try{let e=new t({config:s,cliVersion:o.cliVersion,token:c});await e.revokeCurrentToken()}catch{}await n(),a({json:o.json})?i({type:`done`,command:`logout`,exitCode:0}):process.stdout.write(`Logged out.
2
2
  `)}export{o as logoutCommand};
@@ -1,3 +1,3 @@
1
- import{readConfig as e}from"./config-ZTGpKEWg.js";import{readToken as t}from"./api-D5XQeEDF.js";import{formatTabular as n,selectFormat as r}from"./formatter-DQ6l4sWM.js";import"./panel-DglZ755S.js";import"./keybar-D2OI-8rx.js";import"./prompt-hjzdzlyj.js";import"./sparkline-CR_bzxwB.js";import{runAnalyticalScreen as i}from"./analytical-screen-CS1ZL5Mo.js";import{Table as a}from"./ui-Bk5nl2yb.js";import{ApiV2Client as o}from"./api-v2-DP5YEHL_.js";import{Box as s,Text as c}from"ink";import l from"react";async function u(u){let d=await e(),f=await t({strict:!1}),p=u.siteId??f?.teamId??``;if(!p)return process.stderr.write(`No site selected — pass --site-id or set ZENOVAY_SITE.
1
+ import{readConfig as e}from"./config-ZTGpKEWg.js";import{readToken as t}from"./api-D5XQeEDF.js";import{formatTabular as n,selectFormat as r}from"./formatter-45-fT1Hv.js";import"./panel-DglZ755S.js";import"./keybar-D2OI-8rx.js";import"./prompt-hjzdzlyj.js";import"./sparkline-CR_bzxwB.js";import{runAnalyticalScreen as i}from"./analytical-screen-CdtZfbes.js";import{Table as a}from"./ui-Bk5nl2yb.js";import{ApiV2Client as o}from"./api-v2-DP5YEHL_.js";import{Box as s,Text as c}from"ink";import l from"react";async function u(u){let d=await e(),f=await t({strict:!1}),p=u.siteId??f?.teamId??``;if(!p)return process.stderr.write(`No site selected — pass --site-id or set ZENOVAY_SITE.
2
2
  `),2;let m=new o({config:d,cliVersion:u.cliVersion,token:f}),h=r(u),g=[{key:`isCurrent`,header:``,width:2,format:e=>e?`*`:` `},{key:`name`,header:`project`,width:26},{key:`domain`,header:`domain`,width:28,format:e=>String(e??`—`)},{key:`tier`,header:`tier`,width:10},{key:`pageviews24h`,header:`24h pv`,width:8,align:`right`},{key:`id`,header:`id`,width:38,format:e=>String(e).slice(0,38)}];return i({cliVersion:u.cliVersion,title:`projects · ${f?.teamId??`—`}`,commandName:`projects`,authToken:f?.accessToken??null,refreshIntervalMs:0,fetcher:e=>m.getProjects(p,e),format:h,headlessEmit:(e,t)=>{if(t===`json`||t===`ndjson`){if(t===`ndjson`)for(let t of e.projects)process.stdout.write(JSON.stringify(t)+`
3
3
  `);else process.stdout.write(JSON.stringify(e,null,2));return}process.stdout.write(n(e.projects,[`id`,`name`,`domain`,`tier`,`pageviews24h`,`isCurrent`],t))},panels:[{id:`summary`,title:`Tracked sites`,render:e=>{let t=e.projects.find(e=>e.isCurrent);return l.createElement(s,{flexDirection:`column`},l.createElement(c,null,l.createElement(c,{bold:!0},e.projects.length),l.createElement(c,{color:`gray`},` projects`)),t?l.createElement(c,{color:`gray`},`current: `,l.createElement(c,{color:`cyan`},t.name),` `,`(`,t.domain??`—`,`, `,t.tier,`)`):l.createElement(c,{color:`gray`},`no current project bound to this token`))}},{id:`list`,title:`List`,render:e=>e.projects.length===0?l.createElement(c,{color:`gray`},`— no projects yet —`):l.createElement(a,{data:e.projects,columns:g})},{id:`hint`,title:`Switch`,render:()=>l.createElement(c,{color:`gray`},"To switch project: run `zenovay logout` then `zenovay login` (V2.1 adds a faster /switch flow).")}]})}export{u as projectsCommand};
@@ -1,4 +1,4 @@
1
- import{readConfig as e}from"./config-ZTGpKEWg.js";import{readToken as t}from"./api-D5XQeEDF.js";import{formatTabular as n,selectFormat as r}from"./formatter-DQ6l4sWM.js";import{Panel as i}from"./panel-DglZ755S.js";import{Banner as a}from"./keybar-D2OI-8rx.js";import"./prompt-hjzdzlyj.js";import"./sparkline-CR_bzxwB.js";import{Table as o}from"./ui-Bk5nl2yb.js";import{ApiV2Client as s}from"./api-v2-DP5YEHL_.js";import{Box as c,Text as l,useApp as u,useInput as d}from"ink";import f,{useMemo as p,useState as m}from"react";import h from"ink-text-input";function g({api:e,siteId:t,maxRows:n}){let{exit:r}=u(),[s,g]=m(``),[_,v]=m(null),[y,b]=m(null),[x,S]=m(!1),[C,w]=m([]);d((e,t)=>{t.escape&&r()});let T=async i=>{if(i.trim()){if(i.trim()===`\\q`||i.trim()===`exit`||i.trim()===`quit`){r();return}w(e=>[...e,i]),S(!0),b(null);try{let r=await e.runSqlQuery(t,i,{maxRows:n});v(r)}catch(e){b(e.message),v(null)}finally{S(!1),g(``)}}},E=p(()=>_?_.columns.map(e=>({key:e,header:e,width:18,format:e=>e==null?`∅`:String(e).slice(0,18)})):[],[_]);return f.createElement(c,{flexDirection:`column`},f.createElement(a,{version:`query`}),f.createElement(i,{title:`History`,state:`idle`},C.length===0?f.createElement(l,{color:`gray`},`— no queries yet — Esc or \\q to exit —`):C.slice(-5).map((e,t)=>f.createElement(l,{key:t,color:`gray`},`> ${e.slice(0,80)}${e.length>80?`…`:``}`))),f.createElement(c,null,f.createElement(l,{color:`magenta`},`sql`,`>`,` `),f.createElement(h,{value:s,onChange:g,onSubmit:T})),x?f.createElement(l,{color:`gray`},`running…`):null,y?f.createElement(i,{title:`Error`,state:`err`},f.createElement(l,{color:`red`},y)):null,_?f.createElement(i,{title:`${_.row_count} rows · ${_.duration_ms}ms${_.truncated?` · truncated`:``}`,state:`ok`},_.row_count===0?f.createElement(l,{color:`gray`},`— empty —`):f.createElement(o,{data:_.rows.slice(0,50),columns:E})):null)}async function _(i){let a=await e(),o=await t({strict:!1}),c=i.siteId??o?.teamId??``;if(!c)return process.stderr.write(`No site selected — pass --site-id or set ZENOVAY_SITE.
1
+ import{readConfig as e}from"./config-ZTGpKEWg.js";import{readToken as t}from"./api-D5XQeEDF.js";import{formatTabular as n,selectFormat as r}from"./formatter-45-fT1Hv.js";import{Panel as i}from"./panel-DglZ755S.js";import{Banner as a}from"./keybar-D2OI-8rx.js";import"./prompt-hjzdzlyj.js";import"./sparkline-CR_bzxwB.js";import{Table as o}from"./ui-Bk5nl2yb.js";import{ApiV2Client as s}from"./api-v2-DP5YEHL_.js";import{Box as c,Text as l,useApp as u,useInput as d}from"ink";import f,{useMemo as p,useState as m}from"react";import h from"ink-text-input";function g({api:e,siteId:t,maxRows:n}){let{exit:r}=u(),[s,g]=m(``),[_,v]=m(null),[y,b]=m(null),[x,S]=m(!1),[C,w]=m([]);d((e,t)=>{t.escape&&r()});let T=async i=>{if(i.trim()){if(i.trim()===`\\q`||i.trim()===`exit`||i.trim()===`quit`){r();return}w(e=>[...e,i]),S(!0),b(null);try{let r=await e.runSqlQuery(t,i,{maxRows:n});v(r)}catch(e){b(e.message),v(null)}finally{S(!1),g(``)}}},E=p(()=>_?_.columns.map(e=>({key:e,header:e,width:18,format:e=>e==null?`∅`:String(e).slice(0,18)})):[],[_]);return f.createElement(c,{flexDirection:`column`},f.createElement(a,{version:`query`}),f.createElement(i,{title:`History`,state:`idle`},C.length===0?f.createElement(l,{color:`gray`},`— no queries yet — Esc or \\q to exit —`):C.slice(-5).map((e,t)=>f.createElement(l,{key:t,color:`gray`},`> ${e.slice(0,80)}${e.length>80?`…`:``}`))),f.createElement(c,null,f.createElement(l,{color:`magenta`},`sql`,`>`,` `),f.createElement(h,{value:s,onChange:g,onSubmit:T})),x?f.createElement(l,{color:`gray`},`running…`):null,y?f.createElement(i,{title:`Error`,state:`err`},f.createElement(l,{color:`red`},y)):null,_?f.createElement(i,{title:`${_.row_count} rows · ${_.duration_ms}ms${_.truncated?` · truncated`:``}`,state:`ok`},_.row_count===0?f.createElement(l,{color:`gray`},`— empty —`):f.createElement(o,{data:_.rows.slice(0,50),columns:E})):null)}async function _(i){let a=await e(),o=await t({strict:!1}),c=i.siteId??o?.teamId??``;if(!c)return process.stderr.write(`No site selected — pass --site-id or set ZENOVAY_SITE.
2
2
  `),2;let l=new s({config:a,cliVersion:i.cliVersion,token:o}),u=i.maxRows??1e3,d=r(i);if(i.sql)try{let e=await l.runSqlQuery(c,i.sql,{maxRows:u});if(d===`json`)process.stdout.write(JSON.stringify(e,null,2)),process.stdout.write(`
3
3
  `);else if(d===`ndjson`)for(let t of e.rows)process.stdout.write(JSON.stringify(t)+`
4
4
  `);else if(d===`csv`||d===`tsv`)process.stdout.write(n(e.rows,e.columns,d));else{let t=e.columns.map(t=>Math.max(t.length,...e.rows.map(e=>String(e[t]??``).length))),n=`+`+t.map(e=>`-`.repeat(e+2)).join(`+`)+`+`;process.stdout.write(n+`
@@ -1,3 +1,3 @@
1
- import{readConfig as e}from"./config-ZTGpKEWg.js";import{readToken as t}from"./api-D5XQeEDF.js";import{formatTabular as n,selectFormat as r}from"./formatter-DQ6l4sWM.js";import"./panel-DglZ755S.js";import"./keybar-D2OI-8rx.js";import"./prompt-hjzdzlyj.js";import{spark as i}from"./sparkline-CR_bzxwB.js";import{runAnalyticalScreen as a}from"./analytical-screen-CS1ZL5Mo.js";import"./ui-Bk5nl2yb.js";import{ApiV2Client as o}from"./api-v2-DP5YEHL_.js";import{Box as s,Text as c}from"ink";import l from"react";function u(e,t){let n=e/100,r=new Intl.NumberFormat(`en-US`,{minimumFractionDigits:0,maximumFractionDigits:0}).format(n),i=(t||`USD`).toUpperCase();return i===`USD`?`$${r}`:i===`EUR`?`€${r}`:i===`GBP`?`£${r}`:`${r} ${i}`}async function d(d){let f=await e(),p=await t({strict:!1}),m=d.siteId??p?.teamId??``;if(!m)return process.stderr.write(`No site selected — pass --site-id or set ZENOVAY_SITE.
1
+ import{readConfig as e}from"./config-ZTGpKEWg.js";import{readToken as t}from"./api-D5XQeEDF.js";import{formatTabular as n,selectFormat as r}from"./formatter-45-fT1Hv.js";import"./panel-DglZ755S.js";import"./keybar-D2OI-8rx.js";import"./prompt-hjzdzlyj.js";import{spark as i}from"./sparkline-CR_bzxwB.js";import{runAnalyticalScreen as a}from"./analytical-screen-CdtZfbes.js";import"./ui-Bk5nl2yb.js";import{ApiV2Client as o}from"./api-v2-DP5YEHL_.js";import{Box as s,Text as c}from"ink";import l from"react";function u(e,t){let n=e/100,r=new Intl.NumberFormat(`en-US`,{minimumFractionDigits:0,maximumFractionDigits:0}).format(n),i=(t||`USD`).toUpperCase();return i===`USD`?`$${r}`:i===`EUR`?`€${r}`:i===`GBP`?`£${r}`:`${r} ${i}`}async function d(d){let f=await e(),p=await t({strict:!1}),m=d.siteId??p?.teamId??``;if(!m)return process.stderr.write(`No site selected — pass --site-id or set ZENOVAY_SITE.
2
2
  `),2;let h=new o({config:f,cliVersion:d.cliVersion,token:p}),g=r(d),_=d.range??`30d`;return a({cliVersion:d.cliVersion,title:`revenue · ${m} · ${_}`,commandName:`revenue`,authToken:p?.accessToken??null,refreshIntervalMs:d.watch?5*6e4:0,fetcher:e=>h.getRevenue(m,_,e),format:g,headlessEmit:(e,t)=>{if(t===`json`||t===`ndjson`){process.stdout.write(JSON.stringify(e,null,t===`json`?2:0)),t===`ndjson`&&process.stdout.write(`
3
3
  `);return}process.stdout.write(n(e.series,[`bucket`,`amount`,`currency`,`transactions`],t))},panels:[{id:`totals`,title:`Top line`,render:e=>l.createElement(s,{flexDirection:`column`},l.createElement(c,null,l.createElement(c,{color:`green`,bold:!0},u(e.totalAmount,e.currency)),` `,l.createElement(c,{color:`gray`},`total · `,e.totalTransactions,` transactions`)),typeof e.mrr==`number`?l.createElement(c,null,l.createElement(c,{bold:!0},`MRR `),l.createElement(c,{color:`magenta`},u(e.mrr,e.currency)),typeof e.arpu==`number`?l.createElement(c,{color:`gray`},` · ARPU `,u(e.arpu,e.currency)):null):null)},{id:`series`,title:`Daily (${_})`,render:e=>{let t=e.series.map(e=>e.amount);if(t.length===0)return l.createElement(c,{color:`gray`},`— no transactions —`);let n=Math.max(...t,1);return l.createElement(s,{flexDirection:`column`},l.createElement(c,{color:`magenta`},i(t,Math.min(60,t.length*2))),l.createElement(c,{color:`gray`},`peak: `,u(n,e.currency),` ·`,` `,`avg: `,u(e.totalAmount/Math.max(1,t.length),e.currency)))}},{id:`window`,title:`Window`,render:e=>l.createElement(c,{color:`gray`},new Date(e.windowStart).toISOString().slice(0,10),` →`,` `,new Date(e.windowEnd).toISOString().slice(0,10))}]})}export{d as revenueCommand};
@@ -1,3 +1,3 @@
1
- import{readConfig as e}from"./config-ZTGpKEWg.js";import{readToken as t}from"./api-D5XQeEDF.js";import{formatTabular as n,selectFormat as r}from"./formatter-DQ6l4sWM.js";import"./panel-DglZ755S.js";import"./keybar-D2OI-8rx.js";import"./prompt-hjzdzlyj.js";import"./sparkline-CR_bzxwB.js";import{runAnalyticalScreen as i}from"./analytical-screen-CS1ZL5Mo.js";import{Table as a}from"./ui-Bk5nl2yb.js";import{ApiV2Client as o}from"./api-v2-DP5YEHL_.js";import{Box as s,Text as c}from"ink";import l from"react";function u(e,t){let n=Math.round(e/100*t);return`█`.repeat(n)+`░`.repeat(Math.max(0,t-n))}function d(e){return e==null?{glyph:`·`,color:`gray`}:e>.5?{glyph:`▲`,color:`green`}:e<-.5?{glyph:`▼`,color:`red`}:{glyph:`→`,color:`gray`}}async function f(f){let p=await e(),m=await t({strict:!1}),h=f.siteId??m?.teamId??``;if(!h)return process.stderr.write(`No site selected — pass --site-id or set ZENOVAY_SITE.
1
+ import{readConfig as e}from"./config-ZTGpKEWg.js";import{readToken as t}from"./api-D5XQeEDF.js";import{formatTabular as n,selectFormat as r}from"./formatter-45-fT1Hv.js";import"./panel-DglZ755S.js";import"./keybar-D2OI-8rx.js";import"./prompt-hjzdzlyj.js";import"./sparkline-CR_bzxwB.js";import{runAnalyticalScreen as i}from"./analytical-screen-CdtZfbes.js";import{Table as a}from"./ui-Bk5nl2yb.js";import{ApiV2Client as o}from"./api-v2-DP5YEHL_.js";import{Box as s,Text as c}from"ink";import l from"react";function u(e,t){let n=Math.round(e/100*t);return`█`.repeat(n)+`░`.repeat(Math.max(0,t-n))}function d(e){return e==null?{glyph:`·`,color:`gray`}:e>.5?{glyph:`▲`,color:`green`}:e<-.5?{glyph:`▼`,color:`red`}:{glyph:`→`,color:`gray`}}async function f(f){let p=await e(),m=await t({strict:!1}),h=f.siteId??m?.teamId??``;if(!h)return process.stderr.write(`No site selected — pass --site-id or set ZENOVAY_SITE.
2
2
  `),2;let g=new o({config:p,cliVersion:f.cliVersion,token:m}),_=r(f),v=f.period??`30d`,y=[{key:`source`,header:`source`,width:22},{key:`channel`,header:`channel`,width:10,format:e=>String(e??`—`)},{key:`visitors`,header:`visitors`,width:8,align:`right`},{key:`delta`,header:`Δ`,width:6,align:`right`,format:e=>typeof e==`number`?`${e>0?`+`:``}${(e*100).toFixed(1)}%`:`—`}];return i({cliVersion:f.cliVersion,title:`sources · ${h} · ${v}`,commandName:`sources`,authToken:m?.accessToken??null,refreshIntervalMs:6e4,fetcher:e=>g.getSources(h,v,f.compare,e),format:_,headlessEmit:(e,t)=>{if(t===`json`||t===`ndjson`){process.stdout.write(JSON.stringify(e,null,t===`json`?2:0)),t===`ndjson`&&process.stdout.write(`
3
3
  `);return}process.stdout.write(n(e.sources,[`source`,`channel`,`visitors`,`conversions`,`revenue`,`delta`],t))},panels:[{id:`summary`,title:`Total`,render:e=>l.createElement(c,null,l.createElement(c,{bold:!0},e.totalVisitors.toLocaleString()),` `,l.createElement(c,{color:`gray`},`visitors · `,e.sources.length,` sources`))},{id:`channels`,title:`By channel`,render:e=>{if(e.sources.length===0)return l.createElement(c,{color:`gray`},`— no source data —`);let t=e.totalVisitors||1,n=[...e.sources].sort((e,t)=>t.visitors-e.visitors).slice(0,12);return l.createElement(s,{flexDirection:`column`},n.map((e,n)=>{let r=e.visitors/t*100,i=d(e.delta);return l.createElement(s,{key:`${e.source}-${n}`},l.createElement(c,null,l.createElement(c,{color:`cyan`},e.source.padEnd(20).slice(0,20)),` `,l.createElement(c,{color:`magenta`},u(r,30)),` `,l.createElement(c,null,e.visitors.toString().padStart(6),` `),l.createElement(c,{color:`gray`},`(`,r.toFixed(1),`%)`),` `,l.createElement(c,{color:i.color},i.glyph)))}))}},{id:`table`,title:`Detail`,render:e=>e.sources.length===0?l.createElement(c,{color:`gray`},`— —`):l.createElement(a,{data:e.sources.slice(0,20),columns:y})}]})}export{f as sourcesCommand};
@@ -1,3 +1,3 @@
1
- import{readConfig as e}from"./config-ZTGpKEWg.js";import{readToken as t}from"./api-D5XQeEDF.js";import{formatTabular as n,selectFormat as r}from"./formatter-DQ6l4sWM.js";import"./panel-DglZ755S.js";import"./keybar-D2OI-8rx.js";import"./prompt-hjzdzlyj.js";import"./sparkline-CR_bzxwB.js";import{runAnalyticalScreen as i}from"./analytical-screen-CS1ZL5Mo.js";import{Table as a}from"./ui-Bk5nl2yb.js";import{ApiV2Client as o}from"./api-v2-DP5YEHL_.js";import{Box as s,Text as c}from"ink";import l from"react";function u(e){return`${(e*100).toFixed(1)}%`}function d(e){return e<60?`${Math.round(e)}s`:e<3600?`${Math.floor(e/60)}m ${Math.round(e%60)}s`:`${Math.floor(e/3600)}h ${Math.floor(e%3600/60)}m`}async function f(f){let p=await e(),m=await t({strict:!1}),h=f.siteId??m?.teamId??``;if(!h)return process.stderr.write(`No site selected — pass --site-id or set ZENOVAY_SITE.
1
+ import{readConfig as e}from"./config-ZTGpKEWg.js";import{readToken as t}from"./api-D5XQeEDF.js";import{formatTabular as n,selectFormat as r}from"./formatter-45-fT1Hv.js";import"./panel-DglZ755S.js";import"./keybar-D2OI-8rx.js";import"./prompt-hjzdzlyj.js";import"./sparkline-CR_bzxwB.js";import{runAnalyticalScreen as i}from"./analytical-screen-CdtZfbes.js";import{Table as a}from"./ui-Bk5nl2yb.js";import{ApiV2Client as o}from"./api-v2-DP5YEHL_.js";import{Box as s,Text as c}from"ink";import l from"react";function u(e){return`${(e*100).toFixed(1)}%`}function d(e){return e<60?`${Math.round(e)}s`:e<3600?`${Math.floor(e/60)}m ${Math.round(e%60)}s`:`${Math.floor(e/3600)}h ${Math.floor(e%3600/60)}m`}async function f(f){let p=await e(),m=await t({strict:!1}),h=f.siteId??m?.teamId??``;if(!h)return process.stderr.write(`No site selected — pass --site-id or set ZENOVAY_SITE.
2
2
  `),2;let g=new o({config:p,cliVersion:f.cliVersion,token:m}),_=r(f),v=f.range??`24h`,y=[{key:`url`,header:`page`,width:40,format:e=>String(e??`—`)},{key:`views`,header:`views`,width:8,align:`right`}],b=[{key:`country`,header:`country`,width:8},{key:`visitors`,header:`visitors`,width:8,align:`right`}];return i({cliVersion:f.cliVersion,title:`stats · ${h} · ${v}`,commandName:`stats`,authToken:m?.accessToken??null,refreshIntervalMs:f.watch?6e4:0,fetcher:e=>g.getStats(h,v,e),format:_,headlessEmit:(e,t)=>{if(t===`json`||t===`ndjson`){process.stdout.write(JSON.stringify(e,null,t===`json`?2:0)),t===`ndjson`&&process.stdout.write(`
3
3
  `);return}process.stdout.write(n([{range:v,visitors:e.visitors,pageviews:e.pageviews,sessions:e.sessions,bounceRate:u(e.bounceRate),avgSession:d(e.avgSessionSec)}],[`range`,`visitors`,`pageviews`,`sessions`,`bounceRate`,`avgSession`],t))},panels:[{id:`summary`,title:`Summary`,render:e=>l.createElement(s,{flexDirection:`column`},l.createElement(c,null,l.createElement(c,{bold:!0},e.visitors.toLocaleString()),l.createElement(c,{color:`gray`},` visitors `),l.createElement(c,{bold:!0},e.pageviews.toLocaleString()),l.createElement(c,{color:`gray`},` pageviews `),l.createElement(c,{bold:!0},e.sessions.toLocaleString()),l.createElement(c,{color:`gray`},` sessions`)),l.createElement(c,{color:`gray`},`bounce `,u(e.bounceRate),` · avg session `,d(e.avgSessionSec)))},{id:`pages`,title:`Top pages`,render:e=>e.topPages.length===0?l.createElement(c,{color:`gray`},`— no pages —`):l.createElement(a,{data:e.topPages.slice(0,10),columns:y})},{id:`countries`,title:`Top countries`,render:e=>e.topCountries.length===0?l.createElement(c,{color:`gray`},`— no country data —`):l.createElement(a,{data:e.topCountries.slice(0,10),columns:b})}]})}export{f as statsCommand};
@@ -1 +1 @@
1
- import{readConfig as e}from"./config-ZTGpKEWg.js";import"./formatter-DQ6l4sWM.js";import{emit as t,isHeadless as n}from"./emit-DIRc7UzM.js";import{classifyBump as r,fetchManifest as i,platformKey as a}from"./check-S0ACFIfq.js";import o from"node:path";import{promises as s}from"node:fs";import c from"node:os";import l from"node:crypto";import u from"semver";const d=`AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=`;async function f(e){let t=await i({cliBase:e.cliBase,fetchImpl:e.fetchImpl});return p({...e,manifest:t})}async function p(e){let{manifest:t,currentVersion:n,forceDowngrade:i}=e,o=r(n,t.latest);if(o===`none`)return{updated:!1,from:n,to:t.latest,reason:`already-latest`};if(o===`downgrade`&&!i)return{updated:!1,from:n,to:t.latest,reason:`downgrade-blocked`};t.minSupported&&u.lt(n,t.minSupported);let c=a(),l=t.platforms[c];if(!l)throw Error(`No release binary for platform ${c}`);let d=await m(l,e.fetchImpl);try{return await h(d,l.sha256),await g(l,t.latest,c),await _(d,e.binaryPath),{updated:!0,from:n,to:t.latest}}catch(e){throw await s.unlink(d).catch(()=>void 0),e}}async function m(e,t=fetch){let n=await t(e.url);if(!n.ok)throw Error(`Download failed: ${n.status}`);let r=Buffer.from(await n.arrayBuffer()),i=await s.mkdtemp(o.join(c.tmpdir(),`zenovay-update-`)),a=o.join(i,`zenovay.new`);return await s.writeFile(a,r,{mode:493}),a}async function h(e,t){let n=await s.readFile(e),r=l.createHash(`sha256`).update(n).digest(`hex`);if(r.toLowerCase()!==t.toLowerCase())throw Error(`Checksum mismatch: expected ${t}, got ${r}. Update REFUSED.`)}async function g(e,t,n){let r=Buffer.from(d,`base64`);if(r.length!==32)throw Error(`Invalid release public key — update REFUSED.`);let i=Buffer.from(`${e.sha256}|${t}|${n}`),a=Buffer.from(e.sig,`base64`),o=l.createPublicKey({key:Buffer.concat([Buffer.from(`302a300506032b6570032100`,`hex`),r]),format:`der`,type:`spki`}),s=l.verify(null,i,o,a);if(!s)throw Error(`Signature verification FAILED. Update REFUSED.`)}async function _(e,t){let n=`${t}.old-${Date.now()}`;try{await s.rename(t,n)}catch(e){if(e.code!==`ENOENT`)throw e}try{await s.rename(e,t),process.platform!==`win32`&&await s.chmod(t,493),await s.unlink(n).catch(()=>void 0)}catch(e){try{await s.rename(n,t)}catch{}throw e}}async function v(a){let o=await e(),s=await i({cliBase:o.cliBase}),c=r(a.cliVersion,s.latest);if(a.check)return n({json:a.json})?t({type:`info`,message:`latest=${s.latest} current=${a.cliVersion} bump=${c}`}):process.stdout.write(`Current: ${a.cliVersion}\nLatest: ${s.latest}\nBump: ${c}\n`),{updated:!1,from:a.cliVersion,to:s.latest};if(c===`none`)return n({json:a.json})||process.stdout.write(`Already on latest (${a.cliVersion}).\n`),{updated:!1,from:a.cliVersion,to:s.latest};if(c===`downgrade`&&!a.forceDowngrade)throw Error(`Refused to downgrade ${a.cliVersion} → ${s.latest}. Pass --force-downgrade if you really want this.`);let l=await f({currentVersion:a.cliVersion,cliBase:o.cliBase,binaryPath:a.binaryPath,forceDowngrade:a.forceDowngrade});return n({json:a.json})?l.updated&&t({type:`update.applied`,from:l.from,to:l.to}):l.updated?process.stdout.write(`Updated ${l.from} → ${l.to}\n`):process.stdout.write(`Not updated (${l.reason??`unknown`}).\n`),l}export{v as updateCommand};
1
+ import{readConfig as e}from"./config-ZTGpKEWg.js";import"./formatter-45-fT1Hv.js";import{emit as t,isHeadless as n}from"./emit-0WJ_OGeT.js";import{classifyBump as r,fetchManifest as i,platformKey as a}from"./check-S0ACFIfq.js";import o from"node:path";import{promises as s}from"node:fs";import c from"node:os";import l from"node:crypto";import u from"semver";const d=`AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=`;async function f(e){let t=await i({cliBase:e.cliBase,fetchImpl:e.fetchImpl});return p({...e,manifest:t})}async function p(e){let{manifest:t,currentVersion:n,forceDowngrade:i}=e,o=r(n,t.latest);if(o===`none`)return{updated:!1,from:n,to:t.latest,reason:`already-latest`};if(o===`downgrade`&&!i)return{updated:!1,from:n,to:t.latest,reason:`downgrade-blocked`};t.minSupported&&u.lt(n,t.minSupported);let c=a(),l=t.platforms[c];if(!l)throw Error(`No release binary for platform ${c}`);let d=await m(l,e.fetchImpl);try{return await h(d,l.sha256),await g(l,t.latest,c),await _(d,e.binaryPath),{updated:!0,from:n,to:t.latest}}catch(e){throw await s.unlink(d).catch(()=>void 0),e}}async function m(e,t=fetch){let n=await t(e.url);if(!n.ok)throw Error(`Download failed: ${n.status}`);let r=Buffer.from(await n.arrayBuffer()),i=await s.mkdtemp(o.join(c.tmpdir(),`zenovay-update-`)),a=o.join(i,`zenovay.new`);return await s.writeFile(a,r,{mode:493}),a}async function h(e,t){let n=await s.readFile(e),r=l.createHash(`sha256`).update(n).digest(`hex`);if(r.toLowerCase()!==t.toLowerCase())throw Error(`Checksum mismatch: expected ${t}, got ${r}. Update REFUSED.`)}async function g(e,t,n){let r=Buffer.from(d,`base64`);if(r.length!==32)throw Error(`Invalid release public key — update REFUSED.`);let i=Buffer.from(`${e.sha256}|${t}|${n}`),a=Buffer.from(e.sig,`base64`),o=l.createPublicKey({key:Buffer.concat([Buffer.from(`302a300506032b6570032100`,`hex`),r]),format:`der`,type:`spki`}),s=l.verify(null,i,o,a);if(!s)throw Error(`Signature verification FAILED. Update REFUSED.`)}async function _(e,t){let n=`${t}.old-${Date.now()}`;try{await s.rename(t,n)}catch(e){if(e.code!==`ENOENT`)throw e}try{await s.rename(e,t),process.platform!==`win32`&&await s.chmod(t,493),await s.unlink(n).catch(()=>void 0)}catch(e){try{await s.rename(n,t)}catch{}throw e}}async function v(a){let o=await e(),s=await i({cliBase:o.cliBase}),c=r(a.cliVersion,s.latest);if(a.check)return n({json:a.json})?t({type:`info`,message:`latest=${s.latest} current=${a.cliVersion} bump=${c}`}):process.stdout.write(`Current: ${a.cliVersion}\nLatest: ${s.latest}\nBump: ${c}\n`),{updated:!1,from:a.cliVersion,to:s.latest};if(c===`none`)return n({json:a.json})||process.stdout.write(`Already on latest (${a.cliVersion}).\n`),{updated:!1,from:a.cliVersion,to:s.latest};if(c===`downgrade`&&!a.forceDowngrade)throw Error(`Refused to downgrade ${a.cliVersion} → ${s.latest}. Pass --force-downgrade if you really want this.`);let l=await f({currentVersion:a.cliVersion,cliBase:o.cliBase,binaryPath:a.binaryPath,forceDowngrade:a.forceDowngrade});return n({json:a.json})?l.updated&&t({type:`update.applied`,from:l.from,to:l.to}):l.updated?process.stdout.write(`Updated ${l.from} → ${l.to}\n`):process.stdout.write(`Not updated (${l.reason??`unknown`}).\n`),l}export{v as updateCommand};
@@ -1,3 +1,3 @@
1
- import{readConfig as e}from"./config-ZTGpKEWg.js";import{readToken as t}from"./api-D5XQeEDF.js";import{formatTabular as n,selectFormat as r}from"./formatter-DQ6l4sWM.js";import"./panel-DglZ755S.js";import"./keybar-D2OI-8rx.js";import"./prompt-hjzdzlyj.js";import"./sparkline-CR_bzxwB.js";import{runAnalyticalScreen as i}from"./analytical-screen-CS1ZL5Mo.js";import{Table as a}from"./ui-Bk5nl2yb.js";import{ApiV2Client as o}from"./api-v2-DP5YEHL_.js";import{Box as s,Text as c}from"ink";import l from"react";const u={lcp:{good:2500,poor:4e3},inp:{good:200,poor:500},cls:{good:.1,poor:.25},ttfb:{good:800,poor:1800},fcp:{good:1800,poor:3e3}};function d(e,t){let n=u[e];return t<=n.good?{label:`good`,color:`green`}:t<=n.poor?{label:`needs`,color:`yellow`}:{label:`poor`,color:`red`}}function f(e,t){return e===`cls`?t.toFixed(3):t<1e3?`${Math.round(t)}ms`:`${(t/1e3).toFixed(2)}s`}async function p(u){let p=await e(),m=await t({strict:!1}),h=u.siteId??m?.teamId??``;if(!h)return process.stderr.write(`No site selected — pass --site-id or set ZENOVAY_SITE.
1
+ import{readConfig as e}from"./config-ZTGpKEWg.js";import{readToken as t}from"./api-D5XQeEDF.js";import{formatTabular as n,selectFormat as r}from"./formatter-45-fT1Hv.js";import"./panel-DglZ755S.js";import"./keybar-D2OI-8rx.js";import"./prompt-hjzdzlyj.js";import"./sparkline-CR_bzxwB.js";import{runAnalyticalScreen as i}from"./analytical-screen-CdtZfbes.js";import{Table as a}from"./ui-Bk5nl2yb.js";import{ApiV2Client as o}from"./api-v2-DP5YEHL_.js";import{Box as s,Text as c}from"ink";import l from"react";const u={lcp:{good:2500,poor:4e3},inp:{good:200,poor:500},cls:{good:.1,poor:.25},ttfb:{good:800,poor:1800},fcp:{good:1800,poor:3e3}};function d(e,t){let n=u[e];return t<=n.good?{label:`good`,color:`green`}:t<=n.poor?{label:`needs`,color:`yellow`}:{label:`poor`,color:`red`}}function f(e,t){return e===`cls`?t.toFixed(3):t<1e3?`${Math.round(t)}ms`:`${(t/1e3).toFixed(2)}s`}async function p(u){let p=await e(),m=await t({strict:!1}),h=u.siteId??m?.teamId??``;if(!h)return process.stderr.write(`No site selected — pass --site-id or set ZENOVAY_SITE.
2
2
  `),2;let g=new o({config:p,cliVersion:u.cliVersion,token:m}),_=r(u),v=[{key:`url`,header:`url`,width:32},{key:`device`,header:`device`,width:7,format:e=>String(e??`—`)},{key:`lcp`,header:`LCP p75`,width:9,align:`right`,format:e=>e&&typeof e==`object`&&`p75`in e?f(`lcp`,e.p75):`—`},{key:`inp`,header:`INP p75`,width:9,align:`right`,format:e=>e&&typeof e==`object`&&`p75`in e?f(`inp`,e.p75):`—`},{key:`cls`,header:`CLS p75`,width:9,align:`right`,format:e=>e&&typeof e==`object`&&`p75`in e?f(`cls`,e.p75):`—`},{key:`samples`,header:`n`,width:6,align:`right`}];return i({cliVersion:u.cliVersion,title:`vitals · ${h}`,commandName:`vitals`,authToken:m?.accessToken??null,refreshIntervalMs:u.watch?5*6e4:0,fetcher:e=>g.getVitals(h,{url:u.url,device:u.device,window:u.window},e),format:_,headlessEmit:(e,t)=>{if(t===`json`||t===`ndjson`){process.stdout.write(JSON.stringify(e,null,t===`json`?2:0)),t===`ndjson`&&process.stdout.write(`
3
3
  `);return}process.stdout.write(n(e.vitals,[`url`,`device`,`samples`],t))},panels:[{id:`summary`,title:`Site-wide p75`,render:e=>{let t=t=>{let n=0,r=0;for(let i of e.vitals){let e=i[t]?.p75;typeof e==`number`&&(n+=e*i.samples,r+=i.samples)}return r>0?n/r:0},n=[`lcp`,`inp`,`cls`,`ttfb`,`fcp`];return l.createElement(s,{flexDirection:`column`},n.map(e=>{let n=t(e),r=d(e,n);return l.createElement(c,{key:e},l.createElement(c,{color:r.color},`● `),l.createElement(c,{bold:!0},e.toUpperCase().padEnd(5)),` `,l.createElement(c,null,f(e,n).padStart(8)),` `,l.createElement(c,{color:r.color},r.label))}))}},{id:`pages`,title:`Per-page`,render:e=>e.vitals.length===0?l.createElement(c,{color:`gray`},`— no vitals data yet —`):l.createElement(a,{data:e.vitals.slice(0,15),columns:v})}]})}export{p as vitalsCommand};
@@ -1,2 +1,2 @@
1
- import{readConfig as e}from"./config-ZTGpKEWg.js";import{ApiClient as t,readToken as n}from"./api-D5XQeEDF.js";import{parseSseStream as r}from"./client-Bc1xZcH_.js";import"./formatter-DQ6l4sWM.js";import{emit as i,isHeadless as a}from"./emit-DIRc7UzM.js";import{Panel as o}from"./panel-DglZ755S.js";import{Banner as s,Keybar as c}from"./keybar-D2OI-8rx.js";import{spark as l}from"./sparkline-CR_bzxwB.js";import{Box as u,Text as d,render as f,useApp as p,useInput as m}from"ink";import h,{useEffect as g,useState as _}from"react";import v from"ink-spinner";import y from"ink-text-input";const b=Math.PI*2;function x(e){let t=e,n=Math.PI*Math.sin(e);for(let e=0;e<6;e++){let e=2*t+Math.sin(2*t)-n,r=2+2*Math.cos(2*t);if(r===0)break;t-=e/r}return t}function S(e,t){if(e<-90||e>90||t<-180||t>180)return null;let n=e*Math.PI/180,r=t*Math.PI/180,i=x(n),a=r*Math.cos(i)/Math.PI,o=Math.sin(i);return{x:a,y:o}}function C(e){if(e)return!0;let t=process.env;if(t.NO_COLOR||t.ZENOVAY_GLOBE===`ascii`)return!0;let n=(t.LANG||t.LC_ALL||t.LC_CTYPE||``).toLowerCase();return!!(n&&!n.includes(`utf`))}function w(e,t){let n=e*2,r=t*4;return{dw:n,dh:r,bits:new Uint8Array(n*r)}}function T(e,t,n){t<0||t>=e.dw||n<0||n>=e.dh||(e.bits[n*e.dw+t]=1)}function E(e){let t=e.dw/2,n=e.dh/2,r=e.dw/2-1,i=e.dh/2-1,a=Math.max(e.dw,e.dh)*2;for(let o=0;o<a;o++){let s=o/a*b,c=Math.round(t+r*Math.cos(s)),l=Math.round(n+i*Math.sin(s));T(e,c,l)}}function D(e){let t=Math.floor(e.dh/2);for(let n=0;n<e.dw;n+=4)T(e,n,t)}function O(e,t){let n=e.dw/2,r=e.dh/2,i=e.dw/2-1,a=e.dh/2-1;for(let o of t){let t=S(o.lat,o.lng);if(!t)continue;let s=Math.round(n+t.x*i),c=Math.round(r-t.y*a);T(e,s,c),T(e,s+1,c),T(e,s,c+1),T(e,s+1,c+1)}}const k=[[0,0],[0,1],[0,2],[1,0],[1,1],[1,2],[0,3],[1,3]];function A(e,t,n){let r=0;for(let i=0;i<k.length;i++){let[a,o]=k[i],s=t*2+a,c=n*4+o;e.bits[c*e.dw+s]&&(r|=1<<i)}return r===0?` `:String.fromCodePoint(10240+r)}function j(e,t,n){let r=0;for(let i=0;i<4;i++)for(let a=0;a<2;a++){let o=t*2+a,s=n*4+i;e.bits[s*e.dw+o]&&r++}return r===0?` `:r<=2?`.`:r<=4?`:`:r<=6?`*`:`#`}function M({data:e,width:t=80,height:n=20,asciiOnly:r}){let i=C(r),a=w(t,n);E(a),D(a),O(a,e);let o=[];for(let e=0;e<n;e++){let n=``;for(let r=0;r<t;r++)n+=i?j(a,r,e):A(a,r,e);o.push(n)}return h.createElement(u,{flexDirection:`column`},o.map((e,t)=>h.createElement(d,{key:t,color:`magenta`},e)),h.createElement(d,{color:`gray`},e.length,` live · `,i?`ascii mode`:`braille mode`))}async function N(r){let o=await e(),s=await n({strict:!1});if(!s)return process.stderr.write("Not logged in — run `zenovay login` first.\n"),2;let c=new t({config:o,cliVersion:r.cliVersion,token:s}),l=r.siteId??s.teamId;if(!l)return process.stderr.write(`No site selected — pass --site-id.
1
+ import{readConfig as e}from"./config-ZTGpKEWg.js";import{ApiClient as t,readToken as n}from"./api-D5XQeEDF.js";import{parseSseStream as r}from"./client-DZ4Awt8u.js";import"./formatter-45-fT1Hv.js";import{emit as i,isHeadless as a}from"./emit-0WJ_OGeT.js";import{Panel as o}from"./panel-DglZ755S.js";import{Banner as s,Keybar as c}from"./keybar-D2OI-8rx.js";import{spark as l}from"./sparkline-CR_bzxwB.js";import{Box as u,Text as d,render as f,useApp as p,useInput as m}from"ink";import h,{useEffect as g,useState as _}from"react";import v from"ink-spinner";import y from"ink-text-input";const b=Math.PI*2;function x(e){let t=e,n=Math.PI*Math.sin(e);for(let e=0;e<6;e++){let e=2*t+Math.sin(2*t)-n,r=2+2*Math.cos(2*t);if(r===0)break;t-=e/r}return t}function S(e,t){if(e<-90||e>90||t<-180||t>180)return null;let n=e*Math.PI/180,r=t*Math.PI/180,i=x(n),a=r*Math.cos(i)/Math.PI,o=Math.sin(i);return{x:a,y:o}}function C(e){if(e)return!0;let t=process.env;if(t.NO_COLOR||t.ZENOVAY_GLOBE===`ascii`)return!0;let n=(t.LANG||t.LC_ALL||t.LC_CTYPE||``).toLowerCase();return!!(n&&!n.includes(`utf`))}function w(e,t){let n=e*2,r=t*4;return{dw:n,dh:r,bits:new Uint8Array(n*r)}}function T(e,t,n){t<0||t>=e.dw||n<0||n>=e.dh||(e.bits[n*e.dw+t]=1)}function E(e){let t=e.dw/2,n=e.dh/2,r=e.dw/2-1,i=e.dh/2-1,a=Math.max(e.dw,e.dh)*2;for(let o=0;o<a;o++){let s=o/a*b,c=Math.round(t+r*Math.cos(s)),l=Math.round(n+i*Math.sin(s));T(e,c,l)}}function D(e){let t=Math.floor(e.dh/2);for(let n=0;n<e.dw;n+=4)T(e,n,t)}function O(e,t){let n=e.dw/2,r=e.dh/2,i=e.dw/2-1,a=e.dh/2-1;for(let o of t){let t=S(o.lat,o.lng);if(!t)continue;let s=Math.round(n+t.x*i),c=Math.round(r-t.y*a);T(e,s,c),T(e,s+1,c),T(e,s,c+1),T(e,s+1,c+1)}}const k=[[0,0],[0,1],[0,2],[1,0],[1,1],[1,2],[0,3],[1,3]];function A(e,t,n){let r=0;for(let i=0;i<k.length;i++){let[a,o]=k[i],s=t*2+a,c=n*4+o;e.bits[c*e.dw+s]&&(r|=1<<i)}return r===0?` `:String.fromCodePoint(10240+r)}function j(e,t,n){let r=0;for(let i=0;i<4;i++)for(let a=0;a<2;a++){let o=t*2+a,s=n*4+i;e.bits[s*e.dw+o]&&r++}return r===0?` `:r<=2?`.`:r<=4?`:`:r<=6?`*`:`#`}function M({data:e,width:t=80,height:n=20,asciiOnly:r}){let i=C(r),a=w(t,n);E(a),D(a),O(a,e);let o=[];for(let e=0;e<n;e++){let n=``;for(let r=0;r<t;r++)n+=i?j(a,r,e):A(a,r,e);o.push(n)}return h.createElement(u,{flexDirection:`column`},o.map((e,t)=>h.createElement(d,{key:t,color:`magenta`},e)),h.createElement(d,{color:`gray`},e.length,` live · `,i?`ascii mode`:`braille mode`))}async function N(r){let o=await e(),s=await n({strict:!1});if(!s)return process.stderr.write("Not logged in — run `zenovay login` first.\n"),2;let c=new t({config:o,cliVersion:r.cliVersion,token:s}),l=r.siteId??s.teamId;if(!l)return process.stderr.write(`No site selected — pass --site-id.
2
2
  `),2;if(a(r)){let e=await c.getDashboardSnapshot(l);return i({type:`watch.tick`,snapshot:e}),0}return new Promise(e=>{let{unmount:t}=f(h.createElement(P,{api:c,siteId:l,intervalMs:r.intervalMs??15e3,cliVersion:r.cliVersion,onExit:n=>{t(),e(n)}}))})}const P=({api:e,siteId:t,intervalMs:n,cliVersion:i,onExit:a})=>{let{exit:l}=p(),[f,y]=_(null),[b,x]=_(null),[S,C]=_(null),[w,T]=_([]),[E,D]=_(!0),[O,k]=_(null),[A,j]=_(1),[N,P]=_(!1),[H,U]=_(!1);if(m((e,t)=>{if(e===`q`){l(),a(0);return}if(e===`?`||e===`/`){U(e=>!e);return}if(e===`g`){P(e=>!e);return}if(t.tab){j(e=>{let n=t.shift?(e+4)%6+1:e%6+1;return n});return}(e===`1`||e===`2`||e===`3`||e===`4`||e===`5`||e===`6`)&&j(Number(e))}),g(()=>{let r=!1,i=async()=>{try{let n=await e.getDashboardSnapshot(t);if(r)return;y(n);let i=e.getVitals;typeof i==`function`&&i.call(e,t).then(e=>{r||x(e)},()=>{});let a=e.getGoals;typeof a==`function`&&a.call(e,t).then(e=>{r||C(e)},()=>{}),D(!1),k(null)}catch(e){r||k(e.message)}};i();let a=setInterval(i,n);return()=>{r=!0,clearInterval(a)}},[e,t,n]),g(()=>{let n=new AbortController;return(async()=>{try{let i=await e.openEventsStream(t,n.signal);for await(let e of r(i))e.type===`error`&&T(t=>[...t,`[ERR ${e.code}] ${e.message}`].slice(-10))}catch{}})(),()=>n.abort()},[e,t]),E)return h.createElement(u,{flexDirection:`column`},h.createElement(s,{version:i,subtitle:`watch · ${t}`}),h.createElement(o,{title:`Loading`,state:`busy`},h.createElement(u,null,h.createElement(d,{color:`magenta`},h.createElement(v,{type:`dots`})),h.createElement(d,null,` Fetching snapshot…`))));if(O&&!f)return h.createElement(u,{flexDirection:`column`},h.createElement(s,{version:i,subtitle:`watch · ${t}`}),h.createElement(o,{title:`Error`,state:`err`},h.createElement(d,{color:`red`},O)));let W=process.stdout.columns??80,G=Math.max(20,Math.floor(W/3)-1),K=[];return h.createElement(u,{flexDirection:`column`},h.createElement(s,{version:i,subtitle:`watch · ${t}${N?` · globe`:``}`}),h.createElement(u,{flexDirection:`row`},h.createElement(u,{flexDirection:`column`},N?h.createElement(o,{title:`Live globe`,focused:A===1,width:G},h.createElement(M,{data:K,width:Math.max(40,G-4),height:12})):h.createElement(I,{snapshot:f,focused:A===1,width:G}),h.createElement(z,{events:w,focused:A===4,width:G})),h.createElement(u,{flexDirection:`column`},h.createElement(L,{snapshot:f,focused:A===2,width:G}),h.createElement(B,{vitals:b,focused:A===5,width:G})),h.createElement(u,{flexDirection:`column`},h.createElement(R,{snapshot:f,focused:A===3,width:G}),h.createElement(V,{goals:S,focused:A===6,width:G}))),H?h.createElement(F,{api:e,siteId:t,width:W-2}):null,h.createElement(c,{items:[{key:`tab`,label:`next`},{key:`1-6`,label:`jump`},{key:`g`,label:N?`panels`:`globe`},{key:`?/`,label:H?`close chat`:`ai chat`},{key:`q`,label:`quit`}]}))},F=({api:e,siteId:t,width:n})=>{let[i,a]=_(``),[s,c]=_([]),[l,f]=_(!1),[p,m]=_(``),[g,v]=_(null),b=async n=>{let i=n.trim();if(!i||l)return;v(null),a(``);let o=[...s,{role:`user`,content:i}];c(o),f(!0),m(``);try{let n=o.map(e=>({role:e.role,content:e.content})),i=await e.openAiStream(`chat`,{messages:n,siteId:t},void 0),a=``;for await(let e of r(i))if(e.type===`delta`)a+=e.content,m(a);else if(e.type===`error`)v(`${e.code}: ${e.message}`);else if(e.type===`done`)break;c([...o,{role:`assistant`,content:a}]),m(``)}catch(e){v(e instanceof Error?e.message:`chat failed`)}finally{f(!1)}};return h.createElement(u,{marginTop:1},h.createElement(o,{title:`AI chat (esc / ?/ to close)`,focused:!0,width:n},h.createElement(u,{flexDirection:`column`},s.slice(-6).map((e,t)=>h.createElement(u,{key:t,flexDirection:`column`,marginBottom:1},h.createElement(d,{color:e.role===`user`?`cyan`:`magenta`,bold:!0},e.role===`user`?`you`:`zenovay`),h.createElement(d,null,e.content))),l&&p?h.createElement(u,{flexDirection:`column`,marginBottom:1},h.createElement(d,{color:`magenta`,bold:!0},`zenovay`),h.createElement(d,null,p)):null,g?h.createElement(d,{color:`red`},`✗ `,g):null,h.createElement(u,null,h.createElement(d,{color:`cyan`},l?`⠋ `:`▸ `),h.createElement(y,{value:i,onChange:a,onSubmit:b,placeholder:l?`streaming…`:`ask anything about your analytics`})))))},I=({snapshot:e,focused:t,width:n})=>{let r=e?.visitors?.count??0,i=e?.visitors?.series??[];return h.createElement(o,{title:`Visitors`,focused:t,width:n},h.createElement(d,{bold:!0},r.toString()),h.createElement(d,{color:`gray`},i.length>0?l(i,Math.max(8,n-6)):`— no data —`))},L=({snapshot:e,focused:t,width:n})=>{let r=e?.topPages?.slice(0,5)??[];return h.createElement(o,{title:`Top pages`,focused:t,width:n},r.length===0?h.createElement(d,{color:`gray`},`— no data —`):r.map(e=>h.createElement(u,{key:e.path},h.createElement(d,null,e.path.padEnd(n-10).slice(0,n-10)),h.createElement(d,{color:`gray`},` `,e.views))))},R=({snapshot:e,focused:t,width:n})=>{let r=e?.sources?.slice(0,5)??[];return h.createElement(o,{title:`Sources`,focused:t,width:n},r.length===0?h.createElement(d,{color:`gray`},`— no data —`):r.map(e=>h.createElement(u,{key:e.source},h.createElement(d,null,e.source.padEnd(n-10).slice(0,n-10)),h.createElement(d,{color:`gray`},` `,e.visitors))))},z=({events:e,focused:t,width:n})=>h.createElement(o,{title:`Events`,focused:t,width:n},e.length===0?h.createElement(d,{color:`gray`},`— waiting —`):e.slice(-10).map((e,t)=>h.createElement(d,{key:t},e.slice(0,n-4)))),B=({vitals:e,focused:t,width:n})=>{let r=(e,t,n)=>h.createElement(u,{key:e},h.createElement(d,{bold:!0},e.padEnd(6)),h.createElement(d,{color:`gray`},typeof t==`number`?`${t.toFixed(0)}${n}`:`—`));return h.createElement(o,{title:`Vitals`,focused:t,width:n},r(`LCP`,e?.lcpP75,`ms`),r(`INP`,e?.inpP75,`ms`),r(`CLS`,e?.clsP75?e.clsP75*1e3:void 0,`/1k`),r(`TTFB`,e?.ttfbP75,`ms`),r(`FCP`,e?.fcpP75,`ms`))},V=({goals:e,focused:t,width:n})=>{let r=e?.goals?.slice(0,5)??[];return h.createElement(o,{title:`Goals`,focused:t,width:n},r.length===0?h.createElement(d,{color:`gray`},`— no data —`):r.map(e=>h.createElement(u,{key:e.name},h.createElement(d,null,e.name.padEnd(n-10).slice(0,n-10)),h.createElement(d,{color:`gray`},` `,e.completions))))};export{N as watchCommand};
@@ -1,2 +1,2 @@
1
1
  #!/usr/bin/env node
2
- import(`./init-DPyKsF9Y.js`).then(async({initCommand:e})=>{let{readFileSync:t}=await import(`node:fs`),n=await import(`node:path`),{fileURLToPath:r}=await import(`node:url`),i=n.dirname(r(import.meta.url)),a=JSON.parse(t(n.join(i,`..`,`package.json`),`utf8`)),o=process.argv.slice(2),s=o.includes(`--json`),c=o.includes(`--yes`),l=o.includes(`--skip-mcp`),u=o.includes(`--skip-verify`),d=await e({cliVersion:a.version,cwd:process.cwd(),json:s,yes:c,skipMcp:l,skipVerify:u});process.exit(d)});
2
+ import(`./init-DlfdHqEi.js`).then(async({initCommand:e})=>{let{readFileSync:t}=await import(`node:fs`),n=await import(`node:path`),{fileURLToPath:r}=await import(`node:url`),i=n.dirname(r(import.meta.url)),a=JSON.parse(t(n.join(i,`..`,`package.json`),`utf8`)),o=process.argv.slice(2),s=o.includes(`--json`),c=o.includes(`--yes`),l=o.includes(`--skip-mcp`),u=o.includes(`--skip-verify`),d=await e({cliVersion:a.version,cwd:process.cwd(),json:s,yes:c,skipMcp:l,skipVerify:u});process.exit(d)});
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zenovay/cli",
3
- "version": "0.1.7",
3
+ "version": "0.1.8",
4
4
  "description": "Zenovay CLI — AI install wizard + full terminal analytics dashboard",
5
5
  "type": "module",
6
6
  "bin": {
@@ -1,11 +0,0 @@
1
- import{readConfig as e}from"./config-ZTGpKEWg.js";import{ApiClient as t,readToken as n}from"./api-D5XQeEDF.js";import{parseSseStream as r}from"./client-Bc1xZcH_.js";import"./formatter-DQ6l4sWM.js";import{emit as i,isHeadless as a}from"./emit-DIRc7UzM.js";import{initCommand as o}from"./init-B_nZyv9Q.js";import"./login-CxXnVN9s.js";import{Panel as s}from"./panel-DglZ755S.js";import"./keybar-D2OI-8rx.js";import{Select as c}from"./prompt-hjzdzlyj.js";import"./sparkline-CR_bzxwB.js";import l from"node:path";import{promises as u}from"node:fs";import{Box as d,Text as f,render as p}from"ink";import m from"react";import{globby as h}from"globby";const g=[`@zenovay/tracker`,`@zenovay/next`,`@zenovay/nuxt`,`@zenovay/svelte`,`@zenovay/astro`,`@zenovay/remix`,`@zenovay/node`],_=[`zenovay.config.ts`,`zenovay.config.js`,`zenovay.config.mjs`,`zenovay.config.json`],v=/api\.zenovay\.com\/z\.js|cdn\.zenovay\.com\/t\.js/,y=/data-zenovay-site|data-id\s*=\s*"ZV_/;async function b(e){let t=[],n={installed:!1,reasons:t};try{let r=await u.readFile(l.join(e,`package.json`),`utf8`),i=JSON.parse(r),a={...i.dependencies,...i.devDependencies};for(let e of g)if(e in a){t.push(`dep:${e}`),n.packageMarker=e,n.installed=!0;break}}catch{}for(let r of _)try{await u.access(l.join(e,r)),t.push(`config:${r}`),n.configFile=r,n.installed=!0;break}catch{}try{let r=await h([`**/*.{html,htm,tsx,jsx,vue,svelte,astro,ts,js,mjs}`,`!node_modules/**`,`!.git/**`,`!dist/**`,`!.next/**`,`!.nuxt/**`,`!build/**`,`!.output/**`],{cwd:e,gitignore:!0,deep:4,absolute:!0});for(let i of r.slice(0,200))try{let r=await u.readFile(i,`utf8`);if(v.test(r)||y.test(r)){t.push(`script:${l.relative(e,i)}`),n.scriptFile=l.relative(e,i),n.installed=!0;break}}catch{}}catch{}return n}async function x(e){let t=await b(e.cwd),n;if(e.mode)n=e.mode;else if(!t.installed)n=`install`;else if(a(e))return i({type:`error`,code:`no_mode`,message:`Headless mode requires --mode chat|mcp|install`}),2;else n=await S(t);return n===`install`?o({cliVersion:e.cliVersion,cwd:e.cwd,json:e.json}):n===`chat`?C(e):w(e)}async function S(e){return new Promise(t=>{let n=[{label:`Chat with your analytics`,value:`chat`,description:`Ask natural-language questions about your data`},{label:`Manage via MCP`,value:`mcp`,description:`Create goals, funnels, sites, etc. in plain English`},{label:`Re-run install / repair`,value:`install`,description:`Run the install wizard again`}],{unmount:r}=p(m.createElement(d,{flexDirection:`column`},m.createElement(s,{title:`Zenovay detected${e.packageMarker?` (${e.packageMarker})`:``}`,state:`idle`},m.createElement(f,null,`What do you want to do?`)),m.createElement(c,{items:n,onSelect:e=>{r(),t(e)}})))})}async function C(i){let a=await e(),o=await n({strict:!1});if(!o)return process.stderr.write("Not logged in — run `zenovay login` first.\n"),2;let s=new t({config:a,cliVersion:i.cliVersion,token:o});process.stdout.write(`
2
- Zenovay · chat mode — type your question then press Enter. Ctrl-C to exit.
3
-
4
- > `);let c=await T();if(!c)return 0;let l=await s.openAiStream(`chat`,{messages:[{role:`user`,content:c}]});for await(let e of r(l)){if(e.type===`delta`&&process.stdout.write(e.content),e.type===`done`){process.stdout.write(`
5
- `);break}if(e.type===`error`)return process.stderr.write(`\n[${e.code}] ${e.message}\n`),1}return 0}async function w(i){let a=await e(),o=await n({strict:!1});if(!o)return process.stderr.write("Not logged in — run `zenovay login` first.\n"),2;let s=new t({config:a,cliVersion:i.cliVersion,token:o});process.stdout.write(`
6
- Zenovay · MCP mode — describe what you want to create or change. Ctrl-C to exit.
7
-
8
- > `);let c=await T();if(!c)return 0;let l=await s.openAiStream(`mcp`,{messages:[{role:`user`,content:c}]});for await(let e of r(l)){if(e.type===`delta`&&process.stdout.write(e.content),e.type===`tool_start`&&process.stdout.write(`\n[tool: ${e.name}] `),e.type===`tool_result`&&process.stdout.write(`
9
- [result]`),e.type===`done`){process.stdout.write(`
10
- `);break}if(e.type===`error`)return process.stderr.write(`\n[${e.code}] ${e.message}\n`),1}return 0}function T(){return new Promise(e=>{let t=``,n=r=>{let i=r.toString(`utf8`);i.includes(`
11
- `)||i.includes(`\r`)?(t+=i.replace(/[\r\n]/g,``),process.stdin.off(`data`,n),process.stdin.pause(),e(t)):t+=i};process.stdin.resume(),process.stdin.on(`data`,n)})}export{x as aiCommand};
@@ -1,61 +0,0 @@
1
- import{readConfig as e}from"./config-ZTGpKEWg.js";import{ApiClient as t,readToken as n}from"./api-D5XQeEDF.js";import{parseSseStream as r}from"./client-Bc1xZcH_.js";import{emit as i,isHeadless as a}from"./emit-DIRc7UzM.js";import{loginCommand as o}from"./login-CxXnVN9s.js";import{Panel as s}from"./panel-DglZ755S.js";import{Banner as c,BrandGradient as l,Keybar as u}from"./keybar-D2OI-8rx.js";import{Select as d}from"./prompt-hjzdzlyj.js";import{spark as f}from"./sparkline-CR_bzxwB.js";import p from"node:path";import{promises as m}from"node:fs";import{Box as h,Text as g,render as _,useApp as ee,useInput as v}from"ink";import y,{useEffect as b,useRef as te,useState as x}from"react";import S from"node:os";import{z as C}from"zod";import{globby as w}from"globby";import T from"ink-spinner";import E from"node:crypto";import{ulid as D}from"ulid";import{applyPatch as O}from"diff";const k=[{name:`openai-proj`,regex:/\bsk-proj-[A-Za-z0-9_-]{20,}\b/g},{name:`anthropic`,regex:/\bsk-ant-[A-Za-z0-9_-]{20,}\b/g},{name:`openai-sk`,regex:/\bsk-[A-Za-z0-9]{20,}\b/g},{name:`github-pat-new`,regex:/\bgithub_pat_[A-Za-z0-9_]{82}\b/g},{name:`github-pat`,regex:/\bghp_[A-Za-z0-9]{36}\b/g},{name:`github-oauth`,regex:/\bgho_[A-Za-z0-9]{36}\b/g},{name:`aws-access-key`,regex:/\b(?:AKIA|ASIA)[A-Z0-9]{16}\b/g},{name:`stripe-live`,regex:/\b(?:sk|pk)_live_[A-Za-z0-9]{24,}\b/g},{name:`stripe-test`,regex:/\b(?:sk|pk)_test_[A-Za-z0-9]{24,}\b/g},{name:`stripe-restricted`,regex:/\brk_(?:live|test)_[A-Za-z0-9]{24,}\b/g},{name:`stripe-webhook`,regex:/\bwhsec_[A-Za-z0-9]{24,}\b/g},{name:`slack-bot`,regex:/\bxox[bpoa]-[A-Za-z0-9-]{10,}\b/g},{name:`google-api`,regex:/\bAIza[0-9A-Za-z_-]{35}\b/g},{name:`jwt`,regex:/\beyJ[A-Za-z0-9_-]+\.eyJ[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\b/g},{name:`private-key-rsa`,regex:/-----BEGIN (?:RSA|EC|OPENSSH|DSA|PGP) PRIVATE KEY(?: BLOCK)?-----/g},{name:`private-key-pkcs8`,regex:/-----BEGIN PRIVATE KEY-----/g}];function A(e){let t=e;for(let e of k){let n=new RegExp(e.regex.source,e.regex.flags);t=t.replace(n,`[REDACTED:${e.name}]`)}return t}const j=[/^package\.json$/,/^package-lock\.json$/,/^pnpm-lock\.yaml$/,/^yarn\.lock$/,/^bun\.lock$/,/^tsconfig.*\.json$/,/^(next|nuxt|vite|astro|remix|svelte|tailwind|postcss)\.config\.(ts|mts|cts|js|mjs|cjs)$/,/^app\/.*\.(tsx|ts|jsx|js|svelte|astro|vue)$/,/^pages\/.*\.(tsx|ts|jsx|js)$/,/^public\/index\.html$/,/^index\.html$/,/^src\/main\.(tsx|ts|jsx|js)$/,/^src\/App\.(tsx|ts|jsx|js|svelte|vue)$/,/^src\/routes\/\+layout\.(svelte|ts|js)$/,/^src\/routes\/root\..*$/,/^src\/layouts\/.*\.(astro|svelte|vue)$/,/^\.env\.example$/,/^README\.md$/,/^\.gitignore$/,/^nuxt\.config\.(ts|js|mjs)$/,/^plugins\/.*\.(ts|js)$/],M=[/(^|\/)\.env($|\.(?!example$)[^/]+$)/,/(^|\/)\.git(\/|$)/,/(^|\/)node_modules\//,/(^|\/)\.ssh\//,/(^|\/)\.aws\//,/\.pem$/,/\.key$/,/(^|\/)id_rsa($|\.)/,/(^|\/)\.npmrc$/,/(^|\/)credentials(\.|$)/],N=256*1024,P=50,F=20,I=40;var L=class extends Error{constructor(e,t){super(t),this.code=e,this.name=`SandboxError`}},R=class{sessionId;cwd;cwdReal;undoRoot;readCount=0;writeCount=0;roundCount=0;constructor(e){this.sessionId=e.sessionId??D(),this.cwd=e.cwd,this.cwdReal=m.realpath(e.cwd),this.undoRoot=e.undoRoot??p.join(S.homedir(),`.zenovay`,`undo`)}incrementRound(){if(this.roundCount++,this.roundCount>I)throw new L(`round-cap`,`Tool-call recursion cap (${I}) exceeded.`)}stats(){return{sessionId:this.sessionId,reads:this.readCount,writes:this.writeCount,rounds:this.roundCount}}async resolveForRead(e){return this.resolveSafe(e,`read`)}async resolveForWrite(e){return this.resolveSafe(e,`write`)}async resolveSafe(e,t){if(typeof e!=`string`||e.length===0)throw new L(`escape`,`Path must be a non-empty string.`);if(e.includes(`\0`))throw new L(`escape`,`Null byte in path.`);if(/^\\\\[?.]\\/.test(e)||/^\\\\[A-Za-z0-9]/.test(e))throw new L(`escape`,`Windows special path prefix: ${e}`);if(/%/.test(e))try{let t=decodeURIComponent(e);if(/%[0-9A-Fa-f]{2}/.test(t))throw new L(`escape`,`Double-encoded path: ${e}`);e=t}catch(t){throw t instanceof L?t:new L(`escape`,`Malformed percent-encoding: ${e}`)}if(e.includes(`\0`))throw new L(`escape`,`Null byte in decoded path.`);if(e.includes(`\\`))throw new L(`escape`,`Backslash in path (Windows-style separator not accepted): ${e}`);let n=await this.cwdReal,r=p.isAbsolute(e)?e:p.join(n,e),i=p.normalize(r),a=i;try{a=await m.realpath(i)}catch(e){if(e.code!==`ENOENT`)throw new L(`escape`,`realpath failed: ${e.message}`);let t=p.dirname(i);try{let e=await m.realpath(t);a=p.join(e,p.basename(i))}catch{}}if(!this.isWithin(a,n))throw new L(`escape`,`Path escapes cwd: ${e}`);let o=p.relative(n,a);for(let e of M)if(e.test(o)){if(t===`read`&&/(^|\/)node_modules\//.test(o))continue;throw new L(`blocklisted`,`Path is on the hard blocklist: ${o}`)}if(t===`write`){let e=j.some(e=>e.test(o));if(!e&&!/^\.env(\.local)?$/.test(o)&&!/^\.claude\//.test(o)&&!/^\.cursor\//.test(o))throw new L(`not-allowlisted`,`Write path not on allowlist: ${o}`)}return a}isWithin(e,t){let n=p.relative(t,e);return!n.startsWith(`..`)&&!p.isAbsolute(n)}async safeRead(e){if(this.readCount>=P)throw new L(`read-cap`,`Read cap (${P}) reached.`);let t=await this.resolveForRead(e),n=await m.stat(t);if(n.size>N)throw new L(`too-large`,`File exceeds ${N}B: ${e} (${n.size}B)`);let r=await m.readFile(t),i=r.subarray(0,Math.min(r.length,8192));if(i.includes(0))throw new L(`binary-rejected`,`Binary content in ${e}.`);return this.readCount++,r.toString(`utf8`)}async safeWrite(e,t){if(this.writeCount>=F)throw new L(`write-cap`,`Write cap (${F}) reached.`);if(t.length>N)throw new L(`too-large`,`Write exceeds ${N}B: ${e}`);let n=await this.resolveForWrite(e),r=await this.journalBackup(n);return await m.mkdir(p.dirname(n),{recursive:!0}),await m.writeFile(n,t,`utf8`),this.writeCount++,{backupPath:r}}async journalBackup(e){let t=await m.readFile(e).catch(e=>{if(e.code===`ENOENT`)return null;throw e}),n=p.join(this.undoRoot,this.sessionId);await m.mkdir(n,{recursive:!0,mode:448});let r=E.createHash(`sha256`).update(e).digest(`hex`).slice(0,16),i=p.join(n,`${r}.bak`),a=p.join(n,`manifest.jsonl`);t&&await m.writeFile(i,t,{mode:384});let o=JSON.stringify({abs:e,backupPath:t?i:null,ts:Date.now()});return await m.appendFile(a,o+`
2
- `,{mode:384}),t?i:null}static wrapForModel(e,t){let n=E.createHash(`sha256`).update(t).digest(`hex`).slice(0,16),r=t.replaceAll(`&`,`&amp;`).replaceAll(`<`,`&lt;`).replaceAll(`>`,`&gt;`);return`<FILE path="${e}" sha256="${n}">\n${r}\n</FILE>`}static scrubSecrets(e){return A(e)}};const ne=[`astro.config.ts`,`astro.config.mjs`,`astro.config.js`];async function re(e){for(let t of ne)if(await e.exists(t))return{matched:!0,confidence:.95,reason:`Detected Astro via \`${t}\`.`};let t=await e.readFile(`package.json`);if(t)try{let e=JSON.parse(t);if(e.dependencies?.astro??e.devDependencies?.astro)return{matched:!0,confidence:.8,reason:"Detected Astro via `astro` dependency."}}catch{}return{matched:!1,confidence:0,reason:"No astro.config.* or `astro` dependency found."}}function ie(e){let t=e.trackingCode??e.siteId??``,n=`<script defer data-id="${t}" data-allow-localhost="true" src="https://api.zenovay.com/z.js" is:inline></script>`;return[{targetPath:`src/layouts/Layout.astro`,anchorKind:`head-tag`,code:n,description:`Inject the Zenovay tracker inside <head> of the primary layout.`},{targetPath:`src/layouts/BaseHead.astro`,anchorKind:`head-tag`,code:n,description:"Fallback target when the project uses a dedicated `BaseHead.astro`."}]}const ae={id:`astro`,displayName:`Astro`,detect:re,files:[{path:`src/layouts/Layout.astro`,kind:`mutate`,required:!1},{path:`src/layouts/BaseHead.astro`,kind:`mutate`,required:!1},{path:`.env`,kind:`create`,required:!0}],envVarName:`PUBLIC_ZENOVAY_SITE`,buildSnippets:ie},oe=[`app/layout.tsx`,`app/layout.ts`,`app/layout.jsx`,`app/layout.js`];async function se(e){for(let t of oe)if(await e.exists(t))return t;return null}async function ce(e){let t=await e.readFile(`package.json`);if(!t)return!1;try{let e=JSON.parse(t);return!!(e.dependencies?.next??e.devDependencies?.next)}catch{return!1}}async function le(e){let t=await ce(e),n=await e.exists(`app`),r=await se(e);return t?n?r?{matched:!0,confidence:.95,reason:`Detected Next.js App Router via \`next\` dep + \`${r}\`.`}:{matched:!1,confidence:.4,reason:"Found `app/` but no root layout file (layout.tsx/ts/jsx/js)."}:{matched:!1,confidence:0,reason:"No `app/` directory found — not an App Router project."}:{matched:!1,confidence:0,reason:"package.json does not list `next` as a dependency."}}function ue(e){let t=`app/layout.tsx`,n=e.trackingCode??e.siteId??``;return[{targetPath:t,anchorKind:`after-imports`,code:`import Script from 'next/script';`,description:`Import next/script to inject the Zenovay tracker.`},{targetPath:t,anchorKind:`wrap-children`,code:`<Script
3
- defer
4
- data-id="${n}"
5
- data-allow-localhost="true"
6
- src="https://api.zenovay.com/z.js"
7
- strategy="afterInteractive"
8
- />
9
- {children}`,description:`Add the Zenovay tracker <Script> next to children in the root layout.`}]}const de={id:`next-app-router`,displayName:`Next.js (App Router)`,detect:le,files:[{path:`app/layout.tsx`,kind:`mutate`,required:!0}],envVarName:`NEXT_PUBLIC_ZENOVAY_SITE`,buildSnippets:ue},z=[`pages/_app.tsx`,`pages/_app.ts`,`pages/_app.jsx`,`pages/_app.js`,`src/pages/_app.tsx`,`src/pages/_app.ts`,`src/pages/_app.jsx`,`src/pages/_app.js`];async function B(e){for(let t of z)if(await e.exists(t))return t;return null}async function V(e){let t=await e.readFile(`package.json`);if(!t)return!1;try{let e=JSON.parse(t);return!!(e.dependencies?.next??e.devDependencies?.next)}catch{return!1}}async function H(e){let t=await V(e);if(!t)return{matched:!1,confidence:0,reason:"package.json does not list `next` as a dependency."};let n=await B(e);if(n)return{matched:!0,confidence:.9,reason:`Detected Next.js Pages Router via \`${n}\`.`};let r=await e.exists(`app`),i=await e.glob(`pages/**/*.{tsx,ts,jsx,js}`);return i.length>0&&!r?{matched:!0,confidence:.7,reason:"Found `pages/` directory with route files but no `_app` — will create one."}:{matched:!1,confidence:.2,reason:`Next.js detected, but no pages-router entry point found.`}}function fe(e){let t=`pages/_app.tsx`,n=e.trackingCode??e.siteId??``,r=`import type { AppProps } from 'next/app';
10
- import Script from 'next/script';
11
-
12
- export default function App({ Component, pageProps }: AppProps) {
13
- return (
14
- <>
15
- <Script
16
- defer
17
- data-id="${n}"
18
- data-allow-localhost="true"
19
- src="https://api.zenovay.com/z.js"
20
- strategy="afterInteractive"
21
- />
22
- <Component {...pageProps} />
23
- </>
24
- );
25
- }
26
- `;return[{targetPath:t,anchorKind:`after-imports`,code:`import Script from 'next/script';`,description:"Import next/script in `_app`."},{targetPath:t,anchorKind:`wrap-children`,code:`<><Script defer data-id="${n}" data-allow-localhost="true" src="https://api.zenovay.com/z.js" strategy="afterInteractive" /><Component {...pageProps} /></>`,description:`Render the Zenovay tracker alongside the page component.`},{targetPath:t,anchorKind:`replace-file`,code:r,description:"Full replacement when `_app` does not exist yet."}]}const pe={id:`next-pages-router`,displayName:`Next.js (Pages Router)`,detect:H,files:[{path:`pages/_app.tsx`,kind:`mutate`,required:!0}],envVarName:`NEXT_PUBLIC_ZENOVAY_SITE`,buildSnippets:fe},me=C.object({modules:C.array(C.string()).optional(),runtimeConfig:C.object({public:C.record(C.string(),C.unknown()).optional()}).optional()}).passthrough();async function he(e){let t=await e.readFile(`package.json`);if(!t)return{matched:!1,confidence:0,reason:`No package.json found.`};try{let e=JSON.parse(t),n=!!(e.dependencies?.nuxt??e.devDependencies?.nuxt??e.dependencies?.nuxt3??e.devDependencies?.nuxt3);if(n)return{matched:!0,confidence:.95,reason:"Detected Nuxt via `nuxt` / `nuxt3` dependency."}}catch{}let n=await e.exists(`nuxt.config.ts`)||await e.exists(`nuxt.config.js`)||await e.exists(`nuxt.config.mjs`);return n?{matched:!0,confidence:.6,reason:"Found `nuxt.config.*` but no explicit dependency listing."}:{matched:!1,confidence:0,reason:`No Nuxt dependency or config detected.`}}function ge(e){let t=e.trackingCode??e.siteId??``,n=` app: {
27
- head: {
28
- script: [
29
- {
30
- defer: true,
31
- src: 'https://api.zenovay.com/z.js',
32
- 'data-id': '${t}',
33
- 'data-allow-localhost': 'true',
34
- },
35
- ],
36
- },
37
- },`;return[{targetPath:`nuxt.config.ts`,anchorKind:`head-tag`,code:n,description:"Add the Zenovay tracker to Nuxt's `app.head.script` so every page loads it."}]}const _e={id:`nuxt`,displayName:`Nuxt`,detect:he,files:[{path:`nuxt.config.ts`,kind:`mutate`,required:!0}],envVarName:`NUXT_PUBLIC_ZENOVAY_SITE`,buildSnippets:ge},ve=[`index.html`,`public/index.html`,`dist/index.html`];async function ye(e){for(let t of ve)if(await e.exists(t))return{matched:!0,confidence:.5,reason:`Detected plain HTML project via \`${t}\`.`};let t=await e.glob(`**/*.html`);return t.length>0?{matched:!0,confidence:.3,reason:`Found ${t.length} HTML file(s); plain-HTML adapter is usable as fallback.`}:{matched:!1,confidence:0,reason:`No HTML files found in the project.`}}function be(e){let t=e.siteId??``,n=`<script defer\n data-id="${t}"\n data-allow-localhost="true"\n src="https://api.zenovay.com/z.js">\n</script>`;return[{targetPath:`index.html`,anchorKind:`head-tag`,code:n,description:`Inject the Zenovay tracker inside <head>. Repeat for every HTML file that contains a <head>.`}]}const xe={id:`plain-html`,displayName:`Plain HTML`,detect:ye,files:[{path:`index.html`,kind:`mutate`,required:!0}],envVarName:`PUBLIC_ZENOVAY_SITE`,buildSnippets:be};async function Se(e){let t=await e.readFile(`package.json`);if(t)try{let e=JSON.parse(t),n={...e.dependencies??{},...e.devDependencies??{}},r=Object.keys(n).some(e=>e.startsWith(`@remix-run/`));if(r)return{matched:!0,confidence:.95,reason:"Detected Remix via `@remix-run/*` dependencies."}}catch{}return await e.exists(`remix.config.js`)||await e.exists(`remix.config.ts`)?{matched:!0,confidence:.8,reason:"Detected Remix via `remix.config.*`."}:{matched:!1,confidence:0,reason:`No Remix dependency or config detected.`}}function Ce(e){let t=e.trackingCode??e.siteId??``;return[{targetPath:`app/root.tsx`,anchorKind:`head-tag`,code:`<script defer data-id="${t}" data-allow-localhost="true" src="https://api.zenovay.com/z.js"></script>`,description:`Inline the Zenovay tracker <script> inside the document <head>.`}]}const we={id:`remix`,displayName:`Remix`,detect:Se,files:[{path:`app/root.tsx`,kind:`mutate`,required:!0}],envVarName:`PUBLIC_ZENOVAY_SITE`,buildSnippets:Ce};async function Te(e){let t=await e.readFile(`package.json`);if(!t)return{matched:!1,confidence:0,reason:`No package.json found.`};try{let e=JSON.parse(t),n=!!(e.dependencies?.[`@sveltejs/kit`]??e.devDependencies?.[`@sveltejs/kit`]);return n?{matched:!0,confidence:.95,reason:"Detected SvelteKit via `@sveltejs/kit` dependency."}:{matched:!1,confidence:0,reason:"`@sveltejs/kit` not in dependencies."}}catch{return{matched:!1,confidence:0,reason:`package.json is not valid JSON.`}}}function Ee(e){let t=e.trackingCode??e.siteId??``,n=`<svelte:head>
38
- <script defer data-id="${t}" data-allow-localhost="true" src="https://api.zenovay.com/z.js"></script>
39
- </svelte:head>
40
-
41
- <slot />
42
- `;return[{targetPath:`src/routes/+layout.svelte`,anchorKind:`replace-file`,code:n,description:`Root layout that loads the Zenovay tracker in every route via <svelte:head>.`}]}const De={id:`sveltekit`,displayName:`SvelteKit`,detect:Te,files:[{path:`src/routes/+layout.svelte`,kind:`mutate`,required:!0}],envVarName:`PUBLIC_ZENOVAY_SITE`,buildSnippets:Ee},Oe=[de,pe,_e,De,ae,we,xe];async function U(e){let t=[];for(let n of Oe){let r=await n.detect(e);t.push({adapter:n,result:r})}let n=[...t].sort((e,t)=>t.result.confidence-e.result.confidence),r=n[0],i=r&&r.result.matched?r.adapter:null;return{adapter:i,ranked:n}}function W(e){let t=t=>p.resolve(e,t);return{cwd:e,async readFile(e){try{return await m.readFile(t(e),`utf8`)}catch(e){let t=e.code;if(t===`ENOENT`||t===`EISDIR`)return null;throw e}},async exists(e){try{return await m.access(t(e)),!0}catch{return!1}},async glob(t){return w(t,{cwd:e,dot:!1,gitignore:!0,onlyFiles:!0,followSymbolicLinks:!1})}}}async function G(e,t){let n=W(e),{adapter:r,ranked:i}=await U(n),a=i[0];return r&&a&&a.result.confidence>=.7?r:t?t.pickInteractively(i):r}function ke(e,t){let n=/[\s"'#=]/.test(t)||t===``,r=n?`"${t.replace(/\\/g,`\\\\`).replace(/"/g,`\\"`)}"`:t;return`${e}=${r}`}function Ae(e){let t=new Set;for(let n of e.split(/\r?\n/)){let e=n.trim();if(!e||e.startsWith(`#`))continue;let r=e.indexOf(`=`);if(r<=0)continue;let i=e.slice(0,r).trim();/^[A-Za-z_][A-Za-z0-9_]*$/.test(i)&&t.add(i)}return t}async function K(e,t,n={}){let r=n.filename??`.env.local`,i=p.resolve(e,r),a=``,o=!0;try{a=await m.readFile(i,`utf8`)}catch(e){if(e.code===`ENOENT`)o=!1;else throw e}let s=o?Ae(a):new Set,c=[],l=[],u=[];for(let[e,n]of Object.entries(t)){if(s.has(e)){l.push(e);continue}u.push(ke(e,n)),c.push(e)}if(c.length===0)return{created:!1,existing:o,addedKeys:c,skippedKeys:l};let d=`# Added by Zenovay CLI`,f;if(o){let e=a.length>0&&!a.endsWith(`
43
- `);f=a+(e?`
44
- `:``)+`
45
- `+d+`
46
- `+u.join(`
47
- `)+`
48
- `}else f=d+`
49
- `+u.join(`
50
- `)+`
51
- `;if(o)await m.writeFile(i,f,`utf8`);else{let e=await m.open(i,`w`,384);try{await e.writeFile(f,`utf8`)}finally{await e.close()}}return{created:!o,existing:o,addedKeys:c,skippedKeys:l}}const je=`https://api.zenovay.com/mcp`,Me=C.object({url:C.string().url(),headers:C.record(C.string(),C.string()).optional()}),Ne=C.object({mcpServers:C.record(C.string(),Me).optional()}).passthrough();function Pe(e){return e.HOME??e.USERPROFILE??S.homedir()}function Fe(e){return e.APPDATA??null}function Ie(e,t){let n=Pe(t),r=Fe(t),i=[];return i.push({id:`cursor`,displayName:`Cursor`,configPath:p.join(n,`.cursor`,`mcp.json`)}),e===`win32`&&r&&i.push({id:`cursor`,displayName:`Cursor (AppData)`,configPath:p.join(r,`Cursor`,`User`,`globalStorage`,`cursor.mcp`,`mcp.json`)}),e===`darwin`?i.push({id:`claude-desktop`,displayName:`Claude Desktop`,configPath:p.join(n,`Library`,`Application Support`,`Claude`,`claude_desktop_config.json`)}):e===`win32`&&r?i.push({id:`claude-desktop`,displayName:`Claude Desktop`,configPath:p.join(r,`Claude`,`claude_desktop_config.json`)}):i.push({id:`claude-desktop`,displayName:`Claude Desktop`,configPath:p.join(n,`.config`,`Claude`,`claude_desktop_config.json`)}),i.push({id:`vscode`,displayName:`VS Code`,configPath:p.join(n,`.vscode`,`mcp.json`)}),i}async function Le(e){try{return await m.access(e),!0}catch{return!1}}async function Re(e){try{let t=await m.readFile(e,`utf8`);if(t.trim().length===0)return{};let n=JSON.parse(t),r=Ne.safeParse(n);return r.success?r.data:n&&typeof n==`object`?n:{}}catch{return{}}}function ze(e){return{url:je,headers:{Authorization:`Bearer ${e}`}}}async function Be(e){let t=e.env??process.env,n=e.platform??process.platform,r=new Set(e.skip??[]),i=[],a=[],o=[],s=new Set,c=ze(e.accessToken);for(let e of Ie(n,t)){if(r.has(e.id)){a.push(e.displayName);continue}if(s.has(e.configPath))continue;s.add(e.configPath);try{let t=await Le(e.configPath);if(!t){a.push(e.displayName);continue}let n=await Re(e.configPath),r=`${e.configPath}.bak`;await m.copyFile(e.configPath,r);let o={...n,mcpServers:{...n.mcpServers??{},zenovay:c}};await m.mkdir(p.dirname(e.configPath),{recursive:!0}),await m.writeFile(e.configPath,JSON.stringify(o,null,2)+`
52
- `,`utf8`),i.push(e.displayName)}catch(t){o.push({client:e.displayName,message:t instanceof Error?t.message:String(t)})}}return{installed:i,skipped:a,errors:o}}async function Ve(e,t,n){let r=n.timeoutMs??18e4,i=n.pollIntervalMs??2e3,a=n.now??(()=>Date.now()),o=n.sleep??(e=>new Promise(t=>setTimeout(t,e))),s=a(),c=s+r;for(n.onTick?.(0);;){let l=await n.api.getFirstEvent({siteId:e,since:t});if(l.received)return{received:!0,event:l.event};let u=a()-s;if(u>=r)return{received:!1};let d=c-a(),f=Math.min(i,Math.max(0,d));if(f<=0)return{received:!1};await o(f),n.onTick?.(a()-s)}}const He=C.object({path:C.string().min(1)}),Ue=C.object({path:C.string().min(1),content:C.string(),reason:C.string().min(1)}),We=C.object({path:C.string().min(1),patch:C.string().min(1),reason:C.string().min(1)}),Ge=C.object({}),Ke=C.object({question:C.string().min(1),choices:C.array(C.string()).optional()});async function qe(e,t){let n=He.safeParse(t);if(!n.success)return{ok:!1,content:null,error:`invalid_args`};try{let t=await e.safeRead(n.data.path),r=R.scrubSecrets(t);return{ok:!0,content:R.wrapForModel(n.data.path,r)}}catch(e){return{ok:!1,content:null,error:e.message}}}async function q(e,t,n){let r=Ue.safeParse(t);if(!r.success)return{ok:!1,content:null,error:`invalid_args`};let{path:i,content:a,reason:o}=r.data,s=``;try{s=await e.safeRead(i)}catch{s=``}let c=await n.approve({path:i,oldContent:s,newContent:a,reason:o});if(c===`n`)return{ok:!1,content:null,error:`skipped_by_user`};if(c===`e`)return{ok:!1,content:null,error:`deferred_to_user_edit`};try{let{backupPath:t}=await e.safeWrite(i,a);return{ok:!0,content:{path:i,backupPath:t}}}catch(e){return{ok:!1,content:null,error:e.message}}}async function Je(e,t,n){let r=We.safeParse(t);if(!r.success)return{ok:!1,content:null,error:`invalid_args`};let{path:i,patch:a,reason:o}=r.data,s;try{s=await e.safeRead(i)}catch(e){return{ok:!1,content:null,error:e.message}}let c=O(s,a);return c===!1||typeof c!=`string`?{ok:!1,content:null,error:`patch_did_not_apply_cleanly`}:q(e,{path:i,content:c,reason:o},n)}async function Ye(e){try{let t=W(e),{adapter:n,ranked:r}=await U(t);return{ok:!0,content:{matched:n!==null,adapter:n?.id,displayName:n?.displayName,ranked:r.map(e=>({id:e.adapter.id,confidence:e.result.confidence,reason:e.result.reason}))}}}catch(e){return{ok:!1,content:null,error:e.message}}}async function Xe(e,t){let n=Ke.safeParse(t);if(!n.success)return{ok:!1,content:null,error:`invalid_args`};try{let t=await e.ask(n.data);return{ok:!0,content:{answer:t}}}catch(e){return{ok:!1,content:null,error:e.message}}}async function Ze(e){let{api:t,sandbox:n,approval:i,prompter:a,handlers:o}=e,s=[...e.initialMessages],c=``,l=0;for(;l<I;){n.incrementRound(),l++;let e=await t.openAiStream(`install`,{messages:s,cwd_fingerprint:n.sessionId}),u=[],d=``;for await(let t of r(e))switch(t.type){case`delta`:d+=t.content,o?.onDelta?.(t.content);break;case`tool_start`:o?.onToolStart?.({id:t.id,name:t.name});break;case`tool_call`:{let e=await Qe(t.name,t.arguments,{sandbox:n,cwd:n.cwd,approval:i,prompter:a});u.push({id:t.id,name:t.name,arguments:t.arguments,result:e}),o?.onToolResult?.({id:t.id,name:t.name,result:e});break}case`usage`:o?.onUsage?.(t);break;case`error`:throw o?.onError?.(t),Error(`[${t.code}] ${t.message}`);case`done`:break}if(d&&(c+=d),u.length===0){d&&s.push({role:`assistant`,content:d});break}s.push({role:`assistant`,content:d,toolCalls:u.map(e=>({id:e.id,type:`function`,function:{name:e.name,arguments:JSON.stringify(e.arguments)}}))});for(let e of u)s.push({role:`tool`,toolCallId:e.id,toolName:e.name,content:JSON.stringify(e.result)})}return{finalText:c,rounds:l}}async function Qe(e,t,n){switch(e){case`read_file`:return qe(n.sandbox,t);case`write_file`:return q(n.sandbox,t,n.approval);case`patch_file`:return Je(n.sandbox,t,n.approval);case`detect_framework`:return Ye(n.cwd);case`ask_user`:return Xe(n.prompter,t);default:return{ok:!1,content:null,error:`unknown_tool:${e}`}}}function $e(){let e=[12,15,18,22,28,35,41,50,58,64,72,78],t=f(e,24);return[` ↑`,` ${t}`,` └────────────────────────`,` May Jun Jul Aug Sep`]}function et(){return[` Landing page ████████████████████ 100%`,` ↓ -28%`,` Pricing ██████████████░░░░░░ 72%`,` ↓ -50%`,` Checkout ███████░░░░░░░░░░░░░ 36%`,` ↓ -64%`,` Purchased ███░░░░░░░░░░░░░░░░░ 13%`]}function tt(){return[` ▇▇▇▇▇▇▇▇▇▎ 89 Sarah K. /pricing 🇺🇸`,` ▇▇▇▇▇▇░░░░ 61 anon /docs 🇩🇪`,` ▇▇▇░░░░░░░ 34 anon /changelog 🇯🇵`]}function nt(){return[` LCP ● 2.1s good ████████████░░░░░░`,` INP ● 89ms good ██████████████████`,` CLS ⚠ 0.14 needs ████████████░░░░░░`,` TTFB ● 380ms good ███████████████░░░`]}const J=[{title:`Welcome`,body:[`The wizard is an agent — it handles the entire`,`Zenovay setup process on your behalf.`,``,`Reading your project, deciding where the tracker`,`belongs, and writing the snippet for you.`]},{title:`Events`,body:[`Events are the foundation of Zenovay analytics.`,``,`Every pageview, click, and custom action is an`,`event. Group them into Goals to track conversions.`]},{title:`Trends`,body:[`Use trends to measure growth.`,``,`See how visitors, signups, and revenue have`,`changed over the last week, month, or quarter.`],visual:$e},{title:`Funnels`,body:[`Funnels reveal where users drop off.`,``,`Define the steps you care about — landing,`,`pricing, checkout, purchase — and Zenovay shows`,`the per-step conversion rate.`],visual:et},{title:`Live visitors`,body:[`Watch every visitor in real time, ranked by an`,`AI score that highlights high-intent traffic.`,``,"Use `zenovay visitors --live` after install."],visual:tt},{title:`Core Web Vitals`,body:[`LCP, INP, CLS — Google's page-experience metrics,`,`collected automatically once the tracker is in.`,``,"Use `zenovay vitals` to see them per page + device."],visual:nt},{title:`MCP integration`,body:[`Your CLI session can install Zenovay's MCP server`,`into Cursor / Claude Desktop / VS Code.`,``,`Then ask your AI: "what were my top pages today?"`,`and it queries Zenovay directly.`]},{title:`AI insights`,body:[`Zenovay watches your data and surfaces anomalies`,`automatically — traffic spikes, error bursts,`,`revenue drops — without you needing to ask.`,``,"Run `zenovay ai` after install to chat with them."]},{title:`Privacy-first`,body:[`No cookies required. No third-party trackers.`,`Cookieless mode is one toggle in your dashboard.`,``,`GDPR, CCPA, and PECR-compliant out of the box.`]}],rt=8e3,it=({width:e,height:t})=>{let[n,r]=x(0);b(()=>{let e=setInterval(()=>{r(e=>(e+1)%J.length)},rt);return()=>clearInterval(e)},[]);let i=J[n],a=i.visual?i.visual():[],o=J.map((e,t)=>t===n?`●`:`·`).join(` `);return y.createElement(h,{flexDirection:`column`,width:e,height:t,paddingX:2,paddingY:1},y.createElement(h,{marginBottom:1},y.createElement(g,{color:`magentaBright`,bold:!0},`Learn`)),y.createElement(h,{marginBottom:1},y.createElement(g,{bold:!0,color:`white`},i.title)),i.body.map((e,t)=>y.createElement(g,{key:t,color:`gray`},e||` `)),a.length>0&&y.createElement(h,{flexDirection:`column`,marginTop:1},a.map((e,t)=>y.createElement(g,{key:t,color:`cyan`},e))),y.createElement(h,{flexGrow:1}),y.createElement(h,{marginTop:1},y.createElement(g,{color:`gray`,dimColor:!0},o,` · `,n+1,` / `,J.length)))},at={pending:`·`,active:`⠋`,done:`✓`,error:`✗`},ot={pending:`gray`,active:`magenta`,done:`green`,error:`red`},st=({tasks:e,width:t,height:n,liveLine:r})=>{let i=e.filter(e=>e.status===`done`).length;return y.createElement(h,{flexDirection:`column`,width:t,height:n,paddingX:2,paddingY:1},y.createElement(h,{marginBottom:1},y.createElement(g,{color:`magentaBright`,bold:!0},`Tasks`)),e.map(e=>y.createElement(h,{key:e.id,flexDirection:`column`},y.createElement(h,null,e.status===`active`?y.createElement(g,{color:`magenta`},y.createElement(T,{type:`dots`})):y.createElement(g,{color:ot[e.status]},at[e.status]),y.createElement(g,null,` `),y.createElement(g,{color:e.status===`pending`?`gray`:`white`},e.label)),e.detail&&y.createElement(h,{paddingLeft:2},y.createElement(g,{color:`gray`,dimColor:!0},e.detail)))),y.createElement(h,{flexGrow:1}),r&&y.createElement(h,{marginTop:1},y.createElement(g,{color:`cyan`},`◆ `),y.createElement(g,{color:`white`},r)),y.createElement(h,{marginTop:1},y.createElement(g,{color:`gray`,dimColor:!0},i,` / `,e.length)))};async function ct(e){return a(e)?lt(e):new Promise(t=>{let{unmount:n,waitUntilExit:r}=_(y.createElement(ut,{opts:e,onExit:e=>{n(),t(e)}}));r().catch(()=>t(1))})}async function lt(r){try{let a=await e(),o=await G(r.cwd);if(!o)return i({type:`error`,code:`no_framework`,message:`Could not detect framework (headless mode has no picker).`}),2;i({type:`framework.detected`,framework:o.id,confidence:1});let s=await n({strict:!1});if(!s&&!process.env.ZENOVAY_API_TOKEN)return i({type:`error`,code:`not_logged_in`,message:"Run `zenovay login` first (or set ZENOVAY_API_TOKEN)."}),2;let c=new t({config:a,cliVersion:r.cliVersion,token:s}),l=await c.getSites(),u=r.siteId?l.find(e=>e.id===r.siteId):l[0];if(!u&&r.siteId)return i({type:`error`,code:`site_not_found`,message:`Site ${r.siteId} not found.`}),2;if(!u)return i({type:`error`,code:`no_site`,message:`No sites exist; create one at app.zenovay.com or re-run interactively.`}),2;i({type:`info`,message:`Using site ${u.id} (${u.name}) trackingCode=${u.trackingCode??u.id}`});let d=await K(r.cwd,{[o.envVarName]:u.trackingCode??u.id});return i({type:`info`,message:`env vars added: ${d.addedKeys.join(`,`)}`}),i({type:`done`,command:`init`,exitCode:0}),0}catch(e){return i({type:`error`,code:`init_failed`,message:e.message}),1}}const ut=({opts:r,onExit:i})=>{let{exit:a}=ee(),[l,d]=x(`intro`),[f,p]=x(null),[m,_]=x([]),[v,S]=x(null),[C,w]=x(null),[E,D]=x(null),[O,k]=x([]),[A,j]=x(void 0),[M,N]=x(null),[P,F]=x(0),I=te(!1);return b(()=>(process.stdout.isTTY&&process.stdout.write(`\x1B[?1049h\x1B[H`),()=>{process.stdout.isTTY&&process.stdout.write(`\x1B[?1049l`)}),[]),b(()=>{I.current||(I.current=!0,(async()=>{try{d(`detecting`);let i=await G(r.cwd);if(!i){D(`Could not detect your framework. Supported: Next.js, Nuxt, SvelteKit, Astro, Remix, plain HTML.`),d(`error`);return}p(i);let a=await n({strict:!1});!process.env.ZENOVAY_API_TOKEN&&!a&&(d(`login`),await o({cliVersion:r.cliVersion})),d(`loading-sites`);let s=await e(),c=await n({strict:!1}),l=new t({config:s,cliVersion:r.cliVersion,token:c}),u=await l.getSites(),f=await xt(r.cwd),m=Q(u,f);if(_(u),S(f),u.length===0){d(`create-site`);return}if(r.siteId){let e=u.find(e=>e.id===r.siteId);if(!e){D(`Site ${r.siteId} not found in your account.`),d(`error`);return}w(e),Y(e,i,r,{setPhase:d,setErrorMsg:D,setTasks:k,setLiveLine:j,setSandboxStats:N});return}if(r.yes&&m){w(m),Y(m,i,r,{setPhase:d,setErrorMsg:D,setTasks:k,setLiveLine:j,setSandboxStats:N});return}d(`site-picker`)}catch(e){D(e.message),d(`error`)}})())},[]),b(()=>{l===`success`&&setTimeout(()=>{a(),i(0)},1500),l===`error`&&setTimeout(()=>{a(),i(1)},8e3)},[l]),y.createElement(h,{flexDirection:`column`},y.createElement(c,{version:r.cliVersion,subtitle:`AI install wizard`}),l===`intro`&&y.createElement(dt,null),l===`detecting`&&y.createElement(s,{title:`Scanning`,state:`busy`},y.createElement(h,null,y.createElement(g,{color:`magenta`},y.createElement(T,{type:`dots`})),y.createElement(g,null,` Detecting framework…`))),l===`login`&&y.createElement(s,{title:`Authenticating`,state:`busy`},y.createElement(g,null,`Opening browser for login… (paste ZENOVAY_API_TOKEN env var to skip)`)),l===`loading-sites`&&y.createElement(s,{title:`Loading your sites`,state:`busy`},y.createElement(h,null,y.createElement(g,{color:`magenta`},y.createElement(T,{type:`dots`})),y.createElement(g,null,` Fetching your Zenovay sites…`))),l===`site-picker`&&f&&y.createElement(pt,{sites:m,preselectHint:v,onPick:e=>{if(e===`create-new`){d(`create-site`);return}w(e),Y(e,f,r,{setPhase:d,setErrorMsg:D,setTasks:k,setLiveLine:j,setSandboxStats:N})}}),l===`create-site`&&y.createElement(s,{title:`Create a new site`,state:`warn`},y.createElement(g,{color:`yellow`},"No site picked (or none exist yet). Visit https://app.zenovay.com/websites to create one, then re-run `zenovay init`."),y.createElement(g,{color:`gray`},`(Inline site creation from the CLI is scheduled for V1.1 — it requires a plan-limit check.)`)),l===`agent`&&f&&C&&y.createElement(ft,{adapter:f,site:C,tasks:O,liveLine:A}),l===`install-complete`&&f&&C&&y.createElement(ht,{adapter:f,site:C,stats:M,onCommit:()=>d(`commit-prompt`),onSkipCommit:()=>d(`deploy-prompt`)}),l===`commit-prompt`&&C&&y.createElement(X,{cwd:r.cwd,onDone:e=>{e.committed&&j(`Pushed ${e.shortSha} to ${e.branch}`),d(`deploy-prompt`)},onError:e=>{D(e),d(`error`)}}),l===`deploy-prompt`&&C&&y.createElement(gt,{site:C,onDeployed:()=>d(`visit-prompt`),onSkip:()=>d(`verify`)}),l===`visit-prompt`&&C&&y.createElement(_t,{site:C,onContinue:()=>d(`verify`)}),l===`verify`&&C&&y.createElement(vt,{site:C,elapsed:P,onTick:e=>F(e),onArrived:()=>d(`success`),onTimeout:()=>d(`success`)}),l===`success`&&f&&C&&y.createElement(mt,{adapter:f,site:C,stats:M}),l===`error`&&y.createElement(s,{title:`Install failed`,state:`err`},y.createElement(g,{color:`red`},E??`Unknown error`)),y.createElement(u,{items:[{key:`q`,label:`quit`},{key:`ctrl-c`,label:`abort`}]}))};async function Y(r,i,a,o){try{o.setPhase(`agent`);let s=await e(),c=await n({strict:!1}),l=new t({config:s,cliVersion:a.cliVersion,token:c}),u=new R({cwd:a.cwd}),d=r.trackingCode??r.id,f=i.buildSnippets({trackingCode:d,siteId:r.id}),p=`Install Zenovay tracking into this ${i.displayName} project.\nSite: ${r.name} (trackingCode: ${d}).\n1. Call detect_framework to confirm the framework.\n2. Read the entry file(s) for this framework:\n`+i.files.map(e=>` - ${e.path}`).join(`
53
- `)+`
54
- 3. Insert the tracker using the snippet below.
55
- 4. Confirm the change with a diff before writing.
56
-
57
- Snippet reference (anchored by anchorKind — adapt to the actual file):
58
- `+f.map(e=>` ${e.anchorKind} @ ${e.targetPath}:\n ${e.code.replace(/\n/g,`
59
- `)}`).join(`
60
-
61
- `);o.setTasks([{id:`detect`,label:`Detect framework`,status:`active`},{id:`read`,label:`Read project entry files`,status:`pending`},{id:`write`,label:`Insert tracker snippet`,status:`pending`},{id:`env`,label:`Write env vars (.env.local)`,status:`pending`},{id:`mcp`,label:`Install MCP clients (Cursor/Claude/VS Code)`,status:`pending`},{id:`verify`,label:`Wait for first event`,status:`pending`}]);let m=(e,t,n)=>{o.setTasks(r=>r.map(r=>r.id===e?{...r,status:t,detail:n??r.detail}:r))},h=null;try{await Ze({api:l,sandbox:u,approval:{async approve(){return`y`}},prompter:{async ask({question:e}){return e}},handlers:{onToolStart:({name:e})=>{e===`detect_framework`?(m(`detect`,`active`),o.setLiveLine(`Inspecting package.json + config files…`)):e===`read_file`?(m(`detect`,`done`),m(`read`,`active`)):(e===`write_file`||e===`patch_file`)&&(m(`read`,`done`),m(`write`,`active`))},onToolResult:({name:e,result:t})=>{let n=t?.ok!==!1,r=t?.content??{};e===`detect_framework`&&n&&(m(`detect`,`done`,i.displayName),o.setLiveLine(`Detected ${i.displayName}`)),e===`read_file`&&n&&r.path&&o.setLiveLine(`Read ${r.path}`),(e===`write_file`||e===`patch_file`)&&n&&r.path&&o.setLiveLine(`Wrote ${r.path}`)},onDelta:e=>{let t=e.replace(/\s+/g,` `).trim();t.length>4&&o.setLiveLine(t.slice(0,80))}},initialMessages:[{role:`user`,content:p}]})}catch(e){h=e}let g=u.stats();if(g.writes===0){let e=h?`Agent error: ${h.message}`:`Agent returned without writing any files (${g.reads} reads, ${g.rounds} rounds). The model may have refused or the AI Gateway may be misconfigured. Check api.zenovay.com logs.`;throw Error(e)}m(`write`,`done`),m(`env`,`active`),o.setLiveLine(`Adding env var to .env.local`);let _=await K(a.cwd,{[i.envVarName]:d});if(m(`env`,`done`,`${_.addedKeys.length} key(s) added`),!a.skipMcp&&c){m(`mcp`,`active`),o.setLiveLine(`Detecting Cursor / Claude Desktop / VS Code…`);let e=await Be({accessToken:c.accessToken}).catch(()=>null);e&&e.installed.length>0?m(`mcp`,`done`,e.installed.join(`, `)):m(`mcp`,`done`,`none detected`)}else m(`mcp`,`done`,`skipped`);o.setTasks(e=>e.map(e=>e.id===`detect`||e.id===`read`||e.id===`write`?{...e,status:e.status===`pending`?`done`:e.status}:e)),o.setLiveLine(void 0),o.setSandboxStats?.(g),o.setPhase(`install-complete`)}catch(e){o.setErrorMsg(e.message),o.setPhase(`error`)}}const dt=()=>y.createElement(s,{title:`Zenovay wants to set up your project`,state:`idle`},y.createElement(g,null,`We'll use AI to analyze your codebase and add the Zenovay tracker.`),y.createElement(g,{color:`gray`},`.env* contents stay on your machine. Only framework metadata reaches api.zenovay.com.`)),ft=({adapter:e,site:t,tasks:n,liveLine:r})=>{let i=process.stdout.columns??100,a=(process.stdout.rows??30)-6,o=Math.floor(i/2)-1,s=Math.max(14,a);return y.createElement(h,{flexDirection:`column`},y.createElement(h,{flexDirection:`row`,height:s,borderStyle:`round`,borderColor:`gray`},y.createElement(h,{width:o,flexDirection:`column`},y.createElement(it,{width:o,height:s})),y.createElement(h,{width:1,flexDirection:`column`,height:s},y.createElement(g,{color:`gray`},`│`)),y.createElement(h,{width:o,flexDirection:`column`},y.createElement(st,{tasks:n,liveLine:r,width:o,height:s}))),y.createElement(h,{marginTop:1},y.createElement(g,{color:`gray`},`Site: `,t.name,` · code: `,t.trackingCode??t.id,` · Framework: `,e.displayName)))},pt=({sites:e,preselectHint:t,onPick:n})=>{let r=Q(e,t),i=e.filter(e=>e.id!==r?.id),a=r?[r,...i]:i,o=[...a.map(e=>({label:bt(e,e.id===r?.id),value:e,description:e.trackingCode?`trackingCode: ${e.trackingCode}`:void 0})),{label:`+ Create new site on app.zenovay.com`,value:`create-new`,description:`Open the dashboard to add a new website`}];return y.createElement(s,{title:t?`Pick a site (best match: ${t})`:`Pick a site`,state:`idle`},y.createElement(d,{items:o,onSelect:n}))},mt=({adapter:e,site:t,stats:n})=>y.createElement(s,{title:`You're live on Zenovay`,state:`ok`},y.createElement(g,null,y.createElement(l,null,`✔ Installed successfully`)),y.createElement(g,null,`Framework: `,e.displayName),y.createElement(g,null,`Site: `,t.name,` (`,t.url,`)`),t.trackingCode?y.createElement(g,{color:`gray`},`Tracker code: `,t.trackingCode):null,n?y.createElement(g,{color:`gray`},n.writes,` file(s) modified across `,n.rounds,` agent round(s)`):null,y.createElement(g,{color:`gray`},`Dashboard: https://app.zenovay.com/sites/`,t.id),y.createElement(g,{color:`gray`},"Next: `zenovay watch` for a live TUI.")),ht=({adapter:e,site:t,stats:n,onCommit:r,onSkipCommit:i})=>(Z(e=>{e===`y`||e===`Y`||e===`\r`?r():(e===`n`||e===`N`||e===`s`||e===`S`)&&i()}),y.createElement(s,{title:`Tracker installed`,state:`ok`},y.createElement(g,null,y.createElement(l,null,`✔ `),`The Zenovay tracker is in your project.`),y.createElement(h,{marginTop:1},y.createElement(g,{color:`gray`},`Framework: `),y.createElement(g,null,e.displayName)),y.createElement(h,null,y.createElement(g,{color:`gray`},`Site: `),y.createElement(g,null,t.name,` (`,t.url,`)`)),n&&y.createElement(h,null,y.createElement(g,{color:`gray`},`Modified: `),y.createElement(g,null,n.writes,` file(s)`)),y.createElement(h,{marginTop:1},y.createElement(g,null,`Commit + push these changes to git? `),y.createElement(g,{color:`cyan`},`[Y/n]`)))),X=({cwd:e,onDone:t,onError:n})=>{let[r,i]=x(`committing`),[a,o]=x(`Staging changes…`);return b(()=>{(async()=>{try{let n=await yt(e,e=>o(e),e=>i(e));n.committed?o(`Pushed ${n.shortSha} to origin/${n.branch}`):o(`No changes to commit (already up-to-date).`),setTimeout(()=>t(n),800)}catch(e){n(e.message)}})()},[]),y.createElement(s,{title:`Committing to git`,state:`busy`},y.createElement(h,null,y.createElement(g,{color:`magenta`},y.createElement(T,{type:`dots`})),y.createElement(g,null,` `,r===`pushing`?`Pushing to origin`:`Committing`,`…`)),y.createElement(h,{marginTop:1},y.createElement(g,{color:`gray`},a)))},gt=({site:e,onDeployed:t,onSkip:n})=>(Z(e=>{e===`y`||e===`Y`||e===`\r`||e===`d`||e===`D`?t():(e===`n`||e===`N`||e===`s`||e===`S`)&&n()}),y.createElement(s,{title:`Ready to deploy?`,state:`idle`},y.createElement(g,null,`The tracker is installed locally. To capture events you need it on the live site:`),y.createElement(g,null,` `),y.createElement(h,null,y.createElement(g,{color:`cyan`},` → `),y.createElement(g,null,e.url)),y.createElement(g,null,` `),y.createElement(g,{color:`gray`},`Push the change through your normal deploy pipeline (Vercel auto-deploy, CI/CD, etc.).`),y.createElement(h,{marginTop:1},y.createElement(g,null,`Once it's deployed, press `),y.createElement(g,{color:`cyan`},`[Y]`),y.createElement(g,null,` to verify the tracker is firing. `),y.createElement(g,{color:`gray`},`[s] skip verification`)))),_t=({site:e,onContinue:t})=>(Z(()=>t()),y.createElement(s,{title:`Visit your site`,state:`idle`},y.createElement(g,null,`To send a test event, open any page on your site:`),y.createElement(g,null,` `),y.createElement(h,null,y.createElement(g,{color:`cyan`},` → `),y.createElement(g,null,e.url)),y.createElement(g,null,` `),y.createElement(g,{color:`gray`},`The tracker fires automatically on page load. We'll verify the next event arrives.`),y.createElement(h,{marginTop:1},y.createElement(g,null,`Press `),y.createElement(g,{color:`cyan`},`[any key]`),y.createElement(g,null,` when you've visited the page.`)))),vt=({site:r,elapsed:i,onTick:a,onArrived:o,onTimeout:c})=>{b(()=>{let i=!1,s=Date.now();return(async()=>{try{let l=await e(),u=await n({strict:!1}),d=new t({config:l,cliVersion:`0`,token:u}),f=await Ve(r.id,s,{api:d,timeoutMs:18e4,pollIntervalMs:2500,onTick:e=>{i||a(e)}});if(i)return;f.received?o():c()}catch{i||c()}})(),()=>{i=!0}},[]);let l=Math.floor(i/1e3);return y.createElement(s,{title:`Waiting for first event`,state:`busy`},y.createElement(h,null,y.createElement(g,{color:`magenta`},y.createElement(T,{type:`dots`})),y.createElement(g,null,` Polling api.zenovay.com for the first hit on `),y.createElement(g,{color:`cyan`},r.url),y.createElement(g,null,` (`,l,`s elapsed)`)),y.createElement(h,{marginTop:1},y.createElement(g,{color:`gray`},`Reload the page if nothing arrives within ~30 seconds.`)))};function Z(e){v((t,n)=>{e(t,{return:n.return,escape:n.escape})},{isActive:!0})}async function yt(e,t,n){let{execFile:r}=await import(`node:child_process`),{promisify:i}=await import(`node:util`),a=i(r),o=async(t,n)=>{let{stdout:r}=await a(t,n,{cwd:e,maxBuffer:4e6});return r.trim()};try{await o(`git`,[`rev-parse`,`--is-inside-work-tree`])}catch{return t(`Not a git repository — skipped.`),{committed:!1}}let s=await o(`git`,[`status`,`--porcelain`]);if(!s)return{committed:!1};t(`Staging tracker changes…`),await o(`git`,[`add`,`-A`]),t(`Creating commit…`),await o(`git`,[`commit`,`-m`,`chore(zenovay): install tracking script via @zenovay/cli`]);let c=await o(`git`,[`rev-parse`,`--short`,`HEAD`]),l=await o(`git`,[`rev-parse`,`--abbrev-ref`,`HEAD`]);n(`pushing`),t(`Pushing to origin/${l}…`);try{await o(`git`,[`push`,`origin`,l])}catch(e){return t(`Commit ${c} created locally; push failed (${e.message.slice(0,80)}). Push manually with: git push origin ${l}`),{committed:!0,shortSha:c,branch:l}}return n(`done`),{committed:!0,shortSha:c,branch:l}}function bt(e,t){let n=`${e.name}`.padEnd(30,` `).slice(0,30),r=e.url.replace(/^https?:\/\//,``).padEnd(28,` `).slice(0,28),i=t?` ← best match`:``;return`${n} ${r}${i}`}async function xt(e){try{let t=await m.readFile(p.join(e,`package.json`),`utf8`),n=JSON.parse(t);if(n.name)return String(n.name).replace(/^@[^/]+\//,``)}catch{}try{let t=await m.readFile(p.join(e,`.git`,`config`),`utf8`),n=t.match(/url\s*=\s*.*[/:]([^/]+?)(?:\.git)?\s*$/m);if(n&&n[1])return n[1]}catch{}return p.basename(e)}function Q(e,t){if(!t||e.length===0)return e[0]??null;let n=$(t),r=e.find(e=>$(e.name)===n);if(r)return r;let i=e.find(e=>{let t=e.url.replace(/^https?:\/\//,``).replace(/\/.*$/,``),[r]=t.split(`.`);return $(r??``)===n});if(i)return i;let a=e.find(e=>$(e.name).includes(n)||$(e.url).includes(n));return a??e[0]??null}function $(e){return e.toLowerCase().replace(/[^a-z0-9]/g,``)}export{ct as initCommand};
@@ -1 +0,0 @@
1
- import"./config-ZTGpKEWg.js";import"./api-D5XQeEDF.js";import"./client-Bc1xZcH_.js";import"./formatter-DQ6l4sWM.js";import"./emit-DIRc7UzM.js";import{initCommand as e}from"./init-B_nZyv9Q.js";import"./login-CxXnVN9s.js";import"./panel-DglZ755S.js";import"./keybar-D2OI-8rx.js";import"./prompt-hjzdzlyj.js";import"./sparkline-CR_bzxwB.js";export{e as initCommand};
@@ -1 +0,0 @@
1
- import"./config-ZTGpKEWg.js";import"./api-D5XQeEDF.js";import"./formatter-DQ6l4sWM.js";import"./emit-DIRc7UzM.js";import{loginCommand as e}from"./login-CxXnVN9s.js";export{e as loginCommand};
File without changes