@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,174 @@
1
+ import { createOpenAI } from "@ai-sdk/openai";
2
+ import { stepCountIs, streamText } from "ai";
3
+ import { CloudflareModels } from "../constants/enums.js";
4
+ import { BaseProvider } from "../core/baseProvider.js";
5
+ import { DEFAULT_MAX_STEPS } from "../core/constants.js";
6
+ import { streamAnalyticsCollector } from "../core/streamAnalytics.js";
7
+ import { isNeuroLink } from "../neurolink.js";
8
+ import { createLoggingFetch } from "../utils/loggingFetch.js";
9
+ import { tracers, ATTR, withClientStreamSpan } from "../telemetry/index.js";
10
+ import { AuthenticationError, InvalidModelError, NetworkError, ProviderError, RateLimitError, } from "../types/index.js";
11
+ import { logger } from "../utils/logger.js";
12
+ import { createCloudflareConfig, getProviderModel, validateApiKey, } from "../utils/providerConfig.js";
13
+ import { composeAbortSignals, createTimeoutController, TimeoutError, } from "../utils/timeout.js";
14
+ import { emitToolEndFromStepFinish } from "../utils/toolEndEmitter.js";
15
+ import { resolveToolChoice } from "../utils/toolChoice.js";
16
+ import { toAnalyticsStreamResult } from "./providerTypeUtils.js";
17
+ /**
18
+ * Cloudflare Workers AI exposes an OpenAI-compatible endpoint scoped per
19
+ * account: `https://api.cloudflare.com/client/v4/accounts/{ACCOUNT_ID}/ai/v1`.
20
+ * The account id is required — without it the URL would 404.
21
+ */
22
+ const buildCloudflareBaseURL = (accountId) => `https://api.cloudflare.com/client/v4/accounts/${accountId}/ai/v1`;
23
+ const getCloudflareApiKey = () => validateApiKey(createCloudflareConfig());
24
+ const getDefaultCloudflareModel = () => getProviderModel("CLOUDFLARE_MODEL", CloudflareModels.LLAMA_3_3_70B_FAST);
25
+ /**
26
+ * Cloudflare Workers AI Provider
27
+ *
28
+ * Edge-served open models (Llama / Mistral / Qwen / Gemma) at
29
+ * `https://api.cloudflare.com/client/v4/accounts/{accountId}/ai/v1`
30
+ * (OpenAI-compatible). Cheapest tier for high-volume usage.
31
+ *
32
+ * Required env: `CLOUDFLARE_API_KEY` + `CLOUDFLARE_ACCOUNT_ID`.
33
+ *
34
+ * @see https://developers.cloudflare.com/workers-ai/configuration/open-ai-compatibility/
35
+ */
36
+ export class CloudflareProvider extends BaseProvider {
37
+ model;
38
+ apiKey;
39
+ baseURL;
40
+ constructor(modelName, sdk, _region, credentials) {
41
+ const validatedNeurolink = isNeuroLink(sdk) ? sdk : undefined;
42
+ super(modelName, "cloudflare", validatedNeurolink);
43
+ const overrideApiKey = credentials?.apiKey?.trim();
44
+ this.apiKey =
45
+ overrideApiKey && overrideApiKey.length > 0
46
+ ? overrideApiKey
47
+ : getCloudflareApiKey();
48
+ const accountId = (credentials?.accountId ??
49
+ process.env.CLOUDFLARE_ACCOUNT_ID ??
50
+ "").trim();
51
+ if (!accountId) {
52
+ throw new Error("CLOUDFLARE_ACCOUNT_ID is required (or pass credentials.cloudflare.accountId). Get the account id from https://dash.cloudflare.com/");
53
+ }
54
+ this.baseURL = credentials?.baseURL ?? buildCloudflareBaseURL(accountId);
55
+ const cloudflare = createOpenAI({
56
+ apiKey: this.apiKey,
57
+ baseURL: this.baseURL,
58
+ fetch: createLoggingFetch("cloudflare"),
59
+ });
60
+ this.model = cloudflare.chat(this.modelName);
61
+ logger.debug("Cloudflare Workers AI Provider initialized", {
62
+ modelName: this.modelName,
63
+ providerName: this.providerName,
64
+ baseURL: this.baseURL,
65
+ });
66
+ }
67
+ async executeStream(options, _analysisSchema) {
68
+ return withClientStreamSpan({
69
+ name: "neurolink.provider.stream",
70
+ tracer: tracers.provider,
71
+ attributes: {
72
+ [ATTR.GEN_AI_SYSTEM]: "cloudflare",
73
+ [ATTR.GEN_AI_MODEL]: this.modelName,
74
+ [ATTR.GEN_AI_OPERATION]: "stream",
75
+ [ATTR.NL_STREAM_MODE]: true,
76
+ },
77
+ }, async () => this.executeStreamInner(options), (r) => r.stream, (r, wrapped) => ({ ...r, stream: wrapped }));
78
+ }
79
+ async executeStreamInner(options) {
80
+ this.validateStreamOptions(options);
81
+ const startTime = Date.now();
82
+ const timeout = this.getTimeout(options);
83
+ const timeoutController = createTimeoutController(timeout, this.providerName, "stream");
84
+ try {
85
+ const shouldUseTools = !options.disableTools && this.supportsTools();
86
+ const tools = shouldUseTools
87
+ ? options.tools || (await this.getAllTools())
88
+ : {};
89
+ const messages = await this.buildMessagesForStream(options);
90
+ const model = await this.getAISDKModelWithMiddleware(options);
91
+ const result = await streamText({
92
+ model,
93
+ messages,
94
+ temperature: options.temperature,
95
+ maxOutputTokens: options.maxTokens,
96
+ tools,
97
+ stopWhen: stepCountIs(options.maxSteps || DEFAULT_MAX_STEPS),
98
+ toolChoice: resolveToolChoice(options, tools, shouldUseTools),
99
+ abortSignal: composeAbortSignals(options.abortSignal, timeoutController?.controller.signal),
100
+ experimental_telemetry: this.telemetryHandler.getTelemetryConfig(options),
101
+ experimental_repairToolCall: this.getToolCallRepairFn(options),
102
+ onStepFinish: ({ toolCalls, toolResults }) => {
103
+ emitToolEndFromStepFinish(this.neurolink?.getEventEmitter(), toolResults);
104
+ this.handleToolExecutionStorage(toolCalls, toolResults, options, new Date()).catch((error) => {
105
+ logger.warn("[CloudflareProvider] Failed to store tool executions", {
106
+ provider: this.providerName,
107
+ error: error instanceof Error ? error.message : String(error),
108
+ });
109
+ });
110
+ },
111
+ });
112
+ timeoutController?.cleanup();
113
+ const transformedStream = this.createTextStream(result);
114
+ const analyticsPromise = streamAnalyticsCollector.createAnalytics(this.providerName, this.modelName, toAnalyticsStreamResult(result), Date.now() - startTime, {
115
+ requestId: `cloudflare-stream-${Date.now()}`,
116
+ streamingMode: true,
117
+ });
118
+ return {
119
+ stream: transformedStream,
120
+ provider: this.providerName,
121
+ model: this.modelName,
122
+ analytics: analyticsPromise,
123
+ metadata: { startTime, streamId: `cloudflare-${Date.now()}` },
124
+ };
125
+ }
126
+ catch (error) {
127
+ timeoutController?.cleanup();
128
+ throw this.handleProviderError(error);
129
+ }
130
+ }
131
+ getProviderName() {
132
+ return this.providerName;
133
+ }
134
+ getDefaultModel() {
135
+ return getDefaultCloudflareModel();
136
+ }
137
+ getAISDKModel() {
138
+ return this.model;
139
+ }
140
+ formatProviderError(error) {
141
+ if (error instanceof TimeoutError) {
142
+ return new NetworkError(`Request timed out: ${error.message}`, "cloudflare");
143
+ }
144
+ const errorRecord = error;
145
+ const message = typeof errorRecord?.message === "string"
146
+ ? errorRecord.message
147
+ : "Unknown error";
148
+ if (message.includes("Invalid API key") ||
149
+ message.includes("Authentication") ||
150
+ message.includes("401")) {
151
+ return new AuthenticationError("Invalid Cloudflare API key. Use a token with Workers AI Read+Write scope. Get one at https://dash.cloudflare.com/profile/api-tokens", "cloudflare");
152
+ }
153
+ if (message.includes("rate limit") || message.includes("429")) {
154
+ return new RateLimitError("Cloudflare Workers AI rate limit exceeded. Free-tier neurons reset daily.", "cloudflare");
155
+ }
156
+ if (message.includes("model_not_found") || message.includes("404")) {
157
+ return new InvalidModelError(`Cloudflare model '${this.modelName}' not found. Browse https://developers.cloudflare.com/workers-ai/models/`, "cloudflare");
158
+ }
159
+ return new ProviderError(`Cloudflare Workers AI error: ${message}`, "cloudflare");
160
+ }
161
+ async validateConfiguration() {
162
+ return typeof this.apiKey === "string" && this.apiKey.trim().length > 0;
163
+ }
164
+ getConfiguration() {
165
+ return {
166
+ provider: this.providerName,
167
+ model: this.modelName,
168
+ defaultModel: getDefaultCloudflareModel(),
169
+ baseURL: this.baseURL,
170
+ };
171
+ }
172
+ }
173
+ export default CloudflareProvider;
174
+ //# sourceMappingURL=cloudflare.js.map
@@ -0,0 +1,52 @@
1
+ import { type LanguageModel } from "ai";
2
+ import type { AIProviderName } from "../constants/enums.js";
3
+ import { BaseProvider } from "../core/baseProvider.js";
4
+ import type { NeurolinkCredentials, StreamOptions, StreamResult, ValidationSchema } from "../types/index.js";
5
+ /**
6
+ * Cohere Provider
7
+ *
8
+ * Routes Command R / Command R+ chat completions through Cohere's OpenAI-
9
+ * compatible endpoint. Embed v3 and Rerank v3 are top-tier for RAG but are
10
+ * accessed via the Cohere native SDK / dedicated embedding routes (out of
11
+ * scope for the LLM provider).
12
+ *
13
+ * @see https://docs.cohere.com/docs/compatibility-api
14
+ */
15
+ export declare class CohereProvider extends BaseProvider {
16
+ private model;
17
+ private apiKey;
18
+ private baseURL;
19
+ constructor(modelName?: string, sdk?: unknown, _region?: string, credentials?: NeurolinkCredentials["cohere"]);
20
+ protected executeStream(options: StreamOptions, _analysisSchema?: ValidationSchema): Promise<StreamResult>;
21
+ private executeStreamInner;
22
+ protected getProviderName(): AIProviderName;
23
+ protected getDefaultModel(): string;
24
+ protected getAISDKModel(): LanguageModel;
25
+ protected formatProviderError(error: unknown): Error;
26
+ validateConfiguration(): Promise<boolean>;
27
+ getConfiguration(): {
28
+ provider: AIProviderName;
29
+ model: string;
30
+ defaultModel: string;
31
+ baseURL: string;
32
+ };
33
+ /**
34
+ * Default embedding model for Cohere.
35
+ */
36
+ protected getDefaultEmbeddingModel(): string;
37
+ /**
38
+ * Generate an embedding for a single text via Cohere's native /v2/embed
39
+ * endpoint. Returns the float[] embedding vector.
40
+ *
41
+ * The shared OpenAI-compatible /compatibility/v1 path is chat-only; embed
42
+ * lives on the native API (POST /v2/embed). Documented at
43
+ * https://docs.cohere.com/reference/embed.
44
+ */
45
+ embed(text: string, modelName?: string): Promise<number[]>;
46
+ /**
47
+ * Batch embedding via Cohere's native /v2/embed endpoint. Cohere caps at
48
+ * 96 inputs per request; larger batches are chunked.
49
+ */
50
+ embedMany(texts: string[], modelName?: string): Promise<number[][]>;
51
+ }
52
+ export default CohereProvider;
@@ -0,0 +1,253 @@
1
+ import { createOpenAI } from "@ai-sdk/openai";
2
+ import { stepCountIs, streamText } from "ai";
3
+ import { CohereModels } from "../constants/enums.js";
4
+ import { BaseProvider } from "../core/baseProvider.js";
5
+ import { DEFAULT_MAX_STEPS } from "../core/constants.js";
6
+ import { streamAnalyticsCollector } from "../core/streamAnalytics.js";
7
+ import { isNeuroLink } from "../neurolink.js";
8
+ import { createLoggingFetch } from "../utils/loggingFetch.js";
9
+ import { tracers, ATTR, withClientStreamSpan } from "../telemetry/index.js";
10
+ import { AuthenticationError, InvalidModelError, NetworkError, ProviderError, RateLimitError, } from "../types/index.js";
11
+ import { logger } from "../utils/logger.js";
12
+ import { createCohereConfig, getProviderModel, validateApiKey, } from "../utils/providerConfig.js";
13
+ import { composeAbortSignals, createTimeoutController, TimeoutError, } from "../utils/timeout.js";
14
+ import { emitToolEndFromStepFinish } from "../utils/toolEndEmitter.js";
15
+ import { resolveToolChoice } from "../utils/toolChoice.js";
16
+ import { toAnalyticsStreamResult } from "./providerTypeUtils.js";
17
+ /**
18
+ * Cohere uses an OpenAI-compatible endpoint at /compatibility/v1 that
19
+ * accepts the same chat-completions shape. Embeddings + Rerank live on
20
+ * the native API and are not exposed through this LLM provider class
21
+ * (use the Cohere SDK directly or the embed/rerank routes when added).
22
+ */
23
+ const COHERE_DEFAULT_BASE_URL = "https://api.cohere.com/compatibility/v1";
24
+ const getCohereApiKey = () => validateApiKey(createCohereConfig());
25
+ const getDefaultCohereModel = () => getProviderModel("COHERE_MODEL", CohereModels.COMMAND_R_PLUS);
26
+ /**
27
+ * Cohere Provider
28
+ *
29
+ * Routes Command R / Command R+ chat completions through Cohere's OpenAI-
30
+ * compatible endpoint. Embed v3 and Rerank v3 are top-tier for RAG but are
31
+ * accessed via the Cohere native SDK / dedicated embedding routes (out of
32
+ * scope for the LLM provider).
33
+ *
34
+ * @see https://docs.cohere.com/docs/compatibility-api
35
+ */
36
+ export class CohereProvider extends BaseProvider {
37
+ model;
38
+ apiKey;
39
+ baseURL;
40
+ constructor(modelName, sdk, _region, credentials) {
41
+ const validatedNeurolink = isNeuroLink(sdk) ? sdk : undefined;
42
+ super(modelName, "cohere", validatedNeurolink);
43
+ const overrideApiKey = credentials?.apiKey?.trim();
44
+ this.apiKey =
45
+ overrideApiKey && overrideApiKey.length > 0
46
+ ? overrideApiKey
47
+ : getCohereApiKey();
48
+ this.baseURL =
49
+ credentials?.baseURL ??
50
+ process.env.COHERE_BASE_URL ??
51
+ COHERE_DEFAULT_BASE_URL;
52
+ const cohere = createOpenAI({
53
+ apiKey: this.apiKey,
54
+ baseURL: this.baseURL,
55
+ fetch: createLoggingFetch("cohere"),
56
+ });
57
+ this.model = cohere.chat(this.modelName);
58
+ logger.debug("Cohere Provider initialized", {
59
+ modelName: this.modelName,
60
+ providerName: this.providerName,
61
+ baseURL: this.baseURL,
62
+ });
63
+ }
64
+ async executeStream(options, _analysisSchema) {
65
+ // withClientStreamSpan: keeps the span open until the consumer reaches
66
+ // end-of-stream / error, so the recorded duration reflects the actual
67
+ // stream lifetime instead of just setup.
68
+ return withClientStreamSpan({
69
+ name: "neurolink.provider.stream",
70
+ tracer: tracers.provider,
71
+ attributes: {
72
+ [ATTR.GEN_AI_SYSTEM]: "cohere",
73
+ [ATTR.GEN_AI_MODEL]: this.modelName,
74
+ [ATTR.GEN_AI_OPERATION]: "stream",
75
+ [ATTR.NL_STREAM_MODE]: true,
76
+ },
77
+ }, async () => this.executeStreamInner(options), (r) => r.stream, (r, wrapped) => ({ ...r, stream: wrapped }));
78
+ }
79
+ async executeStreamInner(options) {
80
+ this.validateStreamOptions(options);
81
+ // Resolve per-call credentials first, then fall back to instance-level.
82
+ const perCallCreds = options.credentials?.cohere;
83
+ const effectiveApiKey = perCallCreds?.apiKey?.trim() || this.apiKey;
84
+ const effectiveBaseURL = perCallCreds?.baseURL || this.baseURL;
85
+ const startTime = Date.now();
86
+ const timeout = this.getTimeout(options);
87
+ const timeoutController = createTimeoutController(timeout, this.providerName, "stream");
88
+ try {
89
+ const shouldUseTools = !options.disableTools && this.supportsTools();
90
+ const tools = shouldUseTools
91
+ ? options.tools || (await this.getAllTools())
92
+ : {};
93
+ const messages = await this.buildMessagesForStream(options);
94
+ // When per-call credentials differ from instance, build a fresh client.
95
+ const hasDifferentCreds = effectiveApiKey !== this.apiKey || effectiveBaseURL !== this.baseURL;
96
+ const model = hasDifferentCreds
97
+ ? createOpenAI({
98
+ apiKey: effectiveApiKey,
99
+ baseURL: effectiveBaseURL,
100
+ fetch: createLoggingFetch("cohere"),
101
+ }).chat(this.modelName)
102
+ : await this.getAISDKModelWithMiddleware(options);
103
+ const result = await streamText({
104
+ model,
105
+ messages,
106
+ temperature: options.temperature,
107
+ maxOutputTokens: options.maxTokens,
108
+ tools,
109
+ stopWhen: stepCountIs(options.maxSteps || DEFAULT_MAX_STEPS),
110
+ toolChoice: resolveToolChoice(options, tools, shouldUseTools),
111
+ abortSignal: composeAbortSignals(options.abortSignal, timeoutController?.controller.signal),
112
+ experimental_telemetry: this.telemetryHandler.getTelemetryConfig(options),
113
+ experimental_repairToolCall: this.getToolCallRepairFn(options),
114
+ onStepFinish: ({ toolCalls, toolResults }) => {
115
+ emitToolEndFromStepFinish(this.neurolink?.getEventEmitter(), toolResults);
116
+ this.handleToolExecutionStorage(toolCalls, toolResults, options, new Date()).catch((error) => {
117
+ logger.warn("[CohereProvider] Failed to store tool executions", {
118
+ provider: this.providerName,
119
+ error: error instanceof Error ? error.message : String(error),
120
+ });
121
+ });
122
+ },
123
+ });
124
+ timeoutController?.cleanup();
125
+ const transformedStream = this.createTextStream(result);
126
+ const analyticsPromise = streamAnalyticsCollector.createAnalytics(this.providerName, this.modelName, toAnalyticsStreamResult(result), Date.now() - startTime, {
127
+ requestId: `cohere-stream-${Date.now()}`,
128
+ streamingMode: true,
129
+ });
130
+ return {
131
+ stream: transformedStream,
132
+ provider: this.providerName,
133
+ model: this.modelName,
134
+ analytics: analyticsPromise,
135
+ metadata: { startTime, streamId: `cohere-${Date.now()}` },
136
+ };
137
+ }
138
+ catch (error) {
139
+ timeoutController?.cleanup();
140
+ throw this.handleProviderError(error);
141
+ }
142
+ }
143
+ getProviderName() {
144
+ return this.providerName;
145
+ }
146
+ getDefaultModel() {
147
+ return getDefaultCohereModel();
148
+ }
149
+ getAISDKModel() {
150
+ return this.model;
151
+ }
152
+ formatProviderError(error) {
153
+ if (error instanceof TimeoutError) {
154
+ return new NetworkError(`Request timed out: ${error.message}`, "cohere");
155
+ }
156
+ const errorRecord = error;
157
+ const message = typeof errorRecord?.message === "string"
158
+ ? errorRecord.message
159
+ : "Unknown error";
160
+ if (message.includes("invalid api token") ||
161
+ message.includes("Authentication") ||
162
+ message.includes("401") ||
163
+ message.includes("invalid_api_token")) {
164
+ return new AuthenticationError("Invalid Cohere API key. Check COHERE_API_KEY. Get one at https://dashboard.cohere.com/api-keys", "cohere");
165
+ }
166
+ if (message.includes("rate limit") || message.includes("429")) {
167
+ return new RateLimitError("Cohere rate limit exceeded. Back off and retry.", "cohere");
168
+ }
169
+ if (message.includes("model_not_found") || message.includes("404")) {
170
+ return new InvalidModelError(`Cohere model '${this.modelName}' not found. Use command-r, command-r-plus, or command-r7b-12-2024.`, "cohere");
171
+ }
172
+ if (message.includes("trial limit") || message.includes("trial_limit")) {
173
+ return new ProviderError("Cohere trial usage limit exceeded. Upgrade at https://dashboard.cohere.com/billing.", "cohere");
174
+ }
175
+ return new ProviderError(`Cohere error: ${message}`, "cohere");
176
+ }
177
+ async validateConfiguration() {
178
+ return typeof this.apiKey === "string" && this.apiKey.trim().length > 0;
179
+ }
180
+ getConfiguration() {
181
+ return {
182
+ provider: this.providerName,
183
+ model: this.modelName,
184
+ defaultModel: getDefaultCohereModel(),
185
+ baseURL: this.baseURL,
186
+ };
187
+ }
188
+ /**
189
+ * Default embedding model for Cohere.
190
+ */
191
+ getDefaultEmbeddingModel() {
192
+ return CohereModels.EMBED_ENGLISH_V3;
193
+ }
194
+ /**
195
+ * Generate an embedding for a single text via Cohere's native /v2/embed
196
+ * endpoint. Returns the float[] embedding vector.
197
+ *
198
+ * The shared OpenAI-compatible /compatibility/v1 path is chat-only; embed
199
+ * lives on the native API (POST /v2/embed). Documented at
200
+ * https://docs.cohere.com/reference/embed.
201
+ */
202
+ async embed(text, modelName) {
203
+ const vectors = await this.embedMany([text], modelName);
204
+ if (!vectors[0]) {
205
+ throw new ProviderError("Cohere /v2/embed returned no embeddings.", "cohere");
206
+ }
207
+ return vectors[0];
208
+ }
209
+ /**
210
+ * Batch embedding via Cohere's native /v2/embed endpoint. Cohere caps at
211
+ * 96 inputs per request; larger batches are chunked.
212
+ */
213
+ async embedMany(texts, modelName) {
214
+ if (texts.length === 0) {
215
+ return [];
216
+ }
217
+ const model = modelName ?? this.getDefaultEmbeddingModel();
218
+ const baseUrl = this.baseURL.replace(/\/compatibility\/v\d+\/?$/, "");
219
+ const url = `${baseUrl}/v2/embed`;
220
+ const BATCH_SIZE = 96;
221
+ const results = [];
222
+ for (let i = 0; i < texts.length; i += BATCH_SIZE) {
223
+ const batch = texts.slice(i, i + BATCH_SIZE);
224
+ const response = await fetch(url, {
225
+ method: "POST",
226
+ headers: {
227
+ Authorization: `Bearer ${this.apiKey}`,
228
+ "Content-Type": "application/json",
229
+ },
230
+ body: JSON.stringify({
231
+ model,
232
+ texts: batch,
233
+ input_type: "search_document",
234
+ embedding_types: ["float"],
235
+ }),
236
+ });
237
+ if (!response.ok) {
238
+ const body = await response.text();
239
+ throw this.formatProviderError(new Error(`Cohere /v2/embed failed: ${response.status} — ${body.slice(0, 500)}`));
240
+ }
241
+ const json = (await response.json());
242
+ const floatVecs = json.embeddings?.float ??
243
+ (Array.isArray(json.embeddings) ? json.embeddings : undefined);
244
+ if (!floatVecs || floatVecs.length !== batch.length) {
245
+ throw new ProviderError(`Cohere /v2/embed returned ${floatVecs?.length ?? 0} embeddings for ${batch.length} inputs.`, "cohere");
246
+ }
247
+ results.push(...floatVecs);
248
+ }
249
+ return results;
250
+ }
251
+ }
252
+ export default CohereProvider;
253
+ //# sourceMappingURL=cohere.js.map
@@ -1,11 +1,13 @@
1
- import { createOpenAI } from "@ai-sdk/openai";
1
+ import { createOpenAICompatible } from "@ai-sdk/openai-compatible";
2
2
  import { stepCountIs, streamText } from "ai";
