@juspay/neurolink 9.63.1 → 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 (358) hide show
  1. package/CHANGELOG.md +12 -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 +42 -11
  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 +573 -554
  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 +25 -1
  29. package/dist/cli/factories/commandFactory.js +341 -63
  30. package/dist/cli/loop/optionsSchema.d.ts +1 -1
  31. package/dist/cli/loop/optionsSchema.js +12 -0
  32. package/dist/constants/contextWindows.js +101 -0
  33. package/dist/constants/enums.d.ts +273 -2
  34. package/dist/constants/enums.js +290 -1
  35. package/dist/constants/videoErrors.d.ts +4 -0
  36. package/dist/constants/videoErrors.js +4 -0
  37. package/dist/core/baseProvider.d.ts +23 -3
  38. package/dist/core/baseProvider.js +217 -11
  39. package/dist/core/constants.d.ts +11 -0
  40. package/dist/core/constants.js +69 -1
  41. package/dist/core/modules/MessageBuilder.js +20 -0
  42. package/dist/core/redisConversationMemoryManager.js +6 -0
  43. package/dist/evaluation/index.d.ts +2 -0
  44. package/dist/evaluation/index.js +4 -0
  45. package/dist/factories/providerFactory.js +7 -1
  46. package/dist/factories/providerRegistry.js +203 -2
  47. package/dist/features/ppt/contentPlanner.js +42 -14
  48. package/dist/index.d.ts +9 -1
  49. package/dist/index.js +16 -1
  50. package/dist/lib/adapters/providerImageAdapter.js +29 -1
  51. package/dist/lib/adapters/replicate/auth.d.ts +19 -0
  52. package/dist/lib/adapters/replicate/auth.js +33 -0
  53. package/dist/lib/adapters/replicate/predictionLifecycle.d.ts +46 -0
  54. package/dist/lib/adapters/replicate/predictionLifecycle.js +284 -0
  55. package/dist/lib/adapters/video/klingVideoHandler.d.ts +37 -0
  56. package/dist/lib/adapters/video/klingVideoHandler.js +306 -0
  57. package/dist/lib/adapters/video/replicateVideoHandler.d.ts +29 -0
  58. package/dist/lib/adapters/video/replicateVideoHandler.js +158 -0
  59. package/dist/lib/adapters/video/runwayVideoHandler.d.ts +32 -0
  60. package/dist/lib/adapters/video/runwayVideoHandler.js +317 -0
  61. package/dist/lib/adapters/video/vertexVideoHandler.d.ts +19 -1
  62. package/dist/lib/adapters/video/vertexVideoHandler.js +42 -11
  63. package/dist/lib/autoresearch/runner.js +8 -2
  64. package/dist/lib/avatar/index.d.ts +13 -0
  65. package/dist/lib/avatar/index.js +14 -0
  66. package/dist/lib/avatar/providers/DIDAvatar.d.ts +49 -0
  67. package/dist/lib/avatar/providers/DIDAvatar.js +502 -0
  68. package/dist/lib/avatar/providers/HeyGenAvatar.d.ts +30 -0
  69. package/dist/lib/avatar/providers/HeyGenAvatar.js +338 -0
  70. package/dist/lib/avatar/providers/ReplicateAvatar.d.ts +36 -0
  71. package/dist/lib/avatar/providers/ReplicateAvatar.js +268 -0
  72. package/dist/lib/constants/contextWindows.js +101 -0
  73. package/dist/lib/constants/enums.d.ts +273 -2
  74. package/dist/lib/constants/enums.js +290 -1
  75. package/dist/lib/constants/videoErrors.d.ts +4 -0
  76. package/dist/lib/constants/videoErrors.js +4 -0
  77. package/dist/lib/core/baseProvider.d.ts +23 -3
  78. package/dist/lib/core/baseProvider.js +217 -11
  79. package/dist/lib/core/constants.d.ts +11 -0
  80. package/dist/lib/core/constants.js +69 -1
  81. package/dist/lib/core/modules/MessageBuilder.js +20 -0
  82. package/dist/lib/core/redisConversationMemoryManager.js +6 -0
  83. package/dist/lib/evaluation/index.d.ts +2 -0
  84. package/dist/lib/evaluation/index.js +4 -0
  85. package/dist/lib/factories/providerFactory.js +7 -1
  86. package/dist/lib/factories/providerRegistry.js +203 -2
  87. package/dist/lib/features/ppt/contentPlanner.js +42 -14
  88. package/dist/lib/index.d.ts +9 -1
  89. package/dist/lib/index.js +16 -1
  90. package/dist/lib/memory/hippocampusInitializer.d.ts +2 -2
  91. package/dist/lib/memory/hippocampusInitializer.js +32 -2
  92. package/dist/lib/middleware/builtin/lifecycle.js +52 -51
  93. package/dist/lib/music/index.d.ts +13 -0
  94. package/dist/lib/music/index.js +14 -0
  95. package/dist/lib/music/providers/BeatovenMusic.d.ts +31 -0
  96. package/dist/lib/music/providers/BeatovenMusic.js +334 -0
  97. package/dist/lib/music/providers/ElevenLabsMusic.d.ts +30 -0
  98. package/dist/lib/music/providers/ElevenLabsMusic.js +169 -0
  99. package/dist/lib/music/providers/LyriaMusic.d.ts +29 -0
  100. package/dist/lib/music/providers/LyriaMusic.js +173 -0
  101. package/dist/lib/music/providers/ReplicateMusic.d.ts +31 -0
  102. package/dist/lib/music/providers/ReplicateMusic.js +262 -0
  103. package/dist/lib/neurolink.d.ts +30 -0
  104. package/dist/lib/neurolink.js +342 -49
  105. package/dist/lib/providers/amazonBedrock.d.ts +10 -0
  106. package/dist/lib/providers/amazonBedrock.js +94 -39
  107. package/dist/lib/providers/anthropic.js +55 -7
  108. package/dist/lib/providers/anthropicBaseProvider.js +1 -1
  109. package/dist/lib/providers/azureOpenai.js +66 -17
  110. package/dist/lib/providers/cloudflare.d.ts +35 -0
  111. package/dist/lib/providers/cloudflare.js +174 -0
  112. package/dist/lib/providers/cohere.d.ts +52 -0
  113. package/dist/lib/providers/cohere.js +253 -0
  114. package/dist/lib/providers/deepseek.js +72 -17
  115. package/dist/lib/providers/fireworks.d.ts +33 -0
  116. package/dist/lib/providers/fireworks.js +164 -0
  117. package/dist/lib/providers/googleAiStudio.d.ts +11 -3
  118. package/dist/lib/providers/googleAiStudio.js +336 -344
  119. package/dist/lib/providers/googleNativeGemini3.d.ts +107 -2
  120. package/dist/lib/providers/googleNativeGemini3.js +381 -25
  121. package/dist/lib/providers/googleVertex.d.ts +116 -129
  122. package/dist/lib/providers/googleVertex.js +3002 -1988
  123. package/dist/lib/providers/groq.d.ts +33 -0
  124. package/dist/lib/providers/groq.js +181 -0
  125. package/dist/lib/providers/huggingFace.js +9 -8
  126. package/dist/lib/providers/ideogram.d.ts +34 -0
  127. package/dist/lib/providers/ideogram.js +184 -0
  128. package/dist/lib/providers/index.d.ts +13 -0
  129. package/dist/lib/providers/index.js +13 -0
  130. package/dist/lib/providers/jina.d.ts +59 -0
  131. package/dist/lib/providers/jina.js +218 -0
  132. package/dist/lib/providers/llamaCpp.js +14 -46
  133. package/dist/lib/providers/lmStudio.js +14 -47
  134. package/dist/lib/providers/mistral.js +7 -7
  135. package/dist/lib/providers/nvidiaNim.js +160 -19
  136. package/dist/lib/providers/ollama.js +7 -7
  137. package/dist/lib/providers/openAI.d.ts +22 -1
  138. package/dist/lib/providers/openAI.js +181 -0
  139. package/dist/lib/providers/openRouter.js +38 -22
  140. package/dist/lib/providers/openaiCompatible.js +9 -8
  141. package/dist/lib/providers/perplexity.d.ts +33 -0
  142. package/dist/lib/providers/perplexity.js +179 -0
  143. package/dist/lib/providers/recraft.d.ts +34 -0
  144. package/dist/lib/providers/recraft.js +197 -0
  145. package/dist/lib/providers/replicate.d.ts +75 -0
  146. package/dist/lib/providers/replicate.js +403 -0
  147. package/dist/lib/providers/stability.d.ts +37 -0
  148. package/dist/lib/providers/stability.js +191 -0
  149. package/dist/lib/providers/togetherAi.d.ts +33 -0
  150. package/dist/lib/providers/togetherAi.js +176 -0
  151. package/dist/lib/providers/voyage.d.ts +47 -0
  152. package/dist/lib/providers/voyage.js +177 -0
  153. package/dist/lib/providers/xai.d.ts +33 -0
  154. package/dist/lib/providers/xai.js +172 -0
  155. package/dist/lib/telemetry/index.d.ts +1 -1
  156. package/dist/lib/telemetry/index.js +1 -1
  157. package/dist/lib/telemetry/tracers.d.ts +19 -0
  158. package/dist/lib/telemetry/tracers.js +19 -0
  159. package/dist/lib/telemetry/withSpan.d.ts +35 -0
  160. package/dist/lib/telemetry/withSpan.js +103 -0
  161. package/dist/lib/types/aliases.d.ts +14 -0
  162. package/dist/lib/types/avatar.d.ts +143 -0
  163. package/dist/lib/types/avatar.js +20 -0
  164. package/dist/lib/types/cli.d.ts +6 -0
  165. package/dist/lib/types/common.d.ts +0 -3
  166. package/dist/lib/types/conversation.d.ts +10 -3
  167. package/dist/lib/types/generate.d.ts +76 -5
  168. package/dist/lib/types/index.d.ts +6 -0
  169. package/dist/lib/types/index.js +8 -0
  170. package/dist/lib/types/memory.d.ts +96 -0
  171. package/dist/lib/types/memory.js +23 -0
  172. package/dist/lib/types/middleware.d.ts +27 -0
  173. package/dist/lib/types/multimodal.d.ts +35 -2
  174. package/dist/lib/types/music.d.ts +165 -0
  175. package/dist/lib/types/music.js +21 -0
  176. package/dist/lib/types/providers.d.ts +284 -3
  177. package/dist/lib/types/replicate.d.ts +67 -0
  178. package/dist/lib/types/replicate.js +10 -0
  179. package/dist/lib/types/safeFetch.d.ts +15 -0
  180. package/dist/lib/types/safeFetch.js +7 -0
  181. package/dist/lib/types/stream.d.ts +8 -1
  182. package/dist/lib/types/tools.d.ts +13 -0
  183. package/dist/lib/types/video.d.ts +89 -0
  184. package/dist/lib/types/video.js +15 -0
  185. package/dist/lib/utils/avatarProcessor.d.ts +68 -0
  186. package/dist/lib/utils/avatarProcessor.js +172 -0
  187. package/dist/lib/utils/cloneOptions.d.ts +36 -0
  188. package/dist/lib/utils/cloneOptions.js +62 -0
  189. package/dist/lib/utils/lifecycleCallbacks.d.ts +56 -0
  190. package/dist/lib/utils/lifecycleCallbacks.js +100 -0
  191. package/dist/lib/utils/lifecycleTimeout.d.ts +25 -0
  192. package/dist/lib/utils/lifecycleTimeout.js +39 -0
  193. package/dist/lib/utils/logSanitize.d.ts +49 -0
  194. package/dist/lib/utils/logSanitize.js +170 -0
  195. package/dist/lib/utils/loggingFetch.d.ts +29 -0
  196. package/dist/lib/utils/loggingFetch.js +60 -0
  197. package/dist/lib/utils/messageBuilder.d.ts +10 -0
  198. package/dist/lib/utils/messageBuilder.js +83 -30
  199. package/dist/lib/utils/modelChoices.js +236 -3
  200. package/dist/lib/utils/modelDetection.d.ts +11 -0
  201. package/dist/lib/utils/modelDetection.js +27 -0
  202. package/dist/lib/utils/musicProcessor.d.ts +67 -0
  203. package/dist/lib/utils/musicProcessor.js +189 -0
  204. package/dist/lib/utils/optionsConversion.js +3 -2
  205. package/dist/lib/utils/parameterValidation.js +14 -4
  206. package/dist/lib/utils/pricing.js +193 -0
  207. package/dist/lib/utils/providerConfig.d.ts +55 -0
  208. package/dist/lib/utils/providerConfig.js +224 -0
  209. package/dist/lib/utils/providerHealth.js +7 -7
  210. package/dist/lib/utils/safeFetch.d.ts +26 -0
  211. package/dist/lib/utils/safeFetch.js +83 -0
  212. package/dist/lib/utils/schemaConversion.d.ts +1 -1
  213. package/dist/lib/utils/schemaConversion.js +59 -4
  214. package/dist/lib/utils/sizeGuard.d.ts +34 -0
  215. package/dist/lib/utils/sizeGuard.js +45 -0
  216. package/dist/lib/utils/ssrfGuard.d.ts +52 -0
  217. package/dist/lib/utils/ssrfGuard.js +411 -0
  218. package/dist/lib/utils/tokenLimits.js +23 -32
  219. package/dist/lib/utils/videoProcessor.d.ts +60 -0
  220. package/dist/lib/utils/videoProcessor.js +201 -0
  221. package/dist/lib/voice/providers/FishAudioTTS.d.ts +27 -0
  222. package/dist/lib/voice/providers/FishAudioTTS.js +183 -0
  223. package/dist/lib/workflow/core/ensembleExecutor.js +26 -9
  224. package/dist/memory/hippocampusInitializer.d.ts +2 -2
  225. package/dist/memory/hippocampusInitializer.js +32 -2
  226. package/dist/middleware/builtin/lifecycle.js +52 -51
  227. package/dist/music/index.d.ts +13 -0
  228. package/dist/music/index.js +13 -0
  229. package/dist/music/providers/BeatovenMusic.d.ts +31 -0
  230. package/dist/music/providers/BeatovenMusic.js +333 -0
  231. package/dist/music/providers/ElevenLabsMusic.d.ts +30 -0
  232. package/dist/music/providers/ElevenLabsMusic.js +168 -0
  233. package/dist/music/providers/LyriaMusic.d.ts +29 -0
  234. package/dist/music/providers/LyriaMusic.js +172 -0
  235. package/dist/music/providers/ReplicateMusic.d.ts +31 -0
  236. package/dist/music/providers/ReplicateMusic.js +261 -0
  237. package/dist/neurolink.d.ts +30 -0
  238. package/dist/neurolink.js +342 -49
  239. package/dist/providers/amazonBedrock.d.ts +10 -0
  240. package/dist/providers/amazonBedrock.js +94 -39
  241. package/dist/providers/anthropic.js +55 -7
  242. package/dist/providers/anthropicBaseProvider.js +1 -1
  243. package/dist/providers/azureOpenai.js +66 -17
  244. package/dist/providers/cloudflare.d.ts +35 -0
  245. package/dist/providers/cloudflare.js +173 -0
  246. package/dist/providers/cohere.d.ts +52 -0
  247. package/dist/providers/cohere.js +252 -0
  248. package/dist/providers/deepseek.js +72 -17
  249. package/dist/providers/fireworks.d.ts +33 -0
  250. package/dist/providers/fireworks.js +163 -0
  251. package/dist/providers/googleAiStudio.d.ts +11 -3
  252. package/dist/providers/googleAiStudio.js +335 -344
  253. package/dist/providers/googleNativeGemini3.d.ts +107 -2
  254. package/dist/providers/googleNativeGemini3.js +381 -25
  255. package/dist/providers/googleVertex.d.ts +116 -129
  256. package/dist/providers/googleVertex.js +3000 -1987
  257. package/dist/providers/groq.d.ts +33 -0
  258. package/dist/providers/groq.js +180 -0
  259. package/dist/providers/huggingFace.js +9 -8
  260. package/dist/providers/ideogram.d.ts +34 -0
  261. package/dist/providers/ideogram.js +183 -0
  262. package/dist/providers/index.d.ts +13 -0
  263. package/dist/providers/index.js +13 -0
  264. package/dist/providers/jina.d.ts +59 -0
  265. package/dist/providers/jina.js +217 -0
  266. package/dist/providers/llamaCpp.js +14 -46
  267. package/dist/providers/lmStudio.js +14 -47
  268. package/dist/providers/mistral.js +7 -7
  269. package/dist/providers/nvidiaNim.js +160 -19
  270. package/dist/providers/ollama.js +7 -7
  271. package/dist/providers/openAI.d.ts +22 -1
  272. package/dist/providers/openAI.js +181 -0
  273. package/dist/providers/openRouter.js +38 -22
  274. package/dist/providers/openaiCompatible.js +9 -8
  275. package/dist/providers/perplexity.d.ts +33 -0
  276. package/dist/providers/perplexity.js +178 -0
  277. package/dist/providers/recraft.d.ts +34 -0
  278. package/dist/providers/recraft.js +196 -0
  279. package/dist/providers/replicate.d.ts +75 -0
  280. package/dist/providers/replicate.js +402 -0
  281. package/dist/providers/stability.d.ts +37 -0
  282. package/dist/providers/stability.js +190 -0
  283. package/dist/providers/togetherAi.d.ts +33 -0
  284. package/dist/providers/togetherAi.js +175 -0
  285. package/dist/providers/voyage.d.ts +47 -0
  286. package/dist/providers/voyage.js +176 -0
  287. package/dist/providers/xai.d.ts +33 -0
  288. package/dist/providers/xai.js +171 -0
  289. package/dist/telemetry/index.d.ts +1 -1
  290. package/dist/telemetry/index.js +1 -1
  291. package/dist/telemetry/tracers.d.ts +19 -0
  292. package/dist/telemetry/tracers.js +19 -0
  293. package/dist/telemetry/withSpan.d.ts +35 -0
  294. package/dist/telemetry/withSpan.js +103 -0
  295. package/dist/types/aliases.d.ts +14 -0
  296. package/dist/types/avatar.d.ts +143 -0
  297. package/dist/types/avatar.js +19 -0
  298. package/dist/types/cli.d.ts +6 -0
  299. package/dist/types/common.d.ts +0 -3
  300. package/dist/types/conversation.d.ts +10 -3
  301. package/dist/types/generate.d.ts +76 -5
  302. package/dist/types/index.d.ts +6 -0
  303. package/dist/types/index.js +8 -0
  304. package/dist/types/memory.d.ts +96 -0
  305. package/dist/types/memory.js +22 -0
  306. package/dist/types/middleware.d.ts +27 -0
  307. package/dist/types/multimodal.d.ts +35 -2
  308. package/dist/types/music.d.ts +165 -0
  309. package/dist/types/music.js +20 -0
  310. package/dist/types/providers.d.ts +284 -3
  311. package/dist/types/replicate.d.ts +67 -0
  312. package/dist/types/replicate.js +9 -0
  313. package/dist/types/safeFetch.d.ts +15 -0
  314. package/dist/types/safeFetch.js +6 -0
  315. package/dist/types/stream.d.ts +8 -1
  316. package/dist/types/tools.d.ts +13 -0
  317. package/dist/types/video.d.ts +89 -0
  318. package/dist/types/video.js +14 -0
  319. package/dist/utils/avatarProcessor.d.ts +68 -0
  320. package/dist/utils/avatarProcessor.js +171 -0
  321. package/dist/utils/cloneOptions.d.ts +36 -0
  322. package/dist/utils/cloneOptions.js +61 -0
  323. package/dist/utils/lifecycleCallbacks.d.ts +56 -0
  324. package/dist/utils/lifecycleCallbacks.js +99 -0
  325. package/dist/utils/lifecycleTimeout.d.ts +25 -0
  326. package/dist/utils/lifecycleTimeout.js +38 -0
  327. package/dist/utils/logSanitize.d.ts +49 -0
  328. package/dist/utils/logSanitize.js +169 -0
  329. package/dist/utils/loggingFetch.d.ts +29 -0
  330. package/dist/utils/loggingFetch.js +59 -0
  331. package/dist/utils/messageBuilder.d.ts +10 -0
  332. package/dist/utils/messageBuilder.js +83 -30
  333. package/dist/utils/modelChoices.js +236 -3
  334. package/dist/utils/modelDetection.d.ts +11 -0
  335. package/dist/utils/modelDetection.js +27 -0
  336. package/dist/utils/musicProcessor.d.ts +67 -0
  337. package/dist/utils/musicProcessor.js +188 -0
  338. package/dist/utils/optionsConversion.js +3 -2
  339. package/dist/utils/parameterValidation.js +14 -4
  340. package/dist/utils/pricing.js +193 -0
  341. package/dist/utils/providerConfig.d.ts +55 -0
  342. package/dist/utils/providerConfig.js +224 -0
  343. package/dist/utils/providerHealth.js +7 -7
  344. package/dist/utils/safeFetch.d.ts +26 -0
  345. package/dist/utils/safeFetch.js +82 -0
  346. package/dist/utils/schemaConversion.d.ts +1 -1
  347. package/dist/utils/schemaConversion.js +59 -4
  348. package/dist/utils/sizeGuard.d.ts +34 -0
  349. package/dist/utils/sizeGuard.js +44 -0
  350. package/dist/utils/ssrfGuard.d.ts +52 -0
  351. package/dist/utils/ssrfGuard.js +410 -0
  352. package/dist/utils/tokenLimits.js +23 -32
  353. package/dist/utils/videoProcessor.d.ts +60 -0
  354. package/dist/utils/videoProcessor.js +200 -0
  355. package/dist/voice/providers/FishAudioTTS.d.ts +27 -0
  356. package/dist/voice/providers/FishAudioTTS.js +182 -0
  357. package/dist/workflow/core/ensembleExecutor.js +26 -9
  358. package/package.json +42 -8
