@juspay/neurolink 9.68.6 → 9.68.8

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.
@@ -1,9 +1,8 @@
1
1
  import type { AIProviderName } from "../constants/enums.js";
2
- import { BaseProvider } from "../core/baseProvider.js";
3
- import type { NeurolinkCredentials, StreamOptions, StreamResult, ValidationSchema } from "../types/index.js";
4
- import type { LanguageModel } from "../types/index.js";
2
+ import type { NeurolinkCredentials } from "../types/index.js";
3
+ import { OpenAIChatCompletionsProvider } from "./openaiChatCompletionsBase.js";
5
4
  /**
6
- * Cloudflare Workers AI Provider
5
+ * Cloudflare Workers AI Provider — direct HTTP, no AI SDK.
7
6
  *
8
7
  * Edge-served open models (Llama / Mistral / Qwen / Gemma) at
9
8
  * `https://api.cloudflare.com/client/v4/accounts/{accountId}/ai/v1`
@@ -11,25 +10,17 @@ import type { LanguageModel } from "../types/index.js";
11
10
  *
12
11
  * Required env: `CLOUDFLARE_API_KEY` + `CLOUDFLARE_ACCOUNT_ID`.
13
12
  *
13
+ * All request/stream/tool-loop orchestration lives in
14
+ * `OpenAIChatCompletionsProvider`; this class only declares configuration
15
+ * and provider-specific error mapping.
16
+ *
14
17
  * @see https://developers.cloudflare.com/workers-ai/configuration/open-ai-compatibility/
15
18
  */
