@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.
- package/CHANGELOG.md +12 -0
- package/dist/browser/neurolink.min.js +430 -417
- package/dist/cli/loop/optionsSchema.js +4 -0
- package/dist/constants/contextWindows.d.ts +24 -0
- package/dist/constants/contextWindows.js +50 -0
- package/dist/context/errorDetection.d.ts +6 -0
- package/dist/context/errorDetection.js +18 -0
- package/dist/context/stepBudgetGuard.d.ts +17 -3
- package/dist/context/stepBudgetGuard.js +53 -14
- package/dist/core/baseProvider.d.ts +12 -0
- package/dist/core/baseProvider.js +18 -0
- package/dist/core/modules/GenerationHandler.js +208 -42
- package/dist/core/modules/ToolsManager.d.ts +17 -0
- package/dist/core/modules/ToolsManager.js +99 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +3 -0
- package/dist/knowledge/context.d.ts +18 -0
- package/dist/knowledge/context.js +91 -0
- package/dist/knowledge/defaults.d.ts +24 -0
- package/dist/knowledge/defaults.js +29 -0
- package/dist/knowledge/engine.d.ts +35 -0
- package/dist/knowledge/engine.js +179 -0
- package/dist/knowledge/index.d.ts +15 -0
- package/dist/knowledge/index.js +15 -0
- package/dist/knowledge/indexCache.d.ts +19 -0
- package/dist/knowledge/indexCache.js +109 -0
- package/dist/knowledge/knowledgeIndex.d.ts +41 -0
- package/dist/knowledge/knowledgeIndex.js +204 -0
- package/dist/knowledge/normalize.d.ts +32 -0
- package/dist/knowledge/normalize.js +74 -0
- package/dist/knowledge/resolve.d.ts +18 -0
- package/dist/knowledge/resolve.js +156 -0
- package/dist/knowledge/retrieval.d.ts +16 -0
- package/dist/knowledge/retrieval.js +221 -0
- package/dist/lib/constants/contextWindows.d.ts +24 -0
- package/dist/lib/constants/contextWindows.js +50 -0
- package/dist/lib/context/errorDetection.d.ts +6 -0
- package/dist/lib/context/errorDetection.js +18 -0
- package/dist/lib/context/stepBudgetGuard.d.ts +17 -3
- package/dist/lib/context/stepBudgetGuard.js +53 -14
- package/dist/lib/core/baseProvider.d.ts +12 -0
- package/dist/lib/core/baseProvider.js +18 -0
- package/dist/lib/core/modules/GenerationHandler.js +208 -42
- package/dist/lib/core/modules/ToolsManager.d.ts +17 -0
- package/dist/lib/core/modules/ToolsManager.js +99 -1
- package/dist/lib/files/fileTools.d.ts +1 -1
- package/dist/lib/index.d.ts +1 -0
- package/dist/lib/index.js +3 -0
- package/dist/lib/knowledge/context.d.ts +18 -0
- package/dist/lib/knowledge/context.js +92 -0
- package/dist/lib/knowledge/defaults.d.ts +24 -0
- package/dist/lib/knowledge/defaults.js +30 -0
- package/dist/lib/knowledge/engine.d.ts +35 -0
- package/dist/lib/knowledge/engine.js +180 -0
- package/dist/lib/knowledge/index.d.ts +15 -0
- package/dist/lib/knowledge/index.js +16 -0
- package/dist/lib/knowledge/indexCache.d.ts +19 -0
- package/dist/lib/knowledge/indexCache.js +110 -0
- package/dist/lib/knowledge/knowledgeIndex.d.ts +41 -0
- package/dist/lib/knowledge/knowledgeIndex.js +205 -0
- package/dist/lib/knowledge/normalize.d.ts +32 -0
- package/dist/lib/knowledge/normalize.js +75 -0
- package/dist/lib/knowledge/resolve.d.ts +18 -0
- package/dist/lib/knowledge/resolve.js +157 -0
- package/dist/lib/knowledge/retrieval.d.ts +16 -0
- package/dist/lib/knowledge/retrieval.js +222 -0
- package/dist/lib/mcp/toolDiscoveryService.js +59 -20
- package/dist/lib/neurolink.d.ts +14 -1
- package/dist/lib/neurolink.js +142 -12
- package/dist/lib/providers/litellm.d.ts +27 -19
- package/dist/lib/providers/litellm.js +171 -92
- package/dist/lib/providers/openaiChatCompletionsBase.d.ts +37 -1
- package/dist/lib/providers/openaiChatCompletionsBase.js +201 -33
- package/dist/lib/providers/openaiChatCompletionsClient.d.ts +23 -5
- package/dist/lib/providers/openaiChatCompletionsClient.js +94 -14
- package/dist/lib/proxy/proxyFetch.d.ts +17 -0
- package/dist/lib/proxy/proxyFetch.js +42 -4
- package/dist/lib/types/config.d.ts +12 -0
- package/dist/lib/types/conversation.d.ts +1 -1
- package/dist/lib/types/dynamic.d.ts +12 -0
- package/dist/lib/types/generate.d.ts +32 -2
- package/dist/lib/types/index.d.ts +1 -0
- package/dist/lib/types/index.js +1 -0
- package/dist/lib/types/knowledge.d.ts +342 -0
- package/dist/lib/types/knowledge.js +30 -0
- package/dist/lib/types/openaiCompatible.d.ts +2 -0
- package/dist/lib/types/providers.d.ts +9 -0
- package/dist/lib/types/stream.d.ts +14 -0
- package/dist/lib/utils/errorHandling.js +8 -2
- package/dist/lib/utils/schemaConversion.d.ts +16 -0
- package/dist/lib/utils/schemaConversion.js +165 -8
- package/dist/lib/utils/timeout.d.ts +22 -0
- package/dist/lib/utils/timeout.js +72 -12
- package/dist/lib/utils/tokenLimits.js +22 -0
- package/dist/lib/utils/toolCallRepair.d.ts +8 -0
- package/dist/lib/utils/toolCallRepair.js +4 -1
- package/dist/mcp/toolDiscoveryService.js +59 -20
- package/dist/neurolink.d.ts +14 -1
- package/dist/neurolink.js +142 -12
- package/dist/providers/litellm.d.ts +27 -19
- package/dist/providers/litellm.js +171 -92
- package/dist/providers/openaiChatCompletionsBase.d.ts +37 -1
- package/dist/providers/openaiChatCompletionsBase.js +201 -33
- package/dist/providers/openaiChatCompletionsClient.d.ts +23 -5
- package/dist/providers/openaiChatCompletionsClient.js +94 -14
- package/dist/proxy/proxyFetch.d.ts +17 -0
- package/dist/proxy/proxyFetch.js +42 -4
- package/dist/types/config.d.ts +12 -0
- package/dist/types/conversation.d.ts +1 -1
- package/dist/types/dynamic.d.ts +12 -0
- package/dist/types/generate.d.ts +32 -2
- package/dist/types/index.d.ts +1 -0
- package/dist/types/index.js +1 -0
- package/dist/types/knowledge.d.ts +342 -0
- package/dist/types/knowledge.js +29 -0
- package/dist/types/openaiCompatible.d.ts +2 -0
- package/dist/types/providers.d.ts +9 -0
- package/dist/types/stream.d.ts +14 -0
- package/dist/utils/errorHandling.js +8 -2
- package/dist/utils/schemaConversion.d.ts +16 -0
- package/dist/utils/schemaConversion.js +165 -8
- package/dist/utils/timeout.d.ts +22 -0
- package/dist/utils/timeout.js +72 -12
- package/dist/utils/tokenLimits.js +22 -0
- package/dist/utils/toolCallRepair.d.ts +8 -0
- package/dist/utils/toolCallRepair.js +4 -1
- package/package.json +4 -1
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { AIProviderName } from "../constants/enums.js";
|
|
2
2
|
import type { EvaluationData } from "./evaluation.js";
|
|
3
3
|
import type { RAGConfig } from "./rag.js";
|
|
4
|
+
import type { KnowledgeGroundingMetadata, KnowledgeRequestScope } from "./knowledge.js";
|
|
4
5
|
import type { SkillsCallOptions } from "./skills.js";
|
|
5
6
|
import type { AnalyticsData, ToolExecutionEvent, ToolExecutionSummary } from "../types/index.js";
|
|
6
7
|
import type { MiddlewareFactoryOptions, OnChunkCallback, OnErrorCallback, OnFinishCallback } from "../types/middleware.js";
|
|
@@ -169,6 +170,17 @@ export type StreamChunk = {
|
|
|
169
170
|
audio: TTSChunk;
|
|
170
171
|
};
|
|
171
172
|
export type StreamOptions = {
|
|
173
|
+
/**
|
|
174
|
+
* Opt this stream call into the knowledge grounding configured on the
|
|
175
|
+
* NeuroLink instance. Defaults to `false` when omitted.
|
|
176
|
+
*/
|
|
177
|
+
useKnowledgeGrounding?: boolean;
|
|
178
|
+
/**
|
|
179
|
+
* Enabled integrations used to scope knowledge retrieval for this turn.
|
|
180
|
+
* Used only when `useKnowledgeGrounding` is true and knowledge grounding is
|
|
181
|
+
* enabled on the NeuroLink instance.
|
|
182
|
+
*/
|
|
183
|
+
knowledgeContext?: KnowledgeRequestScope;
|
|
172
184
|
input: {
|
|
173
185
|
/** Prompt text. Optional for media-only modes (avatar, music) that are driven by uploaded files rather than a prompt. */
|
|
174
186
|
text?: string;
|
|
@@ -552,6 +564,8 @@ export type StreamOptions = {
|
|
|
552
564
|
* Future-ready for multi-modal outputs while maintaining text focus
|
|
553
565
|
*/
|
|
554
566
|
export type StreamResult = {
|
|
567
|
+
/** Knowledge-grounding diagnostics for this turn (present only when grounding ran). */
|
|
568
|
+
knowledge?: KnowledgeGroundingMetadata;
|
|
555
569
|
stream: AsyncIterable<{
|
|
556
570
|
content: string;
|
|
557
571
|
reasoning?: string;
|
|
@@ -1012,12 +1012,18 @@ export class ErrorFactory {
|
|
|
1012
1012
|
* Timeout wrapper for async operations
|
|
1013
1013
|
*/
|
|
1014
1014
|
export async function withTimeout(promise, timeoutMs, timeoutError) {
|
|
1015
|
+
let timer;
|
|
1015
1016
|
const timeoutPromise = new Promise((_, reject) => {
|
|
1016
|
-
setTimeout(() => {
|
|
1017
|
+
timer = setTimeout(() => {
|
|
1017
1018
|
reject(timeoutError || new Error(`Operation timed out after ${timeoutMs}ms`));
|
|
1018
1019
|
}, timeoutMs);
|
|
1019
1020
|
});
|
|
1020
|
-
|
|
1021
|
+
try {
|
|
1022
|
+
return await Promise.race([promise, timeoutPromise]);
|
|
1023
|
+
}
|
|
1024
|
+
finally {
|
|
1025
|
+
clearTimeout(timer);
|
|
1026
|
+
}
|
|
1021
1027
|
}
|
|
1022
1028
|
/**
|
|
1023
1029
|
* Retry mechanism for retriable operations
|
|
@@ -29,6 +29,22 @@ export declare function ensureNestedSchemaTypes(schema: Record<string, unknown>)
|
|
|
29
29
|
*/
|
|
30
30
|
export declare function convertZodToJsonSchema(zodSchema: ZodUnknownSchema, target?: "jsonSchema7" | "openApi3"): object;
|
|
31
31
|
export declare function normalizeJsonSchemaObject(schema: Record<string, unknown> | undefined | null): Record<string, unknown>;
|
|
32
|
+
/**
|
|
33
|
+
* Normalize a JSON Schema for the OpenAI chat-completions `tools` wire
|
|
34
|
+
* block. Generic proxied backends (LiteLLM → vllm/GLM/Qwen, local servers)
|
|
35
|
+
* render tool schemas into chat templates more or less verbatim, so `$ref`
|
|
36
|
+
* indirection, `$defs` containers, `$schema` annotations, and zod's
|
|
37
|
+
* nullable `anyOf` pattern all measurably degrade argument generation —
|
|
38
|
+
* this is the parity gap behind "the model can't find the right arguments"
|
|
39
|
+
* on litellm while the same tools work on Gemini/Claude native paths
|
|
40
|
+
* (which sanitize schemas before the wire).
|
|
41
|
+
*
|
|
42
|
+
* Pipeline: strip annotation keys → inline local `$ref`/`$defs`/
|
|
43
|
+
* `definitions` → collapse nullable variants → guarantee a top-level object
|
|
44
|
+
* shape. Identity for already-clean schemas; `description`, `required`,
|
|
45
|
+
* `enum`, and `default` — what models actually read — are always preserved.
|
|
46
|
+
*/
|
|
47
|
+
export declare function normalizeWireToolSchema(schema: unknown): Record<string, unknown>;
|
|
32
48
|
/**
|
|
33
49
|
* Check if a value is a Zod schema
|
|
34
50
|
*/
|
|
@@ -80,9 +80,11 @@ function safePercentDecode(segment) {
|
|
|
80
80
|
* - Circular reference detection to prevent infinite loops
|
|
81
81
|
*/
|
|
82
82
|
export function inlineJsonSchema(schema, definitions, visited = new Set(), rootSchema) {
|
|
83
|
-
// Use definitions from schema if not provided
|
|
83
|
+
// Use definitions from schema if not provided. Modern MCP servers and
|
|
84
|
+
// zod v4's native toJSONSchema emit the 2020-12 `$defs` keyword; older
|
|
85
|
+
// emitters use draft-07 `definitions`. Support both.
|
|
84
86
|
const defs = definitions ||
|
|
85
|
-
schema.definitions;
|
|
87
|
+
(schema.definitions ?? schema.$defs);
|
|
86
88
|
// Keep track of the root schema for deep ref resolution
|
|
87
89
|
const root = rootSchema || schema;
|
|
88
90
|
// Handle $ref at current level
|
|
@@ -94,10 +96,14 @@ export function inlineJsonSchema(schema, definitions, visited = new Set(), rootS
|
|
|
94
96
|
// Return a simple object placeholder for circular refs
|
|
95
97
|
return { type: "object" };
|
|
96
98
|
}
|
|
97
|
-
// Try simple definition lookup first (
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
99
|
+
// Try simple definition lookup first (#/definitions/SomeName or the
|
|
100
|
+
// 2020-12 #/$defs/SomeName form)
|
|
101
|
+
if (refPath.startsWith("#/definitions/") ||
|
|
102
|
+
refPath.startsWith("#/$defs/")) {
|
|
103
|
+
const defName = refPath
|
|
104
|
+
.replace("#/definitions/", "")
|
|
105
|
+
.replace("#/$defs/", "");
|
|
106
|
+
// Check if it's a simple definition name (no slashes after the prefix)
|
|
101
107
|
if (!defName.includes("/") && defs && defs[defName]) {
|
|
102
108
|
visited.add(refPath);
|
|
103
109
|
const resolved = inlineJsonSchema({ ...defs[defName] }, defs, visited, root);
|
|
@@ -124,8 +130,8 @@ export function inlineJsonSchema(schema, definitions, visited = new Set(), rootS
|
|
|
124
130
|
// Create result without $ref and definitions
|
|
125
131
|
const result = {};
|
|
126
132
|
for (const [key, value] of Object.entries(schema)) {
|
|
127
|
-
// Skip $ref and
|
|
128
|
-
if (key === "$ref" || key === "definitions") {
|
|
133
|
+
// Skip $ref and definition-container keys (both draft-07 and 2020-12)
|
|
134
|
+
if (key === "$ref" || key === "definitions" || key === "$defs") {
|
|
129
135
|
continue;
|
|
130
136
|
}
|
|
131
137
|
// Recursively process nested schemas
|
|
@@ -402,6 +408,157 @@ function ensureTypeField(schema) {
|
|
|
402
408
|
}
|
|
403
409
|
return schema;
|
|
404
410
|
}
|
|
411
|
+
/** JSON Schema keys whose values are themselves schemas (single). */
|
|
412
|
+
const SCHEMA_VALUE_KEYS = new Set([
|
|
413
|
+
"items",
|
|
414
|
+
"additionalProperties",
|
|
415
|
+
"not",
|
|
416
|
+
"if",
|
|
417
|
+
"then",
|
|
418
|
+
"else",
|
|
419
|
+
"contains",
|
|
420
|
+
"propertyNames",
|
|
421
|
+
]);
|
|
422
|
+
/** JSON Schema keys whose values are arrays of schemas. */
|
|
423
|
+
const SCHEMA_ARRAY_KEYS = new Set(["allOf", "anyOf", "oneOf", "prefixItems"]);
|
|
424
|
+
/** JSON Schema keys whose values are name → schema maps. */
|
|
425
|
+
const SCHEMA_MAP_KEYS = new Set([
|
|
426
|
+
"properties",
|
|
427
|
+
"patternProperties",
|
|
428
|
+
"$defs",
|
|
429
|
+
"definitions",
|
|
430
|
+
]);
|
|
431
|
+
/**
|
|
432
|
+
* Annotation keys that carry no validation semantics for a model and that
|
|
433
|
+
* generic OpenAI-compatible backends (vllm, GLM/Qwen chat templates, local
|
|
434
|
+
* servers) may render into the prompt verbatim, confusing argument
|
|
435
|
+
* generation. Removed only at SCHEMA positions — never inside data values
|
|
436
|
+
* like `default`, `const`, `enum` or `examples`, where `$id` etc. are
|
|
437
|
+
* legitimate payload.
|
|
438
|
+
*/
|
|
439
|
+
const SCHEMA_ANNOTATION_KEYS = new Set(["$schema", "$id", "$comment"]);
|
|
440
|
+
/** Walk schema positions only, dropping annotation-only keys. */
|
|
441
|
+
function stripSchemaAnnotations(schema) {
|
|
442
|
+
const result = {};
|
|
443
|
+
for (const [key, value] of Object.entries(schema)) {
|
|
444
|
+
if (SCHEMA_ANNOTATION_KEYS.has(key)) {
|
|
445
|
+
continue;
|
|
446
|
+
}
|
|
447
|
+
if (SCHEMA_VALUE_KEYS.has(key) &&
|
|
448
|
+
value &&
|
|
449
|
+
typeof value === "object" &&
|
|
450
|
+
!Array.isArray(value)) {
|
|
451
|
+
result[key] = stripSchemaAnnotations(value);
|
|
452
|
+
}
|
|
453
|
+
else if (SCHEMA_ARRAY_KEYS.has(key) && Array.isArray(value)) {
|
|
454
|
+
result[key] = value.map((item) => item && typeof item === "object" && !Array.isArray(item)
|
|
455
|
+
? stripSchemaAnnotations(item)
|
|
456
|
+
: item);
|
|
457
|
+
}
|
|
458
|
+
else if (SCHEMA_MAP_KEYS.has(key) &&
|
|
459
|
+
value &&
|
|
460
|
+
typeof value === "object" &&
|
|
461
|
+
!Array.isArray(value)) {
|
|
462
|
+
const map = {};
|
|
463
|
+
for (const [name, sub] of Object.entries(value)) {
|
|
464
|
+
map[name] =
|
|
465
|
+
sub && typeof sub === "object" && !Array.isArray(sub)
|
|
466
|
+
? stripSchemaAnnotations(sub)
|
|
467
|
+
: sub;
|
|
468
|
+
}
|
|
469
|
+
result[key] = map;
|
|
470
|
+
}
|
|
471
|
+
else {
|
|
472
|
+
result[key] = value;
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
return result;
|
|
476
|
+
}
|
|
477
|
+
/**
|
|
478
|
+
* Collapse the zod-emitted nullable pattern `anyOf/oneOf: [T, {type:"null"}]`
|
|
479
|
+
* into `{...T, type: [t, "null"]}`. Weaker OSS models handle a plain type
|
|
480
|
+
* array far better than composition keywords when choosing tool arguments.
|
|
481
|
+
* Conservative: only fires for exactly-two variants where the non-null
|
|
482
|
+
* variant has a primitive `type` string — everything else passes through.
|
|
483
|
+
*/
|
|
484
|
+
function collapseNullableVariants(schema) {
|
|
485
|
+
const result = {};
|
|
486
|
+
for (const [key, value] of Object.entries(schema)) {
|
|
487
|
+
if (SCHEMA_VALUE_KEYS.has(key) &&
|
|
488
|
+
value &&
|
|
489
|
+
typeof value === "object" &&
|
|
490
|
+
!Array.isArray(value)) {
|
|
491
|
+
result[key] = collapseNullableVariants(value);
|
|
492
|
+
}
|
|
493
|
+
else if (SCHEMA_ARRAY_KEYS.has(key) && Array.isArray(value)) {
|
|
494
|
+
result[key] = value.map((item) => item && typeof item === "object" && !Array.isArray(item)
|
|
495
|
+
? collapseNullableVariants(item)
|
|
496
|
+
: item);
|
|
497
|
+
}
|
|
498
|
+
else if (SCHEMA_MAP_KEYS.has(key) &&
|
|
499
|
+
value &&
|
|
500
|
+
typeof value === "object" &&
|
|
501
|
+
!Array.isArray(value)) {
|
|
502
|
+
const map = {};
|
|
503
|
+
for (const [name, sub] of Object.entries(value)) {
|
|
504
|
+
map[name] =
|
|
505
|
+
sub && typeof sub === "object" && !Array.isArray(sub)
|
|
506
|
+
? collapseNullableVariants(sub)
|
|
507
|
+
: sub;
|
|
508
|
+
}
|
|
509
|
+
result[key] = map;
|
|
510
|
+
}
|
|
511
|
+
else {
|
|
512
|
+
result[key] = value;
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
for (const compositionKey of ["anyOf", "oneOf"]) {
|
|
516
|
+
const variants = result[compositionKey];
|
|
517
|
+
if (!Array.isArray(variants) || variants.length !== 2) {
|
|
518
|
+
continue;
|
|
519
|
+
}
|
|
520
|
+
const isNullVariant = (v) => !!v &&
|
|
521
|
+
typeof v === "object" &&
|
|
522
|
+
v.type === "null";
|
|
523
|
+
const nullIndex = variants.findIndex(isNullVariant);
|
|
524
|
+
if (nullIndex === -1) {
|
|
525
|
+
continue;
|
|
526
|
+
}
|
|
527
|
+
const other = variants[1 - nullIndex];
|
|
528
|
+
if (!other ||
|
|
529
|
+
typeof other !== "object" ||
|
|
530
|
+
Array.isArray(other) ||
|
|
531
|
+
typeof other.type !== "string" ||
|
|
532
|
+
other.type === "null") {
|
|
533
|
+
continue;
|
|
534
|
+
}
|
|
535
|
+
// Merge: variant content + outer annotations (description etc.) win.
|
|
536
|
+
const { [compositionKey]: _dropped, ...outer } = result;
|
|
537
|
+
return { ...other, ...outer, type: [other.type, "null"] };
|
|
538
|
+
}
|
|
539
|
+
return result;
|
|
540
|
+
}
|
|
541
|
+
/**
|
|
542
|
+
* Normalize a JSON Schema for the OpenAI chat-completions `tools` wire
|
|
543
|
+
* block. Generic proxied backends (LiteLLM → vllm/GLM/Qwen, local servers)
|
|
544
|
+
* render tool schemas into chat templates more or less verbatim, so `$ref`
|
|
545
|
+
* indirection, `$defs` containers, `$schema` annotations, and zod's
|
|
546
|
+
* nullable `anyOf` pattern all measurably degrade argument generation —
|
|
547
|
+
* this is the parity gap behind "the model can't find the right arguments"
|
|
548
|
+
* on litellm while the same tools work on Gemini/Claude native paths
|
|
549
|
+
* (which sanitize schemas before the wire).
|
|
550
|
+
*
|
|
551
|
+
* Pipeline: strip annotation keys → inline local `$ref`/`$defs`/
|
|
552
|
+
* `definitions` → collapse nullable variants → guarantee a top-level object
|
|
553
|
+
* shape. Identity for already-clean schemas; `description`, `required`,
|
|
554
|
+
* `enum`, and `default` — what models actually read — are always preserved.
|
|
555
|
+
*/
|
|
556
|
+
export function normalizeWireToolSchema(schema) {
|
|
557
|
+
if (!schema || typeof schema !== "object" || Array.isArray(schema)) {
|
|
558
|
+
return { type: "object", properties: {} };
|
|
559
|
+
}
|
|
560
|
+
return ensureTypeField(collapseNullableVariants(inlineJsonSchema(stripSchemaAnnotations(schema))));
|
|
561
|
+
}
|
|
405
562
|
/**
|
|
406
563
|
* Check if a value is a Zod schema
|
|
407
564
|
*/
|
|
@@ -128,8 +128,30 @@ export declare function createTimeoutController(timeout: number | string | undef
|
|
|
128
128
|
* @returns Combined AbortSignal, or undefined if neither is present
|
|
129
129
|
*/
|
|
130
130
|
export declare function composeAbortSignals(externalSignal?: AbortSignal, timeoutSignal?: AbortSignal): AbortSignal | undefined;
|
|
131
|
+
/**
|
|
132
|
+
* Scoped variant of {@link composeAbortSignals} for per-step / per-request
|
|
133
|
+
* composition against a LONG-LIVED external signal (e.g. the generate-call
|
|
134
|
+
* signal inside a multi-step agent loop). `AbortSignal.any` keeps its source
|
|
135
|
+
* registration alive until the derived signal is GC'd, so composing per step
|
|
136
|
+
* accumulates listeners on the outer signal for the whole turn
|
|
137
|
+
* (MaxListenersExceededWarning at 10+ steps). This helper registers plain
|
|
138
|
+
* listeners instead and returns a `dispose()` that removes them the moment
|
|
139
|
+
* the step settles.
|
|
140
|
+
*/
|
|
141
|
+
export declare function composeAbortSignalsScoped(externalSignal?: AbortSignal, timeoutSignal?: AbortSignal): {
|
|
142
|
+
signal: AbortSignal | undefined;
|
|
143
|
+
dispose: () => void;
|
|
144
|
+
};
|
|
131
145
|
/**
|
|
132
146
|
* Merge abort signals (for combining user abort with timeout)
|
|
147
|
+
*
|
|
148
|
+
* Implemented via `AbortSignal.any` with a single once-listener forward, so
|
|
149
|
+
* no per-source listeners are left behind on long-lived input signals once
|
|
150
|
+
* the merged controller becomes unreachable (registrations are released with
|
|
151
|
+
* the derived signal). The previous implementation attached one permanent
|
|
152
|
+
* listener per source per call — repeated stream calls sharing one caller
|
|
153
|
+
* signal accumulated listeners for the life of that signal.
|
|
154
|
+
*
|
|
133
155
|
* @param signals - Array of abort signals to merge
|
|
134
156
|
* @returns Combined abort controller
|
|
135
157
|
*/
|
|
@@ -342,26 +342,86 @@ export function composeAbortSignals(externalSignal, timeoutSignal) {
|
|
|
342
342
|
}
|
|
343
343
|
return externalSignal ?? timeoutSignal;
|
|
344
344
|
}
|
|
345
|
+
/**
|
|
346
|
+
* Scoped variant of {@link composeAbortSignals} for per-step / per-request
|
|
347
|
+
* composition against a LONG-LIVED external signal (e.g. the generate-call
|
|
348
|
+
* signal inside a multi-step agent loop). `AbortSignal.any` keeps its source
|
|
349
|
+
* registration alive until the derived signal is GC'd, so composing per step
|
|
350
|
+
* accumulates listeners on the outer signal for the whole turn
|
|
351
|
+
* (MaxListenersExceededWarning at 10+ steps). This helper registers plain
|
|
352
|
+
* listeners instead and returns a `dispose()` that removes them the moment
|
|
353
|
+
* the step settles.
|
|
354
|
+
*/
|
|
355
|
+
export function composeAbortSignalsScoped(externalSignal, timeoutSignal) {
|
|
356
|
+
if (!externalSignal || !timeoutSignal) {
|
|
357
|
+
return { signal: externalSignal ?? timeoutSignal, dispose: () => { } };
|
|
358
|
+
}
|
|
359
|
+
const controller = new AbortController();
|
|
360
|
+
const sources = [externalSignal, timeoutSignal];
|
|
361
|
+
const listeners = [];
|
|
362
|
+
const dispose = () => {
|
|
363
|
+
for (const { source, listener } of listeners) {
|
|
364
|
+
source.removeEventListener("abort", listener);
|
|
365
|
+
}
|
|
366
|
+
listeners.length = 0;
|
|
367
|
+
};
|
|
368
|
+
const onAbort = (source) => {
|
|
369
|
+
if (!controller.signal.aborted) {
|
|
370
|
+
controller.abort(source.reason);
|
|
371
|
+
}
|
|
372
|
+
// Self-clean on abort: once the composed signal fired, no source
|
|
373
|
+
// listener has any work left — detach from the OTHER source too (the
|
|
374
|
+
// firing one auto-removed via `once`), so callers that only observe
|
|
375
|
+
// `signal.aborted` and never reach their dispose() leave nothing behind.
|
|
376
|
+
dispose();
|
|
377
|
+
};
|
|
378
|
+
for (const source of sources) {
|
|
379
|
+
const listener = () => onAbort(source);
|
|
380
|
+
source.addEventListener("abort", listener, { once: true });
|
|
381
|
+
listeners.push({ source, listener });
|
|
382
|
+
}
|
|
383
|
+
for (const source of sources) {
|
|
384
|
+
if (source.aborted) {
|
|
385
|
+
onAbort(source);
|
|
386
|
+
break;
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
return { signal: controller.signal, dispose };
|
|
390
|
+
}
|
|
345
391
|
/**
|
|
346
392
|
* Merge abort signals (for combining user abort with timeout)
|
|
393
|
+
*
|
|
394
|
+
* Implemented via `AbortSignal.any` with a single once-listener forward, so
|
|
395
|
+
* no per-source listeners are left behind on long-lived input signals once
|
|
396
|
+
* the merged controller becomes unreachable (registrations are released with
|
|
397
|
+
* the derived signal). The previous implementation attached one permanent
|
|
398
|
+
* listener per source per call — repeated stream calls sharing one caller
|
|
399
|
+
* signal accumulated listeners for the life of that signal.
|
|
400
|
+
*
|
|
347
401
|
* @param signals - Array of abort signals to merge
|
|
348
402
|
* @returns Combined abort controller
|
|
349
403
|
*/
|
|
350
404
|
export function mergeAbortSignals(signals) {
|
|
351
405
|
const controller = new AbortController();
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
}
|
|
358
|
-
});
|
|
359
|
-
}
|
|
360
|
-
if (signal?.aborted) {
|
|
361
|
-
controller.abort(signal.reason);
|
|
362
|
-
break;
|
|
363
|
-
}
|
|
406
|
+
const active = signals.filter((s) => s !== undefined);
|
|
407
|
+
const aborted = active.find((s) => s.aborted);
|
|
408
|
+
if (aborted) {
|
|
409
|
+
controller.abort(aborted.reason);
|
|
410
|
+
return controller;
|
|
364
411
|
}
|
|
412
|
+
if (active.length === 0) {
|
|
413
|
+
return controller;
|
|
414
|
+
}
|
|
415
|
+
const merged = AbortSignal.any(active);
|
|
416
|
+
merged.addEventListener("abort", () => {
|
|
417
|
+
if (!controller.signal.aborted) {
|
|
418
|
+
controller.abort(merged.reason);
|
|
419
|
+
}
|
|
420
|
+
}, { once: true });
|
|
421
|
+
// Pin the derived signal to the returned controller: sources hold only
|
|
422
|
+
// weak refs to `any()` dependents, so without this strong ref the derived
|
|
423
|
+
// signal (and the forward listener with it) could be GC'd before firing.
|
|
424
|
+
controller.__nlMergedSignal = merged;
|
|
365
425
|
return controller;
|
|
366
426
|
}
|
|
367
427
|
//# sourceMappingURL=timeout.js.map
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
* Provider-specific token limit utilities
|
|
3
3
|
* Provides safe maxTokens values based on provider and model capabilities
|
|
4
4
|
*/
|
|
5
|
+
import { getRuntimeOutputCeiling } from "../constants/contextWindows.js";
|
|
5
6
|
import { PROVIDER_MAX_TOKENS } from "../core/constants.js";
|
|
6
7
|
import { logger } from "./logger.js";
|
|
7
8
|
import { hasRestrictedOutputLimit, RESTRICTED_OUTPUT_TOKEN_LIMIT, } from "./modelDetection.js";
|
|
@@ -34,6 +35,27 @@ export function getSafeMaxTokens(provider, model, requestedMaxTokens) {
|
|
|
34
35
|
// Otherwise, use the requested value (it's within limits, including 0)
|
|
35
36
|
return requestedMaxTokens;
|
|
36
37
|
}
|
|
38
|
+
// Runtime-discovered output ceiling (e.g. LiteLLM /model/info
|
|
39
|
+
// max_output_tokens): the serving infrastructure's own number for the
|
|
40
|
+
// deployed model, authoritative over the static per-provider table. This
|
|
41
|
+
// both clamps over-large requests to the real cap AND replaces the static
|
|
42
|
+
// provider default for callers that pass no maxTokens — the litellm
|
|
43
|
+
// blanket default (128000) is a context-window-sized value that slashed
|
|
44
|
+
// usable input on total-context backends. Checked AFTER the
|
|
45
|
+
// restricted-model branch so hard caps proven at the origin API (Gemini 3
|
|
46
|
+
// / image models) still win over a proxy that over-advertises them.
|
|
47
|
+
const runtimeCeiling = getRuntimeOutputCeiling(provider, model);
|
|
48
|
+
if (runtimeCeiling !== undefined) {
|
|
49
|
+
if (requestedMaxTokens === undefined || requestedMaxTokens === null) {
|
|
50
|
+
return runtimeCeiling;
|
|
51
|
+
}
|
|
52
|
+
if (requestedMaxTokens > runtimeCeiling) {
|
|
53
|
+
logger.warn(`Requested maxTokens ${requestedMaxTokens} exceeds the advertised ` +
|
|
54
|
+
`${provider}/${model} output ceiling of ${runtimeCeiling}. Using ${runtimeCeiling} instead.`);
|
|
55
|
+
return runtimeCeiling;
|
|
56
|
+
}
|
|
57
|
+
return requestedMaxTokens;
|
|
58
|
+
}
|
|
37
59
|
// Get provider-specific limits
|
|
38
60
|
const providerLimits = PROVIDER_MAX_TOKENS[provider];
|
|
39
61
|
if (!providerLimits) {
|
|
@@ -4,3 +4,11 @@ import type { ToolCallRepairFunction, ToolSet } from "../types/index.js";
|
|
|
4
4
|
* Fully dynamic — reads the tool schema at repair time, no configuration needed.
|
|
5
5
|
*/
|
|
6
6
|
export declare function createToolCallRepair(): ToolCallRepairFunction<ToolSet>;
|
|
7
|
+
/**
|
|
8
|
+
* Coerce a value to match the expected schema type.
|
|
9
|
+
* Handles: string→number, JSON string→object, JSON string→array, value→[value].
|
|
10
|
+
* Exported for reuse by the MCP-layer parameter validator
|
|
11
|
+
* (toolDiscoveryService), which coerces before rejecting so a recoverable
|
|
12
|
+
* mismatch doesn't cost the agent loop a full model round-trip.
|
|
13
|
+
*/
|
|
14
|
+
export declare function coerceType(value: unknown, propSchema: Record<string, unknown>): unknown;
|
|
@@ -173,8 +173,11 @@ function findMatchingKey(inputKey, schemaKeys) {
|
|
|
173
173
|
/**
|
|
174
174
|
* Coerce a value to match the expected schema type.
|
|
175
175
|
* Handles: string→number, JSON string→object, JSON string→array, value→[value].
|
|
176
|
+
* Exported for reuse by the MCP-layer parameter validator
|
|
177
|
+
* (toolDiscoveryService), which coerces before rejecting so a recoverable
|
|
178
|
+
* mismatch doesn't cost the agent loop a full model round-trip.
|
|
176
179
|
*/
|
|
177
|
-
function coerceType(value, propSchema) {
|
|
180
|
+
export function coerceType(value, propSchema) {
|
|
178
181
|
const expectedType = propSchema.type;
|
|
179
182
|
if (!expectedType || value === null || value === undefined) {
|
|
180
183
|
return value;
|
|
@@ -9,6 +9,7 @@ import { globalCircuitBreakerManager, CircuitBreakerOpenError, } from "./mcpCirc
|
|
|
9
9
|
import { isObject, isNullish } from "../utils/typeUtils.js";
|
|
10
10
|
import { validateToolName, validateToolDescription, } from "../utils/parameterValidation.js";
|
|
11
11
|
import { withTimeout } from "../utils/errorHandling.js";
|
|
12
|
+
import { coerceType } from "../utils/toolCallRepair.js";
|
|
12
13
|
import { extractMcpErrorText } from "../utils/mcpErrorText.js";
|
|
13
14
|
import { SpanKind, SpanStatusCode } from "@opentelemetry/api";
|
|
14
15
|
import { tracers } from "../telemetry/tracers.js";
|
|
@@ -416,12 +417,16 @@ export class ToolDiscoveryService extends EventEmitter {
|
|
|
416
417
|
if (!toolInfo.isAvailable) {
|
|
417
418
|
throw new Error(`Tool '${toolName}' is not available`);
|
|
418
419
|
}
|
|
419
|
-
// Validate input parameters if requested
|
|
420
|
+
// Validate input parameters if requested. Validation coerces
|
|
421
|
+
// recoverable mismatches (numeric strings for number params, "true"
|
|
422
|
+
// for booleans, JSON-encoded objects/arrays) instead of rejecting —
|
|
423
|
+
// a rejection here costs the agent loop a full model round-trip.
|
|
424
|
+
let effectiveParameters = parameters;
|
|
420
425
|
if (options.validateInput !== false) {
|
|
421
|
-
this.validateToolParameters(toolInfo, parameters);
|
|
426
|
+
effectiveParameters = this.validateToolParameters(toolInfo, parameters);
|
|
422
427
|
}
|
|
423
428
|
mcpLogger.debug(`[ToolDiscoveryService] Executing tool: ${toolName} on ${serverId}`, {
|
|
424
|
-
parameters,
|
|
429
|
+
parameters: effectiveParameters,
|
|
425
430
|
});
|
|
426
431
|
// Create circuit breaker for tool execution
|
|
427
432
|
const effectiveTimeout = options.timeout || DEFAULT_TOOL_TIMEOUT;
|
|
@@ -448,16 +453,22 @@ export class ToolDiscoveryService extends EventEmitter {
|
|
|
448
453
|
"gen_ai.tool.name": toolName,
|
|
449
454
|
"gen_ai.request": safeJsonStringify({
|
|
450
455
|
name: toolName,
|
|
451
|
-
arguments: redactForPreview(
|
|
456
|
+
arguments: redactForPreview(effectiveParameters),
|
|
452
457
|
}, 2048),
|
|
453
458
|
},
|
|
454
459
|
}, async (callSpan) => {
|
|
455
460
|
try {
|
|
456
461
|
const timeout = effectiveTimeout;
|
|
462
|
+
// Pass the timeout as MCP RequestOptions too: without it the
|
|
463
|
+
// SDK applies its own DEFAULT_REQUEST_TIMEOUT_MSEC (60s), so a
|
|
464
|
+
// configured server timeout above 60s never took effect — the
|
|
465
|
+
// SDK aborted first. The SDK timeout also cancels the transport
|
|
466
|
+
// request and sends a cancellation notification, which the
|
|
467
|
+
// outer Promise.race below (kept as a backstop) cannot do.
|
|
457
468
|
const callResult = await withTimeout(client.callTool({
|
|
458
469
|
name: toolName,
|
|
459
|
-
arguments:
|
|
460
|
-
}), timeout, new Error(`Tool execution timeout: ${toolName}`));
|
|
470
|
+
arguments: effectiveParameters,
|
|
471
|
+
}, undefined, { timeout: effectiveTimeout }), timeout, new Error(`Tool execution timeout: ${toolName}`));
|
|
461
472
|
// Curator P0-1/P0-2: the MCP client does NOT throw on protocol
|
|
462
473
|
// errors — it returns { isError: true, content: [...] }. Detect
|
|
463
474
|
// that pattern so the span status reflects reality.
|
|
@@ -603,25 +614,45 @@ export class ToolDiscoveryService extends EventEmitter {
|
|
|
603
614
|
*/
|
|
604
615
|
validateToolParameters(toolInfo, parameters) {
|
|
605
616
|
if (!toolInfo.inputSchema) {
|
|
606
|
-
return; // No schema to validate against
|
|
617
|
+
return parameters; // No schema to validate against
|
|
607
618
|
}
|
|
608
|
-
// Basic validation - check required properties
|
|
609
619
|
const schema = toolInfo.inputSchema;
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
//
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
620
|
+
const properties = schema.properties && typeof schema.properties === "object"
|
|
621
|
+
? schema.properties
|
|
622
|
+
: {};
|
|
623
|
+
const requiredProps = Array.isArray(schema.required)
|
|
624
|
+
? schema.required.filter((r) => typeof r === "string")
|
|
625
|
+
: [];
|
|
626
|
+
// The thrown message is fed back to the MODEL as the tool result, so it
|
|
627
|
+
// restates the full contract — a bare "missing X" made weaker models
|
|
628
|
+
// guess again and burn another loop step per attempt.
|
|
629
|
+
const contract = () => Object.entries(properties)
|
|
630
|
+
.map(([key, prop]) => `${key}${requiredProps.includes(key) ? "" : "?"}: ${prop.type ?? "any"}`)
|
|
631
|
+
.join(", ");
|
|
632
|
+
// Basic validation - check required properties
|
|
633
|
+
const missing = requiredProps.filter((prop) => !(prop in parameters));
|
|
634
|
+
if (missing.length > 0) {
|
|
635
|
+
throw new Error(`Missing required parameter${missing.length > 1 ? "s" : ""}: ${missing.join(", ")}. ` +
|
|
636
|
+
`Expected arguments: { ${contract()} }; received keys: [${Object.keys(parameters).join(", ")}]`);
|
|
637
|
+
}
|
|
638
|
+
// Type validation for properties — coerce recoverable mismatches first
|
|
639
|
+
// (numeric strings, "true"/"false", JSON-encoded objects/arrays) so a
|
|
640
|
+
// sloppy-but-unambiguous call executes instead of failing back to the
|
|
641
|
+
// model. Only genuinely wrong types still throw.
|
|
642
|
+
let coerced;
|
|
643
|
+
for (const [propName, propSchema] of Object.entries(properties)) {
|
|
644
|
+
if (propName in parameters) {
|
|
645
|
+
const originalValue = parameters[propName];
|
|
646
|
+
const coercedValue = coerceType(originalValue, propSchema);
|
|
647
|
+
if (coercedValue !== originalValue) {
|
|
648
|
+
mcpLogger.debug(`[ToolDiscoveryService] Coerced parameter '${propName}' for tool '${toolInfo.name}': ${typeof originalValue} → ${typeof coercedValue}`);
|
|
649
|
+
coerced = coerced ?? { ...parameters };
|
|
650
|
+
coerced[propName] = coercedValue;
|
|
622
651
|
}
|
|
652
|
+
this.validateParameterType(propName, (coerced ? coerced[propName] : originalValue), propSchema);
|
|
623
653
|
}
|
|
624
654
|
}
|
|
655
|
+
return coerced ?? parameters;
|
|
625
656
|
}
|
|
626
657
|
/**
|
|
627
658
|
* Validate parameter type
|
|
@@ -643,6 +674,14 @@ export class ToolDiscoveryService extends EventEmitter {
|
|
|
643
674
|
throw new Error(`Parameter '${name}' must be a number, got ${actualType}`);
|
|
644
675
|
}
|
|
645
676
|
break;
|
|
677
|
+
case "integer":
|
|
678
|
+
// coerceType treats "integer" as distinct from "number"; without
|
|
679
|
+
// this case an uncoercible value ("3.7", "abc") passed through to
|
|
680
|
+
// the MCP server unvalidated.
|
|
681
|
+
if (actualType !== "number" || !Number.isInteger(value)) {
|
|
682
|
+
throw new Error(`Parameter '${name}' must be an integer, got ${actualType === "number" ? String(value) : actualType}`);
|
|
683
|
+
}
|
|
684
|
+
break;
|
|
646
685
|
case "boolean":
|
|
647
686
|
if (actualType !== "boolean") {
|
|
648
687
|
throw new Error(`Parameter '${name}' must be a boolean, got ${actualType}`);
|
package/dist/neurolink.d.ts
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* Uses real MCP infrastructure for tool discovery and execution.
|
|
7
7
|
*/
|
|
8
8
|
import type { AgentDefinition, AgentNetworkConfig, NetworkExecutionInput, NetworkExecutionOptions, NetworkExecutionResult, NetworkStreamChunk } from "./types/index.js";
|
|
9
|
-
import type { CompactionConfig, CompactionResult, SpanData, ObservabilityConfig, MetricsSummary, MCPToolAnnotations, TraceView, AuthenticatedContext, AuthProvider, JsonObject, NeuroLinkEvents, TypedEventEmitter, MCPEnhancementsConfig, NeuroLinkAuthConfig, NeurolinkConstructorConfig, ChatMessage, ExternalMCPOperationResult, ExternalMCPServerInstance, ExternalMCPToolInfo, GenerateOptions, GenerateResult, ProviderStatus, TextGenerationOptions, TextGenerationResult, MCPExecutableTool, MCPServerInfo, MCPStatus, StreamOptions, StreamResult, ToolExecutionContext, ToolExecutionSummary, ToolInfo, ToolRegistrationOptions, BatchOperationResult, StreamGenerationEndContext, ToolRoutingServerDescriptor, ToolDedupConfig, ToolConfig } from "./types/index.js";
|
|
9
|
+
import type { CompactionConfig, CompactionResult, SpanData, ObservabilityConfig, MetricsSummary, MCPToolAnnotations, TraceView, AuthenticatedContext, AuthProvider, JsonObject, NeuroLinkEvents, TypedEventEmitter, MCPEnhancementsConfig, NeuroLinkAuthConfig, NeurolinkConstructorConfig, ChatMessage, ExternalMCPOperationResult, ExternalMCPServerInstance, ExternalMCPToolInfo, GenerateOptions, GenerateResult, ProviderStatus, TextGenerationOptions, TextGenerationResult, MCPExecutableTool, MCPServerInfo, MCPStatus, StreamOptions, StreamResult, ToolExecutionContext, ToolExecutionSummary, ToolInfo, ToolRegistrationOptions, BatchOperationResult, StreamGenerationEndContext, ToolRoutingServerDescriptor, ToolDedupConfig, ToolConfig, KnowledgeEngineStatus } from "./types/index.js";
|
|
10
10
|
import { ConversationMemoryManager } from "./core/conversationMemoryManager.js";
|
|
11
11
|
import type { RedisConversationMemoryManager } from "./core/redisConversationMemoryManager.js";
|
|
12
12
|
import { ExternalServerManager } from "./mcp/externalServerManager.js";
|
|
@@ -107,6 +107,7 @@ export declare class NeuroLink {
|
|
|
107
107
|
private toolRoutingConfig?;
|
|
108
108
|
private toolRoutingCacheInstance?;
|
|
109
109
|
private toolRoutingVectorCache?;
|
|
110
|
+
private knowledgeGroundingEngine?;
|
|
110
111
|
private toolDedupConfig?;
|
|
111
112
|
private toolsConfig?;
|
|
112
113
|
/** Session-scoped pins of tools discovered via search_tools (tools.discovery mode). */
|
|
@@ -629,6 +630,7 @@ export declare class NeuroLink {
|
|
|
629
630
|
* @param optionsOrPrompt.maxTokens - Maximum tokens to generate
|
|
630
631
|
* @param optionsOrPrompt.thinkingConfig - Extended thinking configuration (thinkingLevel: 'minimal'|'low'|'medium'|'high')
|
|
631
632
|
* @param optionsOrPrompt.context - Context with conversationId and userId for memory
|
|
633
|
+
* @param optionsOrPrompt.useKnowledgeGrounding - Whether to use the instance's configured knowledge for this call
|
|
632
634
|
* @returns Promise resolving to generation result with content and metadata
|
|
633
635
|
*
|
|
634
636
|
* @example Basic text generation
|
|
@@ -904,6 +906,7 @@ export declare class NeuroLink {
|
|
|
904
906
|
* @param options.enableEvaluation - Whether to include response quality evaluation
|
|
905
907
|
* @param options.context - Additional context for the request
|
|
906
908
|
* @param options.evaluationDomain - Domain for specialized evaluation
|
|
909
|
+
* @param options.useKnowledgeGrounding - Whether to use the instance's configured knowledge for this call
|
|
907
910
|
*
|
|
908
911
|
* @returns Promise resolving to StreamResult with an async iterable stream
|
|
909
912
|
*
|
|
@@ -989,6 +992,16 @@ export declare class NeuroLink {
|
|
|
989
992
|
* alone does not activate it.
|
|
990
993
|
*/
|
|
991
994
|
setToolRoutingServers(servers: ToolRoutingServerDescriptor[]): void;
|
|
995
|
+
/** Knowledge-grounding engine health (null when it was not configured). */
|
|
996
|
+
getKnowledgeStatus(): KnowledgeEngineStatus | null;
|
|
997
|
+
private appendKnowledgeGroundingBlockToSystemPrompt;
|
|
998
|
+
/**
|
|
999
|
+
* Retrieve knowledge grounding for a public generate/stream call without
|
|
1000
|
+
* mutating its options. The outer call boundary decides how to apply the
|
|
1001
|
+
* returned context. Returns undefined when the call does not opt in,
|
|
1002
|
+
* grounding is disabled/not applicable, or retrieval fails open.
|
|
1003
|
+
*/
|
|
1004
|
+
private retrieveKnowledgeGrounding;
|
|
992
1005
|
private validateStreamRequestOptions;
|
|
993
1006
|
private maybeHandleWorkflowStreamRequest;
|
|
994
1007
|
private runStandardStreamRequest;
|