@juspay/neurolink 10.3.0 → 10.4.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.
Files changed (127) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/browser/neurolink.min.js +430 -417
  3. package/dist/cli/loop/optionsSchema.js +4 -0
  4. package/dist/constants/contextWindows.d.ts +24 -0
  5. package/dist/constants/contextWindows.js +50 -0
  6. package/dist/context/errorDetection.d.ts +6 -0
  7. package/dist/context/errorDetection.js +18 -0
  8. package/dist/context/stepBudgetGuard.d.ts +17 -3
  9. package/dist/context/stepBudgetGuard.js +53 -14
  10. package/dist/core/baseProvider.d.ts +12 -0
  11. package/dist/core/baseProvider.js +18 -0
  12. package/dist/core/modules/GenerationHandler.js +208 -42
  13. package/dist/core/modules/ToolsManager.d.ts +17 -0
  14. package/dist/core/modules/ToolsManager.js +99 -1
  15. package/dist/index.d.ts +1 -0
  16. package/dist/index.js +3 -0
  17. package/dist/knowledge/context.d.ts +18 -0
  18. package/dist/knowledge/context.js +91 -0
  19. package/dist/knowledge/defaults.d.ts +24 -0
  20. package/dist/knowledge/defaults.js +29 -0
  21. package/dist/knowledge/engine.d.ts +35 -0
  22. package/dist/knowledge/engine.js +179 -0
  23. package/dist/knowledge/index.d.ts +15 -0
  24. package/dist/knowledge/index.js +15 -0
  25. package/dist/knowledge/indexCache.d.ts +19 -0
  26. package/dist/knowledge/indexCache.js +109 -0
  27. package/dist/knowledge/knowledgeIndex.d.ts +41 -0
  28. package/dist/knowledge/knowledgeIndex.js +204 -0
  29. package/dist/knowledge/normalize.d.ts +32 -0
  30. package/dist/knowledge/normalize.js +74 -0
  31. package/dist/knowledge/resolve.d.ts +18 -0
  32. package/dist/knowledge/resolve.js +156 -0
  33. package/dist/knowledge/retrieval.d.ts +16 -0
  34. package/dist/knowledge/retrieval.js +221 -0
  35. package/dist/lib/constants/contextWindows.d.ts +24 -0
  36. package/dist/lib/constants/contextWindows.js +50 -0
  37. package/dist/lib/context/errorDetection.d.ts +6 -0
  38. package/dist/lib/context/errorDetection.js +18 -0
  39. package/dist/lib/context/stepBudgetGuard.d.ts +17 -3
  40. package/dist/lib/context/stepBudgetGuard.js +53 -14
  41. package/dist/lib/core/baseProvider.d.ts +12 -0
  42. package/dist/lib/core/baseProvider.js +18 -0
  43. package/dist/lib/core/modules/GenerationHandler.js +208 -42
  44. package/dist/lib/core/modules/ToolsManager.d.ts +17 -0
  45. package/dist/lib/core/modules/ToolsManager.js +99 -1
  46. package/dist/lib/files/fileTools.d.ts +1 -1
  47. package/dist/lib/index.d.ts +1 -0
  48. package/dist/lib/index.js +3 -0
  49. package/dist/lib/knowledge/context.d.ts +18 -0
  50. package/dist/lib/knowledge/context.js +92 -0
  51. package/dist/lib/knowledge/defaults.d.ts +24 -0
  52. package/dist/lib/knowledge/defaults.js +30 -0
  53. package/dist/lib/knowledge/engine.d.ts +35 -0
  54. package/dist/lib/knowledge/engine.js +180 -0
  55. package/dist/lib/knowledge/index.d.ts +15 -0
  56. package/dist/lib/knowledge/index.js +16 -0
  57. package/dist/lib/knowledge/indexCache.d.ts +19 -0
  58. package/dist/lib/knowledge/indexCache.js +110 -0
  59. package/dist/lib/knowledge/knowledgeIndex.d.ts +41 -0
  60. package/dist/lib/knowledge/knowledgeIndex.js +205 -0
  61. package/dist/lib/knowledge/normalize.d.ts +32 -0
  62. package/dist/lib/knowledge/normalize.js +75 -0
  63. package/dist/lib/knowledge/resolve.d.ts +18 -0
  64. package/dist/lib/knowledge/resolve.js +157 -0
  65. package/dist/lib/knowledge/retrieval.d.ts +16 -0
  66. package/dist/lib/knowledge/retrieval.js +222 -0
  67. package/dist/lib/mcp/toolDiscoveryService.js +59 -20
  68. package/dist/lib/neurolink.d.ts +14 -1
  69. package/dist/lib/neurolink.js +142 -12
  70. package/dist/lib/providers/litellm.d.ts +27 -19
  71. package/dist/lib/providers/litellm.js +171 -92
  72. package/dist/lib/providers/openaiChatCompletionsBase.d.ts +37 -1
  73. package/dist/lib/providers/openaiChatCompletionsBase.js +201 -33
  74. package/dist/lib/providers/openaiChatCompletionsClient.d.ts +23 -5
  75. package/dist/lib/providers/openaiChatCompletionsClient.js +94 -14
  76. package/dist/lib/proxy/proxyFetch.d.ts +17 -0
  77. package/dist/lib/proxy/proxyFetch.js +42 -4
  78. package/dist/lib/types/config.d.ts +12 -0
  79. package/dist/lib/types/conversation.d.ts +1 -1
  80. package/dist/lib/types/dynamic.d.ts +12 -0
  81. package/dist/lib/types/generate.d.ts +32 -2
  82. package/dist/lib/types/index.d.ts +1 -0
  83. package/dist/lib/types/index.js +1 -0
  84. package/dist/lib/types/knowledge.d.ts +342 -0
  85. package/dist/lib/types/knowledge.js +30 -0
  86. package/dist/lib/types/openaiCompatible.d.ts +2 -0
  87. package/dist/lib/types/providers.d.ts +9 -0
  88. package/dist/lib/types/stream.d.ts +14 -0
  89. package/dist/lib/utils/errorHandling.js +8 -2
  90. package/dist/lib/utils/schemaConversion.d.ts +16 -0
  91. package/dist/lib/utils/schemaConversion.js +165 -8
  92. package/dist/lib/utils/timeout.d.ts +22 -0
  93. package/dist/lib/utils/timeout.js +72 -12
  94. package/dist/lib/utils/tokenLimits.js +22 -0
  95. package/dist/lib/utils/toolCallRepair.d.ts +8 -0
  96. package/dist/lib/utils/toolCallRepair.js +4 -1
  97. package/dist/mcp/toolDiscoveryService.js +59 -20
  98. package/dist/neurolink.d.ts +14 -1
  99. package/dist/neurolink.js +142 -12
  100. package/dist/providers/litellm.d.ts +27 -19
  101. package/dist/providers/litellm.js +171 -92
  102. package/dist/providers/openaiChatCompletionsBase.d.ts +37 -1
  103. package/dist/providers/openaiChatCompletionsBase.js +201 -33
  104. package/dist/providers/openaiChatCompletionsClient.d.ts +23 -5
  105. package/dist/providers/openaiChatCompletionsClient.js +94 -14
  106. package/dist/proxy/proxyFetch.d.ts +17 -0
  107. package/dist/proxy/proxyFetch.js +42 -4
  108. package/dist/types/config.d.ts +12 -0
  109. package/dist/types/conversation.d.ts +1 -1
  110. package/dist/types/dynamic.d.ts +12 -0
  111. package/dist/types/generate.d.ts +32 -2
  112. package/dist/types/index.d.ts +1 -0
  113. package/dist/types/index.js +1 -0
  114. package/dist/types/knowledge.d.ts +342 -0
  115. package/dist/types/knowledge.js +29 -0
  116. package/dist/types/openaiCompatible.d.ts +2 -0
  117. package/dist/types/providers.d.ts +9 -0
  118. package/dist/types/stream.d.ts +14 -0
  119. package/dist/utils/errorHandling.js +8 -2
  120. package/dist/utils/schemaConversion.d.ts +16 -0
  121. package/dist/utils/schemaConversion.js +165 -8
  122. package/dist/utils/timeout.d.ts +22 -0
  123. package/dist/utils/timeout.js +72 -12
  124. package/dist/utils/tokenLimits.js +22 -0
  125. package/dist/utils/toolCallRepair.d.ts +8 -0
  126. package/dist/utils/toolCallRepair.js +4 -1
  127. package/package.json +4 -1
