@juspay/neurolink 12.16.0 → 12.17.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.
@@ -20,6 +20,8 @@
20
20
  import { trace } from "@opentelemetry/api";
21
21
  import { getAvailableInputTokens, getRuntimeContextWindow, getRuntimeOutputCeiling, registerRuntimeContextWindow, } from "../constants/contextWindows.js";
22
22
  import { guardOpenAICompatConversation } from "../context/openaiCompatLoopGuard.js";
23
+ import { estimateTokens, serializeForEstimate, } from "../utils/tokenEstimation.js";
24
+ import { createNativeGenerateGuard } from "../context/nativeGenerateGuard.js";
23
25
  import { isContextOverflowError, parseProviderOverflowDetails, } from "../context/errorDetection.js";
24
26
  import { ContextBudgetExceededError } from "../context/errors.js";
25
27
  import { BaseProvider } from "../core/baseProvider.js";
@@ -899,6 +901,19 @@ export class OpenAIChatCompletionsProvider extends BaseProvider {
899
901
  // legal again on a vendor that refuses the two together.
900
902
  withTools = true) => runNativeGenerateLoop({
901
903
  doGenerate,
904
+ ...createNativeGenerateGuard({
905
+ provider: this.providerName,
906
+ availableInputTokens: getAvailableInputTokens(this.providerName, modelId, options.maxTokens ?? undefined),
907
+ // Runs on every step of the generate loop, so a cyclic or
908
+ // oversized tool schema must not throw the turn away. Shares the
909
+ // estimator's own serializer: its fallback over-reports, which
910
+ // makes the guard fire rather than silently size the overhead at
911
+ // nothing.
912
+ getFixedOverheadTokens: () => estimateTokens(serializeForEstimate({
913
+ tools: v3Tools,
914
+ responseFormat: format,
915
+ }), this.providerName),
916
+ }),
902
917
  conversation: conv,
903
918
  ...(withTools && v3Tools ? { tools: v3Tools } : {}),
904
919
  toolsRecord,
@@ -415,6 +415,16 @@ export type ToolConfig = {
415
415
  enableMCPTools?: boolean;
416
416
  /** Whether the bash command execution tool should be enabled (opt-in, defaults to false) */
417
417
  enableBashTool?: boolean;
418
+ /**
419
+ * Byte ceiling for the safety-net truncation `ToolsManager` applies to
420
+ * every direct/custom/external-MCP tool result before it reaches the AI
421
+ * SDK accumulator (BZ-666). Independent of `mcp.outputLimits`, which only
422
+ * governs external MCP results earlier in the pipeline via its own
423
+ * externalize-to-artifact-store strategy. Default: 51200 (50 KB) —
424
+ * unchanged from the previous hard-coded ceiling, so existing consumers
425
+ * see no behavior change unless they set this explicitly.
426
+ */
427
+ outputTruncationMaxBytes?: number;
418
428
  };
419
429
  /**
420
430
  * Backup metadata information
@@ -373,6 +373,15 @@ export type ToolOutputPreviewOptions = {
373
373
  headRatio?: number;
374
374
  /** Fraction of preview budget allocated to the tail (default: 0.75) */
375
375
  tailRatio?: number;
376
+ /**
377
+ * Override the omission notice spliced between head and tail. A string is
378
+ * used verbatim; a function receives the omitted byte count and returns
379
+ * the notice text. When omitted, the built-in default is used, which
380
+ * names the `retrieve_context` tool — pass this when that tool is not
381
+ * registered on the calling instance so the model isn't pointed at a tool
382
+ * that doesn't exist.
383
+ */
384
+ notice?: string | ((omittedBytes: number) => string);
376
385
  };
377
386
  /** Result of tool output preview generation. */
378
387
  export type ToolOutputPreviewResult = {
@@ -562,4 +571,10 @@ export type FileSummarizationServiceOptions = {
562
571
  provider?: string;
563
572
  model?: string;
564
573
  };
574
+ /** Per-turn configuration for reclaiming a native V3 conversation. */
575
+ export type NativeGenerateGuardConfig = {
576
+ provider: string;
577
+ availableInputTokens: number;
578
+ getFixedOverheadTokens: () => number;
579
+ };
565
580
  export {};
@@ -1604,6 +1604,15 @@ export type GenerateOptionsNormalized = GenerateOptions & {
1604
1604
  * `doGenerate`; the provider supplies the wire details.
1605
1605
  */
1606
1606
  export type NativeGenerateLoopArgs = {
1607
+ /** Observed usage for calibrating the next step against the last request. */
1608
+ observeUsage?: (usage: unknown) => void;
1609
+ /**
1610
+ * Per-step context reclaim, called before every model call with the
1611
+ * conversation as it now stands. Return a replacement to have the loop adopt
1612
+ * it, or undefined to leave it untouched. The provider owns this because the
1613
+ * reclaim has to understand its wire shape.
1614
+ */
1615
+ guardConversation?: (conversation: Array<Record<string, unknown>>) => Array<Record<string, unknown>> | undefined;
1607
1616
  doGenerate: (options: Record<string, unknown>) => Promise<Record<string, unknown>>;
1608
1617
  /** Conversation in the message-builder shape each doGenerate converts itself. */
1609
1618
  conversation: Array<Record<string, unknown>>;
@@ -47,6 +47,19 @@ export declare function getProviderMultiplier(provider?: string): number;
47
47
  * @returns Estimated token count
48
48
  */
49
49
  export declare function estimateTokens(text: string, provider?: string, isCode?: boolean): number;
50
+ /**
51
+ * Serialize an arbitrary value for estimation. Never throws: `JSON.stringify`
52
+ * raises RangeError once a value exceeds V8's max string length, and a tool
53
+ * argument blob is exactly the shape that gets there. A payload that large is
54
+ * charged at the fallback size rather than aborting the estimate (and with it
55
+ * the whole turn).
56
+ */
57
+ /**
58
+ * Serialize a value for token estimation. The fallback is deliberately huge:
59
+ * an estimator that cannot measure a value must over-report, so a budget guard
60
+ * fires rather than waving through content it failed to size.
61
+ */
62
+ export declare function serializeForEstimate(value: unknown): string;
50
63
  /**
51
64
  * Estimate token count for a single ChatMessage.
52
65
  * Includes message framing overhead.
@@ -93,7 +93,12 @@ export function estimateTokens(text, provider, isCode) {
93
93
  * charged at the fallback size rather than aborting the estimate (and with it
94
94
  * the whole turn).
95
95
  */
96
- function serializeForEstimate(value) {
96
+ /**
97
+ * Serialize a value for token estimation. The fallback is deliberately huge:
98
+ * an estimator that cannot measure a value must over-report, so a budget guard
99
+ * fires rather than waving through content it failed to size.
100
+ */
101
+ export function serializeForEstimate(value) {
97
102
  if (typeof value === "string") {
98
103
  return value;
99
104
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@juspay/neurolink",
3
- "version": "12.16.0",
3
+ "version": "12.17.0",
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": {
@@ -166,7 +166,9 @@
166
166
  "test:agents-live": "tsx test/continuous-test-agents-live.ts",
167
167
  "test:tool-routing-cli": "pnpm exec tsx test/continuous-test-suite-tool-routing-cli.ts",
168
168
  "test:tool-dedup": "pnpm exec tsx test/continuous-test-suite-tool-dedup.ts",
169
+ "test:tools-manager-truncation": "pnpm exec tsx test/continuous-test-suite-tools-manager-truncation.ts",
169
170
  "test:model-not-found-retryable": "pnpm exec tsx test/continuous-test-suite-model-not-found-retryable.ts",
171
+ "test:reasoning-parity-live": "pnpm exec tsx test/continuous-test-suite-reasoning-parity-live.ts",
170
172
  "test:ci": "pnpm run test && pnpm run test:client && pnpm run test:hitl",
171
173
  "// CI tier — fast, no live AI calls, safe for every commit (test:unit; also see the separate provider-safety-net CI job, which runs build + test:providers-mocked + test:provider-structure + test:error-classifier-contract on every PR)": "",
172
174
  "test:tool-routing": "pnpm exec tsx test/continuous-test-suite-tool-routing.ts",