@kenkaiiii/gg-editor 0.7.0 → 0.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +64 -1
- package/dist/cli.js.map +1 -1
- package/dist/core/audio-mix.d.ts.map +1 -1
- package/dist/core/audio-mix.js +8 -1
- package/dist/core/audio-mix.js.map +1 -1
- package/dist/core/audio-mix.test.js +1 -1
- package/dist/core/audio-mix.test.js.map +1 -1
- package/dist/core/auth/api-keys.d.ts +1 -1
- package/dist/core/auth/api-keys.d.ts.map +1 -1
- package/dist/core/auth/api-keys.js +2 -1
- package/dist/core/auth/api-keys.js.map +1 -1
- package/dist/core/auth/login.d.ts.map +1 -1
- package/dist/core/auth/login.js.map +1 -1
- package/dist/core/beats.d.ts +59 -0
- package/dist/core/beats.d.ts.map +1 -0
- package/dist/core/beats.js +122 -0
- package/dist/core/beats.js.map +1 -0
- package/dist/core/beats.test.d.ts +2 -0
- package/dist/core/beats.test.d.ts.map +1 -0
- package/dist/core/beats.test.js +86 -0
- package/dist/core/beats.test.js.map +1 -0
- package/dist/core/brand-kit.d.ts +80 -0
- package/dist/core/brand-kit.d.ts.map +1 -0
- package/dist/core/brand-kit.js +96 -0
- package/dist/core/brand-kit.js.map +1 -0
- package/dist/core/brand-kit.test.d.ts +2 -0
- package/dist/core/brand-kit.test.d.ts.map +1 -0
- package/dist/core/brand-kit.test.js +76 -0
- package/dist/core/brand-kit.test.js.map +1 -0
- package/dist/core/bundled-sfx.d.ts +64 -0
- package/dist/core/bundled-sfx.d.ts.map +1 -0
- package/dist/core/bundled-sfx.js +218 -0
- package/dist/core/bundled-sfx.js.map +1 -0
- package/dist/core/bundled-sfx.test.d.ts +2 -0
- package/dist/core/bundled-sfx.test.d.ts.map +1 -0
- package/dist/core/bundled-sfx.test.js +81 -0
- package/dist/core/bundled-sfx.test.js.map +1 -0
- package/dist/core/child-abort.d.ts +57 -0
- package/dist/core/child-abort.d.ts.map +1 -0
- package/dist/core/child-abort.js +95 -0
- package/dist/core/child-abort.js.map +1 -0
- package/dist/core/child-abort.test.d.ts +2 -0
- package/dist/core/child-abort.test.d.ts.map +1 -0
- package/dist/core/child-abort.test.js +88 -0
- package/dist/core/child-abort.test.js.map +1 -0
- package/dist/core/clip-scoring.d.ts +44 -0
- package/dist/core/clip-scoring.d.ts.map +1 -0
- package/dist/core/clip-scoring.js +165 -0
- package/dist/core/clip-scoring.js.map +1 -0
- package/dist/core/clip-scoring.test.d.ts +2 -0
- package/dist/core/clip-scoring.test.d.ts.map +1 -0
- package/dist/core/clip-scoring.test.js +113 -0
- package/dist/core/clip-scoring.test.js.map +1 -0
- package/dist/core/emoji-captions.d.ts +45 -0
- package/dist/core/emoji-captions.d.ts.map +1 -0
- package/dist/core/emoji-captions.js +121 -0
- package/dist/core/emoji-captions.js.map +1 -0
- package/dist/core/face-reframe.d.ts +91 -0
- package/dist/core/face-reframe.d.ts.map +1 -0
- package/dist/core/face-reframe.js +141 -0
- package/dist/core/face-reframe.js.map +1 -0
- package/dist/core/face-reframe.test.d.ts +2 -0
- package/dist/core/face-reframe.test.d.ts.map +1 -0
- package/dist/core/face-reframe.test.js +171 -0
- package/dist/core/face-reframe.test.js.map +1 -0
- package/dist/core/filler-words.d.ts +57 -9
- package/dist/core/filler-words.d.ts.map +1 -1
- package/dist/core/filler-words.js +61 -9
- package/dist/core/filler-words.js.map +1 -1
- package/dist/core/filler-words.test.js +91 -17
- package/dist/core/filler-words.test.js.map +1 -1
- package/dist/core/hook-rewrite.d.ts +48 -0
- package/dist/core/hook-rewrite.d.ts.map +1 -0
- package/dist/core/hook-rewrite.js +151 -0
- package/dist/core/hook-rewrite.js.map +1 -0
- package/dist/core/hook-rewrite.test.d.ts +2 -0
- package/dist/core/hook-rewrite.test.d.ts.map +1 -0
- package/dist/core/hook-rewrite.test.js +58 -0
- package/dist/core/hook-rewrite.test.js.map +1 -0
- package/dist/core/hosts/lazy.d.ts.map +1 -1
- package/dist/core/hosts/lazy.js +2 -0
- package/dist/core/hosts/lazy.js.map +1 -1
- package/dist/core/hosts/premiere/adapter.d.ts +1 -0
- package/dist/core/hosts/premiere/adapter.d.ts.map +1 -1
- package/dist/core/hosts/premiere/adapter.js.map +1 -1
- package/dist/core/hosts/premiere/bridge-source.d.ts.map +1 -1
- package/dist/core/hosts/premiere/bridge-source.js +6 -3
- package/dist/core/hosts/premiere/bridge-source.js.map +1 -1
- package/dist/core/hosts/resolve/adapter.d.ts +1 -0
- package/dist/core/hosts/resolve/adapter.d.ts.map +1 -1
- package/dist/core/hosts/resolve/adapter.js.map +1 -1
- package/dist/core/hosts/resolve/bridge-source.d.ts.map +1 -1
- package/dist/core/hosts/resolve/bridge-source.js +31 -4
- package/dist/core/hosts/resolve/bridge-source.js.map +1 -1
- package/dist/core/hosts/resolve/bridge.d.ts +2 -19
- package/dist/core/hosts/resolve/bridge.d.ts.map +1 -1
- package/dist/core/hosts/resolve/bridge.js +70 -41
- package/dist/core/hosts/resolve/bridge.js.map +1 -1
- package/dist/core/hosts/resolve/bridge.test.js +130 -0
- package/dist/core/hosts/resolve/bridge.test.js.map +1 -1
- package/dist/core/hosts/types.d.ts +6 -0
- package/dist/core/hosts/types.d.ts.map +1 -1
- package/dist/core/hosts/types.js.map +1 -1
- package/dist/core/logger.d.ts +32 -0
- package/dist/core/logger.d.ts.map +1 -0
- package/dist/core/logger.js +188 -0
- package/dist/core/logger.js.map +1 -0
- package/dist/core/loop-match.d.ts +57 -0
- package/dist/core/loop-match.d.ts.map +1 -0
- package/dist/core/loop-match.js +91 -0
- package/dist/core/loop-match.js.map +1 -0
- package/dist/core/media/ffmpeg.d.ts.map +1 -1
- package/dist/core/media/ffmpeg.js +14 -3
- package/dist/core/media/ffmpeg.js.map +1 -1
- package/dist/core/multi-format.d.ts +67 -0
- package/dist/core/multi-format.d.ts.map +1 -0
- package/dist/core/multi-format.js +127 -0
- package/dist/core/multi-format.js.map +1 -0
- package/dist/core/multi-format.test.d.ts +2 -0
- package/dist/core/multi-format.test.d.ts.map +1 -0
- package/dist/core/multi-format.test.js +151 -0
- package/dist/core/multi-format.test.js.map +1 -0
- package/dist/core/python/beats.py +61 -0
- package/dist/core/python/face_reframe.py +163 -0
- package/dist/core/python/sidecar-path.d.ts +13 -0
- package/dist/core/python/sidecar-path.d.ts.map +1 -0
- package/dist/core/python/sidecar-path.js +24 -0
- package/dist/core/python/sidecar-path.js.map +1 -0
- package/dist/core/python.d.ts +57 -0
- package/dist/core/python.d.ts.map +1 -0
- package/dist/core/python.js +107 -0
- package/dist/core/python.js.map +1 -0
- package/dist/core/python.test.d.ts +2 -0
- package/dist/core/python.test.d.ts.map +1 -0
- package/dist/core/python.test.js +129 -0
- package/dist/core/python.test.js.map +1 -0
- package/dist/core/retention-structure.d.ts +81 -0
- package/dist/core/retention-structure.d.ts.map +1 -0
- package/dist/core/retention-structure.js +206 -0
- package/dist/core/retention-structure.js.map +1 -0
- package/dist/core/retention-structure.test.d.ts +2 -0
- package/dist/core/retention-structure.test.d.ts.map +1 -0
- package/dist/core/retention-structure.test.js +88 -0
- package/dist/core/retention-structure.test.js.map +1 -0
- package/dist/core/review.d.ts +17 -0
- package/dist/core/review.d.ts.map +1 -1
- package/dist/core/review.js +20 -24
- package/dist/core/review.js.map +1 -1
- package/dist/core/safe-paths.d.ts +11 -0
- package/dist/core/safe-paths.d.ts.map +1 -1
- package/dist/core/safe-paths.js +26 -10
- package/dist/core/safe-paths.js.map +1 -1
- package/dist/core/safe-paths.test.js +16 -0
- package/dist/core/safe-paths.test.js.map +1 -1
- package/dist/core/skills-loader.d.ts +48 -2
- package/dist/core/skills-loader.d.ts.map +1 -1
- package/dist/core/skills-loader.js +97 -19
- package/dist/core/skills-loader.js.map +1 -1
- package/dist/core/skills-loader.test.js +63 -1
- package/dist/core/skills-loader.test.js.map +1 -1
- package/dist/core/srt.d.ts +42 -7
- package/dist/core/srt.d.ts.map +1 -1
- package/dist/core/srt.js +101 -32
- package/dist/core/srt.js.map +1 -1
- package/dist/core/srt.test.js +54 -1
- package/dist/core/srt.test.js.map +1 -1
- package/dist/core/thumbnail-compose.d.ts +58 -0
- package/dist/core/thumbnail-compose.d.ts.map +1 -0
- package/dist/core/thumbnail-compose.js +101 -0
- package/dist/core/thumbnail-compose.js.map +1 -0
- package/dist/core/thumbnail-promise.d.ts +46 -0
- package/dist/core/thumbnail-promise.d.ts.map +1 -0
- package/dist/core/thumbnail-promise.js +133 -0
- package/dist/core/thumbnail-promise.js.map +1 -0
- package/dist/core/thumbnail-promise.test.d.ts +2 -0
- package/dist/core/thumbnail-promise.test.d.ts.map +1 -0
- package/dist/core/thumbnail-promise.test.js +52 -0
- package/dist/core/thumbnail-promise.test.js.map +1 -0
- package/dist/core/viral-moments.d.ts +70 -0
- package/dist/core/viral-moments.d.ts.map +1 -0
- package/dist/core/viral-moments.js +192 -0
- package/dist/core/viral-moments.js.map +1 -0
- package/dist/core/viral-moments.test.d.ts +2 -0
- package/dist/core/viral-moments.test.d.ts.map +1 -0
- package/dist/core/viral-moments.test.js +153 -0
- package/dist/core/viral-moments.test.js.map +1 -0
- package/dist/core/whisper.d.ts +16 -0
- package/dist/core/whisper.d.ts.map +1 -1
- package/dist/core/whisper.js +72 -5
- package/dist/core/whisper.js.map +1 -1
- package/dist/core/whisper.test.js +111 -1
- package/dist/core/whisper.test.js.map +1 -1
- package/dist/core/youtube-metadata.d.ts +44 -0
- package/dist/core/youtube-metadata.d.ts.map +1 -0
- package/dist/core/youtube-metadata.js +168 -0
- package/dist/core/youtube-metadata.js.map +1 -0
- package/dist/core/youtube-metadata.test.d.ts +2 -0
- package/dist/core/youtube-metadata.test.d.ts.map +1 -0
- package/dist/core/youtube-metadata.test.js +132 -0
- package/dist/core/youtube-metadata.test.js.map +1 -0
- package/dist/prompt-commands.d.ts +24 -0
- package/dist/prompt-commands.d.ts.map +1 -0
- package/dist/prompt-commands.js +243 -0
- package/dist/prompt-commands.js.map +1 -0
- package/dist/prompt-commands.test.d.ts +2 -0
- package/dist/prompt-commands.test.d.ts.map +1 -0
- package/dist/prompt-commands.test.js +46 -0
- package/dist/prompt-commands.test.js.map +1 -0
- package/dist/skills.d.ts +6 -6
- package/dist/skills.d.ts.map +1 -1
- package/dist/skills.js +1426 -445
- package/dist/skills.js.map +1 -1
- package/dist/system-prompt.d.ts.map +1 -1
- package/dist/system-prompt.js +108 -0
- package/dist/system-prompt.js.map +1 -1
- package/dist/tools/add-fades.d.ts.map +1 -1
- package/dist/tools/add-fades.js +2 -1
- package/dist/tools/add-fades.js.map +1 -1
- package/dist/tools/add-sfx-at-cuts.d.ts.map +1 -1
- package/dist/tools/add-sfx-at-cuts.js +36 -11
- package/dist/tools/add-sfx-at-cuts.js.map +1 -1
- package/dist/tools/add-sfx-to-timeline.d.ts +34 -0
- package/dist/tools/add-sfx-to-timeline.d.ts.map +1 -0
- package/dist/tools/add-sfx-to-timeline.js +169 -0
- package/dist/tools/add-sfx-to-timeline.js.map +1 -0
- package/dist/tools/add-sfx-to-timeline.test.d.ts +2 -0
- package/dist/tools/add-sfx-to-timeline.test.d.ts.map +1 -0
- package/dist/tools/add-sfx-to-timeline.test.js +181 -0
- package/dist/tools/add-sfx-to-timeline.test.js.map +1 -0
- package/dist/tools/audit-first-frame.d.ts +36 -0
- package/dist/tools/audit-first-frame.d.ts.map +1 -0
- package/dist/tools/audit-first-frame.js +181 -0
- package/dist/tools/audit-first-frame.js.map +1 -0
- package/dist/tools/audit-retention-structure.d.ts +20 -0
- package/dist/tools/audit-retention-structure.d.ts.map +1 -0
- package/dist/tools/audit-retention-structure.js +95 -0
- package/dist/tools/audit-retention-structure.js.map +1 -0
- package/dist/tools/audit-retention-structure.test.d.ts +2 -0
- package/dist/tools/audit-retention-structure.test.d.ts.map +1 -0
- package/dist/tools/audit-retention-structure.test.js +93 -0
- package/dist/tools/audit-retention-structure.test.js.map +1 -0
- package/dist/tools/bleep-words.d.ts +59 -0
- package/dist/tools/bleep-words.d.ts.map +1 -0
- package/dist/tools/bleep-words.js +211 -0
- package/dist/tools/bleep-words.js.map +1 -0
- package/dist/tools/bleep-words.test.d.ts +2 -0
- package/dist/tools/bleep-words.test.d.ts.map +1 -0
- package/dist/tools/bleep-words.test.js +96 -0
- package/dist/tools/bleep-words.test.js.map +1 -0
- package/dist/tools/burn-subtitles.d.ts.map +1 -1
- package/dist/tools/burn-subtitles.js +10 -5
- package/dist/tools/burn-subtitles.js.map +1 -1
- package/dist/tools/clean-audio.d.ts.map +1 -1
- package/dist/tools/clean-audio.js +2 -1
- package/dist/tools/clean-audio.js.map +1 -1
- package/dist/tools/cluster-takes.js +2 -1
- package/dist/tools/cluster-takes.js.map +1 -1
- package/dist/tools/compose-thumbnail-variants.d.ts +70 -0
- package/dist/tools/compose-thumbnail-variants.d.ts.map +1 -0
- package/dist/tools/compose-thumbnail-variants.js +274 -0
- package/dist/tools/compose-thumbnail-variants.js.map +1 -0
- package/dist/tools/compose-thumbnail.d.ts +6 -13
- package/dist/tools/compose-thumbnail.d.ts.map +1 -1
- package/dist/tools/compose-thumbnail.js +44 -81
- package/dist/tools/compose-thumbnail.js.map +1 -1
- package/dist/tools/concat-videos.d.ts.map +1 -1
- package/dist/tools/concat-videos.js +12 -5
- package/dist/tools/concat-videos.js.map +1 -1
- package/dist/tools/concat-videos.test.d.ts +2 -0
- package/dist/tools/concat-videos.test.d.ts.map +1 -0
- package/dist/tools/concat-videos.test.js +103 -0
- package/dist/tools/concat-videos.test.js.map +1 -0
- package/dist/tools/crossfade-videos.d.ts.map +1 -1
- package/dist/tools/crossfade-videos.js +2 -1
- package/dist/tools/crossfade-videos.js.map +1 -1
- package/dist/tools/cut-filler-words.d.ts.map +1 -1
- package/dist/tools/cut-filler-words.js +24 -8
- package/dist/tools/cut-filler-words.js.map +1 -1
- package/dist/tools/detect-speaker-changes.js +2 -1
- package/dist/tools/detect-speaker-changes.js.map +1 -1
- package/dist/tools/extract-audio.d.ts.map +1 -1
- package/dist/tools/extract-audio.js +13 -7
- package/dist/tools/extract-audio.js.map +1 -1
- package/dist/tools/face-reframe.d.ts +30 -0
- package/dist/tools/face-reframe.d.ts.map +1 -0
- package/dist/tools/face-reframe.js +143 -0
- package/dist/tools/face-reframe.js.map +1 -0
- package/dist/tools/face-reframe.test.d.ts +2 -0
- package/dist/tools/face-reframe.test.d.ts.map +1 -0
- package/dist/tools/face-reframe.test.js +139 -0
- package/dist/tools/face-reframe.test.js.map +1 -0
- package/dist/tools/find-viral-moments.d.ts +23 -0
- package/dist/tools/find-viral-moments.d.ts.map +1 -0
- package/dist/tools/find-viral-moments.js +176 -0
- package/dist/tools/find-viral-moments.js.map +1 -0
- package/dist/tools/find-viral-moments.test.d.ts +2 -0
- package/dist/tools/find-viral-moments.test.d.ts.map +1 -0
- package/dist/tools/find-viral-moments.test.js +144 -0
- package/dist/tools/find-viral-moments.test.js.map +1 -0
- package/dist/tools/generate-gif.d.ts.map +1 -1
- package/dist/tools/generate-gif.js +47 -40
- package/dist/tools/generate-gif.js.map +1 -1
- package/dist/tools/generate-gif.test.d.ts +2 -0
- package/dist/tools/generate-gif.test.d.ts.map +1 -0
- package/dist/tools/generate-gif.test.js +115 -0
- package/dist/tools/generate-gif.test.js.map +1 -0
- package/dist/tools/generate-outro.d.ts +18 -0
- package/dist/tools/generate-outro.d.ts.map +1 -0
- package/dist/tools/generate-outro.js +175 -0
- package/dist/tools/generate-outro.js.map +1 -0
- package/dist/tools/generate-youtube-metadata.d.ts +23 -0
- package/dist/tools/generate-youtube-metadata.d.ts.map +1 -0
- package/dist/tools/generate-youtube-metadata.js +103 -0
- package/dist/tools/generate-youtube-metadata.js.map +1 -0
- package/dist/tools/generate-youtube-metadata.test.d.ts +2 -0
- package/dist/tools/generate-youtube-metadata.test.d.ts.map +1 -0
- package/dist/tools/generate-youtube-metadata.test.js +118 -0
- package/dist/tools/generate-youtube-metadata.test.js.map +1 -0
- package/dist/tools/index.d.ts +14 -0
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +130 -1
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/index.test.js +27 -1
- package/dist/tools/index.test.js.map +1 -1
- package/dist/tools/ken-burns.d.ts.map +1 -1
- package/dist/tools/ken-burns.js +2 -1
- package/dist/tools/ken-burns.js.map +1 -1
- package/dist/tools/loop-match-short.d.ts +22 -0
- package/dist/tools/loop-match-short.d.ts.map +1 -0
- package/dist/tools/loop-match-short.js +107 -0
- package/dist/tools/loop-match-short.js.map +1 -0
- package/dist/tools/mix-audio.d.ts.map +1 -1
- package/dist/tools/mix-audio.js +2 -1
- package/dist/tools/mix-audio.js.map +1 -1
- package/dist/tools/normalize-loudness.d.ts.map +1 -1
- package/dist/tools/normalize-loudness.js +2 -1
- package/dist/tools/normalize-loudness.js.map +1 -1
- package/dist/tools/path-traversal.test.d.ts +15 -0
- package/dist/tools/path-traversal.test.d.ts.map +1 -0
- package/dist/tools/path-traversal.test.js +223 -0
- package/dist/tools/path-traversal.test.js.map +1 -0
- package/dist/tools/pick-best-takes.js +2 -1
- package/dist/tools/pick-best-takes.js.map +1 -1
- package/dist/tools/punch-in.d.ts.map +1 -1
- package/dist/tools/punch-in.js +2 -1
- package/dist/tools/punch-in.js.map +1 -1
- package/dist/tools/read-transcript.js +2 -1
- package/dist/tools/read-transcript.js.map +1 -1
- package/dist/tools/render-multi-format.d.ts +35 -0
- package/dist/tools/render-multi-format.d.ts.map +1 -0
- package/dist/tools/render-multi-format.js +206 -0
- package/dist/tools/render-multi-format.js.map +1 -0
- package/dist/tools/render-multi-format.test.d.ts +2 -0
- package/dist/tools/render-multi-format.test.d.ts.map +1 -0
- package/dist/tools/render-multi-format.test.js +312 -0
- package/dist/tools/render-multi-format.test.js.map +1 -0
- package/dist/tools/render.d.ts.map +1 -1
- package/dist/tools/render.js +2 -2
- package/dist/tools/render.js.map +1 -1
- package/dist/tools/rewrite-hook.d.ts +32 -0
- package/dist/tools/rewrite-hook.d.ts.map +1 -0
- package/dist/tools/rewrite-hook.js +65 -0
- package/dist/tools/rewrite-hook.js.map +1 -0
- package/dist/tools/score-clip.d.ts +30 -0
- package/dist/tools/score-clip.d.ts.map +1 -0
- package/dist/tools/score-clip.js +109 -0
- package/dist/tools/score-clip.js.map +1 -0
- package/dist/tools/score-clip.test.d.ts +2 -0
- package/dist/tools/score-clip.test.d.ts.map +1 -0
- package/dist/tools/score-clip.test.js +110 -0
- package/dist/tools/score-clip.test.js.map +1 -0
- package/dist/tools/search-tools.d.ts +34 -0
- package/dist/tools/search-tools.d.ts.map +1 -0
- package/dist/tools/search-tools.js +86 -0
- package/dist/tools/search-tools.js.map +1 -0
- package/dist/tools/search-tools.test.d.ts +2 -0
- package/dist/tools/search-tools.test.d.ts.map +1 -0
- package/dist/tools/search-tools.test.js +60 -0
- package/dist/tools/search-tools.test.js.map +1 -0
- package/dist/tools/snap-cuts-to-beats.d.ts +18 -0
- package/dist/tools/snap-cuts-to-beats.d.ts.map +1 -0
- package/dist/tools/snap-cuts-to-beats.js +110 -0
- package/dist/tools/snap-cuts-to-beats.js.map +1 -0
- package/dist/tools/snap-cuts-to-beats.test.d.ts +2 -0
- package/dist/tools/snap-cuts-to-beats.test.d.ts.map +1 -0
- package/dist/tools/snap-cuts-to-beats.test.js +99 -0
- package/dist/tools/snap-cuts-to-beats.test.js.map +1 -0
- package/dist/tools/speed-ramp.d.ts.map +1 -1
- package/dist/tools/speed-ramp.js +2 -1
- package/dist/tools/speed-ramp.js.map +1 -1
- package/dist/tools/stabilize-video.d.ts.map +1 -1
- package/dist/tools/stabilize-video.js +2 -1
- package/dist/tools/stabilize-video.js.map +1 -1
- package/dist/tools/suggest-broll.d.ts +34 -0
- package/dist/tools/suggest-broll.d.ts.map +1 -0
- package/dist/tools/suggest-broll.js +367 -0
- package/dist/tools/suggest-broll.js.map +1 -0
- package/dist/tools/suggest-broll.test.d.ts +2 -0
- package/dist/tools/suggest-broll.test.d.ts.map +1 -0
- package/dist/tools/suggest-broll.test.js +217 -0
- package/dist/tools/suggest-broll.test.js.map +1 -0
- package/dist/tools/text-based-cut.d.ts +33 -0
- package/dist/tools/text-based-cut.d.ts.map +1 -0
- package/dist/tools/text-based-cut.js +172 -0
- package/dist/tools/text-based-cut.js.map +1 -0
- package/dist/tools/text-based-cut.test.d.ts +2 -0
- package/dist/tools/text-based-cut.test.d.ts.map +1 -0
- package/dist/tools/text-based-cut.test.js +32 -0
- package/dist/tools/text-based-cut.test.js.map +1 -0
- package/dist/tools/transcribe.d.ts +1 -1
- package/dist/tools/transition-videos.d.ts +1 -1
- package/dist/tools/transition-videos.d.ts.map +1 -1
- package/dist/tools/transition-videos.js +2 -1
- package/dist/tools/transition-videos.js.map +1 -1
- package/dist/tools/trim-dead-air.d.ts +59 -0
- package/dist/tools/trim-dead-air.d.ts.map +1 -0
- package/dist/tools/trim-dead-air.js +215 -0
- package/dist/tools/trim-dead-air.js.map +1 -0
- package/dist/tools/trim-dead-air.test.d.ts +2 -0
- package/dist/tools/trim-dead-air.test.d.ts.map +1 -0
- package/dist/tools/trim-dead-air.test.js +75 -0
- package/dist/tools/trim-dead-air.test.js.map +1 -0
- package/dist/tools/verify-thumbnail-promise.d.ts +33 -0
- package/dist/tools/verify-thumbnail-promise.d.ts.map +1 -0
- package/dist/tools/verify-thumbnail-promise.js +112 -0
- package/dist/tools/verify-thumbnail-promise.js.map +1 -0
- package/dist/tools/verify-thumbnail-promise.test.d.ts +2 -0
- package/dist/tools/verify-thumbnail-promise.test.d.ts.map +1 -0
- package/dist/tools/verify-thumbnail-promise.test.js +38 -0
- package/dist/tools/verify-thumbnail-promise.test.js.map +1 -0
- package/dist/tools/write-keyword-captions.d.ts +7 -0
- package/dist/tools/write-keyword-captions.d.ts.map +1 -1
- package/dist/tools/write-keyword-captions.js +35 -4
- package/dist/tools/write-keyword-captions.js.map +1 -1
- package/dist/ui/App.d.ts.map +1 -1
- package/dist/ui/App.js +75 -11
- package/dist/ui/App.js.map +1 -1
- package/dist/ui/tool-formatters.d.ts +30 -0
- package/dist/ui/tool-formatters.d.ts.map +1 -0
- package/dist/ui/tool-formatters.js +461 -0
- package/dist/ui/tool-formatters.js.map +1 -0
- package/dist/ui/tool-formatters.test.d.ts +2 -0
- package/dist/ui/tool-formatters.test.d.ts.map +1 -0
- package/dist/ui/tool-formatters.test.js +143 -0
- package/dist/ui/tool-formatters.test.js.map +1 -0
- package/package.json +10 -9
|
@@ -0,0 +1,367 @@
|
|
|
1
|
+
import { mkdirSync, mkdtempSync, readFileSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { tmpdir } from "node:os";
|
|
3
|
+
import { join, resolve as resolvePath } from "node:path";
|
|
4
|
+
import { z } from "zod";
|
|
5
|
+
import { resolveApiKey } from "../core/auth/api-keys.js";
|
|
6
|
+
import { compact, err } from "../core/format.js";
|
|
7
|
+
import { safeOutputPath } from "../core/safe-paths.js";
|
|
8
|
+
import { parseTranscript } from "../core/whisper.js";
|
|
9
|
+
/**
|
|
10
|
+
* suggest_broll — extract visually-searchable concepts from a transcript
|
|
11
|
+
* window via ONE LLM call, then query Pexels' free stock-video library
|
|
12
|
+
* and (optionally) download the top match per concept. The output shape
|
|
13
|
+
* is shaped to feed `insert_broll` directly:
|
|
14
|
+
*
|
|
15
|
+
* for (const it of items) {
|
|
16
|
+
* await insert_broll({
|
|
17
|
+
* mediaPath: it.mediaPath,
|
|
18
|
+
* recordFrame: Math.round(it.atSec * fps),
|
|
19
|
+
* });
|
|
20
|
+
* }
|
|
21
|
+
*/
|
|
22
|
+
const SuggestBrollParams = z.object({
|
|
23
|
+
transcript: z
|
|
24
|
+
.string()
|
|
25
|
+
.describe("Path to a transcript JSON written by `transcribe`. Word-level timings not required — " +
|
|
26
|
+
"segment-level start/end is enough to place each B-roll suggestion."),
|
|
27
|
+
startSec: z
|
|
28
|
+
.number()
|
|
29
|
+
.min(0)
|
|
30
|
+
.optional()
|
|
31
|
+
.describe("Window start (seconds). Default 0. The LLM only sees text inside [startSec, endSec)."),
|
|
32
|
+
endSec: z
|
|
33
|
+
.number()
|
|
34
|
+
.min(0)
|
|
35
|
+
.optional()
|
|
36
|
+
.describe("Window end (seconds). Default = transcript.durationSec."),
|
|
37
|
+
topN: z
|
|
38
|
+
.number()
|
|
39
|
+
.int()
|
|
40
|
+
.min(1)
|
|
41
|
+
.max(20)
|
|
42
|
+
.optional()
|
|
43
|
+
.describe("Maximum B-roll suggestions to return. Default 5. Hard cap 20 — more than that bloats " +
|
|
44
|
+
"downloads and Pexels' free tier."),
|
|
45
|
+
orientation: z
|
|
46
|
+
.enum(["landscape", "portrait", "square"])
|
|
47
|
+
.optional()
|
|
48
|
+
.describe("Pexels orientation filter. Default 'landscape'. Use 'portrait' for Shorts/Reels/TikTok."),
|
|
49
|
+
minDurationSec: z
|
|
50
|
+
.number()
|
|
51
|
+
.min(1)
|
|
52
|
+
.optional()
|
|
53
|
+
.describe("Discard Pexels clips shorter than this (seconds). Default 5. Stops the tool from picking " +
|
|
54
|
+
"tiny stings that won't cover even one filler-cut."),
|
|
55
|
+
outDir: z
|
|
56
|
+
.string()
|
|
57
|
+
.optional()
|
|
58
|
+
.describe("Directory to download chosen videos into (relative resolves to cwd). Default '.gg/broll-cache'. " +
|
|
59
|
+
"Ignored when download=false."),
|
|
60
|
+
model: z
|
|
61
|
+
.string()
|
|
62
|
+
.optional()
|
|
63
|
+
.describe("OpenAI chat model used for the noun-phrase extraction step. Default 'gpt-4o-mini'."),
|
|
64
|
+
download: z
|
|
65
|
+
.boolean()
|
|
66
|
+
.optional()
|
|
67
|
+
.describe("When true (default), fetch each chosen video file to outDir and return its local path. " +
|
|
68
|
+
"When false, return only the Pexels CDN URL — useful for previewing before committing bandwidth."),
|
|
69
|
+
});
|
|
70
|
+
const LLM_SYSTEM = `You extract visually-searchable B-roll concepts from a video transcript.
|
|
71
|
+
|
|
72
|
+
Return JSON: {"queries":[{"atSec": number, "query": string, "why": string}, ...]}
|
|
73
|
+
|
|
74
|
+
Each query must be 2-4 words describing a CONCRETE visual that stock-footage libraries actually have:
|
|
75
|
+
GOOD: "coffee shop morning", "highway sunset driving", "woman typing laptop", "city skyline timelapse".
|
|
76
|
+
BAD : "the importance of focus", "feeling productive", "thinking about life".
|
|
77
|
+
Avoid abstract concepts, emotions, and named people/brands.
|
|
78
|
+
|
|
79
|
+
\`atSec\` is the timeline second nearest where the concept is mentioned in the transcript.
|
|
80
|
+
\`why\` is a ≤80-char rationale ("speaker mentions morning routine").
|
|
81
|
+
|
|
82
|
+
Return up to N queries, ordered by importance (most cover-worthy first).`;
|
|
83
|
+
export function createSuggestBrollTool(cwd) {
|
|
84
|
+
return {
|
|
85
|
+
name: "suggest_broll",
|
|
86
|
+
description: "Find B-roll for a transcript window: extracts visual concepts from the transcript via ONE " +
|
|
87
|
+
"LLM call, queries Pexels' free video library, downloads the top match per concept. REQUIRES " +
|
|
88
|
+
"PEXELS_API_KEY (free at pexels.com/api) and OPENAI_API_KEY (for the extraction step). " +
|
|
89
|
+
"Returns {count, items: [{atSec, mediaPath, query, durationSec, sourceUrl, photographer, ...}]} " +
|
|
90
|
+
"ready to feed `insert_broll(mediaPath, recordFrame=atSec*fps)`. The biggest creator multiplier — " +
|
|
91
|
+
"turns 'cover up these ums' into one tool call.",
|
|
92
|
+
parameters: SuggestBrollParams,
|
|
93
|
+
async execute(args, ctx) {
|
|
94
|
+
try {
|
|
95
|
+
const pexelsKey = resolveApiKey("PEXELS_API_KEY", "pexels");
|
|
96
|
+
if (!pexelsKey) {
|
|
97
|
+
return err("PEXELS_API_KEY not set", "free at https://www.pexels.com/api/ — set env or run ggeditor with the key in ~/.gg/api-keys.json");
|
|
98
|
+
}
|
|
99
|
+
const openaiKey = resolveApiKey("OPENAI_API_KEY", "openai");
|
|
100
|
+
if (!openaiKey) {
|
|
101
|
+
return err("OPENAI_API_KEY not set", "needed for the noun-phrase extraction step — set env or store via the onboarding flow");
|
|
102
|
+
}
|
|
103
|
+
const transcriptAbs = resolvePath(cwd, args.transcript);
|
|
104
|
+
let raw;
|
|
105
|
+
try {
|
|
106
|
+
raw = readFileSync(transcriptAbs, "utf8");
|
|
107
|
+
}
|
|
108
|
+
catch (e) {
|
|
109
|
+
return err(`cannot read transcript ${transcriptAbs}: ${e.message}`, "verify the transcript JSON exists");
|
|
110
|
+
}
|
|
111
|
+
let transcript;
|
|
112
|
+
try {
|
|
113
|
+
transcript = parseTranscript(raw);
|
|
114
|
+
}
|
|
115
|
+
catch (e) {
|
|
116
|
+
return err(e.message, "regenerate via transcribe()");
|
|
117
|
+
}
|
|
118
|
+
const startSec = args.startSec ?? 0;
|
|
119
|
+
const endSec = args.endSec ?? transcript.durationSec ?? Infinity;
|
|
120
|
+
if (endSec <= startSec) {
|
|
121
|
+
return err(`empty window: endSec (${endSec}) <= startSec (${startSec})`, "widen the [startSec, endSec) interval");
|
|
122
|
+
}
|
|
123
|
+
const topN = args.topN ?? 5;
|
|
124
|
+
const orientation = args.orientation ?? "landscape";
|
|
125
|
+
const minDurationSec = args.minDurationSec ?? 5;
|
|
126
|
+
const model = args.model ?? "gpt-4o-mini";
|
|
127
|
+
const download = args.download ?? true;
|
|
128
|
+
const windowText = buildWindowText(transcript.segments, startSec, endSec, 6000);
|
|
129
|
+
if (windowText.trim().length === 0) {
|
|
130
|
+
return err("no transcript text in window", "widen [startSec, endSec) or check the transcript");
|
|
131
|
+
}
|
|
132
|
+
// ── 1. LLM extraction ───────────────────────────────────
|
|
133
|
+
let queries;
|
|
134
|
+
try {
|
|
135
|
+
queries = await runQueryExtraction({
|
|
136
|
+
apiKey: openaiKey,
|
|
137
|
+
model,
|
|
138
|
+
text: windowText,
|
|
139
|
+
n: topN,
|
|
140
|
+
startSec,
|
|
141
|
+
endSec,
|
|
142
|
+
signal: ctx?.signal,
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
catch (e) {
|
|
146
|
+
return err(`LLM extraction failed: ${e.message}`);
|
|
147
|
+
}
|
|
148
|
+
if (queries.length === 0) {
|
|
149
|
+
return err("LLM returned zero queries", "the window may be too short or too abstract — widen it or try a different model");
|
|
150
|
+
}
|
|
151
|
+
// ── 2. Resolve outDir (only if downloading) ─────────────
|
|
152
|
+
let outDirAbs;
|
|
153
|
+
if (download) {
|
|
154
|
+
outDirAbs = args.outDir
|
|
155
|
+
? safeOutputPath(cwd, args.outDir)
|
|
156
|
+
: safeOutputPath(cwd, join(".gg", "broll-cache"));
|
|
157
|
+
mkdirSync(outDirAbs, { recursive: true });
|
|
158
|
+
}
|
|
159
|
+
// ── 3. Pexels per query ─────────────────────────────────
|
|
160
|
+
const items = [];
|
|
161
|
+
const skipped = [];
|
|
162
|
+
for (const q of queries.slice(0, topN)) {
|
|
163
|
+
try {
|
|
164
|
+
const search = await searchPexels({
|
|
165
|
+
apiKey: pexelsKey,
|
|
166
|
+
query: q.query,
|
|
167
|
+
orientation,
|
|
168
|
+
perPage: 3,
|
|
169
|
+
signal: ctx?.signal,
|
|
170
|
+
});
|
|
171
|
+
const candidate = pickFirstAcceptable(search.videos, minDurationSec);
|
|
172
|
+
if (!candidate) {
|
|
173
|
+
skipped.push({ query: q.query, reason: "no Pexels match" });
|
|
174
|
+
continue;
|
|
175
|
+
}
|
|
176
|
+
const file = pickBestFile(candidate.video.video_files);
|
|
177
|
+
if (!file) {
|
|
178
|
+
skipped.push({ query: q.query, reason: "no playable video_file" });
|
|
179
|
+
continue;
|
|
180
|
+
}
|
|
181
|
+
let mediaPath;
|
|
182
|
+
if (download && outDirAbs) {
|
|
183
|
+
try {
|
|
184
|
+
mediaPath = await downloadVideo({
|
|
185
|
+
url: file.link,
|
|
186
|
+
fileType: file.file_type,
|
|
187
|
+
pexelsId: candidate.video.id,
|
|
188
|
+
outDir: outDirAbs,
|
|
189
|
+
signal: ctx?.signal,
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
catch (e) {
|
|
193
|
+
skipped.push({
|
|
194
|
+
query: q.query,
|
|
195
|
+
reason: `download failed: ${e.message}`,
|
|
196
|
+
});
|
|
197
|
+
continue;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
items.push({
|
|
201
|
+
atSec: clampSec(q.atSec, startSec, endSec),
|
|
202
|
+
durationSec: candidate.video.duration,
|
|
203
|
+
mediaPath,
|
|
204
|
+
query: q.query,
|
|
205
|
+
why: q.why,
|
|
206
|
+
sourceUrl: candidate.video.url,
|
|
207
|
+
photographer: candidate.video.user?.name ?? "unknown",
|
|
208
|
+
pexelsId: candidate.video.id,
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
catch (e) {
|
|
212
|
+
// Per-query Pexels failures: surface 401 / 429 with actionable
|
|
213
|
+
// fixes; everything else lands in skipped[] so partial success
|
|
214
|
+
// is still useful.
|
|
215
|
+
const msg = e.message;
|
|
216
|
+
if (msg.startsWith("PEXELS_401")) {
|
|
217
|
+
return err("Pexels 401 unauthorized", "verify PEXELS_API_KEY");
|
|
218
|
+
}
|
|
219
|
+
if (msg.startsWith("PEXELS_429")) {
|
|
220
|
+
return err("Pexels rate-limited", "wait ~1h or upgrade plan");
|
|
221
|
+
}
|
|
222
|
+
skipped.push({ query: q.query, reason: msg.slice(0, 200) });
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
return compact({
|
|
226
|
+
count: items.length,
|
|
227
|
+
items,
|
|
228
|
+
skipped: skipped.length > 0 ? skipped : undefined,
|
|
229
|
+
});
|
|
230
|
+
}
|
|
231
|
+
catch (e) {
|
|
232
|
+
return err(e.message);
|
|
233
|
+
}
|
|
234
|
+
},
|
|
235
|
+
};
|
|
236
|
+
}
|
|
237
|
+
// ── Helpers ──────────────────────────────────────────────────
|
|
238
|
+
function buildWindowText(segments, startSec, endSec, maxChars) {
|
|
239
|
+
const parts = [];
|
|
240
|
+
let total = 0;
|
|
241
|
+
for (const s of segments) {
|
|
242
|
+
if (s.end <= startSec)
|
|
243
|
+
continue;
|
|
244
|
+
if (s.start >= endSec)
|
|
245
|
+
break;
|
|
246
|
+
const stamped = `[${s.start.toFixed(1)}s] ${s.text.trim()}`;
|
|
247
|
+
if (total + stamped.length + 1 > maxChars)
|
|
248
|
+
break;
|
|
249
|
+
parts.push(stamped);
|
|
250
|
+
total += stamped.length + 1;
|
|
251
|
+
}
|
|
252
|
+
return parts.join("\n");
|
|
253
|
+
}
|
|
254
|
+
function clampSec(v, lo, hi) {
|
|
255
|
+
if (!Number.isFinite(v))
|
|
256
|
+
return lo;
|
|
257
|
+
if (v < lo)
|
|
258
|
+
return lo;
|
|
259
|
+
if (v >= hi)
|
|
260
|
+
return Math.max(lo, hi - 0.001);
|
|
261
|
+
return +v.toFixed(2);
|
|
262
|
+
}
|
|
263
|
+
async function runQueryExtraction(opts) {
|
|
264
|
+
const userMsg = `Window: [${opts.startSec.toFixed(1)}s, ${opts.endSec.toFixed(1)}s). Return up to ${opts.n} queries.\n\n` +
|
|
265
|
+
`TRANSCRIPT:\n${opts.text}`;
|
|
266
|
+
const body = {
|
|
267
|
+
model: opts.model,
|
|
268
|
+
messages: [
|
|
269
|
+
{ role: "system", content: LLM_SYSTEM },
|
|
270
|
+
{ role: "user", content: userMsg },
|
|
271
|
+
],
|
|
272
|
+
response_format: { type: "json_object" },
|
|
273
|
+
temperature: 0,
|
|
274
|
+
};
|
|
275
|
+
const res = await fetch("https://api.openai.com/v1/chat/completions", {
|
|
276
|
+
method: "POST",
|
|
277
|
+
headers: {
|
|
278
|
+
Authorization: `Bearer ${opts.apiKey}`,
|
|
279
|
+
"Content-Type": "application/json",
|
|
280
|
+
},
|
|
281
|
+
body: JSON.stringify(body),
|
|
282
|
+
signal: opts.signal,
|
|
283
|
+
});
|
|
284
|
+
if (!res.ok) {
|
|
285
|
+
const text = await res.text().catch(() => "");
|
|
286
|
+
throw new Error(`OpenAI HTTP ${res.status}: ${text.slice(0, 200)}`);
|
|
287
|
+
}
|
|
288
|
+
const data = (await res.json());
|
|
289
|
+
const content = data.choices?.[0]?.message?.content;
|
|
290
|
+
if (!content)
|
|
291
|
+
throw new Error("empty model response");
|
|
292
|
+
const start = content.indexOf("{");
|
|
293
|
+
const end = content.lastIndexOf("}");
|
|
294
|
+
if (start < 0 || end < start)
|
|
295
|
+
throw new Error("no JSON object in response");
|
|
296
|
+
const parsed = JSON.parse(content.slice(start, end + 1));
|
|
297
|
+
if (!Array.isArray(parsed.queries))
|
|
298
|
+
throw new Error("response missing queries[]");
|
|
299
|
+
const out = [];
|
|
300
|
+
for (const raw of parsed.queries) {
|
|
301
|
+
if (!raw || typeof raw !== "object")
|
|
302
|
+
continue;
|
|
303
|
+
const r = raw;
|
|
304
|
+
const query = String(r.query ?? "").trim();
|
|
305
|
+
if (!query)
|
|
306
|
+
continue;
|
|
307
|
+
const atSecRaw = Number(r.atSec);
|
|
308
|
+
const atSec = Number.isFinite(atSecRaw) ? atSecRaw : opts.startSec;
|
|
309
|
+
const why = String(r.why ?? "").slice(0, 200);
|
|
310
|
+
out.push({ atSec, query, why });
|
|
311
|
+
}
|
|
312
|
+
return out;
|
|
313
|
+
}
|
|
314
|
+
async function searchPexels(opts) {
|
|
315
|
+
const url = `https://api.pexels.com/videos/search` +
|
|
316
|
+
`?query=${encodeURIComponent(opts.query)}` +
|
|
317
|
+
`&per_page=${opts.perPage}` +
|
|
318
|
+
`&orientation=${opts.orientation}`;
|
|
319
|
+
const res = await fetch(url, {
|
|
320
|
+
headers: { Authorization: opts.apiKey },
|
|
321
|
+
signal: opts.signal,
|
|
322
|
+
});
|
|
323
|
+
if (res.status === 401)
|
|
324
|
+
throw new Error("PEXELS_401");
|
|
325
|
+
if (res.status === 429)
|
|
326
|
+
throw new Error("PEXELS_429");
|
|
327
|
+
if (!res.ok) {
|
|
328
|
+
const t = await res.text().catch(() => "");
|
|
329
|
+
throw new Error(`Pexels HTTP ${res.status}: ${t.slice(0, 200)}`);
|
|
330
|
+
}
|
|
331
|
+
return (await res.json());
|
|
332
|
+
}
|
|
333
|
+
function pickFirstAcceptable(videos, minDurationSec) {
|
|
334
|
+
if (!Array.isArray(videos))
|
|
335
|
+
return undefined;
|
|
336
|
+
for (const v of videos) {
|
|
337
|
+
if ((v.duration ?? 0) >= minDurationSec)
|
|
338
|
+
return { video: v };
|
|
339
|
+
}
|
|
340
|
+
return undefined;
|
|
341
|
+
}
|
|
342
|
+
/**
|
|
343
|
+
* Pick the best `video_files` entry: prefer mp4, prefer hd over sd, avoid
|
|
344
|
+
* uhd (multi-GB downloads on free tier are not creator-friendly).
|
|
345
|
+
*/
|
|
346
|
+
function pickBestFile(files) {
|
|
347
|
+
if (!Array.isArray(files) || files.length === 0)
|
|
348
|
+
return undefined;
|
|
349
|
+
const mp4 = files.filter((f) => f.file_type === "video/mp4");
|
|
350
|
+
const pool = mp4.length > 0 ? mp4 : files;
|
|
351
|
+
return pool.find((f) => f.quality === "hd") ?? pool.find((f) => f.quality === "sd") ?? pool[0];
|
|
352
|
+
}
|
|
353
|
+
async function downloadVideo(opts) {
|
|
354
|
+
const res = await fetch(opts.url, { signal: opts.signal });
|
|
355
|
+
if (!res.ok)
|
|
356
|
+
throw new Error(`HTTP ${res.status}`);
|
|
357
|
+
const buf = Buffer.from(await res.arrayBuffer());
|
|
358
|
+
const ext = opts.fileType.endsWith("/webm") ? "webm" : "mp4";
|
|
359
|
+
const out = join(opts.outDir, `pexels-${opts.pexelsId}.${ext}`);
|
|
360
|
+
writeFileSync(out, buf);
|
|
361
|
+
return out;
|
|
362
|
+
}
|
|
363
|
+
// Re-export for tests that want to seed a tempdir without poking the cwd.
|
|
364
|
+
export function _tempBrollDir() {
|
|
365
|
+
return mkdtempSync(join(tmpdir(), "gg-broll-"));
|
|
366
|
+
}
|
|
367
|
+
//# sourceMappingURL=suggest-broll.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"suggest-broll.js","sourceRoot":"","sources":["../../src/tools/suggest-broll.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"suggest-broll.test.d.ts","sourceRoot":"","sources":["../../src/tools/suggest-broll.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
import { existsSync, mkdtempSync, readdirSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { tmpdir } from "node:os";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
5
|
+
import { createSuggestBrollTool } from "./suggest-broll.js";
|
|
6
|
+
/**
|
|
7
|
+
* suggest_broll mocks the network (OpenAI + Pexels) and the filesystem
|
|
8
|
+
* download path. It never actually hits the wire.
|
|
9
|
+
*
|
|
10
|
+
* Test ordering matters because we mutate process.env.PEXELS_API_KEY /
|
|
11
|
+
* OPENAI_API_KEY and stub global.fetch — every `it` cleans up.
|
|
12
|
+
*/
|
|
13
|
+
const TX = {
|
|
14
|
+
language: "en",
|
|
15
|
+
durationSec: 60,
|
|
16
|
+
segments: [
|
|
17
|
+
{ start: 0, end: 5, text: "Today I want to talk about my morning coffee routine." },
|
|
18
|
+
{ start: 5, end: 10, text: "I drive down the highway as the sun rises." },
|
|
19
|
+
{ start: 10, end: 15, text: "Then I open my laptop and start typing." },
|
|
20
|
+
],
|
|
21
|
+
};
|
|
22
|
+
function makeTranscriptFile(t) {
|
|
23
|
+
const dir = mkdtempSync(join(tmpdir(), "gg-sbr-"));
|
|
24
|
+
const path = join(dir, "transcript.json");
|
|
25
|
+
writeFileSync(path, JSON.stringify(t), "utf8");
|
|
26
|
+
return { dir, path };
|
|
27
|
+
}
|
|
28
|
+
const ctx = {
|
|
29
|
+
signal: new AbortController().signal,
|
|
30
|
+
toolCallId: "t1",
|
|
31
|
+
};
|
|
32
|
+
// JSON helper for fetch mocks
|
|
33
|
+
function jsonResponse(body, status = 200) {
|
|
34
|
+
return new Response(JSON.stringify(body), {
|
|
35
|
+
status,
|
|
36
|
+
headers: { "Content-Type": "application/json" },
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
function llmResponse(queries) {
|
|
40
|
+
return jsonResponse({
|
|
41
|
+
choices: [{ message: { content: JSON.stringify({ queries }) } }],
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
function pexelsVideo(opts) {
|
|
45
|
+
return {
|
|
46
|
+
id: opts.id,
|
|
47
|
+
width: 1920,
|
|
48
|
+
height: 1080,
|
|
49
|
+
duration: opts.duration ?? 12,
|
|
50
|
+
url: opts.url ?? `https://www.pexels.com/video/${opts.id}/`,
|
|
51
|
+
user: { name: opts.user ?? "Jane Photographer" },
|
|
52
|
+
video_files: [
|
|
53
|
+
{
|
|
54
|
+
link: opts.link ?? `https://cdn.pexels.com/v/${opts.id}.mp4`,
|
|
55
|
+
quality: "hd",
|
|
56
|
+
width: 1920,
|
|
57
|
+
height: 1080,
|
|
58
|
+
file_type: "video/mp4",
|
|
59
|
+
},
|
|
60
|
+
],
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
const ENV_BACKUP = {};
|
|
64
|
+
beforeEach(() => {
|
|
65
|
+
ENV_BACKUP.PEXELS_API_KEY = process.env.PEXELS_API_KEY;
|
|
66
|
+
ENV_BACKUP.OPENAI_API_KEY = process.env.OPENAI_API_KEY;
|
|
67
|
+
process.env.PEXELS_API_KEY = "test-pexels";
|
|
68
|
+
process.env.OPENAI_API_KEY = "test-openai";
|
|
69
|
+
});
|
|
70
|
+
afterEach(() => {
|
|
71
|
+
for (const [k, v] of Object.entries(ENV_BACKUP)) {
|
|
72
|
+
if (v === undefined)
|
|
73
|
+
delete process.env[k];
|
|
74
|
+
else
|
|
75
|
+
process.env[k] = v;
|
|
76
|
+
}
|
|
77
|
+
vi.restoreAllMocks();
|
|
78
|
+
vi.unstubAllGlobals();
|
|
79
|
+
});
|
|
80
|
+
describe("suggest_broll", () => {
|
|
81
|
+
it("errors when PEXELS_API_KEY is unset", async () => {
|
|
82
|
+
delete process.env.PEXELS_API_KEY;
|
|
83
|
+
// Make sure the stored-key fallback returns nothing either.
|
|
84
|
+
vi.doMock("../core/auth/api-keys.js", async (orig) => {
|
|
85
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-imports
|
|
86
|
+
const mod = await orig();
|
|
87
|
+
return {
|
|
88
|
+
...mod,
|
|
89
|
+
getStoredApiKey: () => undefined,
|
|
90
|
+
resolveApiKey: (envVar) => envVar === "OPENAI_API_KEY" ? process.env.OPENAI_API_KEY : undefined,
|
|
91
|
+
};
|
|
92
|
+
});
|
|
93
|
+
// Re-import after the mock so the tool resolves the stubbed module.
|
|
94
|
+
const { createSuggestBrollTool: freshCreate } = await import("./suggest-broll.js");
|
|
95
|
+
const { dir } = makeTranscriptFile(TX);
|
|
96
|
+
const tool = freshCreate(dir);
|
|
97
|
+
const r = (await tool.execute({ transcript: "transcript.json" }, ctx));
|
|
98
|
+
expect(r).toMatch(/^error: PEXELS_API_KEY not set/);
|
|
99
|
+
vi.doUnmock("../core/auth/api-keys.js");
|
|
100
|
+
});
|
|
101
|
+
it("errors when transcript file is missing", async () => {
|
|
102
|
+
const dir = mkdtempSync(join(tmpdir(), "gg-sbr-"));
|
|
103
|
+
const tool = createSuggestBrollTool(dir);
|
|
104
|
+
const r = (await tool.execute({ transcript: "nope.json" }, ctx));
|
|
105
|
+
expect(r).toMatch(/^error: cannot read transcript/);
|
|
106
|
+
});
|
|
107
|
+
it("errors when transcript is malformed JSON", async () => {
|
|
108
|
+
const dir = mkdtempSync(join(tmpdir(), "gg-sbr-"));
|
|
109
|
+
writeFileSync(join(dir, "t.json"), "{not json", "utf8");
|
|
110
|
+
const tool = createSuggestBrollTool(dir);
|
|
111
|
+
const r = (await tool.execute({ transcript: "t.json" }, ctx));
|
|
112
|
+
expect(r).toMatch(/^error: Invalid transcript: not valid JSON/);
|
|
113
|
+
});
|
|
114
|
+
it("returns formatted items when LLM + Pexels both succeed (download=false)", async () => {
|
|
115
|
+
const fetchMock = vi
|
|
116
|
+
.fn()
|
|
117
|
+
.mockResolvedValueOnce(llmResponse([
|
|
118
|
+
{ atSec: 2, query: "morning coffee shop", why: "speaker mentions coffee" },
|
|
119
|
+
{ atSec: 7, query: "highway sunrise driving", why: "speaker drives at sunrise" },
|
|
120
|
+
]))
|
|
121
|
+
.mockResolvedValueOnce(jsonResponse({ videos: [pexelsVideo({ id: 1001 })] }))
|
|
122
|
+
.mockResolvedValueOnce(jsonResponse({ videos: [pexelsVideo({ id: 1002 })] }));
|
|
123
|
+
vi.stubGlobal("fetch", fetchMock);
|
|
124
|
+
const { dir } = makeTranscriptFile(TX);
|
|
125
|
+
const tool = createSuggestBrollTool(dir);
|
|
126
|
+
const r = (await tool.execute({ transcript: "transcript.json", download: false }, ctx));
|
|
127
|
+
expect(r).not.toMatch(/^error/);
|
|
128
|
+
const parsed = JSON.parse(r);
|
|
129
|
+
expect(parsed.count).toBe(2);
|
|
130
|
+
expect(parsed.items).toHaveLength(2);
|
|
131
|
+
expect(parsed.items[0].query).toBe("morning coffee shop");
|
|
132
|
+
expect(parsed.items[0].sourceUrl).toContain("pexels.com");
|
|
133
|
+
expect(parsed.items[0].pexelsId).toBe(1001);
|
|
134
|
+
// download=false → no mediaPath
|
|
135
|
+
expect(parsed.items[0].mediaPath).toBeUndefined();
|
|
136
|
+
expect(parsed.items[1].pexelsId).toBe(1002);
|
|
137
|
+
// First call hits OpenAI, next two hit Pexels (no download fetches).
|
|
138
|
+
expect(fetchMock).toHaveBeenCalledTimes(3);
|
|
139
|
+
const urls = fetchMock.mock.calls.map((c) => c[0]);
|
|
140
|
+
expect(urls[0]).toContain("api.openai.com");
|
|
141
|
+
expect(urls[1]).toContain("api.pexels.com/videos/search");
|
|
142
|
+
expect(urls[2]).toContain("api.pexels.com/videos/search");
|
|
143
|
+
});
|
|
144
|
+
it("returns user-friendly error on Pexels 401", async () => {
|
|
145
|
+
const fetchMock = vi
|
|
146
|
+
.fn()
|
|
147
|
+
.mockResolvedValueOnce(llmResponse([{ atSec: 1, query: "morning coffee", why: "x" }]))
|
|
148
|
+
.mockResolvedValueOnce(new Response("unauthorized", { status: 401 }));
|
|
149
|
+
vi.stubGlobal("fetch", fetchMock);
|
|
150
|
+
const { dir } = makeTranscriptFile(TX);
|
|
151
|
+
const tool = createSuggestBrollTool(dir);
|
|
152
|
+
const r = (await tool.execute({ transcript: "transcript.json", download: false }, ctx));
|
|
153
|
+
expect(r).toMatch(/^error: Pexels 401 unauthorized/);
|
|
154
|
+
expect(r).toContain("verify PEXELS_API_KEY");
|
|
155
|
+
});
|
|
156
|
+
it("collects per-query failures into skipped[] and still returns successes", async () => {
|
|
157
|
+
const fetchMock = vi
|
|
158
|
+
.fn()
|
|
159
|
+
.mockResolvedValueOnce(llmResponse([
|
|
160
|
+
{ atSec: 2, query: "coffee shop morning", why: "a" },
|
|
161
|
+
{ atSec: 7, query: "obscure abstract concept", why: "b" },
|
|
162
|
+
]))
|
|
163
|
+
.mockResolvedValueOnce(jsonResponse({ videos: [pexelsVideo({ id: 2001 })] }))
|
|
164
|
+
.mockResolvedValueOnce(jsonResponse({ videos: [] })); // empty → skipped
|
|
165
|
+
vi.stubGlobal("fetch", fetchMock);
|
|
166
|
+
const { dir } = makeTranscriptFile(TX);
|
|
167
|
+
const tool = createSuggestBrollTool(dir);
|
|
168
|
+
const r = (await tool.execute({ transcript: "transcript.json", download: false }, ctx));
|
|
169
|
+
expect(r).not.toMatch(/^error/);
|
|
170
|
+
const parsed = JSON.parse(r);
|
|
171
|
+
expect(parsed.count).toBe(1);
|
|
172
|
+
expect(parsed.items[0].pexelsId).toBe(2001);
|
|
173
|
+
expect(parsed.skipped).toHaveLength(1);
|
|
174
|
+
expect(parsed.skipped[0].query).toBe("obscure abstract concept");
|
|
175
|
+
expect(parsed.skipped[0].reason).toMatch(/no Pexels match/);
|
|
176
|
+
});
|
|
177
|
+
it("downloads to outDir when download=true and writes the file", async () => {
|
|
178
|
+
const downloadDir = mkdtempSync(join(tmpdir(), "gg-sbr-out-"));
|
|
179
|
+
const fakeBytes = Buffer.from("FAKE_VIDEO_BYTES");
|
|
180
|
+
const fetchMock = vi
|
|
181
|
+
.fn()
|
|
182
|
+
.mockResolvedValueOnce(llmResponse([{ atSec: 2, query: "coffee shop morning", why: "x" }]))
|
|
183
|
+
.mockResolvedValueOnce(jsonResponse({ videos: [pexelsVideo({ id: 3001 })] }))
|
|
184
|
+
.mockResolvedValueOnce(new Response(fakeBytes, { status: 200, headers: { "Content-Type": "video/mp4" } }));
|
|
185
|
+
vi.stubGlobal("fetch", fetchMock);
|
|
186
|
+
const { dir } = makeTranscriptFile(TX);
|
|
187
|
+
const tool = createSuggestBrollTool(dir);
|
|
188
|
+
const r = (await tool.execute({
|
|
189
|
+
transcript: "transcript.json",
|
|
190
|
+
download: true,
|
|
191
|
+
outDir: downloadDir,
|
|
192
|
+
}, ctx));
|
|
193
|
+
expect(r).not.toMatch(/^error/);
|
|
194
|
+
const parsed = JSON.parse(r);
|
|
195
|
+
expect(parsed.count).toBe(1);
|
|
196
|
+
expect(parsed.items[0].mediaPath).toBe(join(downloadDir, "pexels-3001.mp4"));
|
|
197
|
+
expect(existsSync(parsed.items[0].mediaPath)).toBe(true);
|
|
198
|
+
// Files in the dir = exactly one mp4.
|
|
199
|
+
const files = readdirSync(downloadDir);
|
|
200
|
+
expect(files).toContain("pexels-3001.mp4");
|
|
201
|
+
});
|
|
202
|
+
it("output is valid JSON with {count, items} shape", async () => {
|
|
203
|
+
const fetchMock = vi
|
|
204
|
+
.fn()
|
|
205
|
+
.mockResolvedValueOnce(llmResponse([{ atSec: 1, query: "city skyline", why: "x" }]))
|
|
206
|
+
.mockResolvedValueOnce(jsonResponse({ videos: [pexelsVideo({ id: 9 })] }));
|
|
207
|
+
vi.stubGlobal("fetch", fetchMock);
|
|
208
|
+
const { dir } = makeTranscriptFile(TX);
|
|
209
|
+
const tool = createSuggestBrollTool(dir);
|
|
210
|
+
const r = (await tool.execute({ transcript: "transcript.json", download: false }, ctx));
|
|
211
|
+
const parsed = JSON.parse(r);
|
|
212
|
+
expect(parsed).toHaveProperty("count");
|
|
213
|
+
expect(parsed).toHaveProperty("items");
|
|
214
|
+
expect(Array.isArray(parsed.items)).toBe(true);
|
|
215
|
+
});
|
|
216
|
+
});
|
|
217
|
+
//# sourceMappingURL=suggest-broll.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"suggest-broll.test.js","sourceRoot":"","sources":["../../src/tools/suggest-broll.test.ts"],"names":[],"mappings":"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"}
|