@juspay/neurolink 9.80.3 → 9.80.4
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 +6 -0
- package/dist/browser/neurolink.min.js +346 -346
- package/dist/context/stages/structuredSummarizer.js +15 -4
- package/dist/core/modules/GenerationHandler.js +28 -10
- package/dist/core/modules/structuredOutputPolicy.d.ts +19 -0
- package/dist/core/modules/structuredOutputPolicy.js +26 -0
- package/dist/lib/context/stages/structuredSummarizer.js +15 -4
- package/dist/lib/core/modules/GenerationHandler.js +28 -10
- package/dist/lib/core/modules/structuredOutputPolicy.d.ts +19 -0
- package/dist/lib/core/modules/structuredOutputPolicy.js +26 -0
- package/dist/lib/mcp/externalServerManager.js +21 -6
- package/dist/lib/mcp/mcpClientFactory.js +5 -1
- package/dist/lib/neurolink.js +58 -25
- package/dist/lib/providers/googleVertex.js +116 -19
- package/dist/lib/types/generate.d.ts +13 -0
- package/dist/lib/utils/conversationMemory.js +19 -8
- package/dist/lib/utils/logSanitize.d.ts +26 -0
- package/dist/lib/utils/logSanitize.js +56 -0
- package/dist/mcp/externalServerManager.js +21 -6
- package/dist/mcp/mcpClientFactory.js +5 -1
- package/dist/neurolink.js +58 -25
- package/dist/providers/googleVertex.js +116 -19
- package/dist/types/generate.d.ts +13 -0
- package/dist/utils/conversationMemory.js +19 -8
- package/dist/utils/logSanitize.d.ts +26 -0
- package/dist/utils/logSanitize.js +56 -0
- package/package.json +1 -1
|
@@ -7,6 +7,8 @@ import { ErrorCategory, ErrorSeverity, } from "../constants/enums.js";
|
|
|
7
7
|
import { BaseProvider } from "../core/baseProvider.js";
|
|
8
8
|
import { DEFAULT_GEMINI_STREAM_TIMEOUT_MS, DEFAULT_MAX_STEPS, DEFAULT_TOOL_MAX_RETRIES, GLOBAL_LOCATION_MODELS, IMAGE_GENERATION_MODELS, TOOL_STORAGE_TIMEOUT_MS, } from "../core/constants.js";
|
|
9
9
|
import { ModelConfigurationManager } from "../core/modelConfiguration.js";
|
|
10
|
+
import { isSchemaComplexityError } from "../core/modules/structuredOutputPolicy.js";
|
|
11
|
+
import { stringifyContentSafe } from "../utils/logSanitize.js";
|
|
10
12
|
import { createProxyFetch } from "../proxy/proxyFetch.js";
|
|
11
13
|
import { AuthenticationError, InvalidModelError, NetworkError, ProviderError, RateLimitError, } from "../types/index.js";
|
|
12
14
|
import { ERROR_CODES, NeuroLinkError } from "../utils/errorHandling.js";
|
|
@@ -2351,7 +2353,25 @@ export class GoogleVertexProvider extends BaseProvider {
|
|
|
2351
2353
|
wasAborted = true;
|
|
2352
2354
|
break;
|
|
2353
2355
|
}
|
|
2354
|
-
logger.error("[GoogleVertex] Native SDK generate error",
|
|
2356
|
+
logger.error("[GoogleVertex] Native SDK generate error", {
|
|
2357
|
+
error,
|
|
2358
|
+
model: modelName,
|
|
2359
|
+
location: effectiveLocation,
|
|
2360
|
+
status: error?.status,
|
|
2361
|
+
});
|
|
2362
|
+
// Best-effort request context for formatProviderError —
|
|
2363
|
+
// this.modelName can be stale when options.model overrides the
|
|
2364
|
+
// instance default.
|
|
2365
|
+
try {
|
|
2366
|
+
if (error && typeof error === "object") {
|
|
2367
|
+
const e = error;
|
|
2368
|
+
e.requestModel = modelName;
|
|
2369
|
+
e.requestRegion = effectiveLocation;
|
|
2370
|
+
}
|
|
2371
|
+
}
|
|
2372
|
+
catch {
|
|
2373
|
+
/* frozen/sealed error — context stays best-effort */
|
|
2374
|
+
}
|
|
2355
2375
|
throw this.handleProviderError(error);
|
|
2356
2376
|
}
|
|
2357
2377
|
}
|
|
@@ -2585,9 +2605,7 @@ export class GoogleVertexProvider extends BaseProvider {
|
|
|
2585
2605
|
if (msg.role === "user" || msg.role === "assistant") {
|
|
2586
2606
|
messages.push({
|
|
2587
2607
|
role: msg.role,
|
|
2588
|
-
content:
|
|
2589
|
-
? msg.content
|
|
2590
|
-
: JSON.stringify(msg.content),
|
|
2608
|
+
content: stringifyContentSafe(msg.content),
|
|
2591
2609
|
});
|
|
2592
2610
|
}
|
|
2593
2611
|
}
|
|
@@ -3190,7 +3208,7 @@ export class GoogleVertexProvider extends BaseProvider {
|
|
|
3190
3208
|
// so coerce defensively to keep the follow-up turn valid.
|
|
3191
3209
|
const resultContent = typeof result === "string"
|
|
3192
3210
|
? result
|
|
3193
|
-
: (
|
|
3211
|
+
: stringifyContentSafe(result ?? null);
|
|
3194
3212
|
toolResults.push({
|
|
3195
3213
|
type: "tool_result",
|
|
3196
3214
|
tool_use_id: toolUse.id,
|
|
@@ -3651,9 +3669,7 @@ export class GoogleVertexProvider extends BaseProvider {
|
|
|
3651
3669
|
if (msg.role === "user" || msg.role === "assistant") {
|
|
3652
3670
|
messages.push({
|
|
3653
3671
|
role: msg.role,
|
|
3654
|
-
content:
|
|
3655
|
-
? msg.content
|
|
3656
|
-
: JSON.stringify(msg.content),
|
|
3672
|
+
content: stringifyContentSafe(msg.content),
|
|
3657
3673
|
});
|
|
3658
3674
|
}
|
|
3659
3675
|
}
|
|
@@ -4032,7 +4048,7 @@ export class GoogleVertexProvider extends BaseProvider {
|
|
|
4032
4048
|
// so coerce defensively to keep the follow-up turn valid.
|
|
4033
4049
|
const resultContent = typeof result === "string"
|
|
4034
4050
|
? result
|
|
4035
|
-
: (
|
|
4051
|
+
: stringifyContentSafe(result ?? null);
|
|
4036
4052
|
toolResults.push({
|
|
4037
4053
|
type: "tool_result",
|
|
4038
4054
|
tool_use_id: toolUse.id,
|
|
@@ -4158,7 +4174,22 @@ export class GoogleVertexProvider extends BaseProvider {
|
|
|
4158
4174
|
wasAborted = true;
|
|
4159
4175
|
break;
|
|
4160
4176
|
}
|
|
4161
|
-
logger.error("[GoogleVertex] Native Anthropic SDK generate error",
|
|
4177
|
+
logger.error("[GoogleVertex] Native Anthropic SDK generate error", {
|
|
4178
|
+
error,
|
|
4179
|
+
model: modelName,
|
|
4180
|
+
step,
|
|
4181
|
+
status: error?.status,
|
|
4182
|
+
});
|
|
4183
|
+
// Best-effort request context for formatProviderError — see the
|
|
4184
|
+
// native Gemini catch for rationale.
|
|
4185
|
+
try {
|
|
4186
|
+
if (error && typeof error === "object") {
|
|
4187
|
+
error.requestModel = modelName;
|
|
4188
|
+
}
|
|
4189
|
+
}
|
|
4190
|
+
catch {
|
|
4191
|
+
/* frozen/sealed error — context stays best-effort */
|
|
4192
|
+
}
|
|
4162
4193
|
throw this.handleProviderError(error);
|
|
4163
4194
|
}
|
|
4164
4195
|
}
|
|
@@ -4622,8 +4653,49 @@ export class GoogleVertexProvider extends BaseProvider {
|
|
|
4622
4653
|
model: modelName,
|
|
4623
4654
|
totalToolCount: Object.keys(mergedOptions.tools).length,
|
|
4624
4655
|
});
|
|
4625
|
-
|
|
4626
|
-
|
|
4656
|
+
try {
|
|
4657
|
+
nativeResult =
|
|
4658
|
+
await this.executeNativeGemini3Generate(mergedOptions);
|
|
4659
|
+
}
|
|
4660
|
+
catch (nativeError) {
|
|
4661
|
+
// Vertex rejects over-constrained responseSchemas with a
|
|
4662
|
+
// deterministic 400 ("too many states" — constrained-decoding
|
|
4663
|
+
// state explosion). Re-sending the same schema can never
|
|
4664
|
+
// succeed, so retry ONCE with the schema dropped but JSON
|
|
4665
|
+
// mode kept: output.format "json" still sets
|
|
4666
|
+
// responseMimeType application/json on the no-tools path,
|
|
4667
|
+
// so the model is forced to emit JSON — just without the
|
|
4668
|
+
// offending schema constraints. The NeuroLink layer then
|
|
4669
|
+
// coerces the JSON text into the caller's original schema
|
|
4670
|
+
// (generate({schema}) guarantee holds).
|
|
4671
|
+
const requestedStructured = mergedOptions.schema !== undefined ||
|
|
4672
|
+
mergedOptions.output?.format === "json";
|
|
4673
|
+
// Tools present → the executor skips responseMimeType, so a
|
|
4674
|
+
// schema-less retry would NOT actually run in JSON mode and
|
|
4675
|
+
// the structured-output contract would silently degrade to
|
|
4676
|
+
// prose. Only the no-tools case retries faithfully; with
|
|
4677
|
+
// tools, surface the 400 to the caller instead.
|
|
4678
|
+
const hasTools = !mergedOptions.disableTools &&
|
|
4679
|
+
Object.keys(mergedOptions.tools ?? {}).length > 0;
|
|
4680
|
+
if (requestedStructured &&
|
|
4681
|
+
!hasTools &&
|
|
4682
|
+
isSchemaComplexityError(nativeError)) {
|
|
4683
|
+
logger.warn("[GoogleVertex] responseSchema too complex for constrained decoding — retrying native generate in schema-less JSON mode", {
|
|
4684
|
+
model: modelName,
|
|
4685
|
+
error: nativeError instanceof Error
|
|
4686
|
+
? nativeError.message
|
|
4687
|
+
: String(nativeError),
|
|
4688
|
+
});
|
|
4689
|
+
nativeResult = await this.executeNativeGemini3Generate({
|
|
4690
|
+
...mergedOptions,
|
|
4691
|
+
schema: undefined,
|
|
4692
|
+
output: { format: "json" },
|
|
4693
|
+
});
|
|
4694
|
+
}
|
|
4695
|
+
else {
|
|
4696
|
+
throw nativeError;
|
|
4697
|
+
}
|
|
4698
|
+
}
|
|
4627
4699
|
}
|
|
4628
4700
|
executionSpan.setAttribute(LANGFUSE_ATTR.OBSERVATION_OUTPUT, spanJsonAttribute(nativeResult?.content ?? ""));
|
|
4629
4701
|
return nativeResult;
|
|
@@ -4960,17 +5032,42 @@ export class GoogleVertexProvider extends BaseProvider {
|
|
|
4960
5032
|
`3. Ensure your project has access to the model ` +
|
|
4961
5033
|
`4. For Claude models, enable Anthropic integration in Google Cloud Console`, this.providerName);
|
|
4962
5034
|
}
|
|
4963
|
-
// Rate limit
|
|
5035
|
+
// Rate limit / quota / capacity errors. Anthropic-on-Vertex capacity
|
|
5036
|
+
// exhaustion surfaces as overloaded_error (HTTP 529) — same operational
|
|
5037
|
+
// meaning as a 429, so classify it here instead of the generic 5xx branch.
|
|
4964
5038
|
if (message.includes("QUOTA_EXCEEDED") ||
|
|
4965
5039
|
message.includes("RATE_LIMIT_EXCEEDED") ||
|
|
4966
5040
|
message.includes("rate limit") ||
|
|
4967
5041
|
message.includes("429") ||
|
|
4968
|
-
statusCode === 429
|
|
4969
|
-
|
|
4970
|
-
|
|
4971
|
-
|
|
4972
|
-
|
|
4973
|
-
|
|
5042
|
+
statusCode === 429 ||
|
|
5043
|
+
statusCode === 529 ||
|
|
5044
|
+
/overloaded/i.test(message)) {
|
|
5045
|
+
// Surface retry guidance when the SDK error carries it. @google/genai
|
|
5046
|
+
// ApiError nests RetryInfo inside the JSON error body's details array,
|
|
5047
|
+
// so fall back to scraping retryDelay out of the raw message.
|
|
5048
|
+
const retryDelay = typeof errorRecord?.retryDelay === "string"
|
|
5049
|
+
? errorRecord.retryDelay
|
|
5050
|
+
: (/["']?retryDelay["']?\s*[:=]\s*["']?(\d+(?:\.\d+)?s)/.exec(message)?.[1] ?? undefined);
|
|
5051
|
+
// Prefer the per-request context the native catches attach to the
|
|
5052
|
+
// error (this.modelName can be stale when options.model overrides the
|
|
5053
|
+
// instance default). Gemini models are force-routed to the "global"
|
|
5054
|
+
// endpoint regardless of configured location — report the region the
|
|
5055
|
+
// request actually hit.
|
|
5056
|
+
const requestModel = typeof errorRecord?.requestModel === "string"
|
|
5057
|
+
? errorRecord.requestModel
|
|
5058
|
+
: this.modelName;
|
|
5059
|
+
const effectiveRegion = typeof errorRecord?.requestRegion === "string"
|
|
5060
|
+
? errorRecord.requestRegion
|
|
5061
|
+
: resolveVertexRegionForModel(requestModel, this.location);
|
|
5062
|
+
return new RateLimitError(`Google Vertex AI rate limit / shared-capacity exhausted (429 RESOURCE_EXHAUSTED / overloaded) ` +
|
|
5063
|
+
`for model '${requestModel}' in region '${effectiveRegion}'.` +
|
|
5064
|
+
(retryDelay
|
|
5065
|
+
? ` Upstream suggests retrying after ${retryDelay}.`
|
|
5066
|
+
: "") +
|
|
5067
|
+
` Solutions: 1. Retry with backoff ` +
|
|
5068
|
+
`2. Check your Vertex AI quotas in Google Cloud Console (shared-capacity 429s can occur below quota) ` +
|
|
5069
|
+
`3. Try a different region or model ` +
|
|
5070
|
+
`4. Request provisioned throughput for sustained load`, this.providerName);
|
|
4974
5071
|
}
|
|
4975
5072
|
// Network connectivity errors
|
|
4976
5073
|
if (message.includes("ECONNRESET") ||
|
package/dist/types/generate.d.ts
CHANGED
|
@@ -296,6 +296,19 @@ export type GenerateOptions = {
|
|
|
296
296
|
* ```
|
|
297
297
|
*/
|
|
298
298
|
enabledToolNames?: string[];
|
|
299
|
+
/**
|
|
300
|
+
* Request timeout (e.g. 30000, '30s', '2m').
|
|
301
|
+
*
|
|
302
|
+
* PER-STEP semantics in agentic loops: on providers that run a native
|
|
303
|
+
* multi-step tool loop (Vertex Gemini / Vertex Claude), this bounds EACH
|
|
304
|
+
* model call in the loop, not the whole turn — a tool-heavy turn may run
|
|
305
|
+
* far longer than this value in total. Size it for the slowest single
|
|
306
|
+
* step (default 300s), and use `abortSignal` for a total-turn deadline.
|
|
307
|
+
*
|
|
308
|
+
* When set explicitly, a step timeout is surfaced immediately instead of
|
|
309
|
+
* burning internal retries/fallbacks that would re-run the same
|
|
310
|
+
* provider+model with the same doomed budget.
|
|
311
|
+
*/
|
|
299
312
|
timeout?: number | string;
|
|
300
313
|
/** AbortSignal for external cancellation of the AI call */
|
|
301
314
|
abortSignal?: AbortSignal;
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
import { SpanKind, SpanStatusCode } from "@opentelemetry/api";
|
|
6
6
|
import { tracers } from "../telemetry/tracers.js";
|
|
7
7
|
import { withTimeout } from "./errorHandling.js";
|
|
8
|
+
import { safeDebugSerialize, sanitizeRecord } from "./logSanitize.js";
|
|
8
9
|
import { DEFAULT_FALLBACK_THRESHOLD, getConversationMemoryDefaults, MEMORY_THRESHOLD_PERCENTAGE, } from "../config/conversationMemory.js";
|
|
9
10
|
import { getAvailableInputTokens } from "../constants/contextWindows.js";
|
|
10
11
|
import { buildSummarizationPrompt } from "../context/prompts/summarizationPrompt.js";
|
|
@@ -106,20 +107,30 @@ export function applyConversationMemoryDefaults(userConfig) {
|
|
|
106
107
|
* Get conversation history as message array, summarizing if needed.
|
|
107
108
|
*/
|
|
108
109
|
export async function getConversationMessages(conversationMemory, options) {
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
110
|
+
// Logger Guard: options carries the full conversation history + tool
|
|
111
|
+
// outputs; eager JSON.stringify of it can throw RangeError: Invalid string
|
|
112
|
+
// length and abort the turn. Serialize lazily, bounded, never-throwing,
|
|
113
|
+
// and redacted (sanitizeRecord strips credential/PII keys).
|
|
114
|
+
if (logger.shouldLog("debug")) {
|
|
115
|
+
logger.debug("[conversationMemoryUtils] getConversationMessages called", {
|
|
116
|
+
hasMemory: !!conversationMemory,
|
|
117
|
+
memoryType: conversationMemory?.constructor?.name || "NONE",
|
|
118
|
+
hasContext: !!options.context,
|
|
119
|
+
enableSummarization: options.enableSummarization ?? false,
|
|
120
|
+
options: safeDebugSerialize(sanitizeRecord(options)),
|
|
121
|
+
});
|
|
122
|
+
}
|
|
116
123
|
if (!conversationMemory || !options.context) {
|
|
117
124
|
logger.warn("[conversationMemoryUtils] No memory or context, returning empty messages", {
|
|
118
125
|
hasMemory: !!conversationMemory,
|
|
119
126
|
memoryType: conversationMemory?.constructor?.name || "NONE",
|
|
120
127
|
hasContext: !!options.context,
|
|
121
128
|
enableSummarization: options.enableSummarization ?? false,
|
|
122
|
-
options
|
|
129
|
+
// The options dump is debug-grade detail — don't pay for (or leak)
|
|
130
|
+
// the serialization on every memory-disabled call at warn level.
|
|
131
|
+
...(logger.shouldLog("debug")
|
|
132
|
+
? { options: safeDebugSerialize(sanitizeRecord(options)) }
|
|
133
|
+
: {}),
|
|
123
134
|
});
|
|
124
135
|
return [];
|
|
125
136
|
}
|
|
@@ -26,6 +26,32 @@
|
|
|
26
26
|
* @param maxLen - Maximum number of characters to keep (default 500).
|
|
27
27
|
*/
|
|
28
28
|
export declare function sanitizeForLog(text: string, maxLen?: number): string;
|
|
29
|
+
/**
|
|
30
|
+
* Stringify non-string message/tool content without ever throwing.
|
|
31
|
+
* JSON.stringify on a giant multimodal/tool-result payload can exceed V8's
|
|
32
|
+
* maximum string length and throw `RangeError: Invalid string length` — a
|
|
33
|
+
* generation turn must degrade to a placeholder, not abort, when that
|
|
34
|
+
* happens. Shared by the SDK core and providers (single source of truth).
|
|
35
|
+
*/
|
|
36
|
+
export declare function stringifyContentSafe(content: unknown): string;
|
|
37
|
+
/**
|
|
38
|
+
* Serialize an arbitrary value for a debug log without ever throwing or
|
|
39
|
+
* producing an unbounded string.
|
|
40
|
+
*
|
|
41
|
+
* `JSON.stringify` on a full options object (conversation history + tool
|
|
42
|
+
* outputs) can exceed V8's maximum string length and throw
|
|
43
|
+
* `RangeError: Invalid string length`, which — when evaluated eagerly inside
|
|
44
|
+
* a logger call — aborts the surrounding generation turn (observed in
|
|
45
|
+
* production). This helper caps the output and converts any stringify
|
|
46
|
+
* failure (RangeError, circular structure, BigInt, …) into a placeholder.
|
|
47
|
+
*
|
|
48
|
+
* Callers MUST still gate on `logger.shouldLog("debug")` per the Logger
|
|
49
|
+
* Guard rule — this helper makes serialization safe, not free.
|
|
50
|
+
*
|
|
51
|
+
* @param value - Arbitrary value to serialize.
|
|
52
|
+
* @param maxLen - Maximum number of characters to keep (default 10 000).
|
|
53
|
+
*/
|
|
54
|
+
export declare function safeDebugSerialize(value: unknown, maxLen?: number): string;
|
|
29
55
|
/**
|
|
30
56
|
* Strip embedded `user:pass@` credentials from a URL's authority component
|
|
31
57
|
* before logging it or surfacing it in a user-facing error.
|
|
@@ -74,6 +74,13 @@ const SENSITIVE_OBJECT_KEYS = [
|
|
|
74
74
|
"oauth",
|
|
75
75
|
"oauthToken",
|
|
76
76
|
"credentials",
|
|
77
|
+
"authContext",
|
|
78
|
+
"authToken",
|
|
79
|
+
"sessionToken",
|
|
80
|
+
"serviceAccountKey",
|
|
81
|
+
"secretAccessKey",
|
|
82
|
+
// PII, not a secret — but it has no business in debug log dumps.
|
|
83
|
+
"userEmail",
|
|
77
84
|
];
|
|
78
85
|
/**
|
|
79
86
|
* Truncate `text` to `maxLen` chars then replace embedded secrets with `***`.
|
|
@@ -91,6 +98,55 @@ export function sanitizeForLog(text, maxLen = 500) {
|
|
|
91
98
|
}
|
|
92
99
|
return text.slice(0, maxLen).replace(SECRET_PATTERN, "***");
|
|
93
100
|
}
|
|
101
|
+
/**
|
|
102
|
+
* Stringify non-string message/tool content without ever throwing.
|
|
103
|
+
* JSON.stringify on a giant multimodal/tool-result payload can exceed V8's
|
|
104
|
+
* maximum string length and throw `RangeError: Invalid string length` — a
|
|
105
|
+
* generation turn must degrade to a placeholder, not abort, when that
|
|
106
|
+
* happens. Shared by the SDK core and providers (single source of truth).
|
|
107
|
+
*/
|
|
108
|
+
export function stringifyContentSafe(content) {
|
|
109
|
+
if (typeof content === "string") {
|
|
110
|
+
return content;
|
|
111
|
+
}
|
|
112
|
+
try {
|
|
113
|
+
return JSON.stringify(content) ?? String(content);
|
|
114
|
+
}
|
|
115
|
+
catch {
|
|
116
|
+
return "[content too large to serialize]";
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Serialize an arbitrary value for a debug log without ever throwing or
|
|
121
|
+
* producing an unbounded string.
|
|
122
|
+
*
|
|
123
|
+
* `JSON.stringify` on a full options object (conversation history + tool
|
|
124
|
+
* outputs) can exceed V8's maximum string length and throw
|
|
125
|
+
* `RangeError: Invalid string length`, which — when evaluated eagerly inside
|
|
126
|
+
* a logger call — aborts the surrounding generation turn (observed in
|
|
127
|
+
* production). This helper caps the output and converts any stringify
|
|
128
|
+
* failure (RangeError, circular structure, BigInt, …) into a placeholder.
|
|
129
|
+
*
|
|
130
|
+
* Callers MUST still gate on `logger.shouldLog("debug")` per the Logger
|
|
131
|
+
* Guard rule — this helper makes serialization safe, not free.
|
|
132
|
+
*
|
|
133
|
+
* @param value - Arbitrary value to serialize.
|
|
134
|
+
* @param maxLen - Maximum number of characters to keep (default 10 000).
|
|
135
|
+
*/
|
|
136
|
+
export function safeDebugSerialize(value, maxLen = 10_000) {
|
|
137
|
+
try {
|
|
138
|
+
const json = JSON.stringify(value);
|
|
139
|
+
if (json === undefined) {
|
|
140
|
+
return String(value);
|
|
141
|
+
}
|
|
142
|
+
return json.length > maxLen
|
|
143
|
+
? `${json.slice(0, maxLen)}…[truncated ${json.length - maxLen} chars]`
|
|
144
|
+
: json;
|
|
145
|
+
}
|
|
146
|
+
catch (error) {
|
|
147
|
+
return `[unserializable: ${error instanceof Error ? error.message : String(error)}]`;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
94
150
|
/**
|
|
95
151
|
* Strip embedded `user:pass@` credentials from a URL's authority component
|
|
96
152
|
* before logging it or surfacing it in a user-facing error.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@juspay/neurolink",
|
|
3
|
-
"version": "9.80.
|
|
3
|
+
"version": "9.80.4",
|
|
4
4
|
"packageManager": "pnpm@10.15.1",
|
|
5
5
|
"description": "Universal AI Development Platform with working MCP integration, multi-provider support, voice (TTS/STT/realtime), and professional CLI. 58+ external MCP servers discoverable, multimodal file processing, RAG pipelines. Build, test, and deploy AI applications with 21+ providers: OpenAI, Anthropic, Google AI Studio, Google Vertex, AWS Bedrock, Azure OpenAI, Mistral, LiteLLM, SageMaker, Hugging Face, Ollama, OpenAI-compatible, OpenRouter, DeepSeek, NVIDIA NIM, LM Studio, llama.cpp, plus voice (OpenAI TTS, ElevenLabs, Deepgram, Azure Speech).",
|
|
6
6
|
"author": {
|