@juspay/neurolink 9.65.0 → 9.65.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (266) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/dist/adapters/video/videoAnalyzer.d.ts +1 -1
  3. package/dist/agent/directTools.d.ts +9 -17
  4. package/dist/agent/directTools.js +12 -8
  5. package/dist/autoresearch/tools.d.ts +2 -214
  6. package/dist/autoresearch/tools.js +1 -1
  7. package/dist/browser/neurolink.min.js +362 -368
  8. package/dist/client/reactHooks.js +16 -8
  9. package/dist/client/reactHooks.tsx +24 -9
  10. package/dist/core/baseProvider.d.ts +1 -6
  11. package/dist/core/baseProvider.js +1 -1
  12. package/dist/core/constants.d.ts +1 -0
  13. package/dist/core/constants.js +3 -0
  14. package/dist/core/modules/GenerationHandler.d.ts +2 -2
  15. package/dist/core/modules/GenerationHandler.js +3 -1
  16. package/dist/core/modules/MessageBuilder.d.ts +1 -15
  17. package/dist/core/modules/MessageBuilder.js +0 -14
  18. package/dist/core/modules/StreamHandler.js +1 -1
  19. package/dist/core/modules/ToolsManager.d.ts +1 -17
  20. package/dist/core/modules/ToolsManager.js +1 -17
  21. package/dist/core/redisConversationMemoryManager.js +0 -6
  22. package/dist/core/streamAnalytics.js +1 -1
  23. package/dist/evaluation/contextBuilder.d.ts +1 -4
  24. package/dist/evaluation/contextBuilder.js +0 -3
  25. package/dist/evaluation/index.d.ts +1 -4
  26. package/dist/evaluation/index.js +0 -3
  27. package/dist/files/fileTools.d.ts +2 -18
  28. package/dist/files/fileTools.js +3 -19
  29. package/dist/lib/adapters/video/videoAnalyzer.d.ts +1 -1
  30. package/dist/lib/agent/directTools.d.ts +9 -17
  31. package/dist/lib/agent/directTools.js +12 -8
  32. package/dist/lib/autoresearch/tools.d.ts +2 -214
  33. package/dist/lib/autoresearch/tools.js +1 -1
  34. package/dist/lib/client/reactHooks.js +16 -8
  35. package/dist/lib/core/baseProvider.d.ts +1 -6
  36. package/dist/lib/core/baseProvider.js +1 -1
  37. package/dist/lib/core/constants.d.ts +1 -0
  38. package/dist/lib/core/constants.js +3 -0
  39. package/dist/lib/core/modules/GenerationHandler.d.ts +2 -2
  40. package/dist/lib/core/modules/GenerationHandler.js +3 -1
  41. package/dist/lib/core/modules/MessageBuilder.d.ts +1 -15
  42. package/dist/lib/core/modules/MessageBuilder.js +0 -14
  43. package/dist/lib/core/modules/StreamHandler.js +1 -1
  44. package/dist/lib/core/modules/ToolsManager.d.ts +1 -17
  45. package/dist/lib/core/modules/ToolsManager.js +1 -17
  46. package/dist/lib/core/redisConversationMemoryManager.js +0 -6
  47. package/dist/lib/core/streamAnalytics.js +1 -1
  48. package/dist/lib/evaluation/contextBuilder.d.ts +1 -4
  49. package/dist/lib/evaluation/contextBuilder.js +0 -3
  50. package/dist/lib/evaluation/index.d.ts +1 -4
  51. package/dist/lib/evaluation/index.js +0 -3
  52. package/dist/lib/files/fileTools.d.ts +2 -18
  53. package/dist/lib/files/fileTools.js +3 -19
  54. package/dist/lib/memory/memoryRetrievalTools.d.ts +2 -126
  55. package/dist/lib/memory/memoryRetrievalTools.js +1 -9
  56. package/dist/lib/middleware/builtin/autoEvaluation.d.ts +0 -3
  57. package/dist/lib/middleware/builtin/autoEvaluation.js +0 -3
  58. package/dist/lib/middleware/builtin/guardrails.js +1 -1
  59. package/dist/lib/middleware/builtin/lifecycle.d.ts +0 -9
  60. package/dist/lib/middleware/builtin/lifecycle.js +0 -9
  61. package/dist/lib/middleware/factory.d.ts +1 -1
  62. package/dist/lib/middleware/factory.js +1 -1
  63. package/dist/lib/middleware/registry.d.ts +1 -1
  64. package/dist/lib/neurolink.d.ts +14 -2
  65. package/dist/lib/neurolink.js +46 -18
  66. package/dist/lib/processors/media/AudioProcessor.js +8 -3
  67. package/dist/lib/providers/amazonBedrock.js +1 -2
  68. package/dist/lib/providers/amazonSagemaker.d.ts +1 -7
  69. package/dist/lib/providers/amazonSagemaker.js +0 -6
  70. package/dist/lib/providers/anthropic.d.ts +1 -1
  71. package/dist/lib/providers/anthropic.js +2 -1
  72. package/dist/lib/providers/anthropicBaseProvider.d.ts +1 -1
  73. package/dist/lib/providers/anthropicBaseProvider.js +2 -1
  74. package/dist/lib/providers/azureOpenai.d.ts +1 -1
  75. package/dist/lib/providers/azureOpenai.js +2 -1
  76. package/dist/lib/providers/cloudflare.d.ts +1 -1
  77. package/dist/lib/providers/cloudflare.js +2 -1
  78. package/dist/lib/providers/cohere.d.ts +1 -1
  79. package/dist/lib/providers/cohere.js +2 -1
  80. package/dist/lib/providers/deepseek.d.ts +1 -1
  81. package/dist/lib/providers/deepseek.js +2 -1
  82. package/dist/lib/providers/fireworks.d.ts +1 -1
  83. package/dist/lib/providers/fireworks.js +2 -1
  84. package/dist/lib/providers/googleAiStudio.d.ts +1 -1
  85. package/dist/lib/providers/googleAiStudio.js +82 -6
  86. package/dist/lib/providers/googleNativeGemini3.d.ts +3 -6
  87. package/dist/lib/providers/googleNativeGemini3.js +104 -9
  88. package/dist/lib/providers/googleVertex.d.ts +1 -1
  89. package/dist/lib/providers/googleVertex.js +466 -165
  90. package/dist/lib/providers/groq.d.ts +1 -1
  91. package/dist/lib/providers/groq.js +2 -1
  92. package/dist/lib/providers/huggingFace.d.ts +1 -1
  93. package/dist/lib/providers/huggingFace.js +3 -1
  94. package/dist/lib/providers/ideogram.d.ts +1 -1
  95. package/dist/lib/providers/jina.d.ts +1 -1
  96. package/dist/lib/providers/litellm.d.ts +1 -1
  97. package/dist/lib/providers/litellm.js +12 -6
  98. package/dist/lib/providers/llamaCpp.d.ts +1 -1
  99. package/dist/lib/providers/llamaCpp.js +2 -1
  100. package/dist/lib/providers/lmStudio.d.ts +1 -1
  101. package/dist/lib/providers/lmStudio.js +2 -1
  102. package/dist/lib/providers/mistral.d.ts +1 -1
  103. package/dist/lib/providers/mistral.js +2 -1
  104. package/dist/lib/providers/nvidiaNim.d.ts +1 -1
  105. package/dist/lib/providers/nvidiaNim.js +2 -1
  106. package/dist/lib/providers/ollama.d.ts +1 -1
  107. package/dist/lib/providers/ollama.js +1 -2
  108. package/dist/lib/providers/openAI.d.ts +1 -1
  109. package/dist/lib/providers/openAI.js +3 -1
  110. package/dist/lib/providers/openRouter.d.ts +1 -1
  111. package/dist/lib/providers/openRouter.js +3 -1
  112. package/dist/lib/providers/openaiCompatible.d.ts +1 -1
  113. package/dist/lib/providers/openaiCompatible.js +3 -1
  114. package/dist/lib/providers/perplexity.d.ts +1 -1
  115. package/dist/lib/providers/perplexity.js +2 -1
  116. package/dist/lib/providers/providerTypeUtils.d.ts +2 -7
  117. package/dist/lib/providers/providerTypeUtils.js +0 -6
  118. package/dist/lib/providers/recraft.d.ts +1 -1
  119. package/dist/lib/providers/replicate.d.ts +1 -1
  120. package/dist/lib/providers/stability.d.ts +1 -1
  121. package/dist/lib/providers/togetherAi.d.ts +1 -1
  122. package/dist/lib/providers/togetherAi.js +2 -1
  123. package/dist/lib/providers/voyage.d.ts +1 -1
  124. package/dist/lib/providers/xai.d.ts +1 -1
  125. package/dist/lib/providers/xai.js +2 -1
  126. package/dist/lib/proxy/claudeFormat.d.ts +0 -15
  127. package/dist/lib/proxy/claudeFormat.js +1 -11
  128. package/dist/lib/rag/ragIntegration.d.ts +1 -12
  129. package/dist/lib/rag/ragIntegration.js +0 -8
  130. package/dist/lib/tasks/tools/taskTools.d.ts +2 -117
  131. package/dist/lib/tasks/tools/taskTools.js +1 -10
  132. package/dist/lib/types/aliases.d.ts +1 -1
  133. package/dist/lib/types/conversation.d.ts +17 -0
  134. package/dist/lib/types/evaluation.d.ts +1 -5
  135. package/dist/lib/types/evaluation.js +0 -4
  136. package/dist/lib/types/generate.d.ts +2 -22
  137. package/dist/lib/types/guardrails.d.ts +1 -1
  138. package/dist/lib/types/middleware.d.ts +8 -3
  139. package/dist/lib/types/providers.d.ts +2 -1
  140. package/dist/lib/types/rag.d.ts +1 -1
  141. package/dist/lib/types/rag.js +0 -6
  142. package/dist/lib/types/stream.d.ts +2 -11
  143. package/dist/lib/types/tools.d.ts +2 -1
  144. package/dist/lib/utils/generation.d.ts +8 -0
  145. package/dist/lib/utils/generation.js +9 -0
  146. package/dist/lib/utils/generationErrors.d.ts +10 -0
  147. package/dist/lib/utils/generationErrors.js +11 -0
  148. package/dist/lib/utils/messageBuilder.d.ts +1 -6
  149. package/dist/lib/utils/messageBuilder.js +0 -5
  150. package/dist/lib/utils/noOutputSentinel.d.ts +0 -13
  151. package/dist/lib/utils/noOutputSentinel.js +1 -14
  152. package/dist/lib/utils/providerRetry.js +1 -1
  153. package/dist/lib/utils/tool.d.ts +8 -0
  154. package/dist/lib/utils/tool.js +9 -0
  155. package/dist/lib/utils/toolCallRepair.d.ts +1 -16
  156. package/dist/lib/utils/toolCallRepair.js +1 -16
  157. package/dist/lib/utils/toolChoice.d.ts +1 -1
  158. package/dist/lib/utils/videoAnalysisProcessor.d.ts +1 -8
  159. package/dist/lib/utils/videoAnalysisProcessor.js +0 -7
  160. package/dist/memory/memoryRetrievalTools.d.ts +2 -126
  161. package/dist/memory/memoryRetrievalTools.js +1 -9
  162. package/dist/middleware/builtin/autoEvaluation.d.ts +0 -3
  163. package/dist/middleware/builtin/autoEvaluation.js +0 -3
  164. package/dist/middleware/builtin/guardrails.js +1 -1
  165. package/dist/middleware/builtin/lifecycle.d.ts +0 -9
  166. package/dist/middleware/builtin/lifecycle.js +0 -9
  167. package/dist/middleware/factory.d.ts +1 -1
  168. package/dist/middleware/factory.js +1 -1
  169. package/dist/middleware/registry.d.ts +1 -1
  170. package/dist/neurolink.d.ts +14 -2
  171. package/dist/neurolink.js +46 -18
  172. package/dist/processors/media/AudioProcessor.js +8 -3
  173. package/dist/providers/amazonBedrock.js +1 -2
  174. package/dist/providers/amazonSagemaker.d.ts +1 -7
  175. package/dist/providers/amazonSagemaker.js +0 -6
  176. package/dist/providers/anthropic.d.ts +1 -1
  177. package/dist/providers/anthropic.js +2 -1
  178. package/dist/providers/anthropicBaseProvider.d.ts +1 -1
  179. package/dist/providers/anthropicBaseProvider.js +2 -1
  180. package/dist/providers/azureOpenai.d.ts +1 -1
  181. package/dist/providers/azureOpenai.js +2 -1
  182. package/dist/providers/cloudflare.d.ts +1 -1
  183. package/dist/providers/cloudflare.js +2 -1
  184. package/dist/providers/cohere.d.ts +1 -1
  185. package/dist/providers/cohere.js +2 -1
  186. package/dist/providers/deepseek.d.ts +1 -1
  187. package/dist/providers/deepseek.js +2 -1
  188. package/dist/providers/fireworks.d.ts +1 -1
  189. package/dist/providers/fireworks.js +2 -1
  190. package/dist/providers/googleAiStudio.d.ts +1 -1
  191. package/dist/providers/googleAiStudio.js +82 -5
  192. package/dist/providers/googleNativeGemini3.d.ts +3 -6
  193. package/dist/providers/googleNativeGemini3.js +104 -9
  194. package/dist/providers/googleVertex.d.ts +1 -1
  195. package/dist/providers/googleVertex.js +466 -164
  196. package/dist/providers/groq.d.ts +1 -1
  197. package/dist/providers/groq.js +2 -1
  198. package/dist/providers/huggingFace.d.ts +1 -1
  199. package/dist/providers/huggingFace.js +3 -1
  200. package/dist/providers/ideogram.d.ts +1 -1
  201. package/dist/providers/jina.d.ts +1 -1
  202. package/dist/providers/litellm.d.ts +1 -1
  203. package/dist/providers/litellm.js +12 -6
  204. package/dist/providers/llamaCpp.d.ts +1 -1
  205. package/dist/providers/llamaCpp.js +2 -1
  206. package/dist/providers/lmStudio.d.ts +1 -1
  207. package/dist/providers/lmStudio.js +2 -1
  208. package/dist/providers/mistral.d.ts +1 -1
  209. package/dist/providers/mistral.js +2 -1
  210. package/dist/providers/nvidiaNim.d.ts +1 -1
  211. package/dist/providers/nvidiaNim.js +2 -1
  212. package/dist/providers/ollama.d.ts +1 -1
  213. package/dist/providers/ollama.js +1 -2
  214. package/dist/providers/openAI.d.ts +1 -1
  215. package/dist/providers/openAI.js +3 -1
  216. package/dist/providers/openRouter.d.ts +1 -1
  217. package/dist/providers/openRouter.js +3 -1
  218. package/dist/providers/openaiCompatible.d.ts +1 -1
  219. package/dist/providers/openaiCompatible.js +3 -1
  220. package/dist/providers/perplexity.d.ts +1 -1
  221. package/dist/providers/perplexity.js +2 -1
  222. package/dist/providers/providerTypeUtils.d.ts +2 -7
  223. package/dist/providers/providerTypeUtils.js +0 -6
  224. package/dist/providers/recraft.d.ts +1 -1
  225. package/dist/providers/replicate.d.ts +1 -1
  226. package/dist/providers/stability.d.ts +1 -1
  227. package/dist/providers/togetherAi.d.ts +1 -1
  228. package/dist/providers/togetherAi.js +2 -1
  229. package/dist/providers/voyage.d.ts +1 -1
  230. package/dist/providers/xai.d.ts +1 -1
  231. package/dist/providers/xai.js +2 -1
  232. package/dist/proxy/claudeFormat.d.ts +0 -15
  233. package/dist/proxy/claudeFormat.js +1 -11
  234. package/dist/rag/ragIntegration.d.ts +1 -12
  235. package/dist/rag/ragIntegration.js +0 -8
  236. package/dist/tasks/tools/taskTools.d.ts +2 -117
  237. package/dist/tasks/tools/taskTools.js +1 -10
  238. package/dist/types/aliases.d.ts +1 -1
  239. package/dist/types/conversation.d.ts +17 -0
  240. package/dist/types/evaluation.d.ts +1 -5
  241. package/dist/types/evaluation.js +0 -4
  242. package/dist/types/generate.d.ts +2 -22
  243. package/dist/types/guardrails.d.ts +1 -1
  244. package/dist/types/middleware.d.ts +8 -3
  245. package/dist/types/providers.d.ts +2 -1
  246. package/dist/types/rag.d.ts +1 -1
  247. package/dist/types/rag.js +0 -6
  248. package/dist/types/stream.d.ts +2 -11
  249. package/dist/types/tools.d.ts +2 -1
  250. package/dist/utils/generation.d.ts +8 -0
  251. package/dist/utils/generation.js +8 -0
  252. package/dist/utils/generationErrors.d.ts +10 -0
  253. package/dist/utils/generationErrors.js +10 -0
  254. package/dist/utils/messageBuilder.d.ts +1 -6
  255. package/dist/utils/messageBuilder.js +0 -5
  256. package/dist/utils/noOutputSentinel.d.ts +0 -13
  257. package/dist/utils/noOutputSentinel.js +1 -14
  258. package/dist/utils/providerRetry.js +1 -1
  259. package/dist/utils/tool.d.ts +8 -0
  260. package/dist/utils/tool.js +8 -0
  261. package/dist/utils/toolCallRepair.d.ts +1 -16
  262. package/dist/utils/toolCallRepair.js +1 -16
  263. package/dist/utils/toolChoice.d.ts +1 -1
  264. package/dist/utils/videoAnalysisProcessor.d.ts +1 -8
  265. package/dist/utils/videoAnalysisProcessor.js +0 -7
  266. package/package.json +2 -3