3
3
  import { DeepSeekModels } from "../constants/enums.js";
4
4
  import { BaseProvider } from "../core/baseProvider.js";
5
5
  import { DEFAULT_MAX_STEPS } from "../core/constants.js";
6
6
  import { streamAnalyticsCollector } from "../core/streamAnalytics.js";
7
+ import { isNeuroLink } from "../neurolink.js";
7
8
  import { createProxyFetch, maskProxyUrl } from "../proxy/proxyFetch.js";
8
- import { tracers, ATTR, withClientSpan } from "../telemetry/index.js";
9
+ import { tracers, ATTR, withClientStreamSpan } from "../telemetry/index.js";
10
+ import { AuthenticationError, InvalidModelError, NetworkError, ProviderError, RateLimitError, } from "../types/index.js";
9
11
  import { logger } from "../utils/logger.js";
10
12
  import { createDeepSeekConfig, getProviderModel, validateApiKey, } from "../utils/providerConfig.js";
11
13
  import { composeAbortSignals, createTimeoutController, TimeoutError, } from "../utils/timeout.js";
@@ -58,9 +60,7 @@ export class DeepSeekProvider extends BaseProvider {
58
60
  apiKey;
59
61
  baseURL;
60
62
  constructor(modelName, sdk, _region, credentials) {
61
- const validatedNeurolink = sdk && typeof sdk === "object" && "getInMemoryServers" in sdk
62
- ? sdk
63
- : undefined;
63
+ const validatedNeurolink = isNeuroLink(sdk) ? sdk : undefined;
64
64
  super(modelName, "deepseek", validatedNeurolink);
65
65
  // Trim the override before applying precedence. A blank/whitespace
66
66
  // `credentials.apiKey` should NOT bypass `getDeepSeekApiKey()` — that
@@ -75,14 +75,69 @@ export class DeepSeekProvider extends BaseProvider {
75
75
  credentials?.baseURL ??
76
76
  process.env.DEEPSEEK_BASE_URL ??
77
77
  DEEPSEEK_DEFAULT_BASE_URL;
78
- const deepseek = createOpenAI({
78
+ // We deliberately use `@ai-sdk/openai-compatible` rather than
79
+ // `@ai-sdk/openai`. Two upstream behaviors of `@ai-sdk/openai` break us:
80
+ // 1. It always sends `response_format: { type: "json_schema" }` when a
81
+ // schema is provided. DeepSeek's API rejects that with the literal
82
+ // message "This response_format type is unavailable now".
83
+ // 2. It does not parse the `reasoning_content` field that
84
+ // `deepseek-reasoner` emits, so chain-of-thought is silently dropped.
85
+ // `@ai-sdk/openai-compatible` honors `supportsStructuredOutputs: false`
86
+ // (falls back to `{ type: "json_object" }` and injects the schema into
87
+ // the prompt) and parses both `choice.message.reasoning_content` and
88
+ // `delta.reasoning_content` into the SDK-standard `reasoning` part.
89
+ const deepseek = createOpenAICompatible({
90
+ name: "deepseek",
79
91
  apiKey: this.apiKey,
80
92
  baseURL: this.baseURL,
81
93
  fetch: makeLoggingFetch("deepseek"),
94
+ supportsStructuredOutputs: false,
95
+ includeUsage: true,
96
+ // DeepSeek's `response_format: { type: "json_object" }` requires the
97
+ // prompt to literally contain the word "json" — otherwise the API
98
+ // rejects with: "Prompt must contain the word 'json' in some form to
99
+ // use 'response_format' of type 'json_object'." The OpenAI-compatible
100
+ // SDK fallback path (used because supportsStructuredOutputs is false)
101
+ // does not inject this guidance itself, so we prepend a system
102
+ // message when it's missing. No-op for non-JSON requests.
103
+ transformRequestBody: (body) => {
104
+ const rf = body
105
+ .response_format;
106
+ if (rf?.type !== "json_object") {
107
+ return body;
108
+ }
109
+ const messages = body
110
+ .messages;
111
+ if (!Array.isArray(messages)) {
112
+ return body;
113
+ }
114
+ const containsJsonWord = messages.some((m) => {
115
+ const c = m?.content;
116
+ if (typeof c === "string") {
117
+ return /\bjson\b/i.test(c);
118
+ }
119
+ if (Array.isArray(c)) {
120
+ return c.some((part) => typeof part?.text === "string" &&
121
+ /\bjson\b/i.test(part.text));
122
+ }
123
+ return false;
124
+ });
125
+ if (containsJsonWord) {
126
+ return body;
127
+ }
128
+ return {
129
+ ...body,
130
+ messages: [
131
+ {
132
+ role: "system",
133
+ content: "Respond with valid JSON that satisfies the requested schema. Output JSON only — no prose, no markdown fencing.",
134
+ },
135
+ ...messages,
136
+ ],
137
+ };
138
+ },
82
139
  });
83
- // .chat() returns a Chat Completions model. The default factory call
84
- // returns a Responses API model which OpenAI-compat providers don't implement.
85
- this.model = deepseek.chat(this.modelName);
140
+ this.model = deepseek.chatModel(this.modelName);
86
141
  logger.debug("DeepSeek Provider initialized", {
87
142
  modelName: this.modelName,
88
143
  providerName: this.providerName,
@@ -90,7 +145,7 @@ export class DeepSeekProvider extends BaseProvider {
90
145
  });
91
146
  }
92
147
  async executeStream(options, _analysisSchema) {
93
- return withClientSpan({
148
+ return withClientStreamSpan({
94
149
  name: "neurolink.provider.stream",
95
150
  tracer: tracers.provider,
96
151
  attributes: {
@@ -99,7 +154,7 @@ export class DeepSeekProvider extends BaseProvider {
99
154
  [ATTR.GEN_AI_OPERATION]: "stream",
100
155
  [ATTR.NL_STREAM_MODE]: true,
101
156
  },
102
- }, async () => this.executeStreamInner(options));
157
+ }, async () => this.executeStreamInner(options), (r) => r.stream, (r, wrapped) => ({ ...r, stream: wrapped }));
103
158
  }
104
159
  async executeStreamInner(options) {
105
160
  this.validateStreamOptions(options);
@@ -176,7 +231,7 @@ export class DeepSeekProvider extends BaseProvider {
176
231
  }
177
232
  formatProviderError(error) {
178
233
  if (error instanceof TimeoutError) {
179
- return new Error(`DeepSeek request timed out: ${error.message}`);
234
+ return new NetworkError(`Request timed out: ${error.message}`, "deepseek");
180
235
  }
181
236
  const errorRecord = error;
182
237
  const message = typeof errorRecord?.message === "string"
@@ -185,20 +240,20 @@ export class DeepSeekProvider extends BaseProvider {
185
240
  if (message.includes("Invalid API key") ||
186
241
  message.includes("Authentication") ||
187
242
  message.includes("401")) {
188
- return new Error("Invalid DeepSeek API key. Please check your DEEPSEEK_API_KEY environment variable.");
243
+ return new AuthenticationError("Invalid DeepSeek API key. Please check your DEEPSEEK_API_KEY environment variable.", "deepseek");
189
244
  }
190
245
  if (message.includes("rate limit") || message.includes("429")) {
191
- return new Error("DeepSeek rate limit exceeded");
246
+ return new RateLimitError("DeepSeek rate limit exceeded", "deepseek");
192
247
  }
193
248
  if (message.includes("Insufficient Balance") ||
194
249
  message.includes("insufficient_balance") ||
195
250
  message.includes("402")) {
196
- return new Error("DeepSeek account has insufficient balance. Top up at https://platform.deepseek.com/usage");
251
+ return new ProviderError("DeepSeek account has insufficient balance. Top up at https://platform.deepseek.com/usage", "deepseek");
197
252
  }
198
253
  if (message.includes("model_not_found") || message.includes("404")) {
199
- return new Error(`DeepSeek model '${this.modelName}' not found. Use 'deepseek-chat' or 'deepseek-reasoner'.`);
254
+ return new InvalidModelError(`DeepSeek model '${this.modelName}' not found. Use 'deepseek-chat' or 'deepseek-reasoner'.`, "deepseek");
200
255
  }
201
- return new Error(`DeepSeek error: ${message}`);
256
+ return new ProviderError(`DeepSeek error: ${message}`, "deepseek");
202
257
  }
203
258
  async validateConfiguration() {
204
259
  return typeof this.apiKey === "string" && this.apiKey.trim().length > 0;
@@ -0,0 +1,33 @@
1
+ import { type LanguageModel } from "ai";
2
+ import type { AIProviderName } from "../constants/enums.js";
3
+ import { BaseProvider } from "../core/baseProvider.js";
4
+ import type { NeurolinkCredentials, StreamOptions, StreamResult, ValidationSchema } from "../types/index.js";
5
+ /**
6
+ * Fireworks AI Provider
7
+ *
8
+ * Hosted open-model serving at api.fireworks.ai/inference/v1
9
+ * (OpenAI-compatible). Best for low-latency at scale on Llama / Mixtral /
10
+ * Qwen / DeepSeek.
11
+ *
12
+ * @see https://docs.fireworks.ai/api-reference/introduction
13
+ */
14
+ export declare class FireworksProvider extends BaseProvider {
15
+ private model;
16
+ private apiKey;
17
+ private baseURL;
18
+ constructor(modelName?: string, sdk?: unknown, _region?: string, credentials?: NeurolinkCredentials["fireworks"]);
19
+ protected executeStream(options: StreamOptions, _analysisSchema?: ValidationSchema): Promise<StreamResult>;
20
+ private executeStreamInner;
21
+ protected getProviderName(): AIProviderName;
22
+ protected getDefaultModel(): string;
23
+ protected getAISDKModel(): LanguageModel;
24
+ protected formatProviderError(error: unknown): Error;
25
+ validateConfiguration(): Promise<boolean>;
26
+ getConfiguration(): {
27
+ provider: AIProviderName;
28
+ model: string;
29
+ defaultModel: string;
30
+ baseURL: string;
31
+ };
32
+ }
33
+ export default FireworksProvider;