@vfrey/vfrey 0.0.1 → 1.0.0-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (603) hide show
  1. package/LICENSE +33 -0
  2. package/README.md +78 -3
  3. package/accounts.example.json +61 -0
  4. package/accounts.first-run.json +41 -0
  5. package/bin/vfrey.mjs +36 -0
  6. package/integration-tools/README.md +43 -0
  7. package/integration-tools/image/pillow.md +32 -0
  8. package/integration-tools/image/playwright.md +33 -0
  9. package/integration-tools/image/resvg.md +36 -0
  10. package/integration-tools/image/satori.md +36 -0
  11. package/integration-tools/image/sharp.md +38 -0
  12. package/integration-tools/video/blender.md +34 -0
  13. package/integration-tools/video/ffmpeg.md +41 -0
  14. package/integration-tools/video/manim.md +37 -0
  15. package/integration-tools/video/motion-canvas.md +37 -0
  16. package/integration-tools/video/remotion.md +50 -0
  17. package/integration-tools/video/revideo.md +32 -0
  18. package/package.json +74 -6
  19. package/skills/vfrey-orchestrator/SKILL.md +15 -0
  20. package/skills/vfrey-orchestrator/channel-video/SKILL.md +41 -0
  21. package/skills/vfrey-product/SKILL.md +63 -0
  22. package/skills/vfrey-product/examples/concurrency-vs-parallelism/framey/cook-one.svg +14 -0
  23. package/skills/vfrey-product/examples/concurrency-vs-parallelism/framey/cook-two.svg +22 -0
  24. package/skills/vfrey-product/examples/concurrency-vs-parallelism/framey/index.html +70 -0
  25. package/skills/vfrey-product/examples/concurrency-vs-parallelism/remotion/cook-one.svg +14 -0
  26. package/skills/vfrey-product/examples/concurrency-vs-parallelism/remotion/cook-two.svg +22 -0
  27. package/skills/vfrey-product/examples/concurrency-vs-parallelism/remotion/index.tsx +49 -0
  28. package/skills/vfrey-product/examples/concurrency-vs-parallelism/script.json +15 -0
  29. package/skills/vfrey-product/examples/octopus-facts/index.html +60 -0
  30. package/skills/vfrey-product/examples/octopus-facts/octopus.svg +8 -0
  31. package/skills/vfrey-product/examples/octopus-facts/script.json +14 -0
  32. package/skills/vfrey-product/push/SKILL.md +15 -0
  33. package/skills/vfrey-product/scenes/NOTICE +5 -0
  34. package/skills/vfrey-product/scenes/blocks.md +57 -0
  35. package/skills/vfrey-product/scenes/craft.md +118 -0
  36. package/skills/vfrey-product/scenes/motion.md +88 -0
  37. package/src/analytics/dashboard.ts +109 -0
  38. package/src/analytics/index.ts +260 -0
  39. package/src/api/client.ts +282 -0
  40. package/src/api/commands.ts +330 -0
  41. package/src/api/config.ts +34 -0
  42. package/src/api/creators.ts +463 -0
  43. package/src/api/credentials.ts +152 -0
  44. package/src/api/mail.ts +333 -0
  45. package/src/api/topics.ts +207 -0
  46. package/src/api/types.ts +205 -0
  47. package/src/cli.ts +467 -0
  48. package/src/cloud/executor.ts +281 -0
  49. package/src/cloud/job.ts +106 -0
  50. package/src/cloud/render-job.ts +187 -0
  51. package/src/config.ts +309 -0
  52. package/src/dashboard-link.ts +180 -0
  53. package/src/dashboard-start.ts +103 -0
  54. package/src/desk/channel.ts +64 -0
  55. package/src/desk/cli.ts +216 -0
  56. package/src/desk/creators-route.ts +129 -0
  57. package/src/desk/fonts/JetBrainsMono-OFL.txt +93 -0
  58. package/src/desk/fonts/google-sans-flex-latin.woff2 +0 -0
  59. package/src/desk/fonts/jetbrains-mono-medium.woff2 +0 -0
  60. package/src/desk/http.ts +460 -0
  61. package/src/desk/mail-route.ts +103 -0
  62. package/src/desk/overlay.ts +112 -0
  63. package/src/desk/preview.ts +422 -0
  64. package/src/desk/screens.ts +149 -0
  65. package/src/desk/secrets.ts +143 -0
  66. package/src/desk/series.ts +127 -0
  67. package/src/desk/state.ts +77 -0
  68. package/src/desk/studio-route.ts +119 -0
  69. package/src/desk/tick-runner.ts +66 -0
  70. package/src/desk/tick.ts +56 -0
  71. package/src/desk/topics-route.ts +41 -0
  72. package/src/desk/ui/app.css +505 -0
  73. package/src/desk/ui/app.js +185 -0
  74. package/src/desk/ui/apple-icon.png +0 -0
  75. package/src/desk/ui/components.js +79 -0
  76. package/src/desk/ui/core.js +156 -0
  77. package/src/desk/ui/favicon.ico +0 -0
  78. package/src/desk/ui/icon.svg +1 -0
  79. package/src/desk/ui/icons.js +49 -0
  80. package/src/desk/ui/index.html +41 -0
  81. package/src/desk/ui/metrics-math.d.ts +22 -0
  82. package/src/desk/ui/metrics-math.js +135 -0
  83. package/src/desk/ui/theme.js +5 -0
  84. package/src/desk/ui/views-creators.js +209 -0
  85. package/src/desk/ui/views-keys.js +114 -0
  86. package/src/desk/ui/views-mail.js +188 -0
  87. package/src/desk/ui/views-misc.js +123 -0
  88. package/src/desk/ui/views-review.js +119 -0
  89. package/src/desk/ui/views-runs.js +350 -0
  90. package/src/desk/ui/views-screens.js +163 -0
  91. package/src/desk/ui/views-series.js +318 -0
  92. package/src/desk/ui/views-topics.js +87 -0
  93. package/src/desk/verbs.ts +361 -0
  94. package/src/doctor.ts +212 -0
  95. package/src/drain.ts +14 -0
  96. package/src/engage/index.ts +217 -0
  97. package/src/generate/index.ts +110 -0
  98. package/src/generate/script.ts +152 -0
  99. package/src/generate/title.ts +78 -0
  100. package/src/help.ts +233 -0
  101. package/src/home.ts +45 -0
  102. package/src/llm/client.ts +177 -0
  103. package/src/log.ts +7 -0
  104. package/src/oauth/tokens.ts +189 -0
  105. package/src/oauth/vault.ts +72 -0
  106. package/src/pipeline/review.ts +642 -0
  107. package/src/pipeline/run.ts +443 -0
  108. package/src/pipeline/series-guard.ts +26 -0
  109. package/src/pipeline/source-fetch.ts +69 -0
  110. package/src/pipeline/stages.ts +728 -0
  111. package/src/pipeline/topics-source.ts +90 -0
  112. package/src/product/commands.ts +296 -0
  113. package/src/product/config-file.ts +38 -0
  114. package/src/product/engine-choice.ts +89 -0
  115. package/src/product/engines.ts +103 -0
  116. package/src/product/insights.ts +50 -0
  117. package/src/product/keys.ts +67 -0
  118. package/src/product/paths.ts +18 -0
  119. package/src/product/probes.ts +88 -0
  120. package/src/product/push-flow.ts +90 -0
  121. package/src/product/render-video.ts +21 -0
  122. package/src/product/short.ts +62 -0
  123. package/src/product/update.ts +32 -0
  124. package/src/project/canonical.ts +14 -0
  125. package/src/project/commands.ts +177 -0
  126. package/src/project/dashboard-status.ts +28 -0
  127. package/src/project/discover.ts +19 -0
  128. package/src/project/index-file.ts +73 -0
  129. package/src/project/marker.ts +87 -0
  130. package/src/project/migrate.ts +201 -0
  131. package/src/project/names.ts +27 -0
  132. package/src/project/notice.ts +16 -0
  133. package/src/project/open.ts +88 -0
  134. package/src/project/scaffold.ts +112 -0
  135. package/src/project/templates.ts +42 -0
  136. package/src/project/videos.ts +64 -0
  137. package/src/publish/facebook.ts +91 -0
  138. package/src/publish/index.ts +12 -0
  139. package/src/publish/instagram.ts +97 -0
  140. package/src/publish/rate.ts +62 -0
  141. package/src/publish/session.ts +242 -0
  142. package/src/publish/tiktok.ts +202 -0
  143. package/src/publish/youtube.ts +177 -0
  144. package/src/queue/desk-ops.ts +1170 -0
  145. package/src/queue/seal.ts +3 -0
  146. package/src/queue/store.ts +1006 -0
  147. package/src/remotion/AiLabel.tsx +26 -0
  148. package/src/remotion/Root.tsx +73 -0
  149. package/src/remotion/defaults.ts +26 -0
  150. package/src/remotion/films/claude/ClaudeFilm.tsx +1014 -0
  151. package/src/remotion/films/engine/EngineMark.tsx +17 -0
  152. package/src/remotion/films/rea/ReaShort.tsx +552 -0
  153. package/src/remotion/films/rea/drawings.tsx +907 -0
  154. package/src/remotion/films/rea/timing.ts +144 -0
  155. package/src/remotion/index.ts +4 -0
  156. package/src/remotion/templates/EditorialSplit.tsx +39 -0
  157. package/src/remotion/templates/KineticType.tsx +39 -0
  158. package/src/remotion/templates/SignalBoard.tsx +50 -0
  159. package/src/remotion/timing.ts +22 -0
  160. package/src/render/chrome.ts +78 -0
  161. package/src/render/engine-mark.ts +29 -0
  162. package/src/render/framey-template.ts +130 -0
  163. package/src/render/html-engine.ts +149 -0
  164. package/src/render/node-crypto-stub.ts +11 -0
  165. package/src/render/probe.ts +29 -0
  166. package/src/render/props.ts +17 -0
  167. package/src/render/vertical-short.ts +35 -0
  168. package/src/render/webpack.ts +33 -0
  169. package/src/render/worker.ts +65 -0
  170. package/src/scene/assets/fonts/TitanOne-OFL.txt +94 -0
  171. package/src/scene/assets/fonts/titan-one.woff2 +0 -0
  172. package/src/scene/assets/gsap/LICENSE.txt +8 -0
  173. package/src/scene/assets/gsap/gsap.min.js +11 -0
  174. package/src/scene/audio.ts +54 -0
  175. package/src/scene/blocks/LICENSE +190 -0
  176. package/src/scene/blocks/NOTICE +5 -0
  177. package/src/scene/blocks/bar-chart-race/bar-chart-race.html +585 -0
  178. package/src/scene/blocks/beat-freeze-cut/beat-freeze-cut.html +874 -0
  179. package/src/scene/blocks/camcorder-hud/camcorder-hud.html +164 -0
  180. package/src/scene/blocks/camera-dolly-zoom/camera-dolly-zoom.html +355 -0
  181. package/src/scene/blocks/code-diff/code-diff.html +817 -0
  182. package/src/scene/blocks/code-snippet-apple-terminal-pro/code-snippet-apple-terminal-pro.html +248 -0
  183. package/src/scene/blocks/code-typing/code-typing.html +764 -0
  184. package/src/scene/blocks/data-chart/data-chart.html +452 -0
  185. package/src/scene/blocks/flowchart-vertical/flowchart-vertical.html +454 -0
  186. package/src/scene/blocks/hw-scribble-transition/hw-scribble-transition.html +153 -0
  187. package/src/scene/blocks/index.json +824 -0
  188. package/src/scene/blocks/lt-accent-underline/lt-accent-underline.html +107 -0
  189. package/src/scene/blocks/lt-bold-block/lt-bold-block.html +109 -0
  190. package/src/scene/blocks/lt-clean-bar/lt-clean-bar.html +112 -0
  191. package/src/scene/blocks/lt-dark-card/lt-dark-card.html +111 -0
  192. package/src/scene/blocks/lt-kicker-name/lt-kicker-name.html +114 -0
  193. package/src/scene/blocks/lt-mask-reveal/lt-mask-reveal.html +120 -0
  194. package/src/scene/blocks/lt-neon-border/lt-neon-border.html +391 -0
  195. package/src/scene/blocks/lt-stack-bars/lt-stack-bars.html +109 -0
  196. package/src/scene/blocks/macos-notification/macos-notification.html +194 -0
  197. package/src/scene/blocks/mk-background/mk-background.html +236 -0
  198. package/src/scene/blocks/mk-callout-highlight/mk-callout-highlight.html +183 -0
  199. package/src/scene/blocks/mk-clone-wall-transition/mk-clone-wall-transition.html +226 -0
  200. package/src/scene/blocks/mk-line-graph/mk-line-graph.html +293 -0
  201. package/src/scene/blocks/mk-progress-stat/mk-progress-stat.html +186 -0
  202. package/src/scene/blocks/mk-specs-list/mk-specs-list.html +223 -0
  203. package/src/scene/blocks/news-ticker/news-ticker.html +409 -0
  204. package/src/scene/blocks/organic-light-leak-overlay/organic-light-leak-overlay.html +126 -0
  205. package/src/scene/blocks/oscilloscope-trace/oscilloscope-trace.html +519 -0
  206. package/src/scene/blocks/snow/snow.html +205 -0
  207. package/src/scene/blocks/split-flap-board/split-flap-board.html +347 -0
  208. package/src/scene/blocks/spotify-card/spotify-card.html +294 -0
  209. package/src/scene/blocks/starfield/starfield.html +188 -0
  210. package/src/scene/blocks/thread-message-stack/thread-message-stack.html +239 -0
  211. package/src/scene/blocks/week-in-merges/week-in-merges.html +470 -0
  212. package/src/scene/blocks/x-post/x-post.html +437 -0
  213. package/src/scene/blocks/yt-comment-card/yt-comment-card.html +319 -0
  214. package/src/scene/blocks/yt-lcd-background/yt-lcd-background.html +307 -0
  215. package/src/scene/blocks/yt-prism-title/yt-prism-title.html +205 -0
  216. package/src/scene/blocks.ts +229 -0
  217. package/src/scene/command.ts +272 -0
  218. package/src/scene/figure.ts +181 -0
  219. package/src/scene/glyphs.ts +107 -0
  220. package/src/scene/init.ts +86 -0
  221. package/src/scene/inspect/css-tree.d.ts +6 -0
  222. package/src/scene/inspect/page-scripts.ts +272 -0
  223. package/src/scene/inspect/report.ts +405 -0
  224. package/src/scene/inspect/run.ts +200 -0
  225. package/src/scene/inspect/source.ts +236 -0
  226. package/src/scene/label.ts +131 -0
  227. package/src/scene/net-guard.ts +74 -0
  228. package/src/scene/render.ts +292 -0
  229. package/src/scene/runtime/browser.ts +199 -0
  230. package/src/scene/runtime/core.ts +181 -0
  231. package/src/scene/runtime/react.tsx +115 -0
  232. package/src/scene/runtime/transitions.ts +133 -0
  233. package/src/scene/sanitize.ts +181 -0
  234. package/src/scene/scene.ts +152 -0
  235. package/src/scene/studio-command.ts +48 -0
  236. package/src/scene/studio-skin.ts +59 -0
  237. package/src/scene/studio.ts +337 -0
  238. package/src/scene/supply.ts +111 -0
  239. package/src/scene/timing.ts +288 -0
  240. package/src/scene/transitions/LICENSE +190 -0
  241. package/src/scene/transitions/NOTICE +5 -0
  242. package/src/scene/transitions/SOURCE.json +24 -0
  243. package/src/scene/transitions/transitions.global.js +38 -0
  244. package/src/scene/transitions.ts +26 -0
  245. package/src/service/all-projects.ts +153 -0
  246. package/src/service/commands.ts +256 -0
  247. package/src/service/due.ts +82 -0
  248. package/src/service/lock.ts +101 -0
  249. package/src/service/log-file.ts +56 -0
  250. package/src/service/state.ts +41 -0
  251. package/src/service/units.ts +90 -0
  252. package/src/service/worker.ts +51 -0
  253. package/src/skill-agents.ts +74 -0
  254. package/src/skill-install.ts +334 -0
  255. package/src/sync-write.ts +21 -0
  256. package/src/tick-report.ts +205 -0
  257. package/src/tts.ts +124 -0
  258. package/vendor/@vfrey/contracts/dist/account.d.ts +97 -0
  259. package/vendor/@vfrey/contracts/dist/account.js +27 -0
  260. package/vendor/@vfrey/contracts/dist/checks.d.ts +8 -0
  261. package/vendor/@vfrey/contracts/dist/checks.js +1 -0
  262. package/vendor/@vfrey/contracts/dist/credentials/crypto.d.ts +4 -0
  263. package/vendor/@vfrey/contracts/dist/credentials/crypto.js +38 -0
  264. package/vendor/@vfrey/contracts/dist/domain/advice-persona.d.ts +10 -0
  265. package/vendor/@vfrey/contracts/dist/domain/advice-persona.js +24 -0
  266. package/vendor/@vfrey/contracts/dist/domain/backoff.d.ts +13 -0
  267. package/vendor/@vfrey/contracts/dist/domain/backoff.js +27 -0
  268. package/vendor/@vfrey/contracts/dist/domain/cadence.d.ts +29 -0
  269. package/vendor/@vfrey/contracts/dist/domain/cadence.js +95 -0
  270. package/vendor/@vfrey/contracts/dist/domain/creators.d.ts +146 -0
  271. package/vendor/@vfrey/contracts/dist/domain/creators.js +2 -0
  272. package/vendor/@vfrey/contracts/dist/domain/disclosure.d.ts +127 -0
  273. package/vendor/@vfrey/contracts/dist/domain/disclosure.js +250 -0
  274. package/vendor/@vfrey/contracts/dist/domain/errors.d.ts +34 -0
  275. package/vendor/@vfrey/contracts/dist/domain/errors.js +68 -0
  276. package/vendor/@vfrey/contracts/dist/domain/redact.d.ts +1 -0
  277. package/vendor/@vfrey/contracts/dist/domain/redact.js +21 -0
  278. package/vendor/@vfrey/contracts/dist/domain/revenue.d.ts +13 -0
  279. package/vendor/@vfrey/contracts/dist/domain/revenue.js +16 -0
  280. package/vendor/@vfrey/contracts/dist/domain/safety.d.ts +20 -0
  281. package/vendor/@vfrey/contracts/dist/domain/safety.js +61 -0
  282. package/vendor/@vfrey/contracts/dist/domain/similarity.d.ts +13 -0
  283. package/vendor/@vfrey/contracts/dist/domain/similarity.js +100 -0
  284. package/vendor/@vfrey/contracts/dist/domain/templates.d.ts +18 -0
  285. package/vendor/@vfrey/contracts/dist/domain/templates.js +67 -0
  286. package/vendor/@vfrey/contracts/dist/domain/tiktok-chunks.d.ts +19 -0
  287. package/vendor/@vfrey/contracts/dist/domain/tiktok-chunks.js +52 -0
  288. package/vendor/@vfrey/contracts/dist/domain/topics.d.ts +78 -0
  289. package/vendor/@vfrey/contracts/dist/domain/topics.js +4 -0
  290. package/vendor/@vfrey/contracts/dist/domain/types.d.ts +216 -0
  291. package/vendor/@vfrey/contracts/dist/domain/types.js +1 -0
  292. package/vendor/@vfrey/contracts/dist/domain/variation.d.ts +57 -0
  293. package/vendor/@vfrey/contracts/dist/domain/variation.js +278 -0
  294. package/vendor/@vfrey/contracts/dist/events.d.ts +20 -0
  295. package/vendor/@vfrey/contracts/dist/events.js +1 -0
  296. package/vendor/@vfrey/contracts/dist/http.d.ts +11 -0
  297. package/vendor/@vfrey/contracts/dist/http.js +37 -0
  298. package/vendor/@vfrey/contracts/dist/index.d.ts +22 -0
  299. package/vendor/@vfrey/contracts/dist/index.js +22 -0
  300. package/vendor/@vfrey/contracts/dist/log.d.ts +2 -0
  301. package/vendor/@vfrey/contracts/dist/log.js +10 -0
  302. package/vendor/@vfrey/contracts/dist/mail.d.ts +55 -0
  303. package/vendor/@vfrey/contracts/dist/mail.js +1 -0
  304. package/vendor/@vfrey/contracts/package.json +18 -0
  305. package/vendor/@vfrey/ingest/dist/index.d.ts +41 -0
  306. package/vendor/@vfrey/ingest/dist/index.js +221 -0
  307. package/vendor/@vfrey/ingest/dist/parse.d.ts +5 -0
  308. package/vendor/@vfrey/ingest/dist/parse.js +165 -0
  309. package/vendor/@vfrey/ingest/package.json +21 -0
  310. package/vendor/framey/LICENSE +190 -0
  311. package/vendor/framey/NOTICE +15 -0
  312. package/vendor/framey/SOURCE.json +24 -0
  313. package/vendor/framey/STUDIO-SOURCE.json +9 -0
  314. package/vendor/framey/bin/framey-localize-fonts.mjs +12 -0
  315. package/vendor/framey/bin/framey.mjs +16 -0
  316. package/vendor/framey/dist/add-VMJD5KBS.js +75 -0
  317. package/vendor/framey/dist/animatedGifPrep-QPKGJ6PM.js +43 -0
  318. package/vendor/framey/dist/api.d.ts +211 -0
  319. package/vendor/framey/dist/api.js +76 -0
  320. package/vendor/framey/dist/appHistory-WW56FZTT.js +31 -0
  321. package/vendor/framey/dist/asset-WQKGOELE.js +26 -0
  322. package/vendor/framey/dist/audio-RSJWVWRA.js +1936 -0
  323. package/vendor/framey/dist/batchRender-3HPICDCT.js +366 -0
  324. package/vendor/framey/dist/beats-HL2BDUZI.js +273 -0
  325. package/vendor/framey/dist/benchmark-RWCWHI5Z.js +230 -0
  326. package/vendor/framey/dist/browser-ECYET3Q2.js +206 -0
  327. package/vendor/framey/dist/bundleWithLocalizedFonts-ALYBQEQT.js +52 -0
  328. package/vendor/framey/dist/captureCompositionFrame-4DA6SEH2.js +94 -0
  329. package/vendor/framey/dist/catalog-5JVDEUWK.js +979 -0
  330. package/vendor/framey/dist/catch-up-NEBCL5NO.js +106 -0
  331. package/vendor/framey/dist/check-F5N544ML.js +111 -0
  332. package/vendor/framey/dist/checkBrowser-LZ66CMJG.js +110 -0
  333. package/vendor/framey/dist/chunk-2K7Z2HVP.js +372 -0
  334. package/vendor/framey/dist/chunk-2UZQHDM7.js +323 -0
  335. package/vendor/framey/dist/chunk-2X4PQEYM.js +34 -0
  336. package/vendor/framey/dist/chunk-3422KMTD.js +168 -0
  337. package/vendor/framey/dist/chunk-3FYD4YEK.js +72 -0
  338. package/vendor/framey/dist/chunk-3GXQPCJC.js +682 -0
  339. package/vendor/framey/dist/chunk-3LM6YPBR.js +179 -0
  340. package/vendor/framey/dist/chunk-442JNXRM.js +20 -0
  341. package/vendor/framey/dist/chunk-4BNN5FGX.js +182 -0
  342. package/vendor/framey/dist/chunk-4P7NX5BM.js +11532 -0
  343. package/vendor/framey/dist/chunk-4UMPIPCQ.js +88 -0
  344. package/vendor/framey/dist/chunk-4YYJOFKS.js +28 -0
  345. package/vendor/framey/dist/chunk-54HJ63Q2.js +29 -0
  346. package/vendor/framey/dist/chunk-5ETJX6WM.js +89 -0
  347. package/vendor/framey/dist/chunk-5SG54JRS.js +68 -0
  348. package/vendor/framey/dist/chunk-634HSJ3J.js +58 -0
  349. package/vendor/framey/dist/chunk-66LREXGS.js +48 -0
  350. package/vendor/framey/dist/chunk-6BEFEWFB.js +25 -0
  351. package/vendor/framey/dist/chunk-6BNTGNGD.js +286 -0
  352. package/vendor/framey/dist/chunk-6DDPOHMK.js +140 -0
  353. package/vendor/framey/dist/chunk-6GV5XSOR.js +214 -0
  354. package/vendor/framey/dist/chunk-6JR2XUEE.js +127 -0
  355. package/vendor/framey/dist/chunk-73QVATIM.js +362 -0
  356. package/vendor/framey/dist/chunk-7FMUTGOH.js +279 -0
  357. package/vendor/framey/dist/chunk-7JQFJ6JJ.js +291 -0
  358. package/vendor/framey/dist/chunk-AHPGAESX.js +113 -0
  359. package/vendor/framey/dist/chunk-AHX34EFP.js +15 -0
  360. package/vendor/framey/dist/chunk-AJ5CSAEZ.js +487 -0
  361. package/vendor/framey/dist/chunk-B7RJV74O.js +5047 -0
  362. package/vendor/framey/dist/chunk-BL4U6U52.js +254 -0
  363. package/vendor/framey/dist/chunk-BSQ7XANM.js +210 -0
  364. package/vendor/framey/dist/chunk-BZ56MTDX.js +6 -0
  365. package/vendor/framey/dist/chunk-C5BO7PMT.js +282 -0
  366. package/vendor/framey/dist/chunk-CFUCHO4T.js +358 -0
  367. package/vendor/framey/dist/chunk-CZGHFATT.js +31 -0
  368. package/vendor/framey/dist/chunk-DLA44CMS.js +5649 -0
  369. package/vendor/framey/dist/chunk-DPVXBVLL.js +31292 -0
  370. package/vendor/framey/dist/chunk-DQBY7FRR.js +397 -0
  371. package/vendor/framey/dist/chunk-EAMLBAHA.js +154 -0
  372. package/vendor/framey/dist/chunk-EOVYQ3IG.js +143 -0
  373. package/vendor/framey/dist/chunk-EVMY7IPL.js +612 -0
  374. package/vendor/framey/dist/chunk-FG4BBFZI.js +122 -0
  375. package/vendor/framey/dist/chunk-FI4I7CME.js +56 -0
  376. package/vendor/framey/dist/chunk-FLREUEHW.js +2081 -0
  377. package/vendor/framey/dist/chunk-FUFP7A7S.js +1126 -0
  378. package/vendor/framey/dist/chunk-FV3PIKGH.js +56 -0
  379. package/vendor/framey/dist/chunk-FXMKHHPO.js +123 -0
  380. package/vendor/framey/dist/chunk-GGZAM5VH.js +1187 -0
  381. package/vendor/framey/dist/chunk-GKZEVJIB.js +39 -0
  382. package/vendor/framey/dist/chunk-GMECXFAN.js +57 -0
  383. package/vendor/framey/dist/chunk-GNEFDLFB.js +621 -0
  384. package/vendor/framey/dist/chunk-GPMLSOEG.js +19274 -0
  385. package/vendor/framey/dist/chunk-GPYVT5EE.js +59 -0
  386. package/vendor/framey/dist/chunk-H6IEMZEV.js +40 -0
  387. package/vendor/framey/dist/chunk-HEFQCIXR.js +170 -0
  388. package/vendor/framey/dist/chunk-HFQ4CWHA.js +118 -0
  389. package/vendor/framey/dist/chunk-HPDTCOKE.js +304 -0
  390. package/vendor/framey/dist/chunk-HTUHQKDB.js +548 -0
  391. package/vendor/framey/dist/chunk-HU2SPFNG.js +103 -0
  392. package/vendor/framey/dist/chunk-HVW7ABXD.js +19 -0
  393. package/vendor/framey/dist/chunk-IG7NDKXO.js +26 -0
  394. package/vendor/framey/dist/chunk-II3J3WXK.js +246 -0
  395. package/vendor/framey/dist/chunk-IR35BCLK.js +13 -0
  396. package/vendor/framey/dist/chunk-ISN5GRYI.js +20 -0
  397. package/vendor/framey/dist/chunk-IUONB55J.js +669 -0
  398. package/vendor/framey/dist/chunk-IVSUQR2B.js +161 -0
  399. package/vendor/framey/dist/chunk-IXU6PQSW.js +259 -0
  400. package/vendor/framey/dist/chunk-IZCW2NKT.js +29 -0
  401. package/vendor/framey/dist/chunk-JGXJU5PF.js +68 -0
  402. package/vendor/framey/dist/chunk-JHOCK3DG.js +27 -0
  403. package/vendor/framey/dist/chunk-JVBRJMOP.js +121 -0
  404. package/vendor/framey/dist/chunk-K4MJX7SR.js +17 -0
  405. package/vendor/framey/dist/chunk-K4WKGXRC.js +18 -0
  406. package/vendor/framey/dist/chunk-KGPLIH7B.js +127 -0
  407. package/vendor/framey/dist/chunk-KLIKCX6Q.js +63 -0
  408. package/vendor/framey/dist/chunk-KXTKKBOC.js +61 -0
  409. package/vendor/framey/dist/chunk-KZI44OPA.js +185 -0
  410. package/vendor/framey/dist/chunk-LEKZNRKI.js +45 -0
  411. package/vendor/framey/dist/chunk-LFGJWOVA.js +61 -0
  412. package/vendor/framey/dist/chunk-LLMSX6V6.js +17 -0
  413. package/vendor/framey/dist/chunk-LTGTN2TH.js +195 -0
  414. package/vendor/framey/dist/chunk-M2WBOQ2Q.js +54 -0
  415. package/vendor/framey/dist/chunk-MI5FTLYK.js +399 -0
  416. package/vendor/framey/dist/chunk-MLQP2QUF.js +1809 -0
  417. package/vendor/framey/dist/chunk-MMQ52NIZ.js +956 -0
  418. package/vendor/framey/dist/chunk-ND46XKK3.js +742 -0
  419. package/vendor/framey/dist/chunk-NYEXNSHM.js +504 -0
  420. package/vendor/framey/dist/chunk-O4YRB27L.js +57 -0
  421. package/vendor/framey/dist/chunk-O7BGSQ5F.js +92 -0
  422. package/vendor/framey/dist/chunk-OFQWTKPW.js +117 -0
  423. package/vendor/framey/dist/chunk-P5ZBLXJ6.js +91 -0
  424. package/vendor/framey/dist/chunk-P6LJ4Y32.js +4662 -0
  425. package/vendor/framey/dist/chunk-PKZ7RK5N.js +281 -0
  426. package/vendor/framey/dist/chunk-PURHAXFL.js +15 -0
  427. package/vendor/framey/dist/chunk-Q5X2B5WT.js +29 -0
  428. package/vendor/framey/dist/chunk-QAMKOG67.js +248 -0
  429. package/vendor/framey/dist/chunk-R6YBK4XX.js +514 -0
  430. package/vendor/framey/dist/chunk-RGLQURIX.js +2997 -0
  431. package/vendor/framey/dist/chunk-RNV3DM4S.js +3573 -0
  432. package/vendor/framey/dist/chunk-ROEW726S.js +4638 -0
  433. package/vendor/framey/dist/chunk-RQVDTPGD.js +6 -0
  434. package/vendor/framey/dist/chunk-RVZHGOGR.js +26 -0
  435. package/vendor/framey/dist/chunk-RXATE6FZ.js +385 -0
  436. package/vendor/framey/dist/chunk-S3S4TGEH.js +424 -0
  437. package/vendor/framey/dist/chunk-SDYDNHEE.js +11202 -0
  438. package/vendor/framey/dist/chunk-SSWBU67I.js +173 -0
  439. package/vendor/framey/dist/chunk-ST35C4K6.js +28 -0
  440. package/vendor/framey/dist/chunk-SZNTYTIV.js +990 -0
  441. package/vendor/framey/dist/chunk-T2EUWCJE.js +29 -0
  442. package/vendor/framey/dist/chunk-T6AGUTZJ.js +444 -0
  443. package/vendor/framey/dist/chunk-THJALHFJ.js +11131 -0
  444. package/vendor/framey/dist/chunk-TIQB63MX.js +18128 -0
  445. package/vendor/framey/dist/chunk-U242RTCT.js +134 -0
  446. package/vendor/framey/dist/chunk-UJZREAV6.js +3901 -0
  447. package/vendor/framey/dist/chunk-UMD3V7CU.js +264 -0
  448. package/vendor/framey/dist/chunk-UOFAE5RF.js +42 -0
  449. package/vendor/framey/dist/chunk-UTEIUGAZ.js +29 -0
  450. package/vendor/framey/dist/chunk-VAS6HQX3.js +138 -0
  451. package/vendor/framey/dist/chunk-VC76R6W2.js +27 -0
  452. package/vendor/framey/dist/chunk-VFZ7W5W7.js +226 -0
  453. package/vendor/framey/dist/chunk-VHNLZAE2.js +348 -0
  454. package/vendor/framey/dist/chunk-VMC4WSH5.js +278 -0
  455. package/vendor/framey/dist/chunk-VORQIH64.js +108 -0
  456. package/vendor/framey/dist/chunk-VTXFRIHO.js +186 -0
  457. package/vendor/framey/dist/chunk-W2LGJSEN.js +182 -0
  458. package/vendor/framey/dist/chunk-WKBM7NDG.js +32 -0
  459. package/vendor/framey/dist/chunk-WMQNIQDJ.js +2057 -0
  460. package/vendor/framey/dist/chunk-WN4XZC5F.js +504 -0
  461. package/vendor/framey/dist/chunk-WQ6ZXHFQ.js +133 -0
  462. package/vendor/framey/dist/chunk-X7HBSTCZ.js +53 -0
  463. package/vendor/framey/dist/chunk-X7MTZ4T2.js +6 -0
  464. package/vendor/framey/dist/chunk-XPTOJZJF.js +308 -0
  465. package/vendor/framey/dist/chunk-XT6MXC7A.js +6 -0
  466. package/vendor/framey/dist/chunk-XT7X6QCP.js +6 -0
  467. package/vendor/framey/dist/chunk-XTMDWNEC.js +2820 -0
  468. package/vendor/framey/dist/chunk-XUHOIDKG.js +6 -0
  469. package/vendor/framey/dist/chunk-XX7LTW5Y.js +138 -0
  470. package/vendor/framey/dist/chunk-Y3YGTZEG.js +382 -0
  471. package/vendor/framey/dist/chunk-Y5SBSGN7.js +346 -0
  472. package/vendor/framey/dist/chunk-YCMVI4MZ.js +625 -0
  473. package/vendor/framey/dist/chunk-YOR4CTCE.js +261 -0
  474. package/vendor/framey/dist/chunk-YPRBGITP.js +2748 -0
  475. package/vendor/framey/dist/chunk-ZKDMAOFU.js +32 -0
  476. package/vendor/framey/dist/chunk-ZW6DURPF.js +1318 -0
  477. package/vendor/framey/dist/clean-ZJOGDKDM.js +336 -0
  478. package/vendor/framey/dist/cli.js +439 -0
  479. package/vendor/framey/dist/cloudrun-HGJ3B6ZV.js +767 -0
  480. package/vendor/framey/dist/commands/contrast-audit.browser.js +643 -0
  481. package/vendor/framey/dist/commands/layout-audit.browser.js +2914 -0
  482. package/vendor/framey/dist/commands/motion-sample.browser.js +74 -0
  483. package/vendor/framey/dist/commands/motion-signature.browser.js +475 -0
  484. package/vendor/framey/dist/compare-W7UY3BAZ.js +463 -0
  485. package/vendor/framey/dist/compiler-TM3W6GYF.js +136 -0
  486. package/vendor/framey/dist/component-QF5VGYMU.js +176 -0
  487. package/vendor/framey/dist/compositions-XT3PMNDF.js +238 -0
  488. package/vendor/framey/dist/contactSheet-7W6GYHBQ.js +24 -0
  489. package/vendor/framey/dist/deploy-6FJPWKF2.js +299 -0
  490. package/vendor/framey/dist/destroy-HE2RIPKZ.js +57 -0
  491. package/vendor/framey/dist/deterministicFonts-RADD3BSX.js +50 -0
  492. package/vendor/framey/dist/dist-4S2FGGVY.js +422 -0
  493. package/vendor/framey/dist/dist-BE4B2EZE.js +32 -0
  494. package/vendor/framey/dist/dist-EWXJGN63.js +129 -0
  495. package/vendor/framey/dist/docs-VKIRFEEX.js +131 -0
  496. package/vendor/framey/dist/doctor-2UNJ2G7U.js +74 -0
  497. package/vendor/framey/dist/dom-37K6YOH4.js +14 -0
  498. package/vendor/framey/dist/dotEnv-7PZQTVIM.js +54 -0
  499. package/vendor/framey/dist/events-ACY3P2PA.js +76 -0
  500. package/vendor/framey/dist/events-IHB3B2MK.js +69 -0
  501. package/vendor/framey/dist/ffmpeg-DR5LGGSK.js +63 -0
  502. package/vendor/framey/dist/figma-BODVUPHB.js +63 -0
  503. package/vendor/framey/dist/fontData.generated-NXAOI4GH.js +13 -0
  504. package/vendor/framey/dist/fontLocalizeCli.js +142 -0
  505. package/vendor/framey/dist/gpuPolicy-XLEXORZY.js +49 -0
  506. package/vendor/framey/dist/grade-compare-GAXFQ74C.js +661 -0
  507. package/vendor/framey/dist/gsapParser-IEUSLYDJ.js +2885 -0
  508. package/vendor/framey/dist/gsapParserAcorn-LZJKCFQI.js +30 -0
  509. package/vendor/framey/dist/help-VCB5X2HS.js +184 -0
  510. package/vendor/framey/dist/history-ENGZEVFT.js +471 -0
  511. package/vendor/framey/dist/hyperframe.manifest.json +22 -0
  512. package/vendor/framey/dist/hyperframe.runtime.iife.js +1132 -0
  513. package/vendor/framey/dist/hyperframes-player.global.js +478 -0
  514. package/vendor/framey/dist/hyperframes-slideshow.global.js +148 -0
  515. package/vendor/framey/dist/info-WPCJHBMU.js +182 -0
  516. package/vendor/framey/dist/init-G4WGLYGD.js +1176 -0
  517. package/vendor/framey/dist/inspect-5IQ6CNEQ.js +106 -0
  518. package/vendor/framey/dist/installer-ML4HWUV7.js +40 -0
  519. package/vendor/framey/dist/keyframes-Q6XJO7VW.js +2755 -0
  520. package/vendor/framey/dist/lambda-A7JC74JF.js +468 -0
  521. package/vendor/framey/dist/layout-YET6XNXA.js +95 -0
  522. package/vendor/framey/dist/lint-I7FZN2VJ.js +162 -0
  523. package/vendor/framey/dist/lintProject-PDB3UN72.js +30 -0
  524. package/vendor/framey/dist/manager-CD6LJ7ZN.js +45 -0
  525. package/vendor/framey/dist/manager-WA4F2GST.js +67 -0
  526. package/vendor/framey/dist/media-treatment-BXYS4WVA.js +1030 -0
  527. package/vendor/framey/dist/media-use-LWH3MANK.js +113 -0
  528. package/vendor/framey/dist/models-K363FYM4.js +195 -0
  529. package/vendor/framey/dist/motionShot-GPAVWXLH.js +640 -0
  530. package/vendor/framey/dist/normalize-FASIPBUM.js +24 -0
  531. package/vendor/framey/dist/normalize-audio-VDWYRHN6.js +268 -0
  532. package/vendor/framey/dist/open-E3TB6P6J.js +128 -0
  533. package/vendor/framey/dist/parakeetRunner-UP34UOI2.js +58 -0
  534. package/vendor/framey/dist/pipeline-VXIUYEBU.js +64 -0
  535. package/vendor/framey/dist/play-BUTDQ4DV.js +353 -0
  536. package/vendor/framey/dist/policies-OLDYGFK5.js +309 -0
  537. package/vendor/framey/dist/preflight-2KZ2GWAZ.js +55 -0
  538. package/vendor/framey/dist/present-GXYSM7NX.js +353 -0
  539. package/vendor/framey/dist/preview-EKZ33JOJ.js +1910 -0
  540. package/vendor/framey/dist/producer-SKU5EV3J.js +13 -0
  541. package/vendor/framey/dist/progress-ZWB4Z4ET.js +76 -0
  542. package/vendor/framey/dist/projectConfig-3MZAYVTS.js +60 -0
  543. package/vendor/framey/dist/publication-DTKWNF74.js +33 -0
  544. package/vendor/framey/dist/remove-background-OY5L7XN2.js +265 -0
  545. package/vendor/framey/dist/render-CDV4GDFX.js +187 -0
  546. package/vendor/framey/dist/render-YE5YAMOD.js +2620 -0
  547. package/vendor/framey/dist/render-batch-ZAMFPCLL.js +274 -0
  548. package/vendor/framey/dist/renderSetupWorker.js +120 -0
  549. package/vendor/framey/dist/resolver-D5BIPSEW.js +42 -0
  550. package/vendor/framey/dist/runtimeVersion.js +18 -0
  551. package/vendor/framey/dist/sam-WFZXI4F7.js +23 -0
  552. package/vendor/framey/dist/shaderTransitionWorker.js +44 -0
  553. package/vendor/framey/dist/sherpa-RQWLV7I3.js +79 -0
  554. package/vendor/framey/dist/sherpaWorker.js +84 -0
  555. package/vendor/framey/dist/sites-AMOVABTK.js +54 -0
  556. package/vendor/framey/dist/skill-ZHVLH7KX.js +15 -0
  557. package/vendor/framey/dist/slideshow-SJGK4RQS.js +24 -0
  558. package/vendor/framey/dist/snapshot-TUXL6LBQ.js +1515 -0
  559. package/vendor/framey/dist/src-JHQGB2S6.js +215 -0
  560. package/vendor/framey/dist/src-Z5PGEMXB.js +532 -0
  561. package/vendor/framey/dist/state-B6H3WHCF.js +28 -0
  562. package/vendor/framey/dist/staticProjectServer-DFVZOUGI.js +63 -0
  563. package/vendor/framey/dist/studio/assets/hyperframes-player-DLaKjw0L.js +478 -0
  564. package/vendor/framey/dist/studio/assets/index-BX3KHhGX.js +71 -0
  565. package/vendor/framey/dist/studio/assets/index-CYbvOVp-.css +1 -0
  566. package/vendor/framey/dist/studio/assets/index-Dp3QEUGL.js +402 -0
  567. package/vendor/framey/dist/studio/assets/index-qrTAXbqc.js +531 -0
  568. package/vendor/framey/dist/studio/favicon.svg +14 -0
  569. package/vendor/framey/dist/studio/icons/timeline/audio.svg +7 -0
  570. package/vendor/framey/dist/studio/icons/timeline/captions.svg +5 -0
  571. package/vendor/framey/dist/studio/icons/timeline/composition.svg +12 -0
  572. package/vendor/framey/dist/studio/icons/timeline/image.svg +18 -0
  573. package/vendor/framey/dist/studio/icons/timeline/music.svg +10 -0
  574. package/vendor/framey/dist/studio/icons/timeline/text.svg +3 -0
  575. package/vendor/framey/dist/studio/index.html +23 -0
  576. package/vendor/framey/dist/studio-api-2NECGRMB.js +179 -0
  577. package/vendor/framey/dist/studioSelectionClient-IUUPKUHZ.js +25 -0
  578. package/vendor/framey/dist/studioServer-N2OPUMOQ.js +1569 -0
  579. package/vendor/framey/dist/synthesize-PKTB5ATG.js +183 -0
  580. package/vendor/framey/dist/system-7F3UEHQT.js +27 -0
  581. package/vendor/framey/dist/telemetry-DQGPEKM6.js +145 -0
  582. package/vendor/framey/dist/telemetry-UN55N6U6.js +77 -0
  583. package/vendor/framey/dist/timeline-LHUUMK63.js +1295 -0
  584. package/vendor/framey/dist/tokens-OLECWDFK.js +92 -0
  585. package/vendor/framey/dist/transcribe-O7HQKMIV.js +331 -0
  586. package/vendor/framey/dist/transcribe-UJESPBT5.js +76 -0
  587. package/vendor/framey/dist/tts-YCCQHZD4.js +234 -0
  588. package/vendor/framey/dist/urlDownloader-H2LXLG4U.js +48 -0
  589. package/vendor/framey/dist/usage-HG4WMM7A.js +2167 -0
  590. package/vendor/framey/dist/validate-F2XMN6EV.js +87 -0
  591. package/vendor/framey/dist/vendor/npm/gsap@3.15.0/GSAP-LICENSE.txt +8 -0
  592. package/vendor/framey/dist/vendor/npm/gsap@3.15.0/dist/CustomEase.min.js +11 -0
  593. package/vendor/framey/dist/vendor/npm/gsap@3.15.0/dist/MotionPathPlugin.min.js +11 -0
  594. package/vendor/framey/dist/vendor/npm/gsap@3.15.0/dist/gsap.min.js +11 -0
  595. package/vendor/framey/dist/warmCheck.js +220 -0
  596. package/vendor/framey/dist/warmCheckClient.js +139 -0
  597. package/vendor/framey/dist/workspaceBuildCheck-XYD2YTFW.js +133 -0
  598. package/vendor/framey-player/LICENSE +190 -0
  599. package/vendor/framey-player/NOTICE +16 -0
  600. package/vendor/framey-player/SOURCE.json +6 -0
  601. package/vendor/framey-player/hyperframes-player.global.js +478 -0
  602. package/vendor/framey.pin +1 -0
  603. package/bin/index.js +0 -3
