@juspay/neurolink 10.2.0 → 10.2.2

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.
@@ -62,6 +62,21 @@ export declare abstract class OpenAIChatCompletionsProvider extends BaseProvider
62
62
  * downgraded `json_schema` to `json_object`. Subclasses replicate that here.
63
63
  */
64
64
  protected adjustResponseFormat(rf: OpenAICompatResponseFormat | undefined, _modelId: string): OpenAICompatResponseFormat | undefined;
65
+ /**
66
+ * When true (default), `response_format` is NOT sent on requests that carry
67
+ * tools. The AI SDK sets responseFormat on EVERY step of a tool loop, and
68
+ * generic/proxy backends (LiteLLM→vllm/GLM, openai-compatible, local
69
+ * servers) may silently honor it over tool calling — answering with
70
+ * final-shape JSON on step 1 instead of running the agentic loop. No error
71
+ * is raised, so the runtime tools↔schema conflict detector cannot catch it.
72
+ * The schema is still enforced post-hoc (GenerationHandler coerces the final
73
+ * text against it) — the same contract as the Gemini tools↔schema exclusion.
74
+ * Mirrors the streaming path, which never sends response_format.
75
+ *
76
+ * Backends with first-party support for tools + json_schema in one request
77
+ * (OpenAI, Azure OpenAI) override this to false.
78
+ */
79
+ protected suppressResponseFormatWithTools(): boolean;
65
80
  /**
66
81
  * Hook to adjust the fully-built wire request body before it is sent, on
67
82
  * both the streaming and non-streaming paths. Default identity. Override for
@@ -76,6 +76,23 @@ export class OpenAIChatCompletionsProvider extends BaseProvider {
76
76
  adjustResponseFormat(rf, _modelId) {
77
77
  return rf;
78
78
  }
79
+ /**
80
+ * When true (default), `response_format` is NOT sent on requests that carry
81
+ * tools. The AI SDK sets responseFormat on EVERY step of a tool loop, and
82
+ * generic/proxy backends (LiteLLM→vllm/GLM, openai-compatible, local
83
+ * servers) may silently honor it over tool calling — answering with
84
+ * final-shape JSON on step 1 instead of running the agentic loop. No error
85
+ * is raised, so the runtime tools↔schema conflict detector cannot catch it.
86
+ * The schema is still enforced post-hoc (GenerationHandler coerces the final
87
+ * text against it) — the same contract as the Gemini tools↔schema exclusion.
88
+ * Mirrors the streaming path, which never sends response_format.
89
+ *
90
+ * Backends with first-party support for tools + json_schema in one request
91
+ * (OpenAI, Azure OpenAI) override this to false.
92
+ */
93
+ suppressResponseFormatWithTools() {
94
+ return true;
95
+ }
79
96
  /**
80
97
  * Hook to adjust the fully-built wire request body before it is sent, on
81
98
  * both the streaming and non-streaming paths. Default identity. Override for
@@ -221,6 +238,7 @@ export class OpenAIChatCompletionsProvider extends BaseProvider {
221
238
  const adjustResponseFormat = this.adjustResponseFormat.bind(this);
222
239
  const adjustRequestBody = this.adjustRequestBody.bind(this);
223
240
  const adjustBodyAfter400 = this.adjustBodyAfter400.bind(this);
241
+ const suppressResponseFormatWithTools = this.suppressResponseFormatWithTools.bind(this);
224
242
  const getTimeoutForOptions = (opts) => this.getTimeout((opts ?? {}));
225
243
  return {
226
244
  specificationVersion: "v3",
@@ -229,7 +247,9 @@ export class OpenAIChatCompletionsProvider extends BaseProvider {
229
247
  supportedUrls: {},
230
248
  doGenerate: async (options) => {
231
249
  const baseMessages = messageBuilderToOpenAI(options.prompt);
232
- const responseFormat = options.responseFormat
250
+ const hasTools = Array.isArray(options.tools) && options.tools.length > 0;
251
+ const responseFormat = options.responseFormat &&
252
+ !(hasTools && suppressResponseFormatWithTools())
233
253
  ? adjustResponseFormat(v3ResponseFormatToOpenAI(options.responseFormat), modelId)
234
254
  : undefined;
235
255
  // ensureJsonWordInBody runs LAST — on the body after adjustRequestBody —
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@juspay/neurolink",
3
- "version": "10.2.0",
3
+ "version": "10.2.2",
4
4
  "packageManager": "pnpm@10.15.1",
5
5
  "description": "TypeScript AI SDK with 24+ LLM providers behind one consistent API. MCP-native (connect any MCP server), voice TTS/STT/realtime, RAG, agents, memory, context compaction. OpenAI · Anthropic · Gemini · Bedrock · Azure · Ollama · DeepSeek · NVIDIA NIM and more.",
6
6
  "author": {
@@ -147,7 +147,7 @@
147
147
  "test:system-messages:vitest": "pnpm exec vitest run test/systemMessages.test.ts",
148
148
  "test:tool-routing-semantic:vitest": "pnpm exec vitest run test/toolRoutingSemantic.test.ts",
149
149
  "test:tool-routing-semantic": "pnpm run test:tool-routing-semantic:vitest && npx tsx test/continuous-test-suite-tool-routing-semantic.ts",
150
- "test:unit": "pnpm run test:envguard && pnpm run test:bugfixes && pnpm run test:file-detector-extension && pnpm run test:mcp:infra && pnpm run test:mcp:bash && pnpm run test:mcp:limits && pnpm run test:mcp:spans && pnpm run test:autoresearch:redis && pnpm run test:unit:vitest && pnpm run test:tool-routing-cli:vitest && pnpm run test:tool-dedup:vitest && pnpm run test:model-pool:vitest && pnpm run test:system-messages:vitest && pnpm run test:tool-routing-semantic:vitest && pnpm run test:anthropic-tools-policy && pnpm run test:sagemaker-tools && pnpm run test:anthropic-multimodal && pnpm run test:excel-interop",
150
+ "test:unit": "pnpm run test:envguard && pnpm run test:bugfixes && pnpm run test:file-detector-extension && pnpm run test:mcp:infra && pnpm run test:mcp:bash && pnpm run test:mcp:limits && pnpm run test:mcp:spans && pnpm run test:autoresearch:redis && pnpm run test:unit:vitest && pnpm run test:tool-routing-cli:vitest && pnpm run test:tool-dedup:vitest && pnpm run test:model-pool:vitest && pnpm run test:litellm-context:vitest && pnpm run test:system-messages:vitest && pnpm run test:tool-routing-semantic:vitest && pnpm run test:anthropic-tools-policy && pnpm run test:sagemaker-tools && pnpm run test:anthropic-multimodal && pnpm run test:excel-interop",
151
151
  "// CI tier — live providers, runs only when API keys are present (test:credentials and test:dynamic make real provider calls when keys are set, so they live here, not in test:unit)": "",
152
152
  "test:live": "pnpm run test:providers && pnpm run test:mcp:http && pnpm run test:mcp:sdk && pnpm run test:mcp:cli && pnpm run test:observability && pnpm run test:context && pnpm run test:memory && pnpm run test:tool-reliability && pnpm run test:evaluation && pnpm run test:autoresearch && pnpm run test:credentials && pnpm run test:dynamic",
153
153
  "// CI tier — product output (image/video/TTS/PPT) — costs $$ per run": "",
@@ -208,7 +208,8 @@
208
208
  "quality:report": "pnpm run quality:metrics && echo 'Quality metrics saved to quality-metrics.json'",
209
209
  "pre-commit": "lint-staged",
210
210
  "pre-push": "pnpm run validate:commit && pnpm run validate:env && pnpm run validate && pnpm run test:ci",
211
- "check:all": "pnpm run lint && pnpm run format --check && pnpm run validate && pnpm run validate:commit"
211
+ "check:all": "pnpm run lint && pnpm run format --check && pnpm run validate && pnpm run validate:commit",
212
+ "test:litellm-context:vitest": "pnpm exec vitest run test/litellmContextWindows.test.ts"
212
213
  },
213
214
  "files": [
214
215
  "dist",