@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
@@ -40,6 +40,8 @@ import { ToolCallBatcher } from "./mcp/batching/index.js";
40
40
  import { ToolResultCache } from "./mcp/caching/index.js";
41
41
  import { EnhancedToolDiscovery } from "./mcp/enhancedToolDiscovery.js";
42
42
  import { ExternalServerManager } from "./mcp/externalServerManager.js";
43
+ import { McpOutputNormalizer, DEFAULT_MAX_MCP_OUTPUT_BYTES, DEFAULT_WARN_MCP_OUTPUT_BYTES, } from "./mcp/mcpOutputNormalizer.js";
44
+ import { LocalTempArtifactStore } from "./artifacts/artifactStore.js";
43
45
  import { ToolRouter } from "./mcp/routing/index.js";
44
46
  // Import direct tools server for automatic registration
45
47
  import { directToolsServer } from "./mcp/servers/agent/directToolsServer.js";
@@ -216,6 +218,8 @@ export class NeuroLink {
216
218
  mcpToolBatcher;
217
219
  mcpEnhancedDiscovery;
218
220
  mcpToolMiddlewares = [];
221
+ /** Artifact store for externalized MCP tool outputs (set when strategy=externalize). */
222
+ mcpArtifactStore;
219
223
  _disableToolCacheForCurrentRequest = false;
220
224
  mcpEnhancementsConfig;
221
225
  // Enhanced error handling support
@@ -255,6 +259,60 @@ export class NeuroLink {
255
259
  authProvider;
256
260
  pendingAuthConfig;
257
261
  authInitPromise;
262
+ // Per-provider credential overrides (instance-level default)
263
+ credentials;
264
+ /**
265
+ * Merge instance-level credentials with per-call credentials.
266
+ *
267
+ * Semantics: **deep merge at the provider level.** For each provider key
268
+ * present in both `this.credentials` and `callCredentials`, the per-call
269
+ * fields are merged ON TOP of the instance-level fields, so fields not
270
+ * mentioned in the per-call slice are preserved.
271
+ *
272
+ * Example:
273
+ * ```
274
+ * instance: { openai: { apiKey: "key1", baseURL: "url1" } }
275
+ * per-call: { openai: { apiKey: "key2" } }
276
+ * merged: { openai: { apiKey: "key2", baseURL: "url1" } } // baseURL preserved
277
+ * ```
278
+ *
279
+ * Providers present only in one source are carried through unchanged.
280
+ * Unrelated providers (not overridden in callCredentials) are carried through
281
+ * from instance credentials unchanged.
282
+ */
283
+ resolveCredentials(callCredentials) {
284
+ if (!this.credentials && !callCredentials) {
285
+ return undefined;
286
+ }
287
+ if (!this.credentials) {
288
+ return callCredentials;
289
+ }
290
+ if (!callCredentials) {
291
+ return this.credentials;
292
+ }
293
+ // Per-provider deep merge: for each provider key in the per-call
294
+ // override, merge its fields on top of the instance-level slice so
295
+ // individual fields (e.g. baseURL) are preserved when only apiKey
296
+ // is overridden per-call.
297
+ const merged = { ...this.credentials };
298
+ for (const key of Object.keys(callCredentials)) {
299
+ const instanceSlice = this.credentials[key];
300
+ const callSlice = callCredentials[key];
301
+ if (instanceSlice &&
302
+ callSlice &&
303
+ typeof instanceSlice === "object" &&
304
+ typeof callSlice === "object") {
305
+ merged[key] = {
306
+ ...instanceSlice,
307
+ ...callSlice,
308
+ };
309
+ }
310
+ else {
311
+ merged[key] = callSlice ?? instanceSlice;
312
+ }
313
+ }
314
+ return merged;
315
+ }
258
316
  // HITL (Human-in-the-Loop) support
259
317
  hitlManager;
260
318
  // Accumulated cost in USD across all generate() calls on this instance
@@ -595,6 +653,10 @@ export class NeuroLink {
595
653
  if (config?.auth) {
596
654
  this.pendingAuthConfig = config.auth;
597
655
  }
656
+ // Store per-provider credential overrides
657
+ if (config?.credentials) {
658
+ this.credentials = config.credentials;
659
+ }
598
660
  // Store task config for lazy initialization
599
661
  this._taskManagerConfig = config?.tasks;
600
662
  // Eagerly create TaskManager and register tools if config is provided
@@ -818,6 +880,25 @@ export class NeuroLink {
818
880
  });
819
881
  }
820
882
  // ToolRouter — lazy-initialized when 2+ external servers exist (see addExternalMCPServer)
883
+ // McpOutputNormalizer — active when mcp.outputLimits is configured
884
+ if (mcpConfig?.outputLimits) {
885
+ const strategy = mcpConfig.outputLimits.strategy ?? "externalize";
886
+ const maxBytes = mcpConfig.outputLimits.maxBytes ?? DEFAULT_MAX_MCP_OUTPUT_BYTES;
887
+ const warnBytes = mcpConfig.outputLimits.warnBytes ?? DEFAULT_WARN_MCP_OUTPUT_BYTES;
888
+ let artifactStore;
889
+ if (strategy === "externalize") {
890
+ artifactStore = new LocalTempArtifactStore();
891
+ this.mcpArtifactStore = artifactStore;
892
+ logger.debug("[NeuroLink] MCP artifact store initialized (local-temp)");
893
+ }
894
+ const normalizer = new McpOutputNormalizer({ strategy, maxBytes, warnBytes }, artifactStore);
895
+ this.externalServerManager.setOutputNormalizer(normalizer);
896
+ logger.debug("[NeuroLink] MCP output normalizer initialized", {
897
+ strategy,
898
+ maxBytes,
899
+ warnBytes,
900
+ });
901
+ }
821
902
  }