@@ -0,0 +1,1910 @@
1
+ import { createRequire as __hf_createRequire } from "node:module";
2
+ import { fileURLToPath as __hf_fileURLToPath } from "node:url";
3
+ import { dirname as __hf_dirname } from "node:path";
4
+ var require = __hf_createRequire(import.meta.url);
5
+ var __filename = __hf_fileURLToPath(import.meta.url);
6
+ var __dirname = __hf_dirname(__filename);
7
+ import {
8
+ formatLintStartupMessage
9
+ } from "./chunk-JGXJU5PF.js";
10
+ import {
11
+ openBrowser,
12
+ parseRemoteDebuggingPort,
13
+ validateRemoteDebuggingPortDeps
14
+ } from "./chunk-LFGJWOVA.js";
15
+ import {
16
+ desktopHint,
17
+ insideHostApp
18
+ } from "./chunk-VTXFRIHO.js";
19
+ import "./chunk-VFZ7W5W7.js";
20
+ import {
21
+ buildNpxCommand
22
+ } from "./chunk-6BEFEWFB.js";
23
+ import {
24
+ R,
25
+ ft,
26
+ ge
27
+ } from "./chunk-WMQNIQDJ.js";
28
+ import {
29
+ resolveProject,
30
+ resolveProjectOrThrow
31
+ } from "./chunk-O7BGSQ5F.js";
32
+ import "./chunk-P5ZBLXJ6.js";
33
+ import {
34
+ resolveAutoProxy
35
+ } from "./chunk-4BNN5FGX.js";
36
+ import "./chunk-XT7X6QCP.js";
37
+ import "./chunk-4YYJOFKS.js";
38
+ import "./chunk-HVW7ABXD.js";
39
+ import {
40
+ MAX_PORT_SCAN,
41
+ PreviewServerPortMismatchError,
42
+ activeServerOnPort,
43
+ findPortAndServe,
44
+ killActiveServers,
45
+ scanActiveServers
46
+ } from "./chunk-DQBY7FRR.js";
47
+ import {
48
+ resolveLocalBrowserGpuMode
49
+ } from "./chunk-WKBM7NDG.js";
50
+ import "./chunk-XX7LTW5Y.js";
51
+ import "./chunk-JHOCK3DG.js";
52
+ import "./chunk-XPTOJZJF.js";
53
+ import "./chunk-RGLQURIX.js";
54
+ import "./chunk-P6LJ4Y32.js";
55
+ import "./chunk-GMECXFAN.js";
56
+ import "./chunk-EOVYQ3IG.js";
57
+ import "./chunk-GNEFDLFB.js";
58
+ import "./chunk-2UZQHDM7.js";
59
+ import "./chunk-NYEXNSHM.js";
60
+ import {
61
+ defineCommand
62
+ } from "./chunk-S3S4TGEH.js";
63
+ import "./chunk-54HJ63Q2.js";
64
+ import {
65
+ isDevMode
66
+ } from "./chunk-ISN5GRYI.js";
67
+ import {
68
+ c
69
+ } from "./chunk-VORQIH64.js";
70
+ import {
71
+ requestCliExit,
72
+ setCommandExitCode
73
+ } from "./chunk-JVBRJMOP.js";
74
+ import "./chunk-TIQB63MX.js";
75
+ import "./chunk-IZCW2NKT.js";
76
+ import "./chunk-RNV3DM4S.js";
77
+ import "./chunk-DLA44CMS.js";
78
+ import "./chunk-UJZREAV6.js";
79
+ import "./chunk-VC76R6W2.js";
80
+ import "./chunk-X7HBSTCZ.js";
81
+ import "./chunk-B7RJV74O.js";
82
+ import "./chunk-DPVXBVLL.js";
83
+ import "./chunk-OFQWTKPW.js";
84
+ import "./chunk-634HSJ3J.js";
85
+ import "./chunk-FXMKHHPO.js";
86
+ import "./chunk-RQVDTPGD.js";
87
+ import "./chunk-AHX34EFP.js";
88
+ import {
89
+ isProcessDescendant,
90
+ killOrphanedProcesses,
91
+ killProcessTree,
92
+ processIdentity
93
+ } from "./chunk-LTGTN2TH.js";
94
+ import {
95
+ runRenderSetupWorker
96
+ } from "./chunk-BL4U6U52.js";
97
+ import {
98
+ normalizeErrorMessage
99
+ } from "./chunk-T2EUWCJE.js";
100
+ import "./chunk-T6AGUTZJ.js";
101
+ import "./chunk-XT6MXC7A.js";
102
+ import "./chunk-K4MJX7SR.js";
103
+ import "./chunk-4UMPIPCQ.js";
104
+ import "./chunk-4P7NX5BM.js";
105
+ import "./chunk-VAS6HQX3.js";
106
+ import "./chunk-6BNTGNGD.js";
107
+ import "./chunk-CZGHFATT.js";
108
+ import "./chunk-PKZ7RK5N.js";
109
+ import "./chunk-W2LGJSEN.js";
110
+ import "./chunk-MMQ52NIZ.js";
111
+ import "./chunk-BSQ7XANM.js";
112
+ import "./chunk-SDYDNHEE.js";
113
+ import "./chunk-RXATE6FZ.js";
114
+ import "./chunk-3422KMTD.js";
115
+ import {
116
+ terminateProcessTree
117
+ } from "./chunk-KGPLIH7B.js";
118
+ import "./chunk-3GXQPCJC.js";
119
+ import "./chunk-M2WBOQ2Q.js";
120
+
121
+ // src/commands/preview.ts
122
+ import { spawn } from "child_process";
123
+ import { existsSync as existsSync2, lstatSync, mkdirSync as mkdirSync2, readlinkSync, symlinkSync, unlinkSync } from "fs";
124
+ import { resolve as resolve2, dirname as dirname2, basename, join as join2 } from "path";
125
+ import { fileURLToPath } from "url";
126
+ import { createRequire } from "module";
127
+
128
+ // src/utils/studioProxyEnv.ts
129
+ function studioProxyEnv(autoProxy, baseEnv = process.env, preview) {
130
+ return {
131
+ ...baseEnv,
132
+ HYPERFRAMES_AUTO_PROXY: autoProxy ? "true" : "false",
133
+ ...preview ? {
134
+ HYPERFRAMES_PREVIEW_PROJECT_DIR: preview.projectDir,
135
+ HYPERFRAMES_PREVIEW_PROJECT_NAME: preview.projectName,
136
+ ...preview.browserGpuMode ? { HYPERFRAMES_PREVIEW_BROWSER_GPU_MODE: preview.browserGpuMode } : {}
137
+ } : {}
138
+ };
139
+ }
140
+
141
+ // src/commands/previewLifecycle.ts
142
+ import { spawn as nodeSpawn } from "child_process";
143
+ import { createHash } from "crypto";
144
+ import {
145
+ closeSync,
146
+ existsSync,
147
+ mkdirSync,
148
+ openSync,
149
+ readFileSync,
150
+ readdirSync,
151
+ renameSync,
152
+ rmSync,
153
+ writeFileSync
154
+ } from "fs";
155
+ import { homedir } from "os";
156
+ import { dirname, join, resolve } from "path";
157
+ import { stripVTControlCharacters } from "util";
158
+ var PreviewPortUnavailableError = class extends Error {
159
+ requestedPort;
160
+ boundPort;
161
+ constructor(requestedPort, boundPort) {
162
+ super(
163
+ `Port ${requestedPort} is already in use; the background preview would have started on port ${boundPort} instead. Free port ${requestedPort}, pick another --port, or omit --port to accept the next free port.`
164
+ );
165
+ this.name = "PreviewPortUnavailableError";
166
+ this.requestedPort = requestedPort;
167
+ this.boundPort = boundPort;
168
+ }
169
+ };
170
+ function defaultStateHome() {
171
+ return process.env.XDG_STATE_HOME || join(homedir(), ".local", "state");
172
+ }
173
+ function normalized(path) {
174
+ const resolved = resolve(path).replace(/\\/g, "/");
175
+ return process.platform === "win32" ? resolved.toLowerCase() : resolved;
176
+ }
177
+ function sessionDirectory(stateHome = defaultStateHome()) {
178
+ return join(stateHome, "hyperframes", "previews");
179
+ }
180
+ function previewSessionPath(projectDir, stateHome = defaultStateHome()) {
181
+ const key = createHash("sha256").update(normalized(projectDir)).digest("hex").slice(0, 16);
182
+ return join(sessionDirectory(stateHome), `${key}.json`);
183
+ }
184
+ function previewLogPath(projectDir, stateHome = defaultStateHome()) {
185
+ return previewSessionPath(projectDir, stateHome).replace(/\.json$/, ".log");
186
+ }
187
+ function writePreviewSession(session, stateHome = defaultStateHome()) {
188
+ const path = previewSessionPath(session.projectDir, stateHome);
189
+ mkdirSync(dirname(path), { recursive: true });
190
+ const temporary = `${path}.${process.pid}.tmp`;
191
+ try {
192
+ writeFileSync(temporary, `${JSON.stringify(session, null, 2)}
193
+ `, { mode: 384 });
194
+ renameSync(temporary, path);
195
+ } finally {
196
+ rmSync(temporary, { force: true });
197
+ }
198
+ }
199
+ function readPreviewSession(projectDir, stateHome = defaultStateHome()) {
200
+ const path = previewSessionPath(projectDir, stateHome);
201
+ if (!existsSync(path)) return null;
202
+ try {
203
+ const parsed = JSON.parse(readFileSync(path, "utf8"));
204
+ if (!Number.isInteger(parsed.pid) || parsed.pid <= 0 || normalized(parsed.projectDir) !== normalized(projectDir)) {
205
+ throw new Error("invalid preview session");
206
+ }
207
+ return parsed;
208
+ } catch {
209
+ rmSync(path, { force: true });
210
+ return null;
211
+ }
212
+ }
213
+ function hasValidPreviewProcess(session) {
214
+ return Number.isInteger(session.pid) && session.pid > 0;
215
+ }
216
+ function hasValidPreviewEndpoint(session) {
217
+ return Number.isInteger(session.port) && session.port > 0 && session.port <= 65535;
218
+ }
219
+ function matchesPreviewSessionFile(session, path, stateHome) {
220
+ return typeof session.projectDir === "string" && typeof session.logPath === "string" && previewSessionPath(session.projectDir, stateHome) === path;
221
+ }
222
+ function readPreviewSessionFile(path, stateHome) {
223
+ try {
224
+ const parsed = JSON.parse(readFileSync(path, "utf8"));
225
+ if (!hasValidPreviewProcess(parsed) || !hasValidPreviewEndpoint(parsed) || !matchesPreviewSessionFile(parsed, path, stateHome)) {
226
+ throw new Error("invalid preview session");
227
+ }
228
+ return parsed;
229
+ } catch {
230
+ rmSync(path, { force: true });
231
+ return null;
232
+ }
233
+ }
234
+ function removePreviewSession(projectDir, stateHome = defaultStateHome()) {
235
+ rmSync(previewSessionPath(projectDir, stateHome), { force: true });
236
+ }
237
+ function matchingServer(servers, projectDir, browserGpuMode) {
238
+ return policyMatchingServers(servers, projectDir, browserGpuMode)[0] ?? null;
239
+ }
240
+ function policyMatchingServers(servers, projectDir, browserGpuMode) {
241
+ return sameProjectServers(servers, projectDir).filter(
242
+ (server) => browserGpuMode === void 0 || server.browserGpuMode === browserGpuMode
243
+ );
244
+ }
245
+ function matchingServerAtPort(servers, projectDir, port) {
246
+ return matchingServer(
247
+ servers.filter((server) => server.port === port),
248
+ projectDir
249
+ );
250
+ }
251
+ function sameProjectServers(servers, projectDir) {
252
+ const project = normalized(projectDir);
253
+ return servers.filter((server) => normalized(server.projectDir) === project);
254
+ }
255
+ function sameProjectPorts(servers, projectDir) {
256
+ return new Set(sameProjectServers(servers, projectDir).map((server) => server.port));
257
+ }
258
+ async function stopProcess(pid) {
259
+ await terminateProcessTree(pid);
260
+ }
261
+ var delay = (ms) => new Promise((done) => setTimeout(done, ms));
262
+ function spawnDetachedPreview(projectDir, stateHome, dependencies) {
263
+ const logPath = previewLogPath(projectDir, stateHome);
264
+ mkdirSync(dirname(logPath), { recursive: true });
265
+ const logFd = openSync(logPath, "a", 384);
266
+ const spawn2 = dependencies.spawn ?? nodeSpawn;
267
+ let child;
268
+ try {
269
+ child = spawn2(
270
+ dependencies.execPath ?? process.execPath,
271
+ buildBackgroundPreviewArgs(dependencies.argv ?? process.argv.slice(1)),
272
+ {
273
+ detached: true,
274
+ windowsHide: true,
275
+ stdio: ["ignore", logFd, logFd],
276
+ env: process.env
277
+ }
278
+ );
279
+ } finally {
280
+ closeSync(logFd);
281
+ }
282
+ if (!child.pid) throw new Error("background preview child did not report a PID");
283
+ let exit = null;
284
+ child.once?.("exit", (code, signal) => {
285
+ exit = signal ? `signal ${signal}` : `exit code ${code}`;
286
+ });
287
+ child.unref();
288
+ return {
289
+ pid: child.pid,
290
+ wrapperIdentity: (dependencies.identity ?? processIdentity)(child.pid) ?? void 0,
291
+ logPath,
292
+ exitedWith: () => exit
293
+ };
294
+ }
295
+ function startedServer(servers, projectDir, preLaunchPorts, launchedPid, dependencies) {
296
+ const isDescendant = dependencies.isDescendant ?? isProcessDescendant;
297
+ const ours = (server) => {
298
+ const pid = Number(server.pid);
299
+ return pid === launchedPid || isDescendant(pid, launchedPid);
300
+ };
301
+ const candidates = servers.filter((server) => !preLaunchPorts.has(server.port) && ours(server));
302
+ return matchingServer(candidates, projectDir, dependencies.browserGpuMode);
303
+ }
304
+ function buildBackgroundPreviewArgs(argv) {
305
+ const filtered = argv.filter(
306
+ (arg) => arg !== "--background" && !arg.startsWith("--background=") && arg !== "--foreground" && !arg.startsWith("--foreground=") && arg !== "--open" && arg !== "--no-open" && arg !== "--force-new" && arg !== "--json"
307
+ );
308
+ return [...filtered, "--foreground", "--no-open", "--force-new"];
309
+ }
310
+ function statusServer(servers, projectDir, saved, preferredPort) {
311
+ const candidates = sameProjectServers(servers, projectDir);
312
+ return candidates.find((server) => server.port === preferredPort) ?? candidates.find((server) => server.port === saved?.port) ?? candidates[0] ?? null;
313
+ }
314
+ function isCurrentPreviewWrapper(saved, dependencies) {
315
+ return !!saved.wrapperIdentity && (dependencies.identity ?? processIdentity)(saved.pid) === saved.wrapperIdentity;
316
+ }
317
+ function managedStatusLogPath(server, saved, pid, dependencies) {
318
+ if (!saved || saved.port !== server.port || server.pidSource !== "os") {
319
+ return void 0;
320
+ }
321
+ if (!isCurrentPreviewWrapper(saved, dependencies)) {
322
+ return void 0;
323
+ }
324
+ const isDescendant = dependencies.isDescendant ?? isProcessDescendant;
325
+ return pid === saved.pid || isDescendant(pid, saved.pid) ? saved.logPath : void 0;
326
+ }
327
+ async function readBackgroundPreviewStatus(projectDir, startPort, dependencies = {}) {
328
+ const { stateHome, saved, scanned } = await readPreviewLifecycleState(
329
+ projectDir,
330
+ startPort,
331
+ dependencies
332
+ );
333
+ const server = statusServer(scanned, projectDir, saved, dependencies.preferredPort);
334
+ if (server) {
335
+ const listenerPid = Number(server.pid);
336
+ const pid = Number.isInteger(listenerPid) && listenerPid > 0 ? listenerPid : null;
337
+ const logPath = pid === null ? void 0 : managedStatusLogPath(server, saved, pid, dependencies);
338
+ return {
339
+ pid,
340
+ port: server.port,
341
+ projectDir: resolve(projectDir),
342
+ ...logPath ? { logPath } : {}
343
+ };
344
+ }
345
+ if (saved && wrapperProcessIsAlive(saved, dependencies)) return null;
346
+ removePreviewSession(projectDir, stateHome);
347
+ return null;
348
+ }
349
+ function processIsSignalable(pid) {
350
+ try {
351
+ process.kill(pid, 0);
352
+ return true;
353
+ } catch (error) {
354
+ return error?.code === "EPERM";
355
+ }
356
+ }
357
+ function wrapperProcessIsAlive(saved, dependencies) {
358
+ if (!saved.wrapperIdentity) return false;
359
+ const signalable = dependencies.isSignalable ?? processIsSignalable;
360
+ if (!signalable(saved.pid)) return false;
361
+ const identity = (dependencies.identity ?? processIdentity)(saved.pid);
362
+ if (identity === null) return true;
363
+ return identity === saved.wrapperIdentity;
364
+ }
365
+ async function listBackgroundPreviewStatuses(dependencies = {}) {
366
+ const stateHome = dependencies.stateHome ?? defaultStateHome();
367
+ const directory = sessionDirectory(stateHome);
368
+ let files;
369
+ try {
370
+ files = readdirSync(directory).filter((name) => name.endsWith(".json")).map((name) => join(directory, name));
371
+ } catch {
372
+ return [];
373
+ }
374
+ const saved = files.map((path) => readPreviewSessionFile(path, stateHome)).filter((session) => session !== null);
375
+ const statuses = await Promise.all(
376
+ saved.map(
377
+ (session) => readBackgroundPreviewStatus(session.projectDir, session.port, {
378
+ ...dependencies,
379
+ stateHome
380
+ })
381
+ )
382
+ );
383
+ return statuses.filter((status) => status !== null);
384
+ }
385
+ function readyPreviewSession(server, pid, wrapperIdentity, projectDir, logPath, dependencies) {
386
+ const identity = wrapperIdentity ?? (dependencies.identity ?? processIdentity)(pid) ?? void 0;
387
+ const liveServerPid = Number(server.pid);
388
+ return {
389
+ session: {
390
+ pid,
391
+ wrapperIdentity: identity,
392
+ port: server.port,
393
+ projectDir: resolve(projectDir),
394
+ logPath
395
+ },
396
+ publicPid: Number.isInteger(liveServerPid) && liveServerPid > 0 ? liveServerPid : pid
397
+ };
398
+ }
399
+ function ownedStopTargetPid(saved, liveServerPid, dependencies) {
400
+ if (!saved?.wrapperIdentity) return liveServerPid;
401
+ const identity = dependencies.identity ?? processIdentity;
402
+ if (identity(saved.pid) !== saved.wrapperIdentity) return liveServerPid;
403
+ if (saved.pid === liveServerPid) return saved.pid;
404
+ const isDescendant = dependencies.isDescendant ?? isProcessDescendant;
405
+ return isDescendant(liveServerPid, saved.pid) ? saved.pid : liveServerPid;
406
+ }
407
+ async function stopOwnedPreviewBeforeReplacement(owned, projectDir, dependencies) {
408
+ if (!owned) return;
409
+ await stopBackgroundPreview(projectDir, owned.port, dependencies);
410
+ }
411
+ function savedOwnedPreview(servers, saved, projectDir) {
412
+ if (!saved) return null;
413
+ const savedPortServers = servers.filter((server) => server.port === saved.port);
414
+ return matchingServer(savedPortServers, projectDir);
415
+ }
416
+ function isPortInScanRange(port, scanStart) {
417
+ return port >= scanStart && port < scanStart + MAX_PORT_SCAN;
418
+ }
419
+ async function addSavedPortServer(scanned, savedPort, scanStart, dependencies) {
420
+ if (savedPort === void 0 || isPortInScanRange(savedPort, scanStart)) return;
421
+ const server = await (dependencies.probe ?? activeServerOnPort)(savedPort);
422
+ if (server) scanned.push(server);
423
+ }
424
+ async function readPreviewLifecycleState(projectDir, startPort, dependencies) {
425
+ const scan = dependencies.scan ?? scanActiveServers;
426
+ const stateHome = dependencies.stateHome ?? defaultStateHome();
427
+ const saved = readPreviewSession(projectDir, stateHome);
428
+ const scanStart = dependencies.preferredPort ?? saved?.port ?? startPort;
429
+ const scanned = await scan(scanStart);
430
+ await addSavedPortServer(scanned, saved?.port, scanStart, dependencies);
431
+ return { scan, stateHome, saved, scanned };
432
+ }
433
+ function unmetPreferredPort(port, preferredPort) {
434
+ return preferredPort !== void 0 && port !== preferredPort ? preferredPort : void 0;
435
+ }
436
+ function reuseExistingPreview(reusableExisting, candidates, dependencies) {
437
+ if (!reusableExisting || dependencies.forceNew) return null;
438
+ const unmet = unmetPreferredPort(reusableExisting.port, dependencies.preferredPort);
439
+ if (unmet !== void 0) {
440
+ throw new PreviewServerPortMismatchError(
441
+ unmet,
442
+ candidates,
443
+ ` To start one on port ${unmet} instead, add --force-new or run --stop first.`
444
+ );
445
+ }
446
+ return {
447
+ type: "reused",
448
+ port: reusableExisting.port,
449
+ pid: reusableExisting.pid ? Number(reusableExisting.pid) : null,
450
+ logPath: null
451
+ };
452
+ }
453
+ async function startBackgroundPreview(projectDir, startPort, dependencies = {}) {
454
+ const launchStart = dependencies.preferredPort ?? startPort;
455
+ const { scan, stateHome, saved, scanned } = await readPreviewLifecycleState(
456
+ projectDir,
457
+ startPort,
458
+ dependencies
459
+ );
460
+ const candidates = policyMatchingServers(scanned, projectDir, dependencies.browserGpuMode);
461
+ const onPreferredPort = candidates.find((server2) => server2.port === dependencies.preferredPort) ?? null;
462
+ const requestedExisting = candidates[0] ?? null;
463
+ const ownedExisting = savedOwnedPreview(scanned, saved, projectDir);
464
+ const reusableOwned = ownedExisting ? matchingServer([ownedExisting], projectDir, dependencies.browserGpuMode) : null;
465
+ const reusableExisting = onPreferredPort ?? reusableOwned ?? (ownedExisting ? null : requestedExisting);
466
+ const reused = reuseExistingPreview(reusableExisting, candidates, dependencies);
467
+ if (reused) return reused;
468
+ await stopOwnedPreviewBeforeReplacement(ownedExisting, projectDir, dependencies);
469
+ const preLaunchPorts = sameProjectPorts(await scan(launchStart), projectDir);
470
+ const { pid, wrapperIdentity, logPath, exitedWith } = spawnDetachedPreview(
471
+ projectDir,
472
+ stateHome,
473
+ dependencies
474
+ );
475
+ const kill = dependencies.kill ?? stopProcess;
476
+ const server = await awaitStartedServer(
477
+ projectDir,
478
+ launchStart,
479
+ preLaunchPorts,
480
+ pid,
481
+ exitedWith,
482
+ dependencies
483
+ );
484
+ if (!server) {
485
+ const exit = exitedWith();
486
+ if (exit) {
487
+ throw new Error(
488
+ `background preview exited (${exit}) before it was ready; see ${logPath}${logTail(logPath)}`
489
+ );
490
+ }
491
+ await kill(pid);
492
+ throw new Error(`background preview did not become ready; see ${logPath}`);
493
+ }
494
+ const unmet = unmetPreferredPort(server.port, dependencies.preferredPort);
495
+ if (unmet !== void 0) {
496
+ await kill(pid);
497
+ if (!await awaitServerGone(projectDir, server.port, dependencies)) {
498
+ throw new Error(
499
+ `background preview on port ${server.port} did not stop after failing to bind port ${unmet}; see ${logPath}`
500
+ );
501
+ }
502
+ throw new PreviewPortUnavailableError(unmet, server.port);
503
+ }
504
+ const ready = readyPreviewSession(
505
+ server,
506
+ pid,
507
+ wrapperIdentity,
508
+ projectDir,
509
+ logPath,
510
+ dependencies
511
+ );
512
+ writePreviewSession(ready.session, stateHome);
513
+ return {
514
+ type: "started",
515
+ ...ready.session,
516
+ pid: ready.publicPid
517
+ };
518
+ }
519
+ function logTail(logPath) {
520
+ try {
521
+ const text = stripVTControlCharacters(readFileSync(logPath, "utf8"));
522
+ const lines = text.trimEnd().split("\n").slice(-5);
523
+ return lines.join("").trim() ? `
524
+ ${lines.join("\n")}` : "";
525
+ } catch {
526
+ return "";
527
+ }
528
+ }
529
+ async function awaitStartedServer(projectDir, startPort, preLaunchPorts, launchedPid, exitedWith, dependencies) {
530
+ const scan = dependencies.scan ?? scanActiveServers;
531
+ const sleep = dependencies.sleep ?? delay;
532
+ for (let attempt = 0; attempt < 50 && !exitedWith(); attempt++) {
533
+ const server = startedServer(
534
+ await scan(startPort),
535
+ projectDir,
536
+ preLaunchPorts,
537
+ launchedPid,
538
+ dependencies
539
+ );
540
+ if (server) return server;
541
+ await sleep(200);
542
+ }
543
+ return null;
544
+ }
545
+ async function stopBackgroundPreview(projectDir, startPort, dependencies = {}) {
546
+ const stateHome = dependencies.stateHome ?? defaultStateHome();
547
+ const saved = readPreviewSession(projectDir, stateHome);
548
+ const scan = dependencies.scan ?? scanActiveServers;
549
+ const server = saved ? await probeMatchingServerAtPort(projectDir, saved.port, dependencies) : matchingServer(await scan(dependencies.preferredPort ?? startPort), projectDir);
550
+ if (!server) {
551
+ removePreviewSession(projectDir, stateHome);
552
+ return false;
553
+ }
554
+ const pid = Number(server.pid);
555
+ if (!Number.isInteger(pid) || pid <= 0) {
556
+ throw new Error(`preview ownership could not be proven for ${resolve(projectDir)}`);
557
+ }
558
+ const kill = dependencies.kill ?? stopProcess;
559
+ await kill(ownedStopTargetPid(saved, pid, dependencies));
560
+ if (!await awaitServerGone(projectDir, server.port, dependencies)) {
561
+ throw new Error(`background preview did not stop for ${resolve(projectDir)}`);
562
+ }
563
+ removePreviewSession(projectDir, stateHome);
564
+ return true;
565
+ }
566
+ async function probeMatchingServerAtPort(projectDir, port, dependencies) {
567
+ const server = await (dependencies.probe ?? activeServerOnPort)(port);
568
+ return matchingServerAtPort(server ? [server] : [], projectDir, port);
569
+ }
570
+ async function awaitServerGone(projectDir, port, dependencies) {
571
+ const sleep = dependencies.sleep ?? delay;
572
+ for (let attempt = 0; attempt < 25; attempt++) {
573
+ if (!await probeMatchingServerAtPort(projectDir, port, dependencies)) return true;
574
+ await sleep(100);
575
+ }
576
+ return false;
577
+ }
578
+
579
+ // src/commands/previewLifecycleOutput.ts
580
+ function lifecyclePayload(operation, result) {
581
+ return { schemaVersion: 1, operation, ok: true, result };
582
+ }
583
+ function lifecycleFailurePayload(operation, code, message) {
584
+ return { schemaVersion: 1, operation, ok: false, error: { code, message } };
585
+ }
586
+ function writeLifecycleJson(payload) {
587
+ console.log(JSON.stringify(payload));
588
+ }
589
+
590
+ // src/commands/preview.ts
591
+ var examples = [
592
+ ["Preview the current project", "framey preview"],
593
+ ["Print the current Studio selection as JSON", "framey preview --selection --json"],
594
+ ["Print current Studio context as JSON", "framey preview --context --json"],
595
+ ["Preview a specific project directory", "framey preview ./my-video"],
596
+ ["Use a custom port", "framey preview --port 8080"],
597
+ ["Force a new server even if one is already running", "framey preview --force-new"],
598
+ ["Keep preview running after this command exits", "framey preview --background"],
599
+ ["Force an attached preview in a non-interactive shell", "framey preview --foreground"],
600
+ ["Show the background preview for this project", "framey preview --status"],
601
+ ["Stop the background preview for this project", "framey preview --stop"],
602
+ ["Start without opening the browser", "framey preview --no-open"],
603
+ ["Open with a specific browser", "framey preview --browser-path /usr/bin/chromium"],
604
+ [
605
+ "Open with CDP enabled (requires browser path + isolated profile)",
606
+ "framey preview --browser-path /usr/bin/chromium --user-data-dir /tmp/hf-profile --remote-debugging-port 9222"
607
+ ],
608
+ ["List all active preview servers", "framey preview --list"],
609
+ ["Kill all active preview servers", "framey preview --kill-all"],
610
+ [
611
+ "Disable auto-proxying of browser-hostile video codecs (HEVC, ProRes, AV1)",
612
+ "framey preview --no-proxy"
613
+ ],
614
+ [
615
+ "Show full lint findings on startup instead of the summary line",
616
+ "framey preview --lint-verbose"
617
+ ]
618
+ ];
619
+ var STUDIO_CHILD_SHUTDOWN_SIGNALS = ["SIGINT", "SIGTERM", "SIGHUP"];
620
+ var DEFAULT_CONTEXT_FIELDS = ["server", "selection", "lint", "capabilities"];
621
+ var PREVIEW_PORT_MISMATCH_CODE = "preview-port-mismatch";
622
+ function backgroundStartFailureCode(error) {
623
+ if (error instanceof PreviewServerPortMismatchError) return PREVIEW_PORT_MISMATCH_CODE;
624
+ if (error instanceof PreviewPortUnavailableError) return "preview-port-unavailable";
625
+ return "preview-start-failed";
626
+ }
627
+ var preview_default = defineCommand({
628
+ meta: {
629
+ name: "preview",
630
+ description: "Start the studio for previewing compositions"
631
+ },
632
+ args: {
633
+ dir: {
634
+ type: "positional",
635
+ description: "Project directory",
636
+ required: false
637
+ },
638
+ port: {
639
+ type: "string",
640
+ description: "Port to run the preview server on",
641
+ default: "3002"
642
+ },
643
+ "force-new": {
644
+ type: "boolean",
645
+ description: "Start a new server even if one is already running for this project",
646
+ default: false
647
+ },
648
+ background: {
649
+ type: "boolean",
650
+ description: "Start a preview that remains running after the command exits",
651
+ default: false
652
+ },
653
+ foreground: {
654
+ type: "boolean",
655
+ description: "Keep preview attached even when the shell is non-interactive",
656
+ default: false
657
+ },
658
+ status: {
659
+ type: "boolean",
660
+ description: "Show the background preview for this project and exit",
661
+ default: false
662
+ },
663
+ stop: {
664
+ type: "boolean",
665
+ description: "Stop the background preview for this project and exit",
666
+ default: false
667
+ },
668
+ list: {
669
+ type: "boolean",
670
+ description: "List all active preview servers and exit",
671
+ default: false
672
+ },
673
+ "kill-all": {
674
+ type: "boolean",
675
+ description: "Kill all active preview servers and exit",
676
+ default: false
677
+ },
678
+ "lint-verbose": {
679
+ type: "boolean",
680
+ description: "Show full lint findings on startup (default: a one-line summary)",
681
+ default: false
682
+ },
683
+ open: {
684
+ type: "boolean",
685
+ default: true,
686
+ description: "Open browser automatically"
687
+ },
688
+ selection: {
689
+ type: "boolean",
690
+ description: "Print the current element selected in a running Studio preview and exit",
691
+ default: false
692
+ },
693
+ json: {
694
+ type: "boolean",
695
+ description: "Output selection, context, or managed lifecycle state as JSON",
696
+ default: false
697
+ },
698
+ context: {
699
+ type: "boolean",
700
+ description: "Print the current agent-readable context from a running Studio preview and exit",
701
+ default: false
702
+ },
703
+ "context-fields": {
704
+ type: "string",
705
+ description: "Comma-separated context fields to include: server,selection,lint,capabilities (only with --context)"
706
+ },
707
+ "context-detail": {
708
+ type: "string",
709
+ description: "Context payload detail: compact or full (only with --context)",
710
+ default: "compact"
711
+ },
712
+ "browser-path": {
713
+ type: "string",
714
+ description: "Path to the browser executable to open"
715
+ },
716
+ "user-data-dir": {
717
+ type: "string",
718
+ description: "Chromium-compatible user data directory (requires --browser-path)"
719
+ },
720
+ "remote-debugging-port": {
721
+ type: "string",
722
+ description: "Chromium remote debugging port (requires --browser-path and --user-data-dir)"
723
+ },
724
+ "browser-no-gpu": {
725
+ type: "boolean",
726
+ default: false,
727
+ description: "Launch the opened browser with --disable-gpu (requires --browser-path). For hosts where hardware acceleration crashes the graphics driver (e.g. NVIDIA Xid resets); with the system default browser use --no-open instead."
728
+ },
729
+ "browser-gpu": {
730
+ type: "boolean",
731
+ description: "Use hardware GPU for Studio thumbnails and frame capture; pass --no-browser-gpu for deterministic SwiftShader (default: auto-detect)",
732
+ default: void 0
733
+ },
734
+ proxy: {
735
+ type: "boolean",
736
+ description: "Auto-transcode browser-hostile video codecs (HEVC, ProRes, AV1) to a cached authoring proxy for preview (default: on; overrides hyperframes.json's media.autoProxy)",
737
+ negativeDescription: "Disable auto-proxying of browser-hostile video codecs"
738
+ }
739
+ },
740
+ async run({ args }) {
741
+ const launchModeError = previewLaunchModeError({
742
+ background: Boolean(args.background),
743
+ foreground: Boolean(args.foreground),
744
+ forceNew: Boolean(args["force-new"]),
745
+ status: Boolean(args.status),
746
+ stop: Boolean(args.stop),
747
+ list: Boolean(args.list),
748
+ killAll: Boolean(args["kill-all"])
749
+ });
750
+ if (launchModeError) {
751
+ if (args.json) {
752
+ writeLifecycleJson(
753
+ lifecycleFailurePayload(
754
+ args.status ? "status" : args.stop ? "stop" : args.list ? "list" : args["kill-all"] ? "kill-all" : "start",
755
+ "conflicting-lifecycle-flags",
756
+ launchModeError
757
+ )
758
+ );
759
+ } else {
760
+ R.error(launchModeError);
761
+ }
762
+ setCommandExitCode(1);
763
+ return;
764
+ }
765
+ const portError = previewPortError(args.port);
766
+ if (portError) {
767
+ reportPreviewFailure(
768
+ Boolean(args.json),
769
+ args.status ? "status" : args.stop ? "stop" : args.list ? "list" : args["kill-all"] ? "kill-all" : "start",
770
+ "preview-validation-failed",
771
+ portError
772
+ );
773
+ return;
774
+ }
775
+ const browserGpuMode = resolveLocalBrowserGpuMode(args["browser-gpu"]);
776
+ if (args["browser-gpu"] === true) process.env.PRODUCER_BROWSER_GPU_MODE = "hardware";
777
+ if (args["browser-gpu"] === false) process.env.PRODUCER_BROWSER_GPU_MODE = "software";
778
+ const startPort = parseInt(args.port ?? "3002", 10);
779
+ const explicitPort = hasExplicitPreviewPort(process.argv) ? startPort : void 0;
780
+ if (args.status || args.stop) {
781
+ try {
782
+ const project2 = args.json ? resolveProjectOrThrow(args.dir) : resolveProject(args.dir);
783
+ if (args.stop) {
784
+ const stopped = await stopBackgroundPreview(project2.dir, startPort, {
785
+ preferredPort: explicitPort
786
+ });
787
+ if (args.json) {
788
+ writeLifecycleJson(
789
+ lifecyclePayload(
790
+ "stop",
791
+ stopped ? { state: "stopped", projectDir: project2.dir } : { state: "not-running", projectDir: project2.dir }
792
+ )
793
+ );
794
+ } else {
795
+ console.log(
796
+ stopped ? `
797
+ ${c.success("Stopped background preview")} ${c.dim(project2.dir)}
798
+ ` : `
799
+ ${c.dim("No background preview is running for")} ${project2.dir}
800
+ `
801
+ );
802
+ }
803
+ return;
804
+ }
805
+ const status = await readBackgroundPreviewStatus(project2.dir, startPort, {
806
+ preferredPort: explicitPort
807
+ });
808
+ if (!status) {
809
+ if (args.json) {
810
+ writeLifecycleJson(
811
+ lifecyclePayload("status", {
812
+ state: "not-running",
813
+ projectDir: project2.dir
814
+ })
815
+ );
816
+ } else {
817
+ console.log(`
818
+ ${c.dim("No background preview is running for")} ${project2.dir}
819
+ `);
820
+ }
821
+ return;
822
+ }
823
+ if (args.json) {
824
+ writeLifecycleJson(
825
+ lifecyclePayload(
826
+ "status",
827
+ previewLifecycleSession({
828
+ state: "running",
829
+ mode: status.logPath ? "background" : "unknown",
830
+ projectName: project2.name,
831
+ projectDir: project2.dir,
832
+ port: status.port,
833
+ pid: status.pid,
834
+ logPath: status.logPath
835
+ })
836
+ )
837
+ );
838
+ return;
839
+ }
840
+ printStudioSummary(project2.name, previewBaseUrl(status.port), project2.dir, {
841
+ details: [
842
+ `${status.logPath ? "Background preview" : "Preview"} running${status.pid === null ? "" : ` (PID ${status.pid})`}.`,
843
+ ...status.logPath ? [`Log: ${status.logPath}`] : []
844
+ ]
845
+ });
846
+ return;
847
+ } catch (error) {
848
+ reportPreviewFailure(
849
+ Boolean(args.json),
850
+ args.stop ? "stop" : "status",
851
+ args.stop ? "preview-stop-failed" : "preview-status-failed",
852
+ normalizeErrorMessage(error)
853
+ );
854
+ return;
855
+ }
856
+ }
857
+ if (args.list) {
858
+ await handlePreviewList(startPort, Boolean(args.json));
859
+ return;
860
+ }
861
+ if (args["kill-all"]) {
862
+ await handlePreviewKillAll(startPort, Boolean(args.json));
863
+ return;
864
+ }
865
+ if (args.context) {
866
+ const project2 = resolveProject(args.dir);
867
+ return printCurrentContext(project2.dir, startPort, {
868
+ json: Boolean(args.json),
869
+ fields: args["context-fields"],
870
+ detail: args["context-detail"],
871
+ preferredPort: explicitPort
872
+ });
873
+ }
874
+ if (args.selection) {
875
+ const project2 = resolveProject(args.dir);
876
+ return printCurrentSelection(project2.dir, startPort, Boolean(args.json), explicitPort);
877
+ }
878
+ const rawArg = args.dir;
879
+ const isImplicitCwd = !rawArg || rawArg === "." || rawArg === "./";
880
+ let project;
881
+ try {
882
+ project = args.json ? resolveProjectOrThrow(rawArg) : resolveProject(rawArg);
883
+ } catch (error) {
884
+ reportPreviewFailure(
885
+ Boolean(args.json),
886
+ "start",
887
+ "preview-start-failed",
888
+ normalizeErrorMessage(error)
889
+ );
890
+ return;
891
+ }
892
+ const dir = project.dir;
893
+ const projectName = isImplicitCwd ? basename(process.env.PWD ?? dir) : project.name;
894
+ if (args["user-data-dir"] && !args["browser-path"]) {
895
+ reportPreviewFailure(
896
+ Boolean(args.json),
897
+ "start",
898
+ "preview-validation-failed",
899
+ "--user-data-dir requires --browser-path"
900
+ );
901
+ return;
902
+ }
903
+ const depsError = validateRemoteDebuggingPortDeps({
904
+ browserPath: args["browser-path"],
905
+ userDataDir: args["user-data-dir"],
906
+ remoteDebuggingPort: args["remote-debugging-port"]
907
+ });
908
+ if (depsError) {
909
+ reportPreviewFailure(Boolean(args.json), "start", "preview-validation-failed", depsError);
910
+ return;
911
+ }
912
+ const noOpen = !args.open;
913
+ const browserPath = args["browser-path"];
914
+ const browserNoGpu = !!args["browser-no-gpu"];
915
+ if (browserNoGpu && !browserPath) {
916
+ reportPreviewFailure(
917
+ Boolean(args.json),
918
+ "start",
919
+ "preview-validation-failed",
920
+ "--browser-no-gpu requires --browser-path (the system default browser cannot receive Chromium flags \u2014 use --no-open on GPU-unstable hosts)"
921
+ );
922
+ return;
923
+ }
924
+ const userDataDir = args["user-data-dir"];
925
+ let remoteDebuggingPort;
926
+ try {
927
+ remoteDebuggingPort = parseRemoteDebuggingPort(
928
+ args["remote-debugging-port"]
929
+ );
930
+ } catch (err) {
931
+ reportPreviewFailure(
932
+ Boolean(args.json),
933
+ "start",
934
+ "preview-validation-failed",
935
+ err.message
936
+ );
937
+ return;
938
+ }
939
+ const autoProxy = resolveAutoProxy(dir, args.proxy);
940
+ const launchMode = previewLaunchMode({
941
+ background: Boolean(args.background),
942
+ foreground: Boolean(args.foreground),
943
+ interactive: Boolean(process.stdin.isTTY && process.stdout.isTTY),
944
+ devMode: isDevMode(),
945
+ localStudio: hasLocalStudio(dir)
946
+ });
947
+ const hostAppError = previewHostAppError(launchMode);
948
+ if (hostAppError) {
949
+ reportPreviewFailure(Boolean(args.json), "start", "host-app-owns-preview", hostAppError);
950
+ return;
951
+ }
952
+ const orphansKilled = killOrphanedProcesses();
953
+ if (orphansKilled > 0 && !args.json) {
954
+ console.log(
955
+ ` ${c.dim(`Cleaned up ${orphansKilled} orphaned process${orphansKilled === 1 ? "" : "es"} from a previous session.`)}`
956
+ );
957
+ }
958
+ const startupLint = args.json ? null : printStartupLint(dir, Boolean(args["lint-verbose"]));
959
+ if (launchMode === "background") {
960
+ let background;
961
+ try {
962
+ background = await startBackgroundPreview(dir, startPort, {
963
+ forceNew: Boolean(args["force-new"]),
964
+ // A bare launch promises same-project reuse, regardless of the mode
965
+ // the existing managed server resolved earlier. Only an explicit
966
+ // --browser-gpu/--no-browser-gpu request authorizes replacement.
967
+ browserGpuMode: args["browser-gpu"] === void 0 ? void 0 : browserGpuMode,
968
+ preferredPort: explicitPort
969
+ });
970
+ } catch (error) {
971
+ const message = normalizeErrorMessage(error);
972
+ if (args.json) {
973
+ writeLifecycleJson(
974
+ lifecycleFailurePayload("start", backgroundStartFailureCode(error), message)
975
+ );
976
+ } else {
977
+ R.error(message);
978
+ }
979
+ setCommandExitCode(1);
980
+ return;
981
+ }
982
+ const url = `http://localhost:${background.port}`;
983
+ if (args.json) {
984
+ writeLifecycleJson(
985
+ lifecyclePayload(
986
+ "start",
987
+ previewLifecycleSession({
988
+ state: background.type,
989
+ mode: "background",
990
+ projectName,
991
+ projectDir: dir,
992
+ port: background.port,
993
+ pid: background.pid,
994
+ ...background.logPath ? { logPath: background.logPath } : {}
995
+ })
996
+ )
997
+ );
998
+ } else {
999
+ ge(c.bold("framey preview"));
1000
+ printStudioSummary(projectName, url, dir, {
1001
+ details: [
1002
+ background.type === "reused" ? "Reusing the background server already running for this project." : `Running in the background. Log: ${background.logPath}`,
1003
+ "Changes reload automatically in the studio."
1004
+ ],
1005
+ footer: `Stop with: framey preview ${JSON.stringify(dir)} --stop`
1006
+ });
1007
+ }
1008
+ openStudioBrowser(url, projectName, {
1009
+ noOpen,
1010
+ browserPath,
1011
+ userDataDir,
1012
+ remoteDebuggingPort,
1013
+ browserNoGpu
1014
+ });
1015
+ await startupLint;
1016
+ return;
1017
+ }
1018
+ if (launchMode === "dev") {
1019
+ return runDevMode(dir, {
1020
+ projectName,
1021
+ noOpen,
1022
+ browserPath,
1023
+ userDataDir,
1024
+ remoteDebuggingPort,
1025
+ browserNoGpu,
1026
+ autoProxy,
1027
+ browserGpuMode,
1028
+ port: startPort,
1029
+ json: Boolean(args.json)
1030
+ });
1031
+ }
1032
+ if (launchMode === "local") {
1033
+ return runLocalStudioMode(dir, {
1034
+ projectName,
1035
+ noOpen,
1036
+ browserPath,
1037
+ userDataDir,
1038
+ remoteDebuggingPort,
1039
+ browserNoGpu,
1040
+ autoProxy,
1041
+ browserGpuMode,
1042
+ port: startPort,
1043
+ json: Boolean(args.json)
1044
+ });
1045
+ }
1046
+ const forceNew = !!args["force-new"];
1047
+ return runEmbeddedMode(dir, startPort, {
1048
+ projectName,
1049
+ forceNew,
1050
+ autoProxy,
1051
+ noOpen,
1052
+ browserPath,
1053
+ userDataDir,
1054
+ remoteDebuggingPort,
1055
+ browserNoGpu,
1056
+ browserGpuMode,
1057
+ json: Boolean(args.json)
1058
+ });
1059
+ }
1060
+ });
1061
+ async function printStartupLint(dir, verbose) {
1062
+ try {
1063
+ const lintResult = await runRenderSetupWorker(
1064
+ "lint",
1065
+ { projectDir: dir },
1066
+ { maxBufferBytes: 8 * 1024 * 1024 }
1067
+ );
1068
+ if (lintResult.totalErrors === 0 && lintResult.totalWarnings === 0) return;
1069
+ console.log();
1070
+ for (const line of formatLintStartupMessage(
1071
+ lintResult,
1072
+ verbose ? { kind: "verbose" } : { kind: "summary", pointer: "studio" }
1073
+ ))
1074
+ console.log(line);
1075
+ console.log();
1076
+ } catch (error) {
1077
+ R.warn(`Lint did not finish: ${normalizeErrorMessage(error)}`);
1078
+ }
1079
+ }
1080
+ function previewLaunchMode(options) {
1081
+ if (options.background) return "background";
1082
+ if (!options.foreground && !options.interactive) return "background";
1083
+ if (options.devMode) return "dev";
1084
+ return options.localStudio ? "local" : "embedded";
1085
+ }
1086
+ function previewHostAppError(mode, env = process.env) {
1087
+ if (mode !== "background" || !insideHostApp(env)) return null;
1088
+ return "A host app is running this project and owns its preview, so a background preview here would outlive this run and keep the project's history locked. Use the host app's preview, or run with --foreground to keep a preview attached to this run.";
1089
+ }
1090
+ function previewLaunchModeError(options) {
1091
+ if (options.background && options.foreground) {
1092
+ return "--background and --foreground cannot be used together";
1093
+ }
1094
+ const actionCount = [options.status, options.stop, options.list, options.killAll].filter(
1095
+ Boolean
1096
+ ).length;
1097
+ if (actionCount > 1) {
1098
+ return "Only one of --status, --stop, --list, or --kill-all can be used at a time";
1099
+ }
1100
+ if (actionCount > 0 && (options.background || options.foreground || options.forceNew)) {
1101
+ return "Preview launch overrides cannot be combined with lifecycle actions";
1102
+ }
1103
+ return null;
1104
+ }
1105
+ function previewPortError(port) {
1106
+ const value = port ?? "3002";
1107
+ if (!/^\d+$/.test(value)) return "--port must be an integer between 1 and 65535";
1108
+ const parsed = Number(value);
1109
+ return parsed >= 1 && parsed <= 65535 ? null : "--port must be an integer between 1 and 65535";
1110
+ }
1111
+ function publicPreviewPid(serverPid, fallbackPid) {
1112
+ const parsed = Number(serverPid);
1113
+ return Number.isInteger(parsed) && parsed > 0 ? parsed : fallbackPid;
1114
+ }
1115
+ function reportPreviewFailure(json, operation, code, message) {
1116
+ if (json) writeLifecycleJson(lifecycleFailurePayload(operation, code, message));
1117
+ else R.error(message);
1118
+ setCommandExitCode(1);
1119
+ }
1120
+ async function handlePreviewList(startPort, json, dependencies = {}) {
1121
+ try {
1122
+ const [scannedServers, managedSessions] = await Promise.all([
1123
+ (dependencies.scan ?? scanActiveServers)(startPort),
1124
+ (dependencies.listManaged ?? listBackgroundPreviewStatuses)()
1125
+ ]);
1126
+ const listedSessions = managedSessions.filter(
1127
+ (session) => session.pid !== null || !scannedServers.some(
1128
+ (server) => publicPreviewPid(server.pid, null) !== null && server.port === session.port && resolve2(server.projectDir) === resolve2(session.projectDir)
1129
+ )
1130
+ );
1131
+ const managedKeys = new Set(
1132
+ listedSessions.map((session) => `${resolve2(session.projectDir)}\0${session.port}`)
1133
+ );
1134
+ const servers = [
1135
+ ...listedSessions.map((session) => ({
1136
+ port: session.port,
1137
+ host: "127.0.0.1",
1138
+ projectName: basename(session.projectDir),
1139
+ projectDir: session.projectDir,
1140
+ version: session.logPath ? "managed" : "unknown",
1141
+ pid: session.pid === null ? null : String(session.pid)
1142
+ })),
1143
+ ...scannedServers.filter(
1144
+ (server) => !managedKeys.has(`${resolve2(server.projectDir)}\0${server.port}`)
1145
+ )
1146
+ ];
1147
+ if (json) {
1148
+ writeLifecycleJson(
1149
+ lifecyclePayload("list", {
1150
+ state: "listed",
1151
+ sessions: servers.map(
1152
+ (server) => previewLifecycleSession({
1153
+ state: "running",
1154
+ mode: server.version === "managed" ? "background" : "unknown",
1155
+ projectName: server.projectName,
1156
+ projectDir: server.projectDir,
1157
+ port: server.port,
1158
+ pid: server.pid ? Number(server.pid) : null,
1159
+ host: server.host
1160
+ })
1161
+ )
1162
+ })
1163
+ );
1164
+ return;
1165
+ }
1166
+ if (servers.length === 0) {
1167
+ console.log("\n No active preview servers found.\n");
1168
+ return;
1169
+ }
1170
+ console.log(`
1171
+ ${c.bold("Active preview servers:")}
1172
+ `);
1173
+ for (const server of servers) {
1174
+ const pid = server.pid ? c.dim(` (PID ${server.pid})`) : "";
1175
+ console.log(
1176
+ ` ${c.accent(`Port ${server.port}`)} ${server.projectName} ${c.dim(server.projectDir)}${pid}`
1177
+ );
1178
+ }
1179
+ console.log(`
1180
+ ${servers.length} server${servers.length === 1 ? "" : "s"} running.
1181
+ `);
1182
+ } catch (error) {
1183
+ reportPreviewFailure(json, "list", "preview-list-failed", normalizeErrorMessage(error));
1184
+ }
1185
+ }
1186
+ async function handlePreviewKillAll(startPort, json, dependencies = {}) {
1187
+ try {
1188
+ const managedSessions = await (dependencies.listManaged ?? listBackgroundPreviewStatuses)();
1189
+ let killed = 0;
1190
+ const failures = [];
1191
+ for (const session of managedSessions) {
1192
+ try {
1193
+ if (await (dependencies.stopManaged ?? stopBackgroundPreview)(
1194
+ session.projectDir,
1195
+ session.port
1196
+ )) {
1197
+ killed++;
1198
+ }
1199
+ } catch (error) {
1200
+ failures.push(`${session.projectDir}: ${normalizeErrorMessage(error)}`);
1201
+ }
1202
+ }
1203
+ const swept = await (dependencies.killScanned ?? killActiveServers)(startPort);
1204
+ killed += swept.killed;
1205
+ const unverified = swept.unverified;
1206
+ if (json) {
1207
+ writeLifecycleJson(
1208
+ lifecyclePayload("kill-all", {
1209
+ state: "killed-all",
1210
+ stopped: killed,
1211
+ ...failures.length > 0 ? { failed: failures } : {},
1212
+ ...unverified.length > 0 ? { unverifiedPorts: unverified } : {}
1213
+ })
1214
+ );
1215
+ } else if (failures.length > 0 || unverified.length > 0) {
1216
+ console.log(`
1217
+ Killed ${killed} preview server${killed === 1 ? "" : "s"}.`);
1218
+ for (const failure of failures) R.warn(`Could not stop ${failure}`);
1219
+ if (unverified.length > 0) {
1220
+ const plural = unverified.length === 1 ? "" : "s";
1221
+ R.warn(
1222
+ `Left ${unverified.length} server${plural} alone (port${plural} ${unverified.join(", ")}): the OS could not confirm which process owns the socket, and the server's own claim is not proof. Install lsof, or stop it with its own preview --stop.`
1223
+ );
1224
+ }
1225
+ console.log();
1226
+ } else if (killed === 0) {
1227
+ console.log("\n No active preview servers to kill.\n");
1228
+ } else {
1229
+ console.log(`
1230
+ Killed ${killed} preview server${killed === 1 ? "" : "s"}.
1231
+ `);
1232
+ }
1233
+ } catch (error) {
1234
+ reportPreviewFailure(json, "kill-all", "preview-kill-all-failed", normalizeErrorMessage(error));
1235
+ }
1236
+ }
1237
+ function previewViteArgs(port) {
1238
+ return ["--host", "127.0.0.1", ...port === void 0 ? [] : ["--port", String(port)]];
1239
+ }
1240
+ function previewBaseUrl(port, host = "127.0.0.1") {
1241
+ return `http://${host}:${port}`;
1242
+ }
1243
+ function absolutePreviewUrl(port, path, host = "127.0.0.1") {
1244
+ if (/^https?:\/\//.test(path)) return path;
1245
+ return `${previewBaseUrl(port, host)}${path.startsWith("/") ? path : `/${path}`}`;
1246
+ }
1247
+ function hasExplicitPreviewPort(argv) {
1248
+ return argv.some((arg) => arg === "--port" || arg.startsWith("--port="));
1249
+ }
1250
+ function printSelectionFailure(code, message, json) {
1251
+ if (json) {
1252
+ console.log(JSON.stringify({ ok: false, error: { code, message } }, null, 2));
1253
+ } else {
1254
+ R.error(message);
1255
+ }
1256
+ setCommandExitCode(1);
1257
+ }
1258
+ function previewServerPayload(server) {
1259
+ return {
1260
+ port: server.port,
1261
+ projectName: server.projectName,
1262
+ projectDir: server.projectDir,
1263
+ url: previewBaseUrl(server.port, server.host)
1264
+ };
1265
+ }
1266
+ function parseContextFields(value) {
1267
+ if (value === void 0) return DEFAULT_CONTEXT_FIELDS;
1268
+ if (!value.trim()) throw new Error("--context-fields cannot be empty");
1269
+ const allowed = new Set(DEFAULT_CONTEXT_FIELDS);
1270
+ const fields = value.split(",").map((field) => field.trim()).filter(Boolean);
1271
+ const invalid = fields.filter((field) => !allowed.has(field));
1272
+ if (invalid.length > 0) {
1273
+ throw new Error(
1274
+ `Unknown context field${invalid.length === 1 ? "" : "s"}: ${invalid.join(", ")}`
1275
+ );
1276
+ }
1277
+ return [...new Set(fields)];
1278
+ }
1279
+ function contextIncludes(fields, field) {
1280
+ return fields.includes(field);
1281
+ }
1282
+ function addContextError(payload, field, error) {
1283
+ payload.errors = {
1284
+ ...payload.errors ?? {},
1285
+ [field]: error
1286
+ };
1287
+ }
1288
+ async function printCurrentSelection(projectDir, startPort, json, preferredPort) {
1289
+ const {
1290
+ AmbiguousPreviewServerError,
1291
+ PreviewServerPortMismatchError: PreviewServerPortMismatchError2,
1292
+ fetchStudioSelection,
1293
+ findPreviewServerForProject
1294
+ } = await import("./studioSelectionClient-IUUPKUHZ.js");
1295
+ let server;
1296
+ try {
1297
+ server = await findPreviewServerForProject(
1298
+ projectDir,
1299
+ startPort,
1300
+ void 0,
1301
+ void 0,
1302
+ preferredPort === void 0 ? void 0 : { preferredPort }
1303
+ );
1304
+ } catch (err) {
1305
+ if (err instanceof AmbiguousPreviewServerError) {
1306
+ printSelectionFailure("ambiguous-preview-server", err.message, json);
1307
+ return;
1308
+ }
1309
+ if (err instanceof PreviewServerPortMismatchError2) {
1310
+ printSelectionFailure(PREVIEW_PORT_MISMATCH_CODE, err.message, json);
1311
+ return;
1312
+ }
1313
+ throw err;
1314
+ }
1315
+ if (!server) {
1316
+ printSelectionFailure(
1317
+ "preview-not-running",
1318
+ "No running Studio preview found for this project. Start one with: framey preview",
1319
+ json
1320
+ );
1321
+ return;
1322
+ }
1323
+ let response;
1324
+ try {
1325
+ response = await fetchStudioSelection(server);
1326
+ } catch (err) {
1327
+ printSelectionFailure("selection-unavailable", normalizeErrorMessage(err), json);
1328
+ return;
1329
+ }
1330
+ if (!response.selection) {
1331
+ printSelectionFailure(
1332
+ "no-selection",
1333
+ "Studio is running, but no element is selected. Select an element in Studio and rerun this command.",
1334
+ json
1335
+ );
1336
+ return;
1337
+ }
1338
+ const selection = {
1339
+ ...response.selection,
1340
+ thumbnailUrl: absolutePreviewUrl(server.port, response.selection.thumbnailUrl, server.host)
1341
+ };
1342
+ if (json) {
1343
+ console.log(
1344
+ JSON.stringify(
1345
+ {
1346
+ ok: true,
1347
+ server: previewServerPayload(server),
1348
+ selection,
1349
+ updatedAt: response.updatedAt
1350
+ },
1351
+ null,
1352
+ 2
1353
+ )
1354
+ );
1355
+ return;
1356
+ }
1357
+ console.log(`${c.success("\u25C7")} ${c.accent(selection.label)} selected in Studio`);
1358
+ console.log(` ${c.dim("Source")} ${selection.sourceFile}`);
1359
+ console.log(
1360
+ ` ${c.dim("Target")} ${selection.target.hfId ?? selection.target.id ?? selection.target.selector ?? "(none)"}`
1361
+ );
1362
+ console.log(` ${c.dim("Time")} ${selection.currentTime.toFixed(3)}s`);
1363
+ console.log(` ${c.dim("Thumbnail")} ${selection.thumbnailUrl}`);
1364
+ console.log();
1365
+ console.log(c.dim("Use --json for the full agent-readable selection payload."));
1366
+ }
1367
+ function countLintFindings(findings) {
1368
+ return {
1369
+ errors: findings.filter((finding) => finding.severity === "error").length,
1370
+ warnings: findings.filter((finding) => finding.severity === "warning").length
1371
+ };
1372
+ }
1373
+ async function printCurrentContext(projectDir, startPort, options) {
1374
+ let fields;
1375
+ try {
1376
+ fields = parseContextFields(options.fields);
1377
+ } catch (err) {
1378
+ printSelectionFailure("invalid-context-fields", normalizeErrorMessage(err), options.json);
1379
+ return;
1380
+ }
1381
+ const fullDetail = options.detail === "full";
1382
+ if (options.detail !== void 0 && !["compact", "full"].includes(options.detail)) {
1383
+ printSelectionFailure(
1384
+ "invalid-context-detail",
1385
+ "--context-detail must be compact or full",
1386
+ options.json
1387
+ );
1388
+ return;
1389
+ }
1390
+ const {
1391
+ AmbiguousPreviewServerError,
1392
+ PreviewServerPortMismatchError: PreviewServerPortMismatchError2,
1393
+ fetchStudioLint,
1394
+ fetchStudioSelection,
1395
+ findPreviewServerForProject
1396
+ } = await import("./studioSelectionClient-IUUPKUHZ.js");
1397
+ let server;
1398
+ try {
1399
+ server = await findPreviewServerForProject(
1400
+ projectDir,
1401
+ startPort,
1402
+ void 0,
1403
+ void 0,
1404
+ options.preferredPort === void 0 ? void 0 : { preferredPort: options.preferredPort }
1405
+ );
1406
+ } catch (err) {
1407
+ if (err instanceof AmbiguousPreviewServerError) {
1408
+ printSelectionFailure("ambiguous-preview-server", err.message, options.json);
1409
+ return;
1410
+ }
1411
+ if (err instanceof PreviewServerPortMismatchError2) {
1412
+ printSelectionFailure(PREVIEW_PORT_MISMATCH_CODE, err.message, options.json);
1413
+ return;
1414
+ }
1415
+ throw err;
1416
+ }
1417
+ if (!server) {
1418
+ printSelectionFailure(
1419
+ "preview-not-running",
1420
+ "No running Studio preview found for this project. Start one with: framey preview",
1421
+ options.json
1422
+ );
1423
+ return;
1424
+ }
1425
+ const wantsSelection = contextIncludes(fields, "selection");
1426
+ const wantsLint = contextIncludes(fields, "lint");
1427
+ const [selectionResult, lintResult] = await Promise.allSettled([
1428
+ wantsSelection ? fetchStudioSelection(server) : Promise.resolve(null),
1429
+ wantsLint ? fetchStudioLint(server) : Promise.resolve(null)
1430
+ ]);
1431
+ const selection = selectionResult.status === "fulfilled" && selectionResult.value?.selection ? {
1432
+ ok: true,
1433
+ value: fullDetail ? {
1434
+ ...selectionResult.value.selection,
1435
+ thumbnailUrl: absolutePreviewUrl(
1436
+ server.port,
1437
+ selectionResult.value.selection.thumbnailUrl
1438
+ )
1439
+ } : compactSelectionPayload({
1440
+ ...selectionResult.value.selection,
1441
+ thumbnailUrl: absolutePreviewUrl(
1442
+ server.port,
1443
+ selectionResult.value.selection.thumbnailUrl
1444
+ )
1445
+ }),
1446
+ updatedAt: selectionResult.value.updatedAt
1447
+ } : {
1448
+ ok: false,
1449
+ error: selectionResult.status === "rejected" ? {
1450
+ code: "selection-unavailable",
1451
+ message: normalizeErrorMessage(selectionResult.reason)
1452
+ } : {
1453
+ code: "no-selection",
1454
+ message: "Studio is running, but no element is selected."
1455
+ }
1456
+ };
1457
+ const lint = lintResult.status === "fulfilled" && lintResult.value ? {
1458
+ ok: true,
1459
+ summary: countLintFindings(lintResult.value.findings),
1460
+ findings: lintResult.value.findings
1461
+ } : {
1462
+ ok: false,
1463
+ error: lintResult.status === "rejected" ? {
1464
+ code: "lint-unavailable",
1465
+ message: normalizeErrorMessage(lintResult.reason)
1466
+ } : {
1467
+ code: "lint-not-requested",
1468
+ message: "Lint was not requested."
1469
+ }
1470
+ };
1471
+ const payload = { ok: true };
1472
+ if (contextIncludes(fields, "server")) payload.server = previewServerPayload(server);
1473
+ if (contextIncludes(fields, "selection")) {
1474
+ payload.selection = selection.ok ? selection.value : null;
1475
+ payload.selectionUpdatedAt = selection.ok ? selection.updatedAt : null;
1476
+ if (!selection.ok) addContextError(payload, "selection", selection.error);
1477
+ }
1478
+ if (contextIncludes(fields, "lint")) payload.lint = lint;
1479
+ if (contextIncludes(fields, "capabilities")) {
1480
+ payload.capabilities = {
1481
+ selection: true,
1482
+ lint: true,
1483
+ frame: false,
1484
+ visibleElements: false,
1485
+ lastAction: false
1486
+ };
1487
+ }
1488
+ if (options.json) {
1489
+ console.log(JSON.stringify(payload, null, 2));
1490
+ return;
1491
+ }
1492
+ console.log(`${c.success("\u25C7")} Studio context`);
1493
+ if (contextIncludes(fields, "server")) {
1494
+ console.log(` ${c.dim("Project")} ${server.projectName}`);
1495
+ console.log(` ${c.dim("Studio")} ${previewBaseUrl(server.port, server.host)}`);
1496
+ }
1497
+ if (contextIncludes(fields, "selection")) {
1498
+ if (selection.ok) {
1499
+ console.log(` ${c.dim("Selection")} ${selection.value.label}`);
1500
+ } else {
1501
+ console.log(` ${c.dim("Selection")} ${selection.error.message}`);
1502
+ }
1503
+ }
1504
+ if (contextIncludes(fields, "lint")) {
1505
+ if (lint.ok) {
1506
+ console.log(
1507
+ ` ${c.dim("Lint")} ${lint.summary.errors} error(s), ${lint.summary.warnings} warning(s)`
1508
+ );
1509
+ } else {
1510
+ console.log(` ${c.dim("Lint")} ${lint.error.message}`);
1511
+ }
1512
+ }
1513
+ console.log();
1514
+ console.log(c.dim("Use --json for the full agent-readable context payload."));
1515
+ }
1516
+ function compactSelectionPayload(selection) {
1517
+ return {
1518
+ schemaVersion: selection.schemaVersion,
1519
+ projectId: selection.projectId,
1520
+ compositionPath: selection.compositionPath,
1521
+ sourceFile: selection.sourceFile,
1522
+ currentTime: selection.currentTime,
1523
+ target: selection.target,
1524
+ label: selection.label,
1525
+ tagName: selection.tagName,
1526
+ boundingBox: selection.boundingBox,
1527
+ textContent: selection.textContent,
1528
+ thumbnailUrl: selection.thumbnailUrl
1529
+ };
1530
+ }
1531
+ function studioDeepLink(url, projectName) {
1532
+ return `${url}/#project/${encodeURIComponent(projectName)}`;
1533
+ }
1534
+ function studioSummaryUrls(projectName, serverUrl) {
1535
+ return {
1536
+ serverUrl,
1537
+ studioUrl: studioDeepLink(serverUrl, projectName)
1538
+ };
1539
+ }
1540
+ function prebuildPreview(fetchApp, serverUrl, projectName) {
1541
+ const previewUrl = `${serverUrl}/api/projects/${encodeURIComponent(projectName)}/preview`;
1542
+ return Promise.resolve().then(() => fetchApp(new Request(previewUrl))).catch(() => void 0);
1543
+ }
1544
+ function foregroundPreviewReadyPayload(projectName, serverUrl, projectDir, pid) {
1545
+ const port = Number(new URL(serverUrl).port);
1546
+ return lifecyclePayload(
1547
+ "start",
1548
+ previewLifecycleSession({
1549
+ state: "started",
1550
+ mode: "foreground",
1551
+ projectName,
1552
+ projectDir,
1553
+ port,
1554
+ pid
1555
+ })
1556
+ );
1557
+ }
1558
+ function previewLifecycleSession(options) {
1559
+ const host = options.host ?? "127.0.0.1";
1560
+ const serverUrl = previewBaseUrl(options.port, host);
1561
+ return {
1562
+ state: options.state,
1563
+ mode: options.mode,
1564
+ projectName: options.projectName,
1565
+ projectDir: options.projectDir,
1566
+ host,
1567
+ port: options.port,
1568
+ pid: options.pid,
1569
+ serverUrl,
1570
+ studioUrl: studioDeepLink(serverUrl, options.projectName),
1571
+ ready: true,
1572
+ ...options.logPath ? { logPath: options.logPath } : {}
1573
+ };
1574
+ }
1575
+ function openStudioBrowser(url, projectName, options) {
1576
+ if (options?.noOpen) return;
1577
+ openBrowser(studioDeepLink(url, projectName), {
1578
+ browserPath: options?.browserPath,
1579
+ userDataDir: options?.userDataDir,
1580
+ remoteDebuggingPort: options?.remoteDebuggingPort,
1581
+ disableGpu: options?.browserNoGpu
1582
+ });
1583
+ }
1584
+ function printStudioSummary(projectName, serverUrl, projectDir, opts = {}) {
1585
+ const urls = studioSummaryUrls(projectName, serverUrl);
1586
+ console.log();
1587
+ console.log(` ${c.dim("Project")} ${c.accent(projectName)}`);
1588
+ console.log(` ${c.dim("Studio")} ${c.accent(urls.studioUrl)}`);
1589
+ console.log(` ${c.dim("Server")} ${c.accent(urls.serverUrl)}`);
1590
+ const hint = desktopHint(projectDir);
1591
+ if (hint) console.log(` ${c.dim("Desktop")} ${hint}`);
1592
+ console.log();
1593
+ for (const detail of opts.details ?? []) {
1594
+ console.log(` ${c.dim(detail)}`);
1595
+ }
1596
+ if (opts.details?.length && opts.footer) console.log();
1597
+ if (opts.footer) console.log(` ${c.dim(opts.footer)}`);
1598
+ console.log();
1599
+ }
1600
+ function linkProjectIntoStudioData(dir, projectsDir, projectName) {
1601
+ const symlinkPath = join2(projectsDir, projectName);
1602
+ mkdirSync2(projectsDir, { recursive: true });
1603
+ let createdSymlink = false;
1604
+ if (dir !== symlinkPath) {
1605
+ if (existsSync2(symlinkPath)) {
1606
+ try {
1607
+ const stat = lstatSync(symlinkPath);
1608
+ if (stat.isSymbolicLink() && resolve2(readlinkSync(symlinkPath)) !== resolve2(dir)) {
1609
+ unlinkSync(symlinkPath);
1610
+ }
1611
+ } catch {
1612
+ }
1613
+ }
1614
+ if (!existsSync2(symlinkPath)) {
1615
+ symlinkSync(dir, symlinkPath, process.platform === "win32" ? "junction" : "dir");
1616
+ createdSymlink = true;
1617
+ }
1618
+ }
1619
+ return { symlinkPath, createdSymlink };
1620
+ }
1621
+ function removeSymlinkOnExit(createdSymlink, symlinkPath) {
1622
+ if (!createdSymlink) return;
1623
+ process.on("exit", () => {
1624
+ try {
1625
+ if (existsSync2(symlinkPath)) unlinkSync(symlinkPath);
1626
+ } catch {
1627
+ }
1628
+ });
1629
+ }
1630
+ function waitForStudioChildClose(child, signalTarget = process) {
1631
+ const shutdown = () => {
1632
+ if (child.pid) killProcessTree(child.pid);
1633
+ };
1634
+ for (const signal of STUDIO_CHILD_SHUTDOWN_SIGNALS) signalTarget.once(signal, shutdown);
1635
+ const closed = child.exitCode !== null || child.signalCode !== null ? Promise.resolve() : new Promise((resolveClose) => {
1636
+ child.once("exit", () => resolveClose());
1637
+ });
1638
+ return closed.finally(() => {
1639
+ for (const signal of STUDIO_CHILD_SHUTDOWN_SIGNALS) signalTarget.off(signal, shutdown);
1640
+ });
1641
+ }
1642
+ function attachStudioReadyHandler(child, spinner, projectName, projectDir, options) {
1643
+ let detected = false;
1644
+ async function handleOutput(data) {
1645
+ const url = studioReadyUrl(data.toString());
1646
+ if (!url || detected) return;
1647
+ detected = true;
1648
+ if (options?.json) {
1649
+ const port = Number(new URL(url).port);
1650
+ const server = await activeServerOnPort(port);
1651
+ writeLifecycleJson(
1652
+ foregroundPreviewReadyPayload(
1653
+ projectName,
1654
+ url,
1655
+ projectDir,
1656
+ publicPreviewPid(server?.pid, child.pid ?? null)
1657
+ )
1658
+ );
1659
+ } else {
1660
+ spinner.stop(c.success("Studio running"));
1661
+ printStudioSummary(projectName, url, projectDir, {
1662
+ footer: "Press Ctrl+C to stop"
1663
+ });
1664
+ }
1665
+ openStudioBrowser(url, projectName, options);
1666
+ child.stdout.removeListener("data", handleOutput);
1667
+ child.stderr.removeListener("data", handleOutput);
1668
+ }
1669
+ child.stdout.on("data", (data) => void handleOutput(data));
1670
+ child.stderr.on("data", (data) => void handleOutput(data));
1671
+ child.on("error", (err) => {
1672
+ if (options?.json) {
1673
+ reportPreviewFailure(true, "start", "preview-start-failed", err.message);
1674
+ } else {
1675
+ spinner.stop(c.error("Failed to start studio"));
1676
+ console.error(c.dim(err.message));
1677
+ }
1678
+ });
1679
+ }
1680
+ function studioReadyUrl(output) {
1681
+ const localLine = output.split(/\r?\n/).find((line) => line.includes("Local:"));
1682
+ return localLine?.match(/https?:\/\/(?:localhost|127\.0\.0\.1|\[::1\]):\d+/)?.[0] ?? null;
1683
+ }
1684
+ function reportPreviewShutdown(json) {
1685
+ if (json) return;
1686
+ console.log();
1687
+ console.log(` ${c.dim("Shutting down studio...")}`);
1688
+ }
1689
+ async function runDevMode(dir, options) {
1690
+ const thisFile = fileURLToPath(import.meta.url);
1691
+ const repoRoot = resolve2(dirname2(thisFile), "..", "..", "..", "..");
1692
+ const projectsDir = join2(repoRoot, "packages", "studio", "data", "projects");
1693
+ const pName = options?.projectName ?? basename(dir);
1694
+ const { symlinkPath, createdSymlink } = linkProjectIntoStudioData(dir, projectsDir, pName);
1695
+ if (!options?.json) ge(c.bold("framey preview"));
1696
+ const s = ft();
1697
+ if (!options?.json) s.start("Starting studio...");
1698
+ const studioPkgDir = join2(repoRoot, "packages", "studio");
1699
+ const child = spawn("bun", ["run", "dev", "--", ...previewViteArgs(options?.port)], {
1700
+ cwd: studioPkgDir,
1701
+ stdio: ["ignore", "pipe", "pipe"],
1702
+ windowsHide: true,
1703
+ env: studioProxyEnv(options?.autoProxy ?? true, process.env, {
1704
+ projectDir: dir,
1705
+ projectName: pName,
1706
+ browserGpuMode: options?.browserGpuMode
1707
+ })
1708
+ });
1709
+ attachStudioReadyHandler(child, s, pName, dir, options);
1710
+ removeSymlinkOnExit(createdSymlink, symlinkPath);
1711
+ return waitForStudioChildClose(child);
1712
+ }
1713
+ function hasLocalStudio(dir) {
1714
+ try {
1715
+ const req = createRequire(join2(dir, "package.json"));
1716
+ const studioPkgPath = dirname2(req.resolve("@framey/studio/package.json"));
1717
+ return existsSync2(join2(studioPkgPath, "vite.config.ts"));
1718
+ } catch {
1719
+ return false;
1720
+ }
1721
+ }
1722
+ async function runLocalStudioMode(dir, options) {
1723
+ const req = createRequire(join2(dir, "package.json"));
1724
+ const studioPkgPath = dirname2(req.resolve("@framey/studio/package.json"));
1725
+ const pName = options?.projectName ?? basename(dir);
1726
+ const projectsDir = join2(studioPkgPath, "data", "projects");
1727
+ const { symlinkPath, createdSymlink } = linkProjectIntoStudioData(dir, projectsDir, pName);
1728
+ if (!options?.json) ge(c.bold("framey preview") + c.dim(" (local studio)"));
1729
+ const s = ft();
1730
+ if (!options?.json) s.start("Starting studio...");
1731
+ const viteCommand = buildNpxCommand(["vite", ...previewViteArgs(options?.port)]);
1732
+ const child = spawn(viteCommand.command, viteCommand.args, {
1733
+ cwd: studioPkgPath,
1734
+ stdio: ["ignore", "pipe", "pipe"],
1735
+ windowsHide: true,
1736
+ env: studioProxyEnv(options?.autoProxy ?? true, process.env, {
1737
+ projectDir: dir,
1738
+ projectName: pName,
1739
+ browserGpuMode: options?.browserGpuMode
1740
+ })
1741
+ });
1742
+ attachStudioReadyHandler(child, s, pName, dir, options);
1743
+ removeSymlinkOnExit(createdSymlink, symlinkPath);
1744
+ return waitForStudioChildClose(child);
1745
+ }
1746
+ async function runEmbeddedMode(dir, startPort, options) {
1747
+ const { createStudioServer, loadPreviewServerBuildSignature, resolveStudioBundle } = await import("./studioServer-N2OPUMOQ.js");
1748
+ const pName = options?.projectName ?? basename(dir);
1749
+ const studioBundle = resolveStudioBundle();
1750
+ if (!options?.json) ge(c.bold("framey preview"));
1751
+ const s = ft();
1752
+ if (!options?.json) s.start("Starting studio...");
1753
+ if (!studioBundle.available) {
1754
+ if (options?.json) {
1755
+ reportPreviewFailure(true, "start", "preview-start-failed", "Studio build missing");
1756
+ } else {
1757
+ s.stop(c.error("Studio build missing"));
1758
+ console.error();
1759
+ console.error(` ${c.dim("Could not find")} ${c.accent("index.html")} ${c.dim("in:")}`);
1760
+ for (const checkedPath of studioBundle.checkedPaths) {
1761
+ console.error(` ${c.dim("-")} ${checkedPath}`);
1762
+ }
1763
+ console.error();
1764
+ console.error(` ${c.dim("Rebuild the CLI package with")} ${c.accent("bun run build")}`);
1765
+ console.error();
1766
+ }
1767
+ setCommandExitCode(1);
1768
+ return;
1769
+ }
1770
+ const serverBuildSignature = await loadPreviewServerBuildSignature();
1771
+ let listening;
1772
+ const {
1773
+ app,
1774
+ watcher,
1775
+ shutdown: shutdownStudio
1776
+ } = createStudioServer({
1777
+ projectDir: dir,
1778
+ projectName: pName,
1779
+ autoProxy: options?.autoProxy,
1780
+ browserGpuMode: options?.browserGpuMode,
1781
+ origin: () => listening
1782
+ });
1783
+ let result;
1784
+ try {
1785
+ result = await findPortAndServe(
1786
+ app.fetch,
1787
+ startPort,
1788
+ dir,
1789
+ !!options?.forceNew,
1790
+ serverBuildSignature,
1791
+ void 0,
1792
+ options?.browserGpuMode
1793
+ );
1794
+ } catch (err) {
1795
+ watcher.close();
1796
+ if (!options?.json) s.stop(c.error("Could not start studio"));
1797
+ reportPreviewFailure(
1798
+ Boolean(options?.json),
1799
+ "start",
1800
+ "preview-start-failed",
1801
+ err.message
1802
+ );
1803
+ return;
1804
+ }
1805
+ if (result.type === "already-running") {
1806
+ watcher.close();
1807
+ const url2 = `http://localhost:${result.port}`;
1808
+ if (options?.json) {
1809
+ const server = await activeServerOnPort(result.port);
1810
+ writeLifecycleJson(
1811
+ lifecyclePayload(
1812
+ "start",
1813
+ previewLifecycleSession({
1814
+ state: "reused",
1815
+ mode: "foreground",
1816
+ projectName: pName,
1817
+ projectDir: dir,
1818
+ port: result.port,
1819
+ pid: publicPreviewPid(server?.pid, null)
1820
+ })
1821
+ )
1822
+ );
1823
+ } else {
1824
+ s.stop(c.success("Already running"));
1825
+ printStudioSummary(pName, url2, dir, {
1826
+ details: ["Reusing existing server. Use --force-new to start a fresh instance."]
1827
+ });
1828
+ }
1829
+ openStudioBrowser(url2, pName, options);
1830
+ return;
1831
+ }
1832
+ const url = `http://localhost:${result.port}`;
1833
+ listening = `http://127.0.0.1:${result.port}`;
1834
+ if (options?.json) {
1835
+ writeLifecycleJson(foregroundPreviewReadyPayload(pName, url, dir, process.pid));
1836
+ } else {
1837
+ s.stop(c.success("Studio running"));
1838
+ console.log();
1839
+ if (result.port !== startPort) {
1840
+ console.log(` ${c.warn(`Port ${startPort} is in use, using ${result.port} instead`)}`);
1841
+ console.log();
1842
+ }
1843
+ printStudioSummary(pName, url, dir, {
1844
+ details: [
1845
+ "Edit with your AI agent \u2014 it has Framey skills installed.",
1846
+ "Changes reload automatically in the studio."
1847
+ ],
1848
+ footer: "Press Ctrl+C to stop"
1849
+ });
1850
+ }
1851
+ openStudioBrowser(url, pName, options);
1852
+ void prebuildPreview(app.fetch, url, pName);
1853
+ let rl;
1854
+ if (process.platform === "win32") {
1855
+ const readline = await import("readline");
1856
+ rl = readline.createInterface({
1857
+ input: process.stdin,
1858
+ output: process.stdout
1859
+ });
1860
+ rl.on("SIGINT", () => {
1861
+ process.emit("SIGINT", "SIGINT");
1862
+ });
1863
+ }
1864
+ return new Promise((resolveRun) => {
1865
+ let shuttingDown = false;
1866
+ const shutdown = () => {
1867
+ if (shuttingDown) return;
1868
+ shuttingDown = true;
1869
+ rl?.close();
1870
+ reportPreviewShutdown(Boolean(options?.json));
1871
+ setTimeout(() => requestCliExit(0), 3e3).unref();
1872
+ shutdownStudio().catch(() => {
1873
+ }).finally(() => {
1874
+ watcher.close();
1875
+ result.server.close(() => resolveRun());
1876
+ });
1877
+ };
1878
+ process.on("SIGINT", shutdown);
1879
+ process.on("SIGTERM", shutdown);
1880
+ import("./src-Z5PGEMXB.js").then(({ killTrackedProcesses }) => {
1881
+ process.once("exit", () => {
1882
+ if (!shuttingDown) killTrackedProcesses();
1883
+ });
1884
+ }).catch(() => {
1885
+ });
1886
+ });
1887
+ }
1888
+ export {
1889
+ backgroundStartFailureCode,
1890
+ preview_default as default,
1891
+ examples,
1892
+ foregroundPreviewReadyPayload,
1893
+ handlePreviewKillAll,
1894
+ handlePreviewList,
1895
+ prebuildPreview,
1896
+ previewHostAppError,
1897
+ previewLaunchMode,
1898
+ previewLaunchModeError,
1899
+ previewPortError,
1900
+ previewViteArgs,
1901
+ publicPreviewPid,
1902
+ reportPreviewShutdown,
1903
+ runDevMode,
1904
+ runEmbeddedMode,
1905
+ runLocalStudioMode,
1906
+ studioDeepLink,
1907
+ studioReadyUrl,
1908
+ studioSummaryUrls,
1909
+ waitForStudioChildClose
1910
+ };