@juspay/neurolink 12.49.4 → 12.49.6
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 +2 -3
- package/dist/browser/neurolink.min.js +334 -334
- package/dist/constants/contextWindows.d.ts +11 -0
- package/dist/constants/contextWindows.js +5 -1
- package/dist/providers/litellm/client.d.ts +5 -0
- package/dist/providers/litellm/client.js +33 -7
- package/dist/providers/ollama/client.d.ts +5 -0
- package/dist/providers/ollama/client.js +33 -7
- package/dist/proxy/utils/noProxyUtils.d.ts +4 -0
- package/dist/proxy/utils/noProxyUtils.js +24 -5
- package/dist/types/providers.d.ts +7 -0
- package/dist/utils/tokenLimits.js +11 -1
- package/docs-site/static/search-index.json +2 -2
- package/package.json +1 -1
|
@@ -56,6 +56,17 @@ export declare function getRuntimeOutputCeiling(provider: string, model?: string
|
|
|
56
56
|
export declare function clearRuntimeOutputCeiling(provider: string, model: string): void;
|
|
57
57
|
/** Test hook: clear runtime-discovered output ceilings (state is module-global). */
|
|
58
58
|
export declare function clearRuntimeOutputCeilings(): void;
|
|
59
|
+
/**
|
|
60
|
+
* `us.anthropic.claude-sonnet-4-6` -> `anthropic.claude-sonnet-4-6`.
|
|
61
|
+
*
|
|
62
|
+
* Undefined for any other shape, so an id that merely starts with `us.` is
|
|
63
|
+
* never rewritten. Removes one geography at most: no vendor is a geography.
|
|
64
|
+
*
|
|
65
|
+
* Every Bedrock table keyed by bare ids (context windows here, output ceilings
|
|
66
|
+
* in `getSafeMaxTokens`) goes through this one function, so they cannot
|
|
67
|
+
* disagree about which ids are cross-region profile ids.
|
|
68
|
+
*/
|
|
69
|
+
export declare function stripBedrockGeoPrefix(model: string): string | undefined;
|
|
59
70
|
/**
|
|
60
71
|
* Resolve context window size for a provider/model combination.
|
|
61
72
|
*
|
|
@@ -507,8 +507,12 @@ const BEDROCK_VENDORS = new Set(Object.values(BedrockModels)
|
|
|
507
507
|
*
|
|
508
508
|
* Undefined for any other shape, so an id that merely starts with `us.` is
|
|
509
509
|
* never rewritten. Removes one geography at most: no vendor is a geography.
|
|
510
|
+
*
|
|
511
|
+
* Every Bedrock table keyed by bare ids (context windows here, output ceilings
|
|
512
|
+
* in `getSafeMaxTokens`) goes through this one function, so they cannot
|
|
513
|
+
* disagree about which ids are cross-region profile ids.
|
|
510
514
|
*/
|
|
511
|
-
function stripBedrockGeoPrefix(model) {
|
|
515
|
+
export function stripBedrockGeoPrefix(model) {
|
|
512
516
|
const [geo, vendor, ...rest] = model.split(".");
|
|
513
517
|
if (rest.length === 0 ||
|
|
514
518
|
!BEDROCK_GEO_PREFIXES.has(geo) ||
|
|
@@ -92,5 +92,10 @@ export declare class LiteLLMProvider extends OpenAIChatCompletionsProvider {
|
|
|
92
92
|
* Generate embeddings for multiple text inputs via native /v1/embeddings.
|
|
93
93
|
*/
|
|
94
94
|
embedMany(texts: string[], modelName?: string): Promise<number[][]>;
|
|
95
|
+
/**
|
|
96
|
+
* One non-empty vector per input, or fail: a dropped or empty row would
|
|
97
|
+
* pair later texts with the wrong vectors, or score 0 downstream.
|
|
98
|
+
*/
|
|
99
|
+
private requireEmbeddings;
|
|
95
100
|
private callEmbeddings;
|
|
96
101
|
}
|
|
@@ -474,7 +474,8 @@ export class LiteLLMProvider extends OpenAIChatCompletionsProvider {
|
|
|
474
474
|
const embeddingModelName = modelName ||
|
|
475
475
|
process.env.LITELLM_EMBEDDING_MODEL ||
|
|
476
476
|
"gemini-embedding-001";
|
|
477
|
-
const
|
|
477
|
+
const rows = await this.callEmbeddings(embeddingModelName, [text], "embed");
|
|
478
|
+
const [embedding] = this.requireEmbeddings(rows, 1, embeddingModelName);
|
|
478
479
|
return embedding;
|
|
479
480
|
}
|
|
480
481
|
/**
|
|
@@ -484,7 +485,34 @@ export class LiteLLMProvider extends OpenAIChatCompletionsProvider {
|
|
|
484
485
|
const embeddingModelName = modelName ||
|
|
485
486
|
process.env.LITELLM_EMBEDDING_MODEL ||
|
|
486
487
|
"gemini-embedding-001";
|
|
487
|
-
|
|
488
|
+
const rows = await this.callEmbeddings(embeddingModelName, texts, "embedMany");
|
|
489
|
+
return this.requireEmbeddings(rows, texts.length, embeddingModelName);
|
|
490
|
+
}
|
|
491
|
+
/**
|
|
492
|
+
* One non-empty vector per input, or fail: a dropped or empty row would
|
|
493
|
+
* pair later texts with the wrong vectors, or score 0 downstream.
|
|
494
|
+
*/
|
|
495
|
+
requireEmbeddings(rows, inputCount, modelName) {
|
|
496
|
+
if (rows.length !== inputCount) {
|
|
497
|
+
logger.error("Embedding response held the wrong number of vectors", {
|
|
498
|
+
provider: this.providerName,
|
|
499
|
+
model: modelName,
|
|
500
|
+
expected: inputCount,
|
|
501
|
+
received: rows.length,
|
|
502
|
+
});
|
|
503
|
+
throw new ProviderError(`Embedding response held ${rows.length} vectors for ${inputCount} texts`, this.providerName);
|
|
504
|
+
}
|
|
505
|
+
return rows.map((values, index) => {
|
|
506
|
+
if (!values || values.length === 0) {
|
|
507
|
+
logger.error("Embedding returned no values", {
|
|
508
|
+
provider: this.providerName,
|
|
509
|
+
model: modelName,
|
|
510
|
+
index,
|
|
511
|
+
});
|
|
512
|
+
throw new ProviderError(`Embedding for the text at index ${index} came back without values`, this.providerName);
|
|
513
|
+
}
|
|
514
|
+
return values;
|
|
515
|
+
});
|
|
488
516
|
}
|
|
489
517
|
async callEmbeddings(modelName, input, operation) {
|
|
490
518
|
const url = `${stripTrailingSlash(this.config.baseURL)}/embeddings`;
|
|
@@ -514,13 +542,11 @@ export class LiteLLMProvider extends OpenAIChatCompletionsProvider {
|
|
|
514
542
|
`LiteLLM ${operation} failed with status ${res.status}`));
|
|
515
543
|
}
|
|
516
544
|
const json = (await res.json());
|
|
517
|
-
const
|
|
518
|
-
|
|
519
|
-
.filter((e) => Array.isArray(e));
|
|
520
|
-
if (embeddings.length === 0) {
|
|
545
|
+
const rows = (json.data ?? []).map((row) => Array.isArray(row.embedding) ? row.embedding : undefined);
|
|
546
|
+
if (rows.length === 0) {
|
|
521
547
|
throw new ProviderError(`LiteLLM ${operation} returned no embeddings`, this.providerName);
|
|
522
548
|
}
|
|
523
|
-
return
|
|
549
|
+
return rows;
|
|
524
550
|
}
|
|
525
551
|
finally {
|
|
526
552
|
timeoutController?.cleanup();
|
|
@@ -67,5 +67,10 @@ export declare class OllamaProvider extends OpenAIChatCompletionsProvider {
|
|
|
67
67
|
* Generate embeddings for multiple text inputs via native /v1/embeddings.
|
|
68
68
|
*/
|
|
69
69
|
embedMany(texts: string[], modelName?: string): Promise<number[][]>;
|
|
70
|
+
/**
|
|
71
|
+
* One non-empty vector per input, or fail: a dropped or empty row would
|
|
72
|
+
* pair later texts with the wrong vectors, or score 0 downstream.
|
|
73
|
+
*/
|
|
74
|
+
private requireEmbeddings;
|
|
70
75
|
private callEmbeddings;
|
|
71
76
|
}
|
|
@@ -216,7 +216,8 @@ export class OllamaProvider extends OpenAIChatCompletionsProvider {
|
|
|
216
216
|
const embeddingModel = modelName ||
|
|
217
217
|
process.env.OLLAMA_EMBEDDING_MODEL ||
|
|
218
218
|
DEFAULT_EMBEDDING_MODEL;
|
|
219
|
-
const
|
|
219
|
+
const rows = await this.callEmbeddings(embeddingModel, [text], "embed");
|
|
220
|
+
const [embedding] = this.requireEmbeddings(rows, 1, embeddingModel);
|
|
220
221
|
return embedding;
|
|
221
222
|
}
|
|
222
223
|
/**
|
|
@@ -226,7 +227,34 @@ export class OllamaProvider extends OpenAIChatCompletionsProvider {
|
|
|
226
227
|
const embeddingModel = modelName ||
|
|
227
228
|
process.env.OLLAMA_EMBEDDING_MODEL ||
|
|
228
229
|
DEFAULT_EMBEDDING_MODEL;
|
|
229
|
-
|
|
230
|
+
const rows = await this.callEmbeddings(embeddingModel, texts, "embedMany");
|
|
231
|
+
return this.requireEmbeddings(rows, texts.length, embeddingModel);
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* One non-empty vector per input, or fail: a dropped or empty row would
|
|
235
|
+
* pair later texts with the wrong vectors, or score 0 downstream.
|
|
236
|
+
*/
|
|
237
|
+
requireEmbeddings(rows, inputCount, modelName) {
|
|
238
|
+
if (rows.length !== inputCount) {
|
|
239
|
+
logger.error("Embedding response held the wrong number of vectors", {
|
|
240
|
+
provider: this.providerName,
|
|
241
|
+
model: modelName,
|
|
242
|
+
expected: inputCount,
|
|
243
|
+
received: rows.length,
|
|
244
|
+
});
|
|
245
|
+
throw new ProviderError(`Embedding response held ${rows.length} vectors for ${inputCount} texts`, this.providerName);
|
|
246
|
+
}
|
|
247
|
+
return rows.map((values, index) => {
|
|
248
|
+
if (!values || values.length === 0) {
|
|
249
|
+
logger.error("Embedding returned no values", {
|
|
250
|
+
provider: this.providerName,
|
|
251
|
+
model: modelName,
|
|
252
|
+
index,
|
|
253
|
+
});
|
|
254
|
+
throw new ProviderError(`Embedding for the text at index ${index} came back without values`, this.providerName);
|
|
255
|
+
}
|
|
256
|
+
return values;
|
|
257
|
+
});
|
|
230
258
|
}
|
|
231
259
|
async callEmbeddings(modelName, input, operation) {
|
|
232
260
|
const url = `${stripTrailingSlash(this.config.baseURL)}/embeddings`;
|
|
@@ -265,13 +293,11 @@ export class OllamaProvider extends OpenAIChatCompletionsProvider {
|
|
|
265
293
|
`Ollama ${operation} failed with status ${res.status}`));
|
|
266
294
|
}
|
|
267
295
|
const json = (await res.json());
|
|
268
|
-
const
|
|
269
|
-
|
|
270
|
-
.filter((e) => Array.isArray(e));
|
|
271
|
-
if (embeddings.length === 0) {
|
|
296
|
+
const rows = (json.data ?? []).map((row) => Array.isArray(row.embedding) ? row.embedding : undefined);
|
|
297
|
+
if (rows.length === 0) {
|
|
272
298
|
throw new ProviderError(`Ollama ${operation} returned no embeddings`, "ollama");
|
|
273
299
|
}
|
|
274
|
-
return
|
|
300
|
+
return rows;
|
|
275
301
|
}
|
|
276
302
|
finally {
|
|
277
303
|
timeoutController?.cleanup();
|
|
@@ -17,6 +17,8 @@
|
|
|
17
17
|
* - "192.168.1.10", "::1", "[::1]:8080" - an IP literal, exactly
|
|
18
18
|
* - "192.168.1.0/24" - an IPv4 CIDR range, for IPv4 literal targets (IPv6 CIDR
|
|
19
19
|
* ranges are not supported)
|
|
20
|
+
* - "." and ".." - an entry made only of dots names no host, so it matches
|
|
21
|
+
* nothing, as in curl
|
|
20
22
|
*
|
|
21
23
|
* @param targetUrl - The URL to check for proxy bypass
|
|
22
24
|
* @param noProxyEnv - Optional NO_PROXY environment variable value (if not provided, reads from process.env)
|
|
@@ -37,6 +39,8 @@ export declare function getNoProxyEnv(): string | undefined;
|
|
|
37
39
|
* - "example.com" - exact match
|
|
38
40
|
* - ".example.com" - domain suffix match
|
|
39
41
|
*
|
|
42
|
+
* An entry made only of dots names no host and matches nothing.
|
|
43
|
+
*
|
|
40
44
|
* @param targetUrl - The URL to check
|
|
41
45
|
* @param noProxyValue - The NO_PROXY value to check against
|
|
42
46
|
* @returns true if should bypass proxy
|
|
@@ -44,6 +44,10 @@ function canonicalIpv6Host(address) {
|
|
|
44
44
|
function withoutTrailingDot(name) {
|
|
45
45
|
return name.endsWith(".") ? name.slice(0, -1) : name;
|
|
46
46
|
}
|
|
47
|
+
/** An entry made only of dots (`.`, `..`) names no host. */
|
|
48
|
+
function isDotsOnly(entry) {
|
|
49
|
+
return /^\.+$/.test(entry);
|
|
50
|
+
}
|
|
47
51
|
/**
|
|
48
52
|
* curl's rules for one list entry: an optional leading `.` or `*.` is ignored;
|
|
49
53
|
* the entry names that host and every subdomain of it, an IP literal only
|
|
@@ -106,13 +110,20 @@ function matchesNoProxyEntry(entry, hostname, port) {
|
|
|
106
110
|
return name === domain || name.endsWith(`.${domain}`);
|
|
107
111
|
}
|
|
108
112
|
/**
|
|
109
|
-
* The rules this function applied before it followed curl,
|
|
110
|
-
*
|
|
111
|
-
*
|
|
112
|
-
*
|
|
113
|
-
*
|
|
113
|
+
* The rules this function applied before it followed curl, still consulted so
|
|
114
|
+
* that a configuration that bypassed the proxy through them keeps doing so.
|
|
115
|
+
* That includes where they are looser than curl (`.example.com` also matches
|
|
116
|
+
* `notexample.com`) and an IPv4 CIDR range such as `192.168.1.0/24`, which
|
|
117
|
+
* curl-style entries do not express. They are unchanged except that an entry
|
|
118
|
+
* made only of dots names no host, as in the curl-style rules.
|
|
114
119
|
*/
|
|
115
120
|
function matchesLegacyNoProxyEntry(lowerPattern, hostname, port) {
|
|
121
|
+
// Taken as a suffix, "." leaves the empty string, which every host name ends
|
|
122
|
+
// with, and ".." leaves ".", which every host written with a trailing dot
|
|
123
|
+
// ends with.
|
|
124
|
+
if (isDotsOnly(lowerPattern)) {
|
|
125
|
+
return false;
|
|
126
|
+
}
|
|
116
127
|
// Domain suffix match (.example.com)
|
|
117
128
|
if (lowerPattern.startsWith(".")) {
|
|
118
129
|
const suffix = lowerPattern.slice(1);
|
|
@@ -145,6 +156,8 @@ function matchesLegacyNoProxyEntry(lowerPattern, hostname, port) {
|
|
|
145
156
|
* - "192.168.1.10", "::1", "[::1]:8080" - an IP literal, exactly
|
|
146
157
|
* - "192.168.1.0/24" - an IPv4 CIDR range, for IPv4 literal targets (IPv6 CIDR
|
|
147
158
|
* ranges are not supported)
|
|
159
|
+
* - "." and ".." - an entry made only of dots names no host, so it matches
|
|
160
|
+
* nothing, as in curl
|
|
148
161
|
*
|
|
149
162
|
* @param targetUrl - The URL to check for proxy bypass
|
|
150
163
|
* @param noProxyEnv - Optional NO_PROXY environment variable value (if not provided, reads from process.env)
|
|
@@ -197,6 +210,8 @@ export function getNoProxyEnv() {
|
|
|
197
210
|
* - "example.com" - exact match
|
|
198
211
|
* - ".example.com" - domain suffix match
|
|
199
212
|
*
|
|
213
|
+
* An entry made only of dots names no host and matches nothing.
|
|
214
|
+
*
|
|
200
215
|
* @param targetUrl - The URL to check
|
|
201
216
|
* @param noProxyValue - The NO_PROXY value to check against
|
|
202
217
|
* @returns true if should bypass proxy
|
|
@@ -211,6 +226,10 @@ export function shouldBypassProxySimple(targetUrl, noProxyValue) {
|
|
|
211
226
|
if (!pattern) {
|
|
212
227
|
continue;
|
|
213
228
|
}
|
|
229
|
+
// As a suffix, "." would match every host written with a trailing dot.
|
|
230
|
+
if (isDotsOnly(pattern)) {
|
|
231
|
+
continue;
|
|
232
|
+
}
|
|
214
233
|
// Exact match
|
|
215
234
|
if (hostname === pattern) {
|
|
216
235
|
return true;
|
|
@@ -136,6 +136,13 @@ export type NeurolinkCredentials = {
|
|
|
136
136
|
/** Inline service-account fields (alternative to serviceAccountKey) */
|
|
137
137
|
clientEmail?: string;
|
|
138
138
|
privateKey?: string;
|
|
139
|
+
/**
|
|
140
|
+
* Overrides the Vertex API base URL, e.g. to reach a local stand-in. Used
|
|
141
|
+
* for Gemini and Claude models, in Express Mode and with a project and
|
|
142
|
+
* location. Takes precedence over `GOOGLE_VERTEX_BASE_URL`; a blank value
|
|
143
|
+
* counts as unset.
|
|
144
|
+
*/
|
|
145
|
+
baseURL?: string;
|
|
139
146
|
};
|
|
140
147
|
bedrock?: {
|
|
141
148
|
accessKeyId?: string;
|
|
@@ -2,7 +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
|
+
import { getRuntimeOutputCeiling, stripBedrockGeoPrefix, } from "../constants/contextWindows.js";
|
|
6
6
|
import { PROVIDER_MAX_TOKENS } from "../core/constants.js";
|
|
7
7
|
import { logger } from "./logger.js";
|
|
8
8
|
import { hasRestrictedOutputLimit, RESTRICTED_OUTPUT_TOKEN_LIMIT, } from "./modelDetection.js";
|
|
@@ -67,6 +67,11 @@ export function getSafeMaxTokens(provider, model, requestedMaxTokens) {
|
|
|
67
67
|
}
|
|
68
68
|
return requestedMaxTokens;
|
|
69
69
|
}
|
|
70
|
+
// The Bedrock rows are keyed by bare id, but for many models the cross-region
|
|
71
|
+
// profile id (us.amazon.nova-pro-v1:0) is the only one a caller can invoke.
|
|
72
|
+
// The bare id is tried only after the id as given misses, so an explicit row
|
|
73
|
+
// for the prefixed id still wins.
|
|
74
|
+
const bareModel = provider === "bedrock" && model ? stripBedrockGeoPrefix(model) : undefined;
|
|
70
75
|
// Get model-specific limit or provider default
|
|
71
76
|
let maxLimit;
|
|
72
77
|
if (model &&
|
|
@@ -74,6 +79,11 @@ export function getSafeMaxTokens(provider, model, requestedMaxTokens) {
|
|
|
74
79
|
providerLimits[model]) {
|
|
75
80
|
maxLimit = providerLimits[model];
|
|
76
81
|
}
|
|
82
|
+
else if (bareModel !== undefined &&
|
|
83
|
+
typeof providerLimits === "object" &&
|
|
84
|
+
providerLimits[bareModel]) {
|
|
85
|
+
maxLimit = providerLimits[bareModel];
|
|
86
|
+
}
|
|
77
87
|
else if (typeof providerLimits === "object" &&
|
|
78
88
|
providerLimits.default) {
|
|
79
89
|
maxLimit = providerLimits.default;
|
|
@@ -4146,13 +4146,13 @@
|
|
|
4146
4146
|
{"objectID":"1d8625a67cba7bc640e454fe15f76d86e2be4fbe79e9496fc085e5a6df496086","title":"Future Enhancements","url":"/docs/features/pdf-support#future-enhancements","content":"Planned features for PDF support:\nOCR Integration: Extract text from scanned PDFs\nPage Selection: Analyze specific pages only\nPDF Generation: Create PDFs from AI responses\nForm Filling: Extract and populate PDF forms","hierarchy":{"lvl0":"Features","lvl1":"PDF File Support","lvl2":"Future Enhancements","lvl3":""}},
|
|
4147
4147
|
{"objectID":"20bb5119cb74199a04bebd17c621d8c6a0438c0833f12103b9f3914c5f026ceb","title":"Feedback and Support","url":"/docs/features/pdf-support#feedback-and-support","content":"Found a bug or have a feature request? Please:\nCheck existing issues on GitHub\nCreate a new issue with:\nProvider used\nPDF file details (size, pages)\nError message or unexpected behavior\nSample code (if possible)","hierarchy":{"lvl0":"Features","lvl1":"PDF File Support","lvl2":"Feedback and Support","lvl3":""}},
|
|
4148
4148
|
{"objectID":"7c47c75b9023d438078ad3ed696c167cb9b5beaa369fad844635f7f32cce74a5","title":"Version 9.2.0 (Current)","url":"/docs/features/pdf-support#version-920-current","content":"✅ Initial PDF support for Vertex AI, Anthropic, Bedrock, AI Studio\n✅ Auto-detection via --file flag\n✅ Multiple PDF processing\n✅ Size and page limit validation\n✅ Comprehensive error messages\n✅ CLI and SDK integration\n✅ Streaming support\n✅ Mixed multimodal inputs (PDF + CSV + images)\n\nNext: Multimodal Chat Guide | CSV Support","hierarchy":{"lvl0":"Features","lvl1":"PDF File Support","lvl2":"Version 9.2.0 (Current)","lvl3":""}},
|
|
4149
|
-
{"objectID":"2a46dad649fcc5c7b389d9db519211899183703302b4127f0a4a2285018e1362","title":"Per-Request Credentials","url":"/docs/features/per-request-credentials","content":"Per-Request Credentials\n\nStatus: Stable | Availability: SDK only\n\nOverview\n\nNeuroLink allows provider credentials to be supplied at two levels below the environment-variable default: on the NeuroLink constructor (instance level) and on individual generate() / stream() calls (per-call level). Credentials are resolved in the following order of precedence:\n\nThis enables multi-tenant architectures where different users or tenants supply their own provider API keys (bring-your-own-key, BYOK), without requiring separate NeuroLink instances per user or touching the process environment.\n\nTypical use cases:\nMulti-tenant SaaS — each API request carries the calling user's provider key; no shared key leakage between tenants\nBYOK products — end users paste their OpenAI / Anthropic keys in settings; you forward them to NeuroLink per call\nTesting and CI — inject credentials programmatically without setting environment variables\nProvider switching — override only the active provider's credentials while leaving others to fall through to env vars\n\nQuick Start\n\nInstance-Level vs Per-Call\n\nInstance-Level Credentials\n\nSet credentials in the NeuroLink constructor. These apply as the default for every generate() and stream() call made on that instance. Useful when serving a single tenant or when you have a known key for the duration of the instance lifecycle.\n\nPer-Call Credentials\n\nSet credentials directly on generate() or stream(). These override the instance-level credentials for that single call only. Only the providers you explicitly set are overridden — others continue falling through to instance credentials and then environment variables.\n\nPrecedence Rules\n\n| Level | Scope | Set on |\n| ----------- | --------------------- | ----------------------------------------------------------------------------------- |\n| Per-call | Single request only | generate({ credentials }), stream({ credentials }) or decide({ credentials }) |\n| Instance | All calls on instance | new NeuroLink({ credentials }) |\n| Environment | Process-wide fallback | OPENAI_API_KEY, ANTHROPIC_API_KEY, … |\n\nUnset providers at any level fall through to the next. You never need to repeat a credential at the per-call level if the instance default is correct.\n\nProvider Credential Reference\n\nAll fields are optional — omit any field you want to fall through to a lower-precedence level.\n\n| Provider | Key | Fields
|
|
4149
|
+
{"objectID":"2a46dad649fcc5c7b389d9db519211899183703302b4127f0a4a2285018e1362","title":"Per-Request Credentials","url":"/docs/features/per-request-credentials","content":"Per-Request Credentials\n\nStatus: Stable | Availability: SDK only\n\nOverview\n\nNeuroLink allows provider credentials to be supplied at two levels below the environment-variable default: on the NeuroLink constructor (instance level) and on individual generate() / stream() calls (per-call level). Credentials are resolved in the following order of precedence:\n\nThis enables multi-tenant architectures where different users or tenants supply their own provider API keys (bring-your-own-key, BYOK), without requiring separate NeuroLink instances per user or touching the process environment.\n\nTypical use cases:\nMulti-tenant SaaS — each API request carries the calling user's provider key; no shared key leakage between tenants\nBYOK products — end users paste their OpenAI / Anthropic keys in settings; you forward them to NeuroLink per call\nTesting and CI — inject credentials programmatically without setting environment variables\nProvider switching — override only the active provider's credentials while leaving others to fall through to env vars\n\nQuick Start\n\nInstance-Level vs Per-Call\n\nInstance-Level Credentials\n\nSet credentials in the NeuroLink constructor. These apply as the default for every generate() and stream() call made on that instance. Useful when serving a single tenant or when you have a known key for the duration of the instance lifecycle.\n\nPer-Call Credentials\n\nSet credentials directly on generate() or stream(). These override the instance-level credentials for that single call only. Only the providers you explicitly set are overridden — others continue falling through to instance credentials and then environment variables.\n\nPrecedence Rules\n\n| Level | Scope | Set on |\n| ----------- | --------------------- | ----------------------------------------------------------------------------------- |\n| Per-call | Single request only | generate({ credentials }), stream({ credentials }) or decide({ credentials }) |\n| Instance | All calls on instance | new NeuroLink({ credentials }) |\n| Environment | Process-wide fallback | OPENAI_API_KEY, ANTHROPIC_API_KEY, … |\n\nUnset providers at any level fall through to the next. You never need to repeat a credential at the per-call level if the instance default is correct.\n\nProvider Credential Reference\n\nAll fields are optional — omit any field you want to fall through to a lower-precedence level.\n\n| Provider | Key | Fields |\n| -------------------- | ------------------- | ------------------------------------------------------------------------------------------------------------- |\n| OpenAI | openai | apiKey, baseURL |\n| Anthropic | anthropic | apiKey, oauthToken, baseURL |\n| Google AI Studio | googleAiStudio | apiKey, baseURL |\n| Google Vertex AI | vertex | projectId, location, apiKey (Express Mode), serviceAccountKey, clientEmail, privateKey, baseURL |\n| Amazon Bedrock | bedrock | accessKeyId, secretAccessKey, sessionToken, region |\n| Amazon SageMaker | sagemaker | accessKeyId, secretAccessKey, sessionToken, region, endpoint |\n| Azure OpenAI | azure | apiKey, resourceName, deploymentName, apiVersion |\n| Mistral | mistral | apiKey |\n| Hugging Face | huggingFace | apiKey, baseURL |\n| OpenRouter | openrouter | apiKey, baseURL |\n| LiteLLM | litellm | apiKey, baseURL |\n| OpenAI-Compatible | openaiCompatible | apiKey, baseURL |\n| Cerebras | cerebras | apiKey, baseURL |\n| SambaNova | sambanova | apiKey, baseURL ","hierarchy":{"lvl0":"Features","lvl1":"Per-Request Credentials","lvl2":"","lvl3":""}},
|
|
4150
4150
|
{"objectID":"12291afcfaaf4af65b01b07e93a9eac08280ff7c61394f6051a86c1b152a7b4a","title":"Per-Request Credentials","url":"/docs/features/per-request-credentials#per-request-credentials","content":"Status: Stable | Availability: SDK only","hierarchy":{"lvl0":"Features","lvl1":"Per-Request Credentials","lvl2":"Per-Request Credentials","lvl3":""}},
|
|
4151
4151
|
{"objectID":"6c6756b0806344240b3c86d6b0063587db50f2c4ccf936a32e87d4377b77014c","title":"Overview","url":"/docs/features/per-request-credentials#overview","content":"NeuroLink allows provider credentials to be supplied at two levels below the environment-variable default: on the NeuroLink constructor (instance level) and on individual generate() / stream() calls (per-call level). Credentials are resolved in the following order of precedence:\n\nThis enables multi-tenant architectures where different users or tenants supply their own provider API keys (bring-your-own-key, BYOK), without requiring separate NeuroLink instances per user or touching the process environment.\n\nTypical use cases:\nMulti-tenant SaaS — each API request carries the calling user's provider key; no shared key leakage between tenants\nBYOK products — end users paste their OpenAI / Anthropic keys in settings; you forward them to NeuroLink per call\nTesting and CI — inject credentials programmatically without setting environment variables\nProvider switching — override only the active provider's credentials while leaving others to fall through to env vars","hierarchy":{"lvl0":"Features","lvl1":"Per-Request Credentials","lvl2":"Overview","lvl3":""}},
|
|
4152
4152
|
{"objectID":"d4e86918319aa78b4e4461dbf29a60ebe90935e74fc70617f59bf524ba3e1eae","title":"Instance-Level Credentials","url":"/docs/features/per-request-credentials#instance-level-credentials","content":"Set credentials in the NeuroLink constructor. These apply as the default for every generate() and stream() call made on that instance. Useful when serving a single tenant or when you have a known key for the duration of the instance lifecycle.","hierarchy":{"lvl0":"Features","lvl1":"Per-Request Credentials","lvl2":"Instance-Level Credentials","lvl3":""}},
|
|
4153
4153
|
{"objectID":"250b1dd11e018f5f252b27ce408e3dade21eff1cf26eed4aaf81126fad6ab691","title":"Per-Call Credentials","url":"/docs/features/per-request-credentials#per-call-credentials","content":"Set credentials directly on generate() or stream(). These override the instance-level credentials for that single call only. Only the providers you explicitly set are overridden — others continue falling through to instance credentials and then environment variables.","hierarchy":{"lvl0":"Features","lvl1":"Per-Request Credentials","lvl2":"Per-Call Credentials","lvl3":""}},
|
|
4154
4154
|
{"objectID":"4166cbaf6e6263ac98e24d7ede9950b44aade18e787b57e71138d2fc2deaaa07","title":"Precedence Rules","url":"/docs/features/per-request-credentials#precedence-rules","content":"| Level | Scope | Set on |\n| ----------- | --------------------- | ----------------------------------------------------------------------------------- |\n| Per-call | Single request only | generate({ credentials }), stream({ credentials }) or decide({ credentials }) |\n| Instance | All calls on instance | new NeuroLink({ credentials }) |\n| Environment | Process-wide fallback | OPENAI_API_KEY, ANTHROPIC_API_KEY, … |\n\nUnset providers at any level fall through to the next. You never need to repeat a credential at the per-call level if the instance default is correct.","hierarchy":{"lvl0":"Features","lvl1":"Per-Request Credentials","lvl2":"Precedence Rules","lvl3":""}},
|
|
4155
|
-
{"objectID":"b739fcf7819dd6f055ebe3bcdb161ff839067dc172235f9d0072f9cf79d7bcd3","title":"Provider Credential Reference","url":"/docs/features/per-request-credentials#provider-credential-reference","content":"All fields are optional — omit any field you want to fall through to a lower-precedence level.\n\n| Provider | Key | Fields
|
|
4155
|
+
{"objectID":"b739fcf7819dd6f055ebe3bcdb161ff839067dc172235f9d0072f9cf79d7bcd3","title":"Provider Credential Reference","url":"/docs/features/per-request-credentials#provider-credential-reference","content":"All fields are optional — omit any field you want to fall through to a lower-precedence level.\n\n| Provider | Key | Fields |\n| -------------------- | ------------------- | ------------------------------------------------------------------------------------------------------------- |\n| OpenAI | openai | apiKey, baseURL |\n| Anthropic | anthropic | apiKey, oauthToken, baseURL |\n| Google AI Studio | googleAiStudio | apiKey, baseURL |\n| Google Vertex AI | vertex | projectId, location, apiKey (Express Mode), serviceAccountKey, clientEmail, privateKey, baseURL |\n| Amazon Bedrock | bedrock | accessKeyId, secretAccessKey, sessionToken, region |\n| Amazon SageMaker | sagemaker | accessKeyId, secretAccessKey, sessionToken, region, endpoint |\n| Azure OpenAI | azure | apiKey, resourceName, deploymentName, apiVersion |\n| Mistral | mistral | apiKey |\n| Hugging Face | huggingFace | apiKey, baseURL |\n| OpenRouter | openrouter | apiKey, baseURL |\n| LiteLLM | litellm | apiKey, baseURL","hierarchy":{"lvl0":"Features","lvl1":"Per-Request Credentials","lvl2":"Provider Credential Reference","lvl3":""}},
|
|
4156
4156
|
{"objectID":"575e2e50c5fd00e53fce66deee556264f3df8962e2188ac446e6e7d4ad29b2ed","title":"OpenAI","url":"/docs/features/per-request-credentials#openai","content":"Custom base URL for OpenAI-compatible proxies:","hierarchy":{"lvl0":"Features","lvl1":"Per-Request Credentials","lvl2":"OpenAI","lvl3":""}},
|
|
4157
4157
|
{"objectID":"499e7c1d012d337ad54e06db35770d5b3471afb0f9e3f471564642e8ba7e5c6b","title":"Anthropic","url":"/docs/features/per-request-credentials#anthropic","content":"OAuth token (Anthropic Claude subscription):\n\nA gateway or proxy in front of Anthropic (baseURL wins over ANTHROPIC_BASE_URL, with or without a trailing /v1; a gateway that does its own auth accepts any apiKey):","hierarchy":{"lvl0":"Features","lvl1":"Per-Request Credentials","lvl2":"Anthropic","lvl3":""}},
|
|
4158
4158
|
{"objectID":"3f5ea871d2750f36fca227c33f109de53f5d0bc4c184ea956d0b8c3736babe29","title":"Vertex AI — Express Mode","url":"/docs/features/per-request-credentials#vertex-ai-express-mode","content":"Express Mode uses a simple API key instead of service-account credentials, making it suitable for per-request BYOK flows:\n\nFull service-account credentials (server-side only — keep private keys out of client code):","hierarchy":{"lvl0":"Features","lvl1":"Per-Request Credentials","lvl2":"Vertex AI — Express Mode","lvl3":""}},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@juspay/neurolink",
|
|
3
|
-
"version": "12.49.
|
|
3
|
+
"version": "12.49.6",
|
|
4
4
|
"packageManager": "pnpm@10.15.1",
|
|
5
5
|
"description": "The pipe layer of an AI nervous system: one interface connecting provider neurons to your application, across three inference types — generate, stream and decide. `decide` returns typed, calibrated judgements from a non-generative model (~400ms, ~$0.00002/call) for routing, tool selection and context budgeting. MCP-native (4 transports), voice TTS/STT/realtime, RAG, agents, memory, compaction, 9 observability exporters. OpenAI · Anthropic · Gemini · Bedrock · Azure · Ollama · TypeSafe Jev and more.",
|
|
6
6
|
"author": {
|