@juspay/neurolink 9.64.0 → 9.65.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (322) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/README.md +18 -17
  3. package/dist/adapters/providerImageAdapter.js +29 -1
  4. package/dist/adapters/replicate/auth.d.ts +19 -0
  5. package/dist/adapters/replicate/auth.js +32 -0
  6. package/dist/adapters/replicate/predictionLifecycle.d.ts +46 -0
  7. package/dist/adapters/replicate/predictionLifecycle.js +283 -0
  8. package/dist/adapters/video/klingVideoHandler.d.ts +37 -0
  9. package/dist/adapters/video/klingVideoHandler.js +305 -0
  10. package/dist/adapters/video/replicateVideoHandler.d.ts +29 -0
  11. package/dist/adapters/video/replicateVideoHandler.js +157 -0
  12. package/dist/adapters/video/runwayVideoHandler.d.ts +32 -0
  13. package/dist/adapters/video/runwayVideoHandler.js +316 -0
  14. package/dist/adapters/video/vertexVideoHandler.d.ts +19 -1
  15. package/dist/adapters/video/vertexVideoHandler.js +33 -9
  16. package/dist/autoresearch/runner.js +8 -2
  17. package/dist/avatar/index.d.ts +13 -0
  18. package/dist/avatar/index.js +13 -0
  19. package/dist/avatar/providers/DIDAvatar.d.ts +49 -0
  20. package/dist/avatar/providers/DIDAvatar.js +501 -0
  21. package/dist/avatar/providers/HeyGenAvatar.d.ts +30 -0
  22. package/dist/avatar/providers/HeyGenAvatar.js +337 -0
  23. package/dist/avatar/providers/ReplicateAvatar.d.ts +36 -0
  24. package/dist/avatar/providers/ReplicateAvatar.js +267 -0
  25. package/dist/browser/neurolink.min.js +633 -610
  26. package/dist/cli/commands/mcp.js +29 -0
  27. package/dist/cli/commands/proxy.js +24 -5
  28. package/dist/cli/factories/commandFactory.d.ts +11 -1
  29. package/dist/cli/factories/commandFactory.js +291 -38
  30. package/dist/constants/contextWindows.js +101 -0
  31. package/dist/constants/enums.d.ts +273 -2
  32. package/dist/constants/enums.js +290 -1
  33. package/dist/constants/videoErrors.d.ts +4 -0
  34. package/dist/constants/videoErrors.js +4 -0
  35. package/dist/core/baseProvider.d.ts +22 -2
  36. package/dist/core/baseProvider.js +217 -11
  37. package/dist/core/constants.d.ts +11 -0
  38. package/dist/core/constants.js +69 -1
  39. package/dist/core/redisConversationMemoryManager.js +6 -0
  40. package/dist/evaluation/index.d.ts +2 -0
  41. package/dist/evaluation/index.js +4 -0
  42. package/dist/factories/providerFactory.js +7 -1
  43. package/dist/factories/providerRegistry.js +202 -5
  44. package/dist/features/ppt/contentPlanner.js +42 -14
  45. package/dist/index.d.ts +9 -1
  46. package/dist/index.js +16 -1
  47. package/dist/lib/adapters/providerImageAdapter.js +29 -1
  48. package/dist/lib/adapters/replicate/auth.d.ts +19 -0
  49. package/dist/lib/adapters/replicate/auth.js +33 -0
  50. package/dist/lib/adapters/replicate/predictionLifecycle.d.ts +46 -0
  51. package/dist/lib/adapters/replicate/predictionLifecycle.js +284 -0
  52. package/dist/lib/adapters/video/klingVideoHandler.d.ts +37 -0
  53. package/dist/lib/adapters/video/klingVideoHandler.js +306 -0
  54. package/dist/lib/adapters/video/replicateVideoHandler.d.ts +29 -0
  55. package/dist/lib/adapters/video/replicateVideoHandler.js +158 -0
  56. package/dist/lib/adapters/video/runwayVideoHandler.d.ts +32 -0
  57. package/dist/lib/adapters/video/runwayVideoHandler.js +317 -0
  58. package/dist/lib/adapters/video/vertexVideoHandler.d.ts +19 -1
  59. package/dist/lib/adapters/video/vertexVideoHandler.js +33 -9
  60. package/dist/lib/autoresearch/runner.js +8 -2
  61. package/dist/lib/avatar/index.d.ts +13 -0
  62. package/dist/lib/avatar/index.js +14 -0
  63. package/dist/lib/avatar/providers/DIDAvatar.d.ts +49 -0
  64. package/dist/lib/avatar/providers/DIDAvatar.js +502 -0
  65. package/dist/lib/avatar/providers/HeyGenAvatar.d.ts +30 -0
  66. package/dist/lib/avatar/providers/HeyGenAvatar.js +338 -0
  67. package/dist/lib/avatar/providers/ReplicateAvatar.d.ts +36 -0
  68. package/dist/lib/avatar/providers/ReplicateAvatar.js +268 -0
  69. package/dist/lib/constants/contextWindows.js +101 -0
  70. package/dist/lib/constants/enums.d.ts +273 -2
  71. package/dist/lib/constants/enums.js +290 -1
  72. package/dist/lib/constants/videoErrors.d.ts +4 -0
  73. package/dist/lib/constants/videoErrors.js +4 -0
  74. package/dist/lib/core/baseProvider.d.ts +22 -2
  75. package/dist/lib/core/baseProvider.js +217 -11
  76. package/dist/lib/core/constants.d.ts +11 -0
  77. package/dist/lib/core/constants.js +69 -1
  78. package/dist/lib/core/redisConversationMemoryManager.js +6 -0
  79. package/dist/lib/evaluation/index.d.ts +2 -0
  80. package/dist/lib/evaluation/index.js +4 -0
  81. package/dist/lib/factories/providerFactory.js +7 -1
  82. package/dist/lib/factories/providerRegistry.js +202 -5
  83. package/dist/lib/features/ppt/contentPlanner.js +42 -14
  84. package/dist/lib/index.d.ts +9 -1
  85. package/dist/lib/index.js +16 -1
  86. package/dist/lib/middleware/builtin/lifecycle.js +39 -9
  87. package/dist/lib/music/index.d.ts +13 -0
  88. package/dist/lib/music/index.js +14 -0
  89. package/dist/lib/music/providers/BeatovenMusic.d.ts +31 -0
  90. package/dist/lib/music/providers/BeatovenMusic.js +334 -0
  91. package/dist/lib/music/providers/ElevenLabsMusic.d.ts +30 -0
  92. package/dist/lib/music/providers/ElevenLabsMusic.js +169 -0
  93. package/dist/lib/music/providers/LyriaMusic.d.ts +29 -0
  94. package/dist/lib/music/providers/LyriaMusic.js +173 -0
  95. package/dist/lib/music/providers/ReplicateMusic.d.ts +31 -0
  96. package/dist/lib/music/providers/ReplicateMusic.js +262 -0
  97. package/dist/lib/neurolink.d.ts +30 -0
  98. package/dist/lib/neurolink.js +323 -77
  99. package/dist/lib/providers/amazonBedrock.d.ts +10 -0
  100. package/dist/lib/providers/amazonBedrock.js +94 -39
  101. package/dist/lib/providers/anthropic.js +55 -7
  102. package/dist/lib/providers/anthropicBaseProvider.js +1 -1
  103. package/dist/lib/providers/azureOpenai.js +66 -17
  104. package/dist/lib/providers/cloudflare.d.ts +35 -0
  105. package/dist/lib/providers/cloudflare.js +174 -0
  106. package/dist/lib/providers/cohere.d.ts +52 -0
  107. package/dist/lib/providers/cohere.js +253 -0
  108. package/dist/lib/providers/deepseek.js +72 -17
  109. package/dist/lib/providers/fireworks.d.ts +33 -0
  110. package/dist/lib/providers/fireworks.js +164 -0
  111. package/dist/lib/providers/googleAiStudio.js +45 -6
  112. package/dist/lib/providers/googleNativeGemini3.d.ts +24 -1
  113. package/dist/lib/providers/googleNativeGemini3.js +173 -21
  114. package/dist/lib/providers/googleVertex.js +173 -17
  115. package/dist/lib/providers/groq.d.ts +33 -0
  116. package/dist/lib/providers/groq.js +181 -0
  117. package/dist/lib/providers/huggingFace.js +9 -8
  118. package/dist/lib/providers/ideogram.d.ts +34 -0
  119. package/dist/lib/providers/ideogram.js +184 -0
  120. package/dist/lib/providers/index.d.ts +13 -0
  121. package/dist/lib/providers/index.js +13 -0
  122. package/dist/lib/providers/jina.d.ts +59 -0
  123. package/dist/lib/providers/jina.js +218 -0
  124. package/dist/lib/providers/llamaCpp.js +14 -46
  125. package/dist/lib/providers/lmStudio.js +14 -47
  126. package/dist/lib/providers/mistral.js +7 -7
  127. package/dist/lib/providers/nvidiaNim.js +160 -19
  128. package/dist/lib/providers/ollama.js +7 -7
  129. package/dist/lib/providers/openAI.d.ts +22 -1
  130. package/dist/lib/providers/openAI.js +181 -0
  131. package/dist/lib/providers/openRouter.js +35 -23
  132. package/dist/lib/providers/openaiCompatible.js +9 -8
  133. package/dist/lib/providers/perplexity.d.ts +33 -0
  134. package/dist/lib/providers/perplexity.js +179 -0
  135. package/dist/lib/providers/recraft.d.ts +34 -0
  136. package/dist/lib/providers/recraft.js +197 -0
  137. package/dist/lib/providers/replicate.d.ts +75 -0
  138. package/dist/lib/providers/replicate.js +403 -0
  139. package/dist/lib/providers/stability.d.ts +37 -0
  140. package/dist/lib/providers/stability.js +191 -0
  141. package/dist/lib/providers/togetherAi.d.ts +33 -0
  142. package/dist/lib/providers/togetherAi.js +176 -0
  143. package/dist/lib/providers/voyage.d.ts +47 -0
  144. package/dist/lib/providers/voyage.js +177 -0
  145. package/dist/lib/providers/xai.d.ts +33 -0
  146. package/dist/lib/providers/xai.js +172 -0
  147. package/dist/lib/telemetry/index.d.ts +1 -1
  148. package/dist/lib/telemetry/index.js +1 -1
  149. package/dist/lib/telemetry/tracers.d.ts +19 -0
  150. package/dist/lib/telemetry/tracers.js +19 -0
  151. package/dist/lib/telemetry/withSpan.d.ts +35 -0
  152. package/dist/lib/telemetry/withSpan.js +103 -0
  153. package/dist/lib/types/avatar.d.ts +143 -0
  154. package/dist/lib/types/avatar.js +20 -0
  155. package/dist/lib/types/cli.d.ts +6 -0
  156. package/dist/lib/types/generate.d.ts +62 -5
  157. package/dist/lib/types/index.d.ts +5 -0
  158. package/dist/lib/types/index.js +7 -0
  159. package/dist/lib/types/middleware.d.ts +27 -0
  160. package/dist/lib/types/multimodal.d.ts +35 -2
  161. package/dist/lib/types/music.d.ts +165 -0
  162. package/dist/lib/types/music.js +21 -0
  163. package/dist/lib/types/providers.d.ts +144 -1
  164. package/dist/lib/types/replicate.d.ts +67 -0
  165. package/dist/lib/types/replicate.js +10 -0
  166. package/dist/lib/types/safeFetch.d.ts +15 -0
  167. package/dist/lib/types/safeFetch.js +7 -0
  168. package/dist/lib/types/stream.d.ts +2 -1
  169. package/dist/lib/types/tools.d.ts +13 -0
  170. package/dist/lib/types/video.d.ts +89 -0
  171. package/dist/lib/types/video.js +15 -0
  172. package/dist/lib/utils/avatarProcessor.d.ts +68 -0
  173. package/dist/lib/utils/avatarProcessor.js +172 -0
  174. package/dist/lib/utils/cloneOptions.d.ts +36 -0
  175. package/dist/lib/utils/cloneOptions.js +62 -0
  176. package/dist/lib/utils/lifecycleCallbacks.d.ts +51 -8
  177. package/dist/lib/utils/lifecycleCallbacks.js +82 -26
  178. package/dist/lib/utils/lifecycleTimeout.d.ts +25 -0
  179. package/dist/lib/utils/lifecycleTimeout.js +39 -0
  180. package/dist/lib/utils/logSanitize.d.ts +49 -0
  181. package/dist/lib/utils/logSanitize.js +170 -0
  182. package/dist/lib/utils/loggingFetch.d.ts +29 -0
  183. package/dist/lib/utils/loggingFetch.js +60 -0
  184. package/dist/lib/utils/messageBuilder.js +43 -25
  185. package/dist/lib/utils/modelChoices.js +236 -3
  186. package/dist/lib/utils/musicProcessor.d.ts +67 -0
  187. package/dist/lib/utils/musicProcessor.js +189 -0
  188. package/dist/lib/utils/optionsConversion.js +3 -2
  189. package/dist/lib/utils/parameterValidation.js +14 -4
  190. package/dist/lib/utils/pricing.js +193 -0
  191. package/dist/lib/utils/providerConfig.d.ts +55 -0
  192. package/dist/lib/utils/providerConfig.js +224 -0
  193. package/dist/lib/utils/safeFetch.d.ts +26 -0
  194. package/dist/lib/utils/safeFetch.js +83 -0
  195. package/dist/lib/utils/sizeGuard.d.ts +34 -0
  196. package/dist/lib/utils/sizeGuard.js +45 -0
  197. package/dist/lib/utils/ssrfGuard.d.ts +52 -0
  198. package/dist/lib/utils/ssrfGuard.js +411 -0
  199. package/dist/lib/utils/videoProcessor.d.ts +60 -0
  200. package/dist/lib/utils/videoProcessor.js +201 -0
  201. package/dist/lib/voice/providers/FishAudioTTS.d.ts +27 -0
  202. package/dist/lib/voice/providers/FishAudioTTS.js +183 -0
  203. package/dist/lib/workflow/core/ensembleExecutor.js +26 -9
  204. package/dist/middleware/builtin/lifecycle.js +39 -9
  205. package/dist/music/index.d.ts +13 -0
  206. package/dist/music/index.js +13 -0
  207. package/dist/music/providers/BeatovenMusic.d.ts +31 -0
  208. package/dist/music/providers/BeatovenMusic.js +333 -0
  209. package/dist/music/providers/ElevenLabsMusic.d.ts +30 -0
  210. package/dist/music/providers/ElevenLabsMusic.js +168 -0
  211. package/dist/music/providers/LyriaMusic.d.ts +29 -0
  212. package/dist/music/providers/LyriaMusic.js +172 -0
  213. package/dist/music/providers/ReplicateMusic.d.ts +31 -0
  214. package/dist/music/providers/ReplicateMusic.js +261 -0
  215. package/dist/neurolink.d.ts +30 -0
  216. package/dist/neurolink.js +323 -77
  217. package/dist/providers/amazonBedrock.d.ts +10 -0
  218. package/dist/providers/amazonBedrock.js +94 -39
  219. package/dist/providers/anthropic.js +55 -7
  220. package/dist/providers/anthropicBaseProvider.js +1 -1
  221. package/dist/providers/azureOpenai.js +66 -17
  222. package/dist/providers/cloudflare.d.ts +35 -0
  223. package/dist/providers/cloudflare.js +173 -0
  224. package/dist/providers/cohere.d.ts +52 -0
  225. package/dist/providers/cohere.js +252 -0
  226. package/dist/providers/deepseek.js +72 -17
  227. package/dist/providers/fireworks.d.ts +33 -0
  228. package/dist/providers/fireworks.js +163 -0
  229. package/dist/providers/googleAiStudio.js +45 -6
  230. package/dist/providers/googleNativeGemini3.d.ts +24 -1
  231. package/dist/providers/googleNativeGemini3.js +173 -21
  232. package/dist/providers/googleVertex.js +173 -17
  233. package/dist/providers/groq.d.ts +33 -0
  234. package/dist/providers/groq.js +180 -0
  235. package/dist/providers/huggingFace.js +9 -8
  236. package/dist/providers/ideogram.d.ts +34 -0
  237. package/dist/providers/ideogram.js +183 -0
  238. package/dist/providers/index.d.ts +13 -0
  239. package/dist/providers/index.js +13 -0
  240. package/dist/providers/jina.d.ts +59 -0
  241. package/dist/providers/jina.js +217 -0
  242. package/dist/providers/llamaCpp.js +14 -46
  243. package/dist/providers/lmStudio.js +14 -47
  244. package/dist/providers/mistral.js +7 -7
  245. package/dist/providers/nvidiaNim.js +160 -19
  246. package/dist/providers/ollama.js +7 -7
  247. package/dist/providers/openAI.d.ts +22 -1
  248. package/dist/providers/openAI.js +181 -0
  249. package/dist/providers/openRouter.js +35 -23
  250. package/dist/providers/openaiCompatible.js +9 -8
  251. package/dist/providers/perplexity.d.ts +33 -0
  252. package/dist/providers/perplexity.js +178 -0
  253. package/dist/providers/recraft.d.ts +34 -0
  254. package/dist/providers/recraft.js +196 -0
  255. package/dist/providers/replicate.d.ts +75 -0
  256. package/dist/providers/replicate.js +402 -0
  257. package/dist/providers/stability.d.ts +37 -0
  258. package/dist/providers/stability.js +190 -0
  259. package/dist/providers/togetherAi.d.ts +33 -0
  260. package/dist/providers/togetherAi.js +175 -0
  261. package/dist/providers/voyage.d.ts +47 -0
  262. package/dist/providers/voyage.js +176 -0
  263. package/dist/providers/xai.d.ts +33 -0
  264. package/dist/providers/xai.js +171 -0
  265. package/dist/telemetry/index.d.ts +1 -1
  266. package/dist/telemetry/index.js +1 -1
  267. package/dist/telemetry/tracers.d.ts +19 -0
  268. package/dist/telemetry/tracers.js +19 -0
  269. package/dist/telemetry/withSpan.d.ts +35 -0
  270. package/dist/telemetry/withSpan.js +103 -0
  271. package/dist/types/avatar.d.ts +143 -0
  272. package/dist/types/avatar.js +19 -0
  273. package/dist/types/cli.d.ts +6 -0
  274. package/dist/types/generate.d.ts +62 -5
  275. package/dist/types/index.d.ts +5 -0
  276. package/dist/types/index.js +7 -0
  277. package/dist/types/middleware.d.ts +27 -0
  278. package/dist/types/multimodal.d.ts +35 -2
  279. package/dist/types/music.d.ts +165 -0
  280. package/dist/types/music.js +20 -0
  281. package/dist/types/providers.d.ts +144 -1
  282. package/dist/types/replicate.d.ts +67 -0
  283. package/dist/types/replicate.js +9 -0
  284. package/dist/types/safeFetch.d.ts +15 -0
  285. package/dist/types/safeFetch.js +6 -0
  286. package/dist/types/stream.d.ts +2 -1
  287. package/dist/types/tools.d.ts +13 -0
  288. package/dist/types/video.d.ts +89 -0
  289. package/dist/types/video.js +14 -0
  290. package/dist/utils/avatarProcessor.d.ts +68 -0
  291. package/dist/utils/avatarProcessor.js +171 -0
  292. package/dist/utils/cloneOptions.d.ts +36 -0
  293. package/dist/utils/cloneOptions.js +61 -0
  294. package/dist/utils/lifecycleCallbacks.d.ts +51 -8
  295. package/dist/utils/lifecycleCallbacks.js +82 -26
  296. package/dist/utils/lifecycleTimeout.d.ts +25 -0
  297. package/dist/utils/lifecycleTimeout.js +38 -0
  298. package/dist/utils/logSanitize.d.ts +49 -0
  299. package/dist/utils/logSanitize.js +169 -0
  300. package/dist/utils/loggingFetch.d.ts +29 -0
  301. package/dist/utils/loggingFetch.js +59 -0
  302. package/dist/utils/messageBuilder.js +43 -25
  303. package/dist/utils/modelChoices.js +236 -3
  304. package/dist/utils/musicProcessor.d.ts +67 -0
  305. package/dist/utils/musicProcessor.js +188 -0
  306. package/dist/utils/optionsConversion.js +3 -2
  307. package/dist/utils/parameterValidation.js +14 -4
  308. package/dist/utils/pricing.js +193 -0
  309. package/dist/utils/providerConfig.d.ts +55 -0
  310. package/dist/utils/providerConfig.js +224 -0
  311. package/dist/utils/safeFetch.d.ts +26 -0
  312. package/dist/utils/safeFetch.js +82 -0
  313. package/dist/utils/sizeGuard.d.ts +34 -0
  314. package/dist/utils/sizeGuard.js +44 -0
  315. package/dist/utils/ssrfGuard.d.ts +52 -0
  316. package/dist/utils/ssrfGuard.js +410 -0
  317. package/dist/utils/videoProcessor.d.ts +60 -0
  318. package/dist/utils/videoProcessor.js +200 -0
  319. package/dist/voice/providers/FishAudioTTS.d.ts +27 -0
  320. package/dist/voice/providers/FishAudioTTS.js +182 -0
  321. package/dist/workflow/core/ensembleExecutor.js +26 -9
  322. package/package.json +32 -5