@@ -1,14 +1,16 @@
1
1
  import { ErrorCategory, ErrorSeverity, GoogleAIModels, } from "../constants/enums.js";
2
2
  import { BaseProvider } from "../core/baseProvider.js";
3
- import { IMAGE_GENERATION_MODELS } from "../core/constants.js";
3
+ import { IMAGE_GENERATION_MODELS, TOOL_STORAGE_TIMEOUT_MS, } from "../core/constants.js";
4
4
  import { processUnifiedFilesArray } from "../utils/messageBuilder.js";
5
5
  import { ATTR, tracers, withClientSpan, withClientStreamSpan, withSpan, } from "../telemetry/index.js";
6
6
  import { AuthenticationError, InvalidModelError, NetworkError, ProviderError, RateLimitError, } from "../types/index.js";
7
7
  import { ERROR_CODES, NeuroLinkError } from "../utils/errorHandling.js";
8
8
  import { logger } from "../utils/logger.js";
9
9
  import { composeAbortSignals, createTimeoutController, TimeoutError, } from "../utils/timeout.js";
10
+ import { withTimeout } from "../utils/async/index.js";
10
11
  import { estimateTokens } from "../utils/tokenEstimation.js";
11
- import { buildGeminiResponseSchema, buildNativeConfig, buildNativeToolDeclarations, collectStreamChunks, collectStreamChunksIncremental, computeMaxSteps, createTextChannel, buildUserPartsWithMultimodal, executeNativeToolCalls, extractTextFromParts, handleMaxStepsTermination, prependConversationMessages, pushModelResponseToHistory, } from "./googleNativeGemini3.js";
12
+ import { transformToolExecutions } from "../utils/transformationUtils.js";
13
+ import { buildGeminiResponseSchema, buildNativeConfig, buildNativeToolDeclarations, collectStreamChunks, collectStreamChunksIncremental, computeMaxSteps, createTextChannel, buildUserPartsWithMultimodal, executeNativeToolCalls, extractTextFromParts, extractThoughtSignature, handleMaxStepsTermination, prependConversationMessages, pushModelResponseToHistory, } from "./googleNativeGemini3.js";
12
14
  import { createProxyFetch } from "../proxy/proxyFetch.js";
