@zenovay/cli 0.1.68 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (173) hide show
  1. package/README.md +1 -1
  2. package/dist/{agency-BRTQMQko.js → agency-cNkRWBOo.js} +1 -1
  3. package/dist/ai-DDefS75j.js +3 -0
  4. package/dist/alerts-BQ0EMdBT.js +3 -0
  5. package/dist/analytical-screen-B4xo6sII.js +2 -0
  6. package/dist/analytics-ZCtpMy4v.js +2 -0
  7. package/dist/annotation-aMzsv1oV.js +8 -0
  8. package/dist/{api-hWp9s3Y8.js → api-CdcB84ie.js} +1 -1
  9. package/dist/{api-keys-BmmNLpjG.js → api-keys-x_GGL61a.js} +1 -1
  10. package/dist/api-v2-Co0dWAP5.js +1 -0
  11. package/dist/api-v2-D0mvt__4.js +1 -0
  12. package/dist/{apply-B19bFTz0.js → apply-oUMOH7u2.js} +1 -1
  13. package/dist/{audit-D_NXQFBa.js → audit-VHsZwYPM.js} +1 -1
  14. package/dist/bar-NfgovYHe.js +1 -0
  15. package/dist/bin.js +7 -6
  16. package/dist/chat-panel-D9IjovCR.js +12 -0
  17. package/dist/commands-BE8-kQ9U.js +2 -0
  18. package/dist/companies-BFUFJkEM.js +2 -0
  19. package/dist/{completions-D-Esx72b.js → completions-suqE20Pu.js} +1 -1
  20. package/dist/{config-DB3jF5gG.js → config-B72_Kfe0.js} +1 -1
  21. package/dist/{config--JRu_jFq.js → config-JVhBplSX.js} +1 -1
  22. package/dist/csv-emit-C-9o-imN.js +1 -0
  23. package/dist/csv-emit-CmlDBfbA.js +1 -0
  24. package/dist/data-table-BhKjjiOS.js +1 -0
  25. package/dist/deploys-DLvmc21H.js +2 -0
  26. package/dist/devices-BMdSSO0o.js +2 -0
  27. package/dist/{doctor-B_C_zJQh.js → doctor-BI6TF72T.js} +1 -1
  28. package/dist/{domains-xWz-syku.js → domains-CNv8-i1K.js} +1 -1
  29. package/dist/{emit-NkY7PE3R.js → emit-D4YlMlzk.js} +2 -2
  30. package/dist/empty-state-D-krMX62.js +1 -0
  31. package/dist/error-codes-BiKo9PGm.js +1 -0
  32. package/dist/{error-codes-D4XO4okw.js → error-codes-ByhvHx2M.js} +1 -1
  33. package/dist/errors-DTs33lNs.js +2 -0
  34. package/dist/events-tail-CzYtpjey.js +5 -0
  35. package/dist/export-BAFQahzg.js +4 -0
  36. package/dist/funnel-CnkLL8HX.js +3 -0
  37. package/dist/geo-B9TL_gUX.js +2 -0
  38. package/dist/globe-CnpFQ9iU.js +2 -0
  39. package/dist/{goals-cNoELf2s.js → goals-DQqxuANi.js} +1 -1
  40. package/dist/grid-CMwhs-Ms.js +1 -0
  41. package/dist/health-C6ZK4ZDk.js +1 -0
  42. package/dist/health-Cg5Vtq-A.js +2 -0
  43. package/dist/heatmaps-BLVXNROm.js +1 -0
  44. package/dist/home-CcQ7J4RY.js +2 -0
  45. package/dist/init-CczZwsQf.js +105 -0
  46. package/dist/init-DJbtwhvX.js +1 -0
  47. package/dist/insights-J4kYprJu.js +1 -0
  48. package/dist/{integrations-m8rSzn3o.js → integrations-C3z-N73K.js} +1 -1
  49. package/dist/journeys-BRqDOAqs.js +1 -0
  50. package/dist/keybar-DO5OoZy9.js +1 -0
  51. package/dist/keybar-deep-link-B4VJn2ko.js +1 -0
  52. package/dist/live-DJsNJ-fo.js +1 -0
  53. package/dist/login-CDAP0iKS.js +1 -0
  54. package/dist/login-DU1fY88U.js +2 -0
  55. package/dist/logout-u6BpGCg6.js +2 -0
  56. package/dist/metric-card-C4iqxdww.js +1 -0
  57. package/dist/{notes-IHtGD1hp.js → notes-sFga-5H5.js} +1 -1
  58. package/dist/pages-DXd2DGo6.js +2 -0
  59. package/dist/panel-CTtQ2ue6.js +1 -0
  60. package/dist/{plans-BjApr8oD.js → plans-BhicnNJA.js} +1 -1
  61. package/dist/{profile-u9G8Sxdv.js → profile-DsSj1vSw.js} +1 -1
  62. package/dist/{progress-row-5ns2IsFh.js → progress-row-Afnt5Ng8.js} +1 -1
  63. package/dist/projects-CTXvqzN8.js +2 -0
  64. package/dist/{prompt-CJw_Mqo2.js → prompt-BXvg2B4R.js} +1 -1
  65. package/dist/query-Ds3hjKZ8.js +8 -0
  66. package/dist/range-tabs-BbJdVWNV.js +1 -0
  67. package/dist/resolve-site-BTVBMF1C.js +2 -0
  68. package/dist/retention-DWQML_Jo.js +1 -0
  69. package/dist/revenue-Dm4wls0K.js +2 -0
  70. package/dist/secrets-c-NB_plk.js +1 -0
  71. package/dist/{self-test-QdQWJ7tK.js → self-test-CEclBRpu.js} +3 -3
  72. package/dist/sessions-KmEQ4zZp.js +1 -0
  73. package/dist/{settings-HSntEG-D.js → settings-1kdqZcWp.js} +1 -1
  74. package/dist/share-BsCpBNTV.js +6 -0
  75. package/dist/site-switcher-B2L1-Pjd.js +1 -0
  76. package/dist/sources-CJQtexqb.js +2 -0
  77. package/dist/stats-ctt0SOlE.js +2 -0
  78. package/dist/{status-agent-C2-h8fKK.js → status-agent-CMpp3zEX.js} +1 -1
  79. package/dist/{team-_SMC_yFx.js → team-CyzZCg--.js} +1 -1
  80. package/dist/{teams-C_eV1rXM.js → teams-DnOLx5tK.js} +1 -1
  81. package/dist/{telemetry-BJbpxgIp.js → telemetry-BV-xvfdt.js} +2 -2
  82. package/dist/telemetry-Bbh6Vtst.js +1 -0
  83. package/dist/{telemetry-BwXO7Z83.js → telemetry-C-0DECLq.js} +1 -1
  84. package/dist/themes-6H0KlK3b.js +4 -0
  85. package/dist/{tier-C4q8fJ8m.js → tier-DDIroQbc.js} +1 -1
  86. package/dist/{token-store-BQuGH0z2.js → token-store-BvSCse1t.js} +1 -1
  87. package/dist/token-store-QTNSg4TT.js +1 -0
  88. package/dist/tour-fOYY-mK0.js +8 -0
  89. package/dist/update-C72vyFU1.js +1 -0
  90. package/dist/uptime-Dgi5KItw.js +1 -0
  91. package/dist/{usage-beKJ1HbM.js → usage-BOlapdBM.js} +1 -1
  92. package/dist/{use-DbUqNyZk.js → use-DBiMOOkB.js} +2 -2
  93. package/dist/use-fullscreen-ucSyZkjO.js +1 -0
  94. package/dist/visitors-CbU2tXXG.js +2 -0
  95. package/dist/vitals-3NBHzH_m.js +2 -0
  96. package/dist/watch-GUa_JTOS.js +1 -0
  97. package/dist/{webhooks-CFtGBoJm.js → webhooks-CrE9paQf.js} +1 -1
  98. package/dist/webhooks-forward-CCd-RyJc.js +2 -0
  99. package/dist/wizard-bin.js +1 -1
  100. package/dist/wrapper-Dl9i0Nh7.js +6 -0
  101. package/dist/ws-client-MoEdfqAO.js +1 -0
  102. package/package.json +9 -7
  103. package/dist/ai-RVuD47iX.js +0 -1
  104. package/dist/alerts-B65b9jWl.js +0 -3
  105. package/dist/analytical-screen-DM7SBY5U.js +0 -2
  106. package/dist/analytics-CBP38R6T.js +0 -2
  107. package/dist/annotation-CdqECkB6.js +0 -8
  108. package/dist/api-v2-C6bvRBzw.js +0 -1
  109. package/dist/api-v2-C82L-ZOL.js +0 -1
  110. package/dist/banner-DdgwXGzt.js +0 -1
  111. package/dist/bar-C1Zrfe9H.js +0 -1
  112. package/dist/chat-panel-DS-FxXoL.js +0 -7
  113. package/dist/commands-BJQxwCUl.js +0 -2
  114. package/dist/companies-DNay1Xrh.js +0 -2
  115. package/dist/csv-emit-BWWv60mT.js +0 -1
  116. package/dist/csv-emit-CVO5kebZ.js +0 -1
  117. package/dist/data-table-DJzT7bAr.js +0 -1
  118. package/dist/deploys-BnByoalt.js +0 -2
  119. package/dist/devices-Di7NUUmM.js +0 -2
  120. package/dist/empty-state-DbToIL5T.js +0 -1
  121. package/dist/error-codes-DpKbL-uM.js +0 -1
  122. package/dist/errors-DhQE6fJQ.js +0 -2
  123. package/dist/events-tail-CSHCH77I.js +0 -5
  124. package/dist/export-CmypMMjU.js +0 -4
  125. package/dist/funnel-DwBZVMGB.js +0 -3
  126. package/dist/geo-hKUpyWuw.js +0 -2
  127. package/dist/globe-8qdyNUN-.js +0 -2
  128. package/dist/health-BJwKEdIp.js +0 -2
  129. package/dist/health-CbaNXgdP.js +0 -1
  130. package/dist/heatmaps-SCfq5M8H.js +0 -1
  131. package/dist/home-DAEqaTOD.js +0 -2
  132. package/dist/init-C7zAAhfS.js +0 -79
  133. package/dist/init-DOrkLxxe.js +0 -1
  134. package/dist/insights-Bshy_7Ln.js +0 -1
  135. package/dist/journeys-DZvlQiCz.js +0 -1
  136. package/dist/keybar-QgnmSion.js +0 -1
  137. package/dist/keybar-deep-link-DbmPjAEz.js +0 -1
  138. package/dist/live-3YVbBo2f.js +0 -1
  139. package/dist/login-COMo5KUL.js +0 -2
  140. package/dist/login-W7wIGtyL.js +0 -1
  141. package/dist/logout-D89CET3S.js +0 -2
  142. package/dist/metric-card-bQ-j_G6l.js +0 -1
  143. package/dist/pages-BD1BmfgN.js +0 -2
  144. package/dist/panel-B-XxdP-N.js +0 -1
  145. package/dist/projects-DK9ZO7qd.js +0 -2
  146. package/dist/query-BhtiMkwf.js +0 -8
  147. package/dist/resolve-site-GDYx0__E.js +0 -2
  148. package/dist/retention-BA59Mo79.js +0 -1
  149. package/dist/revenue-vHyW8Ypm.js +0 -2
  150. package/dist/secrets-BBaEWu03.js +0 -1
  151. package/dist/sessions-DN4j8OEV.js +0 -1
  152. package/dist/share-CQwuZtgh.js +0 -6
  153. package/dist/sources-CSFQi-V7.js +0 -2
  154. package/dist/stats-DCzM0MeA.js +0 -2
  155. package/dist/telemetry-CZhEbFqI.js +0 -1
  156. package/dist/themes-D5A3e_mg.js +0 -4
  157. package/dist/token-store-TmBx42nv.js +0 -1
  158. package/dist/tour-STZ66G7K.js +0 -8
  159. package/dist/update-DoOjZZNm.js +0 -1
  160. package/dist/uptime-Da9_QYPm.js +0 -1
  161. package/dist/visitors-CJ2FfgSL.js +0 -2
  162. package/dist/vitals-Cczahuhy.js +0 -2
  163. package/dist/watch-6c4jbLbR.js +0 -1
  164. package/dist/webhooks-forward-D-erVn8S.js +0 -3
  165. package/dist/ws-client-BZMMGeRe.js +0 -1
  166. /package/dist/{client-I4GTcUcm.js → client-ntsEXSVC.js} +0 -0
  167. /package/dist/{confirm-CIdxMt7N.js → confirm-DS5wux0g.js} +0 -0
  168. /package/dist/{examples-CFatZcPz.js → examples-DikBW-H2.js} +0 -0
  169. /package/dist/{formatter-DDG2TSOz.js → formatter-C4YSOKuq.js} +0 -0
  170. /package/dist/{open-url-CTfSApWl.js → open-url-BtI5aLgL.js} +0 -0
  171. /package/dist/{secrets-DzueUVGL.js → secrets-ApB7yh2A.js} +0 -0
  172. /package/dist/{theme-BuGrQHax.js → theme-Brz9wK0w.js} +0 -0
  173. /package/dist/{ui-whccLLRv.js → ui-C5Te-OTJ.js} +0 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zenovay/cli",
3
- "version": "0.1.68",
3
+ "version": "1.0.1",
4
4
  "description": "Zenovay CLI — AI install wizard + full terminal analytics dashboard",
5
5
  "type": "module",
6
6
  "bin": {
@@ -28,14 +28,12 @@
28
28
  "test:smoke": "vitest run tests/smoke --testTimeout=60000",
29
29
  "test:update-golden": "UPDATE_GOLDEN=1 vitest run tests/e2e",
30
30
  "render:globe": "tsx scripts/render-globe.ts",
31
- "smoke": "bash scripts/smoke-test.sh",
32
- "prepare": "husky install"
31
+ "smoke": "bash scripts/smoke-test.sh"
33
32
  },
34
33
  "dependencies": {
35
- "@hono/node-server": "^1.14.0",
36
34
  "cac": "^6.7.14",
37
35
  "chalk": "^5.4.1",
38
- "diff": "^7.0.0",
36
+ "diff": "^8.0.3",
39
37
  "globby": "^14.1.0",
40
38
  "ink": "^5.1.0",
41
39
  "ink-gradient": "^3.0.0",
@@ -45,12 +43,12 @@
45
43
  "open": "^10.1.0",
46
44
  "react": "^18.3.1",
47
45
  "semver": "^7.6.3",
46
+ "string-width": "^7.2.0",
48
47
  "ulid": "^2.3.0",
49
48
  "zod": "^3.23.8"
50
49
  },
51
50
  "devDependencies": {
52
51
  "@aws-sdk/client-s3": "^3.1036.0",
53
- "@types/diff": "^7.0.0",
54
52
  "@types/node": "^22.10.0",
55
53
  "@types/react": "^18.3.12",
56
54
  "@types/semver": "^7.5.8",
@@ -58,7 +56,6 @@
58
56
  "@vitest/coverage-v8": "^2.1.8",
59
57
  "csv-parse": "^6.2.1",
60
58
  "eslint": "^9.16.0",
61
- "husky": "^9.1.7",
62
59
  "ink-testing-library": "^4.0.0",
63
60
  "react-devtools-core": "^4.19.1",
64
61
  "tsdown": "^0.9.0",
@@ -70,6 +67,11 @@
70
67
  "node": ">=20.0.0"
71
68
  },
72
69
  "packageManager": "pnpm@9.15.9",
70
+ "pnpm": {
71
+ "overrides": {
72
+ "ws@>=8.0.0 <8.21.0": ">=8.21.0"
73
+ }
74
+ },
73
75
  "author": "Zenovay <cli@zenovay.com>",
74
76
  "license": "SEE LICENSE IN LICENSE",
75
77
  "homepage": "https://cli.zenovay.com",
