@juspay/neurolink 9.68.20 → 9.69.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.
@@ -16,12 +16,12 @@ import { OpenAIChatCompletionsProvider } from "./openaiChatCompletionsBase.js";
16
16
  * `@ai-sdk/openai-compatible` path this migration replaced. The base
17
17
  * client injects the literal "json" word the API requires for that mode.
18
18
  *
19
- * 2. Reasoning support — the opt-in `thinking` request param (non-reasoner
20
- * chat models) and `reasoning_content` surfacing (deepseek-reasoner / R1)
21
- * both require plumbing the thinking signal and the reasoning delta
22
- * through the native base client. That plumbing isn't in place yet, so
23
- * neither is wired here; it is tracked as a base-client follow-up. All
24
- * other behavior is preserved.
19
+ * 2. Reasoning support — `reasoning_content` (deepseek-reasoner / R1) is
20
+ * surfaced automatically by the native base client: streamed deltas
21
+ * arrive as `{ content: "", reasoning }` chunks and the non-streaming
22
+ * result carries `result.reasoning`. The opt-in `thinking` request
23
+ * param (non-reasoner chat models) still needs thinking-signal plumbing
24
+ * and is tracked as a follow-up. All other behavior is preserved.
25
25
  *
26
26
  * @see https://api-docs.deepseek.com
27
27
  */
