youtube-knowledge-mcp 2.2.0 → 3.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +126 -36
- package/dist/brain-schemas.d.ts +10 -0
- package/dist/brain-schemas.d.ts.map +1 -1
- package/dist/harvest-schemas.d.ts +75 -0
- package/dist/harvest-schemas.d.ts.map +1 -0
- package/dist/harvest-schemas.js +111 -0
- package/dist/harvest-schemas.js.map +1 -0
- package/dist/registry/brain-tools.d.ts.map +1 -1
- package/dist/registry/brain-tools.js +16 -0
- package/dist/registry/brain-tools.js.map +1 -1
- package/dist/registry/channel-tools.d.ts.map +1 -1
- package/dist/registry/channel-tools.js +16 -0
- package/dist/registry/channel-tools.js.map +1 -1
- package/dist/registry/harvest-tools.d.ts +10 -0
- package/dist/registry/harvest-tools.d.ts.map +1 -0
- package/dist/registry/harvest-tools.js +109 -0
- package/dist/registry/harvest-tools.js.map +1 -0
- package/dist/registry/health-tools.d.ts.map +1 -1
- package/dist/registry/health-tools.js +18 -0
- package/dist/registry/health-tools.js.map +1 -1
- package/dist/registry/index.d.ts.map +1 -1
- package/dist/registry/index.js +6 -0
- package/dist/registry/index.js.map +1 -1
- package/dist/registry/media-tools.d.ts.map +1 -1
- package/dist/registry/media-tools.js +31 -0
- package/dist/registry/media-tools.js.map +1 -1
- package/dist/registry/store-tools.d.ts +9 -0
- package/dist/registry/store-tools.d.ts.map +1 -0
- package/dist/registry/store-tools.js +59 -0
- package/dist/registry/store-tools.js.map +1 -0
- package/dist/registry/transcript-tools.d.ts +4 -1
- package/dist/registry/transcript-tools.d.ts.map +1 -1
- package/dist/registry/transcript-tools.js +20 -1
- package/dist/registry/transcript-tools.js.map +1 -1
- package/dist/registry/video-tools.d.ts.map +1 -1
- package/dist/registry/video-tools.js +49 -1
- package/dist/registry/video-tools.js.map +1 -1
- package/dist/registry/vision-tools.d.ts +7 -0
- package/dist/registry/vision-tools.d.ts.map +1 -0
- package/dist/registry/vision-tools.js +55 -0
- package/dist/registry/vision-tools.js.map +1 -0
- package/dist/schemas.d.ts +245 -0
- package/dist/schemas.d.ts.map +1 -1
- package/dist/schemas.js +58 -0
- package/dist/schemas.js.map +1 -1
- package/dist/thumbnail-schemas.d.ts +38 -28
- package/dist/thumbnail-schemas.d.ts.map +1 -1
- package/dist/tools/ask-brain.js +1 -1
- package/dist/tools/ask-brain.js.map +1 -1
- package/dist/tools/ask-brains.d.ts +66 -0
- package/dist/tools/ask-brains.d.ts.map +1 -0
- package/dist/tools/ask-brains.js +111 -0
- package/dist/tools/ask-brains.js.map +1 -0
- package/dist/tools/brain-info.js +1 -1
- package/dist/tools/brain-info.js.map +1 -1
- package/dist/tools/check-health.d.ts +75 -6
- package/dist/tools/check-health.d.ts.map +1 -1
- package/dist/tools/check-health.js +114 -6
- package/dist/tools/check-health.js.map +1 -1
- package/dist/tools/check-new-uploads.d.ts +55 -0
- package/dist/tools/check-new-uploads.d.ts.map +1 -0
- package/dist/tools/check-new-uploads.js +74 -0
- package/dist/tools/check-new-uploads.js.map +1 -0
- package/dist/tools/clips.d.ts +15 -0
- package/dist/tools/clips.d.ts.map +1 -1
- package/dist/tools/clips.js +5 -5
- package/dist/tools/clips.js.map +1 -1
- package/dist/tools/detect-scenes.d.ts +38 -0
- package/dist/tools/detect-scenes.d.ts.map +1 -0
- package/dist/tools/detect-scenes.js +66 -0
- package/dist/tools/detect-scenes.js.map +1 -0
- package/dist/tools/export-data.d.ts +85 -0
- package/dist/tools/export-data.d.ts.map +1 -0
- package/dist/tools/export-data.js +99 -0
- package/dist/tools/export-data.js.map +1 -0
- package/dist/tools/fetch-channel-thumbnails.d.ts +8 -8
- package/dist/tools/fetch-videos.d.ts +15 -4
- package/dist/tools/fetch-videos.d.ts.map +1 -1
- package/dist/tools/fetch-videos.js +63 -22
- package/dist/tools/fetch-videos.js.map +1 -1
- package/dist/tools/frames-subtitles.d.ts.map +1 -1
- package/dist/tools/frames-subtitles.js +16 -8
- package/dist/tools/frames-subtitles.js.map +1 -1
- package/dist/tools/frames.d.ts +73 -0
- package/dist/tools/frames.d.ts.map +1 -0
- package/dist/tools/frames.js +136 -0
- package/dist/tools/frames.js.map +1 -0
- package/dist/tools/get-channel-info.d.ts +2 -0
- package/dist/tools/get-channel-info.d.ts.map +1 -1
- package/dist/tools/get-channel-info.js +4 -0
- package/dist/tools/get-channel-info.js.map +1 -1
- package/dist/tools/get-comments.d.ts +238 -6
- package/dist/tools/get-comments.d.ts.map +1 -1
- package/dist/tools/get-comments.js +85 -21
- package/dist/tools/get-comments.js.map +1 -1
- package/dist/tools/get-coverage.d.ts +122 -0
- package/dist/tools/get-coverage.d.ts.map +1 -0
- package/dist/tools/get-coverage.js +105 -0
- package/dist/tools/get-coverage.js.map +1 -0
- package/dist/tools/get-sponsor-segments.d.ts +49 -0
- package/dist/tools/get-sponsor-segments.d.ts.map +1 -0
- package/dist/tools/get-sponsor-segments.js +61 -0
- package/dist/tools/get-sponsor-segments.js.map +1 -0
- package/dist/tools/get-thumbnail.d.ts.map +1 -1
- package/dist/tools/get-thumbnail.js +2 -1
- package/dist/tools/get-thumbnail.js.map +1 -1
- package/dist/tools/get-transcript.d.ts +1 -0
- package/dist/tools/get-transcript.d.ts.map +1 -1
- package/dist/tools/get-transcript.js +11 -4
- package/dist/tools/get-transcript.js.map +1 -1
- package/dist/tools/get-video-details.d.ts +118 -0
- package/dist/tools/get-video-details.d.ts.map +1 -0
- package/dist/tools/get-video-details.js +147 -0
- package/dist/tools/get-video-details.js.map +1 -0
- package/dist/tools/gif-concat.d.ts +49 -0
- package/dist/tools/gif-concat.d.ts.map +1 -0
- package/dist/tools/gif-concat.js +96 -0
- package/dist/tools/gif-concat.js.map +1 -0
- package/dist/tools/harvest-channel.d.ts +92 -0
- package/dist/tools/harvest-channel.d.ts.map +1 -0
- package/dist/tools/harvest-channel.js +62 -0
- package/dist/tools/harvest-channel.js.map +1 -0
- package/dist/tools/harvest-comments.d.ts +81 -0
- package/dist/tools/harvest-comments.d.ts.map +1 -0
- package/dist/tools/harvest-comments.js +115 -0
- package/dist/tools/harvest-comments.js.map +1 -0
- package/dist/tools/harvest-details.d.ts +84 -0
- package/dist/tools/harvest-details.d.ts.map +1 -0
- package/dist/tools/harvest-details.js +71 -0
- package/dist/tools/harvest-details.js.map +1 -0
- package/dist/tools/library.js +1 -1
- package/dist/tools/library.js.map +1 -1
- package/dist/tools/list-captions.d.ts +17 -0
- package/dist/tools/list-captions.d.ts.map +1 -0
- package/dist/tools/list-captions.js +60 -0
- package/dist/tools/list-captions.js.map +1 -0
- package/dist/tools/list-channel-playlists.d.ts +30 -0
- package/dist/tools/list-channel-playlists.d.ts.map +1 -0
- package/dist/tools/list-channel-playlists.js +44 -0
- package/dist/tools/list-channel-playlists.js.map +1 -0
- package/dist/tools/list-channel-thumbnails.d.ts +10 -10
- package/dist/tools/list-channel-thumbnails.js +1 -1
- package/dist/tools/list-channel-thumbnails.js.map +1 -1
- package/dist/tools/list-library.js +1 -1
- package/dist/tools/list-library.js.map +1 -1
- package/dist/tools/prune-harvest.d.ts +59 -0
- package/dist/tools/prune-harvest.d.ts.map +1 -0
- package/dist/tools/prune-harvest.js +108 -0
- package/dist/tools/prune-harvest.js.map +1 -0
- package/dist/tools/query-comments.d.ts +125 -0
- package/dist/tools/query-comments.d.ts.map +1 -0
- package/dist/tools/query-comments.js +106 -0
- package/dist/tools/query-comments.js.map +1 -0
- package/dist/tools/query-videos.d.ts +118 -0
- package/dist/tools/query-videos.d.ts.map +1 -0
- package/dist/tools/query-videos.js +97 -0
- package/dist/tools/query-videos.js.map +1 -0
- package/dist/tools/repair-store.d.ts +34 -0
- package/dist/tools/repair-store.d.ts.map +1 -0
- package/dist/tools/repair-store.js +58 -0
- package/dist/tools/repair-store.js.map +1 -0
- package/dist/tools/search-channels.d.ts +6 -0
- package/dist/tools/search-channels.d.ts.map +1 -1
- package/dist/tools/search-channels.js +5 -1
- package/dist/tools/search-channels.js.map +1 -1
- package/dist/tools/search-videos.js +1 -1
- package/dist/tools/search-videos.js.map +1 -1
- package/dist/tools/transcribe-video.d.ts +28 -0
- package/dist/tools/transcribe-video.d.ts.map +1 -0
- package/dist/tools/transcribe-video.js +52 -0
- package/dist/tools/transcribe-video.js.map +1 -0
- package/dist/utils/brain-fusion.d.ts +24 -0
- package/dist/utils/brain-fusion.d.ts.map +1 -0
- package/dist/utils/brain-fusion.js +18 -0
- package/dist/utils/brain-fusion.js.map +1 -0
- package/dist/utils/channel-playlists.d.ts +21 -0
- package/dist/utils/channel-playlists.d.ts.map +1 -0
- package/dist/utils/channel-playlists.js +56 -0
- package/dist/utils/channel-playlists.js.map +1 -0
- package/dist/utils/clips.d.ts.map +1 -1
- package/dist/utils/clips.js +3 -17
- package/dist/utils/clips.js.map +1 -1
- package/dist/utils/comment-store.d.ts +71 -0
- package/dist/utils/comment-store.d.ts.map +1 -0
- package/dist/utils/comment-store.js +129 -0
- package/dist/utils/comment-store.js.map +1 -0
- package/dist/utils/comment-threads.d.ts +51 -0
- package/dist/utils/comment-threads.d.ts.map +1 -0
- package/dist/utils/comment-threads.js +76 -0
- package/dist/utils/comment-threads.js.map +1 -0
- package/dist/utils/concat.d.ts +19 -0
- package/dist/utils/concat.d.ts.map +1 -0
- package/dist/utils/concat.js +135 -0
- package/dist/utils/concat.js.map +1 -0
- package/dist/utils/contact-sheet.d.ts +28 -0
- package/dist/utils/contact-sheet.d.ts.map +1 -0
- package/dist/utils/contact-sheet.js +65 -0
- package/dist/utils/contact-sheet.js.map +1 -0
- package/dist/utils/coverage-text.d.ts +3 -0
- package/dist/utils/coverage-text.d.ts.map +1 -0
- package/dist/utils/coverage-text.js +62 -0
- package/dist/utils/coverage-text.js.map +1 -0
- package/dist/utils/coverage.d.ts +57 -0
- package/dist/utils/coverage.d.ts.map +1 -0
- package/dist/utils/coverage.js +142 -0
- package/dist/utils/coverage.js.map +1 -0
- package/dist/utils/detail-batch.d.ts +25 -0
- package/dist/utils/detail-batch.d.ts.map +1 -0
- package/dist/utils/detail-batch.js +58 -0
- package/dist/utils/detail-batch.js.map +1 -0
- package/dist/utils/errors.d.ts +1 -1
- package/dist/utils/errors.d.ts.map +1 -1
- package/dist/utils/errors.js +19 -1
- package/dist/utils/errors.js.map +1 -1
- package/dist/utils/export-data.d.ts +41 -0
- package/dist/utils/export-data.d.ts.map +1 -0
- package/dist/utils/export-data.js +114 -0
- package/dist/utils/export-data.js.map +1 -0
- package/dist/utils/export-format.d.ts +23 -0
- package/dist/utils/export-format.d.ts.map +1 -0
- package/dist/utils/export-format.js +59 -0
- package/dist/utils/export-format.js.map +1 -0
- package/dist/utils/export-load.d.ts +28 -0
- package/dist/utils/export-load.d.ts.map +1 -0
- package/dist/utils/export-load.js +70 -0
- package/dist/utils/export-load.js.map +1 -0
- package/dist/utils/export-rows.d.ts +35 -0
- package/dist/utils/export-rows.d.ts.map +1 -0
- package/dist/utils/export-rows.js +69 -0
- package/dist/utils/export-rows.js.map +1 -0
- package/dist/utils/ffmpeg.d.ts +26 -0
- package/dist/utils/ffmpeg.d.ts.map +1 -0
- package/dist/utils/ffmpeg.js +28 -0
- package/dist/utils/ffmpeg.js.map +1 -0
- package/dist/utils/format.d.ts +23 -1
- package/dist/utils/format.d.ts.map +1 -1
- package/dist/utils/format.js +5 -1
- package/dist/utils/format.js.map +1 -1
- package/dist/utils/frame-plan.d.ts +24 -0
- package/dist/utils/frame-plan.d.ts.map +1 -0
- package/dist/utils/frame-plan.js +58 -0
- package/dist/utils/frame-plan.js.map +1 -0
- package/dist/utils/frames.d.ts +32 -0
- package/dist/utils/frames.d.ts.map +1 -0
- package/dist/utils/frames.js +60 -0
- package/dist/utils/frames.js.map +1 -0
- package/dist/utils/gif.d.ts +31 -0
- package/dist/utils/gif.d.ts.map +1 -0
- package/dist/utils/gif.js +77 -0
- package/dist/utils/gif.js.map +1 -0
- package/dist/utils/harvest-catalog.d.ts +54 -0
- package/dist/utils/harvest-catalog.d.ts.map +1 -0
- package/dist/utils/harvest-catalog.js +173 -0
- package/dist/utils/harvest-catalog.js.map +1 -0
- package/dist/utils/harvest-details.d.ts +30 -0
- package/dist/utils/harvest-details.d.ts.map +1 -0
- package/dist/utils/harvest-details.js +98 -0
- package/dist/utils/harvest-details.js.map +1 -0
- package/dist/utils/harvest-lock.d.ts +3 -0
- package/dist/utils/harvest-lock.d.ts.map +1 -0
- package/dist/utils/harvest-lock.js +26 -0
- package/dist/utils/harvest-lock.js.map +1 -0
- package/dist/utils/harvest-receipts.d.ts +14 -0
- package/dist/utils/harvest-receipts.d.ts.map +1 -0
- package/dist/utils/harvest-receipts.js +110 -0
- package/dist/utils/harvest-receipts.js.map +1 -0
- package/dist/utils/listing-cursor.d.ts +31 -0
- package/dist/utils/listing-cursor.d.ts.map +1 -0
- package/dist/utils/listing-cursor.js +39 -0
- package/dist/utils/listing-cursor.js.map +1 -0
- package/dist/utils/local-transcription.d.ts +14 -0
- package/dist/utils/local-transcription.d.ts.map +1 -0
- package/dist/utils/local-transcription.js +85 -0
- package/dist/utils/local-transcription.js.map +1 -0
- package/dist/utils/moment.d.ts +24 -0
- package/dist/utils/moment.d.ts.map +1 -0
- package/dist/utils/moment.js +22 -0
- package/dist/utils/moment.js.map +1 -0
- package/dist/utils/most-replayed.d.ts +15 -0
- package/dist/utils/most-replayed.d.ts.map +1 -0
- package/dist/utils/most-replayed.js +25 -0
- package/dist/utils/most-replayed.js.map +1 -0
- package/dist/utils/pot-preflight.d.ts +53 -0
- package/dist/utils/pot-preflight.d.ts.map +1 -0
- package/dist/utils/pot-preflight.js +146 -0
- package/dist/utils/pot-preflight.js.map +1 -0
- package/dist/utils/scenes.d.ts +39 -0
- package/dist/utils/scenes.d.ts.map +1 -0
- package/dist/utils/scenes.js +83 -0
- package/dist/utils/scenes.js.map +1 -0
- package/dist/utils/seconds.d.ts +5 -0
- package/dist/utils/seconds.d.ts.map +1 -0
- package/dist/utils/seconds.js +7 -0
- package/dist/utils/seconds.js.map +1 -0
- package/dist/utils/sleep.d.ts +9 -0
- package/dist/utils/sleep.d.ts.map +1 -0
- package/dist/utils/sleep.js +25 -0
- package/dist/utils/sleep.js.map +1 -0
- package/dist/utils/sponsorblock.d.ts +24 -0
- package/dist/utils/sponsorblock.d.ts.map +1 -0
- package/dist/utils/sponsorblock.js +153 -0
- package/dist/utils/sponsorblock.js.map +1 -0
- package/dist/utils/store-health.d.ts +37 -0
- package/dist/utils/store-health.d.ts.map +1 -0
- package/dist/utils/store-health.js +92 -0
- package/dist/utils/store-health.js.map +1 -0
- package/dist/utils/store-migrations.d.ts +33 -0
- package/dist/utils/store-migrations.d.ts.map +1 -0
- package/dist/utils/store-migrations.js +41 -0
- package/dist/utils/store-migrations.js.map +1 -0
- package/dist/utils/store-paths.d.ts +33 -0
- package/dist/utils/store-paths.d.ts.map +1 -0
- package/dist/utils/store-paths.js +48 -0
- package/dist/utils/store-paths.js.map +1 -0
- package/dist/utils/store-rows.d.ts +22 -0
- package/dist/utils/store-rows.d.ts.map +1 -0
- package/dist/utils/store-rows.js +62 -0
- package/dist/utils/store-rows.js.map +1 -0
- package/dist/utils/store-schema.d.ts +16 -0
- package/dist/utils/store-schema.d.ts.map +1 -0
- package/dist/utils/store-schema.js +168 -0
- package/dist/utils/store-schema.js.map +1 -0
- package/dist/utils/store.d.ts +34 -0
- package/dist/utils/store.d.ts.map +1 -0
- package/dist/utils/store.js +157 -0
- package/dist/utils/store.js.map +1 -0
- package/dist/utils/transcript-cache.d.ts +5 -1
- package/dist/utils/transcript-cache.d.ts.map +1 -1
- package/dist/utils/transcript-cache.js +31 -50
- package/dist/utils/transcript-cache.js.map +1 -1
- package/dist/utils/transcript-files.d.ts +24 -0
- package/dist/utils/transcript-files.d.ts.map +1 -0
- package/dist/utils/transcript-files.js +61 -0
- package/dist/utils/transcript-files.js.map +1 -0
- package/dist/utils/transcript.d.ts +3 -0
- package/dist/utils/transcript.d.ts.map +1 -1
- package/dist/utils/transcript.js +2 -0
- package/dist/utils/transcript.js.map +1 -1
- package/dist/utils/upload-check.d.ts +38 -0
- package/dist/utils/upload-check.d.ts.map +1 -0
- package/dist/utils/upload-check.js +93 -0
- package/dist/utils/upload-check.js.map +1 -0
- package/dist/utils/validate.d.ts +2 -0
- package/dist/utils/validate.d.ts.map +1 -1
- package/dist/utils/validate.js +4 -0
- package/dist/utils/validate.js.map +1 -1
- package/dist/utils/video-detail-store.d.ts +47 -0
- package/dist/utils/video-detail-store.d.ts.map +1 -0
- package/dist/utils/video-detail-store.js +89 -0
- package/dist/utils/video-detail-store.js.map +1 -0
- package/dist/utils/video-stats-cache.d.ts +16 -0
- package/dist/utils/video-stats-cache.d.ts.map +1 -0
- package/dist/utils/video-stats-cache.js +81 -0
- package/dist/utils/video-stats-cache.js.map +1 -0
- package/dist/utils/video-stats-schema.d.ts +187 -0
- package/dist/utils/video-stats-schema.d.ts.map +1 -0
- package/dist/utils/video-stats-schema.js +50 -0
- package/dist/utils/video-stats-schema.js.map +1 -0
- package/dist/utils/video-stats-storage.d.ts +16 -0
- package/dist/utils/video-stats-storage.d.ts.map +1 -0
- package/dist/utils/video-stats-storage.js +37 -0
- package/dist/utils/video-stats-storage.js.map +1 -0
- package/dist/utils/video-stats.d.ts +82 -0
- package/dist/utils/video-stats.d.ts.map +1 -0
- package/dist/utils/video-stats.js +108 -0
- package/dist/utils/video-stats.js.map +1 -0
- package/dist/utils/video-store.d.ts +69 -0
- package/dist/utils/video-store.d.ts.map +1 -0
- package/dist/utils/video-store.js +77 -0
- package/dist/utils/video-store.js.map +1 -0
- package/dist/utils/video-stream.d.ts +21 -0
- package/dist/utils/video-stream.d.ts.map +1 -0
- package/dist/utils/video-stream.js +36 -0
- package/dist/utils/video-stream.js.map +1 -0
- package/dist/utils/whisper.d.ts +39 -0
- package/dist/utils/whisper.d.ts.map +1 -0
- package/dist/utils/whisper.js +137 -0
- package/dist/utils/whisper.js.map +1 -0
- package/dist/utils/youtube-channel.d.ts +13 -2
- package/dist/utils/youtube-channel.d.ts.map +1 -1
- package/dist/utils/youtube-channel.js +39 -3
- package/dist/utils/youtube-channel.js.map +1 -1
- package/dist/utils/youtube-schemas.d.ts +104 -0
- package/dist/utils/youtube-schemas.d.ts.map +1 -1
- package/dist/utils/youtube-schemas.js +32 -0
- package/dist/utils/youtube-schemas.js.map +1 -1
- package/dist/utils/youtube-video.d.ts +22 -1
- package/dist/utils/youtube-video.d.ts.map +1 -1
- package/dist/utils/youtube-video.js +40 -28
- package/dist/utils/youtube-video.js.map +1 -1
- package/dist/utils/ytdlp-limiter.d.ts +3 -0
- package/dist/utils/ytdlp-limiter.d.ts.map +1 -1
- package/dist/utils/ytdlp-limiter.js +19 -3
- package/dist/utils/ytdlp-limiter.js.map +1 -1
- package/dist/utils/ytdlp-pacer.d.ts +64 -0
- package/dist/utils/ytdlp-pacer.d.ts.map +1 -0
- package/dist/utils/ytdlp-pacer.js +165 -0
- package/dist/utils/ytdlp-pacer.js.map +1 -0
- package/dist/utils/ytdlp-stream.d.ts +32 -0
- package/dist/utils/ytdlp-stream.d.ts.map +1 -0
- package/dist/utils/ytdlp-stream.js +61 -0
- package/dist/utils/ytdlp-stream.js.map +1 -0
- package/dist/utils/ytdlp.d.ts +10 -0
- package/dist/utils/ytdlp.d.ts.map +1 -1
- package/dist/utils/ytdlp.js +36 -25
- package/dist/utils/ytdlp.js.map +1 -1
- package/package.json +10 -4
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* How this server reacts to being throttled.
|
|
3
|
+
*
|
|
4
|
+
* The old behaviour was three attempts with at most ~1.5 seconds of jitter and
|
|
5
|
+
* no memory between calls, which is fine for a blip and useless for an
|
|
6
|
+
* hour-long harvest: nothing slowed down, nothing waited, and a hard block
|
|
7
|
+
* produced an hour of identical failures.
|
|
8
|
+
*
|
|
9
|
+
* This adds three things that only make sense across calls — a shared
|
|
10
|
+
* cooldown, an adaptive concurrency ceiling, and a circuit breaker — so the
|
|
11
|
+
* state is deliberately process-global, the same scope as the limiter it
|
|
12
|
+
* cooperates with.
|
|
13
|
+
*/
|
|
14
|
+
export const RATE_LIMIT_COOLDOWN_BASE_MS = 30_000;
|
|
15
|
+
export const RATE_LIMIT_COOLDOWN_MAX_MS = 15 * 60_000;
|
|
16
|
+
export const BOT_CHECK_COOLDOWN_MS = 10 * 60_000;
|
|
17
|
+
export const MAX_BACKOFF_MS = 120_000;
|
|
18
|
+
export const BASE_BACKOFF_MS = 750;
|
|
19
|
+
export const AIMD_MIN_CONCURRENCY = 1;
|
|
20
|
+
export const AIMD_INCREASE_AFTER_SUCCESSES = 20;
|
|
21
|
+
export const AIMD_DECREASE_FACTOR = 0.5;
|
|
22
|
+
/** Consecutive throttles before a global cooldown starts. */
|
|
23
|
+
export const COOLDOWN_AFTER_STRIKES = 2;
|
|
24
|
+
export const CIRCUIT_STRIKES = 5;
|
|
25
|
+
export const CIRCUIT_OPEN_MS = 5 * 60_000;
|
|
26
|
+
const TERMINAL = {
|
|
27
|
+
attempts: 1,
|
|
28
|
+
backoff: 'none',
|
|
29
|
+
cooldown: 'none',
|
|
30
|
+
concurrency: 'none',
|
|
31
|
+
};
|
|
32
|
+
/**
|
|
33
|
+
* What to do about each kind of failure.
|
|
34
|
+
*
|
|
35
|
+
* BOT_CHECK does not retry, and that is measured rather than assumed: from a
|
|
36
|
+
* datacenter address, eight player clients, a fifteen-minute cooldown, a PO
|
|
37
|
+
* token provider and curl_cffi TLS impersonation all returned the same answer.
|
|
38
|
+
* Retrying spends requests on a known-dead path; stopping and naming the cause
|
|
39
|
+
* is the useful response. The cooldown still applies, because whatever else is
|
|
40
|
+
* in flight should not keep hammering.
|
|
41
|
+
*/
|
|
42
|
+
const POLICIES = {
|
|
43
|
+
RATE_LIMITED: {
|
|
44
|
+
attempts: 5,
|
|
45
|
+
backoff: 'exponential',
|
|
46
|
+
cooldown: 'rate-limit',
|
|
47
|
+
concurrency: 'decrease',
|
|
48
|
+
},
|
|
49
|
+
BOT_CHECK: { attempts: 1, backoff: 'none', cooldown: 'bot-check', concurrency: 'floor' },
|
|
50
|
+
TIMEOUT: { attempts: 3, backoff: 'exponential', cooldown: 'none', concurrency: 'decrease' },
|
|
51
|
+
// Deliberately absent: an unclassified yt-dlp failure carries no evidence
|
|
52
|
+
// that a second attempt would go differently, and `retryable` is false on it,
|
|
53
|
+
// so it falls through to TERMINAL. Listing it here with attempts > 1 would
|
|
54
|
+
// state a policy the retry loop correctly refuses to honour.
|
|
55
|
+
};
|
|
56
|
+
export function policyFor(code) {
|
|
57
|
+
return POLICIES[code] ?? TERMINAL;
|
|
58
|
+
}
|
|
59
|
+
let state = {
|
|
60
|
+
cooldownUntil: 0,
|
|
61
|
+
circuitOpenUntil: 0,
|
|
62
|
+
strikes: 0,
|
|
63
|
+
successes: 0,
|
|
64
|
+
concurrency: Number.POSITIVE_INFINITY,
|
|
65
|
+
};
|
|
66
|
+
/** ±25% so parallel callers do not come back in lockstep. */
|
|
67
|
+
function jitter(ms) {
|
|
68
|
+
return Math.round(ms * (0.75 + Math.random() * 0.5));
|
|
69
|
+
}
|
|
70
|
+
function cooldownFor(kind, strikes) {
|
|
71
|
+
if (kind === 'none')
|
|
72
|
+
return 0;
|
|
73
|
+
if (kind === 'bot-check')
|
|
74
|
+
return BOT_CHECK_COOLDOWN_MS;
|
|
75
|
+
const escalated = RATE_LIMIT_COOLDOWN_BASE_MS * 2 ** Math.max(0, strikes - 1);
|
|
76
|
+
return jitter(Math.min(escalated, RATE_LIMIT_COOLDOWN_MAX_MS));
|
|
77
|
+
}
|
|
78
|
+
export function backoffDelay(attempt, style) {
|
|
79
|
+
if (style === 'none')
|
|
80
|
+
return 0;
|
|
81
|
+
// Exponential with full jitter, capped so a long run cannot stall for hours.
|
|
82
|
+
const ceiling = Math.min(BASE_BACKOFF_MS * 2 ** (attempt - 1), MAX_BACKOFF_MS);
|
|
83
|
+
return Math.round(Math.random() * ceiling);
|
|
84
|
+
}
|
|
85
|
+
/** Records a failure and says whether to try again, and after how long. */
|
|
86
|
+
export function onFailure(code, attempt, now = Date.now()) {
|
|
87
|
+
const policy = policyFor(code);
|
|
88
|
+
const throttled = policy.cooldown !== 'none';
|
|
89
|
+
if (throttled) {
|
|
90
|
+
state.strikes += 1;
|
|
91
|
+
state.successes = 0;
|
|
92
|
+
// A first strike gets the exponential backoff and nothing more: one 429 is
|
|
93
|
+
// a blip, and making a single interactive call wait out a 30-second global
|
|
94
|
+
// cooldown would be worse than the problem. The cooldown starts once the
|
|
95
|
+
// client has been refused twice in a row, which is when it has stopped
|
|
96
|
+
// being a blip. A bot check skips the grace: it was measured not to clear
|
|
97
|
+
// on its own, so there is nothing to be gained by trying again sooner.
|
|
98
|
+
const grace = policy.cooldown === 'bot-check' ? 1 : COOLDOWN_AFTER_STRIKES;
|
|
99
|
+
if (state.strikes >= grace) {
|
|
100
|
+
state.cooldownUntil = Math.max(state.cooldownUntil, now + cooldownFor(policy.cooldown, state.strikes));
|
|
101
|
+
}
|
|
102
|
+
if (policy.concurrency === 'floor') {
|
|
103
|
+
state.concurrency = AIMD_MIN_CONCURRENCY;
|
|
104
|
+
}
|
|
105
|
+
else if (policy.concurrency === 'decrease') {
|
|
106
|
+
state.concurrency = Math.max(AIMD_MIN_CONCURRENCY, Math.floor(effectiveConcurrency(now) * AIMD_DECREASE_FACTOR));
|
|
107
|
+
}
|
|
108
|
+
if (state.strikes >= CIRCUIT_STRIKES) {
|
|
109
|
+
state.circuitOpenUntil = now + CIRCUIT_OPEN_MS;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
return attempt >= policy.attempts
|
|
113
|
+
? { giveUp: true, delayMs: 0 }
|
|
114
|
+
: { giveUp: false, delayMs: backoffDelay(attempt, policy.backoff) };
|
|
115
|
+
}
|
|
116
|
+
/** Records a clean spawn, easing the ceiling back up one step at a time. */
|
|
117
|
+
export function onSuccess() {
|
|
118
|
+
state.strikes = 0;
|
|
119
|
+
state.successes += 1;
|
|
120
|
+
if (state.successes >= AIMD_INCREASE_AFTER_SUCCESSES) {
|
|
121
|
+
state.successes = 0;
|
|
122
|
+
if (Number.isFinite(state.concurrency))
|
|
123
|
+
state.concurrency += 1;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
/** How long a caller should wait before spawning, in milliseconds. */
|
|
127
|
+
export function waitMs(now = Date.now()) {
|
|
128
|
+
if (state.circuitOpenUntil > now)
|
|
129
|
+
return state.circuitOpenUntil - now;
|
|
130
|
+
return Math.max(0, state.cooldownUntil - now);
|
|
131
|
+
}
|
|
132
|
+
export function circuitOpen(now = Date.now()) {
|
|
133
|
+
return state.circuitOpenUntil > now;
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* The ceiling the limiter should honour right now.
|
|
137
|
+
*
|
|
138
|
+
* Infinite until something throttles us, so an untroubled server runs at
|
|
139
|
+
* whatever YOUTUBE_MCP_MAX_CONCURRENCY allows and the limiter stays the only
|
|
140
|
+
* authority on the normal case.
|
|
141
|
+
*/
|
|
142
|
+
export function effectiveConcurrency(now = Date.now()) {
|
|
143
|
+
if (circuitOpen(now))
|
|
144
|
+
return AIMD_MIN_CONCURRENCY;
|
|
145
|
+
return state.concurrency;
|
|
146
|
+
}
|
|
147
|
+
export function pacerState(now = Date.now()) {
|
|
148
|
+
return {
|
|
149
|
+
cooldownMs: waitMs(now),
|
|
150
|
+
circuitOpen: circuitOpen(now),
|
|
151
|
+
strikes: state.strikes,
|
|
152
|
+
concurrency: effectiveConcurrency(now),
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
/** Test seam; the pacer is process-global in normal use. */
|
|
156
|
+
export function resetPacer() {
|
|
157
|
+
state = {
|
|
158
|
+
cooldownUntil: 0,
|
|
159
|
+
circuitOpenUntil: 0,
|
|
160
|
+
strikes: 0,
|
|
161
|
+
successes: 0,
|
|
162
|
+
concurrency: Number.POSITIVE_INFINITY,
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
//# sourceMappingURL=ytdlp-pacer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ytdlp-pacer.js","sourceRoot":"","sources":["../../src/utils/ytdlp-pacer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Running yt-dlp and reading its output a line at a time.
|
|
3
|
+
*
|
|
4
|
+
* `runYtDlp` buffers everything into a string, which is right for a metadata
|
|
5
|
+
* read and wrong for a long walk: a 40,000-entry channel listing killed at
|
|
6
|
+
* minute nine yields nothing at all, and the 64MB buffer is a hard ceiling.
|
|
7
|
+
*
|
|
8
|
+
* Here each line is handed over as it arrives, so a caller can checkpoint as
|
|
9
|
+
* it goes and keep what it already had. Paired with `--lazy-playlist`, which
|
|
10
|
+
* makes yt-dlp emit entries while it walks rather than after.
|
|
11
|
+
*/
|
|
12
|
+
export interface StreamOptions {
|
|
13
|
+
label?: string;
|
|
14
|
+
timeoutMs?: number;
|
|
15
|
+
target: string;
|
|
16
|
+
/** Called per line, in order. A throw here aborts the walk. */
|
|
17
|
+
onLine: (line: string) => void;
|
|
18
|
+
}
|
|
19
|
+
export interface StreamResult {
|
|
20
|
+
lines: number;
|
|
21
|
+
/** False when the walk was cut short, so the caller knows not to claim completeness. */
|
|
22
|
+
completed: boolean;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Streams stdout line by line.
|
|
26
|
+
*
|
|
27
|
+
* A failure part-way through is not thrown away: the caller keeps every line
|
|
28
|
+
* delivered so far and is told the walk did not complete, which is the whole
|
|
29
|
+
* point of streaming rather than buffering.
|
|
30
|
+
*/
|
|
31
|
+
export declare function runYtDlpLines(args: string[], options: StreamOptions): Promise<StreamResult>;
|
|
32
|
+
//# sourceMappingURL=ytdlp-stream.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ytdlp-stream.d.ts","sourceRoot":"","sources":["../../src/utils/ytdlp-stream.ts"],"names":[],"mappings":"AAQA;;;;;;;;;;GAUG;AAEH,MAAM,WAAW,aAAa;IAC5B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,+DAA+D;IAC/D,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CAChC;AAED,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,wFAAwF;IACxF,SAAS,EAAE,OAAO,CAAC;CACpB;AAED;;;;;;GAMG;AACH,wBAAsB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,YAAY,CAAC,CA+CjG"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { execa } from 'execa';
|
|
2
|
+
import { createInterface } from 'node:readline';
|
|
3
|
+
import { currentContext } from './context.js';
|
|
4
|
+
import { acquireSlot, releaseSlot } from './ytdlp-limiter.js';
|
|
5
|
+
import { readYtDlpEnv } from './ytdlp-env.js';
|
|
6
|
+
import { YouTubeError } from './errors.js';
|
|
7
|
+
import { SOCKET_TIMEOUT_S } from './ytdlp.js';
|
|
8
|
+
/**
|
|
9
|
+
* Streams stdout line by line.
|
|
10
|
+
*
|
|
11
|
+
* A failure part-way through is not thrown away: the caller keeps every line
|
|
12
|
+
* delivered so far and is told the walk did not complete, which is the whole
|
|
13
|
+
* point of streaming rather than buffering.
|
|
14
|
+
*/
|
|
15
|
+
export async function runYtDlpLines(args, options) {
|
|
16
|
+
const { timeoutMs = 0, target, onLine } = options;
|
|
17
|
+
const { signal } = currentContext();
|
|
18
|
+
if (signal?.aborted === true) {
|
|
19
|
+
throw new YouTubeError('CANCELLED', 'The request was cancelled.');
|
|
20
|
+
}
|
|
21
|
+
await acquireSlot(signal);
|
|
22
|
+
let lines = 0;
|
|
23
|
+
try {
|
|
24
|
+
const argv = [
|
|
25
|
+
'--socket-timeout',
|
|
26
|
+
SOCKET_TIMEOUT_S,
|
|
27
|
+
...readYtDlpEnv().args,
|
|
28
|
+
...args,
|
|
29
|
+
'--',
|
|
30
|
+
target,
|
|
31
|
+
];
|
|
32
|
+
const child = execa('yt-dlp', argv, {
|
|
33
|
+
timeout: timeoutMs > 0 ? timeoutMs : undefined,
|
|
34
|
+
cancelSignal: signal,
|
|
35
|
+
buffer: false,
|
|
36
|
+
stdout: 'pipe',
|
|
37
|
+
});
|
|
38
|
+
// `stdout: 'pipe'` with `buffer: false` guarantees a stream here, so there
|
|
39
|
+
// is nothing to guard against.
|
|
40
|
+
const reader = createInterface({ input: child.stdout, crlfDelay: Infinity });
|
|
41
|
+
for await (const line of reader) {
|
|
42
|
+
if (line.trim() === '')
|
|
43
|
+
continue;
|
|
44
|
+
onLine(line);
|
|
45
|
+
lines += 1;
|
|
46
|
+
}
|
|
47
|
+
await child;
|
|
48
|
+
return { lines, completed: true };
|
|
49
|
+
}
|
|
50
|
+
catch (error) {
|
|
51
|
+
// Everything delivered so far is already the caller's. Reporting how far
|
|
52
|
+
// it got matters more than the reason, which the caller can classify.
|
|
53
|
+
if (error instanceof YouTubeError)
|
|
54
|
+
throw error;
|
|
55
|
+
return { lines, completed: false };
|
|
56
|
+
}
|
|
57
|
+
finally {
|
|
58
|
+
releaseSlot();
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=ytdlp-stream.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ytdlp-stream.js","sourceRoot":"","sources":["../../src/utils/ytdlp-stream.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,OAAO,CAAC;AAC9B,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAC9D,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AA4B9C;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,IAAc,EAAE,OAAsB;IACxE,MAAM,EAAE,SAAS,GAAG,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC;IAClD,MAAM,EAAE,MAAM,EAAE,GAAG,cAAc,EAAE,CAAC;IAEpC,IAAI,MAAM,EAAE,OAAO,KAAK,IAAI,EAAE,CAAC;QAC7B,MAAM,IAAI,YAAY,CAAC,WAAW,EAAE,4BAA4B,CAAC,CAAC;IACpE,CAAC;IAED,MAAM,WAAW,CAAC,MAAM,CAAC,CAAC;IAC1B,IAAI,KAAK,GAAG,CAAC,CAAC;IAEd,IAAI,CAAC;QACH,MAAM,IAAI,GAAG;YACX,kBAAkB;YAClB,gBAAgB;YAChB,GAAG,YAAY,EAAE,CAAC,IAAI;YACtB,GAAG,IAAI;YACP,IAAI;YACJ,MAAM;SACP,CAAC;QAEF,MAAM,KAAK,GAAG,KAAK,CAAC,QAAQ,EAAE,IAAI,EAAE;YAClC,OAAO,EAAE,SAAS,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS;YAC9C,YAAY,EAAE,MAAM;YACpB,MAAM,EAAE,KAAK;YACb,MAAM,EAAE,MAAM;SACf,CAAC,CAAC;QAEH,2EAA2E;QAC3E,+BAA+B;QAC/B,MAAM,MAAM,GAAG,eAAe,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC,CAAC;QAC7E,IAAI,KAAK,EAAE,MAAM,IAAI,IAAI,MAAM,EAAE,CAAC;YAChC,IAAI,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE;gBAAE,SAAS;YACjC,MAAM,CAAC,IAAI,CAAC,CAAC;YACb,KAAK,IAAI,CAAC,CAAC;QACb,CAAC;QAED,MAAM,KAAK,CAAC;QACZ,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;IACpC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,yEAAyE;QACzE,sEAAsE;QACtE,IAAI,KAAK,YAAY,YAAY;YAAE,MAAM,KAAK,CAAC;QAC/C,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;IACrC,CAAC;YAAS,CAAC;QACT,WAAW,EAAE,CAAC;IAChB,CAAC;AACH,CAAC"}
|
package/dist/utils/ytdlp.d.ts
CHANGED
|
@@ -19,6 +19,16 @@ export declare const TIMEOUTS: {
|
|
|
19
19
|
/** Media transfers: unbounded here; cancellation is the client's lever. */
|
|
20
20
|
readonly download: 0;
|
|
21
21
|
};
|
|
22
|
+
/**
|
|
23
|
+
* Seconds of socket inactivity before yt-dlp gives up on a connection.
|
|
24
|
+
*
|
|
25
|
+
* Media transfers deliberately run without a wall-clock timeout — a long clip
|
|
26
|
+
* is allowed to take as long as it honestly takes — which left a dead
|
|
27
|
+
* connection indistinguishable from a slow one, holding its concurrency slot
|
|
28
|
+
* forever. This bounds the silence, not the work: a transfer still making
|
|
29
|
+
* progress is never interrupted.
|
|
30
|
+
*/
|
|
31
|
+
export declare const SOCKET_TIMEOUT_S = "30";
|
|
22
32
|
export interface RunOptions {
|
|
23
33
|
/** Milliseconds before the child is killed. 0 disables the timeout. */
|
|
24
34
|
timeoutMs?: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ytdlp.d.ts","sourceRoot":"","sources":["../../src/utils/ytdlp.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ytdlp.d.ts","sourceRoot":"","sources":["../../src/utils/ytdlp.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAEvE;;;;;;;GAOG;AAEH,kFAAkF;AAClF,eAAO,MAAM,QAAQ;IACnB,wDAAwD;;IAExD,gDAAgD;;IAEhD,iEAAiE;;IAEjE,2EAA2E;;CAEnE,CAAC;AAMX;;;;;;;;GAQG;AACH,eAAO,MAAM,gBAAgB,OAAO,CAAC;AAErC,MAAM,WAAW,UAAU;IACzB,uEAAuE;IACvE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,iFAAiF;IACjF,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,wDAAwD;IACxD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;;;OAMG;IACH,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;GAMG;AACH,wBAAsB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CA8DnF"}
|
package/dist/utils/ytdlp.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { execa, ExecaError } from 'execa';
|
|
2
2
|
import { currentContext, log } from './context.js';
|
|
3
|
+
import { sleep } from './sleep.js';
|
|
4
|
+
import { circuitOpen, onFailure, onSuccess, waitMs } from './ytdlp-pacer.js';
|
|
3
5
|
import { YouTubeError, classifyYtDlpFailure } from './errors.js';
|
|
4
6
|
import { acquireSlot, releaseSlot } from './ytdlp-limiter.js';
|
|
5
7
|
import { readYtDlpEnv } from './ytdlp-env.js';
|
|
@@ -25,7 +27,6 @@ export const TIMEOUTS = {
|
|
|
25
27
|
download: 0,
|
|
26
28
|
};
|
|
27
29
|
const MAX_ATTEMPTS = 3;
|
|
28
|
-
const BASE_BACKOFF_MS = 750;
|
|
29
30
|
/** Guards against a pathological video description blowing up memory. */
|
|
30
31
|
const MAX_OUTPUT_BYTES = 64 * 1024 * 1024;
|
|
31
32
|
/**
|
|
@@ -37,25 +38,7 @@ const MAX_OUTPUT_BYTES = 64 * 1024 * 1024;
|
|
|
37
38
|
* forever. This bounds the silence, not the work: a transfer still making
|
|
38
39
|
* progress is never interrupted.
|
|
39
40
|
*/
|
|
40
|
-
const SOCKET_TIMEOUT_S = '30';
|
|
41
|
-
function backoffDelay(attempt) {
|
|
42
|
-
// Exponential with full jitter, so parallel callers do not retry in lockstep.
|
|
43
|
-
const ceiling = BASE_BACKOFF_MS * 2 ** (attempt - 1);
|
|
44
|
-
return Math.round(Math.random() * ceiling);
|
|
45
|
-
}
|
|
46
|
-
async function sleep(ms, signal) {
|
|
47
|
-
await new Promise((resolve, reject) => {
|
|
48
|
-
const timer = setTimeout(() => {
|
|
49
|
-
signal?.removeEventListener('abort', onAbort);
|
|
50
|
-
resolve();
|
|
51
|
-
}, ms);
|
|
52
|
-
const onAbort = () => {
|
|
53
|
-
clearTimeout(timer);
|
|
54
|
-
reject(new YouTubeError('CANCELLED', 'The request was cancelled.'));
|
|
55
|
-
};
|
|
56
|
-
signal?.addEventListener('abort', onAbort, { once: true });
|
|
57
|
-
});
|
|
58
|
-
}
|
|
41
|
+
export const SOCKET_TIMEOUT_S = '30';
|
|
59
42
|
/**
|
|
60
43
|
* Run yt-dlp and return its stdout.
|
|
61
44
|
*
|
|
@@ -74,17 +57,45 @@ export async function runYtDlp(args, options) {
|
|
|
74
57
|
if (signal?.aborted === true) {
|
|
75
58
|
throw new YouTubeError('CANCELLED', 'The request was cancelled.');
|
|
76
59
|
}
|
|
60
|
+
// The cooldown gates NEW work, not this call's own retries: it applies on
|
|
61
|
+
// the first attempt only. Mixing the two would make a single call's latency
|
|
62
|
+
// unbounded — its retry would wait out a global cooldown that exists to
|
|
63
|
+
// slow the *next* caller down. Retries use the backoff.
|
|
64
|
+
//
|
|
65
|
+
// Deliberately outside the try: an open circuit is this server's own
|
|
66
|
+
// decision, not a spawn failure, and letting the catch below translate and
|
|
67
|
+
// retry it would spawn the very request the circuit exists to prevent.
|
|
68
|
+
// Waiting also happens before a slot is taken, so a cooling-down server
|
|
69
|
+
// does not sit on the concurrency queue while it waits.
|
|
70
|
+
const wait = attempt === 1 ? waitMs() : 0;
|
|
71
|
+
if (wait > 0) {
|
|
72
|
+
if (circuitOpen()) {
|
|
73
|
+
throw new YouTubeError('RATE_LIMITED', 'YouTube has refused this client repeatedly, so requests are paused.', {
|
|
74
|
+
nextStep: `Wait about ${String(Math.ceil(wait / 60_000))} minutes. If it persists this address is likely being gated: check check_health for the cookie and PO token provider settings.`,
|
|
75
|
+
retryable: true,
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
log('info', `${label} waiting ${String(wait)}ms before spawning`);
|
|
79
|
+
await sleep(wait, signal);
|
|
80
|
+
}
|
|
77
81
|
try {
|
|
78
|
-
|
|
82
|
+
const stdout = await spawnOnce(args, target, timeoutMs, signal);
|
|
83
|
+
onSuccess();
|
|
84
|
+
return stdout;
|
|
79
85
|
}
|
|
80
86
|
catch (error) {
|
|
81
87
|
const failure = translateExecaFailure(error, timeoutMs);
|
|
82
|
-
|
|
88
|
+
const decision = onFailure(failure.code, attempt);
|
|
89
|
+
// The error's own `retryable` wins over the pacer's policy. The
|
|
90
|
+
// classifier read the stderr and knows whether a retry can help; the
|
|
91
|
+
// pacer only knows the code. Dropping this gate made every unclassified
|
|
92
|
+
// YTDLP_FAILED retry, doubling requests on exactly the failures we cannot
|
|
93
|
+
// diagnose — the opposite of the point.
|
|
94
|
+
if (!failure.retryable || decision.giveUp || attempt >= maxAttempts)
|
|
83
95
|
throw failure;
|
|
84
|
-
|
|
85
|
-
log('warning', `${label} failed (${failure.code}), retrying in ${delay}ms`);
|
|
96
|
+
log('warning', `${label} failed (${failure.code}), retrying in ${String(decision.delayMs)}ms`);
|
|
86
97
|
// The slot is already released, so the backoff does not hold the queue.
|
|
87
|
-
await sleep(
|
|
98
|
+
await sleep(decision.delayMs, signal);
|
|
88
99
|
}
|
|
89
100
|
}
|
|
90
101
|
}
|
package/dist/utils/ytdlp.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ytdlp.js","sourceRoot":"","sources":["../../src/utils/ytdlp.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,OAAO,CAAC;AAC1C,OAAO,EAAE,cAAc,EAAE,GAAG,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,EAAE,YAAY,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AACjE,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAC9D,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAE9C,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAEvE;;;;;;;GAOG;AAEH,kFAAkF;AAClF,MAAM,CAAC,MAAM,QAAQ,GAAG;IACtB,wDAAwD;IACxD,QAAQ,EAAE,MAAM;IAChB,gDAAgD;IAChD,UAAU,EAAE,MAAM;IAClB,iEAAiE;IACjE,QAAQ,EAAE,OAAO;IACjB,2EAA2E;IAC3E,QAAQ,EAAE,CAAC;CACH,CAAC;AAEX,MAAM,YAAY,GAAG,CAAC,CAAC;AACvB,
|
|
1
|
+
{"version":3,"file":"ytdlp.js","sourceRoot":"","sources":["../../src/utils/ytdlp.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "youtube-knowledge-mcp",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.1",
|
|
4
4
|
"description": "MCP Server for extracting and managing YouTube video knowledge",
|
|
5
5
|
"author": "teobouancheau",
|
|
6
6
|
"repository": {
|
|
@@ -42,9 +42,13 @@
|
|
|
42
42
|
"test:coverage": "vitest run --coverage",
|
|
43
43
|
"test:e2e": "npm run build && vitest run -c vitest.e2e.config.ts",
|
|
44
44
|
"typecheck": "tsc --noEmit",
|
|
45
|
-
"validate": "npm run typecheck && npm run lint && npm run format:check && npm run test:coverage",
|
|
45
|
+
"validate": "npm run secrets && npm run typecheck && npm run lint && npm run format:check && npm run test:coverage",
|
|
46
46
|
"prepare": "husky",
|
|
47
|
-
"prepublishOnly": "npm run rebuild && npm run validate"
|
|
47
|
+
"prepublishOnly": "npm run rebuild && npm run validate",
|
|
48
|
+
"render:icon": "node scripts/render-icon.mjs",
|
|
49
|
+
"secrets": "sh scripts/secret-scan.sh tree",
|
|
50
|
+
"audit": "npm audit --audit-level=moderate",
|
|
51
|
+
"smoke": "npm run build && node scripts/smoke.mjs"
|
|
48
52
|
},
|
|
49
53
|
"files": [
|
|
50
54
|
"dist"
|
|
@@ -66,6 +70,8 @@
|
|
|
66
70
|
"zod": "^3.25.0"
|
|
67
71
|
},
|
|
68
72
|
"devDependencies": {
|
|
73
|
+
"@commitlint/cli": "^21.2.3",
|
|
74
|
+
"@commitlint/config-conventional": "^21.2.3",
|
|
69
75
|
"@eslint/js": "^10.0.1",
|
|
70
76
|
"@types/express": "^5.0.6",
|
|
71
77
|
"@types/node": "^22.20.1",
|
|
@@ -83,6 +89,6 @@
|
|
|
83
89
|
"vitest": "^4.1.10"
|
|
84
90
|
},
|
|
85
91
|
"engines": {
|
|
86
|
-
"node": ">=22.
|
|
92
|
+
"node": ">=22.13.0"
|
|
87
93
|
}
|
|
88
94
|
}
|