@@ -1 +0,0 @@
1
- import{readConfig as e}from"./config--JRu_jFq.js";import"./api-hWp9s3Y8.js";import{readToken as t}from"./token-store-BQuGH0z2.js";import{emit$1 as n}from"./telemetry-BJbpxgIp.js";import{ApiV2Client as r}from"./api-v2-C82L-ZOL.js";import{detectInstalled as i,initCommand as a}from"./init-C7zAAhfS.js";import"./formatter-DDG2TSOz.js";import{emit as o,isHeadless as s}from"./emit-NkY7PE3R.js";import"./open-url-CTfSApWl.js";import"./secrets-DzueUVGL.js";import{parseSseStream as c}from"./client-I4GTcUcm.js";import"./login-COMo5KUL.js";import"./theme-BuGrQHax.js";import{Panel as l,useTheme as u}from"./panel-B-XxdP-N.js";import{Banner as d}from"./banner-DdgwXGzt.js";import"./progress-row-5ns2IsFh.js";import{Select as f}from"./prompt-CJw_Mqo2.js";import"./keybar-QgnmSion.js";import"./sparkline-CpoBjjlc.js";import{ChatPanel as p}from"./chat-panel-DS-FxXoL.js";import{resolveSiteId as m}from"./resolve-site-GDYx0__E.js";import{Box as h,Static as g,Text as _,render as v,useApp as y,useInput as b}from"ink";import x,{useEffect as S,useRef as C,useState as w}from"react";import T from"ink-spinner";import E from"ink-text-input";const D=30,O=9e4;function k(e){return e.replace(/_/g,` `)}function A(e){if(!e)return``;let t=Object.entries(e).map(([e,t])=>`${e}: ${JSON.stringify(t)}`).join(`, `);return t.length>80?t.slice(0,77)+`…`:t}const j=({cliVersion:e,api:t,siteId:r,siteLabel:i,initialAllowAll:a=!1,onClose:o})=>{let{theme:s}=u(),{exit:f}=y(),[p,m]=w([]),[v,j]=w(``),[M,N]=w(!1),[P,F]=w(``),[I,L]=w([]),[R,z]=w(null),[B,V]=w(a),[H,U]=w(!1),[W,G]=w(0),K=C(``),q=C(null),J=C(Date.now());S(()=>{if(!M)return;let e=setInterval(()=>{K.current!==P&&F(K.current)},Math.floor(1e3/D));return()=>clearInterval(e)},[M,P]),S(()=>(n(`mcp.open`,{properties:{has_site:!!r}}),()=>{n(`mcp.close`,{duration_ms:Date.now()-J.current})}),[r]),b((e,t)=>{if(t.escape||t.ctrl&&e===`c`){q.current?.abort(),o();return}if(e===`a`||e===`A`){V(!0),H&&U(!1);return}if(e===`x`||e===`X`){q.current?.abort(),z(`Cancelled.`),U(!1),N(!1);return}if((t.return||e===`y`||e===`Y`)&&H){U(!1);return}if((e===`n`||e===`N`)&&H){q.current?.abort(),z(`Cancelled by user.`),U(!1),N(!1);return}});let Y=async e=>{let i=e.trim();if(!i||M||H)return;j(``),z(null),m(e=>[...e,{role:`user`,content:i}]),K.current=``,F(``),L([]),G(0),N(!0),q.current=new AbortController;let a=setTimeout(()=>{q.current?.abort(),z(`Request timed out after ${O/1e3}s`)},O);try{let e=p.map(e=>({role:e.role,content:e.content}));e.push({role:`user`,content:i});let a=await t.openAiStream(`mcp`,{messages:e,siteId:r},q.current.signal);if(!a.ok){z(`MCP request failed (${a.status})`);return}let o=0,s=new Map;for await(let e of c(a))if(e.type===`delta`)K.current+=e.content;else if(e.type===`tool_call`)s.set(e.id,e.arguments),o+=1,G(o),n(`mcp.tool_call`,{properties:{tool_name:e.name}}),L(t=>[...t,{id:e.id,name:e.name,argsPreview:A(e.arguments),status:`running`}]);else if(e.type===`tool_start`){let t=s.get(e.id);L(r=>r.some(t=>t.id===e.id)?r:(o+=1,G(o),n(`mcp.tool_call`,{properties:{tool_name:e.name}}),[...r,{id:e.id,name:e.name,argsPreview:A(t),status:`running`}]))}else if(e.type===`tool_result`)L(t=>t.map(t=>t.id===e.id?{...t,status:e.error?`error`:`done`,result:e.summary,error:e.error,name:e.name??t.name}:t));else if(e.type===`done`){let e=K.current;m(t=>[...t,{role:`assistant`,content:e||``}]),o>0&&!B&&U(!0);break}else if(e.type===`error`){z(e.message);break}}catch(e){e.name!==`AbortError`&&z(e.message??`unknown error`)}finally{clearTimeout(a),K.current=``,F(``),N(!1),q.current=null}},X=[`mcp`,i].filter(Boolean).join(` · `);return x.createElement(h,{flexDirection:`column`},x.createElement(d,{version:e,subtitle:X}),p.length===0&&!M?x.createElement(h,{marginTop:1,marginLeft:2,flexDirection:`column`},x.createElement(_,{color:s.muted},`Describe what you want to create or change. Examples:`),x.createElement(h,{marginTop:0,flexDirection:`column`},x.createElement(_,{color:s.dim},` · "Create a goal for newsletter signups"`),x.createElement(_,{color:s.dim},` · "Add a funnel: landing page → signup → dashboard"`),x.createElement(_,{color:s.dim},` · "Annotate today with our product launch"`),x.createElement(_,{color:s.dim},` · "Set up uptime monitoring for /api/health"`)),x.createElement(h,{marginTop:1},x.createElement(_,{color:s.dim},`MCP actions execute server-side. `),x.createElement(_,{color:s.warn},`Review each turn before continuing.`)),x.createElement(h,{marginTop:0},x.createElement(_,{color:s.dim},`[a] allow-all [Esc] close`))):null,x.createElement(g,{items:p},(e,t)=>x.createElement(h,{key:t,marginTop:1},x.createElement(l,{title:e.role===`user`?`you`:`Zenovay MCP`,pillColor:e.role===`user`?s.accent:s.info,state:`idle`},x.createElement(_,{color:s.fg,wrap:`wrap`},e.content)))),M?x.createElement(h,{flexDirection:`column`},I.length>0?x.createElement(h,{marginTop:1},x.createElement(l,{title:`Actions${B?` (allow-all)`:``}`,state:I.some(e=>e.status===`running`)?`busy`:`ok`},I.map(e=>x.createElement(h,{key:e.id,flexDirection:`column`,marginBottom:0},x.createElement(h,{flexDirection:`row`},x.createElement(_,{color:e.status===`error`?s.error:e.status===`done`?s.success:s.accent},e.status===`done`?`✓ `:e.status===`error`?`✗ `:`⋯ `),x.createElement(_,{color:s.fg,bold:!0},k(e.name))),e.argsPreview?x.createElement(h,{marginLeft:2},x.createElement(_,{color:s.dim},e.argsPreview)):null,e.status===`done`&&e.result?x.createElement(h,{marginLeft:2},x.createElement(_,{color:s.success},`→ `,e.result.slice(0,80))):null,e.status===`error`&&e.error?x.createElement(h,{marginLeft:2},x.createElement(_,{color:s.error},`✗ `,e.error.slice(0,80))):null)))):null,P.length>0?x.createElement(h,{marginTop:1},x.createElement(l,{title:`Zenovay MCP`,pillColor:s.info,state:`busy`},x.createElement(_,{color:s.fg,wrap:`wrap`},P))):I.every(e=>e.status!==`running`)||I.length===0?x.createElement(h,{marginTop:1,marginLeft:2,flexDirection:`row`},x.createElement(_,{color:s.accent},x.createElement(T,{type:`dots`})),x.createElement(_,{color:s.muted},` Planning actions…`)):null):null,H&&!M?x.createElement(h,{marginTop:1},x.createElement(l,{title:`Continue?`,state:`warn`,pillColor:s.warn},x.createElement(_,{color:s.muted},W,` action`,W===1?``:`s`,` executed this turn. Send another message?`),x.createElement(h,{marginTop:1,flexDirection:`row`},x.createElement(_,{color:s.success},`[Enter / y] `),x.createElement(_,{color:s.dim},`continue `),x.createElement(_,{color:s.error},`[n] `),x.createElement(_,{color:s.dim},`cancel `),x.createElement(_,{color:s.accent},`[a] `),x.createElement(_,{color:s.dim},`allow-all this session `),x.createElement(_,{color:s.warn},`[x] `),x.createElement(_,{color:s.dim},`abort`)))):null,R?x.createElement(h,{marginTop:1,marginLeft:2},x.createElement(_,{color:s.error},`✗ `,R)):null,x.createElement(h,{marginTop:1,marginLeft:2,flexDirection:`column`},x.createElement(h,{flexDirection:`row`},x.createElement(_,{color:M||H?s.dim:s.accent},M?`⋯ `:H?`? `:`> `),x.createElement(E,{value:v,onChange:j,onSubmit:e=>void Y(e),placeholder:M?`executing…`:H?`press Enter to continue, n to cancel…`:`describe what to create or change…`})),x.createElement(h,{marginTop:1},x.createElement(_,{color:s.dim},`[Enter] send [a] allow-all [x] abort [Esc] close`,B?` `:``),B?x.createElement(_,{color:s.success},` ● allow-all`):null)))};async function M(e){let t=await i(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 N(t);return n===`install`?a({cliVersion:e.cliVersion,cwd:e.cwd,json:e.json}):n===`chat`?P(e):F(e)}async function N(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}=v(x.createElement(h,{flexDirection:`column`},x.createElement(l,{title:`Zenovay detected${e.packageMarker?` (${e.packageMarker})`:``}`,state:`idle`},x.createElement(_,null,`What do you want to do?`)),x.createElement(f,{items:n,onSelect:e=>{r(),t(e)}})))})}async function P(n){let i=await e(),a=await t({strict:!1});if(!a)return process.stderr.write("Not logged in — run `zenovay login` first.\n"),2;let o=i.defaultSiteId,s=i.defaultSiteName,c=new r({config:i,cliVersion:n.cliVersion,token:a});return new Promise(e=>{let{unmount:t}=v(x.createElement(p,{cliVersion:n.cliVersion,api:c,dashboardContext:{commandName:`ai chat`,siteId:o,siteLabel:s,metricsSnapshot:null},onClose:()=>{t(),e(0)}}))})}async function F(n){let i=await e(),a=await t({strict:!1});if(!a)return process.stderr.write("Not logged in — run `zenovay login` first.\n"),2;let o=new r({config:i,cliVersion:n.cliVersion,token:a}),s,c;try{let e=await m(o,{explicit:void 0,headless:!1,cliVersion:n.cliVersion});s=e.siteId,c=e.site?.url?e.site.url.replace(/^https?:\/\//,``).replace(/\/$/,``):e.site?.name??s}catch{}return new Promise(e=>{let{unmount:t}=v(x.createElement(j,{cliVersion:n.cliVersion,api:o,siteId:s,siteLabel:c,onClose:()=>{t(),e(0)}}))})}export{M as aiCommand};
@@ -1,3 +0,0 @@
1
- import{readConfig as e}from"./config--JRu_jFq.js";import"./api-hWp9s3Y8.js";import{readToken as t}from"./token-store-BQuGH0z2.js";import{emitErrorEnvelope as n}from"./error-codes-D4XO4okw.js";import{ApiV2Client as r}from"./api-v2-C82L-ZOL.js";import{confirmDestructive as i}from"./confirm-CIdxMt7N.js";import"./formatter-DDG2TSOz.js";import{emitEnvelope as a,wrapItem as o,wrapList as s}from"./emit-NkY7PE3R.js";import"./theme-BuGrQHax.js";import{Panel as c,useTheme as l}from"./panel-B-XxdP-N.js";import{Banner as u}from"./banner-DdgwXGzt.js";import"./prompt-CJw_Mqo2.js";import{resolveSiteId as d}from"./resolve-site-GDYx0__E.js";import{fmtDate as f,shortId as p}from"./fmt-xxIPQJX-.js";import{DataTable as m}from"./data-table-DJzT7bAr.js";import{Box as h,Text as g,render as _}from"ink";import v from"react";const y=new Set([`visitors`,`pageviews`,`bounce_rate`,`avg_session_duration`,`errors`,`lcp`,`inp`,`cls`,`uptime`,`revenue`]),b=/^\d+(m|h|d)$/;function x(e){let t=e.metric;if(!t)return{errorMessage:"--metric is required for `alerts create`."};if(!y.has(t))return{errorMessage:`--metric must be one of: ${[...y].join(`, `)}. Got: ${t}.`};let n=e.op;if(n!==`gt`&&n!==`lt`)return{errorMessage:"--op must be `gt` or `lt`."};let r=e.threshold,i=typeof r==`number`?r:Number(r);if(!Number.isFinite(i))return{errorMessage:`--threshold must be a number.`};let a=e.window;if(!a||!b.test(a))return{errorMessage:"--window must match `<n>m|h|d` (e.g. 5m, 1h, 7d)."};let o=e.channel,s=`email`;if(o!==void 0){if(o!==`email`&&o!==`webhook`)return{errorMessage:`--channel must be 'email' or 'webhook'. Got: ${o}.`};s=o}return s===`email`&&!e.email?{errorMessage:`--email <addr> is required when --channel email (the default).`}:{body:{metric:t,op:n,threshold:i,window:a,...e.name?{name:e.name}:{},channel:s,...e.email?{email:e.email}:{}}}}async function S(c){let l=await e(),u=await t({strict:!1}),f=new r({config:l,cliVersion:c.cliVersion,token:u}),m;try{({siteId:m}=await d(f,{explicit:c.siteId,headless:!!c.json,cliVersion:c.cliVersion}))}catch(e){return c.json?n(e,{command:`alerts`,cliVersion:c.cliVersion}):(process.stderr.write(`${e.message}\n`),2)}try{switch(c.action){case`list`:{let e=await f.listAlerts(m);return c.json?(a(s(e,`alerts.list`,{siteId:m,cliVersion:c.cliVersion,command:`alerts list`})),0):e.length===0?(process.stdout.write("No alerts yet. Create one with `zenovay alerts create --metric <m> --op <gt|lt> --threshold <n> --window <1h>`.\n"),0):T(e,m,c.cliVersion)}case`create`:{let e=x(c);if(`errorMessage`in e)return c.json?n(new C(e.errorMessage),{command:`alerts create`,cliVersion:c.cliVersion}):(process.stderr.write(`Error: ${e.errorMessage}\n`),2);let t=await f.createAlert(m,e.body);return c.json?(a(o(t,`alerts.created`,{siteId:m,cliVersion:c.cliVersion,command:`alerts create`})),0):(process.stdout.write(`\n ✓ Alert created: ${t.metric} ${t.op} ${t.threshold} over ${t.window}\n id: ${t.id}\n\n`),0)}case`delete`:{if(!c.id){let e="alert id is required for `alerts delete`.";return c.json?n(new C(e),{command:`alerts delete`,cliVersion:c.cliVersion}):(process.stderr.write(`Error: ${e}\n`),2)}let e;try{let t=await f.listAlerts(m);e=t.find(e=>e.id===c.id)}catch{}let t=e?`${e.metric} ${e.op} ${e.threshold} (${p(c.id)})`:p(c.id),r=await i({resource:`alert`,name:t,yes:c.yes,destructive:!0});return r?(await f.deleteAlert(m,c.id),c.json?(a(o({deleted:!0,id:c.id},`alerts.deleted`,{siteId:m,cliVersion:c.cliVersion,command:`alerts delete`})),0):(process.stdout.write(`✓ Alert deleted (${p(c.id)}). Notifications stopped immediately.\n`),0)):c.json?(process.stdout.write(JSON.stringify({cancelled:!0})+`
2
- `),1):(process.stdout.write(`Cancelled.
3
- `),1)}}}catch(e){return c.json?n(e,{command:`alerts ${c.action}`,cliVersion:c.cliVersion}):(process.stderr.write(`✗ ${e.message}\n`),1)}}var C=class extends Error{constructor(e){super(e),this.name=`ValidationError`}};const w=({items:e,siteId:t,cliVersion:n})=>{let{theme:r}=l(),i=[{key:`id`,label:`id`,width:14,format:e=>p(String(e))},{key:`metric`,label:`metric`,width:18},{key:`op`,label:`op`,width:3},{key:`threshold`,label:`threshold`,width:10,align:`right`,format:e=>String(e??``)},{key:`window`,label:`window`,width:7},{key:`createdAt`,label:`created`,width:10,format:e=>f(e)}];return v.createElement(h,{flexDirection:`column`},v.createElement(u,{version:n,subtitle:`alerts · ${t}`}),v.createElement(c,{title:`${e.length} alert${e.length===1?``:`s`}`,state:`idle`},v.createElement(m,{columns:i,data:e,headerStyle:`accent`}),v.createElement(h,{marginTop:1},v.createElement(g,{color:r.muted},`Create: zenovay alerts create --metric <m> --op <gt|lt> --threshold <n> --window <1h>`))))};function T(e,t,n){return new Promise(r=>{let i=_(v.createElement(w,{items:e,siteId:t,cliVersion:n}));setTimeout(()=>{i.unmount(),r(0)},50)})}export{S as alertsCommand};
@@ -1,2 +0,0 @@
1
- import{ApiError as e}from"./api-hWp9s3Y8.js";import{buildErrorEnvelope as t}from"./error-codes-D4XO4okw.js";import{formatEvent as n}from"./formatter-DDG2TSOz.js";import{Panel as r,useTheme as i}from"./panel-B-XxdP-N.js";import{Banner as a}from"./banner-DdgwXGzt.js";import{Keybar as o}from"./keybar-QgnmSion.js";import{ChatPanel as s}from"./chat-panel-DS-FxXoL.js";import{Box as c,Text as l,render as u,useApp as d,useInput as f}from"ink";import p,{useEffect as m,useMemo as h,useReducer as g,useRef as _,useState as v}from"react";import y from"ink-spinner";function b(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}}function x(e){return e.replace(/\b[A-Z]+\s+\/v1\/cli\/\S*(?:\s+→\s+\d{3})?/g,``).replace(/\/v1\/cli\/\S*/g,``).replace(/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/gi,``).replace(/\s{2,}/g,` `).trim()}function S(n,r){let i=t(n,{command:r});if(n instanceof e){let e={400:{message:`The request was rejected — check the command flags and arguments.`},404:{message:`The requested site or resource was not found.`,hint:"Run `zenovay domains` to list available domains."}},t=e[n.status];if(t)return i.message=t.message,t.hint?i.hint=t.hint:i.code===`validation_failed`&&!i.hint&&(i.hint=`Check the command flags and arguments.`),i}return i.message=x(i.message)||`The request failed.`,i.hint&&=x(i.hint),i}async function C(e,t){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,t):process.stdout.write(n(i,t)),e.streamer)for await(let i of e.streamer(r.signal))process.stdout.write(n(i,t));return 0}catch(r){if(r.name===`AbortError`)return 0;let i=S(r,e.commandName);return t===`json`?process.stdout.write(JSON.stringify(i,null,2)+`
2
- `):process.stdout.write(n(i,t)),1}finally{process.off(`SIGINT`,i)}}const w=({cliVersion:e})=>{let{theme:t}=i();return p.createElement(c,{flexDirection:`column`},p.createElement(a,{version:e,subtitle:`login required`}),p.createElement(r,{title:`Not logged in`,state:`warn`},p.createElement(l,null,`You need to authenticate before running this command.`),p.createElement(l,null,` `),p.createElement(l,{color:t.muted},`Run `),p.createElement(l,{color:t.accent},`zenovay login`),p.createElement(l,{color:t.muted},` to start the device-flow.`)))};function T(t){let{exit:n}=d(),{theme:u}=i(),[S,C]=g(b,{data:null,status:`loading`,error:null,refreshTick:0,focusIndex:0,showHelp:!1}),[w,T]=v(!1),E=_(C);E.current=C;let D=h(()=>{let e={q:{label:`quit`,handler:()=>{n(),t.onExit(0)}},r:{label:`refresh`,handler:()=>E.current({type:`refresh`})},"?":{label:`help`,handler:()=>E.current({type:`help-toggle`})}};return t.ai&&(e[`/`]={label:`ask AI`,handler:()=>T(!0)}),e},[n,t]),O=h(()=>({...t.keybindings??{},...D}),[t.keybindings,D]);if(f((e,n)=>{if(w)return;if(n.tab&&n.shift){C({type:`focus`,index:(S.focusIndex-1+t.panels.length)%t.panels.length});return}if(n.tab){C({type:`focus`,index:(S.focusIndex+1)%t.panels.length});return}if(e>=`1`&&e<=`9`){let n=Number(e)-1;n<t.panels.length&&C({type:`focus`,index:n});return}let r=O[e];r&&r.handler()}),m(()=>{let n=new AbortController,r=!1,i=async()=>{try{let e=await t.fetcher(n.signal);r||E.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;E.current({type:`error`,message:`This command requires a higher plan.`,status:402,upgradeUrl:n});return}E.current({type:`error`,message:x(t.message)||`The request failed.`,status:t.status});return}if(t.name===`AbortError`)return;E.current({type:`error`,message:x(t.message)||`The request failed.`})}};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,S.refreshTick]),m(()=>{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;E.current({type:`merge`,partial:r})}}catch(e){if(n||e.name===`AbortError`)return;E.current({type:`error`,message:x(e.message)||`The request failed.`})}})(),()=>{n=!0,e.abort()}},[t.streamer]),w&&t.ai)return p.createElement(s,{cliVersion:t.cliVersion,api:t.ai.api,dashboardContext:{commandName:t.commandName,siteId:t.ai.siteId,siteLabel:t.ai.siteLabel,metricsSnapshot:S.data},onClose:()=>T(!1)});if(S.status===`loading`&&S.data===null)return p.createElement(c,{flexDirection:`column`},p.createElement(a,{version:t.cliVersion,subtitle:t.title}),p.createElement(r,{title:`Loading`,state:`busy`},p.createElement(c,null,p.createElement(l,{color:u.accent},p.createElement(y,{type:`dots`})),p.createElement(l,null,` Fetching `,t.commandName,`…`))),p.createElement(o,{items:[{key:`q`,label:`quit`}]}));if(S.status===`error`&&S.error){let e=S.error.status===402;return p.createElement(c,{flexDirection:`column`},p.createElement(a,{version:t.cliVersion,subtitle:t.title}),p.createElement(r,{title:e?`Upgrade required`:`Error`,state:e?`warn`:`err`},p.createElement(l,{color:e?u.warn:u.error},S.error.message),e&&S.error.upgradeUrl?p.createElement(p.Fragment,null,p.createElement(l,null,` `),p.createElement(l,{color:u.muted},`Upgrade: `),p.createElement(l,{color:u.accent},S.error.upgradeUrl)):null),p.createElement(o,{items:[{key:`r`,label:`retry`},{key:`q`,label:`quit`}]}))}let k=S.data,A=Object.entries(O).map(([e,t])=>({key:e,label:t.label})),j=Math.ceil(t.panels.length/2),M=t.panels.slice(0,j),N=t.panels.slice(j);return p.createElement(c,{flexDirection:`column`},p.createElement(a,{version:t.cliVersion,subtitle:t.title}),p.createElement(c,{flexDirection:`row`},M.map((e,t)=>{let n=S.focusIndex===t;return p.createElement(c,{key:e.id,flexDirection:`column`,marginRight:1,flexGrow:1},p.createElement(r,{title:e.title,state:n?`busy`:`idle`},e.render(k,n)))})),N.length>0?p.createElement(c,{flexDirection:`row`},N.map((e,t)=>{let n=t+j,i=S.focusIndex===n;return p.createElement(c,{key:e.id,flexDirection:`column`,marginRight:1,flexGrow:1},p.createElement(r,{title:e.title,state:i?`busy`:`idle`},e.render(k,i)))})):null,S.showHelp?p.createElement(r,{title:`Help`,state:`idle`},Object.entries(O).map(([e,t])=>p.createElement(l,{key:e},`[`,e,`] `,t.label)),p.createElement(l,{color:u.muted},`[tab/shift+tab] cycle focus [1-9] focus panel`)):null,p.createElement(o,{items:A}))}async function E(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}=u(p.createElement(w,{cliVersion:e.cliVersion}));setTimeout(()=>{n(),t(2)},50)}):e.format?C(e,e.format):new Promise(t=>{let{unmount:n}=u(p.createElement(T,{...e,onExit:e=>{n(),t(e)}}))})}export{E as runAnalyticalScreen};
@@ -1,2 +0,0 @@
1
- import{readConfig as e}from"./config--JRu_jFq.js";import{ApiError as t}from"./api-hWp9s3Y8.js";import{readToken as n}from"./token-store-BQuGH0z2.js";import"./telemetry-BJbpxgIp.js";import{ApiV2Client as r}from"./api-v2-C82L-ZOL.js";import"./formatter-DDG2TSOz.js";import{emit as i,isHeadless as a}from"./emit-NkY7PE3R.js";import{openInBrowser as o}from"./open-url-CTfSApWl.js";import"./client-I4GTcUcm.js";import"./theme-BuGrQHax.js";import{Panel as s,useTheme as c}from"./panel-B-XxdP-N.js";import{Banner as l}from"./banner-DdgwXGzt.js";import"./prompt-CJw_Mqo2.js";import{Keybar as u}from"./keybar-QgnmSion.js";import"./sparkline-CpoBjjlc.js";import{ChatPanel as d}from"./chat-panel-DS-FxXoL.js";import{resolveSiteId as f}from"./resolve-site-GDYx0__E.js";import{stripUrlPrefix as p}from"./fmt-xxIPQJX-.js";import{DataTable as m}from"./data-table-DJzT7bAr.js";import{EmptyState as h}from"./empty-state-DbToIL5T.js";import{MetricCard as g}from"./metric-card-bQ-j_G6l.js";import{Bar as _}from"./bar-C1Zrfe9H.js";import{deepLinkFor as ee}from"./keybar-deep-link-DbmPjAEz.js";import{Box as v,Text as y,render as b,useApp as te,useInput as x}from"ink";import S,{useEffect as ne,useState as C}from"react";import re from"ink-spinner";function w(e){if(!(e instanceof t))return!1;let n=e.status;if(n===401||n===403||n===404)return!0;let r=e.body,i=r?.code;return i===`forbidden`||i===`not_found`||i===`auth_required`||i===`auth_invalid`||i===`tier_insufficient`}function T(e,t){return e.catch(e=>{if(w(e))throw e;return t})}async function E(t){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 r({config:o,cliVersion:t.cliVersion,token:s}),l,u;try{({siteId:l,site:u}=await f(c,{explicit:t.siteId,headless:!!t.json,cliVersion:t.cliVersion}))}catch(e){return process.stderr.write(`${e.message}\n`),2}let d=u?.url?u.url.replace(/^https?:\/\//,``).replace(/\/$/,``):u?.name??l;if(a(t))try{let e=await O(c,l,`24h`);if(t.csv||t.tsv){let{writeCsv:n}=await import(`./csv-emit-CVO5kebZ.js`);return n(e.topPages,[`path`,`views`,`uniqueVisitors`,`avgTime`,`bounceRate`],t.tsv?`tsv`:`csv`)}if(t.ndjson){for(let t of e.topPages)process.stdout.write(JSON.stringify(t)+`
2
- `);return 0}return i({type:`overview.snapshot`,data:e}),0}catch(e){let{emitErrorEnvelope:n}=await import(`./error-codes-DpKbL-uM.js`);return n(e,{command:`analytics`,cliVersion:t.cliVersion})}return new Promise(e=>{let{unmount:n}=b(S.createElement(k,{api:c,siteId:l,siteLabel:d,cliVersion:t.cliVersion,onExit:t=>{n(),e(t)}}))})}function D(e){return e===`24h`?`7d`:e}async function O(e,t,n){let[r,i,a,o,s]=await Promise.all([T(e.getStats(t,n),null),T(e.getPages(t),[]),T(e.getSources(t,D(n),`prev`),null),T(e.getGeo(t),null),T(e.getDevices(t),null)]),c=i.reduce((e,t)=>e+t.views,0),l=(r?.daily??[]).map(e=>e.visitors),u=(r?.daily??[]).map(e=>e.pageviews),d=Math.floor(l.length/2),f=l.slice(0,d).reduce((e,t)=>e+t,0),p=u.slice(0,d).reduce((e,t)=>e+t,0),m=(a?.sources??[]).filter(e=>e.channel!==`other`||!e.source.includes(`/`)).slice(0,6).map(e=>({name:e.source,visitors:e.visitors,delta:e.delta??null}));return{visitors:r?.visitors??0,pageviews:r?.pageviews??c,bounceRate:r?.bounceRate??null,avgSession:r?.avgSessionSec??null,series:l,pageviewsSeries:u,prevVisitors:f,prevPageviews:p,topPages:i.slice(0,10),channels:m,countries:(o?.countries??[]).slice(0,8),browsers:(s?.browsers??[]).slice(0,5),devices:(s?.devices??[]).slice(0,5)}}const k=({api:e,siteId:t,siteLabel:n,cliVersion:r,onExit:i})=>{let{exit:a}=te(),{theme:f}=c(),[b,w]=C(null),[T,E]=C(!0),[D,k]=C(null),[A,j]=C(`24h`),[M,N]=C(!1),[P,F]=C(t),[I,L]=C(n),[R,z]=C(!1),[B,V]=C([]),[H,ie]=C(0),[U,W]=C(!1);x(async t=>{if(!U){if(t===`/`){W(!0);return}if(t===`r`||t===`R`){ie(e=>e+1);return}if(t===`o`||t===`O`){o(ee(`overview`,{siteId:P}));return}if(t===`q`){a(),i(0);return}if(t===`1`){N(!1),j(`24h`);return}if(t===`2`){N(!1),j(`7d`);return}if(t===`3`){N(!1),j(`30d`);return}if(t===`4`){N(!1),j(`90d`);return}if(t===`s`){if(B.length===0)try{let t=await e.getSites();V(t)}catch{}z(e=>!e);return}}}),ne(()=>{let t=!1;return E(!0),(async()=>{try{let n=await O(e,P,A);if(t)return;let r=n.visitors===0&&n.pageviews===0&&n.topPages.length===0;if(r&&A===`24h`&&!M){N(!0),j(`7d`);return}w(n),E(!1)}catch(e){t||(k(e.message),E(!1))}})(),()=>{t=!0}},[e,P,A,H]);let G=()=>S.createElement(s,{title:`Switch site`,state:`idle`},B.length===0?S.createElement(y,{color:f.muted},`Loading your sites…`):B.map(e=>S.createElement(v,{key:e.id},S.createElement(y,{color:e.id===P?f.accent:f.muted},e.id===P?`› `:` `),S.createElement(y,{bold:e.id===P},e.name),S.createElement(y,{color:f.muted},` (`,e.url.replace(/^https?:\/\//,``).replace(/\/$/,``),`)`))),S.createElement(v,{marginTop:1},S.createElement(y,{color:f.muted},`Press `),S.createElement(y,{color:f.accent},`[number]`),S.createElement(y,{color:f.muted},` to pick, `),S.createElement(y,{color:f.accent},`[s]`),S.createElement(y,{color:f.muted},` to close.`)));x(e=>{if(U||!R)return;let t=Number(e);if(Number.isInteger(t)&&t>=1&&t<=B.length){let e=B[t-1];F(e.id),L(e.url.replace(/^https?:\/\//,``).replace(/\/$/,``)),z(!1)}});let K=`overview · ${I} · ${A}${M?` (auto)`:``}`,q=[{key:`q`,label:`quit`},{key:`/`,label:`AI chat`},{key:`r`,label:`refresh`},{key:`o`,label:`browser`},{key:`s`,label:`site`},{key:`1-4`,label:`time range`}];if(U)return S.createElement(d,{cliVersion:r,api:e,dashboardContext:{commandName:`overview`,siteId:P,siteLabel:I,metricsSnapshot:b},onClose:()=>W(!1)});if(T)return S.createElement(v,{flexDirection:`column`},S.createElement(l,{version:r,subtitle:K}),S.createElement(s,{title:`Loading`,state:`busy`},S.createElement(v,null,S.createElement(y,{color:f.accent},S.createElement(re,{type:`dots`})),S.createElement(y,null,` Fetching dashboard…`))),R?G():null);if(D)return S.createElement(v,{flexDirection:`column`},S.createElement(l,{version:r,subtitle:K}),S.createElement(h,{reason:`error`,headline:`Failed to load`,hint:D}),R?G():null,S.createElement(u,{items:q}));if(!b||b.visitors===0&&b.pageviews===0&&b.topPages.length===0)return S.createElement(v,{flexDirection:`column`},S.createElement(l,{version:r,subtitle:K}),S.createElement(h,{reason:`no-data`,headline:`No data yet`,hint:M?`No data in 7d either. Visit your site to send the first event — press [s] to switch site.`:`Visit your site to send the first event, or press [3] for 30d / [4] for 90d to widen the window.`}),R?G():null,S.createElement(u,{items:q}));let J=process.stdout.columns??80,Y=Math.max(18,Math.floor(J/4)-1),X=Math.max(28,Math.floor(J/2)-2),ae=[{key:`path`,label:`path`,width:32,format:e=>p(String(e??``))},{key:`views`,label:`views`,align:`right`,width:8},{key:`uniqueVisitors`,label:`visitors`,align:`right`,width:8},{key:`avgTime`,label:`avg time`,align:`right`,width:9,format:e=>typeof e==`number`?`${Math.round(e/1e3)}s`:`—`},{key:`bounceRate`,label:`bounce`,align:`right`,width:7,format:e=>typeof e==`number`?`${(e*100).toFixed(0)}%`:`—`}],Z=b.prevVisitors>0?(b.visitors-b.prevVisitors)/b.prevVisitors:void 0,Q=b.prevPageviews>0?(b.pageviews-b.prevPageviews)/b.prevPageviews:void 0,oe=Math.max(1,...b.channels.map(e=>e.visitors)),se=Math.max(1,...b.countries.map(e=>e.visitors)),ce=Math.max(1,...b.browsers.map(e=>e.visitors)),le=Math.max(1,...b.devices.map(e=>e.visitors)),$=Math.max(8,Math.floor(X/3));return S.createElement(v,{flexDirection:`column`},S.createElement(l,{version:r,subtitle:K}),S.createElement(v,{flexDirection:`row`},S.createElement(g,{title:`Visitors`,value:b.visitors,format:`number`,width:Y,series:b.series,...typeof Z==`number`?{delta:Z}:{}}),S.createElement(g,{title:`Pageviews`,value:b.pageviews,format:`number`,width:Y,series:b.pageviewsSeries,...typeof Q==`number`?{delta:Q}:{}}),S.createElement(g,{title:`Bounce rate`,value:b.bounceRate??``,emptyHint:`—`,format:`percent`,width:Y}),S.createElement(g,{title:`Avg session`,value:b.avgSession??``,emptyHint:`—`,format:`duration`,width:Y})),(b.channels.length>0||b.countries.length>0)&&S.createElement(v,{flexDirection:`row`,flexWrap:`wrap`},b.channels.length>0&&S.createElement(v,{width:X,flexDirection:`column`},S.createElement(s,{title:`Channels`},b.channels.map(e=>S.createElement(v,{key:e.name,flexDirection:`row`},S.createElement(v,{width:12},S.createElement(y,null,e.name)),S.createElement(_,{value:e.visitors,max:oe,width:$,showPercent:!1,...typeof e.delta==`number`?{delta:e.delta}:{}}),S.createElement(y,{color:f.muted},` `,e.visitors))))),b.countries.length>0&&S.createElement(v,{width:X,flexDirection:`column`},S.createElement(s,{title:`Top countries`},b.countries.map(e=>S.createElement(v,{key:e.country,flexDirection:`row`},S.createElement(v,{width:5},S.createElement(y,null,e.country)),S.createElement(_,{value:e.visitors,max:se,width:$,showPercent:!1}),S.createElement(y,{color:f.muted},` `,e.visitors)))))),(b.browsers.length>0||b.devices.length>0)&&S.createElement(v,{flexDirection:`row`,flexWrap:`wrap`},b.browsers.length>0&&S.createElement(v,{width:X,flexDirection:`column`},S.createElement(s,{title:`Top browsers`},b.browsers.map(e=>S.createElement(v,{key:e.name,flexDirection:`row`},S.createElement(v,{width:12},S.createElement(y,null,e.name)),S.createElement(_,{value:e.visitors,max:ce,width:$,showPercent:!1}),S.createElement(y,{color:f.muted},` `,e.visitors))))),b.devices.length>0&&S.createElement(v,{width:X,flexDirection:`column`},S.createElement(s,{title:`Top devices`},b.devices.map(e=>S.createElement(v,{key:e.name,flexDirection:`row`},S.createElement(v,{width:12},S.createElement(y,null,e.name)),S.createElement(_,{value:e.visitors,max:le,width:$,showPercent:!1}),S.createElement(y,{color:f.muted},` `,e.visitors)))))),S.createElement(s,{title:`Top pages (${A})`},b.topPages.length===0?S.createElement(y,{color:f.muted},`No pages with data in this window yet.`):S.createElement(m,{columns:ae,data:b.topPages,zebra:!0})),R?G():null,S.createElement(u,{items:q}))};async function A(e){return E(e)}export{A as analyticsCommand};
@@ -1,8 +0,0 @@
1
- import{readConfig as e}from"./config--JRu_jFq.js";import{ensureFreshToken as t}from"./api-hWp9s3Y8.js";import{readToken as n}from"./token-store-BQuGH0z2.js";import{ApiV2Client as r}from"./api-v2-C82L-ZOL.js";import"./theme-BuGrQHax.js";import"./panel-B-XxdP-N.js";import"./banner-DdgwXGzt.js";import"./prompt-CJw_Mqo2.js";import{resolveSiteId as i}from"./resolve-site-GDYx0__E.js";const a=[`deploy`,`release`,`campaign`,`incident`,`custom`];function o(e){return a.includes(e)}async function s(s){if(!s.message||s.message.length<1||s.message.length>500)return process.stderr.write(`Error: --message is required and must be 1–500 chars.
2
- `),2;if(!o(s.type))return process.stderr.write(`Error: --type must be one of: ${a.join(`, `)}\n`),2;if(s.occurredAt&&Number.isNaN(Date.parse(s.occurredAt)))return process.stderr.write(`Error: --occurred-at must be a valid ISO 8601 timestamp.
3
- `),2;let c=await e(),l=await n({strict:!1});if(!l)return process.stderr.write(`Error: not logged in. Run: zenovay login
4
- `),3;let u=new r({config:c,cliVersion:s.cliVersion,token:l}),d;try{({siteId:d}=await i(u,{explicit:s.siteId,headless:!!s.json,cliVersion:s.cliVersion}))}catch(e){return process.stderr.write(`${e.message}\n`),2}let f=await t({apiBase:c.apiBase});if(!f)return process.stderr.write(`Error: token expired and refresh failed. Run: zenovay login
5
- `),3;l=f;let p=`${c.apiBase}/v1/cli/mutate/annotations`,m;try{m=await fetch(p,{method:`POST`,headers:{"Content-Type":`application/json`,Authorization:`Bearer ${l.accessToken}`,"User-Agent":`@zenovay/cli/${s.cliVersion}`},body:JSON.stringify({siteId:d,type:s.type,message:s.message,occurredAt:s.occurredAt,metadata:s.metadata})})}catch(e){return process.stderr.write(`Network error: ${e.message}\n`),1}let h=await m.text(),g={};try{g=h?JSON.parse(h):{}}catch{}if(!m.ok){let e=typeof g.error==`string`?g.error:g.error?.message,t=e||g.message||h||`${m.status} ${m.statusText}`;return s.json?process.stdout.write(JSON.stringify({success:!1,error:t,status:m.status})+`
6
- `):process.stderr.write(`Failed to create annotation: ${t}\n`),m.status===402?4:m.status===409?5:1}let _=g.annotation||g.data?.annotation;return s.json?process.stdout.write(JSON.stringify({success:!0,annotation:_})+`
7
- `):process.stdout.write(`\n ✓ Created ${s.type} annotation\n ${s.message}\n`+(_?.occurred_at?` at ${new Date(_.occurred_at).toISOString()}\n`:``)+(_?.id?` id ${_.id}\n`:``)+`
8
- `),0}export{s as annotationCreateCommand};
@@ -1 +0,0 @@
1
- import"./config--JRu_jFq.js";import{ApiError as e}from"./api-hWp9s3Y8.js";import"./token-store-BQuGH0z2.js";import{ApiV2Client as t}from"./api-v2-C82L-ZOL.js";export{t as ApiV2Client};
@@ -1 +0,0 @@
1
- import{ApiClient as e,ApiError as t,ensureFreshToken as n}from"./api-hWp9s3Y8.js";import{z as r}from"zod";const i=r.object({id:r.string(),startedAt:r.string(),country:r.string().nullable().optional(),city:r.string().nullable().optional(),device:r.enum([`mobile`,`desktop`,`tablet`,`unknown`]).optional(),os:r.string().nullable().optional(),browser:r.string().nullable().optional(),page:r.string().optional(),referrer:r.string().nullable().optional(),utmSource:r.string().nullable().optional(),utmMedium:r.string().nullable().optional(),utmCampaign:r.string().nullable().optional(),aiScore:r.number().min(0).max(100).nullable().optional()}),a=r.object({visitors:r.array(i),total:r.number().int(),windowStart:r.string(),windowEnd:r.string()}),o=r.object({type:r.enum([`visitor.started`,`visitor.ended`,`visitor.heartbeat`]),visitor:i}),s=r.object({source:r.string(),channel:r.enum([`direct`,`organic`,`paid`,`social`,`referral`,`email`,`other`]).optional(),visitors:r.number().int(),conversions:r.number().int().optional(),revenue:r.number().int().optional(),delta:r.number().nullable().optional()}),c=r.object({sources:r.array(s),totalVisitors:r.number().int(),windowStart:r.string(),windowEnd:r.string()}),l=r.object({bucket:r.string(),amount:r.number().int(),currency:r.string(),transactions:r.number().int()}),u=r.object({series:r.array(l),totalAmount:r.number().int(),currency:r.string(),totalTransactions:r.number().int(),mrr:r.number().int().optional(),arpu:r.number().int().optional(),windowStart:r.string(),windowEnd:r.string()}),d=r.object({url:r.string(),device:r.enum([`mobile`,`desktop`]).optional(),lcp:r.object({p50:r.number(),p75:r.number(),p90:r.number()}).optional(),inp:r.object({p50:r.number(),p75:r.number(),p90:r.number()}).optional(),cls:r.object({p50:r.number(),p75:r.number(),p90:r.number()}).optional(),ttfb:r.object({p50:r.number(),p75:r.number(),p90:r.number()}).optional(),fcp:r.object({p50:r.number(),p75:r.number(),p90:r.number()}).optional(),samples:r.number().int()}),f=r.object({vitals:r.array(d),windowStart:r.string(),windowEnd:r.string()}),p=r.object({id:r.string(),name:r.string(),visitors:r.number().int(),conversions:r.number().int(),dropOff:r.number().min(0).max(1).optional()}),m=r.object({funnelId:r.string(),name:r.string(),steps:r.array(p),totalEntries:r.number().int(),totalCompletions:r.number().int(),conversionRate:r.number().min(0).max(1),windowStart:r.string(),windowEnd:r.string()}),h=r.object({id:r.string(),name:r.string(),stepCount:r.number().int(),lastEvaluatedAt:r.string().nullable().optional()}),g=r.object({funnels:r.array(h)}),_=r.object({visitors:r.number().int(),pageviews:r.number().int(),sessions:r.number().int(),bounceRate:r.number().min(0).max(1),avgSessionSec:r.number(),topPages:r.array(r.object({url:r.string(),views:r.number().int()})),topCountries:r.array(r.object({country:r.string(),visitors:r.number().int()})),windowStart:r.string(),windowEnd:r.string(),daily:r.array(r.object({date:r.string(),visitors:r.number().int(),pageviews:r.number().int()})).optional()}),v=r.object({id:r.string(),name:r.string(),type:r.enum([`event`,`pageview`,`revenue`]),conversions24h:r.number().int(),conversions7d:r.number().int()}),y=r.object({goals:r.array(v)}),b=r.object({id:r.string(),name:r.string(),domain:r.string().nullable().optional(),industry:r.string().nullable().optional(),employeeCount:r.number().int().nullable().optional(),visitorCount:r.number().int(),firstSeenAt:r.string(),lastSeenAt:r.string()}),x=r.object({type:r.enum([`company.identified`,`company.returning`]),company:b}),S=r.object({companies:r.array(b),total:r.number().int()}),C=r.object({type:r.literal(`error.captured`),id:r.string(),message:r.string(),stack:r.string().optional(),url:r.string().optional(),occurredAt:r.string(),count:r.number().int().optional(),spike:r.number().optional()}),w=r.object({id:r.string(),ts:r.string(),class:r.string(),message:r.string(),page:r.string().nullable(),device:r.string().nullable(),fingerprint:r.string().nullable()}),T=r.object({errors:r.array(w),total:r.number().int()}),E=r.object({id:r.string(),name:r.string(),domain:r.string().nullable(),industry:r.string().nullable(),employeeCount:r.number().int().nullable(),visitCount:r.number().int(),firstSeenAt:r.string(),lastSeenAt:r.string(),isNew:r.boolean()}),D=r.object({companies:r.array(E),total:r.number().int()}),O=r.object({columns:r.array(r.string()),rows:r.array(r.record(r.unknown())),row_count:r.number(),duration_ms:r.number(),truncated:r.boolean()}),k=r.object({id:r.string(),provider:r.literal(`github`),commit_sha:r.string(),commit_message:r.string().nullable(),commit_author:r.string().nullable(),branch:r.string().nullable(),repository:r.string().nullable(),commit_url:r.string().nullable(),pushed_at:r.string(),show_on_chart:r.boolean()}),A=r.object({deploys:r.array(k),total:r.number().int()}),j=r.object({id:r.string(),name:r.string(),domain:r.string().nullable(),tier:r.string(),pageviews24h:r.number().int(),isCurrent:r.boolean()}),M=r.object({projects:r.array(j)}),N=r.object({type:r.string(),bucket:r.string(),count:r.number().int()}),P=r.object({events:r.array(N),windowStart:r.string(),windowEnd:r.string()}),F=r.object({id:r.string(),receivedAt:r.string(),url:r.string(),method:r.string(),headers:r.record(r.string(),r.string()),body:r.string()}),I=r.object({columns:r.array(r.string()),rows:r.array(r.array(r.unknown())),rowCount:r.number().int(),durationMs:r.number(),truncated:r.boolean().optional()}),L=r.object({resource:r.string(),values:r.array(r.string()),cachedAt:r.string().optional()});function R(e,t){throw Error(`api-v2: ${e} not yet implemented; awaiting backend Wave ${t}`)}async function*z(e,t){R(e,t)}function B(e){switch(e){case`24h`:return 1;case`7d`:return 7;case`30d`:return 30;case`90d`:return 90;case`1y`:return 365;default:return 7}}var V=class extends e{v2Opts;v2Fetch;v2Token;constructor(e){super(e),this.v2Opts=e,this.v2Fetch=e.fetchImpl??fetch,this.v2Token=e.token??null}get v2ApiBase(){return this.v2Opts.config.apiBase}async v2Headers(e={}){let t=process.env.ZENOVAY_TEAM_ID,r=t&&t.trim()?{"X-Zenovay-Team-Id":t.trim()}:{},i=process.env.ZENOVAY_API_TOKEN;if(i&&i.trim())return{Accept:`application/json`,"User-Agent":`zenovay-cli/${this.v2Opts.cliVersion}`,"X-Zenovay-CLI-Version":this.v2Opts.cliVersion,Authorization:`Bearer ${i.trim()}`,...r,...e};this.v2Token||=await n({apiBase:this.v2ApiBase});let a={Accept:`application/json`,"User-Agent":`zenovay-cli/${this.v2Opts.cliVersion}`,"X-Zenovay-CLI-Version":this.v2Opts.cliVersion,...r,...e};return this.v2Token&&(a.Authorization=`${this.v2Token.tokenType} ${this.v2Token.accessToken}`),a}async v2Request(e,n,r={},i){let a=`${this.v2ApiBase}${e}`,o=await this.v2Headers(r.headers??{}),s=await this.v2Fetch(a,{...r,headers:o,signal:i});if(s.status===401&&this.v2Token){this.v2Token=null;let e=await this.v2Headers(r.headers??{});s=await this.v2Fetch(a,{...r,headers:e,signal:i})}if(!s.ok){let n=await s.text().catch(()=>``),i=n;try{i=JSON.parse(n)}catch{}throw new t(s.status,i,`${r.method??`GET`} ${e} → ${s.status}`)}let c=await s.json();return n.parse(c)}async v2RequestRaw(e,n={},r){let i=`${this.v2ApiBase}${e}`,a=await this.v2Headers(n.headers??{}),o=await this.v2Fetch(i,{...n,headers:a,signal:r});if(o.status===401&&this.v2Token){this.v2Token=null;let e=await this.v2Headers(n.headers??{});o=await this.v2Fetch(i,{...n,headers:e,signal:r})}if(!o.ok){let r=await o.text().catch(()=>``),i=r;try{i=JSON.parse(r)}catch{}throw new t(o.status,i,`${n.method??`GET`} ${e} → ${o.status}`)}let s=await o.json();return s?.data??s}async getVisitors(e,t,n){let r=new URLSearchParams({site_id:e});t?.since&&r.set(`since`,t.since),typeof t?.limit==`number`&&r.set(`limit`,String(t.limit));let i=await this.v2RequestRaw(`/v1/cli/visitors?${r.toString()}`,{},n),o=new Date,s=new Date(Date.now()-24*3600*1e3),c=e=>{if(!e)return`unknown`;let t=e.toLowerCase();return t.includes(`mobile`)?`mobile`:t.includes(`tablet`)?`tablet`:t.includes(`desktop`)?`desktop`:`unknown`};return a.parse({total:i.liveCount??i.visitors?.length??0,visitors:(i.visitors??[]).map(e=>({id:e.sessionId,startedAt:e.lastSeen,country:e.country,city:null,device:c(e.device??null),page:e.currentPath??void 0,aiScore:typeof e.valueScore==`number`?Math.max(0,Math.min(100,e.valueScore)):null})),windowStart:s.toISOString(),windowEnd:o.toISOString()})}streamVisitors(e,t){return this.streamChannel(e,`visitors`,t)}async getSources(e,t=`30d`,n,r){let i=new URLSearchParams({site_id:e,period:t});n&&i.set(`compare`,n);let a=await this.v2RequestRaw(`/v1/cli/sources?${i.toString()}`,{},r),o=a.channels??[],s=a.top_utm_sources??[],l=o.reduce((e,t)=>e+t.visitors,0),u=new Set([`direct`,`organic`,`paid`,`social`,`referral`,`email`]),d=[...o.map(e=>({source:e.name,channel:u.has(e.name)?e.name:`other`,visitors:e.visitors,delta:typeof e.delta==`number`?e.delta/100:null})),...s.map(e=>({source:e.medium?`${e.source}/${e.medium}`:e.source,channel:`other`,visitors:e.visitors}))],f=new Date,p=new Date(Date.now()-B(t)*24*3600*1e3);return c.parse({sources:d,totalVisitors:l,windowStart:p.toISOString(),windowEnd:f.toISOString()})}async getRevenue(e,t=`30d`,n){let r=new URLSearchParams({site_id:e,window:t}),i=await this.v2RequestRaw(`/v1/cli/revenue?${r.toString()}`,{},n),a=(i.daily??[]).map(e=>({bucket:e.date,amount:e.cents,currency:i.currency??`USD`,transactions:e.transactions})),o=a.reduce((e,t)=>e+t.amount,0),s=a.reduce((e,t)=>e+t.transactions,0),c=new Date,l=new Date(Date.now()-B(t)*24*3600*1e3),d={series:a,totalAmount:o,currency:i.currency??`USD`,totalTransactions:s,windowStart:l.toISOString(),windowEnd:c.toISOString()};return typeof i.mrr_cents==`number`&&(d.mrr=i.mrr_cents),u.parse(d)}async getVitals(e,t,n){let r=new URLSearchParams({site_id:e});t?.url&&r.set(`url`,t.url),t?.device&&r.set(`device`,t.device),t?.window&&r.set(`window`,t.window);let i=await this.v2RequestRaw(`/v1/cli/vitals?${r.toString()}`,{},n),a=[];if(i.p75&&(i.sample_count??0)>0){let e=i.p75,n={url:`— site-wide aggregate —`,device:t?.device??void 0,samples:i.sample_count??0,...typeof e.lcp==`number`?{lcp:{p50:e.lcp,p75:e.lcp,p90:e.lcp}}:{},...typeof e.inp==`number`?{inp:{p50:e.inp,p75:e.inp,p90:e.inp}}:{},...typeof e.cls==`number`?{cls:{p50:e.cls,p75:e.cls,p90:e.cls}}:{},...typeof e.fcp==`number`?{fcp:{p50:e.fcp,p75:e.fcp,p90:e.fcp}}:{},...typeof e.ttfb==`number`?{ttfb:{p50:e.ttfb,p75:e.ttfb,p90:e.ttfb}}:{}};a.push(n)}for(let e of i.worst_pages??[])a.push({url:e.path,device:t?.device??void 0,samples:e.sample_count,lcp:{p50:e.lcp_p75,p75:e.lcp_p75,p90:e.lcp_p75}});let o=new Date,s=new Date(Date.now()-B(t?.window??`7d`)*24*3600*1e3);return f.parse({vitals:a,windowStart:s.toISOString(),windowEnd:o.toISOString()})}async getFunnel(e,t,n=`30d`,r){let i=new URLSearchParams({site_id:e,window:n}),a=await this.v2RequestRaw(`/v1/cli/funnels/${encodeURIComponent(t)}?${i.toString()}`,{},r),o=a.total_entries??0,s=(a.steps??[]).map(e=>({id:`step-${e.order}`,name:e.name,visitors:e.visitors,conversions:e.visitors,dropOff:Math.max(0,Math.min(1,e.dropoffPct/100))})),c=s[s.length-1],l=c?.visitors??0,u=o>0?Math.min(1,l/o):0,d=new Date,f=new Date(Date.now()-B(n)*24*3600*1e3);return m.parse({funnelId:a.id??t,name:a.name??t,steps:s,totalEntries:o,totalCompletions:l,conversionRate:u,windowStart:f.toISOString(),windowEnd:d.toISOString()})}async listFunnels(e,t){let n=new URLSearchParams({site_id:e}),r=await this.v2RequestRaw(`/v1/cli/funnels?${n.toString()}`,{},t);return g.parse({funnels:(r.funnels??[]).map(e=>({id:e.id,name:e.name,stepCount:e.step_count}))})}async getStats(e,t=`24h`,n){let r=new URLSearchParams({site_id:e,range:t}),i=await this.v2RequestRaw(`/v1/cli/stats?${r.toString()}`,{},n),a=i.visitors??0,o=i.pageviews??0,s=a,c=s>0?o/s:0,l=c>0?Math.max(0,Math.min(1,1/Math.max(1,c))):0,u=i.avgSessionSec??0,d=new Date,f=new Date(Date.now()-B(t)*24*3600*1e3);return _.parse({visitors:a,pageviews:o,sessions:s,bounceRate:l,avgSessionSec:u,topPages:i.topPage?[{url:i.topPage.path,views:i.topPage.views}]:[],topCountries:i.topSource?[{country:i.topSource.channel,visitors:i.topSource.visitors}]:[],windowStart:f.toISOString(),windowEnd:d.toISOString(),daily:i.daily})}async getGoals(e,t){let n=new URLSearchParams({site_id:e});return this.v2Request(`/v1/cli/goals?${n.toString()}`,y,{},t)}async getLive(e,t){let n=new URLSearchParams({site_id:e});return await this.v2RawJson(`/v1/cli/live?${n.toString()}`,t)}async getPages(e,t){let n=new URLSearchParams({site_id:e});return await this.v2RawJson(`/v1/cli/pages?${n.toString()}`,t)}async getDevices(e,t){let n=new URLSearchParams({site_id:e});return await this.v2RawJson(`/v1/cli/devices?${n.toString()}`,t)}async getGeo(e,t){let n=new URLSearchParams({site_id:e});return await this.v2RawJson(`/v1/cli/geo?${n.toString()}`,t)}async getRetention(e,t){let n=new URLSearchParams({site_id:e});return await this.v2RawJson(`/v1/cli/retention?${n.toString()}`,t)}async getUptime(e,t){let n=new URLSearchParams({site_id:e});return await this.v2RawJson(`/v1/cli/uptime?${n.toString()}`,t)}async getSessions(e,t){let n=new URLSearchParams({site_id:e});return await this.v2RawJson(`/v1/cli/sessions?${n.toString()}`,t)}async getHeatmaps(e,t){let n=new URLSearchParams({site_id:e});return await this.v2RawJson(`/v1/cli/heatmaps?${n.toString()}`,t)}async getJourneys(e,t){let n=new URLSearchParams({site_id:e});return await this.v2RawJson(`/v1/cli/journeys?${n.toString()}`,t)}async getInsights(e,t){let n=new URLSearchParams({site_id:e});return await this.v2RawJson(`/v1/cli/insights?${n.toString()}`,t)}async v2RawJson(e,n){let r=`${this.v2ApiBase}${e}`,i=await this.v2Headers(),a=await this.v2Fetch(r,{headers:i,signal:n});if(a.status===401&&this.v2Token){this.v2Token=null;let e=await this.v2Headers();a=await this.v2Fetch(r,{headers:e,signal:n})}if(!a.ok){let n=await a.text().catch(()=>``),r=n;try{r=JSON.parse(n)}catch{}throw new t(a.status,r,`GET ${e} → ${a.status}`)}return a.json()}streamCompaniesV2(e,t){return this.streamChannel(e,`companies`,t)}streamCompanies(e,t){return z(`streamCompanies`,2)}async getCompanies(e){R(`getCompanies`,2)}async getCompaniesSnapshot(e,t,n){let r=new URLSearchParams({site_id:e});t?.window&&r.set(`window`,t.window),typeof t?.limit==`number`&&r.set(`limit`,String(t.limit));let i=await this.v2RequestRaw(`/v1/cli/companies?${r.toString()}`,{},n);return D.parse(i)}async runSqlQuery(e,n,r,i){let a=`${this.v2ApiBase}/v1/cli/query`,o=await this.v2Headers({"Content-Type":`application/json`}),s=await this.v2Fetch(a,{method:`POST`,headers:o,signal:i,body:JSON.stringify({site_id:e,sql:n,...r?.maxRows?{max_rows:r.maxRows}:{}})});if(!s.ok){let e=await s.text().catch(()=>``),n=e;try{n=JSON.parse(e)}catch{}throw new t(s.status,n,`POST /v1/cli/query → ${s.status}`)}let c=await s.json();return O.parse(c.data??c)}async getDeploys(e,t,n){let r=new URLSearchParams({site_id:e});t?.since&&r.set(`since`,t.since),typeof t?.limit==`number`&&r.set(`limit`,String(t.limit)),t?.branch&&r.set(`branch`,t.branch),t?.onChartOnly&&r.set(`on_chart_only`,`true`);let i=await this.v2RequestRaw(`/v1/cli/deploys?${r.toString()}`,{},n);return A.parse(i)}async getProjects(e,t){let n=new URLSearchParams({site_id:e}),r=await this.v2RequestRaw(`/v1/cli/projects?${n.toString()}`,{},t);return M.parse(r)}async getErrors(e,t,n){let r=new URLSearchParams({site_id:e});t?.window&&r.set(`window`,t.window),typeof t?.limit==`number`&&r.set(`limit`,String(t.limit));let i=await this.v2RequestRaw(`/v1/cli/errors?${r.toString()}`,{},n);return T.parse(i)}streamErrorsV2(e,t){return this.streamChannel(e,`errors`,t)}streamErrors(e,t){return z(`streamErrors`,2)}async getEventsHistory(e,t){R(`getEventsHistory`,2)}forwardWebhook(e,t){return z(`forwardWebhook`,2)}async registerTunnel(e,t){R(`registerTunnel`,2)}async queryRaw(e,t,n){R(`queryRaw`,3)}async getCompletions(e,t){R(`getCompletions`,3)}async listApiKeys(e){return await this.v2RawJson(`/v1/cli/mutate/keys`,e)}async createApiKey(e,t){return await this.v2Mutate(`/v1/cli/mutate/keys`,`POST`,e,t)}async deleteApiKey(e,t){return await this.v2Mutate(`/v1/cli/mutate/keys/${encodeURIComponent(e)}`,`DELETE`,void 0,t)}async addDomain(e,t){return await this.v2Mutate(`/v1/cli/mutate/domains`,`POST`,e,t)}async deleteDomain(e,t){return await this.v2Mutate(`/v1/cli/mutate/domains/${encodeURIComponent(e)}`,`DELETE`,void 0,t)}async listTeam(e){return await this.v2RawJson(`/v1/cli/mutate/team`,e)}async inviteTeamMember(e,t){return await this.v2Mutate(`/v1/cli/mutate/team/invite`,`POST`,e,t)}async removeTeamMember(e,t){return await this.v2Mutate(`/v1/cli/mutate/team/members/${encodeURIComponent(e)}`,`DELETE`,void 0,t)}async updateTeamMemberRole(e,t,n){return await this.v2Mutate(`/v1/cli/mutate/team/members/${encodeURIComponent(e)}/role`,`PATCH`,{role:t},n)}async updateProfile(e,t){return await this.v2Mutate(`/v1/cli/mutate/profile`,`POST`,e,t)}async getPlanInfo(e){return await this.v2RawJson(`/v1/cli/mutate/plans/info`,e)}async upgradePlan(e,t){return await this.v2Mutate(`/v1/cli/mutate/plans/upgrade`,`POST`,{targetPlan:e},t)}async cancelPlan(e){return await this.v2Mutate(`/v1/cli/mutate/plans/cancel`,`POST`,{},e)}async getSettings(e){return await this.v2RawJson(`/v1/cli/mutate/settings`,e)}async getUsage(e){return await this.v2RawJson(`/v1/cli/mutate/usage`,e)}async setSetting(e,t,n){return await this.v2Mutate(`/v1/cli/mutate/settings`,`POST`,{key:e,value:t},n)}async listIntegrations(e){return await this.v2RawJson(`/v1/cli/mutate/integrations`,e)}async disconnectIntegration(e,t){return await this.v2Mutate(`/v1/cli/mutate/integrations/disconnect`,`POST`,{name:e},t)}async listGoals(e){return await this.v2RawJson(`/v1/cli/mutate/goals`,e)}async createGoal(e,t){return await this.v2Mutate(`/v1/cli/mutate/goals`,`POST`,e,t)}async deleteGoal(e,t){return await this.v2Mutate(`/v1/cli/mutate/goals/${encodeURIComponent(e)}`,`DELETE`,void 0,t)}async listNotes(e){return await this.v2RawJson(`/v1/cli/mutate/notes`,e)}async createNote(e,t){return await this.v2Mutate(`/v1/cli/mutate/notes`,`POST`,e,t)}async deleteNote(e,t){return await this.v2Mutate(`/v1/cli/mutate/notes/${encodeURIComponent(e)}`,`DELETE`,void 0,t)}async listAgencyClients(e){return await this.v2RawJson(`/v1/cli/mutate/agency/clients`,e)}async addAgencyClient(e,t){return await this.v2Mutate(`/v1/cli/mutate/agency/clients`,`POST`,e,t)}async removeAgencyClient(e,t){return await this.v2Mutate(`/v1/cli/mutate/agency/clients/${encodeURIComponent(e)}`,`DELETE`,void 0,t)}async sendAgencyReport(e,t){return await this.v2Mutate(`/v1/cli/mutate/agency/report/${encodeURIComponent(e)}`,`POST`,{},t)}async listWebhooks(e){return await this.v2RawJson(`/v1/cli/mutate/webhooks`,e)}async createWebhook(e,t){return await this.v2Mutate(`/v1/cli/mutate/webhooks`,`POST`,e,t)}async deleteWebhook(e,t){return await this.v2Mutate(`/v1/cli/mutate/webhooks/${encodeURIComponent(e)}`,`DELETE`,void 0,t)}async rotateWebhookSecret(e,t){return await this.v2Mutate(`/v1/cli/mutate/webhooks/${encodeURIComponent(e)}/rotate`,`POST`,{},t)}async testWebhook(e,t){return await this.v2Mutate(`/v1/cli/mutate/webhooks/${encodeURIComponent(e)}/test`,`POST`,{},t)}async getAuditLogs(e,t){let n=new URLSearchParams;e.since&&n.set(`since`,e.since),e.action&&n.set(`action`,e.action),e.actor&&n.set(`actor`,e.actor);let r=n.toString()?`/v1/cli/mutate/audit/logs?${n.toString()}`:`/v1/cli/mutate/audit/logs`;return await this.v2RawJson(r,t)}async exportAudit(e,n){let r=`${this.v2ApiBase}/v1/cli/mutate/audit/export?format=${encodeURIComponent(e.format)}`,i=await this.v2Headers(),a=await this.v2Fetch(r,{headers:i,signal:n});if(a.status===401&&this.v2Token){this.v2Token=null;let e=await this.v2Headers();a=await this.v2Fetch(r,{headers:e,signal:n})}if(!a.ok){let e=await a.text().catch(()=>``),n=e;try{n=JSON.parse(e)}catch{}throw new t(a.status,n,`GET /v1/cli/mutate/audit/export → ${a.status}`)}return a.text()}async getShare(e,t){let n=new URLSearchParams({siteId:e});return await this.v2RawJson(`/v1/cli/mutate/share?${n.toString()}`,t)}async enableShare(e,t){return await this.v2Mutate(`/v1/cli/mutate/share/enable`,`POST`,{siteId:e},t)}async disableShare(e,t){return await this.v2Mutate(`/v1/cli/mutate/share/disable`,`POST`,{siteId:e},t)}async v2Mutate(e,n,r,i){let a=`${this.v2ApiBase}${e}`,o=await this.v2Headers(r===void 0?{}:{"Content-Type":`application/json`}),s={method:n,headers:o,signal:i};r!==void 0&&(s.body=JSON.stringify(r));let c=await this.v2Fetch(a,s);if(c.status===401&&this.v2Token){this.v2Token=null;let e=await this.v2Headers(r===void 0?{}:{"Content-Type":`application/json`});c=await this.v2Fetch(a,{...s,headers:e})}if(!c.ok){let r=await c.text().catch(()=>``),i=r;try{i=JSON.parse(r)}catch{}throw new t(c.status,i,`${n} ${e} → ${c.status}`)}let l=c.headers.get(`content-type`)??``;return l.includes(`application/json`)?c.json():{}}async*streamChannel(e,t,n){let{connectWs:r}=await import(`./ws-client-BZMMGeRe.js`),i=this.v2ApiBase.replace(/^https:\/\//,`wss://`).replace(/^http:\/\//,`ws://`),a=`${i}/v1/cli/stream/${encodeURIComponent(e)}?channels=${t}`,o=this.v2Token?.accessToken;for await(let e of r({url:a,bearer:o,signal:n})){if(e.type!==`message`)continue;let t=e.data;if(t&&typeof t==`object`){let e=t;yield e.event??t}}}async createTunnel(e,n,r){let i=`${this.v2ApiBase}/v1/cli/tunnels`,a=await this.v2Headers({"Content-Type":`application/json`}),o=await this.v2Fetch(i,{method:`POST`,headers:a,signal:r,body:JSON.stringify({site_id:e,target_pattern:n})});if(!o.ok){let e=await o.text().catch(()=>``);throw new t(o.status,e,`POST /v1/cli/tunnels → ${o.status}`)}let s=await o.json(),c=s.data??{};if(!c.tunnel_key||!c.public_url||!c.ws_url)throw new t(500,s,`createTunnel: malformed response`);return{tunnelKey:c.tunnel_key,publicUrl:c.public_url,wsUrl:c.ws_url,siteId:c.site_id??e}}tunnelClient(e){let t=this.v2Token?.accessToken;return{start:async(n,r)=>{let{WsTunnelClient:i}=await import(`./ws-client-BZMMGeRe.js`),a=new i({url:e,bearer:t,signal:r});await a.start(n)}}}async listAlerts(e,t){let n=new URLSearchParams({site_id:e}),r=await this.v2RawJson(`/v1/cli/alerts?${n.toString()}`,t),i=(()=>{if(Array.isArray(r))return r;let e=r;if(Array.isArray(e?.alerts))return e.alerts;if(e?.data&&typeof e.data==`object`){let t=e.data;if(Array.isArray(t.alerts))return t.alerts;if(Array.isArray(e.data))return e.data}return[]})();return i.map(H)}async createAlert(e,t,n){let r=t.op===`gt`?`greater_than`:(t.op,`less_than`),i=t.channel===`webhook`?`webhook`:`email`;if(i===`email`&&!t.email){let e=Error(`--channel email requires --email <addr>`);throw e.name=`ValidationError`,e}let a={site_id:e,name:t.name??`${t.metric} ${t.op} ${t.threshold}`,metric:t.metric,threshold:t.threshold,comparator:r,window:t.window,channel:i,email:t.email??``},o=await this.v2Mutate(`/v1/cli/alerts`,`POST`,a,n),s=`data`in o&&o.data?o.data:o;return H(s)}async deleteAlert(e,t,n){let r=new URLSearchParams({site_id:e});await this.v2Mutate(`/v1/cli/alerts/${encodeURIComponent(t)}?${r.toString()}`,`DELETE`,void 0,n)}};function H(e){let t=(()=>e.op===`gt`||e.op===`lt`?e.op:e.comparator===`greater_than`?`gt`:e.comparator===`less_than`?`lt`:`gt`)();return{id:String(e.id),metric:e.metric,op:t,threshold:e.threshold,window:e.window,createdAt:e.createdAt??e.created_at??null}}export{V as ApiV2Client};
@@ -1 +0,0 @@
1
- import{useTheme as e}from"./panel-B-XxdP-N.js";import{Box as t,Text as n}from"ink";import r from"react";function i(){let e=process.stdout.columns;return typeof e==`number`&&e>0?e:80}function a({version:a,subtitle:o}){let{theme:s}=e(),c=i(),l=`ZENOVAY`,u=`real-time analytics`,d=`v${a}`,f=`╭─ `,p=`─╮`,m=f.length+l.length+2+u.length+1+d.length+1+p.length,h=Math.max(2,c-m),g=`─`.repeat(h),_=`─`.repeat(Math.max(2,c-2)),v=o??``,y=v.slice(0,Math.max(0,c-4)),b=` `.repeat(Math.max(1,c-2-1-y.length-1));return r.createElement(t,{flexDirection:`column`},r.createElement(t,{flexDirection:`row`},r.createElement(n,{color:s.border},f),r.createElement(n,{color:s.accent,bold:!0},l),r.createElement(n,{color:s.dim},` `,u),r.createElement(n,{color:s.border},g),r.createElement(n,{color:s.dim},` `,d,` `),r.createElement(n,{color:s.border},p)),o?r.createElement(t,{flexDirection:`row`},r.createElement(n,{color:s.border},`│ `),r.createElement(n,{color:s.fg},y),r.createElement(n,{color:s.border},b,`│`)):null,r.createElement(t,{flexDirection:`row`},r.createElement(n,{color:s.border},`╰`,_,`╯`)))}export{a as Banner};
@@ -1 +0,0 @@
1
- import{useTheme as e}from"./panel-B-XxdP-N.js";import{Box as t,Text as n}from"ink";import r from"react";const i=[` `,`▏`,`▎`,`▍`,`▌`,`▋`,`▊`,`▉`,`█`];function a(e,t,n){let r=Math.max(0,Math.min(t*8,Math.round(e*t*8))),a=Math.floor(r/8),o=r%8,s=o>0&&a<t,c=s?i[o]??``:``,l=`█`.repeat(a)+c,u=Math.max(0,t-a-(s?1:0)),d=n===`outline`?`░`.repeat(u):` `.repeat(u);return l+d}function o({value:i,max:o,width:s=24,delta:c,label:l,theme:u,variant:d=`filled`,color:f,maxWidth:p,showPercent:m=!0}){let{theme:h}=e(),g=u??h,_=process.stdout.columns,v=typeof _==`number`&&_>4?_-4:80,y=p??v,b=Math.max(1,Math.min(s,y)),x=o<=0?1:o,S=Math.max(0,Math.min(1,i/x)),C=a(S,b,d),w=`${Math.round(S*100)}%`,T=f??g.accent,E=null;if(typeof c==`number`){let e=Math.abs(c);E=e<.5?r.createElement(n,{color:g.dim},` `,`→ `,e.toFixed(1),`%`):c>0?r.createElement(n,{color:g.success},` `,`↑ `,e.toFixed(1),`%`):r.createElement(n,{color:g.error},` `,`↓ `,e.toFixed(1),`%`)}return r.createElement(t,{flexDirection:`row`},l===void 0?null:r.createElement(n,{color:g.muted},l,` `),r.createElement(n,{color:T},C),m?r.createElement(n,{color:g.fg},` `,w):null,E)}export{o as Bar};
@@ -1,7 +0,0 @@
1
- import{emit$1 as e}from"./telemetry-BJbpxgIp.js";import{parseSseStream as t}from"./client-I4GTcUcm.js";import{Panel as n,useTheme as r}from"./panel-B-XxdP-N.js";import{Banner as i}from"./banner-DdgwXGzt.js";import{Box as a,Static as o,Text as s,useApp as c,useInput as l}from"ink";import u,{useEffect as d,useRef as f,useState as p}from"react";import m from"ink-spinner";import h from"ink-text-input";const g=2048;async function*_(e){let n=[{role:`system`,content:v(e.context)},...e.transcript,{role:`user`,content:e.newUserMessage}],r;try{r=await e.api.openAiStream(`chat`,{messages:n,siteId:e.context.siteId},e.signal)}catch(e){yield{type:`error`,message:e.message??`request failed`};return}if(!r.ok){yield{type:`error`,message:`chat request failed (${r.status})`,code:String(r.status)};return}let i=parseInt(r.headers.get(`X-CLI-Queries-Today`)??`0`,10),a=parseInt(r.headers.get(`X-CLI-Queries-Daily-Limit`)??`0`,10),o=r.headers.get(`X-CLI-Tier`)??``;a>0&&(yield{type:`rate_limit`,used:i,limit:a,tier:o});let s=``;try{for await(let e of t(r))if(e.type===`delta`)s+=e.content,yield{type:`delta`,text:e.content};else if(e.type===`tool_start`)yield{type:`tool_start`,id:e.id,name:e.name};else if(e.type===`tool_result`)yield{type:`tool_result`,id:e.id,name:e.name,summary:e.summary,error:e.error};else if(e.type===`done`){yield{type:`done`,fullText:s};return}else if(e.type===`error`){yield{type:`error`,message:e.message,code:e.code};return}yield{type:`done`,fullText:s}}catch(e){if(e.name===`AbortError`){yield{type:`error`,message:`cancelled`,code:`aborted`};return}yield{type:`error`,message:e.message??`stream parse failed`}}}function v(e){let t=new Date().toISOString(),n=e.metricsSnapshot?y(e.metricsSnapshot,g):`(no live data yet)`,r=e.siteLabel?`${e.siteLabel}${e.siteId?` (id: ${e.siteId})`:``}`:e.siteId??`(no site)`;return[`You are the Zenovay AI assistant, embedded in the Zenovay terminal CLI.`,``,`The user is currently looking at the \`${e.commandName}\` view for their site ${r}.`,`They can ask questions about their analytics in plain English. Be concise`,`(≤200 words unless they ask for more). Cite specific numbers from the snapshot`,`below. Use plain text only — the terminal does not render markdown.`,``,`Current dashboard snapshot (live as of ${t}):`,n,``,`When you do not have enough data to answer, say so explicitly and tell`,`the user which command would surface that data (e.g. "run zenovay sources`,`--period 30d to get monthly trends"). Do NOT fabricate numbers.`].join(`
2
- `)}function y(e,t){let n=JSON.stringify(e);if(n.length<=t)return JSON.stringify(e,null,2);let r=JSON.parse(n);for(let e=0;e<5;e+=1){r=b(r,10-e*2);let n=JSON.stringify(r);if(n.length<=t)return JSON.stringify(r,null,2)}let i=JSON.stringify(r).slice(0,t-16);return i+`… [truncated]`}function b(e,t){if(Array.isArray(e))return e.length>t?[...e.slice(0,t),`… ${e.length-t} more elided`]:e.map(e=>b(e,t));if(e&&typeof e==`object`){let n={};for(let[r,i]of Object.entries(e))n[r]=b(i,t);return n}return e}const x=30,S=6e4;function C(e){return e.replace(/^ask_/,``).replace(/_/g,` `)}const w=({cliVersion:t,api:g,dashboardContext:v,onClose:y})=>{let{theme:b}=r(),{exit:w}=c(),[T,E]=p([]),[D,O]=p(``),[k,A]=p(!1),[j,M]=p(``),[N,P]=p(null),[F,I]=p([]),[L,R]=p(null),z=f(``),B=f(null);d(()=>{if(!k)return;let e=setInterval(()=>{z.current!==j&&M(z.current)},Math.floor(1e3/x));return()=>clearInterval(e)},[k,j]);let V=f(Date.now()),H=f(0),U=f(0);d(()=>(e(`chat.open`,{properties:{from:v.commandName,has_site:!!v.siteId}}),()=>{e(`chat.close`,{duration_ms:Date.now()-V.current,properties:{turns:H.current,tools_called:U.current}})}),[v.commandName,v.siteId]),l((e,t)=>{if(t.escape){B.current?.abort(),y();return}if(t.ctrl&&e===`c`){B.current?.abort(),y();return}});let W=async t=>{let n=t.trim();if(!n)return;if(n.startsWith(`/`)){G(n),O(``);return}if(k)return;O(``),P(null);let r={role:`user`,content:n};E(e=>[...e,r]),z.current=``,M(``),I([]),A(!0),B.current=new AbortController;let i=setTimeout(()=>{B.current?.abort(),P(`Request timed out after ${S/1e3}s`)},S);try{let t=_({api:g,transcript:T,newUserMessage:n,context:v,signal:B.current.signal});H.current+=1;for await(let n of t)if(n.type===`delta`)z.current+=n.text;else if(n.type===`rate_limit`)R({used:n.used,limit:n.limit,tier:n.tier});else if(n.type===`tool_start`)U.current+=1,e(`chat.tool_call`,{properties:{tool_name:n.name}}),I(e=>[...e,{id:n.id,name:n.name,status:`running`}]);else if(n.type===`tool_result`)n.error&&e(`chat.tool_error`,{properties:{tool_name:n.name??`unknown`,error:n.error.slice(0,128)}}),I(e=>e.map(e=>e.id===n.id?{...e,status:n.error?`error`:`done`,summary:n.summary,error:n.error,name:n.name??e.name}:e));else if(n.type===`done`){let e=n.fullText.length>0?n.fullText:z.current;E(t=>[...t,{role:`assistant`,content:e}]);break}else if(n.type===`error`){P(n.message),z.current.length>0&&E(e=>[...e,{role:`assistant`,content:z.current}]);break}}catch(e){P(e.message??`unknown error`)}finally{clearTimeout(i),z.current=``,M(``),I([]),A(!1),B.current=null}},G=e=>{let t=e.toLowerCase();if(t===`/clear`){E([]),P(null);return}if(t===`/exit`||t===`/quit`){B.current?.abort(),y();return}if(t===`/help`){E(e=>[...e,{role:`assistant`,content:`Commands:
3
- /clear — wipe the transcript
4
- /exit — close chat (or press Esc)
5
- /help — show this
6
-
7
- Ask anything about your analytics data.`}]);return}P(`Unknown command: ${e}. Try /help.`)},K=[`chat`,v.commandName,v.siteLabel].filter(e=>!!e),q=F.some(e=>e.status===`running`),J=L&&L.limit>0?L.used/L.limit:0;return u.createElement(a,{flexDirection:`column`},u.createElement(i,{version:t,subtitle:K.join(` · `)}),T.length===0&&!k?u.createElement(a,{marginTop:1,marginLeft:2,flexDirection:`column`},u.createElement(s,{color:b.muted},`Ask anything about your analytics. Examples:`),u.createElement(a,{marginTop:0,flexDirection:`column`},u.createElement(s,{color:b.dim},` · "What's my top page today?"`),u.createElement(s,{color:b.dim},` · "Where are most visitors coming from?"`),u.createElement(s,{color:b.dim},` · "Show me the bounce rate trend this week"`),u.createElement(s,{color:b.dim},` · "Which pages have the highest bounce rate?"`)),u.createElement(a,{marginTop:1},u.createElement(s,{color:b.dim},`Type `),u.createElement(s,{color:b.accent},`/help`),u.createElement(s,{color:b.dim},` for commands · `),u.createElement(s,{color:b.accent},`Esc`),u.createElement(s,{color:b.dim},` to close`))):null,u.createElement(o,{items:T},(e,t)=>u.createElement(a,{key:t,marginTop:1},u.createElement(n,{title:e.role===`user`?`you`:`Zenovay`,pillColor:e.role===`user`?b.accent:b.info,state:`idle`},u.createElement(s,{color:b.fg,wrap:`wrap`},e.content)))),k?u.createElement(a,{flexDirection:`column`},F.length>0?u.createElement(a,{marginTop:1},u.createElement(n,{title:`Fetching data`,state:q?`busy`:`ok`},F.map(e=>u.createElement(a,{key:e.id,flexDirection:`row`},u.createElement(s,{color:e.status===`error`?b.error:e.status===`done`?b.success:b.accent},e.status===`done`?`✓ `:e.status===`error`?`✗ `:`⋯ `),u.createElement(s,{color:b.muted},C(e.name)),e.status===`done`&&e.summary?u.createElement(s,{color:b.dim},` → `,e.summary):null,e.status===`error`&&e.error?u.createElement(s,{color:b.error},` : `,e.error.slice(0,60)):null)))):null,j.length>0?u.createElement(a,{marginTop:1},u.createElement(n,{title:`Zenovay`,pillColor:b.info,state:`busy`},u.createElement(s,{color:b.fg,wrap:`wrap`},j))):!q||F.length===0?u.createElement(a,{marginTop:1,marginLeft:2,flexDirection:`row`},u.createElement(s,{color:b.accent},u.createElement(m,{type:`dots`})),u.createElement(s,{color:b.muted},` Zenovay is thinking…`)):null):null,N?u.createElement(a,{marginTop:1,marginLeft:2},u.createElement(s,{color:b.error},`✗ `,N)):null,u.createElement(a,{marginTop:1,marginLeft:2,flexDirection:`column`},u.createElement(a,{flexDirection:`row`},u.createElement(s,{color:k?b.dim:b.accent},k?`⋯ `:`> `),u.createElement(h,{value:D,onChange:O,onSubmit:e=>void W(e),placeholder:k?`waiting for response…`:`ask the AI…`})),u.createElement(a,{marginTop:1,flexDirection:`row`,justifyContent:`space-between`},u.createElement(s,{color:b.dim},`[Enter] send [/clear] [/help] [Esc] back`),L&&L.limit>0?u.createElement(s,{color:J>.85?b.warn:b.dim},L.tier,` · `,L.used,`/`,L.limit,` today`):null)))};export{w as ChatPanel};
@@ -1,2 +0,0 @@
1
- import"./formatter-DDG2TSOz.js";import{isHeadless as e}from"./emit-NkY7PE3R.js";const t={flag:`--site-id <id>`,description:`Site ID`},n={flag:`--json`,description:`Emit JSON`},r=[n,{flag:`--csv`,description:`Emit CSV`},{flag:`--tsv`,description:`Emit TSV`},{flag:`--ndjson`,description:`Emit NDJSON`}],i=[{name:`analytics`,description:`Landing dashboard — visitors, pageviews, bounce, top pages`,group:`ANALYTICS`,tier:`free`,options:[t,n]},{name:`overview`,description:"Alias for `analytics` (kept for back-compat)",group:`ANALYTICS`,tier:`free`,options:[t,n]},{name:`watch`,description:"Alias for `analytics` (deprecated)",group:`ANALYTICS`,tier:`free`,options:[t,{flag:`--interval <ms>`,description:`Poll interval ms (legacy; ignored)`,default:15e3},n]},{name:`home`,description:`Top-level summary — sites + this-week deltas`,group:`ANALYTICS`,tier:`free`,options:[n]},{name:`live`,description:`Real-time visitors + globe + recent events (2s polling)`,group:`ANALYTICS`,tier:`free`,options:[t,n]},{name:`pages`,description:`Top pages by views — last 24h`,group:`ANALYTICS`,tier:`free`,options:[t,n]},{name:`devices`,description:`Device / browser / OS breakdown — last 24h`,group:`ANALYTICS`,tier:`free`,options:[t,n]},{name:`geo`,description:`Countries + cities + globe — last 24h`,group:`ANALYTICS`,tier:`free`,options:[t,n]},{name:`sources`,description:`Traffic source breakdown with delta arrows`,group:`ANALYTICS`,tier:`free`,options:[t,{flag:`--period <p>`,description:`7d | 30d | 90d | 1y`,default:`30d`},{flag:`--compare <c>`,description:`Comparison window (use "prev" for period-over-period)`},...r]},{name:`revenue`,description:`MRR / ARR / transaction series`,group:`ANALYTICS`,tier:`free`,options:[t,{flag:`--range <r>`,description:`24h | 7d | 30d | 1y`,default:`30d`},{flag:`--watch`,description:`Auto-refresh every 5 minutes`},...r]},{name:`stats`,description:`One-shot dashboard summary (scriptable by default)`,group:`ANALYTICS`,tier:`free`,options:[t,{flag:`--range <range>`,description:`24h | 7d | 30d`,default:`24h`},{flag:`--watch`,description:`Auto-refresh every 60s`},...r]},{name:`globe`,description:"Hint — use `zenovay live` for the terminal real-time view",group:`ANALYTICS`,tier:`free`,options:[n]},{name:`vitals`,description:`Core Web Vitals dashboard (LCP / INP / CLS / TTFB / FCP)`,group:`BEHAVIOR`,tier:`pro`,options:[t,{flag:`--url <path>`,description:`Filter to a single URL`},{flag:`--device <type>`,description:`mobile | desktop`},{flag:`--window <w>`,description:`24h | 7d | 30d | 90d`,default:`7d`},{flag:`--watch`,description:`Auto-refresh every 5 minutes`},...r]},{name:`retention`,description:`Cohort retention heatmap — D1 / D7 / D30 (Pro+)`,group:`BEHAVIOR`,tier:`pro`,options:[t,n]},{name:`uptime`,description:`Uptime monitors with status + p95 (Pro+)`,group:`BEHAVIOR`,tier:`pro`,options:[t,n]},{name:`sessions`,description:`Recent session-replay list (Pro+)`,group:`BEHAVIOR`,tier:`pro`,options:[t,n]},{name:`heatmaps`,description:`Recent heatmap captures (Pro+)`,group:`BEHAVIOR`,tier:`pro`,options:[t,n]},{name:`journeys`,description:`Page-to-page transition flow (Pro+)`,group:`BEHAVIOR`,tier:`pro`,options:[t,n]},{name:`errors`,description:`Recent error snapshot (SSE coming in V2.1)`,group:`BEHAVIOR`,tier:`pro`,options:[t,{flag:`--window <w>`,description:`24h | 7d | 30d | 90d`,default:`24h`},{flag:`--limit <n>`,description:`Max errors to fetch`,default:100},{flag:`--search <q>`,description:`Filter by class or message substring`},{flag:`--watch`,description:`Auto-refresh every 30s`},...r]},{name:`funnels`,description:`List available funnels (Pro+)`,group:`BEHAVIOR`,tier:`pro`,options:[t,...r]},{name:`funnel`,description:`Funnel drop-off chart for a specific funnel (Pro+)`,group:`BEHAVIOR`,tier:`pro`,actions:[`<id>`],options:[t,{flag:`--window <w>`,description:`7d | 30d`,default:`30d`},...r]},{name:`insights`,description:`AI-generated anomaly / trend / recommendation cards (Pro+)`,group:`INTELLIGENCE`,tier:`pro`,options:[t,n]},{name:`companies`,description:`B2B identification feed (Scale+)`,group:`INTELLIGENCE`,tier:`scale`,options:[t,{flag:`--window <w>`,description:`24h | 7d | 30d | 90d`,default:`24h`},{flag:`--limit <n>`,description:`Max rows`,default:100},{flag:`--new-only`,description:`Show only newly identified companies (first-seen in last hour)`},{flag:`--watch`,description:`Auto-refresh every 30s`},...r]},{name:`query`,description:`Restricted SQL REPL over the analytics schema (Scale+)`,group:`INTELLIGENCE`,tier:`scale`,actions:[`[sql]`],options:[t,{flag:`--max-rows <n>`,description:`Cap result row count`,default:1e3},...r]},{name:`ai`,description:`3-mode AI assistant (install / chat / mcp)`,group:`INTELLIGENCE`,tier:`free`,options:[{flag:`--mode <mode>`,description:`install | chat | mcp`},n]},{name:`api-keys`,description:`API key management`,group:`MANAGE`,tier:`free`,actions:[`list`,`create`,`delete`],options:[{flag:`--name <n>`,description:`Human-readable label (create)`},{flag:`--scope <scope>`,description:`read | write (create)`,default:`read`},{flag:`--yes`,description:`Skip confirmation (delete)`},n]},{name:`domains`,description:`Domain (tracked-website) management`,group:`MANAGE`,tier:`free`,actions:[`list`,`add`,`delete`],options:[{flag:`--name <n>`,description:`Friendly project name (add; default: domain itself)`},{flag:`--yes`,description:`Skip confirmation (delete)`},n]},{name:`team`,description:`Team member + invitation management (Pro+)`,group:`MANAGE`,tier:`pro`,actions:[`list`,`invite`,`remove`,`role`],options:[{flag:`--role <role>`,description:`admin | member (invite)`,default:`member`},{flag:`--yes`,description:`Skip confirmation (remove)`},n]},{name:`profile`,description:`Current-user profile`,group:`ACCOUNT`,tier:`free`,actions:[`show`,`edit`],options:[{flag:`--name <n>`,description:`New display name (edit)`},{flag:`--notifications <pref>`,description:`email | none (edit)`},n]},{name:`plans`,description:`Subscription plan management`,group:`ACCOUNT`,tier:`free`,actions:[`info`,`upgrade`,`cancel`,`payment`],options:[{flag:`--yes`,description:"Required for `cancel`"},n]},{name:`billing`,description:"Alias for `plans info`",group:`ACCOUNT`,tier:`free`,options:[n]},{name:`settings`,description:`Get / set user settings`,group:`ACCOUNT`,tier:`free`,actions:[`get`,`set`],options:[n]},{name:`integrations`,description:`Connect / disconnect external integrations (gsc, github)`,group:`ACCOUNT`,tier:`free`,actions:[`list`,`connect`,`disconnect`],options:[{flag:`--yes`,description:`Skip confirmation (disconnect)`},n]},{name:`goals`,description:`Goal management (Pro+)`,group:`ACCOUNT`,tier:`pro`,actions:[`list`,`create`,`delete`],options:[{flag:`--name <n>`,description:`Goal name (create)`},{flag:`--type <t>`,description:`pageview | event (create)`},{flag:`--target <v>`,description:`URL pattern or event name (create)`},{flag:`--yes`,description:`Skip confirmation (delete)`},n]},{name:`notes`,description:`Annotation / note management`,group:`ACCOUNT`,tier:`free`,actions:[`list`,`create`,`delete`],options:[{flag:`--content <text>`,description:`Note body (create)`},{flag:`--site-id <id>`,description:`Attach to a specific site (create; defaults to current)`},{flag:`--yes`,description:`Skip confirmation (delete)`},n]},{name:`agency`,description:`Agency client + report management (Scale+)`,group:`ACCOUNT`,tier:`scale`,actions:[`clients list`,`clients add`,`clients remove`,`report send`],options:[{flag:`--email <e>`,description:`Client contact email (clients add)`},{flag:`--name <n>`,description:`Client name (clients add)`},{flag:`--yes`,description:`Skip confirmation (clients remove)`},n]},{name:`usage`,description:`Current month events vs plan limits + headcounts`,group:`ACCOUNT`,tier:`free`,options:[n]},{name:`events tail`,description:`Stream live events`,group:`OPERATIONS`,tier:`free`,options:[{flag:`--site-id <id>`,description:`Site ID`,default:``},{flag:`--filter <expr>`,description:`Filter expression (e.g. 'type=pageview AND country=US')`},{flag:`--forward-to <url>`,description:`POST each event to a webhook with HMAC-SHA256 signature`},{flag:`--replay-24h`,description:`Replay the last 24h before going live`},{flag:`--set-forward-secret <hex>`,description:`Persist the HMAC secret used by --forward-to`},n]},{name:`deploys`,description:`Recent GitHub commits overlaid on charts`,group:`OPERATIONS`,tier:`free`,options:[t,{flag:`--branch <name>`,description:`Filter to a single branch (e.g. main, develop)`},{flag:`--since <iso>`,description:`Only commits after this ISO timestamp`},{flag:`--limit <n>`,description:`Max rows`,default:50},{flag:`--connect`,description:`Print the GitHub-integration deep link in app.zenovay.com`},...r]},{name:`webhooks forward`,description:`Forward webhook events to a local URL (stripe-listen-style)`,group:`OPERATIONS`,tier:`free`,options:[{flag:`--to <url>`,description:`Local URL to POST events to (e.g. localhost:3000/webhook)`},t,{flag:`--sign`,description:`HMAC-sign each forwarded request with X-Zenovay-Signature`},{flag:`--secret <hex>`,description:`HMAC secret (auto-derived from tunnel key if --sign without --secret)`},{flag:`--max-retries <n>`,description:`Per-request retry count`,default:3}]},{name:`projects`,description:`List your tracked projects`,group:`OPERATIONS`,tier:`free`,options:[t,...r]},{name:`use`,description:`Set / show / reset your default site (used when --site-id is omitted)`,group:`OPERATIONS`,tier:`free`,actions:[`[site]`],options:[{flag:`--reset`,description:`Clear the stored default site`},{flag:`--show`,description:`Print the current default and exit`},n]},{name:`init`,description:`AI install wizard — add Zenovay tracking to your codebase`,group:`OPERATIONS`,tier:`free`,options:[{flag:`--json`,description:`Emit NDJSON events to stdout`},{flag:`--yes`,description:`Auto-approve all diffs (for CI)`},{flag:`--skip-mcp`,description:`Skip MCP client install`},{flag:`--skip-verify`,description:`Skip first-event verification`}]},{name:`login`,description:`Authenticate via OAuth device flow`,group:`OPERATIONS`,tier:`free`,options:[n,{flag:`--no-browser`,description:`Skip opening the browser automatically`}]},{name:`logout`,description:`Revoke current session and delete local auth`,group:`OPERATIONS`,tier:`free`,options:[n]},{name:`health`,description:`Run self-diagnostic checks`,group:`OPERATIONS`,tier:`free`,options:[n]},{name:`doctor`,description:`AI-assisted self-healing + AI-agent detection`,group:`OPERATIONS`,tier:`free`,options:[n]},{name:`update`,description:`Manually install the latest version`,group:`OPERATIONS`,tier:`free`,options:[{flag:`--check`,description:`Don't install — just print latest`},{flag:`--force-downgrade`,description:`Allow downgrading to an older version`},{flag:`--no-update-check`,description:`Disable auto-update for this invocation`},n]},{name:`themes`,description:`List available themes with colored swatches`,group:`OPERATIONS`,tier:`free`,options:[{flag:`--validate <path>`,description:`Validate a custom theme JSON file`},n]},{name:`completions`,description:`Emit shell-completion script (bash | zsh | fish | nushell | pwsh)`,group:`OPERATIONS`,tier:`free`,actions:[`[shell]`],options:[{flag:`--list`,description:`List supported shells`}]},{name:`commands`,description:`Dump the full command tree as JSON (for AI-agent discovery)`,group:`OPERATIONS`,tier:`free`,options:[n]}];async function a(t){let n={version:t.cliVersion,commands:i},r=e({json:t.json}),a=JSON.stringify(n,null,r?0:2);return process.stdout.write(a+`
2
- `),0}export{a as commandsCommand};
@@ -1,2 +0,0 @@
1
- import{readConfig as e}from"./config--JRu_jFq.js";import"./api-hWp9s3Y8.js";import{readToken as t}from"./token-store-BQuGH0z2.js";import"./error-codes-D4XO4okw.js";import"./telemetry-BJbpxgIp.js";import{ApiV2Client as n}from"./api-v2-C82L-ZOL.js";import{formatTabular as r,selectFormat as i}from"./formatter-DDG2TSOz.js";import{openInBrowser as a}from"./open-url-CTfSApWl.js";import"./client-I4GTcUcm.js";import"./theme-BuGrQHax.js";import{useTheme as o}from"./panel-B-XxdP-N.js";import"./banner-DdgwXGzt.js";import"./prompt-CJw_Mqo2.js";import"./keybar-QgnmSion.js";import"./chat-panel-DS-FxXoL.js";import{resolveSiteId as s}from"./resolve-site-GDYx0__E.js";import{DataTable as c}from"./data-table-DJzT7bAr.js";import{deepLinkFor as l}from"./keybar-deep-link-DbmPjAEz.js";import{runAnalyticalScreen as u}from"./analytical-screen-DM7SBY5U.js";import{Box as d,Text as f}from"ink";import p from"react";function m(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 h(e){return e==null?`—`:e>=500?`Enterprise`:e>=50?`Growth`:`SMB`}function g({data:e,window:t}){let{theme:n}=o(),r=e.companies.filter(e=>e.isNew).length,i=e.companies.filter(e=>(e.employeeCount??0)>=500).length;return p.createElement(d,{flexDirection:`column`},p.createElement(f,null,p.createElement(f,{bold:!0},e.total),p.createElement(f,{color:n.muted},` companies in `,t)),p.createElement(f,{color:n.muted},p.createElement(f,{color:n.success},`● `,r,` new`),` · `,i,` enterprise`))}function _({data:e,newOnly:t,columns:n}){let{theme:r}=o(),i=t?e.companies.filter(e=>e.isNew):e.companies;return i.length===0?p.createElement(f,{color:r.muted},`— no `,t?`new `:``,`companies in window —`):p.createElement(c,{data:i.slice(0,30),columns:n,headerStyle:`accent`})}async function v(o){let c=await e(),d=await t({strict:!1}),f=new n({config:c,cliVersion:o.cliVersion,token:d}),v,y;try{({siteId:v,site:y}=await s(f,{explicit:o.siteId,headless:!!(o.json||o.csv||o.tsv||o.ndjson),cliVersion:o.cliVersion}))}catch(e){return process.stderr.write(`${e.message}\n`),2}let b=i(o),x=o.window??`24h`,S=o.limit??100,C=[{key:`lastSeenAt`,label:`when`,width:6,format:e=>m(String(e))},{key:`name`,label:`company`,width:24,format:e=>String(e).slice(0,24)},{key:`employeeCount`,label:`tier`,width:11,format:e=>h(typeof e==`number`?e:null)},{key:`industry`,label:`industry`,width:18,format:e=>String(e??`—`).slice(0,18)},{key:`visitCount`,label:`visits`,width:6,align:`right`},{key:`isNew`,label:``,width:5,format:e=>e?`NEW`:``}];return u({cliVersion:o.cliVersion,title:`companies · ${v} · ${x}`,commandName:`companies`,ai:{api:f,siteId:v,siteLabel:y?.url?y.url.replace(/^https?:\/\//,``).replace(/\/$/,``):y?.name??v},authToken:d?.accessToken??null,refreshIntervalMs:o.watch?3e4:0,fetcher:e=>f.getCompaniesSnapshot(v,{window:x,limit:S},e),format:b,keybindings:{o:{label:`open in browser`,handler:()=>{a(l(`companies`,{siteId:v}))}}},headlessEmit:(e,t)=>{let n=o.newOnly?e.companies.filter(e=>e.isNew):e.companies;if(t===`json`||t===`ndjson`){if(t===`ndjson`)for(let e of n)process.stdout.write(JSON.stringify(e)+`
2
- `);else process.stdout.write(JSON.stringify({companies:n,total:n.length},null,2));return}process.stdout.write(r(n,[`name`,`domain`,`industry`,`employeeCount`,`visitCount`,`firstSeenAt`,`lastSeenAt`,`isNew`],t))},panels:[{id:`summary`,title:`Now`,render:e=>p.createElement(g,{data:e,window:x})},{id:`feed`,title:`Feed`,render:e=>p.createElement(_,{data:e,newOnly:!!o.newOnly,columns:C})}]})}export{v as companiesCommand};
@@ -1 +0,0 @@
1
- import{formatTabular as e}from"./formatter-DDG2TSOz.js";function t(t,n,r){return e(t,n,r)}function n(e,n,r){return process.stdout.write(t(e,n,r)),0}export{t as toCsv,n as writeCsv};
@@ -1 +0,0 @@
1
- import"./formatter-DDG2TSOz.js";import{toCsv as e,writeCsv as t}from"./csv-emit-BWWv60mT.js";export{t as writeCsv};
@@ -1 +0,0 @@
1
- import{useTheme as e}from"./panel-B-XxdP-N.js";import{Box as t,Text as n}from"ink";import r from"react";function i(e,t){return e.length<=t?e:t<=1?e.slice(0,t):`${e.slice(0,t-1)}…`}function a(e,t,n){if(e.length>=t)return i(e,t);let r=t-e.length;return n===`right`?` `.repeat(r)+e:e+` `.repeat(r)}function o(e){return e.label??e.header??``}function s(e,t){return e.map(e=>{if(typeof e.width==`number`&&e.width>0)return e.width;let n=o(e).length;for(let r of t){let t=r[e.key],i=e.format?e.format(t,r):String(t??``);i.length>n&&(n=i.length)}return Math.max(3,n)})}function c({columns:i,data:c,zebra:l=!1,headerStyle:u=`plain`}){let{theme:d}=e(),f=s(i,c),p=f.reduce((e,t)=>e+t,0)+i.length*3+1,m=(e,t,n)=>{let r=e;return f.forEach((e,i)=>{r+=`─`.repeat(e+2),r+=i===f.length-1?n:t}),r},h=m(`╭`,`┬`,`╮`),g=m(`├`,`┼`,`┤`),_=m(`╰`,`┴`,`╯`),v=i.map((e,t)=>a(o(e),f[t]??o(e).length,e.align??`left`)).join(` │ `),y=u===`accent`?d.accent:d.fg;return r.createElement(t,{flexDirection:`column`,width:p},r.createElement(n,{color:d.border},h),r.createElement(t,{flexDirection:`row`},r.createElement(n,{color:d.border},`│ `),r.createElement(n,{color:y,bold:!0},v),r.createElement(n,{color:d.border},` │`)),r.createElement(n,{color:d.border},g),c.map((e,o)=>{let s=l&&o%2==1,c=s?d.muted:d.fg,u=i.map((t,n)=>{let r=e[t.key],i=t.format?t.format(r,e):String(r??``);return a(i,f[n]??i.length,t.align??`left`)}).join(` │ `);return r.createElement(t,{key:o,flexDirection:`row`},r.createElement(n,{color:d.border},`│ `),r.createElement(n,{color:c},u),r.createElement(n,{color:d.border},` │`))}),r.createElement(n,{color:d.border},_))}export{c as DataTable};
@@ -1,2 +0,0 @@
1
- import{readConfig as e}from"./config--JRu_jFq.js";import"./api-hWp9s3Y8.js";import{readToken as t}from"./token-store-BQuGH0z2.js";import"./error-codes-D4XO4okw.js";import"./telemetry-BJbpxgIp.js";import{ApiV2Client as n}from"./api-v2-C82L-ZOL.js";import{formatTabular as r,selectFormat as i}from"./formatter-DDG2TSOz.js";import"./client-I4GTcUcm.js";import"./theme-BuGrQHax.js";import{useTheme as a}from"./panel-B-XxdP-N.js";import"./banner-DdgwXGzt.js";import"./prompt-CJw_Mqo2.js";import"./keybar-QgnmSion.js";import"./chat-panel-DS-FxXoL.js";import{resolveSiteId as o}from"./resolve-site-GDYx0__E.js";import{DataTable as s}from"./data-table-DJzT7bAr.js";import{runAnalyticalScreen as c}from"./analytical-screen-DM7SBY5U.js";import{Box as l,Text as u}from"ink";import d from"react";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(a){if(a.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 s=await e(),l=await t({strict:!1}),u=new n({config:s,cliVersion:a.cliVersion,token:l}),p,g;try{({siteId:p,site:g}=await o(u,{explicit:a.siteId,headless:!!(a.json||a.csv||a.tsv||a.ndjson),cliVersion:a.cliVersion}))}catch(e){return process.stderr.write(`${e.message}\n`),2}let _=i(a),v=a.limit??50,y=[{key:`pushed_at`,label:`when`,width:6,format:e=>f(String(e))},{key:`branch`,label:`branch`,width:14,format:e=>String(e??`—`).slice(0,14)},{key:`commit_sha`,label:`commit`,width:9,format:e=>String(e).slice(0,8)},{key:`commit_author`,label:`author`,width:16,format:e=>String(e??`—`).slice(0,16)},{key:`commit_message`,label:`message`,width:40,format:e=>String(e??`—`).slice(0,40)},{key:`show_on_chart`,label:`chart`,width:5,format:e=>e?`●`:`○`}];return c({cliVersion:a.cliVersion,title:`deploys · ${p}`,commandName:`deploys`,ai:{api:u,siteId:p,siteLabel:g?.url?g.url.replace(/^https?:\/\//,``).replace(/\/$/,``):g?.name??p},authToken:l?.accessToken??null,refreshIntervalMs:0,fetcher:e=>u.getDeploys(p,{branch:a.branch,since:a.since,limit:v},e),format:_,headlessEmit:(e,t)=>{if(t===`json`||t===`ndjson`){if(t===`ndjson`)for(let t of e.deploys)process.stdout.write(JSON.stringify(t)+`
2
- `);else process.stdout.write(JSON.stringify(e,null,2));return}process.stdout.write(r(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=>d.createElement(m,{data:e,branch:a.branch})},{id:`list`,title:`Recent`,render:e=>d.createElement(h,{data:e,columns:y})}]})}const m=({data:e,branch:t})=>{let{theme:n}=a(),r=e.deploys.filter(e=>e.show_on_chart).length,i=new Set(e.deploys.map(e=>e.repository).filter(e=>!!e));return d.createElement(l,{flexDirection:`column`},d.createElement(u,null,d.createElement(u,{bold:!0},e.total),d.createElement(u,{color:n.muted},` commits`,t?` · branch=${t}`:``)),d.createElement(u,{color:n.muted},d.createElement(u,{color:n.accent},`● `,r,` on chart`),d.createElement(u,null,` · `),d.createElement(u,null,i.size,` `,i.size===1?`repo`:`repos`)))},h=({data:e,columns:t})=>{let{theme:n}=a();return e.deploys.length===0?d.createElement(l,{flexDirection:`column`},d.createElement(u,{color:n.muted},`— no commits yet —`),d.createElement(u,{color:n.dim},"Run `zenovay deploys --connect` to wire up the GitHub integration.")):d.createElement(s,{data:e.deploys.slice(0,30),columns:t,headerStyle:`accent`})};export{p as deploysCommand};
@@ -1,2 +0,0 @@
1
- import{readConfig as e}from"./config--JRu_jFq.js";import"./api-hWp9s3Y8.js";import{readToken as t}from"./token-store-BQuGH0z2.js";import{ApiV2Client as n}from"./api-v2-C82L-ZOL.js";import"./formatter-DDG2TSOz.js";import{emit as r,isHeadless as i}from"./emit-NkY7PE3R.js";import{openInBrowser as a}from"./open-url-CTfSApWl.js";import"./theme-BuGrQHax.js";import{Panel as o,useTheme as s}from"./panel-B-XxdP-N.js";import{Banner as c}from"./banner-DdgwXGzt.js";import"./prompt-CJw_Mqo2.js";import{Keybar as l}from"./keybar-QgnmSion.js";import{resolveSiteId as u}from"./resolve-site-GDYx0__E.js";import{DataTable as d}from"./data-table-DJzT7bAr.js";import{EmptyState as f}from"./empty-state-DbToIL5T.js";import{deepLinkFor as p}from"./keybar-deep-link-DbmPjAEz.js";import{Box as m,Text as h,render as g,useApp as _,useInput as v}from"ink";import y,{useEffect as b,useState as x}from"react";import S from"ink-spinner";async function C(a){let o=await e(),s=await t({strict:!1});if(!s)return process.stderr.write("Not logged in — run `zenovay login` first.\n"),2;let c=new n({config:o,cliVersion:a.cliVersion,token:s}),l,d;try{({siteId:l,site:d}=await u(c,{explicit:a.siteId,headless:!!a.json,cliVersion:a.cliVersion}))}catch(e){return process.stderr.write(`${e.message}\n`),2}let f=d?.url?d.url.replace(/^https?:\/\//,``).replace(/\/$/,``):d?.name??l;if(i(a)){let e=await c.getDevices(l);if(a.csv||a.tsv){let{writeCsv:t}=await import(`./csv-emit-CVO5kebZ.js`);return t(e.devices,[`name`,`visitors`],a.tsv?`tsv`:`csv`)}if(a.ndjson){for(let t of e.devices)process.stdout.write(JSON.stringify(t)+`
2
- `);return 0}return r({type:`devices.snapshot`,data:e}),0}return new Promise(e=>{let{unmount:t}=g(y.createElement(w,{api:c,siteId:l,siteLabel:f,cliVersion:a.cliVersion,onExit:n=>{t(),e(n)}}))})}const w=({api:e,siteId:t,siteLabel:n,cliVersion:r,onExit:i})=>{let{exit:u}=_(),{theme:g}=s(),[C,w]=x(null),[T,E]=x(!0),[D,O]=x(null);if(v(e=>{if(e===`o`||e===`O`){a(p(`devices`,{siteId:t}));return}e===`q`&&(u(),i(0))}),b(()=>{let n=!1;return(async()=>{try{let r=await e.getDevices(t);n||(w(r),E(!1))}catch(e){n||(O(e.message),E(!1))}})(),()=>{n=!0}},[e,t]),T)return y.createElement(m,{flexDirection:`column`},y.createElement(c,{version:r,subtitle:`devices · ${n}`}),y.createElement(o,{title:`Loading`,state:`busy`},y.createElement(m,null,y.createElement(h,{color:g.accent},y.createElement(S,{type:`dots`})),y.createElement(h,null,` Fetching breakdown…`))));if(D)return y.createElement(m,{flexDirection:`column`},y.createElement(c,{version:r,subtitle:`devices · ${n}`}),y.createElement(f,{reason:`error`,headline:`Failed to load`,hint:D}));let k=!C||C.devices.length===0&&C.browsers.length===0&&C.os.length===0;if(k)return y.createElement(m,{flexDirection:`column`},y.createElement(c,{version:r,subtitle:`devices · ${n}`}),y.createElement(f,{reason:`no-data`,headline:`No data yet`,hint:`Visit your site to send the first event`}));let A=[{key:`name`,label:`name`,width:16},{key:`visitors`,label:`visitors`,align:`right`,width:8}];return y.createElement(m,{flexDirection:`column`},y.createElement(c,{version:r,subtitle:`devices · ${n}`}),y.createElement(m,{flexDirection:`row`},y.createElement(o,{title:`Devices`},C.devices.length===0?y.createElement(h,{color:g.dim},`— —`):y.createElement(d,{columns:A,data:C.devices,zebra:!0})),y.createElement(o,{title:`Browsers`},C.browsers.length===0?y.createElement(h,{color:g.dim},`— —`):y.createElement(d,{columns:A,data:C.browsers,zebra:!0})),y.createElement(o,{title:`OS`},C.os.length===0?y.createElement(h,{color:g.dim},`— —`):y.createElement(d,{columns:A,data:C.os,zebra:!0}))),y.createElement(l,{items:[{key:`o`,label:`open in browser`},{key:`q`,label:`quit`}]}))};export{C as devicesCommand};
@@ -1 +0,0 @@
1
- import{useTheme as e}from"./panel-B-XxdP-N.js";import{Box as t,Text as n}from"ink";import r from"react";const i={"no-data":`○`,"tier-gated":`◆`,error:`✗`},a=`https://app.zenovay.com/billing`;function o({headline:o,hint:s,reason:c=`no-data`,cta:l,width:u}){let{theme:d}=e(),f=i[c],p=c===`error`?d.error:c===`tier-gated`?d.accent2:d.muted,m=l??(c===`tier-gated`?`Upgrade → ${a}`:void 0);return r.createElement(t,{flexDirection:`column`,alignItems:`center`,width:u},r.createElement(n,{color:p,bold:!0},f),r.createElement(n,{color:d.typography.title.color,bold:d.typography.title.bold},o),s?r.createElement(n,{color:d.dim},s):null,m?r.createElement(n,{color:d.accent},m):null)}export{o as EmptyState};
@@ -1 +0,0 @@
1
- import"./config--JRu_jFq.js";import"./api-hWp9s3Y8.js";import"./token-store-BQuGH0z2.js";import{buildErrorEnvelope as e,emitErrorEnvelope as t,isJsonOutputMode as n,normalizeError as r}from"./error-codes-D4XO4okw.js";export{t as emitErrorEnvelope};
@@ -1,2 +0,0 @@
1
- import{readConfig as e}from"./config--JRu_jFq.js";import"./api-hWp9s3Y8.js";import{readToken as t}from"./token-store-BQuGH0z2.js";import"./error-codes-D4XO4okw.js";import"./telemetry-BJbpxgIp.js";import{ApiV2Client as n}from"./api-v2-C82L-ZOL.js";import{formatTabular as r,selectFormat as i}from"./formatter-DDG2TSOz.js";import{openInBrowser as a}from"./open-url-CTfSApWl.js";import"./client-I4GTcUcm.js";import"./theme-BuGrQHax.js";import{useTheme as o}from"./panel-B-XxdP-N.js";import"./banner-DdgwXGzt.js";import"./progress-row-5ns2IsFh.js";import"./prompt-CJw_Mqo2.js";import"./keybar-QgnmSion.js";import{spark as s}from"./sparkline-CpoBjjlc.js";import"./chat-panel-DS-FxXoL.js";import{resolveSiteId as c}from"./resolve-site-GDYx0__E.js";import{DataTable as l}from"./data-table-DJzT7bAr.js";import"./bar-C1Zrfe9H.js";import{deepLinkFor as u}from"./keybar-deep-link-DbmPjAEz.js";import{runAnalyticalScreen as d}from"./analytical-screen-DM7SBY5U.js";import"./ui-whccLLRv.js";import{Box as f,Text as p}from"ink";import m from"react";function h(e,t){return e.length<=t?e:e.slice(0,t-1)+`…`}function g(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`}const _=({filtered:e,window:t})=>{let{theme:n}=o(),r=new Map,i=Date.now(),a=60;for(let t of e){let e=new Date(t.ts).getTime(),n=Math.floor((i-e)/(60*1e3));if(n<0||n>=a)continue;let o=r.get(t.class)??Array(a).fill(0),s=a-1-n;o[s]+=1,r.set(t.class,o)}let c=[...r.entries()].sort((e,t)=>t[1].reduce((e,t)=>e+t,0)-e[1].reduce((e,t)=>e+t,0)).slice(0,6);return m.createElement(f,{flexDirection:`column`},m.createElement(p,null,m.createElement(p,{bold:!0},e.length),m.createElement(p,{color:n.muted},` errors in `,t)),c.length===0?null:m.createElement(f,{flexDirection:`column`,marginTop:1},c.map(([e,t])=>m.createElement(p,{key:e},m.createElement(p,{color:n.accent},e.padEnd(20).slice(0,20)),` `,m.createElement(p,{color:n.accent},s(t,30))))))},v=({filtered:e,search:t,columns:n})=>{let{theme:r}=o();return e.length===0?m.createElement(p,{color:r.dim},`— no errors `,t?`matching "${t}"`:`in window`,` —`):m.createElement(l,{data:e.slice(0,30),columns:n,headerStyle:`accent`})};async function y(o){let s=await e(),l=await t({strict:!1}),f=new n({config:s,cliVersion:o.cliVersion,token:l}),p,y;try{({siteId:p,site:y}=await c(f,{explicit:o.siteId,headless:!!(o.json||o.csv||o.tsv||o.ndjson),cliVersion:o.cliVersion}))}catch(e){return process.stderr.write(`${e.message}\n`),2}let b=i(o),x=o.window??`24h`,S=o.limit??100,C=[{key:`ts`,label:`when`,width:6,format:e=>g(String(e))},{key:`class`,label:`class`,width:18,format:e=>String(e)},{key:`message`,label:`message`,width:42,format:e=>h(String(e??``),42)},{key:`page`,label:`page`,width:24,format:e=>String(e??`—`)},{key:`device`,label:`device`,width:8,format:e=>String(e??`—`)}];return d({cliVersion:o.cliVersion,title:`errors · ${p} · ${x}`,commandName:`errors`,ai:{api:f,siteId:p,siteLabel:y?.url?y.url.replace(/^https?:\/\//,``).replace(/\/$/,``):y?.name??p},authToken:l?.accessToken??null,refreshIntervalMs:o.watch?3e4:0,fetcher:e=>f.getErrors(p,{window:x,limit:S},e),format:b,keybindings:{o:{label:`open in browser`,handler:()=>{a(u(`errors`,{siteId:p}))}}},headlessEmit:(e,t)=>{let n=o.search?e.errors.filter(e=>e.class.toLowerCase().includes(o.search.toLowerCase())||e.message.toLowerCase().includes(o.search.toLowerCase())):e.errors;if(t===`json`||t===`ndjson`){if(t===`ndjson`)for(let e of n)process.stdout.write(JSON.stringify(e)+`
2
- `);else process.stdout.write(JSON.stringify({errors:n,total:n.length},null,2));return}process.stdout.write(r(n,[`ts`,`class`,`message`,`page`,`device`,`fingerprint`],t))},panels:[{id:`summary`,title:`Recent errors`,render:e=>{let t=o.search?e.errors.filter(e=>e.class.toLowerCase().includes(o.search.toLowerCase())||e.message.toLowerCase().includes(o.search.toLowerCase())):e.errors;return m.createElement(_,{filtered:t,window:x})}},{id:`table`,title:`Detail`,render:e=>{let t=o.search?e.errors.filter(e=>e.class.toLowerCase().includes(o.search.toLowerCase())||e.message.toLowerCase().includes(o.search.toLowerCase())):e.errors;return m.createElement(v,{filtered:t,search:o.search,columns:C})}}]})}export{y as errorsCommand};
@@ -1,5 +0,0 @@
1
- import{readConfig as e,updateConfig as t}from"./config--JRu_jFq.js";import{ApiClient as n}from"./api-hWp9s3Y8.js";import{readToken as r}from"./token-store-BQuGH0z2.js";import"./formatter-DDG2TSOz.js";import{isHeadless as i}from"./emit-NkY7PE3R.js";import{parseSseStream as a}from"./client-I4GTcUcm.js";import"./theme-BuGrQHax.js";import{Panel as o,useTheme as s}from"./panel-B-XxdP-N.js";import{Banner as c}from"./banner-DdgwXGzt.js";import{TextInput as l}from"./prompt-CJw_Mqo2.js";import{Keybar as u}from"./keybar-QgnmSion.js";import d from"node:path";import{promises as f}from"node:fs";import p from"node:os";import m from"node:crypto";import{Box as h,Static as g,Text as _,render as v,useApp as y,useInput as b}from"ink";import x,{useEffect as S,useRef as C,useState as w}from"react";const T=new Set([`type`,`page`,`country`,`device`,`user_id`,`sessionId`,`referrer`,`ts`,`url`,`method`,`status`]);function E(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 D(e){return e.replace(/[.*+?^${}()|[\]\\]/g,`\\$&`)}function O(e,t,n){let r=e==null?``:String(e);switch(t){case`=`:return r===n;case`!=`:return r!==n;case`~`:{let e=new RegExp(D(n),`i`);return e.test(r)}case`!~`:{let e=new RegExp(D(n),`i`);return!e.test(r)}}}function k(e){return e.tokens[e.pos]}function A(e){let t=e.tokens[e.pos];return e.pos+=1,t}function j(e){let t=k(e);if(!t)throw Error(`filter: unexpected end of expression`);if(t.kind===`lparen`){A(e);let t=M(e),n=A(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}`);A(e);let n=t.value;if(!T.has(n))throw Error(`filter: unknown key "${n}". Allowed: ${[...T].join(`, `)}`);let r=A(e);if(!r||r.kind!==`op`)throw Error(`filter: expected operator after "${n}"`);let i=A(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=>O(e[n],a,o)}function M(e){let t=j(e);for(;;){let n=k(e);if(!n)break;if(n.kind===`and`){A(e);let n=j(e),r=t;t=e=>r(e)&&n(e);continue}if(n.kind===`or`){A(e);let n=j(e),r=t;t=e=>r(e)||n(e);continue}break}return t}function N(e){if(typeof e!=`string`||e.trim().length===0)throw Error(`filter: expression is empty`);let t=E(e);if(t.length===0)throw Error(`filter: expression is empty`);let n={tokens:t,pos:0},r=M(n);if(n.pos!==t.length){let e=n.tokens[n.pos];throw Error(`filter: unexpected trailing token "${P(e)}"`)}return r}function P(e){return e.kind===`ident`||e.kind===`string`||e.kind===`op`?e.value:e.kind}const F=10*1024*1024;var I=class{currentBytes=0;initialized=!1;writeQueue=Promise.resolve();constructor(e,t=F){this.filePath=e,this.maxBytes=t}async init(){if(!this.initialized){this.initialized=!0;try{await f.mkdir(d.dirname(this.filePath),{recursive:!0,mode:448})}catch{}try{let e=await f.stat(this.filePath);this.currentBytes=e.size}catch{this.currentBytes=0}}}append(e){let t=(async()=>{await this.init();let t=e.endsWith(`
2
- `)?e:`${e}\n`,n=Buffer.byteLength(t,`utf8`);this.currentBytes+n>this.maxBytes&&await this.rotate();try{await f.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=d.parse(this.filePath);return d.join(t.dir,`${t.name}.${e}${t.ext}`)};try{await f.unlink(e(3))}catch{}for(let t=2;t>=0;--t)try{await f.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 L=5e3,R=33,z=`─── replay end, live below ───`;async function B(a){if(a.setForwardSecret)return await t({forwardSecret:a.setForwardSecret}),process.stdout.write(`Forward secret saved.
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:a.cliVersion,token:s}),l=null;if(a.filter)try{l=N(a.filter)}catch(e){return process.stderr.write(`Invalid --filter expression: ${e.message}\n`),2}if(i(a))return U(c,a,l,o.forwardSecret);let u=a.scrollbackPath??d.join(p.homedir(),`.zenovay`,`events-scrollback.log`);return new Promise(e=>{let{unmount:t}=v(x.createElement(W,{api:c,opts:a,predicate:l,forwardSecret:o.forwardSecret,scrollbackPath:u,onExit:n=>{t(),e(n)}}))})}function V(e){return{raw:JSON.stringify(e),parsed:e}}async function H(e,t,n){let r=JSON.stringify(n),i=m.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 U(e,t,n,r){let i=new AbortController;process.on(`SIGINT`,()=>i.abort());let o=()=>new Date().toISOString();try{let s=await e.openEventsStream(t.siteId,i.signal);for await(let e of a(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 H(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 W=({api:e,opts:t,predicate:n,forwardSecret:r,scrollbackPath:i,onExit:d})=>{let{theme:p}=s(),{exit:m}=y(),v=C([]),T=C(null),[E,D]=w([]),[O,k]=w(null),[A,j]=w(!1),[M,N]=w(null);T.current||=new I(i),b(n=>{if(!A){if(O){k(null);return}if(n===`q`){m(),d(0);return}if(n===`f`){let e=v.current[v.current.length-1];e&&k(e);return}if(n===`w`){j(!0);return}if(n===`r`){K(e,t.siteId,v,N);return}}}),S(()=>{let e=setInterval(()=>{let e=v.current.slice(-100);D(e)},R);return()=>clearInterval(e)},[]),S(()=>{let i=new AbortController,o=!1;return(async()=>{t.replay24h&&await K(e,t.siteId,v,N);try{let s=await e.openEventsStream(t.siteId,i.signal);for await(let e of a(s)){if(o)break;if(e.type===`error`){let t={raw:`[ERR ${e.code}] ${e.message}`};G(v,t),T.current?.append(t.raw);continue}if(e.type===`done`)break;let i=e;if(n&&!n(i))continue;let a=V(e);G(v,a),T.current?.append(a.raw),t.forwardTo&&r&&H(t.forwardTo,r,{event:e,ts:new Date().toISOString(),site_id:t.siteId})}}catch(e){let t={raw:`[DISCONNECT] ${e.message}`};G(v,t)}})(),()=>{o=!0,i.abort(),T.current?.close()}},[e,t.siteId,t.replay24h,t.forwardTo,n,r]);let P=async e=>{let t=e.trim()||`events.ndjson`;try{let e=v.current.map(e=>e.raw).join(`
4
- `)+`
5
- `;await f.writeFile(t,e,{mode:384}),N(`Wrote ${v.current.length} events → ${t}`)}catch(e){N(`Write failed: ${e.message}`)}j(!1)};return x.createElement(h,{flexDirection:`column`},x.createElement(c,{version:t.cliVersion,subtitle:`events tail · ${t.siteId}`}),x.createElement(g,{items:E},(e,t)=>x.createElement(_,{key:`v-${t}`,color:e.marker?p.accent:void 0},e.raw)),O?x.createElement(o,{title:`Frozen event (press any key to resume)`,state:`warn`},x.createElement(_,null,O.parsed?JSON.stringify(O.parsed,null,2):O.raw)):null,A?x.createElement(o,{title:`Write buffer to NDJSON`,state:`busy`},x.createElement(l,{question:`filename:`,placeholder:`events.ndjson`,onSubmit:P})):null,M?x.createElement(_,{color:p.success},M):null,x.createElement(u,{items:[{key:`f`,label:`freeze`},{key:`w`,label:`write`},{key:`r`,label:`replay 24h`},{key:`q`,label:`quit`}]}))};function G(e,t){e.current.push(t),e.current.length>L&&e.current.splice(0,e.current.length-L)}async function K(e,t,n,r){let i=e.getEventsHistory;if(typeof i==`function`)try{let a=await i.call(e,t,`24h`);if(Array.isArray(a))for(let e of a)G(n,{raw:JSON.stringify(e),parsed:e});G(n,{raw:z,marker:!0}),r(`Replayed ${Array.isArray(a)?a.length:0} events`);return}catch(e){r(`Replay failed: ${e.message}`);return}r(`Replay endpoint coming Wave 1`)}export{B as eventsTailCommand};
@@ -1,4 +0,0 @@
1
- import{readConfig as e}from"./config--JRu_jFq.js";import"./api-hWp9s3Y8.js";import{readToken as t}from"./token-store-BQuGH0z2.js";import{emitErrorEnvelope as n}from"./error-codes-D4XO4okw.js";import{ApiV2Client as r}from"./api-v2-C82L-ZOL.js";import{requireTier as i}from"./tier-C4q8fJ8m.js";import"./formatter-DDG2TSOz.js";import{emitEnvelope as a,wrapItem as o}from"./emit-NkY7PE3R.js";import"./theme-BuGrQHax.js";import"./panel-B-XxdP-N.js";import"./banner-DdgwXGzt.js";import"./prompt-CJw_Mqo2.js";import{resolveSiteId as s}from"./resolve-site-GDYx0__E.js";import{toCsv as c}from"./csv-emit-BWWv60mT.js";import{resolve as l}from"node:path";import{writeFile as u}from"node:fs/promises";function d(e){let t=(e??`30d`).toLowerCase();return t===`7d`||t===`30d`||t===`90d`?t:`30d`}function f(e,t){t||process.stderr.isTTY&&process.stderr.write(`${e}\n`)}async function p(c){let p=await e(),g=await t({strict:!1}),_=new r({config:p,cliVersion:c.cliVersion,token:g});if(c.type!==`analytics`&&c.type!==`sessions`&&c.type!==`heatmaps`){let e=`Unknown export type '${c.type}'. Use one of: analytics, sessions, heatmaps.`;return c.json?n(Error(e),{command:`export`,cliVersion:c.cliVersion}):(process.stderr.write(`Error: ${e}\n`),2)}let v=c.format??`csv`;if(v!==`csv`&&v!==`json`){let e=`Unknown export format '${v}'. Use one of: csv, json.`;return c.json?n(Error(e),{command:`export ${c.type}`,cliVersion:c.cliVersion}):(process.stderr.write(`Error: ${e}\n`),2)}let y=v,b=d(c.range),x=!!c.json;if(c.type===`sessions`||c.type===`heatmaps`)try{await i(_,`pro`)}catch(e){return c.json?n(e,{command:`export ${c.type}`,cliVersion:c.cliVersion}):(process.stderr.write(`${e.message}\n`),2)}let S;try{({siteId:S}=await s(_,{explicit:c.siteId,headless:x,cliVersion:c.cliVersion}))}catch(e){return c.json?n(e,{command:`export ${c.type}`,cliVersion:c.cliVersion}):(process.stderr.write(`${e.message}\n`),2)}try{f(`→ Fetching ${c.type} ${b}...`,x);let{rows:e,columns:t}=await m(_,c.type,S,b),n=h(e,t,y),r=c.out?l(process.cwd(),c.out):null;return r?(await u(r,n,`utf8`),c.json?(a(o({rowsWritten:e.length,file:r,format:y,range:b,type:c.type},`export.completed`,{siteId:S,command:`export ${c.type}`,cliVersion:c.cliVersion})),0):(process.stdout.write(`✓ Exported ${e.length} rows to ${r}\n`),0)):(process.stdout.write(n),n.endsWith(`
2
- `)||process.stdout.write(`
3
- `),c.json&&a(o({rowsWritten:e.length,file:null,format:y,range:b,type:c.type},`export.completed`,{siteId:S,command:`export ${c.type}`,cliVersion:c.cliVersion})),0)}catch(e){return c.json?n(e,{command:`export ${c.type}`,cliVersion:c.cliVersion}):(process.stderr.write(`✗ ${e.message}\n`),1)}}async function m(e,t,n,r){if(t===`analytics`){let t=await e.getStats(n,r);if(t.daily&&t.daily.length>0){let e=t.daily.map(e=>({date:e.date,visitors:e.visitors,pageviews:e.pageviews}));return{rows:e,columns:[`date`,`visitors`,`pageviews`]}}let i=[{range:r,visitors:t.visitors,pageviews:t.pageviews,sessions:t.sessions,bounceRate:t.bounceRate,avgSessionSec:t.avgSessionSec,windowStart:t.windowStart,windowEnd:t.windowEnd}];return{rows:i,columns:[`range`,`visitors`,`pageviews`,`sessions`,`bounceRate`,`avgSessionSec`,`windowStart`,`windowEnd`]}}if(t===`sessions`){let t=await e.getSessions(n),r=t.map(e=>({id:e.id,visitor:e.visitor,durationMs:e.duration,startedAt:e.startedAt,pageCount:e.pageCount,deviceType:e.deviceType??``}));return{rows:r,columns:[`id`,`visitor`,`durationMs`,`startedAt`,`pageCount`,`deviceType`]}}let i=await e.getHeatmaps(n),a=i.map(e=>({id:e.id,url:e.url,type:e.type,captureCount:e.captureCount,createdAt:e.createdAt}));return{rows:a,columns:[`id`,`url`,`type`,`captureCount`,`createdAt`]}}function h(e,t,n){if(n===`json`){let n=e.map(e=>{let n={};for(let r of t)n[String(r)]=e[r];return n});return JSON.stringify(n,null,2)+`
4
- `}return c(e,t,`csv`)}export{p as exportCommand};
@@ -1,3 +0,0 @@
1
- import{readConfig as e}from"./config--JRu_jFq.js";import"./api-hWp9s3Y8.js";import{readToken as t}from"./token-store-BQuGH0z2.js";import"./error-codes-D4XO4okw.js";import"./telemetry-BJbpxgIp.js";import{ApiV2Client as n}from"./api-v2-C82L-ZOL.js";import{formatTabular as r,selectFormat as i}from"./formatter-DDG2TSOz.js";import{openInBrowser as a}from"./open-url-CTfSApWl.js";import"./client-I4GTcUcm.js";import"./theme-BuGrQHax.js";import{useTheme as o}from"./panel-B-XxdP-N.js";import"./banner-DdgwXGzt.js";import"./prompt-CJw_Mqo2.js";import"./keybar-QgnmSion.js";import"./chat-panel-DS-FxXoL.js";import{resolveSiteId as s}from"./resolve-site-GDYx0__E.js";import{DataTable as c}from"./data-table-DJzT7bAr.js";import{deepLinkFor as l}from"./keybar-deep-link-DbmPjAEz.js";import{runAnalyticalScreen as u}from"./analytical-screen-DM7SBY5U.js";import{Box as d,Text as f}from"ink";import p from"react";function m(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 h(o){let d=await e(),f=await t({strict:!1}),m=new n({config:d,cliVersion:o.cliVersion,token:f}),h,x;try{({siteId:h,site:x}=await s(m,{explicit:o.siteId,headless:!!(o.json||o.csv||o.tsv||o.ndjson),cliVersion:o.cliVersion}))}catch(e){return process.stderr.write(`${e.message}\n`),2}let S=i(o);if(!o.funnelId){let e=[{key:`name`,label:`name`,width:30},{key:`stepCount`,label:`steps`,width:6,align:`right`},{key:`id`,label:`id`,width:36,format:e=>String(e).slice(0,36)}];return u({cliVersion:o.cliVersion,title:`funnels · ${h}`,commandName:`funnels`,ai:{api:m,siteId:h,siteLabel:x?.url?x.url.replace(/^https?:\/\//,``).replace(/\/$/,``):x?.name??h},authToken:f?.accessToken??null,refreshIntervalMs:0,fetcher:e=>m.listFunnels(h,e),format:S,keybindings:{o:{label:`open in browser`,handler:()=>{a(l(`funnel`,{siteId:h}))}}},headlessEmit:(e,t)=>{if(t===`json`||t===`ndjson`){process.stdout.write(JSON.stringify(e,null,t===`json`?2:0)),t===`ndjson`&&process.stdout.write(`
2
- `);return}process.stdout.write(r(e.funnels,[`id`,`name`,`stepCount`],t))},panels:[{id:`funnels`,title:`Funnels`,render:t=>t.funnels.length===0?p.createElement(_,null):p.createElement(c,{data:t.funnels,columns:e,headerStyle:`accent`})},{id:`hint`,title:`Next`,render:()=>p.createElement(v,null)}]})}let C=o.window??`30d`;return u({cliVersion:o.cliVersion,title:`funnel · ${o.funnelId} · ${C}`,commandName:`funnel`,ai:{api:m,siteId:h,siteLabel:x?.url?x.url.replace(/^https?:\/\//,``).replace(/\/$/,``):x?.name??h},authToken:f?.accessToken??null,refreshIntervalMs:0,fetcher:e=>m.getFunnel(h,o.funnelId,C,e),format:S,keybindings:{o:{label:`open in browser`,handler:()=>{a(l(`funnel`,{siteId:h}))}}},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
- `);return}process.stdout.write(r(e.steps,[`id`,`name`,`visitors`,`conversions`],t))},panels:[{id:`overview`,title:g(`Overview`),render:e=>p.createElement(y,{data:e})},{id:`flow`,title:`Flow`,render:e=>p.createElement(b,{data:e})}]})}function g(e){return e}function _(){let{theme:e}=o();return p.createElement(f,{color:e.muted},`— no funnels defined —`)}function v(){let{theme:e}=o();return p.createElement(f,{color:e.dim},"Run `zenovay funnel <id>` for drop-off detail.")}function y({data:e}){let{theme:t}=o();return p.createElement(d,{flexDirection:`column`},p.createElement(f,{bold:!0},e.name),p.createElement(f,{color:t.muted},e.totalEntries.toLocaleString(),` entries · `,e.totalCompletions.toLocaleString(),` completed (`,(e.conversionRate*100).toFixed(1),`%)`))}function b({data:e}){let{theme:t}=o(),n=e.totalEntries||1;return p.createElement(d,{flexDirection:`column`},e.steps.map((r,i)=>{let a=r.visitors/n,o=e.steps[i-1],s=o?o.visitors-r.visitors:0,c=o?s/Math.max(1,o.visitors)*100:0;return p.createElement(d,{key:r.id,flexDirection:`column`},o?p.createElement(f,{color:t.error},` `,`↓ drop `,s.toLocaleString(),` (`,c.toFixed(1),`%)`):null,p.createElement(f,null,p.createElement(f,{bold:!0},`${i+1}. ${r.name}`.padEnd(22).slice(0,22)),` `,p.createElement(f,{color:t.accent},m(a,30)),` `,p.createElement(f,null,(a*100).toFixed(1).padStart(5),`% `),p.createElement(f,{color:t.muted},r.visitors.toLocaleString())))}))}export{h as funnelCommand};
@@ -1,2 +0,0 @@
1
- import{readConfig as e}from"./config--JRu_jFq.js";import"./api-hWp9s3Y8.js";import{readToken as t}from"./token-store-BQuGH0z2.js";import{ApiV2Client as n}from"./api-v2-C82L-ZOL.js";import"./formatter-DDG2TSOz.js";import{emit as r,isHeadless as i}from"./emit-NkY7PE3R.js";import{openInBrowser as a}from"./open-url-CTfSApWl.js";import"./theme-BuGrQHax.js";import{Panel as o,useTheme as s}from"./panel-B-XxdP-N.js";import{Banner as c}from"./banner-DdgwXGzt.js";import"./prompt-CJw_Mqo2.js";import{Keybar as l}from"./keybar-QgnmSion.js";import{resolveSiteId as u}from"./resolve-site-GDYx0__E.js";import{DataTable as d}from"./data-table-DJzT7bAr.js";import{EmptyState as f}from"./empty-state-DbToIL5T.js";import{deepLinkFor as p}from"./keybar-deep-link-DbmPjAEz.js";import{Box as m,Text as h,render as g,useApp as _,useInput as v}from"ink";import y,{useEffect as b,useState as x}from"react";import S from"ink-spinner";async function C(a){let o=await e(),s=await t({strict:!1});if(!s)return process.stderr.write("Not logged in — run `zenovay login` first.\n"),2;let c=new n({config:o,cliVersion:a.cliVersion,token:s}),l,d;try{({siteId:l,site:d}=await u(c,{explicit:a.siteId,headless:!!a.json,cliVersion:a.cliVersion}))}catch(e){return process.stderr.write(`${e.message}\n`),2}let f=d?.url?d.url.replace(/^https?:\/\//,``).replace(/\/$/,``):d?.name??l;if(i(a)){let e=await c.getGeo(l);if(a.csv||a.tsv){let{writeCsv:t}=await import(`./csv-emit-CVO5kebZ.js`);return t(e.countries,[`country`,`visitors`],a.tsv?`tsv`:`csv`)}if(a.ndjson){for(let t of e.countries)process.stdout.write(JSON.stringify(t)+`
2
- `);return 0}return r({type:`geo.snapshot`,data:e}),0}return new Promise(e=>{let{unmount:t}=g(y.createElement(w,{api:c,siteId:l,siteLabel:f,cliVersion:a.cliVersion,onExit:n=>{t(),e(n)}}))})}const w=({api:e,siteId:t,siteLabel:n,cliVersion:r,onExit:i})=>{let{exit:u}=_(),{theme:g}=s(),[C,w]=x(null),[T,E]=x(!0),[D,O]=x(null);if(v(e=>{if(e===`o`||e===`O`){a(p(`geo`,{siteId:t}));return}e===`q`&&(u(),i(0))}),b(()=>{let n=!1;return(async()=>{try{let r=await e.getGeo(t);n||(w(r),E(!1))}catch(e){n||(O(e.message),E(!1))}})(),()=>{n=!0}},[e,t]),T)return y.createElement(m,{flexDirection:`column`},y.createElement(c,{version:r,subtitle:`geo · ${n}`}),y.createElement(o,{title:`Loading`,state:`busy`},y.createElement(m,null,y.createElement(h,{color:g.accent},y.createElement(S,{type:`dots`})),y.createElement(h,null,` Fetching geo…`))));if(D)return y.createElement(m,{flexDirection:`column`},y.createElement(c,{version:r,subtitle:`geo · ${n}`}),y.createElement(f,{reason:`error`,headline:`Failed to load`,hint:D}));let k=!C||C.countries.length===0&&C.cities.length===0;if(k)return y.createElement(m,{flexDirection:`column`},y.createElement(c,{version:r,subtitle:`geo · ${n}`}),y.createElement(f,{reason:`no-data`,headline:`No data yet`,hint:`Visit your site to send the first event`}));let A=[{key:`country`,label:`country`,width:18},{key:`visitors`,label:`visitors`,align:`right`,width:8}],j=[{key:`city`,label:`city`,width:20},{key:`country`,label:`country`,width:12},{key:`visitors`,label:`visitors`,align:`right`,width:8}],M=process.stdout.columns??80;return y.createElement(m,{flexDirection:`column`},y.createElement(c,{version:r,subtitle:`geo · ${n}`}),y.createElement(o,{title:`Countries`},C.countries.length===0?y.createElement(h,{color:g.dim},`— —`):y.createElement(d,{columns:A,data:C.countries.slice(0,15),zebra:!0})),y.createElement(o,{title:`Cities`},C.cities.length===0?y.createElement(h,{color:g.dim},`— —`):y.createElement(d,{columns:j,data:C.cities.slice(0,20),zebra:!0})),y.createElement(l,{items:[{key:`o`,label:`open in browser`},{key:`q`,label:`quit`}]}))};export{C as geoCommand};
@@ -1,2 +0,0 @@
1
- import{readConfig as e}from"./config--JRu_jFq.js";import"./api-hWp9s3Y8.js";import{readToken as t}from"./token-store-BQuGH0z2.js";import"./telemetry-BJbpxgIp.js";import{ApiV2Client as n}from"./api-v2-C82L-ZOL.js";import"./formatter-DDG2TSOz.js";import{emit as r,isHeadless as i}from"./emit-NkY7PE3R.js";import{openInBrowser as a}from"./open-url-CTfSApWl.js";import"./client-I4GTcUcm.js";import"./theme-BuGrQHax.js";import{Panel as o,useTheme as s}from"./panel-B-XxdP-N.js";import{Banner as c}from"./banner-DdgwXGzt.js";import"./prompt-CJw_Mqo2.js";import{Keybar as l}from"./keybar-QgnmSion.js";import{ChatPanel as u}from"./chat-panel-DS-FxXoL.js";import{resolveSiteId as d}from"./resolve-site-GDYx0__E.js";import{EmptyState as f}from"./empty-state-DbToIL5T.js";import{Bar as p}from"./bar-C1Zrfe9H.js";import{deepLinkFor as m}from"./keybar-deep-link-DbmPjAEz.js";import{Box as h,Text as g,render as _,useApp as v,useInput as y}from"ink";import b,{useEffect as x,useMemo as ee,useRef as te,useState as S}from"react";import ne from"ink-spinner";const C={DZ:{lat:28.0339,lng:1.6596,name:`Algeria`,spread:8},EG:{lat:26.8206,lng:30.8025,name:`Egypt`,spread:6},ET:{lat:9.145,lng:40.4897,name:`Ethiopia`,spread:6},GH:{lat:7.9465,lng:-1.0232,name:`Ghana`,spread:3},KE:{lat:-.0236,lng:37.9062,name:`Kenya`,spread:4},MA:{lat:31.7917,lng:-7.0926,name:`Morocco`,spread:5},NG:{lat:9.082,lng:8.6753,name:`Nigeria`,spread:5},ZA:{lat:-30.5595,lng:22.9375,name:`South Africa`,spread:7},TZ:{lat:-6.369,lng:34.8888,name:`Tanzania`,spread:5},UG:{lat:1.3733,lng:32.2903,name:`Uganda`,spread:3},TN:{lat:33.8869,lng:9.5375,name:`Tunisia`,spread:3},SN:{lat:14.4974,lng:-14.4524,name:`Senegal`,spread:3},CI:{lat:7.54,lng:-5.5471,name:`Côte d'Ivoire`,spread:3},CM:{lat:7.3697,lng:12.3547,name:`Cameroon`,spread:4},AO:{lat:-11.2027,lng:17.8739,name:`Angola`,spread:6},MZ:{lat:-18.6657,lng:35.5296,name:`Mozambique`,spread:6},ZW:{lat:-19.0154,lng:29.1549,name:`Zimbabwe`,spread:4},ZM:{lat:-13.1339,lng:27.8493,name:`Zambia`,spread:5},RW:{lat:-1.9403,lng:29.8739,name:`Rwanda`,spread:1.5},MG:{lat:-18.7669,lng:46.8691,name:`Madagascar`,spread:5},LY:{lat:26.3351,lng:17.2283,name:`Libya`,spread:8},SD:{lat:12.8628,lng:30.2176,name:`Sudan`,spread:7},US:{lat:39.0902,lng:-98.5795,name:`United States`,spread:18},CA:{lat:56.1304,lng:-106.3468,name:`Canada`,spread:22},MX:{lat:23.6345,lng:-102.5528,name:`Mexico`,spread:9},BR:{lat:-10.235,lng:-51.9253,name:`Brazil`,spread:18},AR:{lat:-38.4161,lng:-63.6167,name:`Argentina`,spread:11},CL:{lat:-35.6751,lng:-71.543,name:`Chile`,spread:11},CO:{lat:4.5709,lng:-74.2973,name:`Colombia`,spread:6},PE:{lat:-9.19,lng:-75.0152,name:`Peru`,spread:7},VE:{lat:6.4238,lng:-66.5897,name:`Venezuela`,spread:6},EC:{lat:-1.8312,lng:-78.1834,name:`Ecuador`,spread:3},BO:{lat:-16.2902,lng:-63.5887,name:`Bolivia`,spread:6},UY:{lat:-32.5228,lng:-55.7658,name:`Uruguay`,spread:2.5},PY:{lat:-23.4425,lng:-58.4438,name:`Paraguay`,spread:4},GT:{lat:15.7835,lng:-90.2308,name:`Guatemala`,spread:2},CU:{lat:21.5218,lng:-77.7812,name:`Cuba`,spread:3},DO:{lat:18.7357,lng:-70.1627,name:`Dominican Republic`,spread:1.5},CR:{lat:9.7489,lng:-83.7534,name:`Costa Rica`,spread:1.2},PA:{lat:8.538,lng:-80.7821,name:`Panama`,spread:1.5},HN:{lat:15.2,lng:-86.2419,name:`Honduras`,spread:2},PR:{lat:18.2208,lng:-66.5901,name:`Puerto Rico`,spread:.6},JM:{lat:18.1096,lng:-77.2975,name:`Jamaica`,spread:.7},TT:{lat:10.6918,lng:-61.2225,name:`Trinidad and Tobago`,spread:.6},GB:{lat:55.3781,lng:-3.436,name:`United Kingdom`,spread:3},IE:{lat:53.4129,lng:-8.2439,name:`Ireland`,spread:2},FR:{lat:46.6034,lng:1.8883,name:`France`,spread:4},DE:{lat:51.1657,lng:10.4515,name:`Germany`,spread:3.5},IT:{lat:41.8719,lng:12.5674,name:`Italy`,spread:3.5},ES:{lat:40.4637,lng:-3.7492,name:`Spain`,spread:4},PT:{lat:39.3999,lng:-8.2245,name:`Portugal`,spread:2},NL:{lat:52.1326,lng:5.2913,name:`Netherlands`,spread:1.2},BE:{lat:50.5039,lng:4.4699,name:`Belgium`,spread:1},CH:{lat:46.8182,lng:8.2275,name:`Switzerland`,spread:1.4},AT:{lat:47.5162,lng:14.5501,name:`Austria`,spread:2},PL:{lat:51.9194,lng:19.1451,name:`Poland`,spread:3.5},CZ:{lat:49.8175,lng:15.473,name:`Czechia`,spread:1.8},SE:{lat:60.1282,lng:18.6435,name:`Sweden`,spread:5},NO:{lat:60.472,lng:8.4689,name:`Norway`,spread:5},FI:{lat:61.9241,lng:25.7482,name:`Finland`,spread:4},DK:{lat:56.2639,lng:9.5018,name:`Denmark`,spread:1.5},IS:{lat:64.9631,lng:-19.0208,name:`Iceland`,spread:3},GR:{lat:39.0742,lng:21.8243,name:`Greece`,spread:3},TR:{lat:38.9637,lng:35.2433,name:`Turkey`,spread:6},RO:{lat:45.9432,lng:24.9668,name:`Romania`,spread:3},HU:{lat:47.1625,lng:19.5033,name:`Hungary`,spread:2},UA:{lat:48.3794,lng:31.1656,name:`Ukraine`,spread:5},RU:{lat:61.524,lng:80,name:`Russia`,spread:28},BG:{lat:42.7339,lng:25.4858,name:`Bulgaria`,spread:2},HR:{lat:45.1,lng:15.2,name:`Croatia`,spread:2},RS:{lat:44.0165,lng:21.0059,name:`Serbia`,spread:2},SK:{lat:48.669,lng:19.699,name:`Slovakia`,spread:1.8},SI:{lat:46.1512,lng:14.9955,name:`Slovenia`,spread:1.2},LT:{lat:55.1694,lng:23.8813,name:`Lithuania`,spread:1.5},LV:{lat:56.8796,lng:24.6032,name:`Latvia`,spread:1.5},EE:{lat:58.5953,lng:25.0136,name:`Estonia`,spread:1.5},BY:{lat:53.7098,lng:27.9534,name:`Belarus`,spread:3},MD:{lat:47.4116,lng:28.3699,name:`Moldova`,spread:1.2},AL:{lat:41.1533,lng:20.1683,name:`Albania`,spread:1},MK:{lat:41.6086,lng:21.7453,name:`North Macedonia`,spread:1},BA:{lat:43.9159,lng:17.6791,name:`Bosnia and Herzegovina`,spread:1.2},ME:{lat:42.7087,lng:19.3744,name:`Montenegro`,spread:.8},XK:{lat:42.6026,lng:20.903,name:`Kosovo`,spread:.7},LU:{lat:49.8153,lng:6.1296,name:`Luxembourg`,spread:.4},MT:{lat:35.9375,lng:14.3754,name:`Malta`,spread:.3},CY:{lat:35.1264,lng:33.4299,name:`Cyprus`,spread:.6},CN:{lat:35.8617,lng:104.1954,name:`China`,spread:18},JP:{lat:36.2048,lng:138.2529,name:`Japan`,spread:5},KR:{lat:35.9078,lng:127.7669,name:`South Korea`,spread:2},IN:{lat:20.5937,lng:78.9629,name:`India`,spread:12},ID:{lat:-2.7893,lng:113.9213,name:`Indonesia`,spread:12},PH:{lat:12.8797,lng:121.774,name:`Philippines`,spread:5},VN:{lat:14.0583,lng:108.2772,name:`Vietnam`,spread:5},TH:{lat:15.87,lng:100.9925,name:`Thailand`,spread:4},MY:{lat:4.2105,lng:101.9758,name:`Malaysia`,spread:4},SG:{lat:1.3521,lng:103.8198,name:`Singapore`,spread:.3},PK:{lat:30.3753,lng:69.3451,name:`Pakistan`,spread:6},BD:{lat:23.685,lng:90.3563,name:`Bangladesh`,spread:3},LK:{lat:7.8731,lng:80.7718,name:`Sri Lanka`,spread:2},MM:{lat:21.9162,lng:95.956,name:`Myanmar`,spread:6},KH:{lat:12.5657,lng:104.991,name:`Cambodia`,spread:3},LA:{lat:19.8563,lng:102.4955,name:`Laos`,spread:3},NP:{lat:28.3949,lng:84.124,name:`Nepal`,spread:3},IR:{lat:32.4279,lng:53.688,name:`Iran`,spread:7},IQ:{lat:33.2232,lng:43.6793,name:`Iraq`,spread:4},IL:{lat:31.0461,lng:34.8516,name:`Israel`,spread:1},SA:{lat:23.8859,lng:45.0792,name:`Saudi Arabia`,spread:8},AE:{lat:23.4241,lng:53.8478,name:`UAE`,spread:2},QA:{lat:25.3548,lng:51.1839,name:`Qatar`,spread:.6},KW:{lat:29.3117,lng:47.4818,name:`Kuwait`,spread:.8},OM:{lat:21.4735,lng:55.9754,name:`Oman`,spread:4},JO:{lat:30.5852,lng:36.2384,name:`Jordan`,spread:2},LB:{lat:33.8547,lng:35.8623,name:`Lebanon`,spread:.7},SY:{lat:34.8021,lng:38.9968,name:`Syria`,spread:3},YE:{lat:15.5527,lng:48.5164,name:`Yemen`,spread:4},AF:{lat:33.9391,lng:67.71,name:`Afghanistan`,spread:5},KZ:{lat:48.0196,lng:66.9237,name:`Kazakhstan`,spread:13},UZ:{lat:41.3775,lng:64.5853,name:`Uzbekistan`,spread:5},TM:{lat:38.9697,lng:59.5563,name:`Turkmenistan`,spread:5},KG:{lat:41.2044,lng:74.7661,name:`Kyrgyzstan`,spread:3},TJ:{lat:38.861,lng:71.2761,name:`Tajikistan`,spread:3},AZ:{lat:40.1431,lng:47.5769,name:`Azerbaijan`,spread:2},GE:{lat:42.3154,lng:43.3569,name:`Georgia`,spread:2},AM:{lat:40.0691,lng:45.0382,name:`Armenia`,spread:1.2},HK:{lat:22.3193,lng:114.1694,name:`Hong Kong`,spread:.3},TW:{lat:23.6978,lng:120.9605,name:`Taiwan`,spread:1.5},AU:{lat:-25.2744,lng:133.7751,name:`Australia`,spread:18},NZ:{lat:-40.9006,lng:174.886,name:`New Zealand`,spread:5},PG:{lat:-6.314,lng:143.9555,name:`Papua New Guinea`,spread:5},FJ:{lat:-16.578,lng:179.4144,name:`Fiji`,spread:1}},re=Object.fromEntries(Object.entries(C).map(([e,t])=>[e,{lat:t.lat,lng:t.lng}]));function w(e){return!e||e.length!==2?null:C[e.toUpperCase()]??null}function T(e,t){let n=w(e);if(!n||t<=0)return[];let r=[],i=0;for(let t=0;t<e.length;t++)i=i*31+e.charCodeAt(t)>>>0;for(let e=0;e<t;e++){i=i+1831565813>>>0;let e=i;e=Math.imul(e^e>>>15,e|1)>>>0,e=(e^e+(Math.imul(e^e>>>7,e|61)>>>0))>>>0;let t=((e^e>>>14)>>>0)/4294967296;i=i+2246822507>>>0;let a=i;a=Math.imul(a^a>>>15,a|1)>>>0,a=(a^a+(Math.imul(a^a>>>7,a|61)>>>0))>>>0;let o=((a^a>>>14)>>>0)/4294967296,s=n.spread*Math.sqrt(t),c=o*2*Math.PI;r.push({lat:n.lat+s*Math.sin(c)*.7,lng:n.lng+s*Math.cos(c)/Math.max(.3,Math.cos(n.lat*Math.PI/180))})}return r}const E=360,D=180,O=new Uint8Array(E*D),k=new Uint8Array(E*D),A=[`__OCEAN__`];function j(e){let t=(e%360+360)%360;return Math.floor(t)}function M(e){return Math.max(0,Math.min(D-1,Math.floor(90-e)))}function N(e,t,n){let r=M(e),i=j(t);O[r*E+i]=1,k[r*E+i]=n}for(let e of Object.keys(C)){let t=C[e];A.push(e);let n=A.length-1,r=Math.max(.5,t.spread*.85),i=Math.max(.25,Math.cos(t.lat*Math.PI/180)),a=Math.max(.5,t.spread/i),o=Math.floor(t.lat-r),s=Math.ceil(t.lat+r),c=Math.floor(t.lng-a),l=Math.ceil(t.lng+a);for(let e=o;e<=s;e++)for(let i=c;i<=l;i++){let o=(e-t.lat)/r,s=(i-t.lng)/a;s*s+o*o>1||N(e,i,n)}}const P=new Uint8Array(O);for(let e=1;e<D-1;e++)for(let t=0;t<E;t++){if(O[e*E+t])continue;let n=0,r=0;for(let i=-1;i<=1;i++)for(let a=-1;a<=1;a++){if(i===0&&a===0)continue;let o=(t+a+E)%E;O[(e+i)*E+o]&&(n++,r||=k[(e+i)*E+o]??0)}n>=4&&(P[e*E+t]=1,k[e*E+t]=r)}O.set(P);const F=new Uint8Array(E*D);for(let e=0;e<D;e++)for(let t=0;t<E;t++){let n=k[e*E+t];if(!n)continue;let r=e>0?k[(e-1)*E+t]:0,i=e<D-1?k[(e+1)*E+t]:0,a=k[e*E+(t-1+E)%E],o=k[e*E+(t+1)%E];(r!==n||i!==n||a!==n||o!==n)&&(F[e*E+t]=1)}function I(e,t){if(e<-90||e>90)return 0;let n=Math.max(0,Math.min(D-1,Math.floor(90-e))),r=(t%360+360)%360,i=Math.floor(r);return O[n*E+i]===1?1:0}function L(e,t){if(e<-90||e>90)return 0;let n=Math.max(0,Math.min(D-1,Math.floor(90-e))),r=(t%360+360)%360,i=Math.floor(r);return F[n*E+i]===1?1:0}function R(e){return e*Math.PI/180}function z(e,t){let n=R(e),r=R(t);return{x:Math.cos(n)*Math.sin(r),y:Math.sin(n),z:Math.cos(n)*Math.cos(r)}}function B(e,t){let n=Math.cos(t),r=Math.sin(t);return{x:n*e.x+r*e.z,y:e.y,z:-r*e.x+n*e.z}}function V(e,t){let n=Math.cos(t),r=Math.sin(t);return{x:e.x,y:n*e.y-r*e.z,z:r*e.y+n*e.z}}function H(e,t){let n=e*2,r=t*4;return{dw:n,dh:r,bits:new Uint8Array(n*r)}}function U(e,t,n){t<0||t>=e.dw||n<0||n>=e.dh||(e.bits[n*e.dw+t]=1)}function W(e,t,n,r){let i=r*r;for(let a=-r;a<=r;a++)for(let o=-r;o<=r;o++)o*o+a*a<=i&&U(e,Math.round(t+o),Math.round(n+a))}const G=[[0,0],[0,1],[0,2],[1,0],[1,1],[1,2],[0,3],[1,3]];function K(e,t,n){let r=0;for(let i=0;i<G.length;i++){let[a,o]=G[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 q(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<=5?`○`:`●`}function J(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 Y(e,t,n){if(e.z<0)return null;let r=t/2,i=n/2,a=Math.min(t,n/2)*.95;return{x:r+e.x*a,y:i-e.y*a}}function X(e){let t=e.dw/2,n=e.dh/2,r=Math.min(e.dw,e.dh/2)*.95,i=Math.round(2*Math.PI*r);for(let a=0;a<i;a++){let o=a/i*2*Math.PI,s=Math.round(t+r*Math.cos(o)),c=Math.round(n+r*Math.sin(o));U(e,s,c)}}function ie(e,t,n){for(let r of[-60,-30,0,30,60])for(let i=-180;i<=180;i+=4){let a=V(B(z(r,i),t),n),o=Y(a,e.dw,e.dh);o&&U(e,Math.round(o.x),Math.round(o.y))}for(let r=-180;r<180;r+=30)for(let i=-85;i<=85;i+=4){let a=V(B(z(i,r),t),n),o=Y(a,e.dw,e.dh);o&&U(e,Math.round(o.x),Math.round(o.y))}}function ae({visitors:e,highlight:t,width:n=50,height:r=25,rotationDeg:i=0,tiltDeg:a=20,gridlines:o=!0,asciiOnly:c}){let{theme:l}=s(),u=J(c),d=H(n,r),f=H(n,r),p=H(n,r),m=H(n,r),_=H(n,r),v=R(i),y=R(-a);X(d),o&&ie(d,v,y);{let e=f.dw/2,t=f.dh/2,n=Math.min(f.dw,f.dh/2)*.95,r=Math.cos(v),i=Math.sin(v),a=Math.cos(y),o=Math.sin(y);for(let s=0;s<f.dh;s++){let c=(t-s)/n;if(!(c<-1||c>1))for(let t=0;t<f.dw;t++){let l=(t-e)/n,u=l*l+c*c;if(u>1)continue;let d=Math.sqrt(1-u),m=l,h=c,g=a*h+o*d,_=-o*h+a*d,v=r*m-i*_,y=i*m+r*_,b=Math.asin(g)*(180/Math.PI),x=Math.atan2(v,y)*(180/Math.PI);I(b,x)&&(U(f,t,s),L(b,x)&&U(p,t,s))}}}for(let t of e){let e=V(B(z(t.lat,t.lng),v),y),n=Y(e,m.dw,m.dh);if(!n)continue;let r=typeof t.freshness==`number`?t.freshness:.5;W(m,n.x,n.y,r>.7?2:1)}if(t&&t.length>0)for(let e of t){let t=V(B(z(e.lat,e.lng),v),y),n=Y(t,_.dw,_.dh);if(!n)continue;W(_,n.x,n.y,2)}let x=[];for(let e=0;e<r;e++){let t=[],r=null,i=(e,n)=>{r&&r.color===e?r.text+=n:(r={color:e,text:n},t.push(r))};for(let r=0;r<n;r++){let n=u?q(_,r,e):K(_,r,e);if(n!==` `){i(l.warn,n);continue}let a=u?q(m,r,e):K(m,r,e);if(a!==` `){i(l.accent,a);continue}let o=u?q(p,r,e):K(p,r,e);if(o!==` `){i(l.fg,o);continue}let s=u?q(f,r,e):K(f,r,e);if(s!==` `){i(l.success,s);continue}let c=u?q(d,r,e):K(d,r,e);if(c!==` `){i(l.muted,c);continue}let h=t.length>0?t[t.length-1]:void 0;i(h?h.color:l.muted,` `)}x.push(b.createElement(h,{key:e},b.createElement(g,null,t.map((e,t)=>b.createElement(g,{key:t,color:e.color,bold:!0},e.text)))))}return b.createElement(h,{flexDirection:`column`},x)}async function Z(e,t,n){let r=await e.getGeo(t).catch(()=>({countries:[],cities:[]})),i=(r.countries??[]).map(e=>{let t=w(e.country),r=n.get(e.country)??0;return{code:e.country,visitors:e.visitors,lat:t?.lat,lng:t?.lng,freshness:e.visitors>r?1:.4}});return{countries:i,totalVisitors:i.reduce((e,t)=>e+t.visitors,0),unknownCount:i.filter(e=>typeof e.lat!=`number`).reduce((e,t)=>e+t.visitors,0),lastFetchedAt:Date.now()}}async function Q(o){let s=await e(),c=await t({strict:!1});if(!c)return process.stderr.write("Not logged in — run `zenovay login` first.\n"),2;let l=new n({config:s,cliVersion:o.cliVersion,token:c}),u,f;try{({siteId:u,site:f}=await d(l,{explicit:o.siteId,headless:!!o.json,cliVersion:o.cliVersion}))}catch(e){return process.stderr.write(`${e.message}\n`),2}let p=f?.url?f.url.replace(/^https?:\/\//,``).replace(/\/$/,``):f?.name??u;if(o.browser){let e=m(`globe`,{siteId:u});o.json?process.stdout.write(JSON.stringify({openedUrl:e})+`
2
- `):process.stdout.write(`\n Opening Mapbox globe in your default browser:\n ${e}\n\n`);try{await a(e)}catch{}return 0}if(i(o)){let e=await Z(l,u,new Map);return r({type:`globe.snapshot`,data:{countries:e.countries,total:e.totalVisitors,unknownCount:e.unknownCount}}),0}return new Promise(e=>{let{unmount:t}=_(b.createElement(ue,{api:l,siteId:u,siteLabel:p,cliVersion:o.cliVersion,onExit:n=>{t(),e(n)}}))})}const oe=5e3,se=60,ce=1,le=80,ue=({api:e,siteId:t,siteLabel:n,cliVersion:r,onExit:i})=>{let{exit:d}=v(),{theme:_}=s(),[C,re]=S(null),[E,D]=S(!0),[O,k]=S(null),[A,j]=S(0),[M,N]=S(!1),[P,F]=S(20),[I,L]=S(1),[R,z]=S(0),B=te(new Map),[V,H]=S(!1);y(n=>{if(!V){if(n===`/`){H(!0);return}if(n===`q`){d(),i(0);return}if(n===` `){N(e=>!e);return}if(n===`+`||n===`=`){L(e=>Math.min(1.6,e+.1));return}if(n===`-`||n===`_`){L(e=>Math.max(.7,e-.1));return}if(n===`t`){F(e=>(e+15)%60);return}if(n===`j`){z(e=>e+1);return}if(n===`k`){z(e=>Math.max(0,e-1));return}if(n===`o`||n===`O`||n===`w`){a(m(`globe`,{siteId:t}));return}if(n===`c`&&C){let e=C.countries[R];e?.lng!==void 0&&(j(-e.lng),N(!0));return}n===`r`&&(async()=>{try{let n=await Z(e,t,B.current);B.current=new Map(n.countries.map(e=>[e.code,e.visitors])),re(n)}catch(e){k(e.message)}})()}}),x(()=>{let n=!1,r=null,i=async()=>{try{let r=await Z(e,t,B.current);if(n)return;B.current=new Map(r.countries.map(e=>[e.code,e.visitors])),re(r),D(!1)}catch(e){n||(k(e.message),D(!1))}n||(r=setTimeout(i,oe))};return i(),()=>{n=!0,r&&clearTimeout(r)}},[e,t]),x(()=>{if(M)return;let e=setInterval(()=>{j(e=>(e+ce)%360)},se);return()=>clearInterval(e)},[M]);let U=ee(()=>{if(!C)return[];let e=[];for(let t of C.countries){if(typeof t.lat!=`number`||typeof t.lng!=`number`)continue;let n=Math.min(le,Math.max(3,t.visitors*5));for(let r of T(t.code,n))e.push({lat:r.lat,lng:r.lng,freshness:t.freshness})}return e},[C]),W=ee(()=>{if(!C)return[];let e=C.countries[Math.min(R,C.countries.length-1)];return!e||typeof e.lat!=`number`?[]:T(e.code,Math.min(80,Math.max(8,e.visitors*4)))},[C,R]),G=`globe · ${n} · live`,K=[{key:`q`,label:`quit`},{key:`j/k`,label:`select country`},{key:`c`,label:`center on selected`},{key:`space`,label:M?`resume`:`pause`},{key:`t`,label:`tilt ${P}°`},{key:`+/-`,label:`zoom`},{key:`o`,label:`open web globe`},{key:`r`,label:`refresh`},{key:`/`,label:`ask AI`}];if(V)return b.createElement(u,{cliVersion:r,api:e,dashboardContext:{commandName:`globe`,siteId:t,siteLabel:n,metricsSnapshot:C},onClose:()=>H(!1)});if(E)return b.createElement(h,{flexDirection:`column`},b.createElement(c,{version:r,subtitle:G}),b.createElement(o,{title:`Loading`,state:`busy`},b.createElement(h,null,b.createElement(g,{color:_.accent},b.createElement(ne,{type:`dots`})),b.createElement(g,null,` Spinning up Earth…`))));if(O)return b.createElement(h,{flexDirection:`column`},b.createElement(c,{version:r,subtitle:G}),b.createElement(f,{reason:`error`,headline:`Failed to load`,hint:O}),b.createElement(l,{items:K}));if(!C||C.countries.length===0&&C.unknownCount===0)return b.createElement(h,{flexDirection:`column`},b.createElement(c,{version:r,subtitle:G}),b.createElement(f,{reason:`no-data`,headline:`No geolocated visitors yet`,hint:`Visit your site to populate the map.`}),b.createElement(l,{items:K}));let q=process.stdout.columns??100,J=36,Y=Math.max(40,Math.min(90,q-J-4)),X=Math.round(Y*I),ie=Math.round(X*.5),Q=C.countries.slice(0,12),ue=Math.max(1,...Q.map(e=>e.visitors)),de=Math.max(1,Math.floor((Date.now()-C.lastFetchedAt)/1e3)),$=C.countries[Math.min(R,C.countries.length-1)],fe=$?w($.code):null;return b.createElement(h,{flexDirection:`column`},b.createElement(c,{version:r,subtitle:G}),$?b.createElement(h,{flexDirection:`row`,marginBottom:1},b.createElement(h,{width:2}),b.createElement(h,{borderStyle:`round`,borderColor:_.warn,paddingX:1},b.createElement(g,{color:_.warn,bold:!0},fe?.name??$.code),b.createElement(g,{color:_.dim},` · `),b.createElement(g,{color:_.fg},$.visitors,` visitor`,$.visitors===1?``:`s`))):null,b.createElement(h,{flexDirection:`row`},b.createElement(h,{flexDirection:`column`,marginRight:2},b.createElement(ae,{visitors:U,highlight:W,width:X,height:ie,rotationDeg:A,tiltDeg:P}),b.createElement(h,{marginTop:1},b.createElement(g,{color:_.dim},C.totalVisitors,` visitors · `,C.countries.length,` countries`,C.unknownCount>0?` · ${C.unknownCount} unmapped`:``,` · `,M?`rotation paused`:`↻ ${ce}°/${se}ms`,` · refreshed `,de,`s ago`))),b.createElement(h,{flexDirection:`column`,width:J},b.createElement(o,{title:`Live by country`},Q.map((e,t)=>{let n=t===Math.min(R,C.countries.length-1),r=e.freshness>.7,i=n?_.warn:r?_.success:_.fg;return b.createElement(h,{key:e.code,flexDirection:`row`},b.createElement(h,{width:2},b.createElement(g,{color:_.warn},n?`›`:` `)),b.createElement(h,{width:3},b.createElement(g,{color:i,bold:n},e.code)),b.createElement(p,{value:e.visitors,max:ue,width:14,showPercent:!1}),b.createElement(h,{width:6},b.createElement(g,{color:_.muted},String(e.visitors).padStart(5))))})),C.countries.length>12?b.createElement(h,{marginTop:1},b.createElement(g,{color:_.muted},`+`,C.countries.length-12,` more (j/k to scroll)`)):null)),b.createElement(l,{items:K}))};export{Q as globeCommand};
@@ -1,2 +0,0 @@
1
- import{configPath as e,readConfig as t}from"./config--JRu_jFq.js";import{fetchManifest as n}from"./check-D9G0N7NB.js";import{ApiClient as r}from"./api-hWp9s3Y8.js";import{readToken as i}from"./token-store-BQuGH0z2.js";import{isHeadless as a}from"./emit-NkY7PE3R.js";import{Panel as o,useTheme as s}from"./panel-B-XxdP-N.js";import{spawnSync as c}from"node:child_process";import l from"node:path";import{existsSync as u,promises as d,statSync as f}from"node:fs";import p from"node:os";import{Box as m,Text as h,render as g}from"ink";import _ from"react";const v=6*60*60*1e3;function y(){return l.join(p.homedir(),`.zenovay`,`update.json`)}async function b(){try{let e=await d.readFile(y(),`utf8`);return JSON.parse(e)}catch{return null}}async function x(e){let t=y();await d.mkdir(l.dirname(t),{recursive:!0,mode:448}),await d.writeFile(t,JSON.stringify(e,null,2))}async function S(){let e=await t();if(e.noUpdateCheck||process.env.ZENOVAY_NO_UPDATE_CHECK===`1`||process.env.CI===`true`)return null;let r=await b();if(r&&Date.now()-r.fetchedAt<v)return r;try{let t=await n({cliBase:e.cliBase}),i={manifest:t,fetchedAt:Date.now(),lastNoticeAt:r?.lastNoticeAt};return await x(i),i}catch{return r}}async function C(){try{await S()}catch{}process.exit(0)}process.env.ZENOVAY_UPDATE_WORKER_FORK===`1`&&C();function w(e){return e.includes(`/Cellar/`)||e.includes(`/opt/homebrew/`)||e.includes(`/usr/local/Cellar/`)?`brew`:e.includes(`.npm-global`)||e.includes(`node_modules/.bin`)||e.includes(`npm/bin`)?`npm-global`:e.endsWith(`/.local/bin/zenovay`)||e.endsWith(`\\.local\\bin\\zenovay.exe`)?`curl-installer`:e.includes(`/lib/node_modules/`)||e.includes(`\\nodejs\\`)?`npm-prefix`:`unknown`}function T(e){let t=process.platform===`win32`,n=t?`where`:`which`,r=t?[e]:[`-a`,e];try{let e=c(n,r,{encoding:`utf8`,timeout:3e3});if(e.status!==0||!e.stdout)return[];let t=e.stdout.split(/\r?\n/).map(e=>e.trim()).filter(Boolean);return[...new Set(t)]}catch{return[]}}function E(e){let t=process.platform===`win32`,n=t?`;`:`:`,r=(process.env.PATH??``).split(n).filter(Boolean),i=t?[`.exe`,`.cmd`,``]:[``],a=[];for(let t of r)for(let n of i){let r=l.join(t,e+n);if(u(r))try{let e=f(r);e.isFile()&&a.push(r)}catch{}}return[...new Set(a)]}function D(e=`zenovay`){let t=T(e);t.length===0&&(t=E(e));let n=t.map(e=>({path:e,kind:w(e)})),r=t[0]??null;return{paths:t,active:r,kinds:n}}function O(e,t){if(e.paths.length<2)return``;let n=[];n.push(`Multiple zenovay binaries detected on PATH:`);for(let r of e.kinds){let i=r.path===e.active,a=t&&r.path===t,o=[i&&`(first on PATH)`,a&&`(currently running)`].filter(Boolean).join(` `);n.push(` • ${r.path} [${r.kind}] ${o}`)}n.push(``),n.push(`Pick one and uninstall the others to avoid version drift:`);let r=new Set(e.kinds.map(e=>e.kind));return r.has(`npm-global`)&&n.push(` npm uninstall -g @zenovay/cli # remove the npm-installed one`),r.has(`brew`)&&n.push(` brew uninstall zenovay # remove the Homebrew-installed one`),r.has(`curl-installer`)&&n.push(` rm ~/.local/bin/zenovay # remove the curl-installer one`),n.join(`
2
- `)}const k=2e3,A=5e3;async function j(e,t){let n=`${e}/mcp`,r=Date.now(),i=new AbortController,a=setTimeout(()=>i.abort(),k);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 M(){try{let t=await d.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 N(){let e=p.homedir(),t=[l.join(e,`.zshrc`),l.join(e,`.bashrc`),l.join(e,`.config`,`fish`,`completions`,`zenovay.fish`)],n=[];for(let e of t)try{let t=await d.readFile(e,`utf8`);(/zenovay\s+(complet|--?complet)/i.test(t)||/_zenovay/.test(t)||/complete\s+-c\s+zenovay/.test(t))&&n.push(l.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 P(e,t,n,r){if(!e||!t)return{name:`Events stream`,status:`skip`,detail:`not authenticated`};let i=new AbortController,a=setTimeout(()=>i.abort(),A),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 F(n){let a=n.fetchImpl??fetch,o=[],s=await t().catch(()=>null);o.push({name:`Binary`,status:`pass`,detail:`v${n.cliVersion} (${n.binaryPath})`});let c=D(`zenovay`);if(c.paths.length>=2){let e=c.kinds.map(e=>e.kind).join(` + `);o.push({name:`Install paths`,status:`warn`,detail:`${c.paths.length} binaries on PATH (${e}). Active: ${c.active}. Run \`zenovay doctor\` for cleanup.`})}else o.push({name:`Install paths`,status:`pass`,detail:c.active??`no zenovay on PATH`});o.push({name:`Config file`,status:s?`pass`:`warn`,detail:e()});let l=await i({strict:!1}).catch(()=>null);o.push({name:`Auth`,status:l?`pass`:`fail`,detail:l?`logged in${l.email?` as ${l.email}`:``}`:`not logged in`});let u=null;if(s)try{u=new r({config:s,cliVersion:n.cliVersion,token:l,fetchImpl:a});let e=await u.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 d=await b().catch(()=>null);o.push({name:`Auto-update`,status:s?.noUpdateCheck?`warn`:`pass`,detail:s?.noUpdateCheck?`disabled`:d?`latest=${d.manifest.latest}`:`manifest not yet fetched`});let f=s?.apiBase??`https://api.zenovay.com`;return o.push(await j(f,a)),o.push(await M()),o.push(await N()),o.push(await P(u,!!l,f,a)),o}function I(e){return e.some(e=>e.status===`fail`)?1:0}async function L(e){let t=await F(e),n=I(t),r=n===0;return a({json:e.json})?(process.stdout.write(`${JSON.stringify({checks:t,passed:r})}\n`),n):new Promise(e=>{let{unmount:r}=g(_.createElement(R,{checks:t}),{exitOnCtrlC:!0});setImmediate(()=>{r(),e(n)})})}const R=({checks:e})=>{let{theme:t}=s();return _.createElement(o,{title:`Zenovay CLI health check`,state:`idle`},e.map(e=>_.createElement(m,{key:e.name},_.createElement(h,{color:B(t,e.status)},z(e.status)),_.createElement(h,null,` `),_.createElement(h,{bold:!0},e.name.padEnd(18)),_.createElement(h,{color:t.muted},e.detail))))};function z(e){return e===`pass`?`✔`:e===`warn`?`⚠`:e===`skip`?`∼`:`✗`}function B(e,t){return t===`pass`?e.success:t===`warn`?e.warn:t===`skip`?e.dim:e.error}export{R as HealthReport,D as detectInstallPaths,I as exitCodeFor,L as healthCommand,O as remediationHint,F as runHealthChecks};
@@ -1 +0,0 @@
1
- import"./config--JRu_jFq.js";import"./check-D9G0N7NB.js";import"./api-hWp9s3Y8.js";import"./token-store-BQuGH0z2.js";import"./formatter-DDG2TSOz.js";import"./emit-NkY7PE3R.js";import"./theme-BuGrQHax.js";import"./panel-B-XxdP-N.js";import{HealthReport as e,exitCodeFor as t,healthCommand as n,runHealthChecks as r}from"./health-BJwKEdIp.js";export{n as healthCommand};
@@ -1 +0,0 @@
1
- import{readConfig as e}from"./config--JRu_jFq.js";import"./api-hWp9s3Y8.js";import{readToken as t}from"./token-store-BQuGH0z2.js";import{ApiV2Client as n}from"./api-v2-C82L-ZOL.js";import{requireTier as r}from"./tier-C4q8fJ8m.js";import"./formatter-DDG2TSOz.js";import{emit as i,isHeadless as a}from"./emit-NkY7PE3R.js";import{openInBrowser as o}from"./open-url-CTfSApWl.js";import"./theme-BuGrQHax.js";import{Panel as s,useTheme as c}from"./panel-B-XxdP-N.js";import{Banner as l}from"./banner-DdgwXGzt.js";import"./prompt-CJw_Mqo2.js";import{Keybar as u}from"./keybar-QgnmSion.js";import{resolveSiteId as d}from"./resolve-site-GDYx0__E.js";import{DataTable as f}from"./data-table-DJzT7bAr.js";import{EmptyState as p}from"./empty-state-DbToIL5T.js";import{deepLinkFor as m}from"./keybar-deep-link-DbmPjAEz.js";import{Box as h,Text as g,render as _,useApp as v,useInput as y}from"ink";import b,{useEffect as x,useState as S}from"react";import C from"ink-spinner";async function w(o){let s=await e(),c=await t({strict:!1});if(!c)return process.stderr.write("Not logged in — run `zenovay login` first.\n"),2;let l=new n({config:s,cliVersion:o.cliVersion,token:c});try{await r(l,`pro`)}catch(e){return process.stderr.write(`${e.message}\n`),2}let u,f;try{({siteId:u,site:f}=await d(l,{explicit:o.siteId,headless:!!o.json,cliVersion:o.cliVersion}))}catch(e){return process.stderr.write(`${e.message}\n`),2}let p=f?.url?f.url.replace(/^https?:\/\//,``).replace(/\/$/,``):f?.name??u;if(a(o)){let e=await l.getHeatmaps(u);return i({type:`heatmaps.snapshot`,data:e}),0}return new Promise(e=>{let{unmount:t}=_(b.createElement(T,{api:l,siteId:u,siteLabel:p,cliVersion:o.cliVersion,onExit:n=>{t(),e(n)}}))})}const T=({api:e,siteId:t,siteLabel:n,cliVersion:r,onExit:i})=>{let{exit:a}=v(),{theme:d}=c(),[_,w]=S(null),[T,E]=S(!0),[D,O]=S(null);if(y(e=>{if(e===`o`||e===`O`){o(m(`heatmaps`,{siteId:t}));return}e===`q`&&(a(),i(0))}),x(()=>{let n=!1;return(async()=>{try{let r=await e.getHeatmaps(t);n||(w(r),E(!1))}catch(e){n||(O(e.message),E(!1))}})(),()=>{n=!0}},[e,t]),T)return b.createElement(h,{flexDirection:`column`},b.createElement(l,{version:r,subtitle:`heatmaps · ${n}`}),b.createElement(s,{title:`Loading`,state:`busy`},b.createElement(h,null,b.createElement(g,{color:d.accent},b.createElement(C,{type:`dots`})),b.createElement(g,null,` Fetching heatmaps…`))));if(D)return b.createElement(h,{flexDirection:`column`},b.createElement(l,{version:r,subtitle:`heatmaps · ${n}`}),b.createElement(p,{reason:`error`,headline:`Failed to load`,hint:D}));if(!_||_.length===0)return b.createElement(h,{flexDirection:`column`},b.createElement(l,{version:r,subtitle:`heatmaps · ${n}`}),b.createElement(p,{reason:`no-data`,headline:`No heatmaps yet`,hint:`Enable heatmaps in your site settings`}));let k=[{key:`url`,label:`page`,width:36},{key:`type`,label:`type`,width:12},{key:`captureCount`,label:`captures`,align:`right`,width:10},{key:`createdAt`,label:`first seen`,width:24}];return b.createElement(h,{flexDirection:`column`},b.createElement(l,{version:r,subtitle:`heatmaps · ${n}`}),b.createElement(s,{title:`Heatmaps (${_.length})`},b.createElement(f,{columns:k,data:_,zebra:!0})),b.createElement(h,{marginTop:1},b.createElement(g,{color:d.muted},`Open any heatmap at https://app.zenovay.com/heatmaps`)),b.createElement(u,{items:[{key:`o`,label:`open in browser`},{key:`q`,label:`quit`}]}))};export{w as heatmapsCommand};
@@ -1,2 +0,0 @@
1
- import{readConfig as e}from"./config--JRu_jFq.js";import"./api-hWp9s3Y8.js";import{readToken as t}from"./token-store-BQuGH0z2.js";import{ApiV2Client as n}from"./api-v2-C82L-ZOL.js";import"./formatter-DDG2TSOz.js";import{isHeadless as r}from"./emit-NkY7PE3R.js";import"./theme-BuGrQHax.js";import{Panel as i,useTheme as a}from"./panel-B-XxdP-N.js";import{Banner as o}from"./banner-DdgwXGzt.js";import{Keybar as s}from"./keybar-QgnmSion.js";import{DataTable as c}from"./data-table-DJzT7bAr.js";import{EmptyState as l}from"./empty-state-DbToIL5T.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";function y(e){if(!e)return`—`;let t=new Date(e);return Number.isNaN(t.getTime())?`—`:t.toISOString().slice(0,10)}async function b(e){let t=await e.me().catch(()=>null),n=t?.user.name?.trim()||t?.user.email||`you`,r=await e.getSites().catch(()=>[]),i=r.map(e=>({id:e.id,name:e.name,domain:e.url.replace(/^https?:\/\//,``).replace(/\/$/,``),lastActive:e.lastActiveAt??null})),a={visitors:0,pageviews:0,deltaPct:null};if(r.length>0){let t=r[0].id,[n,i]=await Promise.all([e.getStats(t,`7d`).catch(()=>null),e.getSources(t,`7d`,`prev`).catch(()=>null)]);n&&(a.visitors=n.visitors,a.pageviews=n.pageviews);let o=i?.sources?.filter(e=>typeof e.delta==`number`)??[];if(o.length>0){let e=o.reduce((e,t)=>e+(t.delta??0),0);a.deltaPct=e/o.length*100}}return{sites:i,weekly:a,userLabel:n}}async function x(i){let a=await e(),o=await t({strict:!1});if(!o)return process.stderr.write("Not logged in — run `zenovay login` first.\n"),2;let s=new n({config:a,cliVersion:i.cliVersion,token:o});if(r(i))try{let e=await b(s);return process.stdout.write(JSON.stringify({sites:e.sites,weekly:{visitors:e.weekly.visitors,pageviews:e.weekly.pageviews,deltaPct:e.weekly.deltaPct}},null,2)+`
2
- `),0}catch(e){return process.stderr.write(`✗ ${e.message}\n`),1}return new Promise(e=>{let{unmount:t}=f(h.createElement(S,{api:s,cliVersion:i.cliVersion,onExit:n=>{t(),e(n)}}))})}const S=({api:e,cliVersion:t,onExit:n})=>{let{exit:r}=p(),{theme:f}=a(),[x,S]=_(null),[C,w]=_(!0),[T,E]=_(null);m(e=>{e===`q`&&(r(),n(0))}),g(()=>{let t=!1;return(async()=>{try{let n=await b(e);t||(S(n),w(!1))}catch(e){t||(E(e.message),w(!1))}})(),()=>{t=!0}},[e]);let D=`home · ${x?.userLabel??`…`}`,O=[{key:`q`,label:`quit`}];if(C)return h.createElement(u,{flexDirection:`column`},h.createElement(o,{version:t,subtitle:D}),h.createElement(i,{title:`Loading`,state:`busy`},h.createElement(u,null,h.createElement(d,{color:f.accent},h.createElement(v,{type:`dots`})),h.createElement(d,null,` Fetching your home dashboard…`))));if(T)return h.createElement(u,{flexDirection:`column`},h.createElement(o,{version:t,subtitle:D}),h.createElement(l,{reason:`error`,headline:`Failed to load`,hint:T}),h.createElement(s,{items:O}));if(!x)return h.createElement(u,{flexDirection:`column`},h.createElement(o,{version:t,subtitle:D}),h.createElement(l,{reason:`no-data`,headline:`No data`}),h.createElement(s,{items:O}));let k=[{key:`name`,label:`site`,width:24},{key:`domain`,label:`domain`,width:32},{key:`lastActive`,label:`last active`,width:12,format:e=>y(e)}],A=x.weekly.deltaPct===null?`—`:`${x.weekly.deltaPct>=0?`+`:``}${x.weekly.deltaPct.toFixed(1)}%`;return h.createElement(u,{flexDirection:`column`},h.createElement(o,{version:t,subtitle:D}),h.createElement(i,{title:`Your sites (${x.sites.length})`},x.sites.length===0?h.createElement(d,{color:f.muted},"No sites yet — run `zenovay init` to add one."):h.createElement(c,{columns:k,data:x.sites,zebra:!0})),h.createElement(i,{title:`This week`},h.createElement(d,null,h.createElement(d,{color:f.accent},`Visitors`),` `,x.weekly.visitors.toLocaleString(),` `,h.createElement(d,{color:f.accent},`Pageviews`),` `,x.weekly.pageviews.toLocaleString(),` `,h.createElement(d,{color:f.accent},`Δ vs last week`),` `,A)),h.createElement(s,{items:O}))};export{x as homeCommand};