@@ -40,7 +40,26 @@ export declare const STREAM_DEDUP_CONTEXT_KEY: "_streamDedupContext";
40
40
  export declare function markStreamProviderEmittedGenerationEnd(options: {
41
41
  _streamDedupContext?: StreamGenerationEndContext;
42
42
  } | undefined): void;
43
+ /**
44
+ * Symbol-based brand for cross-module identification without circular imports.
45
+ *
46
+ * Provider constructors receive `sdk?: unknown` (the factory layer's
47
+ * contract). Rather than duck-typing via `"getInMemoryServers" in sdk`,
48
+ * use `isNeuroLink(value)` from this module to do a brand check —
49
+ * survives minification AND doesn't rely on method-name stability.
50
+ */
51
+ export declare const NEUROLINK_BRAND: unique symbol;
52
+ /**
53
+ * Type-guard for opaque values that should be a {@link NeuroLink} instance.
54
+ *
55
+ * Designed for the provider-factory boundary where TS can't carry the type
56
+ * through `UnknownRecord` without forcing every caller into a circular
57
+ * dependency. Cheap to call and unaffected by minification.
58
+ */
59
+ export declare function isNeuroLink(value: unknown): value is NeuroLink;
43
60
  export declare class NeuroLink {
61
+ /** @internal Brand for cross-module identification — see {@link isNeuroLink}. */
62
+ readonly [NEUROLINK_BRAND]: true;
44
63
  private mcpInitialized;
45
64
  private mcpSkipped;
46
65
  private mcpInitPromise;
@@ -570,6 +589,7 @@ export declare class NeuroLink {
570
589
  * @since 1.0.0
571
590
  */
572
591
  generate(optionsOrPrompt: GenerateOptions | DynamicOptions | string): Promise<GenerateResult>;
592
+ private fireConsumerOnErrorIfNotFired;
573
593
  /**
574
594
  * Curator P2-3: wraps a generate/stream call with the fallback
575
595
  * orchestration (`providerFallback` callback + `modelChain` walker).
@@ -603,6 +623,16 @@ export declare class NeuroLink {
603
623
  * Handle PPT generation mode
604
624
  */
605
625
  private generateWithPPT;
626
+ /**
627
+ * Dispatch a music-generation request to the registered music handler
628
+ * for the provider named in `options.output.music.provider`.
629
+ */
630
+ private generateWithMusic;
631
+ /**
632
+ * Dispatch an avatar (lip-sync) request to the registered avatar handler
633
+ * for the provider named in `options.output.avatar.provider`.
634
+ */
635
+ private generateWithAvatar;
606
636
  /**
607
637
  * Generate with workflow engine integration
608
638
  * Returns both original and processed responses for AB testing
package/dist/neurolink.js CHANGED
@@ -62,6 +62,9 @@ import { tracers } from "./telemetry/tracers.js";
62
62
  import { getConversationMessages, storeConversationTurn, } from "./utils/conversationMemory.js";
63
63
  // Enhanced error handling imports
64
64
  import { CircuitBreaker, ERROR_CODES, ErrorFactory, isAbortError, isRetriableError, logStructuredError, NeuroLinkError, withRetry, withTimeout, } from "./utils/errorHandling.js";
65
+ import { hasLifecycleErrorFired, markLifecycleErrorFired, } from "./utils/lifecycleCallbacks.js";
66
+ import { resolveLifecycleTimeoutMs } from "./utils/lifecycleTimeout.js";
67
+ import { cloneOptionsForCallIsolation } from "./utils/cloneOptions.js";
65
68
  // Factory processing imports
66
69
  import { createCleanStreamOptions, enhanceTextGenerationOptions, processFactoryOptions, processStreamingFactoryOptions, validateFactoryConfig, } from "./utils/factoryProcessing.js";
67
70
  import { logger, mcpLogger } from "./utils/logger.js";
@@ -333,7 +336,30 @@ export function markStreamProviderEmittedGenerationEnd(options) {
333
336
  ctx.providerEmitted = true;
334
337
  }
335
338
  }
339
+ /**
340
+ * Symbol-based brand for cross-module identification without circular imports.
341
+ *
342
+ * Provider constructors receive `sdk?: unknown` (the factory layer's
343
+ * contract). Rather than duck-typing via `"getInMemoryServers" in sdk`,
344
+ * use `isNeuroLink(value)` from this module to do a brand check —
345
+ * survives minification AND doesn't rely on method-name stability.
346
+ */
347
+ export const NEUROLINK_BRAND = Symbol.for("@juspay/neurolink/sdk-brand");
348
+ /**
349
+ * Type-guard for opaque values that should be a {@link NeuroLink} instance.
350
+ *
351
+ * Designed for the provider-factory boundary where TS can't carry the type
352
+ * through `UnknownRecord` without forcing every caller into a circular
353
+ * dependency. Cheap to call and unaffected by minification.
354
+ */
355
+ export function isNeuroLink(value) {
356
+ return (typeof value === "object" &&
357
+ value !== null &&
358
+ value[NEUROLINK_BRAND] === true);
359
+ }
336
360
  export class NeuroLink {
361
+ /** @internal Brand for cross-module identification — see {@link isNeuroLink}. */
362
+ [NEUROLINK_BRAND] = true;
337
363
  mcpInitialized = false;
338
364
  mcpSkipped = false;
339
365
  mcpInitPromise = null;
@@ -2753,7 +2779,66 @@ Current user's request: ${currentInput}`;
2753
2779
  * @since 1.0.0
2754
2780
  */
2755
2781
  async generate(optionsOrPrompt) {
2756
- return this.runWithFallbackOrchestration(optionsOrPrompt, "generate", (opts) => tracers.sdk.startActiveSpan("neurolink.generate", { kind: SpanKind.INTERNAL }, (generateSpan) => this.executeGenerateWithMetricsContext(opts, generateSpan)));
2782
+ // Defensive call-isolation clone mirrors stream(): downstream
2783
+ // generate-prep (memory retrieval, orchestration, RAG/MCP tool
2784
+ // injection) mutates nested branches on the caller-supplied options
2785
+ // object. Without cloning here, callers reusing a single options
2786
+ // bag across generate() calls accumulate state across them.
2787
+ // String prompts are immutable, so they pass through.
2788
+ if (typeof optionsOrPrompt !== "string") {
2789
+ optionsOrPrompt = cloneOptionsForCallIsolation(optionsOrPrompt);
2790
+ }
2791
+ const startedAt = Date.now();
2792
+ try {
2793
+ return await this.runWithFallbackOrchestration(optionsOrPrompt, "generate", (opts) => tracers.sdk.startActiveSpan("neurolink.generate", { kind: SpanKind.INTERNAL }, (generateSpan) => this.executeGenerateWithMetricsContext(opts, generateSpan)));
2794
+ }
2795
+ catch (error) {
2796
+ // Lifecycle middleware (wrapGenerate.catch in builtin/lifecycle.ts)
2797
+ // stamps errors it already surfaced with the shared Symbol marker
2798
+ // (see utils/lifecycleCallbacks.ts). For errors thrown BEFORE the
2799
+ // language model was wrapped (e.g. unknown provider name,
2800
+ // validation failures, factory exceptions), the mark is absent —
2801
+ // fire the consumer's onError here so it sees every failure path.
2802
+ // Awaited so async handlers fully settle before generate()
2803
+ // rethrows, matching the middleware-managed path.
2804
+ await this.fireConsumerOnErrorIfNotFired(optionsOrPrompt, error, startedAt);
2805
+ throw error;
2806
+ }
2807
+ }
2808
+ async fireConsumerOnErrorIfNotFired(optionsOrPrompt, error, startedAt) {
2809
+ if (hasLifecycleErrorFired(error)) {
2810
+ return;
2811
+ }
2812
+ if (typeof optionsOrPrompt !== "object" || optionsOrPrompt === null) {
2813
+ return;
2814
+ }
2815
+ const opts = optionsOrPrompt;
2816
+ const userOnError = opts.onError;
2817
+ if (!userOnError) {
2818
+ return;
2819
+ }
2820
+ const err = error instanceof Error ? error : new Error(String(error));
2821
+ // Bound the consumer callback so a never-settling handler can't hang
2822
+ // generate()/stream(). The deadline honors per-call
2823
+ // `lifecycle.timeoutMs` and the `NEUROLINK_LIFECYCLE_TIMEOUT_MS` env
2824
+ // var (CLI surface), falling back to 5_000. Errors raised here are
2825
+ // logged and swallowed; the original failure still propagates to the
2826
+ // caller because the outer catch re-throws.
2827
+ const lifecycle = opts.middleware?.middlewareConfig?.lifecycle?.config;
2828
+ const timeoutMs = resolveLifecycleTimeoutMs(lifecycle);
2829
+ // Mark the error first so the AI-SDK lifecycle middleware can't
2830
+ // re-fire the same callback if the throw races a parallel catch.
2831
+ markLifecycleErrorFired(err);
2832
+ try {
2833
+ await withTimeout(Promise.resolve(userOnError({
2834
+ error: err,
2835
+ duration: Date.now() - startedAt,
2836
+ recoverable: false,
2837
+ })), timeoutMs, new Error(`consumer onError callback timed out after ${timeoutMs}ms`));
2838
+ }
2839
+ catch (e) {
2840
+ logger.warn("[NeuroLink] consumer onError callback error:", e);
2841
+ }
2757
2842
  }
2758
2843
  /**
2759
2844
  * Curator P2-3: wraps a generate/stream call with the fallback
@@ -2838,15 +2923,23 @@ Current user's request: ${currentInput}`;
2838
2923
  catch {
2839
2924
  /* listener errors are non-fatal */
2840
2925
  }
2926
+ // Defensive call-isolation clone for the retry attempt. The shallow
2927
+ // spread below would keep nested branches (`input`, `tools`, `memory`,
2928
+ // `rag`, …) pointing at the same objects the previous attempt's
2929
+ // prepare stages mutated — so the retry inherits e.g. memory-retrieved
2930
+ // history appended to `input.messages`, RAG-injected tools, etc.
2931
+ // Re-cloning at the retry boundary mirrors the entry-level isolation
2932
+ // applied in generate()/stream() so each fallback attempt sees a
2933
+ // fresh options bag.
2841
2934
  const retriedOptions = typeof optionsOrPrompt === "object"
2842
- ? {
2935
+ ? cloneOptionsForCallIsolation({
2843
2936
  ...optionsOrPrompt,
2844
2937
  ...(next.provider && { provider: next.provider }),
2845
2938
  ...(next.model && { model: next.model }),
2846
2939
  // Strip the fallback hooks so the retry doesn't re-orchestrate.
2847
2940
  providerFallback: undefined,
2848
2941
  modelChain: undefined,
2849
- }
2942
+ })
2850
2943
  : optionsOrPrompt;
2851
2944
  const retryAttempt = await this.attemptInner(inner, retriedOptions);
2852
2945
  if ("ok" in retryAttempt) {
@@ -2922,6 +3015,12 @@ Current user's request: ${currentInput}`;
2922
3015
  const options = typeof optionsOrPrompt === "string"
2923
3016
  ? { input: { text: optionsOrPrompt } }
2924
3017
  : { ...optionsOrPrompt };
3018
+ // Normalise: all downstream code assumes options.input is defined.
3019
+ // Media-only callers may omit `input` entirely (or pass `input: {}`);
3020
+ // synthesise an empty shell so the rest of the pipeline can rely on it.
3021
+ if (!options.input) {
3022
+ options.input = {};
3023
+ }
2925
3024
  // Dynamic argument resolution — resolve any function-valued options before downstream use
2926
3025
  await this.resolveDynamicOptions(options);
2927
3026
  options.model = resolveModel(options.model, this.modelAliasConfig);
@@ -2932,13 +3031,28 @@ Current user's request: ${currentInput}`;
2932
3031
  ? optionsOrPrompt.length
2933
3032
  : options.input?.text?.length || 0);
2934
3033
  generateSpan.setAttribute("neurolink.has_tools", !!(options.tools && Object.keys(options.tools).length > 0));
2935
- // When STT audio is provided, ensure options.input exists (the transcription
2936
- // will supply the text inside runStandardGenerateRequest) and skip text validation.
3034
+ // Ensure options.input is always an object callers may omit it for
3035
+ // media-only modes (avatar / music / video) or STT flows. Downstream code
3036
+ // accesses it unconditionally, so we guarantee a non-null object here and
3037
+ // rely on the per-mode checks below to populate / validate the text field.
3038
+ options.input ??= {};
3039
+ // When STT audio is provided, ensure options.input.text is initialised
3040
+ // (the transcription will supply the text inside runStandardGenerateRequest).
2937
3041
  const hasSttAudio = !!(options.stt?.enabled && options.stt?.audio);
2938
- if (hasSttAudio && !options.input) {
2939
- options.input = { text: "" };
2940
- }
2941
- if (!hasSttAudio) {
3042
+ if (hasSttAudio && !options.input.text) {
3043
+ options.input.text = "";
3044
+ }
3045
+ // Modality dispatch (video / avatar / music) carries the prompt inside
3046
+ // `output.{video|avatar|music}` — input.text is not meaningful for these
3047
+ // modes. Synthesize an empty input.text and skip validation, mirroring
3048
+ // the STT-audio exception above.
3049
+ const isMediaModalityMode = options.output?.mode === "video" ||
3050
+ options.output?.mode === "avatar" ||
3051
+ options.output?.mode === "music";
3052
+ if (isMediaModalityMode && !options.input.text) {
3053
+ options.input.text = "";
3054
+ }
3055
+ if (!hasSttAudio && !isMediaModalityMode) {
2942
3056
  this.assertInputText(options.input?.text, "Input text is required and must be a non-empty string");
2943
3057
  }
2944
3058
  this.enforceSessionBudget(options.maxBudgetUsd);
@@ -2948,6 +3062,16 @@ Current user's request: ${currentInput}`;
2948
3062
  }
2949
3063
  async maybeHandleEarlyGenerateResult(options, generateSpan) {
2950
3064
  if (options.workflow || options.workflowConfig) {
3065
+ // Workflow engine operates on text; media generation modes (avatar, music,
3066
+ // video, ppt) use dedicated code paths and are incompatible with workflows.
3067
+ const workflowMediaMode = options.output?.mode;
3068
+ if (workflowMediaMode === "avatar" ||
3069
+ workflowMediaMode === "music" ||
3070
+ workflowMediaMode === "video" ||
3071
+ workflowMediaMode === "ppt") {
3072
+ throw new Error(`Workflow mode is not compatible with output.mode="${workflowMediaMode}". ` +
3073
+ 'Remove the workflow config or use output.mode="text".');
3074
+ }
2951
3075
  if (options.stt?.enabled && options.stt?.audio) {
2952
3076
  // prepareGenerateRequest synthesizes input.text = "" for audio-only
2953
3077
  // calls, so without this guard generateWithWorkflow runs with an
@@ -2959,6 +3083,12 @@ Current user's request: ${currentInput}`;
2959
3083
  }
2960
3084
  return this.generateWithWorkflow(options);
2961
3085
  }
3086
+ if (options.output?.mode === "music") {
3087
+ return this.generateWithMusic(options, generateSpan);
3088
+ }
3089
+ if (options.output?.mode === "avatar") {
3090
+ return this.generateWithAvatar(options, generateSpan);
3091
+ }
2962
3092
  if (options.output?.mode !== "ppt") {
2963
3093
  return null;
2964
3094
  }
@@ -3076,7 +3206,7 @@ Current user's request: ${currentInput}`;
3076
3206
  originalProvider: options.provider || "auto",
3077
3207
  orchestratedProvider: orchestratedOptions.provider,
3078
3208
  orchestratedModel: orchestratedOptions.model,
3079
- prompt: options.input.text.substring(0, 100),
3209
+ prompt: (options.input?.text ?? "").substring(0, 100),
3080
3210
  });
3081
3211
  Object.assign(options, orchestratedOptions);
3082
3212
  if (orchestratedOptions.model) {
@@ -3121,12 +3251,22 @@ Current user's request: ${currentInput}`;
3121
3251
  });