13
15
  // Google AI Live API types now imported from ../types/providerSpecific.js
14
16
  // Import proper types for multimodal message handling
@@ -556,6 +558,10 @@ export class GoogleAIStudioProvider extends BaseProvider {
556
558
  const channel = createTextChannel();
557
559
  // Shared mutable state updated by the background agentic loop.
558
560
  const allToolCalls = [];
561
+ // Mirror the Vertex Gemini stream path: track tool executions so
562
+ // the storage hook can persist real outputs and StreamResult can
563
+ // surface toolsUsed/toolExecutions for tool-bearing turns.
564
+ const toolExecutions = [];
559
565
  // analyticsResolvers lets the background loop settle the analytics
560
566
  // promise once token counts are known (after the loop completes).
561
567
  let analyticsResolve;
@@ -626,7 +632,40 @@ export class GoogleAIStudioProvider extends BaseProvider {
626
632
  logger.debug(`[GoogleAIStudio] Executing ${chunkResult.stepFunctionCalls.length} function calls`);
627
633
  // Add model response with ALL parts (including thoughtSignature) to history
628
634
  pushModelResponseToHistory(currentContents, chunkResult.rawResponseParts, chunkResult.stepFunctionCalls);
629
- const functionResponses = await executeNativeToolCalls("[GoogleAIStudio]", chunkResult.stepFunctionCalls, executeMap, failedTools, allToolCalls, { abortSignal: composedSignal, originalNameMap });
635
+ const toolCallsBefore = allToolCalls.length;
636
+ const toolExecsBefore = toolExecutions.length;
637
+ const functionResponses = await executeNativeToolCalls("[GoogleAIStudio]", chunkResult.stepFunctionCalls, executeMap, failedTools, allToolCalls, {
638
+ abortSignal: composedSignal,
639
+ originalNameMap,
640
+ toolExecutions,
641
+ });
642
+ // Persist this step's tool calls/results into conversation
643
+ // memory. Without this, tool_call / tool_result rows never
644
+ // reach Redis and the chat-history UI loses every tool
645
+ // invocation.
646
+ const stepToolCalls = allToolCalls.slice(toolCallsBefore);
647
+ const stepToolExecs = toolExecutions.slice(toolExecsBefore);
648
+ if (stepToolCalls.length > 0 || stepToolExecs.length > 0) {
649
+ const stepThoughtSig = extractThoughtSignature(chunkResult.rawResponseParts);
650
+ withTimeout(this.handleToolExecutionStorage(stepToolCalls.map((tc, i) => ({
651
+ toolName: tc.toolName,
652
+ args: tc.args,
653
+ ...(i === 0 && stepThoughtSig
654
+ ? { thoughtSignature: stepThoughtSig }
655
+ : {}),
656
+ stepIndex: step,
657
+ })), stepToolExecs.map((te) => ({
658
+ toolName: te.name,
659
+ output: te.output,
660
+ stepIndex: step,
661
+ })), options, new Date()), TOOL_STORAGE_TIMEOUT_MS, "tool storage write timed out").catch((error) => {
662
+ logger.warn("[GoogleAIStudio] Failed to store native tool executions", {
663
+ error: error instanceof Error
664
+ ? error.message
665
+ : String(error),
666
+ });
667
+ });
668
+ }
630
669
  // Add function responses to history — the @google/genai SDK
631
670
  // only accepts "user" and "model" as valid roles in contents.
632
671
  // Function/tool responses must use role: "user" (matching the
@@ -683,7 +722,7 @@ export class GoogleAIStudioProvider extends BaseProvider {
683
722
  // Suppress unhandled-rejection warnings on loopPromise — errors are
684
723
  // forwarded to the channel and will surface when the caller iterates.
685
724
  loopPromise.catch(() => undefined);
686
- return {
725
+ const result = {
687
726
  stream: channel.iterable,
688
727
  provider: this.providerName,
689
728
  model: modelName,
@@ -691,6 +730,20 @@ export class GoogleAIStudioProvider extends BaseProvider {
691
730
  analytics: analyticsPromise,
692
731
  metadata,
693
732
  };
733
+ // Surface tools-used + executions via getters so they resolve at
734
+ // access time, after the background loop has populated the live
735
+ // arrays. Same lazy pattern used for `structuredOutput` elsewhere.
736
+ Object.defineProperty(result, "toolsUsed", {
737
+ enumerable: true,
738
+ configurable: true,
739
+ get: () => allToolCalls.map((tc) => tc.toolName),
740
+ });
741
+ Object.defineProperty(result, "toolExecutions", {
742
+ enumerable: true,
743
+ configurable: true,
744
+ get: () => transformToolExecutions(toolExecutions),
745
+ });
746
+ return result;
694
747
  }
695
748
  finally {
696
749
  // Timeout controller cleanup is managed inside the background loop
@@ -821,11 +874,35 @@ export class GoogleAIStudioProvider extends BaseProvider {
821
874
  // Add model response with ALL parts (including thoughtSignature) to history
822
875
  // This is critical for Gemini 3 - it requires thought signatures in subsequent turns
823
876
  pushModelResponseToHistory(currentContents, chunkResult.rawResponseParts, chunkResult.stepFunctionCalls);
877
+ const toolCallsBefore = allToolCalls.length;
878
+ const toolExecsBefore = toolExecutions.length;
824
879
  const functionResponses = await executeNativeToolCalls("[GoogleAIStudio]", chunkResult.stepFunctionCalls, executeMap, failedTools, allToolCalls, {
825
880
  toolExecutions,
826
881
  abortSignal: composedSignal,
827
882
  originalNameMap,
828
883
  });
884
+ // Persist this step's tool calls/results into conversation memory.
885
+ const stepToolCalls = allToolCalls.slice(toolCallsBefore);
886
+ const stepToolExecs = toolExecutions.slice(toolExecsBefore);
887
+ if (stepToolCalls.length > 0 || stepToolExecs.length > 0) {
888
+ const stepThoughtSig = extractThoughtSignature(chunkResult.rawResponseParts);
889
+ withTimeout(this.handleToolExecutionStorage(stepToolCalls.map((tc, i) => ({
890
+ toolName: tc.toolName,
891
+ args: tc.args,
892
+ ...(i === 0 && stepThoughtSig
893
+ ? { thoughtSignature: stepThoughtSig }
894
+ : {}),
895
+ stepIndex: step,
896
+ })), stepToolExecs.map((te) => ({
897
+ toolName: te.name,
898
+ output: te.output,
899
+ stepIndex: step,
900
+ })), options, new Date()), TOOL_STORAGE_TIMEOUT_MS, "tool storage write timed out").catch((error) => {
901
+ logger.warn("[GoogleAIStudio] Failed to store native generate tool executions", {
902
+ error: error instanceof Error ? error.message : String(error),
903
+ });
904
+ });
905
+ }
829
906
  // Add function responses to history — the @google/genai SDK
830
907
  // only accepts "user" and "model" as valid roles in contents.
831
908
  // Function/tool responses must use role: "user" (matching the
@@ -861,7 +938,7 @@ export class GoogleAIStudioProvider extends BaseProvider {
861
938
  },
862
939
  responseTime,
863
940
  toolsUsed: allToolCalls.map((tc) => tc.toolName),
864
- toolExecutions: toolExecutions,
941
+ toolExecutions: transformToolExecutions(toolExecutions),
865
942
  enhancedWithTools: allToolCalls.length > 0,
866
943
  };
867
944
  return this.enhanceResult(baseResult, options, startTime);
@@ -8,8 +8,8 @@
8
8
  * This module extracts the functions that are duplicated between the two
9
9
  * providers so they can share a single implementation.
10
10
  */
11
- import { type Tool } from "ai";
12
- import type { ThinkingConfig, CollectedChunkResult, NativeFunctionCall, NativeFunctionResponse, NativeToolDeclarationsResult, NativeToolsConfig, TextChannel, VertexNativePart, GeminiMultimodalInput } from "../types/index.js";
11
+ import type { ThinkingConfig, ChatMessage, CollectedChunkResult, MinimalChatMessage, NativeFunctionCall, NativeFunctionResponse, NativeToolDeclarationsResult, NativeToolsConfig, TextChannel, VertexNativePart, GeminiMultimodalInput } from "../types/index.js";
12
+ import type { Tool } from "../types/index.js";
13
13
  export declare function sanitizeForGoogleFunctionName(name: string): string;
14
14
  /**
15
15
  * Resolve a sanitized Gemini tool name to one that is both unique within
@@ -218,10 +218,7 @@ export declare function buildGeminiResponseSchema(schema: unknown): Record<strin
218
218
  export declare function prependConversationMessages(contents: Array<{
219
219
  role: string;
220
220
  parts: unknown[];
221
- }>, conversationMessages?: Array<{
222
- role: string;
223
- content: string;
224
- }>): void;
221
+ }>, conversationMessages?: Array<ChatMessage | MinimalChatMessage>): void;
225
222
  /**
226
223
  * Build the `parts` array for the current user turn of a Gemini native
227
224
  * `generateContent` request, including inline image + PDF blobs.
@@ -11,11 +11,11 @@
11
11
  import { randomUUID } from "node:crypto";
12
12
  import { existsSync, readFileSync } from "node:fs";
13
13
  import { extname } from "node:path";
14
- import { jsonSchema as aiJsonSchema, tool as createAISDKTool, } from "ai";
15
14
  import { DEFAULT_MAX_STEPS, DEFAULT_TOOL_MAX_RETRIES, } from "../core/constants.js";
16
15
  import { logger } from "../utils/logger.js";
17
16
  import { convertZodToJsonSchema, ensureNestedSchemaTypes, inlineJsonSchema, isZodSchema, normalizeJsonSchemaObject, } from "../utils/schemaConversion.js";
18
17
  import { createNativeThinkingConfig } from "../utils/thinkingConfig.js";
18
+ import { jsonSchema as aiJsonSchema, tool as createAISDKTool, } from "../utils/tool.js";
19
19
  // ── Functions ──
20
20
  /**
21
21
  * Google's `function_declarations[].name` validator regex.
@@ -646,6 +646,10 @@ export async function executeNativeToolCalls(logLabel, stepFunctionCalls, execut
646
646
  // original name. Falls back to the safe name if the map is missing or
647
647
  // doesn't contain the call (e.g. tool added mid-conversation).
648
648
  const externalName = (safeName) => options?.originalNameMap?.get(safeName) ?? safeName;
649
+ // Note: tool:start / tool:end events are emitted by ToolsManager's
650
+ // `execute` wrapper (see src/lib/core/modules/ToolsManager.ts:355 and :790)
651
+ // around every tool's execute function. The native paths invoke that same
652
+ // wrapped execute via the executeMap, so emitting here would duplicate.
649
653
  for (const call of stepFunctionCalls) {
650
654
  const exposedName = externalName(call.name);
651
655
  allToolCalls.push({ toolName: exposedName, args: call.args });
@@ -808,22 +812,113 @@ export function buildGeminiResponseSchema(schema) {
808
812
  * - The current user input should be appended AFTER calling this helper
809
813
  * so the prior turns appear first in chronological order.
810
814
  */
811
- export function prependConversationMessages(contents, conversationMessages) {
815
+ export function prependConversationMessages(contents,
816
+ // Accept either the full ChatMessage shape (when callers pass real Redis-
817
+ // backed history) or the reduced MinimalChatMessage shape (tests / synthetic
818
+ // callers). Only role, content, tool, args, and metadata.* are read here.
819
+ conversationMessages) {
812
820
  if (!conversationMessages || conversationMessages.length === 0) {
813
821
  return;
814
822
  }
823
+ // Walk prior turns building ordered segments. Tool_call / tool_result rows
824
+ // get grouped by (turnCounter, stepIndex) so parallel calls within a step
825
+ // stay together and don't bleed across turn boundaries. Regular user/
826
+ // assistant messages act as those boundaries.
827
+ //
828
+ // Without this reconstruction, a text-only mapper would strip tool rows
829
+ // from history — leaving the model unaware of any tools it called in
830
+ // prior turns. The grouped emit (model with functionCall parts → user
831
+ // with functionResponse parts) is what @google/genai's own
832
+ // automaticFunctionCalling produces, so the SDK validates it as a
833
+ // well-formed multi-turn conversation.
834
+ const stepMap = new Map();
835
+ const segments = [];
836
+ let turnCounter = 0;
837
+ const makeKey = (stepIndex) => `${turnCounter}:${stepIndex ?? "undefined"}`;
838
+ const getOrCreateStep = (stepIndex) => {
839
+ const key = makeKey(stepIndex);
840
+ const existing = stepMap.get(key);
841
+ if (existing) {
842
+ return existing;
843
+ }
844
+ const step = {
845
+ type: "tool_step",
846
+ callParts: [],
847
+ resultParts: [],
848
+ };
849
+ stepMap.set(key, step);
850
+ segments.push(step);
851
+ return step;
852
+ };
815
853
  for (const msg of conversationMessages) {
816
- if (msg.role !== "user" && msg.role !== "assistant") {
854
+ if (msg.role === "tool_call") {
855
+ const step = getOrCreateStep(msg.metadata?.stepIndex);
856
+ const fcPart = {
857
+ functionCall: {
858
+ name: msg.tool || "unknown",
859
+ args: msg.args || {},
860
+ },
861
+ };
862
+ if (msg.metadata?.thoughtSignature) {
863
+ fcPart.thoughtSignature = msg.metadata.thoughtSignature;
864
+ }
865
+ step.callParts.push(fcPart);
817
866
  continue;
818
867
  }
819
- const text = typeof msg.content === "string" ? msg.content : "";
820
- if (text.length === 0) {
868
+ if (msg.role === "tool_result") {
869
+ const step = getOrCreateStep(msg.metadata?.stepIndex);
870
+ let responsePayload;
871
+ try {
872
+ responsePayload =
873
+ msg.content !== undefined && msg.content !== null
874
+ ? { result: JSON.parse(msg.content) }
875
+ : { result: "success" };
876
+ }
877
+ catch {
878
+ responsePayload = { result: msg.content ?? "success" };
879
+ }
880
+ step.resultParts.push({
881
+ functionResponse: {
882
+ name: msg.tool || "unknown",
883
+ response: responsePayload,
884
+ },
885
+ });
821
886
  continue;
822
887
  }
823
- contents.push({
824
- role: msg.role === "assistant" ? "model" : "user",
825
- parts: [{ text }],
826
- });
888
+ // Regular (user / assistant) message — acts as a turn boundary.
889
+ const role = msg.role === "assistant" ? "model" : msg.role;
890
+ if (role !== "user" && role !== "model") {
891
+ continue;
892
+ }
893
+ if (!msg.content || msg.content.trim().length === 0) {
894
+ continue;
895
+ }
896
+ // Increment turn counter BEFORE pushing the segment so any tool_calls
897
+ // that follow this message get a fresh (turnCounter, stepIndex) namespace.
898
+ turnCounter++;
899
+ const textPart = { text: msg.content };
900
+ if (msg.metadata?.thoughtSignature) {
901
+ textPart.thoughtSignature = msg.metadata.thoughtSignature;
902
+ }
903
+ segments.push({ type: "regular", role, parts: [textPart] });
904
+ }
905
+ // Emit in order: each ToolStep → model turn (calls) + user turn (results)
906
+ // — same ordering @google/genai's automaticFunctionCalling produces.
907
+ for (const seg of segments) {
908
+ if (seg.type === "regular") {
909
+ contents.push({ role: seg.role, parts: seg.parts });
910
+ continue;
911
+ }
912
+ if (seg.callParts.length === 0) {
913
+ if (seg.resultParts.length > 0) {
914
+ logger.debug("[GoogleNativeGemini3] Dropping orphan tool_result segment with no matching tool_call rows", { resultCount: seg.resultParts.length });
915
+ }
916
+ continue;
917
+ }
918
+ contents.push({ role: "model", parts: seg.callParts });
919
+ if (seg.resultParts.length > 0) {
920
+ contents.push({ role: "user", parts: seg.resultParts });
921
+ }
827
922
  }
828
923
  }
829
924
  /**
@@ -1,8 +1,8 @@
1
1
  import type { ZodType } from "zod";
2
- import { type Schema, type LanguageModel } from "ai";
3
2
  import { AIProviderName } from "../constants/enums.js";
4
3
  import { BaseProvider } from "../core/baseProvider.js";
5
4
  import type { EnhancedGenerateResult, TextGenerationOptions, StreamOptions, StreamResult } from "../types/index.js";
5
+ import type { Schema, LanguageModel } from "../types/index.js";
6
6
  /**
7
7
  * Resolve the effective Vertex region for a given model.
8
8
  *