822
903
  /**
823
904
  * Register file reference tools with the MCP tool registry.
@@ -937,90 +1018,46 @@ export class NeuroLink {
937
1018
  "redis" in memConfig &&
938
1019
  !!memConfig.redis) ||
939
1020
  process.env.STORAGE_TYPE === "redis";
940
- if (!memConfig?.enabled || !hasRedisConfig) {
941
- logger.debug("[NeuroLink] Skipping memory retrieval tools requires Redis conversation memory");
1021
+ const hasArtifactStore = !!this.mcpArtifactStore;
1022
+ // Register when Redis is configured OR when an artifact store exists.
1023
+ // Artifact store alone is sufficient for the artifactId retrieval path —
1024
+ // session history retrieval just returns a clear error when Redis is absent.
1025
+ if ((!memConfig?.enabled || !hasRedisConfig) && !hasArtifactStore) {
1026
+ logger.debug("[NeuroLink] Skipping memory retrieval tools — requires Redis conversation memory or an artifact store");
942
1027
  return;
943
1028
  }
944
- const tools = {
945
- retrieve_context: {
946
- description: "Retrieve messages from conversation memory. Use this to access full tool " +
947
- "outputs when a result was truncated, review previous assistant responses, " +
948
- "or search through conversation history.",
949
- execute: async (params) => {
950
- // Lazy access: conversationMemory is initialized on first generate() call
951
- const memoryManager = this.conversationMemory;
952
- if (!memoryManager || !("getSessionRaw" in memoryManager)) {
953
- return {
954
- success: false,
955
- error: "Memory retrieval not available — Redis memory manager not initialized",
956
- metadata: {
957
- toolName: "retrieve_context",
958
- serverId: "direct",
959
- executionTime: 0,
960
- },
961
- };
962
- }
963
- const actualTools = createMemoryRetrievalTools(memoryManager);
964
- const result = await actualTools.retrieve_context.execute(params, {
965
- toolCallId: "memory-retrieval",
966
- messages: [],
967
- });
968
- // Check if the tool itself reported an error
969
- const hasError = result &&
970
- typeof result === "object" &&
971
- "error" in result &&
972
- !("messages" in result);
973
- const errorMsg = hasError
974
- ? result.error
975
- : undefined;
976
- return {
977
- success: !hasError,
978
- data: result,
979
- ...(errorMsg ? { error: errorMsg } : {}),
980
- metadata: {
981
- toolName: "retrieve_context",
982
- serverId: "direct",
983
- executionTime: 0,
984
- },
985
- };
986
- },
1029
+ // Extract the canonical tool definition (schema + description) from the
1030
+ // memoryRetrievalTools factory. We pass undefined as the memoryManager here
1031
+ // because we only need the Zod inputSchema and description at registration
1032
+ // time the actual manager is resolved lazily at execution time.
1033
+ const canonicalTools = createMemoryRetrievalTools(undefined, this.mcpArtifactStore);
1034
+ const retrieveContextDef = canonicalTools.retrieve_context;
1035
+ // Register via this.registerTool() so the tool ends up in the "user-defined"
1036
+ // category inside toolRegistry. getCustomTools() returns that category, which
1037
+ // is what ToolsManager reads to build the tool schema sent to the LLM.
1038
+ // (Tools registered via toolRegistry.registerTool() directly land in the
1039
+ // "built-in" category and are never included in the LLM's tool schema.)
1040
+ this.registerTool("retrieve_context", {
1041
+ name: "retrieve_context",
1042
+ description: retrieveContextDef.description ?? "Retrieve context or artifacts",
1043
+ // Pass the Zod schema so ToolsManager gives the LLM full parameter types.
1044
+ // registerTool() detects isZodSchema on inputSchema and preserves it.
1045
+ inputSchema: retrieveContextDef
1046
+ .inputSchema,
1047
+ execute: async (params) => {
1048
+ // Lazy: conversationMemory is initialized on the first generate() call.
1049
+ // When only an artifact store is present (no Redis), memoryManager is
1050
+ // undefined — createMemoryRetrievalTools handles that via an explicit guard.
1051
+ const memoryManager = this.conversationMemory;
1052
+ const tools = createMemoryRetrievalTools(memoryManager, this.mcpArtifactStore);
1053
+ // Return the result directly so the LLM receives clean output instead
1054
+ // of a nested { success, data, metadata } wrapper.
1055
+ // Bounded by TOOL_TIMEOUTS.EXECUTION_DEFAULT_MS so a stalled Redis or
1056
+ // filesystem backend never hangs the tool call indefinitely.
1057
+ return await withTimeout(tools.retrieve_context.execute(params, { toolCallId: "memory-retrieval", messages: [] }), TOOL_TIMEOUTS.EXECUTION_DEFAULT_MS, ErrorFactory.toolTimeout("retrieve_context", TOOL_TIMEOUTS.EXECUTION_DEFAULT_MS));
987
1058
  },
988
- };
989
- const registrations = Object.entries(tools).map(async ([toolName, toolDef]) => {
990
- const toolId = `direct.${toolName}`;
991
- const toolInfo = {
992
- name: toolName,
993
- description: toolDef.description,
994
- inputSchema: {},
995
- serverId: "direct",
996
- category: "built-in",
997
- };
998
- await this.toolRegistry.registerTool(toolId, toolInfo, {
999
- execute: async (params) => {
1000
- try {
1001
- return await toolDef.execute(params);
1002
- }
1003
- catch (error) {
1004
- // Known limitation: this non-throwing error path returns
1005
- // { success: false } without recording errorCategories in
1006
- // toolExecutionMetrics. These are internal memory-tool failures
1007
- // (low frequency), so the risk of metric gaps is minimal.
1008
- // A full fix would require access to the metrics map here,
1009
- // which is not available in the registration closure.
1010
- return {
1011
- success: false,
1012
- error: error instanceof Error ? error.message : String(error),
1013
- metadata: { toolName, serverId: "direct", executionTime: 0 },
1014
- };
1015
- }
1016
- },
1017
- description: toolDef.description,
1018
- inputSchema: {},
1019
- });
1020
- });
1021
- void Promise.all(registrations).then(() => {
1022
- logger.info("[NeuroLink] Memory retrieval tools registered");
1023
1059
  });
1060
+ logger.info("[NeuroLink] Memory retrieval tools registered");
1024
1061
  }
1025
1062
  /** Format memory context for prompt inclusion */
