@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,217 @@
1
+ import { JinaModels } from "../constants/enums.js";
2
+ import { BaseProvider } from "../core/baseProvider.js";
3
+ import { isNeuroLink } from "../neurolink.js";
4
+ import { createProxyFetch } from "../proxy/proxyFetch.js";
5
+ import { AuthenticationError, InvalidModelError, ProviderError, RateLimitError, } from "../types/index.js";
6
+ import { logger } from "../utils/logger.js";
7
+ import { createJinaConfig, getProviderModel, validateApiKey, } from "../utils/providerConfig.js";
8
+ const JINA_DEFAULT_BASE_URL = "https://api.jina.ai/v1";
9
+ const REQUEST_TIMEOUT_MS = 60_000;
10
+ const getJinaApiKey = () => validateApiKey(createJinaConfig());
11
+ const getDefaultJinaModel = () => getProviderModel("JINA_MODEL", JinaModels.JINA_EMBEDDINGS_V3);
12
+ /**
13
+ * Jina AI Provider — embeddings + reranking.
14
+ *
15
+ * Native API at api.jina.ai/v1. Chat / streaming / tool calling are not
16
+ * supported. Use `embed()` / `embedMany()` for embeddings, or call
17
+ * `rerank()` directly for retrieval reranking (Jina's strength).
18
+ *
19
+ * @see https://jina.ai/embeddings/
20
+ */
21
+ export class JinaProvider extends BaseProvider {
22
+ apiKey;
23
+ baseURL;
24
+ proxyFetch;
25
+ constructor(modelName, sdk, _region, credentials) {
26
+ const validatedNeurolink = isNeuroLink(sdk) ? sdk : undefined;
27
+ super(modelName, "jina", validatedNeurolink);
28
+ const overrideKey = credentials?.apiKey?.trim();
29
+ this.apiKey =
30
+ overrideKey && overrideKey.length > 0 ? overrideKey : getJinaApiKey();
31
+ this.baseURL =
32
+ credentials?.baseURL ??
33
+ process.env.JINA_BASE_URL ??
34
+ JINA_DEFAULT_BASE_URL;
35
+ this.proxyFetch = createProxyFetch();
36
+ logger.debug("Jina Provider initialized (embeddings + reranking)", {
37
+ modelName: this.modelName,
38
+ baseURL: this.baseURL,
39
+ });
40
+ }
41
+ getProviderName() {
42
+ return this.providerName;
43
+ }
44
+ getDefaultModel() {
45
+ return getDefaultJinaModel();
46
+ }
47
+ supportsTools() {
48
+ return false;
49
+ }
50
+ getDefaultEmbeddingModel() {
51
+ return getDefaultJinaModel();
52
+ }
53
+ getAISDKModel() {
54
+ throw new Error("Jina AI is an embeddings + reranking provider; chat completions are not available. Use `embed()` / `embedMany()` / `rerank()`.");
55
+ }
56
+ async executeStream(_options, _analysisSchema) {
57
+ throw new Error("Jina AI is an embeddings + reranking provider; streaming chat is not available.");
58
+ }
59
+ formatProviderError(error) {
60
+ const message = error instanceof Error
61
+ ? error.message
62
+ : typeof error === "string"
63
+ ? error
64
+ : "Unknown error";
65
+ if (message.includes("401") ||
66
+ message.toLowerCase().includes("unauthorized")) {
67
+ return new AuthenticationError("Invalid Jina AI API key. Get one at https://jina.ai/?sui=apikey", "jina");
68
+ }
69
+ if (message.includes("429") ||
70
+ message.toLowerCase().includes("rate limit")) {
71
+ return new RateLimitError("Jina AI rate limit exceeded. Back off and retry.", "jina");
72
+ }
73
+ if (message.includes("404") ||
74
+ message.toLowerCase().includes("model_not_found")) {
75
+ return new InvalidModelError(`Jina AI model '${this.modelName}' not found. See https://jina.ai/embeddings/`, "jina");
76
+ }
77
+ return new ProviderError(`Jina AI error: ${message}`, "jina");
78
+ }
79
+ async embed(text, modelName) {
80
+ const vectors = await this.callEmbeddings([text], modelName);
81
+ if (!vectors[0]) {
82
+ throw new Error("Jina AI returned no embedding for the provided text");
83
+ }
84
+ return vectors[0];
85
+ }
86
+ async embedMany(texts, modelName) {
87
+ if (texts.length === 0) {
88
+ return [];
89
+ }
90
+ return this.callEmbeddings(texts, modelName);
91
+ }
92
+ /**
93
+ * Rerank a list of documents against a query.
94
+ *
95
+ * Returns the documents sorted by relevance (highest first), with
96
+ * score and original index preserved so callers can map back.
97
+ *
98
+ * Note: not exposed on `BaseProvider` — accessed by casting to
99
+ * `JinaProvider` or via the dedicated rerank route on the public API
100
+ * (`POST /api/agent/rerank` in the server module, when added).
101
+ *
102
+ * Per-call credentials can be supplied via `options.credentials?.jina`,
103
+ * overriding the instance-level credentials for this request only.
104
+ */
105
+ async rerank(query, documents, options = {}) {
106
+ if (documents.length === 0) {
107
+ return [];
108
+ }
109
+ const model = options.model ?? JinaModels.JINA_RERANKER_V2_BASE_MULTILINGUAL;
110
+ // Resolve per-call credentials first, then fall back to instance-level.
111
+ const perCallCreds = options.credentials;
112
+ const effectiveApiKey = perCallCreds?.apiKey?.trim() || this.apiKey;
113
+ const effectiveBaseURL = perCallCreds?.baseURL || this.baseURL;
114
+ const controller = new AbortController();
115
+ const timeoutId = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);
116
+ let response;
117
+ try {
118
+ response = await this.proxyFetch(`${effectiveBaseURL}/rerank`, {
119
+ method: "POST",
120
+ headers: {
121
+ Authorization: `Bearer ${effectiveApiKey}`,
122
+ "Content-Type": "application/json",
123
+ },
124
+ body: JSON.stringify({
125
+ model,
126
+ query,
127
+ documents,
128
+ top_n: options.topN ?? documents.length,
129
+ }),
130
+ signal: controller.signal,
131
+ });
132
+ }
133
+ catch (err) {
134
+ if (err instanceof Error && err.name === "AbortError") {
135
+ throw this.formatProviderError(new Error(`Jina rerank request timed out after ${REQUEST_TIMEOUT_MS / 1000}s`));
136
+ }
137
+ throw this.formatProviderError(err);
138
+ }
139
+ finally {
140
+ clearTimeout(timeoutId);
141
+ }
142
+ if (!response.ok) {
143
+ const text = await response.text();
144
+ throw this.formatProviderError(new Error(`Jina rerank failed: ${response.status} — ${text}`));
145
+ }
146
+ const data = (await response.json());
147
+ return (data.results ?? []).map((r) => ({
148
+ index: r.index,
149
+ score: r.relevance_score,
150
+ document: documents[r.index] ?? r.document?.text ?? "",
151
+ }));
152
+ }
153
+ async callEmbeddings(inputs, modelName, credentials) {
154
+ const model = modelName ?? this.modelName;
155
+ // Resolve per-call credentials first, then fall back to instance-level.
156
+ const effectiveApiKey = credentials?.apiKey?.trim() || this.apiKey;
157
+ const effectiveBaseURL = credentials?.baseURL || this.baseURL;
158
+ const controller = new AbortController();
159
+ const timeoutId = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);
160
+ let response;
161
+ try {
162
+ response = await this.proxyFetch(`${effectiveBaseURL}/embeddings`, {
163
+ method: "POST",
164
+ headers: {
165
+ Authorization: `Bearer ${effectiveApiKey}`,
166
+ "Content-Type": "application/json",
167
+ },
168
+ body: JSON.stringify({
169
+ input: inputs,
170
+ model,
171
+ }),
172
+ signal: controller.signal,
173
+ });
174
+ }
175
+ catch (err) {
176
+ if (err instanceof Error && err.name === "AbortError") {
177
+ throw this.formatProviderError(new Error(`Jina embeddings request timed out after ${REQUEST_TIMEOUT_MS / 1000}s`));
178
+ }
179
+ throw this.formatProviderError(err);
180
+ }
181
+ finally {
182
+ clearTimeout(timeoutId);
183
+ }
184
+ if (!response.ok) {
185
+ const text = await response.text();
186
+ throw this.formatProviderError(new Error(`Jina embeddings failed: ${response.status} — ${text}`));
187
+ }
188
+ const data = (await response.json());
189
+ if (!data.data || data.data.length === 0) {
190
+ throw new Error("Jina embeddings response missing data");
191
+ }
192
+ // Validate that the response covers all requested inputs.
193
+ if (data.data.length !== inputs.length) {
194
+ throw new Error(`Jina embeddings response count mismatch: expected ${inputs.length}, got ${data.data.length}`);
195
+ }
196
+ // Sort by index and verify sequential coverage (0 … n-1).
197
+ const sorted = data.data.slice().sort((a, b) => a.index - b.index);
198
+ for (let i = 0; i < sorted.length; i++) {
199
+ if (sorted[i].index !== i) {
200
+ throw new Error(`Jina embeddings response has unexpected index ordering: position ${i} has index ${sorted[i].index}`);
201
+ }
202
+ }
203
+ return sorted.map((d) => d.embedding);
204
+ }
205
+ async validateConfiguration() {
206
+ return typeof this.apiKey === "string" && this.apiKey.trim().length > 0;
207
+ }
208
+ getConfiguration() {
209
+ return {
210
+ provider: this.providerName,
211
+ model: this.modelName,
212
+ defaultModel: getDefaultJinaModel(),
213
+ baseURL: this.baseURL,
214
+ };
215
+ }
216
+ }
217
+ export default JinaProvider;
@@ -3,46 +3,16 @@ import { stepCountIs, streamText } from "ai";
3
3
  import { BaseProvider } from "../core/baseProvider.js";
