@juspay/neurolink 9.41.0 → 9.42.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 (189) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/README.md +7 -1
  3. package/dist/auth/anthropicOAuth.d.ts +18 -3
  4. package/dist/auth/anthropicOAuth.js +137 -4
  5. package/dist/auth/providers/firebase.js +5 -1
  6. package/dist/auth/providers/jwt.js +5 -1
  7. package/dist/auth/providers/workos.js +5 -1
  8. package/dist/auth/sessionManager.d.ts +1 -1
  9. package/dist/auth/sessionManager.js +58 -27
  10. package/dist/browser/neurolink.min.js +337 -318
  11. package/dist/cli/commands/mcp.js +3 -0
  12. package/dist/cli/commands/proxy.d.ts +2 -1
  13. package/dist/cli/commands/proxy.js +279 -16
  14. package/dist/cli/commands/task.js +3 -0
  15. package/dist/cli/factories/commandFactory.d.ts +2 -0
  16. package/dist/cli/factories/commandFactory.js +38 -0
  17. package/dist/cli/parser.js +4 -3
  18. package/dist/client/aiSdkAdapter.js +3 -0
  19. package/dist/client/streamingClient.js +30 -10
  20. package/dist/core/modules/GenerationHandler.js +3 -2
  21. package/dist/core/redisConversationMemoryManager.js +7 -3
  22. package/dist/evaluation/BatchEvaluator.js +4 -1
  23. package/dist/evaluation/hooks/observabilityHooks.js +5 -3
  24. package/dist/evaluation/pipeline/evaluationPipeline.d.ts +3 -2
  25. package/dist/evaluation/pipeline/evaluationPipeline.js +20 -8
  26. package/dist/evaluation/pipeline/strategies/batchStrategy.js +6 -3
  27. package/dist/evaluation/pipeline/strategies/samplingStrategy.js +18 -10
  28. package/dist/lib/auth/anthropicOAuth.d.ts +18 -3
  29. package/dist/lib/auth/anthropicOAuth.js +137 -4
  30. package/dist/lib/auth/providers/firebase.js +5 -1
  31. package/dist/lib/auth/providers/jwt.js +5 -1
  32. package/dist/lib/auth/providers/workos.js +5 -1
  33. package/dist/lib/auth/sessionManager.d.ts +1 -1
  34. package/dist/lib/auth/sessionManager.js +58 -27
  35. package/dist/lib/client/aiSdkAdapter.js +3 -0
  36. package/dist/lib/client/streamingClient.js +30 -10
  37. package/dist/lib/core/modules/GenerationHandler.js +3 -2
  38. package/dist/lib/core/redisConversationMemoryManager.js +7 -3
  39. package/dist/lib/evaluation/BatchEvaluator.js +4 -1
  40. package/dist/lib/evaluation/hooks/observabilityHooks.js +5 -3
  41. package/dist/lib/evaluation/pipeline/evaluationPipeline.d.ts +3 -2
  42. package/dist/lib/evaluation/pipeline/evaluationPipeline.js +20 -8
  43. package/dist/lib/evaluation/pipeline/strategies/batchStrategy.js +6 -3
  44. package/dist/lib/evaluation/pipeline/strategies/samplingStrategy.js +18 -10
  45. package/dist/lib/neurolink.d.ts +3 -2
  46. package/dist/lib/neurolink.js +260 -494
  47. package/dist/lib/observability/otelBridge.d.ts +2 -2
  48. package/dist/lib/observability/otelBridge.js +12 -3
  49. package/dist/lib/providers/amazonBedrock.js +2 -4
  50. package/dist/lib/providers/anthropic.d.ts +9 -5
  51. package/dist/lib/providers/anthropic.js +19 -14
  52. package/dist/lib/providers/anthropicBaseProvider.d.ts +3 -3
  53. package/dist/lib/providers/anthropicBaseProvider.js +5 -4
  54. package/dist/lib/providers/azureOpenai.d.ts +1 -1
  55. package/dist/lib/providers/azureOpenai.js +5 -4
  56. package/dist/lib/providers/googleAiStudio.js +30 -1
  57. package/dist/lib/providers/googleVertex.js +28 -6
  58. package/dist/lib/providers/huggingFace.d.ts +3 -3
  59. package/dist/lib/providers/huggingFace.js +6 -8
  60. package/dist/lib/providers/litellm.js +41 -29
  61. package/dist/lib/providers/mistral.js +2 -1
  62. package/dist/lib/providers/ollama.js +80 -23
  63. package/dist/lib/providers/openAI.js +3 -2
  64. package/dist/lib/providers/openRouter.js +2 -1
  65. package/dist/lib/providers/openaiCompatible.d.ts +4 -4
  66. package/dist/lib/providers/openaiCompatible.js +4 -4
  67. package/dist/lib/proxy/claudeFormat.d.ts +3 -2
  68. package/dist/lib/proxy/claudeFormat.js +25 -20
  69. package/dist/lib/proxy/cloaking/plugins/sessionIdentity.d.ts +2 -6
  70. package/dist/lib/proxy/cloaking/plugins/sessionIdentity.js +9 -33
  71. package/dist/lib/proxy/modelRouter.js +3 -0
  72. package/dist/lib/proxy/oauthFetch.d.ts +1 -1
  73. package/dist/lib/proxy/oauthFetch.js +65 -72
  74. package/dist/lib/proxy/proxyConfig.js +44 -24
  75. package/dist/lib/proxy/proxyEnv.d.ts +19 -0
  76. package/dist/lib/proxy/proxyEnv.js +73 -0
  77. package/dist/lib/proxy/proxyFetch.js +50 -4
  78. package/dist/lib/proxy/proxyTracer.d.ts +133 -0
  79. package/dist/lib/proxy/proxyTracer.js +645 -0
  80. package/dist/lib/proxy/rawStreamCapture.d.ts +10 -0
  81. package/dist/lib/proxy/rawStreamCapture.js +83 -0
  82. package/dist/lib/proxy/requestLogger.d.ts +32 -5
  83. package/dist/lib/proxy/requestLogger.js +406 -37
  84. package/dist/lib/proxy/sseInterceptor.d.ts +97 -0
  85. package/dist/lib/proxy/sseInterceptor.js +402 -0
  86. package/dist/lib/proxy/usageStats.d.ts +4 -3
  87. package/dist/lib/proxy/usageStats.js +25 -12
  88. package/dist/lib/rag/chunkers/MarkdownChunker.js +13 -5
  89. package/dist/lib/rag/chunking/markdownChunker.js +15 -6
  90. package/dist/lib/server/routes/claudeProxyRoutes.d.ts +7 -2
  91. package/dist/lib/server/routes/claudeProxyRoutes.js +1737 -508
  92. package/dist/lib/services/server/ai/observability/instrumentation.d.ts +7 -1
  93. package/dist/lib/services/server/ai/observability/instrumentation.js +240 -40
  94. package/dist/lib/tasks/backends/bullmqBackend.d.ts +1 -0
  95. package/dist/lib/tasks/backends/bullmqBackend.js +14 -7
  96. package/dist/lib/tasks/store/redisTaskStore.d.ts +1 -0
  97. package/dist/lib/tasks/store/redisTaskStore.js +34 -26
  98. package/dist/lib/tasks/taskManager.d.ts +3 -0
  99. package/dist/lib/tasks/taskManager.js +63 -30
  100. package/dist/lib/telemetry/index.d.ts +2 -1
  101. package/dist/lib/telemetry/index.js +2 -1
  102. package/dist/lib/telemetry/telemetryService.d.ts +3 -0
  103. package/dist/lib/telemetry/telemetryService.js +65 -5
  104. package/dist/lib/types/cli.d.ts +10 -0
  105. package/dist/lib/types/proxyTypes.d.ts +37 -5
  106. package/dist/lib/types/streamTypes.d.ts +25 -3
  107. package/dist/lib/utils/messageBuilder.js +3 -2
  108. package/dist/lib/utils/providerHealth.d.ts +18 -0
  109. package/dist/lib/utils/providerHealth.js +240 -9
  110. package/dist/lib/utils/providerUtils.js +14 -8
  111. package/dist/lib/utils/toolChoice.d.ts +4 -0
  112. package/dist/lib/utils/toolChoice.js +7 -0
  113. package/dist/neurolink.d.ts +3 -2
  114. package/dist/neurolink.js +260 -494
  115. package/dist/observability/otelBridge.d.ts +2 -2
  116. package/dist/observability/otelBridge.js +12 -3
  117. package/dist/providers/amazonBedrock.js +2 -4
  118. package/dist/providers/anthropic.d.ts +9 -5
  119. package/dist/providers/anthropic.js +19 -14
  120. package/dist/providers/anthropicBaseProvider.d.ts +3 -3
  121. package/dist/providers/anthropicBaseProvider.js +5 -4
  122. package/dist/providers/azureOpenai.d.ts +1 -1
  123. package/dist/providers/azureOpenai.js +5 -4
  124. package/dist/providers/googleAiStudio.js +30 -1
  125. package/dist/providers/googleVertex.js +28 -6
  126. package/dist/providers/huggingFace.d.ts +3 -3
  127. package/dist/providers/huggingFace.js +6 -7
  128. package/dist/providers/litellm.js +41 -29
  129. package/dist/providers/mistral.js +2 -1
  130. package/dist/providers/ollama.js +80 -23
  131. package/dist/providers/openAI.js +3 -2
  132. package/dist/providers/openRouter.js +2 -1
  133. package/dist/providers/openaiCompatible.d.ts +4 -4
  134. package/dist/providers/openaiCompatible.js +4 -3
  135. package/dist/proxy/claudeFormat.d.ts +3 -2
  136. package/dist/proxy/claudeFormat.js +25 -20
  137. package/dist/proxy/cloaking/plugins/sessionIdentity.d.ts +2 -6
  138. package/dist/proxy/cloaking/plugins/sessionIdentity.js +9 -33
  139. package/dist/proxy/modelRouter.js +3 -0
  140. package/dist/proxy/oauthFetch.d.ts +1 -1
  141. package/dist/proxy/oauthFetch.js +65 -72
  142. package/dist/proxy/proxyConfig.js +44 -24
  143. package/dist/proxy/proxyEnv.d.ts +19 -0
  144. package/dist/proxy/proxyEnv.js +72 -0
  145. package/dist/proxy/proxyFetch.js +50 -4
  146. package/dist/proxy/proxyTracer.d.ts +133 -0
  147. package/dist/proxy/proxyTracer.js +644 -0
  148. package/dist/proxy/rawStreamCapture.d.ts +10 -0
  149. package/dist/proxy/rawStreamCapture.js +82 -0
  150. package/dist/proxy/requestLogger.d.ts +32 -5
  151. package/dist/proxy/requestLogger.js +406 -37
  152. package/dist/proxy/sseInterceptor.d.ts +97 -0
  153. package/dist/proxy/sseInterceptor.js +401 -0
  154. package/dist/proxy/usageStats.d.ts +4 -3
  155. package/dist/proxy/usageStats.js +25 -12
  156. package/dist/rag/chunkers/MarkdownChunker.js +13 -5
  157. package/dist/rag/chunking/markdownChunker.js +15 -6
  158. package/dist/server/routes/claudeProxyRoutes.d.ts +7 -2
  159. package/dist/server/routes/claudeProxyRoutes.js +1737 -508
  160. package/dist/services/server/ai/observability/instrumentation.d.ts +7 -1
  161. package/dist/services/server/ai/observability/instrumentation.js +240 -40
  162. package/dist/tasks/backends/bullmqBackend.d.ts +1 -0
  163. package/dist/tasks/backends/bullmqBackend.js +14 -7
  164. package/dist/tasks/store/redisTaskStore.d.ts +1 -0
  165. package/dist/tasks/store/redisTaskStore.js +34 -26
  166. package/dist/tasks/taskManager.d.ts +3 -0
  167. package/dist/tasks/taskManager.js +63 -30
  168. package/dist/telemetry/index.d.ts +2 -1
  169. package/dist/telemetry/index.js +2 -1
  170. package/dist/telemetry/telemetryService.d.ts +3 -0
  171. package/dist/telemetry/telemetryService.js +65 -5
  172. package/dist/types/cli.d.ts +10 -0
  173. package/dist/types/proxyTypes.d.ts +37 -5
  174. package/dist/types/streamTypes.d.ts +25 -3
  175. package/dist/utils/messageBuilder.js +3 -2
  176. package/dist/utils/providerHealth.d.ts +18 -0
  177. package/dist/utils/providerHealth.js +240 -9
  178. package/dist/utils/providerUtils.js +14 -8
  179. package/dist/utils/toolChoice.d.ts +4 -0
  180. package/dist/utils/toolChoice.js +6 -0
  181. package/docs/assets/dashboards/neurolink-proxy-observability-dashboard.json +6609 -0
  182. package/docs/changelog.md +252 -0
  183. package/package.json +17 -1
  184. package/scripts/observability/check-proxy-telemetry.mjs +235 -0
  185. package/scripts/observability/docker-compose.proxy-observability.yaml +55 -0
  186. package/scripts/observability/import-openobserve-dashboard.mjs +240 -0
  187. package/scripts/observability/manage-local-openobserve.sh +184 -0
  188. package/scripts/observability/otel-collector.proxy-observability.yaml +78 -0
  189. package/scripts/observability/proxy-observability.env.example +23 -0
