@juspay/neurolink 9.51.3 → 9.52.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.
Files changed (118) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/artifacts/artifactStore.d.ts +56 -0
  3. package/dist/artifacts/artifactStore.js +143 -0
  4. package/dist/browser/neurolink.min.js +311 -298
  5. package/dist/cli/commands/mcp.d.ts +6 -0
  6. package/dist/cli/commands/mcp.js +128 -86
  7. package/dist/cli/loop/optionsSchema.d.ts +1 -1
  8. package/dist/core/factory.d.ts +2 -2
  9. package/dist/core/factory.js +4 -4
  10. package/dist/core/redisConversationMemoryManager.js +20 -0
  11. package/dist/factories/providerFactory.d.ts +4 -4
  12. package/dist/factories/providerFactory.js +20 -7
  13. package/dist/factories/providerRegistry.d.ts +5 -0
  14. package/dist/factories/providerRegistry.js +45 -26
  15. package/dist/lib/artifacts/artifactStore.d.ts +56 -0
  16. package/dist/lib/artifacts/artifactStore.js +144 -0
  17. package/dist/lib/core/factory.d.ts +2 -2
  18. package/dist/lib/core/factory.js +4 -4
  19. package/dist/lib/core/redisConversationMemoryManager.js +20 -0
  20. package/dist/lib/factories/providerFactory.d.ts +4 -4
  21. package/dist/lib/factories/providerFactory.js +20 -7
  22. package/dist/lib/factories/providerRegistry.d.ts +5 -0
  23. package/dist/lib/factories/providerRegistry.js +45 -26
  24. package/dist/lib/mcp/externalServerManager.d.ts +6 -0
  25. package/dist/lib/mcp/externalServerManager.js +9 -0
  26. package/dist/lib/mcp/mcpOutputNormalizer.d.ts +49 -0
  27. package/dist/lib/mcp/mcpOutputNormalizer.js +182 -0
  28. package/dist/lib/mcp/toolDiscoveryService.d.ts +10 -0
  29. package/dist/lib/mcp/toolDiscoveryService.js +32 -1
  30. package/dist/lib/memory/memoryRetrievalTools.d.ts +64 -9
  31. package/dist/lib/memory/memoryRetrievalTools.js +77 -9
  32. package/dist/lib/neurolink.d.ts +23 -0
  33. package/dist/lib/neurolink.js +128 -86
  34. package/dist/lib/providers/amazonBedrock.d.ts +6 -1
  35. package/dist/lib/providers/amazonBedrock.js +14 -2
  36. package/dist/lib/providers/amazonSagemaker.d.ts +7 -1
  37. package/dist/lib/providers/amazonSagemaker.js +21 -3
  38. package/dist/lib/providers/anthropic.d.ts +4 -1
  39. package/dist/lib/providers/anthropic.js +18 -5
  40. package/dist/lib/providers/azureOpenai.d.ts +2 -1
  41. package/dist/lib/providers/azureOpenai.js +10 -5
  42. package/dist/lib/providers/googleAiStudio.d.ts +4 -1
  43. package/dist/lib/providers/googleAiStudio.js +6 -7
  44. package/dist/lib/providers/googleVertex.d.ts +3 -1
  45. package/dist/lib/providers/googleVertex.js +96 -17
  46. package/dist/lib/providers/huggingFace.d.ts +2 -1
  47. package/dist/lib/providers/huggingFace.js +4 -4
  48. package/dist/lib/providers/litellm.d.ts +5 -1
  49. package/dist/lib/providers/litellm.js +14 -9
  50. package/dist/lib/providers/mistral.d.ts +2 -1
  51. package/dist/lib/providers/mistral.js +2 -2
  52. package/dist/lib/providers/ollama.d.ts +3 -1
  53. package/dist/lib/providers/ollama.js +2 -2
  54. package/dist/lib/providers/openAI.d.ts +5 -1
  55. package/dist/lib/providers/openAI.js +15 -5
  56. package/dist/lib/providers/openRouter.d.ts +5 -1
  57. package/dist/lib/providers/openRouter.js +17 -5
  58. package/dist/lib/providers/openaiCompatible.d.ts +4 -1
  59. package/dist/lib/providers/openaiCompatible.js +15 -3
  60. package/dist/lib/session/globalSessionState.js +44 -1
  61. package/dist/lib/types/artifactTypes.d.ts +63 -0
  62. package/dist/lib/types/artifactTypes.js +11 -0
  63. package/dist/lib/types/configTypes.d.ts +39 -0
  64. package/dist/lib/types/conversation.d.ts +7 -0
  65. package/dist/lib/types/generateTypes.d.ts +13 -0
  66. package/dist/lib/types/index.d.ts +2 -0
  67. package/dist/lib/types/mcpOutputTypes.d.ts +40 -0
  68. package/dist/lib/types/mcpOutputTypes.js +9 -0
  69. package/dist/lib/types/providers.d.ts +75 -0
  70. package/dist/lib/types/streamTypes.d.ts +7 -1
  71. package/dist/mcp/externalServerManager.d.ts +6 -0
  72. package/dist/mcp/externalServerManager.js +9 -0
  73. package/dist/mcp/mcpOutputNormalizer.d.ts +49 -0
  74. package/dist/mcp/mcpOutputNormalizer.js +181 -0
  75. package/dist/mcp/toolDiscoveryService.d.ts +10 -0
  76. package/dist/mcp/toolDiscoveryService.js +32 -1
  77. package/dist/memory/memoryRetrievalTools.d.ts +64 -9
  78. package/dist/memory/memoryRetrievalTools.js +77 -9
  79. package/dist/neurolink.d.ts +23 -0
  80. package/dist/neurolink.js +128 -86
  81. package/dist/providers/amazonBedrock.d.ts +6 -1
  82. package/dist/providers/amazonBedrock.js +14 -2
  83. package/dist/providers/amazonSagemaker.d.ts +7 -1
  84. package/dist/providers/amazonSagemaker.js +21 -3
  85. package/dist/providers/anthropic.d.ts +4 -1
  86. package/dist/providers/anthropic.js +18 -5
  87. package/dist/providers/azureOpenai.d.ts +2 -1
  88. package/dist/providers/azureOpenai.js +10 -5
  89. package/dist/providers/googleAiStudio.d.ts +4 -1
  90. package/dist/providers/googleAiStudio.js +6 -7
  91. package/dist/providers/googleVertex.d.ts +3 -1
  92. package/dist/providers/googleVertex.js +96 -17
  93. package/dist/providers/huggingFace.d.ts +2 -1
  94. package/dist/providers/huggingFace.js +4 -4
  95. package/dist/providers/litellm.d.ts +5 -1
  96. package/dist/providers/litellm.js +14 -9
  97. package/dist/providers/mistral.d.ts +2 -1
  98. package/dist/providers/mistral.js +2 -2
  99. package/dist/providers/ollama.d.ts +3 -1
  100. package/dist/providers/ollama.js +2 -2
  101. package/dist/providers/openAI.d.ts +5 -1
  102. package/dist/providers/openAI.js +15 -5
  103. package/dist/providers/openRouter.d.ts +5 -1
  104. package/dist/providers/openRouter.js +17 -5
  105. package/dist/providers/openaiCompatible.d.ts +4 -1
  106. package/dist/providers/openaiCompatible.js +15 -3
  107. package/dist/session/globalSessionState.js +44 -1
  108. package/dist/types/artifactTypes.d.ts +63 -0
  109. package/dist/types/artifactTypes.js +10 -0
  110. package/dist/types/configTypes.d.ts +39 -0
  111. package/dist/types/conversation.d.ts +7 -0
  112. package/dist/types/generateTypes.d.ts +13 -0
  113. package/dist/types/index.d.ts +2 -0
  114. package/dist/types/mcpOutputTypes.d.ts +40 -0
  115. package/dist/types/mcpOutputTypes.js +8 -0
  116. package/dist/types/providers.d.ts +75 -0
  117. package/dist/types/streamTypes.d.ts +7 -1
  118. package/package.json +3 -2
