@framers/agentos 0.1.113 → 0.1.114

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 (510) hide show
  1. package/README.md +39 -5
  2. package/dist/api/AgentOS.d.ts +45 -12
  3. package/dist/api/AgentOS.d.ts.map +1 -1
  4. package/dist/api/AgentOS.js +225 -78
  5. package/dist/api/AgentOS.js.map +1 -1
  6. package/dist/api/AgentOSOrchestrator.d.ts +8 -0
  7. package/dist/api/AgentOSOrchestrator.d.ts.map +1 -1
  8. package/dist/api/AgentOSOrchestrator.js +350 -59
  9. package/dist/api/AgentOSOrchestrator.js.map +1 -1
  10. package/dist/api/StreamChunkEmitter.d.ts.map +1 -1
  11. package/dist/api/StreamChunkEmitter.js +2 -0
  12. package/dist/api/StreamChunkEmitter.js.map +1 -1
  13. package/dist/api/agency.d.ts.map +1 -1
  14. package/dist/api/agency.js +47 -1
  15. package/dist/api/agency.js.map +1 -1
  16. package/dist/api/agent.d.ts +18 -5
  17. package/dist/api/agent.d.ts.map +1 -1
  18. package/dist/api/agent.js +48 -9
  19. package/dist/api/agent.js.map +1 -1
  20. package/dist/api/agentExport.d.ts +202 -0
  21. package/dist/api/agentExport.d.ts.map +1 -0
  22. package/dist/api/agentExport.js +323 -0
  23. package/dist/api/agentExport.js.map +1 -0
  24. package/dist/api/editImage.d.ts +119 -0
  25. package/dist/api/editImage.d.ts.map +1 -0
  26. package/dist/api/editImage.js +150 -0
  27. package/dist/api/editImage.js.map +1 -0
  28. package/dist/api/embedText.d.ts +137 -0
  29. package/dist/api/embedText.d.ts.map +1 -0
  30. package/dist/api/embedText.js +229 -0
  31. package/dist/api/embedText.js.map +1 -0
  32. package/dist/api/externalToolRegistry.d.ts +44 -0
  33. package/dist/api/externalToolRegistry.d.ts.map +1 -0
  34. package/dist/api/externalToolRegistry.js +245 -0
  35. package/dist/api/externalToolRegistry.js.map +1 -0
  36. package/dist/api/generateImage.d.ts +1 -1
  37. package/dist/api/generateImage.d.ts.map +1 -1
  38. package/dist/api/generateImage.js +17 -13
  39. package/dist/api/generateImage.js.map +1 -1
  40. package/dist/api/generateObject.d.ts +185 -0
  41. package/dist/api/generateObject.d.ts.map +1 -0
  42. package/dist/api/generateObject.js +249 -0
  43. package/dist/api/generateObject.js.map +1 -0
  44. package/dist/api/generateText.d.ts +13 -3
  45. package/dist/api/generateText.d.ts.map +1 -1
  46. package/dist/api/generateText.js +20 -5
  47. package/dist/api/generateText.js.map +1 -1
  48. package/dist/api/interfaces/IAgentOS.d.ts +29 -1
  49. package/dist/api/interfaces/IAgentOS.d.ts.map +1 -1
  50. package/dist/api/model.d.ts +7 -7
  51. package/dist/api/model.d.ts.map +1 -1
  52. package/dist/api/model.js +22 -16
  53. package/dist/api/model.js.map +1 -1
  54. package/dist/api/processRequestWithExternalTools.d.ts +26 -0
  55. package/dist/api/processRequestWithExternalTools.d.ts.map +1 -0
  56. package/dist/api/processRequestWithExternalTools.js +52 -0
  57. package/dist/api/processRequestWithExternalTools.js.map +1 -0
  58. package/dist/api/processRequestWithRegisteredTools.d.ts +56 -0
  59. package/dist/api/processRequestWithRegisteredTools.d.ts.map +1 -0
  60. package/dist/api/processRequestWithRegisteredTools.js +125 -0
  61. package/dist/api/processRequestWithRegisteredTools.js.map +1 -0
  62. package/dist/api/provider-defaults.d.ts.map +1 -1
  63. package/dist/api/provider-defaults.js +28 -0
  64. package/dist/api/provider-defaults.js.map +1 -1
  65. package/dist/api/resumeExternalToolRequestWithRegisteredTools.d.ts +71 -0
  66. package/dist/api/resumeExternalToolRequestWithRegisteredTools.d.ts.map +1 -0
  67. package/dist/api/resumeExternalToolRequestWithRegisteredTools.js +159 -0
  68. package/dist/api/resumeExternalToolRequestWithRegisteredTools.js.map +1 -0
  69. package/dist/api/strategies/agentGraphBuilder.d.ts +170 -0
  70. package/dist/api/strategies/agentGraphBuilder.d.ts.map +1 -0
  71. package/dist/api/strategies/agentGraphBuilder.js +299 -0
  72. package/dist/api/strategies/agentGraphBuilder.js.map +1 -0
  73. package/dist/api/strategies/graphCompiler.d.ts +84 -0
  74. package/dist/api/strategies/graphCompiler.d.ts.map +1 -0
  75. package/dist/api/strategies/graphCompiler.js +617 -0
  76. package/dist/api/strategies/graphCompiler.js.map +1 -0
  77. package/dist/api/strategies/hierarchical.d.ts.map +1 -1
  78. package/dist/api/strategies/hierarchical.js +2 -1
  79. package/dist/api/strategies/hierarchical.js.map +1 -1
  80. package/dist/api/strategies/index.d.ts +3 -0
  81. package/dist/api/strategies/index.d.ts.map +1 -1
  82. package/dist/api/strategies/index.js +2 -0
  83. package/dist/api/strategies/index.js.map +1 -1
  84. package/dist/api/strategies/shared.d.ts +1 -1
  85. package/dist/api/strategies/shared.d.ts.map +1 -1
  86. package/dist/api/strategies/shared.js +3 -2
  87. package/dist/api/strategies/shared.js.map +1 -1
  88. package/dist/api/streamObject.d.ts +166 -0
  89. package/dist/api/streamObject.d.ts.map +1 -0
  90. package/dist/api/streamObject.js +268 -0
  91. package/dist/api/streamObject.js.map +1 -0
  92. package/dist/api/streamText.d.ts +1 -1
  93. package/dist/api/streamText.d.ts.map +1 -1
  94. package/dist/api/streamText.js +26 -8
  95. package/dist/api/streamText.js.map +1 -1
  96. package/dist/api/toolAdapter.d.ts +44 -8
  97. package/dist/api/toolAdapter.d.ts.map +1 -1
  98. package/dist/api/toolAdapter.js +224 -45
  99. package/dist/api/toolAdapter.js.map +1 -1
  100. package/dist/api/types/AgentOSExternalToolRequest.d.ts +35 -0
  101. package/dist/api/types/AgentOSExternalToolRequest.d.ts.map +1 -0
  102. package/dist/api/types/AgentOSExternalToolRequest.js +2 -0
  103. package/dist/api/types/AgentOSExternalToolRequest.js.map +1 -0
  104. package/dist/api/types/AgentOSResponse.d.ts +25 -0
  105. package/dist/api/types/AgentOSResponse.d.ts.map +1 -1
  106. package/dist/api/types/AgentOSResponse.js +20 -0
  107. package/dist/api/types/AgentOSResponse.js.map +1 -1
  108. package/dist/api/types/AgentOSToolResult.d.ts +11 -0
  109. package/dist/api/types/AgentOSToolResult.d.ts.map +1 -0
  110. package/dist/api/types/AgentOSToolResult.js +2 -0
  111. package/dist/api/types/AgentOSToolResult.js.map +1 -0
  112. package/dist/api/types.d.ts +28 -4
  113. package/dist/api/types.d.ts.map +1 -1
  114. package/dist/api/types.js.map +1 -1
  115. package/dist/api/upscaleImage.d.ts +92 -0
  116. package/dist/api/upscaleImage.d.ts.map +1 -0
  117. package/dist/api/upscaleImage.js +133 -0
  118. package/dist/api/upscaleImage.js.map +1 -0
  119. package/dist/api/variateImage.d.ts +102 -0
  120. package/dist/api/variateImage.d.ts.map +1 -0
  121. package/dist/api/variateImage.js +154 -0
  122. package/dist/api/variateImage.js.map +1 -0
  123. package/dist/cognitive_substrate/GMI.d.ts +16 -2
  124. package/dist/cognitive_substrate/GMI.d.ts.map +1 -1
  125. package/dist/cognitive_substrate/GMI.js +188 -56
  126. package/dist/cognitive_substrate/GMI.js.map +1 -1
  127. package/dist/cognitive_substrate/IGMI.d.ts +10 -0
  128. package/dist/cognitive_substrate/IGMI.d.ts.map +1 -1
  129. package/dist/cognitive_substrate/IGMI.js.map +1 -1
  130. package/dist/config/AgentOSConfig.d.ts +19 -2
  131. package/dist/config/AgentOSConfig.d.ts.map +1 -1
  132. package/dist/config/AgentOSConfig.js +46 -29
  133. package/dist/config/AgentOSConfig.js.map +1 -1
  134. package/dist/core/guardrails/IGuardrailService.d.ts +1 -1
  135. package/dist/core/images/IImageProvider.d.ts +93 -0
  136. package/dist/core/images/IImageProvider.d.ts.map +1 -1
  137. package/dist/core/images/IImageProvider.js.map +1 -1
  138. package/dist/core/images/ImageOperationError.d.ts +52 -0
  139. package/dist/core/images/ImageOperationError.d.ts.map +1 -0
  140. package/dist/core/images/ImageOperationError.js +58 -0
  141. package/dist/core/images/ImageOperationError.js.map +1 -0
  142. package/dist/core/images/imageToBuffer.d.ts +41 -0
  143. package/dist/core/images/imageToBuffer.d.ts.map +1 -0
  144. package/dist/core/images/imageToBuffer.js +95 -0
  145. package/dist/core/images/imageToBuffer.js.map +1 -0
  146. package/dist/core/images/index.d.ts +4 -0
  147. package/dist/core/images/index.d.ts.map +1 -1
  148. package/dist/core/images/index.js +8 -0
  149. package/dist/core/images/index.js.map +1 -1
  150. package/dist/core/images/providers/FalImageProvider.d.ts +208 -0
  151. package/dist/core/images/providers/FalImageProvider.d.ts.map +1 -0
  152. package/dist/core/images/providers/FalImageProvider.js +301 -0
  153. package/dist/core/images/providers/FalImageProvider.js.map +1 -0
  154. package/dist/core/images/providers/FluxImageProvider.d.ts +197 -0
  155. package/dist/core/images/providers/FluxImageProvider.d.ts.map +1 -0
  156. package/dist/core/images/providers/FluxImageProvider.js +271 -0
  157. package/dist/core/images/providers/FluxImageProvider.js.map +1 -0
  158. package/dist/core/images/providers/OpenAIImageProvider.d.ts +33 -1
  159. package/dist/core/images/providers/OpenAIImageProvider.d.ts.map +1 -1
  160. package/dist/core/images/providers/OpenAIImageProvider.js +125 -0
  161. package/dist/core/images/providers/OpenAIImageProvider.js.map +1 -1
  162. package/dist/core/images/providers/ReplicateImageProvider.d.ts +26 -1
  163. package/dist/core/images/providers/ReplicateImageProvider.d.ts.map +1 -1
  164. package/dist/core/images/providers/ReplicateImageProvider.js +118 -0
  165. package/dist/core/images/providers/ReplicateImageProvider.js.map +1 -1
  166. package/dist/core/images/providers/StabilityImageProvider.d.ts +41 -1
  167. package/dist/core/images/providers/StabilityImageProvider.d.ts.map +1 -1
  168. package/dist/core/images/providers/StabilityImageProvider.js +180 -7
  169. package/dist/core/images/providers/StabilityImageProvider.js.map +1 -1
  170. package/dist/core/images/providers/StableDiffusionLocalProvider.d.ts +29 -1
  171. package/dist/core/images/providers/StableDiffusionLocalProvider.d.ts.map +1 -1
  172. package/dist/core/images/providers/StableDiffusionLocalProvider.js +124 -0
  173. package/dist/core/images/providers/StableDiffusionLocalProvider.js.map +1 -1
  174. package/dist/core/llm/IPromptEngine.d.ts +2 -2
  175. package/dist/core/llm/IPromptEngine.d.ts.map +1 -1
  176. package/dist/core/llm/IPromptEngine.js +2 -2
  177. package/dist/core/llm/IPromptEngine.js.map +1 -1
  178. package/dist/core/llm/providers/AIModelProviderManager.d.ts +7 -1
  179. package/dist/core/llm/providers/AIModelProviderManager.d.ts.map +1 -1
  180. package/dist/core/llm/providers/AIModelProviderManager.js +24 -0
  181. package/dist/core/llm/providers/AIModelProviderManager.js.map +1 -1
  182. package/dist/core/llm/providers/errors/AnthropicProviderError.d.ts +42 -0
  183. package/dist/core/llm/providers/errors/AnthropicProviderError.d.ts.map +1 -0
  184. package/dist/core/llm/providers/errors/AnthropicProviderError.js +45 -0
  185. package/dist/core/llm/providers/errors/AnthropicProviderError.js.map +1 -0
  186. package/dist/core/llm/providers/errors/GeminiProviderError.d.ts +45 -0
  187. package/dist/core/llm/providers/errors/GeminiProviderError.d.ts.map +1 -0
  188. package/dist/core/llm/providers/errors/GeminiProviderError.js +46 -0
  189. package/dist/core/llm/providers/errors/GeminiProviderError.js.map +1 -0
  190. package/dist/core/llm/providers/errors/OllamaProviderError.d.ts +1 -1
  191. package/dist/core/llm/providers/errors/OllamaProviderError.d.ts.map +1 -1
  192. package/dist/core/llm/providers/errors/OllamaProviderError.js +1 -1
  193. package/dist/core/llm/providers/errors/OllamaProviderError.js.map +1 -1
  194. package/dist/core/llm/providers/errors/OpenAIProviderError.d.ts +1 -1
  195. package/dist/core/llm/providers/errors/OpenAIProviderError.js +1 -1
  196. package/dist/core/llm/providers/errors/OpenRouterProviderError.d.ts +1 -1
  197. package/dist/core/llm/providers/errors/OpenRouterProviderError.js +1 -1
  198. package/dist/core/llm/providers/implementations/AnthropicProvider.d.ts +340 -0
  199. package/dist/core/llm/providers/implementations/AnthropicProvider.d.ts.map +1 -0
  200. package/dist/core/llm/providers/implementations/AnthropicProvider.js +959 -0
  201. package/dist/core/llm/providers/implementations/AnthropicProvider.js.map +1 -0
  202. package/dist/core/llm/providers/implementations/GeminiProvider.d.ts +339 -0
  203. package/dist/core/llm/providers/implementations/GeminiProvider.d.ts.map +1 -0
  204. package/dist/core/llm/providers/implementations/GeminiProvider.js +1004 -0
  205. package/dist/core/llm/providers/implementations/GeminiProvider.js.map +1 -0
  206. package/dist/core/llm/providers/implementations/GroqProvider.d.ts +105 -0
  207. package/dist/core/llm/providers/implementations/GroqProvider.d.ts.map +1 -0
  208. package/dist/core/llm/providers/implementations/GroqProvider.js +134 -0
  209. package/dist/core/llm/providers/implementations/GroqProvider.js.map +1 -0
  210. package/dist/core/llm/providers/implementations/MistralProvider.d.ts +105 -0
  211. package/dist/core/llm/providers/implementations/MistralProvider.d.ts.map +1 -0
  212. package/dist/core/llm/providers/implementations/MistralProvider.js +146 -0
  213. package/dist/core/llm/providers/implementations/MistralProvider.js.map +1 -0
  214. package/dist/core/llm/providers/implementations/TogetherProvider.d.ts +107 -0
  215. package/dist/core/llm/providers/implementations/TogetherProvider.d.ts.map +1 -0
  216. package/dist/core/llm/providers/implementations/TogetherProvider.js +138 -0
  217. package/dist/core/llm/providers/implementations/TogetherProvider.js.map +1 -0
  218. package/dist/core/llm/providers/implementations/XAIProvider.d.ts +102 -0
  219. package/dist/core/llm/providers/implementations/XAIProvider.d.ts.map +1 -0
  220. package/dist/core/llm/providers/implementations/XAIProvider.js +123 -0
  221. package/dist/core/llm/providers/implementations/XAIProvider.js.map +1 -0
  222. package/dist/core/orchestration/AgentOrchestrator.d.ts.map +1 -1
  223. package/dist/core/orchestration/AgentOrchestrator.js +26 -5
  224. package/dist/core/orchestration/AgentOrchestrator.js.map +1 -1
  225. package/dist/core/tools/IToolOrchestrator.d.ts +2 -2
  226. package/dist/core/tools/IToolOrchestrator.d.ts.map +1 -1
  227. package/dist/core/tools/ToolExecutor.d.ts +3 -0
  228. package/dist/core/tools/ToolExecutor.d.ts.map +1 -1
  229. package/dist/core/tools/ToolExecutor.js +2 -1
  230. package/dist/core/tools/ToolExecutor.js.map +1 -1
  231. package/dist/core/tools/ToolOrchestrator.d.ts +7 -7
  232. package/dist/core/tools/ToolOrchestrator.d.ts.map +1 -1
  233. package/dist/core/tools/ToolOrchestrator.js +135 -36
  234. package/dist/core/tools/ToolOrchestrator.js.map +1 -1
  235. package/dist/core/tools/permissions/ToolPermissionManager.d.ts +6 -5
  236. package/dist/core/tools/permissions/ToolPermissionManager.d.ts.map +1 -1
  237. package/dist/core/tools/permissions/ToolPermissionManager.js +47 -21
  238. package/dist/core/tools/permissions/ToolPermissionManager.js.map +1 -1
  239. package/dist/core/vision/VisionPipeline.d.ts +437 -0
  240. package/dist/core/vision/VisionPipeline.d.ts.map +1 -0
  241. package/dist/core/vision/VisionPipeline.js +1113 -0
  242. package/dist/core/vision/VisionPipeline.js.map +1 -0
  243. package/dist/core/vision/index.d.ts +97 -0
  244. package/dist/core/vision/index.d.ts.map +1 -0
  245. package/dist/core/vision/index.js +182 -0
  246. package/dist/core/vision/index.js.map +1 -0
  247. package/dist/core/vision/providers/LLMVisionProvider.d.ts +135 -0
  248. package/dist/core/vision/providers/LLMVisionProvider.d.ts.map +1 -0
  249. package/dist/core/vision/providers/LLMVisionProvider.js +136 -0
  250. package/dist/core/vision/providers/LLMVisionProvider.js.map +1 -0
  251. package/dist/core/vision/providers/PipelineVisionProvider.d.ts +154 -0
  252. package/dist/core/vision/providers/PipelineVisionProvider.d.ts.map +1 -0
  253. package/dist/core/vision/providers/PipelineVisionProvider.js +160 -0
  254. package/dist/core/vision/providers/PipelineVisionProvider.js.map +1 -0
  255. package/dist/core/vision/types.d.ts +286 -0
  256. package/dist/core/vision/types.d.ts.map +1 -0
  257. package/dist/core/vision/types.js +24 -0
  258. package/dist/core/vision/types.js.map +1 -0
  259. package/dist/discovery/CapabilityDiscoveryEngine.d.ts +1 -1
  260. package/dist/discovery/CapabilityDiscoveryEngine.d.ts.map +1 -1
  261. package/dist/discovery/CapabilityDiscoveryEngine.js +1 -1
  262. package/dist/discovery/CapabilityDiscoveryEngine.js.map +1 -1
  263. package/dist/emergent/ComposableToolBuilder.d.ts +15 -4
  264. package/dist/emergent/ComposableToolBuilder.d.ts.map +1 -1
  265. package/dist/emergent/ComposableToolBuilder.js +29 -14
  266. package/dist/emergent/ComposableToolBuilder.js.map +1 -1
  267. package/dist/emergent/EmergentCapabilityEngine.d.ts +3 -3
  268. package/dist/emergent/EmergentCapabilityEngine.d.ts.map +1 -1
  269. package/dist/emergent/EmergentCapabilityEngine.js +15 -12
  270. package/dist/emergent/EmergentCapabilityEngine.js.map +1 -1
  271. package/dist/emergent/EmergentJudge.d.ts +20 -0
  272. package/dist/emergent/EmergentJudge.d.ts.map +1 -1
  273. package/dist/emergent/EmergentJudge.js +121 -26
  274. package/dist/emergent/EmergentJudge.js.map +1 -1
  275. package/dist/emergent/EmergentToolRegistry.d.ts +17 -0
  276. package/dist/emergent/EmergentToolRegistry.d.ts.map +1 -1
  277. package/dist/emergent/EmergentToolRegistry.js +26 -0
  278. package/dist/emergent/EmergentToolRegistry.js.map +1 -1
  279. package/dist/emergent/ForgeToolMetaTool.d.ts +1 -1
  280. package/dist/emergent/ForgeToolMetaTool.d.ts.map +1 -1
  281. package/dist/emergent/ForgeToolMetaTool.js +15 -2
  282. package/dist/emergent/ForgeToolMetaTool.js.map +1 -1
  283. package/dist/emergent/SandboxedToolForge.d.ts +2 -2
  284. package/dist/emergent/SandboxedToolForge.d.ts.map +1 -1
  285. package/dist/emergent/SandboxedToolForge.js +13 -23
  286. package/dist/emergent/SandboxedToolForge.js.map +1 -1
  287. package/dist/emergent/SkillExporter.d.ts +119 -0
  288. package/dist/emergent/SkillExporter.d.ts.map +1 -0
  289. package/dist/emergent/SkillExporter.js +344 -0
  290. package/dist/emergent/SkillExporter.js.map +1 -0
  291. package/dist/emergent/index.d.ts +1 -0
  292. package/dist/emergent/index.d.ts.map +1 -1
  293. package/dist/emergent/index.js +1 -0
  294. package/dist/emergent/index.js.map +1 -1
  295. package/dist/emergent/types.d.ts +4 -4
  296. package/dist/index.d.ts +30 -5
  297. package/dist/index.d.ts.map +1 -1
  298. package/dist/index.js +19 -2
  299. package/dist/index.js.map +1 -1
  300. package/dist/memory/index.d.ts +10 -8
  301. package/dist/memory/index.d.ts.map +1 -1
  302. package/dist/memory/index.js +2 -0
  303. package/dist/memory/index.js.map +1 -1
  304. package/dist/memory/ingestion/DoclingLoader.d.ts +3 -3
  305. package/dist/memory/ingestion/DoclingLoader.d.ts.map +1 -1
  306. package/dist/memory/ingestion/DoclingLoader.js +12 -8
  307. package/dist/memory/ingestion/DoclingLoader.js.map +1 -1
  308. package/dist/memory/ingestion/FolderScanner.d.ts +7 -7
  309. package/dist/memory/ingestion/FolderScanner.d.ts.map +1 -1
  310. package/dist/memory/ingestion/FolderScanner.js +6 -6
  311. package/dist/memory/ingestion/FolderScanner.js.map +1 -1
  312. package/dist/memory/ingestion/LoaderRegistry.d.ts +8 -8
  313. package/dist/memory/ingestion/LoaderRegistry.d.ts.map +1 -1
  314. package/dist/memory/ingestion/LoaderRegistry.js +9 -11
  315. package/dist/memory/ingestion/LoaderRegistry.js.map +1 -1
  316. package/dist/memory/ingestion/MultimodalAggregator.d.ts +1 -1
  317. package/dist/memory/ingestion/MultimodalAggregator.js +1 -1
  318. package/dist/memory/ingestion/OcrPdfLoader.d.ts +2 -2
  319. package/dist/memory/ingestion/OcrPdfLoader.d.ts.map +1 -1
  320. package/dist/memory/ingestion/OcrPdfLoader.js +12 -8
  321. package/dist/memory/ingestion/OcrPdfLoader.js.map +1 -1
  322. package/dist/memory/ingestion/PdfLoader.d.ts +8 -8
  323. package/dist/memory/ingestion/PdfLoader.d.ts.map +1 -1
  324. package/dist/memory/ingestion/PdfLoader.js +13 -10
  325. package/dist/memory/ingestion/PdfLoader.js.map +1 -1
  326. package/dist/memory/io/MarkdownExporter.d.ts +1 -1
  327. package/dist/memory/io/MarkdownExporter.d.ts.map +1 -1
  328. package/dist/memory/io/MarkdownExporter.js +1 -1
  329. package/dist/memory/io/MarkdownExporter.js.map +1 -1
  330. package/dist/memory/tools/MemoryAddTool.d.ts +2 -2
  331. package/dist/memory/tools/MemoryAddTool.d.ts.map +1 -1
  332. package/dist/memory/tools/MemoryAddTool.js +8 -3
  333. package/dist/memory/tools/MemoryAddTool.js.map +1 -1
  334. package/dist/memory/tools/MemorySearchTool.d.ts +3 -3
  335. package/dist/memory/tools/MemorySearchTool.d.ts.map +1 -1
  336. package/dist/memory/tools/MemorySearchTool.js +11 -9
  337. package/dist/memory/tools/MemorySearchTool.js.map +1 -1
  338. package/dist/memory/tools/scopeContext.d.ts +11 -0
  339. package/dist/memory/tools/scopeContext.d.ts.map +1 -0
  340. package/dist/memory/tools/scopeContext.js +46 -0
  341. package/dist/memory/tools/scopeContext.js.map +1 -0
  342. package/dist/orchestration/builders/AgentGraph.d.ts +12 -11
  343. package/dist/orchestration/builders/AgentGraph.d.ts.map +1 -1
  344. package/dist/orchestration/builders/AgentGraph.js +12 -11
  345. package/dist/orchestration/builders/AgentGraph.js.map +1 -1
  346. package/dist/orchestration/builders/VoiceNodeBuilder.d.ts +2 -2
  347. package/dist/orchestration/builders/VoiceNodeBuilder.d.ts.map +1 -1
  348. package/dist/orchestration/builders/VoiceNodeBuilder.js +2 -2
  349. package/dist/orchestration/builders/VoiceNodeBuilder.js.map +1 -1
  350. package/dist/orchestration/builders/WorkflowBuilder.d.ts +1 -1
  351. package/dist/orchestration/builders/WorkflowBuilder.d.ts.map +1 -1
  352. package/dist/orchestration/builders/WorkflowBuilder.js +1 -1
  353. package/dist/orchestration/builders/WorkflowBuilder.js.map +1 -1
  354. package/dist/orchestration/checkpoint/InMemoryCheckpointStore.d.ts +7 -54
  355. package/dist/orchestration/checkpoint/InMemoryCheckpointStore.d.ts.map +1 -1
  356. package/dist/orchestration/checkpoint/InMemoryCheckpointStore.js +8 -56
  357. package/dist/orchestration/checkpoint/InMemoryCheckpointStore.js.map +1 -1
  358. package/dist/orchestration/events/GraphEvent.d.ts +12 -12
  359. package/dist/orchestration/events/GraphEvent.d.ts.map +1 -1
  360. package/dist/orchestration/events/GraphEvent.js.map +1 -1
  361. package/dist/orchestration/runtime/GraphRuntime.d.ts.map +1 -1
  362. package/dist/orchestration/runtime/GraphRuntime.js +151 -1
  363. package/dist/orchestration/runtime/GraphRuntime.js.map +1 -1
  364. package/dist/orchestration/runtime/LoopController.d.ts +3 -3
  365. package/dist/orchestration/runtime/LoopController.d.ts.map +1 -1
  366. package/dist/orchestration/runtime/LoopController.js.map +1 -1
  367. package/dist/orchestration/runtime/StateManager.d.ts +3 -3
  368. package/dist/orchestration/runtime/StateManager.js +3 -3
  369. package/dist/orchestration/runtime/VoiceNodeExecutor.d.ts +6 -6
  370. package/dist/orchestration/runtime/VoiceNodeExecutor.d.ts.map +1 -1
  371. package/dist/orchestration/runtime/VoiceNodeExecutor.js +27 -10
  372. package/dist/orchestration/runtime/VoiceNodeExecutor.js.map +1 -1
  373. package/dist/orchestration/runtime/VoiceTransportAdapter.d.ts +5 -5
  374. package/dist/orchestration/runtime/VoiceTransportAdapter.js +5 -5
  375. package/dist/orchestration/runtime/VoiceTurnCollector.d.ts +2 -2
  376. package/dist/orchestration/runtime/VoiceTurnCollector.js +2 -2
  377. package/dist/query-router/KeywordFallback.d.ts +70 -0
  378. package/dist/query-router/KeywordFallback.d.ts.map +1 -0
  379. package/dist/query-router/KeywordFallback.js +132 -0
  380. package/dist/query-router/KeywordFallback.js.map +1 -0
  381. package/dist/query-router/QueryClassifier.d.ts +140 -0
  382. package/dist/query-router/QueryClassifier.d.ts.map +1 -0
  383. package/dist/query-router/QueryClassifier.js +223 -0
  384. package/dist/query-router/QueryClassifier.js.map +1 -0
  385. package/dist/query-router/QueryDispatcher.d.ts +139 -0
  386. package/dist/query-router/QueryDispatcher.d.ts.map +1 -0
  387. package/dist/query-router/QueryDispatcher.js +297 -0
  388. package/dist/query-router/QueryDispatcher.js.map +1 -0
  389. package/dist/query-router/QueryGenerator.d.ts +184 -0
  390. package/dist/query-router/QueryGenerator.d.ts.map +1 -0
  391. package/dist/query-router/QueryGenerator.js +241 -0
  392. package/dist/query-router/QueryGenerator.js.map +1 -0
  393. package/dist/query-router/QueryRouter.d.ts +292 -0
  394. package/dist/query-router/QueryRouter.d.ts.map +1 -0
  395. package/dist/query-router/QueryRouter.js +803 -0
  396. package/dist/query-router/QueryRouter.js.map +1 -0
  397. package/dist/query-router/TopicExtractor.d.ts +73 -0
  398. package/dist/query-router/TopicExtractor.d.ts.map +1 -0
  399. package/dist/query-router/TopicExtractor.js +95 -0
  400. package/dist/query-router/TopicExtractor.js.map +1 -0
  401. package/dist/query-router/index.d.ts +40 -0
  402. package/dist/query-router/index.d.ts.map +1 -0
  403. package/dist/query-router/index.js +46 -0
  404. package/dist/query-router/index.js.map +1 -0
  405. package/dist/query-router/types.d.ts +508 -0
  406. package/dist/query-router/types.d.ts.map +1 -0
  407. package/dist/query-router/types.js +39 -0
  408. package/dist/query-router/types.js.map +1 -0
  409. package/dist/rag/index.d.ts +5 -0
  410. package/dist/rag/index.d.ts.map +1 -1
  411. package/dist/rag/index.js +7 -0
  412. package/dist/rag/index.js.map +1 -1
  413. package/dist/rag/multimodal/LLMVisionAdapter.d.ts +43 -0
  414. package/dist/rag/multimodal/LLMVisionAdapter.d.ts.map +1 -0
  415. package/dist/rag/multimodal/LLMVisionAdapter.js +46 -0
  416. package/dist/rag/multimodal/LLMVisionAdapter.js.map +1 -0
  417. package/dist/rag/multimodal/MultimodalIndexer.d.ts +244 -0
  418. package/dist/rag/multimodal/MultimodalIndexer.d.ts.map +1 -0
  419. package/dist/rag/multimodal/MultimodalIndexer.js +411 -0
  420. package/dist/rag/multimodal/MultimodalIndexer.js.map +1 -0
  421. package/dist/rag/multimodal/MultimodalMemoryBridge.d.ts +448 -0
  422. package/dist/rag/multimodal/MultimodalMemoryBridge.d.ts.map +1 -0
  423. package/dist/rag/multimodal/MultimodalMemoryBridge.js +941 -0
  424. package/dist/rag/multimodal/MultimodalMemoryBridge.js.map +1 -0
  425. package/dist/rag/multimodal/SpeechProviderAdapter.d.ts +139 -0
  426. package/dist/rag/multimodal/SpeechProviderAdapter.d.ts.map +1 -0
  427. package/dist/rag/multimodal/SpeechProviderAdapter.js +143 -0
  428. package/dist/rag/multimodal/SpeechProviderAdapter.js.map +1 -0
  429. package/dist/rag/multimodal/createMultimodalIndexerFromResolver.d.ts +172 -0
  430. package/dist/rag/multimodal/createMultimodalIndexerFromResolver.d.ts.map +1 -0
  431. package/dist/rag/multimodal/createMultimodalIndexerFromResolver.js +152 -0
  432. package/dist/rag/multimodal/createMultimodalIndexerFromResolver.js.map +1 -0
  433. package/dist/rag/multimodal/index.d.ts +44 -0
  434. package/dist/rag/multimodal/index.d.ts.map +1 -0
  435. package/dist/rag/multimodal/index.js +42 -0
  436. package/dist/rag/multimodal/index.js.map +1 -0
  437. package/dist/rag/multimodal/types.d.ts +276 -0
  438. package/dist/rag/multimodal/types.d.ts.map +1 -0
  439. package/dist/rag/multimodal/types.js +26 -0
  440. package/dist/rag/multimodal/types.js.map +1 -0
  441. package/dist/social-posting/SocialPostManager.d.ts +3 -3
  442. package/dist/social-posting/SocialPostManager.d.ts.map +1 -1
  443. package/dist/social-posting/SocialPostManager.js +3 -5
  444. package/dist/social-posting/SocialPostManager.js.map +1 -1
  445. package/dist/speech/FallbackProxy.d.ts +6 -6
  446. package/dist/speech/FallbackProxy.d.ts.map +1 -1
  447. package/dist/speech/FallbackProxy.js +3 -3
  448. package/dist/speech/FallbackProxy.js.map +1 -1
  449. package/dist/speech/SpeechProviderResolver.d.ts +8 -8
  450. package/dist/speech/SpeechProviderResolver.d.ts.map +1 -1
  451. package/dist/speech/SpeechProviderResolver.js +22 -11
  452. package/dist/speech/SpeechProviderResolver.js.map +1 -1
  453. package/dist/speech/SpeechRuntime.d.ts +1 -5
  454. package/dist/speech/SpeechRuntime.d.ts.map +1 -1
  455. package/dist/speech/SpeechRuntime.js +17 -9
  456. package/dist/speech/SpeechRuntime.js.map +1 -1
  457. package/dist/speech/providers/AssemblyAISTTProvider.d.ts +4 -4
  458. package/dist/speech/providers/AssemblyAISTTProvider.js +4 -4
  459. package/dist/speech/providers/AzureSpeechTTSProvider.d.ts +3 -3
  460. package/dist/speech/providers/AzureSpeechTTSProvider.js +2 -2
  461. package/dist/speech/providers/AzureSpeechTTSProvider.js.map +1 -1
  462. package/dist/speech/providers/BuiltInAdaptiveVadProvider.d.ts +9 -9
  463. package/dist/speech/providers/BuiltInAdaptiveVadProvider.d.ts.map +1 -1
  464. package/dist/speech/providers/BuiltInAdaptiveVadProvider.js +5 -5
  465. package/dist/speech/providers/BuiltInAdaptiveVadProvider.js.map +1 -1
  466. package/dist/speech/providers/DeepgramBatchSTTProvider.d.ts +2 -2
  467. package/dist/speech/providers/DeepgramBatchSTTProvider.js +2 -2
  468. package/dist/speech/providers/OpenAITextToSpeechProvider.d.ts +3 -3
  469. package/dist/speech/providers/OpenAITextToSpeechProvider.js +2 -2
  470. package/dist/speech/providers/OpenAIWhisperSpeechToTextProvider.d.ts +1 -1
  471. package/dist/speech/providers/OpenAIWhisperSpeechToTextProvider.d.ts.map +1 -1
  472. package/dist/speech/providers/OpenAIWhisperSpeechToTextProvider.js +1 -1
  473. package/dist/speech/providers/OpenAIWhisperSpeechToTextProvider.js.map +1 -1
  474. package/dist/voice/TelephonyStreamTransport.d.ts +6 -6
  475. package/dist/voice/TelephonyStreamTransport.d.ts.map +1 -1
  476. package/dist/voice/TelephonyStreamTransport.js +5 -5
  477. package/dist/voice/TelephonyStreamTransport.js.map +1 -1
  478. package/dist/voice-pipeline/AcousticEndpointDetector.d.ts +4 -4
  479. package/dist/voice-pipeline/AcousticEndpointDetector.d.ts.map +1 -1
  480. package/dist/voice-pipeline/AcousticEndpointDetector.js +4 -4
  481. package/dist/voice-pipeline/AcousticEndpointDetector.js.map +1 -1
  482. package/dist/voice-pipeline/HardCutBargeinHandler.d.ts +3 -3
  483. package/dist/voice-pipeline/HardCutBargeinHandler.js +3 -3
  484. package/dist/voice-pipeline/HeuristicEndpointDetector.d.ts +3 -3
  485. package/dist/voice-pipeline/HeuristicEndpointDetector.d.ts.map +1 -1
  486. package/dist/voice-pipeline/HeuristicEndpointDetector.js +3 -3
  487. package/dist/voice-pipeline/HeuristicEndpointDetector.js.map +1 -1
  488. package/dist/voice-pipeline/SoftFadeBargeinHandler.d.ts +5 -5
  489. package/dist/voice-pipeline/SoftFadeBargeinHandler.js +1 -1
  490. package/dist/voice-pipeline/VoiceInterruptError.d.ts +6 -6
  491. package/dist/voice-pipeline/VoiceInterruptError.d.ts.map +1 -1
  492. package/dist/voice-pipeline/VoiceInterruptError.js +4 -4
  493. package/dist/voice-pipeline/VoiceInterruptError.js.map +1 -1
  494. package/dist/voice-pipeline/VoicePipelineOrchestrator.d.ts +9 -9
  495. package/dist/voice-pipeline/VoicePipelineOrchestrator.d.ts.map +1 -1
  496. package/dist/voice-pipeline/VoicePipelineOrchestrator.js +8 -8
  497. package/dist/voice-pipeline/VoicePipelineOrchestrator.js.map +1 -1
  498. package/dist/voice-pipeline/WebRTCStreamTransport.d.ts +421 -0
  499. package/dist/voice-pipeline/WebRTCStreamTransport.d.ts.map +1 -0
  500. package/dist/voice-pipeline/WebRTCStreamTransport.js +573 -0
  501. package/dist/voice-pipeline/WebRTCStreamTransport.js.map +1 -0
  502. package/dist/voice-pipeline/WebSocketStreamTransport.d.ts +8 -8
  503. package/dist/voice-pipeline/WebSocketStreamTransport.js +5 -5
  504. package/dist/voice-pipeline/index.d.ts +1 -0
  505. package/dist/voice-pipeline/index.d.ts.map +1 -1
  506. package/dist/voice-pipeline/index.js +2 -0
  507. package/dist/voice-pipeline/index.js.map +1 -1
  508. package/dist/voice-pipeline/types.d.ts +43 -43
  509. package/dist/voice-pipeline/types.d.ts.map +1 -1
  510. package/package.json +19 -1