@@ -14,8 +14,72 @@
14
14
  * module is to be the native replacement for the AI SDK's OpenAI wrapper.
15
15
  */
16
16
  import { createParser } from "eventsource-parser";
17
- import { convertZodToJsonSchema } from "../utils/schemaConversion.js";
17
+ import { sanitizeToolName } from "../mcp/toolConverter.js";
18
+ import { convertZodToJsonSchema, normalizeWireToolSchema, } from "../utils/schemaConversion.js";
19
+ import { estimateTokens, TOKENS_PER_MESSAGE, } from "../utils/tokenEstimation.js";
18
20
  export const stripTrailingSlash = (s) => s.replace(/\/+$/, "");
21
+ // OpenAI-compatible wire tool names: first char letter/underscore (some
22
+ // chat templates treat a leading digit or hyphen as invalid identifiers),
23
+ // then letters/digits/underscore/hyphen, 64 chars total — exactly the
24
+ // pattern below, which mirrors sanitizeToolName's output alphabet. MCP
25
+ // servers can register names outside it (dots, colons, spaces); sent
26
+ // verbatim they make backends reject the tools block or emit tool_calls
27
+ // that no longer match the registry.
28
+ const WIRE_TOOL_NAME_RE = /^[a-zA-Z_][a-zA-Z0-9_-]{0,63}$/;
29
+ /**
30
+ * Build a bijective original ↔ wire tool-name map. Returns undefined when
31
+ * every name is already wire-valid (the common case — the wire then uses
32
+ * original names untouched and callers skip all mapping). Sanitized names
33
+ * that collide get a deterministic numeric suffix so the map stays
34
+ * invertible.
35
+ */
36
+ export const buildWireToolNameMaps = (names) => {
37
+ if (names.every((name) => WIRE_TOOL_NAME_RE.test(name))) {
38
+ return undefined;
39
+ }
40
+ const toWire = new Map();
41
+ const fromWire = new Map();
42
+ for (const name of names) {
43
+ let wire = WIRE_TOOL_NAME_RE.test(name) ? name : sanitizeToolName(name);
44
+ if (fromWire.has(wire)) {
45
+ let suffix = 2;
46
+ let candidate;
47
+ do {
48
+ const tail = `_${suffix}`;
49
+ candidate = `${wire.slice(0, 64 - tail.length)}${tail}`;
50
+ suffix++;
51
+ } while (fromWire.has(candidate));
52
+ wire = candidate;
53
+ }
54
+ toWire.set(name, wire);
55
+ fromWire.set(wire, name);
56
+ }
57
+ return { toWire, fromWire };
58
+ };
59
+ /**
60
+ * Estimate the input-token cost of a fully-built wire request (messages +
61
+ * tool definitions). Used by the per-request max_tokens fit against a
62
+ * RUNTIME-DISCOVERED context window — deliberately the same char-based
63
+ * estimator the budget pipeline uses, so both layers agree.
64
+ */
65
+ export const estimateWireTokens = (messages, tools, provider) => {
66
+ let total = 0;
67
+ for (const message of messages) {
68
+ const content = typeof message.content === "string"
69
+ ? message.content
70
+ : safeStringify(message.content);
71
+ total += estimateTokens(content, provider) + TOKENS_PER_MESSAGE;
72
+ // tool_calls only exists on the assistant variant of the message union.
73
+ const toolCalls = message.tool_calls;
74
+ if (toolCalls) {
75
+ total += estimateTokens(safeStringify(toolCalls), provider);
76
+ }
77
+ }
78
+ if (tools && tools.length > 0) {
79
+ total += estimateTokens(safeStringify(tools), provider);
80
+ }
81
+ return total;
82
+ };
19
83
  export const safeStringify = (value) => {
20
84
  try {
21
85
  return JSON.stringify(value ?? "");
@@ -132,7 +196,7 @@ export const convertContentForOpenAI = (content) => {
132
196
  }
133
197
  return out;
134
198
  };
135
- export const messageBuilderToOpenAI = (messages) => {
199
+ export const messageBuilderToOpenAI = (messages, toolNameToWire) => {
136
200
  const out = [];
137
201
  for (const msg of messages) {
138
202
  switch (msg.role) {
@@ -165,11 +229,14 @@ export const messageBuilderToOpenAI = (messages) => {
165
229
  }
166
230
  else if (p.type === "tool-call") {
167
231
  const tc = part;
232
+ // History tool-call names must match the wire `tools` block —
233
+ // forward-map when a wire-name map is in effect.
234
+ const historyName = tc.toolName ?? "";
168
235
  toolCalls.push({
169
236
  id: tc.toolCallId ?? "",
170
237
  type: "function",
171
238
  function: {
172
- name: tc.toolName ?? "",
239
+ name: toolNameToWire?.get(historyName) ?? historyName,
173
240
  arguments: stringifyToolInput(tc.input),
174
241
  },
175
242
  });
@@ -223,7 +290,7 @@ export const messageBuilderToOpenAI = (messages) => {
223
290
  }
224
291
  return out;
225
292
  };
226
- export const buildToolsForOpenAI = (tools) => {
293
+ export const buildToolsForOpenAI = (tools, toolNameToWire) => {
227
294
  const entries = Object.entries(tools);
228
295
  if (entries.length === 0) {
229
296
  return undefined;
@@ -235,14 +302,16 @@ export const buildToolsForOpenAI = (tools) => {
235
302
  // tool.inputSchema may be a Zod schema, an AI SDK jsonSchema() wrapper,
236
303
  // or plain JSON Schema — convertZodToJsonSchema normalizes all three.
237
304
  // Sending raw Zod internals (with `_def`) gets rejected by most
238
- // OpenAI-compatible endpoints.
305
+ // OpenAI-compatible endpoints. normalizeWireToolSchema then strips
306
+ // $schema/$defs indirection that proxied backends render into chat
307
+ // templates verbatim (degrading argument generation).
239
308
  const parameters = rawSchema
240
- ? convertZodToJsonSchema(rawSchema)
309
+ ? normalizeWireToolSchema(convertZodToJsonSchema(rawSchema))
241
310
  : { type: "object", properties: {} };
242
311
  out.push({
243
312
  type: "function",
244
313
  function: {
245
- name,
314
+ name: toolNameToWire?.get(name) ?? name,
246
315
  ...(t.description ? { description: t.description } : {}),
247
316
  parameters,
248
317
  },
@@ -254,7 +323,7 @@ export const buildToolsForOpenAI = (tools) => {
254
323
  // path that BaseProvider's `generate()` still drives via the AI SDK's
255
324
  // `generateText`. The streaming path doesn't need these — it consumes
256
325
  // NeuroLink-shaped options directly.
257
- export const v3ToolsToOpenAI = (tools) => {
326
+ export const v3ToolsToOpenAI = (tools, toolNameToWire) => {
258
327
  if (!tools || tools.length === 0) {
259
328
  return undefined;
260
329
  }
@@ -264,9 +333,12 @@ export const v3ToolsToOpenAI = (tools) => {
264
333
  out.push({
265
334
  type: "function",
266
335
  function: {
267
- name: t.name,
336
+ name: toolNameToWire?.get(t.name) ?? t.name,
268
337
  ...(t.description ? { description: t.description } : {}),
269
- parameters: t.inputSchema,
338
+ // The AI SDK serializes inputSchema to JSON Schema before
339
+ // doGenerate; normalize the wire form ($ref/$defs inlining,
340
+ // annotation stripping, nullable collapse) for proxied backends.
341
+ parameters: normalizeWireToolSchema(t.inputSchema),
270
342
  ...(t.strict !== undefined ? { strict: t.strict } : {}),
271
343
  },
272
344
  });
@@ -276,14 +348,19 @@ export const v3ToolsToOpenAI = (tools) => {
276
348
  }
277
349
  return out.length > 0 ? out : undefined;
278
350
  };
279
- export const v3ToolChoiceToOpenAI = (choice) => {
351
+ export const v3ToolChoiceToOpenAI = (choice, toolNameToWire) => {
280
352
  switch (choice.type) {
281
353
  case "auto":
282
354
  case "none":
283
355
  case "required":
284
356
  return choice.type;
285
357
  case "tool":
286
- return { type: "function", function: { name: choice.toolName } };
358
+ return {
359
+ type: "function",
360
+ function: {
361
+ name: toolNameToWire?.get(choice.toolName) ?? choice.toolName,
362
+ },
363
+ };
287
364
  }
288
365
  };
289
366
  export const v3ResponseFormatToOpenAI = (rf) => {
@@ -303,7 +380,7 @@ export const v3ResponseFormatToOpenAI = (rf) => {
303
380
  },
304
381
  };
305
382
  };
306
- export const mapNeuroLinkToolChoice = (choice) => {
383
+ export const mapNeuroLinkToolChoice = (choice, toolNameToWire) => {
307
384
  if (!choice) {
308
385
  return undefined;
309
386
  }
@@ -313,7 +390,10 @@ export const mapNeuroLinkToolChoice = (choice) => {
313
390
  if (typeof choice === "object" && choice !== null) {
314
391
  const c = choice;
315
392
  if (c.type === "tool" && c.toolName) {
316
- return { type: "function", function: { name: c.toolName } };
393
+ return {
394
+ type: "function",
395
+ function: { name: toolNameToWire?.get(c.toolName) ?? c.toolName },
396
+ };
317
397
  }
318
398
  }
319
399
  return undefined;
@@ -3,6 +3,23 @@
3
3
  * Supports HTTP/HTTPS, SOCKS4/5, authentication, and NO_PROXY bypass
4
4
  * Lightweight implementation extracted from research of major proxy packages
5
5
  */
6
+ /**
7
+ * Classify a fetch failure as a transient network error worth retrying.
8
+ *
9
+ * undici's `fetch()` wraps the real failure in `TypeError: fetch failed`
10
+ * with the actionable code (`ECONNRESET`, `UND_ERR_SOCKET`, ...) on
11
+ * `error.cause` — sometimes nested another level (e.g. SocketError inside
12
+ * a ConnectTimeoutError). Walk the cause chain so those are recognized;
13
+ * checking only the top-level error silently classified every undici
14
+ * connection death as non-retryable.
15
+ *
16
+ * Deliberately NOT retried: `UND_ERR_HEADERS_TIMEOUT` / `UND_ERR_BODY_TIMEOUT`
17
+ * — those already waited out undici's own long deadline (default 300s), and
18
+ * replaying them can triple a stall under the caller's wall-clock budget.
19
+ *
20
+ * Exported for direct coverage by the no-API test suite.
21
+ */
22
+ export declare function isTransientNetworkError(error: unknown): boolean;
6
23
  /**
7
24
  * Create a proxy-aware fetch function with enhanced capabilities
8
25
  * Supports HTTP/HTTPS, SOCKS4/5, authentication, and NO_PROXY bypass
@@ -79,6 +79,47 @@ function extractHostname(url) {
79
79
  return "[unknown]";
80
80
  }
81
81
  }
82
+ /** Error codes classified as transient (module-scope: the retry path is hot). */
83
+ const TRANSIENT_NETWORK_CODES = new Set([
84
+ "ECONNRESET",
85
+ "ETIMEDOUT",
86
+ "ECONNREFUSED",
87
+ "EPIPE",
88
+ "UND_ERR_SOCKET",
89
+ "UND_ERR_CONNECT_TIMEOUT",
90
+ ]);
91
+ /**
92
+ * Classify a fetch failure as a transient network error worth retrying.
93
+ *
94
+ * undici's `fetch()` wraps the real failure in `TypeError: fetch failed`
95
+ * with the actionable code (`ECONNRESET`, `UND_ERR_SOCKET`, ...) on
96
+ * `error.cause` — sometimes nested another level (e.g. SocketError inside
97
+ * a ConnectTimeoutError). Walk the cause chain so those are recognized;
98
+ * checking only the top-level error silently classified every undici
99
+ * connection death as non-retryable.
100
+ *
101
+ * Deliberately NOT retried: `UND_ERR_HEADERS_TIMEOUT` / `UND_ERR_BODY_TIMEOUT`
102
+ * — those already waited out undici's own long deadline (default 300s), and
103
+ * replaying them can triple a stall under the caller's wall-clock budget.
104
+ *
105
+ * Exported for direct coverage by the no-API test suite.
106
+ */
107
+ export function isTransientNetworkError(error) {
108
+ let current = error;
109
+ for (let depth = 0; depth < 5 && current; depth++) {
110
+ const err = current;
111
+ if (err.code && TRANSIENT_NETWORK_CODES.has(err.code)) {
112
+ return true;
113
+ }
114
+ if (err.message?.includes("socket hang up") ||
115
+ err.message?.includes("network socket disconnected") ||
116
+ err.message?.includes("other side closed")) {
117
+ return true;
118
+ }
119
+ current = err.cause;
120
+ }
121
+ return false;
122
+ }
82
123
  /**
83
124
  * Retry-aware fetch wrapper for transient network errors (ECONNRESET, ETIMEDOUT, socket hang up).
84
125
  * Protects all LLM API calls and token refreshes that go through createProxyFetch().
@@ -104,11 +145,8 @@ async function fetchWithRetry(url, init, maxRetries = 3, baseDelay = 500) {
104
145
  return response;
105
146
  }
106
147
  catch (error) {
148
+ const isRetryable = isTransientNetworkError(error);
107
149
  const err = error;
108
- const isRetryable = err?.code === "ECONNRESET" ||
109
- err?.code === "ETIMEDOUT" ||
110
- err?.message?.includes("socket hang up") ||
111
- err?.message?.includes("network socket disconnected");
112
150
  if (!isRetryable || attempt === maxRetries) {
113
151
  // Final failure — record on span and rethrow
114
152
  span.setAttribute("http.request.total_attempts", totalAttempts);
@@ -13,6 +13,7 @@ import type { ModelPoolConfig } from "./modelPool.js";
13
13
  import type { RequestRouter } from "./requestRouter.js";
14
14
  import type { ClassifierRouterConfig } from "./classifierRouter.js";
15
15
  import type { SkillsConfig } from "./skills.js";
16
+ import type { KnowledgeGroundingConfig } from "./knowledge.js";
16
17
  /**
17
18
  * Main NeuroLink configuration type
18
19
  */
@@ -130,6 +131,17 @@ export type NeurolinkConstructorConfig = {
130
131
  * Opt-in and fails open on read paths. See {@link SkillsConfig}.
131
132
  */
132
133
  skills?: SkillsConfig;
134
+ /**
135
+ * Knowledge grounding: lexical-first host-supplied knowledge retrieval. When
136
+ * enabled with at least one source, a deterministic in-memory retrieval runs
137
+ * before each generate()/stream() turn — independently of tool routing — and
138
+ * attaches a token-bounded, ephemeral knowledge block to the model call. No
139
+ * embeddings or vector store. Opt-in (`enabled: false` by default) and fails
140
+ * open: any retrieval failure leaves the turn ungrounded. Sources are fixed
141
+ * for the lifetime of the instance. See
142
+ * {@link KnowledgeGroundingConfig}.
143
+ */
144
+ knowledgeGrounding?: KnowledgeGroundingConfig;
133
145
  };
134
146
  /**
135
147
  * Configuration for MCP enhancement modules wired into generate()/stream() paths.
@@ -429,7 +429,7 @@ export type SessionMetadata = {
429
429
  * Report type for agentic loop reports
430
430
  * Identifies the platform or category of the report
431
431
  */
432
- export type AgenticLoopReportType = "META" | "GOOGLEADS" | "GOOGLEGA4" | "OTHER";
432
+ export type AgenticLoopReportType = "META" | "GOOGLEADS" | "GOOGLEGA4" | "SHOPIFY" | "BREEZE" | "OTHER";
433
433
  /**
434
434
  * Status of an agentic loop report
435
435
  */
@@ -7,6 +7,7 @@
7
7
  * @module types/dynamic
8
8
  */
9
9
  import type { AIProviderName } from "../constants/enums.js";
10
+ import type { KnowledgeRequestScope } from "./knowledge.js";
10
11
  /**
11
12
  * Context passed to context-aware dynamic argument functions.
12
13
  * `requestContext` is whatever the consumer passed as `dynamicContext` —
@@ -39,6 +40,17 @@ export type DynamicArgument<T> = T | (() => T) | (() => Promise<T>) | ((context:
39
40
  * instead of static values for context-aware resolution.
40
41
  */
41
42
  export type DynamicOptions = {
43
+ /**
44
+ * Opt this call into the knowledge grounding configured on the NeuroLink
45
+ * instance. This flag is intentionally static because grounding runs before
46
+ * dynamic arguments are resolved.
47
+ */
48
+ useKnowledgeGrounding?: boolean;
49
+ /**
50
+ * Enabled integrations used to scope knowledge retrieval for this turn.
51
+ * This scope is intentionally static for the same reason.
52
+ */
53
+ knowledgeContext?: KnowledgeRequestScope;
42
54
  model?: DynamicArgument<string>;
43
55
  provider?: DynamicArgument<AIProviderName | string>;
44
56
  temperature?: DynamicArgument<number>;
@@ -1,5 +1,6 @@
1
1
  import type { AIProviderName } from "../constants/enums.js";
2
2
  import type { RAGConfig } from "./rag.js";
3
+ import type { KnowledgeGroundingMetadata, KnowledgeRequestScope } from "./knowledge.js";
3
4
  import type { SkillsCallOptions } from "./skills.js";
4
5
  import type { AnalyticsData, TokenUsage } from "./analytics.js";
5
6
  import type { JsonValue } from "./common.js";
@@ -323,8 +324,15 @@ export type GenerateOptions = {
323
324
  * never the step-cap text. Unset = no turn-level deadline (the library
324
325
  * imposes no product policy).
325
326
  *
326
- * Enforced by the native Vertex loops (Gemini + Claude); AI-SDK-driven
327
- * providers currently ignore it.
327
+ * Enforced by the native Vertex loops (Gemini + Claude) AND the AI-SDK
328
+ * loop path (litellm and other OpenAI-compatible providers). On the AI-SDK
329
+ * path, an explicit `timeout` also engages the same wrap-up when
330
+ * `turnTimeoutMs` is unset. Once the wrap-up window begins (see
331
+ * `wrapupTimeLeadMs`), the loop forcibly sets `toolChoice: "none"` for the
332
+ * remaining steps — overriding any caller-supplied `toolChoice` or
333
+ * `prepareStep` tool selection — and appends an honest time message that a
334
+ * caller's `prepareStep` callback does not observe (it runs before the
335
+ * wrap-up nudge is applied). An honest partial beats a discarded turn.
328
336
  */
329
337
  turnTimeoutMs?: number;
330
338
  /**
@@ -340,6 +348,11 @@ export type GenerateOptions = {
340
348
  * next tool-result turn telling the model to consolidate what it has and
341
349
  * produce its final answer. Defaults to 120_000 when `turnTimeoutMs` is
342
350
  * set; ignored when it is not.
351
+ *
352
+ * On the AI-SDK loop path the lead is clamped to a quarter of the turn
353
+ * budget (so short budgets don't wrap up on step one) and wrap-up steps
354
+ * run with a forced `toolChoice: "none"` — see `turnTimeoutMs` for the
355
+ * exact override semantics.
343
356
  */
344
357
  wrapupTimeLeadMs?: number;
345
358
  /**
@@ -350,6 +363,8 @@ export type GenerateOptions = {
350
363
  toolTimeoutMs?: number;
351
364
  /** AbortSignal for external cancellation of the AI call */
352
365
  abortSignal?: AbortSignal;
366
+ /** Disable the schema-driven tool call repair mechanism (BZ-665). Default: false (repair enabled). */
367
+ disableToolCallRepair?: boolean;
353
368
  /**
354
369
  * Disable tool execution (including built-in tools)
355
370
  *
@@ -531,6 +546,17 @@ export type GenerateOptions = {
531
546
  onError?: OnErrorCallback;
532
547
  /** Pre-validated user context for the request */
533
548
  requestContext?: Record<string, unknown>;
549
+ /**
550
+ * Opt this generation call into the knowledge grounding configured on the
551
+ * NeuroLink instance. Defaults to `false` when omitted.
552
+ */
553
+ useKnowledgeGrounding?: boolean;
554
+ /**
555
+ * Enabled integrations used to scope knowledge retrieval for this turn.
556
+ * Used only when `useKnowledgeGrounding` is true and knowledge grounding is
557
+ * enabled on the NeuroLink instance.
558
+ */
559
+ knowledgeContext?: KnowledgeRequestScope;
534
560
  /** Raw auth token — validated by configured auth provider */
535
561
  auth?: {
536
562
  token: string;
@@ -676,6 +702,8 @@ export type GenerateStopReason = "completed" | "step-cap" | "context-cap" | "tim
676
702
  */
677
703
  export type GenerateResult = {
678
704
  content: string;
705
+ /** Knowledge-grounding diagnostics for this turn (present only when grounding ran). */
706
+ knowledge?: KnowledgeGroundingMetadata;
679
707
  /**
680
708
  * Parsed structured object when a `schema` was requested. Populated from
681
709
  * AI-SDK experimental_output, or from text-mode coercion (balanced-scan +
@@ -1015,6 +1043,8 @@ export type TextGenerationOptions = {
1015
1043
  /** AbortSignal for external cancellation of the AI call */
1016
1044
  abortSignal?: AbortSignal;
1017
1045
  disableTools?: boolean;
1046
+ /** Disable the schema-driven tool call repair mechanism (BZ-665). Default: false (repair enabled). */
1047
+ disableToolCallRepair?: boolean;
1018
1048
  maxSteps?: number;
1019
1049
  /** Include only these tools by name (whitelist). If set, only matching tools are available. */
1020
1050
  toolFilter?: string[];
@@ -28,6 +28,7 @@ export * from "./generate.js";
28
28
  export * from "./grounding.js";
29
29
  export * from "./guardrails.js";
30
30
  export * from "./hitl.js";
31
+ export * from "./knowledge.js";
31
32
  export * from "./livekit.js";
32
33
  export * from "./mcp.js";
33
34
  export * from "./mcpOutput.js";
@@ -29,6 +29,7 @@ export * from "./generate.js";
29
29
  export * from "./grounding.js";
30
30
  export * from "./guardrails.js";
31
31
  export * from "./hitl.js";
32
+ export * from "./knowledge.js";
32
33
  export * from "./livekit.js";
33
34
  export * from "./mcp.js";
34
35
  export * from "./mcpOutput.js";