1026
1063
  formatMemoryContext(memoryContext, currentInput) {
@@ -2143,6 +2180,7 @@ Current user's request: ${currentInput}`;
2143
2180
  }
2144
2181
  }
2145
2182
  logger.debug("[NeuroLink] Graceful shutdown completed");
2183
+ this.credentials = undefined;
2146
2184
  }
2147
2185
  catch (error) {
2148
2186
  logger.error("[NeuroLink] Shutdown failed:", error);
@@ -2671,6 +2709,7 @@ Current user's request: ${currentInput}`;
2671
2709
  skipToolPromptInjection: options.skipToolPromptInjection,
2672
2710
  middleware: options.middleware,
2673
2711
  conversationMessages: options.conversationMessages,
2712
+ credentials: options.credentials,
2674
2713
  };
2675
2714
  const extraContext = options;
2676
2715
  if (extraContext.sessionId || extraContext.userId) {
@@ -2805,7 +2844,7 @@ Current user's request: ${currentInput}`;
2805
2844
  const { extractPPTContext, getEffectivePPTProvider } = await import("./features/ppt/utils.js");
2806
2845
  // Get provider instance for content planning
2807
2846
  const requestedProvider = (options.provider || "vertex");
2808
- const provider = await AIProviderFactory.createProvider(requestedProvider, options.model, true, this);
2847
+ const provider = await AIProviderFactory.createProvider(requestedProvider, options.model, true, this, undefined, this.resolveCredentials(options.credentials));
2809
2848
  // Resolve effective PPT provider (may auto-select if current is not PPT-compatible)
2810
2849
  const effectiveProvider = await getEffectivePPTProvider(provider, requestedProvider, options.model || "default", this);
2811
2850
  // Extract PPT context from options
@@ -3839,7 +3878,7 @@ Current user's request: ${currentInput}`;
3839
3878
  }