4
4
  import { DEFAULT_MAX_STEPS } from "../core/constants.js";
5
5
  import { streamAnalyticsCollector } from "../core/streamAnalytics.js";
6
- import { createProxyFetch, maskProxyUrl } from "../proxy/proxyFetch.js";
7
- import { tracers, ATTR, withClientSpan } from "../telemetry/index.js";
6
+ import { isNeuroLink } from "../neurolink.js";
7
+ import { createProxyFetch } from "../proxy/proxyFetch.js";
8
+ import { createLoggingFetch } from "../utils/loggingFetch.js";
9
+ import { tracers, ATTR, withClientStreamSpan } from "../telemetry/index.js";
10
+ import { NetworkError, ProviderError } from "../types/index.js";
8
11
  import { logger } from "../utils/logger.js";
9
12
  import { composeAbortSignals, createTimeoutController, TimeoutError, } from "../utils/timeout.js";
10
13
  import { emitToolEndFromStepFinish } from "../utils/toolEndEmitter.js";
11
14
  import { resolveToolChoice } from "../utils/toolChoice.js";
12
15
  import { toAnalyticsStreamResult } from "./providerTypeUtils.js";
13
- const makeLoggingFetch = (provider) => {
14
- const base = createProxyFetch();
15
- return (async (input, init) => {
16
- const url = typeof input === "string"
17
- ? input
18
- : input instanceof URL
19
- ? input.toString()
20
- : input.url;
21
- const reqSize = init?.body && typeof init.body === "string" ? init.body.length : 0;
22
- const response = await base(input, init);
23
- if (!response.ok) {
24
- // Mask any embedded credentials / signed query params before logging.
25
- // Fall back to "<redacted>" rather than the raw URL on a masking miss.
26
- const safeUrl = maskProxyUrl(url) ?? "<redacted>";
27
- // Don't log the raw upstream body — it can echo prompt fragments or
28
- // tool payloads. Log size + status + URL only. Opt into bodies via
29
- // NEUROLINK_DEBUG_HTTP=1 for local debugging.
30
- if (process.env.NEUROLINK_DEBUG_HTTP === "1") {
31
- const clone = response.clone();
32
- const body = await clone.text().catch(() => "<unreadable>");
33
- logger.warn(`[${provider}] upstream ${response.status}`, {
34
- url: safeUrl,
35
- body: body.slice(0, 800),
36
- reqSize,
37
- });
38
- }
39
- else {
40
- logger.warn(`[${provider}] upstream ${response.status} url=${safeUrl} reqSize=${reqSize}`);
41
- }
42
- }
43
- return response;
44
- });
45
- };
46
16
  const LLAMACPP_DEFAULT_BASE_URL = "http://localhost:8080/v1";
