@juspay/neurolink 12.35.4 → 12.35.5

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.
@@ -322,7 +322,7 @@ async function showWelcomeScreen() {
322
322
  chalk.blue(" │"));
323
323
  logger.always(chalk.blue("│ │"));
324
324
  logger.always(chalk.blue("│ ") +
325
- chalk.gray("Universal interface for 8+ AI providers") +
325
+ chalk.gray("Unified interface for many AI providers") +
326
326
  chalk.blue(" │"));
327
327
  logger.always(chalk.blue("│ ") +
328
328
  chalk.gray("• Generate text, code, and creative content") +
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * NeuroLink AI Toolkit
3
3
  *
4
- * A unified AI provider interface with support for 14+ providers,
4
+ * A unified AI provider interface with support for many AI providers,
5
5
  * automatic fallback, streaming, MCP tool integration, HITL security,
6
6
  * Redis persistence, and enterprise-grade middleware.
7
7
  *
@@ -98,7 +98,7 @@ export declare const VERSION = "1.0.0";
98
98
  * Quick start factory function for creating AI provider instances.
99
99
  *
100
100
  * Creates a configured AI provider instance ready for immediate use.
101
- * Supports 14+ providers: OpenAI, Anthropic, Google AI Studio,
101
+ * Supports providers including OpenAI, Anthropic, Google AI Studio,
102
102
  * Google Vertex, AWS Bedrock, AWS SageMaker, Azure OpenAI, Hugging Face,
103
103
  * LiteLLM, Mistral, Ollama, OpenAI Compatible, OpenRouter, and more.
104
104
  *
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * NeuroLink AI Toolkit
3
3
  *
4
- * A unified AI provider interface with support for 14+ providers,
4
+ * A unified AI provider interface with support for many AI providers,
5
5
  * automatic fallback, streaming, MCP tool integration, HITL security,
6
6
  * Redis persistence, and enterprise-grade middleware.
7
7
  *
@@ -220,7 +220,7 @@ export const VERSION = "1.0.0";
220
220
  * Quick start factory function for creating AI provider instances.
221
221
  *
222
222
  * Creates a configured AI provider instance ready for immediate use.
223
- * Supports 14+ providers: OpenAI, Anthropic, Google AI Studio,
223
+ * Supports providers including OpenAI, Anthropic, Google AI Studio,
224
224
  * Google Vertex, AWS Bedrock, AWS SageMaker, Azure OpenAI, Hugging Face,
225
225
  * LiteLLM, Mistral, Ollama, OpenAI Compatible, OpenRouter, and more.
226
226
  *
@@ -692,7 +692,7 @@ export declare class NeuroLink {
692
692
  * Generate AI response with comprehensive feature support.
693
693
  *
694
694
  * Primary method for AI generation with support for all NeuroLink features:
695
- * - Multi-provider support (14+ providers)
695
+ * - Multi-provider support
696
696
  * - MCP tool integration
697
697
  * - Structured JSON output with Zod schemas
698
698
  * - Conversation memory (Redis or in-memory)
package/dist/neurolink.js CHANGED
@@ -194,7 +194,7 @@ const isNonRetryableForPool = sharedIsNonRetryableForPool;
194
194
  /**
195
195
  * NeuroLink - Universal AI Development Platform
196
196
  *
197
- * Main SDK class providing unified access to 14+ AI providers with enterprise features:
197
+ * Main SDK class providing unified access to many AI providers with enterprise features:
198
198
  * - Multi-provider support (OpenAI, Anthropic, Google AI Studio, Google Vertex, AWS Bedrock, etc.)
199
199
  * - MCP (Model Context Protocol) tool integration — connect any MCP-compliant server
200
200
  * - Human-in-the-Loop (HITL) security workflows for regulated industries
@@ -3231,7 +3231,7 @@ Current user's request: ${currentInput}`;
3231
3231
  * Generate AI response with comprehensive feature support.
3232
3232
  *
3233
3233
  * Primary method for AI generation with support for all NeuroLink features:
3234
- * - Multi-provider support (14+ providers)
3234
+ * - Multi-provider support
3235
3235
  * - MCP tool integration
3236
3236
  * - Structured JSON output with Zod schemas
3237
3237
  * - Conversation memory (Redis or in-memory)
@@ -1,6 +1,6 @@
1
1
  import type { OpenAICompatCatalogEntry } from "../types/index.js";
2
2
  /**
3
- * Config-driven catalog of the 10 OpenAI-compatible providers whose only
3
+ * Config-driven catalog of the OpenAI-compatible providers whose only
4
4
  * differences from each other are expressible as named, closed catalog
5
5
  * quirks (messageContentFormat, timeoutErrorClass, responseFormatDowngrade)
6
6
  * rather than real code. Each entry fully replaces what used to be a
@@ -11,7 +11,7 @@ import type { OpenAICompatCatalogEntry } from "../types/index.js";
11
11
  *
12
12
  * The entries themselves are derived from the JSON catalog
13
13
  * (src/lib/providers/catalog/<id>.json) via buildCatalogEntries() — that
14
- * JSON is now the single source of truth for these 10 providers' identity,
14
+ * JSON is now the single source of truth for these providers' identity,
15
15
  * models, error rules and wire config. See
16
16
  * src/lib/providers/catalog/loader.ts for the derivation logic and
17
17
  * docs/superpowers/plans/2026-08-28-provider-json-catalog-spec.md for the
@@ -1,6 +1,6 @@
1
1
  import { buildCatalogEntries } from "./catalog/loader.js";
2
2
  /**
3
- * Config-driven catalog of the 10 OpenAI-compatible providers whose only
3
+ * Config-driven catalog of the OpenAI-compatible providers whose only
4
4
  * differences from each other are expressible as named, closed catalog
5
5
  * quirks (messageContentFormat, timeoutErrorClass, responseFormatDowngrade)
6
6
  * rather than real code. Each entry fully replaces what used to be a
@@ -11,7 +11,7 @@ import { buildCatalogEntries } from "./catalog/loader.js";
11
11
  *
12
12
  * The entries themselves are derived from the JSON catalog
13
13
  * (src/lib/providers/catalog/<id>.json) via buildCatalogEntries() — that
14
- * JSON is now the single source of truth for these 10 providers' identity,
14
+ * JSON is now the single source of truth for these providers' identity,
15
15
  * models, error rules and wire config. See
16
16
  * src/lib/providers/catalog/loader.ts for the derivation logic and
17
17
  * docs/superpowers/plans/2026-08-28-provider-json-catalog-spec.md for the
@@ -1,4 +1,4 @@
1
- import { LoggerProvider } from "@opentelemetry/sdk-logs";
1
+ import type { LoggerProvider as LoggerProviderType } from "@opentelemetry/sdk-logs";
2
2
  import type { ProxyBodyChunkEmitter, ProxyBodyDeliveryResult } from "../types/index.js";
3
3
  /** Explicit opt-in; configuration never silently falls back to file logging. */
4
4
  export declare function isProxyOtelOnly(): boolean;
@@ -9,7 +9,7 @@ export declare function isProxyOtelOnly(): boolean;
9
9
  */
10
10
  export declare function publishProxyOtelBody(captureId: string, body: string, emit: ProxyBodyChunkEmitter): Promise<ProxyBodyDeliveryResult>;
11
11
  /** Initialize a log-only provider in every proxy process, including the supervisor. */
12
- export declare function initializeProxyOtelLogs(role?: string): LoggerProvider | undefined;
12
+ export declare function initializeProxyOtelLogs(role?: string): LoggerProviderType | undefined;
13
13
  /** Structured evidence without final-request dashboard fields on auxiliary events. */
14
14
  export declare function emitProxyOtelEvent(kind: string, record: Record<string, unknown>): void;
15
15
  /** Capture application console diagnostics only inside proxy service processes. */
@@ -1,15 +1,52 @@
1
1
  /* eslint-disable no-console -- This proxy-only sink replaces console methods with OTLP emission. */
2
2
  import { inspect } from "node:util";
3
3
  import { randomUUID } from "node:crypto";
4
+ import { createRequire } from "node:module";
4
5
  import { getProxyRequestTraceContext, proxyLogContext, } from "./proxyTraceContext.js";
5
6
  import { setImmediate as yieldToRequests } from "node:timers/promises";
6
- import { SeverityNumber } from "@opentelemetry/api-logs";
7
- import { ExportResultCode } from "@opentelemetry/core";
8
7
  import { createProxyOtlpLogTransport, getProxyOtlpRetryAfter, } from "./otlpLogTransport.js";
9
- import { resourceFromAttributes } from "@opentelemetry/resources";
10
- import { BatchLogRecordProcessor, LoggerProvider, } from "@opentelemetry/sdk-logs";
11
8
  import { sanitizeForLog } from "../utils/logSanitize.js";
12
9
  import { splitUtf8StringByBytes } from "./bodyCaptureProcessing.js";
10
+ /**
11
+ * @opentelemetry/sdk-logs, resources, api-logs and core are loaded
12
+ * synchronously via require() on first actual use, not via a top-level
13
+ * import — so merely requiring this module (reachable eagerly from
14
+ * dist/server/index.js via codexProxyRoutes.ts/claudeProxyRoutes.ts) no
15
+ * longer pulls in four heavy OTel packages for the overwhelming majority
16
+ * of callers who never set NEUROLINK_PROXY_LOG_SINK=otel. All four ship
17
+ * plain CommonJS builds, so require() works on any Node >=22.0.0 — no
18
+ * experimental flag, unlike require(esm) of a local ES module (which only
19
+ * works unflagged from Node 22.12). otlpLogTransport.js stays a normal
20
+ * static import for exactly that reason; it lazily requires its own two
21
+ * npm dependencies (@opentelemetry/core, otlp-transformer) internally.
22
+ * Everything here stays fully synchronous — construction is still one
23
+ * synchronous call, exactly as before — only the *import* is deferred, not
24
+ * the initialization semantics. Do not convert this to a dynamic
25
+ * `import()`: that would make initializeProxyOtelLogs() asynchronous and
26
+ * break every caller (both production code and the tests below) that
27
+ * relies on the queues/provider existing synchronously the moment it
28
+ * returns.
29
+ */
30
+ const require = createRequire(import.meta.url);
31
+ let SeverityNumber;
32
+ let ExportResultCode;
33
+ let resourceFromAttributes;
34
+ let BatchLogRecordProcessor;
35
+ let LoggerProvider;
36
+ let otelDepsLoaded = false;
37
+ function loadOtelDeps() {
38
+ if (otelDepsLoaded) {
39
+ return;
40
+ }
41
+ ({ SeverityNumber } = require("@opentelemetry/api-logs"));
42
+ ({ ExportResultCode } = require("@opentelemetry/core"));
43
+ ({ resourceFromAttributes } = require("@opentelemetry/resources"));
44
+ ({
45
+ BatchLogRecordProcessor,
46
+ LoggerProvider,
47
+ } = require("@opentelemetry/sdk-logs"));
48
+ otelDepsLoaded = true;
49
+ }
13
50
  let provider;
14
51
  let restoreConsole;
15
52
  const queues = [];
@@ -569,6 +606,9 @@ export function initializeProxyOtelLogs(role = "worker") {
569
606
  throw new Error("Proxy OTLP logs require HTTPS for non-loopback collectors");
570
607
  }
571
608
  }
609
+ // Validation above must run — and be able to throw — before this: a
610
+ // misconfigured endpoint must fail without ever loading the OTel SDK.
611
+ loadOtelDeps();
572
612
  const metadata = createTrackedProcessor(endpoint, 2048, "metadata", 8 * 1024 * 1024);
573
613
  const bodies = createTrackedProcessor(bodyEndpoint, 256, "bodies", 40 * 1024 * 1024);
574
614
  const diagnostics = createTrackedProcessor(endpoint, 512, "diagnostics", 2 * 1024 * 1024);
@@ -10,8 +10,30 @@ import { Agent as HttpsAgent, request as httpsRequest } from "node:https";
10
10
  import { setTimeout as delay } from "node:timers/promises";
11
11
  import { promisify } from "node:util";
12
12
  import { gzip } from "node:zlib";
13
- import { ExportResultCode, parseKeyPairsIntoRecord } from "@opentelemetry/core";
14
- import { JsonLogsSerializer } from "@opentelemetry/otlp-transformer";
13
+ import { createRequire } from "node:module";
14
+ /**
15
+ * @opentelemetry/core and @opentelemetry/otlp-transformer are loaded via
16
+ * require() on first actual use (this file itself stays a normal static
17
+ * import, since it is genuinely CommonJS-safe to require() these two —
18
+ * unlike a local ESM file, which would need Node's newer require(esm)
19
+ * support and break on Node <22.12). Both packages ship plain CJS builds.
20
+ */
21
+ const require = createRequire(import.meta.url);
22
+ let ExportResultCode;
23
+ let parseKeyPairsIntoRecord;
24
+ let JsonLogsSerializer;
25
+ let transportDepsLoaded = false;
26
+ function loadTransportDeps() {
27
+ if (transportDepsLoaded) {
28
+ return;
29
+ }
30
+ ({
31
+ ExportResultCode,
32
+ parseKeyPairsIntoRecord,
33
+ } = require("@opentelemetry/core"));
34
+ ({ JsonLogsSerializer } = require("@opentelemetry/otlp-transformer"));
35
+ transportDepsLoaded = true;
36
+ }
15
37
  const gzipAsync = promisify(gzip);
16
38
  const MAX_RESPONSE_BYTES = 64 * 1024;
17
39
  const MAX_EXPORT_ATTEMPTS = 5;
@@ -151,6 +173,7 @@ function validateAcknowledgement(bytes) {
151
173
  }
152
174
  /** Both proxy queues use this transport; success is not backend persistence. */
153
175
  export function createProxyOtlpLogTransport(endpoint, timeoutMillis) {
176
+ loadTransportDeps();
154
177
  let url;
155
178
  try {
156
179
  url = new URL(endpoint);
@@ -20,7 +20,24 @@ import { captureProxyBody, getBodyCaptureWorkerSnapshot, PROXY_BODY_CAPTURE_DEAD
20
20
  import { prepareProxyBodyForLogging as prepareRedactedBody, redactProxyHeadersForLogging as redactHeaders, splitUtf8StringByBytes, } from "./bodyCaptureProcessing.js";
21
21
  import { isBorrowedRequest } from "./shareContext.js";
22
22
  import { OtelBridge } from "../observability/otelBridge.js";
23
- import { SeverityNumber } from "@opentelemetry/api-logs";
23
+ import { createRequire } from "node:module";
24
+ /**
25
+ * Loaded via require() on first actual use rather than a top-level import,
26
+ * so requiring this module (reachable eagerly from dist/server/index.js)
27
+ * doesn't pull in @opentelemetry/api-logs for callers who never emit an
28
+ * OTLP log record. Both use sites below only run once resolveLoggerProvider()
29
+ * has already resolved a real provider, so OTel logging is already active.
30
+ */
31
+ const otelRequire = createRequire(import.meta.url);
32
+ let SeverityNumber;
33
+ let severityNumberLoaded = false;
34
+ function loadSeverityNumber() {
35
+ if (severityNumberLoaded) {
36
+ return;
37
+ }
38
+ ({ SeverityNumber } = otelRequire("@opentelemetry/api-logs"));
39
+ severityNumberLoaded = true;
40
+ }
24
41
  import { configureProxyLifecycleLogger } from "./proxyLifecycle.js";
25
42
  import { notifyProxyFinalLog, notifyProxyAttemptLog, getProxyRequestAccounting, } from "./proxyActivity.js";
26
43
  import { withTimeout } from "../utils/async/withTimeout.js";
@@ -388,6 +405,7 @@ function emitOtlpLogRecord(entry) {
388
405
  if (!provider) {
389
406
  return;
390
407
  }
408
+ loadSeverityNumber();
391
409
  const otelLogger = provider.getLogger("neurolink-proxy", "1.0.0");
392
410
  // A streaming response can fail after sending HTTP 200. Indexed fields
393
411
  // and severity must agree with the final semantic outcome in the body.
@@ -568,6 +586,7 @@ function emitOtlpBodyLogRecord(entry, stored) {
568
586
  if (!provider || stored.redactedBody === undefined) {
569
587
  return undefined;
570
588
  }
589
+ loadSeverityNumber();
571
590
  const otelLogger = provider.getLogger("neurolink-proxy-bodies", "1.0.0");
572
591
  const captureId = entry.captureId ?? randomUUID();
573
592
  const emit = (chunk, chunkIndex, totalChunks) => {
@@ -9,7 +9,7 @@
9
9
  * routing read none of it beyond cost and quality. `maxContextTokens` in
10
10
  * particular was never read anywhere.
11
11
  *
12
- * The registry covers 7 of the 40 registered providers, so the catalogue is
12
+ * The registry covers 7 of the registered providers, so the catalogue is
13
13
  * an addition to a declared pool, never a replacement: a host routing over
14
14
  * LiteLLM, OpenRouter or a self-hosted model still declares those by hand,
15
15
  * and `enrichCandidate` ranks declared and catalogue members on one scale.
@@ -9,7 +9,7 @@
9
9
  * routing read none of it beyond cost and quality. `maxContextTokens` in
10
10
  * particular was never read anywhere.
11
11
  *
12
- * The registry covers 7 of the 40 registered providers, so the catalogue is
12
+ * The registry covers 7 of the registered providers, so the catalogue is
13
13
  * an addition to a declared pool, never a replacement: a host routing over
14
14
  * LiteLLM, OpenRouter or a self-hosted model still declares those by hand,
15
15
  * and `enrichCandidate` ranks declared and catalogue members on one scale.
@@ -7,10 +7,11 @@ import type { CatalogProviderName, ModelChoice } from "../types/index.js";
7
7
  /**
8
8
  * Default models per provider (first choice/recommended).
9
9
  *
10
- * Covers every provider EXCEPT the 11 JSON-catalog providers — those default
11
- * models come from `models.default` in the catalog JSON, read directly by
12
- * `getDefaultModel()` below. (Two of the 11 — cerebras, sambanova — never had
13
- * a hand entry here at all; `getDefaultModel()` now resolves them too.)
10
+ * Covers every provider EXCEPT the JSON-catalog providers (see
11
+ * `CatalogProviderName`) — those default models come from `models.default`
12
+ * in the catalog JSON, read directly by `getDefaultModel()` below. (cerebras,
13
+ * sambanova — never had a hand entry here at all; `getDefaultModel()` now
14
+ * resolves them too.)
14
15
  *
15
16
  * AUTO is also excluded — it never had an entry here either (matches
16
17
  * pre-existing behavior: `getDefaultModel(AUTO)` returns `undefined`).
@@ -36,9 +36,8 @@ function catalogTopModels(entry) {
36
36
  * Top models per provider with descriptions for CLI prompts
37
37
  * These are curated lists of the most commonly used/recommended models
38
38
  *
39
- * Covers every provider EXCEPT the 11 JSON-catalog providers (cerebras,
40
- * cloudflare, deepseek, fireworks, groq, huggingface, mistral, perplexity,
41
- * sambanova, together-ai, xai) — their entries are derived from
39
+ * Covers every provider EXCEPT the JSON-catalog providers (see
40
+ * `CatalogProviderName`) — their entries are derived from
42
41
  * `models.catalog[*].description` by `catalogTopModels()` and merged in at
43
42
  * the accessor-function level below, never hand-duplicated here.
44
43
  */
@@ -393,10 +392,11 @@ const TOP_MODELS_CONFIG = {
393
392
  /**
394
393
  * Default models per provider (first choice/recommended).
395
394
  *
396
- * Covers every provider EXCEPT the 11 JSON-catalog providers — those default
397
- * models come from `models.default` in the catalog JSON, read directly by
398
- * `getDefaultModel()` below. (Two of the 11 — cerebras, sambanova — never had
399
- * a hand entry here at all; `getDefaultModel()` now resolves them too.)
395
+ * Covers every provider EXCEPT the JSON-catalog providers (see
396
+ * `CatalogProviderName`) — those default models come from `models.default`
397
+ * in the catalog JSON, read directly by `getDefaultModel()` below. (cerebras,
398
+ * sambanova — never had a hand entry here at all; `getDefaultModel()` now
399
+ * resolves them too.)
400
400
  *
401
401
  * AUTO is also excluded — it never had an entry here either (matches
402
402
  * pre-existing behavior: `getDefaultModel(AUTO)` returns `undefined`).
@@ -431,9 +431,10 @@ export const DEFAULT_MODELS = {
431
431
  /**
432
432
  * Model enum mappings for getAllModels.
433
433
  *
434
- * Covers every provider EXCEPT the 11 JSON-catalog providers — those model
435
- * lists come from `Object.keys(models.catalog)` in the catalog JSON, read
436
- * directly by `getAllModels()` below.
434
+ * Covers every provider EXCEPT the JSON-catalog providers (see
435
+ * `CatalogProviderName`) — those model lists come from
436
+ * `Object.keys(models.catalog)` in the catalog JSON, read directly by
437
+ * `getAllModels()` below.
437
438
  */
438
439
  const MODEL_ENUMS = {
439
440
  [AIProviderName.OPENAI]: OpenAIModels,
@@ -92,7 +92,7 @@ export declare class ProviderHealthChecker {
92
92
  * zero-config local proxy. Their real requirement is validated by
93
93
  * checkProviderSpecificConfig()'s dedicated per-provider checks instead.
94
94
  * Naively deriving [apiKey, ...extraRequired] from the descriptor for
95
- * these three (as for the other 27 providers) would make
95
+ * these three (as for the other providers) would make
96
96
  * checkEnvironmentConfiguration() push a false "missing environment
97
97
  * variables" issue — and therefore isHealthy=false — for legitimate
98
98
  * fallback-based Vertex auth, AWS_PROFILE/IAM-role Bedrock auth, and
@@ -449,7 +449,7 @@ export class ProviderHealthChecker {
449
449
  * zero-config local proxy. Their real requirement is validated by
450
450
  * checkProviderSpecificConfig()'s dedicated per-provider checks instead.
451
451
  * Naively deriving [apiKey, ...extraRequired] from the descriptor for
452
- * these three (as for the other 27 providers) would make
452
+ * these three (as for the other providers) would make
453
453
  * checkEnvironmentConfiguration() push a false "missing environment
454
454
  * variables" issue — and therefore isHealthy=false — for legitimate
455
455
  * fallback-based Vertex auth, AWS_PROFILE/IAM-role Bedrock auth, and