@@ -27,12 +27,12 @@ const getDefaultDeepSeekModel = () => {
27
27
  * `@ai-sdk/openai-compatible` path this migration replaced. The base
28
28
  * client injects the literal "json" word the API requires for that mode.
29
29
  *
30
- * 2. Reasoning support — the opt-in `thinking` request param (non-reasoner
31
- * chat models) and `reasoning_content` surfacing (deepseek-reasoner / R1)
32
- * both require plumbing the thinking signal and the reasoning delta
33
- * through the native base client. That plumbing isn't in place yet, so
34
- * neither is wired here; it is tracked as a base-client follow-up. All
35
- * other behavior is preserved.
30
+ * 2. Reasoning support — `reasoning_content` (deepseek-reasoner / R1) is
31
+ * surfaced automatically by the native base client: streamed deltas
32
+ * arrive as `{ content: "", reasoning }` chunks and the non-streaming
33
+ * result carries `result.reasoning`. The opt-in `thinking` request
34
+ * param (non-reasoner chat models) still needs thinking-signal plumbing
35
+ * and is tracked as a follow-up. All other behavior is preserved.
36
36
  *
37
37
  * @see https://api-docs.deepseek.com
38
38
  */
@@ -14,7 +14,9 @@ declare const stripFieldFromJsonBody: (body: string, field: "reasoning_budget" |
14
14
  * Wraps NVIDIA's hosted (or self-hosted) inference endpoints.
15
15
  * Passes NIM-specific extras (top_k, min_p, repetition_penalty,
16
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.
17
+ * reasoning_content is surfaced automatically by the native base client
18
+ * (streamed as `{ content: "", reasoning }` chunks; `result.reasoning` on
19
+ * the non-streaming path); all other behavior is preserved.
18
20
  *
19
21
  * @see https://docs.api.nvidia.com/nim/reference/
20
22
  */
@@ -144,7 +144,9 @@ const getDefaultNimModel = () => {
144
144
  * Wraps NVIDIA's hosted (or self-hosted) inference endpoints.
145
145
  * Passes NIM-specific extras (top_k, min_p, repetition_penalty,
146
146
  * chat_template_kwargs.reasoning_budget) via adjustBuildBodyOptions.
147
- * reasoning_content surfacing is a pending base-client follow-up (not emitted natively yet); all other behavior is preserved.
147
+ * reasoning_content is surfaced automatically by the native base client
148
+ * (streamed as `{ content: "", reasoning }` chunks; `result.reasoning` on
149
+ * the non-streaming path); all other behavior is preserved.
148
150
  *
149
151
  * @see https://docs.api.nvidia.com/nim/reference/
150
152
  */
@@ -269,6 +269,13 @@ export class OpenAIChatCompletionsProvider extends BaseProvider {
269
269
  ? choice.message.content
270
270
  : "") ?? "";
271
271
  const content = [];
272
+ // Reasoner-model output (DeepSeek `reasoning_content`, gateway
273
+ // `reasoning`) becomes a V3 reasoning part ahead of the text part —
274
+ // GenerationHandler joins reasoning parts into `result.reasoning`.
275
+ const reasoningText = choice?.message?.reasoning_content ?? choice?.message?.reasoning;
276
+ if (typeof reasoningText === "string" && reasoningText.length > 0) {
277
+ content.push({ type: "reasoning", text: reasoningText });
278
+ }
272
279
  if (text.length > 0) {
273
280
  content.push({ type: "text", text });
274
281
  }
@@ -300,8 +307,13 @@ export class OpenAIChatCompletionsProvider extends BaseProvider {
300
307
  },
301
308
  outputTokens: {
302
309
  total: json.usage?.completion_tokens,
303
- text: json.usage?.completion_tokens,
304
- reasoning: undefined,
310
+ text: json.usage?.completion_tokens !== undefined &&
311
+ json.usage?.completion_tokens_details?.reasoning_tokens !==
312
+ undefined
313
+ ? json.usage.completion_tokens -
314
+ json.usage.completion_tokens_details.reasoning_tokens
315
+ : json.usage?.completion_tokens,
316
+ reasoning: json.usage?.completion_tokens_details?.reasoning_tokens,
305
317
  },
306
318
  },
307
319
  warnings: [],
@@ -584,6 +596,10 @@ export class OpenAIChatCompletionsProvider extends BaseProvider {
584
596
  }
585
597
  return parseSSEStream(res.body, (delta) => {
586
598
  args.pushChunk({ content: delta });
599
+ }, (reasoningDelta) => {
600
+ // Reasoning rides alongside an empty `content` so plain-text
601
+ // consumers (which only read chunk.content) are unaffected.
602
+ args.pushChunk({ content: "", reasoning: reasoningDelta });
587
603
  });
588
604
  }
589
605
  async executeToolBatch(args) {
@@ -35,7 +35,7 @@ export declare const messagesContainJsonWord: (messages: ReadonlyArray<OpenAICom
35
35
  export declare const ensureJsonWordInBody: (body: OpenAICompatChatRequest) => OpenAICompatChatRequest;
36
36
  export declare const requiresMaxCompletionTokens: (modelId: string) => boolean;
37
37
  export declare const buildBody: (args: OpenAICompatBuildBodyArgs) => OpenAICompatChatRequest;
38
- export declare const parseSSEStream: (body: ReadableStream<Uint8Array>, onTextDelta: (delta: string) => void) => Promise<OpenAICompatSSEResult>;
38
+ export declare const parseSSEStream: (body: ReadableStream<Uint8Array>, onTextDelta: (delta: string) => void, onReasoningDelta?: (delta: string) => void) => Promise<OpenAICompatSSEResult>;
39
39
  export declare const buildAPIError: (url: string, body: OpenAICompatChatRequest, res: Response) => Promise<Error>;
40
40
  export declare const createDeferredAnalytics: () => {
41
41
  usagePromise: Promise<{
@@ -399,9 +399,10 @@ export const buildBody = (args) => {
399
399
  }
400
400
  return body;
401
401
  };
402
- export const parseSSEStream = async (body, onTextDelta) => {
402
+ export const parseSSEStream = async (body, onTextDelta, onReasoningDelta) => {
403
403
  const result = {
404
404
  text: "",
405
+ reasoning: "",
405
406
  toolCalls: new Map(),
406
407
  finishReason: null,
407
408
  usage: undefined,
@@ -433,6 +434,14 @@ export const parseSSEStream = async (body, onTextDelta) => {
433
434
  result.text += delta.content;
434
435
  onTextDelta(delta.content);
435
436
  }
437
+ // Reasoner-model deltas: DeepSeek/NIM emit `reasoning_content`, some
438
+ // gateways emit `reasoning`. The AI SDK's openai-compatible wrapper
439
+ // surfaced these automatically; the native client must do the same.
440
+ const reasoningDelta = delta?.reasoning_content ?? delta?.reasoning;
441
+ if (reasoningDelta) {
442
+ result.reasoning += reasoningDelta;
443
+ onReasoningDelta?.(reasoningDelta);
444
+ }
436
445
  if (delta?.tool_calls) {
437
446
  for (const tc of delta.tool_calls) {
438
447
  let state = result.toolCalls.get(tc.index);
@@ -104,6 +104,8 @@ export type OpenAICompatChatChoiceMessage = {
104
104
  content?: string | null;
105
105
  tool_calls?: OpenAICompatToolCallWire[];
106
106
  refusal?: string | null;
107
+ reasoning_content?: string | null;
108
+ reasoning?: string | null;
107
109
  };
108
110
  export type OpenAICompatChatChoice = {
109
111
  index: number;
@@ -132,6 +134,8 @@ export type OpenAICompatStreamDelta = {
132
134
  };
133
135
  }>;
134
136
  refusal?: string | null;
137
+ reasoning_content?: string | null;
138
+ reasoning?: string | null;
135
139
  };
136
140
  export type OpenAICompatStreamChunkChoice = {
137
141
  index: number;
@@ -186,6 +190,8 @@ export type OpenAICompatMessage = {
186
190
  };
187
191
  export type OpenAICompatSSEResult = {
188
192
  text: string;
193
+ /** Accumulated reasoner-model output (`reasoning_content` / `reasoning` deltas). */
194
+ reasoning: string;
189
195
  toolCalls: Map<number, {
190
196
  id: string;
191
197
  name: string;
@@ -196,6 +202,7 @@ export type OpenAICompatSSEResult = {
196
202
  };
197
203
  export type OpenAICompatStreamChunk = {
198
204
  content: string;
205
+ reasoning?: string;
199
206
  } | {
200
207
  done: true;
201
208
  };
@@ -498,6 +498,7 @@ export type StreamOptions = {
498
498
  export type StreamResult = {
499
499
  stream: AsyncIterable<{
500
500
  content: string;
501
+ reasoning?: string;
501
502
  } | StreamNoOutputSentinel | {
502
503
  type: "audio";
503
504
  audio: AudioChunk;
@@ -16,12 +16,12 @@ import { OpenAIChatCompletionsProvider } from "./openaiChatCompletionsBase.js";
16
16
  * `@ai-sdk/openai-compatible` path this migration replaced. The base
17
17
  * client injects the literal "json" word the API requires for that mode.
18
18
  *
19
- * 2. Reasoning support — the opt-in `thinking` request param (non-reasoner
20
- * chat models) and `reasoning_content` surfacing (deepseek-reasoner / R1)
21
- * both require plumbing the thinking signal and the reasoning delta
22
- * through the native base client. That plumbing isn't in place yet, so
23
- * neither is wired here; it is tracked as a base-client follow-up. All
24
- * other behavior is preserved.
19
+ * 2. Reasoning support — `reasoning_content` (deepseek-reasoner / R1) is
20
+ * surfaced automatically by the native base client: streamed deltas
21
+ * arrive as `{ content: "", reasoning }` chunks and the non-streaming
22
+ * result carries `result.reasoning`. The opt-in `thinking` request
23
+ * param (non-reasoner chat models) still needs thinking-signal plumbing
24
+ * and is tracked as a follow-up. All other behavior is preserved.
25
25
  *
26
26
  * @see https://api-docs.deepseek.com
27
27
  */
@@ -27,12 +27,12 @@ const getDefaultDeepSeekModel = () => {
27
27
  * `@ai-sdk/openai-compatible` path this migration replaced. The base
28
28
  * client injects the literal "json" word the API requires for that mode.
29
29
  *
30
- * 2. Reasoning support — the opt-in `thinking` request param (non-reasoner
31
- * chat models) and `reasoning_content` surfacing (deepseek-reasoner / R1)
32
- * both require plumbing the thinking signal and the reasoning delta
33
- * through the native base client. That plumbing isn't in place yet, so
34
- * neither is wired here; it is tracked as a base-client follow-up. All
35
- * other behavior is preserved.
30
+ * 2. Reasoning support — `reasoning_content` (deepseek-reasoner / R1) is
31
+ * surfaced automatically by the native base client: streamed deltas
32
+ * arrive as `{ content: "", reasoning }` chunks and the non-streaming
33
+ * result carries `result.reasoning`. The opt-in `thinking` request
34
+ * param (non-reasoner chat models) still needs thinking-signal plumbing
35
+ * and is tracked as a follow-up. All other behavior is preserved.
36
36
  *
37
37
  * @see https://api-docs.deepseek.com
38
38
  */
@@ -14,7 +14,9 @@ declare const stripFieldFromJsonBody: (body: string, field: "reasoning_budget" |
14
14
  * Wraps NVIDIA's hosted (or self-hosted) inference endpoints.
15
15
  * Passes NIM-specific extras (top_k, min_p, repetition_penalty,
16
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.
17
+ * reasoning_content is surfaced automatically by the native base client
18
+ * (streamed as `{ content: "", reasoning }` chunks; `result.reasoning` on
19
+ * the non-streaming path); all other behavior is preserved.
18
20
  *
19
21
  * @see https://docs.api.nvidia.com/nim/reference/
20
22
  */
@@ -144,7 +144,9 @@ const getDefaultNimModel = () => {
144
144
  * Wraps NVIDIA's hosted (or self-hosted) inference endpoints.
145
145
  * Passes NIM-specific extras (top_k, min_p, repetition_penalty,
146
146
  * chat_template_kwargs.reasoning_budget) via adjustBuildBodyOptions.
147
- * reasoning_content surfacing is a pending base-client follow-up (not emitted natively yet); all other behavior is preserved.
147
+ * reasoning_content is surfaced automatically by the native base client
148
+ * (streamed as `{ content: "", reasoning }` chunks; `result.reasoning` on
149
+ * the non-streaming path); all other behavior is preserved.
148
150
  *
149
151
  * @see https://docs.api.nvidia.com/nim/reference/
150
152
  */
@@ -269,6 +269,13 @@ export class OpenAIChatCompletionsProvider extends BaseProvider {
269
269
  ? choice.message.content
270
270
  : "") ?? "";
271
271
  const content = [];
272
+ // Reasoner-model output (DeepSeek `reasoning_content`, gateway
273
+ // `reasoning`) becomes a V3 reasoning part ahead of the text part —
274
+ // GenerationHandler joins reasoning parts into `result.reasoning`.
275
+ const reasoningText = choice?.message?.reasoning_content ?? choice?.message?.reasoning;
276
+ if (typeof reasoningText === "string" && reasoningText.length > 0) {
277
+ content.push({ type: "reasoning", text: reasoningText });
278
+ }
272
279
  if (text.length > 0) {
273
280
  content.push({ type: "text", text });
274
281
  }
@@ -300,8 +307,13 @@ export class OpenAIChatCompletionsProvider extends BaseProvider {
300
307
  },
301
308
  outputTokens: {
302
309
  total: json.usage?.completion_tokens,
303
- text: json.usage?.completion_tokens,
304
- reasoning: undefined,
310
+ text: json.usage?.completion_tokens !== undefined &&
311
+ json.usage?.completion_tokens_details?.reasoning_tokens !==
312
+ undefined
313
+ ? json.usage.completion_tokens -
314
+ json.usage.completion_tokens_details.reasoning_tokens
315
+ : json.usage?.completion_tokens,
316
+ reasoning: json.usage?.completion_tokens_details?.reasoning_tokens,
305
317
  },
306
318
  },
307
319
  warnings: [],
@@ -584,6 +596,10 @@ export class OpenAIChatCompletionsProvider extends BaseProvider {
584
596
  }
585
597
  return parseSSEStream(res.body, (delta) => {
586
598
  args.pushChunk({ content: delta });
599
+ }, (reasoningDelta) => {
600
+ // Reasoning rides alongside an empty `content` so plain-text
601
+ // consumers (which only read chunk.content) are unaffected.
602
+ args.pushChunk({ content: "", reasoning: reasoningDelta });
587
603
  });
588
604
  }
589
605
  async executeToolBatch(args) {
@@ -35,7 +35,7 @@ export declare const messagesContainJsonWord: (messages: ReadonlyArray<OpenAICom
35
35
  export declare const ensureJsonWordInBody: (body: OpenAICompatChatRequest) => OpenAICompatChatRequest;
36
36
  export declare const requiresMaxCompletionTokens: (modelId: string) => boolean;
37
37
  export declare const buildBody: (args: OpenAICompatBuildBodyArgs) => OpenAICompatChatRequest;
38
- export declare const parseSSEStream: (body: ReadableStream<Uint8Array>, onTextDelta: (delta: string) => void) => Promise<OpenAICompatSSEResult>;
38
+ export declare const parseSSEStream: (body: ReadableStream<Uint8Array>, onTextDelta: (delta: string) => void, onReasoningDelta?: (delta: string) => void) => Promise<OpenAICompatSSEResult>;
39
39
  export declare const buildAPIError: (url: string, body: OpenAICompatChatRequest, res: Response) => Promise<Error>;
40
40
  export declare const createDeferredAnalytics: () => {
41
41
  usagePromise: Promise<{
@@ -399,9 +399,10 @@ export const buildBody = (args) => {
399
399
  }
400
400
  return body;
401
401
  };
402
- export const parseSSEStream = async (body, onTextDelta) => {
402
+ export const parseSSEStream = async (body, onTextDelta, onReasoningDelta) => {
403
403
  const result = {
404
404
  text: "",
405
+ reasoning: "",
405
406
  toolCalls: new Map(),
406
407
  finishReason: null,
407
408
  usage: undefined,
@@ -433,6 +434,14 @@ export const parseSSEStream = async (body, onTextDelta) => {
433
434
  result.text += delta.content;
434
435
  onTextDelta(delta.content);
435
436
  }
437
+ // Reasoner-model deltas: DeepSeek/NIM emit `reasoning_content`, some
438
+ // gateways emit `reasoning`. The AI SDK's openai-compatible wrapper
439
+ // surfaced these automatically; the native client must do the same.
440
+ const reasoningDelta = delta?.reasoning_content ?? delta?.reasoning;
441
+ if (reasoningDelta) {
442
+ result.reasoning += reasoningDelta;
443
+ onReasoningDelta?.(reasoningDelta);
444
+ }
436
445
  if (delta?.tool_calls) {
437
446
  for (const tc of delta.tool_calls) {
438
447
  let state = result.toolCalls.get(tc.index);
@@ -104,6 +104,8 @@ export type OpenAICompatChatChoiceMessage = {
104
104
  content?: string | null;
105
105
  tool_calls?: OpenAICompatToolCallWire[];
106
106
  refusal?: string | null;
107
+ reasoning_content?: string | null;
108
+ reasoning?: string | null;
107
109
  };
108
110
  export type OpenAICompatChatChoice = {
109
111
  index: number;
@@ -132,6 +134,8 @@ export type OpenAICompatStreamDelta = {
132
134
  };
133
135
  }>;
134
136
  refusal?: string | null;
137
+ reasoning_content?: string | null;
138
+ reasoning?: string | null;
135
139
  };
136
140
  export type OpenAICompatStreamChunkChoice = {
137
141
  index: number;
@@ -186,6 +190,8 @@ export type OpenAICompatMessage = {
186
190
  };
187
191
  export type OpenAICompatSSEResult = {
188
192
  text: string;
193
+ /** Accumulated reasoner-model output (`reasoning_content` / `reasoning` deltas). */
194
+ reasoning: string;
189
195
  toolCalls: Map<number, {
190
196
  id: string;
191
197
  name: string;
@@ -196,6 +202,7 @@ export type OpenAICompatSSEResult = {
196
202
  };
197
203
  export type OpenAICompatStreamChunk = {
198
204
  content: string;
205
+ reasoning?: string;
199
206
  } | {
200
207
  done: true;
201
208
  };
@@ -498,6 +498,7 @@ export type StreamOptions = {
498
498
  export type StreamResult = {
499
499
  stream: AsyncIterable<{
500
500
  content: string;
501
+ reasoning?: string;
501
502
  } | StreamNoOutputSentinel | {
502
503
  type: "audio";
503
504
  audio: AudioChunk;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@juspay/neurolink",
3
- "version": "9.68.20",
3
+ "version": "9.69.0",
4
4
  "packageManager": "pnpm@10.15.1",
5
5
  "description": "Universal AI Development Platform with working MCP integration, multi-provider support, voice (TTS/STT/realtime), and professional CLI. 58+ external MCP servers discoverable, multimodal file processing, RAG pipelines. Build, test, and deploy AI applications with 21+ providers: OpenAI, Anthropic, Google AI Studio, Google Vertex, AWS Bedrock, Azure OpenAI, Mistral, LiteLLM, SageMaker, Hugging Face, Ollama, OpenAI-compatible, OpenRouter, DeepSeek, NVIDIA NIM, LM Studio, llama.cpp, plus voice (OpenAI TTS, ElevenLabs, Deepgram, Azure Speech).",
6
6
  "author": {
@@ -102,6 +102,7 @@
102
102
  "test:image-gen": "npx tsx test/continuous-test-suite-image-gen-extras.ts",
103
103
  "test:ssrf": "npx tsx test/continuous-test-suite-ssrf.ts",
104
104
  "test:log-sanitize": "npx tsx test/continuous-test-suite-log-sanitize.ts",
105
+ "test:sse-client": "npx tsx test/continuous-test-suite-sse-client.ts",
105
106
  "test:stream-span": "npx tsx test/continuous-test-suite-stream-span.ts",
106
107
  "test:credentials": "npx tsx test/continuous-test-suite-credentials.ts",
107
108
  "test:dynamic": "npx tsx test/continuous-test-suite-dynamic.ts",
@@ -297,10 +298,8 @@
297
298
  },
298
299
  "dependencies": {
299
300
  "@ai-sdk/anthropic": "^3.0.50",
300
- "@ai-sdk/azure": "^3.0.38",
301
301
  "@ai-sdk/mistral": "^3.0.21",
302
302
  "@ai-sdk/openai": "^3.0.37",
303
- "@ai-sdk/openai-compatible": "^2.0.41",
304
303
  "@ai-sdk/provider": "^3.0.8",
305
304
  "@anthropic-ai/vertex-sdk": "^0.16.0",
306
305
  "@aws-sdk/client-bedrock": "^3.1000.0",
@@ -313,7 +312,6 @@
313
312
  "@google/genai": "^1.43.0",
314
313
  "@huggingface/inference": "^4.13.14",
315
314
  "@modelcontextprotocol/sdk": "^1.27.1",
316
- "@openrouter/ai-sdk-provider": "^2.2.3",
317
315
  "@opentelemetry/api-logs": "^0.214.0",
318
316
  "@opentelemetry/context-async-hooks": "^2.6.1",
319
317
  "@opentelemetry/core": "^2.6.0",