47
17
  const LLAMACPP_PLACEHOLDER_KEY = "llamacpp";
48
18
  const FALLBACK_MODEL = "loaded-model";
@@ -66,9 +36,7 @@ export class LlamaCppProvider extends BaseProvider {
66
36
  discoveredModel;
67
37
  llamaCppClient;
68
38
  constructor(modelName, sdk, _region, credentials) {
69
- const validatedNeurolink = sdk && typeof sdk === "object" && "getInMemoryServers" in sdk
70
- ? sdk
71
- : undefined;
39
+ const validatedNeurolink = isNeuroLink(sdk) ? sdk : undefined;
72
40
  super(modelName, "llamacpp", validatedNeurolink);
73
41
  this.requestedModelName = modelName;
74
42
  this.baseURL = credentials?.baseURL ?? getLlamaCppBaseURL();
@@ -82,7 +50,7 @@ export class LlamaCppProvider extends BaseProvider {
82
50
  this.llamaCppClient = createOpenAI({
83
51
  baseURL: this.baseURL,
84
52
  apiKey: this.apiKey,
85
- fetch: makeLoggingFetch("llamacpp"),
53
+ fetch: createLoggingFetch("llamacpp"),
86
54
  });
87
55
  logger.debug("llama.cpp Provider initialized", {
88
56
  modelName: this.modelName,
@@ -169,7 +137,7 @@ export class LlamaCppProvider extends BaseProvider {
169
137
  // Pass the caller's abort signal so user cancellation / per-request
170
138
  // timeouts are honored during the discovery probe.
171
139
  await this.getAISDKModel(options.abortSignal);
172
- return withClientSpan({
140
+ return withClientStreamSpan({
173
141
  name: "neurolink.provider.stream",
174
142
  tracer: tracers.provider,
175
143
  attributes: {
@@ -178,7 +146,7 @@ export class LlamaCppProvider extends BaseProvider {
178
146
  [ATTR.GEN_AI_OPERATION]: "stream",
179
147
  [ATTR.NL_STREAM_MODE]: true,
180
148
  },
181
- }, async () => this.executeStreamInner(options));
149
+ }, async () => this.executeStreamInner(options), (r) => r.stream, (r, wrapped) => ({ ...r, stream: wrapped }));
182
150
  }
183
151
  async executeStreamInner(options) {
184
152
  this.validateStreamOptions(options);
@@ -243,7 +211,7 @@ export class LlamaCppProvider extends BaseProvider {
243
211
  }
244
212
  formatProviderError(error) {
245
213
  if (error instanceof TimeoutError) {
246
- return new Error(`llama.cpp request timed out: ${error.message}`);
214
+ return new NetworkError(`Request timed out: ${error.message}`, "llamacpp");
247
215
  }
248
216
  const errorRecord = error;
249
217
  const message = typeof errorRecord?.message === "string"
@@ -255,13 +223,13 @@ export class LlamaCppProvider extends BaseProvider {
255
223
  message.includes("ECONNREFUSED") ||
256
224
  message.includes("Failed to fetch") ||
257
225
  message.includes("fetch failed")) {
258
- return new Error(`llama.cpp server not reachable at ${this.baseURL}. ` +
259
- "Start it with: ./llama-server -m model.gguf --port 8080");
226
+ return new NetworkError(`llama.cpp server not reachable at ${this.baseURL}. ` +
227
+ "Start it with: ./llama-server -m model.gguf --port 8080", "llamacpp");
260
228
  }
261
229
  if (message.includes("400")) {
262
- return new Error("llama.cpp rejected the request. Common cause: model doesn't support tools (start llama-server with --jinja for tool support).");
230
+ return new ProviderError("llama.cpp rejected the request. Common cause: model doesn't support tools (start llama-server with --jinja for tool support).", "llamacpp");
263
231
  }
264
- return new Error(`llama.cpp error: ${message}`);
232
+ return new ProviderError(`llama.cpp error: ${message}`, "llamacpp");
265
233
  }
266
234
  async validateConfiguration() {
267
235
  // Retry up to 3x with 500ms backoff. llama-server can be briefly unresponsive
@@ -3,47 +3,16 @@ import { stepCountIs, streamText } from "ai";
3
3
  import { BaseProvider } from "../core/baseProvider.js";
4
4
  import { DEFAULT_MAX_STEPS } from "../core/constants.js";
5
5
  import { streamAnalyticsCollector } from "../core/streamAnalytics.js";
6
- import { createProxyFetch, maskProxyUrl } from "../proxy/proxyFetch.js";
7
- import { tracers, ATTR, withClientSpan } from "../telemetry/index.js";
6
+ import { isNeuroLink } from "../neurolink.js";
7
+ import { createProxyFetch } from "../proxy/proxyFetch.js";
8
+ import { createLoggingFetch } from "../utils/loggingFetch.js";
9
+ import { tracers, ATTR, withClientStreamSpan } from "../telemetry/index.js";
10
+ import { InvalidModelError, NetworkError, ProviderError, } from "../types/index.js";
8
11
  import { logger } from "../utils/logger.js";
9
12
  import { composeAbortSignals, createTimeoutController, TimeoutError, } from "../utils/timeout.js";
10
13
  import { emitToolEndFromStepFinish } from "../utils/toolEndEmitter.js";
11
14
  import { resolveToolChoice } from "../utils/toolChoice.js";
12
15
  import { toAnalyticsStreamResult } from "./providerTypeUtils.js";
13
- const makeLoggingFetch = (provider) => {
14
- const base = createProxyFetch();
15
- return (async (input, init) => {
16
- const url = typeof input === "string"
17
- ? input
18
- : input instanceof URL
19
- ? input.toString()
20
- : input.url;
21
- const reqSize = init?.body && typeof init.body === "string" ? init.body.length : 0;
22
- const response = await base(input, init);
23
- if (!response.ok) {
24
- // Mask any embedded credentials / signed query params before logging.
25
- // Fall back to "<redacted>" rather than the raw URL on a masking miss —
26
- // logging the unsanitized form would defeat the redaction.
27
- const safeUrl = maskProxyUrl(url) ?? "<redacted>";
28
- // Don't log the raw upstream body or request payload — they can contain
29
- // user prompts, tool arguments, and other sensitive data. Log size +
30
- // status + URL only. Set NEUROLINK_DEBUG_HTTP=1 to opt into raw bodies.
31
- if (process.env.NEUROLINK_DEBUG_HTTP === "1") {
32
- const clone = response.clone();
33
- const body = await clone.text().catch(() => "<unreadable>");
34
- logger.warn(`[${provider}] upstream ${response.status}`, {
35
- url: safeUrl,
36
- body: body.slice(0, 400),
37
- reqSize,
38
- });
39
- }
40
- else {
41
- logger.warn(`[${provider}] upstream ${response.status} url=${safeUrl} reqSize=${reqSize}`);
42
- }
43
- }
44
- return response;
45
- });
46
- };
47
16
  const LM_STUDIO_DEFAULT_BASE_URL = "http://localhost:1234/v1";
48
17
  const LM_STUDIO_PLACEHOLDER_KEY = "lm-studio";
49
18
  const FALLBACK_MODEL = "local-model";
@@ -67,9 +36,7 @@ export class LMStudioProvider extends BaseProvider {
67
36
  discoveredModel;
68
37
  lmstudioClient;
69
38
  constructor(modelName, sdk, _region, credentials) {
70
- const validatedNeurolink = sdk && typeof sdk === "object" && "getInMemoryServers" in sdk
71
- ? sdk
72
- : undefined;
39
+ const validatedNeurolink = isNeuroLink(sdk) ? sdk : undefined;
73
40
  super(modelName, "lm-studio", validatedNeurolink);
74
41
  this.requestedModelName = modelName;
75
42
  this.baseURL = credentials?.baseURL ?? getLmStudioBaseURL();
@@ -83,7 +50,7 @@ export class LMStudioProvider extends BaseProvider {
83
50
  this.lmstudioClient = createOpenAI({
84
51
  baseURL: this.baseURL,
85
52
  apiKey: this.apiKey,
86
- fetch: makeLoggingFetch("lm-studio"),
53
+ fetch: createLoggingFetch("lm-studio"),
87
54
  });
88
55
  logger.debug("LM Studio Provider initialized", {
89
56
  modelName: this.modelName,
@@ -173,7 +140,7 @@ export class LMStudioProvider extends BaseProvider {
173
140
  // Pass the caller's abort signal so user cancellation / per-request
174
141
  // timeouts are honored during the discovery probe (not just after it).
175
142
  await this.getAISDKModel(options.abortSignal);
176
- return withClientSpan({
143
+ return withClientStreamSpan({
177
144
  name: "neurolink.provider.stream",
178
145
  tracer: tracers.provider,
179
146
  attributes: {
@@ -182,7 +149,7 @@ export class LMStudioProvider extends BaseProvider {
182
149
  [ATTR.GEN_AI_OPERATION]: "stream",
183
150
  [ATTR.NL_STREAM_MODE]: true,
184
151
  },
185
- }, async () => this.executeStreamInner(options));
152
+ }, async () => this.executeStreamInner(options), (r) => r.stream, (r, wrapped) => ({ ...r, stream: wrapped }));
186
153
  }
187
154
  async executeStreamInner(options) {
188
155
  this.validateStreamOptions(options);
@@ -249,7 +216,7 @@ export class LMStudioProvider extends BaseProvider {
249
216
  }
250
217
  formatProviderError(error) {
251
218
  if (error instanceof TimeoutError) {
252
- return new Error(`LM Studio request timed out: ${error.message}`);
219
+ return new NetworkError(`Request timed out: ${error.message}`, "lm-studio");
253
220
  }
254
221
  const errorRecord = error;
255
222
  const message = typeof errorRecord?.message === "string"
@@ -261,13 +228,13 @@ export class LMStudioProvider extends BaseProvider {
261
228
  message.includes("ECONNREFUSED") ||
262
229
  message.includes("Failed to fetch") ||
263
230
  message.includes("fetch failed")) {
264
- return new Error(`LM Studio server not reachable at ${this.baseURL}. ` +
265
- `Open the LM Studio app, load a model, and click "Start Server".`);
231
+ return new NetworkError(`LM Studio server not reachable at ${this.baseURL}. ` +
232
+ `Open the LM Studio app, load a model, and click "Start Server".`, "lm-studio");
266
233
  }
267
234
  if (message.includes("model_not_found") || message.includes("404")) {
268
- return new Error(`LM Studio model '${this.modelName}' is not loaded. Load it in the LM Studio app first.`);
235
+ return new InvalidModelError(`LM Studio model '${this.modelName}' is not loaded. Load it in the LM Studio app first.`, "lm-studio");
269
236
  }
270
- return new Error(`LM Studio error: ${message}`);
237
+ return new ProviderError(`LM Studio error: ${message}`, "lm-studio");
271
238
  }
272
239
  async validateConfiguration() {
273
240
  try {
@@ -3,7 +3,9 @@ import { stepCountIs, streamText } from "ai";
3
3
  import { BaseProvider } from "../core/baseProvider.js";
4
4
  import { DEFAULT_MAX_STEPS } from "../core/constants.js";
5
5
  import { streamAnalyticsCollector } from "../core/streamAnalytics.js";
6
+ import { isNeuroLink } from "../neurolink.js";
6
7
  import { createProxyFetch } from "../proxy/proxyFetch.js";
8
+ import { AuthenticationError, NetworkError, ProviderError, RateLimitError, } from "../types/index.js";
7
9
  import { emitToolEndFromStepFinish } from "../utils/toolEndEmitter.js";
8
10
  import { logger } from "../utils/logger.js";
9
11
  import { createMistralConfig, getProviderModel, validateApiKey, } from "../utils/providerConfig.js";
@@ -26,9 +28,7 @@ export class MistralProvider extends BaseProvider {
26
28
  model;
27
29
  constructor(modelName, sdk, _region, credentials) {
28
30
  // Type guard for NeuroLink parameter validation
29
- const validatedNeurolink = sdk && typeof sdk === "object" && "getInMemoryServers" in sdk
30
- ? sdk
31
- : undefined;
31
+ const validatedNeurolink = isNeuroLink(sdk) ? sdk : undefined;
32
32
  super(modelName, "mistral", validatedNeurolink);
33
33
  // Initialize Mistral model with API key validation and proxy support
34
34
  const apiKey = credentials?.apiKey ?? getMistralApiKey();
@@ -131,7 +131,7 @@ export class MistralProvider extends BaseProvider {
131
131
  }
132
132
  formatProviderError(error) {
133
133
  if (error instanceof TimeoutError) {
134
- return new Error(`Mistral request timed out: ${error.message}`);
134
+ return new NetworkError(`Request timed out: ${error.message}`, "mistral");
135
135
  }
136
136
  const errorRecord = error;
137
137
  const message = typeof errorRecord?.message === "string"
@@ -139,12 +139,12 @@ export class MistralProvider extends BaseProvider {
139
139
  : "Unknown error";
140
140
  if (message.includes("API_KEY_INVALID") ||
141
141
  message.includes("Invalid API key")) {
142
- return new Error("Invalid Mistral API key. Please check your MISTRAL_API_KEY environment variable.");
142
+ return new AuthenticationError("Invalid Mistral API key. Please check your MISTRAL_API_KEY environment variable.", "mistral");
143
143
  }
144
144
  if (message.includes("Rate limit exceeded")) {
145
- return new Error("Mistral rate limit exceeded");
145
+ return new RateLimitError("Mistral rate limit exceeded", "mistral");
146
146
  }
147
- return new Error(`Mistral error: ${message}`);
147
+ return new ProviderError(`Mistral error: ${message}`, "mistral");
148
148
  }
149
149
  /**
150
150
  * Validate provider configuration