@@ -0,0 +1,144 @@
1
+ /**
2
+ * Artifact Store
3
+ *
4
+ * Pluggable storage for externalized MCP tool outputs.
5
+ *
6
+ * When `mcp.outputLimits.strategy = "externalize"` the full tool payload is
7
+ * written here instead of being sent inline to the LLM. The model receives a
8
+ * compact surrogate with a preview and an artifact ID. The full payload can be
9
+ * retrieved on demand via the `retrieve_context` tool.
10
+ *
11
+ * Architecture:
12
+ * ArtifactStore (interface) — canonical types in src/lib/types/artifactTypes.ts
13
+ * LocalTempArtifactStore — single-process, filesystem-backed implementation
14
+ *
15
+ * Distributed backends (S3, Redis blobs) can be added later by implementing
16
+ * ArtifactStore from types/artifactTypes.ts.
17
+ *
18
+ * @module artifacts/artifactStore
19
+ */
20
+ import { randomUUID } from "node:crypto";
21
+ import { mkdir, readFile, rm, writeFile } from "node:fs/promises";
22
+ import { tmpdir } from "node:os";
23
+ import { join } from "node:path";
24
+ import { logger } from "../utils/logger.js";
25
+ // ---------------------------------------------------------------------------
26
+ // LocalTempArtifactStore
27
+ // ---------------------------------------------------------------------------
28
+ /** Characters used for the quick preview embedded in surrogate results. */
29
+ const DEFAULT_PREVIEW_CHARS = 500;
30
+ /**
31
+ * Filesystem-backed artifact store using the OS temp directory.
32
+ *
33
+ * Files are written with mode 0o600 (owner read/write only).
34
+ * An in-memory index tracks metadata without a separate index file.
35
+ *
36
+ * Suitable for:
37
+ * - CLI usage
38
+ * - Single-process SDK deployments
39
+ * - Multi-process deployments where each process manages its own artifacts
40
+ * (artifacts created in one process are not visible to others)
41
+ *
42
+ * @example
43
+ * ```typescript
44
+ * const store = new LocalTempArtifactStore();
45
+ * const ref = await store.store(largeJson, {
46
+ * toolName: "list_files",
47
+ * serverId: "filesystem-server",
48
+ * sizeBytes: Buffer.byteLength(largeJson),
49
+ * contentType: "json",
50
+ * });
51
+ * // Later, via retrieve_context:
52
+ * const full = await store.retrieve(ref.id);
53
+ * ```
54
+ */
55
+ export class LocalTempArtifactStore {
56
+ dir;
57
+ index = new Map();
58
+ constructor(dir) {
59
+ this.dir = dir ?? join(tmpdir(), "neurolink-artifacts");
60
+ }
61
+ generatePreview(payload) {
62
+ if (payload.length <= DEFAULT_PREVIEW_CHARS) {
63
+ return payload;
64
+ }
65
+ return `${payload.slice(0, DEFAULT_PREVIEW_CHARS)}…`;
66
+ }
67
+ async store(payload, meta) {
68
+ await mkdir(this.dir, { recursive: true, mode: 0o700 });
69
+ const id = randomUUID();
70
+ const ext = meta.contentType === "json" ? ".json" : ".txt";
71
+ const filePath = join(this.dir, `${id}${ext}`);
72
+ await writeFile(filePath, payload, { encoding: "utf-8", mode: 0o600 });
73
+ const fullMeta = {
74
+ ...meta,
75
+ createdAt: Date.now(),
76
+ path: filePath,
77
+ };
78
+ this.index.set(id, fullMeta);
79
+ logger.debug(`[ArtifactStore] Stored artifact ${id} for tool "${meta.toolName}" ` +
80
+ `(${formatBytes(meta.sizeBytes)})`);
81
+ return {
82
+ id,
83
+ preview: this.generatePreview(payload),
84
+ sizeBytes: meta.sizeBytes,
85
+ meta: { ...meta, createdAt: fullMeta.createdAt },
86
+ };
87
+ }
88
+ async retrieve(id) {
89
+ const entry = this.index.get(id);
90
+ if (!entry) {
91
+ logger.debug(`[ArtifactStore] Artifact ${id} not in index`);
92
+ return null;
93
+ }
94
+ try {
95
+ const content = await readFile(entry.path, "utf-8");
96
+ logger.debug(`[ArtifactStore] Retrieved artifact ${id} (${formatBytes(entry.sizeBytes)})`);
97
+ return content;
98
+ }
99
+ catch (err) {
100
+ logger.warn(`[ArtifactStore] Failed to read artifact ${id}: ${err instanceof Error ? err.message : String(err)}`);
101
+ return null;
102
+ }
103
+ }
104
+ async delete(id) {
105
+ const entry = this.index.get(id);
106
+ if (!entry) {
107
+ return;
108
+ }
109
+ try {
110
+ await rm(entry.path, { force: true });
111
+ }
112
+ catch {
113
+ // Suppress — file may already be gone
114
+ }
115
+ this.index.delete(id);
116
+ }
117
+ async cleanup(olderThanMs) {
118
+ const cutoff = Date.now() - olderThanMs;
119
+ let count = 0;
120
+ for (const [id, entry] of this.index.entries()) {
121
+ if (entry.createdAt < cutoff) {
122
+ await this.delete(id);
123
+ count++;
124
+ }
125
+ }
126
+ if (count > 0) {
127
+ logger.debug(`[ArtifactStore] Cleaned up ${count} expired artifact(s)`);
128
+ }
129
+ return count;
130
+ }
131
+ }
132
+ // ---------------------------------------------------------------------------
133
+ // Helpers
134
+ // ---------------------------------------------------------------------------
135
+ function formatBytes(bytes) {
136
+ if (bytes < 1024) {
137
+ return `${bytes} B`;
138
+ }
139
+ if (bytes < 1024 * 1024) {
140
+ return `${(bytes / 1024).toFixed(1)} KB`;
141
+ }
142
+ return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
143
+ }
144
+ //# sourceMappingURL=artifactStore.js.map
@@ -1,4 +1,4 @@
1
- import type { AIProvider, SupportedModelName } from "../types/index.js";
1
+ import type { AIProvider, SupportedModelName, NeurolinkCredentials } from "../types/index.js";
2
2
  import { AIProviderName } from "../constants/enums.js";
