@juspay/neurolink 9.74.0 → 9.76.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 +292 -292
- package/dist/cli/factories/commandFactory.js +62 -0
- package/dist/cli/utils/toolRoutingFlags.d.ts +20 -0
- package/dist/cli/utils/toolRoutingFlags.js +115 -0
- package/dist/core/baseProvider.js +29 -4
- package/dist/core/toolDedup.d.ts +51 -0
- package/dist/core/toolDedup.js +193 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +2 -0
- package/dist/lib/core/baseProvider.js +29 -4
- package/dist/lib/core/toolDedup.d.ts +51 -0
- package/dist/lib/core/toolDedup.js +194 -0
- package/dist/lib/index.d.ts +1 -0
- package/dist/lib/index.js +2 -0
- package/dist/lib/neurolink.d.ts +15 -1
- package/dist/lib/neurolink.js +20 -0
- package/dist/lib/session/globalSessionState.d.ts +10 -1
- package/dist/lib/session/globalSessionState.js +18 -0
- package/dist/lib/types/cli.d.ts +29 -3
- package/dist/lib/types/config.d.ts +14 -2
- package/dist/lib/types/index.d.ts +1 -0
- package/dist/lib/types/index.js +1 -0
- package/dist/lib/types/toolDedup.d.ts +45 -0
- package/dist/lib/types/toolDedup.js +14 -0
- package/dist/neurolink.d.ts +15 -1
- package/dist/neurolink.js +20 -0
- package/dist/session/globalSessionState.d.ts +10 -1
- package/dist/session/globalSessionState.js +18 -0
- package/dist/types/cli.d.ts +29 -3
- package/dist/types/config.d.ts +14 -2
- package/dist/types/index.d.ts +1 -0
- package/dist/types/index.js +1 -0
- package/dist/types/toolDedup.d.ts +45 -0
- package/dist/types/toolDedup.js +13 -0
- package/package.json +6 -2
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool-signature deduplication — pure module, no I/O, no side effects.
|
|
3
|
+
*
|
|
4
|
+
* ## Algorithm
|
|
5
|
+
*
|
|
6
|
+
* `computeToolSignature` builds a canonical, order-insensitive string from:
|
|
7
|
+
* 1. The tool's name (exact, case-preserved).
|
|
8
|
+
* 2. A normalised description: lowercased, all whitespace runs collapsed to a
|
|
9
|
+
* single space, leading/trailing whitespace stripped.
|
|
10
|
+
* 3. A sorted, deduplicated list of JSON-schema property names (top-level
|
|
11
|
+
* `properties` keys from `inputSchema`). If the schema exposes a `type`
|
|
12
|
+
* field on each property, that type string is appended as `name:type`.
|
|
13
|
+
*
|
|
14
|
+
* `dedupeTools` clusters tools by pairwise token-set Jaccard similarity:
|
|
15
|
+
*
|
|
16
|
+
* Jaccard(A, B) = |A ∩ B| / |A ∪ B|
|
|
17
|
+
*
|
|
18
|
+
* where A and B are the _sets_ of whitespace-split tokens from each tool's
|
|
19
|
+
* canonical signature. This is deterministic, symmetric, and independent of
|
|
20
|
+
* token ordering — making it robust to minor rewording while being fast (O(n²)
|
|
21
|
+
* in the number of tools, which is bounded in practice by provider limits).
|
|
22
|
+
*
|
|
23
|
+
* The first tool encountered in stable input-iteration order becomes the
|
|
24
|
+
* cluster representative; subsequent tools in the same cluster are dropped.
|
|
25
|
+
*/
|
|
26
|
+
import type { Tool } from "../types/index.js";
|
|
27
|
+
import type { ToolDedupConfig, ToolDedupResult } from "../types/index.js";
|
|
28
|
+
/**
|
|
29
|
+
* Build a canonical, order-insensitive signature string for a named tool.
|
|
30
|
+
*
|
|
31
|
+
* The signature is composed of:
|
|
32
|
+
* - the tool's name
|
|
33
|
+
* - a normalised description (lowercased, whitespace-collapsed)
|
|
34
|
+
* - sorted parameter property names (with types when available)
|
|
35
|
+
*
|
|
36
|
+
* Stable regardless of property declaration order in the schema.
|
|
37
|
+
*/
|
|
38
|
+
export declare function computeToolSignature(name: string, tool: Tool): string;
|
|
39
|
+
/**
|
|
40
|
+
* Collapse near-duplicate tools in a name→Tool record.
|
|
41
|
+
*
|
|
42
|
+
* When `options.enabled` is falsy (the default), returns the original record
|
|
43
|
+
* and an empty `removed` array — byte-for-byte unchanged behaviour.
|
|
44
|
+
*
|
|
45
|
+
* When enabled, tools whose token-set Jaccard similarity (over their canonical
|
|
46
|
+
* signatures) meets or exceeds `options.threshold` (default 0.9) are collapsed
|
|
47
|
+
* to a single representative (the first in stable iteration order).
|
|
48
|
+
*
|
|
49
|
+
* Any exception thrown internally returns the ORIGINAL tool set (fail-open).
|
|
50
|
+
*/
|
|
51
|
+
export declare function dedupeTools<T extends Tool>(tools: Record<string, T>, options: ToolDedupConfig): ToolDedupResult<Record<string, T>>;
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool-signature deduplication — pure module, no I/O, no side effects.
|
|
3
|
+
*
|
|
4
|
+
* ## Algorithm
|
|
5
|
+
*
|
|
6
|
+
* `computeToolSignature` builds a canonical, order-insensitive string from:
|
|
7
|
+
* 1. The tool's name (exact, case-preserved).
|
|
8
|
+
* 2. A normalised description: lowercased, all whitespace runs collapsed to a
|
|
9
|
+
* single space, leading/trailing whitespace stripped.
|
|
10
|
+
* 3. A sorted, deduplicated list of JSON-schema property names (top-level
|
|
11
|
+
* `properties` keys from `inputSchema`). If the schema exposes a `type`
|
|
12
|
+
* field on each property, that type string is appended as `name:type`.
|
|
13
|
+
*
|
|
14
|
+
* `dedupeTools` clusters tools by pairwise token-set Jaccard similarity:
|
|
15
|
+
*
|
|
16
|
+
* Jaccard(A, B) = |A ∩ B| / |A ∪ B|
|
|
17
|
+
*
|
|
18
|
+
* where A and B are the _sets_ of whitespace-split tokens from each tool's
|
|
19
|
+
* canonical signature. This is deterministic, symmetric, and independent of
|
|
20
|
+
* token ordering — making it robust to minor rewording while being fast (O(n²)
|
|
21
|
+
* in the number of tools, which is bounded in practice by provider limits).
|
|
22
|
+
*
|
|
23
|
+
* The first tool encountered in stable input-iteration order becomes the
|
|
24
|
+
* cluster representative; subsequent tools in the same cluster are dropped.
|
|
25
|
+
*/
|
|
26
|
+
// ---------------------------------------------------------------------------
|
|
27
|
+
// Internal helpers
|
|
28
|
+
// ---------------------------------------------------------------------------
|
|
29
|
+
/**
|
|
30
|
+
* Extract top-level property names (and optionally their types) from a JSON
|
|
31
|
+
* Schema-shaped `inputSchema`. Returns a sorted, stable list.
|
|
32
|
+
*
|
|
33
|
+
* The `inputSchema` on a `Tool` is typed as `FlexibleSchema<INPUT>` (opaque at
|
|
34
|
+
* runtime), so we access it via index to avoid casting.
|
|
35
|
+
*/
|
|
36
|
+
function extractSchemaTokens(inputSchema) {
|
|
37
|
+
if (!inputSchema) {
|
|
38
|
+
return [];
|
|
39
|
+
}
|
|
40
|
+
// FlexibleSchema may be a Zod schema, a jsonSchema() wrapper, or a plain
|
|
41
|
+
// JSON Schema object. All three expose `jsonSchema` or fall through to the
|
|
42
|
+
// raw object. We look for the plain JSON Schema `properties` key.
|
|
43
|
+
const schema = inputSchema;
|
|
44
|
+
// Vercel AI SDK wraps plain schemas in { jsonSchema: {...}, ... }
|
|
45
|
+
const rawSchema = schema["jsonSchema"] !== undefined
|
|
46
|
+
? schema["jsonSchema"]
|
|
47
|
+
: schema;
|
|
48
|
+
const properties = rawSchema["properties"];
|
|
49
|
+
if (!properties || typeof properties !== "object" || properties === null) {
|
|
50
|
+
return [];
|
|
51
|
+
}
|
|
52
|
+
const tokens = [];
|
|
53
|
+
const props = properties;
|
|
54
|
+
for (const propName of Object.keys(props)) {
|
|
55
|
+
const propDef = props[propName];
|
|
56
|
+
if (propDef && typeof propDef === "object" && propDef !== null) {
|
|
57
|
+
const t = propDef["type"];
|
|
58
|
+
tokens.push(typeof t === "string" ? `${propName}:${t}` : propName);
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
tokens.push(propName);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
return tokens.sort();
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Normalise a description string: lowercase, collapse whitespace, strip ends.
|
|
68
|
+
*/
|
|
69
|
+
function normaliseDescription(desc) {
|
|
70
|
+
if (!desc) {
|
|
71
|
+
return "";
|
|
72
|
+
}
|
|
73
|
+
return desc.toLowerCase().replace(/\s+/g, " ").trim();
|
|
74
|
+
}
|
|
75
|
+
// ---------------------------------------------------------------------------
|
|
76
|
+
// Public API
|
|
77
|
+
// ---------------------------------------------------------------------------
|
|
78
|
+
/**
|
|
79
|
+
* Build a canonical, order-insensitive signature string for a named tool.
|
|
80
|
+
*
|
|
81
|
+
* The signature is composed of:
|
|
82
|
+
* - the tool's name
|
|
83
|
+
* - a normalised description (lowercased, whitespace-collapsed)
|
|
84
|
+
* - sorted parameter property names (with types when available)
|
|
85
|
+
*
|
|
86
|
+
* Stable regardless of property declaration order in the schema.
|
|
87
|
+
*/
|
|
88
|
+
export function computeToolSignature(name, tool) {
|
|
89
|
+
const descPart = normaliseDescription(tool.description);
|
|
90
|
+
const schemaParts = extractSchemaTokens(tool.inputSchema);
|
|
91
|
+
// Pipe-separated sections keep tokens within each section unambiguous.
|
|
92
|
+
return [name, descPart, schemaParts.join(",")].join("|");
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Compute the token-set Jaccard similarity between two signature strings.
|
|
96
|
+
*
|
|
97
|
+
* Jaccard(A, B) = |A ∩ B| / |A ∪ B|
|
|
98
|
+
*
|
|
99
|
+
* Splits on whitespace and also on the pipe/comma delimiters used by
|
|
100
|
+
* `computeToolSignature` so that structural differences (e.g. a parameter
|
|
101
|
+
* missing from one tool) are properly reflected.
|
|
102
|
+
*/
|
|
103
|
+
function jaccardSimilarity(sigA, sigB) {
|
|
104
|
+
const tokenise = (s) => new Set(s.split(/[\s|,]+/).filter((t) => t.length > 0));
|
|
105
|
+
const setA = tokenise(sigA);
|
|
106
|
+
const setB = tokenise(sigB);
|
|
107
|
+
if (setA.size === 0 && setB.size === 0) {
|
|
108
|
+
return 1;
|
|
109
|
+
}
|
|
110
|
+
if (setA.size === 0 || setB.size === 0) {
|
|
111
|
+
return 0;
|
|
112
|
+
}
|
|
113
|
+
let intersection = 0;
|
|
114
|
+
for (const token of setA) {
|
|
115
|
+
if (setB.has(token)) {
|
|
116
|
+
intersection += 1;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
const union = setA.size + setB.size - intersection;
|
|
120
|
+
return intersection / union;
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Collapse near-duplicate tools in a name→Tool record.
|
|
124
|
+
*
|
|
125
|
+
* When `options.enabled` is falsy (the default), returns the original record
|
|
126
|
+
* and an empty `removed` array — byte-for-byte unchanged behaviour.
|
|
127
|
+
*
|
|
128
|
+
* When enabled, tools whose token-set Jaccard similarity (over their canonical
|
|
129
|
+
* signatures) meets or exceeds `options.threshold` (default 0.9) are collapsed
|
|
130
|
+
* to a single representative (the first in stable iteration order).
|
|
131
|
+
*
|
|
132
|
+
* Any exception thrown internally returns the ORIGINAL tool set (fail-open).
|
|
133
|
+
*/
|
|
134
|
+
export function dedupeTools(tools, options) {
|
|
135
|
+
const noOp = { tools, removed: [] };
|
|
136
|
+
if (!options.enabled) {
|
|
137
|
+
return noOp;
|
|
138
|
+
}
|
|
139
|
+
try {
|
|
140
|
+
const rawThreshold = options.threshold ?? 0.9;
|
|
141
|
+
const threshold = Math.min(1, Math.max(0, rawThreshold));
|
|
142
|
+
const entries = Object.entries(tools);
|
|
143
|
+
if (entries.length <= 1) {
|
|
144
|
+
return noOp;
|
|
145
|
+
}
|
|
146
|
+
// Pre-compute signatures once.
|
|
147
|
+
const signatures = new Map();
|
|
148
|
+
for (const [name, tool] of entries) {
|
|
149
|
+
signatures.set(name, computeToolSignature(name, tool));
|
|
150
|
+
}
|
|
151
|
+
// representative[toolName] = name of the cluster representative.
|
|
152
|
+
// Tools not yet assigned to a cluster act as their own representative.
|
|
153
|
+
const representativeOf = new Map();
|
|
154
|
+
for (const [nameA] of entries) {
|
|
155
|
+
if (representativeOf.has(nameA)) {
|
|
156
|
+
// Already absorbed into another cluster.
|
|
157
|
+
continue;
|
|
158
|
+
}
|
|
159
|
+
const sigA = signatures.get(nameA) ?? "";
|
|
160
|
+
for (const [nameB] of entries) {
|
|
161
|
+
if (nameA === nameB || representativeOf.has(nameB)) {
|
|
162
|
+
continue;
|
|
163
|
+
}
|
|
164
|
+
const sigB = signatures.get(nameB) ?? "";
|
|
165
|
+
const sim = jaccardSimilarity(sigA, sigB);
|
|
166
|
+
if (sim >= threshold) {
|
|
167
|
+
representativeOf.set(nameB, nameA);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
if (representativeOf.size === 0) {
|
|
172
|
+
return noOp;
|
|
173
|
+
}
|
|
174
|
+
const dedupedTools = {};
|
|
175
|
+
const removed = [];
|
|
176
|
+
for (const [name, tool] of entries) {
|
|
177
|
+
const rep = representativeOf.get(name);
|
|
178
|
+
if (rep !== undefined) {
|
|
179
|
+
// Compute similarity again to include in the removed record.
|
|
180
|
+
const sim = jaccardSimilarity(signatures.get(name) ?? "", signatures.get(rep) ?? "");
|
|
181
|
+
removed.push({ name, duplicateOf: rep, similarity: sim });
|
|
182
|
+
}
|
|
183
|
+
else {
|
|
184
|
+
dedupedTools[name] = tool;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
return { tools: dedupedTools, removed };
|
|
188
|
+
}
|
|
189
|
+
catch {
|
|
190
|
+
// Fail open — return the original set.
|
|
191
|
+
return noOp;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
//# sourceMappingURL=toolDedup.js.map
|
package/dist/lib/index.d.ts
CHANGED
|
@@ -214,6 +214,7 @@ export declare function createBestAIProvider(requestedProvider?: string, modelNa
|
|
|
214
214
|
* ```
|
|
215
215
|
*/
|
|
216
216
|
export { CircuitBreakerManager, calculateExpiresAt, createMCPServer, createOAuthProviderFromConfig, DEFAULT_HTTP_RETRY_CONFIG, DEFAULT_RATE_LIMIT_CONFIG, executeMCP, FileTokenStorage, getMCPStats, getServerInfo, globalCircuitBreakerManager, globalRateLimiterManager, HTTPRateLimiter, InMemoryTokenStorage, initializeMCPEcosystem, isRetryableHTTPError, isRetryableStatusCode, isTokenExpired, listMCPs, CircuitBreakerOpenError, MCPCircuitBreaker, mcpLogger, NeuroLinkOAuthProvider, RateLimiterManager, validateServerTools, validateTool as validateMCPTool, withHTTPRetry, MCPToolRegistry, ExternalServerManager, MCPClientFactory, ToolRouter, createToolRouter, DEFAULT_ROUTER_CONFIG, ToolCache, createToolCache, DEFAULT_CACHE_CONFIG, ToolResultCache, createToolResultCache, RequestBatcher, ToolCallBatcher, createRequestBatcher, createToolCallBatcher, DEFAULT_BATCH_CONFIG, inferAnnotations, createAnnotatedTool, validateAnnotations, filterToolsByAnnotations, mergeAnnotations, getAnnotationSummary, requiresConfirmation, isSafeToRetry, getToolSafetyLevel, ElicitationManager, globalElicitationManager, EnhancedToolDiscovery, MCPRegistryClient, globalMCPRegistryClient, getWellKnownServer, getAllWellKnownServers, MCPServerBase, MultiServerManager, globalMultiServerManager, AgentExposureManager, exposeAgentAsTool, exposeAgentsAsTools, exposeWorkflowAsTool, exposeWorkflowsAsTools, globalAgentExposureManager, ServerCapabilitiesManager, createTextResource, createJsonResource, createPrompt, neuroLinkToolToMCP, mcpToolToNeuroLink, batchConvertToMCP, batchConvertToNeuroLink, sanitizeToolName, validateToolName, createToolFromFunction, mcpProtocolToolToServerTool, serverToolToMCPProtocol, TOOL_COMPATIBILITY, ToolIntegrationManager, globalToolIntegrationManager, wrapToolWithElicitation, wrapToolsWithElicitation, createElicitationContext, confirmationMiddleware, validationMiddleware, loggingMiddleware, createRetryMiddleware, createTimeoutMiddleware, createToolMiddlewareChain, ElicitationProtocolAdapter, globalElicitationProtocol, isElicitationProtocolMessage, protocolMessageToElicitation, elicitationResponseToProtocol, createElicitationRequest, createElicitationResponse, createElicitationCancel, createTextInputRequest, createSelectRequest, createConfirmationRequest, createFormRequest, } from "./mcp/index.js";
|
|
217
|
+
export { computeToolSignature, dedupeTools } from "./core/toolDedup.js";
|
|
217
218
|
export { logger } from "./utils/logger.js";
|
|
218
219
|
export { getPoolStats } from "./utils/redis.js";
|
|
219
220
|
export { ToolRoutingCache } from "./core/toolRoutingCache.js";
|
package/dist/lib/index.js
CHANGED
|
@@ -354,6 +354,8 @@ neuroLinkToolToMCP, mcpToolToNeuroLink, batchConvertToMCP, batchConvertToNeuroLi
|
|
|
354
354
|
ToolIntegrationManager, globalToolIntegrationManager, wrapToolWithElicitation, wrapToolsWithElicitation, createElicitationContext, confirmationMiddleware, validationMiddleware, loggingMiddleware, createRetryMiddleware, createTimeoutMiddleware, createToolMiddlewareChain,
|
|
355
355
|
// MCP Enhancements - Elicitation Protocol
|
|
356
356
|
ElicitationProtocolAdapter, globalElicitationProtocol, isElicitationProtocolMessage, protocolMessageToElicitation, elicitationResponseToProtocol, createElicitationRequest, createElicitationResponse, createElicitationCancel, createTextInputRequest, createSelectRequest, createConfirmationRequest, createFormRequest, } from "./mcp/index.js";
|
|
357
|
+
// Tool signature deduplication utilities (opt-in, fail-open)
|
|
358
|
+
export { computeToolSignature, dedupeTools } from "./core/toolDedup.js";
|
|
357
359
|
export { logger } from "./utils/logger.js";
|
|
358
360
|
export { getPoolStats } from "./utils/redis.js";
|
|
359
361
|
// Pre-call tool routing cache (ITEM C: LRU+TTL cache + session stickiness)
|
package/dist/lib/neurolink.d.ts
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* Enhanced AI provider system with natural MCP tool access.
|
|
6
6
|
* Uses real MCP infrastructure for tool discovery and execution.
|
|
7
7
|
*/
|
|
8
|
-
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 } from "./types/index.js";
|
|
8
|
+
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 } from "./types/index.js";
|
|
9
9
|
import { ConversationMemoryManager } from "./core/conversationMemoryManager.js";
|
|
10
10
|
import type { RedisConversationMemoryManager } from "./core/redisConversationMemoryManager.js";
|
|
11
11
|
import { ExternalServerManager } from "./mcp/externalServerManager.js";
|
|
@@ -102,6 +102,7 @@ export declare class NeuroLink {
|
|
|
102
102
|
private conversationMemoryConfig?;
|
|
103
103
|
private toolRoutingConfig?;
|
|
104
104
|
private toolRoutingCacheInstance?;
|
|
105
|
+
private toolDedupConfig?;
|
|
105
106
|
private enableOrchestration;
|
|
106
107
|
private authProvider?;
|
|
107
108
|
private pendingAuthConfig?;
|
|
@@ -1089,6 +1090,19 @@ export declare class NeuroLink {
|
|
|
1089
1090
|
* @see {@link NeuroLink.executeTool} for events related to tool execution
|
|
1090
1091
|
*/
|
|
1091
1092
|
getEventEmitter(): TypedEventEmitter<NeuroLinkEvents>;
|
|
1093
|
+
/**
|
|
1094
|
+
* Returns the instance-level tool-dedup configuration, or `undefined` when
|
|
1095
|
+
* toolDedup was not provided at construction time.
|
|
1096
|
+
*
|
|
1097
|
+
* The stored object is returned as-is whenever `toolDedup` was supplied,
|
|
1098
|
+
* including when `enabled: false` — only the complete absence of a `toolDedup`
|
|
1099
|
+
* option results in `undefined`.
|
|
1100
|
+
*
|
|
1101
|
+
* Called by `BaseProvider.applyToolFiltering` so the dedup pass uses the
|
|
1102
|
+
* same config for every generate/stream call without threading an extra
|
|
1103
|
+
* parameter through the full call stack.
|
|
1104
|
+
*/
|
|
1105
|
+
getToolDedupConfig(): ToolDedupConfig | undefined;
|
|
1092
1106
|
/**
|
|
1093
1107
|
* Curator P1-1: synchronous credential health check for a single provider.
|
|
1094
1108
|
*
|
package/dist/lib/neurolink.js
CHANGED
|
@@ -445,6 +445,8 @@ export class NeuroLink {
|
|
|
445
445
|
// Lazy-initialized routing decision cache (ITEM C). Created on first use so
|
|
446
446
|
// instances that don't use routing pay no overhead.
|
|
447
447
|
toolRoutingCacheInstance;
|
|
448
|
+
// Opt-in tool-signature deduplication config.
|
|
449
|
+
toolDedupConfig;
|
|
448
450
|
// Add orchestration property
|
|
449
451
|
enableOrchestration;
|
|
450
452
|
// Authentication provider for secure access control
|
|
@@ -857,6 +859,9 @@ export class NeuroLink {
|
|
|
857
859
|
// multiple NeuroLink instances.
|
|
858
860
|
this.toolRoutingConfig = { ...config.toolRouting };
|
|
859
861
|
}
|
|
862
|
+
if (config?.toolDedup) {
|
|
863
|
+
this.toolDedupConfig = { ...config.toolDedup };
|
|
864
|
+
}
|
|
860
865
|
logger.setEventEmitter(this.emitter);
|
|
861
866
|
// Read tool cache duration from environment variables, with a default
|
|
862
867
|
const cacheDurationEnv = process.env.NEUROLINK_TOOL_CACHE_DURATION;
|
|
@@ -7513,6 +7518,21 @@ Current user's request: ${currentInput}`;
|
|
|
7513
7518
|
getEventEmitter() {
|
|
7514
7519
|
return this.emitter;
|
|
7515
7520
|
}
|
|
7521
|
+
/**
|
|
7522
|
+
* Returns the instance-level tool-dedup configuration, or `undefined` when
|
|
7523
|
+
* toolDedup was not provided at construction time.
|
|
7524
|
+
*
|
|
7525
|
+
* The stored object is returned as-is whenever `toolDedup` was supplied,
|
|
7526
|
+
* including when `enabled: false` — only the complete absence of a `toolDedup`
|
|
7527
|
+
* option results in `undefined`.
|
|
7528
|
+
*
|
|
7529
|
+
* Called by `BaseProvider.applyToolFiltering` so the dedup pass uses the
|
|
7530
|
+
* same config for every generate/stream call without threading an extra
|
|
7531
|
+
* parameter through the full call stack.
|
|
7532
|
+
*/
|
|
7533
|
+
getToolDedupConfig() {
|
|
7534
|
+
return this.toolDedupConfig;
|
|
7535
|
+
}
|
|
7516
7536
|
/**
|
|
7517
7537
|
* Curator P1-1: synchronous credential health check for a single provider.
|
|
7518
7538
|
*
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { NeuroLink } from "../neurolink.js";
|
|
2
|
-
import type { ConversationMemoryConfig, LoopSessionState, SessionVariableValue } from "../types/index.js";
|
|
2
|
+
import type { ConversationMemoryConfig, LoopSessionState, SessionVariableValue, ToolRoutingConfig } from "../types/index.js";
|
|
3
3
|
export declare class GlobalSessionManager {
|
|
4
4
|
private static instance;
|
|
5
5
|
private loopSession;
|
|
6
|
+
/** Optional tool-routing config set by CLI handlers before SDK construction. */
|
|
7
|
+
private _toolRoutingConfig;
|
|
6
8
|
static getInstance(): GlobalSessionManager;
|
|
7
9
|
setLoopSession(config?: ConversationMemoryConfig): string;
|
|
8
10
|
/**
|
|
@@ -33,6 +35,13 @@ export declare class GlobalSessionManager {
|
|
|
33
35
|
updateSessionId(newSessionId: string): void;
|
|
34
36
|
getLoopSession(): LoopSessionState | null;
|
|
35
37
|
clearLoopSession(): void;
|
|
38
|
+
/**
|
|
39
|
+
* Store a tool-routing config to be injected at SDK construction time.
|
|
40
|
+
* Call this BEFORE `getOrCreateNeuroLink()` inside a command handler.
|
|
41
|
+
* When a loop session is already active the config is ignored (the instance
|
|
42
|
+
* already exists).
|
|
43
|
+
*/
|
|
44
|
+
setToolRoutingConfig(config: ToolRoutingConfig): void;
|
|
36
45
|
getOrCreateNeuroLink(): NeuroLink;
|
|
37
46
|
getCurrentSessionId(): string | undefined;
|
|
38
47
|
setSessionVariable(key: string, value: SessionVariableValue): void;
|
|
@@ -31,6 +31,8 @@ function buildMcpOutputLimitsFromEnv() {
|
|
|
31
31
|
export class GlobalSessionManager {
|
|
32
32
|
static instance;
|
|
33
33
|
loopSession = null;
|
|
34
|
+
/** Optional tool-routing config set by CLI handlers before SDK construction. */
|
|
35
|
+
_toolRoutingConfig = undefined;
|
|
34
36
|
static getInstance() {
|
|
35
37
|
if (!GlobalSessionManager.instance) {
|
|
36
38
|
GlobalSessionManager.instance = new GlobalSessionManager();
|
|
@@ -127,6 +129,18 @@ export class GlobalSessionManager {
|
|
|
127
129
|
this.loopSession = null;
|
|
128
130
|
}
|
|
129
131
|
}
|
|
132
|
+
/**
|
|
133
|
+
* Store a tool-routing config to be injected at SDK construction time.
|
|
134
|
+
* Call this BEFORE `getOrCreateNeuroLink()` inside a command handler.
|
|
135
|
+
* When a loop session is already active the config is ignored (the instance
|
|
136
|
+
* already exists).
|
|
137
|
+
*/
|
|
138
|
+
setToolRoutingConfig(config) {
|
|
139
|
+
if (this.hasActiveSession()) {
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
this._toolRoutingConfig = config;
|
|
143
|
+
}
|
|
130
144
|
getOrCreateNeuroLink() {
|
|
131
145
|
const session = this.getLoopSession();
|
|
132
146
|
if (session) {
|
|
@@ -142,6 +156,10 @@ export class GlobalSessionManager {
|
|
|
142
156
|
if (mcpOutputLimits) {
|
|
143
157
|
options.mcp = { outputLimits: mcpOutputLimits };
|
|
144
158
|
}
|
|
159
|
+
if (this._toolRoutingConfig) {
|
|
160
|
+
options.toolRouting = this._toolRoutingConfig;
|
|
161
|
+
this._toolRoutingConfig = undefined;
|
|
162
|
+
}
|
|
145
163
|
return new NeuroLink(Object.keys(options).length ? options : undefined);
|
|
146
164
|
}
|
|
147
165
|
getCurrentSessionId() {
|
package/dist/lib/types/cli.d.ts
CHANGED
|
@@ -45,7 +45,7 @@ export type BaseCommandArgs = {
|
|
|
45
45
|
/**
|
|
46
46
|
* Generate command arguments
|
|
47
47
|
*/
|
|
48
|
-
export type GenerateCommandArgs = BaseCommandArgs & {
|
|
48
|
+
export type GenerateCommandArgs = BaseCommandArgs & CliToolRoutingFlags & {
|
|
49
49
|
/** Input text or prompt */
|
|
50
50
|
input?: string;
|
|
51
51
|
/** AI provider to use */
|
|
@@ -110,7 +110,7 @@ export type GenerateCommandArgs = BaseCommandArgs & {
|
|
|
110
110
|
/**
|
|
111
111
|
* Stream command arguments
|
|
112
112
|
*/
|
|
113
|
-
export type StreamCommandArgs = BaseCommandArgs & {
|
|
113
|
+
export type StreamCommandArgs = BaseCommandArgs & CliToolRoutingFlags & {
|
|
114
114
|
/** Input text or prompt */
|
|
115
115
|
input?: string;
|
|
116
116
|
/** AI provider to use */
|
|
@@ -137,7 +137,7 @@ export type StreamCommandArgs = BaseCommandArgs & {
|
|
|
137
137
|
/**
|
|
138
138
|
* Batch command arguments
|
|
139
139
|
*/
|
|
140
|
-
export type BatchCommandArgs = BaseCommandArgs & {
|
|
140
|
+
export type BatchCommandArgs = BaseCommandArgs & CliToolRoutingFlags & {
|
|
141
141
|
/** Input file path */
|
|
142
142
|
file?: string;
|
|
143
143
|
/** AI provider to use */
|
|
@@ -1500,3 +1500,29 @@ export type CliServeFlatRoute = {
|
|
|
1500
1500
|
description?: string;
|
|
1501
1501
|
group: string;
|
|
1502
1502
|
};
|
|
1503
|
+
/**
|
|
1504
|
+
* Raw CLI flag shape for the tool-routing family of options.
|
|
1505
|
+
* Keys are camelCase as yargs delivers them after parsing kebab-case aliases.
|
|
1506
|
+
*/
|
|
1507
|
+
export type CliToolRoutingFlags = {
|
|
1508
|
+
/** Master enable switch (--tool-routing). */
|
|
1509
|
+
toolRouting?: boolean;
|
|
1510
|
+
/** Router LLM hard timeout in ms (--tool-routing-timeout). */
|
|
1511
|
+
toolRoutingTimeout?: number;
|
|
1512
|
+
/** Router LLM provider override (--tool-routing-router-provider). */
|
|
1513
|
+
toolRoutingRouterProvider?: string;
|
|
1514
|
+
/** Router LLM model override (--tool-routing-router-model). */
|
|
1515
|
+
toolRoutingRouterModel?: string;
|
|
1516
|
+
/** Router LLM region override (--tool-routing-router-region). */
|
|
1517
|
+
toolRoutingRouterRegion?: string;
|
|
1518
|
+
/**
|
|
1519
|
+
* Server ids that are always kept and never offered to the router
|
|
1520
|
+
* (--tool-routing-always-include, repeatable).
|
|
1521
|
+
*/
|
|
1522
|
+
toolRoutingAlwaysInclude?: string[];
|
|
1523
|
+
/**
|
|
1524
|
+
* Path to a JSON file OR inline JSON array of server descriptors
|
|
1525
|
+
* (--tool-routing-servers).
|
|
1526
|
+
*/
|
|
1527
|
+
toolRoutingServers?: string;
|
|
1528
|
+
};
|
|
@@ -9,7 +9,6 @@ import type { ConversationMemoryConfig } from "./conversation.js";
|
|
|
9
9
|
import type { ObservabilityConfig } from "./observability.js";
|
|
10
10
|
import type { AuthProvider, AuthProviderType, AuthProviderConfig, Auth0Config, ClerkConfig, FirebaseConfig, SupabaseConfig, WorkOSConfig, BetterAuthConfig, JWTConfig, OAuth2Config, CognitoConfig, KeycloakConfig, AuthenticatedContext } from "./auth.js";
|
|
11
11
|
import type { NeurolinkCredentials } from "./providers.js";
|
|
12
|
-
import type { ToolRoutingConfig } from "./toolRouting.js";
|
|
13
12
|
/**
|
|
14
13
|
* Main NeuroLink configuration type
|
|
15
14
|
*/
|
|
@@ -74,6 +73,19 @@ export type NeurolinkConstructorConfig = {
|
|
|
74
73
|
* any router failure. See {@link ToolRoutingConfig}.
|
|
75
74
|
*/
|
|
76
75
|
toolRouting?: ToolRoutingConfig;
|
|
76
|
+
/**
|
|
77
|
+
* Opt-in tool-signature deduplication. When enabled, tools whose
|
|
78
|
+
* canonical signatures are sufficiently similar (Jaccard ≥ threshold) are
|
|
79
|
+
* collapsed to a single representative before being sent to the model,
|
|
80
|
+
* reducing token cost and model confusion caused by near-identical tools.
|
|
81
|
+
*
|
|
82
|
+
* Disabled by default — enabling this changes nothing unless you
|
|
83
|
+
* explicitly set `enabled: true`. Always fails open: any error in the
|
|
84
|
+
* dedup pass returns the original tool set unchanged.
|
|
85
|
+
*
|
|
86
|
+
* See {@link ToolDedupConfig}.
|
|
87
|
+
*/
|
|
88
|
+
toolDedup?: ToolDedupConfig;
|
|
77
89
|
};
|
|
78
90
|
/**
|
|
79
91
|
* Configuration for MCP enhancement modules wired into generate()/stream() paths.
|
|
@@ -338,7 +350,7 @@ export type ConfigUpdateOptions = {
|
|
|
338
350
|
*/
|
|
339
351
|
export declare const DEFAULT_CONFIG: NeuroLinkConfig;
|
|
340
352
|
import { TOOL_TIMEOUTS, BACKOFF_CONFIG, PERFORMANCE_PROFILES, PROVIDER_OPERATION_CONFIGS, MCP_OPERATION_CONFIGS } from "../constants/index.js";
|
|
341
|
-
import type { ToolMiddleware, CacheStrategy, RoutingStrategy } from "./index.js";
|
|
353
|
+
import type { ToolMiddleware, CacheStrategy, RoutingStrategy, ToolDedupConfig, ToolRoutingConfig } from "./index.js";
|
|
342
354
|
import type { ModelAliasConfig } from "./generate.js";
|
|
343
355
|
/** Timeout category keys from TOOL_TIMEOUTS. */
|
|
344
356
|
export type TimeoutCategory = keyof typeof TOOL_TIMEOUTS;
|
|
@@ -50,6 +50,7 @@ export * from "./stream.js";
|
|
|
50
50
|
export * from "./subscription.js";
|
|
51
51
|
export * from "./task.js";
|
|
52
52
|
export * from "./taskClassification.js";
|
|
53
|
+
export * from "./toolDedup.js";
|
|
53
54
|
export * from "./toolRouting.js";
|
|
54
55
|
export * from "./tools.js";
|
|
55
56
|
export * from "./voice.js";
|
package/dist/lib/types/index.js
CHANGED
|
@@ -51,6 +51,7 @@ export * from "./stream.js";
|
|
|
51
51
|
export * from "./subscription.js";
|
|
52
52
|
export * from "./task.js";
|
|
53
53
|
export * from "./taskClassification.js";
|
|
54
|
+
export * from "./toolDedup.js";
|
|
54
55
|
export * from "./toolRouting.js";
|
|
55
56
|
export * from "./tools.js";
|
|
56
57
|
export * from "./voice.js";
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool signature deduplication types.
|
|
3
|
+
*
|
|
4
|
+
* When many MCP servers are registered, it is common for tools from different
|
|
5
|
+
* servers to be functionally identical — same purpose, same parameters, only a
|
|
6
|
+
* slightly different name or description phrasing. Sending all of them to the
|
|
7
|
+
* model wastes tokens and can confuse the model into picking the wrong variant.
|
|
8
|
+
*
|
|
9
|
+
* The dedup pass is OPT-IN and FAIL-OPEN. When disabled (the default) the
|
|
10
|
+
* tool set is returned byte-for-byte unchanged. Any error in the dedup logic
|
|
11
|
+
* also returns the original tool set.
|
|
12
|
+
*/
|
|
13
|
+
/** Configuration for the opt-in tool-signature deduplication pass. */
|
|
14
|
+
export type ToolDedupConfig = {
|
|
15
|
+
/**
|
|
16
|
+
* Master switch. Dedup runs only when `true`.
|
|
17
|
+
* Default: `false` (disabled — no change in behaviour).
|
|
18
|
+
*/
|
|
19
|
+
enabled?: boolean;
|
|
20
|
+
/**
|
|
21
|
+
* Jaccard similarity threshold in [0, 1]. Pairs of tools whose token-set
|
|
22
|
+
* Jaccard similarity over their canonical signatures meets or exceeds this
|
|
23
|
+
* value are treated as near-duplicates; only one representative per cluster
|
|
24
|
+
* (the first in stable input order) is forwarded to the model.
|
|
25
|
+
*
|
|
26
|
+
* Default: `0.9`
|
|
27
|
+
*/
|
|
28
|
+
threshold?: number;
|
|
29
|
+
};
|
|
30
|
+
/** Record produced for each tool collapsed by the dedup pass. */
|
|
31
|
+
export type ToolDedupRemoved = {
|
|
32
|
+
/** Name of the tool that was collapsed. */
|
|
33
|
+
name: string;
|
|
34
|
+
/** Name of the representative tool that this one was collapsed into. */
|
|
35
|
+
duplicateOf: string;
|
|
36
|
+
/** Similarity score that triggered the collapse (in [0, 1]). */
|
|
37
|
+
similarity: number;
|
|
38
|
+
};
|
|
39
|
+
/** Return type of `dedupeTools()`. */
|
|
40
|
+
export type ToolDedupResult<T extends Record<string, unknown>> = {
|
|
41
|
+
/** Deduplicated tool set (or original set when dedup is disabled/errored). */
|
|
42
|
+
tools: T;
|
|
43
|
+
/** Tools that were removed along with the reason. Empty when dedup is off. */
|
|
44
|
+
removed: ToolDedupRemoved[];
|
|
45
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool signature deduplication types.
|
|
3
|
+
*
|
|
4
|
+
* When many MCP servers are registered, it is common for tools from different
|
|
5
|
+
* servers to be functionally identical — same purpose, same parameters, only a
|
|
6
|
+
* slightly different name or description phrasing. Sending all of them to the
|
|
7
|
+
* model wastes tokens and can confuse the model into picking the wrong variant.
|
|
8
|
+
*
|
|
9
|
+
* The dedup pass is OPT-IN and FAIL-OPEN. When disabled (the default) the
|
|
10
|
+
* tool set is returned byte-for-byte unchanged. Any error in the dedup logic
|
|
11
|
+
* also returns the original tool set.
|
|
12
|
+
*/
|
|
13
|
+
export {};
|
|
14
|
+
//# sourceMappingURL=toolDedup.js.map
|
package/dist/neurolink.d.ts
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* Enhanced AI provider system with natural MCP tool access.
|
|
6
6
|
* Uses real MCP infrastructure for tool discovery and execution.
|
|
7
7
|
*/
|
|
8
|
-
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 } from "./types/index.js";
|
|
8
|
+
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 } from "./types/index.js";
|
|
9
9
|
import { ConversationMemoryManager } from "./core/conversationMemoryManager.js";
|
|
10
10
|
import type { RedisConversationMemoryManager } from "./core/redisConversationMemoryManager.js";
|
|
11
11
|
import { ExternalServerManager } from "./mcp/externalServerManager.js";
|
|
@@ -102,6 +102,7 @@ export declare class NeuroLink {
|
|
|
102
102
|
private conversationMemoryConfig?;
|
|
103
103
|
private toolRoutingConfig?;
|
|
104
104
|
private toolRoutingCacheInstance?;
|
|
105
|
+
private toolDedupConfig?;
|
|
105
106
|
private enableOrchestration;
|
|
106
107
|
private authProvider?;
|
|
107
108
|
private pendingAuthConfig?;
|
|
@@ -1089,6 +1090,19 @@ export declare class NeuroLink {
|
|
|
1089
1090
|
* @see {@link NeuroLink.executeTool} for events related to tool execution
|
|
1090
1091
|
*/
|
|
1091
1092
|
getEventEmitter(): TypedEventEmitter<NeuroLinkEvents>;
|
|
1093
|
+
/**
|
|
1094
|
+
* Returns the instance-level tool-dedup configuration, or `undefined` when
|
|
1095
|
+
* toolDedup was not provided at construction time.
|
|
1096
|
+
*
|
|
1097
|
+
* The stored object is returned as-is whenever `toolDedup` was supplied,
|
|
1098
|
+
* including when `enabled: false` — only the complete absence of a `toolDedup`
|
|
1099
|
+
* option results in `undefined`.
|
|
1100
|
+
*
|
|
1101
|
+
* Called by `BaseProvider.applyToolFiltering` so the dedup pass uses the
|
|
1102
|
+
* same config for every generate/stream call without threading an extra
|
|
1103
|
+
* parameter through the full call stack.
|
|
1104
|
+
*/
|
|
1105
|
+
getToolDedupConfig(): ToolDedupConfig | undefined;
|
|
1092
1106
|
/**
|
|
1093
1107
|
* Curator P1-1: synchronous credential health check for a single provider.
|
|
1094
1108
|
*
|
package/dist/neurolink.js
CHANGED
|
@@ -445,6 +445,8 @@ export class NeuroLink {
|
|
|
445
445
|
// Lazy-initialized routing decision cache (ITEM C). Created on first use so
|
|
446
446
|
// instances that don't use routing pay no overhead.
|
|
447
447
|
toolRoutingCacheInstance;
|
|
448
|
+
// Opt-in tool-signature deduplication config.
|
|
449
|
+
toolDedupConfig;
|
|
448
450
|
// Add orchestration property
|
|
449
451
|
enableOrchestration;
|
|
450
452
|
// Authentication provider for secure access control
|
|
@@ -857,6 +859,9 @@ export class NeuroLink {
|
|
|
857
859
|
// multiple NeuroLink instances.
|
|
858
860
|
this.toolRoutingConfig = { ...config.toolRouting };
|
|
859
861
|
}
|
|
862
|
+
if (config?.toolDedup) {
|
|
863
|
+
this.toolDedupConfig = { ...config.toolDedup };
|
|
864
|
+
}
|
|
860
865
|
logger.setEventEmitter(this.emitter);
|
|
861
866
|
// Read tool cache duration from environment variables, with a default
|
|
862
867
|
const cacheDurationEnv = process.env.NEUROLINK_TOOL_CACHE_DURATION;
|
|
@@ -7513,6 +7518,21 @@ Current user's request: ${currentInput}`;
|
|
|
7513
7518
|
getEventEmitter() {
|
|
7514
7519
|
return this.emitter;
|
|
7515
7520
|
}
|
|
7521
|
+
/**
|
|
7522
|
+
* Returns the instance-level tool-dedup configuration, or `undefined` when
|
|
7523
|
+
* toolDedup was not provided at construction time.
|
|
7524
|
+
*
|
|
7525
|
+
* The stored object is returned as-is whenever `toolDedup` was supplied,
|
|
7526
|
+
* including when `enabled: false` — only the complete absence of a `toolDedup`
|
|
7527
|
+
* option results in `undefined`.
|
|
7528
|
+
*
|
|
7529
|
+
* Called by `BaseProvider.applyToolFiltering` so the dedup pass uses the
|
|
7530
|
+
* same config for every generate/stream call without threading an extra
|
|
7531
|
+
* parameter through the full call stack.
|
|
7532
|
+
*/
|
|
7533
|
+
getToolDedupConfig() {
|
|
7534
|
+
return this.toolDedupConfig;
|
|
7535
|
+
}
|
|
7516
7536
|
/**
|
|
7517
7537
|
* Curator P1-1: synchronous credential health check for a single provider.
|
|
7518
7538
|
*
|