@juspay/neurolink 9.63.1 → 9.65.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 +18 -17
- package/dist/adapters/providerImageAdapter.js +29 -1
- package/dist/adapters/replicate/auth.d.ts +19 -0
- package/dist/adapters/replicate/auth.js +32 -0
- package/dist/adapters/replicate/predictionLifecycle.d.ts +46 -0
- package/dist/adapters/replicate/predictionLifecycle.js +283 -0
- package/dist/adapters/video/klingVideoHandler.d.ts +37 -0
- package/dist/adapters/video/klingVideoHandler.js +305 -0
- package/dist/adapters/video/replicateVideoHandler.d.ts +29 -0
- package/dist/adapters/video/replicateVideoHandler.js +157 -0
- package/dist/adapters/video/runwayVideoHandler.d.ts +32 -0
- package/dist/adapters/video/runwayVideoHandler.js +316 -0
- package/dist/adapters/video/vertexVideoHandler.d.ts +19 -1
- package/dist/adapters/video/vertexVideoHandler.js +42 -11
- package/dist/autoresearch/runner.js +8 -2
- package/dist/avatar/index.d.ts +13 -0
- package/dist/avatar/index.js +13 -0
- package/dist/avatar/providers/DIDAvatar.d.ts +49 -0
- package/dist/avatar/providers/DIDAvatar.js +501 -0
- package/dist/avatar/providers/HeyGenAvatar.d.ts +30 -0
- package/dist/avatar/providers/HeyGenAvatar.js +337 -0
- package/dist/avatar/providers/ReplicateAvatar.d.ts +36 -0
- package/dist/avatar/providers/ReplicateAvatar.js +267 -0
- package/dist/browser/neurolink.min.js +573 -554
- package/dist/cli/commands/mcp.js +29 -0
- package/dist/cli/commands/proxy.js +24 -5
- package/dist/cli/factories/commandFactory.d.ts +25 -1
- package/dist/cli/factories/commandFactory.js +341 -63
- package/dist/cli/loop/optionsSchema.d.ts +1 -1
- package/dist/cli/loop/optionsSchema.js +12 -0
- package/dist/constants/contextWindows.js +101 -0
- package/dist/constants/enums.d.ts +273 -2
- package/dist/constants/enums.js +290 -1
- package/dist/constants/videoErrors.d.ts +4 -0
- package/dist/constants/videoErrors.js +4 -0
- package/dist/core/baseProvider.d.ts +23 -3
- package/dist/core/baseProvider.js +217 -11
- package/dist/core/constants.d.ts +11 -0
- package/dist/core/constants.js +69 -1
- package/dist/core/modules/MessageBuilder.js +20 -0
- package/dist/core/redisConversationMemoryManager.js +6 -0
- package/dist/evaluation/index.d.ts +2 -0
- package/dist/evaluation/index.js +4 -0
- package/dist/factories/providerFactory.js +7 -1
- package/dist/factories/providerRegistry.js +203 -2
- package/dist/features/ppt/contentPlanner.js +42 -14
- package/dist/index.d.ts +9 -1
- package/dist/index.js +16 -1
- package/dist/lib/adapters/providerImageAdapter.js +29 -1
- package/dist/lib/adapters/replicate/auth.d.ts +19 -0
- package/dist/lib/adapters/replicate/auth.js +33 -0
- package/dist/lib/adapters/replicate/predictionLifecycle.d.ts +46 -0
- package/dist/lib/adapters/replicate/predictionLifecycle.js +284 -0
- package/dist/lib/adapters/video/klingVideoHandler.d.ts +37 -0
- package/dist/lib/adapters/video/klingVideoHandler.js +306 -0
- package/dist/lib/adapters/video/replicateVideoHandler.d.ts +29 -0
- package/dist/lib/adapters/video/replicateVideoHandler.js +158 -0
- package/dist/lib/adapters/video/runwayVideoHandler.d.ts +32 -0
- package/dist/lib/adapters/video/runwayVideoHandler.js +317 -0
- package/dist/lib/adapters/video/vertexVideoHandler.d.ts +19 -1
- package/dist/lib/adapters/video/vertexVideoHandler.js +42 -11
- package/dist/lib/autoresearch/runner.js +8 -2
- package/dist/lib/avatar/index.d.ts +13 -0
- package/dist/lib/avatar/index.js +14 -0
- package/dist/lib/avatar/providers/DIDAvatar.d.ts +49 -0
- package/dist/lib/avatar/providers/DIDAvatar.js +502 -0
- package/dist/lib/avatar/providers/HeyGenAvatar.d.ts +30 -0
- package/dist/lib/avatar/providers/HeyGenAvatar.js +338 -0
- package/dist/lib/avatar/providers/ReplicateAvatar.d.ts +36 -0
- package/dist/lib/avatar/providers/ReplicateAvatar.js +268 -0
- package/dist/lib/constants/contextWindows.js +101 -0
- package/dist/lib/constants/enums.d.ts +273 -2
- package/dist/lib/constants/enums.js +290 -1
- package/dist/lib/constants/videoErrors.d.ts +4 -0
- package/dist/lib/constants/videoErrors.js +4 -0
- package/dist/lib/core/baseProvider.d.ts +23 -3
- package/dist/lib/core/baseProvider.js +217 -11
- package/dist/lib/core/constants.d.ts +11 -0
- package/dist/lib/core/constants.js +69 -1
- package/dist/lib/core/modules/MessageBuilder.js +20 -0
- package/dist/lib/core/redisConversationMemoryManager.js +6 -0
- package/dist/lib/evaluation/index.d.ts +2 -0
- package/dist/lib/evaluation/index.js +4 -0
- package/dist/lib/factories/providerFactory.js +7 -1
- package/dist/lib/factories/providerRegistry.js +203 -2
- package/dist/lib/features/ppt/contentPlanner.js +42 -14
- package/dist/lib/index.d.ts +9 -1
- package/dist/lib/index.js +16 -1
- package/dist/lib/memory/hippocampusInitializer.d.ts +2 -2
- package/dist/lib/memory/hippocampusInitializer.js +32 -2
- package/dist/lib/middleware/builtin/lifecycle.js +52 -51
- package/dist/lib/music/index.d.ts +13 -0
- package/dist/lib/music/index.js +14 -0
- package/dist/lib/music/providers/BeatovenMusic.d.ts +31 -0
- package/dist/lib/music/providers/BeatovenMusic.js +334 -0
- package/dist/lib/music/providers/ElevenLabsMusic.d.ts +30 -0
- package/dist/lib/music/providers/ElevenLabsMusic.js +169 -0
- package/dist/lib/music/providers/LyriaMusic.d.ts +29 -0
- package/dist/lib/music/providers/LyriaMusic.js +173 -0
- package/dist/lib/music/providers/ReplicateMusic.d.ts +31 -0
- package/dist/lib/music/providers/ReplicateMusic.js +262 -0
- package/dist/lib/neurolink.d.ts +30 -0
- package/dist/lib/neurolink.js +342 -49
- package/dist/lib/providers/amazonBedrock.d.ts +10 -0
- package/dist/lib/providers/amazonBedrock.js +94 -39
- package/dist/lib/providers/anthropic.js +55 -7
- package/dist/lib/providers/anthropicBaseProvider.js +1 -1
- package/dist/lib/providers/azureOpenai.js +66 -17
- package/dist/lib/providers/cloudflare.d.ts +35 -0
- package/dist/lib/providers/cloudflare.js +174 -0
- package/dist/lib/providers/cohere.d.ts +52 -0
- package/dist/lib/providers/cohere.js +253 -0
- package/dist/lib/providers/deepseek.js +72 -17
- package/dist/lib/providers/fireworks.d.ts +33 -0
- package/dist/lib/providers/fireworks.js +164 -0
- package/dist/lib/providers/googleAiStudio.d.ts +11 -3
- package/dist/lib/providers/googleAiStudio.js +336 -344
- package/dist/lib/providers/googleNativeGemini3.d.ts +107 -2
- package/dist/lib/providers/googleNativeGemini3.js +381 -25
- package/dist/lib/providers/googleVertex.d.ts +116 -129
- package/dist/lib/providers/googleVertex.js +3002 -1988
- package/dist/lib/providers/groq.d.ts +33 -0
- package/dist/lib/providers/groq.js +181 -0
- package/dist/lib/providers/huggingFace.js +9 -8
- package/dist/lib/providers/ideogram.d.ts +34 -0
- package/dist/lib/providers/ideogram.js +184 -0
- package/dist/lib/providers/index.d.ts +13 -0
- package/dist/lib/providers/index.js +13 -0
- package/dist/lib/providers/jina.d.ts +59 -0
- package/dist/lib/providers/jina.js +218 -0
- package/dist/lib/providers/llamaCpp.js +14 -46
- package/dist/lib/providers/lmStudio.js +14 -47
- package/dist/lib/providers/mistral.js +7 -7
- package/dist/lib/providers/nvidiaNim.js +160 -19
- package/dist/lib/providers/ollama.js +7 -7
- package/dist/lib/providers/openAI.d.ts +22 -1
- package/dist/lib/providers/openAI.js +181 -0
- package/dist/lib/providers/openRouter.js +38 -22
- package/dist/lib/providers/openaiCompatible.js +9 -8
- package/dist/lib/providers/perplexity.d.ts +33 -0
- package/dist/lib/providers/perplexity.js +179 -0
- package/dist/lib/providers/recraft.d.ts +34 -0
- package/dist/lib/providers/recraft.js +197 -0
- package/dist/lib/providers/replicate.d.ts +75 -0
- package/dist/lib/providers/replicate.js +403 -0
- package/dist/lib/providers/stability.d.ts +37 -0
- package/dist/lib/providers/stability.js +191 -0
- package/dist/lib/providers/togetherAi.d.ts +33 -0
- package/dist/lib/providers/togetherAi.js +176 -0
- package/dist/lib/providers/voyage.d.ts +47 -0
- package/dist/lib/providers/voyage.js +177 -0
- package/dist/lib/providers/xai.d.ts +33 -0
- package/dist/lib/providers/xai.js +172 -0
- package/dist/lib/telemetry/index.d.ts +1 -1
- package/dist/lib/telemetry/index.js +1 -1
- package/dist/lib/telemetry/tracers.d.ts +19 -0
- package/dist/lib/telemetry/tracers.js +19 -0
- package/dist/lib/telemetry/withSpan.d.ts +35 -0
- package/dist/lib/telemetry/withSpan.js +103 -0
- package/dist/lib/types/aliases.d.ts +14 -0
- package/dist/lib/types/avatar.d.ts +143 -0
- package/dist/lib/types/avatar.js +20 -0
- package/dist/lib/types/cli.d.ts +6 -0
- package/dist/lib/types/common.d.ts +0 -3
- package/dist/lib/types/conversation.d.ts +10 -3
- package/dist/lib/types/generate.d.ts +76 -5
- package/dist/lib/types/index.d.ts +6 -0
- package/dist/lib/types/index.js +8 -0
- package/dist/lib/types/memory.d.ts +96 -0
- package/dist/lib/types/memory.js +23 -0
- package/dist/lib/types/middleware.d.ts +27 -0
- package/dist/lib/types/multimodal.d.ts +35 -2
- package/dist/lib/types/music.d.ts +165 -0
- package/dist/lib/types/music.js +21 -0
- package/dist/lib/types/providers.d.ts +284 -3
- package/dist/lib/types/replicate.d.ts +67 -0
- package/dist/lib/types/replicate.js +10 -0
- package/dist/lib/types/safeFetch.d.ts +15 -0
- package/dist/lib/types/safeFetch.js +7 -0
- package/dist/lib/types/stream.d.ts +8 -1
- package/dist/lib/types/tools.d.ts +13 -0
- package/dist/lib/types/video.d.ts +89 -0
- package/dist/lib/types/video.js +15 -0
- package/dist/lib/utils/avatarProcessor.d.ts +68 -0
- package/dist/lib/utils/avatarProcessor.js +172 -0
- package/dist/lib/utils/cloneOptions.d.ts +36 -0
- package/dist/lib/utils/cloneOptions.js +62 -0
- package/dist/lib/utils/lifecycleCallbacks.d.ts +56 -0
- package/dist/lib/utils/lifecycleCallbacks.js +100 -0
- package/dist/lib/utils/lifecycleTimeout.d.ts +25 -0
- package/dist/lib/utils/lifecycleTimeout.js +39 -0
- package/dist/lib/utils/logSanitize.d.ts +49 -0
- package/dist/lib/utils/logSanitize.js +170 -0
- package/dist/lib/utils/loggingFetch.d.ts +29 -0
- package/dist/lib/utils/loggingFetch.js +60 -0
- package/dist/lib/utils/messageBuilder.d.ts +10 -0
- package/dist/lib/utils/messageBuilder.js +83 -30
- package/dist/lib/utils/modelChoices.js +236 -3
- package/dist/lib/utils/modelDetection.d.ts +11 -0
- package/dist/lib/utils/modelDetection.js +27 -0
- package/dist/lib/utils/musicProcessor.d.ts +67 -0
- package/dist/lib/utils/musicProcessor.js +189 -0
- package/dist/lib/utils/optionsConversion.js +3 -2
- package/dist/lib/utils/parameterValidation.js +14 -4
- package/dist/lib/utils/pricing.js +193 -0
- package/dist/lib/utils/providerConfig.d.ts +55 -0
- package/dist/lib/utils/providerConfig.js +224 -0
- package/dist/lib/utils/providerHealth.js +7 -7
- package/dist/lib/utils/safeFetch.d.ts +26 -0
- package/dist/lib/utils/safeFetch.js +83 -0
- package/dist/lib/utils/schemaConversion.d.ts +1 -1
- package/dist/lib/utils/schemaConversion.js +59 -4
- package/dist/lib/utils/sizeGuard.d.ts +34 -0
- package/dist/lib/utils/sizeGuard.js +45 -0
- package/dist/lib/utils/ssrfGuard.d.ts +52 -0
- package/dist/lib/utils/ssrfGuard.js +411 -0
- package/dist/lib/utils/tokenLimits.js +23 -32
- package/dist/lib/utils/videoProcessor.d.ts +60 -0
- package/dist/lib/utils/videoProcessor.js +201 -0
- package/dist/lib/voice/providers/FishAudioTTS.d.ts +27 -0
- package/dist/lib/voice/providers/FishAudioTTS.js +183 -0
- package/dist/lib/workflow/core/ensembleExecutor.js +26 -9
- package/dist/memory/hippocampusInitializer.d.ts +2 -2
- package/dist/memory/hippocampusInitializer.js +32 -2
- package/dist/middleware/builtin/lifecycle.js +52 -51
- package/dist/music/index.d.ts +13 -0
- package/dist/music/index.js +13 -0
- package/dist/music/providers/BeatovenMusic.d.ts +31 -0
- package/dist/music/providers/BeatovenMusic.js +333 -0
- package/dist/music/providers/ElevenLabsMusic.d.ts +30 -0
- package/dist/music/providers/ElevenLabsMusic.js +168 -0
- package/dist/music/providers/LyriaMusic.d.ts +29 -0
- package/dist/music/providers/LyriaMusic.js +172 -0
- package/dist/music/providers/ReplicateMusic.d.ts +31 -0
- package/dist/music/providers/ReplicateMusic.js +261 -0
- package/dist/neurolink.d.ts +30 -0
- package/dist/neurolink.js +342 -49
- package/dist/providers/amazonBedrock.d.ts +10 -0
- package/dist/providers/amazonBedrock.js +94 -39
- package/dist/providers/anthropic.js +55 -7
- package/dist/providers/anthropicBaseProvider.js +1 -1
- package/dist/providers/azureOpenai.js +66 -17
- package/dist/providers/cloudflare.d.ts +35 -0
- package/dist/providers/cloudflare.js +173 -0
- package/dist/providers/cohere.d.ts +52 -0
- package/dist/providers/cohere.js +252 -0
- package/dist/providers/deepseek.js +72 -17
- package/dist/providers/fireworks.d.ts +33 -0
- package/dist/providers/fireworks.js +163 -0
- package/dist/providers/googleAiStudio.d.ts +11 -3
- package/dist/providers/googleAiStudio.js +335 -344
- package/dist/providers/googleNativeGemini3.d.ts +107 -2
- package/dist/providers/googleNativeGemini3.js +381 -25
- package/dist/providers/googleVertex.d.ts +116 -129
- package/dist/providers/googleVertex.js +3000 -1987
- package/dist/providers/groq.d.ts +33 -0
- package/dist/providers/groq.js +180 -0
- package/dist/providers/huggingFace.js +9 -8
- package/dist/providers/ideogram.d.ts +34 -0
- package/dist/providers/ideogram.js +183 -0
- package/dist/providers/index.d.ts +13 -0
- package/dist/providers/index.js +13 -0
- package/dist/providers/jina.d.ts +59 -0
- package/dist/providers/jina.js +217 -0
- package/dist/providers/llamaCpp.js +14 -46
- package/dist/providers/lmStudio.js +14 -47
- package/dist/providers/mistral.js +7 -7
- package/dist/providers/nvidiaNim.js +160 -19
- package/dist/providers/ollama.js +7 -7
- package/dist/providers/openAI.d.ts +22 -1
- package/dist/providers/openAI.js +181 -0
- package/dist/providers/openRouter.js +38 -22
- package/dist/providers/openaiCompatible.js +9 -8
- package/dist/providers/perplexity.d.ts +33 -0
- package/dist/providers/perplexity.js +178 -0
- package/dist/providers/recraft.d.ts +34 -0
- package/dist/providers/recraft.js +196 -0
- package/dist/providers/replicate.d.ts +75 -0
- package/dist/providers/replicate.js +402 -0
- package/dist/providers/stability.d.ts +37 -0
- package/dist/providers/stability.js +190 -0
- package/dist/providers/togetherAi.d.ts +33 -0
- package/dist/providers/togetherAi.js +175 -0
- package/dist/providers/voyage.d.ts +47 -0
- package/dist/providers/voyage.js +176 -0
- package/dist/providers/xai.d.ts +33 -0
- package/dist/providers/xai.js +171 -0
- package/dist/telemetry/index.d.ts +1 -1
- package/dist/telemetry/index.js +1 -1
- package/dist/telemetry/tracers.d.ts +19 -0
- package/dist/telemetry/tracers.js +19 -0
- package/dist/telemetry/withSpan.d.ts +35 -0
- package/dist/telemetry/withSpan.js +103 -0
- package/dist/types/aliases.d.ts +14 -0
- package/dist/types/avatar.d.ts +143 -0
- package/dist/types/avatar.js +19 -0
- package/dist/types/cli.d.ts +6 -0
- package/dist/types/common.d.ts +0 -3
- package/dist/types/conversation.d.ts +10 -3
- package/dist/types/generate.d.ts +76 -5
- package/dist/types/index.d.ts +6 -0
- package/dist/types/index.js +8 -0
- package/dist/types/memory.d.ts +96 -0
- package/dist/types/memory.js +22 -0
- package/dist/types/middleware.d.ts +27 -0
- package/dist/types/multimodal.d.ts +35 -2
- package/dist/types/music.d.ts +165 -0
- package/dist/types/music.js +20 -0
- package/dist/types/providers.d.ts +284 -3
- package/dist/types/replicate.d.ts +67 -0
- package/dist/types/replicate.js +9 -0
- package/dist/types/safeFetch.d.ts +15 -0
- package/dist/types/safeFetch.js +6 -0
- package/dist/types/stream.d.ts +8 -1
- package/dist/types/tools.d.ts +13 -0
- package/dist/types/video.d.ts +89 -0
- package/dist/types/video.js +14 -0
- package/dist/utils/avatarProcessor.d.ts +68 -0
- package/dist/utils/avatarProcessor.js +171 -0
- package/dist/utils/cloneOptions.d.ts +36 -0
- package/dist/utils/cloneOptions.js +61 -0
- package/dist/utils/lifecycleCallbacks.d.ts +56 -0
- package/dist/utils/lifecycleCallbacks.js +99 -0
- package/dist/utils/lifecycleTimeout.d.ts +25 -0
- package/dist/utils/lifecycleTimeout.js +38 -0
- package/dist/utils/logSanitize.d.ts +49 -0
- package/dist/utils/logSanitize.js +169 -0
- package/dist/utils/loggingFetch.d.ts +29 -0
- package/dist/utils/loggingFetch.js +59 -0
- package/dist/utils/messageBuilder.d.ts +10 -0
- package/dist/utils/messageBuilder.js +83 -30
- package/dist/utils/modelChoices.js +236 -3
- package/dist/utils/modelDetection.d.ts +11 -0
- package/dist/utils/modelDetection.js +27 -0
- package/dist/utils/musicProcessor.d.ts +67 -0
- package/dist/utils/musicProcessor.js +188 -0
- package/dist/utils/optionsConversion.js +3 -2
- package/dist/utils/parameterValidation.js +14 -4
- package/dist/utils/pricing.js +193 -0
- package/dist/utils/providerConfig.d.ts +55 -0
- package/dist/utils/providerConfig.js +224 -0
- package/dist/utils/providerHealth.js +7 -7
- package/dist/utils/safeFetch.d.ts +26 -0
- package/dist/utils/safeFetch.js +82 -0
- package/dist/utils/schemaConversion.d.ts +1 -1
- package/dist/utils/schemaConversion.js +59 -4
- package/dist/utils/sizeGuard.d.ts +34 -0
- package/dist/utils/sizeGuard.js +44 -0
- package/dist/utils/ssrfGuard.d.ts +52 -0
- package/dist/utils/ssrfGuard.js +410 -0
- package/dist/utils/tokenLimits.js +23 -32
- package/dist/utils/videoProcessor.d.ts +60 -0
- package/dist/utils/videoProcessor.js +200 -0
- package/dist/voice/providers/FishAudioTTS.d.ts +27 -0
- package/dist/voice/providers/FishAudioTTS.js +182 -0
- package/dist/workflow/core/ensembleExecutor.js +26 -9
- package/package.json +42 -8
|
@@ -1,22 +1,15 @@
|
|
|
1
|
-
import { createGoogleGenerativeAI } from "@ai-sdk/google";
|
|
2
|
-
import { embed, embedMany, stepCountIs, streamText, } from "ai";
|
|
3
1
|
import { ErrorCategory, ErrorSeverity, GoogleAIModels, } from "../constants/enums.js";
|
|
4
2
|
import { BaseProvider } from "../core/baseProvider.js";
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import { ATTR, tracers, withClientSpan } from "../telemetry/index.js";
|
|
10
|
-
import { AuthenticationError, NetworkError, ProviderError, RateLimitError, } from "../types/index.js";
|
|
3
|
+
import { IMAGE_GENERATION_MODELS } from "../core/constants.js";
|
|
4
|
+
import { processUnifiedFilesArray } from "../utils/messageBuilder.js";
|
|
5
|
+
import { ATTR, tracers, withClientSpan, withClientStreamSpan, withSpan, } from "../telemetry/index.js";
|
|
6
|
+
import { AuthenticationError, InvalidModelError, NetworkError, ProviderError, RateLimitError, } from "../types/index.js";
|
|
11
7
|
import { ERROR_CODES, NeuroLinkError } from "../utils/errorHandling.js";
|
|
12
8
|
import { logger } from "../utils/logger.js";
|
|
13
|
-
import { isGemini3Model } from "../utils/modelDetection.js";
|
|
14
9
|
import { composeAbortSignals, createTimeoutController, TimeoutError, } from "../utils/timeout.js";
|
|
15
10
|
import { estimateTokens } from "../utils/tokenEstimation.js";
|
|
16
|
-
import {
|
|
17
|
-
import {
|
|
18
|
-
import { buildNativeConfig, buildNativeToolDeclarations, collectStreamChunks, collectStreamChunksIncremental, computeMaxSteps, createTextChannel, executeNativeToolCalls, extractTextFromParts, handleMaxStepsTermination, pushModelResponseToHistory, sanitizeToolsForGemini, } from "./googleNativeGemini3.js";
|
|
19
|
-
import { toAnalyticsStreamResult } from "./providerTypeUtils.js";
|
|
11
|
+
import { buildGeminiResponseSchema, buildNativeConfig, buildNativeToolDeclarations, collectStreamChunks, collectStreamChunksIncremental, computeMaxSteps, createTextChannel, buildUserPartsWithMultimodal, executeNativeToolCalls, extractTextFromParts, handleMaxStepsTermination, prependConversationMessages, pushModelResponseToHistory, } from "./googleNativeGemini3.js";
|
|
12
|
+
import { createProxyFetch } from "../proxy/proxyFetch.js";
|
|
20
13
|
// Google AI Live API types now imported from ../types/providerSpecific.js
|
|
21
14
|
// Import proper types for multimodal message handling
|
|
22
15
|
// Create Google GenAI client
|
|
@@ -34,7 +27,13 @@ async function createGoogleGenAIClient(apiKey) {
|
|
|
34
27
|
});
|
|
35
28
|
}
|
|
36
29
|
const Ctor = ctor;
|
|
37
|
-
|
|
30
|
+
// Include httpOptions with proxy fetch for corporate network support
|
|
31
|
+
return new Ctor({
|
|
32
|
+
apiKey,
|
|
33
|
+
httpOptions: {
|
|
34
|
+
fetch: createProxyFetch(),
|
|
35
|
+
},
|
|
36
|
+
});
|
|
38
37
|
}
|
|
39
38
|
/**
|
|
40
39
|
* Google AI Studio provider implementation using BaseProvider
|
|
@@ -88,12 +87,18 @@ export class GoogleAIStudioProvider extends BaseProvider {
|
|
|
88
87
|
return process.env.GOOGLE_AI_MODEL || GoogleAIModels.GEMINI_2_5_FLASH;
|
|
89
88
|
}
|
|
90
89
|
/**
|
|
91
|
-
*
|
|
90
|
+
* AI SDK model instance — no longer used.
|
|
91
|
+
* All models are routed through native @google/genai SDK directly.
|
|
92
92
|
*/
|
|
93
93
|
getAISDKModel() {
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
94
|
+
throw new NeuroLinkError({
|
|
95
|
+
code: ERROR_CODES.INVALID_CONFIGURATION,
|
|
96
|
+
message: "GoogleAIStudioProvider no longer uses @ai-sdk/google. All models use native @google/genai SDK.",
|
|
97
|
+
category: ErrorCategory.CONFIGURATION,
|
|
98
|
+
severity: ErrorSeverity.CRITICAL,
|
|
99
|
+
retriable: false,
|
|
100
|
+
context: { provider: this.providerName, model: this.modelName },
|
|
101
|
+
});
|
|
97
102
|
}
|
|
98
103
|
formatProviderError(error) {
|
|
99
104
|
if (error instanceof TimeoutError) {
|
|
@@ -103,12 +108,53 @@ export class GoogleAIStudioProvider extends BaseProvider {
|
|
|
103
108
|
const message = typeof errorRecord?.message === "string"
|
|
104
109
|
? errorRecord.message
|
|
105
110
|
: "Unknown error";
|
|
106
|
-
|
|
111
|
+
const statusCode = typeof errorRecord?.status === "number"
|
|
112
|
+
? errorRecord.status
|
|
113
|
+
: typeof errorRecord?.statusCode === "number"
|
|
114
|
+
? errorRecord.statusCode
|
|
115
|
+
: undefined;
|
|
116
|
+
// Authentication errors
|
|
117
|
+
if (message.includes("API_KEY_INVALID") ||
|
|
118
|
+
message.includes("Invalid API key") ||
|
|
119
|
+
statusCode === 401) {
|
|
107
120
|
return new AuthenticationError("Invalid Google AI API key. Please check your GOOGLE_AI_API_KEY environment variable.", this.providerName);
|
|
108
121
|
}
|
|
109
|
-
|
|
122
|
+
// Rate limit errors
|
|
123
|
+
if (message.includes("RATE_LIMIT_EXCEEDED") ||
|
|
124
|
+
message.includes("rate limit") ||
|
|
125
|
+
message.includes("429") ||
|
|
126
|
+
statusCode === 429) {
|
|
110
127
|
return new RateLimitError("Google AI rate limit exceeded. Please try again later.", this.providerName);
|
|
111
128
|
}
|
|
129
|
+
// Model not found errors — gate on a 404 status when available; fall
|
|
130
|
+
// back to literal phrase matching only when we have no status code at
|
|
131
|
+
// all. Avoids misclassifying permission/validation errors that happen
|
|
132
|
+
// to mention model resource paths (e.g. "...models/foo permission...").
|
|
133
|
+
if (statusCode === 404 ||
|
|
134
|
+
(statusCode === undefined &&
|
|
135
|
+
(message.includes("model not found") ||
|
|
136
|
+
message.includes("Model not found")))) {
|
|
137
|
+
return new InvalidModelError(`Model '${this.modelName}' not found. Please check the model name and ensure it is available.`, this.providerName);
|
|
138
|
+
}
|
|
139
|
+
// Network connectivity errors
|
|
140
|
+
if (message.includes("ECONNRESET") ||
|
|
141
|
+
message.includes("ENOTFOUND") ||
|
|
142
|
+
message.includes("ETIMEDOUT") ||
|
|
143
|
+
message.includes("ECONNREFUSED") ||
|
|
144
|
+
message.includes("network") ||
|
|
145
|
+
message.includes("connection")) {
|
|
146
|
+
return new NetworkError(`Connection error: ${message}`, this.providerName);
|
|
147
|
+
}
|
|
148
|
+
// Server errors (5xx)
|
|
149
|
+
if (message.includes("500") ||
|
|
150
|
+
message.includes("502") ||
|
|
151
|
+
message.includes("503") ||
|
|
152
|
+
message.includes("504") ||
|
|
153
|
+
message.includes("server error") ||
|
|
154
|
+
message.includes("Internal Server Error") ||
|
|
155
|
+
(statusCode && statusCode >= 500 && statusCode < 600)) {
|
|
156
|
+
return new ProviderError(`Google AI server error: ${message}. Please try again later.`, this.providerName);
|
|
157
|
+
}
|
|
112
158
|
return new ProviderError(`Google AI error: ${message}`, this.providerName);
|
|
113
159
|
}
|
|
114
160
|
/**
|
|
@@ -388,202 +434,53 @@ export class GoogleAIStudioProvider extends BaseProvider {
|
|
|
388
434
|
}
|
|
389
435
|
// executeGenerate removed - BaseProvider handles all generation with tools
|
|
390
436
|
async executeStream(options, analysisSchema) {
|
|
391
|
-
|
|
392
|
-
const gemini3CheckModelName = options.model || this.modelName;
|
|
393
|
-
// Structured output (analysisSchema, JSON format, or schema) is incompatible with tools on Gemini.
|
|
394
|
-
// Compute once and reuse in both the native Gemini 3 gate and the streamText fallback path.
|
|
395
|
-
const wantsStructuredOutput = analysisSchema || options.output?.format === "json" || options.schema;
|
|
396
|
-
// Check for tools from options AND from SDK (MCP tools)
|
|
397
|
-
// Need to check early if we should route to native SDK
|
|
398
|
-
const gemini3CheckShouldUseTools = !options.disableTools && this.supportsTools() && !wantsStructuredOutput;
|
|
399
|
-
const tools = options.tools || {};
|
|
400
|
-
const hasTools = gemini3CheckShouldUseTools && Object.keys(tools).length > 0;
|
|
401
|
-
if (isGemini3Model(gemini3CheckModelName) && hasTools) {
|
|
402
|
-
// Merge SDK tools into options for native SDK path
|
|
403
|
-
let mergedOptions = {
|
|
404
|
-
...options,
|
|
405
|
-
tools: tools,
|
|
406
|
-
};
|
|
407
|
-
// Check for tools + JSON schema conflict (Gemini limitation)
|
|
408
|
-
const wantsJsonOutput = options.output?.format === "json" || options.schema;
|
|
409
|
-
if (wantsJsonOutput &&
|
|
410
|
-
mergedOptions.tools &&
|
|
411
|
-
Object.keys(mergedOptions.tools).length > 0 &&
|
|
412
|
-
!mergedOptions.disableTools) {
|
|
413
|
-
logger.warn("[GoogleAIStudio] Gemini does not support tools and JSON schema output simultaneously. Disabling tools for this request.");
|
|
414
|
-
mergedOptions = { ...mergedOptions, disableTools: true, tools: {} };
|
|
415
|
-
}
|
|
416
|
-
// Only route to native path if tools are still active after conflict check
|
|
417
|
-
const hasActiveTools = !mergedOptions.disableTools &&
|
|
418
|
-
mergedOptions.tools &&
|
|
419
|
-
Object.keys(mergedOptions.tools).length > 0;
|
|
420
|
-
if (hasActiveTools) {
|
|
421
|
-
logger.info("[GoogleAIStudio] Routing Gemini 3 to native SDK for tool calling", {
|
|
422
|
-
model: gemini3CheckModelName,
|
|
423
|
-
totalToolCount: Object.keys(mergedOptions.tools ?? {}).length,
|
|
424
|
-
});
|
|
425
|
-
return this.executeNativeGemini3Stream(mergedOptions);
|
|
426
|
-
}
|
|
427
|
-
// Fall through to standard stream path using merged options (tools disabled for schema)
|
|
428
|
-
options = mergedOptions;
|
|
429
|
-
}
|
|
437
|
+
const modelName = options.model || this.modelName;
|
|
430
438
|
// Phase 1: if audio input present, bridge to Gemini Live (Studio) using @google/genai
|
|
431
439
|
if (options.input?.audio) {
|
|
432
440
|
return await this.executeAudioStreamViaGeminiLive(options);
|
|
433
441
|
}
|
|
434
|
-
|
|
435
|
-
const
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
if (sanitized.dropped.length > 0) {
|
|
456
|
-
logger.warn(`[GoogleAIStudio] Dropped ${sanitized.dropped.length} incompatible tool(s): ${sanitized.dropped.join(", ")}`);
|
|
457
|
-
}
|
|
458
|
-
tools =
|
|
459
|
-
Object.keys(sanitized.tools).length > 0 ? sanitized.tools : undefined;
|
|
460
|
-
}
|
|
461
|
-
else {
|
|
462
|
-
tools = undefined;
|
|
463
|
-
}
|
|
464
|
-
// Build message array from options with multimodal support
|
|
465
|
-
// Using protected helper from BaseProvider to eliminate code duplication
|
|
466
|
-
const messages = await this.buildMessagesForStream(options);
|
|
467
|
-
const collectedToolCalls = [];
|
|
468
|
-
const collectedToolResults = [];
|
|
469
|
-
// Reviewer follow-up: capture upstream provider errors via onError
|
|
470
|
-
// so the post-stream NoOutput sentinel carries the real cause.
|
|
471
|
-
let capturedProviderError;
|
|
472
|
-
const result = await streamText({
|
|
473
|
-
model,
|
|
474
|
-
messages: messages,
|
|
475
|
-
temperature: options.temperature,
|
|
476
|
-
maxOutputTokens: options.maxTokens, // No default limit - unlimited unless specified
|
|
477
|
-
tools,
|
|
478
|
-
stopWhen: stepCountIs(options.maxSteps || DEFAULT_MAX_STEPS),
|
|
479
|
-
toolChoice: resolveToolChoice(options, tools, shouldUseTools),
|
|
480
|
-
abortSignal: composeAbortSignals(options.abortSignal, timeoutController?.controller.signal),
|
|
481
|
-
experimental_telemetry: this.telemetryHandler.getTelemetryConfig(options),
|
|
482
|
-
experimental_repairToolCall: this.getToolCallRepairFn(options),
|
|
483
|
-
onError: (event) => {
|
|
484
|
-
capturedProviderError = event.error;
|
|
485
|
-
logger.error("GoogleAiStudio: Stream error", {
|
|
486
|
-
error: event.error instanceof Error
|
|
487
|
-
? event.error.message
|
|
488
|
-
: String(event.error),
|
|
489
|
-
});
|
|
490
|
-
},
|
|
491
|
-
// Gemini 3: use thinkingLevel via providerOptions
|
|
492
|
-
// Gemini 2.5: use thinkingBudget via providerOptions
|
|
493
|
-
...(options.thinkingConfig?.enabled && {
|
|
494
|
-
providerOptions: {
|
|
495
|
-
google: {
|
|
496
|
-
thinkingConfig: {
|
|
497
|
-
...(options.thinkingConfig.thinkingLevel && {
|
|
498
|
-
thinkingLevel: options.thinkingConfig.thinkingLevel,
|
|
499
|
-
}),
|
|
500
|
-
...(options.thinkingConfig.budgetTokens &&
|
|
501
|
-
!options.thinkingConfig.thinkingLevel && {
|
|
502
|
-
thinkingBudget: options.thinkingConfig.budgetTokens,
|
|
503
|
-
}),
|
|
504
|
-
includeThoughts: true,
|
|
505
|
-
},
|
|
506
|
-
},
|
|
507
|
-
},
|
|
508
|
-
}),
|
|
509
|
-
onStepFinish: ({ toolCalls, toolResults }) => {
|
|
510
|
-
for (const toolCall of toolCalls) {
|
|
511
|
-
collectedToolCalls.push({
|
|
512
|
-
toolCallId: toolCall.toolCallId,
|
|
513
|
-
toolName: toolCall.toolName,
|
|
514
|
-
args: toolCall.args ??
|
|
515
|
-
toolCall.input ??
|
|
516
|
-
toolCall
|
|
517
|
-
.parameters ??
|
|
518
|
-
{},
|
|
519
|
-
});
|
|
520
|
-
}
|
|
521
|
-
for (const toolResult of toolResults) {
|
|
522
|
-
const rawToolResult = toolResult;
|
|
523
|
-
collectedToolResults.push({
|
|
524
|
-
toolName: toolResult.toolName,
|
|
525
|
-
status: rawToolResult.error ? "failure" : "success",
|
|
526
|
-
output: (rawToolResult.output ??
|
|
527
|
-
rawToolResult.result) ??
|
|
528
|
-
undefined,
|
|
529
|
-
error: rawToolResult.error,
|
|
530
|
-
id: rawToolResult.toolCallId ?? toolResult.toolName,
|
|
531
|
-
});
|
|
532
|
-
}
|
|
533
|
-
// Emit tool:end for each completed tool result so Pipeline B
|
|
534
|
-
// captures telemetry for AI-SDK-driven tool calls (gap S2).
|
|
535
|
-
emitToolEndFromStepFinish(this.neurolink?.getEventEmitter(), toolResults);
|
|
536
|
-
this.handleToolExecutionStorage(toolCalls, toolResults, options, new Date()).catch((error) => {
|
|
537
|
-
logger.warn("[GoogleAiStudioProvider] Failed to store tool executions", {
|
|
538
|
-
provider: this.providerName,
|
|
539
|
-
error: error instanceof Error ? error.message : String(error),
|
|
540
|
-
});
|
|
541
|
-
});
|
|
542
|
-
},
|
|
543
|
-
});
|
|
544
|
-
// Defer timeout cleanup until the stream completes or errors.
|
|
545
|
-
// Guard against NoOutputGeneratedError becoming an unhandled rejection.
|
|
546
|
-
Promise.resolve(result.text)
|
|
547
|
-
.catch((err) => {
|
|
548
|
-
logger.debug("Stream text promise rejected (expected for empty streams)", {
|
|
549
|
-
error: err instanceof Error ? err.message : String(err),
|
|
550
|
-
});
|
|
551
|
-
})
|
|
552
|
-
.finally(() => timeoutController?.cleanup());
|
|
553
|
-
// Transform string stream to content object stream using BaseProvider method
|
|
554
|
-
const transformedStream = this.createTextStream(result, () => capturedProviderError);
|
|
555
|
-
// Create analytics promise that resolves after stream completion
|
|
556
|
-
const analyticsPromise = streamAnalyticsCollector.createAnalytics(this.providerName, this.modelName, toAnalyticsStreamResult(result), Date.now() - startTime, {
|
|
557
|
-
requestId: `google-ai-stream-${Date.now()}`,
|
|
558
|
-
streamingMode: true,
|
|
559
|
-
});
|
|
560
|
-
return {
|
|
561
|
-
stream: transformedStream,
|
|
562
|
-
provider: this.providerName,
|
|
563
|
-
model: this.modelName,
|
|
564
|
-
...(shouldUseTools && {
|
|
565
|
-
toolCalls: collectedToolCalls,
|
|
566
|
-
toolResults: collectedToolResults,
|
|
567
|
-
}),
|
|
568
|
-
analytics: analyticsPromise,
|
|
569
|
-
metadata: {
|
|
570
|
-
startTime,
|
|
571
|
-
streamId: `google-ai-${Date.now()}`,
|
|
572
|
-
},
|
|
573
|
-
};
|
|
442
|
+
// Structured output (analysisSchema, JSON format, or schema) is incompatible with tools on Gemini.
|
|
443
|
+
const wantsStructuredOutput = analysisSchema || options.output?.format === "json" || options.schema;
|
|
444
|
+
// Tool filter (a0269210): trust options.tools — caller (BaseProvider.stream)
|
|
445
|
+
// already merged MCP/built-in tools with user tools and applied any
|
|
446
|
+
// enabledToolNames filter. Re-attaching getAllTools() here would clobber
|
|
447
|
+
// that filter and re-introduce filtered-out tools.
|
|
448
|
+
const shouldUseTools = !options.disableTools && this.supportsTools() && !wantsStructuredOutput;
|
|
449
|
+
const optionTools = options.tools || {};
|
|
450
|
+
// Merge into options for native SDK path
|
|
451
|
+
let mergedOptions = {
|
|
452
|
+
...options,
|
|
453
|
+
tools: optionTools,
|
|
454
|
+
};
|
|
455
|
+
// Check for tools + JSON schema conflict (Gemini limitation)
|
|
456
|
+
const wantsJsonOutput = options.output?.format === "json" || options.schema;
|
|
457
|
+
if (wantsJsonOutput &&
|
|
458
|
+
mergedOptions.tools &&
|
|
459
|
+
Object.keys(mergedOptions.tools).length > 0 &&
|
|
460
|
+
!mergedOptions.disableTools) {
|
|
461
|
+
logger.warn("[GoogleAIStudio] Gemini does not support tools and JSON schema output simultaneously. Disabling tools for this request.");
|
|
462
|
+
mergedOptions = { ...mergedOptions, disableTools: true, tools: {} };
|
|
574
463
|
}
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
464
|
+
const hasActiveTools = shouldUseTools &&
|
|
465
|
+
!mergedOptions.disableTools &&
|
|
466
|
+
mergedOptions.tools &&
|
|
467
|
+
Object.keys(mergedOptions.tools).length > 0;
|
|
468
|
+
if (hasActiveTools) {
|
|
469
|
+
logger.info("[GoogleAIStudio] Routing to native @google/genai SDK for tool calling", {
|
|
470
|
+
model: modelName,
|
|
471
|
+
totalToolCount: Object.keys(mergedOptions.tools ?? {}).length,
|
|
472
|
+
});
|
|
578
473
|
}
|
|
474
|
+
// Route ALL models through native @google/genai SDK (no more @ai-sdk/google dependency)
|
|
475
|
+
return this.executeNativeGemini3Stream(mergedOptions);
|
|
579
476
|
}
|
|
580
477
|
/**
|
|
581
|
-
* Execute stream using native @google/genai SDK
|
|
582
|
-
*
|
|
478
|
+
* Execute stream using native @google/genai SDK
|
|
479
|
+
* Uses @google/genai directly for all Gemini models (2.0, 2.5, 3.x)
|
|
583
480
|
*/
|
|
584
481
|
async executeNativeGemini3Stream(options) {
|
|
585
482
|
const modelName = options.model || this.modelName;
|
|
586
|
-
return
|
|
483
|
+
return withClientStreamSpan({
|
|
587
484
|
name: "neurolink.provider.stream",
|
|
588
485
|
tracer: tracers.provider,
|
|
589
486
|
attributes: {
|
|
@@ -603,23 +500,54 @@ export class GoogleAIStudioProvider extends BaseProvider {
|
|
|
603
500
|
model: modelName,
|
|
604
501
|
hasTools: !!options.tools && Object.keys(options.tools).length > 0,
|
|
605
502
|
});
|
|
606
|
-
// Build contents from input
|
|
607
|
-
|
|
503
|
+
// Build contents from input. Prepend prior conversation turns so
|
|
504
|
+
// multi-turn callers (memory, loop REPL, agent flows) actually
|
|
505
|
+
// carry context — the previous build started fresh from the
|
|
506
|
+
// current user input only, which silently dropped history.
|
|
507
|
+
//
|
|
508
|
+
// `buildUserPartsWithMultimodal` is the shared helper that also
|
|
509
|
+
// attaches `input.images` and `input.pdfFiles` as `inlineData`
|
|
510
|
+
// parts. The previous AI Studio path pushed only `{ text }` and
|
|
511
|
+
// silently dropped both, which is why the model legitimately
|
|
512
|
+
// reported "no image attached" on multimodal calls.
|
|
513
|
+
const currentContents = [];
|
|
514
|
+
prependConversationMessages(currentContents, options.conversationMessages);
|
|
515
|
+
const userParts = await buildUserPartsWithMultimodal(options.input, options.input.text, "[GoogleAIStudio:stream]");
|
|
516
|
+
currentContents.push({
|
|
517
|
+
role: "user",
|
|
518
|
+
parts: userParts,
|
|
519
|
+
});
|
|
608
520
|
// Convert tools
|
|
609
521
|
let toolsConfig;
|
|
610
522
|
let executeMap = new Map();
|
|
523
|
+
let originalNameMap = new Map();
|
|
611
524
|
if (options.tools &&
|
|
612
525
|
Object.keys(options.tools).length > 0 &&
|
|
613
526
|
!options.disableTools) {
|
|
614
527
|
const result = buildNativeToolDeclarations(options.tools);
|
|
615
528
|
toolsConfig = result.toolsConfig;
|
|
616
529
|
executeMap = result.executeMap;
|
|
530
|
+
originalNameMap = result.originalNameMap;
|
|
617
531
|
logger.debug("[GoogleAIStudio] Converted tools for native SDK", {
|
|
618
532
|
toolCount: toolsConfig[0].functionDeclarations.length,
|
|
619
533
|
toolNames: toolsConfig[0].functionDeclarations.map((t) => t.name),
|
|
620
534
|
});
|
|
621
535
|
}
|
|
622
|
-
|
|
536
|
+
// Native JSON / schema enforcement: when no tools are being sent
|
|
537
|
+
// (the AI Studio orchestrator above already force-disables tools
|
|
538
|
+
// whenever JSON/schema output is requested), enforce the response
|
|
539
|
+
// shape natively via responseMimeType / responseSchema. Without
|
|
540
|
+
// this, JSON output was best-effort prompting only.
|
|
541
|
+
const wantsNativeJson = !toolsConfig &&
|
|
542
|
+
(options.output?.format === "json" || !!options.schema);
|
|
543
|
+
const nativeResponseSchema = wantsNativeJson && options.schema
|
|
544
|
+
? buildGeminiResponseSchema(options.schema)
|
|
545
|
+
: undefined;
|
|
546
|
+
const config = buildNativeConfig({
|
|
547
|
+
...options,
|
|
548
|
+
wantsJsonOutput: wantsNativeJson,
|
|
549
|
+
responseSchema: nativeResponseSchema,
|
|
550
|
+
}, toolsConfig);
|
|
623
551
|
const maxSteps = computeMaxSteps(options.maxSteps);
|
|
624
552
|
// Compose abort signal from user signal + timeout
|
|
625
553
|
const composedSignal = composeAbortSignals(options.abortSignal, timeoutController?.controller.signal);
|
|
@@ -698,7 +626,7 @@ export class GoogleAIStudioProvider extends BaseProvider {
|
|
|
698
626
|
logger.debug(`[GoogleAIStudio] Executing ${chunkResult.stepFunctionCalls.length} function calls`);
|
|
699
627
|
// Add model response with ALL parts (including thoughtSignature) to history
|
|
700
628
|
pushModelResponseToHistory(currentContents, chunkResult.rawResponseParts, chunkResult.stepFunctionCalls);
|
|
701
|
-
const functionResponses = await executeNativeToolCalls("[GoogleAIStudio]", chunkResult.stepFunctionCalls, executeMap, failedTools, allToolCalls, { abortSignal: composedSignal });
|
|
629
|
+
const functionResponses = await executeNativeToolCalls("[GoogleAIStudio]", chunkResult.stepFunctionCalls, executeMap, failedTools, allToolCalls, { abortSignal: composedSignal, originalNameMap });
|
|
702
630
|
// Add function responses to history — the @google/genai SDK
|
|
703
631
|
// only accepts "user" and "model" as valid roles in contents.
|
|
704
632
|
// Function/tool responses must use role: "user" (matching the
|
|
@@ -742,68 +670,9 @@ export class GoogleAIStudioProvider extends BaseProvider {
|
|
|
742
670
|
requestDuration: responseTime,
|
|
743
671
|
timestamp: new Date().toISOString(),
|
|
744
672
|
});
|
|
745
|
-
// Emit generation:end so Pipeline B (Langfuse) creates a GENERATION
|
|
746
|
-
// observation. The native @google/genai stream path bypasses the Vercel
|
|
747
|
-
// AI SDK so experimental_telemetry is never injected; we emit manually.
|
|
748
|
-
const nativeStreamEmitter = this.neurolink?.getEventEmitter();
|
|
749
|
-
if (nativeStreamEmitter) {
|
|
750
|
-
// Curator P2-4 dedup: flag the per-stream context attached
|
|
751
|
-
// to options so the orchestration skips its own emit.
|
|
752
|
-
markStreamProviderEmittedGenerationEnd(options);
|
|
753
|
-
nativeStreamEmitter.emit("generation:end", {
|
|
754
|
-
provider: this.providerName,
|
|
755
|
-
responseTime,
|
|
756
|
-
timestamp: Date.now(),
|
|
757
|
-
result: {
|
|
758
|
-
content: "",
|
|
759
|
-
usage: {
|
|
760
|
-
input: totalInputTokens,
|
|
761
|
-
output: totalOutputTokens,
|
|
762
|
-
total: totalInputTokens + totalOutputTokens,
|
|
763
|
-
},
|
|
764
|
-
model: modelName,
|
|
765
|
-
provider: this.providerName,
|
|
766
|
-
finishReason: hitStepLimitWithoutFinalAnswer
|
|
767
|
-
? "max_steps"
|
|
768
|
-
: "stop",
|
|
769
|
-
},
|
|
770
|
-
success: true,
|
|
771
|
-
});
|
|
772
|
-
}
|
|
773
673
|
channel.close();
|
|
774
674
|
}
|
|
775
675
|
catch (err) {
|
|
776
|
-
// Propagate error to OTel span so traces show ERROR status
|
|
777
|
-
span.recordException(err instanceof Error ? err : new Error(String(err)));
|
|
778
|
-
span.setStatus({
|
|
779
|
-
code: SpanStatusCode.ERROR,
|
|
780
|
-
message: err instanceof Error ? err.message : String(err),
|
|
781
|
-
});
|
|
782
|
-
// Emit failure generation:end so Pipeline B records the failed stream
|
|
783
|
-
const errorEmitter = this.neurolink?.getEventEmitter();
|
|
784
|
-
if (errorEmitter) {
|
|
785
|
-
// Curator P2-4 dedup: flag the per-stream context attached
|
|
786
|
-
// to options so the orchestration skips its own emit.
|
|
787
|
-
markStreamProviderEmittedGenerationEnd(options);
|
|
788
|
-
errorEmitter.emit("generation:end", {
|
|
789
|
-
provider: this.providerName,
|
|
790
|
-
responseTime: Date.now() - startTime,
|
|
791
|
-
timestamp: Date.now(),
|
|
792
|
-
result: {
|
|
793
|
-
content: "",
|
|
794
|
-
usage: {
|
|
795
|
-
input: totalInputTokens,
|
|
796
|
-
output: totalOutputTokens,
|
|
797
|
-
total: totalInputTokens + totalOutputTokens,
|
|
798
|
-
},
|
|
799
|
-
model: modelName,
|
|
800
|
-
provider: this.providerName,
|
|
801
|
-
finishReason: "error",
|
|
802
|
-
},
|
|
803
|
-
success: false,
|
|
804
|
-
error: err instanceof Error ? err.message : String(err),
|
|
805
|
-
});
|
|
806
|
-
}
|
|
807
676
|
channel.error(err);
|
|
808
677
|
analyticsReject(err);
|
|
809
678
|
}
|
|
@@ -826,7 +695,7 @@ export class GoogleAIStudioProvider extends BaseProvider {
|
|
|
826
695
|
finally {
|
|
827
696
|
// Timeout controller cleanup is managed inside the background loop
|
|
828
697
|
}
|
|
829
|
-
});
|
|
698
|
+
}, (r) => r.stream, (r, wrapped) => ({ ...r, stream: wrapped }));
|
|
830
699
|
}
|
|
831
700
|
/**
|
|
832
701
|
* Execute generate using native @google/genai SDK for Gemini 3 models
|
|
@@ -858,10 +727,24 @@ export class GoogleAIStudioProvider extends BaseProvider {
|
|
|
858
727
|
// Prefer input.text over prompt — processCSVFilesForNativeSDK enriches
|
|
859
728
|
// input.text with inlined CSV data, so using prompt first would discard it.
|
|
860
729
|
const promptText = options.input?.text || options.prompt || "";
|
|
861
|
-
|
|
862
|
-
//
|
|
730
|
+
// Prepend prior conversation turns so multi-turn generate calls
|
|
731
|
+
// see history; otherwise the native generate path silently drops
|
|
732
|
+
// every turn before the current prompt.
|
|
733
|
+
//
|
|
734
|
+
// `buildUserPartsWithMultimodal` also attaches inline image / PDF
|
|
735
|
+
// parts. Without it the request body was text-only and the model
|
|
736
|
+
// legitimately reported "no image / PDF attached".
|
|
737
|
+
const currentContents = [];
|
|
738
|
+
prependConversationMessages(currentContents, options.conversationMessages);
|
|
739
|
+
const userParts = await buildUserPartsWithMultimodal(options.input, promptText, "[GoogleAIStudio:generate]");
|
|
740
|
+
currentContents.push({
|
|
741
|
+
role: "user",
|
|
742
|
+
parts: userParts,
|
|
743
|
+
});
|
|
744
|
+
// Convert tools (a0269210: trust options.tools — already merged + filtered upstream)
|
|
863
745
|
let toolsConfig;
|
|
864
746
|
let executeMap = new Map();
|
|
747
|
+
let originalNameMap = new Map();
|
|
865
748
|
const shouldUseTools = !options.disableTools;
|
|
866
749
|
if (shouldUseTools) {
|
|
867
750
|
const tools = options.tools || {};
|
|
@@ -869,13 +752,26 @@ export class GoogleAIStudioProvider extends BaseProvider {
|
|
|
869
752
|
const result = buildNativeToolDeclarations(tools);
|
|
870
753
|
toolsConfig = result.toolsConfig;
|
|
871
754
|
executeMap = result.executeMap;
|
|
755
|
+
originalNameMap = result.originalNameMap;
|
|
872
756
|
logger.debug("[GoogleAIStudio] Converted tools for native SDK generate", {
|
|
873
757
|
toolCount: toolsConfig[0].functionDeclarations.length,
|
|
874
758
|
toolNames: toolsConfig[0].functionDeclarations.map((t) => t.name),
|
|
875
759
|
});
|
|
876
760
|
}
|
|
877
761
|
}
|
|
878
|
-
|
|
762
|
+
// Native JSON / schema enforcement (generate path). Mirrors the
|
|
763
|
+
// stream block above; only set when no tools are being sent
|
|
764
|
+
// because Gemini cannot combine function calling with JSON mime.
|
|
765
|
+
const wantsNativeJson = !toolsConfig &&
|
|
766
|
+
(options.output?.format === "json" || !!options.schema);
|
|
767
|
+
const nativeResponseSchema = wantsNativeJson && options.schema
|
|
768
|
+
? buildGeminiResponseSchema(options.schema)
|
|
769
|
+
: undefined;
|
|
770
|
+
const config = buildNativeConfig({
|
|
771
|
+
...options,
|
|
772
|
+
wantsJsonOutput: wantsNativeJson,
|
|
773
|
+
responseSchema: nativeResponseSchema,
|
|
774
|
+
}, toolsConfig);
|
|
879
775
|
const composedSignal = composeAbortSignals(options.abortSignal, timeoutController?.controller.signal);
|
|
880
776
|
const maxSteps = computeMaxSteps(options.maxSteps);
|
|
881
777
|
let finalText = "";
|
|
@@ -925,7 +821,11 @@ export class GoogleAIStudioProvider extends BaseProvider {
|
|
|
925
821
|
// Add model response with ALL parts (including thoughtSignature) to history
|
|
926
822
|
// This is critical for Gemini 3 - it requires thought signatures in subsequent turns
|
|
927
823
|
pushModelResponseToHistory(currentContents, chunkResult.rawResponseParts, chunkResult.stepFunctionCalls);
|
|
928
|
-
const functionResponses = await executeNativeToolCalls("[GoogleAIStudio]", chunkResult.stepFunctionCalls, executeMap, failedTools, allToolCalls, {
|
|
824
|
+
const functionResponses = await executeNativeToolCalls("[GoogleAIStudio]", chunkResult.stepFunctionCalls, executeMap, failedTools, allToolCalls, {
|
|
825
|
+
toolExecutions,
|
|
826
|
+
abortSignal: composedSignal,
|
|
827
|
+
originalNameMap,
|
|
828
|
+
});
|
|
929
829
|
// Add function responses to history — the @google/genai SDK
|
|
930
830
|
// only accepts "user" and "model" as valid roles in contents.
|
|
931
831
|
// Function/tool responses must use role: "user" (matching the
|
|
@@ -946,31 +846,11 @@ export class GoogleAIStudioProvider extends BaseProvider {
|
|
|
946
846
|
span.setAttribute(ATTR.GEN_AI_INPUT_TOKENS, totalInputTokens);
|
|
947
847
|
span.setAttribute(ATTR.GEN_AI_OUTPUT_TOKENS, totalOutputTokens);
|
|
948
848
|
span.setAttribute(ATTR.GEN_AI_FINISH_REASON, step >= maxSteps ? "max_steps" : "stop");
|
|
949
|
-
//
|
|
950
|
-
//
|
|
951
|
-
//
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
nativeGenerateEmitter.emit("generation:end", {
|
|
955
|
-
provider: this.providerName,
|
|
956
|
-
responseTime,
|
|
957
|
-
timestamp: Date.now(),
|
|
958
|
-
result: {
|
|
959
|
-
content: finalText,
|
|
960
|
-
usage: {
|
|
961
|
-
input: totalInputTokens,
|
|
962
|
-
output: totalOutputTokens,
|
|
963
|
-
total: totalInputTokens + totalOutputTokens,
|
|
964
|
-
},
|
|
965
|
-
model: modelName,
|
|
966
|
-
provider: this.providerName,
|
|
967
|
-
finishReason: step >= maxSteps ? "max_steps" : "stop",
|
|
968
|
-
},
|
|
969
|
-
success: true,
|
|
970
|
-
});
|
|
971
|
-
}
|
|
972
|
-
// Build EnhancedGenerateResult
|
|
973
|
-
return {
|
|
849
|
+
// Build EnhancedGenerateResult and route through enhanceResult so
|
|
850
|
+
// analytics / evaluation / tracing stay attached. The native AI
|
|
851
|
+
// Studio generate path bypasses BaseProvider.generate(), so
|
|
852
|
+
// skipping enhanceResult would silently drop those features.
|
|
853
|
+
const baseResult = {
|
|
974
854
|
content: finalText,
|
|
975
855
|
provider: this.providerName,
|
|
976
856
|
model: modelName,
|
|
@@ -984,6 +864,7 @@ export class GoogleAIStudioProvider extends BaseProvider {
|
|
|
984
864
|
toolExecutions: toolExecutions,
|
|
985
865
|
enhancedWithTools: allToolCalls.length > 0,
|
|
986
866
|
};
|
|
867
|
+
return this.enhanceResult(baseResult, options, startTime);
|
|
987
868
|
}
|
|
988
869
|
finally {
|
|
989
870
|
timeoutController?.cleanup();
|
|
@@ -999,40 +880,147 @@ export class GoogleAIStudioProvider extends BaseProvider {
|
|
|
999
880
|
? { prompt: optionsOrPrompt }
|
|
1000
881
|
: optionsOrPrompt;
|
|
1001
882
|
const modelName = options.model || this.modelName;
|
|
1002
|
-
//
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
883
|
+
// Image-generation models reject function-calling. Route them to
|
|
884
|
+
// executeImageGeneration without merging tools. This must happen
|
|
885
|
+
// BEFORE getToolsForStream to avoid leaking registered (MCP / built-in)
|
|
886
|
+
// tools into the image API request, which trips
|
|
887
|
+
// "Function calling is not enabled for this model".
|
|
888
|
+
// startsWith (not includes) so a hypothetical text model whose ID
|
|
889
|
+
// contains an image-model string as a substring isn't silently routed
|
|
890
|
+
// to executeImageGeneration and stripped of tool support.
|
|
891
|
+
const isImageModel = IMAGE_GENERATION_MODELS.some((m) => modelName.toLowerCase().startsWith(m.toLowerCase()));
|
|
892
|
+
if (isImageModel) {
|
|
893
|
+
logger.info("[GoogleAIStudio] Routing image generation model to executeImageGeneration", { model: modelName });
|
|
894
|
+
return this.executeImageGeneration(options);
|
|
895
|
+
}
|
|
896
|
+
// TTS direct-synthesis mode: synthesise the input text directly (no LLM
|
|
897
|
+
// call). BaseProvider.runGenerateInActiveContext does the same dispatch
|
|
898
|
+
// — replicated here because AI Studio's override bypasses that path.
|
|
899
|
+
if (options.tts?.enabled && !options.tts?.useAiResponse) {
|
|
900
|
+
logger.info("[GoogleAIStudio] Routing TTS direct-synthesis to handleDirectTTSSynthesis", { model: modelName });
|
|
901
|
+
return this.handleDirectTTSSynthesis(options, Date.now());
|
|
902
|
+
}
|
|
903
|
+
// Process the unified `input.files` array before routing to the
|
|
904
|
+
// native SDK. BaseProvider.generate() runs this preprocessing via
|
|
905
|
+
// buildMultimodalMessagesArray, but AI Studio's override skips it,
|
|
906
|
+
// which would otherwise drop text-file content (and the
|
|
907
|
+
// mimetype-hint contract) on the floor. Mutates options.input.text /
|
|
908
|
+
// options.input.images / options.input.pdfFiles in place.
|
|
909
|
+
if (options.input?.files && options.input.files.length > 0) {
|
|
910
|
+
try {
|
|
911
|
+
await processUnifiedFilesArray(options, 100 * 1024 * 1024, this.providerName);
|
|
1019
912
|
}
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
mergedOptions.tools &&
|
|
1023
|
-
Object.keys(mergedOptions.tools).length > 0;
|
|
1024
|
-
if (hasActiveTools) {
|
|
1025
|
-
logger.info("[GoogleAIStudio] Routing Gemini 3 generate to native SDK for tool calling", {
|
|
1026
|
-
model: modelName,
|
|
1027
|
-
totalToolCount: Object.keys(mergedOptions.tools ?? {}).length,
|
|
1028
|
-
});
|
|
1029
|
-
return this.executeNativeGemini3Generate(mergedOptions);
|
|
913
|
+
catch (fileError) {
|
|
914
|
+
logger.warn(`[GoogleAIStudio] processUnifiedFilesArray threw, continuing without file content: ${fileError instanceof Error ? fileError.message : String(fileError)}`);
|
|
1030
915
|
}
|
|
1031
|
-
// Fall through to standard generate path using merged options (tools disabled for schema)
|
|
1032
|
-
return super.generate(mergedOptions);
|
|
1033
916
|
}
|
|
1034
|
-
//
|
|
1035
|
-
|
|
917
|
+
// Merge registered (built-in / MCP) tools with caller-supplied tools.
|
|
918
|
+
// AI Studio's generate() bypasses BaseProvider.generate(), so the
|
|
919
|
+
// ToolsManager-driven merge that normally injects sdk.registerTool()
|
|
920
|
+
// entries never runs here. Without this call, registered tools never
|
|
921
|
+
// reach the native function-calling path.
|
|
922
|
+
const baseTools = !options.disableTools
|
|
923
|
+
? await this.getToolsForStream(options)
|
|
924
|
+
: {};
|
|
925
|
+
let mergedOptions = {
|
|
926
|
+
...options,
|
|
927
|
+
tools: baseTools,
|
|
928
|
+
};
|
|
929
|
+
// Check for tools + JSON schema conflict (Gemini limitation)
|
|
930
|
+
const wantsJsonOutput = options.output?.format === "json" || options.schema;
|
|
931
|
+
if (wantsJsonOutput &&
|
|
932
|
+
mergedOptions.tools &&
|
|
933
|
+
Object.keys(mergedOptions.tools).length > 0 &&
|
|
934
|
+
!mergedOptions.disableTools) {
|
|
935
|
+
logger.warn("[GoogleAIStudio] Gemini does not support tools and JSON schema output simultaneously. Disabling tools for this request.");
|
|
936
|
+
mergedOptions = { ...mergedOptions, disableTools: true, tools: {} };
|
|
937
|
+
}
|
|
938
|
+
const hasActiveTools = !mergedOptions.disableTools &&
|
|
939
|
+
mergedOptions.tools &&
|
|
940
|
+
Object.keys(mergedOptions.tools).length > 0;
|
|
941
|
+
if (hasActiveTools) {
|
|
942
|
+
logger.info("[GoogleAIStudio] Routing generate to native @google/genai SDK for tool calling", {
|
|
943
|
+
model: modelName,
|
|
944
|
+
totalToolCount: Object.keys(mergedOptions.tools ?? {}).length,
|
|
945
|
+
});
|
|
946
|
+
}
|
|
947
|
+
// Route ALL models through native @google/genai SDK (no more @ai-sdk/google dependency).
|
|
948
|
+
// Emit Pipeline B `generation:end` so the observability listener
|
|
949
|
+
// creates a `model.generation` span — AI Studio's native path bypasses
|
|
950
|
+
// the AI SDK + experimental_telemetry plumbing the same way Vertex's
|
|
951
|
+
// does, so the event has to be emitted manually.
|
|
952
|
+
const generateStartTime = Date.now();
|
|
953
|
+
const inputPrompt = mergedOptions.input?.text ||
|
|
954
|
+
mergedOptions.prompt ||
|
|
955
|
+
"";
|
|
956
|
+
try {
|
|
957
|
+
// Wrap in `neurolink.executeGeneration` so the observability span
|
|
958
|
+
// chain (Test: Generate Span Chain) sees a third inner span on the
|
|
959
|
+
// native @google/genai path — Pipeline A providers get this from
|
|
960
|
+
// GenerationHandler.executeGeneration; the native path bypasses
|
|
961
|
+
// GenerationHandler so we add the span here.
|
|
962
|
+
let result = await withSpan({
|
|
963
|
+
name: "neurolink.executeGeneration",
|
|
964
|
+
tracer: tracers.provider,
|
|
965
|
+
attributes: {
|
|
966
|
+
[ATTR.GEN_AI_SYSTEM]: this.providerName,
|
|
967
|
+
[ATTR.GEN_AI_MODEL]: modelName,
|
|
968
|
+
"neurolink.path": "native.google-genai",
|
|
969
|
+
},
|
|
970
|
+
}, async () => this.executeNativeGemini3Generate(mergedOptions));
|
|
971
|
+
// Pipe through TTS-of-AI-response when caller asks for it. No-op when
|
|
972
|
+
// tts is disabled or useAiResponse is false.
|
|
973
|
+
result = await this.synthesizeAIResponseIfNeeded(result, options);
|
|
974
|
+
this.emitPipelineBGenerationEvent(modelName, result, generateStartTime, true, undefined, inputPrompt);
|
|
975
|
+
return result;
|
|
976
|
+
}
|
|
977
|
+
catch (error) {
|
|
978
|
+
this.emitPipelineBGenerationEvent(modelName, null, generateStartTime, false, error, inputPrompt);
|
|
979
|
+
throw error;
|
|
980
|
+
}
|
|
981
|
+
}
|
|
982
|
+
/**
|
|
983
|
+
* Emit `generation:end` so the Pipeline B observability listener creates
|
|
984
|
+
* a `model.generation` span for native Google AI Studio generate calls.
|
|
985
|
+
* Without this hand-off the native path silently disappears from
|
|
986
|
+
* Pipeline B exporters (Langfuse, custom OTEL collectors).
|
|
987
|
+
*/
|
|
988
|
+
emitPipelineBGenerationEvent(modelName, result, startTime, success, error, prompt) {
|
|
989
|
+
const emitter = this.neurolink?.getEventEmitter();
|
|
990
|
+
if (!emitter) {
|
|
991
|
+
return;
|
|
992
|
+
}
|
|
993
|
+
const usage = result?.usage && typeof result.usage === "object"
|
|
994
|
+
? result.usage
|
|
995
|
+
: { input: 0, output: 0, total: 0 };
|
|
996
|
+
// Mark on the result so the SDK-level runStandardGenerateRequest knows
|
|
997
|
+
// this provider already emitted `generation:end` itself and skips its
|
|
998
|
+
// own duplicate emission. Without this flag the public event listener
|
|
999
|
+
// (and the observability test) would see two events per generate call.
|
|
1000
|
+
if (result && typeof result === "object") {
|
|
1001
|
+
result._generationEndEmitted =
|
|
1002
|
+
true;
|
|
1003
|
+
}
|
|
1004
|
+
emitter.emit("generation:end", {
|
|
1005
|
+
provider: this.providerName,
|
|
1006
|
+
responseTime: Date.now() - startTime,
|
|
1007
|
+
timestamp: Date.now(),
|
|
1008
|
+
// The Pipeline B listener reads `data.prompt` to populate the
|
|
1009
|
+
// `input` span attribute. Without this, the Observability Spans
|
|
1010
|
+
// test fails with "input capture not working".
|
|
1011
|
+
prompt: prompt || "",
|
|
1012
|
+
result: {
|
|
1013
|
+
content: result?.content || "",
|
|
1014
|
+
usage,
|
|
1015
|
+
model: modelName,
|
|
1016
|
+
provider: this.providerName,
|
|
1017
|
+
finishReason: success ? "stop" : "error",
|
|
1018
|
+
},
|
|
1019
|
+
success,
|
|
1020
|
+
...(error
|
|
1021
|
+
? { error: error instanceof Error ? error.message : String(error) }
|
|
1022
|
+
: {}),
|
|
1023
|
+
});
|
|
1036
1024
|
}
|
|
1037
1025
|
// ===================
|
|
1038
1026
|
// HELPER METHODS
|
|
@@ -1240,18 +1228,21 @@ export class GoogleAIStudioProvider extends BaseProvider {
|
|
|
1240
1228
|
});
|
|
1241
1229
|
try {
|
|
1242
1230
|
const apiKey = this.getApiKey();
|
|
1243
|
-
const
|
|
1244
|
-
const
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
value: text,
|
|
1231
|
+
const client = await createGoogleGenAIClient(apiKey);
|
|
1232
|
+
const result = await client.models.embedContent({
|
|
1233
|
+
model: embeddingModelName,
|
|
1234
|
+
contents: [text],
|
|
1248
1235
|
});
|
|
1236
|
+
const embedding = result.embeddings?.[0]?.values;
|
|
1237
|
+
if (!embedding) {
|
|
1238
|
+
throw new ProviderError("No embedding returned from Google AI", this.providerName);
|
|
1239
|
+
}
|
|
1249
1240
|
logger.debug("Embedding generated successfully", {
|
|
1250
1241
|
provider: this.providerName,
|
|
1251
1242
|
model: embeddingModelName,
|
|
1252
|
-
embeddingDimension:
|
|
1243
|
+
embeddingDimension: embedding.length,
|
|
1253
1244
|
});
|
|
1254
|
-
return
|
|
1245
|
+
return embedding;
|
|
1255
1246
|
}
|
|
1256
1247
|
catch (error) {
|
|
1257
1248
|
logger.error("Embedding generation failed", {
|
|
@@ -1277,19 +1268,19 @@ export class GoogleAIStudioProvider extends BaseProvider {
|
|
|
1277
1268
|
});
|
|
1278
1269
|
try {
|
|
1279
1270
|
const apiKey = this.getApiKey();
|
|
1280
|
-
const
|
|
1281
|
-
const
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
values: texts,
|
|
1271
|
+
const client = await createGoogleGenAIClient(apiKey);
|
|
1272
|
+
const result = await client.models.embedContent({
|
|
1273
|
+
model: embeddingModelName,
|
|
1274
|
+
contents: texts,
|
|
1285
1275
|
});
|
|
1276
|
+
const embeddings = (result.embeddings || []).map((e) => e.values || []);
|
|
1286
1277
|
logger.debug("Batch embeddings generated successfully", {
|
|
1287
1278
|
provider: this.providerName,
|
|
1288
1279
|
model: embeddingModelName,
|
|
1289
|
-
count:
|
|
1290
|
-
embeddingDimension:
|
|
1280
|
+
count: embeddings.length,
|
|
1281
|
+
embeddingDimension: embeddings[0]?.length,
|
|
1291
1282
|
});
|
|
1292
|
-
return
|
|
1283
|
+
return embeddings;
|
|
1293
1284
|
}
|
|
1294
1285
|
catch (error) {
|
|
1295
1286
|
logger.error("Batch embedding generation failed", {
|