3840
3879
  async generateWithMCPProvider(context) {
3841
3880
  const { options, requestId, functionTag, tryMCPStartTime, providerName, availableTools, enhancedSystemPrompt, conversationMessages, } = context;
3842
- const provider = await AIProviderFactory.createProvider(providerName, options.model, !options.disableTools, this, options.region);
3881
+ const provider = await AIProviderFactory.createProvider(providerName, options.model, !options.disableTools, this, options.region, this.resolveCredentials(options.credentials));
3843
3882
  provider.setTraceContext(this._metricsTraceContext);
3844
3883
  this.emitter.emit("connected");
3845
3884
  this.emitter.emit("message", `${providerName} provider initialized successfully`);
@@ -4035,7 +4074,8 @@ Current user's request: ${currentInput}`;
4035
4074
  }
4036
4075
  const provider = await AIProviderFactory.createProvider(providerName, options.model, !options.disableTools, // Pass disableTools as inverse of enableMCP
4037
4076
  this, // Pass SDK instance
4038
- options.region);
4077
+ options.region, // Pass region parameter
4078
+ this.resolveCredentials(options.credentials));
4039
4079
  // Propagate trace context for parent-child span hierarchy
4040
4080
  provider.setTraceContext(this._metricsTraceContext);
4041
4081
  // ADD: Emit connection events for successful provider creation (Bedrock-compatible)
@@ -4783,7 +4823,7 @@ Current user's request: ${currentInput}`;
4783
4823
  reason: errorMsg,
4784
4824
  });