3122
3252
  }
3123
3253
  }
3124
- if (!this.shouldReadMemory(options.memory, options.context?.userId) ||
3254
+ // Media-only modes (avatar, music, video, ppt) do not have a meaningful
3255
+ // text prompt to augment with memory — skip injection to avoid corrupting
3256
+ // the empty/synthesized input.text that was set for these modes.
3257
+ const mediaOnlyMode = options.output?.mode === "avatar" ||
3258
+ options.output?.mode === "music" ||
3259
+ options.output?.mode === "video" ||
3260
+ options.output?.mode === "ppt";
3261
+ if (mediaOnlyMode ||
3262
+ !this.shouldReadMemory(options.memory, options.context?.userId) ||
3125
3263
  !options.context?.userId) {
3126
3264
  return;
3127
3265
  }
3128
3266
  try {
3129
- options.input.text = await this.retrieveMemory(options.input.text, options.context.userId, options.memory?.additionalUsers);
3267
+ if (options.input) {
3268
+ options.input.text = await this.retrieveMemory(options.input.text ?? "", options.context.userId, options.memory?.additionalUsers);
3269
+ }
3130
3270
  logger.debug("Memory retrieval successful (generate)");
3131
3271
  }
3132
3272
  catch (error) {
@@ -3135,7 +3275,7 @@ Current user's request: ${currentInput}`;
3135
3275
  }
3136
3276
  async buildGenerateTextOptions(options, originalPrompt, factoryResult) {
3137
3277
  const baseOptions = {
3138
- prompt: options.input.text,
3278
+ prompt: options.input?.text,
3139
3279
  provider: options.provider,
3140
3280
  model: options.model,
3141
3281
  temperature: options.temperature,
@@ -3167,6 +3307,12 @@ Current user's request: ${currentInput}`;
3167
3307
  middleware: options.middleware,
3168
3308
  conversationMessages: options.conversationMessages,
3169
3309
  credentials: options.credentials,
3310
+ // Lifecycle callbacks must reach the provider so non-AI-SDK paths
3311
+ // (Vertex's native @google/genai, native Bedrock, Ollama, etc.) can
3312
+ // invoke them directly. Pipeline A also still receives them via the
3313
+ // wrapped middleware config set by applyGenerateLifecycleMiddleware.
3314
+ onFinish: options.onFinish,
3315
+ onError: options.onError,
3170
3316
  };
3171
3317
  const extraContext = options;
3172
3318
  if (extraContext.sessionId || extraContext.userId) {
@@ -3185,11 +3331,11 @@ Current user's request: ${currentInput}`;
3185
3331
  textOptions.conversationMemoryConfig = this.conversationMemory.config;
3186
3332
  textOptions.originalPrompt = originalPrompt;
3187
3333
  }
3188
- const { toolResults, enhancedPrompt } = await this.detectAndExecuteTools(textOptions.prompt || options.input.text, factoryResult.domainType);
3334
+ const { toolResults, enhancedPrompt } = await this.detectAndExecuteTools(textOptions.prompt || options.input?.text || "", factoryResult.domainType);
3189
3335
  if (enhancedPrompt !== textOptions.prompt) {
3190
3336
  textOptions.prompt = enhancedPrompt;
3191
3337
  logger.debug("Enhanced prompt with tool results", {
3192
- originalLength: options.input.text.length,
3338
+ originalLength: (options.input?.text ?? "").length,
3193
3339
  enhancedLength: enhancedPrompt.length,
3194
3340
  toolResults: toolResults.length,
3195
3341
  });
@@ -3198,26 +3344,35 @@ Current user's request: ${currentInput}`;
3198
3344
  }
3199
3345
  finalizeGenerateRequestResult(params) {
3200
3346
  const { generateSpan, options, textOptions, textResult, factoryResult, originalPrompt, startTime, } = params;
3201
- this.emitter.emit("generation:end", {
3202
- provider: textResult.provider,
3203
- responseTime: Date.now() - startTime,
3204
- toolsUsed: textResult.toolsUsed,
3205
- timestamp: Date.now(),
3206
- result: textResult,
3207
- // Use the effective prompt (which already incorporates STT-transcribed
3208
- // text for audio-only calls) so observers see the real prompt instead
3209
- // of an empty string. Falls back through the same chain as before for
3210
- // text-only calls.
3211
- prompt: originalPrompt ||
3212
- options.input?.text ||
3213
- options.prompt,
3214
- temperature: textOptions.temperature,
3215
- maxTokens: textOptions.maxTokens,
3216
- // A2 fix: Signal that Pipeline A (AI SDK @langfuse/otel) already
3217
- // creates a GENERATION observation for this call. The generation:end
3218
- // listener should skip creating a duplicate Pipeline B span.
3219
- pipelineAHandled: true,
3220
- });
3347
+ // Skip the top-level `generation:end` emission when the provider already
3348
+ // emitted it from its native generate path (Vertex / Google AI Studio).
3349
+ // Without this guard, native-path providers would surface TWO events
3350
+ // per generate call (Pipeline A path: 1 from provider native + 1 here;
3351
+ // standard AI-SDK path: 1 here). The observability suite asserts on
3352
+ // emission count and would (and did) fail.
3353
+ const nativeAlreadyEmitted = !!textResult._generationEndEmitted;
3354
+ if (!nativeAlreadyEmitted) {
3355
+ this.emitter.emit("generation:end", {
3356
+ provider: textResult.provider,
3357
+ responseTime: Date.now() - startTime,
3358
+ toolsUsed: textResult.toolsUsed,
3359
+ timestamp: Date.now(),
3360
+ result: textResult,
3361
+ // Use the effective prompt (which already incorporates STT-transcribed
3362
+ // text for audio-only calls) so observers see the real prompt instead
3363
+ // of an empty string. Falls back through the same chain as before for
3364
+ // text-only calls.
3365
+ prompt: originalPrompt ||
3366
+ options.input?.text ||
3367
+ options.prompt,
3368
+ temperature: textOptions.temperature,
3369
+ maxTokens: textOptions.maxTokens,
3370
+ // A2 fix: Signal that Pipeline A (AI SDK → @langfuse/otel) already
3371
+ // creates a GENERATION observation for this call. The generation:end
3372
+ // listener should skip creating a duplicate Pipeline B span.
3373
+ pipelineAHandled: true,
3374
+ });
3375
+ }
3221
3376
  this.emitter.emit("response:end", textResult.content || "");
3222
3377
  this.emitter.emit("message", `Generation completed in ${Date.now() - startTime}ms`);
3223
3378
  const generateResult = {
@@ -3255,7 +3410,18 @@ Current user's request: ${currentInput}`;
3255
3410
  audio: textResult.audio,
3256
3411
  transcription: textResult.transcription,
3257
3412
  video: textResult.video,
3413
+ avatar: textResult.avatar,
3414
+ music: textResult.music,
3258
3415
  ppt: textResult.ppt,
3416
+ // Forward reasoning/reasoningTokens from the provider layer.
3417
+ // BaseProvider's GenerationHandler extracts these from AI-SDK reasoning
3418
+ // parts (DeepSeek's `reasoning_content`, Anthropic thinking blocks,
3419
+ // Gemini thought parts, OpenAI o1) and they're declared on
3420
+ // `GenerateResult`, but the builder previously dropped them on the
3421
+ // floor — so callers asking for `result.reasoning` got `undefined`
3422
+ // even when the model emitted a chain-of-thought.
3423
+ reasoning: textResult.reasoning,
3424
+ reasoningTokens: textResult.reasoningTokens,
3259
3425
  ...(textResult.retries && { retries: textResult.retries }),
3260
3426
  };
3261
3427
  if (generateResult.analytics?.cost && generateResult.analytics.cost > 0) {
@@ -3348,6 +3514,67 @@ Current user's request: ${currentInput}`;
3348
3514
  ppt: pptResult,
3349
3515
  };
3350
3516
  }
3517
+ /**
3518
+ * Dispatch a music-generation request to the registered music handler
3519
+ * for the provider named in `options.output.music.provider`.
3520
+ */
3521
+ async generateWithMusic(options, generateSpan) {
3522
+ const startTime = Date.now();
3523
+ const musicOptions = options.output?.music;
3524
+ if (!musicOptions) {
3525
+ throw new Error('output.mode="music" requires output.music with at least { provider, prompt }.');
3526
+ }
3527
+ const providerName = musicOptions.provider;
3528
+ if (!providerName) {
3529
+ throw new Error('output.music.provider is required (e.g. "beatoven", "elevenlabs-music", "lyria", "replicate").');
3530
+ }
3531
+ const { MusicProcessor } = await import("./utils/musicProcessor.js");
3532
+ const musicResult = await MusicProcessor.generate(providerName, {
3533
+ ...musicOptions,
3534
+ prompt: musicOptions.prompt ?? options.input?.text ?? "",
3535
+ });
3536
+ generateSpan.setAttribute("neurolink.music.provider", providerName);
3537
+ generateSpan.setAttribute("neurolink.music.bytes", musicResult.size);
3538
+ generateSpan.setStatus({ code: SpanStatusCode.OK });
3539
+ return {
3540
+ content: `Music generated (${providerName}, ${musicResult.size} bytes, ${musicResult.format}).`,
3541
+ finishReason: "stop",
3542
+ provider: providerName,
3543
+ model: musicResult.metadata?.model ?? providerName,
3544
+ usage: undefined,
3545
+ responseTime: Date.now() - startTime,
3546
+ music: musicResult,
3547
+ };
3548
+ }
3549
+ /**
3550
+ * Dispatch an avatar (lip-sync) request to the registered avatar handler
3551
+ * for the provider named in `options.output.avatar.provider`.
3552
+ */
3553
+ async generateWithAvatar(options, generateSpan) {
3554
+ const startTime = Date.now();
3555
+ const avatarOptions = options.output?.avatar;
3556
+ if (!avatarOptions) {
3557
+ throw new Error('output.mode="avatar" requires output.avatar with at least { provider, image, audio|text }.');
3558
+ }
3559
+ const providerName = avatarOptions.provider;
3560
+ if (!providerName) {
3561
+ throw new Error('output.avatar.provider is required (e.g. "d-id", "heygen", "replicate").');
3562
+ }
3563
+ const { AvatarProcessor } = await import("./utils/avatarProcessor.js");
3564
+ const avatarResult = await AvatarProcessor.generate(providerName, avatarOptions);
3565
+ generateSpan.setAttribute("neurolink.avatar.provider", providerName);
3566
+ generateSpan.setAttribute("neurolink.avatar.bytes", avatarResult.size);
3567
+ generateSpan.setStatus({ code: SpanStatusCode.OK });
3568
+ return {
3569
+ content: `Avatar generated (${providerName}, ${avatarResult.size} bytes, ${avatarResult.format}).`,
3570
+ finishReason: "stop",
3571
+ provider: providerName,
3572
+ model: avatarResult.metadata?.model ?? providerName,
3573
+ usage: undefined,
3574
+ responseTime: Date.now() - startTime,
3575
+ avatar: avatarResult,
3576
+ };
3577
+ }
3351
3578
  /**
3352
3579
  * Generate with workflow engine integration
3353
3580
  * Returns both original and processed responses for AB testing
@@ -3357,7 +3584,7 @@ Current user's request: ${currentInput}`;
3357
3584
  logger.debug("[NeuroLink] Executing workflow generation", {
3358
3585
  workflowId: options.workflow,
3359
3586
  hasInlineConfig: !!options.workflowConfig,
3360
- prompt: options.input.text.substring(0, 100),
3587
+ prompt: (options.input?.text ?? "").substring(0, 100),
3361
3588
  startTime: workflowStartTime,
3362
3589
  });
3363
3590
  // Determine workflow configuration
@@ -3378,7 +3605,7 @@ Current user's request: ${currentInput}`;
3378
3605
  }
3379
3606
  // Execute workflow
3380
3607
  const workflowResult = await runWorkflow(workflowConfig, {
3381
- prompt: options.input.text,
3608
+ prompt: options.input?.text ?? "",
3382
3609
  conversationHistory: options.conversationMessages
3383
3610
  ?.filter((m) => m.role === "user" || m.role === "assistant")
3384
3611
  .map((m) => ({
@@ -3457,7 +3684,7 @@ Current user's request: ${currentInput}`;
3457
3684
  logger.debug("[NeuroLink] Executing workflow streaming (progressive)", {
3458
3685
  workflowId: options.workflow,
3459
3686
  hasInlineConfig: !!options.workflowConfig,
3460
- prompt: options.input.text.substring(0, 100),
3687
+ prompt: (options.input?.text ?? "").substring(0, 100),
3461
3688
  });
3462
3689
  // Determine workflow configuration
3463
3690
  let workflowConfig;
@@ -3477,7 +3704,7 @@ Current user's request: ${currentInput}`;
3477
3704
  const { runWorkflowWithStreaming } = await import("./workflow/core/workflowRunner.js");
3478
3705
  // Execute workflow with progressive streaming
3479
3706
  const workflowStream = runWorkflowWithStreaming(workflowConfig, {
3480
- prompt: options.input.text,
3707
+ prompt: options.input?.text ?? "",
3481
3708
  conversationHistory: options.conversationMessages
3482
3709
  ?.filter((m) => m.role === "user" || m.role === "assistant")
3483
3710
  .map((m) => ({
@@ -4532,10 +4759,22 @@ Current user's request: ${currentInput}`;
4532
4759
  availableTools: transformToolsForMCP(transformToolsToExpectedFormat(availableTools)),
4533
4760
  audio: result.audio,
4534
4761
  video: result.video,
4762
+ avatar: result.avatar,
4763
+ music: result.music,
4535
4764
  ppt: result.ppt,
4536
4765
  imageOutput: result.imageOutput,
4537
4766
  analytics: result.analytics,
4538
4767
  evaluation: result.evaluation,
4768
+ // Forward reasoning from provider so callers asking for `result.reasoning`
4769
+ // (DeepSeek `reasoning_content`, Anthropic thinking, Gemini thought parts,
4770
+ // OpenAI o1) actually receive it.
4771
+ reasoning: result.reasoning,
4772
+ reasoningTokens: result.reasoningTokens,
4773
+ // Propagate the native-emission flag so finalizeGenerateRequestResult
4774
+ // skips the public top-level `generation:end` emission when the
4775
+ // provider already emitted it itself (Vertex / Google AI Studio).
4776
+ _generationEndEmitted: result
4777
+ ._generationEndEmitted,
4539
4778
  };
4540
4779
  }
4541
4780
  /**
@@ -4807,9 +5046,19 @@ Current user's request: ${currentInput}`;
4807
5046
  evaluation: result.evaluation,
4808
5047
  audio: result.audio,
4809
5048
  video: result.video,
5049
+ avatar: result.avatar,
5050
+ music: result.music,
4810
5051
  ppt: result.ppt,
4811
5052
  // CRITICAL FIX: Include imageOutput for image generation models
4812
5053
  imageOutput: result.imageOutput,
5054
+ // Forward reasoning so callers asking for `result.reasoning`
5055
+ // (DeepSeek `reasoning_content`, Anthropic thinking, Gemini
5056
+ // thought parts, OpenAI o1) actually receive it.
5057
+ reasoning: result.reasoning,
5058
+ reasoningTokens: result.reasoningTokens,
5059
+ // Propagate native-emission flag — see attemptMCPGeneration comment.
5060
+ _generationEndEmitted: result
5061
+ ._generationEndEmitted,
4813
5062
  };
4814
5063
  }
4815
5064
  catch (error) {
@@ -5032,7 +5281,30 @@ Current user's request: ${currentInput}`;
5032
5281
  : [],
5033
5282
  optionKeys: Object.keys(options),
5034
5283
  });
5035
- return this.streamWithIterationFallback(options);
5284
+ // Defensive shallow clone of top-level options + the nested mutable
5285
+ // branches that downstream stages (prepareStreamOptions's memory
5286
+ // retrieval at `options.input.text`, applyStreamOrchestration's merge,
5287
+ // RAG/MCP tool injection, etc.) mutate. Cloning at the entry point
5288
+ // means callers can reuse a single options object across stream()
5289
+ // calls without accumulating mutations across them — the earlier
5290
+ // shallow rebind at the orchestration site only covered the
5291
+ // top-level keys and left `options.input` shared with the caller.
5292
+ options = cloneOptionsForCallIsolation(options);
5293
+ const startedAt = Date.now();
5294
+ try {
5295
+ return await this.streamWithIterationFallback(options);
5296
+ }
5297
+ catch (error) {
5298
+ // Mirror generate(): fire consumer onError for failures that
5299
+ // happened before the wrapped language-model middleware could
5300
+ // observe them (e.g. unknown provider, validation, factory
5301
+ // exceptions). The shared Symbol marker (lifecycleCallbacks.ts)
5302
+ // prevents double-fire when the AI-SDK lifecycle middleware
5303
+ // already handled the error. Awaited so async handlers fully
5304
+ // settle before stream() rethrows.
5305
+ await this.fireConsumerOnErrorIfNotFired(options, error, startedAt);
5306
+ throw error;
5307
+ }
5036
5308
  }
5037
5309
  /**
5038
5310
  * Curator P2-3 / Reviewer Finding #2: stream-fallback that also covers
@@ -5626,14 +5898,36 @@ Current user's request: ${currentInput}`;
5626
5898
  streamResult.usage = streamUsage;
5627
5899
  }
5628
5900
  if (!streamResult.analytics) {
5901
+ // CRITICAL: do NOT `await` a Promise-typed analytics here. Bedrock
5902
+ // resolves its analytics from the stream's `finally` block — it
5903
+ // only completes once the consumer has fully iterated the stream.
5904
+ // Awaiting it before returning the StreamResult deadlocks: caller
5905
+ // can't iterate (no stream yet), analytics can't resolve (no
5906
+ // iteration). Pass the Promise through to the consumer instead;
5907
+ // they (or the cost listener below) can await it after consumption.
5908
+ //
5909
+ // The outer StreamResult type (StreamResult.analytics in
5910
+ // src/lib/types/stream.ts) explicitly allows `AnalyticsData |
5911
+ // Promise<AnalyticsData>` — the cast widens the local
5912
+ // `processStreamResult` return type which only declares the
5913
+ // resolved shape.
5629
5914
  streamResult.analytics =
5630
- streamAnalytics instanceof Promise
5631
- ? await streamAnalytics
5632
- : streamAnalytics;
5633
- }
5634
- if (streamResult.analytics?.cost && streamResult.analytics.cost > 0) {
5635
- this._sessionCostUsd += streamResult.analytics.cost;
5636
- }
5915
+ streamAnalytics;
5916
+ }
5917
+ // The cost listener wants a resolved cost, but if the provider gave
5918
+ // us a Promise (Bedrock) we can't tax the stream's return path on it.
5919
+ // Defer cost accumulation: resolve in the background once the analytics
5920
+ // Promise settles. Synchronous analytics (most providers) still fire
5921
+ // immediately because Promise.resolve(non-promise) is sync-ish.
5922
+ Promise.resolve(streamResult.analytics)
5923
+ .then((analytics) => {
5924
+ if (analytics?.cost && analytics.cost > 0) {
5925
+ this._sessionCostUsd += analytics.cost;
5926
+ }
5927
+ })
5928
+ .catch(() => {
5929
+ /* analytics rejection is non-fatal — cost stays unupdated */
5930
+ });
5637
5931
  this.emitStreamEndEvents(streamResult);