@@ -0,0 +1,1004 @@
1
+ // @ts-nocheck
2
+ // File: backend/agentos/core/llm/providers/implementations/GeminiProvider.ts
3
+ import { GeminiProviderError } from '../errors/GeminiProviderError.js';
4
+ // ---------------------------------------------------------------------------
5
+ // Known model catalog
6
+ // ---------------------------------------------------------------------------
7
+ /** Static catalog of well-known Gemini models and their metadata. */
8
+ const GEMINI_MODELS = [
9
+ {
10
+ modelId: 'gemini-2.5-flash',
11
+ providerId: 'gemini',
12
+ displayName: 'Gemini 2.5 Flash',
13
+ description: 'Fast, cost-effective model with strong reasoning and multimodal capabilities.',
14
+ capabilities: ['chat', 'tool_use', 'vision_input', 'json_mode'],
15
+ contextWindowSize: 1048576,
16
+ outputTokenLimit: 65536,
17
+ pricePer1MTokensInput: 0.15,
18
+ pricePer1MTokensOutput: 0.60,
19
+ supportsStreaming: true,
20
+ status: 'active',
21
+ },
22
+ {
23
+ modelId: 'gemini-2.5-pro',
24
+ providerId: 'gemini',
25
+ displayName: 'Gemini 2.5 Pro',
26
+ description: 'Most capable Gemini model for complex reasoning and analysis.',
27
+ capabilities: ['chat', 'tool_use', 'vision_input', 'json_mode'],
28
+ contextWindowSize: 1048576,
29
+ outputTokenLimit: 65536,
30
+ pricePer1MTokensInput: 1.25,
31
+ pricePer1MTokensOutput: 10.00,
32
+ supportsStreaming: true,
33
+ status: 'active',
34
+ },
35
+ {
36
+ modelId: 'gemini-2.0-flash',
37
+ providerId: 'gemini',
38
+ displayName: 'Gemini 2.0 Flash',
39
+ description: 'Previous-generation fast model with strong performance.',
40
+ capabilities: ['chat', 'tool_use', 'vision_input', 'json_mode'],
41
+ contextWindowSize: 1048576,
42
+ outputTokenLimit: 8192,
43
+ pricePer1MTokensInput: 0.10,
44
+ pricePer1MTokensOutput: 0.40,
45
+ supportsStreaming: true,
46
+ status: 'active',
47
+ },
48
+ {
49
+ modelId: 'gemini-1.5-pro',
50
+ providerId: 'gemini',
51
+ displayName: 'Gemini 1.5 Pro',
52
+ description: 'Stable model with 2M context window for long-document tasks.',
53
+ capabilities: ['chat', 'tool_use', 'vision_input', 'json_mode'],
54
+ contextWindowSize: 2097152,
55
+ outputTokenLimit: 8192,
56
+ pricePer1MTokensInput: 1.25,
57
+ pricePer1MTokensOutput: 5.00,
58
+ supportsStreaming: true,
59
+ status: 'active',
60
+ },
61
+ ];
62
+ // ---------------------------------------------------------------------------
63
+ // Provider implementation
64
+ // ---------------------------------------------------------------------------
65
+ /**
66
+ * @class GeminiProvider
67
+ * @implements {IProvider}
68
+ *
69
+ * Provides native integration with Google's Gemini REST API.
70
+ *
71
+ * Handles the structural differences between Gemini's API and the OpenAI-style
72
+ * conventions used by IProvider: role mapping (`assistant` -> `model`), system
73
+ * instruction extraction, tool schema translation, and finish reason normalization.
74
+ *
75
+ * @example
76
+ * const provider = new GeminiProvider();
77
+ * await provider.initialize({ apiKey: 'AIzaSy...' });
78
+ * const response = await provider.generateCompletion(
79
+ * 'gemini-2.5-flash',
80
+ * [{ role: 'user', content: 'Hello!' }],
81
+ * { maxTokens: 1024 },
82
+ * );
83
+ */
84
+ export class GeminiProvider {
85
+ constructor() {
86
+ /** @inheritdoc */
87
+ this.providerId = 'gemini';
88
+ /** @inheritdoc */
89
+ this.isInitialized = false;
90
+ }
91
+ // -------------------------------------------------------------------------
92
+ // Lifecycle
93
+ // -------------------------------------------------------------------------
94
+ /**
95
+ * Initialize the Gemini provider with the given configuration.
96
+ *
97
+ * Validates that an API key is present. Does NOT make a network call on
98
+ * startup — Gemini does not have a lightweight health/models endpoint
99
+ * that works without model-scoped paths.
100
+ *
101
+ * @param {GeminiProviderConfig} config - Provider configuration.
102
+ * @returns {Promise<void>}
103
+ * @throws {GeminiProviderError} If the API key is missing.
104
+ */
105
+ async initialize(config) {
106
+ if (!config.apiKey) {
107
+ throw new GeminiProviderError('API key is required for GeminiProvider initialization. Set GEMINI_API_KEY.', 'INIT_FAILED_MISSING_API_KEY');
108
+ }
109
+ this.config = {
110
+ baseURL: 'https://generativelanguage.googleapis.com/v1beta',
111
+ maxRetries: 3,
112
+ requestTimeout: 60000,
113
+ defaultModelId: 'gemini-2.5-flash',
114
+ ...config,
115
+ };
116
+ this.defaultModelId = this.config.defaultModelId;
117
+ this.isInitialized = true;
118
+ console.log(`GeminiProvider initialized. Default model: ${this.defaultModelId || 'Not set'}.`);
119
+ }
120
+ // -------------------------------------------------------------------------
121
+ // Chat completions (non-streaming)
122
+ // -------------------------------------------------------------------------
123
+ /**
124
+ * Generates a non-streaming chat completion via Gemini's generateContent endpoint.
125
+ *
126
+ * Extracts system messages and places them in the `systemInstruction` field,
127
+ * maps `assistant` role to `model`, converts tool definitions to Gemini's
128
+ * `functionDeclarations` format, and normalizes the response back to
129
+ * IProvider conventions.
130
+ *
131
+ * @param {string} modelId - The Gemini model to use (e.g., "gemini-2.5-flash").
132
+ * @param {ChatMessage[]} messages - Conversation messages. System-role messages are
133
+ * extracted and sent as the `systemInstruction` field.
134
+ * @param {ModelCompletionOptions} options - Completion options.
135
+ * @returns {Promise<ModelCompletionResponse>} A normalized completion response.
136
+ * @throws {GeminiProviderError} On authentication, validation, or network errors.
137
+ *
138
+ * @example
139
+ * const resp = await provider.generateCompletion('gemini-2.5-flash', [
140
+ * { role: 'system', content: 'You are a helpful assistant.' },
141
+ * { role: 'user', content: 'Explain quantum computing in one sentence.' },
142
+ * ], { maxTokens: 256 });
143
+ * console.log(resp.choices[0].message.content);
144
+ */
145
+ async generateCompletion(modelId, messages, options) {
146
+ this.ensureInitialized();
147
+ const payload = this.buildRequestPayload(modelId, messages, options);
148
+ // Gemini uses model-scoped endpoints: /models/{model}:generateContent
149
+ const endpoint = `/models/${modelId}:generateContent`;
150
+ const apiResponse = await this.makeApiRequest(endpoint, payload);
151
+ return this.mapResponseToCompletion(apiResponse, modelId);
152
+ }
153
+ // -------------------------------------------------------------------------
154
+ // Chat completions (streaming)
155
+ // -------------------------------------------------------------------------
156
+ /**
157
+ * Generates a streaming chat completion via Gemini's streamGenerateContent endpoint.
158
+ *
159
+ * Gemini streaming uses SSE with `alt=sse` query parameter. Each SSE data line
160
+ * contains a JSON object with `candidates[].content.parts[].text` for text deltas
161
+ * and `candidates[].content.parts[].functionCall` for tool invocations.
162
+ *
163
+ * Normalizes all events into the IProvider streaming contract with
164
+ * `responseTextDelta`, `toolCallsDeltas`, and `isFinal`.
165
+ *
166
+ * @param {string} modelId - The Gemini model to use.
167
+ * @param {ChatMessage[]} messages - Conversation messages.
168
+ * @param {ModelCompletionOptions} options - Completion options.
169
+ * @returns {AsyncGenerator<ModelCompletionResponse>} Incremental response chunks.
170
+ * @throws {GeminiProviderError} On connection or stream errors.
171
+ */
172
+ async *generateCompletionStream(modelId, messages, options) {
173
+ this.ensureInitialized();
174
+ const payload = this.buildRequestPayload(modelId, messages, options);
175
+ const responseId = `gemini-${modelId}-${Date.now()}`;
176
+ // Handle pre-aborted signals
177
+ const abortSignal = options.abortSignal;
178
+ if (abortSignal?.aborted) {
179
+ yield this.buildAbortChunk(modelId);
180
+ return;
181
+ }
182
+ // Streaming endpoint uses ?alt=sse and the API key query param
183
+ const endpoint = `/models/${modelId}:streamGenerateContent`;
184
+ const stream = await this.makeStreamRequest(endpoint, payload);
185
+ // Accumulators for building the complete response
186
+ let accumulatedContent = '';
187
+ let lastFinishReason = null;
188
+ let lastUsage;
189
+ /** Map from part index -> tool call accumulator */
190
+ const toolCallAccum = new Map();
191
+ let toolCallIndex = 0;
192
+ const abortHandler = () => { };
193
+ abortSignal?.addEventListener('abort', abortHandler, { once: true });
194
+ try {
195
+ for await (const rawData of this.parseSseStream(stream)) {
196
+ if (abortSignal?.aborted) {
197
+ yield this.buildAbortChunk(modelId);
198
+ break;
199
+ }
200
+ let chunk;
201
+ try {
202
+ chunk = JSON.parse(rawData);
203
+ }
204
+ catch {
205
+ // Malformed JSON — skip
206
+ console.warn('GeminiProvider: Could not parse SSE event JSON:', rawData);
207
+ continue;
208
+ }
209
+ // Handle API-level errors in the stream
210
+ if (chunk.error) {
211
+ yield {
212
+ id: responseId,
213
+ object: 'chat.completion.chunk',
214
+ created: Math.floor(Date.now() / 1000),
215
+ modelId,
216
+ choices: [],
217
+ error: {
218
+ message: chunk.error.message,
219
+ type: chunk.error.status,
220
+ code: chunk.error.code,
221
+ },
222
+ isFinal: true,
223
+ };
224
+ return;
225
+ }
226
+ // Track usage from every chunk — the last one will have final totals
227
+ if (chunk.usageMetadata) {
228
+ lastUsage = chunk.usageMetadata;
229
+ }
230
+ const candidate = chunk.candidates?.[0];
231
+ if (!candidate)
232
+ continue;
233
+ if (candidate.finishReason) {
234
+ lastFinishReason = candidate.finishReason;
235
+ }
236
+ const parts = candidate.content?.parts ?? [];
237
+ for (const part of parts) {
238
+ if (part.text !== undefined) {
239
+ // Text delta
240
+ accumulatedContent += part.text;
241
+ yield {
242
+ id: responseId,
243
+ object: 'chat.completion.chunk',
244
+ created: Math.floor(Date.now() / 1000),
245
+ modelId,
246
+ choices: [{
247
+ index: 0,
248
+ message: { role: 'assistant', content: part.text },
249
+ finishReason: null,
250
+ }],
251
+ responseTextDelta: part.text,
252
+ };
253
+ }
254
+ else if (part.functionCall) {
255
+ // Tool call — Gemini delivers function calls as complete objects,
256
+ // not incremental deltas. We emit them as a single delta per call.
257
+ const idx = toolCallIndex++;
258
+ toolCallAccum.set(idx, {
259
+ name: part.functionCall.name,
260
+ args: part.functionCall.args,
261
+ });
262
+ yield {
263
+ id: responseId,
264
+ object: 'chat.completion.chunk',
265
+ created: Math.floor(Date.now() / 1000),
266
+ modelId,
267
+ choices: [{
268
+ index: 0,
269
+ message: { role: 'assistant', content: null },
270
+ finishReason: null,
271
+ }],
272
+ toolCallsDeltas: [{
273
+ index: idx,
274
+ id: `call_gemini_${Date.now()}_${idx}`,
275
+ type: 'function',
276
+ function: {
277
+ name: part.functionCall.name,
278
+ // Gemini delivers complete args, so emit them as a single delta
279
+ arguments_delta: JSON.stringify(part.functionCall.args),
280
+ },
281
+ }],
282
+ };
283
+ }
284
+ }
285
+ }
286
+ // Emit final chunk with usage and finish reason
287
+ const toolCalls = this.assembleToolCalls(toolCallAccum);
288
+ const hasToolCalls = toolCalls.length > 0;
289
+ const usage = this.mapUsage(lastUsage, modelId);
290
+ yield {
291
+ id: responseId,
292
+ object: 'chat.completion.chunk',
293
+ created: Math.floor(Date.now() / 1000),
294
+ modelId,
295
+ choices: [{
296
+ index: 0,
297
+ message: {
298
+ role: 'assistant',
299
+ content: accumulatedContent || null,
300
+ ...(hasToolCalls && { tool_calls: toolCalls }),
301
+ },
302
+ finishReason: this.mapFinishReason(lastFinishReason),
303
+ }],
304
+ usage,
305
+ isFinal: true,
306
+ };
307
+ }
308
+ catch (streamError) {
309
+ const message = streamError instanceof Error
310
+ ? streamError.message
311
+ : 'Gemini stream processing error';
312
+ console.error(`GeminiProvider stream error for model ${modelId}:`, message);
313
+ yield {
314
+ id: responseId,
315
+ object: 'chat.completion.chunk',
316
+ created: Math.floor(Date.now() / 1000),
317
+ modelId,
318
+ choices: [],
319
+ isFinal: true,
320
+ error: { message, type: 'STREAM_PROCESSING_ERROR' },
321
+ };
322
+ }
323
+ finally {
324
+ abortSignal?.removeEventListener('abort', abortHandler);
325
+ }
326
+ }
327
+ // -------------------------------------------------------------------------
328
+ // Embeddings
329
+ // -------------------------------------------------------------------------
330
+ /**
331
+ * Generates embeddings using Gemini's embedding models.
332
+ *
333
+ * Uses the `models/{model}:embedContent` endpoint. Currently Gemini
334
+ * supports embedding one text at a time, so we batch sequentially.
335
+ *
336
+ * @param {string} modelId - Embedding model (e.g., "text-embedding-004").
337
+ * @param {string[]} texts - Input texts to embed.
338
+ * @param {ProviderEmbeddingOptions} [options] - Optional embedding parameters.
339
+ * @returns {Promise<ProviderEmbeddingResponse>} Embedding vectors.
340
+ * @throws {GeminiProviderError} On API errors.
341
+ */
342
+ async generateEmbeddings(modelId, texts, options) {
343
+ this.ensureInitialized();
344
+ // Gemini's batch embedding endpoint
345
+ const endpoint = `/models/${modelId}:batchEmbedContents`;
346
+ const requests = texts.map(text => ({
347
+ model: `models/${modelId}`,
348
+ content: { parts: [{ text }] },
349
+ }));
350
+ const apiResponse = await this.makeApiRequest(endpoint, { requests });
351
+ return {
352
+ object: 'list',
353
+ data: apiResponse.embeddings.map((emb, index) => ({
354
+ object: 'embedding',
355
+ embedding: emb.values,
356
+ index,
357
+ })),
358
+ model: modelId,
359
+ usage: {
360
+ prompt_tokens: 0, // Gemini does not report embedding token counts
361
+ total_tokens: 0,
362
+ },
363
+ };
364
+ }
365
+ // -------------------------------------------------------------------------
366
+ // Introspection
367
+ // -------------------------------------------------------------------------
368
+ /**
369
+ * Returns a static catalog of known Gemini models.
370
+ *
371
+ * Uses a hardcoded catalog kept up-to-date with major releases, since
372
+ * the Gemini models list endpoint requires iterating over all models.
373
+ *
374
+ * @param {{ capability?: string }} [filter] - Optional capability filter.
375
+ * @returns {Promise<ModelInfo[]>} Array of known Gemini models.
376
+ */
377
+ async listAvailableModels(filter) {
378
+ this.ensureInitialized();
379
+ if (filter?.capability) {
380
+ return GEMINI_MODELS.filter(m => m.capabilities.includes(filter.capability));
381
+ }
382
+ return [...GEMINI_MODELS];
383
+ }
384
+ /**
385
+ * Retrieves metadata for a specific Gemini model from the static catalog.
386
+ *
387
+ * @param {string} modelId - Model identifier (e.g., "gemini-2.5-flash").
388
+ * @returns {Promise<ModelInfo | undefined>} Model info or undefined if not found.
389
+ */
390
+ async getModelInfo(modelId) {
391
+ this.ensureInitialized();
392
+ return GEMINI_MODELS.find(m => m.modelId === modelId);
393
+ }
394
+ /**
395
+ * Performs a lightweight health check by sending a minimal generateContent request.
396
+ *
397
+ * @returns {Promise<{ isHealthy: boolean; details?: unknown }>} Health status.
398
+ */
399
+ async checkHealth() {
400
+ try {
401
+ const model = this.defaultModelId || 'gemini-2.5-flash';
402
+ await this.makeApiRequest(`/models/${model}:generateContent`, {
403
+ contents: [{ role: 'user', parts: [{ text: 'ping' }] }],
404
+ generationConfig: { maxOutputTokens: 1 },
405
+ });
406
+ return { isHealthy: true };
407
+ }
408
+ catch (error) {
409
+ const message = error instanceof Error ? error.message : 'Health check failed';
410
+ return { isHealthy: false, details: { message, error } };
411
+ }
412
+ }
413
+ /** @inheritdoc */
414
+ async shutdown() {
415
+ this.isInitialized = false;
416
+ console.log('GeminiProvider shutdown complete.');
417
+ }
418
+ // =========================================================================
419
+ // Private helpers
420
+ // =========================================================================
421
+ /**
422
+ * Guard that throws if the provider has not been initialized.
423
+ *
424
+ * @private
425
+ * @throws {GeminiProviderError} If not initialized.
426
+ */
427
+ ensureInitialized() {
428
+ if (!this.isInitialized) {
429
+ throw new GeminiProviderError('GeminiProvider is not initialized. Call initialize() first.', 'PROVIDER_NOT_INITIALIZED');
430
+ }
431
+ }
432
+ // -------------------------------------------------------------------------
433
+ // Payload construction
434
+ // -------------------------------------------------------------------------
435
+ /**
436
+ * Builds the Gemini API request payload from IProvider inputs.
437
+ *
438
+ * The key transformations are:
439
+ * 1. System messages extracted to `systemInstruction` (Gemini has no system role).
440
+ * 2. `assistant` role mapped to `model` (Gemini's convention).
441
+ * 3. Tool messages mapped to `functionResponse` parts within user turns.
442
+ * 4. OpenAI-style tool definitions converted to `functionDeclarations`.
443
+ *
444
+ * @param {string} _modelId - Target model (used for endpoint, not in body).
445
+ * @param {ChatMessage[]} messages - Conversation messages.
446
+ * @param {ModelCompletionOptions} options - Completion options.
447
+ * @returns {Record<string, unknown>} The request body for Gemini's API.
448
+ * @private
449
+ */
450
+ buildRequestPayload(_modelId, messages, options) {
451
+ // --- Extract system messages into systemInstruction ---
452
+ // Gemini treats system instructions as a separate top-level field,
453
+ // similar to Anthropic but with a `parts` array wrapper.
454
+ const systemParts = [];
455
+ const conversationMessages = [];
456
+ for (const msg of messages) {
457
+ if (msg.role === 'system') {
458
+ const text = typeof msg.content === 'string'
459
+ ? msg.content
460
+ : Array.isArray(msg.content)
461
+ ? msg.content.filter(p => p.type === 'text').map(p => p.text).join('\n')
462
+ : '';
463
+ if (text)
464
+ systemParts.push(text);
465
+ }
466
+ else {
467
+ conversationMessages.push(msg);
468
+ }
469
+ }
470
+ // --- Convert messages to Gemini content format ---
471
+ const contents = this.convertMessages(conversationMessages);
472
+ const payload = {
473
+ contents,
474
+ };
475
+ // Include systemInstruction only if there's system content
476
+ if (systemParts.length > 0) {
477
+ payload.systemInstruction = {
478
+ parts: [{ text: systemParts.join('\n\n') }],
479
+ };
480
+ }
481
+ // --- Generation config ---
482
+ const generationConfig = {};
483
+ if (options.temperature !== undefined)
484
+ generationConfig.temperature = options.temperature;
485
+ if (options.maxTokens !== undefined)
486
+ generationConfig.maxOutputTokens = options.maxTokens;
487
+ if (options.topP !== undefined)
488
+ generationConfig.topP = options.topP;
489
+ if (options.stopSequences?.length)
490
+ generationConfig.stopSequences = options.stopSequences;
491
+ // JSON mode: Gemini uses responseMimeType to enforce JSON output
492
+ if (options.responseFormat?.type === 'json_object') {
493
+ generationConfig.responseMimeType = 'application/json';
494
+ }
495
+ // topK support via customModelParams
496
+ if (options.customModelParams?.topK !== undefined) {
497
+ generationConfig.topK = options.customModelParams.topK;
498
+ }
499
+ if (Object.keys(generationConfig).length > 0) {
500
+ payload.generationConfig = generationConfig;
501
+ }
502
+ // --- Tool definitions ---
503
+ const tools = this.convertToolDefs(options.tools);
504
+ if (tools.length > 0) {
505
+ payload.tools = [{ functionDeclarations: tools }];
506
+ }
507
+ // Pass through custom model params (excluding ones we already handle)
508
+ if (options.customModelParams) {
509
+ const { topK, ...rest } = options.customModelParams;
510
+ if (Object.keys(rest).length > 0) {
511
+ Object.assign(payload, rest);
512
+ }
513
+ }
514
+ return payload;
515
+ }
516
+ /**
517
+ * Converts an array of ChatMessages to Gemini's content format.
518
+ *
519
+ * Maps IProvider roles to Gemini roles:
520
+ * - `user` -> `user`
521
+ * - `assistant` -> `model` (Gemini uses "model" instead of "assistant")
522
+ * - `tool` -> `user` with `functionResponse` parts
523
+ *
524
+ * @param {ChatMessage[]} messages - IProvider-format messages.
525
+ * @returns {GeminiContent[]} Gemini-format content array.
526
+ * @private
527
+ */
528
+ convertMessages(messages) {
529
+ const contents = [];
530
+ for (const msg of messages) {
531
+ if (msg.role === 'assistant') {
532
+ // --- Assistant messages map to "model" role ---
533
+ const parts = [];
534
+ // Add text content if present
535
+ if (typeof msg.content === 'string' && msg.content) {
536
+ parts.push({ text: msg.content });
537
+ }
538
+ // Convert tool_calls to functionCall parts
539
+ if (msg.tool_calls?.length) {
540
+ for (const tc of msg.tool_calls) {
541
+ let parsedArgs;
542
+ try {
543
+ parsedArgs = typeof tc.function.arguments === 'string'
544
+ ? JSON.parse(tc.function.arguments)
545
+ : tc.function.arguments ?? {};
546
+ }
547
+ catch {
548
+ parsedArgs = {};
549
+ }
550
+ parts.push({
551
+ functionCall: { name: tc.function.name, args: parsedArgs },
552
+ });
553
+ }
554
+ }
555
+ // Ensure at least one part — Gemini requires non-empty parts
556
+ if (parts.length === 0) {
557
+ parts.push({ text: '' });
558
+ }
559
+ contents.push({ role: 'model', parts });
560
+ }
561
+ else if (msg.role === 'tool') {
562
+ // --- Tool result messages become user-role functionResponse ---
563
+ // Gemini expects tool results as functionResponse parts in a user turn.
564
+ let responseData;
565
+ try {
566
+ const raw = typeof msg.content === 'string' ? msg.content : JSON.stringify(msg.content ?? '');
567
+ responseData = typeof msg.content === 'string'
568
+ ? JSON.parse(raw)
569
+ : { result: raw };
570
+ }
571
+ catch {
572
+ // If the tool result isn't valid JSON, wrap it
573
+ responseData = { result: typeof msg.content === 'string' ? msg.content : String(msg.content) };
574
+ }
575
+ contents.push({
576
+ role: 'user',
577
+ parts: [{
578
+ functionResponse: {
579
+ name: msg.name || 'unknown',
580
+ response: responseData,
581
+ },
582
+ }],
583
+ });
584
+ }
585
+ else {
586
+ // --- User messages ---
587
+ const parts = [];
588
+ if (typeof msg.content === 'string') {
589
+ parts.push({ text: msg.content });
590
+ }
591
+ else if (Array.isArray(msg.content)) {
592
+ // Multimodal content — extract text parts
593
+ for (const part of msg.content) {
594
+ if (part.type === 'text') {
595
+ parts.push({ text: part.text });
596
+ }
597
+ // Image support could be added here via inlineData parts
598
+ }
599
+ }
600
+ if (parts.length === 0) {
601
+ parts.push({ text: '' });
602
+ }
603
+ contents.push({ role: 'user', parts });
604
+ }
605
+ }
606
+ return contents;
607
+ }
608
+ /**
609
+ * Converts OpenAI-style tool definitions to Gemini's functionDeclarations format.
610
+ *
611
+ * OpenAI uses `{ type: 'function', function: { name, description, parameters } }`
612
+ * while Gemini uses `{ name, description, parameters }` inside a `functionDeclarations` array.
613
+ *
614
+ * @param {Array<Record<string, unknown>>} [tools] - OpenAI-formatted tool defs.
615
+ * @returns {GeminiFunctionDeclaration[]} Gemini-formatted function declarations.
616
+ * @private
617
+ */
618
+ convertToolDefs(tools) {
619
+ if (!tools || tools.length === 0)
620
+ return [];
621
+ return tools.map(tool => {
622
+ // OpenAI format: { type: 'function', function: { name, description, parameters } }
623
+ const fn = tool?.function;
624
+ if (fn?.name) {
625
+ return {
626
+ name: fn.name,
627
+ description: (fn.description ?? ''),
628
+ // Gemini uses the same "parameters" field name as OpenAI, unlike Anthropic's input_schema
629
+ parameters: fn.parameters,
630
+ };
631
+ }
632
+ // AgentOS ITool format: { name, description, inputSchema }
633
+ return {
634
+ name: tool.name ?? 'unknown',
635
+ description: tool.description ?? '',
636
+ parameters: tool.inputSchema ?? tool.parameters,
637
+ };
638
+ });
639
+ }
640
+ // -------------------------------------------------------------------------
641
+ // Response mapping
642
+ // -------------------------------------------------------------------------
643
+ /**
644
+ * Maps a non-streaming Gemini response to IProvider format.
645
+ *
646
+ * Extracts text from `candidates[0].content.parts`, converts `functionCall`
647
+ * parts to OpenAI-style `tool_calls`, and normalizes usage metadata.
648
+ *
649
+ * @param {GeminiResponse} apiResponse - Raw Gemini API response.
650
+ * @param {string} modelId - The model ID used for the request.
651
+ * @returns {ModelCompletionResponse} Normalized completion response.
652
+ * @private
653
+ */
654
+ mapResponseToCompletion(apiResponse, modelId) {
655
+ const candidate = apiResponse.candidates?.[0];
656
+ const parts = candidate?.content?.parts ?? [];
657
+ // Collect text from all text parts
658
+ const textParts = parts
659
+ .filter(p => p.text !== undefined)
660
+ .map(p => p.text);
661
+ const fullText = textParts.join('');
662
+ // Collect function calls and convert to OpenAI-style tool_calls
663
+ const toolCalls = parts
664
+ .filter(p => p.functionCall)
665
+ .map((p, idx) => ({
666
+ id: `call_gemini_${Date.now()}_${idx}`,
667
+ type: 'function',
668
+ function: {
669
+ name: p.functionCall.name,
670
+ arguments: JSON.stringify(p.functionCall.args ?? {}),
671
+ },
672
+ }));
673
+ const hasToolCalls = toolCalls.length > 0;
674
+ const finishReason = this.mapFinishReason(candidate?.finishReason ?? null);
675
+ const usage = this.mapUsage(apiResponse.usageMetadata, modelId);
676
+ const choice = {
677
+ index: 0,
678
+ message: {
679
+ role: 'assistant',
680
+ content: fullText || null,
681
+ ...(hasToolCalls && { tool_calls: toolCalls }),
682
+ },
683
+ finishReason,
684
+ };
685
+ return {
686
+ id: `gemini-${modelId}-${Date.now()}`,
687
+ object: 'chat.completion',
688
+ created: Math.floor(Date.now() / 1000),
689
+ modelId,
690
+ choices: [choice],
691
+ usage,
692
+ };
693
+ }
694
+ /**
695
+ * Maps Gemini finish reasons to IProvider-convention finish reasons.
696
+ *
697
+ * Gemini uses uppercase enum strings:
698
+ * - `STOP` -> `"stop"` (natural completion)
699
+ * - `MAX_TOKENS` -> `"length"` (hit token limit)
700
+ * - `SAFETY` -> `"content_filter"` (blocked by safety filters)
701
+ * - `RECITATION` -> `"content_filter"` (blocked by recitation check)
702
+ *
703
+ * @param {string | null} finishReason - Gemini's finish reason value.
704
+ * @returns {string} Normalized finish reason.
705
+ * @private
706
+ */
707
+ mapFinishReason(finishReason) {
708
+ switch (finishReason) {
709
+ case 'STOP': return 'stop';
710
+ case 'MAX_TOKENS': return 'length';
711
+ case 'SAFETY': return 'content_filter';
712
+ case 'RECITATION': return 'content_filter';
713
+ default: return finishReason?.toLowerCase() ?? 'stop';
714
+ }
715
+ }
716
+ /**
717
+ * Maps Gemini usage metadata to IProvider's ModelUsage format.
718
+ *
719
+ * @param {GeminiUsageMetadata} [meta] - Gemini usage metadata.
720
+ * @param {string} modelId - Model ID for cost estimation.
721
+ * @returns {ModelUsage} Normalized usage metrics.
722
+ * @private
723
+ */
724
+ mapUsage(meta, modelId) {
725
+ const promptTokens = meta?.promptTokenCount ?? 0;
726
+ const completionTokens = meta?.candidatesTokenCount ?? 0;
727
+ const totalTokens = meta?.totalTokenCount ?? (promptTokens + completionTokens);
728
+ return {
729
+ promptTokens,
730
+ completionTokens,
731
+ totalTokens,
732
+ costUSD: this.estimateCost(promptTokens, completionTokens, modelId),
733
+ };
734
+ }
735
+ /**
736
+ * Assembles completed tool calls from the streaming accumulator.
737
+ *
738
+ * @param {Map<number, { name: string; args: Record<string, unknown> }>} accum - Accumulated tool calls.
739
+ * @returns {NonNullable<ChatMessage['tool_calls']>} OpenAI-style tool_calls array.
740
+ * @private
741
+ */
742
+ assembleToolCalls(accum) {
743
+ if (accum.size === 0)
744
+ return [];
745
+ return Array.from(accum.entries()).map(([idx, tc]) => ({
746
+ id: `call_gemini_${Date.now()}_${idx}`,
747
+ type: 'function',
748
+ function: {
749
+ name: tc.name,
750
+ arguments: JSON.stringify(tc.args ?? {}),
751
+ },
752
+ }));
753
+ }
754
+ /**
755
+ * Estimates USD cost for a given model and token counts.
756
+ *
757
+ * Looks up pricing from the static model catalog. Returns undefined
758
+ * if the model is not found in the catalog.
759
+ *
760
+ * @param {number} inputTokens - Number of input tokens.
761
+ * @param {number} outputTokens - Number of output tokens.
762
+ * @param {string} modelId - Model identifier for pricing lookup.
763
+ * @returns {number | undefined} Estimated cost in USD.
764
+ * @private
765
+ */
766
+ estimateCost(inputTokens, outputTokens, modelId) {
767
+ const info = GEMINI_MODELS.find(m => m.modelId === modelId);
768
+ if (!info?.pricePer1MTokensInput || !info?.pricePer1MTokensOutput)
769
+ return undefined;
770
+ return ((inputTokens / 1000000) * info.pricePer1MTokensInput +
771
+ (outputTokens / 1000000) * info.pricePer1MTokensOutput);
772
+ }
773
+ /**
774
+ * Builds an abort chunk for early stream termination.
775
+ *
776
+ * @param {string} modelId - The model ID for the response.
777
+ * @returns {ModelCompletionResponse} A terminal chunk with abort error.
778
+ * @private
779
+ */
780
+ buildAbortChunk(modelId) {
781
+ return {
782
+ id: `gemini-abort-${Date.now()}`,
783
+ object: 'chat.completion.chunk',
784
+ created: Math.floor(Date.now() / 1000),
785
+ modelId,
786
+ choices: [],
787
+ error: { message: 'Stream aborted by caller', type: 'abort' },
788
+ isFinal: true,
789
+ };
790
+ }
791
+ // -------------------------------------------------------------------------
792
+ // HTTP transport
793
+ // -------------------------------------------------------------------------
794
+ /**
795
+ * Makes a non-streaming API request to the Gemini API with retry logic.
796
+ *
797
+ * Authentication uses a `?key=` query parameter (Gemini's auth mechanism),
798
+ * NOT a header-based approach like OpenAI or Anthropic.
799
+ *
800
+ * @template T The expected response type.
801
+ * @param {string} endpoint - API endpoint path (e.g., "/models/gemini-2.5-flash:generateContent").
802
+ * @param {Record<string, unknown>} body - Request body.
803
+ * @returns {Promise<T>} Parsed JSON response.
804
+ * @throws {GeminiProviderError} On authentication, validation, rate-limit, or network errors.
805
+ * @private
806
+ */
807
+ async makeApiRequest(endpoint, body) {
808
+ // API key is passed as query parameter — Gemini's auth convention
809
+ const url = `${this.config.baseURL}${endpoint}?key=${this.config.apiKey}`;
810
+ const headers = {
811
+ 'Content-Type': 'application/json',
812
+ 'User-Agent': 'AgentOS/1.0 (GeminiProvider)',
813
+ };
814
+ let lastError = new GeminiProviderError('Request failed after all retries.', 'MAX_RETRIES_REACHED');
815
+ for (let attempt = 0; attempt < this.config.maxRetries; attempt++) {
816
+ const controller = new AbortController();
817
+ const timeoutId = setTimeout(() => controller.abort(), this.config.requestTimeout);
818
+ try {
819
+ const response = await fetch(url, {
820
+ method: 'POST',
821
+ headers,
822
+ body: JSON.stringify(body),
823
+ signal: controller.signal,
824
+ });
825
+ clearTimeout(timeoutId);
826
+ if (!response.ok) {
827
+ const errorData = await response.json().catch(() => ({}));
828
+ const errorMessage = errorData.error?.message || `HTTP ${response.status}: ${response.statusText}`;
829
+ const errorStatus = errorData.error?.status;
830
+ // Non-retryable client errors (auth, bad request, not found)
831
+ if (response.status === 400 || response.status === 401 || response.status === 403 || response.status === 404) {
832
+ throw new GeminiProviderError(errorMessage, 'API_CLIENT_ERROR', response.status, errorStatus, errorData);
833
+ }
834
+ // Rate limit — respect Retry-After header
835
+ if (response.status === 429) {
836
+ lastError = new GeminiProviderError(errorMessage, 'RATE_LIMIT_EXCEEDED', 429, errorStatus, errorData);
837
+ const retryAfter = response.headers.get('retry-after');
838
+ const retryAfterMs = retryAfter ? parseInt(retryAfter, 10) * 1000 : (2 ** attempt) * 1000;
839
+ await new Promise(resolve => setTimeout(resolve, retryAfterMs));
840
+ continue;
841
+ }
842
+ // Retryable server errors (5xx)
843
+ if (response.status >= 500) {
844
+ lastError = new GeminiProviderError(errorMessage, 'API_SERVER_ERROR', response.status, errorStatus, errorData);
845
+ await new Promise(resolve => setTimeout(resolve, (2 ** attempt) * 1000));
846
+ continue;
847
+ }
848
+ throw new GeminiProviderError(errorMessage, 'API_REQUEST_FAILED', response.status, errorStatus, errorData);
849
+ }
850
+ return (await response.json());
851
+ }
852
+ catch (error) {
853
+ clearTimeout(timeoutId);
854
+ if (error instanceof GeminiProviderError) {
855
+ if (error.code === 'API_CLIENT_ERROR')
856
+ throw error;
857
+ lastError = error;
858
+ }
859
+ else if (error instanceof Error && error.name === 'AbortError') {
860
+ lastError = new GeminiProviderError(`Request timed out after ${this.config.requestTimeout}ms.`, 'REQUEST_TIMEOUT');
861
+ }
862
+ else {
863
+ lastError = new GeminiProviderError(error instanceof Error ? error.message : 'Network or unknown error', 'NETWORK_ERROR');
864
+ }
865
+ if (attempt === this.config.maxRetries - 1)
866
+ break;
867
+ const delay = Math.min(30000, (1000 * (2 ** attempt)) + Math.random() * 1000);
868
+ console.warn(`[GeminiProvider] Retry ${attempt + 1}/${this.config.maxRetries - 1} in ${(delay / 1000).toFixed(1)}s`);
869
+ await new Promise(resolve => setTimeout(resolve, delay));
870
+ }
871
+ }
872
+ throw lastError;
873
+ }
874
+ /**
875
+ * Makes a streaming API request and returns the raw ReadableStream.
876
+ *
877
+ * Uses the `?alt=sse` query parameter to enable SSE streaming,
878
+ * combined with the `?key=` query parameter for authentication.
879
+ *
880
+ * @param {string} endpoint - API endpoint (e.g., "/models/gemini-2.5-flash:streamGenerateContent").
881
+ * @param {Record<string, unknown>} body - Request body.
882
+ * @returns {Promise<ReadableStream<Uint8Array>>} The response body stream.
883
+ * @throws {GeminiProviderError} On connection errors.
884
+ * @private
885
+ */
886
+ async makeStreamRequest(endpoint, body) {
887
+ // Both alt=sse and key= are query params
888
+ const url = `${this.config.baseURL}${endpoint}?alt=sse&key=${this.config.apiKey}`;
889
+ const headers = {
890
+ 'Content-Type': 'application/json',
891
+ 'User-Agent': 'AgentOS/1.0 (GeminiProvider)',
892
+ };
893
+ const controller = new AbortController();
894
+ const timeoutId = setTimeout(() => controller.abort(), this.config.requestTimeout);
895
+ try {
896
+ const response = await fetch(url, {
897
+ method: 'POST',
898
+ headers,
899
+ body: JSON.stringify(body),
900
+ signal: controller.signal,
901
+ });
902
+ clearTimeout(timeoutId);
903
+ if (!response.ok) {
904
+ const errorData = await response.json().catch(() => ({}));
905
+ const errorMessage = errorData.error?.message || `HTTP ${response.status}: ${response.statusText}`;
906
+ throw new GeminiProviderError(errorMessage, 'STREAM_CONNECTION_FAILED', response.status, errorData.error?.status, errorData);
907
+ }
908
+ if (!response.body) {
909
+ throw new GeminiProviderError('Expected a stream response but body was null.', 'STREAM_BODY_NULL');
910
+ }
911
+ return response.body;
912
+ }
913
+ catch (error) {
914
+ clearTimeout(timeoutId);
915
+ if (error instanceof GeminiProviderError)
916
+ throw error;
917
+ throw new GeminiProviderError(error instanceof Error ? error.message : 'Failed to connect to Gemini stream.', 'STREAM_CONNECTION_FAILED');
918
+ }
919
+ }
920
+ // -------------------------------------------------------------------------
921
+ // SSE parsing
922
+ // -------------------------------------------------------------------------
923
+ /**
924
+ * Parses an SSE (Server-Sent Events) stream from Gemini.
925
+ *
926
+ * Gemini SSE events follow the standard format:
927
+ * ```
928
+ * data: <json_payload>
929
+ *
930
+ * data: <json_payload>
931
+ * ```
932
+ *
933
+ * This parser extracts the `data:` line content for each event and yields
934
+ * the raw JSON strings for the caller to parse and dispatch.
935
+ *
936
+ * @param {ReadableStream<Uint8Array>} stream - The raw SSE byte stream.
937
+ * @returns {AsyncGenerator<string>} Yields JSON string payloads.
938
+ * @private
939
+ */
940
+ async *parseSseStream(stream) {
941
+ const reader = stream.getReader();
942
+ const decoder = new TextDecoder();
943
+ let buffer = '';
944
+ try {
945
+ while (true) {
946
+ const { done, value } = await reader.read();
947
+ if (done)
948
+ break;
949
+ buffer += decoder.decode(value, { stream: true });
950
+ // Process complete events (separated by double newlines)
951
+ const events = buffer.split('\n\n');
952
+ // Keep the last incomplete chunk in the buffer
953
+ buffer = events.pop() || '';
954
+ for (const event of events) {
955
+ const trimmed = event.trim();
956
+ if (!trimmed)
957
+ continue;
958
+ // Extract content after "data: " prefix
959
+ // Events may have multi-line data (though Gemini typically uses single-line)
960
+ const lines = trimmed.split('\n');
961
+ const dataLines = [];
962
+ for (const line of lines) {
963
+ if (line.startsWith('data: ')) {
964
+ dataLines.push(line.slice(6));
965
+ }
966
+ else if (line.startsWith('data:')) {
967
+ dataLines.push(line.slice(5));
968
+ }
969
+ }
970
+ if (dataLines.length > 0) {
971
+ const data = dataLines.join('\n').trim();
972
+ // Skip empty data or the [DONE] signal
973
+ if (data && data !== '[DONE]') {
974
+ yield data;
975
+ }
976
+ }
977
+ }
978
+ }
979
+ // Process any remaining buffer content
980
+ if (buffer.trim()) {
981
+ const lines = buffer.trim().split('\n');
982
+ const dataLines = [];
983
+ for (const line of lines) {
984
+ if (line.startsWith('data: ')) {
985
+ dataLines.push(line.slice(6));
986
+ }
987
+ else if (line.startsWith('data:')) {
988
+ dataLines.push(line.slice(5));
989
+ }
990
+ }
991
+ if (dataLines.length > 0) {
992
+ const data = dataLines.join('\n').trim();
993
+ if (data && data !== '[DONE]') {
994
+ yield data;
995
+ }
996
+ }
997
+ }
998
+ }
999
+ finally {
1000
+ reader.releaseLock();
1001
+ }
1002
+ }
1003
+ }
1004
+ //# sourceMappingURL=GeminiProvider.js.map