@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.
- package/CHANGELOG.md +6 -0
- package/README.md +18 -17
- package/dist/adapters/providerImageAdapter.js +29 -1
- package/dist/adapters/replicate/auth.d.ts +19 -0
- package/dist/adapters/replicate/auth.js +32 -0
- package/dist/adapters/replicate/predictionLifecycle.d.ts +46 -0
- package/dist/adapters/replicate/predictionLifecycle.js +283 -0
- package/dist/adapters/video/klingVideoHandler.d.ts +37 -0
- package/dist/adapters/video/klingVideoHandler.js +305 -0
- package/dist/adapters/video/replicateVideoHandler.d.ts +29 -0
- package/dist/adapters/video/replicateVideoHandler.js +157 -0
- package/dist/adapters/video/runwayVideoHandler.d.ts +32 -0
- package/dist/adapters/video/runwayVideoHandler.js +316 -0
- package/dist/adapters/video/vertexVideoHandler.d.ts +19 -1
- package/dist/adapters/video/vertexVideoHandler.js +33 -9
- package/dist/autoresearch/runner.js +8 -2
- package/dist/avatar/index.d.ts +13 -0
- package/dist/avatar/index.js +13 -0
- package/dist/avatar/providers/DIDAvatar.d.ts +49 -0
- package/dist/avatar/providers/DIDAvatar.js +501 -0
- package/dist/avatar/providers/HeyGenAvatar.d.ts +30 -0
- package/dist/avatar/providers/HeyGenAvatar.js +337 -0
- package/dist/avatar/providers/ReplicateAvatar.d.ts +36 -0
- package/dist/avatar/providers/ReplicateAvatar.js +267 -0
- package/dist/browser/neurolink.min.js +633 -610
- package/dist/cli/commands/mcp.js +29 -0
- package/dist/cli/commands/proxy.js +24 -5
- package/dist/cli/factories/commandFactory.d.ts +11 -1
- package/dist/cli/factories/commandFactory.js +291 -38
- package/dist/constants/contextWindows.js +101 -0
- package/dist/constants/enums.d.ts +273 -2
- package/dist/constants/enums.js +290 -1
- package/dist/constants/videoErrors.d.ts +4 -0
- package/dist/constants/videoErrors.js +4 -0
- package/dist/core/baseProvider.d.ts +22 -2
- package/dist/core/baseProvider.js +217 -11
- package/dist/core/constants.d.ts +11 -0
- package/dist/core/constants.js +69 -1
- package/dist/core/redisConversationMemoryManager.js +6 -0
- package/dist/evaluation/index.d.ts +2 -0
- package/dist/evaluation/index.js +4 -0
- package/dist/factories/providerFactory.js +7 -1
- package/dist/factories/providerRegistry.js +202 -5
- package/dist/features/ppt/contentPlanner.js +42 -14
- package/dist/index.d.ts +9 -1
- package/dist/index.js +16 -1
- package/dist/lib/adapters/providerImageAdapter.js +29 -1
- package/dist/lib/adapters/replicate/auth.d.ts +19 -0
- package/dist/lib/adapters/replicate/auth.js +33 -0
- package/dist/lib/adapters/replicate/predictionLifecycle.d.ts +46 -0
- package/dist/lib/adapters/replicate/predictionLifecycle.js +284 -0
- package/dist/lib/adapters/video/klingVideoHandler.d.ts +37 -0
- package/dist/lib/adapters/video/klingVideoHandler.js +306 -0
- package/dist/lib/adapters/video/replicateVideoHandler.d.ts +29 -0
- package/dist/lib/adapters/video/replicateVideoHandler.js +158 -0
- package/dist/lib/adapters/video/runwayVideoHandler.d.ts +32 -0
- package/dist/lib/adapters/video/runwayVideoHandler.js +317 -0
- package/dist/lib/adapters/video/vertexVideoHandler.d.ts +19 -1
- package/dist/lib/adapters/video/vertexVideoHandler.js +33 -9
- package/dist/lib/autoresearch/runner.js +8 -2
- package/dist/lib/avatar/index.d.ts +13 -0
- package/dist/lib/avatar/index.js +14 -0
- package/dist/lib/avatar/providers/DIDAvatar.d.ts +49 -0
- package/dist/lib/avatar/providers/DIDAvatar.js +502 -0
- package/dist/lib/avatar/providers/HeyGenAvatar.d.ts +30 -0
- package/dist/lib/avatar/providers/HeyGenAvatar.js +338 -0
- package/dist/lib/avatar/providers/ReplicateAvatar.d.ts +36 -0
- package/dist/lib/avatar/providers/ReplicateAvatar.js +268 -0
- package/dist/lib/constants/contextWindows.js +101 -0
- package/dist/lib/constants/enums.d.ts +273 -2
- package/dist/lib/constants/enums.js +290 -1
- package/dist/lib/constants/videoErrors.d.ts +4 -0
- package/dist/lib/constants/videoErrors.js +4 -0
- package/dist/lib/core/baseProvider.d.ts +22 -2
- package/dist/lib/core/baseProvider.js +217 -11
- package/dist/lib/core/constants.d.ts +11 -0
- package/dist/lib/core/constants.js +69 -1
- package/dist/lib/core/redisConversationMemoryManager.js +6 -0
- package/dist/lib/evaluation/index.d.ts +2 -0
- package/dist/lib/evaluation/index.js +4 -0
- package/dist/lib/factories/providerFactory.js +7 -1
- package/dist/lib/factories/providerRegistry.js +202 -5
- package/dist/lib/features/ppt/contentPlanner.js +42 -14
- package/dist/lib/index.d.ts +9 -1
- package/dist/lib/index.js +16 -1
- package/dist/lib/middleware/builtin/lifecycle.js +39 -9
- package/dist/lib/music/index.d.ts +13 -0
- package/dist/lib/music/index.js +14 -0
- package/dist/lib/music/providers/BeatovenMusic.d.ts +31 -0
- package/dist/lib/music/providers/BeatovenMusic.js +334 -0
- package/dist/lib/music/providers/ElevenLabsMusic.d.ts +30 -0
- package/dist/lib/music/providers/ElevenLabsMusic.js +169 -0
- package/dist/lib/music/providers/LyriaMusic.d.ts +29 -0
- package/dist/lib/music/providers/LyriaMusic.js +173 -0
- package/dist/lib/music/providers/ReplicateMusic.d.ts +31 -0
- package/dist/lib/music/providers/ReplicateMusic.js +262 -0
- package/dist/lib/neurolink.d.ts +30 -0
- package/dist/lib/neurolink.js +323 -77
- package/dist/lib/providers/amazonBedrock.d.ts +10 -0
- package/dist/lib/providers/amazonBedrock.js +94 -39
- package/dist/lib/providers/anthropic.js +55 -7
- package/dist/lib/providers/anthropicBaseProvider.js +1 -1
- package/dist/lib/providers/azureOpenai.js +66 -17
- package/dist/lib/providers/cloudflare.d.ts +35 -0
- package/dist/lib/providers/cloudflare.js +174 -0
- package/dist/lib/providers/cohere.d.ts +52 -0
- package/dist/lib/providers/cohere.js +253 -0
- package/dist/lib/providers/deepseek.js +72 -17
- package/dist/lib/providers/fireworks.d.ts +33 -0
- package/dist/lib/providers/fireworks.js +164 -0
- package/dist/lib/providers/googleAiStudio.js +45 -6
- package/dist/lib/providers/googleNativeGemini3.d.ts +24 -1
- package/dist/lib/providers/googleNativeGemini3.js +173 -21
- package/dist/lib/providers/googleVertex.js +173 -17
- package/dist/lib/providers/groq.d.ts +33 -0
- package/dist/lib/providers/groq.js +181 -0
- package/dist/lib/providers/huggingFace.js +9 -8
- package/dist/lib/providers/ideogram.d.ts +34 -0
- package/dist/lib/providers/ideogram.js +184 -0
- package/dist/lib/providers/index.d.ts +13 -0
- package/dist/lib/providers/index.js +13 -0
- package/dist/lib/providers/jina.d.ts +59 -0
- package/dist/lib/providers/jina.js +218 -0
- package/dist/lib/providers/llamaCpp.js +14 -46
- package/dist/lib/providers/lmStudio.js +14 -47
- package/dist/lib/providers/mistral.js +7 -7
- package/dist/lib/providers/nvidiaNim.js +160 -19
- package/dist/lib/providers/ollama.js +7 -7
- package/dist/lib/providers/openAI.d.ts +22 -1
- package/dist/lib/providers/openAI.js +181 -0
- package/dist/lib/providers/openRouter.js +35 -23
- package/dist/lib/providers/openaiCompatible.js +9 -8
- package/dist/lib/providers/perplexity.d.ts +33 -0
- package/dist/lib/providers/perplexity.js +179 -0
- package/dist/lib/providers/recraft.d.ts +34 -0
- package/dist/lib/providers/recraft.js +197 -0
- package/dist/lib/providers/replicate.d.ts +75 -0
- package/dist/lib/providers/replicate.js +403 -0
- package/dist/lib/providers/stability.d.ts +37 -0
- package/dist/lib/providers/stability.js +191 -0
- package/dist/lib/providers/togetherAi.d.ts +33 -0
- package/dist/lib/providers/togetherAi.js +176 -0
- package/dist/lib/providers/voyage.d.ts +47 -0
- package/dist/lib/providers/voyage.js +177 -0
- package/dist/lib/providers/xai.d.ts +33 -0
- package/dist/lib/providers/xai.js +172 -0
- package/dist/lib/telemetry/index.d.ts +1 -1
- package/dist/lib/telemetry/index.js +1 -1
- package/dist/lib/telemetry/tracers.d.ts +19 -0
- package/dist/lib/telemetry/tracers.js +19 -0
- package/dist/lib/telemetry/withSpan.d.ts +35 -0
- package/dist/lib/telemetry/withSpan.js +103 -0
- package/dist/lib/types/avatar.d.ts +143 -0
- package/dist/lib/types/avatar.js +20 -0
- package/dist/lib/types/cli.d.ts +6 -0
- package/dist/lib/types/generate.d.ts +62 -5
- package/dist/lib/types/index.d.ts +5 -0
- package/dist/lib/types/index.js +7 -0
- package/dist/lib/types/middleware.d.ts +27 -0
- package/dist/lib/types/multimodal.d.ts +35 -2
- package/dist/lib/types/music.d.ts +165 -0
- package/dist/lib/types/music.js +21 -0
- package/dist/lib/types/providers.d.ts +144 -1
- package/dist/lib/types/replicate.d.ts +67 -0
- package/dist/lib/types/replicate.js +10 -0
- package/dist/lib/types/safeFetch.d.ts +15 -0
- package/dist/lib/types/safeFetch.js +7 -0
- package/dist/lib/types/stream.d.ts +2 -1
- package/dist/lib/types/tools.d.ts +13 -0
- package/dist/lib/types/video.d.ts +89 -0
- package/dist/lib/types/video.js +15 -0
- package/dist/lib/utils/avatarProcessor.d.ts +68 -0
- package/dist/lib/utils/avatarProcessor.js +172 -0
- package/dist/lib/utils/cloneOptions.d.ts +36 -0
- package/dist/lib/utils/cloneOptions.js +62 -0
- package/dist/lib/utils/lifecycleCallbacks.d.ts +51 -8
- package/dist/lib/utils/lifecycleCallbacks.js +82 -26
- package/dist/lib/utils/lifecycleTimeout.d.ts +25 -0
- package/dist/lib/utils/lifecycleTimeout.js +39 -0
- package/dist/lib/utils/logSanitize.d.ts +49 -0
- package/dist/lib/utils/logSanitize.js +170 -0
- package/dist/lib/utils/loggingFetch.d.ts +29 -0
- package/dist/lib/utils/loggingFetch.js +60 -0
- package/dist/lib/utils/messageBuilder.js +43 -25
- package/dist/lib/utils/modelChoices.js +236 -3
- package/dist/lib/utils/musicProcessor.d.ts +67 -0
- package/dist/lib/utils/musicProcessor.js +189 -0
- package/dist/lib/utils/optionsConversion.js +3 -2
- package/dist/lib/utils/parameterValidation.js +14 -4
- package/dist/lib/utils/pricing.js +193 -0
- package/dist/lib/utils/providerConfig.d.ts +55 -0
- package/dist/lib/utils/providerConfig.js +224 -0
- package/dist/lib/utils/safeFetch.d.ts +26 -0
- package/dist/lib/utils/safeFetch.js +83 -0
- package/dist/lib/utils/sizeGuard.d.ts +34 -0
- package/dist/lib/utils/sizeGuard.js +45 -0
- package/dist/lib/utils/ssrfGuard.d.ts +52 -0
- package/dist/lib/utils/ssrfGuard.js +411 -0
- package/dist/lib/utils/videoProcessor.d.ts +60 -0
- package/dist/lib/utils/videoProcessor.js +201 -0
- package/dist/lib/voice/providers/FishAudioTTS.d.ts +27 -0
- package/dist/lib/voice/providers/FishAudioTTS.js +183 -0
- package/dist/lib/workflow/core/ensembleExecutor.js +26 -9
- package/dist/middleware/builtin/lifecycle.js +39 -9
- package/dist/music/index.d.ts +13 -0
- package/dist/music/index.js +13 -0
- package/dist/music/providers/BeatovenMusic.d.ts +31 -0
- package/dist/music/providers/BeatovenMusic.js +333 -0
- package/dist/music/providers/ElevenLabsMusic.d.ts +30 -0
- package/dist/music/providers/ElevenLabsMusic.js +168 -0
- package/dist/music/providers/LyriaMusic.d.ts +29 -0
- package/dist/music/providers/LyriaMusic.js +172 -0
- package/dist/music/providers/ReplicateMusic.d.ts +31 -0
- package/dist/music/providers/ReplicateMusic.js +261 -0
- package/dist/neurolink.d.ts +30 -0
- package/dist/neurolink.js +323 -77
- package/dist/providers/amazonBedrock.d.ts +10 -0
- package/dist/providers/amazonBedrock.js +94 -39
- package/dist/providers/anthropic.js +55 -7
- package/dist/providers/anthropicBaseProvider.js +1 -1
- package/dist/providers/azureOpenai.js +66 -17
- package/dist/providers/cloudflare.d.ts +35 -0
- package/dist/providers/cloudflare.js +173 -0
- package/dist/providers/cohere.d.ts +52 -0
- package/dist/providers/cohere.js +252 -0
- package/dist/providers/deepseek.js +72 -17
- package/dist/providers/fireworks.d.ts +33 -0
- package/dist/providers/fireworks.js +163 -0
- package/dist/providers/googleAiStudio.js +45 -6
- package/dist/providers/googleNativeGemini3.d.ts +24 -1
- package/dist/providers/googleNativeGemini3.js +173 -21
- package/dist/providers/googleVertex.js +173 -17
- package/dist/providers/groq.d.ts +33 -0
- package/dist/providers/groq.js +180 -0
- package/dist/providers/huggingFace.js +9 -8
- package/dist/providers/ideogram.d.ts +34 -0
- package/dist/providers/ideogram.js +183 -0
- package/dist/providers/index.d.ts +13 -0
- package/dist/providers/index.js +13 -0
- package/dist/providers/jina.d.ts +59 -0
- package/dist/providers/jina.js +217 -0
- package/dist/providers/llamaCpp.js +14 -46
- package/dist/providers/lmStudio.js +14 -47
- package/dist/providers/mistral.js +7 -7
- package/dist/providers/nvidiaNim.js +160 -19
- package/dist/providers/ollama.js +7 -7
- package/dist/providers/openAI.d.ts +22 -1
- package/dist/providers/openAI.js +181 -0
- package/dist/providers/openRouter.js +35 -23
- package/dist/providers/openaiCompatible.js +9 -8
- package/dist/providers/perplexity.d.ts +33 -0
- package/dist/providers/perplexity.js +178 -0
- package/dist/providers/recraft.d.ts +34 -0
- package/dist/providers/recraft.js +196 -0
- package/dist/providers/replicate.d.ts +75 -0
- package/dist/providers/replicate.js +402 -0
- package/dist/providers/stability.d.ts +37 -0
- package/dist/providers/stability.js +190 -0
- package/dist/providers/togetherAi.d.ts +33 -0
- package/dist/providers/togetherAi.js +175 -0
- package/dist/providers/voyage.d.ts +47 -0
- package/dist/providers/voyage.js +176 -0
- package/dist/providers/xai.d.ts +33 -0
- package/dist/providers/xai.js +171 -0
- package/dist/telemetry/index.d.ts +1 -1
- package/dist/telemetry/index.js +1 -1
- package/dist/telemetry/tracers.d.ts +19 -0
- package/dist/telemetry/tracers.js +19 -0
- package/dist/telemetry/withSpan.d.ts +35 -0
- package/dist/telemetry/withSpan.js +103 -0
- package/dist/types/avatar.d.ts +143 -0
- package/dist/types/avatar.js +19 -0
- package/dist/types/cli.d.ts +6 -0
- package/dist/types/generate.d.ts +62 -5
- package/dist/types/index.d.ts +5 -0
- package/dist/types/index.js +7 -0
- package/dist/types/middleware.d.ts +27 -0
- package/dist/types/multimodal.d.ts +35 -2
- package/dist/types/music.d.ts +165 -0
- package/dist/types/music.js +20 -0
- package/dist/types/providers.d.ts +144 -1
- package/dist/types/replicate.d.ts +67 -0
- package/dist/types/replicate.js +9 -0
- package/dist/types/safeFetch.d.ts +15 -0
- package/dist/types/safeFetch.js +6 -0
- package/dist/types/stream.d.ts +2 -1
- package/dist/types/tools.d.ts +13 -0
- package/dist/types/video.d.ts +89 -0
- package/dist/types/video.js +14 -0
- package/dist/utils/avatarProcessor.d.ts +68 -0
- package/dist/utils/avatarProcessor.js +171 -0
- package/dist/utils/cloneOptions.d.ts +36 -0
- package/dist/utils/cloneOptions.js +61 -0
- package/dist/utils/lifecycleCallbacks.d.ts +51 -8
- package/dist/utils/lifecycleCallbacks.js +82 -26
- package/dist/utils/lifecycleTimeout.d.ts +25 -0
- package/dist/utils/lifecycleTimeout.js +38 -0
- package/dist/utils/logSanitize.d.ts +49 -0
- package/dist/utils/logSanitize.js +169 -0
- package/dist/utils/loggingFetch.d.ts +29 -0
- package/dist/utils/loggingFetch.js +59 -0
- package/dist/utils/messageBuilder.js +43 -25
- package/dist/utils/modelChoices.js +236 -3
- package/dist/utils/musicProcessor.d.ts +67 -0
- package/dist/utils/musicProcessor.js +188 -0
- package/dist/utils/optionsConversion.js +3 -2
- package/dist/utils/parameterValidation.js +14 -4
- package/dist/utils/pricing.js +193 -0
- package/dist/utils/providerConfig.d.ts +55 -0
- package/dist/utils/providerConfig.js +224 -0
- package/dist/utils/safeFetch.d.ts +26 -0
- package/dist/utils/safeFetch.js +82 -0
- package/dist/utils/sizeGuard.d.ts +34 -0
- package/dist/utils/sizeGuard.js +44 -0
- package/dist/utils/ssrfGuard.d.ts +52 -0
- package/dist/utils/ssrfGuard.js +410 -0
- package/dist/utils/videoProcessor.d.ts +60 -0
- package/dist/utils/videoProcessor.js +200 -0
- package/dist/voice/providers/FishAudioTTS.d.ts +27 -0
- package/dist/voice/providers/FishAudioTTS.js +182 -0
- package/dist/workflow/core/ensembleExecutor.js +26 -9
- 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 {
|
|
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,
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
254
|
+
return new InvalidModelError(`DeepSeek model '${this.modelName}' not found. Use 'deepseek-chat' or 'deepseek-reasoner'.`, "deepseek");
|
|
200
255
|
}
|
|
201
|
-
return new
|
|
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;
|