5638
5932
  return this.createStreamResponse(streamResult, processedStream, {
5639
5933
  providerName,
@@ -5728,7 +6022,7 @@ Current user's request: ${currentInput}`;
5728
6022
  if (this.shouldReadMemory(options.memory, options.context?.userId) &&
5729
6023
  options.context?.userId) {
5730
6024
  try {
5731
- options.input.text = await this.retrieveMemory(options.input.text, options.context.userId, options.memory?.additionalUsers);
6025
+ options.input.text = await this.retrieveMemory(options.input.text ?? "", options.context.userId, options.memory?.additionalUsers);
5732
6026
  logger.debug("Memory retrieval successful");
5733
6027
  }
5734
6028
  catch (error) {
@@ -5752,7 +6046,6 @@ Current user's request: ${currentInput}`;
5752
6046
  // obvious to future readers, and the lint suppression is scoped
5753
6047
  // narrowly to the one statement that actually rebinds the param.
5754
6048
  const mergedOptions = { ...options, ...orchestratedOptions };
5755
- // eslint-disable-next-line no-param-reassign -- see NEW2/Issue 6 above
5756
6049
  options = mergedOptions;
5757
6050
  // Re-resolve model alias in case orchestration returned an alias
5758
6051
  if (orchestratedOptions.model) {
@@ -7,6 +7,16 @@ export declare class AmazonBedrockProvider extends BaseProvider {
7
7
  private bedrockClient;
8
8
  private conversationHistory;
9
9
  private region;
10
+ /**
11
+ * Parse the region segment from a Bedrock ARN.
12
+ * Returns null when the input is not an ARN.
13
+ *
14
+ * Supports all AWS partitions:
15
+ * - `arn:aws:bedrock:…` (commercial)
16
+ * - `arn:aws-cn:bedrock:…` (China)
17
+ * - `arn:aws-us-gov:bedrock:…` (GovCloud)
18
+ */
19
+ private static extractRegionFromArn;
10
20
  constructor(modelName?: string, neurolink?: NeuroLink, region?: string, credentials?: {
11
21
  accessKeyId?: string;
12
22
  secretAccessKey?: string;