@ignix-social/editor 0.1.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.
- package/LICENSE +190 -0
- package/NOTICE +54 -0
- package/README.md +23 -0
- package/bin/ignix-editor.mjs +8 -0
- package/package.json +53 -0
- package/patches/index.mjs +53 -0
- package/scripts/build-ffmpeg-macos.sh +35 -0
- package/scripts/build-whisper-macos.sh +21 -0
- package/scripts/vendor.mjs +41 -0
- package/skills/ignix-editor/SKILL.md +132 -0
- package/src/audio.mjs +31 -0
- package/src/binaries.json +46 -0
- package/src/binaries.mjs +83 -0
- package/src/cli.mjs +254 -0
- package/src/prepare.mjs +74 -0
- package/src/runtime/ignix-frame.js +92 -0
- package/src/transcribe.mjs +71 -0
- package/src/validate.mjs +71 -0
- package/templates/blank/index.html +41 -0
- package/vendor/hyperframes/README.md +181 -0
- package/vendor/hyperframes/UPSTREAM.json +12 -0
- package/vendor/hyperframes/bin/hyperframes-localize-fonts.mjs +12 -0
- package/vendor/hyperframes/bin/hyperframes.mjs +11 -0
- package/vendor/hyperframes/dist/add-LR3ZR2A5.js +79 -0
- package/vendor/hyperframes/dist/agentPromptGenerator-VIIPZCJ3.js +143 -0
- package/vendor/hyperframes/dist/animatedGifPrep-P2T6YM7Z.js +34 -0
- package/vendor/hyperframes/dist/asset-BE2DOV72.js +26 -0
- package/vendor/hyperframes/dist/assetCataloger-VBLPHX24.js +340 -0
- package/vendor/hyperframes/dist/auth-RCQB2ZT7.js +60 -0
- package/vendor/hyperframes/dist/autoUpdate-RJAX3DAZ.js +268 -0
- package/vendor/hyperframes/dist/backgroundChecks-H2LCUIMJ.js +61 -0
- package/vendor/hyperframes/dist/backgroundChecksWorker.js +26 -0
- package/vendor/hyperframes/dist/batchRender-FT7AP7XH.js +355 -0
- package/vendor/hyperframes/dist/beat-analyzer.global.js +338 -0
- package/vendor/hyperframes/dist/beats-Y2EOP72P.js +309 -0
- package/vendor/hyperframes/dist/benchmark-MZ7GY3JW.js +231 -0
- package/vendor/hyperframes/dist/browser-HUTAMRQE.js +237 -0
- package/vendor/hyperframes/dist/bundleWithLocalizedFonts-5QOPOB5D.js +52 -0
- package/vendor/hyperframes/dist/capture-RLZA6EMR.js +4079 -0
- package/vendor/hyperframes/dist/capture-SZZ4IYJK.js +290 -0
- package/vendor/hyperframes/dist/captureFile-LYOJOUIE.js +15 -0
- package/vendor/hyperframes/dist/captureTimeout-PA4FYWT5.js +27 -0
- package/vendor/hyperframes/dist/catalog-KYU55EWR.js +1001 -0
- package/vendor/hyperframes/dist/check-TCG4PXLR.js +1697 -0
- package/vendor/hyperframes/dist/checkBrowser-RPMO4OW5.js +1032 -0
- package/vendor/hyperframes/dist/chunk-2EAXUCCE.js +88 -0
- package/vendor/hyperframes/dist/chunk-2EGFTPWD.js +1077 -0
- package/vendor/hyperframes/dist/chunk-2PSPARWP.js +6058 -0
- package/vendor/hyperframes/dist/chunk-2YN64IN5.js +5747 -0
- package/vendor/hyperframes/dist/chunk-3GXQPCJC.js +682 -0
- package/vendor/hyperframes/dist/chunk-3ZP5DXE7.js +15 -0
- package/vendor/hyperframes/dist/chunk-4NWOGZZS.js +1990 -0
- package/vendor/hyperframes/dist/chunk-4PFZPP2N.js +587 -0
- package/vendor/hyperframes/dist/chunk-4THIAPBL.js +128 -0
- package/vendor/hyperframes/dist/chunk-4YYJOFKS.js +28 -0
- package/vendor/hyperframes/dist/chunk-54HJ63Q2.js +29 -0
- package/vendor/hyperframes/dist/chunk-5ETJX6WM.js +89 -0
- package/vendor/hyperframes/dist/chunk-5IAKAQA7.js +389 -0
- package/vendor/hyperframes/dist/chunk-5Z63TBTX.js +37 -0
- package/vendor/hyperframes/dist/chunk-6BEFEWFB.js +25 -0
- package/vendor/hyperframes/dist/chunk-6CSYCFQV.js +68 -0
- package/vendor/hyperframes/dist/chunk-6CTIGJY7.js +154 -0
- package/vendor/hyperframes/dist/chunk-7HG4BFIN.js +93 -0
- package/vendor/hyperframes/dist/chunk-7JZ4FXP2.js +118 -0
- package/vendor/hyperframes/dist/chunk-A2Z4Z4VL.js +2961 -0
- package/vendor/hyperframes/dist/chunk-AMKC3AXA.js +25 -0
- package/vendor/hyperframes/dist/chunk-AVUUN2XD.js +4847 -0
- package/vendor/hyperframes/dist/chunk-AWDFDFI3.js +46 -0
- package/vendor/hyperframes/dist/chunk-AWNBM3MZ.js +94 -0
- package/vendor/hyperframes/dist/chunk-BXCMXMJQ.js +73 -0
- package/vendor/hyperframes/dist/chunk-BZ56MTDX.js +6 -0
- package/vendor/hyperframes/dist/chunk-CFKU7HTK.js +171 -0
- package/vendor/hyperframes/dist/chunk-CWPVM2QV.js +308 -0
- package/vendor/hyperframes/dist/chunk-DPVXBVLL.js +31292 -0
- package/vendor/hyperframes/dist/chunk-DQBY7FRR.js +397 -0
- package/vendor/hyperframes/dist/chunk-E6RPWJVC.js +213 -0
- package/vendor/hyperframes/dist/chunk-EISRN4E6.js +294 -0
- package/vendor/hyperframes/dist/chunk-EOVYQ3IG.js +143 -0
- package/vendor/hyperframes/dist/chunk-F3WZGU7C.js +479 -0
- package/vendor/hyperframes/dist/chunk-FCSIGXXP.js +366 -0
- package/vendor/hyperframes/dist/chunk-FI4I7CME.js +56 -0
- package/vendor/hyperframes/dist/chunk-FLWXXDNS.js +15 -0
- package/vendor/hyperframes/dist/chunk-GK4AIFIH.js +11171 -0
- package/vendor/hyperframes/dist/chunk-GMECXFAN.js +57 -0
- package/vendor/hyperframes/dist/chunk-GULOKZLI.js +155 -0
- package/vendor/hyperframes/dist/chunk-H4YZZ2VQ.js +68 -0
- package/vendor/hyperframes/dist/chunk-H6QMKUYA.js +477 -0
- package/vendor/hyperframes/dist/chunk-HBBJFK6I.js +273 -0
- package/vendor/hyperframes/dist/chunk-HRUGC23L.js +212 -0
- package/vendor/hyperframes/dist/chunk-HVW7ABXD.js +19 -0
- package/vendor/hyperframes/dist/chunk-HW6OYASV.js +344 -0
- package/vendor/hyperframes/dist/chunk-HWKCIWQT.js +3578 -0
- package/vendor/hyperframes/dist/chunk-I465DBM6.js +1214 -0
- package/vendor/hyperframes/dist/chunk-IGLEPPTN.js +24 -0
- package/vendor/hyperframes/dist/chunk-IGNAAHS3.js +433 -0
- package/vendor/hyperframes/dist/chunk-IHFUKJOR.js +85 -0
- package/vendor/hyperframes/dist/chunk-IQ3OUQ5Z.js +213 -0
- package/vendor/hyperframes/dist/chunk-ISN5GRYI.js +20 -0
- package/vendor/hyperframes/dist/chunk-IUZFXWSV.js +446 -0
- package/vendor/hyperframes/dist/chunk-JH556Q42.js +647 -0
- package/vendor/hyperframes/dist/chunk-JTHMTOMQ.js +601 -0
- package/vendor/hyperframes/dist/chunk-K2EQN4VU.js +405 -0
- package/vendor/hyperframes/dist/chunk-K2FTXJYH.js +16044 -0
- package/vendor/hyperframes/dist/chunk-K4WIOZFP.js +32 -0
- package/vendor/hyperframes/dist/chunk-K4WKGXRC.js +18 -0
- package/vendor/hyperframes/dist/chunk-KBJUXVOJ.js +172 -0
- package/vendor/hyperframes/dist/chunk-KC5XXX3X.js +590 -0
- package/vendor/hyperframes/dist/chunk-KNU5COPB.js +29 -0
- package/vendor/hyperframes/dist/chunk-KZI44OPA.js +185 -0
- package/vendor/hyperframes/dist/chunk-L3YOGIPG.js +48 -0
- package/vendor/hyperframes/dist/chunk-LAOCA3MQ.js +189 -0
- package/vendor/hyperframes/dist/chunk-LCSMOLGX.js +312 -0
- package/vendor/hyperframes/dist/chunk-LFGJWOVA.js +61 -0
- package/vendor/hyperframes/dist/chunk-LHSR3M4M.js +498 -0
- package/vendor/hyperframes/dist/chunk-LYNI3FOL.js +123 -0
- package/vendor/hyperframes/dist/chunk-M2WBOQ2Q.js +54 -0
- package/vendor/hyperframes/dist/chunk-MRF4AMKD.js +104 -0
- package/vendor/hyperframes/dist/chunk-MWB3ZIFM.js +852 -0
- package/vendor/hyperframes/dist/chunk-NGKM64BP.js +39 -0
- package/vendor/hyperframes/dist/chunk-NXMYHJAL.js +43 -0
- package/vendor/hyperframes/dist/chunk-OAF4XJOW.js +192 -0
- package/vendor/hyperframes/dist/chunk-OFQWTKPW.js +117 -0
- package/vendor/hyperframes/dist/chunk-P6LJ4Y32.js +4662 -0
- package/vendor/hyperframes/dist/chunk-PBN6GBJE.js +108 -0
- package/vendor/hyperframes/dist/chunk-PDAMK4Q5.js +28 -0
- package/vendor/hyperframes/dist/chunk-PFCFR3KZ.js +20 -0
- package/vendor/hyperframes/dist/chunk-PJ3HDUCY.js +108 -0
- package/vendor/hyperframes/dist/chunk-PMRBLBUP.js +152 -0
- package/vendor/hyperframes/dist/chunk-PPQUYWTW.js +240 -0
- package/vendor/hyperframes/dist/chunk-Q5X2B5WT.js +29 -0
- package/vendor/hyperframes/dist/chunk-Q7IU7MOR.js +351 -0
- package/vendor/hyperframes/dist/chunk-QC4FJVLM.js +371 -0
- package/vendor/hyperframes/dist/chunk-QNYYOUU3.js +1318 -0
- package/vendor/hyperframes/dist/chunk-RDNNAKEP.js +161 -0
- package/vendor/hyperframes/dist/chunk-RMHUQGRK.js +657 -0
- package/vendor/hyperframes/dist/chunk-RQVDTPGD.js +6 -0
- package/vendor/hyperframes/dist/chunk-RVCWIIZ7.js +68 -0
- package/vendor/hyperframes/dist/chunk-S3D6GE5W.js +72 -0
- package/vendor/hyperframes/dist/chunk-S3S4TGEH.js +424 -0
- package/vendor/hyperframes/dist/chunk-S7NPLFWV.js +11395 -0
- package/vendor/hyperframes/dist/chunk-SHB5VDMH.js +51 -0
- package/vendor/hyperframes/dist/chunk-TCLGPL65.js +860 -0
- package/vendor/hyperframes/dist/chunk-THXFSPLV.js +40 -0
- package/vendor/hyperframes/dist/chunk-TJSTGSAW.js +354 -0
- package/vendor/hyperframes/dist/chunk-TQFG7HTI.js +1024 -0
- package/vendor/hyperframes/dist/chunk-TVCRUG2S.js +265 -0
- package/vendor/hyperframes/dist/chunk-TWWSYAKJ.js +24 -0
- package/vendor/hyperframes/dist/chunk-U7CZBDMV.js +27 -0
- package/vendor/hyperframes/dist/chunk-UEZXMWG3.js +139 -0
- package/vendor/hyperframes/dist/chunk-UYEZTK4U.js +61 -0
- package/vendor/hyperframes/dist/chunk-VC76R6W2.js +27 -0
- package/vendor/hyperframes/dist/chunk-VFCKXTBB.js +159 -0
- package/vendor/hyperframes/dist/chunk-VWG7OQKU.js +22 -0
- package/vendor/hyperframes/dist/chunk-VXVRPIJA.js +105 -0
- package/vendor/hyperframes/dist/chunk-WBLXWOYK.js +15 -0
- package/vendor/hyperframes/dist/chunk-WERLJGIC.js +20 -0
- package/vendor/hyperframes/dist/chunk-WMQNIQDJ.js +2057 -0
- package/vendor/hyperframes/dist/chunk-WPHMNO44.js +4528 -0
- package/vendor/hyperframes/dist/chunk-X5HWXQPU.js +113 -0
- package/vendor/hyperframes/dist/chunk-X7MTZ4T2.js +6 -0
- package/vendor/hyperframes/dist/chunk-XH4DSOS5.js +59 -0
- package/vendor/hyperframes/dist/chunk-XS4EJSKU.js +23 -0
- package/vendor/hyperframes/dist/chunk-XT5P4QMO.js +181 -0
- package/vendor/hyperframes/dist/chunk-XT7X6QCP.js +6 -0
- package/vendor/hyperframes/dist/chunk-XUHOIDKG.js +6 -0
- package/vendor/hyperframes/dist/chunk-XUXGIA7H.js +485 -0
- package/vendor/hyperframes/dist/chunk-XZABUQTX.js +113 -0
- package/vendor/hyperframes/dist/chunk-Y6W4DVPS.js +356 -0
- package/vendor/hyperframes/dist/chunk-YEIFI443.js +44 -0
- package/vendor/hyperframes/dist/chunk-YQZNILVH.js +375 -0
- package/vendor/hyperframes/dist/chunk-Z27A7NUB.js +65 -0
- package/vendor/hyperframes/dist/chunk-Z6B37SNM.js +3081 -0
- package/vendor/hyperframes/dist/chunk-ZJUKFZ2P.js +10954 -0
- package/vendor/hyperframes/dist/chunk-ZKDMAOFU.js +32 -0
- package/vendor/hyperframes/dist/chunk-ZMXUQLI2.js +17219 -0
- package/vendor/hyperframes/dist/chunk-ZTZ7NCJT.js +58 -0
- package/vendor/hyperframes/dist/chunk-ZTZA4UWZ.js +108 -0
- package/vendor/hyperframes/dist/clean-W57E5YQ3.js +293 -0
- package/vendor/hyperframes/dist/cli.js +495 -0
- package/vendor/hyperframes/dist/cloud-FFTJGZ24.js +70 -0
- package/vendor/hyperframes/dist/cloudrun-AJUTHUEA.js +763 -0
- package/vendor/hyperframes/dist/colors-HKWSZCGK.js +15 -0
- package/vendor/hyperframes/dist/commands/contrast-audit.browser.js +459 -0
- package/vendor/hyperframes/dist/commands/layout-audit.browser.js +2102 -0
- package/vendor/hyperframes/dist/commands/motion-sample.browser.js +74 -0
- package/vendor/hyperframes/dist/commands/motion-signature.browser.js +374 -0
- package/vendor/hyperframes/dist/compare-AYCTT55F.js +421 -0
- package/vendor/hyperframes/dist/compiler-QO36EXLS.js +121 -0
- package/vendor/hyperframes/dist/component-VFFR2O7T.js +176 -0
- package/vendor/hyperframes/dist/compositions-QTVN3U2A.js +228 -0
- package/vendor/hyperframes/dist/contactSheet-27SRU7A4.js +22 -0
- package/vendor/hyperframes/dist/delete-ZAKYCB7I.js +114 -0
- package/vendor/hyperframes/dist/deploy-MX76RZ36.js +101 -0
- package/vendor/hyperframes/dist/destroy-H2TZBYHH.js +42 -0
- package/vendor/hyperframes/dist/deterministicFonts-HAEMV4TM.js +50 -0
- package/vendor/hyperframes/dist/dist-EWXJGN63.js +129 -0
- package/vendor/hyperframes/dist/dist-FNNGCKFS.js +29 -0
- package/vendor/hyperframes/dist/dist-S3PJNPXQ.js +392 -0
- package/vendor/hyperframes/dist/docker/Dockerfile.render +65 -0
- package/vendor/hyperframes/dist/docs/compositions.md +67 -0
- package/vendor/hyperframes/dist/docs/data-attributes.md +27 -0
- package/vendor/hyperframes/dist/docs/examples.md +19 -0
- package/vendor/hyperframes/dist/docs/gsap.md +26 -0
- package/vendor/hyperframes/dist/docs/rendering.md +35 -0
- package/vendor/hyperframes/dist/docs/troubleshooting.md +29 -0
- package/vendor/hyperframes/dist/docs-QAPJEGLS.js +131 -0
- package/vendor/hyperframes/dist/doctor-AI7C3FON.js +67 -0
- package/vendor/hyperframes/dist/dom-IROKGVJI.js +14 -0
- package/vendor/hyperframes/dist/dotEnv-AECLXQSO.js +14 -0
- package/vendor/hyperframes/dist/events-7LALYNKZ.js +92 -0
- package/vendor/hyperframes/dist/events-FQY3HGKZ.js +88 -0
- package/vendor/hyperframes/dist/feedback-WCMDMSTK.js +472 -0
- package/vendor/hyperframes/dist/ffmpeg-QIUFEFTY.js +35 -0
- package/vendor/hyperframes/dist/figma-64WY462P.js +63 -0
- package/vendor/hyperframes/dist/fontData.generated-NXAOI4GH.js +13 -0
- package/vendor/hyperframes/dist/fontLocalizeCli.js +132 -0
- package/vendor/hyperframes/dist/get-FPOMJMZB.js +103 -0
- package/vendor/hyperframes/dist/gpuPolicy-2ZUZE5D6.js +38 -0
- package/vendor/hyperframes/dist/grade-compare-E2CKPST4.js +647 -0
- package/vendor/hyperframes/dist/gsapParser-DIYYX6JT.js +2846 -0
- package/vendor/hyperframes/dist/gsapParserAcorn-E3GEIRZB.js +28 -0
- package/vendor/hyperframes/dist/help-YRQIDDML.js +197 -0
- package/vendor/hyperframes/dist/history-PP5NDRV3.js +571 -0
- package/vendor/hyperframes/dist/hyperframe-runtime.js +1081 -0
- package/vendor/hyperframes/dist/hyperframe.manifest.json +22 -0
- package/vendor/hyperframes/dist/hyperframe.runtime.iife.js +1081 -0
- package/vendor/hyperframes/dist/hyperframes-player.global.js +474 -0
- package/vendor/hyperframes/dist/hyperframes-slideshow.global.js +149 -0
- package/vendor/hyperframes/dist/info-SEX3B7JL.js +153 -0
- package/vendor/hyperframes/dist/init-U3AKHO5B.js +1147 -0
- package/vendor/hyperframes/dist/inspect-Q3K6EDEK.js +97 -0
- package/vendor/hyperframes/dist/installer-K6O5WF44.js +37 -0
- package/vendor/hyperframes/dist/keyframes-DC64JCI3.js +2602 -0
- package/vendor/hyperframes/dist/lambda-D7UMN4DJ.js +451 -0
- package/vendor/hyperframes/dist/layout-XSPPDHOO.js +86 -0
- package/vendor/hyperframes/dist/lib-TPG2ZMAX.js +128 -0
- package/vendor/hyperframes/dist/lint-7DQZE7L3.js +164 -0
- package/vendor/hyperframes/dist/lintProject-OHBBM3DJ.js +27 -0
- package/vendor/hyperframes/dist/list-4K5MVDQX.js +162 -0
- package/vendor/hyperframes/dist/login-NTX4OWXL.js +377 -0
- package/vendor/hyperframes/dist/logout-Q654A3SI.js +100 -0
- package/vendor/hyperframes/dist/manager-67P2XFXQ.js +34 -0
- package/vendor/hyperframes/dist/manager-CT3D67CG.js +38 -0
- package/vendor/hyperframes/dist/manager-GFN75DM4.js +30 -0
- package/vendor/hyperframes/dist/media-treatment-5FYAOPNL.js +972 -0
- package/vendor/hyperframes/dist/media-use-4XXGABIL.js +113 -0
- package/vendor/hyperframes/dist/models-C4E4IWJD.js +137 -0
- package/vendor/hyperframes/dist/motionShot-S4MIGMT5.js +614 -0
- package/vendor/hyperframes/dist/normalize-O76AC4HE.js +333 -0
- package/vendor/hyperframes/dist/normalize-audio-CSFTXLXD.js +276 -0
- package/vendor/hyperframes/dist/open-2ZD6BHZG.js +115 -0
- package/vendor/hyperframes/dist/pipeline-TNGWUZQC.js +54 -0
- package/vendor/hyperframes/dist/play-CTMUXX6E.js +349 -0
- package/vendor/hyperframes/dist/policies-FSDZVS2E.js +292 -0
- package/vendor/hyperframes/dist/preflight-SMNV6RW2.js +45 -0
- package/vendor/hyperframes/dist/present-WQVHV5CR.js +350 -0
- package/vendor/hyperframes/dist/preview-JOJXTH75.js +1820 -0
- package/vendor/hyperframes/dist/producer-ECLEN5RP.js +13 -0
- package/vendor/hyperframes/dist/progress-FBIEEB7Y.js +73 -0
- package/vendor/hyperframes/dist/projectConfig-HYJMJ5BY.js +56 -0
- package/vendor/hyperframes/dist/publication-HQ5Y3KBM.js +29 -0
- package/vendor/hyperframes/dist/publish-VHDYQASC.js +430 -0
- package/vendor/hyperframes/dist/refresh-K24ETHMA.js +53 -0
- package/vendor/hyperframes/dist/remove-background-W2YX2NVH.js +253 -0
- package/vendor/hyperframes/dist/render-AO5VX3YI.js +177 -0
- package/vendor/hyperframes/dist/render-LNO62LEL.js +2367 -0
- package/vendor/hyperframes/dist/render-TTQI7TGN.js +796 -0
- package/vendor/hyperframes/dist/render-batch-YH7CTWNY.js +284 -0
- package/vendor/hyperframes/dist/renderCancellation-JPIHE47X.js +35 -0
- package/vendor/hyperframes/dist/renderSetupWorker.js +79 -0
- package/vendor/hyperframes/dist/resolver-IZ647GBZ.js +38 -0
- package/vendor/hyperframes/dist/runtimeVersion.js +18 -0
- package/vendor/hyperframes/dist/screenshotCapture-ECBTLCU6.js +179 -0
- package/vendor/hyperframes/dist/shaderTransitionWorker.js +44 -0
- package/vendor/hyperframes/dist/sherpa-KKLNW6U2.js +314 -0
- package/vendor/hyperframes/dist/sherpaWorker.js +77 -0
- package/vendor/hyperframes/dist/sites-TNVKZS73.js +52 -0
- package/vendor/hyperframes/dist/skill-ZHVLH7KX.js +15 -0
- package/vendor/hyperframes/dist/skills/hyperframes/SKILL.md +152 -0
- package/vendor/hyperframes/dist/skills/hyperframes/references/brief-contract.md +108 -0
- package/vendor/hyperframes/dist/skills/hyperframes/references/brief-format.md +72 -0
- package/vendor/hyperframes/dist/skills/hyperframes/references/capability-menu.md +47 -0
- package/vendor/hyperframes/dist/skills/hyperframes/references/frame-worker-core.md +80 -0
- package/vendor/hyperframes/dist/skills/hyperframes/references/intent-interview.md +73 -0
- package/vendor/hyperframes/dist/skills/hyperframes/references/pitch-round.md +40 -0
- package/vendor/hyperframes/dist/skills/hyperframes/references/plugin-installation.md +43 -0
- package/vendor/hyperframes/dist/skills/hyperframes/references/production-loop.md +26 -0
- package/vendor/hyperframes/dist/skills/hyperframes/references/review-loop.md +37 -0
- package/vendor/hyperframes/dist/skills/hyperframes/references/route-briefs.md +11 -0
- package/vendor/hyperframes/dist/skills/hyperframes/references/routes/embedded-captions.md +11 -0
- package/vendor/hyperframes/dist/skills/hyperframes/references/routes/faceless-explainer.md +12 -0
- package/vendor/hyperframes/dist/skills/hyperframes/references/routes/general-video.md +12 -0
- package/vendor/hyperframes/dist/skills/hyperframes/references/routes/motion-graphics.md +11 -0
- package/vendor/hyperframes/dist/skills/hyperframes/references/routes/music-to-video.md +12 -0
- package/vendor/hyperframes/dist/skills/hyperframes/references/routes/pr-to-video.md +28 -0
- package/vendor/hyperframes/dist/skills/hyperframes/references/routes/product-launch-video.md +13 -0
- package/vendor/hyperframes/dist/skills/hyperframes/references/routes/remotion-to-hyperframes.md +9 -0
- package/vendor/hyperframes/dist/skills/hyperframes/references/routes/slideshow.md +11 -0
- package/vendor/hyperframes/dist/skills/hyperframes/references/routes/talking-head-recut.md +11 -0
- package/vendor/hyperframes/dist/skills/hyperframes/references/script-format.md +52 -0
- package/vendor/hyperframes/dist/skills/hyperframes/references/skill-lifecycle.md +35 -0
- package/vendor/hyperframes/dist/skills/hyperframes/references/storyboard-format.md +99 -0
- package/vendor/hyperframes/dist/skills/hyperframes/references/subagent-dispatch.md +35 -0
- package/vendor/hyperframes/dist/skills/hyperframes/references/workflow-catalog.md +10 -0
- package/vendor/hyperframes/dist/skills/hyperframes/scripts/lib/frame-packets-core.mjs +194 -0
- package/vendor/hyperframes/dist/skills/hyperframes/scripts/plugin-cli.mjs +88 -0
- package/vendor/hyperframes/dist/skills/hyperframes/scripts/plugin-cli.test.mjs +117 -0
- package/vendor/hyperframes/dist/skills/hyperframes-cli/SKILL.md +189 -0
- package/vendor/hyperframes/dist/skills/hyperframes-cli/references/beats.md +19 -0
- package/vendor/hyperframes/dist/skills/hyperframes-cli/references/cloud.md +163 -0
- package/vendor/hyperframes/dist/skills/hyperframes-cli/references/cloudrun.md +62 -0
- package/vendor/hyperframes/dist/skills/hyperframes-cli/references/compare-and-batch.md +105 -0
- package/vendor/hyperframes/dist/skills/hyperframes-cli/references/doctor-browser.md +57 -0
- package/vendor/hyperframes/dist/skills/hyperframes-cli/references/init-and-scaffold.md +74 -0
- package/vendor/hyperframes/dist/skills/hyperframes-cli/references/lambda.md +185 -0
- package/vendor/hyperframes/dist/skills/hyperframes-cli/references/lint-validate-inspect.md +132 -0
- package/vendor/hyperframes/dist/skills/hyperframes-cli/references/preview-render.md +193 -0
- package/vendor/hyperframes/dist/skills/hyperframes-cli/references/upgrade-info-misc.md +134 -0
- package/vendor/hyperframes/dist/skills/media-use/SKILL.md +100 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/assets/sfx/CREDITS.md +35 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/assets/sfx/chime.mp3 +0 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/assets/sfx/click-soft.mp3 +0 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/assets/sfx/click.mp3 +0 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/assets/sfx/error.mp3 +0 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/assets/sfx/glitch-1.mp3 +0 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/assets/sfx/glitch-2.mp3 +0 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/assets/sfx/glitch-3.mp3 +0 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/assets/sfx/impact-bass-1.mp3 +0 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/assets/sfx/impact-bass-2.mp3 +0 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/assets/sfx/key-press.mp3 +0 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/assets/sfx/manifest.json +97 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/assets/sfx/notification.mp3 +0 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/assets/sfx/ping.mp3 +0 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/assets/sfx/pop.mp3 +0 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/assets/sfx/riser.mp3 +0 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/assets/sfx/sparkle.mp3 +0 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/assets/sfx/typing.mp3 +0 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/assets/sfx/whoosh-cinematic.mp3 +0 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/assets/sfx/whoosh-short.mp3 +0 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/assets/sfx/whoosh.mp3 +0 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/references/bgm.md +76 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/references/captions/authoring.md +163 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/references/captions/motion.md +87 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/references/captions/transcript-handling.md +97 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/references/remove-background.md +143 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/references/requirements.md +29 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/references/sfx.md +42 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/references/transcribe.md +52 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/references/tts-to-captions.md +35 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/references/tts.md +260 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/audio.mjs +311 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/audio.test.mjs +159 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/gemini-pipeline.test.mjs +131 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/heygen-tts.mjs +122 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/heygen-tts.test.mjs +38 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/heygen-voice.mjs +98 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/heygen-voice.test.mjs +233 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/lib/audio-meta.mjs +39 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/lib/audio-meta.test.mjs +136 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/lib/bgm-volume.mjs +4 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/lib/bgm.mjs +257 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/lib/bgm.test.mjs +74 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/lib/concurrency.mjs +14 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/lib/concurrency.test.mjs +41 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/lib/gemini-auth.mjs +43 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/lib/gemini-auth.py +52 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/lib/gemini-auth.test.mjs +86 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/lib/gemini-auth_test.py +90 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/lib/gemini-tts.mjs +122 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/lib/gemini-tts.test.mjs +243 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/lib/heygen.mjs +197 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/lib/heygen.test.mjs +185 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/lib/media-record.mjs +114 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/lib/media-record.test.mjs +205 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/lib/python.mjs +77 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/lib/python.test.mjs +136 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/lib/sfx.mjs +165 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/lib/sfx.test.mjs +121 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/lib/tts.mjs +389 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/lib/tts.spawn.test.mjs +158 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/lib/tts.test.mjs +230 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/lyria-recipe.py +136 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/wait-bgm.mjs +175 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/wait-bgm.test.mjs +108 -0
- package/vendor/hyperframes/dist/skills/media-use/luts/README.md +28 -0
- package/vendor/hyperframes/dist/skills/media-use/luts/index.json +57 -0
- package/vendor/hyperframes/dist/skills/media-use/references/audio.md +20 -0
- package/vendor/hyperframes/dist/skills/media-use/references/grading.md +160 -0
- package/vendor/hyperframes/dist/skills/media-use/references/media-treatment-recipes.md +929 -0
- package/vendor/hyperframes/dist/skills/media-use/references/media-treatments.md +202 -0
- package/vendor/hyperframes/dist/skills/media-use/references/memory.md +37 -0
- package/vendor/hyperframes/dist/skills/media-use/references/meta.md +61 -0
- package/vendor/hyperframes/dist/skills/media-use/references/operations.md +327 -0
- package/vendor/hyperframes/dist/skills/media-use/references/resolve.md +150 -0
- package/vendor/hyperframes/dist/skills/media-use/references/setup-providers.md +80 -0
- package/vendor/hyperframes/dist/skills/media-use/references/telemetry-dashboard.md +49 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/audio-duck.mjs +113 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/compatibility.test.mjs +96 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/dither.mjs +328 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/dither.test.mjs +176 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/eval.mjs +369 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/adopt.mjs +128 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/adopt.test.mjs +95 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/bgm-provider.mjs +20 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/brand-provider.mjs +59 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/bundled-sfx-provider.mjs +119 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/bundled-sfx-provider.test.mjs +139 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/cache.mjs +148 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/candidates.mjs +91 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/candidates.test.mjs +155 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/codex-provider.mjs +161 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/codex-provider.test.mjs +34 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/config-lock.d.mts +3 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/config-lock.mjs +45 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/config-lock.test.mjs +79 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/coverage.test.mjs +136 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/cube-build.mjs +181 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/cube-build.test.mjs +80 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/cube-validate.mjs +198 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/cube-validate.test.mjs +125 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/cutlist.mjs +184 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/cutlist.test.mjs +162 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/duck.mjs +95 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/duck.test.mjs +153 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/error-diffusion.mjs +230 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/error-diffusion.test.mjs +102 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/ff-binaries.mjs +37 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/freeze.mjs +72 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/freeze.test.mjs +138 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/grade-analyzer.mjs +265 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/grade-analyzer.test.mjs +285 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/heygen-cli.mjs +191 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/heygen-cli.test.mjs +301 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/heygen-search.mjs +45 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/heygen-search.test.mjs +49 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/heygen-video-provider.mjs +138 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/heygen-video-provider.test.mjs +435 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/image-provider.mjs +44 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/index-gen.mjs +63 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/local-media-search.mjs +32 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/local-models.mjs +318 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/local-models.test.mjs +220 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/local-run.mjs +78 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/local-run.test.mjs +121 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/logo-provider.mjs +244 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/logo-provider.test.mjs +298 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/ltx-video-provider.mjs +94 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/ltx-video-provider.test.mjs +316 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/lut-preset-provider.mjs +271 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/lut-preset-provider.test.mjs +199 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/manifest.d.mts +19 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/manifest.mjs +279 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/manifest.test.mjs +397 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/match.mjs +47 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/media-fetch.mjs +85 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/media-fetch.test.mjs +197 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/media-home.mjs +20 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/media-home.test.mjs +61 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/media-search.d.mts +9 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/media-search.mjs +107 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/mflux-provider.mjs +128 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/mflux-provider.test.mjs +174 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/misses.mjs +49 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/misses.test.mjs +89 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/npx-sync.mjs +31 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/npx-sync.test.mjs +50 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/parakeet-words.mjs +27 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/parakeet-words.test.mjs +44 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/prefs-store.mjs +180 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/prefs-store.test.mjs +189 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/probe.mjs +41 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/probe.test.mjs +148 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/providers.mjs +5 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/recipe-store.mjs +367 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/recipe-store.test.mjs +367 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/registry.mjs +212 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/registry.test.mjs +262 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/search.mjs +24 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/search.test.mjs +32 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/sfx-provider.mjs +23 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/specs.mjs +132 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/specs.test.mjs +157 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/stats.mjs +117 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/stats.test.mjs +165 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/svg-sanitize.mjs +21 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/telemetry.mjs +210 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/telemetry.test.mjs +437 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/test-home.test.mjs +10 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/transcriptCutFade.mjs +21 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/transcriptCutFade.test.mjs +33 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/tts-local-provider.mjs +94 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/tts-local-provider.test.mjs +72 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/usage.mjs +57 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/usage.test.mjs +54 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/voice-provider.mjs +57 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/voice-provider.test.mjs +46 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/words.mjs +18 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/prefs.mjs +70 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/recipe.mjs +103 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/resolve-plugin.test.mjs +62 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/resolve.mjs +1369 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/transcribe.mjs +194 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/transcribe.test.mjs +112 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/transcript-cut.mjs +270 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/transcript-cut.test.mjs +117 -0
- package/vendor/hyperframes/dist/skills-MJ2J4GEM.js +808 -0
- package/vendor/hyperframes/dist/skillsUpdateCheck-TKTYQN5R.js +26 -0
- package/vendor/hyperframes/dist/slideshow-EJ4IMY6P.js +24 -0
- package/vendor/hyperframes/dist/snapshot-KIVDUUMN.js +875 -0
- package/vendor/hyperframes/dist/src-6YQBJGWR.js +202 -0
- package/vendor/hyperframes/dist/src-PVYUYV3M.js +471 -0
- package/vendor/hyperframes/dist/state-KAXGHF77.js +26 -0
- package/vendor/hyperframes/dist/staticProjectServer-7EU666GS.js +49 -0
- package/vendor/hyperframes/dist/status-YM52BQ6S.js +311 -0
- package/vendor/hyperframes/dist/studio/assets/hyperframes-player-Cp8e_Zst.js +473 -0
- package/vendor/hyperframes/dist/studio/assets/index-BX3KHhGX.js +71 -0
- package/vendor/hyperframes/dist/studio/assets/index-CASEBNy2.js +1 -0
- package/vendor/hyperframes/dist/studio/assets/index-D11atkBt.css +1 -0
- package/vendor/hyperframes/dist/studio/assets/index-DMTt9nTf.js +531 -0
- package/vendor/hyperframes/dist/studio/assets/index-oE1pOdAy.js +399 -0
- package/vendor/hyperframes/dist/studio/chunk-5VSXRGIX.js +948 -0
- package/vendor/hyperframes/dist/studio/chunk-5VSXRGIX.js.map +1 -0
- package/vendor/hyperframes/dist/studio/chunk-7UQWVN52.js +938 -0
- package/vendor/hyperframes/dist/studio/chunk-7UQWVN52.js.map +1 -0
- package/vendor/hyperframes/dist/studio/chunk-EEXSYY5F.js +190 -0
- package/vendor/hyperframes/dist/studio/chunk-EEXSYY5F.js.map +1 -0
- package/vendor/hyperframes/dist/studio/chunk-FOEID72M.js +1441 -0
- package/vendor/hyperframes/dist/studio/chunk-FOEID72M.js.map +1 -0
- package/vendor/hyperframes/dist/studio/chunk-PZ5AY32C.js +10 -0
- package/vendor/hyperframes/dist/studio/chunk-PZ5AY32C.js.map +1 -0
- package/vendor/hyperframes/dist/studio/chunk-TDWGXBUT.js +1103 -0
- package/vendor/hyperframes/dist/studio/chunk-TDWGXBUT.js.map +1 -0
- package/vendor/hyperframes/dist/studio/domEditingLayers-IEVLO54Z.js +47 -0
- package/vendor/hyperframes/dist/studio/domEditingLayers-IEVLO54Z.js.map +1 -0
- package/vendor/hyperframes/dist/studio/favicon.svg +14 -0
- package/vendor/hyperframes/dist/studio/icons/timeline/audio.svg +7 -0
- package/vendor/hyperframes/dist/studio/icons/timeline/captions.svg +5 -0
- package/vendor/hyperframes/dist/studio/icons/timeline/composition.svg +12 -0
- package/vendor/hyperframes/dist/studio/icons/timeline/image.svg +18 -0
- package/vendor/hyperframes/dist/studio/icons/timeline/music.svg +10 -0
- package/vendor/hyperframes/dist/studio/icons/timeline/text.svg +3 -0
- package/vendor/hyperframes/dist/studio/index.css +165 -0
- package/vendor/hyperframes/dist/studio/index.css.map +1 -0
- package/vendor/hyperframes/dist/studio/index.d.ts +4296 -0
- package/vendor/hyperframes/dist/studio/index.html +23 -0
- package/vendor/hyperframes/dist/studio/index.js +99693 -0
- package/vendor/hyperframes/dist/studio/index.js.map +1 -0
- package/vendor/hyperframes/dist/studio/player.d.ts +30 -0
- package/vendor/hyperframes/dist/studio/player.js +10 -0
- package/vendor/hyperframes/dist/studio/player.js.map +1 -0
- package/vendor/hyperframes/dist/studio/styles/tailwind-preset.d.ts +39 -0
- package/vendor/hyperframes/dist/studio/styles/tailwind-preset.js +50 -0
- package/vendor/hyperframes/dist/studio/styles/tailwind-preset.js.map +1 -0
- package/vendor/hyperframes/dist/studio/styles.css +1 -0
- package/vendor/hyperframes/dist/studio/ui.d.ts +296 -0
- package/vendor/hyperframes/dist/studio/ui.js +66 -0
- package/vendor/hyperframes/dist/studio/ui.js.map +1 -0
- package/vendor/hyperframes/dist/studio-api-PNQZRPX5.js +136 -0
- package/vendor/hyperframes/dist/studioSelectionClient-IUUPKUHZ.js +25 -0
- package/vendor/hyperframes/dist/studioServer-UWRBPIOJ.js +1457 -0
- package/vendor/hyperframes/dist/synthesize-K62TIZWI.js +182 -0
- package/vendor/hyperframes/dist/system-EZYZNUFD.js +44 -0
- package/vendor/hyperframes/dist/telemetry-2YC4SGQU.js +144 -0
- package/vendor/hyperframes/dist/telemetry-QMYM4WME.js +95 -0
- package/vendor/hyperframes/dist/templates/_shared/AGENTS.md +107 -0
- package/vendor/hyperframes/dist/templates/_shared/CLAUDE.md +107 -0
- package/vendor/hyperframes/dist/templates/blank/index.html +55 -0
- package/vendor/hyperframes/dist/templates/from-file/index.html +75 -0
- package/vendor/hyperframes/dist/templates/warm-grain/compositions/captions.html +154 -0
- package/vendor/hyperframes/dist/templates/warm-grain/compositions/graphics.html +162 -0
- package/vendor/hyperframes/dist/templates/warm-grain/compositions/intro.html +87 -0
- package/vendor/hyperframes/dist/templates/warm-grain/index.html +264 -0
- package/vendor/hyperframes/dist/templates/warm-grain/registry-item.json +34 -0
- package/vendor/hyperframes/dist/timeline-77Z3BBQM.js +1377 -0
- package/vendor/hyperframes/dist/tokens-OBGTYE4Z.js +92 -0
- package/vendor/hyperframes/dist/transcribe-7NVFHCGA.js +387 -0
- package/vendor/hyperframes/dist/transcribe-BNSJRR4M.js +62 -0
- package/vendor/hyperframes/dist/tts-P3LIPIL5.js +234 -0
- package/vendor/hyperframes/dist/updateCheck-UDWIJ4ZQ.js +39 -0
- package/vendor/hyperframes/dist/upgrade-CT3CPO3E.js +231 -0
- package/vendor/hyperframes/dist/urlDownloader-H6WRI2UE.js +39 -0
- package/vendor/hyperframes/dist/usage-EC3KFUIJ.js +2139 -0
- package/vendor/hyperframes/dist/validate-65QDZJWZ.js +70 -0
- package/vendor/hyperframes/dist/video-FGSGKRSV.js +261 -0
- package/vendor/hyperframes/dist/workspaceBuildCheck-TOLGAI4T.js +133 -0
- package/vendor/hyperframes/package.json +80 -0
|
@@ -0,0 +1,1369 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { spawnSync } from "node:child_process";
|
|
4
|
+
import { existsSync, statSync, writeFileSync, renameSync, rmSync, realpathSync } from "node:fs";
|
|
5
|
+
import { resolve, join, extname, basename, relative, isAbsolute, sep } from "node:path";
|
|
6
|
+
import { parseArgs } from "node:util";
|
|
7
|
+
import {
|
|
8
|
+
AGENT_SOURCES,
|
|
9
|
+
appendRecord,
|
|
10
|
+
latestRecordFor,
|
|
11
|
+
recordInPlace,
|
|
12
|
+
findByPrompt,
|
|
13
|
+
findByEntity,
|
|
14
|
+
nextId,
|
|
15
|
+
withReservedFile,
|
|
16
|
+
withReservedFileSync,
|
|
17
|
+
} from "./lib/manifest.mjs";
|
|
18
|
+
import { regenerateIndex } from "./lib/index-gen.mjs";
|
|
19
|
+
import { cacheGet, cacheGetByEntity, importFromCache, cachePut } from "./lib/cache.mjs";
|
|
20
|
+
import {
|
|
21
|
+
runCapability,
|
|
22
|
+
listTypes,
|
|
23
|
+
providerMatches,
|
|
24
|
+
providerNamesFor,
|
|
25
|
+
providerTierFor,
|
|
26
|
+
} from "./lib/registry.mjs";
|
|
27
|
+
import { freezeUrl, freezeLocalFile, isDirectMediaUrl } from "./lib/freeze.mjs";
|
|
28
|
+
import { findExistingAsset } from "./lib/adopt.mjs";
|
|
29
|
+
import { probe as probeMedia } from "./lib/probe.mjs";
|
|
30
|
+
import { track } from "./lib/telemetry.mjs";
|
|
31
|
+
import { recordMiss } from "./lib/misses.mjs";
|
|
32
|
+
import { buildStats } from "./lib/stats.mjs";
|
|
33
|
+
import { typesMatch } from "./lib/match.mjs";
|
|
34
|
+
import { listCandidates, formatCandidates, CANDIDATE_CAP } from "./lib/candidates.mjs";
|
|
35
|
+
import { findGlobalBySha } from "./lib/cache.mjs";
|
|
36
|
+
import { heygenAuthMethod } from "../audio/scripts/lib/heygen.mjs";
|
|
37
|
+
import { buildCube, paramsFromIntent } from "./lib/cube-build.mjs";
|
|
38
|
+
import { validateCubeFile } from "./lib/cube-validate.mjs";
|
|
39
|
+
import { analyzeMediaGrade, formatMeasuredNote } from "./lib/grade-analyzer.mjs";
|
|
40
|
+
import { FfBinarySettingError, ffmpegBinary, ffprobeBinary } from "./lib/ff-binaries.mjs";
|
|
41
|
+
import {
|
|
42
|
+
freezeLibraryLut,
|
|
43
|
+
isLibraryLutOfflineMiss,
|
|
44
|
+
matchColorLook,
|
|
45
|
+
} from "./lib/lut-preset-provider.mjs";
|
|
46
|
+
import {
|
|
47
|
+
HEYGEN_AUTH_COMMAND,
|
|
48
|
+
HEYGEN_INSTALL_COMMAND,
|
|
49
|
+
HEYGEN_MIN_VERSION,
|
|
50
|
+
HEYGEN_UPDATE_COMMAND,
|
|
51
|
+
consumeHeygenRemediation,
|
|
52
|
+
firstSemver,
|
|
53
|
+
flushHeygenFailureTracking,
|
|
54
|
+
versionLessThan,
|
|
55
|
+
} from "./lib/heygen-cli.mjs";
|
|
56
|
+
import { BundledSfxAssetsError, inspectBundledSfxAssets } from "./lib/bundled-sfx-provider.mjs";
|
|
57
|
+
import {
|
|
58
|
+
fetchMediaVectors,
|
|
59
|
+
mediaVectorRows,
|
|
60
|
+
rankMediaRowsWithVectors,
|
|
61
|
+
} from "./lib/local-media-search.mjs";
|
|
62
|
+
|
|
63
|
+
const INGEST_TYPES = listTypes();
|
|
64
|
+
const DEFAULT_EXT = {
|
|
65
|
+
bgm: ".wav",
|
|
66
|
+
sfx: ".mp3",
|
|
67
|
+
voice: ".wav",
|
|
68
|
+
image: ".jpg",
|
|
69
|
+
icon: ".svg",
|
|
70
|
+
logo: ".svg",
|
|
71
|
+
brand: ".png",
|
|
72
|
+
video: ".mp4",
|
|
73
|
+
grade: ".cube",
|
|
74
|
+
lut: ".cube",
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
// resolve shells `fetch`/`freezeUrl` and modern ESM; 18 is the floor where those
|
|
78
|
+
// exist without flags. Named so the --doctor node check verifies something real
|
|
79
|
+
// (O2). Declared before the top-level `--doctor` branch that calls runDoctor().
|
|
80
|
+
const MIN_NODE_VERSION = "18.0.0";
|
|
81
|
+
|
|
82
|
+
const { values: args } = parseArgs({
|
|
83
|
+
options: {
|
|
84
|
+
type: { type: "string", short: "t" },
|
|
85
|
+
intent: { type: "string", short: "i" },
|
|
86
|
+
entity: { type: "string", short: "e" },
|
|
87
|
+
project: { type: "string", short: "p", default: "." },
|
|
88
|
+
adopt: { type: "boolean", default: false },
|
|
89
|
+
candidates: { type: "boolean", default: false },
|
|
90
|
+
doctor: { type: "boolean", default: false },
|
|
91
|
+
stats: { type: "boolean", default: false },
|
|
92
|
+
days: { type: "string" },
|
|
93
|
+
"dry-run": { type: "boolean", default: false },
|
|
94
|
+
reuse: { type: "string" },
|
|
95
|
+
from: { type: "string" },
|
|
96
|
+
source: { type: "string" },
|
|
97
|
+
params: { type: "string" },
|
|
98
|
+
for: { type: "string" },
|
|
99
|
+
analyze: { type: "boolean", default: false },
|
|
100
|
+
"local-only": { type: "boolean", default: false },
|
|
101
|
+
provider: { type: "string" },
|
|
102
|
+
"avatar-id": { type: "string" },
|
|
103
|
+
"voice-id": { type: "string" },
|
|
104
|
+
json: { type: "boolean", default: false },
|
|
105
|
+
help: { type: "boolean", short: "h", default: false },
|
|
106
|
+
},
|
|
107
|
+
strict: true,
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
if (args.help) {
|
|
111
|
+
console.log(`media-use resolve — turn a media need into a frozen local file
|
|
112
|
+
|
|
113
|
+
Usage:
|
|
114
|
+
node resolve.mjs --type <type> --intent "<description>" [--project <dir>]
|
|
115
|
+
|
|
116
|
+
Types: ${listTypes().join(", ")}
|
|
117
|
+
|
|
118
|
+
Options:
|
|
119
|
+
--type, -t Media type (required)
|
|
120
|
+
--intent, -i What you need (required)
|
|
121
|
+
--entity, -e Entity name for cache matching (optional)
|
|
122
|
+
--project, -p Project directory (default: .)
|
|
123
|
+
--adopt Adopt all existing assets/ files into the manifest
|
|
124
|
+
--candidates List reusable assets (project + global cache) for --type; no
|
|
125
|
+
download, no mutation. Read them and decide reuse yourself.
|
|
126
|
+
--doctor Check local CLI dependencies; no manifest changes.
|
|
127
|
+
--stats Print local usage stats from .media and ~/.media; no mutation.
|
|
128
|
+
--days <N> Limit --stats to records/misses from the last N days when
|
|
129
|
+
timestamps are available.
|
|
130
|
+
--reuse <sha> Import a specific global-cache asset (by content sha/prefix,
|
|
131
|
+
from --candidates) into this project
|
|
132
|
+
--from <file> Freeze a local file or direct public URL (ingest)
|
|
133
|
+
--source <how> With --from: how the file was made (${AGENT_SOURCES.join(" | ")}).
|
|
134
|
+
A file already inside the project is then recorded where it is
|
|
135
|
+
--params <json> Build an explicit parametric LUT (lut/grade only)
|
|
136
|
+
--for <media> Analyze a local image/video and add measured grade adjust
|
|
137
|
+
suggestions (grade only)
|
|
138
|
+
--analyze Return --for grade evidence without recording a candidate
|
|
139
|
+
--local-only Offline: skip every network provider
|
|
140
|
+
--provider Force one generator (e.g. codex, mflux, kokoro, heygen)
|
|
141
|
+
--avatar-id Override the default avatar for heygen.video generation
|
|
142
|
+
--voice-id Override the default voice for voice/heygen.video generation
|
|
143
|
+
--json Output JSON instead of one-line result
|
|
144
|
+
--help, -h Show this help`);
|
|
145
|
+
process.exit(0);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
const projectDir = resolve(args.project);
|
|
149
|
+
const type = args.type;
|
|
150
|
+
const intent = args.intent;
|
|
151
|
+
const entity = args.entity || null;
|
|
152
|
+
|
|
153
|
+
if (args.adopt) {
|
|
154
|
+
const { adoptExistingAssets } = await import("./lib/adopt.mjs");
|
|
155
|
+
let adopted;
|
|
156
|
+
try {
|
|
157
|
+
adopted = adoptExistingAssets(projectDir);
|
|
158
|
+
} catch (err) {
|
|
159
|
+
exitError(err.message);
|
|
160
|
+
}
|
|
161
|
+
if (args.json) {
|
|
162
|
+
console.log(JSON.stringify({ ok: true, adopted: adopted.length, assets: adopted }));
|
|
163
|
+
} else if (adopted.length === 0) {
|
|
164
|
+
console.log("no new assets to adopt (assets/ empty or already registered)");
|
|
165
|
+
} else {
|
|
166
|
+
console.log(`adopted ${adopted.length} asset${adopted.length === 1 ? "" : "s"} from assets/`);
|
|
167
|
+
for (const r of adopted) console.log(` ${r.id} → ${r.path} (${r.type})`);
|
|
168
|
+
}
|
|
169
|
+
process.exit(0);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// Candidates: side-effect-free listing of reusable assets (project + global
|
|
173
|
+
// cache) for --type. No download, no provider, no mutation. The agent reads
|
|
174
|
+
// these and decides semantic fit itself.
|
|
175
|
+
if (args.candidates || args["dry-run"]) {
|
|
176
|
+
await showCandidates();
|
|
177
|
+
process.exit(0);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
if (args.doctor) {
|
|
181
|
+
const doctor = runDoctor();
|
|
182
|
+
const failed = doctor.checks.filter((check) => !check.ok);
|
|
183
|
+
// Non-PII: instrument the exact question the feature exists to answer — how
|
|
184
|
+
// often is --doctor run and which check fails most. Awaited so a short-lived
|
|
185
|
+
// run flushes before exit.
|
|
186
|
+
await track("media_use_doctor_run", {
|
|
187
|
+
ok: doctor.ok,
|
|
188
|
+
checks_failed: failed.length,
|
|
189
|
+
failed: failed.map((check) => check.name),
|
|
190
|
+
});
|
|
191
|
+
if (args.json) {
|
|
192
|
+
console.log(JSON.stringify({ ok: doctor.ok, checks: doctor.checks }));
|
|
193
|
+
} else {
|
|
194
|
+
printDoctor(doctor.checks);
|
|
195
|
+
}
|
|
196
|
+
process.exit(doctor.ok ? 0 : 1);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
if (args.stats) {
|
|
200
|
+
const report = buildStats({
|
|
201
|
+
projectDir,
|
|
202
|
+
days: args.days ? Number(args.days) : undefined,
|
|
203
|
+
});
|
|
204
|
+
if (args.json) {
|
|
205
|
+
console.log(JSON.stringify(report));
|
|
206
|
+
} else {
|
|
207
|
+
printStats(report);
|
|
208
|
+
}
|
|
209
|
+
process.exit(0);
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
// Reuse a global-cache asset selected by content sha or prefix.
|
|
213
|
+
if (args.reuse !== undefined) {
|
|
214
|
+
await reuseGlobal(args.reuse);
|
|
215
|
+
process.exit(0);
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
if (args.source && !args.from) {
|
|
219
|
+
console.error("error: --source goes with --from <file>");
|
|
220
|
+
process.exit(2);
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
// Ingest: freeze a user-supplied local file or direct public URL (no search).
|
|
224
|
+
if (args.from) {
|
|
225
|
+
await ingest(args.from);
|
|
226
|
+
process.exit(0);
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
if (args.analyze) {
|
|
230
|
+
if (type !== "grade" || !args.for) {
|
|
231
|
+
console.error("error: --analyze requires --type grade and --for <media>");
|
|
232
|
+
process.exit(2);
|
|
233
|
+
}
|
|
234
|
+
const mediaPath = resolve(args.for);
|
|
235
|
+
if (!existsSync(mediaPath)) {
|
|
236
|
+
console.error(`error: --for file not found: ${mediaPath}`);
|
|
237
|
+
process.exit(2);
|
|
238
|
+
}
|
|
239
|
+
let analysis;
|
|
240
|
+
try {
|
|
241
|
+
analysis = analyzeMediaGrade(mediaPath, {
|
|
242
|
+
ffmpegPath: ffmpegBinary(),
|
|
243
|
+
ffprobePath: ffprobeBinary(),
|
|
244
|
+
});
|
|
245
|
+
} catch (err) {
|
|
246
|
+
exitError(err.message);
|
|
247
|
+
}
|
|
248
|
+
if (args.json) {
|
|
249
|
+
console.log(JSON.stringify({ ok: true, type: "grade-analysis", ...analysis }));
|
|
250
|
+
} else {
|
|
251
|
+
console.log(formatMeasuredNote(mediaPath, analysis.measured));
|
|
252
|
+
console.log(`suggested adjust: ${JSON.stringify(analysis.adjust)}`);
|
|
253
|
+
}
|
|
254
|
+
process.exit(0);
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
// Resolve named recipe bundles without a provider.
|
|
258
|
+
if (type === "recipe") {
|
|
259
|
+
const { useRecipe } = await import("./lib/recipe-store.mjs");
|
|
260
|
+
const name = (entity || intent || "").trim();
|
|
261
|
+
if (!name) exitError("--type recipe needs --entity <name> (or --intent <name>)", 2);
|
|
262
|
+
try {
|
|
263
|
+
const used = useRecipe({ projectDir, name });
|
|
264
|
+
if (args.json) {
|
|
265
|
+
console.log(JSON.stringify({ ok: true, ...used }));
|
|
266
|
+
} else {
|
|
267
|
+
console.log(
|
|
268
|
+
`resolved recipe ${used.recipe.name} (v${used.recipe.version}, ${used.recipe.workflow})`,
|
|
269
|
+
);
|
|
270
|
+
console.log(` frame spec → ${used.frameSpecPath} (copied over)`);
|
|
271
|
+
console.log(` storyboard skeleton → ${used.skeletonPath}`);
|
|
272
|
+
if (used.briefSkeletonPath) console.log(` brief skeleton → ${used.briefSkeletonPath}`);
|
|
273
|
+
}
|
|
274
|
+
process.exit(0);
|
|
275
|
+
} catch (err) {
|
|
276
|
+
exitError(err.message, 1);
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
if (args.params !== undefined) {
|
|
281
|
+
if (type !== "lut" && type !== "grade") {
|
|
282
|
+
exitError(
|
|
283
|
+
type
|
|
284
|
+
? `--params only supports --type lut or grade (got ${type})`
|
|
285
|
+
: "--params requires --type lut or grade",
|
|
286
|
+
2,
|
|
287
|
+
);
|
|
288
|
+
}
|
|
289
|
+
try {
|
|
290
|
+
await runParams();
|
|
291
|
+
process.exit(0);
|
|
292
|
+
} catch (err) {
|
|
293
|
+
exitError(err.message, 1);
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
if (!args.type || !args.intent || !args.intent.trim()) {
|
|
298
|
+
console.error("error: --type and a non-empty --intent are required");
|
|
299
|
+
process.exit(2);
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
if (!listTypes().includes(args.type)) {
|
|
303
|
+
console.error(`error: unknown media type: ${args.type} (known: ${listTypes().join(", ")})`);
|
|
304
|
+
process.exit(2);
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
// Forced-provider validation: reject an unknown/unavailable provider name up
|
|
308
|
+
// front so a typo reads as a typo, not a catalog miss (`no provider could
|
|
309
|
+
// resolve`). Match rule mirrors runProviders (full name or dotted prefix).
|
|
310
|
+
if (args.provider && !providerMatches(args.type, args.provider)) {
|
|
311
|
+
console.error(
|
|
312
|
+
`error: unknown provider "${args.provider}" for type ${args.type} (available: ${providerNamesFor(args.type).join(", ")})`,
|
|
313
|
+
);
|
|
314
|
+
process.exit(2);
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
function recordAvailable(projectDir, record) {
|
|
318
|
+
if (!record) return false;
|
|
319
|
+
if (record.path) return existsSync(join(projectDir, record.path));
|
|
320
|
+
return record.type === "grade" && record.grading;
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
// Sparse `{ authMethod }` for a heygen-family provider name (e.g. "heygen.tts"),
|
|
324
|
+
// else `{}` — keeps auth_method telemetry absent for every non-heygen resolve
|
|
325
|
+
// instead of implying an auth method that doesn't apply.
|
|
326
|
+
function heygenAuthMethodFor(provider) {
|
|
327
|
+
if (!provider || !provider.startsWith("heygen.")) return {};
|
|
328
|
+
const authMethod = heygenAuthMethod();
|
|
329
|
+
return authMethod ? { authMethod } : {};
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
function localizeImportedRecord(record, localPath) {
|
|
333
|
+
if (record?.type === "grade" && record.grading?.lut) {
|
|
334
|
+
record.grading = {
|
|
335
|
+
...record.grading,
|
|
336
|
+
lut: { ...record.grading.lut, src: localPath },
|
|
337
|
+
};
|
|
338
|
+
}
|
|
339
|
+
return record;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
async function run() {
|
|
343
|
+
// A forced provider bypasses reuse and pins the provider cascade.
|
|
344
|
+
const forced = !!args.provider;
|
|
345
|
+
|
|
346
|
+
// 1. project manifest — exact-prompt match
|
|
347
|
+
const projectHit = forced ? null : findByPrompt(projectDir, intent, type);
|
|
348
|
+
if (recordAvailable(projectDir, projectHit)) {
|
|
349
|
+
return result(projectHit, "cached");
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
// 1b. entity match in project. icon and image are interchangeable for
|
|
353
|
+
// entity hits — both live in images/, and figma-imported brand marks are
|
|
354
|
+
// always recorded as type image while agents ask for logos as type icon.
|
|
355
|
+
if (!forced && entity) {
|
|
356
|
+
const entityHit = findByEntity(projectDir, entity);
|
|
357
|
+
if (entityHit && typesMatch(entityHit.type, type) && recordAvailable(projectDir, entityHit)) {
|
|
358
|
+
return result(entityHit, "cached");
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
// 1c. scan existing assets/ directory for unregistered matches
|
|
363
|
+
const existingAsset =
|
|
364
|
+
forced || type === "grade" || type === "lut"
|
|
365
|
+
? null
|
|
366
|
+
: findExistingAsset(projectDir, intent, type);
|
|
367
|
+
if (existingAsset) {
|
|
368
|
+
const recorded = latestRecordFor(projectDir, existingAsset.relativePath);
|
|
369
|
+
if (recorded) return result(recorded, "cached");
|
|
370
|
+
const id = nextId(projectDir, type);
|
|
371
|
+
const record = {
|
|
372
|
+
id,
|
|
373
|
+
type: existingAsset.type,
|
|
374
|
+
path: existingAsset.relativePath,
|
|
375
|
+
source: "existing",
|
|
376
|
+
description: existingAsset.name.replace(/[-_]/g, " "),
|
|
377
|
+
provenance: { provider: "local", adopted: true, prompt: intent },
|
|
378
|
+
};
|
|
379
|
+
appendRecord(projectDir, record);
|
|
380
|
+
regenerateIndex(projectDir);
|
|
381
|
+
return result(record, "existing");
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
// 2. global cache — exact-prompt or entity match
|
|
385
|
+
const cacheHit = forced ? null : cacheGet(intent, type);
|
|
386
|
+
if (cacheHit) {
|
|
387
|
+
const ext = extname(cacheHit.cached_path);
|
|
388
|
+
const imported = withReservedFileSync(projectDir, type, ext, ({ id, localPath }) =>
|
|
389
|
+
localizeImportedRecord(importFromCache(cacheHit, projectDir, id, localPath), localPath),
|
|
390
|
+
);
|
|
391
|
+
if (imported) {
|
|
392
|
+
appendRecord(projectDir, imported);
|
|
393
|
+
regenerateIndex(projectDir);
|
|
394
|
+
return result(imported, "reused");
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
if (!forced && entity) {
|
|
399
|
+
const entityCacheHit = cacheGetByEntity(entity);
|
|
400
|
+
if (entityCacheHit && typesMatch(entityCacheHit.type, type)) {
|
|
401
|
+
const ext = extname(entityCacheHit.cached_path);
|
|
402
|
+
const imported = withReservedFileSync(projectDir, type, ext, ({ id, localPath }) =>
|
|
403
|
+
localizeImportedRecord(
|
|
404
|
+
importFromCache(entityCacheHit, projectDir, id, localPath),
|
|
405
|
+
localPath,
|
|
406
|
+
),
|
|
407
|
+
);
|
|
408
|
+
if (imported) {
|
|
409
|
+
appendRecord(projectDir, imported);
|
|
410
|
+
regenerateIndex(projectDir);
|
|
411
|
+
return result(imported, "reused");
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
// --local-only skips every remote provider.
|
|
417
|
+
const localOnly = args["local-only"];
|
|
418
|
+
const ctx = {
|
|
419
|
+
entity,
|
|
420
|
+
projectDir,
|
|
421
|
+
localOnly,
|
|
422
|
+
provider: args.provider,
|
|
423
|
+
avatarId: args["avatar-id"],
|
|
424
|
+
voiceId: args["voice-id"],
|
|
425
|
+
};
|
|
426
|
+
|
|
427
|
+
// Suggest candidates before a new fetch.
|
|
428
|
+
try {
|
|
429
|
+
const { similar } = listCandidates({ projectDir, type, intent, cap: CANDIDATE_CAP });
|
|
430
|
+
if (similar > 0) {
|
|
431
|
+
console.error(
|
|
432
|
+
`media-use: ${similar} similar cached asset${similar === 1 ? "" : "s"} already ${similar === 1 ? "exists" : "exist"} — run \`resolve --candidates --type ${type} --intent "${intent}"\` to review and reuse instead of fetching.`,
|
|
433
|
+
);
|
|
434
|
+
}
|
|
435
|
+
} catch {
|
|
436
|
+
// hint is best-effort; never block a resolve
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
if (type === "grade" || type === "lut") {
|
|
440
|
+
return resolveColor(type, intent, { projectDir });
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
// SFX search is bundled, local-index, then HeyGen.
|
|
444
|
+
let searchResult = null;
|
|
445
|
+
let providerFailure = null;
|
|
446
|
+
let localIndexFailure = null;
|
|
447
|
+
try {
|
|
448
|
+
if (type === "sfx" && !args.provider) {
|
|
449
|
+
searchResult = await runCapability(type, "search", intent, {
|
|
450
|
+
...ctx,
|
|
451
|
+
provider: "bundled.sfx",
|
|
452
|
+
});
|
|
453
|
+
if (!searchResult && !localOnly) {
|
|
454
|
+
const registry =
|
|
455
|
+
process.env.HYPERFRAMES_REGISTRY ||
|
|
456
|
+
"https://raw.githubusercontent.com/heygen-com/hyperframes/main/registry";
|
|
457
|
+
try {
|
|
458
|
+
await fetchMediaVectors(registry);
|
|
459
|
+
const ranked = await rankMediaRowsWithVectors(
|
|
460
|
+
intent,
|
|
461
|
+
mediaVectorRows().filter((row) => row.kind === "sfx"),
|
|
462
|
+
);
|
|
463
|
+
const row = ranked.rows[0];
|
|
464
|
+
const candidates = row
|
|
465
|
+
? [resolve(row.file), join(import.meta.dirname, "..", "..", "..", row.file)]
|
|
466
|
+
: [];
|
|
467
|
+
const localPath = candidates.find((candidate) => existsSync(candidate));
|
|
468
|
+
if (row && localPath) {
|
|
469
|
+
searchResult = {
|
|
470
|
+
localPath,
|
|
471
|
+
ext: extname(localPath),
|
|
472
|
+
source: "local-index",
|
|
473
|
+
metadata: {
|
|
474
|
+
description: row.description,
|
|
475
|
+
duration: row.duration ?? null,
|
|
476
|
+
provider: "catalog.local",
|
|
477
|
+
provenance: { library_key: row.id, tier: ranked.tier },
|
|
478
|
+
},
|
|
479
|
+
};
|
|
480
|
+
}
|
|
481
|
+
} catch (error) {
|
|
482
|
+
localIndexFailure = error;
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
if (!searchResult) searchResult = await runCapability(type, "search", intent, ctx);
|
|
486
|
+
// Keep HeyGen remediation diagnostics while bundled remains authoritative.
|
|
487
|
+
else if (!localOnly)
|
|
488
|
+
await runCapability(type, "search", intent, {
|
|
489
|
+
...ctx,
|
|
490
|
+
provider: "heygen.audio.sounds",
|
|
491
|
+
});
|
|
492
|
+
} else {
|
|
493
|
+
searchResult = await runCapability(type, "search", intent, ctx);
|
|
494
|
+
}
|
|
495
|
+
} catch (error) {
|
|
496
|
+
providerFailure = error;
|
|
497
|
+
// search failed, try generate
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
if (localIndexFailure) {
|
|
501
|
+
throw new Error(`local SFX index unavailable: ${localIndexFailure.message}`, {
|
|
502
|
+
cause: localIndexFailure,
|
|
503
|
+
});
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
// 4. generate fallback — same ordered cascade for the generate capability
|
|
507
|
+
if (!searchResult) {
|
|
508
|
+
try {
|
|
509
|
+
searchResult = await runCapability(type, "generate", intent, ctx);
|
|
510
|
+
} catch (error) {
|
|
511
|
+
providerFailure ??= error;
|
|
512
|
+
// generate failed too
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
// Flush provider failure telemetry before the process can exit.
|
|
517
|
+
await flushHeygenFailureTracking();
|
|
518
|
+
|
|
519
|
+
if (!searchResult) {
|
|
520
|
+
await track("media_use_resolve_miss", {
|
|
521
|
+
type,
|
|
522
|
+
local_only: !!localOnly,
|
|
523
|
+
provider_override: !!args.provider,
|
|
524
|
+
});
|
|
525
|
+
recordMiss({
|
|
526
|
+
type,
|
|
527
|
+
intent,
|
|
528
|
+
provider_override: !!args.provider,
|
|
529
|
+
local_only: !!args["local-only"],
|
|
530
|
+
});
|
|
531
|
+
// brand stays local: no frame.md/design.md -> upsell the HyperFrames design
|
|
532
|
+
// flow rather than reporting a generic miss (B5).
|
|
533
|
+
const msg =
|
|
534
|
+
providerFailure instanceof BundledSfxAssetsError ||
|
|
535
|
+
providerFailure instanceof FfBinarySettingError
|
|
536
|
+
? providerFailure.message
|
|
537
|
+
: type === "brand"
|
|
538
|
+
? "no brand spec found — add a frame.md or design.md (colors/font/logo) to this project. Run the HyperFrames design flow to create one; brand tokens are read locally for deterministic rendering."
|
|
539
|
+
: args.provider
|
|
540
|
+
? `provider "${args.provider}" could not resolve ${type}: "${intent}"${localOnly ? " (--local-only skips network providers; drop it or the --provider override)" : ""}`
|
|
541
|
+
: `no provider could resolve ${type}: "${intent}"`;
|
|
542
|
+
if (args.json) {
|
|
543
|
+
console.log(
|
|
544
|
+
JSON.stringify({
|
|
545
|
+
ok: false,
|
|
546
|
+
...(providerFailure instanceof BundledSfxAssetsError
|
|
547
|
+
? { code: providerFailure.code, fix: providerFailure.fix }
|
|
548
|
+
: {}),
|
|
549
|
+
error: msg,
|
|
550
|
+
}),
|
|
551
|
+
);
|
|
552
|
+
} else {
|
|
553
|
+
console.error(`error: ${msg}`);
|
|
554
|
+
}
|
|
555
|
+
process.exit(1);
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
// 5. freeze and register atomically.
|
|
559
|
+
const ext = searchResult.ext || extFromUrl(searchResult.url || "") || defaultExt(type);
|
|
560
|
+
const { id, localPath, fullPath } = await withReservedFile(
|
|
561
|
+
projectDir,
|
|
562
|
+
type,
|
|
563
|
+
ext,
|
|
564
|
+
async (reservation) => {
|
|
565
|
+
if (searchResult.localPath) {
|
|
566
|
+
freezeLocalFile(searchResult.localPath, reservation.fullPath);
|
|
567
|
+
} else if (searchResult.url) {
|
|
568
|
+
await freezeUrl(searchResult.url, reservation.fullPath);
|
|
569
|
+
} else {
|
|
570
|
+
throw new Error("provider returned no url or localPath");
|
|
571
|
+
}
|
|
572
|
+
return reservation;
|
|
573
|
+
},
|
|
574
|
+
);
|
|
575
|
+
|
|
576
|
+
const record = {
|
|
577
|
+
id,
|
|
578
|
+
type,
|
|
579
|
+
path: localPath,
|
|
580
|
+
source: searchResult.source || "search",
|
|
581
|
+
description: searchResult.metadata?.description || intent,
|
|
582
|
+
...(searchResult.metadata?.duration != null && {
|
|
583
|
+
duration: Math.round(searchResult.metadata.duration * 10) / 10,
|
|
584
|
+
}),
|
|
585
|
+
...(searchResult.metadata?.width != null && { width: searchResult.metadata.width }),
|
|
586
|
+
...(searchResult.metadata?.height != null && { height: searchResult.metadata.height }),
|
|
587
|
+
...(searchResult.metadata?.transparent != null && {
|
|
588
|
+
transparent: searchResult.metadata.transparent,
|
|
589
|
+
}),
|
|
590
|
+
...(entity && { entity }),
|
|
591
|
+
provenance: {
|
|
592
|
+
provider: searchResult.metadata?.provider || "unknown",
|
|
593
|
+
prompt: intent,
|
|
594
|
+
// Keep auth method sparse for non-HeyGen providers.
|
|
595
|
+
...heygenAuthMethodFor(searchResult.metadata?.provider),
|
|
596
|
+
...searchResult.metadata?.provenance,
|
|
597
|
+
},
|
|
598
|
+
};
|
|
599
|
+
|
|
600
|
+
const heygenRemediation = consumeHeygenRemediation();
|
|
601
|
+
if (
|
|
602
|
+
searchResult.metadata?.provider === "bundled.sfx" &&
|
|
603
|
+
!localOnly &&
|
|
604
|
+
!args.provider &&
|
|
605
|
+
heygenRemediation
|
|
606
|
+
) {
|
|
607
|
+
record.advisory = heygenRemediation;
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
appendRecord(projectDir, record);
|
|
611
|
+
regenerateIndex(projectDir);
|
|
612
|
+
// Promote fetched assets into the global cache for reuse.
|
|
613
|
+
try {
|
|
614
|
+
cachePut(fullPath, record);
|
|
615
|
+
} catch {
|
|
616
|
+
// promotion is best-effort; a resolve still succeeds locally
|
|
617
|
+
}
|
|
618
|
+
return result(record, searchResult.source || "search");
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
function mergeSmartAdjust(block) {
|
|
622
|
+
if (!args.for) return block;
|
|
623
|
+
const mediaPath = resolve(args.for);
|
|
624
|
+
// Clear upfront error beats an ffmpeg "No such file" stack on a typo'd path.
|
|
625
|
+
if (!existsSync(mediaPath)) throw new Error(`--for file not found: ${mediaPath}`);
|
|
626
|
+
const analysis = analyzeMediaGrade(mediaPath, {
|
|
627
|
+
ffmpegPath: ffmpegBinary(),
|
|
628
|
+
ffprobePath: ffprobeBinary(),
|
|
629
|
+
});
|
|
630
|
+
console.error(formatMeasuredNote(mediaPath, analysis.measured));
|
|
631
|
+
return {
|
|
632
|
+
...block,
|
|
633
|
+
adjust: {
|
|
634
|
+
...(block.adjust || {}),
|
|
635
|
+
...analysis.adjust,
|
|
636
|
+
},
|
|
637
|
+
};
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
function freezeGeneratedLut(
|
|
641
|
+
params,
|
|
642
|
+
{
|
|
643
|
+
projectDir,
|
|
644
|
+
type,
|
|
645
|
+
description = "parametric color grade",
|
|
646
|
+
validationErrorPrefix = "generated LUT failed validation",
|
|
647
|
+
},
|
|
648
|
+
) {
|
|
649
|
+
return withReservedFileSync(projectDir, type, ".cube", ({ id, localPath, fullPath }) => {
|
|
650
|
+
const tmpPath = `${fullPath}.tmp`;
|
|
651
|
+
try {
|
|
652
|
+
// Write + validate at .tmp, then atomic rename, so a crash between write and
|
|
653
|
+
// validate can't leave an invalid .cube at the final path.
|
|
654
|
+
writeFileSync(tmpPath, buildCube(params));
|
|
655
|
+
const check = validateCubeFile(tmpPath);
|
|
656
|
+
if (!check.ok) throw new Error(check.error);
|
|
657
|
+
renameSync(tmpPath, fullPath);
|
|
658
|
+
} catch (err) {
|
|
659
|
+
rmSync(tmpPath, { force: true });
|
|
660
|
+
throw new Error(`${validationErrorPrefix}: ${err.message}`);
|
|
661
|
+
}
|
|
662
|
+
return {
|
|
663
|
+
id,
|
|
664
|
+
localPath,
|
|
665
|
+
fullPath,
|
|
666
|
+
lut: { src: localPath, intensity: 1 },
|
|
667
|
+
source: "generated",
|
|
668
|
+
description,
|
|
669
|
+
metadata: {
|
|
670
|
+
provider: "cube_lut.builder",
|
|
671
|
+
provenance: { params },
|
|
672
|
+
},
|
|
673
|
+
};
|
|
674
|
+
});
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
function exitError(message, status = 1) {
|
|
678
|
+
if (args.json) {
|
|
679
|
+
console.log(JSON.stringify({ ok: false, error: message }));
|
|
680
|
+
} else {
|
|
681
|
+
console.error(`error: ${message}`);
|
|
682
|
+
}
|
|
683
|
+
process.exit(status);
|
|
684
|
+
}
|
|
685
|
+
|
|
686
|
+
function parseExplicitParams() {
|
|
687
|
+
try {
|
|
688
|
+
return JSON.parse(args.params);
|
|
689
|
+
} catch (err) {
|
|
690
|
+
throw new Error(`invalid --params JSON: ${err.message}`);
|
|
691
|
+
}
|
|
692
|
+
}
|
|
693
|
+
|
|
694
|
+
async function runParams() {
|
|
695
|
+
if (type === "lut" && args.for) {
|
|
696
|
+
throw new Error("--for is only supported with --type grade");
|
|
697
|
+
}
|
|
698
|
+
const params = parseExplicitParams();
|
|
699
|
+
const description =
|
|
700
|
+
typeof intent === "string" && intent.trim()
|
|
701
|
+
? intent.trim()
|
|
702
|
+
: `custom parametric ${type === "lut" ? "lut" : "grade"}`;
|
|
703
|
+
const frozen = freezeGeneratedLut(params, {
|
|
704
|
+
projectDir,
|
|
705
|
+
type,
|
|
706
|
+
description,
|
|
707
|
+
validationErrorPrefix: "--params produced an invalid LUT",
|
|
708
|
+
});
|
|
709
|
+
const record = {
|
|
710
|
+
id: frozen.id,
|
|
711
|
+
type,
|
|
712
|
+
path: frozen.localPath,
|
|
713
|
+
source: frozen.source,
|
|
714
|
+
description: frozen.description,
|
|
715
|
+
...(type === "grade" && { grading: mergeSmartAdjust({ intensity: 1, lut: frozen.lut }) }),
|
|
716
|
+
provenance: {
|
|
717
|
+
provider: frozen.metadata.provider,
|
|
718
|
+
...frozen.metadata.provenance,
|
|
719
|
+
},
|
|
720
|
+
};
|
|
721
|
+
return finalizeColorRecord(record, frozen.source, frozen.fullPath);
|
|
722
|
+
}
|
|
723
|
+
|
|
724
|
+
async function finalizeColorRecord(record, source, fullPath = null) {
|
|
725
|
+
appendRecord(projectDir, record);
|
|
726
|
+
regenerateIndex(projectDir);
|
|
727
|
+
if (fullPath) {
|
|
728
|
+
try {
|
|
729
|
+
cachePut(fullPath, record);
|
|
730
|
+
} catch {
|
|
731
|
+
// promotion is best-effort
|
|
732
|
+
}
|
|
733
|
+
}
|
|
734
|
+
return result(record, source);
|
|
735
|
+
}
|
|
736
|
+
|
|
737
|
+
async function colorMiss(type, intent) {
|
|
738
|
+
await track("media_use_resolve_miss", {
|
|
739
|
+
type,
|
|
740
|
+
local_only: !!args["local-only"],
|
|
741
|
+
provider_override: !!args.provider,
|
|
742
|
+
});
|
|
743
|
+
recordMiss({
|
|
744
|
+
type,
|
|
745
|
+
intent,
|
|
746
|
+
provider_override: !!args.provider,
|
|
747
|
+
local_only: !!args["local-only"],
|
|
748
|
+
});
|
|
749
|
+
const msg = `no local color grade could resolve ${type}: "${intent}"`;
|
|
750
|
+
if (args.json) {
|
|
751
|
+
console.log(JSON.stringify({ ok: false, error: msg }));
|
|
752
|
+
} else {
|
|
753
|
+
console.error(`error: ${msg}`);
|
|
754
|
+
}
|
|
755
|
+
process.exit(1);
|
|
756
|
+
}
|
|
757
|
+
|
|
758
|
+
async function resolveGrade(intent, { projectDir }) {
|
|
759
|
+
const match = matchColorLook(intent);
|
|
760
|
+
if (match?.kind === "preset") {
|
|
761
|
+
const id = nextId(projectDir, "grade");
|
|
762
|
+
const grading = mergeSmartAdjust({ preset: match.preset, intensity: 1 });
|
|
763
|
+
const record = {
|
|
764
|
+
id,
|
|
765
|
+
type: "grade",
|
|
766
|
+
source: "preset",
|
|
767
|
+
description: intent,
|
|
768
|
+
grading,
|
|
769
|
+
provenance: {
|
|
770
|
+
provider: "color_grade.local",
|
|
771
|
+
prompt: intent,
|
|
772
|
+
preset: match.preset,
|
|
773
|
+
},
|
|
774
|
+
};
|
|
775
|
+
return finalizeColorRecord(record, "preset");
|
|
776
|
+
}
|
|
777
|
+
|
|
778
|
+
if (match?.kind === "library") {
|
|
779
|
+
let frozen;
|
|
780
|
+
try {
|
|
781
|
+
frozen = await freezeLibraryLut(match, {
|
|
782
|
+
projectDir,
|
|
783
|
+
type: "grade",
|
|
784
|
+
localOnly: args["local-only"],
|
|
785
|
+
});
|
|
786
|
+
} catch (err) {
|
|
787
|
+
if (isLibraryLutOfflineMiss(err)) return colorMiss("grade", intent);
|
|
788
|
+
throw err;
|
|
789
|
+
}
|
|
790
|
+
const grading = mergeSmartAdjust({ intensity: 1, lut: frozen.lut });
|
|
791
|
+
const record = {
|
|
792
|
+
id: frozen.id,
|
|
793
|
+
type: "grade",
|
|
794
|
+
path: frozen.localPath,
|
|
795
|
+
source: frozen.source,
|
|
796
|
+
description: frozen.description,
|
|
797
|
+
grading,
|
|
798
|
+
provenance: {
|
|
799
|
+
provider: frozen.metadata.provider,
|
|
800
|
+
prompt: intent,
|
|
801
|
+
...frozen.metadata.provenance,
|
|
802
|
+
},
|
|
803
|
+
};
|
|
804
|
+
return finalizeColorRecord(record, frozen.source, frozen.fullPath);
|
|
805
|
+
}
|
|
806
|
+
|
|
807
|
+
const params = paramsFromIntent(intent);
|
|
808
|
+
if (!params) {
|
|
809
|
+
// No creative look matched. With --for, the measured adjust block is a
|
|
810
|
+
// valid grade on its own (footage auto-correction); only a true miss
|
|
811
|
+
// (no look AND no analysis) aborts.
|
|
812
|
+
if (args.for) {
|
|
813
|
+
const grading = mergeSmartAdjust({ intensity: 1 });
|
|
814
|
+
const record = {
|
|
815
|
+
id: nextId(projectDir, "grade"),
|
|
816
|
+
type: "grade",
|
|
817
|
+
source: "measured",
|
|
818
|
+
description: intent,
|
|
819
|
+
grading,
|
|
820
|
+
provenance: { provider: "color_grade.local", prompt: intent, measured: true },
|
|
821
|
+
};
|
|
822
|
+
return finalizeColorRecord(record, "measured");
|
|
823
|
+
}
|
|
824
|
+
return colorMiss("grade", intent);
|
|
825
|
+
}
|
|
826
|
+
const frozen = freezeGeneratedLut(params, { projectDir, type: "grade" });
|
|
827
|
+
const grading = mergeSmartAdjust({ intensity: 1, lut: frozen.lut });
|
|
828
|
+
const record = {
|
|
829
|
+
id: frozen.id,
|
|
830
|
+
type: "grade",
|
|
831
|
+
path: frozen.localPath,
|
|
832
|
+
source: frozen.source,
|
|
833
|
+
description: intent,
|
|
834
|
+
grading,
|
|
835
|
+
provenance: {
|
|
836
|
+
provider: frozen.metadata.provider,
|
|
837
|
+
prompt: intent,
|
|
838
|
+
...frozen.metadata.provenance,
|
|
839
|
+
},
|
|
840
|
+
};
|
|
841
|
+
return finalizeColorRecord(record, frozen.source, frozen.fullPath);
|
|
842
|
+
}
|
|
843
|
+
|
|
844
|
+
async function resolveLut(intent, { projectDir }) {
|
|
845
|
+
if (args.for) {
|
|
846
|
+
throw new Error("--for is only supported with --type grade");
|
|
847
|
+
}
|
|
848
|
+
const match = matchColorLook(intent);
|
|
849
|
+
if (match?.kind === "library") {
|
|
850
|
+
let frozen;
|
|
851
|
+
try {
|
|
852
|
+
frozen = await freezeLibraryLut(match, {
|
|
853
|
+
projectDir,
|
|
854
|
+
type: "lut",
|
|
855
|
+
localOnly: args["local-only"],
|
|
856
|
+
});
|
|
857
|
+
} catch (err) {
|
|
858
|
+
if (isLibraryLutOfflineMiss(err)) return colorMiss("lut", intent);
|
|
859
|
+
throw err;
|
|
860
|
+
}
|
|
861
|
+
const record = {
|
|
862
|
+
id: frozen.id,
|
|
863
|
+
type: "lut",
|
|
864
|
+
path: frozen.localPath,
|
|
865
|
+
source: frozen.source,
|
|
866
|
+
description: frozen.description,
|
|
867
|
+
provenance: {
|
|
868
|
+
provider: frozen.metadata.provider,
|
|
869
|
+
prompt: intent,
|
|
870
|
+
...frozen.metadata.provenance,
|
|
871
|
+
},
|
|
872
|
+
};
|
|
873
|
+
return finalizeColorRecord(record, frozen.source, frozen.fullPath);
|
|
874
|
+
}
|
|
875
|
+
|
|
876
|
+
const params = paramsFromIntent(intent);
|
|
877
|
+
if (!params) return colorMiss("lut", intent);
|
|
878
|
+
const frozen = freezeGeneratedLut(params, { projectDir, type: "lut" });
|
|
879
|
+
const record = {
|
|
880
|
+
id: frozen.id,
|
|
881
|
+
type: "lut",
|
|
882
|
+
path: frozen.localPath,
|
|
883
|
+
source: frozen.source,
|
|
884
|
+
description: intent,
|
|
885
|
+
provenance: {
|
|
886
|
+
provider: frozen.metadata.provider,
|
|
887
|
+
prompt: intent,
|
|
888
|
+
...frozen.metadata.provenance,
|
|
889
|
+
},
|
|
890
|
+
};
|
|
891
|
+
return finalizeColorRecord(record, frozen.source, frozen.fullPath);
|
|
892
|
+
}
|
|
893
|
+
|
|
894
|
+
async function resolveColor(type, intent, options) {
|
|
895
|
+
if (type === "grade") return resolveGrade(intent, options);
|
|
896
|
+
return resolveLut(intent, options);
|
|
897
|
+
}
|
|
898
|
+
|
|
899
|
+
async function ingest(src) {
|
|
900
|
+
if (!type || !INGEST_TYPES.includes(type)) {
|
|
901
|
+
console.error(`error: --from requires --type (one of: ${INGEST_TYPES.join(", ")})`);
|
|
902
|
+
process.exit(2);
|
|
903
|
+
}
|
|
904
|
+
const isUrl = /^https?:\/\//i.test(src);
|
|
905
|
+
if (isUrl && !isDirectMediaUrl(src)) {
|
|
906
|
+
console.error(
|
|
907
|
+
`error: --from takes a direct public media URL or a local file; "${src}" is not a direct media link (no platform pages / yt-dlp)`,
|
|
908
|
+
);
|
|
909
|
+
process.exit(2);
|
|
910
|
+
}
|
|
911
|
+
if (!isUrl && !existsSync(resolve(src))) {
|
|
912
|
+
console.error(`error: file not found: ${src}`);
|
|
913
|
+
process.exit(2);
|
|
914
|
+
}
|
|
915
|
+
// Refuse 0-byte input: an empty asset would register clean but fail at render
|
|
916
|
+
// (freezeUrl already rejects empty responses; this covers local files).
|
|
917
|
+
if (!isUrl && statSync(resolve(src)).size === 0) {
|
|
918
|
+
console.error(`error: refusing to ingest a 0-byte file: ${src}`);
|
|
919
|
+
process.exit(2);
|
|
920
|
+
}
|
|
921
|
+
if (args.source && !AGENT_SOURCES.includes(args.source)) {
|
|
922
|
+
console.error(`error: --source takes one of: ${AGENT_SOURCES.join(", ")}`);
|
|
923
|
+
process.exit(2);
|
|
924
|
+
}
|
|
925
|
+
if (args.source && (type === "lut" || type === "grade")) {
|
|
926
|
+
console.error("error: --source records media files; a LUT or grade is ingested without it");
|
|
927
|
+
process.exit(2);
|
|
928
|
+
}
|
|
929
|
+
const real = (path) => (existsSync(path) ? realpathSync(path) : path);
|
|
930
|
+
const inProject = args.source && !isUrl ? relative(real(projectDir), real(resolve(src))) : null;
|
|
931
|
+
if (
|
|
932
|
+
inProject &&
|
|
933
|
+
inProject !== ".." &&
|
|
934
|
+
!inProject.startsWith(`..${sep}`) &&
|
|
935
|
+
!isAbsolute(inProject)
|
|
936
|
+
) {
|
|
937
|
+
return recordProjectFile(inProject.split(sep).join("/"));
|
|
938
|
+
}
|
|
939
|
+
const ext = extname(isUrl ? new URL(src).pathname : src) || defaultExt(type);
|
|
940
|
+
const { id, localPath, fullPath } = await withReservedFile(
|
|
941
|
+
projectDir,
|
|
942
|
+
type,
|
|
943
|
+
ext,
|
|
944
|
+
async (reservation) => {
|
|
945
|
+
if (isUrl) await freezeUrl(src, reservation.fullPath);
|
|
946
|
+
else freezeLocalFile(resolve(src), reservation.fullPath);
|
|
947
|
+
return reservation;
|
|
948
|
+
},
|
|
949
|
+
);
|
|
950
|
+
if (type === "lut" || type === "grade") {
|
|
951
|
+
try {
|
|
952
|
+
const check = validateCubeFile(fullPath);
|
|
953
|
+
if (!check.ok) throw new Error(check.error);
|
|
954
|
+
} catch (err) {
|
|
955
|
+
rmSync(fullPath, { force: true });
|
|
956
|
+
exitError(`ingested LUT is invalid: ${err.message}`, 1);
|
|
957
|
+
}
|
|
958
|
+
}
|
|
959
|
+
const record = {
|
|
960
|
+
id,
|
|
961
|
+
type,
|
|
962
|
+
path: localPath,
|
|
963
|
+
source: args.source || "ingested",
|
|
964
|
+
description: basename(src.split("?")[0]),
|
|
965
|
+
provenance: { provider: "local", from: src },
|
|
966
|
+
};
|
|
967
|
+
appendRecord(projectDir, record);
|
|
968
|
+
regenerateIndex(projectDir);
|
|
969
|
+
try {
|
|
970
|
+
cachePut(fullPath, record); // surface ingested assets globally too (B3)
|
|
971
|
+
} catch {
|
|
972
|
+
// best-effort
|
|
973
|
+
}
|
|
974
|
+
await result(record, "ingested");
|
|
975
|
+
}
|
|
976
|
+
|
|
977
|
+
async function recordProjectFile(path) {
|
|
978
|
+
let duration;
|
|
979
|
+
try {
|
|
980
|
+
duration = probeMedia(join(projectDir, path)).duration;
|
|
981
|
+
} catch (err) {
|
|
982
|
+
exitError(err.message);
|
|
983
|
+
}
|
|
984
|
+
const record = recordInPlace(projectDir, {
|
|
985
|
+
type,
|
|
986
|
+
path,
|
|
987
|
+
source: args.source,
|
|
988
|
+
description: intent,
|
|
989
|
+
duration,
|
|
990
|
+
provenance: {
|
|
991
|
+
provider: args.provider || "local",
|
|
992
|
+
from: path,
|
|
993
|
+
...(intent && { prompt: intent }),
|
|
994
|
+
},
|
|
995
|
+
});
|
|
996
|
+
regenerateIndex(projectDir);
|
|
997
|
+
// "recorded", not the record's source, so usage counts keep meaning fetches.
|
|
998
|
+
await result(record, "recorded");
|
|
999
|
+
}
|
|
1000
|
+
|
|
1001
|
+
async function showCandidates() {
|
|
1002
|
+
const projectDir = resolve(args.project);
|
|
1003
|
+
const type = args.type;
|
|
1004
|
+
if (!type || !listTypes().includes(type)) {
|
|
1005
|
+
console.error(`error: --candidates requires --type (one of: ${listTypes().join(", ")})`);
|
|
1006
|
+
process.exit(2);
|
|
1007
|
+
}
|
|
1008
|
+
const intent = args.intent || "";
|
|
1009
|
+
const { candidates, truncated, total, similar } = listCandidates({
|
|
1010
|
+
projectDir,
|
|
1011
|
+
type,
|
|
1012
|
+
intent,
|
|
1013
|
+
cap: CANDIDATE_CAP,
|
|
1014
|
+
});
|
|
1015
|
+
await track("media_use_candidates", {
|
|
1016
|
+
type,
|
|
1017
|
+
project_n: total.project,
|
|
1018
|
+
global_n: total.global,
|
|
1019
|
+
local_only: !!args["local-only"],
|
|
1020
|
+
});
|
|
1021
|
+
if (args.json) {
|
|
1022
|
+
console.log(JSON.stringify({ ok: true, candidates, truncated, total, similar }));
|
|
1023
|
+
} else {
|
|
1024
|
+
console.log(formatCandidates(candidates, { truncated, total }));
|
|
1025
|
+
}
|
|
1026
|
+
}
|
|
1027
|
+
|
|
1028
|
+
// Best-effort latest stable CLI tag from the CDN (the install script's source of
|
|
1029
|
+
// truth). null on any failure (offline, no curl) — treated as "unknown", never fatal.
|
|
1030
|
+
function latestHeygenStable() {
|
|
1031
|
+
const probe = runCommand("curl", [
|
|
1032
|
+
"-fsSL",
|
|
1033
|
+
"--max-time",
|
|
1034
|
+
"4",
|
|
1035
|
+
"https://static.heygen.ai/cli/stable",
|
|
1036
|
+
]);
|
|
1037
|
+
return probe.status === 0 ? firstSemver(commandText(probe)) : null;
|
|
1038
|
+
}
|
|
1039
|
+
|
|
1040
|
+
function heygenAuthCheck() {
|
|
1041
|
+
// heygen auth status emits JSON by default; parse that output directly.
|
|
1042
|
+
const authProbe = runCommand("heygen", ["auth", "status"]);
|
|
1043
|
+
// spawnSync sets .error/.signal on a timeout or spawn failure (status then
|
|
1044
|
+
// null). A stalled auth endpoint (transient network/DNS) must not be reported
|
|
1045
|
+
// as an authoritative "not authenticated" with a re-login fix.
|
|
1046
|
+
const timedOut = authProbe.error?.code === "ETIMEDOUT" || authProbe.signal != null;
|
|
1047
|
+
const email = authProbe.status === 0 ? emailFromAuthStatus(commandText(authProbe)) : null;
|
|
1048
|
+
return {
|
|
1049
|
+
name: "heygen authenticated",
|
|
1050
|
+
ok: !!email,
|
|
1051
|
+
detail: email
|
|
1052
|
+
? `heygen authenticated as ${email}`
|
|
1053
|
+
: timedOut
|
|
1054
|
+
? "heygen auth status timed out — possible network issue, not proof of sign-out"
|
|
1055
|
+
: "heygen not authenticated",
|
|
1056
|
+
fix: email ? "" : timedOut ? "check network, then re-run --doctor" : HEYGEN_AUTH_COMMAND,
|
|
1057
|
+
};
|
|
1058
|
+
}
|
|
1059
|
+
|
|
1060
|
+
function runDoctor() {
|
|
1061
|
+
const checks = [];
|
|
1062
|
+
const bundledSfx = inspectBundledSfxAssets();
|
|
1063
|
+
checks.push({
|
|
1064
|
+
name: "bundled SFX assets",
|
|
1065
|
+
ok: bundledSfx.ok,
|
|
1066
|
+
detail: bundledSfx.detail,
|
|
1067
|
+
fix: bundledSfx.fix,
|
|
1068
|
+
});
|
|
1069
|
+
const heygenVersionProbe = runCommand("heygen", ["--version"]);
|
|
1070
|
+
const heygenOnPath = heygenVersionProbe.status === 0;
|
|
1071
|
+
const heygenVersionText = commandText(heygenVersionProbe);
|
|
1072
|
+
const heygenVersion = firstSemver(heygenVersionText);
|
|
1073
|
+
|
|
1074
|
+
checks.push({
|
|
1075
|
+
name: "heygen on PATH",
|
|
1076
|
+
ok: heygenOnPath,
|
|
1077
|
+
// Just "is the binary here" — the version row below owns the version string,
|
|
1078
|
+
// so this row must not also render `heygen v0.3.0` (two byte-identical lines).
|
|
1079
|
+
detail: heygenOnPath ? "heygen found on PATH" : "heygen not found",
|
|
1080
|
+
fix: heygenOnPath ? "" : HEYGEN_INSTALL_COMMAND,
|
|
1081
|
+
});
|
|
1082
|
+
|
|
1083
|
+
if (!heygenOnPath) {
|
|
1084
|
+
checks.push({
|
|
1085
|
+
name: "heygen version",
|
|
1086
|
+
ok: false,
|
|
1087
|
+
detail: "heygen version unavailable",
|
|
1088
|
+
fix: HEYGEN_INSTALL_COMMAND,
|
|
1089
|
+
});
|
|
1090
|
+
checks.push({
|
|
1091
|
+
name: "heygen authenticated",
|
|
1092
|
+
ok: false,
|
|
1093
|
+
detail: "heygen auth status unavailable",
|
|
1094
|
+
fix: HEYGEN_INSTALL_COMMAND,
|
|
1095
|
+
});
|
|
1096
|
+
} else if (heygenVersion) {
|
|
1097
|
+
const versionOk = !versionLessThan(heygenVersion, HEYGEN_MIN_VERSION);
|
|
1098
|
+
// Keep it latest: even when the installed version clears the floor, nudge
|
|
1099
|
+
// `heygen update` if a newer stable exists. Best-effort — silently skipped
|
|
1100
|
+
// when the CDN is unreachable, so it never blocks the check.
|
|
1101
|
+
const latest = versionOk ? latestHeygenStable() : null;
|
|
1102
|
+
const behind = latest && versionLessThan(heygenVersion, latest);
|
|
1103
|
+
checks.push({
|
|
1104
|
+
name: "heygen version",
|
|
1105
|
+
ok: versionOk,
|
|
1106
|
+
detail: versionOk
|
|
1107
|
+
? `heygen v${heygenVersion}${behind ? ` (latest v${latest} available)` : ""}`
|
|
1108
|
+
: `heygen v${heygenVersion} (need >= v${HEYGEN_MIN_VERSION})`,
|
|
1109
|
+
fix: versionOk ? (behind ? HEYGEN_UPDATE_COMMAND : "") : HEYGEN_UPDATE_COMMAND,
|
|
1110
|
+
});
|
|
1111
|
+
|
|
1112
|
+
// Older CLI versions cannot provide the auth status used here.
|
|
1113
|
+
checks.push(
|
|
1114
|
+
versionOk
|
|
1115
|
+
? heygenAuthCheck()
|
|
1116
|
+
: {
|
|
1117
|
+
name: "heygen authenticated",
|
|
1118
|
+
ok: false,
|
|
1119
|
+
detail: "skipped — update heygen first",
|
|
1120
|
+
fix: HEYGEN_UPDATE_COMMAND,
|
|
1121
|
+
},
|
|
1122
|
+
);
|
|
1123
|
+
} else {
|
|
1124
|
+
// Fail-open: heygen ran but printed no semver (dev/stripped build). We can't
|
|
1125
|
+
// verify the version, so we don't block on it — but say so rather than a bare
|
|
1126
|
+
// green check that implies a real version comparison happened.
|
|
1127
|
+
checks.push({
|
|
1128
|
+
name: "heygen version",
|
|
1129
|
+
ok: true,
|
|
1130
|
+
detail: "heygen present; version unverifiable (no semver in --version output)",
|
|
1131
|
+
fix: "",
|
|
1132
|
+
});
|
|
1133
|
+
|
|
1134
|
+
checks.push(heygenAuthCheck());
|
|
1135
|
+
}
|
|
1136
|
+
|
|
1137
|
+
checks.push(ffDoctorCheck("ffmpeg", ffmpegBinary), ffDoctorCheck("ffprobe", ffprobeBinary));
|
|
1138
|
+
|
|
1139
|
+
const nodeOk = !versionLessThan(process.versions.node, MIN_NODE_VERSION);
|
|
1140
|
+
checks.push({
|
|
1141
|
+
name: "node version",
|
|
1142
|
+
ok: nodeOk,
|
|
1143
|
+
detail: `${process.version} (need >= v${MIN_NODE_VERSION})`,
|
|
1144
|
+
fix: nodeOk ? "" : `upgrade Node to >= v${MIN_NODE_VERSION}`,
|
|
1145
|
+
});
|
|
1146
|
+
|
|
1147
|
+
// ffmpeg AND ffprobe are both strictly required (see references/setup-providers.md); the exit code
|
|
1148
|
+
// must reflect that so a script gating on `--doctor` doesn't pass with ffprobe
|
|
1149
|
+
// missing and then break at the first probe call.
|
|
1150
|
+
const ffmpeg = checks.find((check) => check.name === "ffmpeg on PATH");
|
|
1151
|
+
const ffprobe = checks.find((check) => check.name === "ffprobe on PATH");
|
|
1152
|
+
return { ok: bundledSfx.ok && !!ffmpeg?.ok && !!ffprobe?.ok, checks };
|
|
1153
|
+
}
|
|
1154
|
+
|
|
1155
|
+
function printDoctor(checks) {
|
|
1156
|
+
const heygenChecks = new Set(["heygen on PATH", "heygen version", "heygen authenticated"]);
|
|
1157
|
+
for (const check of checks) {
|
|
1158
|
+
const prefix = check.ok ? "✓" : "✗";
|
|
1159
|
+
const freePath = heygenChecks.has(check.name)
|
|
1160
|
+
? " — free-usage path: bgm/image/voice/avatar-video"
|
|
1161
|
+
: "";
|
|
1162
|
+
const fix = check.ok || !check.fix ? "" : ` — fix: ${check.fix}`;
|
|
1163
|
+
console.log(`${prefix} ${check.detail}${freePath}${fix}`);
|
|
1164
|
+
}
|
|
1165
|
+
}
|
|
1166
|
+
|
|
1167
|
+
function printStats(report) {
|
|
1168
|
+
console.log("media-use stats");
|
|
1169
|
+
console.log(`total resolves: ${report.total_resolves}`);
|
|
1170
|
+
console.log(`misses: ${report.misses}`);
|
|
1171
|
+
console.log(
|
|
1172
|
+
`hit rate: ${report.hit_rate == null ? "n/a" : `${Math.round(report.hit_rate * 100)}%`}`,
|
|
1173
|
+
);
|
|
1174
|
+
printMap("by type", report.by_type);
|
|
1175
|
+
printMap("by source", report.by_source);
|
|
1176
|
+
printMap("by provider", report.by_provider);
|
|
1177
|
+
printMap("by via", report.by_via);
|
|
1178
|
+
console.log(`global cache assets: ${report.global_cache_assets}`);
|
|
1179
|
+
console.log(`global cache disk: ${report.global_cache_disk_bytes} bytes`);
|
|
1180
|
+
console.log(`cross-project reuse: ${report.cross_project_reuse}`);
|
|
1181
|
+
console.log("top missed intents:");
|
|
1182
|
+
const entries = Object.entries(report.top_missed_intents);
|
|
1183
|
+
if (entries.length === 0) {
|
|
1184
|
+
console.log(" none");
|
|
1185
|
+
return;
|
|
1186
|
+
}
|
|
1187
|
+
for (const [type, misses] of entries) {
|
|
1188
|
+
console.log(` ${type}:`);
|
|
1189
|
+
for (const miss of misses) console.log(` ${miss.count} ${miss.intent}`);
|
|
1190
|
+
}
|
|
1191
|
+
}
|
|
1192
|
+
|
|
1193
|
+
function printMap(label, values) {
|
|
1194
|
+
const entries = Object.entries(values);
|
|
1195
|
+
console.log(`${label}:`);
|
|
1196
|
+
if (entries.length === 0) {
|
|
1197
|
+
console.log(" none");
|
|
1198
|
+
return;
|
|
1199
|
+
}
|
|
1200
|
+
for (const [key, value] of entries) console.log(` ${key}: ${value}`);
|
|
1201
|
+
}
|
|
1202
|
+
|
|
1203
|
+
function ffDoctorCheck(name, binary) {
|
|
1204
|
+
let bin;
|
|
1205
|
+
try {
|
|
1206
|
+
bin = binary();
|
|
1207
|
+
} catch (err) {
|
|
1208
|
+
return {
|
|
1209
|
+
name: `${name} on PATH`,
|
|
1210
|
+
ok: false,
|
|
1211
|
+
detail: err.message,
|
|
1212
|
+
fix: "fix or unset that variable",
|
|
1213
|
+
};
|
|
1214
|
+
}
|
|
1215
|
+
const probe = runCommand(bin, ["-version"]);
|
|
1216
|
+
const ok = probe.status === 0;
|
|
1217
|
+
return {
|
|
1218
|
+
name: `${name} on PATH`,
|
|
1219
|
+
ok,
|
|
1220
|
+
detail: ok ? firstLine(probe.stdout) : `${name} not found`,
|
|
1221
|
+
fix: ok ? "" : "brew install ffmpeg",
|
|
1222
|
+
};
|
|
1223
|
+
}
|
|
1224
|
+
|
|
1225
|
+
function runCommand(bin, argv) {
|
|
1226
|
+
return spawnSync(bin, argv, {
|
|
1227
|
+
encoding: "utf8",
|
|
1228
|
+
timeout: 15000,
|
|
1229
|
+
});
|
|
1230
|
+
}
|
|
1231
|
+
|
|
1232
|
+
function commandText(result) {
|
|
1233
|
+
return [result.stdout, result.stderr].filter(Boolean).join("\n").trim();
|
|
1234
|
+
}
|
|
1235
|
+
|
|
1236
|
+
function firstLine(text) {
|
|
1237
|
+
return (
|
|
1238
|
+
String(text || "")
|
|
1239
|
+
.trim()
|
|
1240
|
+
.split(/\r?\n/)[0] || ""
|
|
1241
|
+
);
|
|
1242
|
+
}
|
|
1243
|
+
|
|
1244
|
+
function emailFromAuthStatus(text) {
|
|
1245
|
+
// JSON only (auth status emits JSON by default). No prose regex fallback: a
|
|
1246
|
+
// human-format body like "Session expired. Contact support@heygen.ai" would
|
|
1247
|
+
// otherwise report the user as authenticated as support@heygen.ai.
|
|
1248
|
+
const trimmed = String(text || "").trim();
|
|
1249
|
+
if (!trimmed.startsWith("{")) return null;
|
|
1250
|
+
try {
|
|
1251
|
+
const parsed = JSON.parse(trimmed);
|
|
1252
|
+
return parsed?.data?.email || parsed?.email || null;
|
|
1253
|
+
} catch {
|
|
1254
|
+
return null;
|
|
1255
|
+
}
|
|
1256
|
+
}
|
|
1257
|
+
|
|
1258
|
+
async function reuseGlobal(shaArg) {
|
|
1259
|
+
const projectDir = resolve(args.project);
|
|
1260
|
+
const type = args.type;
|
|
1261
|
+
if (!type || !listTypes().includes(type)) {
|
|
1262
|
+
console.error(`error: --reuse requires --type (one of: ${listTypes().join(", ")})`);
|
|
1263
|
+
process.exit(2);
|
|
1264
|
+
}
|
|
1265
|
+
if (!shaArg || !shaArg.trim()) {
|
|
1266
|
+
console.error("error: --reuse needs a content sha/prefix (from `resolve --candidates`)");
|
|
1267
|
+
process.exit(2);
|
|
1268
|
+
}
|
|
1269
|
+
const rec = findGlobalBySha(shaArg);
|
|
1270
|
+
if (rec && rec.ambiguous) {
|
|
1271
|
+
console.error(
|
|
1272
|
+
`error: sha prefix "${shaArg}" is ambiguous (${rec.count} matches) — use more characters`,
|
|
1273
|
+
);
|
|
1274
|
+
process.exit(2);
|
|
1275
|
+
}
|
|
1276
|
+
if (!rec) {
|
|
1277
|
+
console.error(`error: no reusable global asset matches sha "${shaArg}"`);
|
|
1278
|
+
process.exit(1);
|
|
1279
|
+
}
|
|
1280
|
+
// Do not import an asset under the wrong type.
|
|
1281
|
+
if (!typesMatch(rec.type, type)) {
|
|
1282
|
+
console.error(`error: sha "${shaArg}" is a ${rec.type} asset, not ${type}`);
|
|
1283
|
+
process.exit(2);
|
|
1284
|
+
}
|
|
1285
|
+
const ext = extname(rec.cached_path || "") || defaultExt(type);
|
|
1286
|
+
const imported = withReservedFileSync(projectDir, type, ext, ({ id, localPath }) =>
|
|
1287
|
+
localizeImportedRecord(importFromCache(rec, projectDir, id, localPath), localPath),
|
|
1288
|
+
);
|
|
1289
|
+
if (!imported) {
|
|
1290
|
+
console.error(`error: cache entry for "${shaArg}" is incomplete or missing on disk`);
|
|
1291
|
+
process.exit(1);
|
|
1292
|
+
}
|
|
1293
|
+
// Distinguish an explicit agent reuse from an automatic normalize-exact hit.
|
|
1294
|
+
imported.source = "reused-explicit";
|
|
1295
|
+
imported.provenance = { ...imported.provenance, reused_by: "agent" };
|
|
1296
|
+
appendRecord(projectDir, imported);
|
|
1297
|
+
regenerateIndex(projectDir);
|
|
1298
|
+
await result(imported, "reused-explicit");
|
|
1299
|
+
}
|
|
1300
|
+
|
|
1301
|
+
async function result(record, source) {
|
|
1302
|
+
// Non-PII usage event: which media type, how it resolved, which provider won.
|
|
1303
|
+
// Never the intent text or paths. Awaited so a short-lived run flushes it.
|
|
1304
|
+
await track("media_use_resolve", {
|
|
1305
|
+
type: record.type,
|
|
1306
|
+
source,
|
|
1307
|
+
provider: record.provenance?.provider,
|
|
1308
|
+
// How a library LUT resolved: "url" (CDN), "params-fallback" (CDN failed →
|
|
1309
|
+
// parametric), or "params" (offline). Surfaces silent CDN→params downgrades
|
|
1310
|
+
// in prod, which --doctor can't (it only answers "reachable now?").
|
|
1311
|
+
via: record.provenance?.via,
|
|
1312
|
+
// OAuth vs. API-key HeyGen paths are sparse for non-HeyGen providers.
|
|
1313
|
+
// signal about the fetch that actually consumed a heygen credit, not
|
|
1314
|
+
// about the (free, no-credential) act of copying a cached file.
|
|
1315
|
+
auth_method: record.provenance?.authMethod,
|
|
1316
|
+
// Provider tiers stay sparse and follow the registry's A/N/P declaration.
|
|
1317
|
+
provider_tier: providerTierFor(record.provenance?.provider),
|
|
1318
|
+
local_only: !!args["local-only"],
|
|
1319
|
+
provider_override: !!args.provider,
|
|
1320
|
+
});
|
|
1321
|
+
if (args.json) {
|
|
1322
|
+
const grading = record.type === "grade" && record.grading ? record.grading : null;
|
|
1323
|
+
console.log(
|
|
1324
|
+
JSON.stringify({
|
|
1325
|
+
ok: true,
|
|
1326
|
+
...record,
|
|
1327
|
+
...(grading || {}),
|
|
1328
|
+
...(grading && { grading }),
|
|
1329
|
+
_source: source,
|
|
1330
|
+
}),
|
|
1331
|
+
);
|
|
1332
|
+
} else {
|
|
1333
|
+
const meta = formatMeta(record, source);
|
|
1334
|
+
console.log(`resolved ${record.id} → ${record.path || "inline"} (${meta})`);
|
|
1335
|
+
}
|
|
1336
|
+
}
|
|
1337
|
+
|
|
1338
|
+
function formatMeta(record, source) {
|
|
1339
|
+
const parts = [record.type];
|
|
1340
|
+
if (record.grading?.preset) parts.push(`preset ${record.grading.preset}`);
|
|
1341
|
+
if (record.grading?.lut) parts.push("lut");
|
|
1342
|
+
if (record.duration != null) parts.push(`${record.duration}s`);
|
|
1343
|
+
if (record.width && record.height) parts.push(`${record.width}×${record.height}`);
|
|
1344
|
+
if (record.transparent) parts.push("transparent");
|
|
1345
|
+
if (source === "reused" || source === "reused-explicit") parts.push("reused");
|
|
1346
|
+
if (source === "generated") parts.push("generated");
|
|
1347
|
+
return parts.join(", ");
|
|
1348
|
+
}
|
|
1349
|
+
|
|
1350
|
+
function extFromUrl(url) {
|
|
1351
|
+
try {
|
|
1352
|
+
return extname(new URL(url).pathname) || null;
|
|
1353
|
+
} catch {
|
|
1354
|
+
return null;
|
|
1355
|
+
}
|
|
1356
|
+
}
|
|
1357
|
+
|
|
1358
|
+
function defaultExt(type) {
|
|
1359
|
+
return DEFAULT_EXT[type] || ".bin";
|
|
1360
|
+
}
|
|
1361
|
+
|
|
1362
|
+
run().catch((err) => {
|
|
1363
|
+
if (args.json) {
|
|
1364
|
+
console.log(JSON.stringify({ ok: false, error: err.message }));
|
|
1365
|
+
} else {
|
|
1366
|
+
console.error(`error: ${err.message}`);
|
|
1367
|
+
}
|
|
1368
|
+
process.exit(1);
|
|
1369
|
+
});
|