vidspotai-shared 1.0.82-dev.0 → 1.0.83
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/lib/globals/aiModels/enums.d.ts +11 -1
- package/lib/globals/aiModels/enums.d.ts.map +1 -1
- package/lib/globals/aiModels/enums.js +24 -1
- package/lib/globals/aiModels/index.d.ts.map +1 -1
- package/lib/globals/aiModels/index.js +2 -0
- package/lib/globals/aiModels/providers/anthropic.d.ts +12 -0
- package/lib/globals/aiModels/providers/anthropic.d.ts.map +1 -0
- package/lib/globals/aiModels/providers/anthropic.js +88 -0
- package/lib/globals/aiModels/providers/google.d.ts.map +1 -1
- package/lib/globals/aiModels/providers/google.js +115 -10
- package/lib/globals/aiModels/providers/openai.d.ts.map +1 -1
- package/lib/globals/aiModels/providers/openai.js +63 -4
- package/lib/globals/aiModels/tierHelpers.d.ts +12 -0
- package/lib/globals/aiModels/tierHelpers.d.ts.map +1 -1
- package/lib/globals/aiModels/tierHelpers.js +83 -0
- package/lib/globals/aiModels/types.d.ts +19 -0
- package/lib/globals/aiModels/types.d.ts.map +1 -1
- package/lib/globals/types.d.ts +120 -1
- package/lib/globals/types.d.ts.map +1 -1
- package/lib/globals/types.js +135 -1
- package/lib/models/agent.model.d.ts +41 -1
- package/lib/models/agent.model.d.ts.map +1 -1
- package/lib/models/index.d.ts +1 -0
- package/lib/models/index.d.ts.map +1 -1
- package/lib/models/index.js +1 -0
- package/lib/models/social.model.d.ts +180 -0
- package/lib/models/social.model.d.ts.map +1 -0
- package/lib/models/social.model.js +2 -0
- package/lib/models/user.model.d.ts +10 -0
- package/lib/models/user.model.d.ts.map +1 -1
- package/lib/models/video.model.d.ts +6 -0
- package/lib/models/video.model.d.ts.map +1 -1
- package/lib/schemas/brief.schema.d.ts +46 -0
- package/lib/schemas/brief.schema.d.ts.map +1 -1
- package/lib/schemas/brief.schema.js +72 -1
- package/lib/schemas/index.d.ts +1 -0
- package/lib/schemas/index.d.ts.map +1 -1
- package/lib/schemas/index.js +1 -0
- package/lib/schemas/project.schema.d.ts +70 -3
- package/lib/schemas/project.schema.d.ts.map +1 -1
- package/lib/schemas/project.schema.js +12 -0
- package/lib/schemas/social.schema.d.ts +91 -0
- package/lib/schemas/social.schema.d.ts.map +1 -0
- package/lib/schemas/social.schema.js +114 -0
- package/lib/schemas/videoPlan.schema.d.ts +117 -3
- package/lib/schemas/videoPlan.schema.d.ts.map +1 -1
- package/lib/schemas/videoPlan.schema.js +141 -1
- package/lib/services/agent/chatAgent.d.ts +25 -1
- package/lib/services/agent/chatAgent.d.ts.map +1 -1
- package/lib/services/agent/chatAgent.js +145 -9
- package/lib/services/agent/costPreflight.d.ts +11 -1
- package/lib/services/agent/costPreflight.d.ts.map +1 -1
- package/lib/services/agent/costPreflight.js +18 -1
- package/lib/services/agent/covers/coverPlanner.d.ts +41 -0
- package/lib/services/agent/covers/coverPlanner.d.ts.map +1 -0
- package/lib/services/agent/covers/coverPlanner.js +278 -0
- package/lib/services/agent/covers/covers.schema.d.ts +158 -0
- package/lib/services/agent/covers/covers.schema.d.ts.map +1 -0
- package/lib/services/agent/covers/covers.schema.js +166 -0
- package/lib/services/agent/covers/index.d.ts +3 -0
- package/lib/services/agent/covers/index.d.ts.map +1 -0
- package/lib/services/agent/covers/index.js +18 -0
- package/lib/services/agent/critic.d.ts +10 -0
- package/lib/services/agent/critic.d.ts.map +1 -1
- package/lib/services/agent/critic.js +37 -1
- package/lib/services/agent/editClassifier.d.ts +4 -4
- package/lib/services/agent/editClassifier.js +2 -2
- package/lib/services/agent/editExisting/editAssembler.d.ts +78 -0
- package/lib/services/agent/editExisting/editAssembler.d.ts.map +1 -0
- package/lib/services/agent/editExisting/editAssembler.js +172 -0
- package/lib/services/agent/editExisting/editExisting.schema.d.ts +119 -0
- package/lib/services/agent/editExisting/editExisting.schema.d.ts.map +1 -0
- package/lib/services/agent/editExisting/editExisting.schema.js +157 -0
- package/lib/services/agent/editExisting/highlightPicker.d.ts +48 -0
- package/lib/services/agent/editExisting/highlightPicker.d.ts.map +1 -0
- package/lib/services/agent/editExisting/highlightPicker.js +199 -0
- package/lib/services/agent/editExisting/index.d.ts +4 -0
- package/lib/services/agent/editExisting/index.d.ts.map +1 -0
- package/lib/services/agent/editExisting/index.js +19 -0
- package/lib/services/agent/eval/recorder.d.ts +13 -1
- package/lib/services/agent/eval/recorder.d.ts.map +1 -1
- package/lib/services/agent/eval/recorder.js +59 -0
- package/lib/services/agent/eval/seedBriefs.d.ts +4 -3
- package/lib/services/agent/eval/seedBriefs.d.ts.map +1 -1
- package/lib/services/agent/eval/seedBriefs.js +283 -3
- package/lib/services/agent/eval/types.d.ts +10 -0
- package/lib/services/agent/eval/types.d.ts.map +1 -1
- package/lib/services/agent/executor/core.d.ts +70 -0
- package/lib/services/agent/executor/core.d.ts.map +1 -0
- package/lib/services/agent/executor/core.js +250 -0
- package/lib/services/agent/executor/duration.d.ts +20 -0
- package/lib/services/agent/executor/duration.d.ts.map +1 -0
- package/lib/services/agent/executor/duration.js +46 -0
- package/lib/services/agent/executor/index.d.ts +15 -0
- package/lib/services/agent/executor/index.d.ts.map +1 -0
- package/lib/services/agent/executor/index.js +32 -0
- package/lib/services/agent/executor/types.d.ts +183 -0
- package/lib/services/agent/executor/types.d.ts.map +1 -0
- package/lib/services/agent/executor/types.js +29 -0
- package/lib/services/agent/executor/visual.d.ts +32 -0
- package/lib/services/agent/executor/visual.d.ts.map +1 -0
- package/lib/services/agent/executor/visual.js +400 -0
- package/lib/services/agent/executor/voice.d.ts +17 -0
- package/lib/services/agent/executor/voice.d.ts.map +1 -0
- package/lib/services/agent/executor/voice.js +119 -0
- package/lib/services/agent/extendChain.d.ts +101 -0
- package/lib/services/agent/extendChain.d.ts.map +1 -0
- package/lib/services/agent/extendChain.js +177 -0
- package/lib/services/agent/index.d.ts +11 -1
- package/lib/services/agent/index.d.ts.map +1 -1
- package/lib/services/agent/index.js +11 -1
- package/lib/services/agent/llmCaller.d.ts +7 -8
- package/lib/services/agent/llmCaller.d.ts.map +1 -1
- package/lib/services/agent/llmCallerAnthropic.d.ts +44 -31
- package/lib/services/agent/llmCallerAnthropic.d.ts.map +1 -1
- package/lib/services/agent/llmCallerAnthropic.js +135 -60
- package/lib/services/agent/llmCallerFactory.d.ts +34 -0
- package/lib/services/agent/llmCallerFactory.d.ts.map +1 -0
- package/lib/services/agent/llmCallerFactory.js +31 -0
- package/lib/services/agent/llmCallerGemini.d.ts +62 -0
- package/lib/services/agent/llmCallerGemini.d.ts.map +1 -0
- package/lib/services/agent/llmCallerGemini.js +235 -0
- package/lib/services/agent/llmCallerOpenai.d.ts +56 -0
- package/lib/services/agent/llmCallerOpenai.d.ts.map +1 -0
- package/lib/services/agent/llmCallerOpenai.js +230 -0
- package/lib/services/agent/llmCallerRegistry.d.ts.map +1 -1
- package/lib/services/agent/llmCallerRegistry.js +7 -7
- package/lib/services/agent/llmCallerRouting.d.ts +63 -0
- package/lib/services/agent/llmCallerRouting.d.ts.map +1 -0
- package/lib/services/agent/llmCallerRouting.js +124 -0
- package/lib/services/agent/llmModelRegistry.d.ts +59 -0
- package/lib/services/agent/llmModelRegistry.d.ts.map +1 -0
- package/lib/services/agent/llmModelRegistry.js +168 -0
- package/lib/services/agent/llmRetry.d.ts +57 -0
- package/lib/services/agent/llmRetry.d.ts.map +1 -0
- package/lib/services/agent/llmRetry.js +102 -0
- package/lib/services/agent/modelRouter.d.ts +3 -3
- package/lib/services/agent/modelRouter.d.ts.map +1 -1
- package/lib/services/agent/modelRouter.js +27 -13
- package/lib/services/agent/planMutations.d.ts +54 -1
- package/lib/services/agent/planMutations.d.ts.map +1 -1
- package/lib/services/agent/planMutations.js +78 -0
- package/lib/services/agent/planner/Planner.d.ts +0 -17
- package/lib/services/agent/planner/Planner.d.ts.map +1 -1
- package/lib/services/agent/planner/Planner.js +67 -303
- package/lib/services/agent/planner/overlayRegen.d.ts +38 -0
- package/lib/services/agent/planner/overlayRegen.d.ts.map +1 -0
- package/lib/services/agent/planner/overlayRegen.js +145 -0
- package/lib/services/agent/planner/plannerMessages.d.ts +34 -0
- package/lib/services/agent/planner/plannerMessages.d.ts.map +1 -0
- package/lib/services/agent/planner/plannerMessages.js +185 -0
- package/lib/services/agent/planner/promptSections.d.ts +12 -0
- package/lib/services/agent/planner/promptSections.d.ts.map +1 -1
- package/lib/services/agent/planner/promptSections.js +57 -0
- package/lib/services/agent/planner/scriptFirstPlanner.d.ts +35 -0
- package/lib/services/agent/planner/scriptFirstPlanner.d.ts.map +1 -0
- package/lib/services/agent/planner/scriptFirstPlanner.js +140 -0
- package/lib/services/agent/planner/structuralRules.d.ts +10 -0
- package/lib/services/agent/planner/structuralRules.d.ts.map +1 -1
- package/lib/services/agent/planner/structuralRules.js +92 -9
- package/lib/services/agent/planner/validators.d.ts +18 -0
- package/lib/services/agent/planner/validators.d.ts.map +1 -1
- package/lib/services/agent/planner/validators.js +97 -0
- package/lib/services/agent/planner.d.ts +2 -1
- package/lib/services/agent/planner.d.ts.map +1 -1
- package/lib/services/agent/planner.js +5 -1
- package/lib/services/agent/priorProject.d.ts +26 -0
- package/lib/services/agent/priorProject.d.ts.map +1 -0
- package/lib/services/agent/priorProject.js +51 -0
- package/lib/services/agent/providerFallback/chains.d.ts.map +1 -1
- package/lib/services/agent/providerFallback/chains.js +27 -15
- package/lib/services/agent/repurpose/index.d.ts +3 -0
- package/lib/services/agent/repurpose/index.d.ts.map +1 -0
- package/lib/services/agent/repurpose/index.js +18 -0
- package/lib/services/agent/repurpose/repurpose.schema.d.ts +132 -0
- package/lib/services/agent/repurpose/repurpose.schema.d.ts.map +1 -0
- package/lib/services/agent/repurpose/repurpose.schema.js +144 -0
- package/lib/services/agent/repurpose/shortsPicker.d.ts +25 -0
- package/lib/services/agent/repurpose/shortsPicker.d.ts.map +1 -0
- package/lib/services/agent/repurpose/shortsPicker.js +218 -0
- package/lib/services/agent/runHelpers.d.ts +21 -2
- package/lib/services/agent/runHelpers.d.ts.map +1 -1
- package/lib/services/agent/runHelpers.js +71 -2
- package/lib/services/agent/tools/animateImage.tool.d.ts +1 -0
- package/lib/services/agent/tools/animateImage.tool.d.ts.map +1 -1
- package/lib/services/agent/tools/animateImage.tool.js +12 -0
- package/lib/services/agent/tools/chapterOutline.tool.d.ts +42 -0
- package/lib/services/agent/tools/chapterOutline.tool.d.ts.map +1 -0
- package/lib/services/agent/tools/chapterOutline.tool.js +115 -0
- package/lib/services/agent/tools/composeScene.tool.d.ts +65 -2
- package/lib/services/agent/tools/composeScene.tool.d.ts.map +1 -1
- package/lib/services/agent/tools/estimateCost.tool.d.ts +28 -1
- package/lib/services/agent/tools/estimateCost.tool.d.ts.map +1 -1
- package/lib/services/agent/tools/estimateCost.tool.js +55 -7
- package/lib/services/agent/tools/extendVideo.tool.d.ts +26 -0
- package/lib/services/agent/tools/extendVideo.tool.d.ts.map +1 -0
- package/lib/services/agent/tools/extendVideo.tool.js +149 -0
- package/lib/services/agent/tools/generateScript.tool.d.ts +184 -0
- package/lib/services/agent/tools/generateScript.tool.d.ts.map +1 -0
- package/lib/services/agent/tools/generateScript.tool.js +123 -0
- package/lib/services/agent/tools/generateVideo.tool.d.ts +1 -0
- package/lib/services/agent/tools/generateVideo.tool.d.ts.map +1 -1
- package/lib/services/agent/tools/generateVideo.tool.js +20 -1
- package/lib/services/agent/tools/index.d.ts +4 -0
- package/lib/services/agent/tools/index.d.ts.map +1 -1
- package/lib/services/agent/tools/index.js +4 -0
- package/lib/services/agent/tools/matchBrollToScript.tool.d.ts +50 -0
- package/lib/services/agent/tools/matchBrollToScript.tool.d.ts.map +1 -0
- package/lib/services/agent/tools/matchBrollToScript.tool.js +139 -0
- package/lib/services/agent/tools/planVideo.tool.d.ts +57 -1
- package/lib/services/agent/tools/planVideo.tool.d.ts.map +1 -1
- package/lib/services/agent/tools/planVideo.tool.js +3 -3
- package/lib/services/agent/tools/render.tool.d.ts +22 -1
- package/lib/services/agent/tools/render.tool.d.ts.map +1 -1
- package/lib/services/aiGen/aiGenFactory.service.d.ts.map +1 -1
- package/lib/services/aiGen/aiGenFactory.service.js +18 -3
- package/lib/services/aiGen/helpers.d.ts +8 -0
- package/lib/services/aiGen/helpers.d.ts.map +1 -1
- package/lib/services/aiGen/helpers.js +12 -0
- package/lib/services/aiGen/providers/anthropic/anthropic.service.d.ts +26 -0
- package/lib/services/aiGen/providers/anthropic/anthropic.service.d.ts.map +1 -0
- package/lib/services/aiGen/providers/anthropic/anthropic.service.js +95 -0
- package/lib/services/aiGen/providers/google/google.service.d.ts +25 -1
- package/lib/services/aiGen/providers/google/google.service.d.ts.map +1 -1
- package/lib/services/aiGen/providers/google/google.service.js +136 -237
- package/lib/services/aiGen/providers/google/googleApiKeys.d.ts +71 -0
- package/lib/services/aiGen/providers/google/googleApiKeys.d.ts.map +1 -0
- package/lib/services/aiGen/providers/google/googleApiKeys.js +137 -0
- package/lib/services/aiGen/providers/google/googleErrors.d.ts +13 -0
- package/lib/services/aiGen/providers/google/googleErrors.d.ts.map +1 -0
- package/lib/services/aiGen/providers/google/googleErrors.js +102 -0
- package/lib/services/aiGen/providers/google/googleFetch.d.ts +8 -0
- package/lib/services/aiGen/providers/google/googleFetch.d.ts.map +1 -0
- package/lib/services/aiGen/providers/google/googleFetch.js +96 -0
- package/lib/services/aiGen/providers/google/googleKeyPool.d.ts +52 -0
- package/lib/services/aiGen/providers/google/googleKeyPool.d.ts.map +1 -0
- package/lib/services/aiGen/providers/google/googleKeyPool.js +129 -0
- package/lib/services/aiGen/providers/google/googleMusic.d.ts +15 -0
- package/lib/services/aiGen/providers/google/googleMusic.d.ts.map +1 -0
- package/lib/services/aiGen/providers/google/googleMusic.js +77 -0
- package/lib/services/aiGen/providers/kling/kling.service.d.ts +7 -3
- package/lib/services/aiGen/providers/kling/kling.service.d.ts.map +1 -1
- package/lib/services/aiGen/providers/kling/kling.service.js +23 -367
- package/lib/services/aiGen/providers/kling/klingCredits.d.ts +9 -0
- package/lib/services/aiGen/providers/kling/klingCredits.d.ts.map +1 -0
- package/lib/services/aiGen/providers/kling/klingCredits.js +63 -0
- package/lib/services/aiGen/providers/kling/klingRequests.d.ts +32 -0
- package/lib/services/aiGen/providers/kling/klingRequests.d.ts.map +1 -0
- package/lib/services/aiGen/providers/kling/klingRequests.js +194 -0
- package/lib/services/aiGen/providers/kling/klingStatus.d.ts +16 -0
- package/lib/services/aiGen/providers/kling/klingStatus.d.ts.map +1 -0
- package/lib/services/aiGen/providers/kling/klingStatus.js +173 -0
- package/lib/services/aiGen/providers/pixverse/pixverse.service.d.ts.map +1 -1
- package/lib/services/aiGen/providers/pixverse/pixverse.service.js +7 -1
- package/lib/services/bullmq.service.d.ts +61 -0
- package/lib/services/bullmq.service.d.ts.map +1 -1
- package/lib/services/bullmq.service.js +124 -2
- package/lib/services/crypto/index.d.ts +2 -0
- package/lib/services/crypto/index.d.ts.map +1 -0
- package/lib/services/crypto/index.js +17 -0
- package/lib/services/crypto/tokenVault.d.ts +47 -0
- package/lib/services/crypto/tokenVault.d.ts.map +1 -0
- package/lib/services/crypto/tokenVault.js +179 -0
- package/lib/services/editor/captionStyleHint.d.ts +3 -0
- package/lib/services/editor/captionStyleHint.d.ts.map +1 -0
- package/lib/services/editor/captionStyleHint.js +112 -0
- package/lib/services/editor/planToProject.d.ts +7 -66
- package/lib/services/editor/planToProject.d.ts.map +1 -1
- package/lib/services/editor/planToProject.helpers.d.ts +40 -0
- package/lib/services/editor/planToProject.helpers.d.ts.map +1 -0
- package/lib/services/editor/planToProject.helpers.js +177 -0
- package/lib/services/editor/planToProject.js +197 -180
- package/lib/services/editor/planToProject.types.d.ts +94 -0
- package/lib/services/editor/planToProject.types.d.ts.map +1 -0
- package/lib/services/editor/planToProject.types.js +2 -0
- package/lib/services/firestore.service.d.ts +5 -0
- package/lib/services/firestore.service.d.ts.map +1 -1
- package/lib/services/firestore.service.js +13 -0
- package/lib/services/index.d.ts +13 -0
- package/lib/services/index.d.ts.map +1 -1
- package/lib/services/index.js +13 -0
- package/lib/services/promptEnhancer/index.d.ts +18 -0
- package/lib/services/promptEnhancer/index.d.ts.map +1 -0
- package/lib/services/promptEnhancer/index.js +33 -0
- package/lib/services/promptEnhancer/models.d.ts +54 -0
- package/lib/services/promptEnhancer/models.d.ts.map +1 -0
- package/lib/services/promptEnhancer/models.js +37 -0
- package/lib/services/promptEnhancer/profiles/agent.profile.d.ts +14 -0
- package/lib/services/promptEnhancer/profiles/agent.profile.d.ts.map +1 -0
- package/lib/services/promptEnhancer/profiles/agent.profile.js +40 -0
- package/lib/services/promptEnhancer/profiles/avatar.profile.d.ts +13 -0
- package/lib/services/promptEnhancer/profiles/avatar.profile.d.ts.map +1 -0
- package/lib/services/promptEnhancer/profiles/avatar.profile.js +40 -0
- package/lib/services/promptEnhancer/profiles/base.d.ts +28 -0
- package/lib/services/promptEnhancer/profiles/base.d.ts.map +1 -0
- package/lib/services/promptEnhancer/profiles/base.js +35 -0
- package/lib/services/promptEnhancer/profiles/image.profile.d.ts +11 -0
- package/lib/services/promptEnhancer/profiles/image.profile.d.ts.map +1 -0
- package/lib/services/promptEnhancer/profiles/image.profile.js +42 -0
- package/lib/services/promptEnhancer/profiles/index.d.ts +12 -0
- package/lib/services/promptEnhancer/profiles/index.d.ts.map +1 -0
- package/lib/services/promptEnhancer/profiles/index.js +33 -0
- package/lib/services/promptEnhancer/profiles/video.profile.d.ts +15 -0
- package/lib/services/promptEnhancer/profiles/video.profile.d.ts.map +1 -0
- package/lib/services/promptEnhancer/profiles/video.profile.js +81 -0
- package/lib/services/promptEnhancer/promptEnhancer.service.d.ts +45 -0
- package/lib/services/promptEnhancer/promptEnhancer.service.d.ts.map +1 -0
- package/lib/services/promptEnhancer/promptEnhancer.service.js +157 -0
- package/lib/services/promptEnhancer/schema.d.ts +19 -0
- package/lib/services/promptEnhancer/schema.d.ts.map +1 -0
- package/lib/services/promptEnhancer/schema.js +43 -0
- package/lib/services/promptEnhancer/types.d.ts +112 -0
- package/lib/services/promptEnhancer/types.d.ts.map +1 -0
- package/lib/services/promptEnhancer/types.js +2 -0
- package/lib/services/rateLimiter/distributedRateLimiter.service.d.ts +60 -5
- package/lib/services/rateLimiter/distributedRateLimiter.service.d.ts.map +1 -1
- package/lib/services/rateLimiter/distributedRateLimiter.service.js +184 -16
- package/lib/services/socialAI/captionGen.d.ts +81 -0
- package/lib/services/socialAI/captionGen.d.ts.map +1 -0
- package/lib/services/socialAI/captionGen.js +206 -0
- package/lib/services/socialAI/hookScore.d.ts +85 -0
- package/lib/services/socialAI/hookScore.d.ts.map +1 -0
- package/lib/services/socialAI/hookScore.js +170 -0
- package/lib/services/socialAI/index.d.ts +3 -0
- package/lib/services/socialAI/index.d.ts.map +1 -0
- package/lib/services/socialAI/index.js +18 -0
- package/lib/services/socialAccounts/index.d.ts +2 -0
- package/lib/services/socialAccounts/index.d.ts.map +1 -0
- package/lib/services/socialAccounts/index.js +17 -0
- package/lib/services/socialAccounts/socialAccountService.d.ts +25 -0
- package/lib/services/socialAccounts/socialAccountService.d.ts.map +1 -0
- package/lib/services/socialAccounts/socialAccountService.js +105 -0
- package/lib/services/socialEngage/factory.d.ts +7 -0
- package/lib/services/socialEngage/factory.d.ts.map +1 -0
- package/lib/services/socialEngage/factory.js +25 -0
- package/lib/services/socialEngage/index.d.ts +6 -0
- package/lib/services/socialEngage/index.d.ts.map +1 -0
- package/lib/services/socialEngage/index.js +21 -0
- package/lib/services/socialEngage/meta.engage.d.ts +17 -0
- package/lib/services/socialEngage/meta.engage.d.ts.map +1 -0
- package/lib/services/socialEngage/meta.engage.js +128 -0
- package/lib/services/socialEngage/metaWebhook.d.ts +50 -0
- package/lib/services/socialEngage/metaWebhook.d.ts.map +1 -0
- package/lib/services/socialEngage/metaWebhook.js +93 -0
- package/lib/services/socialEngage/types.d.ts +72 -0
- package/lib/services/socialEngage/types.d.ts.map +1 -0
- package/lib/services/socialEngage/types.js +10 -0
- package/lib/services/socialEngage/youtube.engage.d.ts +9 -0
- package/lib/services/socialEngage/youtube.engage.d.ts.map +1 -0
- package/lib/services/socialEngage/youtube.engage.js +87 -0
- package/lib/services/socialFormat/aspectGeometry.d.ts +74 -0
- package/lib/services/socialFormat/aspectGeometry.d.ts.map +1 -0
- package/lib/services/socialFormat/aspectGeometry.js +135 -0
- package/lib/services/socialFormat/index.d.ts +2 -0
- package/lib/services/socialFormat/index.d.ts.map +1 -0
- package/lib/services/socialFormat/index.js +19 -0
- package/lib/services/socialInsights/index.d.ts +3 -0
- package/lib/services/socialInsights/index.d.ts.map +1 -0
- package/lib/services/socialInsights/index.js +18 -0
- package/lib/services/socialInsights/recommendations.d.ts +131 -0
- package/lib/services/socialInsights/recommendations.d.ts.map +1 -0
- package/lib/services/socialInsights/recommendations.js +277 -0
- package/lib/services/socialInsights/timeBuckets.d.ts +35 -0
- package/lib/services/socialInsights/timeBuckets.d.ts.map +1 -0
- package/lib/services/socialInsights/timeBuckets.js +78 -0
- package/lib/services/socialMetrics/factory.d.ts +5 -0
- package/lib/services/socialMetrics/factory.d.ts.map +1 -0
- package/lib/services/socialMetrics/factory.js +24 -0
- package/lib/services/socialMetrics/index.d.ts +6 -0
- package/lib/services/socialMetrics/index.d.ts.map +1 -0
- package/lib/services/socialMetrics/index.js +21 -0
- package/lib/services/socialMetrics/meta.metrics.d.ts +22 -0
- package/lib/services/socialMetrics/meta.metrics.d.ts.map +1 -0
- package/lib/services/socialMetrics/meta.metrics.js +137 -0
- package/lib/services/socialMetrics/tiktok.metrics.d.ts +8 -0
- package/lib/services/socialMetrics/tiktok.metrics.d.ts.map +1 -0
- package/lib/services/socialMetrics/tiktok.metrics.js +43 -0
- package/lib/services/socialMetrics/types.d.ts +54 -0
- package/lib/services/socialMetrics/types.d.ts.map +1 -0
- package/lib/services/socialMetrics/types.js +2 -0
- package/lib/services/socialMetrics/youtube.metrics.d.ts +8 -0
- package/lib/services/socialMetrics/youtube.metrics.d.ts.map +1 -0
- package/lib/services/socialMetrics/youtube.metrics.js +43 -0
- package/lib/services/socialOAuth/factory.d.ts +7 -0
- package/lib/services/socialOAuth/factory.d.ts.map +1 -0
- package/lib/services/socialOAuth/factory.js +42 -0
- package/lib/services/socialOAuth/index.d.ts +11 -0
- package/lib/services/socialOAuth/index.d.ts.map +1 -0
- package/lib/services/socialOAuth/index.js +26 -0
- package/lib/services/socialOAuth/linkedin.oauth.d.ts +14 -0
- package/lib/services/socialOAuth/linkedin.oauth.d.ts.map +1 -0
- package/lib/services/socialOAuth/linkedin.oauth.js +127 -0
- package/lib/services/socialOAuth/meta.oauth.d.ts +31 -0
- package/lib/services/socialOAuth/meta.oauth.d.ts.map +1 -0
- package/lib/services/socialOAuth/meta.oauth.js +214 -0
- package/lib/services/socialOAuth/oauthState.d.ts +14 -0
- package/lib/services/socialOAuth/oauthState.d.ts.map +1 -0
- package/lib/services/socialOAuth/oauthState.js +66 -0
- package/lib/services/socialOAuth/pinterest.oauth.d.ts +15 -0
- package/lib/services/socialOAuth/pinterest.oauth.d.ts.map +1 -0
- package/lib/services/socialOAuth/pinterest.oauth.js +126 -0
- package/lib/services/socialOAuth/threads.oauth.d.ts +14 -0
- package/lib/services/socialOAuth/threads.oauth.d.ts.map +1 -0
- package/lib/services/socialOAuth/threads.oauth.js +129 -0
- package/lib/services/socialOAuth/tiktok.oauth.d.ts +15 -0
- package/lib/services/socialOAuth/tiktok.oauth.d.ts.map +1 -0
- package/lib/services/socialOAuth/tiktok.oauth.js +151 -0
- package/lib/services/socialOAuth/types.d.ts +67 -0
- package/lib/services/socialOAuth/types.d.ts.map +1 -0
- package/lib/services/socialOAuth/types.js +2 -0
- package/lib/services/socialOAuth/x.oauth.d.ts +17 -0
- package/lib/services/socialOAuth/x.oauth.d.ts.map +1 -0
- package/lib/services/socialOAuth/x.oauth.js +134 -0
- package/lib/services/socialOAuth/youtube.oauth.d.ts +15 -0
- package/lib/services/socialOAuth/youtube.oauth.d.ts.map +1 -0
- package/lib/services/socialOAuth/youtube.oauth.js +156 -0
- package/lib/services/socialPublish/factory.d.ts +5 -0
- package/lib/services/socialPublish/factory.d.ts.map +1 -0
- package/lib/services/socialPublish/factory.js +32 -0
- package/lib/services/socialPublish/index.d.ts +10 -0
- package/lib/services/socialPublish/index.d.ts.map +1 -0
- package/lib/services/socialPublish/index.js +25 -0
- package/lib/services/socialPublish/linkedin.publish.d.ts +9 -0
- package/lib/services/socialPublish/linkedin.publish.d.ts.map +1 -0
- package/lib/services/socialPublish/linkedin.publish.js +143 -0
- package/lib/services/socialPublish/meta.publish.d.ts +28 -0
- package/lib/services/socialPublish/meta.publish.d.ts.map +1 -0
- package/lib/services/socialPublish/meta.publish.js +149 -0
- package/lib/services/socialPublish/pinterest.publish.d.ts +13 -0
- package/lib/services/socialPublish/pinterest.publish.d.ts.map +1 -0
- package/lib/services/socialPublish/pinterest.publish.js +130 -0
- package/lib/services/socialPublish/threads.publish.d.ts +12 -0
- package/lib/services/socialPublish/threads.publish.d.ts.map +1 -0
- package/lib/services/socialPublish/threads.publish.js +96 -0
- package/lib/services/socialPublish/tiktok.publish.d.ts +13 -0
- package/lib/services/socialPublish/tiktok.publish.d.ts.map +1 -0
- package/lib/services/socialPublish/tiktok.publish.js +118 -0
- package/lib/services/socialPublish/types.d.ts +47 -0
- package/lib/services/socialPublish/types.d.ts.map +1 -0
- package/lib/services/socialPublish/types.js +2 -0
- package/lib/services/socialPublish/x.publish.d.ts +12 -0
- package/lib/services/socialPublish/x.publish.d.ts.map +1 -0
- package/lib/services/socialPublish/x.publish.js +147 -0
- package/lib/services/socialPublish/youtube.publish.d.ts +9 -0
- package/lib/services/socialPublish/youtube.publish.d.ts.map +1 -0
- package/lib/services/socialPublish/youtube.publish.js +107 -0
- package/lib/services/stock/index.d.ts +2 -0
- package/lib/services/stock/index.d.ts.map +1 -0
- package/lib/services/stock/index.js +17 -0
- package/lib/services/stock/realPersonSafety.d.ts +99 -0
- package/lib/services/stock/realPersonSafety.d.ts.map +1 -0
- package/lib/services/stock/realPersonSafety.js +248 -0
- package/lib/services/translation/index.d.ts +2 -0
- package/lib/services/translation/index.d.ts.map +1 -0
- package/lib/services/translation/index.js +9 -0
- package/lib/services/translation/translation.service.d.ts +50 -0
- package/lib/services/translation/translation.service.d.ts.map +1 -0
- package/lib/services/translation/translation.service.js +211 -0
- package/lib/utils/helpers.d.ts +2 -4
- package/lib/utils/helpers.d.ts.map +1 -1
- package/lib/utils/helpers.js +9 -63
- package/lib/utils/index.d.ts +1 -0
- package/lib/utils/index.d.ts.map +1 -1
- package/lib/utils/index.js +1 -0
- package/lib/utils/renderTier.d.ts +26 -0
- package/lib/utils/renderTier.d.ts.map +1 -0
- package/lib/utils/renderTier.js +34 -0
- package/package.json +1 -1
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Pure (SDK-free, Redis-free) helpers for the Google AI Studio API key pool.
|
|
4
|
+
*
|
|
5
|
+
* ── DECISION RECORD (2026-06-15) ────────────────────────────────────────────
|
|
6
|
+
* Problem: Veo on a single Gemini Developer API key is quota-starved — Tier 2
|
|
7
|
+
* is ~4 req/min and ~50/day per Veo model — which serialized bursts of jobs
|
|
8
|
+
* into a multi-hour queue (~370 min observed avg latency).
|
|
9
|
+
*
|
|
10
|
+
* Chosen fix (today): a multi-key pool over TWO Google AI Studio keys that live
|
|
11
|
+
* in SEPARATE GCP projects / billing accounts, so their quotas are independent
|
|
12
|
+
* and ADD UP. Keys are used in PRIORITY order:
|
|
13
|
+
* - key[0] = the NEW key (vidspotai project), currently **Tier 1** (2/min,
|
|
14
|
+
* 10/day per Veo model). Used FIRST, deliberately, to drive usage and
|
|
15
|
+
* promote its billing account up the tier ladder.
|
|
16
|
+
* - key[1] = the CURRENT key, **Tier 2** (4/min, 50/day). Used once key[0]
|
|
17
|
+
* is out of per-minute / per-day budget.
|
|
18
|
+
* Aggregate Veo budget = T1 + T2 = 6/min, 60/day. When BOTH are exhausted, the
|
|
19
|
+
* job-start capacity selector (videoJobProcessor) spills to another provider.
|
|
20
|
+
*
|
|
21
|
+
* When key[1]'s account is billed it moves to Tier 3; bump its tier in
|
|
22
|
+
* GOOGLE_API_KEY_TIERS then (no code change — the ladder below handles it).
|
|
23
|
+
*
|
|
24
|
+
* Vertex AI (DEFERRED, on record for the future): Veo is also available via
|
|
25
|
+
* Vertex, where quota is **per-project** and the current billing account is
|
|
26
|
+
* Tier-2-per-project — so we could create multiple projects under one account
|
|
27
|
+
* to scale further. We are NOT doing Vertex now: the two AI-Studio keys across
|
|
28
|
+
* two billing accounts already cover our needed headroom, and the Vertex path
|
|
29
|
+
* needs a different output flow (GCS `gs://` URIs rather than the Files API)
|
|
30
|
+
* that we'd rather build + test deliberately when the extra capacity is needed.
|
|
31
|
+
*
|
|
32
|
+
* ── CONFIG ──────────────────────────────────────────────────────────────────
|
|
33
|
+
* GOOGLE_API_KEYS — comma-separated keys in PRIORITY order. Falls back
|
|
34
|
+
* to the single legacy GOOGLE_API_KEY when unset.
|
|
35
|
+
* GOOGLE_API_KEY_TIERS — comma-separated tier numbers (1/2/3) aligned to
|
|
36
|
+
* GOOGLE_API_KEYS. Missing/extra entries default to 2.
|
|
37
|
+
* GOOGLE_API_KEY — legacy single key; also the client used to poll
|
|
38
|
+
* tasks submitted before the pool existed (un-tagged).
|
|
39
|
+
*
|
|
40
|
+
* Per-key budget is derived from the model config's Tier-2 baseline
|
|
41
|
+
* (requestPerMin / requestPerDay) scaled by each key's tier (see TIER_FACTORS);
|
|
42
|
+
* the pool gives us the SUM across keys.
|
|
43
|
+
*/
|
|
44
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
45
|
+
exports.parseGoogleApiKeys = parseGoogleApiKeys;
|
|
46
|
+
exports.parseGoogleApiKeyTiers = parseGoogleApiKeyTiers;
|
|
47
|
+
exports.googleApiKeyCount = googleApiKeyCount;
|
|
48
|
+
exports.scaleLimitForTier = scaleLimitForTier;
|
|
49
|
+
exports.googleAggregateFactor = googleAggregateFactor;
|
|
50
|
+
exports.googleKeyId = googleKeyId;
|
|
51
|
+
exports.encodeVeoTask = encodeVeoTask;
|
|
52
|
+
exports.decodeVeoTask = decodeVeoTask;
|
|
53
|
+
/**
|
|
54
|
+
* Per-Veo-model rate ladder, expressed as a factor of the Tier-2 baseline that
|
|
55
|
+
* the model configs encode. Verified against Google's Veo quota
|
|
56
|
+
* (predict_long_running_requests_per_model): RPM 2/4/10 and RPD 10/50/500 for
|
|
57
|
+
* Tier 1/2/3. Only Veo configures per-key min/day caps today, so these factors
|
|
58
|
+
* only materially affect Veo; models with no caps (factor × 0 = 0) are
|
|
59
|
+
* unaffected.
|
|
60
|
+
*/
|
|
61
|
+
const TIER_FACTORS = {
|
|
62
|
+
1: { rpm: 2 / 4, rpd: 10 / 50 }, // 0.5×, 0.2×
|
|
63
|
+
2: { rpm: 1, rpd: 1 },
|
|
64
|
+
3: { rpm: 10 / 4, rpd: 500 / 50 }, // 2.5×, 10×
|
|
65
|
+
};
|
|
66
|
+
function tierFactor(tier) {
|
|
67
|
+
return TIER_FACTORS[tier] ?? TIER_FACTORS[2];
|
|
68
|
+
}
|
|
69
|
+
/** Parse the configured keys in priority order, de-duped, empties removed. */
|
|
70
|
+
function parseGoogleApiKeys() {
|
|
71
|
+
const multi = (process.env.GOOGLE_API_KEYS ?? "").trim();
|
|
72
|
+
const raw = multi || (process.env.GOOGLE_API_KEY ?? "").trim();
|
|
73
|
+
const seen = new Set();
|
|
74
|
+
const keys = [];
|
|
75
|
+
for (const part of raw.split(",")) {
|
|
76
|
+
const k = part.trim();
|
|
77
|
+
if (k && !seen.has(k)) {
|
|
78
|
+
seen.add(k);
|
|
79
|
+
keys.push(k);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return keys;
|
|
83
|
+
}
|
|
84
|
+
/** Tier per key (aligned to parseGoogleApiKeys order); defaults to 2. */
|
|
85
|
+
function parseGoogleApiKeyTiers() {
|
|
86
|
+
const keys = parseGoogleApiKeys();
|
|
87
|
+
const raw = (process.env.GOOGLE_API_KEY_TIERS ?? "").trim();
|
|
88
|
+
const parsed = raw
|
|
89
|
+
? raw.split(",").map((s) => Number(s.trim()))
|
|
90
|
+
: [];
|
|
91
|
+
return keys.map((_, i) => {
|
|
92
|
+
const t = parsed[i];
|
|
93
|
+
return t === 1 || t === 2 || t === 3 ? t : 2;
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
/** Number of configured Google keys (>= 1 so callers can multiply safely). */
|
|
97
|
+
function googleApiKeyCount() {
|
|
98
|
+
return Math.max(1, parseGoogleApiKeys().length);
|
|
99
|
+
}
|
|
100
|
+
/** Per-key rate cap for a given Tier-2 baseline and tier. */
|
|
101
|
+
function scaleLimitForTier(baseline, tier, kind) {
|
|
102
|
+
if (!baseline)
|
|
103
|
+
return 0;
|
|
104
|
+
return Math.max(1, Math.round(baseline * tierFactor(tier)[kind]));
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Aggregate multiplier across all configured keys, for scaling a Google
|
|
108
|
+
* model's Tier-2 baseline into the pool-wide budget. Returns 1 for a single
|
|
109
|
+
* default key (legacy behavior unchanged).
|
|
110
|
+
*/
|
|
111
|
+
function googleAggregateFactor(kind) {
|
|
112
|
+
const tiers = parseGoogleApiKeyTiers();
|
|
113
|
+
if (tiers.length <= 1)
|
|
114
|
+
return 1; // legacy single key → baseline unchanged
|
|
115
|
+
return tiers.reduce((sum, t) => sum + tierFactor(t)[kind], 0);
|
|
116
|
+
}
|
|
117
|
+
/** Stable id for the key at a given priority index. */
|
|
118
|
+
function googleKeyId(index) {
|
|
119
|
+
return `k${index}`;
|
|
120
|
+
}
|
|
121
|
+
const TASK_TAG_RE = /^gk:([a-z0-9]+)::([\s\S]+)$/;
|
|
122
|
+
/**
|
|
123
|
+
* Tag a Veo operation name with the id of the key that created it, so polling
|
|
124
|
+
* + download can re-select the same project-scoped client. With a single key
|
|
125
|
+
* we return the bare operation name (no tag) — byte-for-byte the legacy format,
|
|
126
|
+
* so nothing changes until a real pool is configured.
|
|
127
|
+
*/
|
|
128
|
+
function encodeVeoTask(keyId, operationName, poolSize) {
|
|
129
|
+
return poolSize > 1 ? `gk:${keyId}::${operationName}` : operationName;
|
|
130
|
+
}
|
|
131
|
+
/** Reverse of encodeVeoTask. `keyId` is undefined for legacy/un-tagged tasks. */
|
|
132
|
+
function decodeVeoTask(task) {
|
|
133
|
+
const m = TASK_TAG_RE.exec(task);
|
|
134
|
+
if (m)
|
|
135
|
+
return { keyId: m[1], operationName: m[2] };
|
|
136
|
+
return { operationName: task };
|
|
137
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { UserFacingError } from "../../../../utils/errors";
|
|
2
|
+
/**
|
|
3
|
+
* Maps `@google/genai` `ApiError` failures (whose message is a JSON string)
|
|
4
|
+
* to a `UserFacingError` with a stable code the frontend can translate.
|
|
5
|
+
* Returns null when the error is not a known user-facing case (re-throw as-is).
|
|
6
|
+
*
|
|
7
|
+
* Used both for thrown SDK errors (generateText/Image/Video) and for
|
|
8
|
+
* long-running-operation `result.error` payloads (checkVideoStatus), so a
|
|
9
|
+
* gRPC-13 INTERNAL flake or a RAI/prompt rejection becomes a typed, log-warn
|
|
10
|
+
* error instead of raw provider JSON that pages Slack as a platform bug.
|
|
11
|
+
*/
|
|
12
|
+
export declare function classifyGoogleApiError(err: any): UserFacingError | null;
|
|
13
|
+
//# sourceMappingURL=googleErrors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"googleErrors.d.ts","sourceRoot":"","sources":["../../../../../src/services/aiGen/providers/google/googleErrors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAA2B,MAAM,0BAA0B,CAAC;AAEpF;;;;;;;;;GASG;AACH,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,GAAG,GAAG,eAAe,GAAG,IAAI,CAmHvE"}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.classifyGoogleApiError = classifyGoogleApiError;
|
|
4
|
+
const errors_1 = require("../../../../utils/errors");
|
|
5
|
+
/**
|
|
6
|
+
* Maps `@google/genai` `ApiError` failures (whose message is a JSON string)
|
|
7
|
+
* to a `UserFacingError` with a stable code the frontend can translate.
|
|
8
|
+
* Returns null when the error is not a known user-facing case (re-throw as-is).
|
|
9
|
+
*
|
|
10
|
+
* Used both for thrown SDK errors (generateText/Image/Video) and for
|
|
11
|
+
* long-running-operation `result.error` payloads (checkVideoStatus), so a
|
|
12
|
+
* gRPC-13 INTERNAL flake or a RAI/prompt rejection becomes a typed, log-warn
|
|
13
|
+
* error instead of raw provider JSON that pages Slack as a platform bug.
|
|
14
|
+
*/
|
|
15
|
+
function classifyGoogleApiError(err) {
|
|
16
|
+
const raw = err?.message ?? "";
|
|
17
|
+
try {
|
|
18
|
+
const parsed = JSON.parse(raw);
|
|
19
|
+
const inner = parsed.error ?? parsed;
|
|
20
|
+
const httpCode = inner.code;
|
|
21
|
+
const status = inner.status;
|
|
22
|
+
const msg = inner.message ?? raw;
|
|
23
|
+
if (status === "RESOURCE_EXHAUSTED" || httpCode === 429) {
|
|
24
|
+
return new errors_1.UserFacingError(msg, errors_1.USER_FACING_ERROR_CODES.VIDEO_PROVIDER_RATE_LIMITED);
|
|
25
|
+
}
|
|
26
|
+
// gRPC code 14 = UNAVAILABLE; Veo surfaces "high demand" failures with this.
|
|
27
|
+
if (httpCode === 14 || /high demand/i.test(msg)) {
|
|
28
|
+
return new errors_1.UserFacingError(msg, errors_1.USER_FACING_ERROR_CODES.VIDEO_PROVIDER_HIGH_DEMAND);
|
|
29
|
+
}
|
|
30
|
+
// INVALID_ARGUMENT 400 — narrow match: only the specific "use case is
|
|
31
|
+
// currently not supported" string, which Veo returns when our request
|
|
32
|
+
// structure doesn't match the chosen model variant's capabilities.
|
|
33
|
+
// The pre-call guards above (duration=8 for lastFrame/refs) should
|
|
34
|
+
// prevent the known cases; if we still hit this it's a NEW combo we
|
|
35
|
+
// haven't profiled — surface as CAPABILITY_MISMATCH so the user gets a
|
|
36
|
+
// useful message, AND keep the raw provider text in the error so the
|
|
37
|
+
// next entry in PROD_FIX_LOG can identify which combo broke. Generic
|
|
38
|
+
// 400s (other INVALID_ARGUMENT variants) still surface as `error` so
|
|
39
|
+
// a real platform bug isn't muted.
|
|
40
|
+
if ((status === "INVALID_ARGUMENT" || httpCode === 400) &&
|
|
41
|
+
/use case is currently not supported/i.test(msg)) {
|
|
42
|
+
return new errors_1.UserFacingError(msg, errors_1.USER_FACING_ERROR_CODES.CAPABILITY_MISMATCH);
|
|
43
|
+
}
|
|
44
|
+
// Imagen + Nano-Banana surface Responsible-AI filter rejections as
|
|
45
|
+
// INVALID_ARGUMENT 400 with the literal text "filtered out because they
|
|
46
|
+
// violated Google's Responsible AI practices" (and a recommendation to
|
|
47
|
+
// rephrase). This is user content moderation, not a system bug — show the
|
|
48
|
+
// user the rephrase hint and skip the Slack page. Also matches the Veo
|
|
49
|
+
// RAI message ("violated Google's content policies") for the same reason.
|
|
50
|
+
if ((status === "INVALID_ARGUMENT" || httpCode === 400) &&
|
|
51
|
+
/(filtered out because they violated|violated Google's (?:Responsible AI|content) (?:practices|policies))/i.test(msg)) {
|
|
52
|
+
return new errors_1.UserFacingError("Your prompt was flagged by Google's safety filters. Please rephrase and try again.", errors_1.USER_FACING_ERROR_CODES.CONTENT_POLICY_VIOLATION);
|
|
53
|
+
}
|
|
54
|
+
// Generic INVALID_ARGUMENT 400 on a provided string field. Veo echoes the
|
|
55
|
+
// offending value back ("The string value `<prompt>` ...") and the only
|
|
56
|
+
// large free-text field we send is the prompt, so attribute this to the
|
|
57
|
+
// prompt: it's either over the model's length limit or otherwise rejected
|
|
58
|
+
// by the validator. Either way it's user input, not a platform bug —
|
|
59
|
+
// surface a typed, actionable, non-retryable error (logged warn, no Slack
|
|
60
|
+
// page) instead of leaking the echoed prompt into the error channel.
|
|
61
|
+
if ((status === "INVALID_ARGUMENT" || httpCode === 400) &&
|
|
62
|
+
/string value/i.test(msg)) {
|
|
63
|
+
const tooLong = /(exceed|too long|maximum length|length limit|\blimit\b)/i.test(msg);
|
|
64
|
+
return tooLong
|
|
65
|
+
? new errors_1.UserFacingError("Your prompt is too long for this model. Please shorten it and try again.", errors_1.USER_FACING_ERROR_CODES.PROMPT_TOO_LONG)
|
|
66
|
+
: new errors_1.UserFacingError("Your prompt was rejected by the model. Please simplify or rephrase it and try again.", errors_1.USER_FACING_ERROR_CODES.PROMPT_INVALID);
|
|
67
|
+
}
|
|
68
|
+
// gRPC code 13 = INTERNAL. Veo returns this for transient backend failures
|
|
69
|
+
// ("Video generation failed due to an internal server issue. Please try
|
|
70
|
+
// again in a few minutes."). It is NOT our bug and NOT moderation — a
|
|
71
|
+
// Google-side flake. Surface as a transient PROVIDER_UNAVAILABLE so the
|
|
72
|
+
// user gets a "try again" message and it logs warn (Loki) instead of
|
|
73
|
+
// paging Slack as a platform error. (Egregiously-blocked content that Veo
|
|
74
|
+
// masks as code 13 also lands here; we can't distinguish it from a real
|
|
75
|
+
// internal flake, and "try again" is an acceptable fallback message.)
|
|
76
|
+
if (httpCode === 13 ||
|
|
77
|
+
status === "INTERNAL" ||
|
|
78
|
+
/internal (server|error)/i.test(msg)) {
|
|
79
|
+
return new errors_1.UserFacingError("Google's video service had a temporary problem. Please try again in a few minutes.", errors_1.USER_FACING_ERROR_CODES.PROVIDER_UNAVAILABLE);
|
|
80
|
+
}
|
|
81
|
+
// HTTP 503 / status UNAVAILABLE — Google's video backend is temporarily
|
|
82
|
+
// overloaded or down ("The service is currently unavailable."). Same class
|
|
83
|
+
// as code 13 INTERNAL above: a transient provider outage, not our bug and
|
|
84
|
+
// not moderation. Without this branch it fell through to `return null` and
|
|
85
|
+
// got re-thrown as a raw ApiError → logged at `error` (paging Slack) with
|
|
86
|
+
// the raw provider JSON as the scene's errorMessage. Surface it as
|
|
87
|
+
// PROVIDER_UNAVAILABLE so the user gets a "try again" message and it logs
|
|
88
|
+
// warn (Loki) instead.
|
|
89
|
+
if (httpCode === 503 ||
|
|
90
|
+
status === "UNAVAILABLE" ||
|
|
91
|
+
/service is currently unavailable|temporarily unavailable/i.test(msg)) {
|
|
92
|
+
return new errors_1.UserFacingError("Google's video service is temporarily unavailable. Please try again in a few minutes.", errors_1.USER_FACING_ERROR_CODES.PROVIDER_UNAVAILABLE);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
catch {
|
|
96
|
+
// Not JSON — fall through to non-JSON checks.
|
|
97
|
+
}
|
|
98
|
+
if (/timeout/i.test(raw) || err?.code === "ECONNABORTED") {
|
|
99
|
+
return new errors_1.UserFacingError(raw, errors_1.USER_FACING_ERROR_CODES.VIDEO_PROVIDER_TIMEOUT);
|
|
100
|
+
}
|
|
101
|
+
return null;
|
|
102
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export declare function pickImageMimeType(contentType: string, url: string): string;
|
|
2
|
+
export declare function isTransientFetchError(err: any): boolean;
|
|
3
|
+
export declare function inferImageMime(url: string): string;
|
|
4
|
+
export declare function fetchAsImage(url: string): Promise<{
|
|
5
|
+
mimeType: string;
|
|
6
|
+
imageBytes: string;
|
|
7
|
+
}>;
|
|
8
|
+
//# sourceMappingURL=googleFetch.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"googleFetch.d.ts","sourceRoot":"","sources":["../../../../../src/services/aiGen/providers/google/googleFetch.ts"],"names":[],"mappings":"AAkCA,wBAAgB,iBAAiB,CAAC,WAAW,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAiB1E;AAED,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,GAAG,GAAG,OAAO,CAOvD;AAED,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAKlD;AAED,wBAAsB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CAAC,CAyBjG"}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.pickImageMimeType = pickImageMimeType;
|
|
4
|
+
exports.isTransientFetchError = isTransientFetchError;
|
|
5
|
+
exports.inferImageMime = inferImageMime;
|
|
6
|
+
exports.fetchAsImage = fetchAsImage;
|
|
7
|
+
const errors_1 = require("../../../../utils/errors");
|
|
8
|
+
/**
|
|
9
|
+
* Network + image helpers for the Google provider: transient-error detection
|
|
10
|
+
* (for withTransientRetry) and downloading an input image as Veo-compatible
|
|
11
|
+
* base64 with a correct MIME type. Pure / I/O helpers, no class state.
|
|
12
|
+
*/
|
|
13
|
+
// Codes from undici / Node net layer that indicate a transient network failure
|
|
14
|
+
// the request never reached the server, or the server hung up mid-flight.
|
|
15
|
+
// Retrying these is safe (idempotent at the API layer for our use cases) and usually succeeds.
|
|
16
|
+
const TRANSIENT_NETWORK_CODES = new Set([
|
|
17
|
+
"ECONNRESET",
|
|
18
|
+
"ECONNREFUSED",
|
|
19
|
+
"ETIMEDOUT",
|
|
20
|
+
"ENOTFOUND",
|
|
21
|
+
"EAI_AGAIN",
|
|
22
|
+
"EPIPE",
|
|
23
|
+
"UND_ERR_SOCKET",
|
|
24
|
+
"UND_ERR_CONNECT_TIMEOUT",
|
|
25
|
+
"UND_ERR_HEADERS_TIMEOUT",
|
|
26
|
+
"UND_ERR_BODY_TIMEOUT",
|
|
27
|
+
]);
|
|
28
|
+
// Pick a Veo-compatible image MIME type. Veo accepts image/jpeg, image/png,
|
|
29
|
+
// image/webp. We prefer the upstream Content-Type header (Firebase Storage
|
|
30
|
+
// returns the type set at upload), then fall back to URL extension, then to
|
|
31
|
+
// image/jpeg as a reasonable last resort for phone-camera uploads.
|
|
32
|
+
const VEO_SUPPORTED_IMAGE_MIMES = new Set([
|
|
33
|
+
"image/jpeg",
|
|
34
|
+
"image/png",
|
|
35
|
+
"image/webp",
|
|
36
|
+
]);
|
|
37
|
+
function pickImageMimeType(contentType, url) {
|
|
38
|
+
const normalized = contentType.split(";")[0]?.trim().toLowerCase();
|
|
39
|
+
if (normalized && VEO_SUPPORTED_IMAGE_MIMES.has(normalized)) {
|
|
40
|
+
return normalized;
|
|
41
|
+
}
|
|
42
|
+
// Map common but non-canonical types
|
|
43
|
+
if (normalized === "image/jpg")
|
|
44
|
+
return "image/jpeg";
|
|
45
|
+
// Extension fallback. Strip query string first (Firebase URLs have ?alt=media).
|
|
46
|
+
const pathOnly = url.split("?")[0]?.toLowerCase() ?? "";
|
|
47
|
+
if (pathOnly.endsWith(".png"))
|
|
48
|
+
return "image/png";
|
|
49
|
+
if (pathOnly.endsWith(".webp"))
|
|
50
|
+
return "image/webp";
|
|
51
|
+
if (pathOnly.endsWith(".jpg") || pathOnly.endsWith(".jpeg"))
|
|
52
|
+
return "image/jpeg";
|
|
53
|
+
// Phone uploads default to JPEG far more often than PNG, so it's a safer
|
|
54
|
+
// last-resort than the previous hardcoded "image/png".
|
|
55
|
+
return "image/jpeg";
|
|
56
|
+
}
|
|
57
|
+
function isTransientFetchError(err) {
|
|
58
|
+
if (!err)
|
|
59
|
+
return false;
|
|
60
|
+
// undici wraps low-level errors as `TypeError: fetch failed` with the real
|
|
61
|
+
// reason on `err.cause`. Treat that exact shape as transient.
|
|
62
|
+
if (err.message === "fetch failed")
|
|
63
|
+
return true;
|
|
64
|
+
const code = err.code ?? err.cause?.code;
|
|
65
|
+
return !!code && TRANSIENT_NETWORK_CODES.has(code);
|
|
66
|
+
}
|
|
67
|
+
function inferImageMime(url) {
|
|
68
|
+
const lower = (url.split("?")[0] ?? url).toLowerCase();
|
|
69
|
+
if (lower.endsWith(".jpg") || lower.endsWith(".jpeg"))
|
|
70
|
+
return "image/jpeg";
|
|
71
|
+
if (lower.endsWith(".webp"))
|
|
72
|
+
return "image/webp";
|
|
73
|
+
return "image/png";
|
|
74
|
+
}
|
|
75
|
+
async function fetchAsImage(url) {
|
|
76
|
+
const resp = await fetch(url);
|
|
77
|
+
// fetch() does NOT throw on 4xx/5xx — surface the HTTP error so we don't
|
|
78
|
+
// encode an HTML error page as image bytes (Veo silently rejects them).
|
|
79
|
+
if (!resp.ok) {
|
|
80
|
+
throw new errors_1.UserFacingError(`Input image could not be downloaded (HTTP ${resp.status}). The image URL may have expired or been deleted.`);
|
|
81
|
+
}
|
|
82
|
+
const buf = Buffer.from(await resp.arrayBuffer());
|
|
83
|
+
// 0-byte body slips through resp.ok if the upstream wrote an empty file.
|
|
84
|
+
// Veo treats empty bytes as content-filtered (no error, no video).
|
|
85
|
+
if (buf.length === 0) {
|
|
86
|
+
throw new errors_1.UserFacingError("Input image is empty (0 bytes). Please re-upload the image.");
|
|
87
|
+
}
|
|
88
|
+
// Prefer Content-Type from the response (authoritative — set by Firebase
|
|
89
|
+
// Storage upload metadata) over URL-extension inference. Hardcoded
|
|
90
|
+
// image/png caused Veo to reject JPEG bytes labelled PNG with no detail.
|
|
91
|
+
const respContentType = resp.headers.get("content-type") ?? "";
|
|
92
|
+
return {
|
|
93
|
+
mimeType: pickImageMimeType(respContentType, url),
|
|
94
|
+
imageBytes: buf.toString("base64"),
|
|
95
|
+
};
|
|
96
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { GoogleGenAI } from "@google/genai";
|
|
2
|
+
import { googleApiKeyCount } from "./googleApiKeys";
|
|
3
|
+
/**
|
|
4
|
+
* Google AI Studio multi-key pool.
|
|
5
|
+
*
|
|
6
|
+
* Each configured key is a separate GCP project / billing account with its own
|
|
7
|
+
* Tier-2 quota, so N keys give us N× the per-model daily + per-minute budget.
|
|
8
|
+
* The model-level rate limiter (DistributedRateLimiter) enforces the AGGREGATE
|
|
9
|
+
* (per-key config × key count — see getAiGenModelRateLimiter); this pool decides
|
|
10
|
+
* WHICH key serves each individual submit, in priority order, so we drain the
|
|
11
|
+
* first key's budget before leaning on the next.
|
|
12
|
+
*
|
|
13
|
+
* Veo operations are project-scoped — a task submitted with key K can only be
|
|
14
|
+
* polled / downloaded with key K — so submit tags the task with its key id
|
|
15
|
+
* (encodeVeoTask) and the poll path re-selects the client via clientById().
|
|
16
|
+
*
|
|
17
|
+
* Single-key / unconfigured pool: behaves exactly like the legacy single
|
|
18
|
+
* `GoogleGenAI({ apiKey })` client (no tagging, no Redis routing).
|
|
19
|
+
*/
|
|
20
|
+
interface KeyEntry {
|
|
21
|
+
id: string;
|
|
22
|
+
apiKey: string;
|
|
23
|
+
client: GoogleGenAI;
|
|
24
|
+
/** Gemini API tier (1/2/3) of this key's billing account. */
|
|
25
|
+
tier: number;
|
|
26
|
+
}
|
|
27
|
+
declare class GoogleKeyPool {
|
|
28
|
+
private readonly entries;
|
|
29
|
+
constructor();
|
|
30
|
+
get size(): number;
|
|
31
|
+
/** The highest-priority key's client (index 0). */
|
|
32
|
+
get primaryClient(): GoogleGenAI;
|
|
33
|
+
/** Resolve a tagged task's key id back to its client (undefined if unknown). */
|
|
34
|
+
clientById(id: string | undefined): GoogleGenAI | undefined;
|
|
35
|
+
/**
|
|
36
|
+
* Pick the key that should serve a new submission. Walks keys in priority
|
|
37
|
+
* order and returns the first whose per-key minute + day budgets still have
|
|
38
|
+
* headroom, consuming a slot on it. The caps are the model's Tier-2 baseline
|
|
39
|
+
* (baselineMin / baselineDay) scaled to each key's own tier — so a Tier-1
|
|
40
|
+
* key gets a smaller share than a Tier-2 one. Falls back to the primary key
|
|
41
|
+
* if Redis is down or all are at cap (the aggregate model-level gate should
|
|
42
|
+
* have prevented the latter).
|
|
43
|
+
*/
|
|
44
|
+
pickForSubmit(modelId: string, baselineMin: number, baselineDay: number): Promise<KeyEntry>;
|
|
45
|
+
/** Best-effort increment of a key's per-day + per-minute routing counters. */
|
|
46
|
+
private consume;
|
|
47
|
+
}
|
|
48
|
+
/** Lazily-built process-wide pool. */
|
|
49
|
+
export declare function getGoogleKeyPool(): GoogleKeyPool;
|
|
50
|
+
export { googleApiKeyCount };
|
|
51
|
+
export type { GoogleKeyPool };
|
|
52
|
+
//# sourceMappingURL=googleKeyPool.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"googleKeyPool.d.ts","sourceRoot":"","sources":["../../../../../src/services/aiGen/providers/google/googleKeyPool.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAG5C,OAAO,EACL,iBAAiB,EAKlB,MAAM,iBAAiB,CAAC;AAEzB;;;;;;;;;;;;;;;;GAgBG;AAEH,UAAU,QAAQ;IAChB,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,WAAW,CAAC;IACpB,6DAA6D;IAC7D,IAAI,EAAE,MAAM,CAAC;CACd;AAcD,cAAM,aAAa;IACjB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAa;;IA4BrC,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED,mDAAmD;IACnD,IAAI,aAAa,IAAI,WAAW,CAE/B;IAED,gFAAgF;IAChF,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,SAAS,GAAG,WAAW,GAAG,SAAS;IAK3D;;;;;;;;OAQG;IACG,aAAa,CACjB,OAAO,EAAE,MAAM,EACf,WAAW,EAAE,MAAM,EACnB,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,QAAQ,CAAC;IA2CpB,8EAA8E;YAChE,OAAO;CAUtB;AAID,sCAAsC;AACtC,wBAAgB,gBAAgB,IAAI,aAAa,CAGhD;AAED,OAAO,EAAE,iBAAiB,EAAE,CAAC;AAC7B,YAAY,EAAE,aAAa,EAAE,CAAC"}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.googleApiKeyCount = void 0;
|
|
4
|
+
exports.getGoogleKeyPool = getGoogleKeyPool;
|
|
5
|
+
const genai_1 = require("@google/genai");
|
|
6
|
+
const logger_1 = require("../../../../utils/logger");
|
|
7
|
+
const redis_service_1 = require("../../../redis.service");
|
|
8
|
+
const googleApiKeys_1 = require("./googleApiKeys");
|
|
9
|
+
Object.defineProperty(exports, "googleApiKeyCount", { enumerable: true, get: function () { return googleApiKeys_1.googleApiKeyCount; } });
|
|
10
|
+
function utcDateKey() {
|
|
11
|
+
return new Date().toISOString().slice(0, 10);
|
|
12
|
+
}
|
|
13
|
+
function secsUntilMidnight() {
|
|
14
|
+
const now = new Date();
|
|
15
|
+
const midnight = new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate() + 1));
|
|
16
|
+
return Math.ceil((midnight.getTime() - now.getTime()) / 1000);
|
|
17
|
+
}
|
|
18
|
+
class GoogleKeyPool {
|
|
19
|
+
constructor() {
|
|
20
|
+
const keys = (0, googleApiKeys_1.parseGoogleApiKeys)();
|
|
21
|
+
const tiers = (0, googleApiKeys_1.parseGoogleApiKeyTiers)();
|
|
22
|
+
this.entries = keys.map((apiKey, i) => ({
|
|
23
|
+
id: (0, googleApiKeys_1.googleKeyId)(i),
|
|
24
|
+
apiKey,
|
|
25
|
+
client: new genai_1.GoogleGenAI({ apiKey }),
|
|
26
|
+
tier: tiers[i] ?? 2,
|
|
27
|
+
}));
|
|
28
|
+
if (!this.entries.length) {
|
|
29
|
+
// Mirror the legacy constructor: a bang-asserted GOOGLE_API_KEY. Building
|
|
30
|
+
// a client with undefined defers the failure to first call, same as before.
|
|
31
|
+
this.entries.push({
|
|
32
|
+
id: (0, googleApiKeys_1.googleKeyId)(0),
|
|
33
|
+
apiKey: process.env.GOOGLE_API_KEY ?? "",
|
|
34
|
+
client: new genai_1.GoogleGenAI({ apiKey: process.env.GOOGLE_API_KEY }),
|
|
35
|
+
tier: 2,
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
if (this.entries.length > 1) {
|
|
39
|
+
logger_1.logger.info("googleKeyPool: multi-key pool active", {
|
|
40
|
+
keys: this.entries.map((e) => ({ id: e.id, tier: e.tier })),
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
get size() {
|
|
45
|
+
return this.entries.length;
|
|
46
|
+
}
|
|
47
|
+
/** The highest-priority key's client (index 0). */
|
|
48
|
+
get primaryClient() {
|
|
49
|
+
return this.entries[0].client;
|
|
50
|
+
}
|
|
51
|
+
/** Resolve a tagged task's key id back to its client (undefined if unknown). */
|
|
52
|
+
clientById(id) {
|
|
53
|
+
if (!id)
|
|
54
|
+
return undefined;
|
|
55
|
+
return this.entries.find((e) => e.id === id)?.client;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Pick the key that should serve a new submission. Walks keys in priority
|
|
59
|
+
* order and returns the first whose per-key minute + day budgets still have
|
|
60
|
+
* headroom, consuming a slot on it. The caps are the model's Tier-2 baseline
|
|
61
|
+
* (baselineMin / baselineDay) scaled to each key's own tier — so a Tier-1
|
|
62
|
+
* key gets a smaller share than a Tier-2 one. Falls back to the primary key
|
|
63
|
+
* if Redis is down or all are at cap (the aggregate model-level gate should
|
|
64
|
+
* have prevented the latter).
|
|
65
|
+
*/
|
|
66
|
+
async pickForSubmit(modelId, baselineMin, baselineDay) {
|
|
67
|
+
if (this.entries.length === 1)
|
|
68
|
+
return this.entries[0];
|
|
69
|
+
const client = redis_service_1.redis.getClient();
|
|
70
|
+
if (!client)
|
|
71
|
+
return this.entries[0];
|
|
72
|
+
const date = utcDateKey();
|
|
73
|
+
for (const entry of this.entries) {
|
|
74
|
+
try {
|
|
75
|
+
const perKeyMinLimit = (0, googleApiKeys_1.scaleLimitForTier)(baselineMin, entry.tier, "rpm");
|
|
76
|
+
const perKeyDayLimit = (0, googleApiKeys_1.scaleLimitForTier)(baselineDay, entry.tier, "rpd");
|
|
77
|
+
const dayKey = `gkpool:${entry.id}:${modelId}:day:${date}`;
|
|
78
|
+
const minKey = `gkpool:${entry.id}:${modelId}:min`;
|
|
79
|
+
const [dayRaw, minRaw] = await Promise.all([
|
|
80
|
+
client.get(dayKey),
|
|
81
|
+
client.get(minKey),
|
|
82
|
+
]);
|
|
83
|
+
const dayUsed = dayRaw ? Number(dayRaw) : 0;
|
|
84
|
+
const minUsed = minRaw ? Number(minRaw) : 0;
|
|
85
|
+
const dayOk = perKeyDayLimit <= 0 || dayUsed < perKeyDayLimit;
|
|
86
|
+
const minOk = perKeyMinLimit <= 0 || minUsed < perKeyMinLimit;
|
|
87
|
+
if (dayOk && minOk) {
|
|
88
|
+
await this.consume(entry, modelId, date);
|
|
89
|
+
return entry;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
catch (err) {
|
|
93
|
+
logger_1.logger.warn("googleKeyPool: routing read failed, trying next key", {
|
|
94
|
+
keyId: entry.id,
|
|
95
|
+
err: err instanceof Error ? err.message : String(err),
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
// All at cap / errored — use the primary and let Google's own 429 + the
|
|
100
|
+
// provider-fallback chain handle it.
|
|
101
|
+
logger_1.logger.warn("googleKeyPool: no key with headroom — using primary", {
|
|
102
|
+
modelId,
|
|
103
|
+
poolSize: this.entries.length,
|
|
104
|
+
});
|
|
105
|
+
await this.consume(this.entries[0], modelId, date).catch(() => undefined);
|
|
106
|
+
return this.entries[0];
|
|
107
|
+
}
|
|
108
|
+
/** Best-effort increment of a key's per-day + per-minute routing counters. */
|
|
109
|
+
async consume(entry, modelId, date) {
|
|
110
|
+
const client = redis_service_1.redis.getClient();
|
|
111
|
+
if (!client)
|
|
112
|
+
return;
|
|
113
|
+
const dayKey = `gkpool:${entry.id}:${modelId}:day:${date}`;
|
|
114
|
+
const minKey = `gkpool:${entry.id}:${modelId}:min`;
|
|
115
|
+
const newDay = await client.incr(dayKey);
|
|
116
|
+
if (newDay === 1)
|
|
117
|
+
await client.expire(dayKey, secsUntilMidnight());
|
|
118
|
+
const newMin = await client.incr(minKey);
|
|
119
|
+
if (newMin === 1)
|
|
120
|
+
await client.expire(minKey, 60);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
let pool = null;
|
|
124
|
+
/** Lazily-built process-wide pool. */
|
|
125
|
+
function getGoogleKeyPool() {
|
|
126
|
+
if (!pool)
|
|
127
|
+
pool = new GoogleKeyPool();
|
|
128
|
+
return pool;
|
|
129
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { MusicGenerationParams, MusicGenerationResult } from "../types";
|
|
2
|
+
/**
|
|
3
|
+
* Lyria 2 (Vertex AI) music generation. Standalone — does NOT use the
|
|
4
|
+
* GoogleGenAI (Gemini Developer API) client; it auths via ADC and hits the
|
|
5
|
+
* Vertex predict endpoint directly. Extracted from GoogleService so the class
|
|
6
|
+
* stays focused on the Gemini-SDK paths.
|
|
7
|
+
*
|
|
8
|
+
* Sync — POST {region}-aiplatform.googleapis.com/.../lyria-002:predict returns
|
|
9
|
+
* base64-encoded WAV audio inline. Auth via ADC on the function service account
|
|
10
|
+
* (or GOOGLE_APPLICATION_CREDENTIALS locally).
|
|
11
|
+
*
|
|
12
|
+
* Required env: GCP_PROJECT_ID. Optional: GCP_LOCATION (default us-central1).
|
|
13
|
+
*/
|
|
14
|
+
export declare function generateGoogleMusic(params: MusicGenerationParams): Promise<MusicGenerationResult>;
|
|
15
|
+
//# sourceMappingURL=googleMusic.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"googleMusic.d.ts","sourceRoot":"","sources":["../../../../../src/services/aiGen/providers/google/googleMusic.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,qBAAqB,EAAE,qBAAqB,EAAE,MAAM,UAAU,CAAC;AAExE;;;;;;;;;;;GAWG;AACH,wBAAsB,mBAAmB,CACvC,MAAM,EAAE,qBAAqB,GAC5B,OAAO,CAAC,qBAAqB,CAAC,CAmEhC"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.generateGoogleMusic = generateGoogleMusic;
|
|
4
|
+
const google_auth_library_1 = require("google-auth-library");
|
|
5
|
+
const aiModels_1 = require("../../../../globals/aiModels");
|
|
6
|
+
const firebase_1 = require("../../../../libs/firebase");
|
|
7
|
+
/**
|
|
8
|
+
* Lyria 2 (Vertex AI) music generation. Standalone — does NOT use the
|
|
9
|
+
* GoogleGenAI (Gemini Developer API) client; it auths via ADC and hits the
|
|
10
|
+
* Vertex predict endpoint directly. Extracted from GoogleService so the class
|
|
11
|
+
* stays focused on the Gemini-SDK paths.
|
|
12
|
+
*
|
|
13
|
+
* Sync — POST {region}-aiplatform.googleapis.com/.../lyria-002:predict returns
|
|
14
|
+
* base64-encoded WAV audio inline. Auth via ADC on the function service account
|
|
15
|
+
* (or GOOGLE_APPLICATION_CREDENTIALS locally).
|
|
16
|
+
*
|
|
17
|
+
* Required env: GCP_PROJECT_ID. Optional: GCP_LOCATION (default us-central1).
|
|
18
|
+
*/
|
|
19
|
+
async function generateGoogleMusic(params) {
|
|
20
|
+
const modelConfig = aiModels_1.aiModelConfigs[params.modelKey];
|
|
21
|
+
const modelId = modelConfig?.modelId ?? "lyria-002";
|
|
22
|
+
const projectId = process.env.GCP_PROJECT_ID;
|
|
23
|
+
if (!projectId) {
|
|
24
|
+
throw new Error("Missing GCP_PROJECT_ID env var (required for Vertex Lyria)");
|
|
25
|
+
}
|
|
26
|
+
const location = process.env.GCP_LOCATION ?? "us-central1";
|
|
27
|
+
const auth = new google_auth_library_1.GoogleAuth({
|
|
28
|
+
scopes: ["https://www.googleapis.com/auth/cloud-platform"],
|
|
29
|
+
});
|
|
30
|
+
const client = await auth.getClient();
|
|
31
|
+
const tokenRes = await client.getAccessToken();
|
|
32
|
+
const token = tokenRes?.token;
|
|
33
|
+
if (!token)
|
|
34
|
+
throw new Error("Failed to obtain GCP access token for Vertex Lyria");
|
|
35
|
+
const url = `https://${location}-aiplatform.googleapis.com/v1/projects/${projectId}` +
|
|
36
|
+
`/locations/${location}/publishers/google/models/${modelId}:predict`;
|
|
37
|
+
const instance = { prompt: params.prompt };
|
|
38
|
+
const parameters = {
|
|
39
|
+
sample_count: 1,
|
|
40
|
+
};
|
|
41
|
+
if (params.negativePrompt) {
|
|
42
|
+
instance.negative_prompt = params.negativePrompt;
|
|
43
|
+
}
|
|
44
|
+
if (params.seed !== undefined) {
|
|
45
|
+
parameters.seed = params.seed;
|
|
46
|
+
}
|
|
47
|
+
const resp = await fetch(url, {
|
|
48
|
+
method: "POST",
|
|
49
|
+
headers: {
|
|
50
|
+
Authorization: `Bearer ${token}`,
|
|
51
|
+
"Content-Type": "application/json",
|
|
52
|
+
},
|
|
53
|
+
body: JSON.stringify({ instances: [instance], parameters }),
|
|
54
|
+
});
|
|
55
|
+
if (!resp.ok) {
|
|
56
|
+
const errText = await resp.text();
|
|
57
|
+
throw new Error(`Vertex Lyria failed (${resp.status}): ${errText}`);
|
|
58
|
+
}
|
|
59
|
+
const data = await resp.json();
|
|
60
|
+
const audioB64 = data?.predictions?.[0]?.bytesBase64Encoded;
|
|
61
|
+
if (!audioB64) {
|
|
62
|
+
throw new Error("Vertex Lyria returned no audio data");
|
|
63
|
+
}
|
|
64
|
+
const buffer = Buffer.from(audioB64, "base64");
|
|
65
|
+
const path = `music/lyria/${params.outputFilename}.wav`;
|
|
66
|
+
const file = (0, firebase_1.getBucket)().file(path);
|
|
67
|
+
await file.save(buffer, { contentType: "audio/wav" });
|
|
68
|
+
const [signed] = await file.getSignedUrl({
|
|
69
|
+
action: "read",
|
|
70
|
+
expires: "03-09-2491",
|
|
71
|
+
});
|
|
72
|
+
return {
|
|
73
|
+
audioUrl: signed,
|
|
74
|
+
mimeType: "audio/wav",
|
|
75
|
+
extension: "wav",
|
|
76
|
+
};
|
|
77
|
+
}
|