@officexapp/vidfarm-devcli 0.21.10
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/.agents/skills/dollarplatoon-skill/SKILL.md +1227 -0
- package/.agents/skills/editor-capabilities/SKILL.md +182 -0
- package/.agents/skills/editor-capabilities/references/re-theme-walkthrough.md +58 -0
- package/.agents/skills/embedded-captions/CATALOG.md +93 -0
- package/.agents/skills/embedded-captions/SKILL.md +286 -0
- package/.agents/skills/embedded-captions/assets/brand/CDPR-fankit-terms.txt +35 -0
- package/.agents/skills/embedded-captions/assets/brand/cyberpunk-widths.json +115 -0
- package/.agents/skills/embedded-captions/assets/fonts/char-widths.json +2211 -0
- package/.agents/skills/embedded-captions/assets/strokefonts/HersheyScript1.svg +242 -0
- package/.agents/skills/embedded-captions/assets/strokefonts/HersheyScriptMed.svg +242 -0
- package/.agents/skills/embedded-captions/dna/README.md +148 -0
- package/.agents/skills/embedded-captions/dna/chrome.json +68 -0
- package/.agents/skills/embedded-captions/dna/cream.json +69 -0
- package/.agents/skills/embedded-captions/dna/documentary.json +62 -0
- package/.agents/skills/embedded-captions/dna/editorial.json +70 -0
- package/.agents/skills/embedded-captions/dna/glitch.json +82 -0
- package/.agents/skills/embedded-captions/dna/ink.json +65 -0
- package/.agents/skills/embedded-captions/dna/keynote.json +62 -0
- package/.agents/skills/embedded-captions/dna/loud.json +75 -0
- package/.agents/skills/embedded-captions/dna/neon.json +58 -0
- package/.agents/skills/embedded-captions/dna/velocity.json +89 -0
- package/.agents/skills/embedded-captions/modes/cinematic/README.md +48 -0
- package/.agents/skills/embedded-captions/modes/cinematic/_archive/champion/spec.md +98 -0
- package/.agents/skills/embedded-captions/modes/cinematic/_archive/champion/template.html +188 -0
- package/.agents/skills/embedded-captions/modes/cinematic/_archive/memory-wall/spec.md +134 -0
- package/.agents/skills/embedded-captions/modes/cinematic/_archive/memory-wall/template.html +179 -0
- package/.agents/skills/embedded-captions/modes/cinematic/_archive/portrait-header/spec.md +81 -0
- package/.agents/skills/embedded-captions/modes/cinematic/_archive/portrait-header/template.html +170 -0
- package/.agents/skills/embedded-captions/modes/cinematic/cinematic-cream/spec.md +16 -0
- package/.agents/skills/embedded-captions/modes/cinematic/cinematic-cream/template.html +226 -0
- package/.agents/skills/embedded-captions/modes/cinematic/engine.html +355 -0
- package/.agents/skills/embedded-captions/modes/standard/_anatomy.md +233 -0
- package/.agents/skills/embedded-captions/modes/standard/_motion.md +192 -0
- package/.agents/skills/embedded-captions/modes/standard/fonts/build-fonts-css.cjs +97 -0
- package/.agents/skills/embedded-captions/references/aesthetic-principles.md +168 -0
- package/.agents/skills/embedded-captions/references/anti-patterns.md +188 -0
- package/.agents/skills/embedded-captions/references/bespoke-vs-presets.md +178 -0
- package/.agents/skills/embedded-captions/references/caption-grouping.md +130 -0
- package/.agents/skills/embedded-captions/references/composition-craft.md +522 -0
- package/.agents/skills/embedded-captions/references/direction-catalog.md +138 -0
- package/.agents/skills/embedded-captions/references/example-renders/champion.html +371 -0
- package/.agents/skills/embedded-captions/references/example-renders/memory-wall.html +334 -0
- package/.agents/skills/embedded-captions/references/failure-modes.md +145 -0
- package/.agents/skills/embedded-captions/references/layout-heuristics.md +238 -0
- package/.agents/skills/embedded-captions/references/motion-vocabulary.md +148 -0
- package/.agents/skills/embedded-captions/references/rail.md +68 -0
- package/.agents/skills/embedded-captions/references/reference-bar.md +47 -0
- package/.agents/skills/embedded-captions/references/scene-types.md +94 -0
- package/.agents/skills/embedded-captions/references/test-set.md +66 -0
- package/.agents/skills/embedded-captions/references/typographic-moves.md +266 -0
- package/.agents/skills/embedded-captions/references/typography-presets.md +63 -0
- package/.agents/skills/embedded-captions/scripts/audio-envelope.cjs +95 -0
- package/.agents/skills/embedded-captions/scripts/check-occlusion.cjs +250 -0
- package/.agents/skills/embedded-captions/scripts/check-overflow.cjs +194 -0
- package/.agents/skills/embedded-captions/scripts/check-rail-climax.cjs +233 -0
- package/.agents/skills/embedded-captions/scripts/check-timing.cjs +173 -0
- package/.agents/skills/embedded-captions/scripts/fill-timings.cjs +124 -0
- package/.agents/skills/embedded-captions/scripts/fit-fonts.cjs +158 -0
- package/.agents/skills/embedded-captions/scripts/gen-stroke-path.py +46 -0
- package/.agents/skills/embedded-captions/scripts/inject-fonts.cjs +169 -0
- package/.agents/skills/embedded-captions/scripts/lib-dna.cjs +201 -0
- package/.agents/skills/embedded-captions/scripts/make-cinematic.cjs +1205 -0
- package/.agents/skills/embedded-captions/scripts/make-composition.cjs +404 -0
- package/.agents/skills/embedded-captions/scripts/make-theme.cjs +8781 -0
- package/.agents/skills/embedded-captions/scripts/matte.cjs +294 -0
- package/.agents/skills/embedded-captions/scripts/measure-layout.cjs +293 -0
- package/.agents/skills/embedded-captions/scripts/prepare.sh +39 -0
- package/.agents/skills/embedded-captions/scripts/preview-frames.cjs +268 -0
- package/.agents/skills/embedded-captions/scripts/render-and-composite.sh +509 -0
- package/.agents/skills/embedded-captions/scripts/render-theme.sh +34 -0
- package/.agents/skills/embedded-captions/scripts/safe-zones.cjs +813 -0
- package/.agents/skills/embedded-captions/scripts/transcribe.cjs +349 -0
- package/.agents/skills/embedded-captions/themes/PORTING.md +49 -0
- package/.agents/skills/embedded-captions/themes/README.md +244 -0
- package/.agents/skills/embedded-captions/themes/anchor.json +27 -0
- package/.agents/skills/embedded-captions/themes/arcade.json +51 -0
- package/.agents/skills/embedded-captions/themes/aurora.json +41 -0
- package/.agents/skills/embedded-captions/themes/biolume.json +35 -0
- package/.agents/skills/embedded-captions/themes/brush.json +74 -0
- package/.agents/skills/embedded-captions/themes/chalkboard.json +52 -0
- package/.agents/skills/embedded-captions/themes/dossier.json +56 -0
- package/.agents/skills/embedded-captions/themes/graffiti.json +62 -0
- package/.agents/skills/embedded-captions/themes/hologram.json +41 -0
- package/.agents/skills/embedded-captions/themes/inkwater.json +43 -0
- package/.agents/skills/embedded-captions/themes/laser.json +46 -0
- package/.agents/skills/embedded-captions/themes/lastpage.json +33 -0
- package/.agents/skills/embedded-captions/themes/neonsign.json +53 -0
- package/.agents/skills/embedded-captions/themes/nightcity.json +56 -0
- package/.agents/skills/embedded-captions/themes/ordnance.json +54 -0
- package/.agents/skills/embedded-captions/themes/papercut.json +37 -0
- package/.agents/skills/embedded-captions/themes/popup.json +46 -0
- package/.agents/skills/embedded-captions/themes/ransom.json +62 -0
- package/.agents/skills/embedded-captions/themes/scoreboard.json +54 -0
- package/.agents/skills/embedded-captions/themes/spectrum.json +46 -0
- package/.agents/skills/embedded-captions/themes/stardust.json +29 -0
- package/.agents/skills/embedded-captions/themes/stomp.json +43 -0
- package/.agents/skills/embedded-captions/themes/terminal.json +49 -0
- package/.agents/skills/embedded-captions/themes/thunder.json +44 -0
- package/.agents/skills/embedded-captions/themes/transit.json +44 -0
- package/.agents/skills/embedded-captions/themes/vhs.json +47 -0
- package/.agents/skills/faceless-explainer/SKILL.md +209 -0
- package/.agents/skills/faceless-explainer/references/cut-catalog.md +215 -0
- package/.agents/skills/faceless-explainer/references/motion-language.md +156 -0
- package/.agents/skills/faceless-explainer/references/story-design.md +248 -0
- package/.agents/skills/faceless-explainer/references/visual-design.md +146 -0
- package/.agents/skills/faceless-explainer/scripts/assemble-index.mjs +570 -0
- package/.agents/skills/faceless-explainer/scripts/audio.mjs +260 -0
- package/.agents/skills/faceless-explainer/scripts/build-frame.mjs +536 -0
- package/.agents/skills/faceless-explainer/scripts/captions.mjs +508 -0
- package/.agents/skills/faceless-explainer/scripts/lib/assets.mjs +55 -0
- package/.agents/skills/faceless-explainer/scripts/lib/dimensions.mjs +45 -0
- package/.agents/skills/faceless-explainer/scripts/lib/storyboard.mjs +249 -0
- package/.agents/skills/faceless-explainer/scripts/lib/tokens.mjs +204 -0
- package/.agents/skills/faceless-explainer/scripts/lib/transition-registry.mjs +38 -0
- package/.agents/skills/faceless-explainer/scripts/lib/transitions.json +71 -0
- package/.agents/skills/faceless-explainer/scripts/transitions.mjs +320 -0
- package/.agents/skills/faceless-explainer/sub-agents/frame-worker.md +75 -0
- package/.agents/skills/farmville-saas-ux/SKILL.md +156 -0
- package/.agents/skills/farmville-saas-ux/assets/starter.html +294 -0
- package/.agents/skills/farmville-saas-ux/references/components.md +340 -0
- package/.agents/skills/farmville-saas-ux/references/porting-guide.md +121 -0
- package/.agents/skills/farmville-saas-ux/references/tokens.md +271 -0
- package/.agents/skills/flockposter/LICENSE +17 -0
- package/.agents/skills/flockposter/README.md +72 -0
- package/.agents/skills/flockposter/SKILL.md +562 -0
- package/.agents/skills/flockposter/examples/cli-instagram-reel.sh +21 -0
- package/.agents/skills/flockposter/examples/cli-multi-platform.json +69 -0
- package/.agents/skills/flockposter/examples/cli-tiktok-upload-only.sh +22 -0
- package/.agents/skills/flockposter/examples/cli-x-thread.sh +17 -0
- package/.agents/skills/flockposter/examples/cli-youtube-short.sh +21 -0
- package/.agents/skills/flockposter/examples/public-api-instagram-reel.json +28 -0
- package/.agents/skills/general-video/SKILL.md +143 -0
- package/.agents/skills/hyperframes/SKILL.md +160 -0
- package/.agents/skills/hyperframes-animation/SKILL.md +84 -0
- package/.agents/skills/hyperframes-animation/adapters/animate-text.md +64 -0
- package/.agents/skills/hyperframes-animation/adapters/animejs.md +114 -0
- package/.agents/skills/hyperframes-animation/adapters/css-animations.md +143 -0
- package/.agents/skills/hyperframes-animation/adapters/gsap-easing-and-stagger.md +118 -0
- package/.agents/skills/hyperframes-animation/adapters/gsap-timeline-and-labels.md +96 -0
- package/.agents/skills/hyperframes-animation/adapters/gsap-transforms-and-perf.md +96 -0
- package/.agents/skills/hyperframes-animation/adapters/gsap.md +105 -0
- package/.agents/skills/hyperframes-animation/adapters/html-in-canvas-patterns.md +507 -0
- package/.agents/skills/hyperframes-animation/adapters/lottie.md +117 -0
- package/.agents/skills/hyperframes-animation/adapters/three.md +131 -0
- package/.agents/skills/hyperframes-animation/adapters/typegpu.md +178 -0
- package/.agents/skills/hyperframes-animation/adapters/waapi.md +101 -0
- package/.agents/skills/hyperframes-animation/blueprints/comparison-split.md +27 -0
- package/.agents/skills/hyperframes-animation/blueprints/constellation-hub.md +44 -0
- package/.agents/skills/hyperframes-animation/blueprints/cta-morph-press.md +28 -0
- package/.agents/skills/hyperframes-animation/blueprints/cursor-ui-demo.md +57 -0
- package/.agents/skills/hyperframes-animation/blueprints/dataviz-countup.md +46 -0
- package/.agents/skills/hyperframes-animation/blueprints/device-surface-showcase.md +53 -0
- package/.agents/skills/hyperframes-animation/blueprints/grid-card-assemble.md +66 -0
- package/.agents/skills/hyperframes-animation/blueprints/kinetic-type-beats.md +78 -0
- package/.agents/skills/hyperframes-animation/blueprints/logo-assemble-lockup.md +69 -0
- package/.agents/skills/hyperframes-animation/blueprints/overwhelm-surround.md +28 -0
- package/.agents/skills/hyperframes-animation/blueprints/spatial-pan-stations.md +37 -0
- package/.agents/skills/hyperframes-animation/blueprints/ticker-takeover.md +29 -0
- package/.agents/skills/hyperframes-animation/blueprints/titlecard-reveal.md +42 -0
- package/.agents/skills/hyperframes-animation/blueprints/typewriter-reveal.md +51 -0
- package/.agents/skills/hyperframes-animation/blueprints/video-text-pivot.md +30 -0
- package/.agents/skills/hyperframes-animation/blueprints-index.md +146 -0
- package/.agents/skills/hyperframes-animation/examples/assets/avatars/02.avif +0 -0
- package/.agents/skills/hyperframes-animation/examples/assets/brands/github.avif +0 -0
- package/.agents/skills/hyperframes-animation/examples/assets/brands/nvidia.avif +0 -0
- package/.agents/skills/hyperframes-animation/examples/assets/brands/visa.avif +0 -0
- package/.agents/skills/hyperframes-animation/examples/assets/brands/zoominfo.avif +0 -0
- package/.agents/skills/hyperframes-animation/examples/brand-reveal-assemble-zoom.html +382 -0
- package/.agents/skills/hyperframes-animation/examples/comparison-split-cards.html +649 -0
- package/.agents/skills/hyperframes-animation/examples/concept-demo-decode-pan.html +520 -0
- package/.agents/skills/hyperframes-animation/examples/cta-morph-press.html +468 -0
- package/.agents/skills/hyperframes-animation/examples/cta-orbit-collapse.html +1298 -0
- package/.agents/skills/hyperframes-animation/examples/demo-page-scroll-spotlight.html +759 -0
- package/.agents/skills/hyperframes-animation/examples/hook-counter-burst.html +729 -0
- package/.agents/skills/hyperframes-animation/examples/messaging-multi-phrase.html +352 -0
- package/.agents/skills/hyperframes-animation/examples/metric-video-text-pivot.html +779 -0
- package/.agents/skills/hyperframes-animation/examples/problem-mockup-overwhelm.html +1374 -0
- package/.agents/skills/hyperframes-animation/examples/proof-logo-chain.html +861 -0
- package/.agents/skills/hyperframes-animation/examples/takeover-ticker-displace.html +347 -0
- package/.agents/skills/hyperframes-animation/examples/workflow-approve-press.html +606 -0
- package/.agents/skills/hyperframes-animation/rules/3d-page-scroll.md +227 -0
- package/.agents/skills/hyperframes-animation/rules/3d-text-depth-layers.md +297 -0
- package/.agents/skills/hyperframes-animation/rules/ai-tracking-box.md +382 -0
- package/.agents/skills/hyperframes-animation/rules/ambient-glow-bloom.md +305 -0
- package/.agents/skills/hyperframes-animation/rules/asr-keyword-glow.md +286 -0
- package/.agents/skills/hyperframes-animation/rules/avatar-cloud-network.md +371 -0
- package/.agents/skills/hyperframes-animation/rules/camera-cursor-tracking.md +246 -0
- package/.agents/skills/hyperframes-animation/rules/card-morph-anchor.md +267 -0
- package/.agents/skills/hyperframes-animation/rules/center-outward-expansion.md +227 -0
- package/.agents/skills/hyperframes-animation/rules/context-sensitive-cursor.md +257 -0
- package/.agents/skills/hyperframes-animation/rules/coordinate-target-zoom.md +332 -0
- package/.agents/skills/hyperframes-animation/rules/counting-dynamic-scale.md +283 -0
- package/.agents/skills/hyperframes-animation/rules/css-marker-patterns.md +373 -0
- package/.agents/skills/hyperframes-animation/rules/cursor-click-ripple.md +262 -0
- package/.agents/skills/hyperframes-animation/rules/depth-of-field-blur.md +313 -0
- package/.agents/skills/hyperframes-animation/rules/depth-scatter-assemble.md +303 -0
- package/.agents/skills/hyperframes-animation/rules/discrete-text-sequence.md +273 -0
- package/.agents/skills/hyperframes-animation/rules/dynamic-content-sequencing.md +307 -0
- package/.agents/skills/hyperframes-animation/rules/gsap-effects.md +299 -0
- package/.agents/skills/hyperframes-animation/rules/hacker-flip-3d.md +223 -0
- package/.agents/skills/hyperframes-animation/rules/kinetic-beat-slam.md +183 -0
- package/.agents/skills/hyperframes-animation/rules/motion-blur-streak.md +328 -0
- package/.agents/skills/hyperframes-animation/rules/multi-phase-camera.md +273 -0
- package/.agents/skills/hyperframes-animation/rules/orbit-3d-entry.md +301 -0
- package/.agents/skills/hyperframes-animation/rules/physics-press-reaction.md +350 -0
- package/.agents/skills/hyperframes-animation/rules/press-release-spring.md +296 -0
- package/.agents/skills/hyperframes-animation/rules/reactive-displacement.md +277 -0
- package/.agents/skills/hyperframes-animation/rules/scale-swap-transition.md +298 -0
- package/.agents/skills/hyperframes-animation/rules/sine-wave-loop.md +278 -0
- package/.agents/skills/hyperframes-animation/rules/split-tilt-cards.md +277 -0
- package/.agents/skills/hyperframes-animation/rules/spring-pop-entrance.md +273 -0
- package/.agents/skills/hyperframes-animation/rules/stat-bars-and-fills.md +156 -0
- package/.agents/skills/hyperframes-animation/rules/svg-icon-enrichment.md +329 -0
- package/.agents/skills/hyperframes-animation/rules/svg-path-draw.md +274 -0
- package/.agents/skills/hyperframes-animation/rules/vertical-spring-ticker.md +239 -0
- package/.agents/skills/hyperframes-animation/rules/viewport-change.md +349 -0
- package/.agents/skills/hyperframes-animation/rules-index.md +86 -0
- package/.agents/skills/hyperframes-animation/scripts/animation-map.mjs +606 -0
- package/.agents/skills/hyperframes-animation/scripts/package-loader.mjs +288 -0
- package/.agents/skills/hyperframes-animation/scripts/package-loader.test.mjs +62 -0
- package/.agents/skills/hyperframes-animation/techniques.md +507 -0
- package/.agents/skills/hyperframes-animation/transitions/TRANSITION-REGISTRY.md +167 -0
- package/.agents/skills/hyperframes-animation/transitions/catalog.md +127 -0
- package/.agents/skills/hyperframes-animation/transitions/css-3d.md +12 -0
- package/.agents/skills/hyperframes-animation/transitions/css-blur.md +51 -0
- package/.agents/skills/hyperframes-animation/transitions/css-cover.md +43 -0
- package/.agents/skills/hyperframes-animation/transitions/css-destruction.md +95 -0
- package/.agents/skills/hyperframes-animation/transitions/css-dissolve.md +66 -0
- package/.agents/skills/hyperframes-animation/transitions/css-distortion.md +45 -0
- package/.agents/skills/hyperframes-animation/transitions/css-grid.md +10 -0
- package/.agents/skills/hyperframes-animation/transitions/css-light.md +49 -0
- package/.agents/skills/hyperframes-animation/transitions/css-mechanical.md +30 -0
- package/.agents/skills/hyperframes-animation/transitions/css-other.md +25 -0
- package/.agents/skills/hyperframes-animation/transitions/css-push.md +41 -0
- package/.agents/skills/hyperframes-animation/transitions/css-radial.md +37 -0
- package/.agents/skills/hyperframes-animation/transitions/css-scale.md +24 -0
- package/.agents/skills/hyperframes-animation/transitions/overview.md +153 -0
- package/.agents/skills/hyperframes-cli/SKILL.md +113 -0
- package/.agents/skills/hyperframes-cli/references/doctor-browser.md +45 -0
- package/.agents/skills/hyperframes-cli/references/init-and-scaffold.md +55 -0
- package/.agents/skills/hyperframes-cli/references/lambda.md +132 -0
- package/.agents/skills/hyperframes-cli/references/lint-validate-inspect.md +121 -0
- package/.agents/skills/hyperframes-cli/references/preview-render.md +149 -0
- package/.agents/skills/hyperframes-cli/references/upgrade-info-misc.md +75 -0
- package/.agents/skills/hyperframes-core/SKILL.md +78 -0
- package/.agents/skills/hyperframes-core/references/composition-patterns.md +263 -0
- package/.agents/skills/hyperframes-core/references/data-attributes.md +70 -0
- package/.agents/skills/hyperframes-core/references/determinism-rules.md +68 -0
- package/.agents/skills/hyperframes-core/references/full-screen-motion.md +62 -0
- package/.agents/skills/hyperframes-core/references/minimal-composition.md +66 -0
- package/.agents/skills/hyperframes-core/references/script-format.md +49 -0
- package/.agents/skills/hyperframes-core/references/storyboard-format.md +95 -0
- package/.agents/skills/hyperframes-core/references/sub-compositions.md +237 -0
- package/.agents/skills/hyperframes-core/references/subagent-dispatch.md +41 -0
- package/.agents/skills/hyperframes-core/references/tailwind.md +125 -0
- package/.agents/skills/hyperframes-core/references/tracks-and-clips.md +76 -0
- package/.agents/skills/hyperframes-core/references/variables-and-media.md +90 -0
- package/.agents/skills/hyperframes-creative/SKILL.md +70 -0
- package/.agents/skills/hyperframes-creative/frame-presets/biennale-yellow/FRAME.md +289 -0
- package/.agents/skills/hyperframes-creative/frame-presets/biennale-yellow/caption-skin.html +221 -0
- package/.agents/skills/hyperframes-creative/frame-presets/biennale-yellow/frame-showcase.html +1214 -0
- package/.agents/skills/hyperframes-creative/frame-presets/blockframe/FRAME.md +275 -0
- package/.agents/skills/hyperframes-creative/frame-presets/blockframe/caption-skin.html +224 -0
- package/.agents/skills/hyperframes-creative/frame-presets/blockframe/frame-showcase.html +1347 -0
- package/.agents/skills/hyperframes-creative/frame-presets/blue-professional/FRAME.md +307 -0
- package/.agents/skills/hyperframes-creative/frame-presets/blue-professional/caption-skin.html +223 -0
- package/.agents/skills/hyperframes-creative/frame-presets/blue-professional/frame-showcase.html +1372 -0
- package/.agents/skills/hyperframes-creative/frame-presets/bold-poster/FRAME.md +275 -0
- package/.agents/skills/hyperframes-creative/frame-presets/bold-poster/caption-skin.html +230 -0
- package/.agents/skills/hyperframes-creative/frame-presets/bold-poster/frame-showcase.html +1140 -0
- package/.agents/skills/hyperframes-creative/frame-presets/broadside/FRAME.md +284 -0
- package/.agents/skills/hyperframes-creative/frame-presets/broadside/caption-skin.html +225 -0
- package/.agents/skills/hyperframes-creative/frame-presets/broadside/frame-showcase.html +1166 -0
- package/.agents/skills/hyperframes-creative/frame-presets/capsule/FRAME.md +284 -0
- package/.agents/skills/hyperframes-creative/frame-presets/capsule/caption-skin.html +224 -0
- package/.agents/skills/hyperframes-creative/frame-presets/capsule/frame-showcase.html +1465 -0
- package/.agents/skills/hyperframes-creative/frame-presets/cartesian/FRAME.md +278 -0
- package/.agents/skills/hyperframes-creative/frame-presets/cartesian/caption-skin.html +222 -0
- package/.agents/skills/hyperframes-creative/frame-presets/cartesian/frame-showcase.html +1263 -0
- package/.agents/skills/hyperframes-creative/frame-presets/claude/FRAME.md +277 -0
- package/.agents/skills/hyperframes-creative/frame-presets/claude/caption-skin.html +224 -0
- package/.agents/skills/hyperframes-creative/frame-presets/claude/frame-showcase.html +1439 -0
- package/.agents/skills/hyperframes-creative/frame-presets/cobalt-grid/FRAME.md +265 -0
- package/.agents/skills/hyperframes-creative/frame-presets/cobalt-grid/caption-skin.html +238 -0
- package/.agents/skills/hyperframes-creative/frame-presets/cobalt-grid/frame-showcase.html +1468 -0
- package/.agents/skills/hyperframes-creative/frame-presets/coral/FRAME.md +314 -0
- package/.agents/skills/hyperframes-creative/frame-presets/coral/caption-skin.html +226 -0
- package/.agents/skills/hyperframes-creative/frame-presets/coral/frame-showcase.html +1268 -0
- package/.agents/skills/hyperframes-creative/frame-presets/creative-mode/FRAME.md +333 -0
- package/.agents/skills/hyperframes-creative/frame-presets/creative-mode/caption-skin.html +227 -0
- package/.agents/skills/hyperframes-creative/frame-presets/creative-mode/frame-showcase.html +1330 -0
- package/.agents/skills/hyperframes-creative/frame-presets/daisy-days/FRAME.md +274 -0
- package/.agents/skills/hyperframes-creative/frame-presets/daisy-days/caption-skin.html +230 -0
- package/.agents/skills/hyperframes-creative/frame-presets/daisy-days/frame-showcase.html +1444 -0
- package/.agents/skills/hyperframes-creative/frame-presets/editorial-forest/FRAME.md +265 -0
- package/.agents/skills/hyperframes-creative/frame-presets/editorial-forest/caption-skin.html +223 -0
- package/.agents/skills/hyperframes-creative/frame-presets/editorial-forest/frame-showcase.html +1273 -0
- package/.agents/skills/hyperframes-creative/palettes/bold-energetic.md +14 -0
- package/.agents/skills/hyperframes-creative/palettes/clean-corporate.md +14 -0
- package/.agents/skills/hyperframes-creative/palettes/dark-premium.md +14 -0
- package/.agents/skills/hyperframes-creative/palettes/jewel-rich.md +14 -0
- package/.agents/skills/hyperframes-creative/palettes/monochrome.md +14 -0
- package/.agents/skills/hyperframes-creative/palettes/nature-earth.md +14 -0
- package/.agents/skills/hyperframes-creative/palettes/neon-electric.md +14 -0
- package/.agents/skills/hyperframes-creative/palettes/pastel-soft.md +14 -0
- package/.agents/skills/hyperframes-creative/palettes/warm-editorial.md +14 -0
- package/.agents/skills/hyperframes-creative/references/audio-reactive.md +76 -0
- package/.agents/skills/hyperframes-creative/references/beat-direction.md +164 -0
- package/.agents/skills/hyperframes-creative/references/composition-patterns.md +199 -0
- package/.agents/skills/hyperframes-creative/references/data-in-motion.md +19 -0
- package/.agents/skills/hyperframes-creative/references/design-adherence.md +19 -0
- package/.agents/skills/hyperframes-creative/references/design-picker.md +123 -0
- package/.agents/skills/hyperframes-creative/references/design-spec.md +55 -0
- package/.agents/skills/hyperframes-creative/references/house-style.md +73 -0
- package/.agents/skills/hyperframes-creative/references/motion-principles.md +150 -0
- package/.agents/skills/hyperframes-creative/references/narration.md +92 -0
- package/.agents/skills/hyperframes-creative/references/prompt-expansion.md +68 -0
- package/.agents/skills/hyperframes-creative/references/typography.md +218 -0
- package/.agents/skills/hyperframes-creative/references/video-composition.md +63 -0
- package/.agents/skills/hyperframes-creative/references/visual-styles.md +457 -0
- package/.agents/skills/hyperframes-creative/scripts/contrast-report.mjs +353 -0
- package/.agents/skills/hyperframes-creative/scripts/extract-audio-data.py +188 -0
- package/.agents/skills/hyperframes-creative/scripts/package-loader.mjs +288 -0
- package/.agents/skills/hyperframes-creative/scripts/package-loader.test.mjs +62 -0
- package/.agents/skills/hyperframes-creative/templates/design-picker.html +1432 -0
- package/.agents/skills/hyperframes-keyframes/SKILL.md +237 -0
- package/.agents/skills/hyperframes-keyframes/agents/openai.yaml +4 -0
- package/.agents/skills/hyperframes-keyframes/references/keyframe-patterns.md +106 -0
- package/.agents/skills/motion-graphics/SKILL.md +172 -0
- package/.agents/skills/motion-graphics/agents/builder.md +40 -0
- package/.agents/skills/motion-graphics/agents/director.md +53 -0
- package/.agents/skills/motion-graphics/agents/finalize.md +17 -0
- package/.agents/skills/motion-graphics/catalog-map.md +40 -0
- package/.agents/skills/motion-graphics/categories/asset-fusion/module.md +37 -0
- package/.agents/skills/motion-graphics/categories/charts/module.md +21 -0
- package/.agents/skills/motion-graphics/categories/kinetic-type/module.md +19 -0
- package/.agents/skills/motion-graphics/categories/logo-reveal/module.md +17 -0
- package/.agents/skills/motion-graphics/categories/lower-thirds/module.md +16 -0
- package/.agents/skills/motion-graphics/categories/maps/bake-basemap.mjs +273 -0
- package/.agents/skills/motion-graphics/categories/maps/module.md +61 -0
- package/.agents/skills/motion-graphics/categories/news/module.md +56 -0
- package/.agents/skills/motion-graphics/categories/stat/module.md +21 -0
- package/.agents/skills/motion-graphics/categories/tweet/module.md +16 -0
- package/.agents/skills/motion-graphics/categories/webpage/module.md +21 -0
- package/.agents/skills/motion-graphics/grounding/PROTOCOL.md +64 -0
- package/.agents/skills/motion-graphics/grounding/locate.mjs +227 -0
- package/.agents/skills/motion-graphics/phases/source/guide.md +21 -0
- package/.agents/skills/motion-graphics/references/builder-contract.md +38 -0
- package/.agents/skills/motion-graphics/references/motion-vocabulary.md +43 -0
- package/.agents/skills/motion-graphics/references/shot-plan-ir.md +54 -0
- package/.agents/skills/motion-graphics/samples/asset-fusion/_ref-circle-highlight.html +306 -0
- package/.agents/skills/music/SKILL.md +416 -0
- package/.agents/skills/music/references/api_reference.md +519 -0
- package/.agents/skills/music/references/installation.md +65 -0
- package/.agents/skills/product-launch-video/SKILL.md +208 -0
- package/.agents/skills/product-launch-video/references/cut-catalog.md +220 -0
- package/.agents/skills/product-launch-video/references/motion-language.md +156 -0
- package/.agents/skills/product-launch-video/references/story-design.md +373 -0
- package/.agents/skills/product-launch-video/references/visual-design.md +126 -0
- package/.agents/skills/product-launch-video/scripts/assemble-index.mjs +570 -0
- package/.agents/skills/product-launch-video/scripts/audio.mjs +260 -0
- package/.agents/skills/product-launch-video/scripts/build-frame.mjs +536 -0
- package/.agents/skills/product-launch-video/scripts/captions.mjs +508 -0
- package/.agents/skills/product-launch-video/scripts/lib/assets.mjs +55 -0
- package/.agents/skills/product-launch-video/scripts/lib/dimensions.mjs +45 -0
- package/.agents/skills/product-launch-video/scripts/lib/pad-frame-duration.mjs +36 -0
- package/.agents/skills/product-launch-video/scripts/lib/pad-frame-duration.test.mjs +76 -0
- package/.agents/skills/product-launch-video/scripts/lib/storyboard.mjs +249 -0
- package/.agents/skills/product-launch-video/scripts/lib/tokens.mjs +204 -0
- package/.agents/skills/product-launch-video/scripts/lib/transition-registry.mjs +38 -0
- package/.agents/skills/product-launch-video/scripts/lib/transitions.json +71 -0
- package/.agents/skills/product-launch-video/scripts/stage-assets.mjs +39 -0
- package/.agents/skills/product-launch-video/scripts/transitions.mjs +327 -0
- package/.agents/skills/product-launch-video/sub-agents/frame-worker.md +75 -0
- package/.agents/skills/slideshow/SKILL.md +550 -0
- package/.agents/skills/slideshow/references/standalone-harness.md +1020 -0
- package/.agents/skills/talking-head-recut/NOTICE.md +39 -0
- package/.agents/skills/talking-head-recut/SKILL.md +1195 -0
- package/.agents/skills/talking-head-recut/assets/vendor/gsap.min.js +10 -0
- package/.agents/skills/talking-head-recut/references/DESIGN_INDEX.md +145 -0
- package/.agents/skills/talking-head-recut/references/frames/clean.html +92 -0
- package/.agents/skills/talking-head-recut/references/frames/hairline.html +171 -0
- package/.agents/skills/talking-head-recut/references/frames/polaroid.html +131 -0
- package/.agents/skills/talking-head-recut/references/layouts/overlay.html +164 -0
- package/.agents/skills/talking-head-recut/references/layouts/pip.html +143 -0
- package/.agents/skills/talking-head-recut/references/layouts/split.html +121 -0
- package/.agents/skills/talking-head-recut/references/layouts/stack.html +109 -0
- package/.agents/skills/talking-head-recut/references/styles/academic.html +172 -0
- package/.agents/skills/talking-head-recut/references/styles/audit.html +170 -0
- package/.agents/skills/talking-head-recut/references/styles/editorial.html +189 -0
- package/.agents/skills/talking-head-recut/references/styles/geom.html +181 -0
- package/.agents/skills/talking-head-recut/references/styles/minimal.html +130 -0
- package/.agents/skills/talking-head-recut/references/styles/spotlight.html +142 -0
- package/.agents/skills/talking-head-recut/references/styles/swiss.html +188 -0
- package/.agents/skills/talking-head-recut/references/styles/terminal.html +196 -0
- package/.agents/skills/talking-head-recut/references/styles/whiteboard.html +170 -0
- package/.agents/skills/talking-head-recut/references/styles/xhs.html +206 -0
- package/.agents/skills/text-to-speech/SKILL.md +226 -0
- package/.agents/skills/text-to-speech/references/installation.md +90 -0
- package/.agents/skills/text-to-speech/references/streaming.md +307 -0
- package/.agents/skills/text-to-speech/references/voice-settings.md +115 -0
- package/.agents/skills/vidfarm-director/SKILL.md +179 -0
- package/.agents/skills/vidfarm-director/recipes/find-and-fork-template.md +16 -0
- package/.agents/skills/vidfarm-director/recipes/local-edit-render-approve.md +13 -0
- package/.agents/skills/vidfarm-director/recipes/onboard-a-new-director.md +13 -0
- package/.agents/skills/vidfarm-director/recipes/retheme-template.md +17 -0
- package/.agents/skills/vidfarm-director/references/assets-and-sourcing.md +117 -0
- package/.agents/skills/vidfarm-director/references/automation-and-local-dev.md +276 -0
- package/.agents/skills/vidfarm-director/references/core-workflows.md +301 -0
- package/.agents/skills/vidfarm-director/references/editor-workflows.md +367 -0
- package/.agents/skills/vidfarm-director/references/onboarding.md +28 -0
- package/.agents/skills/vidfarm-director/references/primitives.md +307 -0
- package/.agents/skills/vidfarm-director/references/rest-api.md +84 -0
- package/.agents/skills/vidfarm-media/SKILL.md +158 -0
- package/.agents/skills/vidfarm-media/references/tts.md +111 -0
- package/.agents/skills/vidfarm-media/scripts/audio.mjs +628 -0
- package/.agents/skills/vidfarm-media/scripts/wait-bgm.mjs +31 -0
- package/.agents/skills/website-to-video/SKILL.md +145 -0
- package/.agents/skills/website-to-video/assets/sfx/CREDITS.md +35 -0
- package/.agents/skills/website-to-video/assets/sfx/manifest.json +97 -0
- package/.agents/skills/website-to-video/references/beat-builder-guide.md +263 -0
- package/.agents/skills/website-to-video/references/capabilities.md +713 -0
- package/.agents/skills/website-to-video/references/step-0-capture.md +55 -0
- package/.agents/skills/website-to-video/references/step-1-design.md +333 -0
- package/.agents/skills/website-to-video/references/step-2-brief.md +178 -0
- package/.agents/skills/website-to-video/references/step-3-storyboard.md +572 -0
- package/.agents/skills/website-to-video/references/step-4-vo.md +225 -0
- package/.agents/skills/website-to-video/references/step-5-build.md +483 -0
- package/.agents/skills/website-to-video/references/step-6-validate.md +341 -0
- package/.agents/skills/website-to-video/scripts/w2h-verify.mjs +759 -0
- package/README.md +97 -0
- package/SKILL.director.md +1644 -0
- package/SKILL.md +83 -0
- package/demo/README.md +28 -0
- package/demo/dist/app.css +1 -0
- package/demo/dist/app.js +968 -0
- package/demo/dist/chunks/chunk-3OT2D42H.js +1 -0
- package/demo/dist/chunks/chunk-DXB73IDG.js +1 -0
- package/demo/dist/chunks/domEditingLayers-AT7G6F4L-ZTHJHB7R.js +1 -0
- package/demo/dist/chunks/hyperframes-player-7HKH6NSO.js +459 -0
- package/demo/dist/chunks/lib-XAQ37YOE.js +1 -0
- package/demo/dist/chunks/src-TJ2QYA4U.js +207 -0
- package/demo/dist/favicon.ico +0 -0
- package/demo/dist/icons/timeline/audio.svg +7 -0
- package/demo/dist/icons/timeline/captions.svg +5 -0
- package/demo/dist/icons/timeline/composition.svg +12 -0
- package/demo/dist/icons/timeline/image.svg +18 -0
- package/demo/dist/icons/timeline/music.svg +10 -0
- package/demo/dist/icons/timeline/text.svg +3 -0
- package/demo/dist/index.html +16 -0
- package/dist/src/cli.js +7258 -0
- package/dist/src/devcli/auth-store.js +67 -0
- package/dist/src/devcli/captions.js +310 -0
- package/dist/src/devcli/clip-store.js +368 -0
- package/dist/src/devcli/clips.js +1138 -0
- package/dist/src/devcli/composition-edit.js +1292 -0
- package/dist/src/devcli/cost-mode.js +149 -0
- package/dist/src/devcli/doctor.js +192 -0
- package/dist/src/devcli/hyperframes-cli.js +118 -0
- package/dist/src/devcli/local-backend.js +167 -0
- package/dist/src/devcli/local-frontend-server.js +681 -0
- package/dist/src/devcli/local-render.js +136 -0
- package/dist/src/devcli/skills.js +476 -0
- package/dist/src/devcli/speech.js +178 -0
- package/dist/src/devcli/stills.js +249 -0
- package/dist/src/devcli/telemetry.js +236 -0
- package/dist/src/devcli/timeline-edit.js +490 -0
- package/dist/src/devcli/transitions.js +205 -0
- package/dist/src/hyperframes/composition.js +780 -0
- package/dist/src/lib/crypto.js +45 -0
- package/dist/src/lib/dev-log.js +54 -0
- package/dist/src/lib/display-name.js +11 -0
- package/dist/src/lib/ids.js +24 -0
- package/dist/src/lib/images.js +19 -0
- package/dist/src/lib/json.js +15 -0
- package/dist/src/lib/package-root.js +47 -0
- package/dist/src/lib/render-media-prep.js +293 -0
- package/dist/src/lib/template-paths.js +28 -0
- package/dist/src/lib/time.js +7 -0
- package/dist/src/lib/url-clean.js +85 -0
- package/dist/src/services/captions.js +123 -0
- package/dist/src/services/clip-curation/cost.js +116 -0
- package/dist/src/services/clip-curation/ffmpeg.js +352 -0
- package/dist/src/services/clip-curation/gemini.js +418 -0
- package/dist/src/services/clip-curation/hunt.js +470 -0
- package/dist/src/services/clip-curation/index.js +19 -0
- package/dist/src/services/clip-curation/local-agent.js +248 -0
- package/dist/src/services/clip-curation/media-select.js +152 -0
- package/dist/src/services/clip-curation/presets.js +20 -0
- package/dist/src/services/clip-curation/presets.v1.json +59 -0
- package/dist/src/services/clip-curation/query.js +167 -0
- package/dist/src/services/clip-curation/refine.js +165 -0
- package/dist/src/services/clip-curation/scan.js +189 -0
- package/dist/src/services/clip-curation/source-naming.js +131 -0
- package/dist/src/services/clip-curation/taxonomy.js +73 -0
- package/dist/src/services/clip-curation/taxonomy.v1.json +102 -0
- package/dist/src/services/clip-curation/types.js +7 -0
- package/dist/src/services/composition-lint.js +199 -0
- package/dist/src/services/provider-errors.js +128 -0
- package/dist/src/services/speech.js +629 -0
- package/package.json +154 -0
- package/public/assets/discover-client-app.js +1 -0
- package/public/assets/favicon.ico +0 -0
- package/public/assets/file-directory-app.js +89 -0
- package/public/assets/homepage-app.js +54 -0
- package/public/assets/homepage-client-app.js +80 -0
- package/public/assets/landing-page-client-app.js +87 -0
- package/public/assets/logo-vidfarm.png +0 -0
- package/public/assets/page-runtime-client-app.js +94 -0
- package/public/assets/placeholders/scene-placeholder.png +0 -0
- package/public/serve-shells/editor.html +3146 -0
- package/public/serve-shells/library-files.html +3450 -0
- package/public/serve-shells/library-raws.html +4404 -0
- package/public/serve-shells/tools-clipper.html +3991 -0
- package/public/serve-shells/tools-image.html +5584 -0
- package/public/serve-shells/tools-video.html +4404 -0
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
// Standalone local render — the devcli's own on-machine MP4 pipeline.
|
|
2
|
+
//
|
|
3
|
+
// Vidfarm renders are HyperFrames renders, and the published devcli bundles
|
|
4
|
+
// the `hyperframes` CLI, so a fork can render on the user's machine with ZERO
|
|
5
|
+
// backend and ZERO cloud charge: stage the composition HTML into a temp
|
|
6
|
+
// project, run the download-once/cut-segments media pass, then drive
|
|
7
|
+
// `hyperframes render`. This is what makes the SKILL.md promise of a "free
|
|
8
|
+
// local render loop" true from the public npm package — before this module,
|
|
9
|
+
// `vidfarm render --target local` against the cloud host silently dispatched
|
|
10
|
+
// a BILLED Lambda render.
|
|
11
|
+
//
|
|
12
|
+
// Used by:
|
|
13
|
+
// - `vidfarm render <forkId> --target local` (cli.ts) when the host is not
|
|
14
|
+
// a local serve box,
|
|
15
|
+
// - the serve-shell frontend server's /render intercept, so the web editor's
|
|
16
|
+
// Render button on `vidfarm serve` renders on-machine too.
|
|
17
|
+
import { existsSync } from "node:fs";
|
|
18
|
+
import { mkdir, mkdtemp, readFile, rm, writeFile } from "node:fs/promises";
|
|
19
|
+
import os from "node:os";
|
|
20
|
+
import path from "node:path";
|
|
21
|
+
import { prepareProjectMediaForRender } from "../lib/render-media-prep.js";
|
|
22
|
+
import { runHyperframesCommand } from "./hyperframes-cli.js";
|
|
23
|
+
// Same invariant as the backend's forceEvenCompositionDimensions: libx264
|
|
24
|
+
// (yuv420p) rejects odd frame sizes, so round odd data-width/height down.
|
|
25
|
+
function forceEvenDimensions(html) {
|
|
26
|
+
return html.replace(/\bdata-(width|height)=(["'])(\d+)\2/gi, (match, dim, quote, value) => {
|
|
27
|
+
const n = Number.parseInt(value, 10);
|
|
28
|
+
if (!Number.isFinite(n) || n % 2 === 0)
|
|
29
|
+
return match;
|
|
30
|
+
return `data-${dim}=${quote}${n - 1}${quote}`;
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
// fps must come from the composition ROOT tag (the one carrying
|
|
34
|
+
// data-composition-id) — nested sub-compositions could otherwise hijack it.
|
|
35
|
+
function readRootFps(html) {
|
|
36
|
+
const rootTag = html.match(/<[a-zA-Z][^>]*\bdata-composition-id\s*=[^>]*>/);
|
|
37
|
+
const value = rootTag?.[0].match(/\bdata-fps\s*=\s*["']([^"']*)["']/i)?.[1];
|
|
38
|
+
const fps = Number.parseInt(value ?? "", 10);
|
|
39
|
+
return Number.isFinite(fps) && fps > 0 ? fps : 30;
|
|
40
|
+
}
|
|
41
|
+
// Point the producer's ffmpeg/ffprobe resolution at the bundled statics, same
|
|
42
|
+
// as src/devcli/stills.ts — PATH stays the fallback.
|
|
43
|
+
async function producerFfmpegEnv() {
|
|
44
|
+
const env = {};
|
|
45
|
+
if (!process.env.HYPERFRAMES_FFMPEG_PATH?.trim()) {
|
|
46
|
+
try {
|
|
47
|
+
const mod = (await import("ffmpeg-static"));
|
|
48
|
+
const resolved = typeof mod === "string" ? mod : mod.default;
|
|
49
|
+
if (typeof resolved === "string" && resolved && existsSync(resolved))
|
|
50
|
+
env.HYPERFRAMES_FFMPEG_PATH = resolved;
|
|
51
|
+
}
|
|
52
|
+
catch { /* PATH fallback */ }
|
|
53
|
+
}
|
|
54
|
+
if (!process.env.HYPERFRAMES_FFPROBE_PATH?.trim()) {
|
|
55
|
+
try {
|
|
56
|
+
const mod = (await import("ffprobe-static"));
|
|
57
|
+
const resolved = (mod.path ?? mod.default?.path);
|
|
58
|
+
if (typeof resolved === "string" && resolved && existsSync(resolved))
|
|
59
|
+
env.HYPERFRAMES_FFPROBE_PATH = resolved;
|
|
60
|
+
}
|
|
61
|
+
catch { /* PATH fallback */ }
|
|
62
|
+
}
|
|
63
|
+
return env;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Render composition HTML to a video file on THIS machine via the bundled
|
|
67
|
+
* hyperframes CLI. Free — no cloud dispatch, no wallet charge. Throws with the
|
|
68
|
+
* hyperframes error output on failure.
|
|
69
|
+
*/
|
|
70
|
+
export async function renderCompositionLocally(input) {
|
|
71
|
+
const log = input.log ?? (() => { });
|
|
72
|
+
if (!input.compositionHtml.includes("data-composition-id=")) {
|
|
73
|
+
throw new Error("Local render requires composition HTML with data-composition-id.");
|
|
74
|
+
}
|
|
75
|
+
const startedAt = Date.now();
|
|
76
|
+
const projectDir = await mkdtemp(path.join(os.tmpdir(), "vidfarm-local-render-"));
|
|
77
|
+
let prepNotes = [];
|
|
78
|
+
try {
|
|
79
|
+
let html = forceEvenDimensions(input.compositionHtml);
|
|
80
|
+
// Download-once/cut-segments pass — the same prep the backend renders run,
|
|
81
|
+
// so a timeline that reuses one long source N times stays fast locally.
|
|
82
|
+
try {
|
|
83
|
+
const prep = await prepareProjectMediaForRender({ html, projectDir, log });
|
|
84
|
+
if (prep.changed)
|
|
85
|
+
html = prep.html;
|
|
86
|
+
prepNotes = prep.notes;
|
|
87
|
+
}
|
|
88
|
+
catch (error) {
|
|
89
|
+
log("render_media_prep.failed", { error: error instanceof Error ? error.message : String(error) });
|
|
90
|
+
}
|
|
91
|
+
await writeFile(path.join(projectDir, "index.html"), html, "utf8");
|
|
92
|
+
await mkdir(path.dirname(input.outputPath), { recursive: true });
|
|
93
|
+
const args = [
|
|
94
|
+
projectDir,
|
|
95
|
+
"-o", input.outputPath,
|
|
96
|
+
"--fps", String(input.fps ?? readRootFps(html)),
|
|
97
|
+
"--quality", input.quality ?? "standard",
|
|
98
|
+
"--format", input.format ?? "mp4"
|
|
99
|
+
];
|
|
100
|
+
log("local_render.start", { project_dir: projectDir, output: input.outputPath });
|
|
101
|
+
const result = await runHyperframesCommand("render", args, {
|
|
102
|
+
stdio: input.stdio ?? "inherit",
|
|
103
|
+
env: await producerFfmpegEnv()
|
|
104
|
+
});
|
|
105
|
+
if (result.code !== 0) {
|
|
106
|
+
const detail = `${result.stderr}\n${result.stdout}`.trim().slice(-2000);
|
|
107
|
+
throw new Error(`hyperframes render exited with code ${result.code}${detail ? `:\n${detail}` : ""}`);
|
|
108
|
+
}
|
|
109
|
+
if (!existsSync(input.outputPath)) {
|
|
110
|
+
throw new Error(`hyperframes render reported success but wrote no file at ${input.outputPath}`);
|
|
111
|
+
}
|
|
112
|
+
const durationMs = Date.now() - startedAt;
|
|
113
|
+
log("local_render.succeeded", { output: input.outputPath, duration_ms: durationMs });
|
|
114
|
+
return {
|
|
115
|
+
outputPath: input.outputPath,
|
|
116
|
+
projectDir: input.keepProjectDir ? projectDir : null,
|
|
117
|
+
durationMs,
|
|
118
|
+
prepNotes
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
finally {
|
|
122
|
+
if (!input.keepProjectDir)
|
|
123
|
+
await rm(projectDir, { recursive: true, force: true }).catch(() => { });
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
/** Read a composition.html from a pulled/working dir (or the file itself). */
|
|
127
|
+
export async function readCompositionHtmlFrom(target) {
|
|
128
|
+
const abs = path.resolve(process.cwd(), target);
|
|
129
|
+
const file = abs.endsWith(".html") ? abs : path.join(abs, "composition.html");
|
|
130
|
+
const html = await readFile(file, "utf8");
|
|
131
|
+
if (!html.includes("data-composition-id=")) {
|
|
132
|
+
throw new Error(`${file} is missing data-composition-id — not a renderable composition.`);
|
|
133
|
+
}
|
|
134
|
+
return html;
|
|
135
|
+
}
|
|
136
|
+
//# sourceMappingURL=local-render.js.map
|
|
@@ -0,0 +1,476 @@
|
|
|
1
|
+
// `vidfarm skills` — install/refresh multi-file agent skills into a project.
|
|
2
|
+
//
|
|
3
|
+
// Layout convention (matches how the vidfarm repo itself is set up):
|
|
4
|
+
// <root>/.agents/skills/<name>/ canonical install target
|
|
5
|
+
// <root>/.claude/skills/<name> RELATIVE symlink → ../../.agents/skills/<name>
|
|
6
|
+
// (falls back to a real copy where
|
|
7
|
+
// symlinks are unavailable, e.g. Windows)
|
|
8
|
+
// <root>/skills-lock.json merged lock file (other tools'
|
|
9
|
+
// entries are preserved verbatim)
|
|
10
|
+
//
|
|
11
|
+
// Root resolution (defuses the cwd trap): --dir wins; else walk UP from cwd to
|
|
12
|
+
// the first directory containing .agents/skills or .git; else cwd.
|
|
13
|
+
//
|
|
14
|
+
// Sources, in order:
|
|
15
|
+
// (a) LOCAL — the vidfarm repo's own .agents/skills/<name>, found by walking
|
|
16
|
+
// up from this module's directory (same walk-up pattern as
|
|
17
|
+
// locateBundledSkill in src/cli.ts).
|
|
18
|
+
// (b) REMOTE — the vidfarm skill-pack routes on
|
|
19
|
+
// `${--host || VIDFARM_SKILLS_HOST || VIDFARM_HOST || https://vidfarm.cc}`:
|
|
20
|
+
// GET /skill-pack/index.json → { skills: [{ name, description }] }
|
|
21
|
+
// GET /skill-pack/:name/manifest.json → { name, files: [{ path, size, sha256 }] }
|
|
22
|
+
// GET /skill-pack/:name/files/<relpath> → raw bytes
|
|
23
|
+
// Every downloaded file's sha256 is verified against the manifest.
|
|
24
|
+
import { createHash } from "node:crypto";
|
|
25
|
+
import { cpSync, existsSync, lstatSync, mkdirSync, readdirSync, readFileSync, rmSync, statSync, symlinkSync, unlinkSync, writeFileSync } from "node:fs";
|
|
26
|
+
import path from "node:path";
|
|
27
|
+
import { fileURLToPath } from "node:url";
|
|
28
|
+
import { parseArgs } from "node:util";
|
|
29
|
+
const DEFAULT_SKILLS_HOST = "https://vidfarm.cc";
|
|
30
|
+
const GREEN = "\x1b[32m";
|
|
31
|
+
const RED = "\x1b[31m";
|
|
32
|
+
const DIM = "\x1b[2m";
|
|
33
|
+
const BOLD = "\x1b[1m";
|
|
34
|
+
const RESET = "\x1b[0m";
|
|
35
|
+
// ── Root + source resolution ────────────────────────────────────────────────
|
|
36
|
+
/** --dir wins; else walk UP from cwd to the first dir with .agents/skills or .git; else cwd. */
|
|
37
|
+
export function resolveSkillsRoot(dirFlag) {
|
|
38
|
+
if (dirFlag)
|
|
39
|
+
return path.resolve(process.cwd(), dirFlag);
|
|
40
|
+
let dir = process.cwd();
|
|
41
|
+
for (let i = 0; i < 24; i += 1) {
|
|
42
|
+
if (existsSync(path.join(dir, ".agents", "skills")) || existsSync(path.join(dir, ".git"))) {
|
|
43
|
+
return dir;
|
|
44
|
+
}
|
|
45
|
+
const parent = path.dirname(dir);
|
|
46
|
+
if (parent === dir)
|
|
47
|
+
break;
|
|
48
|
+
dir = parent;
|
|
49
|
+
}
|
|
50
|
+
return process.cwd();
|
|
51
|
+
}
|
|
52
|
+
/** Walk up from this module (mirrors locateBundledSkill in src/cli.ts) to the
|
|
53
|
+
* vidfarm repo/package root that carries its own .agents/skills. */
|
|
54
|
+
function locateLocalSkillsSource() {
|
|
55
|
+
let dir = path.dirname(fileURLToPath(import.meta.url));
|
|
56
|
+
for (let i = 0; i < 6; i += 1) {
|
|
57
|
+
const candidate = path.join(dir, ".agents", "skills");
|
|
58
|
+
if (existsSync(candidate))
|
|
59
|
+
return candidate;
|
|
60
|
+
const parent = path.dirname(dir);
|
|
61
|
+
if (parent === dir)
|
|
62
|
+
break;
|
|
63
|
+
dir = parent;
|
|
64
|
+
}
|
|
65
|
+
return null;
|
|
66
|
+
}
|
|
67
|
+
function resolveSkillsHost(hostFlag) {
|
|
68
|
+
const raw = hostFlag
|
|
69
|
+
|| process.env.VIDFARM_SKILLS_HOST
|
|
70
|
+
|| process.env.VIDFARM_HOST
|
|
71
|
+
|| DEFAULT_SKILLS_HOST;
|
|
72
|
+
return raw.replace(/\/+$/, "");
|
|
73
|
+
}
|
|
74
|
+
// ── Hashing ─────────────────────────────────────────────────────────────────
|
|
75
|
+
/**
|
|
76
|
+
* Lock-file hash algorithm (locally reproducible):
|
|
77
|
+
* sha256 over the concatenation of, for EACH file sorted by its posix-style
|
|
78
|
+
* relative path: `${relpath}\0${bytes}\0` — i.e. the UTF-8 relpath, a NUL
|
|
79
|
+
* byte, the raw file bytes, and a trailing NUL byte, files in sorted order.
|
|
80
|
+
*/
|
|
81
|
+
export function computeSkillHash(files) {
|
|
82
|
+
const hash = createHash("sha256");
|
|
83
|
+
const sorted = [...files].sort((a, b) => (a.path < b.path ? -1 : a.path > b.path ? 1 : 0));
|
|
84
|
+
for (const file of sorted) {
|
|
85
|
+
hash.update(Buffer.from(file.path, "utf8"));
|
|
86
|
+
hash.update(Buffer.from([0]));
|
|
87
|
+
hash.update(file.bytes);
|
|
88
|
+
hash.update(Buffer.from([0]));
|
|
89
|
+
}
|
|
90
|
+
return hash.digest("hex");
|
|
91
|
+
}
|
|
92
|
+
function sha256Hex(bytes) {
|
|
93
|
+
return createHash("sha256").update(bytes).digest("hex");
|
|
94
|
+
}
|
|
95
|
+
function readSkillDirFiles(skillDir) {
|
|
96
|
+
const files = [];
|
|
97
|
+
const walk = (dir, prefix) => {
|
|
98
|
+
for (const entry of readdirSync(dir, { withFileTypes: true })) {
|
|
99
|
+
const abs = path.join(dir, entry.name);
|
|
100
|
+
const rel = prefix ? `${prefix}/${entry.name}` : entry.name;
|
|
101
|
+
if (entry.isDirectory()) {
|
|
102
|
+
walk(abs, rel);
|
|
103
|
+
}
|
|
104
|
+
else if (entry.isFile() || entry.isSymbolicLink()) {
|
|
105
|
+
try {
|
|
106
|
+
files.push({ path: rel, bytes: readFileSync(abs) });
|
|
107
|
+
}
|
|
108
|
+
catch {
|
|
109
|
+
// unreadable entry — skip rather than abort the whole install
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
};
|
|
114
|
+
walk(skillDir, "");
|
|
115
|
+
return files;
|
|
116
|
+
}
|
|
117
|
+
async function fetchSkillPackIndex(host) {
|
|
118
|
+
const res = await fetch(`${host}/skill-pack/index.json`, { headers: { accept: "application/json" } });
|
|
119
|
+
if (!res.ok)
|
|
120
|
+
throw new Error(`GET ${host}/skill-pack/index.json → ${res.status}`);
|
|
121
|
+
const json = await res.json().catch(() => null);
|
|
122
|
+
const skills = Array.isArray(json?.skills) ? json.skills : [];
|
|
123
|
+
return skills
|
|
124
|
+
.filter((entry) => entry && typeof entry.name === "string")
|
|
125
|
+
.map((entry) => ({ name: entry.name, description: typeof entry.description === "string" ? entry.description : undefined }));
|
|
126
|
+
}
|
|
127
|
+
/** Manifest path → posix-relative path, refusing traversal segments. */
|
|
128
|
+
function normalizeManifestPath(name, rawPath) {
|
|
129
|
+
const rel = rawPath.replace(/\\/g, "/").replace(/^\/+/, "");
|
|
130
|
+
if (rel.split("/").some((segment) => segment === "..")) {
|
|
131
|
+
throw new Error(`skill-pack manifest for "${name}" contains an unsafe path: ${rawPath}`);
|
|
132
|
+
}
|
|
133
|
+
return rel;
|
|
134
|
+
}
|
|
135
|
+
async function fetchSkillManifestEntries(host, name) {
|
|
136
|
+
const manifestUrl = `${host}/skill-pack/${encodeURIComponent(name)}/manifest.json`;
|
|
137
|
+
const manifestRes = await fetch(manifestUrl, { headers: { accept: "application/json" } });
|
|
138
|
+
if (!manifestRes.ok)
|
|
139
|
+
throw new Error(`GET ${manifestUrl} → ${manifestRes.status}`);
|
|
140
|
+
const manifest = await manifestRes.json().catch(() => null);
|
|
141
|
+
const entries = Array.isArray(manifest?.files)
|
|
142
|
+
? manifest.files.filter((f) => f && typeof f.path === "string")
|
|
143
|
+
: [];
|
|
144
|
+
if (entries.length === 0)
|
|
145
|
+
throw new Error(`skill-pack manifest for "${name}" lists no files.`);
|
|
146
|
+
return entries;
|
|
147
|
+
}
|
|
148
|
+
/** True when the manifest's per-file {path → sha256} set exactly matches the
|
|
149
|
+
* locally installed pack — every file present, hashes equal, no extras. Any
|
|
150
|
+
* manifest entry without a sha256 means we cannot verify → false (download). */
|
|
151
|
+
function localPackMatchesManifest(root, name, entries) {
|
|
152
|
+
const skillDir = path.join(root, ".agents", "skills", name);
|
|
153
|
+
if (!existsSync(skillDir))
|
|
154
|
+
return false;
|
|
155
|
+
let local;
|
|
156
|
+
try {
|
|
157
|
+
local = readSkillDirFiles(skillDir);
|
|
158
|
+
}
|
|
159
|
+
catch {
|
|
160
|
+
return false;
|
|
161
|
+
}
|
|
162
|
+
if (local.length !== entries.length)
|
|
163
|
+
return false;
|
|
164
|
+
const localHashes = new Map(local.map((file) => [file.path, sha256Hex(file.bytes)]));
|
|
165
|
+
for (const entry of entries) {
|
|
166
|
+
const expected = entry.sha256?.trim().toLowerCase();
|
|
167
|
+
if (!expected)
|
|
168
|
+
return false;
|
|
169
|
+
const rel = normalizeManifestPath(name, entry.path);
|
|
170
|
+
if (localHashes.get(rel) !== expected)
|
|
171
|
+
return false;
|
|
172
|
+
}
|
|
173
|
+
return true;
|
|
174
|
+
}
|
|
175
|
+
// Bounded download parallelism — plenty for small skill files without
|
|
176
|
+
// hammering the host or tripping per-origin connection limits.
|
|
177
|
+
const REMOTE_FETCH_BATCH = 8;
|
|
178
|
+
async function fetchRemoteSkillFiles(host, name) {
|
|
179
|
+
const entries = await fetchSkillManifestEntries(host, name);
|
|
180
|
+
// Validate every path up front (before any network round-trip)…
|
|
181
|
+
const rels = entries.map((entry) => normalizeManifestPath(name, entry.path));
|
|
182
|
+
// …then download in bounded batches, preserving manifest order and applying
|
|
183
|
+
// the same per-file sha256 verification as the sequential version.
|
|
184
|
+
const files = new Array(entries.length);
|
|
185
|
+
for (let start = 0; start < entries.length; start += REMOTE_FETCH_BATCH) {
|
|
186
|
+
const batch = entries.slice(start, start + REMOTE_FETCH_BATCH);
|
|
187
|
+
await Promise.all(batch.map(async (entry, offset) => {
|
|
188
|
+
const index = start + offset;
|
|
189
|
+
const rel = rels[index];
|
|
190
|
+
const fileUrl = `${host}/skill-pack/${encodeURIComponent(name)}/files/${rel.split("/").map(encodeURIComponent).join("/")}`;
|
|
191
|
+
const res = await fetch(fileUrl);
|
|
192
|
+
if (!res.ok)
|
|
193
|
+
throw new Error(`GET ${fileUrl} → ${res.status}`);
|
|
194
|
+
const bytes = Buffer.from(await res.arrayBuffer());
|
|
195
|
+
if (typeof entry.sha256 === "string" && entry.sha256.trim()) {
|
|
196
|
+
const actual = sha256Hex(bytes);
|
|
197
|
+
if (actual !== entry.sha256.trim().toLowerCase()) {
|
|
198
|
+
throw new Error(`sha256 mismatch for ${name}/${rel}: manifest ${entry.sha256}, downloaded ${actual}.`);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
files[index] = { path: rel, bytes };
|
|
202
|
+
}));
|
|
203
|
+
}
|
|
204
|
+
return files;
|
|
205
|
+
}
|
|
206
|
+
// ── Lock file ───────────────────────────────────────────────────────────────
|
|
207
|
+
function readLockFile(root) {
|
|
208
|
+
const lockPath = path.join(root, "skills-lock.json");
|
|
209
|
+
if (!existsSync(lockPath))
|
|
210
|
+
return { version: 1, skills: {} };
|
|
211
|
+
try {
|
|
212
|
+
const parsed = JSON.parse(readFileSync(lockPath, "utf8"));
|
|
213
|
+
if (!parsed || typeof parsed !== "object")
|
|
214
|
+
return { version: 1, skills: {} };
|
|
215
|
+
if (!parsed.skills || typeof parsed.skills !== "object")
|
|
216
|
+
parsed.skills = {};
|
|
217
|
+
if (typeof parsed.version !== "number")
|
|
218
|
+
parsed.version = 1;
|
|
219
|
+
return parsed;
|
|
220
|
+
}
|
|
221
|
+
catch {
|
|
222
|
+
throw new Error(`${lockPath} is not valid JSON — fix or remove it before installing skills.`);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
// MERGE, never clobber: entries owned by other tools (sourceType !== "vidfarm")
|
|
226
|
+
// ride through untouched.
|
|
227
|
+
function writeLockFile(root, lock) {
|
|
228
|
+
const lockPath = path.join(root, "skills-lock.json");
|
|
229
|
+
const sortedSkills = {};
|
|
230
|
+
for (const name of Object.keys(lock.skills).sort())
|
|
231
|
+
sortedSkills[name] = lock.skills[name];
|
|
232
|
+
writeFileSync(lockPath, `${JSON.stringify({ ...lock, skills: sortedSkills }, null, 2)}\n`, "utf8");
|
|
233
|
+
return lockPath;
|
|
234
|
+
}
|
|
235
|
+
// ── Install machinery ───────────────────────────────────────────────────────
|
|
236
|
+
function writeSkillFiles(root, name, files) {
|
|
237
|
+
const target = path.join(root, ".agents", "skills", name);
|
|
238
|
+
rmSync(target, { recursive: true, force: true });
|
|
239
|
+
for (const file of files) {
|
|
240
|
+
const dest = path.join(target, ...file.path.split("/"));
|
|
241
|
+
const resolved = path.resolve(dest);
|
|
242
|
+
if (resolved !== path.resolve(target) && !resolved.startsWith(`${path.resolve(target)}${path.sep}`)) {
|
|
243
|
+
throw new Error(`Refusing to write outside the skill dir: ${file.path}`);
|
|
244
|
+
}
|
|
245
|
+
mkdirSync(path.dirname(dest), { recursive: true });
|
|
246
|
+
writeFileSync(dest, file.bytes);
|
|
247
|
+
}
|
|
248
|
+
return target;
|
|
249
|
+
}
|
|
250
|
+
/** RELATIVE symlink <root>/.claude/skills/<name> → ../../.agents/skills/<name>;
|
|
251
|
+
* a real copy where symlink creation fails (e.g. Windows without dev mode). */
|
|
252
|
+
function linkClaudeSkill(root, name) {
|
|
253
|
+
const claudeDir = path.join(root, ".claude", "skills");
|
|
254
|
+
mkdirSync(claudeDir, { recursive: true });
|
|
255
|
+
const linkPath = path.join(claudeDir, name);
|
|
256
|
+
const relativeTarget = path.join("..", "..", ".agents", "skills", name);
|
|
257
|
+
let existing = null;
|
|
258
|
+
try {
|
|
259
|
+
existing = lstatSync(linkPath);
|
|
260
|
+
}
|
|
261
|
+
catch {
|
|
262
|
+
// nothing there yet
|
|
263
|
+
}
|
|
264
|
+
if (existing) {
|
|
265
|
+
// unlinkSync handles symlinks (even ones pointing at directories) and
|
|
266
|
+
// plain files; only a REAL directory (previous copy-mode install) needs
|
|
267
|
+
// the recursive remove.
|
|
268
|
+
if (existing.isDirectory())
|
|
269
|
+
rmSync(linkPath, { recursive: true, force: true });
|
|
270
|
+
else
|
|
271
|
+
unlinkSync(linkPath);
|
|
272
|
+
}
|
|
273
|
+
try {
|
|
274
|
+
symlinkSync(relativeTarget, linkPath, "junction");
|
|
275
|
+
return { mode: "symlink", path: linkPath };
|
|
276
|
+
}
|
|
277
|
+
catch {
|
|
278
|
+
cpSync(path.join(root, ".agents", "skills", name), linkPath, { recursive: true });
|
|
279
|
+
return { mode: "copy", path: linkPath };
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
async function installSkill(root, name, host) {
|
|
283
|
+
// (a) LOCAL: the vidfarm repo's own bundled copy wins when reachable.
|
|
284
|
+
const localSource = locateLocalSkillsSource();
|
|
285
|
+
let files = null;
|
|
286
|
+
let source = "vidfarm-repo";
|
|
287
|
+
if (localSource && existsSync(path.join(localSource, name))) {
|
|
288
|
+
files = readSkillDirFiles(path.join(localSource, name));
|
|
289
|
+
if (files.length === 0)
|
|
290
|
+
files = null;
|
|
291
|
+
}
|
|
292
|
+
// (b) REMOTE: the vidfarm skill-pack routes.
|
|
293
|
+
if (!files) {
|
|
294
|
+
files = await fetchRemoteSkillFiles(host, name);
|
|
295
|
+
source = host;
|
|
296
|
+
}
|
|
297
|
+
writeSkillFiles(root, name, files);
|
|
298
|
+
const link = linkClaudeSkill(root, name);
|
|
299
|
+
const hash = computeSkillHash(files);
|
|
300
|
+
const lock = readLockFile(root);
|
|
301
|
+
lock.skills[name] = {
|
|
302
|
+
...(lock.skills[name] ?? {}),
|
|
303
|
+
source,
|
|
304
|
+
sourceType: "vidfarm",
|
|
305
|
+
skillPath: `.agents/skills/${name}`,
|
|
306
|
+
computedHash: hash
|
|
307
|
+
};
|
|
308
|
+
writeLockFile(root, lock);
|
|
309
|
+
return { name, source, files: files.length, hash, linkMode: link.mode };
|
|
310
|
+
}
|
|
311
|
+
// ── Subcommands ─────────────────────────────────────────────────────────────
|
|
312
|
+
async function runList(root, host, json) {
|
|
313
|
+
const lock = readLockFile(root);
|
|
314
|
+
const skillsDir = path.join(root, ".agents", "skills");
|
|
315
|
+
const onDisk = existsSync(skillsDir)
|
|
316
|
+
? readdirSync(skillsDir).filter((name) => {
|
|
317
|
+
try {
|
|
318
|
+
return statSync(path.join(skillsDir, name)).isDirectory();
|
|
319
|
+
}
|
|
320
|
+
catch {
|
|
321
|
+
return false;
|
|
322
|
+
}
|
|
323
|
+
})
|
|
324
|
+
: [];
|
|
325
|
+
const installedNames = [...new Set([...Object.keys(lock.skills), ...onDisk])].sort();
|
|
326
|
+
const installed = installedNames.map((name) => ({
|
|
327
|
+
name,
|
|
328
|
+
on_disk: onDisk.includes(name),
|
|
329
|
+
source: lock.skills[name]?.source ?? null,
|
|
330
|
+
source_type: lock.skills[name]?.sourceType ?? null
|
|
331
|
+
}));
|
|
332
|
+
let available = [];
|
|
333
|
+
let availableSource = host;
|
|
334
|
+
try {
|
|
335
|
+
available = await fetchSkillPackIndex(host);
|
|
336
|
+
}
|
|
337
|
+
catch {
|
|
338
|
+
const localSource = locateLocalSkillsSource();
|
|
339
|
+
if (localSource) {
|
|
340
|
+
availableSource = "vidfarm-repo";
|
|
341
|
+
available = readdirSync(localSource)
|
|
342
|
+
.filter((name) => existsSync(path.join(localSource, name, "SKILL.md")))
|
|
343
|
+
.map((name) => ({ name }));
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
if (json) {
|
|
347
|
+
process.stdout.write(`${JSON.stringify({ ok: true, root, installed, available, available_source: availableSource }, null, 2)}\n`);
|
|
348
|
+
return;
|
|
349
|
+
}
|
|
350
|
+
console.log(`${BOLD}Installed${RESET} ${DIM}(${root}/.agents/skills + skills-lock.json)${RESET}`);
|
|
351
|
+
if (installed.length === 0)
|
|
352
|
+
console.log(` ${DIM}(none)${RESET}`);
|
|
353
|
+
for (const entry of installed) {
|
|
354
|
+
const flags = [
|
|
355
|
+
entry.on_disk ? null : "missing on disk",
|
|
356
|
+
entry.source_type && entry.source_type !== "vidfarm" ? entry.source_type : null
|
|
357
|
+
].filter(Boolean).join(", ");
|
|
358
|
+
console.log(` ${entry.name}${entry.source ? ` ${DIM}${entry.source}${flags ? ` [${flags}]` : ""}${RESET}` : flags ? ` ${DIM}[${flags}]${RESET}` : ""}`);
|
|
359
|
+
}
|
|
360
|
+
console.log("");
|
|
361
|
+
console.log(`${BOLD}Available${RESET} ${DIM}(${availableSource})${RESET}`);
|
|
362
|
+
const installedSet = new Set(installedNames);
|
|
363
|
+
for (const entry of available) {
|
|
364
|
+
const mark = installedSet.has(entry.name) ? `${GREEN}✓${RESET} ` : " ";
|
|
365
|
+
console.log(`${mark}${entry.name}${entry.description ? ` ${DIM}${entry.description}${RESET}` : ""}`);
|
|
366
|
+
}
|
|
367
|
+
if (available.length === 0)
|
|
368
|
+
console.log(` ${DIM}(index unavailable)${RESET}`);
|
|
369
|
+
console.log("");
|
|
370
|
+
console.log(`${DIM}Install with: vidfarm skills add <names…>${RESET}`);
|
|
371
|
+
}
|
|
372
|
+
async function runAdd(root, host, names, json) {
|
|
373
|
+
if (names.length === 0)
|
|
374
|
+
throw new Error("skills add requires one or more skill names: `vidfarm skills add hyperframes motion-graphics`.");
|
|
375
|
+
const installed = [];
|
|
376
|
+
for (const name of names) {
|
|
377
|
+
installed.push(await installSkill(root, name, host));
|
|
378
|
+
}
|
|
379
|
+
if (json) {
|
|
380
|
+
process.stdout.write(`${JSON.stringify({ ok: true, root, installed }, null, 2)}\n`);
|
|
381
|
+
return;
|
|
382
|
+
}
|
|
383
|
+
for (const entry of installed) {
|
|
384
|
+
console.log(`${GREEN}Installed ${entry.name}${RESET} ${DIM}(${entry.files} files from ${entry.source}; .claude/skills/${entry.name} ${entry.linkMode})${RESET}`);
|
|
385
|
+
}
|
|
386
|
+
console.log(`${DIM}Lock updated: ${path.join(root, "skills-lock.json")}${RESET}`);
|
|
387
|
+
}
|
|
388
|
+
async function runUpdate(root, host, json) {
|
|
389
|
+
const lock = readLockFile(root);
|
|
390
|
+
const vidfarmSkills = Object.entries(lock.skills).filter(([, entry]) => entry.sourceType === "vidfarm");
|
|
391
|
+
if (vidfarmSkills.length === 0) {
|
|
392
|
+
if (json)
|
|
393
|
+
process.stdout.write(`${JSON.stringify({ ok: true, root, updated: [], note: "no vidfarm-sourced skills in the lock file" }, null, 2)}\n`);
|
|
394
|
+
else
|
|
395
|
+
console.log(`${DIM}No vidfarm-sourced skills in ${path.join(root, "skills-lock.json")} — nothing to update.${RESET}`);
|
|
396
|
+
return;
|
|
397
|
+
}
|
|
398
|
+
const results = [];
|
|
399
|
+
// installSkill prefers the local repo copy whenever one is reachable — the
|
|
400
|
+
// remote short-circuit below only applies when the pack would actually be
|
|
401
|
+
// downloaded (no bundled copy of that skill next to this module).
|
|
402
|
+
const localSource = locateLocalSkillsSource();
|
|
403
|
+
for (const [name, entry] of vidfarmSkills) {
|
|
404
|
+
const previousHash = entry.computedHash;
|
|
405
|
+
try {
|
|
406
|
+
// Re-fetch honoring the entry's original source: repo-sourced entries
|
|
407
|
+
// refresh from the repo copy; host-sourced entries from their host.
|
|
408
|
+
const entryHost = entry.source && entry.source !== "vidfarm-repo" ? entry.source.replace(/\/+$/, "") : host;
|
|
409
|
+
const usesLocalSource = Boolean(localSource && existsSync(path.join(localSource, name)));
|
|
410
|
+
if (!usesLocalSource) {
|
|
411
|
+
// Cheap short-circuit: fetch ONLY the manifest and diff its per-file
|
|
412
|
+
// sha256 set against the installed files — skip every byte download
|
|
413
|
+
// when nothing changed. (The lock's computedHash covers file BYTES,
|
|
414
|
+
// so hashing the local files against the manifest is the
|
|
415
|
+
// lock-compatible comparison.)
|
|
416
|
+
try {
|
|
417
|
+
const manifestEntries = await fetchSkillManifestEntries(entryHost, name);
|
|
418
|
+
if (localPackMatchesManifest(root, name, manifestEntries)) {
|
|
419
|
+
linkClaudeSkill(root, name); // repair a missing .claude link; no downloads
|
|
420
|
+
results.push({ name, status: "unchanged" });
|
|
421
|
+
continue;
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
catch {
|
|
425
|
+
// manifest probe failed — fall through to the full install, whose
|
|
426
|
+
// error reporting is authoritative.
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
const result = await installSkill(root, name, entryHost);
|
|
430
|
+
results.push({ name, status: result.hash === previousHash ? "unchanged" : "changed" });
|
|
431
|
+
}
|
|
432
|
+
catch (error) {
|
|
433
|
+
results.push({ name, status: "failed", detail: error instanceof Error ? error.message : String(error) });
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
if (json) {
|
|
437
|
+
process.stdout.write(`${JSON.stringify({ ok: results.every((r) => r.status !== "failed"), root, updated: results }, null, 2)}\n`);
|
|
438
|
+
}
|
|
439
|
+
else {
|
|
440
|
+
for (const result of results) {
|
|
441
|
+
const color = result.status === "changed" ? GREEN : result.status === "failed" ? RED : DIM;
|
|
442
|
+
console.log(`${color}${result.status.padEnd(9)}${RESET} ${result.name}${result.detail ? ` ${DIM}${result.detail}${RESET}` : ""}`);
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
if (results.some((r) => r.status === "failed"))
|
|
446
|
+
process.exitCode = 1;
|
|
447
|
+
}
|
|
448
|
+
export async function runSkillsCommand(argv) {
|
|
449
|
+
const parsed = parseArgs({
|
|
450
|
+
args: argv,
|
|
451
|
+
allowPositionals: true,
|
|
452
|
+
options: {
|
|
453
|
+
dir: { type: "string" },
|
|
454
|
+
host: { type: "string" },
|
|
455
|
+
json: { type: "boolean", default: false }
|
|
456
|
+
}
|
|
457
|
+
});
|
|
458
|
+
const sub = parsed.positionals[0] ?? "list";
|
|
459
|
+
const root = resolveSkillsRoot(parsed.values.dir);
|
|
460
|
+
const host = resolveSkillsHost(parsed.values.host);
|
|
461
|
+
const json = Boolean(parsed.values.json);
|
|
462
|
+
switch (sub) {
|
|
463
|
+
case "list":
|
|
464
|
+
await runList(root, host, json);
|
|
465
|
+
return;
|
|
466
|
+
case "add":
|
|
467
|
+
await runAdd(root, host, parsed.positionals.slice(1), json);
|
|
468
|
+
return;
|
|
469
|
+
case "update":
|
|
470
|
+
await runUpdate(root, host, json);
|
|
471
|
+
return;
|
|
472
|
+
default:
|
|
473
|
+
throw new Error(`Unknown skills subcommand "${sub}". Use: vidfarm skills <list|add <names…>|update> [--dir <root>] [--host <url>]`);
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
//# sourceMappingURL=skills.js.map
|