16
- export declare class CloudflareProvider extends BaseProvider {
17
- private model;
18
- private apiKey;
19
- private baseURL;
19
+ export declare class CloudflareProvider extends OpenAIChatCompletionsProvider {
20
20
  constructor(modelName?: string, sdk?: unknown, _region?: string, credentials?: NeurolinkCredentials["cloudflare"]);
21
- protected executeStream(options: StreamOptions, _analysisSchema?: ValidationSchema): Promise<StreamResult>;
22
- private executeStreamInner;
23
21
  protected getProviderName(): AIProviderName;
24
22
  protected getDefaultModel(): string;
25
- protected getAISDKModel(): LanguageModel;
23
+ protected getFallbackModelName(): string;
24
+ protected getFallbackModels(): string[];
26
25
  protected formatProviderError(error: unknown): Error;
27
- validateConfiguration(): Promise<boolean>;
28
- getConfiguration(): {
29
- provider: AIProviderName;
30
- model: string;
31
- defaultModel: string;
32
- baseURL: string;
33
- };
34
26
  }
35
- export default CloudflareProvider;
@@ -1,20 +1,9 @@
1
- import { createOpenAI } from "@ai-sdk/openai";
2
1
  import { CloudflareModels } from "../constants/enums.js";
3
- import { BaseProvider } from "../core/baseProvider.js";
4
- import { DEFAULT_MAX_STEPS } from "../core/constants.js";
5
- import { streamAnalyticsCollector } from "../core/streamAnalytics.js";
6
- import { isNeuroLink } from "../neurolink.js";
7
- import { createLoggingFetch } from "../utils/loggingFetch.js";
8
- import { tracers, ATTR, withClientStreamSpan } from "../telemetry/index.js";
9
2
  import { AuthenticationError, InvalidModelError, NetworkError, ProviderError, RateLimitError, } from "../types/index.js";
10
3
  import { logger } from "../utils/logger.js";
11
4
  import { createCloudflareConfig, getProviderModel, validateApiKey, } from "../utils/providerConfig.js";
12
- import { composeAbortSignals, createTimeoutController, TimeoutError, } from "../utils/timeout.js";
13
- import { emitToolEndFromStepFinish } from "../utils/toolEndEmitter.js";
14
- import { resolveToolChoice } from "../utils/toolChoice.js";
15
- import { toAnalyticsStreamResult } from "./providerTypeUtils.js";
16
- import { stepCountIs } from "../utils/tool.js";
17
- import { streamText } from "../utils/generation.js";
5
+ import { TimeoutError } from "../utils/timeout.js";
6
+ import { OpenAIChatCompletionsProvider } from "./openaiChatCompletionsBase.js";
18
7
  /**
19
8
  * Cloudflare Workers AI exposes an OpenAI-compatible endpoint scoped per
20
9
  * account: `https://api.cloudflare.com/client/v4/accounts/{ACCOUNT_ID}/ai/v1`.
@@ -24,7 +13,7 @@ const buildCloudflareBaseURL = (accountId) => `https://api.cloudflare.com/client
24
13
  const getCloudflareApiKey = () => validateApiKey(createCloudflareConfig());
25
14
  const getDefaultCloudflareModel = () => getProviderModel("CLOUDFLARE_MODEL", CloudflareModels.LLAMA_3_3_70B_FAST);
26
15
  /**
27
- * Cloudflare Workers AI Provider
16
+ * Cloudflare Workers AI Provider — direct HTTP, no AI SDK.
28
17
  *
29
18
  * Edge-served open models (Llama / Mistral / Qwen / Gemma) at
30
19
  * `https://api.cloudflare.com/client/v4/accounts/{accountId}/ai/v1`
@@ -32,111 +21,50 @@ const getDefaultCloudflareModel = () => getProviderModel("CLOUDFLARE_MODEL", Clo
32
21
  *
33
22
  * Required env: `CLOUDFLARE_API_KEY` + `CLOUDFLARE_ACCOUNT_ID`.
34
23
  *
24
+ * All request/stream/tool-loop orchestration lives in
25
+ * `OpenAIChatCompletionsProvider`; this class only declares configuration
26
+ * and provider-specific error mapping.
27
+ *
35
28
  * @see https://developers.cloudflare.com/workers-ai/configuration/open-ai-compatibility/
36
29
  */
37
- export class CloudflareProvider extends BaseProvider {
38
- model;
39
- apiKey;
40
- baseURL;
30
+ export class CloudflareProvider extends OpenAIChatCompletionsProvider {
41
31
  constructor(modelName, sdk, _region, credentials) {
42
- const validatedNeurolink = isNeuroLink(sdk) ? sdk : undefined;
43
- super(modelName, "cloudflare", validatedNeurolink);
44
32
  const overrideApiKey = credentials?.apiKey?.trim();
45
- this.apiKey =
46
- overrideApiKey && overrideApiKey.length > 0
47
- ? overrideApiKey
48
- : getCloudflareApiKey();
33
+ const apiKey = overrideApiKey && overrideApiKey.length > 0
34
+ ? overrideApiKey
35
+ : getCloudflareApiKey();
49
36
  const accountId = (credentials?.accountId ??
50
37
  process.env.CLOUDFLARE_ACCOUNT_ID ??
51
38
  "").trim();
52
39
  if (!accountId) {
53
40
  throw new Error("CLOUDFLARE_ACCOUNT_ID is required (or pass credentials.cloudflare.accountId). Get the account id from https://dash.cloudflare.com/");
54
41
  }
55
- this.baseURL = credentials?.baseURL ?? buildCloudflareBaseURL(accountId);
56
- const cloudflare = createOpenAI({
57
- apiKey: this.apiKey,
58
- baseURL: this.baseURL,
59
- fetch: createLoggingFetch("cloudflare"),
60
- });
61
- this.model = cloudflare.chat(this.modelName);
42
+ const baseURL = credentials?.baseURL ?? buildCloudflareBaseURL(accountId);
43
+ super("cloudflare", modelName, sdk, { baseURL, apiKey });
62
44
  logger.debug("Cloudflare Workers AI Provider initialized", {
63
45
  modelName: this.modelName,
64
46
  providerName: this.providerName,
65
- baseURL: this.baseURL,
47
+ baseURL: this.config.baseURL,
66
48
  });
67
49
  }
68
- async executeStream(options, _analysisSchema) {
69
- return withClientStreamSpan({
70
- name: "neurolink.provider.stream",
71
- tracer: tracers.provider,
72
- attributes: {
73
- [ATTR.GEN_AI_SYSTEM]: "cloudflare",
74
- [ATTR.GEN_AI_MODEL]: this.modelName,
75
- [ATTR.GEN_AI_OPERATION]: "stream",
76
- [ATTR.NL_STREAM_MODE]: true,
77
- },
78
- }, async () => this.executeStreamInner(options), (r) => r.stream, (r, wrapped) => ({ ...r, stream: wrapped }));
79
- }
80
- async executeStreamInner(options) {
81
- this.validateStreamOptions(options);
82
- const startTime = Date.now();
83
- const timeout = this.getTimeout(options);
84
- const timeoutController = createTimeoutController(timeout, this.providerName, "stream");
85
- try {
86
- const shouldUseTools = !options.disableTools && this.supportsTools();
87
- const tools = shouldUseTools
88
- ? options.tools || (await this.getAllTools())
89
- : {};
90
- const messages = await this.buildMessagesForStream(options);
91
- const model = await this.getAISDKModelWithMiddleware(options);
92
- const result = await streamText({
93
- model,
94
- messages,
95
- temperature: options.temperature,
96
- maxOutputTokens: options.maxTokens,
97
- tools,
98
- stopWhen: stepCountIs(options.maxSteps || DEFAULT_MAX_STEPS),
99
- toolChoice: resolveToolChoice(options, tools, shouldUseTools),
100
- abortSignal: composeAbortSignals(options.abortSignal, timeoutController?.controller.signal),
101
- experimental_telemetry: this.telemetryHandler.getTelemetryConfig(options),
102
- experimental_repairToolCall: this.getToolCallRepairFn(options),
103
- onStepFinish: ({ toolCalls, toolResults }) => {
104
- emitToolEndFromStepFinish(this.neurolink?.getEventEmitter(), toolResults);
105
- this.handleToolExecutionStorage(toolCalls, toolResults, options, new Date()).catch((error) => {
106
- logger.warn("[CloudflareProvider] Failed to store tool executions", {
107
- provider: this.providerName,
108
- error: error instanceof Error ? error.message : String(error),
109
- });
110
- });
111
- },
112
- });
113
- timeoutController?.cleanup();
114
- const transformedStream = this.createTextStream(result);
115
- const analyticsPromise = streamAnalyticsCollector.createAnalytics(this.providerName, this.modelName, toAnalyticsStreamResult(result), Date.now() - startTime, {
116
- requestId: `cloudflare-stream-${Date.now()}`,
117
- streamingMode: true,
118
- });
119
- return {
120
- stream: transformedStream,
121
- provider: this.providerName,
122
- model: this.modelName,
123
- analytics: analyticsPromise,
124
- metadata: { startTime, streamId: `cloudflare-${Date.now()}` },
125
- };
126
- }
127
- catch (error) {
128
- timeoutController?.cleanup();
129
- throw this.handleProviderError(error);
130
- }
131
- }
132
50
  getProviderName() {
133
- return this.providerName;
51
+ return "cloudflare";
134
52
  }
135
53
  getDefaultModel() {
136
54
  return getDefaultCloudflareModel();
137
55
  }
138
- getAISDKModel() {
139
- return this.model;
56
+ getFallbackModelName() {
57
+ return CloudflareModels.LLAMA_3_1_8B_FAST;
58
+ }
59
+ getFallbackModels() {
60
+ return [
61
+ CloudflareModels.LLAMA_3_3_70B_FAST,
62
+ CloudflareModels.LLAMA_3_1_70B_INSTRUCT,
63
+ CloudflareModels.LLAMA_3_1_8B_FAST,
64
+ CloudflareModels.LLAMA_3_2_11B_VISION,
65
+ CloudflareModels.MISTRAL_7B_INSTRUCT_V0_2,
66
+ CloudflareModels.QWEN_1P5_14B_CHAT_AWQ,
67
+ ];
140
68
  }
141
69
  formatProviderError(error) {
142
70
  if (error instanceof TimeoutError) {
@@ -159,17 +87,5 @@ export class CloudflareProvider extends BaseProvider {
159
87
  }
160
88
  return new ProviderError(`Cloudflare Workers AI error: ${message}`, "cloudflare");
161
89
  }
162
- async validateConfiguration() {
163
- return typeof this.apiKey === "string" && this.apiKey.trim().length > 0;
164
- }
165
- getConfiguration() {
166
- return {
167
- provider: this.providerName,
168
- model: this.modelName,
169
- defaultModel: getDefaultCloudflareModel(),
170
- baseURL: this.baseURL,
171
- };
172
- }
173
90
  }
174
- export default CloudflareProvider;
175
91
  //# sourceMappingURL=cloudflare.js.map
@@ -1,24 +1,37 @@
1
1
  import type { AIProviderName } from "../constants/enums.js";
2
- import { BaseProvider } from "../core/baseProvider.js";
3
- import type { NeurolinkCredentials, StreamOptions, StreamResult, ValidationSchema } from "../types/index.js";
4
- import type { LanguageModel } from "../types/index.js";
2
+ import type { NeurolinkCredentials, OpenAICompatBuildBodyArgs } from "../types/index.js";
3
+ import { OpenAIChatCompletionsProvider } from "./openaiChatCompletionsBase.js";
4
+ declare const isNimFieldRejection: (body: string, field: string) => boolean;
5
5
  /**
6
- * NVIDIA NIM Provider
7
- * Wraps NVIDIA's hosted (or self-hosted) inference endpoints via OpenAI-compat.
6
+ * Strip an offending field from a JSON request body and return the rebuilt
7
+ * stringified body. Returns `null` if the body isn't JSON-parseable or the
8
+ * field isn't present (signal: nothing to retry).
9
+ */
10
+ declare const stripFieldFromJsonBody: (body: string, field: "reasoning_budget" | "chat_template") => string | null;
11
+ /**
12
+ * NVIDIA NIM Provider — native HTTP+SSE, no AI SDK.
13
+ *
14
+ * Wraps NVIDIA's hosted (or self-hosted) inference endpoints.
8
15
  * Passes NIM-specific extras (top_k, min_p, repetition_penalty,
9
- * chat_template_kwargs.reasoning_budget) via providerOptions.openai.body.
10
- * Implements one-retry-on-400 to drop unsupported extras gracefully.
16
+ * chat_template_kwargs.reasoning_budget) via adjustBuildBodyOptions.
17
+ * reasoning_content surfacing is a pending base-client follow-up (not emitted natively yet); all other behavior is preserved.
18
+ *
19
+ * @see https://docs.api.nvidia.com/nim/reference/
11
20
  */
12
- export declare class NvidiaNimProvider extends BaseProvider {
13
- private model;
14
- private apiKey;
15
- private baseURL;
21
+ export declare class NvidiaNimProvider extends OpenAIChatCompletionsProvider {
16
22
  constructor(modelName?: string, sdk?: unknown, _region?: string, credentials?: NeurolinkCredentials["nvidiaNim"]);
17
- protected executeStream(options: StreamOptions, _analysisSchema?: ValidationSchema): Promise<StreamResult>;
18
- private executeStreamInner;
19
23
  protected getProviderName(): AIProviderName;
20
24
  protected getDefaultModel(): string;
21
- protected getAISDKModel(): LanguageModel;
25
+ /**
26
+ * Inject NIM-specific body fields (top_k, min_p, repetition_penalty,
27
+ * min_tokens, chat_template, chat_template_kwargs) into the wire body.
28
+ *
29
+ * The base passes the full StreamOptions as `opts` at runtime (typed
30
+ * narrowly as OpenAICompatBuildBodyArgs["options"] for standard fields).
31
+ * We access thinkingLevel via an indexed-access cast since the runtime
32
+ * value is the full StreamOptions object.
33
+ */
34
+ protected adjustBuildBodyOptions(_modelId: string, opts: OpenAICompatBuildBodyArgs["options"]): OpenAICompatBuildBodyArgs["options"] & Record<string, unknown>;
22
35
  protected formatProviderError(error: unknown): Error;
23
36
  validateConfiguration(): Promise<boolean>;
24
37
  getConfiguration(): {
@@ -28,4 +41,4 @@ export declare class NvidiaNimProvider extends BaseProvider {
28
41
  baseURL: string;
29
42
  };
30
43
  }
31
- export default NvidiaNimProvider;
44
+ export { isNimFieldRejection, stripFieldFromJsonBody };