4785
4825
  try {
4786
- const fallbackProvider = await AIProviderFactory.createProvider(fallbackRoute.provider, fallbackRoute.model);
4826
+ const fallbackProvider = await AIProviderFactory.createProvider(fallbackRoute.provider, fallbackRoute.model, true, undefined, undefined, this.resolveCredentials(enhancedOptions.credentials));
4787
4827
  // Ensure fallback provider can execute tools
4788
4828
  fallbackProvider.setupToolExecutor({
4789
4829
  customTools: this.getCustomTools(),
@@ -4946,7 +4986,8 @@ Current user's request: ${currentInput}`;
4946
4986
  const providerName = await getBestProvider(options.provider);
4947
4987
  const provider = await AIProviderFactory.createProvider(providerName, options.model, !options.disableTools, // Pass disableTools as inverse of enableMCP
4948
4988
  this, // Pass SDK instance
4949
- options.region);
4989
+ options.region, // Pass region parameter
4990
+ this.resolveCredentials(options.credentials));
4950
4991
  // Propagate trace context for parent-child span hierarchy
4951
4992
  provider.setTraceContext(this._metricsTraceContext);
4952
4993
  // Enable tool execution for the provider using BaseProvider method
@@ -5161,7 +5202,7 @@ Current user's request: ${currentInput}`;
5161
5202
  const originalPrompt = options.input.text;
5162
5203
  const responseTime = Date.now() - startTime;
5163
5204
  const providerName = await getBestProvider(options.provider);
5164
- const provider = await AIProviderFactory.createProvider(providerName, options.model);
5205
+ const provider = await AIProviderFactory.createProvider(providerName, options.model, true, undefined, undefined, this.resolveCredentials(options.credentials));
5165
5206
  const fallbackStreamResult = await provider.stream({
5166
5207
  input: { text: options.input.text },
5167
5208
  model: options.model,
@@ -8523,6 +8564,7 @@ Current user's request: ${currentInput}`;
8523
8564
  this.mcpInitialized = false;
8524
8565
  this.mcpInitPromise = null;
8525
8566
  this.conversationMemoryNeedsInit = false;
8567
+ this.credentials = undefined;
8526
8568
  logger.debug("[NeuroLink] Initialization state reset successfully");
8527
8569
  }
8528
8570
  catch (error) {
@@ -8,7 +8,12 @@ export declare class AmazonBedrockProvider extends BaseProvider {
8
8
  private bedrockClient;
9
9
  private conversationHistory;
10
10
  private region;
11
- constructor(modelName?: string, neurolink?: NeuroLink, region?: string);
11
+ constructor(modelName?: string, neurolink?: NeuroLink, region?: string, credentials?: {
12
+ accessKeyId?: string;
13
+ secretAccessKey?: string;
14
+ sessionToken?: string;
15
+ region?: string;
16
+ });
12
17
  /**
13
18
  * Perform initial health check to catch credential/connectivity issues early
14
19
  * This prevents the health check failure we saw in production logs
@@ -18,9 +18,10 @@ export class AmazonBedrockProvider extends BaseProvider {
18
18
  bedrockClient;
19
19
  conversationHistory = [];
20
20
  region;
21
- constructor(modelName, neurolink, region) {
21
+ constructor(modelName, neurolink, region, credentials) {
22
22
  super(modelName, "bedrock", neurolink);
23
- this.region = region || process.env.AWS_REGION || "us-east-1";
23
+ this.region =
24
+ credentials?.region || region || process.env.AWS_REGION || "us-east-1";
24
25
  logger.debug("[AmazonBedrockProvider] Starting constructor with extensive logging for debugging");
25
26
  // Log environment variables for debugging
26
27
  logger.debug(`[AmazonBedrockProvider] Environment check: AWS_REGION=${process.env.AWS_REGION || "undefined"}, AWS_ACCESS_KEY_ID=${process.env.AWS_ACCESS_KEY_ID ? "SET" : "undefined"}, AWS_SECRET_ACCESS_KEY=${process.env.AWS_SECRET_ACCESS_KEY ? "SET" : "undefined"}`);
@@ -35,6 +36,17 @@ export class AmazonBedrockProvider extends BaseProvider {
35
36
  // 2. Environment variables
36
37
  // 3. AWS config files
37
38
  // 4. Instance metadata
39
+ ...(credentials?.accessKeyId && credentials?.secretAccessKey
40
+ ? {
41
+ credentials: {
42
+ accessKeyId: credentials.accessKeyId,
43
+ secretAccessKey: credentials.secretAccessKey,
44
+ ...(credentials.sessionToken
45
+ ? { sessionToken: credentials.sessionToken }
46
+ : {}),
47
+ },
48
+ }
49
+ : {}),
38
50
  });
39
51
  logger.debug(`[AmazonBedrockProvider] Successfully created BedrockRuntimeClient with model: ${this.modelName}, region: ${this.region}`);
40
52
  }
@@ -17,7 +17,13 @@ export declare class AmazonSageMakerProvider extends BaseProvider {
17
17
  private sagemakerModel;
18
18
  private sagemakerConfig;
19
19
  private modelConfig;
20
- constructor(modelName?: string, endpointName?: string, region?: string, neurolink?: NeuroLink);
20
+ constructor(modelName?: string, endpointName?: string, region?: string, neurolink?: NeuroLink, credentials?: {
21
+ accessKeyId?: string;
22
+ secretAccessKey?: string;
23
+ sessionToken?: string;
24
+ region?: string;
25
+ endpoint?: string;
26
+ });
21
27
  protected getProviderName(): AIProviderName;
22
28
  protected getDefaultModel(): string;
23
29
  protected getAISDKModel(): LanguageModel;
@@ -17,11 +17,29 @@ export class AmazonSageMakerProvider extends BaseProvider {
17
17
  sagemakerModel;
18
18
  sagemakerConfig;
19
19
  modelConfig;
20
- constructor(modelName, endpointName, region, neurolink) {
20
+ constructor(modelName, endpointName, region, neurolink, credentials) {
21
21
  super(modelName, "sagemaker", neurolink);
22
22
  try {
23
- // Load and validate configuration
24
- this.sagemakerConfig = getSageMakerConfig(region);
23
+ // Load and validate configuration, then overlay per-request credentials
24
+ const baseConfig = getSageMakerConfig(credentials?.region ?? region);
25
+ this.sagemakerConfig = {
26
+ ...baseConfig,
27
+ ...(credentials?.region !== undefined && {
28
+ region: credentials.region,
29
+ }),
30
+ ...(credentials?.accessKeyId !== undefined && {
31
+ accessKeyId: credentials.accessKeyId,
32
+ }),
33
+ ...(credentials?.secretAccessKey !== undefined && {
34
+ secretAccessKey: credentials.secretAccessKey,
35
+ }),
36
+ ...(credentials?.sessionToken !== undefined && {
37
+ sessionToken: credentials.sessionToken,
38
+ }),
39
+ ...(credentials?.endpoint !== undefined && {
40
+ endpoint: credentials.endpoint,
41
+ }),
42
+ };
25
43
  this.modelConfig = getSageMakerModelConfig(endpointName || getDefaultSageMakerEndpoint());
26
44
  // Create the SageMaker LanguageModel implementation.
27
45
  // SageMakerLanguageModel implements SageMakerAsLanguageModel which is
@@ -41,7 +41,10 @@ export declare class AnthropicProvider extends BaseProvider {
41
41
  * @param sdk - Optional NeuroLink SDK instance
42
42
  * @param config - Optional configuration options for auth, subscription tier, and beta features
43
43
  */
44
- constructor(modelName?: string, sdk?: unknown, config?: AnthropicProviderConfig);
44
+ constructor(modelName?: string, sdk?: unknown, config?: AnthropicProviderConfig, credentials?: {
45
+ apiKey?: string;
46
+ oauthToken?: string;
47
+ });
45
48
  /**
46
49
  * Get authentication headers based on current auth method and configuration.
47
50
  *
@@ -219,14 +219,27 @@ export class AnthropicProvider extends BaseProvider {
219
219
  * @param sdk - Optional NeuroLink SDK instance
220
220
  * @param config - Optional configuration options for auth, subscription tier, and beta features
221
221
  */
222
- constructor(modelName, sdk, config) {
223
- // Pre-compute effective model with tier validation before calling super
224
- const oauthToken = config?.oauthToken ?? getOAuthToken();
222
+ constructor(modelName, sdk, config, credentials) {
223
+ // Pre-compute effective model with tier validation before calling super.
224
+ //
225
+ // When per-request credentials supply an apiKey (without oauthToken),
226
+ // force api_key auth — skip OAuth detection entirely so the caller's
227
+ // key is used rather than a stale OAuth token from ~/.neurolink/.
228
+ const forceApiKey = !!(credentials?.apiKey && !credentials?.oauthToken);
229
+ const oauthToken = forceApiKey
230
+ ? null
231
+ : ((credentials?.oauthToken
232
+ ? { accessToken: credentials.oauthToken }
233
+ : null) ??
234
+ config?.oauthToken ??
235
+ getOAuthToken());
225
236
  // Resolve auth method FIRST so that tier detection uses the chosen method.
226
237
  // If ANTHROPIC_AUTH_METHOD=api_key wins over an existing OAuth token, the
227
238
  // tier must reflect api_key mode (full model access) rather than the OAuth
228
239
  // token's subscription level.
229
- const authMethod = config?.authMethod ?? detectAuthMethod(oauthToken);
240
+ const authMethod = forceApiKey
241
+ ? "api_key"
242
+ : (config?.authMethod ?? detectAuthMethod(oauthToken));
230
243
  const subscriptionTier = config?.subscriptionTier ??
231
244
  (authMethod === "oauth" ? detectSubscriptionTier(oauthToken) : "api");
232
245
  const targetModel = modelName || getDefaultAnthropicModel();
@@ -306,7 +319,7 @@ export class AnthropicProvider extends BaseProvider {
306
319
  }
307
320
  else {
308
321
  // Traditional API key authentication
309
- const apiKeyToUse = config?.apiKey ?? getAnthropicApiKey();
322
+ const apiKeyToUse = credentials?.apiKey ?? config?.apiKey ?? getAnthropicApiKey();
310
323
  anthropic = createAnthropic({
311
324
  apiKey: apiKeyToUse,
312
325
  headers,
@@ -2,13 +2,14 @@ import { type LanguageModel } from "ai";
2
2
  import { type AIProviderName } from "../constants/enums.js";
3
3
  import { BaseProvider } from "../core/baseProvider.js";
4
4
  import type { StreamOptions, StreamResult } from "../types/streamTypes.js";
5
+ import type { NeurolinkCredentials } from "../types/providers.js";
5
6
  export declare class AzureOpenAIProvider extends BaseProvider {
6
7
  private apiKey;
7
8
  private resourceName;
8
9
  private deployment;
9
10
  private apiVersion;
10
11
  private azureProvider;
11
- constructor(modelName?: string, sdk?: unknown);
12
+ constructor(modelName?: string, sdk?: unknown, _region?: string, credentials?: NeurolinkCredentials["azure"]);
12
13
  getProviderName(): AIProviderName;
13
14
  getDefaultModel(): string;
14
15
  /**
@@ -14,22 +14,27 @@ export class AzureOpenAIProvider extends BaseProvider {
14
14
  deployment;
15
15
  apiVersion;
16
16
  azureProvider;
17
- constructor(modelName, sdk) {
17
+ constructor(modelName, sdk, _region, credentials) {
18
18
  super(modelName, "azure", sdk);
19
- this.apiKey = process.env.AZURE_OPENAI_API_KEY || "";
19
+ this.apiKey = credentials?.apiKey || process.env.AZURE_OPENAI_API_KEY || "";
20
20
  const endpoint = process.env.AZURE_OPENAI_ENDPOINT || "";
21
- this.resourceName = endpoint
21
+ const envResourceName = endpoint
22
22
  .replace("https://", "")
23
23
  .replace(/\/+$/, "") // Remove trailing slashes
24
24
  .replace(".openai.azure.com", "")
25
25
  .replace(".cognitiveservices.azure.com", "");
26
+ this.resourceName = credentials?.resourceName || envResourceName;
26
27
  this.deployment =
27
- modelName ||
28
+ credentials?.deploymentName ||
29
+ modelName ||
28
30
  process.env.AZURE_OPENAI_MODEL ||
29
31
  process.env.AZURE_OPENAI_DEPLOYMENT ||
30
32
  process.env.AZURE_OPENAI_DEPLOYMENT_ID ||
31
33
  "gpt-4o";
32
- this.apiVersion = process.env.AZURE_API_VERSION || APIVersions.AZURE_LATEST;
34
+ this.apiVersion =
35
+ credentials?.apiVersion ||
36
+ process.env.AZURE_API_VERSION ||
37
+ APIVersions.AZURE_LATEST;
33
38
  // Configuration validation - now using consolidated utility
34
39
  if (!this.apiKey) {
35
40
  validateApiKey(createAzureAPIKeyConfig());
@@ -36,7 +36,10 @@ import type { ZodUnknownSchema } from "../types/typeAliases.js";
36
36
  * Solution: Simplify schema or use disableTools: true
37
37
  */
38
38
  export declare class GoogleAIStudioProvider extends BaseProvider {
39
- constructor(modelName?: string, sdk?: unknown);
39
+ private credentials?;
40
+ constructor(modelName?: string, sdk?: unknown, credentials?: {
41
+ apiKey?: string;
42
+ });
40
43
  getProviderName(): AIProviderName;
41
44
  getDefaultModel(): string;
42
45
  /**
@@ -65,8 +65,10 @@ async function createGoogleGenAIClient(apiKey) {
65
65
  * Solution: Simplify schema or use disableTools: true
66
66
  */
67
67
  export class GoogleAIStudioProvider extends BaseProvider {
68
- constructor(modelName, sdk) {
68
+ credentials;
69
+ constructor(modelName, sdk, credentials) {
69
70
  super(modelName, "google-ai", sdk);
71
+ this.credentials = credentials;
70
72
  logger.debug("GoogleAIStudioProvider initialized", {
71
73
  model: this.modelName,
72
74
  provider: this.providerName,
@@ -432,11 +434,6 @@ export class GoogleAIStudioProvider extends BaseProvider {
432
434
  }
433
435
  this.validateStreamOptions(options);
434
436
  const startTime = Date.now();
435
- const apiKey = this.getApiKey();
436
- // Ensure environment variable is set for @ai-sdk/google
437
- if (!process.env.GOOGLE_GENERATIVE_AI_API_KEY) {
438
- process.env.GOOGLE_GENERATIVE_AI_API_KEY = apiKey;
439
- }
440
437
  const model = await this.getAISDKModelWithMiddleware(options);
441
438
  const timeout = this.getTimeout(options);
442
439
  const timeoutController = createTimeoutController(timeout, this.providerName, "stream");
@@ -1214,7 +1211,9 @@ export class GoogleAIStudioProvider extends BaseProvider {
1214
1211
  }
1215
1212
  }
1216
1213
  getApiKey() {
1217
- const apiKey = process.env.GOOGLE_AI_API_KEY || process.env.GOOGLE_GENERATIVE_AI_API_KEY;
1214
+ const apiKey = this.credentials?.apiKey ||
1215
+ process.env.GOOGLE_AI_API_KEY ||
1216
+ process.env.GOOGLE_GENERATIVE_AI_API_KEY;
1218
1217
  if (!apiKey) {
1219
1218
  throw new AuthenticationError("GOOGLE_AI_API_KEY or GOOGLE_GENERATIVE_AI_API_KEY environment variable is not set", this.providerName);
1220
1219
  }
@@ -3,6 +3,7 @@ import type { ZodType } from "zod";
3
3
  import { type AIProviderName } from "../constants/enums.js";
4
4
  import { BaseProvider } from "../core/baseProvider.js";
5
5
  import type { EnhancedGenerateResult, TextGenerationOptions } from "../types/generateTypes.js";
6
+ import type { NeurolinkCredentials } from "../types/providers.js";
6
7
  import type { StreamOptions, StreamResult } from "../types/streamTypes.js";
7
8
  /**
8
9
  * Vertex Model Aliases
@@ -70,13 +71,14 @@ export declare class GoogleVertexProvider extends BaseProvider {
70
71
  private location;
71
72
  private registeredTools;
72
73
  private toolContext;
74
+ private credentials;
73
75
  private static modelConfigCache;
74
76
  private static modelConfigCacheTime;
75
77
  private static readonly CACHE_DURATION;
76
78
  private static readonly MAX_CACHE_SIZE;
77
79
  private static maxTokensCache;
78
80
  private static maxTokensCacheTime;
79
- constructor(modelName?: string, _providerName?: string, sdk?: unknown, region?: string);
81
+ constructor(modelName?: string, _providerName?: string, sdk?: unknown, region?: string, credentials?: NeurolinkCredentials["vertex"]);
80
82
  protected getProviderName(): AIProviderName;
81
83
  protected getDefaultModel(): string;
82
84
  /**