3
3
  import type { UnknownRecord } from "../types/common.js";
4
4
  import type { ProviderPairResult } from "../types/typeAliases.js";
@@ -27,7 +27,7 @@ export declare class AIProviderFactory {
27
27
  * @param region - Optional region override for cloud providers
28
28
  * @returns AIProvider instance
29
29
  */
30
- static createProvider(providerName: string, modelName?: string | null, enableMCP?: boolean, sdk?: UnknownRecord, region?: string): Promise<AIProvider>;
30
+ static createProvider(providerName: string, modelName?: string | null, enableMCP?: boolean, sdk?: UnknownRecord, region?: string, credentials?: NeurolinkCredentials): Promise<AIProvider>;
31
31
  /**
32
32
  * Create a provider instance with specific provider enum and model
33
33
  * @param provider - Provider enum value
@@ -168,7 +168,7 @@ export class AIProviderFactory {
168
168
  return resolvedModelName;
169
169
  }
170
170
  }
171
- static async createResolvedProvider(providerName, resolvedModelName, sdk, region, functionTag) {
171
+ static async createResolvedProvider(providerName, resolvedModelName, sdk, region, functionTag, credentials) {
172
172
  await withTimeout(ProviderRegistry.registerAllProviders(), 30_000, ErrorFactory.toolTimeout("provider-registration", 30_000));
173
173
  const normalizedName = this.normalizeProviderName(providerName);
174
174
  const finalModelName = resolvedModelName === "default" || resolvedModelName === null
@@ -180,7 +180,7 @@ export class AIProviderFactory {
180
180
  resolvedModelName: resolvedModelName || "not resolved",
181
181
  finalModelName: finalModelName || "using provider default",
182
182
  });
183
- const provider = await withTimeout(ProviderFactory.createProvider(normalizedName, finalModelName, sdk, region), 30_000, ErrorFactory.toolTimeout(`provider-creation:${normalizedName}`, 30_000));
183
+ const provider = await withTimeout(ProviderFactory.createProvider(normalizedName, finalModelName, sdk, region, credentials), 30_000, ErrorFactory.toolTimeout(`provider-creation:${normalizedName}`, 30_000));
184
184
  return { normalizedName, finalModelName, provider };
185
185
  }
186
186
  /**
@@ -192,7 +192,7 @@ export class AIProviderFactory {
192
192
  * @param region - Optional region override for cloud providers
193
193
  * @returns AIProvider instance
194
194
  */
195
- static async createProvider(providerName, modelName, enableMCP = true, sdk, region) {
195
+ static async createProvider(providerName, modelName, enableMCP = true, sdk, region, credentials) {
196
196
  const functionTag = "AIProviderFactory.createProvider";
197
197
  // Providers are registered via ProviderFactory.initialize() on first use
198
198
  return factoryTracer.startActiveSpan("neurolink.factory.createProvider", {
@@ -226,7 +226,7 @@ export class AIProviderFactory {
226
226
  // The dynamic model provider now provides reliable functionality without hanging
227
227
  let resolvedModelName = this.resolveModelFromEnvironment(providerName, modelName, functionTag);
228
228
  resolvedModelName = await this.resolveDynamicModelName(providerName, modelName, resolvedModelName, functionTag);
229
- const { normalizedName, finalModelName, provider } = await this.createResolvedProvider(providerName, resolvedModelName, sdk, region, functionTag);
229
+ const { normalizedName, finalModelName, provider } = await this.createResolvedProvider(providerName, resolvedModelName, sdk, region, functionTag, credentials);
230
230
  // Summary logging in format expected by debugging tools
231
231
  logger.debug(`[AIProviderFactory] Provider creation completed { providerName: '${normalizedName}', modelName: '${finalModelName}' }`);
232
232
  logger.debug(`[AIProviderFactory] Resolved model: ${finalModelName}`);
@@ -7,6 +7,7 @@ import { tracers } from "../telemetry/tracers.js";
7
7
  import { randomUUID } from "crypto";
8
8
  import { MESSAGES_PER_TURN } from "../config/conversationMemory.js";
9
9
  import { generateToolOutputPreview } from "../context/toolOutputLimits.js";
10
+ import { NEUROLINK_ARTIFACT_ID_KEY } from "../mcp/mcpOutputNormalizer.js";
10
11
  import { SummarizationEngine } from "../context/summarizationEngine.js";
11
12
  import { NeuroLink } from "../neurolink.js";
12
13
  import { ConversationMemoryError } from "../types/conversation.js";
@@ -1320,11 +1321,30 @@ User message: "${userMessage}"`;
1320
1321
  maxBytes: this.config?.contextCompaction?.maxToolOutputBytes,
1321
1322
  maxLines: this.config?.contextCompaction?.maxToolOutputLines,
1322
1323
  });
1324
+ // Extract artifact ID if this result was externalized by McpOutputNormalizer.
1325
+ // The surrogate carries `_meta.neurolinkArtifactId` on the raw result object.
1326
+ let artifactId;
1327
+ try {
1328
+ const rawResult = toolResult.result;
1329
+ if (rawResult && typeof rawResult === "object") {
1330
+ const meta = rawResult._meta;
1331
+ if (meta && typeof meta === "object") {
1332
+ const idValue = meta[NEUROLINK_ARTIFACT_ID_KEY];
1333
+ if (typeof idValue === "string") {
1334
+ artifactId = idValue;
1335
+ }
1336
+ }
1337
+ }
1338
+ }
1339
+ catch {
1340
+ // Ignore extraction errors — artifact ID is best-effort metadata
1341
+ }
1323
1342
  // Build metadata — only store preview when truncation occurred (no duplication)
1324
1343
  const metadata = {
1325
1344
  truncated,
1326
1345
  ...(truncated && { toolOutputPreview: preview }),
1327
1346
  ...(truncated && { originalSize }),
1347
+ ...(artifactId && { artifactId }),
1328
1348
  };
1329
1349
  // Build result — success/error metadata only, NOT the output data
1330
1350
  const result = {
@@ -1,6 +1,6 @@
1
1
  import type { AIProviderName } from "../constants/enums.js";
2
2
  import type { UnknownRecord } from "../types/common.js";
3
- import type { AIProvider } from "../types/index.js";
3
+ import type { AIProvider, NeurolinkCredentials } from "../types/index.js";
4
4
  /**
5
5
  * Provider constructor interface - supports both sync constructors and async factory functions
6
6
  */
@@ -33,7 +33,7 @@ export declare class ProviderFactory {
33
33
  * @param providerName - Provider name (optional, uses NEUROLINK_PROVIDER env var or 'vertex' as default)
34
34
  * @param modelName - Model name (optional, uses provider-specific env var or registry default)
35
35
  */
36
- static createProvider(providerName?: AIProviderName | string, modelName?: string, sdk?: UnknownRecord, region?: string): Promise<AIProvider>;
36
+ static createProvider(providerName?: AIProviderName | string, modelName?: string, sdk?: UnknownRecord, region?: string, credentials?: NeurolinkCredentials): Promise<AIProvider>;
37
37
  /**
38
38
  * Check if a provider is registered
39
39
  */
@@ -67,10 +67,10 @@ export declare class ProviderFactory {
67
67
  * Create the best available provider for the given name
68
68
  * Used by NeuroLink SDK for streaming and generation
69
69
  */
70
- static createBestProvider(providerName: AIProviderName | string, modelName?: string, enableMCP?: boolean, sdk?: UnknownRecord): Promise<AIProvider>;
70
+ static createBestProvider(providerName: AIProviderName | string, modelName?: string, enableMCP?: boolean, sdk?: UnknownRecord, credentials?: NeurolinkCredentials): Promise<AIProvider>;
71
71
  }
72
72
  /**
73
73
  * Helper function to create providers with backward compatibility
74
74
  */
75
- export declare function createAIProvider(providerName: AIProviderName | string, modelName?: string): Promise<AIProvider>;
75
+ export declare function createAIProvider(providerName: AIProviderName | string, modelName?: string, credentials?: NeurolinkCredentials): Promise<AIProvider>;
76
76
  export {};
@@ -30,7 +30,7 @@ export class ProviderFactory {
30
30
  * @param providerName - Provider name (optional, uses NEUROLINK_PROVIDER env var or 'vertex' as default)
31
31
  * @param modelName - Model name (optional, uses provider-specific env var or registry default)
32
32
  */
33
- static async createProvider(providerName, modelName, sdk, region) {
33
+ static async createProvider(providerName, modelName, sdk, region, credentials) {
34
34
  // Note: Providers are registered explicitly by ProviderRegistry to avoid circular dependencies
35
35
  // Use environment variable or default if not specified
36
36
  const resolvedProviderName = providerName ||
@@ -56,13 +56,26 @@ export class ProviderFactory {
56
56
  // Fallback to registry default if no env var
57
57
  model = model || registration.defaultModel;
58
58
  }
59
+ // Map registered provider names to NeurolinkCredentials keys.
60
+ // Most names match (openai, anthropic, vertex, bedrock, etc.)
61
+ // but some differ (google-ai → googleAiStudio, openai-compatible → openaiCompatible).
62
+ const credentialKeyMap = {
63
+ "google-ai": "googleAiStudio",
64
+ "openai-compatible": "openaiCompatible",
65
+ huggingface: "huggingFace",
66
+ };
67
+ const credKey = credentialKeyMap[normalizedName] ?? normalizedName;
68
+ // Extract provider-scoped credential slice (e.g. credentials.openai for OpenAI)
69
+ const scopedCredentials = credentials
70
+ ? credentials[credKey]
71
+ : undefined;
59
72
  try {
60
73
  if (typeof registration.constructor !== "function") {
61
74
  throw new Error(`Invalid constructor for provider ${providerName}: not a function`);
62
75
  }
63
76
  let result;
64
77
  try {
65
- const factoryResult = registration.constructor(model, resolvedProviderName, sdk, region);
78
+ const factoryResult = registration.constructor(model, resolvedProviderName, sdk, region, scopedCredentials);
66
79
  // Handle both sync and async results
67
80
  result =
68
81
  factoryResult instanceof Promise
@@ -74,7 +87,7 @@ export class ProviderFactory {
74
87
  registration.constructor.prototype.constructor ===
75
88
  registration.constructor) {
76
89
  try {
77
- result = new registration.constructor(model, resolvedProviderName, sdk, region);
90
+ result = new registration.constructor(model, resolvedProviderName, sdk, region, scopedCredentials);
78
91
  }
79
92
  catch (constructorError) {
80
93
  throw new Error(`Both factory function and constructor failed. Factory error: ${factoryError}. Constructor error: ${constructorError}`, { cause: constructorError });
@@ -154,14 +167,14 @@ export class ProviderFactory {
154
167
  * Create the best available provider for the given name
155
168
  * Used by NeuroLink SDK for streaming and generation
156
169
  */
157
- static async createBestProvider(providerName, modelName, enableMCP, sdk) {
158
- return await ProviderFactory.createProvider(providerName, modelName, sdk);
170
+ static async createBestProvider(providerName, modelName, enableMCP, sdk, credentials) {
171
+ return await ProviderFactory.createProvider(providerName, modelName, sdk, undefined, credentials);
159
172
  }
160
173
  }
161
174
  /**
162
175
  * Helper function to create providers with backward compatibility
163
176
  */
164
- export async function createAIProvider(providerName, modelName) {
165
- return await ProviderFactory.createProvider(providerName, modelName);
177
+ export async function createAIProvider(providerName, modelName, credentials) {
178
+ return await ProviderFactory.createProvider(providerName, modelName, undefined, undefined, credentials);
166
179
  }
167
180
  //# sourceMappingURL=providerFactory.js.map
@@ -13,6 +13,11 @@ export declare class ProviderRegistry {
13
13
  static registerAllProviders(): Promise<void>;
14
14
  /**
15
15
  * Internal registration implementation
16
+ *
17
+ * This method is a flat list of 13 provider registrations. Each registration
18
+ * is self-contained and extracting helpers would add indirection without
19
+ * reducing complexity — the function is long because there are many providers,
20
+ * not because any single registration is complex.
16
21
  */
17
22
  private static _doRegister;
18
23
  /**
@@ -32,82 +32,101 @@ export class ProviderRegistry {
32
32
  }
33
33
  /**
34
34
  * Internal registration implementation
35
+ *
36
+ * This method is a flat list of 13 provider registrations. Each registration
37
+ * is self-contained and extracting helpers would add indirection without
38
+ * reducing complexity — the function is long because there are many providers,
39
+ * not because any single registration is complex.
35
40
  */
41
+ // eslint-disable-next-line max-lines-per-function
36
42
  static async _doRegister() {
37
43
  try {
38
44
  // Register providers with dynamic import factory functions
39
45
  const { ProviderFactory } = await import("./providerFactory.js");
40
46
  // Register Google AI Studio Provider (our validated baseline)
41
- ProviderFactory.registerProvider(AIProviderName.GOOGLE_AI, async (modelName, _providerName, sdk) => {
47
+ ProviderFactory.registerProvider(AIProviderName.GOOGLE_AI, async (modelName, _providerName, sdk, _region, credentials) => {
48
+ const googleAiCreds = credentials;
42
49
  const { GoogleAIStudioProvider } = await import("../providers/googleAiStudio.js");
43
- return new GoogleAIStudioProvider(modelName, sdk);
50
+ return new GoogleAIStudioProvider(modelName, sdk, googleAiCreds);
44
51
  }, GoogleAIModels.GEMINI_2_5_FLASH, ["googleAiStudio", "google", "gemini", "google-ai", "google-ai-studio"]);
45
52
  // Register OpenAI provider
46
- ProviderFactory.registerProvider(AIProviderName.OPENAI, async (modelName, _providerName, sdk) => {
53
+ ProviderFactory.registerProvider(AIProviderName.OPENAI, async (modelName, _providerName, sdk, _region, credentials) => {
54
+ const openaiCreds = credentials;
47
55
  const { OpenAIProvider } = await import("../providers/openAI.js");
48
- return new OpenAIProvider(modelName, sdk);
56
+ return new OpenAIProvider(modelName, sdk, undefined, openaiCreds);
49
57
  }, OpenAIModels.GPT_4O_MINI, ["gpt", "chatgpt"]);
50
58
  // Register Anthropic provider
51
- ProviderFactory.registerProvider(AIProviderName.ANTHROPIC, async (modelName, _providerName, sdk) => {
59
+ ProviderFactory.registerProvider(AIProviderName.ANTHROPIC, async (modelName, _providerName, sdk, _region, credentials) => {
60
+ const anthropicCreds = credentials;
52
61
  const { AnthropicProvider } = await import("../providers/anthropic.js");
53
- return new AnthropicProvider(modelName, sdk);
62
+ return new AnthropicProvider(modelName, sdk, undefined, anthropicCreds);
54
63
  }, AnthropicModels.CLAUDE_SONNET_4_6, ["claude", "anthropic"]);
55
64
  // Register Amazon Bedrock provider
56
- ProviderFactory.registerProvider(AIProviderName.BEDROCK, async (modelName, _providerName, sdk, region) => {
65
+ ProviderFactory.registerProvider(AIProviderName.BEDROCK, async (modelName, _providerName, sdk, region, credentials) => {
66
+ const bedrockCreds = credentials;
57
67
  const { AmazonBedrockProvider } = await import("../providers/amazonBedrock.js");
58
- return new AmazonBedrockProvider(modelName, sdk, region);
68
+ return new AmazonBedrockProvider(modelName, sdk, region, bedrockCreds);
59
69
  }, undefined, // Let provider read BEDROCK_MODEL from .env
60
70
  ["bedrock", "aws"]);
61
71
  // Register Azure OpenAI provider
62
- ProviderFactory.registerProvider(AIProviderName.AZURE, async (modelName, _providerName, sdk) => {
72
+ ProviderFactory.registerProvider(AIProviderName.AZURE, async (modelName, _providerName, sdk, _region, credentials) => {
73
+ const azureCreds = credentials;
63
74
  const { AzureOpenAIProvider } = await import("../providers/azureOpenai.js");
64
- return new AzureOpenAIProvider(modelName, sdk);
75
+ return new AzureOpenAIProvider(modelName, sdk, undefined, azureCreds);
65
76
  }, process.env.AZURE_MODEL ||
66
77
  process.env.AZURE_OPENAI_MODEL ||
67
78
  process.env.AZURE_OPENAI_DEPLOYMENT ||
68
79
  process.env.AZURE_OPENAI_DEPLOYMENT_ID ||
69
80
  "gpt-4o-mini", ["azure", "azureOpenai"]);
70
81
  // Register Google Vertex AI provider
71
- ProviderFactory.registerProvider(AIProviderName.VERTEX, async (modelName, providerName, sdk, region) => {
82
+ ProviderFactory.registerProvider(AIProviderName.VERTEX, async (modelName, providerName, sdk, region, credentials) => {
83
+ const vertexCreds = credentials;
72
84
  const { GoogleVertexProvider } = await import("../providers/googleVertex.js");
73
- return new GoogleVertexProvider(modelName, providerName, sdk, region);
85
+ return new GoogleVertexProvider(modelName, providerName, sdk, region, vertexCreds);
74
86
  }, VertexModels.CLAUDE_4_6_SONNET, ["vertex", "googleVertex"]);
75
87
  // Register Hugging Face provider (Unified Router implementation)
76
- ProviderFactory.registerProvider(AIProviderName.HUGGINGFACE, async (modelName) => {
88
+ ProviderFactory.registerProvider(AIProviderName.HUGGINGFACE, async (modelName, _providerName, _sdk, _region, credentials) => {
89
+ const hfCreds = credentials;
77
90
  const { HuggingFaceProvider } = await import("../providers/huggingFace.js");
78
- return new HuggingFaceProvider(modelName);
91
+ return new HuggingFaceProvider(modelName, undefined, hfCreds);
79
92
  }, process.env.HUGGINGFACE_MODEL ||
80
93
  HuggingFaceModels.QWEN_2_5_72B_INSTRUCT, ["huggingface", "hf"]);
81
94
  // Register Mistral AI provider
82
- ProviderFactory.registerProvider(AIProviderName.MISTRAL, async (modelName, _providerName, sdk) => {
95
+ ProviderFactory.registerProvider(AIProviderName.MISTRAL, async (modelName, _providerName, sdk, _region, credentials) => {
96
+ const mistralCreds = credentials;
83
97
  const { MistralProvider } = await import("../providers/mistral.js");
84
- return new MistralProvider(modelName, sdk);
98
+ return new MistralProvider(modelName, sdk, undefined, mistralCreds);
85
99
  }, MistralModels.MISTRAL_LARGE_LATEST, ["mistral"]);
86
100
  // Register Ollama provider
87
- ProviderFactory.registerProvider(AIProviderName.OLLAMA, async (modelName) => {
101
+ ProviderFactory.registerProvider(AIProviderName.OLLAMA, async (modelName, _providerName, _sdk, _region, credentials) => {
102
+ const ollamaCreds = credentials;
88
103
  const { OllamaProvider } = await import("../providers/ollama.js");
89
- return new OllamaProvider(modelName);
104
+ return new OllamaProvider(modelName, ollamaCreds);
90
105
  }, process.env.OLLAMA_MODEL || OllamaModels.LLAMA3_2_LATEST, ["ollama", "local"]);
91
106
  // Register LiteLLM provider
92
- ProviderFactory.registerProvider(AIProviderName.LITELLM, async (modelName, _providerName, sdk) => {
107
+ ProviderFactory.registerProvider(AIProviderName.LITELLM, async (modelName, _providerName, sdk, _region, credentials) => {
108
+ const litellmCreds = credentials;
93
109
  const { LiteLLMProvider } = await import("../providers/litellm.js");
94
- return new LiteLLMProvider(modelName, sdk);
110
+ return new LiteLLMProvider(modelName, sdk, undefined, litellmCreds);
95
111
  }, process.env.LITELLM_MODEL || LiteLLMModels.OPENAI_GPT_4O_MINI, ["litellm"]);
96
112
  // Register OpenAI Compatible provider
97
- ProviderFactory.registerProvider(AIProviderName.OPENAI_COMPATIBLE, async (modelName, _providerName, sdk) => {
113
+ ProviderFactory.registerProvider(AIProviderName.OPENAI_COMPATIBLE, async (modelName, _providerName, sdk, _region, credentials) => {
114
+ const openaiCompatCreds = credentials;
98
115
  const { OpenAICompatibleProvider } = await import("../providers/openaiCompatible.js");
99
- return new OpenAICompatibleProvider(modelName, sdk);
116
+ return new OpenAICompatibleProvider(modelName, sdk, undefined, openaiCompatCreds);
100
117
  }, process.env.OPENAI_COMPATIBLE_MODEL || undefined, // Enable auto-discovery when no model specified
101
118
  ["openai-compatible", "vllm", "compatible"]);
102
119
  // Register OpenRouter provider (300+ models from 60+ providers)
103
- ProviderFactory.registerProvider(AIProviderName.OPENROUTER, async (modelName, _providerName, sdk) => {
120
+ ProviderFactory.registerProvider(AIProviderName.OPENROUTER, async (modelName, _providerName, sdk, _region, credentials) => {
121
+ const openrouterCreds = credentials;
104
122
  const { OpenRouterProvider } = await import("../providers/openRouter.js");
105
- return new OpenRouterProvider(modelName, sdk);
123
+ return new OpenRouterProvider(modelName, sdk, undefined, openrouterCreds);
106
124
  }, process.env.OPENROUTER_MODEL || "anthropic/claude-3-5-sonnet", ["openrouter", "or"]);
107
125
  // Register Amazon SageMaker provider
108
- ProviderFactory.registerProvider(AIProviderName.SAGEMAKER, async (modelName, _providerName, _sdk, region) => {
126
+ ProviderFactory.registerProvider(AIProviderName.SAGEMAKER, async (modelName, _providerName, _sdk, region, credentials) => {
127
+ const sagemakerCreds = credentials;
109
128
  const { AmazonSageMakerProvider } = await import("../providers/amazonSagemaker.js");
110
- return new AmazonSageMakerProvider(modelName, undefined, region);
129
+ return new AmazonSageMakerProvider(modelName, undefined, region, undefined, sagemakerCreds);
111
130
  }, process.env.SAGEMAKER_MODEL || "sagemaker-model", ["sagemaker", "aws-sagemaker"]);
112
131
  logger.debug("All providers registered successfully");
113
132
  this.registered = true;
@@ -27,6 +27,12 @@ export declare class ExternalServerManager extends EventEmitter {
27
27
  constructor(config?: ExternalMCPManagerConfig, options?: {
28
28
  enableMainRegistryIntegration?: boolean;
29
29
  });
30
+ /**
31
+ * Attach a McpOutputNormalizer to the underlying ToolDiscoveryService.
32
+ * All tool outputs will be measured and (if oversized) replaced with compact
33
+ * surrogates before being returned to callers.
34
+ */
35
+ setOutputNormalizer(normalizer: import("./mcpOutputNormalizer.js").McpOutputNormalizer): void;
30
36
  /**
31
37
  * Set HITL manager for human-in-the-loop safety mechanisms
32
38
  * @param hitlManager - HITL manager instance (optional, can be undefined to disable)
@@ -210,6 +210,15 @@ export class ExternalServerManager extends EventEmitter {
210
210
  process.on("SIGTERM", () => this.shutdown());
211
211
  process.on("beforeExit", () => this.shutdown());
212
212
  }
213
+ /**
214
+ * Attach a McpOutputNormalizer to the underlying ToolDiscoveryService.
215
+ * All tool outputs will be measured and (if oversized) replaced with compact
216
+ * surrogates before being returned to callers.
217
+ */
218
+ setOutputNormalizer(normalizer) {
219
+ this.toolDiscovery.setOutputNormalizer(normalizer);
220
+ mcpLogger.debug("[ExternalServerManager] MCP output normalizer attached to ToolDiscoveryService");
221
+ }
213
222
  /**
214
223
  * Set HITL manager for human-in-the-loop safety mechanisms
215
224
  * @param hitlManager - HITL manager instance (optional, can be undefined to disable)
@@ -0,0 +1,49 @@
1
+ /**
2
+ * MCP Output Normalizer
3
+ *
4
+ * Single responsibility: intercept a raw MCP `CallToolResult`, measure it,
5
+ * and apply the configured strategy so that oversized payloads never reach
6
+ * caches, Redis, or LLM context windows raw.
7
+ *
8
+ * Two strategies:
9
+ * - "inline" Pass through unchanged. The full payload enters the LLM
10
+ * context as-is. Emit a warning above warnBytes.
11
+ * - "externalize" Write the full payload to the ArtifactStore, return a
12
+ * compact surrogate with a head/tail preview and an artifact
13
+ * ID. The model uses `retrieve_context` with that ID to read
14
+ * the full output on demand, with offset/limit pagination.
15
+ *
16
+ * The surrogate result is shaped as an MCP `CallToolResult` so it passes
17
+ * transparently through any downstream code that expects that format.
18
+ * A `_meta` extension carries the artifact ID for structured extraction in
19
+ * `redisConversationMemoryManager`.
20
+ *
21
+ * @module mcp/mcpOutputNormalizer
22
+ */
23
+ import type { ArtifactStore } from "../artifacts/artifactStore.js";
24
+ import type { McpOutputNormalizerConfig, McpOutputContext, NormalizedMcpOutput } from "../types/mcpOutputTypes.js";
25
+ export type { McpOutputStrategy, McpOutputNormalizerConfig, McpOutputContext, NormalizedMcpOutput, } from "../types/mcpOutputTypes.js";
26
+ /** Default byte ceiling above which externalize fires (100 KB). */
27
+ export declare const DEFAULT_MAX_MCP_OUTPUT_BYTES: number;
28
+ /** Default byte threshold for emitting a warning while still inline (50 KB). */
29
+ export declare const DEFAULT_WARN_MCP_OUTPUT_BYTES: number;
30
+ /** Metadata key embedded in surrogate `_meta` and used by memory manager. */
31
+ export declare const NEUROLINK_ARTIFACT_ID_KEY = "neurolinkArtifactId";
32
+ /**
33
+ * Stateless normalizer (state lives in the injected ArtifactStore).
34
+ *
35
+ * Construct once per NeuroLink instance and set via
36
+ * `ToolDiscoveryService.setOutputNormalizer()`.
37
+ */
38
+ export declare class McpOutputNormalizer {
39
+ private readonly config;
40
+ private readonly artifactStore?;
41
+ constructor(config: McpOutputNormalizerConfig, artifactStore?: ArtifactStore | undefined);
42
+ /**
43
+ * Measure `callResult`, apply strategy if oversized, return normalized output.
44
+ *
45
+ * Never throws: on any internal failure the raw result is returned unchanged
46
+ * with a warning log so tool execution is never broken by the normalizer.
47
+ */
48
+ normalize(callResult: unknown, context: McpOutputContext): Promise<NormalizedMcpOutput>;
49
+ }