@@ -2,7 +2,7 @@
2
2
  * OpenTelemetry Bridge
3
3
  * Bidirectional context propagation between NeuroLink and OpenTelemetry
4
4
  */
5
- import { type SpanContext } from "@opentelemetry/api";
5
+ import { type Context, type SpanContext } from "@opentelemetry/api";
6
6
  import type { SpanData } from "./types/spanTypes.js";
7
7
  import { type SpanType } from "./types/spanTypes.js";
8
8
  /**
@@ -18,7 +18,7 @@ export declare class OtelBridge {
18
18
  /**
19
19
  * Inject trace context into outgoing request headers
20
20
  */
21
- injectContext(headers: Record<string, string>): Record<string, string>;
21
+ injectContext(headers: Record<string, string>, otelContext?: Context): Record<string, string>;
22
22
  /**
23
23
  * Create a NeuroLink span from OpenTelemetry context
24
24
  */
@@ -15,15 +15,24 @@ export class OtelBridge {
15
15
  * Extract trace context from incoming request headers
16
16
  */
17
17
  extractContext(headers) {
18
- const extractedContext = propagation.extract(context.active(), headers);
18
+ // Normalize traceparent: OTel HTTP auto-instrumentation may inject a second traceparent
19
+ // on top of the SDK's manually injected one, producing "val1, val2". The W3C spec rejects
20
+ // multiple values, causing extraction to silently return null. Take the first value only.
21
+ const normalizedHeaders = { ...headers };
22
+ if (typeof normalizedHeaders["traceparent"] === "string" &&
23
+ normalizedHeaders["traceparent"].includes(", ")) {
24
+ normalizedHeaders["traceparent"] =
25
+ normalizedHeaders["traceparent"].split(", ")[0];
26
+ }
27
+ const extractedContext = propagation.extract(context.active(), normalizedHeaders);
19
28
  const spanContext = trace.getSpanContext(extractedContext);
20
29
  return spanContext ?? null;
21
30
  }
22
31
  /**
23
32
  * Inject trace context into outgoing request headers
24
33
  */
25
- injectContext(headers) {
26
- propagation.inject(context.active(), headers);
34
+ injectContext(headers, otelContext = context.active()) {
35
+ propagation.inject(otelContext, headers);
27
36
  return headers;
28
37
  }
29
38
  /**
@@ -1002,8 +1002,7 @@ export class AmazonBedrockProvider extends BaseProvider {
1002
1002
  });
1003
1003
  if (firstStopReason === "tool_use") {
1004
1004
  const toolNames = firstMessageContent
1005
- .filter((b) => b.toolUse?.name)
1006
- .map((b) => b.toolUse.name)
1005
+ .flatMap((b) => (b.toolUse?.name ? [b.toolUse.name] : []))
1007
1006
  .join(", ");
1008
1007
  streamSpan.addEvent("stream.tool_use", {
1009
1008
  iteration: 0,
@@ -1029,8 +1028,7 @@ export class AmazonBedrockProvider extends BaseProvider {
1029
1028
  });
1030
1029
  if (stopReason === "tool_use") {
1031
1030
  const toolNames = assistantMessage.content
1032
- .filter((b) => b.toolUse?.name)
1033
- .map((b) => b.toolUse.name)
1031
+ .flatMap((b) => (b.toolUse?.name ? [b.toolUse.name] : []))
1034
1032
  .join(", ");
1035
1033
  streamSpan.addEvent("stream.tool_use", {
1036
1034
  iteration,
@@ -1,17 +1,21 @@
1
1
  import { type LanguageModel } from "ai";
2
2
  import { type AIProviderName } from "../constants/enums.js";
3
3
  import { BaseProvider } from "../core/baseProvider.js";
4
- import type { TextGenerationOptions, EnhancedGenerateResult } from "../types/generateTypes.js";
4
+ import type { EnhancedGenerateResult, TextGenerationOptions } from "../types/generateTypes.js";
5
+ import type { AnthropicProviderConfig } from "../types/providers.js";
5
6
  import type { StreamOptions, StreamResult } from "../types/streamTypes.js";
7
+ import type { AnthropicAuthMethod, AnthropicResponseMetadata, ClaudeSubscriptionTier, ClaudeUsageInfo } from "../types/subscriptionTypes.js";
6
8
  import type { ValidationSchema } from "../types/typeAliases.js";
7
- import type { ClaudeSubscriptionTier, AnthropicAuthMethod, AnthropicResponseMetadata, ClaudeUsageInfo } from "../types/subscriptionTypes.js";
8
- import type { AnthropicProviderConfig } from "../types/providers.js";
9
9
  /**
10
10
  * Beta headers for Claude Code integration.
11
11
  * These enable experimental features:
12
12
  * - claude-code-20250219: Claude Code specific features
13
- * - interleaved-thinking-2025-05-14: Interleaved thinking mode
14
13
  * - fine-grained-tool-streaming-2025-05-14: Fine-grained tool streaming
14
+ *
15
+ * Note: interleaved-thinking-2025-05-14 was removed — it was claude-3-7-sonnet
16
+ * specific and causes invalid_request_error (HTTP 400) on claude-4 models
17
+ * (claude-opus-4-6, claude-sonnet-4-6) which handle thinking via the
18
+ * `thinking` request body parameter instead.
15
19
  */
16
20
  declare const ANTHROPIC_BETA_HEADERS: {
17
21
  "anthropic-beta": string;
@@ -140,6 +144,6 @@ export declare class AnthropicProvider extends BaseProvider {
140
144
  isAvailable(): Promise<boolean>;
141
145
  getModel(): LanguageModel;
142
146
  }
143
- export { ModelAccessError, isModelAvailableForTier, getRecommendedModelForTier, getModelCapabilities, } from "../models/anthropicModels.js";
147
+ export { getModelCapabilities, getRecommendedModelForTier, isModelAvailableForTier, ModelAccessError, } from "../models/anthropicModels.js";
144
148
  export { ANTHROPIC_BETA_HEADERS };
145
149
  export default AnthropicProvider;
@@ -1,34 +1,37 @@
1
1
  import { createAnthropic } from "@ai-sdk/anthropic";
2
+ import { SpanKind, SpanStatusCode, trace } from "@opentelemetry/api";
2
3
  import { stepCountIs, streamText } from "ai";
3
- import { trace, SpanKind, SpanStatusCode } from "@opentelemetry/api";
4
- import { AnthropicModels } from "../constants/enums.js";
4
+ import { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync, } from "fs";
5
+ import { homedir } from "os";
6
+ import { join } from "path";
7
+ import { ANTHROPIC_TOKEN_URL, CLAUDE_CLI_USER_AGENT, CLAUDE_CODE_CLIENT_ID, } from "../auth/anthropicOAuth.js";
8
+ import { AnthropicModels, TOKEN_EXPIRY_BUFFER_MS, } from "../constants/enums.js";
5
9
  import { BaseProvider } from "../core/baseProvider.js";
6
10
  import { DEFAULT_MAX_STEPS } from "../core/constants.js";
11
+ import { getModelCapabilities, getRecommendedModelForTier, isModelAvailableForTier, } from "../models/anthropicModels.js";
12
+ import { createOAuthFetch } from "../proxy/oauthFetch.js";
7
13
  import { createProxyFetch } from "../proxy/proxyFetch.js";
8
14
  import { AuthenticationError, NetworkError, ProviderError, RateLimitError, } from "../types/errors.js";
9
15
  import { logger } from "../utils/logger.js";
10
16
  import { calculateCost } from "../utils/pricing.js";
11
17
  import { createAnthropicConfig, getProviderModel, validateApiKey, } from "../utils/providerConfig.js";
12
18
  import { composeAbortSignals, createTimeoutController, TimeoutError, } from "../utils/timeout.js";
13
- import { isModelAvailableForTier, getRecommendedModelForTier, getModelCapabilities, } from "../models/anthropicModels.js";
14
- import { CLAUDE_CLI_USER_AGENT, CLAUDE_CODE_CLIENT_ID, ANTHROPIC_TOKEN_URL, } from "../auth/anthropicOAuth.js";
15
- import { createOAuthFetch } from "../proxy/oauthFetch.js";
16
- import { homedir } from "os";
17
- import { readFileSync, existsSync, writeFileSync, mkdirSync, renameSync, } from "fs";
18
- import { join } from "path";
19
- import { TOKEN_EXPIRY_BUFFER_MS } from "../constants/enums.js";
19
+ import { resolveToolChoice } from "../utils/toolChoice.js";
20
20
  import { getModelId } from "./providerTypeUtils.js";
21
21
  /**
22
22
  * Beta headers for Claude Code integration.
23
23
  * These enable experimental features:
24
24
  * - claude-code-20250219: Claude Code specific features
25
- * - interleaved-thinking-2025-05-14: Interleaved thinking mode
26
25
  * - fine-grained-tool-streaming-2025-05-14: Fine-grained tool streaming
26
+ *
27
+ * Note: interleaved-thinking-2025-05-14 was removed — it was claude-3-7-sonnet
28
+ * specific and causes invalid_request_error (HTTP 400) on claude-4 models
29
+ * (claude-opus-4-6, claude-sonnet-4-6) which handle thinking via the
30
+ * `thinking` request body parameter instead.
27
31
  */
28
32
  const ANTHROPIC_BETA_HEADERS = {
29
33
  "anthropic-beta": [
30
34
  "claude-code-20250219",
31
- "interleaved-thinking-2025-05-14",
32
35
  "fine-grained-tool-streaming-2025-05-14",
33
36
  ].join(","),
34
37
  };
@@ -155,7 +158,9 @@ const detectAuthMethod = (oauthToken) => {
155
158
  logger.warn("[detectAuthMethod] ANTHROPIC_AUTH_METHOD=oauth but no OAuth token found; falling through to auto-detection");
156
159
  }
157
160
  else if (explicit) {
158
- logger.warn("[detectAuthMethod] Unrecognized ANTHROPIC_AUTH_METHOD value; falling through to auto-detection", { value: explicit });
161
+ logger.warn("[detectAuthMethod] Unrecognized ANTHROPIC_AUTH_METHOD value; falling through to auto-detection", {
162
+ value: explicit,
163
+ });
159
164
  }
160
165
  // Auto-detect: OAuth takes precedence if available
161
166
  const method = oauthToken ? "oauth" : "api_key";
@@ -762,7 +767,7 @@ export class AnthropicProvider extends BaseProvider {
762
767
  maxRetries: 0, // NL11: Disable AI SDK's invisible internal retries; we handle retries with OTel instrumentation
763
768
  tools,
764
769
  stopWhen: stepCountIs(options.maxSteps || DEFAULT_MAX_STEPS),
765
- toolChoice: shouldUseTools ? "auto" : "none",
770
+ toolChoice: resolveToolChoice(options, tools, shouldUseTools),
766
771
  abortSignal: composeAbortSignals(options.abortSignal, timeoutController?.controller.signal),
767
772
  experimental_telemetry: this.telemetryHandler.getTelemetryConfig(options),
768
773
  onStepFinish: ({ toolCalls, toolResults }) => {
@@ -857,7 +862,7 @@ export class AnthropicProvider extends BaseProvider {
857
862
  }
858
863
  }
859
864
  // Re-export types and utilities for convenience
860
- export { ModelAccessError, isModelAvailableForTier, getRecommendedModelForTier, getModelCapabilities, } from "../models/anthropicModels.js";
865
+ export { getModelCapabilities, getRecommendedModelForTier, isModelAvailableForTier, ModelAccessError, } from "../models/anthropicModels.js";
861
866
  // Export beta headers constant for external use
862
867
  export { ANTHROPIC_BETA_HEADERS };
863
868
  export default AnthropicProvider;
@@ -1,8 +1,8 @@
1
- import type { ZodType } from "zod";
2
1
  import { type LanguageModel, type Schema } from "ai";
3
- import { AIProviderName } from "../constants/enums.js";
4
- import type { StreamOptions, StreamResult } from "../types/streamTypes.js";
2
+ import type { ZodType } from "zod";
3
+ import { type AIProviderName } from "../constants/enums.js";
5
4
  import { BaseProvider } from "../core/baseProvider.js";
5
+ import type { StreamOptions, StreamResult } from "../types/streamTypes.js";
6
6
  /**
7
7
  * Anthropic provider implementation using BaseProvider pattern
8
8
  * Migrated from direct API calls to Vercel AI SDK (@ai-sdk/anthropic)
@@ -1,13 +1,14 @@
1
1
  import { createAnthropic } from "@ai-sdk/anthropic";
2
+ import { SpanKind, SpanStatusCode, trace } from "@opentelemetry/api";
2
3
  import { NoOutputGeneratedError, streamText, } from "ai";
3
- import { trace, SpanKind, SpanStatusCode } from "@opentelemetry/api";
4
- import { AIProviderName, AnthropicModels } from "../constants/enums.js";
4
+ import { AnthropicModels } from "../constants/enums.js";
5
5
  import { BaseProvider } from "../core/baseProvider.js";
6
6
  import { AuthenticationError, NetworkError, ProviderError, RateLimitError, } from "../types/errors.js";
7
7
  import { logger } from "../utils/logger.js";
8
8
  import { calculateCost } from "../utils/pricing.js";
9
+ import { createAnthropicBaseConfig, validateApiKey, } from "../utils/providerConfig.js";
9
10
  import { composeAbortSignals, createTimeoutController, TimeoutError, } from "../utils/timeout.js";
10
- import { validateApiKey, createAnthropicBaseConfig, } from "../utils/providerConfig.js";
11
+ import { resolveToolChoice } from "../utils/toolChoice.js";
11
12
  import { getModelId } from "./providerTypeUtils.js";
12
13
  const streamTracer = trace.getTracer("neurolink.provider.anthropic");
13
14
  /**
@@ -90,7 +91,7 @@ export class AnthropicProviderV2 extends BaseProvider {
90
91
  maxOutputTokens: options.maxTokens, // No default limit - unlimited unless specified
91
92
  maxRetries: 0, // NL11: Disable AI SDK's invisible internal retries; we handle retries with OTel instrumentation
92
93
  tools,
93
- toolChoice: shouldUseTools ? "auto" : "none",
94
+ toolChoice: resolveToolChoice(options, tools, shouldUseTools),
94
95
  abortSignal: composeAbortSignals(options.abortSignal, timeoutController?.controller.signal),
95
96
  experimental_telemetry: this.telemetryHandler.getTelemetryConfig(options),
96
97
  onStepFinish: ({ toolCalls, toolResults }) => {
@@ -1,6 +1,6 @@
1
1
  import { type LanguageModel } from "ai";
2
+ import { type AIProviderName } from "../constants/enums.js";
2
3
  import { BaseProvider } from "../core/baseProvider.js";
3
- import { AIProviderName } from "../constants/enums.js";
4
4
  import type { StreamOptions, StreamResult } from "../types/streamTypes.js";
5
5
  export declare class AzureOpenAIProvider extends BaseProvider {
6
6
  private apiKey;
@@ -1,12 +1,13 @@
1
1
  import { createAzure } from "@ai-sdk/azure";
2
2
  import { stepCountIs, streamText } from "ai";
3
+ import { APIVersions } from "../constants/enums.js";
3
4
  import { BaseProvider } from "../core/baseProvider.js";
4
- import { AIProviderName, APIVersions } from "../constants/enums.js";
5
- import { validateApiKey, createAzureAPIKeyConfig, createAzureEndpointConfig, } from "../utils/providerConfig.js";
6
5
  import { DEFAULT_MAX_STEPS } from "../core/constants.js";
7
- import { logger } from "../utils/logger.js";
8
6
  import { createProxyFetch } from "../proxy/proxyFetch.js";
7
+ import { logger } from "../utils/logger.js";
8
+ import { createAzureAPIKeyConfig, createAzureEndpointConfig, validateApiKey, } from "../utils/providerConfig.js";
9
9
  import { composeAbortSignals, createTimeoutController, TimeoutError, } from "../utils/timeout.js";
10
+ import { resolveToolChoice } from "../utils/toolChoice.js";
10
11
  export class AzureOpenAIProvider extends BaseProvider {
11
12
  apiKey;
12
13
  resourceName;
@@ -108,7 +109,7 @@ export class AzureOpenAIProvider extends BaseProvider {
108
109
  ? { temperature: options.temperature }
109
110
  : {}),
110
111
  tools,
111
- toolChoice: shouldUseTools ? "auto" : "none",
112
+ toolChoice: resolveToolChoice(options, tools, shouldUseTools),
112
113
  stopWhen: stepCountIs(options.maxSteps || DEFAULT_MAX_STEPS),
113
114
  abortSignal: composeAbortSignals(options.abortSignal, timeoutController?.controller.signal),
114
115
  experimental_telemetry: this.telemetryHandler.getTelemetryConfig(options),
@@ -11,6 +11,7 @@ import { logger } from "../utils/logger.js";
11
11
  import { isGemini3Model } from "../utils/modelDetection.js";
12
12
  import { composeAbortSignals, createTimeoutController, TimeoutError, } from "../utils/timeout.js";
13
13
  import { estimateTokens } from "../utils/tokenEstimation.js";
14
+ import { resolveToolChoice } from "../utils/toolChoice.js";
14
15
  import { buildNativeConfig, buildNativeToolDeclarations, collectStreamChunks, collectStreamChunksIncremental, computeMaxSteps, createTextChannel, executeNativeToolCalls, extractTextFromParts, handleMaxStepsTermination, pushModelResponseToHistory, sanitizeToolsForGemini, } from "./googleNativeGemini3.js";
15
16
  import { toAnalyticsStreamResult } from "./providerTypeUtils.js";
16
17
  // Google AI Live API types now imported from ../types/providerSpecific.js
@@ -473,6 +474,8 @@ export class GoogleAIStudioProvider extends BaseProvider {
473
474
  // Build message array from options with multimodal support
474
475
  // Using protected helper from BaseProvider to eliminate code duplication
475
476
  const messages = await this.buildMessagesForStream(options);
477
+ const collectedToolCalls = [];
478
+ const collectedToolResults = [];
476
479
  const result = await streamText({
477
480
  model,
478
481
  messages: messages,
@@ -480,7 +483,7 @@ export class GoogleAIStudioProvider extends BaseProvider {
480
483
  maxOutputTokens: options.maxTokens, // No default limit - unlimited unless specified
481
484
  tools,
482
485
  stopWhen: stepCountIs(options.maxSteps || DEFAULT_MAX_STEPS),
483
- toolChoice: shouldUseTools ? "auto" : "none",
486
+ toolChoice: resolveToolChoice(options, tools, shouldUseTools),
484
487
  abortSignal: composeAbortSignals(options.abortSignal, timeoutController?.controller.signal),
485
488
  experimental_telemetry: this.telemetryHandler.getTelemetryConfig(options),
486
489
  // Gemini 3: use thinkingLevel via providerOptions
@@ -502,6 +505,28 @@ export class GoogleAIStudioProvider extends BaseProvider {
502
505
  },
503
506
  }),
504
507
  onStepFinish: ({ toolCalls, toolResults }) => {
508
+ for (const toolCall of toolCalls) {
509
+ collectedToolCalls.push({
510
+ toolCallId: toolCall.toolCallId,
511
+ toolName: toolCall.toolName,
512
+ args: toolCall.args ??
513
+ toolCall.input ??
514
+ toolCall
515
+ .parameters ??
516
+ {},
517
+ });
518
+ }
519
+ for (const toolResult of toolResults) {
520
+ const rawToolResult = toolResult;
521
+ collectedToolResults.push({
522
+ toolName: toolResult.toolName,
523
+ status: rawToolResult.error ? "failure" : "success",
524
+ output: (rawToolResult.output ??
525
+ rawToolResult.result) ?? undefined,
526
+ error: rawToolResult.error,
527
+ id: rawToolResult.toolCallId ?? toolResult.toolName,
528
+ });
529
+ }
505
530
  this.handleToolExecutionStorage(toolCalls, toolResults, options, new Date()).catch((error) => {
506
531
  logger.warn("[GoogleAiStudioProvider] Failed to store tool executions", {
507
532
  provider: this.providerName,
@@ -530,6 +555,10 @@ export class GoogleAIStudioProvider extends BaseProvider {
530
555
  stream: transformedStream,
531
556
  provider: this.providerName,
532
557
  model: this.modelName,
558
+ ...(shouldUseTools && {
559
+ toolCalls: collectedToolCalls,
560
+ toolResults: collectedToolResults,
561
+ }),
533
562
  analytics: analyticsPromise,
534
563
  metadata: {
535
564
  startTime,
@@ -22,6 +22,7 @@ import { createGoogleAuthConfig, createVertexProjectConfig, validateApiKey, } fr
22
22
  import { convertZodToJsonSchema, inlineJsonSchema, } from "../utils/schemaConversion.js";
23
23
  import { composeAbortSignals, createTimeoutController, TimeoutError, } from "../utils/timeout.js";
24
24
  import { estimateTokens } from "../utils/tokenEstimation.js";
25
+ import { resolveToolChoice } from "../utils/toolChoice.js";
25
26
  import { buildNativeConfig, buildNativeToolDeclarations, collectStreamChunks, collectStreamChunksIncremental, computeMaxSteps as computeMaxStepsShared, createTextChannel, executeNativeToolCalls, extractTextFromParts, handleMaxStepsTermination, pushModelResponseToHistory, sanitizeToolsForGemini, } from "./googleNativeGemini3.js";
26
27
  import { getModelId } from "./providerTypeUtils.js";
27
28
  // Import proper types for multimodal message handling
@@ -856,6 +857,8 @@ export class GoogleVertexProvider extends BaseProvider {
856
857
  const maxTokens = shouldSetMaxTokens
857
858
  ? options.maxTokens // No default limit
858
859
  : undefined;
860
+ const collectedToolCalls = [];
861
+ const collectedToolResults = [];
859
862
  // Build complete stream options with proper typing
860
863
  let streamOptions = {
861
864
  model: model,
@@ -867,7 +870,7 @@ export class GoogleVertexProvider extends BaseProvider {
867
870
  tools &&
868
871
  Object.keys(tools).length > 0 && {
869
872
  tools,
870
- toolChoice: "auto",
873
+ toolChoice: resolveToolChoice(options, tools, shouldUseTools),
871
874
  stopWhen: stepCountIs(options.maxSteps || DEFAULT_MAX_STEPS),
872
875
  }),
873
876
  abortSignal: composeAbortSignals(options.abortSignal, timeoutController?.controller.signal),
@@ -911,6 +914,28 @@ export class GoogleVertexProvider extends BaseProvider {
911
914
  },
912
915
  onStepFinish: ({ toolCalls, toolResults }) => {
913
916
  logger.info("Tool execution completed", { toolResults, toolCalls });
917
+ for (const toolCall of toolCalls) {
918
+ collectedToolCalls.push({
919
+ toolCallId: toolCall.toolCallId,
920
+ toolName: toolCall.toolName,
921
+ args: toolCall.args ??
922
+ toolCall.input ??
923
+ toolCall
924
+ .parameters ??
925
+ {},
926
+ });
927
+ }
928
+ for (const toolResult of toolResults) {
929
+ const rawToolResult = toolResult;
930
+ collectedToolResults.push({
931
+ toolName: toolResult.toolName,
932
+ status: rawToolResult.error ? "failure" : "success",
933
+ output: (rawToolResult.output ??
934
+ rawToolResult.result) ?? undefined,
935
+ error: rawToolResult.error,
936
+ id: rawToolResult.toolCallId ?? toolResult.toolName,
937
+ });
938
+ }
914
939
  // Handle tool execution storage
915
940
  this.handleToolExecutionStorage(toolCalls, toolResults, options, new Date()).catch((error) => {
916
941
  logger.warn("[GoogleVertexProvider] Failed to store tool executions", {
@@ -1011,16 +1036,13 @@ export class GoogleVertexProvider extends BaseProvider {
1011
1036
  .finally(() => timeoutController?.cleanup());
1012
1037
  // Transform string stream to content object stream using BaseProvider method
1013
1038
  const transformedStream = this.createTextStream(result);
1014
- // Track tool calls and results for streaming
1015
- const toolCalls = [];
1016
- const toolResults = [];
1017
1039
  return {
1018
1040
  stream: transformedStream,
1019
1041
  provider: this.providerName,
1020
1042
  model: this.modelName,
1021
1043
  ...(shouldUseTools && {
1022
- toolCalls,
1023
- toolResults,
1044
+ toolCalls: collectedToolCalls,
1045
+ toolResults: collectedToolResults,
1024
1046
  }),
1025
1047
  };
1026
1048
  }
@@ -1,8 +1,8 @@
1
+ import { type LanguageModel, type Schema } from "ai";
1
2
  import type { ZodType } from "zod";
2
- import { type Schema, type LanguageModel } from "ai";
3
- import { AIProviderName } from "../constants/enums.js";
4
- import type { StreamOptions, StreamResult } from "../types/streamTypes.js";
3
+ import type { AIProviderName } from "../constants/enums.js";
5
4
  import { BaseProvider } from "../core/baseProvider.js";
5
+ import type { StreamOptions, StreamResult } from "../types/streamTypes.js";
6
6
  /**
7
7
  * HuggingFace Provider - BaseProvider Implementation
8
8
  * Using AI SDK with HuggingFace's OpenAI-compatible endpoint
@@ -1,12 +1,12 @@
1
1
  import { createOpenAI } from "@ai-sdk/openai";
2
2
  import { NoOutputGeneratedError, stepCountIs, streamText, } from "ai";
3
- import { AIProviderName } from "../constants/enums.js";
4
3
  import { BaseProvider } from "../core/baseProvider.js";
5
- import { logger } from "../utils/logger.js";
6
- import { composeAbortSignals, createTimeoutController, TimeoutError, } from "../utils/timeout.js";
7
4
  import { DEFAULT_MAX_STEPS } from "../core/constants.js";
8
- import { validateApiKey, createHuggingFaceConfig, getProviderModel, } from "../utils/providerConfig.js";
9
5
  import { createProxyFetch } from "../proxy/proxyFetch.js";
6
+ import { logger } from "../utils/logger.js";
7
+ import { createHuggingFaceConfig, getProviderModel, validateApiKey, } from "../utils/providerConfig.js";
8
+ import { composeAbortSignals, createTimeoutController, TimeoutError, } from "../utils/timeout.js";
9
+ import { resolveToolChoice } from "../utils/toolChoice.js";
10
10
  // Configuration helpers - now using consolidated utility
11
11
  const getHuggingFaceApiKey = () => {
12
12
  return validateApiKey(createHuggingFaceConfig());
@@ -136,9 +136,7 @@ export class HuggingFaceProvider extends BaseProvider {
136
136
  tools: (shouldUseTools
137
137
  ? streamOptions.tools || allTools
138
138
  : {}),
139
- toolChoice: (shouldUseTools
140
- ? streamOptions.toolChoice || "auto"
141
- : "none"),
139
+ toolChoice: resolveToolChoice(options, (shouldUseTools ? streamOptions.tools || allTools : {}), shouldUseTools),
142
140
  abortSignal: composeAbortSignals(options.abortSignal, timeoutController?.controller.signal),
143
141
  experimental_telemetry: this.telemetryHandler.getTelemetryConfig(options),
144
142
  onStepFinish: ({ toolCalls, toolResults }) => {
@@ -203,7 +201,7 @@ export class HuggingFaceProvider extends BaseProvider {
203
201
  prompt: options.input.text,
204
202
  system: enhancedSystemPrompt,
205
203
  tools: formattedTools,
206
- toolChoice: formattedTools ? "auto" : undefined,
204
+ toolChoice: formattedTools ? (options.toolChoice ?? "auto") : undefined,
207
205
  };
208
206
  }
209
207
  /**
@@ -1,6 +1,6 @@
1
1
  import { createOpenAI } from "@ai-sdk/openai";
2
2
  import { SpanKind, SpanStatusCode, trace } from "@opentelemetry/api";
3
- import { NoOutputGeneratedError, Output, streamText, } from "ai";
3
+ import { NoOutputGeneratedError, Output, streamText } from "ai";
4
4
  import { BaseProvider } from "../core/baseProvider.js";
5
5
  import { DEFAULT_MAX_STEPS } from "../core/constants.js";
6
6
  import { streamAnalyticsCollector } from "../core/streamAnalytics.js";
@@ -10,7 +10,8 @@ import { isAbortError } from "../utils/errorHandling.js";
10
10
  import { logger } from "../utils/logger.js";
11
11
  import { calculateCost } from "../utils/pricing.js";
12
12
  import { getProviderModel } from "../utils/providerConfig.js";
13
- import { composeAbortSignals, createTimeoutController, TimeoutError, } from "../utils/timeout.js";
13
+ import { composeAbortSignals, createTimeoutController, TimeoutError } from "../utils/timeout.js";
14
+ import { resolveToolChoice } from "../utils/toolChoice.js";
14
15
  import { getModelId } from "./providerTypeUtils.js";
15
16
  const streamTracer = trace.getTracer("neurolink.provider.litellm");
16
17
  // Configuration helpers
@@ -59,7 +60,7 @@ export class LiteLLMProvider extends BaseProvider {
59
60
  apiKey: config.apiKey,
60
61
  fetch: createProxyFetch(),
61
62
  });
62
- this.model = customOpenAI(this.modelName || getDefaultLiteLLMModel());
63
+ this.model = customOpenAI.chat(this.modelName || getDefaultLiteLLMModel());
63
64
  logger.debug("LiteLLM Provider initialized", {
64
65
  modelName: this.modelName,
65
66
  provider: this.providerName,
@@ -85,18 +86,15 @@ export class LiteLLMProvider extends BaseProvider {
85
86
  // Check for timeout by error name and message as fallback
86
87
  const errorRecord = error;
87
88
  if (errorRecord?.name === "TimeoutError" ||
88
- (typeof errorRecord?.message === "string" &&
89
- errorRecord.message.toLowerCase().includes("timeout"))) {
89
+ (typeof errorRecord?.message === "string" && errorRecord.message.toLowerCase().includes("timeout"))) {
90
90
  return new NetworkError(`Request timed out: ${errorRecord?.message || "Unknown timeout"}`, this.providerName);
91
91
  }
92
92
  if (typeof errorRecord?.message === "string") {
93
- if (errorRecord.message.includes("ECONNREFUSED") ||
94
- errorRecord.message.includes("Failed to fetch")) {
93
+ if (errorRecord.message.includes("ECONNREFUSED") || errorRecord.message.includes("Failed to fetch")) {
95
94
  return new NetworkError("LiteLLM proxy server not available. Please start the LiteLLM proxy server at " +
96
95
  `${process.env.LITELLM_BASE_URL || "http://localhost:4000"}`, this.providerName);
97
96
  }
98
- if (errorRecord.message.includes("API_KEY_INVALID") ||
99
- errorRecord.message.includes("Invalid API key")) {
97
+ if (errorRecord.message.includes("API_KEY_INVALID") || errorRecord.message.includes("Invalid API key")) {
100
98
  return new AuthenticationError("Invalid LiteLLM configuration. Please check your LITELLM_API_KEY environment variable.", this.providerName);
101
99
  }
102
100
  if (errorRecord.message.toLowerCase().includes("rate limit")) {
@@ -133,9 +131,7 @@ export class LiteLLMProvider extends BaseProvider {
133
131
  const model = await this.getAISDKModelWithMiddleware(options); // This is where network connection happens!
134
132
  // Get tools - options.tools is pre-merged by BaseProvider.stream()
135
133
  const shouldUseTools = !options.disableTools && this.supportsTools();
136
- const tools = shouldUseTools
137
- ? options.tools || (await this.getAllTools())
138
- : {};
134
+ const tools = shouldUseTools ? options.tools || (await this.getAllTools()) : {};
139
135
  logger.debug(`LiteLLM: Tools for streaming`, {
140
136
  shouldUseTools,
141
137
  toolCount: Object.keys(tools).length,
@@ -160,7 +156,7 @@ export class LiteLLMProvider extends BaseProvider {
160
156
  ...(shouldUseTools &&
161
157
  Object.keys(tools).length > 0 && {
162
158
  tools,
163
- toolChoice: "auto",
159
+ toolChoice: resolveToolChoice(options, tools, shouldUseTools),
164
160
  maxSteps: options.maxSteps || DEFAULT_MAX_STEPS,
165
161
  }),
166
162
  abortSignal: composeAbortSignals(options.abortSignal, timeoutController?.controller.signal),
@@ -186,6 +182,26 @@ export class LiteLLMProvider extends BaseProvider {
186
182
  },
187
183
  onStepFinish: ({ toolCalls, toolResults }) => {
188
184
  logger.info("Tool execution completed", { toolResults, toolCalls });
185
+ for (const toolCall of toolCalls) {
186
+ collectedToolCalls.push({
187
+ toolCallId: toolCall.toolCallId,
188
+ toolName: toolCall.toolName,
189
+ args: toolCall.args ??
190
+ toolCall.input ??
191
+ toolCall.parameters ??
192
+ {},
193
+ });
194
+ }
195
+ for (const toolResult of toolResults) {
196
+ const rawToolResult = toolResult;
197
+ collectedToolResults.push({
198
+ toolName: toolResult.toolName,
199
+ status: rawToolResult.error ? "failure" : "success",
200
+ output: (rawToolResult.output ?? rawToolResult.result) ?? undefined,
201
+ error: rawToolResult.error,
202
+ id: rawToolResult.toolCallId ?? toolResult.toolName,
203
+ });
204
+ }
189
205
  this.handleToolExecutionStorage(toolCalls, toolResults, options, new Date()).catch((error) => {
190
206
  logger.warn("[LiteLLMProvider] Failed to store tool executions", {
191
207
  provider: this.providerName,
@@ -219,15 +235,15 @@ export class LiteLLMProvider extends BaseProvider {
219
235
  },
220
236
  });
221
237
  let result;
238
+ const collectedToolCalls = [];
239
+ const collectedToolResults = [];
222
240
  try {
223
241
  result = streamText(streamOptions);
224
242
  }
225
243
  catch (streamError) {
226
244
  streamSpan.setStatus({
227
245
  code: SpanStatusCode.ERROR,
228
- message: streamError instanceof Error
229
- ? streamError.message
230
- : String(streamError),
246
+ message: streamError instanceof Error ? streamError.message : String(streamError),
231
247
  });
232
248
  streamSpan.end();
233
249
  throw streamError;
@@ -294,9 +310,7 @@ export class LiteLLMProvider extends BaseProvider {
294
310
  yield { content: textDelta };
295
311
  }
296
312
  }
297
- else if ("type" in chunk &&
298
- chunk.type === "tool-call" &&
299
- "toolCallId" in chunk) {
313
+ else if ("type" in chunk && chunk.type === "tool-call" && "toolCallId" in chunk) {
300
314
  // Tool call event - log for debugging
301
315
  const toolCallId = String(chunk.toolCallId);
302
316
  const toolName = "toolName" in chunk ? String(chunk.toolName) : "unknown";
@@ -323,14 +337,17 @@ export class LiteLLMProvider extends BaseProvider {
323
337
  })();
324
338
  // Create analytics promise that resolves after stream completion
325
339
  const analyticsPromise = streamAnalyticsCollector.createAnalytics(this.providerName, this.modelName, result, Date.now() - startTime, {
326
- requestId: options.requestId ??
327
- `litellm-stream-${Date.now()}`,
340
+ requestId: options.requestId ?? `litellm-stream-${Date.now()}`,
328
341
  streamingMode: true,
329
342
  });
330
343
  return {
331
344
  stream: transformedStream,
332
345
  provider: this.providerName,
333
346
  model: this.modelName,
347
+ ...(shouldUseTools && {
348
+ toolCalls: collectedToolCalls,
349
+ toolResults: collectedToolResults,
350
+ }),
334
351
  analytics: analyticsPromise,
335
352
  metadata: {
336
353
  startTime,
@@ -351,9 +368,7 @@ export class LiteLLMProvider extends BaseProvider {
351
368
  const { embed: aiEmbed } = await import("ai");
352
369
  const { createOpenAI } = await import("@ai-sdk/openai");
353
370
  const config = getLiteLLMConfig();
354
- const embeddingModelName = modelName ||
355
- process.env.LITELLM_EMBEDDING_MODEL ||
356
- "gemini-embedding-001";
371
+ const embeddingModelName = modelName || process.env.LITELLM_EMBEDDING_MODEL || "gemini-embedding-001";
357
372
  const customOpenAI = createOpenAI({
358
373
  baseURL: config.baseURL,
359
374
  apiKey: config.apiKey,
@@ -371,9 +386,7 @@ export class LiteLLMProvider extends BaseProvider {
371
386
  const { embedMany: aiEmbedMany } = await import("ai");
372
387
  const { createOpenAI } = await import("@ai-sdk/openai");
373
388
  const config = getLiteLLMConfig();
374
- const embeddingModelName = modelName ||
375
- process.env.LITELLM_EMBEDDING_MODEL ||
376
- "gemini-embedding-001";
389
+ const embeddingModelName = modelName || process.env.LITELLM_EMBEDDING_MODEL || "gemini-embedding-001";
377
390
  const customOpenAI = createOpenAI({
378
391
  baseURL: config.baseURL,
379
392
  apiKey: config.apiKey,
@@ -392,8 +405,7 @@ export class LiteLLMProvider extends BaseProvider {
392
405
  const now = Date.now();
393
406
  // Check if cached models are still valid
394
407
  if (LiteLLMProvider.modelsCache.length > 0 &&
395
- now - LiteLLMProvider.modelsCacheTime <
396
- LiteLLMProvider.MODELS_CACHE_DURATION) {
408
+ now - LiteLLMProvider.modelsCacheTime < LiteLLMProvider.MODELS_CACHE_DURATION) {
397
409
  logger.debug(`[${functionTag}] Using cached models`, {
398
410
  cacheAge: Math.round((now - LiteLLMProvider.modelsCacheTime) / 1000),
399
411
  modelCount: LiteLLMProvider.modelsCache.length,
@@ -7,6 +7,7 @@ import { createProxyFetch } from "../proxy/proxyFetch.js";
7
7
  import { logger } from "../utils/logger.js";
8
8
  import { createMistralConfig, getProviderModel, validateApiKey, } from "../utils/providerConfig.js";
9
9
  import { composeAbortSignals, createTimeoutController, TimeoutError, } from "../utils/timeout.js";
10
+ import { resolveToolChoice } from "../utils/toolChoice.js";
10
11
  import { toAnalyticsStreamResult } from "./providerTypeUtils.js";
11
12
  // Configuration helpers - now using consolidated utility
12
13
  const getMistralApiKey = () => {
@@ -63,7 +64,7 @@ export class MistralProvider extends BaseProvider {
63
64
  maxOutputTokens: options.maxTokens, // No default limit - unlimited unless specified
64
65
  tools,
65
66
  stopWhen: stepCountIs(options.maxSteps || DEFAULT_MAX_STEPS),
66
- toolChoice: shouldUseTools ? "auto" : "none",
67
+ toolChoice: resolveToolChoice(options, tools, shouldUseTools),
67
68
  abortSignal: composeAbortSignals(options.abortSignal, timeoutController?.controller.signal),
68
69
  experimental_telemetry: this.telemetryHandler.getTelemetryConfig(options),
69
70
  onStepFinish: ({ toolCalls, toolResults }) => {