@juspay/neurolink 9.76.0 → 9.78.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 +341 -341
- package/dist/core/toolRouting.d.ts +9 -0
- package/dist/core/toolRouting.js +178 -1
- package/dist/core/toolRoutingEmbedding.d.ts +112 -0
- package/dist/core/toolRoutingEmbedding.js +322 -0
- package/dist/index.d.ts +31 -0
- package/dist/index.js +35 -0
- package/dist/lib/core/toolRouting.d.ts +9 -0
- package/dist/lib/core/toolRouting.js +178 -1
- package/dist/lib/core/toolRoutingEmbedding.d.ts +112 -0
- package/dist/lib/core/toolRoutingEmbedding.js +323 -0
- package/dist/lib/index.d.ts +31 -0
- package/dist/lib/index.js +35 -0
- package/dist/lib/neurolink.d.ts +22 -0
- package/dist/lib/neurolink.js +544 -175
- package/dist/lib/routing/index.d.ts +7 -0
- package/dist/lib/routing/index.js +8 -0
- package/dist/lib/routing/modelPool.d.ts +83 -0
- package/dist/lib/routing/modelPool.js +243 -0
- package/dist/lib/routing/requestRouter.d.ts +30 -0
- package/dist/lib/routing/requestRouter.js +81 -0
- package/dist/lib/types/config.d.ts +18 -0
- package/dist/lib/types/index.d.ts +2 -0
- package/dist/lib/types/index.js +4 -0
- package/dist/lib/types/modelPool.d.ts +47 -0
- package/dist/lib/types/modelPool.js +11 -0
- package/dist/lib/types/requestRouter.d.ts +75 -0
- package/dist/lib/types/requestRouter.js +16 -0
- package/dist/lib/types/toolRouting.d.ts +171 -0
- package/dist/lib/utils/providerErrorClassification.d.ts +24 -0
- package/dist/lib/utils/providerErrorClassification.js +89 -0
- package/dist/neurolink.d.ts +22 -0
- package/dist/neurolink.js +544 -175
- package/dist/routing/index.d.ts +7 -0
- package/dist/routing/index.js +7 -0
- package/dist/routing/modelPool.d.ts +83 -0
- package/dist/routing/modelPool.js +242 -0
- package/dist/routing/requestRouter.d.ts +30 -0
- package/dist/routing/requestRouter.js +80 -0
- package/dist/types/config.d.ts +18 -0
- package/dist/types/index.d.ts +2 -0
- package/dist/types/index.js +4 -0
- package/dist/types/modelPool.d.ts +47 -0
- package/dist/types/modelPool.js +10 -0
- package/dist/types/requestRouter.d.ts +75 -0
- package/dist/types/requestRouter.js +15 -0
- package/dist/types/toolRouting.d.ts +171 -0
- package/dist/utils/providerErrorClassification.d.ts +24 -0
- package/dist/utils/providerErrorClassification.js +88 -0
- package/package.json +6 -2
|
@@ -38,6 +38,71 @@ export type ToolRoutingModelConfig = {
|
|
|
38
38
|
/** Router sampling temperature. Default: 0. */
|
|
39
39
|
temperature?: number;
|
|
40
40
|
};
|
|
41
|
+
/**
|
|
42
|
+
* Weights for the hybrid scoring formula used by `ToolEmbeddingIndex.rank()`.
|
|
43
|
+
* Scores are computed as: `cosine * cosine + bm25 * bm25Score` then
|
|
44
|
+
* normalized before sorting.
|
|
45
|
+
* Default: `{ cosine: 0.8, bm25: 0.2 }`.
|
|
46
|
+
*/
|
|
47
|
+
export type ToolRetrievalWeights = {
|
|
48
|
+
/** Weight applied to the cosine-similarity (dense) component. */
|
|
49
|
+
cosine: number;
|
|
50
|
+
/** Weight applied to the BM25 (sparse/lexical) component. */
|
|
51
|
+
bm25: number;
|
|
52
|
+
};
|
|
53
|
+
/**
|
|
54
|
+
* Configuration for the L2 embedding fast-path (ITEM B).
|
|
55
|
+
*
|
|
56
|
+
* When enabled and the catalog's total tool count reaches `minToolsToActivate`,
|
|
57
|
+
* a hybrid cosine + BM25 retriever ranks all tools by relevance to the query
|
|
58
|
+
* and takes the top-`topK` candidates. This is far cheaper than an LLM call
|
|
59
|
+
* (sub-10 ms warm) and fires BEFORE or INSTEAD of the LLM router.
|
|
60
|
+
*
|
|
61
|
+
* Fail-open: any embedding error (missing provider, network failure, wrong
|
|
62
|
+
* model) silently falls back to the existing LLM-router / server-granularity
|
|
63
|
+
* path — the turn is never broken.
|
|
64
|
+
*/
|
|
65
|
+
export type ToolRoutingEmbeddingConfig = {
|
|
66
|
+
/**
|
|
67
|
+
* Activate the embedding fast-path. Default: false (backward-compatible).
|
|
68
|
+
* Setting this to true without supplying `provider`/`model` causes the SDK
|
|
69
|
+
* to try the stream call's configured provider; if that provider does not
|
|
70
|
+
* support embeddings the layer fails open.
|
|
71
|
+
*/
|
|
72
|
+
enabled?: boolean;
|
|
73
|
+
/**
|
|
74
|
+
* Maximum number of top-ranked tool candidates passed to the post-embedding
|
|
75
|
+
* decision stage. Default: 20.
|
|
76
|
+
*/
|
|
77
|
+
topK?: number;
|
|
78
|
+
/**
|
|
79
|
+
* Minimum total tool count in the catalog before the embedding path
|
|
80
|
+
* activates. Below this threshold the catalog is small enough that the LLM
|
|
81
|
+
* router alone is cheap and fast. Default: 20.
|
|
82
|
+
*/
|
|
83
|
+
minToolsToActivate?: number;
|
|
84
|
+
/**
|
|
85
|
+
* Weights for the hybrid scoring formula:
|
|
86
|
+
* score = cosine * cosineSim + bm25 * bm25Score (both normalized to [0,1])
|
|
87
|
+
* Default: `{ cosine: 0.8, bm25: 0.2 }`.
|
|
88
|
+
*/
|
|
89
|
+
weights?: ToolRetrievalWeights;
|
|
90
|
+
/**
|
|
91
|
+
* Provider name to use for the embedding call (e.g. "openai", "vertex").
|
|
92
|
+
* Defaults to the stream/generate call's configured provider. The provider
|
|
93
|
+
* must support `embedMany()`.
|
|
94
|
+
*/
|
|
95
|
+
provider?: string;
|
|
96
|
+
/**
|
|
97
|
+
* Embedding model name (provider-specific). When omitted the provider's
|
|
98
|
+
* default embedding model is used (e.g. text-embedding-3-small for OpenAI).
|
|
99
|
+
*/
|
|
100
|
+
model?: string;
|
|
101
|
+
/**
|
|
102
|
+
* Timeout for embedding calls in milliseconds. Default: 10000.
|
|
103
|
+
*/
|
|
104
|
+
timeoutMs?: number;
|
|
105
|
+
};
|
|
41
106
|
/** Constructor-level configuration for pre-call tool routing. */
|
|
42
107
|
export type ToolRoutingConfig = {
|
|
43
108
|
/** Master switch. Routing runs only when true AND the server catalog is non-empty. */
|
|
@@ -88,6 +153,24 @@ export type ToolRoutingConfig = {
|
|
|
88
153
|
/** Number of turns for which a previously-selected server stays warm. Default: 3. */
|
|
89
154
|
turns?: number;
|
|
90
155
|
};
|
|
156
|
+
/**
|
|
157
|
+
* L2 embedding fast-path (ITEM B). When enabled the SDK ranks tools by
|
|
158
|
+
* semantic + lexical relevance using a hybrid cosine/BM25 score and narrows
|
|
159
|
+
* the candidate set BEFORE (or instead of) the LLM router. Disabled by
|
|
160
|
+
* default for backward compatibility.
|
|
161
|
+
*/
|
|
162
|
+
embedding?: ToolRoutingEmbeddingConfig;
|
|
163
|
+
/**
|
|
164
|
+
* Routing granularity (ITEM D).
|
|
165
|
+
*
|
|
166
|
+
* - `"server"` (default) — routing excludes the tools of entire unpicked
|
|
167
|
+
* servers. This is the original behavior.
|
|
168
|
+
* - `"tool"` — routing excludes individual tools that are not in the
|
|
169
|
+
* embedding top-K candidate set, regardless of which server they belong
|
|
170
|
+
* to. Requires `embedding.enabled: true`; if the embedding fast-path is
|
|
171
|
+
* off (or fails) the granularity falls back to `"server"` automatically.
|
|
172
|
+
*/
|
|
173
|
+
granularity?: "server" | "tool";
|
|
91
174
|
};
|
|
92
175
|
/** Catalog entry pairing a server descriptor with its registered tool names. */
|
|
93
176
|
export type ToolRoutingCatalogEntry = {
|
|
@@ -152,6 +235,19 @@ export type ToolRoutingDecision = {
|
|
|
152
235
|
cacheHit: boolean;
|
|
153
236
|
/** Wall-clock time spent in the routing resolution in milliseconds. */
|
|
154
237
|
durationMs: number;
|
|
238
|
+
/** True when the L2 embedding fast-path ran and produced candidate results. */
|
|
239
|
+
embeddingActivated?: boolean;
|
|
240
|
+
/**
|
|
241
|
+
* Number of tool candidates produced by the embedding retriever before the
|
|
242
|
+
* post-embedding server or tool filtering step.
|
|
243
|
+
*/
|
|
244
|
+
candidateToolCount?: number;
|
|
245
|
+
/**
|
|
246
|
+
* Granularity at which exclusions were applied ("server" or "tool").
|
|
247
|
+
* Matches `ToolRoutingConfig.granularity`; present only when routing was
|
|
248
|
+
* applied (outcome === "applied").
|
|
249
|
+
*/
|
|
250
|
+
granularity?: "server" | "tool";
|
|
155
251
|
};
|
|
156
252
|
/** Parameters for `resolveToolRoutingExclusions()`. */
|
|
157
253
|
export type ToolRoutingResolutionParams = {
|
|
@@ -176,4 +272,79 @@ export type ToolRoutingResolutionParams = {
|
|
|
176
272
|
* the resolver.
|
|
177
273
|
*/
|
|
178
274
|
emitDecision?: (decision: ToolRoutingDecision) => void;
|
|
275
|
+
/**
|
|
276
|
+
* Injected async function that converts an array of texts into embedding
|
|
277
|
+
* vectors. Built by the caller (NeuroLink) from the configured embedding
|
|
278
|
+
* provider so the resolver stays pure and free of provider imports.
|
|
279
|
+
* When undefined the embedding fast-path is skipped entirely.
|
|
280
|
+
*/
|
|
281
|
+
embedFn?: (texts: string[]) => Promise<number[][]>;
|
|
282
|
+
/**
|
|
283
|
+
* Embedding fast-path configuration forwarded from `ToolRoutingConfig`.
|
|
284
|
+
* Only consulted when `embedFn` is provided.
|
|
285
|
+
*/
|
|
286
|
+
embeddingConfig?: ToolRoutingEmbeddingConfig;
|
|
287
|
+
/**
|
|
288
|
+
* Routing granularity forwarded from `ToolRoutingConfig`. Default: "server".
|
|
289
|
+
*/
|
|
290
|
+
granularity?: "server" | "tool";
|
|
291
|
+
/**
|
|
292
|
+
* Optional shared vector cache for the L2 embedding fast-path. When
|
|
293
|
+
* supplied, tool embedding vectors computed on prior turns are reused rather
|
|
294
|
+
* than re-fetched from the embedding provider on every call.
|
|
295
|
+
*
|
|
296
|
+
* The NeuroLink instance manages the lifecycle: it creates the Map once and
|
|
297
|
+
* passes the same reference across turns. It clears the reference when the
|
|
298
|
+
* tool catalog changes (via `setToolRoutingServers`) so stale vectors are
|
|
299
|
+
* never used after a catalog update.
|
|
300
|
+
*/
|
|
301
|
+
embeddingVectorCache?: Map<string, number[]>;
|
|
302
|
+
};
|
|
303
|
+
/**
|
|
304
|
+
* A single item in the tool retrieval catalog, pairing a tool name with the
|
|
305
|
+
* text (tool description + server context) used to build its embedding vector.
|
|
306
|
+
*/
|
|
307
|
+
export type ToolRetrievalItem = {
|
|
308
|
+
/** Fully-qualified tool name (e.g. `${serverId}_${toolName}`). */
|
|
309
|
+
name: string;
|
|
310
|
+
/** Descriptive text used as the embedding document for this tool. */
|
|
311
|
+
text: string;
|
|
312
|
+
};
|
|
313
|
+
/**
|
|
314
|
+
* One ranked result from `ToolEmbeddingIndex.rank()` or
|
|
315
|
+
* `selectRelevantToolNames()`.
|
|
316
|
+
*/
|
|
317
|
+
export type ToolRetrievalRankedResult = {
|
|
318
|
+
/** Tool name (mirrors `ToolRetrievalItem.name`). */
|
|
319
|
+
name: string;
|
|
320
|
+
/** Combined hybrid score (higher = more relevant). */
|
|
321
|
+
score: number;
|
|
322
|
+
};
|
|
323
|
+
/**
|
|
324
|
+
* Options passed to `selectRelevantToolNames()` — the high-level convenience
|
|
325
|
+
* wrapper around `ToolEmbeddingIndex`.
|
|
326
|
+
*/
|
|
327
|
+
export type ToolRetrievalSelectOptions = {
|
|
328
|
+
/** Maximum number of tool names to return. */
|
|
329
|
+
topK: number;
|
|
330
|
+
/** Optional weight override (defaults to `{ cosine: 0.8, bm25: 0.2 }`). */
|
|
331
|
+
weights?: ToolRetrievalWeights;
|
|
332
|
+
/**
|
|
333
|
+
* Async function that converts an array of text strings into embedding
|
|
334
|
+
* vectors. Must return one vector per input text in the same order.
|
|
335
|
+
* Errors thrown here propagate to the caller (so it can fail open).
|
|
336
|
+
*/
|
|
337
|
+
embedFn: (texts: string[]) => Promise<number[][]>;
|
|
338
|
+
/**
|
|
339
|
+
* Optional shared vector cache (keyed by text string). When supplied the
|
|
340
|
+
* underlying `ToolEmbeddingIndex` reads from and writes to this Map so that
|
|
341
|
+
* tool vectors computed on a prior call are reused on subsequent calls for
|
|
342
|
+
* the same item text. Callers that want warm-cache behavior across turns
|
|
343
|
+
* should pass the same Map instance each time.
|
|
344
|
+
*/
|
|
345
|
+
vectorCache?: Map<string, number[]>;
|
|
346
|
+
/**
|
|
347
|
+
* Timeout for each embedding provider call in milliseconds. Default: 10000.
|
|
348
|
+
*/
|
|
349
|
+
timeoutMs?: number;
|
|
179
350
|
};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared provider-error classification utilities used by both neurolink.ts and
|
|
3
|
+
* the ModelPool routing subsystem.
|
|
4
|
+
*
|
|
5
|
+
* Extracted here to avoid duplication and to ensure that typed error classes
|
|
6
|
+
* (AuthenticationError, AuthorizationError, ModelAccessDeniedError) are
|
|
7
|
+
* checked consistently in both code paths.
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Detects whether an error object looks like a model-access-denied condition.
|
|
11
|
+
* Matches LiteLLM "team not allowed" / "team can only access models=[...]"
|
|
12
|
+
* plus typed-error name/code markers when the full typed class is not present.
|
|
13
|
+
*/
|
|
14
|
+
export declare function looksLikeModelAccessDenied(error: unknown): boolean;
|
|
15
|
+
/**
|
|
16
|
+
* Returns true when the error is definitively non-retryable: typed error
|
|
17
|
+
* classes (auth, access-denied, invalid-model), non-retryable HTTP status
|
|
18
|
+
* codes, or deterministic 400-class message patterns.
|
|
19
|
+
*
|
|
20
|
+
* NOTE: ContextBudgetExceededError is intentionally NOT non-retryable —
|
|
21
|
+
* each provider has its own context window, so a budget rejection on one
|
|
22
|
+
* provider does not preclude another provider accepting the same payload.
|
|
23
|
+
*/
|
|
24
|
+
export declare function isNonRetryableProviderError(error: unknown): boolean;
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared provider-error classification utilities used by both neurolink.ts and
|
|
3
|
+
* the ModelPool routing subsystem.
|
|
4
|
+
*
|
|
5
|
+
* Extracted here to avoid duplication and to ensure that typed error classes
|
|
6
|
+
* (AuthenticationError, AuthorizationError, ModelAccessDeniedError) are
|
|
7
|
+
* checked consistently in both code paths.
|
|
8
|
+
*/
|
|
9
|
+
import { AuthenticationError, AuthorizationError, InvalidModelError, ModelAccessDeniedError, } from "../types/index.js";
|
|
10
|
+
import { NON_RETRYABLE_HTTP_STATUS_CODES, isDeterministicClientErrorMessage, } from "./retryability.js";
|
|
11
|
+
/**
|
|
12
|
+
* Detects whether an error object looks like a model-access-denied condition.
|
|
13
|
+
* Matches LiteLLM "team not allowed" / "team can only access models=[...]"
|
|
14
|
+
* plus typed-error name/code markers when the full typed class is not present.
|
|
15
|
+
*/
|
|
16
|
+
export function looksLikeModelAccessDenied(error) {
|
|
17
|
+
if (!error) {
|
|
18
|
+
return false;
|
|
19
|
+
}
|
|
20
|
+
const e = error;
|
|
21
|
+
if (e.name === "ModelAccessDeniedError") {
|
|
22
|
+
return true;
|
|
23
|
+
}
|
|
24
|
+
if (e.code === "MODEL_ACCESS_DENIED") {
|
|
25
|
+
return true;
|
|
26
|
+
}
|
|
27
|
+
const msg = typeof e.message === "string"
|
|
28
|
+
? e.message
|
|
29
|
+
: error instanceof Error
|
|
30
|
+
? error.message
|
|
31
|
+
: String(error);
|
|
32
|
+
if (!msg) {
|
|
33
|
+
return false;
|
|
34
|
+
}
|
|
35
|
+
const lower = msg.toLowerCase();
|
|
36
|
+
return ((lower.includes("team") && lower.includes("not allowed")) ||
|
|
37
|
+
lower.includes("team can only access") ||
|
|
38
|
+
/not\s+allowed\s+to\s+access\s+(this\s+)?model/i.test(msg));
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Returns true when the error is definitively non-retryable: typed error
|
|
42
|
+
* classes (auth, access-denied, invalid-model), non-retryable HTTP status
|
|
43
|
+
* codes, or deterministic 400-class message patterns.
|
|
44
|
+
*
|
|
45
|
+
* NOTE: ContextBudgetExceededError is intentionally NOT non-retryable —
|
|
46
|
+
* each provider has its own context window, so a budget rejection on one
|
|
47
|
+
* provider does not preclude another provider accepting the same payload.
|
|
48
|
+
*/
|
|
49
|
+
export function isNonRetryableProviderError(error) {
|
|
50
|
+
if (error instanceof InvalidModelError) {
|
|
51
|
+
return true;
|
|
52
|
+
}
|
|
53
|
+
if (error instanceof AuthenticationError) {
|
|
54
|
+
return true;
|
|
55
|
+
}
|
|
56
|
+
if (error instanceof AuthorizationError) {
|
|
57
|
+
return true;
|
|
58
|
+
}
|
|
59
|
+
if (error instanceof ModelAccessDeniedError) {
|
|
60
|
+
return true;
|
|
61
|
+
}
|
|
62
|
+
if (error && typeof error === "object") {
|
|
63
|
+
const err = error;
|
|
64
|
+
const status = typeof err.status === "number"
|
|
65
|
+
? err.status
|
|
66
|
+
: typeof err.statusCode === "number"
|
|
67
|
+
? err.statusCode
|
|
68
|
+
: undefined;
|
|
69
|
+
if (status !== undefined &&
|
|
70
|
+
NON_RETRYABLE_HTTP_STATUS_CODES.includes(status)) {
|
|
71
|
+
return true;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
if (error instanceof Error) {
|
|
75
|
+
const msg = error.message;
|
|
76
|
+
if (msg.includes("NOT_FOUND") ||
|
|
77
|
+
msg.includes("Model Not Found") ||
|
|
78
|
+
msg.includes("model not found") ||
|
|
79
|
+
msg.includes("PERMISSION_DENIED") ||
|
|
80
|
+
msg.includes("UNAUTHENTICATED")) {
|
|
81
|
+
return true;
|
|
82
|
+
}
|
|
83
|
+
if (isDeterministicClientErrorMessage(msg)) {
|
|
84
|
+
return true;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
return false;
|
|
88
|
+
}
|
|
89
|
+
//# sourceMappingURL=providerErrorClassification.js.map
|
package/dist/neurolink.d.ts
CHANGED
|
@@ -102,6 +102,7 @@ export declare class NeuroLink {
|
|
|
102
102
|
private conversationMemoryConfig?;
|
|
103
103
|
private toolRoutingConfig?;
|
|
104
104
|
private toolRoutingCacheInstance?;
|
|
105
|
+
private toolRoutingVectorCache?;
|
|
105
106
|
private toolDedupConfig?;
|
|
106
107
|
private enableOrchestration;
|
|
107
108
|
private authProvider?;
|
|
@@ -109,6 +110,8 @@ export declare class NeuroLink {
|
|
|
109
110
|
private authInitPromise?;
|
|
110
111
|
private credentials?;
|
|
111
112
|
private readonly fallbackConfig;
|
|
113
|
+
private readonly modelPool;
|
|
114
|
+
private readonly requestRouter;
|
|
112
115
|
/**
|
|
113
116
|
* Merge instance-level credentials with per-call credentials.
|
|
114
117
|
*
|
|
@@ -612,6 +615,25 @@ export declare class NeuroLink {
|
|
|
612
615
|
private maybeHandleEarlyGenerateResult;
|
|
613
616
|
private runStandardGenerateRequest;
|
|
614
617
|
private maybeApplyGenerateOrchestration;
|
|
618
|
+
/**
|
|
619
|
+
* Applies the host-configured `requestRouter` to `options` in place.
|
|
620
|
+
*
|
|
621
|
+
* The router is skipped when:
|
|
622
|
+
* - no `requestRouter` is configured on this instance, or
|
|
623
|
+
* - the caller explicitly set both `options.provider` AND `options.model`
|
|
624
|
+
* (we only skip the router if BOTH are set; a caller setting only one
|
|
625
|
+
* still lets the router fill in the other field).
|
|
626
|
+
*
|
|
627
|
+
* Fails open: any router error is logged at WARN level and the call
|
|
628
|
+
* continues with the original options unmodified.
|
|
629
|
+
*
|
|
630
|
+
* @param options — the mutable options object (generate or stream).
|
|
631
|
+
* @param promptText — the text prompt used to build the RouterInputContext.
|
|
632
|
+
* @param hasTools — true when at least one tool is available for this call.
|
|
633
|
+
* @param requiresVision — true when the call includes image attachments.
|
|
634
|
+
* @param thinkingLevel — optional thinking level string from the call options.
|
|
635
|
+
*/
|
|
636
|
+
private applyRequestRouter;
|
|
615
637
|
private prepareGenerateAugmentations;
|
|
616
638
|
private buildGenerateTextOptions;
|
|
617
639
|
private finalizeGenerateRequestResult;
|