@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,305 @@
1
+ /**
2
+ * Kling Video Handler (PiAPI)
3
+ *
4
+ * Image-to-video generation via PiAPI's Kling endpoint. Async job model:
5
+ * POST /image-to-video → poll /task/{id} until completed.
6
+ *
7
+ * NOTE: PiAPI Kling requires a publicly accessible image URL, not inline
8
+ * base64 data. Callers must supply `options.imageUrl` (a URL string) when
9
+ * using KlingVideoHandler. The `image` Buffer parameter is still accepted
10
+ * for interface compatibility (e.g., metadata / downstream use) but is not
11
+ * sent to the API. A clear error is thrown if no URL is provided.
12
+ *
13
+ * @module adapters/video/klingVideoHandler
14
+ * @see https://piapi.ai/docs/kling-api
15
+ */
16
+ import { ErrorCategory, ErrorSeverity } from "../../constants/enums.js";
17
+ import { VIDEO_ERROR_CODES } from "../../constants/videoErrors.js";
18
+ import { logger } from "../../utils/logger.js";
19
+ import { sanitizeForLog } from "../../utils/logSanitize.js";
20
+ import { safeDownload } from "../../utils/safeFetch.js";
21
+ import { VideoError } from "../../utils/videoProcessor.js";
22
+ import { MAX_VIDEO_BYTES } from "../../utils/sizeGuard.js";
23
+ const DEFAULT_BASE_URL = "https://api.piapi.ai/api/kling/v1";
24
+ const REQUEST_TIMEOUT_MS = 30_000;
25
+ const POLL_INTERVAL_MS = 5_000;
26
+ const TOTAL_TIMEOUT_MS = 5 * 60_000;
27
+ /**
28
+ * Kling Video Handler.
29
+ *
30
+ * Auth: `Authorization: Bearer ${KLING_API_KEY}` (PiAPI / Kling key).
31
+ * Models: kling-1.6-i2v (default), kling-1.5-i2v, kling-1.0.
32
+ */
33
+ export class KlingVideoHandler {
34
+ maxDurationSeconds = 10;
35
+ supportedAspectRatios = ["16:9", "9:16", "1:1"];
36
+ supportedResolutions = [
37
+ "720p",
38
+ "1080p",
39
+ ];
40
+ apiKey;
41
+ baseUrl;
42
+ constructor(apiKey) {
43
+ const resolved = (apiKey ?? process.env.KLING_API_KEY ?? "").trim();
44
+ this.apiKey = resolved.length > 0 ? resolved : null;
45
+ this.baseUrl = (process.env.KLING_BASE_URL ?? DEFAULT_BASE_URL).replace(/\/$/, "");
46
+ }
47
+ isConfigured() {
48
+ return this.apiKey !== null;
49
+ }
50
+ async generate(image, prompt, options) {
51
+ if (!this.apiKey) {
52
+ throw new VideoError({
53
+ code: VIDEO_ERROR_CODES.PROVIDER_NOT_CONFIGURED,
54
+ message: "KLING_API_KEY not configured",
55
+ category: ErrorCategory.CONFIGURATION,
56
+ severity: ErrorSeverity.HIGH,
57
+ retriable: false,
58
+ });
59
+ }
60
+ if (!options.imageUrl) {
61
+ throw new VideoError({
62
+ code: VIDEO_ERROR_CODES.INVALID_INPUT,
63
+ message: "KlingVideoHandler requires a publicly accessible image URL. " +
64
+ "Pass options.imageUrl with a URL string pointing to the input image. " +
65
+ "The PiAPI Kling API does not accept inline base64 image data.",
66
+ category: ErrorCategory.CONFIGURATION,
67
+ severity: ErrorSeverity.HIGH,
68
+ retriable: false,
69
+ });
70
+ }
71
+ const startTime = Date.now();
72
+ const abortSignal = options.abortSignal;
73
+ // 1. Submit job.
74
+ const taskId = await this.submitJob(image, prompt, options);
75
+ // 2. Poll until complete.
76
+ const videoUrl = await this.pollUntilComplete(taskId, abortSignal);
77
+ // 3. Download video.
78
+ const buffer = await this.downloadVideo(videoUrl);
79
+ const processingTime = Date.now() - startTime;
80
+ logger.info(`[KlingVideoHandler] Generated ${buffer.length} bytes in ${processingTime}ms — task ${taskId}`);
81
+ return {
82
+ data: buffer,
83
+ mediaType: "video/mp4",
84
+ metadata: {
85
+ duration: options.length ?? 4,
86
+ dimensions: this.calculateDimensions(options),
87
+ model: options.model ?? "kling",
88
+ provider: "kling",
89
+ aspectRatio: options.aspectRatio ?? "16:9",
90
+ audioEnabled: false,
91
+ processingTime,
92
+ },
93
+ };
94
+ }
95
+ async submitJob(_image, prompt, options) {
96
+ // PiAPI Kling requires a publicly accessible URL for the input image.
97
+ // options.imageUrl is validated (non-null) before submitJob is called.
98
+ const body = {
99
+ model: options.model ?? "kling",
100
+ task_type: "video_generation",
101
+ input: {
102
+ image_url: options.imageUrl,
103
+ prompt,
104
+ duration: options.length ?? 4,
105
+ aspect_ratio: options.aspectRatio ?? "16:9",
106
+ cfg_scale: 0.5,
107
+ },
108
+ };
109
+ const response = await this.fetchWithTimeout(`${this.baseUrl}/image-to-video`, {
110
+ method: "POST",
111
+ headers: {
112
+ Authorization: `Bearer ${this.apiKey}`,
113
+ "Content-Type": "application/json",
114
+ },
115
+ body: JSON.stringify(body),
116
+ });
117
+ if (!response.ok) {
118
+ const raw = await response.text();
119
+ const retriable = response.status === 408 ||
120
+ response.status === 429 ||
121
+ response.status >= 500;
122
+ throw new VideoError({
123
+ code: VIDEO_ERROR_CODES.GENERATION_FAILED,
124
+ message: `Kling submit failed: ${response.status} — ${sanitizeForLog(raw, 500)}`,
125
+ category: retriable ? ErrorCategory.NETWORK : ErrorCategory.EXECUTION,
126
+ severity: ErrorSeverity.HIGH,
127
+ retriable,
128
+ context: { status: response.status },
129
+ });
130
+ }
131
+ const json = (await response.json());
132
+ const taskId = json.task_id ?? json.data?.task_id;
133
+ if (!taskId) {
134
+ throw new VideoError({
135
+ code: VIDEO_ERROR_CODES.GENERATION_FAILED,
136
+ message: "Kling submit response missing task_id",
137
+ category: ErrorCategory.EXECUTION,
138
+ severity: ErrorSeverity.HIGH,
139
+ retriable: false,
140
+ context: { response: json },
141
+ });
142
+ }
143
+ return taskId;
144
+ }
145
+ async pollUntilComplete(taskId, abortSignal) {
146
+ const startTime = Date.now();
147
+ while (Date.now() - startTime < TOTAL_TIMEOUT_MS) {
148
+ if (abortSignal?.aborted) {
149
+ throw new VideoError({
150
+ code: VIDEO_ERROR_CODES.GENERATION_FAILED,
151
+ message: `Kling poll for task ${taskId} aborted by caller`,
152
+ category: ErrorCategory.NETWORK,
153
+ severity: ErrorSeverity.MEDIUM,
154
+ retriable: false,
155
+ context: { taskId },
156
+ });
157
+ }
158
+ const response = await this.fetchWithTimeout(`${this.baseUrl}/task/${taskId}`, {
159
+ method: "GET",
160
+ headers: { Authorization: `Bearer ${this.apiKey}` },
161
+ }, abortSignal);
162
+ if (!response.ok) {
163
+ const raw = await response.text();
164
+ throw new VideoError({
165
+ code: VIDEO_ERROR_CODES.GENERATION_FAILED,
166
+ message: `Kling poll failed: ${response.status} — ${sanitizeForLog(raw, 500)}`,
167
+ category: ErrorCategory.NETWORK,
168
+ severity: ErrorSeverity.MEDIUM,
169
+ retriable: response.status >= 500,
170
+ context: { status: response.status, taskId },
171
+ });
172
+ }
173
+ const data = (await response.json());
174
+ if (data.status === "completed" || data.status === "succeeded") {
175
+ const videoUrl = data.video_url ?? data.output?.video_url;
176
+ if (!videoUrl) {
177
+ throw new VideoError({
178
+ code: VIDEO_ERROR_CODES.GENERATION_FAILED,
179
+ message: `Kling task ${taskId} completed but no video URL returned`,
180
+ category: ErrorCategory.EXECUTION,
181
+ severity: ErrorSeverity.HIGH,
182
+ retriable: false,
183
+ context: { taskId, data },
184
+ });
185
+ }
186
+ return videoUrl;
187
+ }
188
+ if (data.status === "failed") {
189
+ throw new VideoError({
190
+ code: VIDEO_ERROR_CODES.GENERATION_FAILED,
191
+ message: `Kling task ${taskId} failed: ${data.error ?? "unknown"}`,
192
+ category: ErrorCategory.EXECUTION,
193
+ severity: ErrorSeverity.HIGH,
194
+ retriable: false,
195
+ context: { taskId, data },
196
+ });
197
+ }
198
+ // Abortable sleep.
199
+ await new Promise((resolve, reject) => {
200
+ const onAbort = () => {
201
+ clearTimeout(timer);
202
+ reject(new VideoError({
203
+ code: VIDEO_ERROR_CODES.GENERATION_FAILED,
204
+ message: `Kling poll for task ${taskId} aborted by caller`,
205
+ category: ErrorCategory.NETWORK,
206
+ severity: ErrorSeverity.MEDIUM,
207
+ retriable: false,
208
+ context: { taskId },
209
+ }));
210
+ };
211
+ const timer = setTimeout(() => {
212
+ abortSignal?.removeEventListener("abort", onAbort);
213
+ resolve();
214
+ }, POLL_INTERVAL_MS);
215
+ abortSignal?.addEventListener("abort", onAbort, { once: true });
216
+ });
217
+ }
218
+ throw new VideoError({
219
+ code: VIDEO_ERROR_CODES.POLL_TIMEOUT,
220
+ message: `Kling task ${taskId} did not complete within ${TOTAL_TIMEOUT_MS / 1000}s`,
221
+ category: ErrorCategory.TIMEOUT,
222
+ severity: ErrorSeverity.MEDIUM,
223
+ retriable: true,
224
+ context: { taskId },
225
+ });
226
+ }
227
+ async downloadVideo(url) {
228
+ try {
229
+ return await safeDownload(url, {
230
+ maxBytes: MAX_VIDEO_BYTES,
231
+ label: "Kling video",
232
+ timeoutMs: REQUEST_TIMEOUT_MS,
233
+ });
234
+ }
235
+ catch (err) {
236
+ throw new VideoError({
237
+ code: VIDEO_ERROR_CODES.GENERATION_FAILED,
238
+ message: `Kling video download rejected: ${err instanceof Error ? err.message : String(err)}`,
239
+ category: ErrorCategory.NETWORK,
240
+ severity: ErrorSeverity.HIGH,
241
+ retriable: false,
242
+ context: { url },
243
+ originalError: err instanceof Error ? err : undefined,
244
+ });
245
+ }
246
+ }
247
+ async fetchWithTimeout(url, init, callerAbortSignal) {
248
+ const controller = new AbortController();
249
+ let timedOut = false;
250
+ const timeoutId = setTimeout(() => {
251
+ timedOut = true;
252
+ controller.abort();
253
+ }, REQUEST_TIMEOUT_MS);
254
+ const onCallerAbort = () => controller.abort();
255
+ callerAbortSignal?.addEventListener("abort", onCallerAbort, { once: true });
256
+ try {
257
+ return await fetch(url, { ...init, signal: controller.signal });
258
+ }
259
+ catch (err) {
260
+ if (err instanceof Error && err.name === "AbortError") {
261
+ if (timedOut) {
262
+ throw new VideoError({
263
+ code: VIDEO_ERROR_CODES.GENERATION_FAILED,
264
+ message: `Kling request timed out after ${REQUEST_TIMEOUT_MS / 1000}s`,
265
+ category: ErrorCategory.NETWORK,
266
+ severity: ErrorSeverity.HIGH,
267
+ retriable: true,
268
+ originalError: err,
269
+ });
270
+ }
271
+ throw new VideoError({
272
+ code: VIDEO_ERROR_CODES.GENERATION_FAILED,
273
+ message: "Kling request aborted by caller",
274
+ category: ErrorCategory.NETWORK,
275
+ severity: ErrorSeverity.MEDIUM,
276
+ retriable: false,
277
+ originalError: err,
278
+ });
279
+ }
280
+ throw err;
281
+ }
282
+ finally {
283
+ callerAbortSignal?.removeEventListener("abort", onCallerAbort);
284
+ clearTimeout(timeoutId);
285
+ }
286
+ }
287
+ calculateDimensions(options) {
288
+ const aspectRatio = options.aspectRatio ?? "16:9";
289
+ const resolution = options.resolution ?? "720p";
290
+ if (resolution === "1080p") {
291
+ if (aspectRatio === "1:1") {
292
+ return { width: 1080, height: 1080 };
293
+ }
294
+ return aspectRatio === "9:16"
295
+ ? { width: 1080, height: 1920 }
296
+ : { width: 1920, height: 1080 };
297
+ }
298
+ if (aspectRatio === "1:1") {
299
+ return { width: 720, height: 720 };
300
+ }
301
+ return aspectRatio === "9:16"
302
+ ? { width: 720, height: 1280 }
303
+ : { width: 1280, height: 720 };
304
+ }
305
+ }
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Replicate Video Handler
3
+ *
4
+ * Routes video generation through the universal Replicate prediction
5
+ * lifecycle. Default model is Wan-Alpha (RGBA video); callers can specify
6
+ * any image-to-video model on Replicate via `options.model`.
7
+ *
8
+ * @module adapters/video/replicateVideoHandler
9
+ * @see https://replicate.com/atonamy/wan-alpha
10
+ */
11
+ import type { NeurolinkCredentials, VideoGenerationResult, VideoHandler, VideoOutputOptions } from "../../types/index.js";
12
+ /**
13
+ * Replicate Video Handler.
14
+ *
15
+ * Capabilities depend on the specific Replicate model — this handler
16
+ * advertises conservative bounds (any provider-supported aspect ratio /
17
+ * resolution; up to 10s typical for Wan-Alpha).
18
+ */
19
+ export declare class ReplicateVideoHandler implements VideoHandler {
20
+ readonly maxDurationSeconds = 10;
21
+ readonly supportedAspectRatios: readonly ("9:16" | "16:9" | "1:1")[];
22
+ readonly supportedResolutions: readonly ("720p" | "1080p")[];
23
+ private readonly instanceCredentials;
24
+ constructor(credentials?: NeurolinkCredentials["replicate"]);
25
+ isConfigured(): boolean;
26
+ generate(image: Buffer, prompt: string, options: VideoOutputOptions): Promise<VideoGenerationResult>;
27
+ private detectImageType;
28
+ private calculateDimensions;
29
+ }
@@ -0,0 +1,157 @@
1
+ /**
2
+ * Replicate Video Handler
3
+ *
4
+ * Routes video generation through the universal Replicate prediction
5
+ * lifecycle. Default model is Wan-Alpha (RGBA video); callers can specify
6
+ * any image-to-video model on Replicate via `options.model`.
7
+ *
8
+ * @module adapters/video/replicateVideoHandler
9
+ * @see https://replicate.com/atonamy/wan-alpha
10
+ */
11
+ import { ErrorCategory, ErrorSeverity } from "../../constants/enums.js";
12
+ import { VIDEO_ERROR_CODES } from "../../constants/videoErrors.js";
13
+ import { logger } from "../../utils/logger.js";
14
+ import { VideoError } from "../../utils/videoProcessor.js";
15
+ import { getReplicateAuth } from "../replicate/auth.js";
16
+ import { downloadPredictionOutput, predict, } from "../replicate/predictionLifecycle.js";
17
+ const DEFAULT_MODEL = "atonamy/wan-alpha";
18
+ /**
19
+ * Replicate Video Handler.
20
+ *
21
+ * Capabilities depend on the specific Replicate model — this handler
22
+ * advertises conservative bounds (any provider-supported aspect ratio /
23
+ * resolution; up to 10s typical for Wan-Alpha).
24
+ */
25
+ export class ReplicateVideoHandler {
26
+ maxDurationSeconds = 10;
27
+ supportedAspectRatios = ["9:16", "16:9", "1:1"];
28
+ supportedResolutions = [
29
+ "720p",
30
+ "1080p",
31
+ ];
32
+ instanceCredentials;
33
+ constructor(credentials) {
34
+ this.instanceCredentials = credentials;
35
+ }
36
+ isConfigured() {
37
+ return getReplicateAuth(this.instanceCredentials) !== null;
38
+ }
39
+ async generate(image, prompt, options) {
40
+ const perCallCreds = options.credentials?.replicate;
41
+ const auth = getReplicateAuth(perCallCreds ?? this.instanceCredentials);
42
+ if (!auth) {
43
+ throw new VideoError({
44
+ code: VIDEO_ERROR_CODES.PROVIDER_NOT_CONFIGURED,
45
+ message: "REPLICATE_API_TOKEN not configured",
46
+ category: ErrorCategory.CONFIGURATION,
47
+ severity: ErrorSeverity.HIGH,
48
+ retriable: false,
49
+ });
50
+ }
51
+ const startTime = Date.now();
52
+ const model = options.model ?? DEFAULT_MODEL;
53
+ const dataUri = `data:image/${this.detectImageType(image)};base64,${image.toString("base64")}`;
54
+ // Wan-Alpha + most image-to-video models accept this shape; specific
55
+ // models may require provider-specific extras passed through
56
+ // VideoOutputOptions.[unknown key].
57
+ //
58
+ // `resolution` is forwarded as the `resolution` input parameter.
59
+ // Wan-Alpha and several other Replicate image-to-video models accept it
60
+ // (e.g. "720p", "1080p"). Models that do not recognise it will silently
61
+ // ignore the field — the Replicate API does not reject unknown input keys.
62
+ // `calculateDimensions` still populates the metadata `dimensions` field
63
+ // so downstream consumers always receive correct width/height regardless
64
+ // of whether the model honoured the resolution hint.
65
+ const inputPayload = {
66
+ image: dataUri,
67
+ prompt,
68
+ num_frames: (options.length ?? 4) * 24, // Assume 24 fps
69
+ fps: 24,
70
+ aspect_ratio: options.aspectRatio,
71
+ ...(options.resolution !== undefined
72
+ ? { resolution: options.resolution }
73
+ : {}),
74
+ };
75
+ let prediction;
76
+ try {
77
+ prediction = await predict(auth, { model, input: inputPayload }, { abortSignal: options.abortSignal });
78
+ }
79
+ catch (err) {
80
+ throw new VideoError({
81
+ code: VIDEO_ERROR_CODES.GENERATION_FAILED,
82
+ message: `Replicate video generation failed: ${err instanceof Error ? err.message : String(err)}`,
83
+ category: ErrorCategory.EXECUTION,
84
+ severity: ErrorSeverity.HIGH,
85
+ retriable: true,
86
+ context: { model, options },
87
+ originalError: err instanceof Error ? err : undefined,
88
+ });
89
+ }
90
+ let videoBuffer;
91
+ try {
92
+ videoBuffer = await downloadPredictionOutput(prediction);
93
+ }
94
+ catch (err) {
95
+ throw new VideoError({
96
+ code: VIDEO_ERROR_CODES.GENERATION_FAILED,
97
+ message: `Replicate video download failed: ${err instanceof Error ? err.message : String(err)}`,
98
+ category: ErrorCategory.NETWORK,
99
+ severity: ErrorSeverity.MEDIUM,
100
+ retriable: true,
101
+ context: { predictionId: prediction.id },
102
+ originalError: err instanceof Error ? err : undefined,
103
+ });
104
+ }
105
+ const processingTime = Date.now() - startTime;
106
+ logger.info(`[ReplicateVideoHandler] Generated ${videoBuffer.length} bytes in ${processingTime}ms — model ${model}`);
107
+ return {
108
+ data: videoBuffer,
109
+ mediaType: "video/mp4",
110
+ metadata: {
111
+ duration: options.length ?? 4,
112
+ dimensions: this.calculateDimensions(options),
113
+ model,
114
+ provider: "replicate",
115
+ aspectRatio: options.aspectRatio ?? "16:9",
116
+ audioEnabled: false, // Most Replicate video models are silent
117
+ processingTime,
118
+ },
119
+ };
120
+ }
121
+ detectImageType(buffer) {
122
+ if (buffer.length < 4) {
123
+ return "jpeg";
124
+ }
125
+ if (buffer[0] === 0x89 && buffer[1] === 0x50) {
126
+ return "png";
127
+ }
128
+ if (buffer[0] === 0xff && buffer[1] === 0xd8) {
129
+ return "jpeg";
130
+ }
131
+ if (buffer[0] === 0x52 &&
132
+ buffer[1] === 0x49 &&
133
+ buffer[2] === 0x46 &&
134
+ buffer[3] === 0x46) {
135
+ return "webp";
136
+ }
137
+ return "jpeg";
138
+ }
139
+ calculateDimensions(options) {
140
+ const aspectRatio = options.aspectRatio ?? "16:9";
141
+ const resolution = options.resolution ?? "720p";
142
+ if (resolution === "1080p") {
143
+ if (aspectRatio === "1:1") {
144
+ return { width: 1080, height: 1080 };
145
+ }
146
+ return aspectRatio === "9:16"
147
+ ? { width: 1080, height: 1920 }
148
+ : { width: 1920, height: 1080 };
149
+ }
150
+ if (aspectRatio === "1:1") {
151
+ return { width: 720, height: 720 };
152
+ }
153
+ return aspectRatio === "9:16"
154
+ ? { width: 720, height: 1280 }
155
+ : { width: 1280, height: 720 };
156
+ }
157
+ }
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Runway Video Handler (Gen-3 Alpha / Gen-4 Turbo)
3
+ *
4
+ * Async generation: POST /v1/image_to_video → poll /v1/tasks/{id}.
5
+ *
6
+ * @module adapters/video/runwayVideoHandler
7
+ * @see https://docs.dev.runwayml.com/api/
8
+ */
9
+ import type { VideoGenerationResult, VideoHandler, VideoOutputOptions } from "../../types/index.js";
10
+ /**
11
+ * Runway Video Handler.
12
+ *
13
+ * Auth: `Authorization: Bearer ${RUNWAY_API_KEY}` + `X-Runway-Version`
14
+ * header. Models: gen3a_turbo (Gen-3 Alpha Turbo, default), gen4_turbo.
15
+ */
16
+ export declare class RunwayVideoHandler implements VideoHandler {
17
+ readonly maxDurationSeconds = 10;
18
+ readonly supportedAspectRatios: readonly ("16:9" | "9:16")[];
19
+ readonly supportedResolutions: readonly ("720p" | "1080p")[];
20
+ private readonly apiKey;
21
+ private readonly baseUrl;
22
+ private readonly apiVersion;
23
+ constructor(apiKey?: string);
24
+ isConfigured(): boolean;
25
+ generate(image: Buffer, prompt: string, options: VideoOutputOptions): Promise<VideoGenerationResult>;
26
+ private submitTask;
27
+ private pollUntilComplete;
28
+ private downloadVideo;
29
+ private fetchWithTimeout;
30
+ private detectImageType;
31
+ private calculateDimensions;
32
+ }