@@ -0,0 +1,333 @@
1
+ /**
2
+ * Beatoven.ai Music Generation Handler
3
+ *
4
+ * Async track-composition API. Submits a compose-track request, polls the
5
+ * task status, and downloads the resulting audio.
6
+ *
7
+ * @module music/providers/BeatovenMusic
8
+ * @see https://www.beatoven.ai/api-docs
9
+ */
10
+ import { ErrorCategory, ErrorSeverity } from "../../constants/enums.js";
11
+ import { logger } from "../../utils/logger.js";
12
+ import { MUSIC_ERROR_CODES, MusicError } from "../../utils/musicProcessor.js";
13
+ import { MAX_AUDIO_BYTES, readBoundedBuffer } from "../../utils/sizeGuard.js";
14
+ import { assertSafeUrl } from "../../utils/ssrfGuard.js";
15
+ const DEFAULT_BASE_URL = "https://public-api.beatoven.ai";
16
+ const REQUEST_TIMEOUT_MS = 30_000;
17
+ const POLL_INTERVAL_MS = 3_000;
18
+ const TOTAL_TIMEOUT_MS = 5 * 60_000;
19
+ /**
20
+ * Beatoven.ai Music Generation Handler.
21
+ *
22
+ * Beatoven is a royalty-free music generation API tuned for
23
+ * background / cinematic / brand music. Tracks are composed
24
+ * asynchronously: submit a prompt, poll the task, then download.
25
+ */
26
+ export class BeatovenMusic {
27
+ maxDurationSeconds = 300; // 5 minutes per track
28
+ supportedFormats = [
29
+ "mp3",
30
+ "wav",
31
+ ];
32
+ supportedGenres = [
33
+ "ambient",
34
+ "cinematic",
35
+ "corporate",
36
+ "lo-fi",
37
+ "rock",
38
+ "pop",
39
+ "electronic",
40
+ "orchestral",
41
+ "folk",
42
+ ];
43
+ apiKey;
44
+ baseUrl;
45
+ constructor(apiKey) {
46
+ const resolved = (apiKey ?? process.env.BEATOVEN_API_KEY ?? "").trim();
47
+ this.apiKey = resolved.length > 0 ? resolved : null;
48
+ this.baseUrl = (process.env.BEATOVEN_BASE_URL ?? DEFAULT_BASE_URL).replace(/\/$/, "");
49
+ }
50
+ isConfigured() {
51
+ return this.apiKey !== null;
52
+ }
53
+ async generate(options) {
54
+ if (!this.apiKey) {
55
+ throw new MusicError({
56
+ code: MUSIC_ERROR_CODES.PROVIDER_NOT_CONFIGURED,
57
+ message: "BEATOVEN_API_KEY not configured",
58
+ category: ErrorCategory.CONFIGURATION,
59
+ severity: ErrorSeverity.HIGH,
60
+ retriable: false,
61
+ });
62
+ }
63
+ const startTime = Date.now();
64
+ const requestedFormat = options.format ?? "mp3";
65
+ if (!this.supportedFormats.includes(requestedFormat)) {
66
+ logger.warn(`[BeatovenMusic] Format "${requestedFormat}" not supported — falling back to "mp3"`);
67
+ }
68
+ const upstreamFormat = this.supportedFormats.includes(requestedFormat)
69
+ ? requestedFormat
70
+ : "mp3";
71
+ // 1. Submit compose-track request.
72
+ const compose = await this.submitCompose(options, upstreamFormat);
73
+ const taskId = compose.task_id;
74
+ // 2. Poll until composed or failed.
75
+ const taskResult = await this.pollUntilComposed(taskId, options.timeout ?? TOTAL_TIMEOUT_MS);
76
+ const trackUrl = taskResult.meta?.track_url;
77
+ if (!trackUrl) {
78
+ throw new MusicError({
79
+ code: MUSIC_ERROR_CODES.GENERATION_FAILED,
80
+ message: `Beatoven task ${taskId} completed but no track_url returned`,
81
+ category: ErrorCategory.EXECUTION,
82
+ severity: ErrorSeverity.HIGH,
83
+ retriable: false,
84
+ context: { taskId, taskResult },
85
+ });
86
+ }
87
+ // 3. Download.
88
+ const buffer = await this.downloadTrack(trackUrl);
89
+ const latency = Date.now() - startTime;
90
+ logger.info(`[BeatovenMusic] Generated ${buffer.length} bytes (${upstreamFormat}) in ${latency}ms — task ${taskId}`);
91
+ return {
92
+ buffer,
93
+ format: upstreamFormat,
94
+ size: buffer.length,
95
+ duration: taskResult.meta?.duration,
96
+ provider: "beatoven",
97
+ metadata: {
98
+ latency,
99
+ provider: "beatoven",
100
+ model: "beatoven-default",
101
+ jobId: taskId,
102
+ trackId: taskResult.meta?.track_id,
103
+ projectId: taskResult.meta?.project_id,
104
+ requestedFormat: options.format,
105
+ },
106
+ };
107
+ }
108
+ async submitCompose(options, format) {
109
+ const durationMs = (options.duration ?? 60) * 1000;
110
+ const promptParts = [options.prompt];
111
+ if (options.genre) {
112
+ promptParts.push(`Genre: ${options.genre}`);
113
+ }
114
+ if (options.mood) {
115
+ promptParts.push(`Mood: ${options.mood}`);
116
+ }
117
+ if (options.tempo !== undefined) {
118
+ promptParts.push(`Tempo: ${options.tempo} BPM`);
119
+ }
120
+ const body = {
121
+ prompt: { text: promptParts.join(". ") },
122
+ duration: durationMs,
123
+ format,
124
+ };
125
+ const controller = new AbortController();
126
+ const timeoutId = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);
127
+ let response;
128
+ try {
129
+ response = await fetch(`${this.baseUrl}/api/v1/tracks/compose`, {
130
+ method: "POST",
131
+ headers: {
132
+ Authorization: `Bearer ${this.apiKey}`,
133
+ "Content-Type": "application/json",
134
+ },
135
+ body: JSON.stringify(body),
136
+ signal: controller.signal,
137
+ });
138
+ }
139
+ catch (err) {
140
+ if (err instanceof Error && err.name === "AbortError") {
141
+ throw new MusicError({
142
+ code: MUSIC_ERROR_CODES.GENERATION_FAILED,
143
+ message: `Beatoven compose request timed out after ${REQUEST_TIMEOUT_MS / 1000}s`,
144
+ category: ErrorCategory.NETWORK,
145
+ severity: ErrorSeverity.HIGH,
146
+ retriable: true,
147
+ originalError: err,
148
+ });
149
+ }
150
+ throw new MusicError({
151
+ code: MUSIC_ERROR_CODES.GENERATION_FAILED,
152
+ message: `Beatoven compose network error: ${err instanceof Error ? err.message : String(err)}`,
153
+ category: ErrorCategory.NETWORK,
154
+ severity: ErrorSeverity.HIGH,
155
+ retriable: true,
156
+ originalError: err instanceof Error ? err : undefined,
157
+ });
158
+ }
159
+ finally {
160
+ clearTimeout(timeoutId);
161
+ }
162
+ if (!response.ok) {
163
+ const text = await response.text();
164
+ const retriable = response.status === 408 ||
165
+ response.status === 429 ||
166
+ response.status >= 500;
167
+ throw new MusicError({
168
+ code: MUSIC_ERROR_CODES.GENERATION_FAILED,
169
+ message: `Beatoven compose failed: ${response.status} — ${text}`,
170
+ category: retriable ? ErrorCategory.NETWORK : ErrorCategory.EXECUTION,
171
+ severity: ErrorSeverity.HIGH,
172
+ retriable,
173
+ context: { status: response.status, body: text },
174
+ });
175
+ }
176
+ const json = (await response.json());
177
+ if (!json.task_id) {
178
+ throw new MusicError({
179
+ code: MUSIC_ERROR_CODES.GENERATION_FAILED,
180
+ message: "Beatoven compose response missing task_id",
181
+ category: ErrorCategory.EXECUTION,
182
+ severity: ErrorSeverity.HIGH,
183
+ retriable: false,
184
+ context: { response: json },
185
+ });
186
+ }
187
+ return json;
188
+ }
189
+ async pollUntilComposed(taskId, totalTimeoutMs) {
190
+ const startTime = Date.now();
191
+ while (Date.now() - startTime < totalTimeoutMs) {
192
+ const status = await this.fetchTaskStatus(taskId);
193
+ if (status.status === "composed") {
194
+ return status;
195
+ }
196
+ if (status.status === "failed") {
197
+ throw new MusicError({
198
+ code: MUSIC_ERROR_CODES.GENERATION_FAILED,
199
+ message: `Beatoven task ${taskId} failed: ${status.message ?? "unknown"}`,
200
+ category: ErrorCategory.EXECUTION,
201
+ severity: ErrorSeverity.HIGH,
202
+ retriable: false,
203
+ context: { taskId, status },
204
+ });
205
+ }
206
+ await new Promise((r) => setTimeout(r, POLL_INTERVAL_MS));
207
+ }
208
+ throw new MusicError({
209
+ code: MUSIC_ERROR_CODES.POLL_TIMEOUT,
210
+ message: `Beatoven task ${taskId} did not complete within ${Math.round(totalTimeoutMs / 1000)}s`,
211
+ category: ErrorCategory.TIMEOUT,
212
+ severity: ErrorSeverity.MEDIUM,
213
+ retriable: true,
214
+ context: { taskId, totalTimeoutMs },
215
+ });
216
+ }
217
+ async fetchTaskStatus(taskId) {
218
+ const controller = new AbortController();
219
+ const timeoutId = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);
220
+ let response;
221
+ try {
222
+ response = await fetch(`${this.baseUrl}/api/v1/tasks/${taskId}`, {
223
+ method: "GET",
224
+ headers: { Authorization: `Bearer ${this.apiKey}` },
225
+ signal: controller.signal,
226
+ });
227
+ }
228
+ catch (err) {
229
+ if (err instanceof Error && err.name === "AbortError") {
230
+ throw new MusicError({
231
+ code: MUSIC_ERROR_CODES.GENERATION_FAILED,
232
+ message: `Beatoven status poll timed out after ${REQUEST_TIMEOUT_MS / 1000}s`,
233
+ category: ErrorCategory.NETWORK,
234
+ severity: ErrorSeverity.MEDIUM,
235
+ retriable: true,
236
+ originalError: err,
237
+ });
238
+ }
239
+ throw new MusicError({
240
+ code: MUSIC_ERROR_CODES.GENERATION_FAILED,
241
+ message: `Beatoven status poll network error: ${err instanceof Error ? err.message : String(err)}`,
242
+ category: ErrorCategory.NETWORK,
243
+ severity: ErrorSeverity.MEDIUM,
244
+ retriable: true,
245
+ originalError: err instanceof Error ? err : undefined,
246
+ context: { taskId },
247
+ });
248
+ }
249
+ finally {
250
+ clearTimeout(timeoutId);
251
+ }
252
+ if (!response.ok) {
253
+ const text = await response.text();
254
+ throw new MusicError({
255
+ code: MUSIC_ERROR_CODES.GENERATION_FAILED,
256
+ message: `Beatoven status request failed: ${response.status} — ${text}`,
257
+ category: ErrorCategory.EXECUTION,
258
+ severity: ErrorSeverity.MEDIUM,
259
+ retriable: response.status >= 500,
260
+ context: { status: response.status, taskId },
261
+ });
262
+ }
263
+ return (await response.json());
264
+ }
265
+ async downloadTrack(url) {
266
+ try {
267
+ await assertSafeUrl(url);
268
+ }
269
+ catch (err) {
270
+ throw new MusicError({
271
+ code: MUSIC_ERROR_CODES.GENERATION_FAILED,
272
+ message: `Beatoven track URL rejected: ${err instanceof Error ? err.message : String(err)}`,
273
+ category: ErrorCategory.VALIDATION,
274
+ severity: ErrorSeverity.HIGH,
275
+ retriable: false,
276
+ context: { url },
277
+ });
278
+ }
279
+ const controller = new AbortController();
280
+ const timeoutId = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);
281
+ let response;
282
+ try {
283
+ response = await fetch(url, { signal: controller.signal });
284
+ }
285
+ catch (err) {
286
+ if (err instanceof Error && err.name === "AbortError") {
287
+ throw new MusicError({
288
+ code: MUSIC_ERROR_CODES.GENERATION_FAILED,
289
+ message: `Beatoven track download timed out after ${REQUEST_TIMEOUT_MS / 1000}s`,
290
+ category: ErrorCategory.NETWORK,
291
+ severity: ErrorSeverity.MEDIUM,
292
+ retriable: true,
293
+ originalError: err,
294
+ });
295
+ }
296
+ throw new MusicError({
297
+ code: MUSIC_ERROR_CODES.GENERATION_FAILED,
298
+ message: `Beatoven track download network error: ${err instanceof Error ? err.message : String(err)}`,
299
+ category: ErrorCategory.NETWORK,
300
+ severity: ErrorSeverity.MEDIUM,
301
+ retriable: true,
302
+ originalError: err instanceof Error ? err : undefined,
303
+ context: { url },
304
+ });
305
+ }
306
+ finally {
307
+ clearTimeout(timeoutId);
308
+ }
309
+ if (!response.ok) {
310
+ throw new MusicError({
311
+ code: MUSIC_ERROR_CODES.GENERATION_FAILED,
312
+ message: `Beatoven track download failed: ${response.status}`,
313
+ category: ErrorCategory.NETWORK,
314
+ severity: ErrorSeverity.MEDIUM,
315
+ retriable: response.status >= 500,
316
+ context: { status: response.status, url },
317
+ });
318
+ }
319
+ try {
320
+ return await readBoundedBuffer(response, MAX_AUDIO_BYTES, "Beatoven track");
321
+ }
322
+ catch (err) {
323
+ throw new MusicError({
324
+ code: MUSIC_ERROR_CODES.GENERATION_FAILED,
325
+ message: `Beatoven track download exceeded size limit: ${err instanceof Error ? err.message : String(err)}`,
326
+ category: ErrorCategory.EXECUTION,
327
+ severity: ErrorSeverity.HIGH,
328
+ retriable: false,
329
+ context: { url },
330
+ });
331
+ }
332
+ }
333
+ }
@@ -0,0 +1,30 @@
1
+ /**
2
+ * ElevenLabs Music / Sound Generation Handler
3
+ *
4
+ * Distinct from ElevenLabs TTS — uses the `/v1/sound-generation` endpoint
5
+ * (synchronous; returns binary audio directly, no polling).
6
+ *
7
+ * @module music/providers/ElevenLabsMusic
8
+ * @see https://elevenlabs.io/docs/api-reference/sound-generation
9
+ */
10
+ import type { MusicAudioFormat, MusicHandler, MusicOptions, MusicResult } from "../../types/index.js";
11
+ /**
12
+ * ElevenLabs Music / Sound Generation Handler.
13
+ *
14
+ * Auth: `xi-api-key: ${ELEVENLABS_API_KEY}` (shares the same env var as
15
+ * ElevenLabs TTS — same account; different endpoint).
16
+ *
17
+ * Best for: short sound effects (ambient drones, hits, foley) and short
18
+ * music loops up to 22 seconds.
19
+ */
20
+ export declare class ElevenLabsMusic implements MusicHandler {
21
+ readonly maxDurationSeconds = 22;
22
+ readonly supportedFormats: readonly MusicAudioFormat[];
23
+ readonly supportedGenres: readonly string[];
24
+ private readonly apiKey;
25
+ private readonly baseUrl;
26
+ constructor(apiKey?: string);
27
+ isConfigured(): boolean;
28
+ generate(options: MusicOptions): Promise<MusicResult>;
29
+ private buildPrompt;
30
+ }
@@ -0,0 +1,168 @@
1
+ /**
2
+ * ElevenLabs Music / Sound Generation Handler
3
+ *
4
+ * Distinct from ElevenLabs TTS — uses the `/v1/sound-generation` endpoint
5
+ * (synchronous; returns binary audio directly, no polling).
6
+ *
7
+ * @module music/providers/ElevenLabsMusic
8
+ * @see https://elevenlabs.io/docs/api-reference/sound-generation
9
+ */
10
+ import { ErrorCategory, ErrorSeverity } from "../../constants/enums.js";
11
+ import { MUSIC_ERROR_CODES, MusicError } from "../../utils/musicProcessor.js";
12
+ import { logger } from "../../utils/logger.js";
13
+ import { MAX_AUDIO_BYTES, readBoundedBuffer } from "../../utils/sizeGuard.js";
14
+ const DEFAULT_BASE_URL = "https://api.elevenlabs.io/v1";
15
+ const REQUEST_TIMEOUT_MS = 60_000; // longer because synchronous generation
16
+ /**
17
+ * ElevenLabs Music / Sound Generation Handler.
18
+ *
19
+ * Auth: `xi-api-key: ${ELEVENLABS_API_KEY}` (shares the same env var as
20
+ * ElevenLabs TTS — same account; different endpoint).
21
+ *
22
+ * Best for: short sound effects (ambient drones, hits, foley) and short
23
+ * music loops up to 22 seconds.
24
+ */
25
+ export class ElevenLabsMusic {
26
+ maxDurationSeconds = 22;
27
+ supportedFormats = ["mp3"];
28
+ supportedGenres = [
29
+ "ambient",
30
+ "cinematic",
31
+ "lo-fi",
32
+ "electronic",
33
+ "orchestral",
34
+ "soundscape",
35
+ ];
36
+ apiKey;
37
+ baseUrl;
38
+ constructor(apiKey) {
39
+ const resolved = (apiKey ?? process.env.ELEVENLABS_API_KEY ?? "").trim();
40
+ this.apiKey = resolved.length > 0 ? resolved : null;
41
+ this.baseUrl = (process.env.ELEVENLABS_BASE_URL ?? DEFAULT_BASE_URL).replace(/\/$/, "");
42
+ }
43
+ isConfigured() {
44
+ return this.apiKey !== null;
45
+ }
46
+ async generate(options) {
47
+ if (!this.apiKey) {
48
+ throw new MusicError({
49
+ code: MUSIC_ERROR_CODES.PROVIDER_NOT_CONFIGURED,
50
+ message: "ELEVENLABS_API_KEY not configured (shared with ElevenLabs TTS — same account, different endpoint)",
51
+ category: ErrorCategory.CONFIGURATION,
52
+ severity: ErrorSeverity.HIGH,
53
+ retriable: false,
54
+ });
55
+ }
56
+ const promptText = options.prompt?.trim();
57
+ if (!promptText) {
58
+ throw new MusicError({
59
+ code: MUSIC_ERROR_CODES.INVALID_INPUT,
60
+ message: "ElevenLabs Music requires a non-empty prompt",
61
+ category: ErrorCategory.VALIDATION,
62
+ severity: ErrorSeverity.LOW,
63
+ retriable: false,
64
+ });
65
+ }
66
+ const requestedDuration = options.duration ?? 8;
67
+ if (requestedDuration <= 0 || requestedDuration > this.maxDurationSeconds) {
68
+ throw new MusicError({
69
+ code: MUSIC_ERROR_CODES.INVALID_INPUT,
70
+ message: `ElevenLabs Music duration must be between 1 and ${this.maxDurationSeconds} seconds; got ${requestedDuration}`,
71
+ category: ErrorCategory.VALIDATION,
72
+ severity: ErrorSeverity.LOW,
73
+ retriable: false,
74
+ context: {
75
+ requested: requestedDuration,
76
+ maximum: this.maxDurationSeconds,
77
+ },
78
+ });
79
+ }
80
+ const startTime = Date.now();
81
+ const duration = requestedDuration;
82
+ const body = {
83
+ text: this.buildPrompt({ ...options, prompt: promptText }),
84
+ duration_seconds: duration,
85
+ prompt_influence: 0.3,
86
+ };
87
+ const controller = new AbortController();
88
+ const timeoutId = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);
89
+ let response;
90
+ try {
91
+ response = await fetch(`${this.baseUrl}/sound-generation`, {
92
+ method: "POST",
93
+ headers: {
94
+ "xi-api-key": this.apiKey,
95
+ "Content-Type": "application/json",
96
+ Accept: "audio/mpeg",
97
+ },
98
+ body: JSON.stringify(body),
99
+ signal: controller.signal,
100
+ });
101
+ }
102
+ catch (err) {
103
+ if (err instanceof Error && err.name === "AbortError") {
104
+ throw new MusicError({
105
+ code: MUSIC_ERROR_CODES.GENERATION_FAILED,
106
+ message: `ElevenLabs Music request timed out after ${REQUEST_TIMEOUT_MS / 1000}s`,
107
+ category: ErrorCategory.NETWORK,
108
+ severity: ErrorSeverity.HIGH,
109
+ retriable: true,
110
+ originalError: err,
111
+ });
112
+ }
113
+ throw new MusicError({
114
+ code: MUSIC_ERROR_CODES.GENERATION_FAILED,
115
+ message: `ElevenLabs Music network error: ${err instanceof Error ? err.message : String(err)}`,
116
+ category: ErrorCategory.NETWORK,
117
+ severity: ErrorSeverity.HIGH,
118
+ retriable: true,
119
+ originalError: err instanceof Error ? err : undefined,
120
+ });
121
+ }
122
+ finally {
123
+ clearTimeout(timeoutId);
124
+ }
125
+ if (!response.ok) {
126
+ const text = await response.text();
127
+ const retriable = response.status === 408 ||
128
+ response.status === 429 ||
129
+ response.status >= 500;
130
+ throw new MusicError({
131
+ code: MUSIC_ERROR_CODES.GENERATION_FAILED,
132
+ message: `ElevenLabs Music synthesis failed: ${response.status} — ${text}`,
133
+ category: retriable ? ErrorCategory.NETWORK : ErrorCategory.EXECUTION,
134
+ severity: ErrorSeverity.HIGH,
135
+ retriable,
136
+ context: { status: response.status },
137
+ });
138
+ }
139
+ const buffer = await readBoundedBuffer(response, MAX_AUDIO_BYTES, "ElevenLabs music");
140
+ const latency = Date.now() - startTime;
141
+ logger.info(`[ElevenLabsMusic] Generated ${buffer.length} bytes in ${latency}ms`);
142
+ return {
143
+ buffer,
144
+ format: "mp3",
145
+ size: buffer.length,
146
+ duration,
147
+ provider: "elevenlabs-music",
148
+ metadata: {
149
+ latency,
150
+ provider: "elevenlabs-music",
151
+ model: "elevenlabs-sound-v1",
152
+ },
153
+ };
154
+ }
155
+ buildPrompt(options) {
156
+ const parts = [options.prompt];
157
+ if (options.genre) {
158
+ parts.push(`Genre: ${options.genre}`);
159
+ }
160
+ if (options.mood) {
161
+ parts.push(`Mood: ${options.mood}`);
162
+ }
163
+ if (options.tempo !== undefined) {
164
+ parts.push(`${options.tempo} BPM`);
165
+ }
166
+ return parts.join(". ");
167
+ }
168
+ }
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Google Lyria 3 Pro Music Handler
3
+ *
4
+ * Synchronous generation against the Generative Language API. Returns
5
+ * audio inline as base64 in the response.
6
+ *
7
+ * @module music/providers/LyriaMusic
8
+ * @see https://ai.google.dev/gemini-api/docs/music-generation
9
+ */
10
+ import type { MusicAudioFormat, MusicHandler, MusicOptions, MusicResult } from "../../types/index.js";
11
+ /**
12
+ * Google Lyria 3 Pro Music Handler.
13
+ *
14
+ * Auth: `Authorization: Bearer ${GOOGLE_API_KEY}` or query-string
15
+ * `?key=${GOOGLE_API_KEY}` (the latter is more compatible with the
16
+ * Generative Language endpoints today).
17
+ */
18
+ export declare class LyriaMusic implements MusicHandler {
19
+ readonly maxDurationSeconds = 30;
20
+ readonly supportedFormats: readonly MusicAudioFormat[];
21
+ readonly supportedGenres: readonly string[];
22
+ private readonly apiKey;
23
+ private readonly baseUrl;
24
+ private readonly model;
25
+ constructor(apiKey?: string);
26
+ isConfigured(): boolean;
27
+ generate(options: MusicOptions): Promise<MusicResult>;
28
+ private buildPrompt;
29
+ }