@juspay/neurolink 9.40.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.
- package/CHANGELOG.md +12 -0
- package/README.md +7 -1
- package/dist/auth/anthropicOAuth.d.ts +18 -3
- package/dist/auth/anthropicOAuth.js +137 -4
- package/dist/auth/providers/firebase.js +5 -1
- package/dist/auth/providers/jwt.js +5 -1
- package/dist/auth/providers/workos.js +5 -1
- package/dist/auth/sessionManager.d.ts +1 -1
- package/dist/auth/sessionManager.js +58 -27
- package/dist/browser/neurolink.min.js +471 -445
- package/dist/cli/commands/mcp.js +3 -0
- package/dist/cli/commands/proxy.d.ts +2 -1
- package/dist/cli/commands/proxy.js +279 -16
- package/dist/cli/commands/task.d.ts +56 -0
- package/dist/cli/commands/task.js +838 -0
- package/dist/cli/factories/commandFactory.d.ts +2 -0
- package/dist/cli/factories/commandFactory.js +38 -0
- package/dist/cli/parser.js +8 -4
- package/dist/client/aiSdkAdapter.js +3 -0
- package/dist/client/streamingClient.js +30 -10
- package/dist/core/modules/GenerationHandler.js +3 -2
- package/dist/core/redisConversationMemoryManager.js +7 -3
- package/dist/evaluation/BatchEvaluator.js +4 -1
- package/dist/evaluation/hooks/observabilityHooks.js +5 -3
- package/dist/evaluation/pipeline/evaluationPipeline.d.ts +3 -2
- package/dist/evaluation/pipeline/evaluationPipeline.js +20 -8
- package/dist/evaluation/pipeline/strategies/batchStrategy.js +6 -3
- package/dist/evaluation/pipeline/strategies/samplingStrategy.js +18 -10
- package/dist/lib/auth/anthropicOAuth.d.ts +18 -3
- package/dist/lib/auth/anthropicOAuth.js +137 -4
- package/dist/lib/auth/providers/firebase.js +5 -1
- package/dist/lib/auth/providers/jwt.js +5 -1
- package/dist/lib/auth/providers/workos.js +5 -1
- package/dist/lib/auth/sessionManager.d.ts +1 -1
- package/dist/lib/auth/sessionManager.js +58 -27
- package/dist/lib/client/aiSdkAdapter.js +3 -0
- package/dist/lib/client/streamingClient.js +30 -10
- package/dist/lib/core/modules/GenerationHandler.js +3 -2
- package/dist/lib/core/redisConversationMemoryManager.js +7 -3
- package/dist/lib/evaluation/BatchEvaluator.js +4 -1
- package/dist/lib/evaluation/hooks/observabilityHooks.js +5 -3
- package/dist/lib/evaluation/pipeline/evaluationPipeline.d.ts +3 -2
- package/dist/lib/evaluation/pipeline/evaluationPipeline.js +20 -8
- package/dist/lib/evaluation/pipeline/strategies/batchStrategy.js +6 -3
- package/dist/lib/evaluation/pipeline/strategies/samplingStrategy.js +18 -10
- package/dist/lib/neurolink.d.ts +18 -1
- package/dist/lib/neurolink.js +367 -484
- package/dist/lib/observability/otelBridge.d.ts +2 -2
- package/dist/lib/observability/otelBridge.js +12 -3
- package/dist/lib/providers/amazonBedrock.js +2 -4
- package/dist/lib/providers/anthropic.d.ts +9 -5
- package/dist/lib/providers/anthropic.js +19 -14
- package/dist/lib/providers/anthropicBaseProvider.d.ts +3 -3
- package/dist/lib/providers/anthropicBaseProvider.js +5 -4
- package/dist/lib/providers/azureOpenai.d.ts +1 -1
- package/dist/lib/providers/azureOpenai.js +5 -4
- package/dist/lib/providers/googleAiStudio.js +30 -1
- package/dist/lib/providers/googleVertex.js +28 -6
- package/dist/lib/providers/huggingFace.d.ts +3 -3
- package/dist/lib/providers/huggingFace.js +6 -8
- package/dist/lib/providers/litellm.js +41 -29
- package/dist/lib/providers/mistral.js +2 -1
- package/dist/lib/providers/ollama.js +80 -23
- package/dist/lib/providers/openAI.js +3 -2
- package/dist/lib/providers/openRouter.js +2 -1
- package/dist/lib/providers/openaiCompatible.d.ts +4 -4
- package/dist/lib/providers/openaiCompatible.js +4 -4
- package/dist/lib/proxy/claudeFormat.d.ts +3 -2
- package/dist/lib/proxy/claudeFormat.js +25 -20
- package/dist/lib/proxy/cloaking/plugins/sessionIdentity.d.ts +2 -6
- package/dist/lib/proxy/cloaking/plugins/sessionIdentity.js +9 -33
- package/dist/lib/proxy/modelRouter.js +3 -0
- package/dist/lib/proxy/oauthFetch.d.ts +1 -1
- package/dist/lib/proxy/oauthFetch.js +65 -72
- package/dist/lib/proxy/proxyConfig.js +44 -24
- package/dist/lib/proxy/proxyEnv.d.ts +19 -0
- package/dist/lib/proxy/proxyEnv.js +73 -0
- package/dist/lib/proxy/proxyFetch.js +50 -4
- package/dist/lib/proxy/proxyTracer.d.ts +133 -0
- package/dist/lib/proxy/proxyTracer.js +645 -0
- package/dist/lib/proxy/rawStreamCapture.d.ts +10 -0
- package/dist/lib/proxy/rawStreamCapture.js +83 -0
- package/dist/lib/proxy/requestLogger.d.ts +32 -5
- package/dist/lib/proxy/requestLogger.js +406 -37
- package/dist/lib/proxy/sseInterceptor.d.ts +97 -0
- package/dist/lib/proxy/sseInterceptor.js +402 -0
- package/dist/lib/proxy/usageStats.d.ts +4 -3
- package/dist/lib/proxy/usageStats.js +25 -12
- package/dist/lib/rag/chunkers/MarkdownChunker.js +13 -5
- package/dist/lib/rag/chunking/markdownChunker.js +15 -6
- package/dist/lib/server/routes/claudeProxyRoutes.d.ts +7 -2
- package/dist/lib/server/routes/claudeProxyRoutes.js +1737 -508
- package/dist/lib/services/server/ai/observability/instrumentation.d.ts +7 -1
- package/dist/lib/services/server/ai/observability/instrumentation.js +240 -40
- package/dist/lib/tasks/backends/bullmqBackend.d.ts +33 -0
- package/dist/lib/tasks/backends/bullmqBackend.js +196 -0
- package/dist/lib/tasks/backends/nodeTimeoutBackend.d.ts +27 -0
- package/dist/lib/tasks/backends/nodeTimeoutBackend.js +141 -0
- package/dist/lib/tasks/backends/taskBackendRegistry.d.ts +31 -0
- package/dist/lib/tasks/backends/taskBackendRegistry.js +66 -0
- package/dist/lib/tasks/errors.d.ts +31 -0
- package/dist/lib/tasks/errors.js +18 -0
- package/dist/lib/tasks/store/fileTaskStore.d.ts +43 -0
- package/dist/lib/tasks/store/fileTaskStore.js +179 -0
- package/dist/lib/tasks/store/redisTaskStore.d.ts +43 -0
- package/dist/lib/tasks/store/redisTaskStore.js +197 -0
- package/dist/lib/tasks/taskExecutor.d.ts +21 -0
- package/dist/lib/tasks/taskExecutor.js +166 -0
- package/dist/lib/tasks/taskManager.d.ts +63 -0
- package/dist/lib/tasks/taskManager.js +426 -0
- package/dist/lib/tasks/tools/taskTools.d.ts +135 -0
- package/dist/lib/tasks/tools/taskTools.js +274 -0
- package/dist/lib/telemetry/index.d.ts +2 -1
- package/dist/lib/telemetry/index.js +2 -1
- package/dist/lib/telemetry/telemetryService.d.ts +3 -0
- package/dist/lib/telemetry/telemetryService.js +65 -5
- package/dist/lib/types/cli.d.ts +10 -0
- package/dist/lib/types/configTypes.d.ts +3 -0
- package/dist/lib/types/generateTypes.d.ts +13 -0
- package/dist/lib/types/index.d.ts +1 -0
- package/dist/lib/types/proxyTypes.d.ts +37 -5
- package/dist/lib/types/streamTypes.d.ts +25 -3
- package/dist/lib/types/taskTypes.d.ts +275 -0
- package/dist/lib/types/taskTypes.js +37 -0
- package/dist/lib/utils/messageBuilder.js +3 -2
- package/dist/lib/utils/providerHealth.d.ts +18 -0
- package/dist/lib/utils/providerHealth.js +240 -9
- package/dist/lib/utils/providerUtils.js +14 -8
- package/dist/lib/utils/toolChoice.d.ts +4 -0
- package/dist/lib/utils/toolChoice.js +7 -0
- package/dist/neurolink.d.ts +18 -1
- package/dist/neurolink.js +367 -484
- package/dist/observability/otelBridge.d.ts +2 -2
- package/dist/observability/otelBridge.js +12 -3
- package/dist/providers/amazonBedrock.js +2 -4
- package/dist/providers/anthropic.d.ts +9 -5
- package/dist/providers/anthropic.js +19 -14
- package/dist/providers/anthropicBaseProvider.d.ts +3 -3
- package/dist/providers/anthropicBaseProvider.js +5 -4
- package/dist/providers/azureOpenai.d.ts +1 -1
- package/dist/providers/azureOpenai.js +5 -4
- package/dist/providers/googleAiStudio.js +30 -1
- package/dist/providers/googleVertex.js +28 -6
- package/dist/providers/huggingFace.d.ts +3 -3
- package/dist/providers/huggingFace.js +6 -7
- package/dist/providers/litellm.js +41 -29
- package/dist/providers/mistral.js +2 -1
- package/dist/providers/ollama.js +80 -23
- package/dist/providers/openAI.js +3 -2
- package/dist/providers/openRouter.js +2 -1
- package/dist/providers/openaiCompatible.d.ts +4 -4
- package/dist/providers/openaiCompatible.js +4 -3
- package/dist/proxy/claudeFormat.d.ts +3 -2
- package/dist/proxy/claudeFormat.js +25 -20
- package/dist/proxy/cloaking/plugins/sessionIdentity.d.ts +2 -6
- package/dist/proxy/cloaking/plugins/sessionIdentity.js +9 -33
- package/dist/proxy/modelRouter.js +3 -0
- package/dist/proxy/oauthFetch.d.ts +1 -1
- package/dist/proxy/oauthFetch.js +65 -72
- package/dist/proxy/proxyConfig.js +44 -24
- package/dist/proxy/proxyEnv.d.ts +19 -0
- package/dist/proxy/proxyEnv.js +72 -0
- package/dist/proxy/proxyFetch.js +50 -4
- package/dist/proxy/proxyTracer.d.ts +133 -0
- package/dist/proxy/proxyTracer.js +644 -0
- package/dist/proxy/rawStreamCapture.d.ts +10 -0
- package/dist/proxy/rawStreamCapture.js +82 -0
- package/dist/proxy/requestLogger.d.ts +32 -5
- package/dist/proxy/requestLogger.js +406 -37
- package/dist/proxy/sseInterceptor.d.ts +97 -0
- package/dist/proxy/sseInterceptor.js +401 -0
- package/dist/proxy/usageStats.d.ts +4 -3
- package/dist/proxy/usageStats.js +25 -12
- package/dist/rag/chunkers/MarkdownChunker.js +13 -5
- package/dist/rag/chunking/markdownChunker.js +15 -6
- package/dist/server/routes/claudeProxyRoutes.d.ts +7 -2
- package/dist/server/routes/claudeProxyRoutes.js +1737 -508
- package/dist/services/server/ai/observability/instrumentation.d.ts +7 -1
- package/dist/services/server/ai/observability/instrumentation.js +240 -40
- package/dist/tasks/backends/bullmqBackend.d.ts +33 -0
- package/dist/tasks/backends/bullmqBackend.js +195 -0
- package/dist/tasks/backends/nodeTimeoutBackend.d.ts +27 -0
- package/dist/tasks/backends/nodeTimeoutBackend.js +140 -0
- package/dist/tasks/backends/taskBackendRegistry.d.ts +31 -0
- package/dist/tasks/backends/taskBackendRegistry.js +65 -0
- package/dist/tasks/errors.d.ts +31 -0
- package/dist/tasks/errors.js +17 -0
- package/dist/tasks/store/fileTaskStore.d.ts +43 -0
- package/dist/tasks/store/fileTaskStore.js +178 -0
- package/dist/tasks/store/redisTaskStore.d.ts +43 -0
- package/dist/tasks/store/redisTaskStore.js +196 -0
- package/dist/tasks/taskExecutor.d.ts +21 -0
- package/dist/tasks/taskExecutor.js +165 -0
- package/dist/tasks/taskManager.d.ts +63 -0
- package/dist/tasks/taskManager.js +425 -0
- package/dist/tasks/tools/taskTools.d.ts +135 -0
- package/dist/tasks/tools/taskTools.js +273 -0
- package/dist/telemetry/index.d.ts +2 -1
- package/dist/telemetry/index.js +2 -1
- package/dist/telemetry/telemetryService.d.ts +3 -0
- package/dist/telemetry/telemetryService.js +65 -5
- package/dist/types/cli.d.ts +10 -0
- package/dist/types/configTypes.d.ts +3 -0
- package/dist/types/generateTypes.d.ts +13 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/proxyTypes.d.ts +37 -5
- package/dist/types/streamTypes.d.ts +25 -3
- package/dist/types/taskTypes.d.ts +275 -0
- package/dist/types/taskTypes.js +36 -0
- package/dist/utils/messageBuilder.js +3 -2
- package/dist/utils/providerHealth.d.ts +18 -0
- package/dist/utils/providerHealth.js +240 -9
- package/dist/utils/providerUtils.js +14 -8
- package/dist/utils/toolChoice.d.ts +4 -0
- package/dist/utils/toolChoice.js +6 -0
- package/docs/assets/dashboards/neurolink-proxy-observability-dashboard.json +6609 -0
- package/docs/changelog.md +252 -0
- package/package.json +19 -1
- package/scripts/observability/check-proxy-telemetry.mjs +235 -0
- package/scripts/observability/docker-compose.proxy-observability.yaml +55 -0
- package/scripts/observability/import-openobserve-dashboard.mjs +240 -0
- package/scripts/observability/manage-local-openobserve.sh +184 -0
- package/scripts/observability/otel-collector.proxy-observability.yaml +78 -0
- 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
|
|
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
|
-
|
|
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(
|
|
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
|
-
.
|
|
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
|
-
.
|
|
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 {
|
|
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 {
|
|
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 {
|
|
4
|
-
import {
|
|
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 {
|
|
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", {
|
|
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:
|
|
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 {
|
|
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 {
|
|
4
|
-
import
|
|
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 {
|
|
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 {
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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
|
|
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
|
|
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
|
|
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:
|
|
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:
|
|
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 }) => {
|