@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,6 @@
1
+ /**
2
+ * Types for the safe-fetch utility (SSRF-hardened binary downloads).
3
+ *
4
+ * Runtime helper lives in `src/lib/utils/safeFetch.ts`.
5
+ */
6
+ export {};
@@ -167,7 +167,8 @@ export type StreamChunk = {
167
167
  };
168
168
  export type StreamOptions = {
169
169
  input: {
170
- text: string;
170
+ /** Prompt text. Optional for media-only modes (avatar, music) that are driven by uploaded files rather than a prompt. */
171
+ text?: string;
171
172
  audio?: AudioInputSpec;
172
173
  /**
173
174
  * Images to include in the request.
@@ -515,3 +515,16 @@ export declare function isToolResult(value: unknown): value is ToolResult;
515
515
  * Type guard for tool definition
516
516
  */
517
517
  export declare function isToolDefinition(value: unknown): value is ToolDefinition;
518
+ /**
519
+ * Result shape returned by the built-in `bashTool` execute function in
520
+ * `src/lib/agent/directTools.ts`. Centralised here per CLAUDE.md rule 2
521
+ * so callers (incl. the mcp-bash test suite) don't need to declare a
522
+ * local re-shaping of the runtime contract.
523
+ */
524
+ export type BashToolResult = {
525
+ success: boolean;
526
+ code: number;
527
+ stdout: string;
528
+ stderr: string;
529
+ error?: string;
530
+ };
@@ -0,0 +1,89 @@
1
+ /**
2
+ * Video Generation Type Definitions
3
+ *
4
+ * Shared types for video generation across providers (Vertex Veo, Kling,
5
+ * Runway, Replicate-hosted models, etc.).
6
+ *
7
+ * The shared base shapes (`VideoOutputOptions`, `VideoGenerationResult`)
8
+ * are defined in `multimodal.ts` for backwards compatibility — they are
9
+ * re-exported here so callers can import every video-related type from a
10
+ * single module.
11
+ *
12
+ * @module types/video
13
+ */
14
+ import type { VideoGenerationResult, VideoOutputOptions } from "./multimodal.js";
15
+ export type { VideoGenerationResult, VideoOutputOptions, } from "./multimodal.js";
16
+ /**
17
+ * Director-mode transition options.
18
+ *
19
+ * Used by handlers that support first-and-last-frame interpolation
20
+ * (e.g., Veo 3.1 Fast). Providers without transition support omit the
21
+ * `generateTransition` method on `VideoHandler`.
22
+ */
23
+ export type VideoTransitionOptions = {
24
+ aspectRatio?: "9:16" | "16:9" | "1:1" | string;
25
+ resolution?: "720p" | "1080p";
26
+ audio?: boolean;
27
+ /** Duration of the transition clip (Veo accepts 4, 6, or 8). Default 4. */
28
+ durationSeconds?: 4 | 6 | 8;
29
+ };
30
+ /**
31
+ * Handler contract for video generation providers.
32
+ *
33
+ * Every concrete handler (`VertexVideoHandler`, `KlingVideoHandler`,
34
+ * `RunwayVideoHandler`, `ReplicateVideoHandler`, …) implements this
35
+ * interface and registers itself with `VideoProcessor.registerHandler`.
36
+ *
37
+ * Implementations MUST enforce their own timeouts. The recommended
38
+ * total-deadline for image-to-video predictLongRunning APIs is
39
+ * 3-5 minutes; the per-request fetch timeout is 30 seconds.
40
+ */
41
+ export type VideoHandler = {
42
+ /**
43
+ * Generate a single video clip from an input image and prompt.
44
+ *
45
+ * @param image - Input image buffer (JPEG, PNG, or WebP)
46
+ * @param prompt - Text prompt describing desired video motion / content
47
+ * @param options - Resolution, length, aspect ratio, audio settings
48
+ * @param region - Provider-specific region override (e.g. Vertex location)
49
+ * @returns Buffer + metadata
50
+ */
51
+ generate(image: Buffer, prompt: string, options: VideoOutputOptions, region?: string): Promise<VideoGenerationResult>;
52
+ /**
53
+ * Optional — generate a transition clip between two frames (Director Mode).
54
+ *
55
+ * Providers without first-and-last-frame interpolation omit this method;
56
+ * `VideoProcessor.generateTransition` will surface a typed error.
57
+ *
58
+ * `durationSeconds` is on `VideoTransitionOptions` (default 4).
59
+ */
60
+ generateTransition?(firstFrame: Buffer, lastFrame: Buffer, prompt: string, options?: VideoTransitionOptions, region?: string): Promise<Buffer>;
61
+ /** Validate the provider is configured (auth, base URL, etc.). */
62
+ isConfigured(): boolean;
63
+ /** Maximum video duration in seconds supported by this provider. */
64
+ readonly maxDurationSeconds?: number;
65
+ /** Supported aspect ratios. */
66
+ readonly supportedAspectRatios?: readonly ("9:16" | "16:9" | "1:1" | "4:3" | "3:4")[];
67
+ /** Supported output resolutions. */
68
+ readonly supportedResolutions?: readonly ("480p" | "720p" | "1080p" | "4k")[];
69
+ };
70
+ /**
71
+ * Kling (PiAPI) task status response.
72
+ */
73
+ export type KlingTaskResponse = {
74
+ status?: string;
75
+ video_url?: string;
76
+ output?: {
77
+ video_url?: string;
78
+ };
79
+ error?: string;
80
+ };
81
+ /**
82
+ * Runway task status response.
83
+ */
84
+ export type RunwayTaskResponse = {
85
+ status?: string;
86
+ output?: string[] | string;
87
+ error?: string;
88
+ failure?: string;
89
+ };
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Video Generation Type Definitions
3
+ *
4
+ * Shared types for video generation across providers (Vertex Veo, Kling,
5
+ * Runway, Replicate-hosted models, etc.).
6
+ *
7
+ * The shared base shapes (`VideoOutputOptions`, `VideoGenerationResult`)
8
+ * are defined in `multimodal.ts` for backwards compatibility — they are
9
+ * re-exported here so callers can import every video-related type from a
10
+ * single module.
11
+ *
12
+ * @module types/video
13
+ */
14
+ export {};
@@ -0,0 +1,68 @@
1
+ /**
2
+ * Avatar / Lip-sync Generation Processing Utility
3
+ *
4
+ * Central registry + dispatch for avatar handlers across providers
5
+ * (D-ID, HeyGen, Replicate-hosted MuseTalk / SadTalker / Wav2Lip).
6
+ *
7
+ * Mirrors the static-handler-registry pattern established by
8
+ * `TTSProcessor` / `STTProcessor` / `VideoProcessor` / `MusicProcessor`.
9
+ *
10
+ * @module utils/avatarProcessor
11
+ */
12
+ import { ErrorCategory, ErrorSeverity } from "../constants/enums.js";
13
+ import type { AvatarHandler, AvatarOptions, AvatarResult } from "../types/index.js";
14
+ import { NeuroLinkError } from "./errorHandling.js";
15
+ /**
16
+ * Avatar-specific error codes.
17
+ */
18
+ export declare const AVATAR_ERROR_CODES: {
19
+ readonly PROVIDER_NOT_SUPPORTED: "AVATAR_PROVIDER_NOT_SUPPORTED";
20
+ readonly PROVIDER_NOT_CONFIGURED: "AVATAR_PROVIDER_NOT_CONFIGURED";
21
+ readonly GENERATION_FAILED: "AVATAR_GENERATION_FAILED";
22
+ readonly POLL_TIMEOUT: "AVATAR_POLL_TIMEOUT";
23
+ readonly INVALID_INPUT: "AVATAR_INVALID_INPUT";
24
+ readonly AUDIO_REQUIRED: "AVATAR_AUDIO_REQUIRED";
25
+ readonly IMAGE_REQUIRED: "AVATAR_IMAGE_REQUIRED";
26
+ readonly AUDIO_TOO_LONG: "AVATAR_AUDIO_TOO_LONG";
27
+ };
28
+ /**
29
+ * Typed error class for avatar-generation failures.
30
+ */
31
+ export declare class AvatarError extends NeuroLinkError {
32
+ constructor(options: {
33
+ code: string;
34
+ message: string;
35
+ category?: ErrorCategory;
36
+ severity?: ErrorSeverity;
37
+ retriable?: boolean;
38
+ context?: Record<string, unknown>;
39
+ originalError?: Error;
40
+ });
41
+ }
42
+ /**
43
+ * Static processor managing the avatar handler registry.
44
+ */
45
+ export declare class AvatarProcessor {
46
+ private static readonly handlers;
47
+ /**
48
+ * Register an avatar handler for a specific provider.
49
+ */
50
+ static registerHandler(providerName: string, handler: AvatarHandler): void;
51
+ /**
52
+ * Check if a provider has a registered avatar handler.
53
+ */
54
+ static supports(providerName: string): boolean;
55
+ /**
56
+ * List the names of all registered providers.
57
+ */
58
+ static listProviders(): string[];
59
+ private static getHandler;
60
+ private static buildSpanAttributes;
61
+ /**
62
+ * Generate an avatar video via the registered handler.
63
+ *
64
+ * @throws AvatarError on registry miss, handler-not-configured, or
65
+ * generation failure.
66
+ */
67
+ static generate(provider: string, options: AvatarOptions): Promise<AvatarResult>;
68
+ }
@@ -0,0 +1,171 @@
1
+ /**
2
+ * Avatar / Lip-sync Generation Processing Utility
3
+ *
4
+ * Central registry + dispatch for avatar handlers across providers
5
+ * (D-ID, HeyGen, Replicate-hosted MuseTalk / SadTalker / Wav2Lip).
6
+ *
7
+ * Mirrors the static-handler-registry pattern established by
8
+ * `TTSProcessor` / `STTProcessor` / `VideoProcessor` / `MusicProcessor`.
9
+ *
10
+ * @module utils/avatarProcessor
11
+ */
12
+ import { ErrorCategory, ErrorSeverity } from "../constants/enums.js";
13
+ import { SpanSerializer, SpanStatus, SpanType, getMetricsAggregator, } from "../observability/index.js";
14
+ import { NeuroLinkError } from "./errorHandling.js";
15
+ import { logger } from "./logger.js";
16
+ /**
17
+ * Avatar-specific error codes.
18
+ */
19
+ export const AVATAR_ERROR_CODES = {
20
+ PROVIDER_NOT_SUPPORTED: "AVATAR_PROVIDER_NOT_SUPPORTED",
21
+ PROVIDER_NOT_CONFIGURED: "AVATAR_PROVIDER_NOT_CONFIGURED",
22
+ GENERATION_FAILED: "AVATAR_GENERATION_FAILED",
23
+ POLL_TIMEOUT: "AVATAR_POLL_TIMEOUT",
24
+ INVALID_INPUT: "AVATAR_INVALID_INPUT",
25
+ AUDIO_REQUIRED: "AVATAR_AUDIO_REQUIRED",
26
+ IMAGE_REQUIRED: "AVATAR_IMAGE_REQUIRED",
27
+ AUDIO_TOO_LONG: "AVATAR_AUDIO_TOO_LONG",
28
+ };
29
+ /**
30
+ * Typed error class for avatar-generation failures.
31
+ */
32
+ export class AvatarError extends NeuroLinkError {
33
+ constructor(options) {
34
+ super({
35
+ code: options.code,
36
+ message: options.message,
37
+ category: options.category ?? ErrorCategory.EXECUTION,
38
+ severity: options.severity ?? ErrorSeverity.HIGH,
39
+ retriable: options.retriable ?? false,
40
+ context: options.context,
41
+ originalError: options.originalError,
42
+ });
43
+ this.name = "AvatarError";
44
+ }
45
+ }
46
+ /**
47
+ * Static processor managing the avatar handler registry.
48
+ */
49
+ export class AvatarProcessor {
50
+ static handlers = new Map();
51
+ /**
52
+ * Register an avatar handler for a specific provider.
53
+ */
54
+ static registerHandler(providerName, handler) {
55
+ if (!providerName) {
56
+ throw new Error("Provider name is required");
57
+ }
58
+ if (!handler) {
59
+ throw new Error("Handler is required");
60
+ }
61
+ const key = providerName.toLowerCase();
62
+ if (this.handlers.has(key)) {
63
+ logger.warn(`[AvatarProcessor] Overwriting existing handler for provider: ${key}`);
64
+ }
65
+ this.handlers.set(key, handler);
66
+ logger.debug(`[AvatarProcessor] Registered avatar handler: ${key}`);
67
+ }
68
+ /**
69
+ * Check if a provider has a registered avatar handler.
70
+ */
71
+ static supports(providerName) {
72
+ if (!providerName) {
73
+ return false;
74
+ }
75
+ return this.handlers.has(providerName.toLowerCase());
76
+ }
77
+ /**
78
+ * List the names of all registered providers.
79
+ */
80
+ static listProviders() {
81
+ return Array.from(this.handlers.keys());
82
+ }
83
+ static getHandler(providerName) {
84
+ return this.handlers.get(providerName.toLowerCase());
85
+ }
86
+ static buildSpanAttributes(provider, options) {
87
+ return {
88
+ "avatar.operation": "generate",
89
+ "avatar.provider": provider,
90
+ "avatar.quality": options.quality,
91
+ "avatar.format": options.format,
92
+ "avatar.has_text": options.text !== undefined,
93
+ "avatar.has_audio": options.audio !== undefined,
94
+ };
95
+ }
96
+ /**
97
+ * Generate an avatar video via the registered handler.
98
+ *
99
+ * @throws AvatarError on registry miss, handler-not-configured, or
100
+ * generation failure.
101
+ */
102
+ static async generate(provider, options) {
103
+ const span = SpanSerializer.createSpan(SpanType.MEDIA_GENERATION, "avatar.generate", this.buildSpanAttributes(provider, options));
104
+ try {
105
+ if (!options.image) {
106
+ throw new AvatarError({
107
+ code: AVATAR_ERROR_CODES.IMAGE_REQUIRED,
108
+ message: "Avatar generation requires an `image` (Buffer, path, or URL)",
109
+ category: ErrorCategory.VALIDATION,
110
+ severity: ErrorSeverity.MEDIUM,
111
+ retriable: false,
112
+ context: { provider },
113
+ });
114
+ }
115
+ if (!options.audio && !options.text) {
116
+ throw new AvatarError({
117
+ code: AVATAR_ERROR_CODES.INVALID_INPUT,
118
+ message: "Avatar generation requires either `audio` (a Buffer/URL) or `text` (to be TTS'd by the provider).",
119
+ category: ErrorCategory.VALIDATION,
120
+ severity: ErrorSeverity.HIGH,
121
+ retriable: false,
122
+ context: { provider },
123
+ });
124
+ }
125
+ const handler = this.getHandler(provider);
126
+ if (!handler) {
127
+ throw new AvatarError({
128
+ code: AVATAR_ERROR_CODES.PROVIDER_NOT_SUPPORTED,
129
+ message: `Avatar provider "${provider}" is not registered. Available: ${this.listProviders().join(", ")}`,
130
+ category: ErrorCategory.CONFIGURATION,
131
+ severity: ErrorSeverity.HIGH,
132
+ retriable: false,
133
+ context: { provider, available: this.listProviders() },
134
+ });
135
+ }
136
+ if (!handler.isConfigured()) {
137
+ throw new AvatarError({
138
+ code: AVATAR_ERROR_CODES.PROVIDER_NOT_CONFIGURED,
139
+ message: `Avatar provider "${provider}" is not configured. Set the required credentials.`,
140
+ category: ErrorCategory.CONFIGURATION,
141
+ severity: ErrorSeverity.HIGH,
142
+ retriable: false,
143
+ context: { provider },
144
+ });
145
+ }
146
+ logger.debug(`[AvatarProcessor] Starting avatar generation with provider: ${provider}`);
147
+ const result = await handler.generate(options);
148
+ const ended = SpanSerializer.endSpan(span, SpanStatus.OK);
149
+ getMetricsAggregator().recordSpan(ended);
150
+ logger.info(`[AvatarProcessor] Generated ${result.size} bytes (${provider})`);
151
+ return result;
152
+ }
153
+ catch (err) {
154
+ const ended = SpanSerializer.endSpan(span, SpanStatus.ERROR, err instanceof Error ? err.message : String(err));
155
+ getMetricsAggregator().recordSpan(ended);
156
+ if (err instanceof AvatarError) {
157
+ throw err;
158
+ }
159
+ const message = err instanceof Error ? err.message : String(err);
160
+ throw new AvatarError({
161
+ code: AVATAR_ERROR_CODES.GENERATION_FAILED,
162
+ message: `Avatar generation failed for provider "${provider}": ${message}`,
163
+ category: ErrorCategory.EXECUTION,
164
+ severity: ErrorSeverity.HIGH,
165
+ retriable: true,
166
+ context: { provider },
167
+ originalError: err instanceof Error ? err : undefined,
168
+ });
169
+ }
170
+ }
171
+ }
@@ -0,0 +1,36 @@
1
+ /**
2
+ * The set of top-level branches on a `StreamOptions` / `GenerateOptions`
3
+ * / `DynamicOptions` bag that downstream prep stages mutate. Listed here
4
+ * once so the runtime clone (`cloneOptionsForCallIsolation`) and any
5
+ * future test that wants to assert call isolation reference the same
6
+ * source of truth.
7
+ *
8
+ * If you add a new top-level field to `StreamOptions` that gets mutated
9
+ * by prepareStreamOptions / applyStreamOrchestration / RAG/MCP injection
10
+ * / memory retrieval / etc., add it here AND add an entry to
11
+ * `test/helpers/cloneOptions.test.ts` so the isolation guarantee gets
12
+ * exercised.
13
+ *
14
+ * Branches that are deliberately NOT cloned (and why):
15
+ * - `signal` / `abortSignal` — `AbortSignal` can't be `structuredClone`d
16
+ * and a shallow copy would strip the listener wiring.
17
+ * - `tools[name].execute` — function identity is used as a cache key
18
+ * downstream; cloning would break that.
19
+ * - schema objects (zod / JSON Schema) — large, frequently frozen,
20
+ * and not mutated by NeuroLink internals.
21
+ */
22
+ export declare const CLONE_MUTABLE_OPTION_BRANCHES: readonly ["input", "context", "memory", "tools", "middleware", "rag", "csvOptions", "stt", "tts"];
23
+ /**
24
+ * Defensive call-isolation clone for stream() / generate()-shaped inputs.
25
+ *
26
+ * Shallow-clones the top-level options bag plus every branch listed in
27
+ * `CLONE_MUTABLE_OPTION_BRANCHES`. Caller-supplied objects can be reused
28
+ * across calls without accumulating cross-call mutations from
29
+ * prepareStreamOptions, applyStreamOrchestration, memory retrieval, or
30
+ * RAG/MCP tool injection.
31
+ *
32
+ * Unclonable / by-reference values are deliberately kept by-reference —
33
+ * cloning them would either fail outright (`structuredClone(AbortSignal)`)
34
+ * or strip behavior (function identity used as a cache key).
35
+ */
36
+ export declare function cloneOptionsForCallIsolation<T>(options: T): T;
@@ -0,0 +1,61 @@
1
+ /**
2
+ * The set of top-level branches on a `StreamOptions` / `GenerateOptions`
3
+ * / `DynamicOptions` bag that downstream prep stages mutate. Listed here
4
+ * once so the runtime clone (`cloneOptionsForCallIsolation`) and any
5
+ * future test that wants to assert call isolation reference the same
6
+ * source of truth.
7
+ *
8
+ * If you add a new top-level field to `StreamOptions` that gets mutated
9
+ * by prepareStreamOptions / applyStreamOrchestration / RAG/MCP injection
10
+ * / memory retrieval / etc., add it here AND add an entry to
11
+ * `test/helpers/cloneOptions.test.ts` so the isolation guarantee gets
12
+ * exercised.
13
+ *
14
+ * Branches that are deliberately NOT cloned (and why):
15
+ * - `signal` / `abortSignal` — `AbortSignal` can't be `structuredClone`d
16
+ * and a shallow copy would strip the listener wiring.
17
+ * - `tools[name].execute` — function identity is used as a cache key
18
+ * downstream; cloning would break that.
19
+ * - schema objects (zod / JSON Schema) — large, frequently frozen,
20
+ * and not mutated by NeuroLink internals.
21
+ */
22
+ export const CLONE_MUTABLE_OPTION_BRANCHES = [
23
+ "input",
24
+ "context",
25
+ "memory",
26
+ "tools",
27
+ "middleware",
28
+ "rag",
29
+ "csvOptions",
30
+ "stt",
31
+ "tts",
32
+ ];
33
+ /**
34
+ * Defensive call-isolation clone for stream() / generate()-shaped inputs.
35
+ *
36
+ * Shallow-clones the top-level options bag plus every branch listed in
37
+ * `CLONE_MUTABLE_OPTION_BRANCHES`. Caller-supplied objects can be reused
38
+ * across calls without accumulating cross-call mutations from
39
+ * prepareStreamOptions, applyStreamOrchestration, memory retrieval, or
40
+ * RAG/MCP tool injection.
41
+ *
42
+ * Unclonable / by-reference values are deliberately kept by-reference —
43
+ * cloning them would either fail outright (`structuredClone(AbortSignal)`)
44
+ * or strip behavior (function identity used as a cache key).
45
+ */
46
+ export function cloneOptionsForCallIsolation(options) {
47
+ if (!options || typeof options !== "object") {
48
+ return options;
49
+ }
50
+ const cloned = { ...options };
51
+ const o = cloned;
52
+ for (const branch of CLONE_MUTABLE_OPTION_BRANCHES) {
53
+ const value = o[branch];
54
+ if (value && typeof value === "object") {
55
+ o[branch] = Array.isArray(value)
56
+ ? [...value]
57
+ : { ...value };
58
+ }
59
+ }
60
+ return cloned;
61
+ }
@@ -1,13 +1,56 @@
1
1
  /**
2
- * Dedupes per-error invocations of the user-supplied `onError` lifecycle
3
- * callback. The same thrown error can travel through both the middleware
4
- * pipeline (which fires `onError` then re-throws) and the top-level
5
- * generate/stream catch in `neurolink.ts` — without a guard, the consumer
6
- * callback would fire twice for one logical failure.
2
+ * Lifecycle callback firing + dedupe.
7
3
  *
8
- * Strategy: stamp a non-enumerable Symbol on the error object the first
9
- * time a firing site is reached, skip subsequent firings. Symbol.for
10
- * lets us share the same key across modules without import gymnastics.
4
+ * The same thrown error can travel through multiple layers that each
5
+ * want to surface it to the consumer's `onError`:
6
+ * - LifecycleMiddleware's `wrapGenerate` / `wrapStream` catch
7
+ * - `BaseProvider.wrapStreamWithLifecycleCallbacks` (raw-fetch
8
+ * streaming providers that bypass AI SDK middleware)
9
+ * - `BaseProvider.fireLifecycleErrorCallback` (top-level provider catch)
10
+ * - `NeuroLink.generate()` / `NeuroLink.stream()` (early-resolution
11
+ * failures, before the language model is wrapped)
12
+ *
13
+ * Without a shared dedupe these layers would fire `onError` multiple
14
+ * times for one logical failure. This module stamps a non-enumerable
15
+ * `Symbol.for("neurolink.onErrorFired")` on the error the first time
16
+ * a firing site is reached; subsequent sites observe the stamp and
17
+ * skip their own fire.
18
+ *
19
+ * `Symbol.for` (rather than a local Symbol) so the same key works
20
+ * across modules — anyone who can read the symbol can read the stamp.
21
+ *
22
+ * Frozen / sealed / non-extensible errors: `Object.defineProperty`
23
+ * throws, we catch and proceed. Worst case is a single duplicate fire
24
+ * (the pre-shared-marker behaviour). `WeakSet`-based bookkeeping
25
+ * would handle this case cleanly but the symbol stamp is preferred
26
+ * for cross-realm consistency: a Symbol.for-keyed property survives
27
+ * structuredClone / cross-realm postMessage where a closed-over
28
+ * WeakSet does not.
11
29
  */
12
30
  import type { LifecycleErrorPayload, OnErrorCallback } from "../types/index.js";
31
+ /**
32
+ * Returns true when `markLifecycleErrorFired` or a previous
33
+ * `fireOnErrorOnce` call has already stamped this error.
34
+ */
35
+ export declare function hasLifecycleErrorFired(error: unknown): boolean;
36
+ /**
37
+ * Stamps the error as already-fired without invoking any callback.
38
+ * Use this from sites that already invoked `onError` via their own
39
+ * path (e.g. a provider-specific raw-fetch stream wrapper) so the
40
+ * shared dedupe still works.
41
+ */
42
+ export declare function markLifecycleErrorFired(error: unknown): void;
43
+ /**
44
+ * Fire the consumer's `onError` once per logical failure.
45
+ *
46
+ * - No-op when `onError` is missing.
47
+ * - No-op when the error is already stamped (any prior layer fired).
48
+ * - Otherwise: stamps the error, then invokes the callback.
49
+ *
50
+ * The callback is fire-and-forget; rejections are swallowed so a
51
+ * faulty handler can't mask the original throw. Callers that need
52
+ * to AWAIT the callback (e.g. to enforce a timeout) should use
53
+ * `hasLifecycleErrorFired` + `markLifecycleErrorFired` directly and
54
+ * run the callback themselves.
55
+ */
13
56
  export declare function fireOnErrorOnce(onError: OnErrorCallback | undefined, error: unknown, payload: LifecycleErrorPayload): void;
@@ -1,37 +1,93 @@
1
1
  /**
2
- * Dedupes per-error invocations of the user-supplied `onError` lifecycle
3
- * callback. The same thrown error can travel through both the middleware
4
- * pipeline (which fires `onError` then re-throws) and the top-level
5
- * generate/stream catch in `neurolink.ts` — without a guard, the consumer
6
- * callback would fire twice for one logical failure.
2
+ * Lifecycle callback firing + dedupe.
7
3
  *
8
- * Strategy: stamp a non-enumerable Symbol on the error object the first
9
- * time a firing site is reached, skip subsequent firings. Symbol.for
10
- * lets us share the same key across modules without import gymnastics.
4
+ * The same thrown error can travel through multiple layers that each
5
+ * want to surface it to the consumer's `onError`:
6
+ * - LifecycleMiddleware's `wrapGenerate` / `wrapStream` catch
7
+ * - `BaseProvider.wrapStreamWithLifecycleCallbacks` (raw-fetch
8
+ * streaming providers that bypass AI SDK middleware)
9
+ * - `BaseProvider.fireLifecycleErrorCallback` (top-level provider catch)
10
+ * - `NeuroLink.generate()` / `NeuroLink.stream()` (early-resolution
11
+ * failures, before the language model is wrapped)
12
+ *
13
+ * Without a shared dedupe these layers would fire `onError` multiple
14
+ * times for one logical failure. This module stamps a non-enumerable
15
+ * `Symbol.for("neurolink.onErrorFired")` on the error the first time
16
+ * a firing site is reached; subsequent sites observe the stamp and
17
+ * skip their own fire.
18
+ *
19
+ * `Symbol.for` (rather than a local Symbol) so the same key works
20
+ * across modules — anyone who can read the symbol can read the stamp.
21
+ *
22
+ * Frozen / sealed / non-extensible errors: `Object.defineProperty`
23
+ * throws, we catch and proceed. Worst case is a single duplicate fire
24
+ * (the pre-shared-marker behaviour). `WeakSet`-based bookkeeping
25
+ * would handle this case cleanly but the symbol stamp is preferred
26
+ * for cross-realm consistency: a Symbol.for-keyed property survives
27
+ * structuredClone / cross-realm postMessage where a closed-over
28
+ * WeakSet does not.
11
29
  */
12
30
  const ON_ERROR_FIRED = Symbol.for("neurolink.onErrorFired");
31
+ function stampFired(error) {
32
+ try {
33
+ Object.defineProperty(error, ON_ERROR_FIRED, {
34
+ value: true,
35
+ enumerable: false,
36
+ writable: false,
37
+ configurable: false,
38
+ });
39
+ }
40
+ catch {
41
+ // Non-extensible — fall through; worst case is a duplicate fire.
42
+ }
43
+ }
44
+ /**
45
+ * Returns true when `markLifecycleErrorFired` or a previous
46
+ * `fireOnErrorOnce` call has already stamped this error.
47
+ */
48
+ export function hasLifecycleErrorFired(error) {
49
+ if (error === null || typeof error !== "object") {
50
+ return false;
51
+ }
52
+ return error[ON_ERROR_FIRED] === true;
53
+ }
54
+ /**
55
+ * Stamps the error as already-fired without invoking any callback.
56
+ * Use this from sites that already invoked `onError` via their own
57
+ * path (e.g. a provider-specific raw-fetch stream wrapper) so the
58
+ * shared dedupe still works.
59
+ */
60
+ export function markLifecycleErrorFired(error) {
61
+ if (error === null || typeof error !== "object") {
62
+ return;
63
+ }
64
+ if (error[ON_ERROR_FIRED] === true) {
65
+ return;
66
+ }
67
+ stampFired(error);
68
+ }
69
+ /**
70
+ * Fire the consumer's `onError` once per logical failure.
71
+ *
72
+ * - No-op when `onError` is missing.
73
+ * - No-op when the error is already stamped (any prior layer fired).
74
+ * - Otherwise: stamps the error, then invokes the callback.
75
+ *
76
+ * The callback is fire-and-forget; rejections are swallowed so a
77
+ * faulty handler can't mask the original throw. Callers that need
78
+ * to AWAIT the callback (e.g. to enforce a timeout) should use
79
+ * `hasLifecycleErrorFired` + `markLifecycleErrorFired` directly and
80
+ * run the callback themselves.
81
+ */
13
82
  export function fireOnErrorOnce(onError, error, payload) {
14
83
  if (typeof onError !== "function") {
15
84
  return;
16
85
  }
17
- if (error && typeof error === "object") {
18
- const errAsRecord = error;
19
- if (errAsRecord[ON_ERROR_FIRED]) {
20
- return;
21
- }
22
- try {
23
- Object.defineProperty(error, ON_ERROR_FIRED, {
24
- value: true,
25
- enumerable: false,
26
- writable: false,
27
- configurable: false,
28
- });
29
- }
30
- catch {
31
- // Frozen/sealed error object — proceed without the stamp; the
32
- // worst case is a single duplicate fire if multiple sites observe
33
- // the same frozen value, which is the pre-existing behaviour.
34
- }
86
+ if (hasLifecycleErrorFired(error)) {
87
+ return;
88
+ }
89
+ if (error !== null && typeof error === "object") {
90
+ stampFired(error);
35
91
  }
36
92
  try {
37
93
  const result = onError(payload);