veryfront 0.1.149 → 0.1.151

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 (529) hide show
  1. package/esm/cli/commands/dev/command.js +3 -3
  2. package/esm/cli/commands/workflow/command-help.js +1 -1
  3. package/esm/cli/commands/workflow/command.js +2 -2
  4. package/esm/cli/shared/config.d.ts.map +1 -1
  5. package/esm/cli/shared/config.js +1 -3
  6. package/esm/deno.d.ts +5 -11
  7. package/esm/deno.js +16 -16
  8. package/esm/src/agent/ag-ui-handler.d.ts.map +1 -1
  9. package/esm/src/agent/ag-ui-handler.js +6 -0
  10. package/esm/src/agent/chat-handler.js +1 -1
  11. package/esm/src/agent/composition/composition.d.ts +1 -1
  12. package/esm/src/agent/composition/composition.d.ts.map +1 -1
  13. package/esm/src/agent/composition/composition.js +2 -2
  14. package/esm/src/agent/{ai-defaults.d.ts → defaults.d.ts} +1 -1
  15. package/esm/src/agent/defaults.d.ts.map +1 -0
  16. package/esm/src/agent/factory.js +1 -1
  17. package/esm/src/agent/react/index.d.ts +1 -1
  18. package/esm/src/agent/react/index.d.ts.map +1 -1
  19. package/esm/src/agent/react/use-chat/browser-inference/browser-engine.d.ts +5 -6
  20. package/esm/src/agent/react/use-chat/browser-inference/browser-engine.d.ts.map +1 -1
  21. package/esm/src/agent/react/use-chat/browser-inference/browser-engine.js +1 -1
  22. package/esm/src/agent/react/use-chat/index.d.ts +2 -1
  23. package/esm/src/agent/react/use-chat/index.d.ts.map +1 -1
  24. package/esm/src/agent/react/use-chat/stream-protocol.d.ts +2 -0
  25. package/esm/src/agent/react/use-chat/stream-protocol.d.ts.map +1 -0
  26. package/esm/src/agent/react/use-chat/stream-protocol.js +1 -0
  27. package/esm/src/agent/react/use-chat/streaming/parts-builder.d.ts +2 -2
  28. package/esm/src/agent/react/use-chat/streaming/parts-builder.d.ts.map +1 -1
  29. package/esm/src/agent/react/use-chat/streaming/types.d.ts +4 -4
  30. package/esm/src/agent/react/use-chat/streaming/types.d.ts.map +1 -1
  31. package/esm/src/agent/react/use-chat/types.d.ts +7 -55
  32. package/esm/src/agent/react/use-chat/types.d.ts.map +1 -1
  33. package/esm/src/agent/react/use-chat/use-chat.d.ts +4 -4
  34. package/esm/src/agent/react/use-chat/use-chat.d.ts.map +1 -1
  35. package/esm/src/agent/react/use-chat/use-chat.js +2 -2
  36. package/esm/src/agent/react/use-chat/utils.d.ts +2 -2
  37. package/esm/src/agent/react/use-chat/utils.d.ts.map +1 -1
  38. package/esm/src/agent/runtime/{ai-stream-handler.d.ts → chat-stream-handler.d.ts} +13 -13
  39. package/esm/src/agent/runtime/chat-stream-handler.d.ts.map +1 -0
  40. package/esm/src/agent/runtime/{ai-stream-handler.js → chat-stream-handler.js} +91 -89
  41. package/esm/src/agent/runtime/constants.js +1 -1
  42. package/esm/src/agent/runtime/index.d.ts +7 -5
  43. package/esm/src/agent/runtime/index.d.ts.map +1 -1
  44. package/esm/src/agent/runtime/index.js +67 -30
  45. package/esm/src/agent/runtime/model-message-converter.d.ts +7 -7
  46. package/esm/src/agent/runtime/model-message-converter.d.ts.map +1 -1
  47. package/esm/src/agent/runtime/model-message-converter.js +8 -6
  48. package/esm/src/agent/runtime/model-runtime-types.d.ts +44 -0
  49. package/esm/src/agent/runtime/model-runtime-types.d.ts.map +1 -0
  50. package/esm/src/agent/runtime/model-runtime-types.js +8 -0
  51. package/esm/src/agent/runtime/model-tool-converter.d.ts +9 -9
  52. package/esm/src/agent/runtime/model-tool-converter.d.ts.map +1 -1
  53. package/esm/src/agent/runtime/model-tool-converter.js +10 -22
  54. package/esm/src/agent/runtime/provider-native-tools.d.ts +3 -0
  55. package/esm/src/agent/runtime/provider-native-tools.d.ts.map +1 -0
  56. package/esm/src/agent/runtime/provider-native-tools.js +56 -0
  57. package/esm/src/agent/runtime/repair-tool-call.d.ts +2 -2
  58. package/esm/src/agent/runtime/repair-tool-call.d.ts.map +1 -1
  59. package/esm/src/agent/runtime/repair-tool-call.js +3 -3
  60. package/esm/src/agent/runtime/runtime-tool-builder.d.ts +48 -0
  61. package/esm/src/agent/runtime/runtime-tool-builder.d.ts.map +1 -0
  62. package/esm/src/agent/runtime/runtime-tool-builder.js +28 -0
  63. package/esm/src/agent/runtime/runtime-tool-errors.d.ts +16 -0
  64. package/esm/src/agent/runtime/runtime-tool-errors.d.ts.map +1 -0
  65. package/esm/src/agent/runtime/runtime-tool-errors.js +28 -0
  66. package/esm/src/agent/runtime/runtime-tool-types.d.ts +104 -0
  67. package/esm/src/agent/runtime/runtime-tool-types.d.ts.map +1 -0
  68. package/esm/src/agent/runtime/runtime-tool-types.js +7 -0
  69. package/esm/src/chat/index.d.ts +9 -9
  70. package/esm/src/chat/index.d.ts.map +1 -1
  71. package/esm/src/chat/index.js +7 -7
  72. package/esm/src/chat/protocol.d.ts +156 -0
  73. package/esm/src/chat/protocol.d.ts.map +1 -0
  74. package/esm/src/chat/protocol.js +7 -0
  75. package/esm/src/discovery/import-rewriter.d.ts.map +1 -1
  76. package/esm/src/discovery/import-rewriter.js +1 -14
  77. package/esm/src/discovery/index.d.ts +1 -1
  78. package/esm/src/discovery/index.d.ts.map +1 -1
  79. package/esm/src/discovery/index.js +2 -2
  80. package/esm/src/discovery/provider-config-validator.d.ts +14 -0
  81. package/esm/src/discovery/provider-config-validator.d.ts.map +1 -0
  82. package/esm/src/discovery/{config-validator.js → provider-config-validator.js} +4 -4
  83. package/esm/src/discovery/transpiler.d.ts.map +1 -1
  84. package/esm/src/discovery/transpiler.js +0 -3
  85. package/esm/src/embedding/embedding.d.ts.map +1 -1
  86. package/esm/src/embedding/embedding.js +1 -1
  87. package/esm/src/embedding/index.d.ts +3 -3
  88. package/esm/src/embedding/index.d.ts.map +1 -1
  89. package/esm/src/embedding/index.js +3 -3
  90. package/esm/src/embedding/rag-store.d.ts.map +1 -1
  91. package/esm/src/embedding/rag-store.js +1 -1
  92. package/esm/src/embedding/resolve.d.ts +5 -7
  93. package/esm/src/embedding/resolve.d.ts.map +1 -1
  94. package/esm/src/embedding/resolve.js +6 -9
  95. package/esm/src/embedding/vector-store.d.ts.map +1 -1
  96. package/esm/src/embedding/vector-store.js +1 -1
  97. package/esm/src/embedding/veryfront-cloud/provider.d.ts +2 -2
  98. package/esm/src/embedding/veryfront-cloud/provider.d.ts.map +1 -1
  99. package/esm/src/embedding/veryfront-cloud/provider.js +5 -6
  100. package/esm/src/internal-agents/ag-ui-sse.d.ts.map +1 -1
  101. package/esm/src/internal-agents/ag-ui-sse.js +12 -0
  102. package/esm/src/markdown/index.d.ts +1 -1
  103. package/esm/src/markdown/index.d.ts.map +1 -1
  104. package/esm/src/markdown/index.js +1 -1
  105. package/esm/src/modules/import-map/default-import-map.js +2 -2
  106. package/esm/src/prompt/registry.d.ts +1 -1
  107. package/esm/src/prompt/registry.d.ts.map +1 -1
  108. package/esm/src/prompt/registry.js +2 -2
  109. package/esm/src/provider/index.d.ts +7 -8
  110. package/esm/src/provider/index.d.ts.map +1 -1
  111. package/esm/src/provider/index.js +6 -8
  112. package/esm/src/provider/local/embedding-runtime-adapter.d.ts +19 -0
  113. package/esm/src/provider/local/embedding-runtime-adapter.d.ts.map +1 -0
  114. package/esm/src/provider/local/{local-embedding-adapter.js → embedding-runtime-adapter.js} +5 -5
  115. package/esm/src/provider/local/model-runtime-adapter.d.ts +18 -0
  116. package/esm/src/provider/local/model-runtime-adapter.d.ts.map +1 -0
  117. package/esm/src/provider/local/{ai-sdk-adapter.js → model-runtime-adapter.js} +10 -12
  118. package/esm/src/provider/model-registry.d.ts +11 -12
  119. package/esm/src/provider/model-registry.d.ts.map +1 -1
  120. package/esm/src/provider/model-registry.js +17 -20
  121. package/esm/src/provider/runtime-inspection.d.ts +6 -0
  122. package/esm/src/provider/runtime-inspection.d.ts.map +1 -0
  123. package/esm/src/provider/runtime-inspection.js +19 -0
  124. package/esm/src/provider/runtime-loader.d.ts +27 -0
  125. package/esm/src/provider/runtime-loader.d.ts.map +1 -0
  126. package/esm/src/provider/runtime-loader.js +1307 -0
  127. package/esm/src/provider/types.d.ts +35 -0
  128. package/esm/src/provider/types.d.ts.map +1 -0
  129. package/esm/src/provider/types.js +1 -0
  130. package/esm/src/provider/veryfront-cloud/provider.d.ts +2 -2
  131. package/esm/src/provider/veryfront-cloud/provider.d.ts.map +1 -1
  132. package/esm/src/provider/veryfront-cloud/provider.js +7 -9
  133. package/esm/src/provider/veryfront-cloud/shared.d.ts +1 -1
  134. package/esm/src/provider/veryfront-cloud/shared.js +1 -1
  135. package/esm/src/react/components/chat/agent-card.d.ts.map +1 -0
  136. package/esm/src/react/components/chat/chat/components/animations.d.ts.map +1 -0
  137. package/esm/src/react/components/chat/chat/components/attachment-pill.d.ts.map +1 -0
  138. package/esm/src/react/components/chat/chat/components/branch-picker.d.ts.map +1 -0
  139. package/esm/src/react/components/chat/chat/components/code-block.d.ts.map +1 -0
  140. package/esm/src/react/components/chat/chat/components/drop-zone.d.ts.map +1 -0
  141. package/esm/src/react/components/chat/chat/components/empty-state.d.ts.map +1 -0
  142. package/esm/src/react/components/chat/chat/components/inference-badge.d.ts.map +1 -0
  143. package/esm/src/react/components/{ai → chat}/chat/components/inference-badge.js +1 -1
  144. package/esm/src/react/components/chat/chat/components/inline-citation.d.ts.map +1 -0
  145. package/esm/src/react/components/chat/chat/components/message-actions.d.ts.map +1 -0
  146. package/esm/src/react/components/chat/chat/components/message-edit-form.d.ts.map +1 -0
  147. package/esm/src/react/components/chat/chat/components/message-feedback.d.ts.map +1 -0
  148. package/esm/src/react/components/chat/chat/components/quick-actions.d.ts.map +1 -0
  149. package/esm/src/react/components/chat/chat/components/reasoning.d.ts.map +1 -0
  150. package/esm/src/react/components/chat/chat/components/sidebar.d.ts.map +1 -0
  151. package/esm/src/react/components/{ai → chat}/chat/components/skill-badge.d.ts +3 -3
  152. package/esm/src/react/components/chat/chat/components/skill-badge.d.ts.map +1 -0
  153. package/esm/src/react/components/{ai → chat}/chat/components/skill-badge.js +1 -1
  154. package/esm/src/react/components/chat/chat/components/sources.d.ts.map +1 -0
  155. package/esm/src/react/components/chat/chat/components/step-indicator.d.ts.map +1 -0
  156. package/esm/src/react/components/chat/chat/components/tab-switcher.d.ts.map +1 -0
  157. package/esm/src/react/components/{ai → chat}/chat/components/tool-ui.d.ts +3 -3
  158. package/esm/src/react/components/chat/chat/components/tool-ui.d.ts.map +1 -0
  159. package/esm/src/react/components/{ai → chat}/chat/components/tool-ui.js +1 -1
  160. package/esm/src/react/components/chat/chat/components/upgrade-cta.d.ts.map +1 -0
  161. package/esm/src/react/components/chat/chat/components/uploads-panel.d.ts.map +1 -0
  162. package/esm/src/react/components/{ai → chat}/chat/composition/api.d.ts +1 -1
  163. package/esm/src/react/components/chat/chat/composition/api.d.ts.map +1 -0
  164. package/esm/src/react/components/{ai → chat}/chat/composition/api.js +1 -1
  165. package/esm/src/react/components/{ai → chat}/chat/composition/chat-composer.d.ts +3 -3
  166. package/esm/src/react/components/chat/chat/composition/chat-composer.d.ts.map +1 -0
  167. package/esm/src/react/components/{ai → chat}/chat/composition/chat-composer.js +1 -1
  168. package/esm/src/react/components/{ai → chat}/chat/composition/chat-empty.d.ts +1 -1
  169. package/esm/src/react/components/chat/chat/composition/chat-empty.d.ts.map +1 -0
  170. package/esm/src/react/components/{ai → chat}/chat/composition/chat-empty.js +1 -1
  171. package/esm/src/react/components/{ai → chat}/chat/composition/chat-if.d.ts +1 -1
  172. package/esm/src/react/components/chat/chat/composition/chat-if.d.ts.map +1 -0
  173. package/esm/src/react/components/{ai → chat}/chat/composition/chat-if.js +1 -1
  174. package/esm/src/react/components/{ai → chat}/chat/composition/chat-message-list.d.ts +5 -5
  175. package/esm/src/react/components/chat/chat/composition/chat-message-list.d.ts.map +1 -0
  176. package/esm/src/react/components/{ai → chat}/chat/composition/chat-message-list.js +2 -2
  177. package/esm/src/react/components/{ai → chat}/chat/composition/chat-root.d.ts +3 -3
  178. package/esm/src/react/components/chat/chat/composition/chat-root.d.ts.map +1 -0
  179. package/esm/src/react/components/{ai → chat}/chat/composition/chat-root.js +1 -1
  180. package/esm/src/react/components/{ai → chat}/chat/composition/error-banner.d.ts +1 -1
  181. package/esm/src/react/components/chat/chat/composition/error-banner.d.ts.map +1 -0
  182. package/esm/src/react/components/{ai → chat}/chat/composition/error-banner.js +1 -1
  183. package/esm/src/react/components/{ai → chat}/chat/composition/message.d.ts +4 -4
  184. package/esm/src/react/components/chat/chat/composition/message.d.ts.map +1 -0
  185. package/esm/src/react/components/{ai → chat}/chat/composition/message.js +1 -1
  186. package/esm/src/react/components/{ai → chat}/chat/composition/model-avatar.d.ts +1 -1
  187. package/esm/src/react/components/chat/chat/composition/model-avatar.d.ts.map +1 -0
  188. package/esm/src/react/components/{ai → chat}/chat/composition/model-avatar.js +1 -1
  189. package/esm/src/react/components/{ai → chat}/chat/contexts/chat-context.d.ts +3 -3
  190. package/esm/src/react/components/chat/chat/contexts/chat-context.d.ts.map +1 -0
  191. package/esm/src/react/components/{ai → chat}/chat/contexts/chat-context.js +1 -1
  192. package/esm/src/react/components/{ai → chat}/chat/contexts/composer-context.d.ts +1 -1
  193. package/esm/src/react/components/chat/chat/contexts/composer-context.d.ts.map +1 -0
  194. package/esm/src/react/components/{ai → chat}/chat/contexts/composer-context.js +1 -1
  195. package/esm/src/react/components/{ai → chat}/chat/contexts/index.d.ts +1 -1
  196. package/esm/src/react/components/chat/chat/contexts/index.d.ts.map +1 -0
  197. package/esm/src/react/components/{ai → chat}/chat/contexts/index.js +1 -1
  198. package/esm/src/react/components/{ai → chat}/chat/contexts/message-context.d.ts +3 -3
  199. package/esm/src/react/components/chat/chat/contexts/message-context.d.ts.map +1 -0
  200. package/esm/src/react/components/{ai → chat}/chat/contexts/message-context.js +1 -1
  201. package/esm/src/react/components/{ai → chat}/chat/contexts/thread-list-context.d.ts +1 -1
  202. package/esm/src/react/components/chat/chat/contexts/thread-list-context.d.ts.map +1 -0
  203. package/esm/src/react/components/{ai → chat}/chat/contexts/thread-list-context.js +1 -1
  204. package/esm/src/react/components/{ai → chat}/chat/hooks/use-threads.d.ts +2 -2
  205. package/esm/src/react/components/chat/chat/hooks/use-threads.d.ts.map +1 -0
  206. package/esm/src/react/components/{ai → chat}/chat/index.d.ts +5 -5
  207. package/esm/src/react/components/chat/chat/index.d.ts.map +1 -0
  208. package/esm/src/react/components/{ai → chat}/chat/index.js +1 -1
  209. package/esm/src/react/components/chat/chat/utils/export.d.ts +10 -0
  210. package/esm/src/react/components/chat/chat/utils/export.d.ts.map +1 -0
  211. package/esm/src/react/components/{ai → chat}/chat/utils/export.js +1 -1
  212. package/esm/src/react/components/{ai → chat}/chat/utils/message-parts.d.ts +10 -10
  213. package/esm/src/react/components/chat/chat/utils/message-parts.d.ts.map +1 -0
  214. package/esm/src/react/components/{ai → chat}/chat/utils/message-parts.js +2 -2
  215. package/esm/src/react/components/chat/chat-with-sidebar.d.ts.map +1 -0
  216. package/esm/src/react/components/{ai → chat}/chat.d.ts +1 -1
  217. package/esm/src/react/components/chat/chat.d.ts.map +1 -0
  218. package/esm/src/react/components/{ai → chat}/chat.js +1 -1
  219. package/esm/src/react/components/chat/csp-nonce.d.ts.map +1 -0
  220. package/esm/src/react/components/{ai → chat}/error-boundary.d.ts +6 -6
  221. package/esm/src/react/components/chat/error-boundary.d.ts.map +1 -0
  222. package/esm/src/react/components/{ai → chat}/error-boundary.js +5 -5
  223. package/esm/src/react/components/{ai → chat}/icons/index.d.ts +1 -1
  224. package/esm/src/react/components/chat/icons/index.d.ts.map +1 -0
  225. package/esm/src/react/components/{ai → chat}/icons/index.js +1 -1
  226. package/esm/src/react/components/chat/markdown.d.ts.map +1 -0
  227. package/esm/src/react/components/{ai → chat}/message.d.ts +8 -8
  228. package/esm/src/react/components/chat/message.d.ts.map +1 -0
  229. package/esm/src/react/components/chat/model-selector.d.ts.map +1 -0
  230. package/esm/src/react/components/chat/theme.d.ts.map +1 -0
  231. package/esm/src/react/primitives/message-list.d.ts +2 -2
  232. package/esm/src/react/primitives/message-list.d.ts.map +1 -1
  233. package/esm/src/react/primitives/tool-primitives.d.ts +3 -3
  234. package/esm/src/react/primitives/tool-primitives.d.ts.map +1 -1
  235. package/esm/src/{ai/registry-manager.d.ts → registry/project-scoped-registry-manager.d.ts} +5 -4
  236. package/esm/src/registry/project-scoped-registry-manager.d.ts.map +1 -0
  237. package/esm/src/{ai/registry-manager.js → registry/project-scoped-registry-manager.js} +5 -4
  238. package/esm/src/{ai/registry-facade.d.ts → registry/scoped-registry-facade.d.ts} +2 -2
  239. package/esm/src/registry/scoped-registry-facade.d.ts.map +1 -0
  240. package/esm/src/rendering/script-page-handling.d.ts.map +1 -1
  241. package/esm/src/rendering/script-page-handling.js +0 -2
  242. package/esm/src/resource/registry.d.ts +1 -1
  243. package/esm/src/resource/registry.d.ts.map +1 -1
  244. package/esm/src/resource/registry.js +2 -2
  245. package/esm/src/routing/api/module-loader/loader.js +3 -19
  246. package/esm/src/runtime/runtime-bridge.d.ts +82 -0
  247. package/esm/src/runtime/runtime-bridge.d.ts.map +1 -0
  248. package/esm/src/runtime/runtime-bridge.js +367 -0
  249. package/esm/src/server/dev-server/file-watch-setup.d.ts +4 -4
  250. package/esm/src/server/dev-server/file-watch-setup.d.ts.map +1 -1
  251. package/esm/src/server/dev-server/file-watch-setup.js +14 -14
  252. package/esm/src/server/dev-server/server.d.ts +2 -2
  253. package/esm/src/server/dev-server/server.d.ts.map +1 -1
  254. package/esm/src/server/dev-server/server.js +20 -18
  255. package/esm/src/server/dev-ui/manifest.d.ts +1 -1
  256. package/esm/src/server/dev-ui/manifest.js +2 -2
  257. package/esm/src/server/handlers/dev/framework-candidates.generated.d.ts.map +1 -1
  258. package/esm/src/server/handlers/dev/framework-candidates.generated.js +58 -61
  259. package/esm/src/server/handlers/request/api/api-handler-wrapper.js +1 -1
  260. package/esm/src/server/handlers/request/api/project-discovery.d.ts +1 -1
  261. package/esm/src/server/handlers/request/api/project-discovery.d.ts.map +1 -1
  262. package/esm/src/server/handlers/request/api/project-discovery.js +12 -10
  263. package/esm/src/server/production-server.js +2 -2
  264. package/esm/src/server/services/rsc/endpoints/rsc-bundles.generated.d.ts.map +1 -1
  265. package/esm/src/server/services/rsc/endpoints/rsc-bundles.generated.js +2 -2
  266. package/esm/src/skill/registry.d.ts +1 -1
  267. package/esm/src/skill/registry.d.ts.map +1 -1
  268. package/esm/src/skill/registry.js +2 -2
  269. package/esm/src/tool/registry.d.ts +1 -1
  270. package/esm/src/tool/registry.d.ts.map +1 -1
  271. package/esm/src/tool/registry.js +2 -2
  272. package/esm/src/transforms/npm-import-rewrites.d.ts +1 -1
  273. package/esm/src/transforms/npm-import-rewrites.d.ts.map +1 -1
  274. package/esm/src/transforms/npm-import-rewrites.js +5 -13
  275. package/esm/src/utils/constants/server.d.ts +4 -4
  276. package/esm/src/utils/constants/server.d.ts.map +1 -1
  277. package/esm/src/utils/constants/server.js +4 -4
  278. package/esm/src/utils/id.js +1 -1
  279. package/esm/src/utils/version-constant.d.ts +1 -1
  280. package/esm/src/utils/version-constant.js +1 -1
  281. package/esm/src/workflow/discovery/workflow-discovery.d.ts +3 -3
  282. package/esm/src/workflow/discovery/workflow-discovery.d.ts.map +1 -1
  283. package/esm/src/workflow/discovery/workflow-discovery.js +3 -3
  284. package/esm/src/workflow/registry.d.ts +1 -1
  285. package/esm/src/workflow/registry.d.ts.map +1 -1
  286. package/esm/src/workflow/registry.js +2 -2
  287. package/package.json +4 -5
  288. package/src/cli/commands/dev/command.ts +3 -3
  289. package/src/cli/commands/workflow/command-help.ts +1 -1
  290. package/src/cli/commands/workflow/command.ts +2 -2
  291. package/src/cli/shared/config.ts +1 -3
  292. package/src/deno.js +16 -16
  293. package/src/src/agent/ag-ui-handler.ts +6 -0
  294. package/src/src/agent/chat-handler.ts +1 -1
  295. package/src/src/agent/composition/composition.ts +2 -2
  296. package/src/src/agent/factory.ts +1 -1
  297. package/src/src/agent/react/index.ts +11 -9
  298. package/src/src/agent/react/use-chat/browser-inference/browser-engine.ts +9 -10
  299. package/src/src/agent/react/use-chat/index.ts +10 -9
  300. package/src/src/agent/react/use-chat/stream-protocol.ts +1 -0
  301. package/src/src/agent/react/use-chat/streaming/handler.ts +17 -17
  302. package/src/src/agent/react/use-chat/streaming/parts-builder.ts +5 -5
  303. package/src/src/agent/react/use-chat/streaming/types.ts +4 -4
  304. package/src/src/agent/react/use-chat/types.ts +27 -73
  305. package/src/src/agent/react/use-chat/use-chat.ts +13 -13
  306. package/src/src/agent/react/use-chat/utils.ts +2 -2
  307. package/src/src/agent/runtime/{ai-stream-handler.ts → chat-stream-handler.ts} +100 -96
  308. package/src/src/agent/runtime/constants.ts +1 -1
  309. package/src/src/agent/runtime/index.ts +88 -40
  310. package/src/src/agent/runtime/model-message-converter.ts +22 -33
  311. package/src/src/agent/runtime/model-runtime-types.ts +55 -0
  312. package/src/src/agent/runtime/model-tool-converter.ts +29 -26
  313. package/src/src/agent/runtime/provider-native-tools.ts +61 -0
  314. package/src/src/agent/runtime/repair-tool-call.ts +6 -9
  315. package/src/src/agent/runtime/runtime-tool-builder.ts +82 -0
  316. package/src/src/agent/runtime/runtime-tool-errors.ts +46 -0
  317. package/src/src/agent/runtime/runtime-tool-types.ts +114 -0
  318. package/src/src/chat/index.ts +22 -20
  319. package/src/src/chat/protocol.ts +210 -0
  320. package/src/src/discovery/import-rewriter.ts +1 -14
  321. package/src/src/discovery/index.ts +2 -2
  322. package/src/src/discovery/{config-validator.ts → provider-config-validator.ts} +4 -4
  323. package/src/src/discovery/transpiler.ts +0 -3
  324. package/src/src/embedding/embedding.ts +1 -1
  325. package/src/src/embedding/index.ts +3 -3
  326. package/src/src/embedding/rag-store.ts +1 -1
  327. package/src/src/embedding/resolve.ts +15 -12
  328. package/src/src/embedding/vector-store.ts +1 -1
  329. package/src/src/embedding/veryfront-cloud/provider.ts +10 -8
  330. package/src/src/internal-agents/ag-ui-sse.ts +12 -0
  331. package/src/src/markdown/index.ts +1 -1
  332. package/src/src/modules/import-map/default-import-map.ts +2 -2
  333. package/src/src/prompt/registry.ts +2 -2
  334. package/src/src/provider/index.ts +7 -8
  335. package/src/src/provider/local/{local-embedding-adapter.ts → embedding-runtime-adapter.ts} +8 -8
  336. package/src/src/provider/local/{ai-sdk-adapter.ts → model-runtime-adapter.ts} +13 -16
  337. package/src/src/provider/model-registry.ts +31 -26
  338. package/src/src/provider/runtime-inspection.ts +25 -0
  339. package/src/src/provider/runtime-loader.ts +1854 -0
  340. package/src/src/provider/types.ts +38 -0
  341. package/src/src/provider/veryfront-cloud/provider.ts +13 -11
  342. package/src/src/provider/veryfront-cloud/shared.ts +1 -1
  343. package/src/src/react/components/{ai → chat}/chat/components/inference-badge.tsx +1 -1
  344. package/src/src/react/components/{ai → chat}/chat/components/skill-badge.tsx +3 -3
  345. package/src/src/react/components/{ai → chat}/chat/components/tool-ui.tsx +3 -3
  346. package/src/src/react/components/{ai → chat}/chat/composition/api.tsx +1 -1
  347. package/src/src/react/components/{ai → chat}/chat/composition/chat-composer.tsx +3 -3
  348. package/src/src/react/components/{ai → chat}/chat/composition/chat-empty.tsx +1 -1
  349. package/src/src/react/components/{ai → chat}/chat/composition/chat-if.tsx +1 -1
  350. package/src/src/react/components/{ai → chat}/chat/composition/chat-message-list.tsx +11 -11
  351. package/src/src/react/components/{ai → chat}/chat/composition/chat-root.tsx +3 -3
  352. package/src/src/react/components/{ai → chat}/chat/composition/error-banner.tsx +1 -1
  353. package/src/src/react/components/{ai → chat}/chat/composition/message.tsx +9 -4
  354. package/src/src/react/components/{ai → chat}/chat/composition/model-avatar.tsx +1 -1
  355. package/src/src/react/components/{ai → chat}/chat/contexts/chat-context.tsx +3 -3
  356. package/src/src/react/components/{ai → chat}/chat/contexts/composer-context.tsx +1 -1
  357. package/src/src/react/components/{ai → chat}/chat/contexts/index.ts +1 -1
  358. package/src/src/react/components/{ai → chat}/chat/contexts/message-context.tsx +3 -3
  359. package/src/src/react/components/{ai → chat}/chat/contexts/thread-list-context.tsx +1 -1
  360. package/src/src/react/components/{ai → chat}/chat/hooks/use-threads.ts +2 -2
  361. package/src/src/react/components/{ai → chat}/chat/index.tsx +7 -7
  362. package/src/src/react/components/{ai → chat}/chat/utils/export.ts +4 -4
  363. package/src/src/react/components/{ai → chat}/chat/utils/message-parts.ts +13 -13
  364. package/src/src/react/components/{ai → chat}/chat.tsx +1 -1
  365. package/src/src/react/components/{ai → chat}/error-boundary.tsx +11 -11
  366. package/src/src/react/components/{ai → chat}/icons/index.ts +1 -1
  367. package/src/src/react/components/{ai → chat}/message.tsx +11 -11
  368. package/src/src/react/primitives/message-list.tsx +2 -2
  369. package/src/src/react/primitives/tool-primitives.tsx +4 -4
  370. package/src/src/{ai/registry-manager.ts → registry/project-scoped-registry-manager.ts} +5 -4
  371. package/src/src/{ai/registry-facade.ts → registry/scoped-registry-facade.ts} +1 -1
  372. package/src/src/rendering/script-page-handling.ts +0 -2
  373. package/src/src/resource/registry.ts +2 -2
  374. package/src/src/routing/api/module-loader/loader.ts +3 -19
  375. package/src/src/runtime/runtime-bridge.ts +608 -0
  376. package/src/src/server/dev-server/file-watch-setup.ts +14 -14
  377. package/src/src/server/dev-server/server.ts +20 -18
  378. package/src/src/server/dev-ui/manifest.js +2 -2
  379. package/src/src/server/handlers/dev/framework-candidates.generated.ts +58 -61
  380. package/src/src/server/handlers/request/api/api-handler-wrapper.ts +1 -1
  381. package/src/src/server/handlers/request/api/project-discovery.ts +12 -10
  382. package/src/src/server/production-server.ts +2 -2
  383. package/src/src/server/services/rsc/endpoints/rsc-bundles.generated.ts +2 -2
  384. package/src/src/skill/registry.ts +2 -2
  385. package/src/src/tool/registry.ts +2 -2
  386. package/src/src/transforms/npm-import-rewrites.ts +5 -13
  387. package/src/src/utils/constants/server.ts +4 -4
  388. package/src/src/utils/id.ts +1 -1
  389. package/src/src/utils/version-constant.ts +1 -1
  390. package/src/src/workflow/discovery/workflow-discovery.ts +4 -4
  391. package/src/src/workflow/registry.ts +2 -2
  392. package/esm/src/agent/ai-defaults.d.ts.map +0 -1
  393. package/esm/src/agent/runtime/ai-stream-handler.d.ts.map +0 -1
  394. package/esm/src/ai/registry-facade.d.ts.map +0 -1
  395. package/esm/src/ai/registry-manager.d.ts.map +0 -1
  396. package/esm/src/discovery/config-validator.d.ts +0 -14
  397. package/esm/src/discovery/config-validator.d.ts.map +0 -1
  398. package/esm/src/provider/local/ai-sdk-adapter.d.ts +0 -19
  399. package/esm/src/provider/local/ai-sdk-adapter.d.ts.map +0 -1
  400. package/esm/src/provider/local/local-embedding-adapter.d.ts +0 -19
  401. package/esm/src/provider/local/local-embedding-adapter.d.ts.map +0 -1
  402. package/esm/src/react/components/ai/agent-card.d.ts.map +0 -1
  403. package/esm/src/react/components/ai/chat/components/animations.d.ts.map +0 -1
  404. package/esm/src/react/components/ai/chat/components/attachment-pill.d.ts.map +0 -1
  405. package/esm/src/react/components/ai/chat/components/branch-picker.d.ts.map +0 -1
  406. package/esm/src/react/components/ai/chat/components/code-block.d.ts.map +0 -1
  407. package/esm/src/react/components/ai/chat/components/drop-zone.d.ts.map +0 -1
  408. package/esm/src/react/components/ai/chat/components/empty-state.d.ts.map +0 -1
  409. package/esm/src/react/components/ai/chat/components/inference-badge.d.ts.map +0 -1
  410. package/esm/src/react/components/ai/chat/components/inline-citation.d.ts.map +0 -1
  411. package/esm/src/react/components/ai/chat/components/message-actions.d.ts.map +0 -1
  412. package/esm/src/react/components/ai/chat/components/message-edit-form.d.ts.map +0 -1
  413. package/esm/src/react/components/ai/chat/components/message-feedback.d.ts.map +0 -1
  414. package/esm/src/react/components/ai/chat/components/quick-actions.d.ts.map +0 -1
  415. package/esm/src/react/components/ai/chat/components/reasoning.d.ts.map +0 -1
  416. package/esm/src/react/components/ai/chat/components/sidebar.d.ts.map +0 -1
  417. package/esm/src/react/components/ai/chat/components/skill-badge.d.ts.map +0 -1
  418. package/esm/src/react/components/ai/chat/components/sources.d.ts.map +0 -1
  419. package/esm/src/react/components/ai/chat/components/step-indicator.d.ts.map +0 -1
  420. package/esm/src/react/components/ai/chat/components/tab-switcher.d.ts.map +0 -1
  421. package/esm/src/react/components/ai/chat/components/tool-ui.d.ts.map +0 -1
  422. package/esm/src/react/components/ai/chat/components/upgrade-cta.d.ts.map +0 -1
  423. package/esm/src/react/components/ai/chat/components/uploads-panel.d.ts.map +0 -1
  424. package/esm/src/react/components/ai/chat/composition/api.d.ts.map +0 -1
  425. package/esm/src/react/components/ai/chat/composition/chat-composer.d.ts.map +0 -1
  426. package/esm/src/react/components/ai/chat/composition/chat-empty.d.ts.map +0 -1
  427. package/esm/src/react/components/ai/chat/composition/chat-if.d.ts.map +0 -1
  428. package/esm/src/react/components/ai/chat/composition/chat-message-list.d.ts.map +0 -1
  429. package/esm/src/react/components/ai/chat/composition/chat-root.d.ts.map +0 -1
  430. package/esm/src/react/components/ai/chat/composition/error-banner.d.ts.map +0 -1
  431. package/esm/src/react/components/ai/chat/composition/message.d.ts.map +0 -1
  432. package/esm/src/react/components/ai/chat/composition/model-avatar.d.ts.map +0 -1
  433. package/esm/src/react/components/ai/chat/contexts/chat-context.d.ts.map +0 -1
  434. package/esm/src/react/components/ai/chat/contexts/composer-context.d.ts.map +0 -1
  435. package/esm/src/react/components/ai/chat/contexts/index.d.ts.map +0 -1
  436. package/esm/src/react/components/ai/chat/contexts/message-context.d.ts.map +0 -1
  437. package/esm/src/react/components/ai/chat/contexts/thread-list-context.d.ts.map +0 -1
  438. package/esm/src/react/components/ai/chat/hooks/use-threads.d.ts.map +0 -1
  439. package/esm/src/react/components/ai/chat/index.d.ts.map +0 -1
  440. package/esm/src/react/components/ai/chat/utils/export.d.ts +0 -10
  441. package/esm/src/react/components/ai/chat/utils/export.d.ts.map +0 -1
  442. package/esm/src/react/components/ai/chat/utils/message-parts.d.ts.map +0 -1
  443. package/esm/src/react/components/ai/chat-with-sidebar.d.ts.map +0 -1
  444. package/esm/src/react/components/ai/chat.d.ts.map +0 -1
  445. package/esm/src/react/components/ai/csp-nonce.d.ts.map +0 -1
  446. package/esm/src/react/components/ai/error-boundary.d.ts.map +0 -1
  447. package/esm/src/react/components/ai/icons/index.d.ts.map +0 -1
  448. package/esm/src/react/components/ai/markdown.d.ts.map +0 -1
  449. package/esm/src/react/components/ai/message.d.ts.map +0 -1
  450. package/esm/src/react/components/ai/model-selector.d.ts.map +0 -1
  451. package/esm/src/react/components/ai/theme.d.ts.map +0 -1
  452. /package/esm/src/agent/{ai-defaults.js → defaults.js} +0 -0
  453. /package/esm/src/react/components/{ai → chat}/agent-card.d.ts +0 -0
  454. /package/esm/src/react/components/{ai → chat}/agent-card.js +0 -0
  455. /package/esm/src/react/components/{ai → chat}/chat/components/animations.d.ts +0 -0
  456. /package/esm/src/react/components/{ai → chat}/chat/components/animations.js +0 -0
  457. /package/esm/src/react/components/{ai → chat}/chat/components/attachment-pill.d.ts +0 -0
  458. /package/esm/src/react/components/{ai → chat}/chat/components/attachment-pill.js +0 -0
  459. /package/esm/src/react/components/{ai → chat}/chat/components/branch-picker.d.ts +0 -0
  460. /package/esm/src/react/components/{ai → chat}/chat/components/branch-picker.js +0 -0
  461. /package/esm/src/react/components/{ai → chat}/chat/components/code-block.d.ts +0 -0
  462. /package/esm/src/react/components/{ai → chat}/chat/components/code-block.js +0 -0
  463. /package/esm/src/react/components/{ai → chat}/chat/components/drop-zone.d.ts +0 -0
  464. /package/esm/src/react/components/{ai → chat}/chat/components/drop-zone.js +0 -0
  465. /package/esm/src/react/components/{ai → chat}/chat/components/empty-state.d.ts +0 -0
  466. /package/esm/src/react/components/{ai → chat}/chat/components/empty-state.js +0 -0
  467. /package/esm/src/react/components/{ai → chat}/chat/components/inference-badge.d.ts +0 -0
  468. /package/esm/src/react/components/{ai → chat}/chat/components/inline-citation.d.ts +0 -0
  469. /package/esm/src/react/components/{ai → chat}/chat/components/inline-citation.js +0 -0
  470. /package/esm/src/react/components/{ai → chat}/chat/components/message-actions.d.ts +0 -0
  471. /package/esm/src/react/components/{ai → chat}/chat/components/message-actions.js +0 -0
  472. /package/esm/src/react/components/{ai → chat}/chat/components/message-edit-form.d.ts +0 -0
  473. /package/esm/src/react/components/{ai → chat}/chat/components/message-edit-form.js +0 -0
  474. /package/esm/src/react/components/{ai → chat}/chat/components/message-feedback.d.ts +0 -0
  475. /package/esm/src/react/components/{ai → chat}/chat/components/message-feedback.js +0 -0
  476. /package/esm/src/react/components/{ai → chat}/chat/components/quick-actions.d.ts +0 -0
  477. /package/esm/src/react/components/{ai → chat}/chat/components/quick-actions.js +0 -0
  478. /package/esm/src/react/components/{ai → chat}/chat/components/reasoning.d.ts +0 -0
  479. /package/esm/src/react/components/{ai → chat}/chat/components/reasoning.js +0 -0
  480. /package/esm/src/react/components/{ai → chat}/chat/components/sidebar.d.ts +0 -0
  481. /package/esm/src/react/components/{ai → chat}/chat/components/sidebar.js +0 -0
  482. /package/esm/src/react/components/{ai → chat}/chat/components/sources.d.ts +0 -0
  483. /package/esm/src/react/components/{ai → chat}/chat/components/sources.js +0 -0
  484. /package/esm/src/react/components/{ai → chat}/chat/components/step-indicator.d.ts +0 -0
  485. /package/esm/src/react/components/{ai → chat}/chat/components/step-indicator.js +0 -0
  486. /package/esm/src/react/components/{ai → chat}/chat/components/tab-switcher.d.ts +0 -0
  487. /package/esm/src/react/components/{ai → chat}/chat/components/tab-switcher.js +0 -0
  488. /package/esm/src/react/components/{ai → chat}/chat/components/upgrade-cta.d.ts +0 -0
  489. /package/esm/src/react/components/{ai → chat}/chat/components/upgrade-cta.js +0 -0
  490. /package/esm/src/react/components/{ai → chat}/chat/components/uploads-panel.d.ts +0 -0
  491. /package/esm/src/react/components/{ai → chat}/chat/components/uploads-panel.js +0 -0
  492. /package/esm/src/react/components/{ai → chat}/chat/hooks/use-threads.js +0 -0
  493. /package/esm/src/react/components/{ai → chat}/chat-with-sidebar.d.ts +0 -0
  494. /package/esm/src/react/components/{ai → chat}/chat-with-sidebar.js +0 -0
  495. /package/esm/src/react/components/{ai → chat}/csp-nonce.d.ts +0 -0
  496. /package/esm/src/react/components/{ai → chat}/csp-nonce.js +0 -0
  497. /package/esm/src/react/components/{ai → chat}/markdown.d.ts +0 -0
  498. /package/esm/src/react/components/{ai → chat}/markdown.js +0 -0
  499. /package/esm/src/react/components/{ai → chat}/message.js +0 -0
  500. /package/esm/src/react/components/{ai → chat}/model-selector.d.ts +0 -0
  501. /package/esm/src/react/components/{ai → chat}/model-selector.js +0 -0
  502. /package/esm/src/react/components/{ai → chat}/theme.d.ts +0 -0
  503. /package/esm/src/react/components/{ai → chat}/theme.js +0 -0
  504. /package/esm/src/{ai/registry-facade.js → registry/scoped-registry-facade.js} +0 -0
  505. /package/src/src/agent/{ai-defaults.ts → defaults.ts} +0 -0
  506. /package/src/src/react/components/{ai → chat}/agent-card.tsx +0 -0
  507. /package/src/src/react/components/{ai → chat}/chat/components/animations.tsx +0 -0
  508. /package/src/src/react/components/{ai → chat}/chat/components/attachment-pill.tsx +0 -0
  509. /package/src/src/react/components/{ai → chat}/chat/components/branch-picker.tsx +0 -0
  510. /package/src/src/react/components/{ai → chat}/chat/components/code-block.tsx +0 -0
  511. /package/src/src/react/components/{ai → chat}/chat/components/drop-zone.tsx +0 -0
  512. /package/src/src/react/components/{ai → chat}/chat/components/empty-state.tsx +0 -0
  513. /package/src/src/react/components/{ai → chat}/chat/components/inline-citation.tsx +0 -0
  514. /package/src/src/react/components/{ai → chat}/chat/components/message-actions.tsx +0 -0
  515. /package/src/src/react/components/{ai → chat}/chat/components/message-edit-form.tsx +0 -0
  516. /package/src/src/react/components/{ai → chat}/chat/components/message-feedback.tsx +0 -0
  517. /package/src/src/react/components/{ai → chat}/chat/components/quick-actions.tsx +0 -0
  518. /package/src/src/react/components/{ai → chat}/chat/components/reasoning.tsx +0 -0
  519. /package/src/src/react/components/{ai → chat}/chat/components/sidebar.tsx +0 -0
  520. /package/src/src/react/components/{ai → chat}/chat/components/sources.tsx +0 -0
  521. /package/src/src/react/components/{ai → chat}/chat/components/step-indicator.tsx +0 -0
  522. /package/src/src/react/components/{ai → chat}/chat/components/tab-switcher.tsx +0 -0
  523. /package/src/src/react/components/{ai → chat}/chat/components/upgrade-cta.tsx +0 -0
  524. /package/src/src/react/components/{ai → chat}/chat/components/uploads-panel.tsx +0 -0
  525. /package/src/src/react/components/{ai → chat}/chat-with-sidebar.tsx +0 -0
  526. /package/src/src/react/components/{ai → chat}/csp-nonce.ts +0 -0
  527. /package/src/src/react/components/{ai → chat}/markdown.tsx +0 -0
  528. /package/src/src/react/components/{ai → chat}/model-selector.tsx +0 -0
  529. /package/src/src/react/components/{ai → chat}/theme.ts +0 -0
@@ -0,0 +1,1854 @@
1
+ import * as dntShim from "../../_dnt.shims.js";
2
+ import type { EmbeddingRuntime, ModelRuntime } from "./types.js";
3
+
4
+ export interface OpenAIRuntimeConfig {
5
+ apiKey: string;
6
+ baseURL?: string;
7
+ name?: string;
8
+ fetch?: typeof dntShim.fetch;
9
+ }
10
+
11
+ export interface AnthropicRuntimeConfig {
12
+ apiKey?: string;
13
+ authToken?: string;
14
+ baseURL?: string;
15
+ name?: string;
16
+ fetch?: typeof dntShim.fetch;
17
+ }
18
+
19
+ export interface GoogleRuntimeConfig {
20
+ apiKey: string;
21
+ baseURL?: string;
22
+ name?: string;
23
+ fetch?: typeof dntShim.fetch;
24
+ }
25
+
26
+ type RuntimePromptMessage =
27
+ | { role: "system"; content: string }
28
+ | { role: "user"; content: Array<{ type: "text"; text: string }> }
29
+ | {
30
+ role: "assistant";
31
+ content: Array<
32
+ | { type: "text"; text: string }
33
+ | {
34
+ type: "tool-call";
35
+ toolCallId: string;
36
+ toolName: string;
37
+ input: unknown;
38
+ providerExecuted?: boolean;
39
+ }
40
+ >;
41
+ }
42
+ | {
43
+ role: "tool";
44
+ content: Array<{
45
+ type: "tool-result";
46
+ toolCallId: string;
47
+ toolName: string;
48
+ output: { type: "json"; value: unknown };
49
+ }>;
50
+ };
51
+ type RuntimeToolDefinition =
52
+ | {
53
+ type: "function";
54
+ name: string;
55
+ description?: string;
56
+ inputSchema: unknown;
57
+ }
58
+ | {
59
+ type: "provider";
60
+ name: string;
61
+ id: `${string}.${string}`;
62
+ args: Record<string, unknown>;
63
+ };
64
+ type OpenAICompatibleLanguageOptions = {
65
+ prompt: RuntimePromptMessage[];
66
+ maxOutputTokens?: number;
67
+ temperature?: number;
68
+ topP?: number;
69
+ topK?: number;
70
+ stopSequences?: string[];
71
+ tools?: RuntimeToolDefinition[];
72
+ toolChoice?: unknown;
73
+ seed?: number;
74
+ presencePenalty?: number;
75
+ frequencyPenalty?: number;
76
+ headers?: dntShim.HeadersInit;
77
+ providerOptions?: Record<string, unknown>;
78
+ includeRawChunks?: boolean;
79
+ abortSignal?: AbortSignal;
80
+ };
81
+ type OpenAICompatibleChatMessage =
82
+ | { role: "system"; content: string }
83
+ | { role: "user"; content: string }
84
+ | {
85
+ role: "assistant";
86
+ content: string | null;
87
+ tool_calls?: Array<{
88
+ id: string;
89
+ type: "function";
90
+ function: {
91
+ name: string;
92
+ arguments: string;
93
+ };
94
+ }>;
95
+ }
96
+ | {
97
+ role: "tool";
98
+ tool_call_id: string;
99
+ content: string;
100
+ };
101
+ type OpenAICompatibleChatRequest = {
102
+ model: string;
103
+ messages: OpenAICompatibleChatMessage[];
104
+ stream?: boolean;
105
+ stream_options?: {
106
+ include_usage?: boolean;
107
+ };
108
+ max_tokens?: number;
109
+ temperature?: number;
110
+ top_p?: number;
111
+ stop?: string[];
112
+ tools?: Array<{
113
+ type: "function";
114
+ function: {
115
+ name: string;
116
+ parameters: unknown;
117
+ description?: string;
118
+ };
119
+ }>;
120
+ tool_choice?: unknown;
121
+ seed?: number;
122
+ presence_penalty?: number;
123
+ frequency_penalty?: number;
124
+ [key: string]: unknown;
125
+ };
126
+ type OpenAICompatibleChoice = {
127
+ message?: unknown;
128
+ delta?: unknown;
129
+ finish_reason?: unknown;
130
+ };
131
+ type OpenAIStreamToolCallState = {
132
+ id: string;
133
+ name: string;
134
+ arguments: string;
135
+ started: boolean;
136
+ };
137
+ type AnthropicCompatibleMessage = {
138
+ role: "user" | "assistant";
139
+ content: Array<Record<string, unknown>>;
140
+ };
141
+ type AnthropicCompatibleRequest = {
142
+ model: string;
143
+ messages: AnthropicCompatibleMessage[];
144
+ max_tokens: number;
145
+ stream?: boolean;
146
+ system?: string;
147
+ temperature?: number;
148
+ top_p?: number;
149
+ stop_sequences?: string[];
150
+ tools?: Array<Record<string, unknown>>;
151
+ tool_choice?: unknown;
152
+ [key: string]: unknown;
153
+ };
154
+ type AnthropicStreamToolCallState = {
155
+ id: string;
156
+ name: string;
157
+ input: string;
158
+ providerExecuted?: boolean;
159
+ };
160
+ type GoogleCompatibleContent = {
161
+ role: "user" | "model";
162
+ parts: Array<Record<string, unknown>>;
163
+ };
164
+ type GoogleCompatibleRequest = {
165
+ contents: GoogleCompatibleContent[];
166
+ systemInstruction?: {
167
+ parts: Array<{ text: string }>;
168
+ };
169
+ tools?: Array<{
170
+ functionDeclarations: Array<Record<string, unknown>>;
171
+ }>;
172
+ toolConfig?: {
173
+ functionCallingConfig: Record<string, unknown>;
174
+ };
175
+ generationConfig?: Record<string, unknown>;
176
+ [key: string]: unknown;
177
+ };
178
+
179
+ const DEFAULT_ANTHROPIC_BASE_URL = "https://api.anthropic.com/v1";
180
+ const DEFAULT_OPENAI_BASE_URL = "https://api.openai.com/v1";
181
+ const DEFAULT_GOOGLE_BASE_URL = "https://generativelanguage.googleapis.com/v1beta";
182
+
183
+ function joinUrl(base: string, path: string): string {
184
+ return `${base.replace(/\/+$/, "")}/${path.replace(/^\/+/, "")}`;
185
+ }
186
+
187
+ function getOpenAIEmbeddingUrl(baseURL?: string): string {
188
+ return joinUrl(baseURL ?? DEFAULT_OPENAI_BASE_URL, "embeddings");
189
+ }
190
+
191
+ function getAnthropicMessagesUrl(baseURL?: string): string {
192
+ return joinUrl(baseURL ?? DEFAULT_ANTHROPIC_BASE_URL, "messages");
193
+ }
194
+
195
+ function getOpenAIChatCompletionsUrl(baseURL?: string): string {
196
+ return joinUrl(baseURL ?? DEFAULT_OPENAI_BASE_URL, "chat/completions");
197
+ }
198
+
199
+ function getGoogleGenerateContentUrl(baseURL: string | undefined, modelId: string): string {
200
+ return joinUrl(
201
+ baseURL ?? DEFAULT_GOOGLE_BASE_URL,
202
+ `models/${encodeURIComponent(modelId)}:generateContent`,
203
+ );
204
+ }
205
+
206
+ function getGoogleStreamGenerateContentUrl(baseURL: string | undefined, modelId: string): string {
207
+ return joinUrl(
208
+ baseURL ?? DEFAULT_GOOGLE_BASE_URL,
209
+ `models/${encodeURIComponent(modelId)}:streamGenerateContent?alt=sse`,
210
+ );
211
+ }
212
+
213
+ function getGoogleEmbeddingUrl(baseURL: string | undefined, modelId: string): string {
214
+ return joinUrl(
215
+ baseURL ?? DEFAULT_GOOGLE_BASE_URL,
216
+ `models/${encodeURIComponent(modelId)}:embedContent`,
217
+ );
218
+ }
219
+
220
+ function isNumberArray(value: unknown): value is number[] {
221
+ return Array.isArray(value) && value.every((entry) => typeof entry === "number");
222
+ }
223
+
224
+ function readRecord(value: unknown): Record<string, unknown> | undefined {
225
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
226
+ return undefined;
227
+ }
228
+
229
+ return Object.fromEntries(Object.entries(value));
230
+ }
231
+
232
+ function extractOpenAIEmbeddings(payload: unknown): number[][] {
233
+ const record = readRecord(payload);
234
+ const data = record?.data;
235
+ if (!Array.isArray(data)) {
236
+ throw new Error("Invalid OpenAI embedding response: data array missing");
237
+ }
238
+
239
+ const embeddings: number[][] = [];
240
+
241
+ for (const item of data) {
242
+ const itemRecord = readRecord(item);
243
+ const embedding = itemRecord?.embedding;
244
+ if (!isNumberArray(embedding)) {
245
+ throw new Error("Invalid OpenAI embedding response: embedding vector missing");
246
+ }
247
+ embeddings.push(embedding);
248
+ }
249
+
250
+ return embeddings;
251
+ }
252
+
253
+ function extractOpenAIUsageTokens(payload: unknown): number | undefined {
254
+ const record = readRecord(payload);
255
+ const usage = readRecord(record?.usage);
256
+ const totalTokens = usage?.total_tokens;
257
+ return typeof totalTokens === "number" ? totalTokens : undefined;
258
+ }
259
+
260
+ function extractGoogleEmbedding(payload: unknown): number[] {
261
+ const record = readRecord(payload);
262
+ const embeddings = record?.embeddings;
263
+
264
+ if (Array.isArray(embeddings) && embeddings.length > 0) {
265
+ const firstEmbedding = readRecord(embeddings[0]);
266
+ const values = firstEmbedding?.values;
267
+ if (isNumberArray(values)) {
268
+ return values;
269
+ }
270
+ }
271
+
272
+ const embedding = readRecord(record?.embedding);
273
+ const values = embedding?.values;
274
+ if (isNumberArray(values)) {
275
+ return values;
276
+ }
277
+
278
+ throw new Error("Invalid Google embedding response: embedding vector missing");
279
+ }
280
+
281
+ function extractGoogleUsageTokens(payload: unknown): number | undefined {
282
+ const record = readRecord(payload);
283
+ const usageMetadata = readRecord(record?.usageMetadata);
284
+ const promptTokenCount = usageMetadata?.promptTokenCount;
285
+ return typeof promptTokenCount === "number" ? promptTokenCount : undefined;
286
+ }
287
+
288
+ async function readErrorMessage(response: dntShim.Response): Promise<string> {
289
+ const text = await response.text();
290
+ return text.trim() || `${response.status} ${response.statusText}`.trim();
291
+ }
292
+
293
+ async function requestJson(options: {
294
+ url: string;
295
+ fetchImpl: typeof dntShim.fetch;
296
+ init: dntShim.RequestInit;
297
+ providerLabel: string;
298
+ }): Promise<unknown> {
299
+ const response = await options.fetchImpl(options.url, options.init);
300
+ if (!response.ok) {
301
+ const message = await readErrorMessage(response);
302
+ throw new Error(`${options.providerLabel} request failed: ${message}`);
303
+ }
304
+
305
+ return response.json();
306
+ }
307
+
308
+ async function requestStream(options: {
309
+ url: string;
310
+ fetchImpl: typeof dntShim.fetch;
311
+ init: dntShim.RequestInit;
312
+ providerLabel: string;
313
+ }): Promise<ReadableStream<Uint8Array>> {
314
+ const response = await options.fetchImpl(options.url, options.init);
315
+ if (!response.ok) {
316
+ const message = await readErrorMessage(response);
317
+ throw new Error(`${options.providerLabel} request failed: ${message}`);
318
+ }
319
+
320
+ if (!response.body) {
321
+ throw new Error(`${options.providerLabel} request failed: stream body missing`);
322
+ }
323
+
324
+ return response.body;
325
+ }
326
+
327
+ function stringifyJsonValue(value: unknown): string {
328
+ if (typeof value === "string") {
329
+ return value;
330
+ }
331
+
332
+ return JSON.stringify(value);
333
+ }
334
+
335
+ function readTextParts(parts: Array<{ type: string; text?: string }>): string {
336
+ let text = "";
337
+ for (const part of parts) {
338
+ if (part.type === "text" && typeof part.text === "string") {
339
+ text += part.text;
340
+ }
341
+ }
342
+ return text;
343
+ }
344
+
345
+ function toOpenAICompatibleMessages(prompt: RuntimePromptMessage[]): OpenAICompatibleChatMessage[] {
346
+ const messages: OpenAICompatibleChatMessage[] = [];
347
+
348
+ for (const message of prompt) {
349
+ switch (message.role) {
350
+ case "system":
351
+ messages.push({ role: "system", content: message.content });
352
+ break;
353
+ case "user":
354
+ messages.push({ role: "user", content: readTextParts(message.content) });
355
+ break;
356
+ case "assistant": {
357
+ let text = "";
358
+ const toolCalls: NonNullable<
359
+ Extract<OpenAICompatibleChatMessage, { role: "assistant" }>["tool_calls"]
360
+ > = [];
361
+
362
+ for (const part of message.content) {
363
+ if (part.type === "text") {
364
+ text += part.text;
365
+ continue;
366
+ }
367
+
368
+ toolCalls.push({
369
+ id: part.toolCallId,
370
+ type: "function",
371
+ function: {
372
+ name: part.toolName,
373
+ arguments: stringifyJsonValue(part.input),
374
+ },
375
+ });
376
+ }
377
+
378
+ messages.push({
379
+ role: "assistant",
380
+ content: text.length > 0 ? text : null,
381
+ ...(toolCalls.length > 0 ? { tool_calls: toolCalls } : {}),
382
+ });
383
+ break;
384
+ }
385
+ case "tool":
386
+ for (const part of message.content) {
387
+ messages.push({
388
+ role: "tool",
389
+ tool_call_id: part.toolCallId,
390
+ content: stringifyJsonValue(part.output.value),
391
+ });
392
+ }
393
+ break;
394
+ }
395
+ }
396
+
397
+ return messages;
398
+ }
399
+
400
+ function toOpenAICompatibleTools(
401
+ tools: RuntimeToolDefinition[] | undefined,
402
+ ): OpenAICompatibleChatRequest["tools"] | undefined {
403
+ if (!tools) {
404
+ return undefined;
405
+ }
406
+
407
+ const functions = tools.flatMap((tool) =>
408
+ tool.type === "function"
409
+ ? [{
410
+ type: "function" as const,
411
+ function: {
412
+ name: tool.name,
413
+ parameters: tool.inputSchema,
414
+ ...(typeof tool.description === "string" ? { description: tool.description } : {}),
415
+ },
416
+ }]
417
+ : []
418
+ );
419
+
420
+ return functions.length > 0 ? functions : undefined;
421
+ }
422
+
423
+ function readProviderOptions(
424
+ providerOptions: Record<string, unknown> | undefined,
425
+ ...providerNames: string[]
426
+ ): Record<string, unknown> {
427
+ if (!providerOptions) {
428
+ return {};
429
+ }
430
+
431
+ const merged: Record<string, unknown> = {};
432
+ for (const key of providerNames) {
433
+ const value = providerOptions[key];
434
+ const record = readRecord(value);
435
+ if (record) {
436
+ Object.assign(merged, record);
437
+ }
438
+ }
439
+
440
+ return merged;
441
+ }
442
+
443
+ function createRequestHeaders(options: {
444
+ apiKeyHeaderName: string;
445
+ apiKey: string;
446
+ extraHeaders?: dntShim.HeadersInit;
447
+ }): dntShim.Headers {
448
+ const headers = new dntShim.Headers(options.extraHeaders);
449
+ headers.set("content-type", "application/json");
450
+ headers.set(options.apiKeyHeaderName, options.apiKey);
451
+ return headers;
452
+ }
453
+
454
+ function normalizeAnthropicFinishReason(
455
+ raw: unknown,
456
+ ): string | { unified: string; raw: string } | null {
457
+ if (typeof raw !== "string") {
458
+ return null;
459
+ }
460
+
461
+ switch (raw) {
462
+ case "tool_use":
463
+ return { unified: "tool-calls", raw };
464
+ case "end_turn":
465
+ case "stop_sequence":
466
+ return { unified: "stop", raw };
467
+ case "max_tokens":
468
+ return { unified: "length", raw };
469
+ default:
470
+ return raw;
471
+ }
472
+ }
473
+
474
+ function extractAnthropicUsage(payload: unknown):
475
+ | { inputTokens?: number; outputTokens?: number; totalTokens?: number }
476
+ | undefined {
477
+ const record = readRecord(payload);
478
+ const usage = readRecord(record?.usage);
479
+ if (!usage) {
480
+ return undefined;
481
+ }
482
+
483
+ const inputTokens = usage.input_tokens;
484
+ const outputTokens = usage.output_tokens;
485
+
486
+ return {
487
+ inputTokens: typeof inputTokens === "number" ? inputTokens : undefined,
488
+ outputTokens: typeof outputTokens === "number" ? outputTokens : undefined,
489
+ totalTokens: typeof inputTokens === "number" || typeof outputTokens === "number"
490
+ ? (typeof inputTokens === "number" ? inputTokens : 0) +
491
+ (typeof outputTokens === "number" ? outputTokens : 0)
492
+ : undefined,
493
+ };
494
+ }
495
+
496
+ function mergeUsage(
497
+ current:
498
+ | { inputTokens?: number; outputTokens?: number; totalTokens?: number }
499
+ | undefined,
500
+ next:
501
+ | { inputTokens?: number; outputTokens?: number; totalTokens?: number }
502
+ | undefined,
503
+ ): { inputTokens?: number; outputTokens?: number; totalTokens?: number } | undefined {
504
+ if (!current) {
505
+ return next;
506
+ }
507
+
508
+ if (!next) {
509
+ return current;
510
+ }
511
+
512
+ const inputTokens = next.inputTokens ?? current.inputTokens;
513
+ const outputTokens = next.outputTokens ?? current.outputTokens;
514
+
515
+ return {
516
+ inputTokens,
517
+ outputTokens,
518
+ totalTokens: (inputTokens ?? 0) + (outputTokens ?? 0),
519
+ };
520
+ }
521
+
522
+ function normalizeAnthropicToolChoice(toolChoice: unknown): unknown {
523
+ if (typeof toolChoice === "string") {
524
+ return { type: toolChoice };
525
+ }
526
+
527
+ return toolChoice;
528
+ }
529
+
530
+ function toSnakeCaseRecord(record: Record<string, unknown>): Record<string, unknown> {
531
+ return Object.fromEntries(
532
+ Object.entries(record).map(([key, value]) => [
533
+ key.replace(/[A-Z]/g, (match) => `_${match.toLowerCase()}`),
534
+ value,
535
+ ]),
536
+ );
537
+ }
538
+
539
+ function toAnthropicMessages(
540
+ prompt: RuntimePromptMessage[],
541
+ ): { system?: string; messages: AnthropicCompatibleMessage[] } {
542
+ const systemParts: string[] = [];
543
+ const messages: AnthropicCompatibleMessage[] = [];
544
+
545
+ for (const message of prompt) {
546
+ switch (message.role) {
547
+ case "system":
548
+ if (message.content.length > 0) {
549
+ systemParts.push(message.content);
550
+ }
551
+ break;
552
+ case "user":
553
+ messages.push({
554
+ role: "user",
555
+ content: [{ type: "text", text: readTextParts(message.content) }],
556
+ });
557
+ break;
558
+ case "assistant":
559
+ messages.push({
560
+ role: "assistant",
561
+ content: message.content.map((part) =>
562
+ part.type === "text" ? { type: "text", text: part.text } : {
563
+ type: "tool_use",
564
+ id: part.toolCallId,
565
+ name: part.toolName,
566
+ input: part.input,
567
+ }
568
+ ),
569
+ });
570
+ break;
571
+ case "tool":
572
+ messages.push({
573
+ role: "user",
574
+ content: message.content.map((part) => ({
575
+ type: "tool_result",
576
+ tool_use_id: part.toolCallId,
577
+ content: stringifyJsonValue(part.output.value),
578
+ })),
579
+ });
580
+ break;
581
+ }
582
+ }
583
+
584
+ return {
585
+ ...(systemParts.length > 0 ? { system: systemParts.join("\n\n") } : {}),
586
+ messages,
587
+ };
588
+ }
589
+
590
+ function toAnthropicTools(
591
+ tools: RuntimeToolDefinition[] | undefined,
592
+ ): Array<Record<string, unknown>> | undefined {
593
+ if (!tools) {
594
+ return undefined;
595
+ }
596
+
597
+ const normalized: Array<Record<string, unknown>> = [];
598
+
599
+ for (const tool of tools) {
600
+ if (tool.type === "function") {
601
+ normalized.push({
602
+ name: tool.name,
603
+ ...(typeof tool.description === "string" ? { description: tool.description } : {}),
604
+ input_schema: tool.inputSchema,
605
+ });
606
+ continue;
607
+ }
608
+
609
+ if (!tool.id.startsWith("anthropic.")) {
610
+ continue;
611
+ }
612
+
613
+ const providerType = tool.id.slice("anthropic.".length);
614
+ if (providerType.length === 0) {
615
+ continue;
616
+ }
617
+
618
+ normalized.push({
619
+ type: providerType,
620
+ name: tool.name,
621
+ ...toSnakeCaseRecord(tool.args),
622
+ });
623
+ }
624
+
625
+ return normalized.length > 0 ? normalized : undefined;
626
+ }
627
+
628
+ function createAnthropicRequestHeaders(options: {
629
+ apiKey?: string;
630
+ authToken?: string;
631
+ extraHeaders?: dntShim.HeadersInit;
632
+ }): dntShim.Headers {
633
+ const headers = new dntShim.Headers(options.extraHeaders);
634
+ headers.set("content-type", "application/json");
635
+ headers.set("anthropic-version", headers.get("anthropic-version") ?? "2023-06-01");
636
+
637
+ if (options.authToken) {
638
+ headers.set("authorization", `Bearer ${options.authToken}`);
639
+ } else if (options.apiKey) {
640
+ headers.set("x-api-key", options.apiKey);
641
+ }
642
+
643
+ return headers;
644
+ }
645
+
646
+ function buildAnthropicMessagesRequest(
647
+ modelId: string,
648
+ providerName: string,
649
+ options: OpenAICompatibleLanguageOptions,
650
+ stream: boolean,
651
+ ): AnthropicCompatibleRequest {
652
+ const { system, messages } = toAnthropicMessages(options.prompt);
653
+ const body: AnthropicCompatibleRequest = {
654
+ model: modelId,
655
+ messages,
656
+ max_tokens: options.maxOutputTokens ?? 1024,
657
+ ...(stream ? { stream: true } : {}),
658
+ ...(system ? { system } : {}),
659
+ ...(options.temperature !== undefined ? { temperature: options.temperature } : {}),
660
+ ...(options.topP !== undefined ? { top_p: options.topP } : {}),
661
+ ...(options.stopSequences && options.stopSequences.length > 0
662
+ ? { stop_sequences: options.stopSequences }
663
+ : {}),
664
+ ...(toAnthropicTools(options.tools) ? { tools: toAnthropicTools(options.tools) } : {}),
665
+ ...(options.toolChoice !== undefined
666
+ ? { tool_choice: normalizeAnthropicToolChoice(options.toolChoice) }
667
+ : {}),
668
+ };
669
+
670
+ Object.assign(body, readProviderOptions(options.providerOptions, "anthropic", providerName));
671
+ return body;
672
+ }
673
+
674
+ function buildAnthropicGenerateResult(payload: unknown): {
675
+ content: Array<
676
+ | { type: "text"; text: string }
677
+ | { type: "tool-call"; toolCallId: string; toolName: string; input: string }
678
+ | { type: "tool-result"; toolCallId: string; toolName: string; result: unknown }
679
+ >;
680
+ finishReason?: string | { unified: string; raw: string } | null;
681
+ usage?: { inputTokens?: number; outputTokens?: number; totalTokens?: number };
682
+ } {
683
+ const record = readRecord(payload);
684
+ const content = Array.isArray(record?.content) ? record.content : [];
685
+ const normalized: Array<
686
+ | { type: "text"; text: string }
687
+ | { type: "tool-call"; toolCallId: string; toolName: string; input: string }
688
+ | { type: "tool-result"; toolCallId: string; toolName: string; result: unknown }
689
+ > = [];
690
+
691
+ for (const blockValue of content) {
692
+ const block = readRecord(blockValue);
693
+ const blockType = typeof block?.type === "string" ? block.type : undefined;
694
+
695
+ if (blockType === "text" && typeof block?.text === "string" && block.text.length > 0) {
696
+ normalized.push({ type: "text", text: block.text });
697
+ continue;
698
+ }
699
+
700
+ if (
701
+ (blockType === "tool_use" || blockType === "server_tool_use") &&
702
+ typeof block?.id === "string" &&
703
+ typeof block?.name === "string"
704
+ ) {
705
+ normalized.push({
706
+ type: "tool-call",
707
+ toolCallId: block.id,
708
+ toolName: block.name,
709
+ input: stringifyJsonValue(block.input ?? {}),
710
+ });
711
+ continue;
712
+ }
713
+
714
+ if (
715
+ blockType === "web_search_tool_result" &&
716
+ typeof block?.tool_use_id === "string" &&
717
+ Array.isArray(block?.content)
718
+ ) {
719
+ normalized.push({
720
+ type: "tool-result",
721
+ toolCallId: block.tool_use_id,
722
+ toolName: "web_search",
723
+ result: block.content,
724
+ });
725
+ }
726
+ }
727
+
728
+ return {
729
+ content: normalized,
730
+ finishReason: normalizeAnthropicFinishReason(record?.stop_reason),
731
+ usage: extractAnthropicUsage(payload),
732
+ };
733
+ }
734
+
735
+ function parseAnthropicSseChunk(chunk: string): {
736
+ events: Array<unknown | "[DONE]">;
737
+ remainder: string;
738
+ } {
739
+ const blocks = chunk.split("\n\n");
740
+ const remainder = blocks.pop() ?? "";
741
+ const events = blocks.flatMap((block) => {
742
+ const dataLines = block.split("\n")
743
+ .filter((line) => line.startsWith("data:"))
744
+ .map((line) => line.slice(5).trimStart());
745
+
746
+ if (!dataLines.length) {
747
+ return [];
748
+ }
749
+
750
+ const payload = dataLines.join("\n").trim();
751
+ if (payload === "[DONE]") {
752
+ return ["[DONE]" as const];
753
+ }
754
+
755
+ try {
756
+ return [JSON.parse(payload) as unknown];
757
+ } catch {
758
+ return [];
759
+ }
760
+ });
761
+
762
+ return { events, remainder };
763
+ }
764
+
765
+ async function* streamAnthropicCompatibleParts(
766
+ stream: ReadableStream<Uint8Array>,
767
+ ): AsyncIterable<unknown> {
768
+ const decoder = new TextDecoder();
769
+ let buffer = "";
770
+ const toolCalls = new Map<number, AnthropicStreamToolCallState>();
771
+ let finishReason: string | { unified: string; raw: string } | null = null;
772
+ let usage: { inputTokens?: number; outputTokens?: number; totalTokens?: number } | undefined;
773
+
774
+ for await (const chunk of stream) {
775
+ buffer += decoder.decode(chunk, { stream: true });
776
+ const parsed = parseAnthropicSseChunk(buffer);
777
+ buffer = parsed.remainder;
778
+
779
+ for (const event of parsed.events) {
780
+ if (event === "[DONE]") {
781
+ continue;
782
+ }
783
+
784
+ const record = readRecord(event);
785
+ const eventType = typeof record?.type === "string" ? record.type : undefined;
786
+ usage = mergeUsage(usage, extractAnthropicUsage(record));
787
+
788
+ if (eventType === "message_start") {
789
+ usage = mergeUsage(usage, extractAnthropicUsage(record?.message));
790
+ continue;
791
+ }
792
+
793
+ if (eventType === "content_block_start") {
794
+ const index = typeof record?.index === "number" ? record.index : 0;
795
+ const contentBlock = readRecord(record?.content_block);
796
+ const blockType = typeof contentBlock?.type === "string" ? contentBlock.type : undefined;
797
+
798
+ if (
799
+ blockType === "text" && typeof contentBlock?.text === "string" &&
800
+ contentBlock.text.length > 0
801
+ ) {
802
+ yield { type: "text-delta", delta: contentBlock.text };
803
+ continue;
804
+ }
805
+
806
+ if (
807
+ (blockType === "tool_use" || blockType === "server_tool_use") &&
808
+ typeof contentBlock?.id === "string" &&
809
+ typeof contentBlock?.name === "string"
810
+ ) {
811
+ const providerExecuted = blockType === "server_tool_use" ? true : undefined;
812
+ const current: AnthropicStreamToolCallState = {
813
+ id: contentBlock.id,
814
+ name: contentBlock.name,
815
+ input: "",
816
+ ...(providerExecuted ? { providerExecuted } : {}),
817
+ };
818
+
819
+ toolCalls.set(index, current);
820
+ yield {
821
+ type: "tool-input-start",
822
+ id: current.id,
823
+ toolName: current.name,
824
+ ...(providerExecuted ? { providerExecuted } : {}),
825
+ };
826
+
827
+ const initialInput = contentBlock.input;
828
+ if (initialInput !== undefined) {
829
+ const serializedInput = stringifyJsonValue(initialInput);
830
+ current.input += serializedInput;
831
+ yield {
832
+ type: "tool-input-delta",
833
+ id: current.id,
834
+ delta: serializedInput,
835
+ };
836
+ }
837
+ continue;
838
+ }
839
+
840
+ if (
841
+ blockType === "web_search_tool_result" &&
842
+ typeof contentBlock?.tool_use_id === "string" &&
843
+ Array.isArray(contentBlock?.content)
844
+ ) {
845
+ yield {
846
+ type: "tool-result",
847
+ toolCallId: contentBlock.tool_use_id,
848
+ toolName: "web_search",
849
+ result: contentBlock.content,
850
+ providerExecuted: true,
851
+ };
852
+ }
853
+
854
+ continue;
855
+ }
856
+
857
+ if (eventType === "content_block_delta") {
858
+ const index = typeof record?.index === "number" ? record.index : 0;
859
+ const delta = readRecord(record?.delta);
860
+ const deltaType = typeof delta?.type === "string" ? delta.type : undefined;
861
+
862
+ if (
863
+ deltaType === "text_delta" && typeof delta?.text === "string" && delta.text.length > 0
864
+ ) {
865
+ yield { type: "text-delta", delta: delta.text };
866
+ continue;
867
+ }
868
+
869
+ if (deltaType === "input_json_delta" && typeof delta?.partial_json === "string") {
870
+ const current = toolCalls.get(index);
871
+ if (!current) {
872
+ continue;
873
+ }
874
+
875
+ current.input += delta.partial_json;
876
+ yield {
877
+ type: "tool-input-delta",
878
+ id: current.id,
879
+ delta: delta.partial_json,
880
+ };
881
+ }
882
+
883
+ continue;
884
+ }
885
+
886
+ if (eventType === "content_block_stop") {
887
+ const index = typeof record?.index === "number" ? record.index : 0;
888
+ const current = toolCalls.get(index);
889
+ if (!current) {
890
+ continue;
891
+ }
892
+
893
+ yield {
894
+ type: "tool-call",
895
+ toolCallId: current.id,
896
+ toolName: current.name,
897
+ input: current.input.length > 0 ? current.input : "{}",
898
+ ...(current.providerExecuted ? { providerExecuted: true } : {}),
899
+ };
900
+ toolCalls.delete(index);
901
+ continue;
902
+ }
903
+
904
+ if (eventType === "message_delta") {
905
+ const delta = readRecord(record?.delta);
906
+ const normalizedFinishReason = normalizeAnthropicFinishReason(delta?.stop_reason);
907
+ if (normalizedFinishReason) {
908
+ finishReason = normalizedFinishReason;
909
+ }
910
+ }
911
+ }
912
+ }
913
+
914
+ if (buffer.trim().length > 0) {
915
+ const parsed = parseAnthropicSseChunk(`${buffer}\n\n`);
916
+ for (const event of parsed.events) {
917
+ if (event === "[DONE]") {
918
+ continue;
919
+ }
920
+ const record = readRecord(event);
921
+ usage = mergeUsage(usage, extractAnthropicUsage(record));
922
+ }
923
+ }
924
+
925
+ yield {
926
+ type: "finish",
927
+ finishReason,
928
+ ...(usage ? { usage } : {}),
929
+ };
930
+ }
931
+
932
+ function normalizeOpenAIFinishReason(
933
+ raw: unknown,
934
+ ): string | { unified: string; raw: string } | null {
935
+ if (typeof raw !== "string") {
936
+ return null;
937
+ }
938
+
939
+ if (raw === "tool_calls") {
940
+ return { unified: "tool-calls", raw };
941
+ }
942
+
943
+ if (raw === "content_filter") {
944
+ return { unified: "content-filter", raw };
945
+ }
946
+
947
+ return raw;
948
+ }
949
+
950
+ function extractOpenAIUsage(payload: unknown):
951
+ | { inputTokens?: number; outputTokens?: number; totalTokens?: number }
952
+ | undefined {
953
+ const record = readRecord(payload);
954
+ const usage = readRecord(record?.usage);
955
+ if (!usage) {
956
+ return undefined;
957
+ }
958
+
959
+ const inputTokens = usage.prompt_tokens;
960
+ const outputTokens = usage.completion_tokens;
961
+ const totalTokens = usage.total_tokens;
962
+
963
+ return {
964
+ inputTokens: typeof inputTokens === "number" ? inputTokens : undefined,
965
+ outputTokens: typeof outputTokens === "number" ? outputTokens : undefined,
966
+ totalTokens: typeof totalTokens === "number" ? totalTokens : undefined,
967
+ };
968
+ }
969
+
970
+ function extractOpenAIContentText(content: unknown): string {
971
+ if (typeof content === "string") {
972
+ return content;
973
+ }
974
+
975
+ if (!Array.isArray(content)) {
976
+ return "";
977
+ }
978
+
979
+ let text = "";
980
+ for (const part of content) {
981
+ const record = readRecord(part);
982
+ const type = record?.type;
983
+ if (type === "text" && typeof record?.text === "string") {
984
+ text += record.text;
985
+ }
986
+ }
987
+
988
+ return text;
989
+ }
990
+
991
+ function extractOpenAIToolCalls(message: Record<string, unknown>): Array<{
992
+ toolCallId: string;
993
+ toolName: string;
994
+ input: string;
995
+ }> {
996
+ const toolCalls = message.tool_calls;
997
+ if (!Array.isArray(toolCalls)) {
998
+ return [];
999
+ }
1000
+
1001
+ const normalized: Array<{ toolCallId: string; toolName: string; input: string }> = [];
1002
+ for (const entry of toolCalls) {
1003
+ const record = readRecord(entry);
1004
+ const id = typeof record?.id === "string" ? record.id : undefined;
1005
+ const fn = readRecord(record?.function);
1006
+ const name = typeof fn?.name === "string" ? fn.name : undefined;
1007
+ const argumentsText = typeof fn?.arguments === "string" ? fn.arguments : undefined;
1008
+ if (!id || !name || argumentsText === undefined) {
1009
+ continue;
1010
+ }
1011
+ normalized.push({
1012
+ toolCallId: id,
1013
+ toolName: name,
1014
+ input: argumentsText,
1015
+ });
1016
+ }
1017
+
1018
+ return normalized;
1019
+ }
1020
+
1021
+ function buildOpenAIChatRequest(
1022
+ modelId: string,
1023
+ providerName: string,
1024
+ options: OpenAICompatibleLanguageOptions,
1025
+ stream: boolean,
1026
+ ): OpenAICompatibleChatRequest {
1027
+ const body: OpenAICompatibleChatRequest = {
1028
+ model: modelId,
1029
+ messages: toOpenAICompatibleMessages(options.prompt),
1030
+ ...(stream ? { stream: true, stream_options: { include_usage: true } } : {}),
1031
+ ...(options.maxOutputTokens !== undefined ? { max_tokens: options.maxOutputTokens } : {}),
1032
+ ...(options.temperature !== undefined ? { temperature: options.temperature } : {}),
1033
+ ...(options.topP !== undefined ? { top_p: options.topP } : {}),
1034
+ ...(options.stopSequences && options.stopSequences.length > 0
1035
+ ? { stop: options.stopSequences }
1036
+ : {}),
1037
+ ...(toOpenAICompatibleTools(options.tools)
1038
+ ? { tools: toOpenAICompatibleTools(options.tools) }
1039
+ : {}),
1040
+ ...(options.toolChoice !== undefined ? { tool_choice: options.toolChoice } : {}),
1041
+ ...(options.seed !== undefined ? { seed: options.seed } : {}),
1042
+ ...(options.presencePenalty !== undefined ? { presence_penalty: options.presencePenalty } : {}),
1043
+ ...(options.frequencyPenalty !== undefined
1044
+ ? { frequency_penalty: options.frequencyPenalty }
1045
+ : {}),
1046
+ };
1047
+
1048
+ Object.assign(body, readProviderOptions(options.providerOptions, "openai", providerName));
1049
+ return body;
1050
+ }
1051
+
1052
+ function normalizeGoogleFinishReason(
1053
+ raw: unknown,
1054
+ ): string | { unified: string; raw: string } | null {
1055
+ if (typeof raw !== "string") {
1056
+ return null;
1057
+ }
1058
+
1059
+ switch (raw) {
1060
+ case "STOP":
1061
+ return { unified: "stop", raw };
1062
+ case "MAX_TOKENS":
1063
+ return { unified: "length", raw };
1064
+ case "SAFETY":
1065
+ case "RECITATION":
1066
+ return { unified: "content-filter", raw };
1067
+ default:
1068
+ return raw.toLowerCase();
1069
+ }
1070
+ }
1071
+
1072
+ function extractGoogleUsage(payload: unknown):
1073
+ | { inputTokens?: number; outputTokens?: number; totalTokens?: number }
1074
+ | undefined {
1075
+ const record = readRecord(payload);
1076
+ const usage = readRecord(record?.usageMetadata);
1077
+ if (!usage) {
1078
+ return undefined;
1079
+ }
1080
+
1081
+ const inputTokens = usage.promptTokenCount;
1082
+ const outputTokens = usage.candidatesTokenCount;
1083
+ const totalTokens = usage.totalTokenCount;
1084
+
1085
+ return {
1086
+ inputTokens: typeof inputTokens === "number" ? inputTokens : undefined,
1087
+ outputTokens: typeof outputTokens === "number" ? outputTokens : undefined,
1088
+ totalTokens: typeof totalTokens === "number" ? totalTokens : undefined,
1089
+ };
1090
+ }
1091
+
1092
+ function toGoogleContents(
1093
+ prompt: RuntimePromptMessage[],
1094
+ ): {
1095
+ systemInstruction?: { parts: Array<{ text: string }> };
1096
+ contents: GoogleCompatibleContent[];
1097
+ } {
1098
+ const systemParts: string[] = [];
1099
+ const contents: GoogleCompatibleContent[] = [];
1100
+
1101
+ for (const message of prompt) {
1102
+ switch (message.role) {
1103
+ case "system":
1104
+ if (message.content.length > 0) {
1105
+ systemParts.push(message.content);
1106
+ }
1107
+ break;
1108
+ case "user":
1109
+ contents.push({
1110
+ role: "user",
1111
+ parts: [{ text: readTextParts(message.content) }],
1112
+ });
1113
+ break;
1114
+ case "assistant":
1115
+ contents.push({
1116
+ role: "model",
1117
+ parts: message.content.map((part) =>
1118
+ part.type === "text" ? { text: part.text } : {
1119
+ functionCall: {
1120
+ id: part.toolCallId,
1121
+ name: part.toolName,
1122
+ args: part.input,
1123
+ },
1124
+ }
1125
+ ),
1126
+ });
1127
+ break;
1128
+ case "tool":
1129
+ contents.push({
1130
+ role: "user",
1131
+ parts: message.content.map((part) => ({
1132
+ functionResponse: {
1133
+ id: part.toolCallId,
1134
+ name: part.toolName,
1135
+ response: {
1136
+ result: part.output.value,
1137
+ },
1138
+ },
1139
+ })),
1140
+ });
1141
+ break;
1142
+ }
1143
+ }
1144
+
1145
+ return {
1146
+ ...(systemParts.length > 0
1147
+ ? { systemInstruction: { parts: systemParts.map((text) => ({ text })) } }
1148
+ : {}),
1149
+ contents,
1150
+ };
1151
+ }
1152
+
1153
+ function toGoogleTools(
1154
+ tools: RuntimeToolDefinition[] | undefined,
1155
+ ): GoogleCompatibleRequest["tools"] | undefined {
1156
+ if (!tools) {
1157
+ return undefined;
1158
+ }
1159
+
1160
+ const functionDeclarations = tools.flatMap((tool) =>
1161
+ tool.type === "function"
1162
+ ? [{
1163
+ name: tool.name,
1164
+ ...(typeof tool.description === "string" ? { description: tool.description } : {}),
1165
+ parameters: tool.inputSchema,
1166
+ }]
1167
+ : []
1168
+ );
1169
+
1170
+ return functionDeclarations.length > 0 ? [{ functionDeclarations }] : undefined;
1171
+ }
1172
+
1173
+ function normalizeGoogleToolChoice(toolChoice: unknown):
1174
+ | GoogleCompatibleRequest["toolConfig"]
1175
+ | undefined {
1176
+ if (toolChoice === undefined) {
1177
+ return undefined;
1178
+ }
1179
+
1180
+ if (typeof toolChoice === "string") {
1181
+ switch (toolChoice) {
1182
+ case "none":
1183
+ return { functionCallingConfig: { mode: "NONE" } };
1184
+ case "any":
1185
+ case "required":
1186
+ return { functionCallingConfig: { mode: "ANY" } };
1187
+ default:
1188
+ return { functionCallingConfig: { mode: "AUTO" } };
1189
+ }
1190
+ }
1191
+
1192
+ const record = readRecord(toolChoice);
1193
+ if (record?.type === "tool" && typeof record.name === "string") {
1194
+ return {
1195
+ functionCallingConfig: {
1196
+ mode: "ANY",
1197
+ allowedFunctionNames: [record.name],
1198
+ },
1199
+ };
1200
+ }
1201
+
1202
+ return undefined;
1203
+ }
1204
+
1205
+ function buildGoogleGenerationConfig(
1206
+ options: OpenAICompatibleLanguageOptions,
1207
+ ): Record<string, unknown> | undefined {
1208
+ const config: Record<string, unknown> = {
1209
+ ...(options.maxOutputTokens !== undefined ? { maxOutputTokens: options.maxOutputTokens } : {}),
1210
+ ...(options.temperature !== undefined ? { temperature: options.temperature } : {}),
1211
+ ...(options.topP !== undefined ? { topP: options.topP } : {}),
1212
+ ...(options.topK !== undefined ? { topK: options.topK } : {}),
1213
+ ...(options.stopSequences && options.stopSequences.length > 0
1214
+ ? { stopSequences: options.stopSequences }
1215
+ : {}),
1216
+ ...(options.seed !== undefined ? { seed: options.seed } : {}),
1217
+ };
1218
+
1219
+ return Object.keys(config).length > 0 ? config : undefined;
1220
+ }
1221
+
1222
+ function buildGoogleGenerateContentRequest(
1223
+ providerName: string,
1224
+ options: OpenAICompatibleLanguageOptions,
1225
+ ): GoogleCompatibleRequest {
1226
+ const { systemInstruction, contents } = toGoogleContents(options.prompt);
1227
+ const body: GoogleCompatibleRequest = {
1228
+ contents,
1229
+ ...(systemInstruction ? { systemInstruction } : {}),
1230
+ ...(toGoogleTools(options.tools) ? { tools: toGoogleTools(options.tools) } : {}),
1231
+ ...(normalizeGoogleToolChoice(options.toolChoice)
1232
+ ? { toolConfig: normalizeGoogleToolChoice(options.toolChoice) }
1233
+ : {}),
1234
+ ...(buildGoogleGenerationConfig(options)
1235
+ ? { generationConfig: buildGoogleGenerationConfig(options) }
1236
+ : {}),
1237
+ };
1238
+
1239
+ Object.assign(body, readProviderOptions(options.providerOptions, "google", providerName));
1240
+ return body;
1241
+ }
1242
+
1243
+ function extractFirstGoogleCandidate(payload: unknown): Record<string, unknown> | undefined {
1244
+ const record = readRecord(payload);
1245
+ const candidates = record?.candidates;
1246
+ if (!Array.isArray(candidates) || candidates.length === 0) {
1247
+ return undefined;
1248
+ }
1249
+
1250
+ return readRecord(candidates[0]);
1251
+ }
1252
+
1253
+ function extractGoogleCandidateParts(payload: unknown): Array<Record<string, unknown>> {
1254
+ const candidate = extractFirstGoogleCandidate(payload);
1255
+ const content = readRecord(candidate?.content);
1256
+ const parts = content?.parts;
1257
+ if (!Array.isArray(parts)) {
1258
+ return [];
1259
+ }
1260
+
1261
+ return parts.flatMap((part) => {
1262
+ const record = readRecord(part);
1263
+ return record ? [record] : [];
1264
+ });
1265
+ }
1266
+
1267
+ function buildGoogleGenerateResult(payload: unknown): {
1268
+ content: Array<
1269
+ | { type: "text"; text: string }
1270
+ | { type: "tool-call"; toolCallId: string; toolName: string; input: string }
1271
+ >;
1272
+ finishReason?: string | { unified: string; raw: string } | null;
1273
+ usage?: { inputTokens?: number; outputTokens?: number; totalTokens?: number };
1274
+ } {
1275
+ const parts = extractGoogleCandidateParts(payload);
1276
+ const content: Array<
1277
+ | { type: "text"; text: string }
1278
+ | { type: "tool-call"; toolCallId: string; toolName: string; input: string }
1279
+ > = [];
1280
+
1281
+ for (const [index, part] of parts.entries()) {
1282
+ if (typeof part.text === "string" && part.text.length > 0) {
1283
+ content.push({ type: "text", text: part.text });
1284
+ continue;
1285
+ }
1286
+
1287
+ const functionCall = readRecord(part.functionCall);
1288
+ if (typeof functionCall?.name === "string") {
1289
+ content.push({
1290
+ type: "tool-call",
1291
+ toolCallId: typeof functionCall.id === "string" ? functionCall.id : `tool-${index}`,
1292
+ toolName: functionCall.name,
1293
+ input: stringifyJsonValue(functionCall.args ?? {}),
1294
+ });
1295
+ }
1296
+ }
1297
+
1298
+ return {
1299
+ content,
1300
+ finishReason: normalizeGoogleFinishReason(extractFirstGoogleCandidate(payload)?.finishReason),
1301
+ usage: extractGoogleUsage(payload),
1302
+ };
1303
+ }
1304
+
1305
+ async function* streamGoogleCompatibleParts(
1306
+ stream: ReadableStream<Uint8Array>,
1307
+ ): AsyncIterable<unknown> {
1308
+ const decoder = new TextDecoder();
1309
+ let buffer = "";
1310
+ const seenToolCalls = new Set<string>();
1311
+ let finishReason: string | { unified: string; raw: string } | null = null;
1312
+ let usage: { inputTokens?: number; outputTokens?: number; totalTokens?: number } | undefined;
1313
+
1314
+ for await (const chunk of stream) {
1315
+ buffer += decoder.decode(chunk, { stream: true });
1316
+ const parsed = parseOpenAISseChunk(buffer);
1317
+ buffer = parsed.remainder;
1318
+
1319
+ for (const event of parsed.events) {
1320
+ if (event === "[DONE]") {
1321
+ continue;
1322
+ }
1323
+
1324
+ usage = extractGoogleUsage(event) ?? usage;
1325
+ const candidate = extractFirstGoogleCandidate(event);
1326
+ const normalizedFinishReason = normalizeGoogleFinishReason(candidate?.finishReason);
1327
+ if (normalizedFinishReason) {
1328
+ finishReason = normalizedFinishReason;
1329
+ }
1330
+
1331
+ for (const [index, part] of extractGoogleCandidateParts(event).entries()) {
1332
+ if (typeof part.text === "string" && part.text.length > 0) {
1333
+ yield { type: "text-delta", delta: part.text };
1334
+ continue;
1335
+ }
1336
+
1337
+ const functionCall = readRecord(part.functionCall);
1338
+ if (typeof functionCall?.name !== "string") {
1339
+ continue;
1340
+ }
1341
+
1342
+ const toolCallId = typeof functionCall.id === "string" ? functionCall.id : `tool-${index}`;
1343
+ if (seenToolCalls.has(toolCallId)) {
1344
+ continue;
1345
+ }
1346
+
1347
+ const serializedInput = stringifyJsonValue(functionCall.args ?? {});
1348
+ seenToolCalls.add(toolCallId);
1349
+ yield {
1350
+ type: "tool-input-start",
1351
+ id: toolCallId,
1352
+ toolName: functionCall.name,
1353
+ };
1354
+ yield {
1355
+ type: "tool-input-delta",
1356
+ id: toolCallId,
1357
+ delta: serializedInput,
1358
+ };
1359
+ yield {
1360
+ type: "tool-call",
1361
+ toolCallId,
1362
+ toolName: functionCall.name,
1363
+ input: serializedInput,
1364
+ };
1365
+ }
1366
+ }
1367
+ }
1368
+
1369
+ if (buffer.trim().length > 0) {
1370
+ const parsed = parseOpenAISseChunk(`${buffer}\n\n`);
1371
+ for (const event of parsed.events) {
1372
+ if (event === "[DONE]") {
1373
+ continue;
1374
+ }
1375
+ usage = extractGoogleUsage(event) ?? usage;
1376
+ }
1377
+ }
1378
+
1379
+ yield {
1380
+ type: "finish",
1381
+ finishReason,
1382
+ ...(usage ? { usage } : {}),
1383
+ };
1384
+ }
1385
+
1386
+ function extractFirstChoice(payload: unknown): OpenAICompatibleChoice | undefined {
1387
+ const record = readRecord(payload);
1388
+ const choices = record?.choices;
1389
+ if (!Array.isArray(choices) || choices.length === 0) {
1390
+ return undefined;
1391
+ }
1392
+
1393
+ const first = readRecord(choices[0]);
1394
+ if (!first) {
1395
+ return undefined;
1396
+ }
1397
+
1398
+ return first;
1399
+ }
1400
+
1401
+ function buildOpenAIGenerateResult(payload: unknown): {
1402
+ content: Array<
1403
+ { type: "text"; text: string } | {
1404
+ type: "tool-call";
1405
+ toolCallId: string;
1406
+ toolName: string;
1407
+ input: string;
1408
+ }
1409
+ >;
1410
+ finishReason?: string | { unified: string; raw: string } | null;
1411
+ usage?: { inputTokens?: number; outputTokens?: number; totalTokens?: number };
1412
+ } {
1413
+ const choice = extractFirstChoice(payload);
1414
+ const message = readRecord(choice?.message);
1415
+ const text = extractOpenAIContentText(message?.content);
1416
+ const toolCalls = message ? extractOpenAIToolCalls(message) : [];
1417
+
1418
+ return {
1419
+ content: [
1420
+ ...(text.length > 0 ? [{ type: "text" as const, text }] : []),
1421
+ ...toolCalls.map((toolCall) => ({
1422
+ type: "tool-call" as const,
1423
+ toolCallId: toolCall.toolCallId,
1424
+ toolName: toolCall.toolName,
1425
+ input: toolCall.input,
1426
+ })),
1427
+ ],
1428
+ finishReason: normalizeOpenAIFinishReason(choice?.finish_reason),
1429
+ usage: extractOpenAIUsage(payload),
1430
+ };
1431
+ }
1432
+
1433
+ function parseOpenAISseChunk(chunk: string): {
1434
+ events: Array<unknown | "[DONE]">;
1435
+ remainder: string;
1436
+ } {
1437
+ const blocks = chunk.split("\n\n");
1438
+ const remainder = blocks.pop() ?? "";
1439
+ const events = blocks.flatMap((block) => {
1440
+ const dataLines = block.split("\n")
1441
+ .filter((line) => line.startsWith("data:"))
1442
+ .map((line) => line.slice(5).trimStart());
1443
+
1444
+ if (!dataLines.length) {
1445
+ return [];
1446
+ }
1447
+
1448
+ const payload = dataLines.join("\n").trim();
1449
+ if (payload === "[DONE]") {
1450
+ return ["[DONE]" as const];
1451
+ }
1452
+
1453
+ try {
1454
+ return [JSON.parse(payload) as unknown];
1455
+ } catch {
1456
+ return [];
1457
+ }
1458
+ });
1459
+
1460
+ return { events, remainder };
1461
+ }
1462
+
1463
+ async function* streamOpenAICompatibleParts(
1464
+ stream: ReadableStream<Uint8Array>,
1465
+ ): AsyncIterable<unknown> {
1466
+ const decoder = new TextDecoder();
1467
+ let buffer = "";
1468
+ const toolCalls = new Map<number, OpenAIStreamToolCallState>();
1469
+ let finishReason: string | { unified: string; raw: string } | null = null;
1470
+ let usage: { inputTokens?: number; outputTokens?: number; totalTokens?: number } | undefined;
1471
+
1472
+ for await (const chunk of stream) {
1473
+ buffer += decoder.decode(chunk, { stream: true });
1474
+ const parsed = parseOpenAISseChunk(buffer);
1475
+ buffer = parsed.remainder;
1476
+
1477
+ for (const event of parsed.events) {
1478
+ if (event === "[DONE]") {
1479
+ continue;
1480
+ }
1481
+
1482
+ const record = readRecord(event);
1483
+ usage = extractOpenAIUsage(record) ?? usage;
1484
+ const choices = Array.isArray(record?.choices) ? record.choices : [];
1485
+
1486
+ for (const choiceValue of choices) {
1487
+ const choice = readRecord(choiceValue);
1488
+ if (!choice) {
1489
+ continue;
1490
+ }
1491
+
1492
+ const delta = readRecord(choice.delta);
1493
+ const textDelta = extractOpenAIContentText(delta?.content);
1494
+ if (textDelta.length > 0) {
1495
+ yield { type: "text-delta", delta: textDelta };
1496
+ }
1497
+
1498
+ const rawToolCalls = Array.isArray(delta?.tool_calls) ? delta.tool_calls : [];
1499
+ for (const rawToolCall of rawToolCalls) {
1500
+ const toolCallRecord = readRecord(rawToolCall);
1501
+ const index = typeof toolCallRecord?.index === "number" ? toolCallRecord.index : 0;
1502
+ const current = toolCalls.get(index) ?? {
1503
+ id: typeof toolCallRecord?.id === "string" ? toolCallRecord.id : `tool-${index}`,
1504
+ name: "",
1505
+ arguments: "",
1506
+ started: false,
1507
+ };
1508
+
1509
+ if (typeof toolCallRecord?.id === "string") {
1510
+ current.id = toolCallRecord.id;
1511
+ }
1512
+
1513
+ const fn = readRecord(toolCallRecord?.function);
1514
+ if (typeof fn?.name === "string") {
1515
+ current.name = fn.name;
1516
+ }
1517
+
1518
+ if (!current.started && current.name.length > 0) {
1519
+ current.started = true;
1520
+ yield {
1521
+ type: "tool-input-start",
1522
+ id: current.id,
1523
+ toolName: current.name,
1524
+ };
1525
+ }
1526
+
1527
+ if (typeof fn?.arguments === "string" && fn.arguments.length > 0) {
1528
+ current.arguments += fn.arguments;
1529
+ yield {
1530
+ type: "tool-input-delta",
1531
+ id: current.id,
1532
+ delta: fn.arguments,
1533
+ };
1534
+ }
1535
+
1536
+ toolCalls.set(index, current);
1537
+ }
1538
+
1539
+ const normalizedFinishReason = normalizeOpenAIFinishReason(choice.finish_reason);
1540
+ if (normalizedFinishReason) {
1541
+ finishReason = normalizedFinishReason;
1542
+ }
1543
+ }
1544
+ }
1545
+ }
1546
+
1547
+ if (buffer.trim().length > 0) {
1548
+ const parsed = parseOpenAISseChunk(`${buffer}\n\n`);
1549
+ for (const event of parsed.events) {
1550
+ if (event === "[DONE]") {
1551
+ continue;
1552
+ }
1553
+
1554
+ const record = readRecord(event);
1555
+ usage = extractOpenAIUsage(record) ?? usage;
1556
+ }
1557
+ }
1558
+
1559
+ if (
1560
+ finishReason &&
1561
+ typeof finishReason === "object" &&
1562
+ finishReason.unified === "tool-calls"
1563
+ ) {
1564
+ for (const toolCall of toolCalls.values()) {
1565
+ yield {
1566
+ type: "tool-call",
1567
+ toolCallId: toolCall.id,
1568
+ toolName: toolCall.name,
1569
+ input: toolCall.arguments,
1570
+ };
1571
+ }
1572
+ }
1573
+
1574
+ yield {
1575
+ type: "finish",
1576
+ finishReason,
1577
+ ...(usage ? { usage } : {}),
1578
+ };
1579
+ }
1580
+
1581
+ export function createOpenAIModelRuntime(
1582
+ config: OpenAIRuntimeConfig,
1583
+ modelId: string,
1584
+ ): ModelRuntime {
1585
+ const fetchImpl = config.fetch ?? dntShim.dntGlobalThis.fetch;
1586
+ return {
1587
+ provider: config.name ?? "openai",
1588
+ modelId,
1589
+ specificationVersion: "v3",
1590
+ supportedUrls: {},
1591
+ doGenerate(optionsForRuntime: unknown) {
1592
+ const options = optionsForRuntime as OpenAICompatibleLanguageOptions;
1593
+ const url = getOpenAIChatCompletionsUrl(config.baseURL);
1594
+ const body = buildOpenAIChatRequest(modelId, config.name ?? "openai", options, false);
1595
+ return requestJson({
1596
+ url,
1597
+ fetchImpl,
1598
+ providerLabel: config.name ?? "openai",
1599
+ init: {
1600
+ method: "POST",
1601
+ headers: createRequestHeaders({
1602
+ apiKeyHeaderName: "authorization",
1603
+ apiKey: `Bearer ${config.apiKey}`,
1604
+ extraHeaders: options.headers,
1605
+ }),
1606
+ body: JSON.stringify(body),
1607
+ signal: options.abortSignal,
1608
+ },
1609
+ }).then(buildOpenAIGenerateResult);
1610
+ },
1611
+ doStream(optionsForRuntime: unknown) {
1612
+ const options = optionsForRuntime as OpenAICompatibleLanguageOptions;
1613
+ const url = getOpenAIChatCompletionsUrl(config.baseURL);
1614
+ const body = buildOpenAIChatRequest(modelId, config.name ?? "openai", options, true);
1615
+ return requestStream({
1616
+ url,
1617
+ fetchImpl,
1618
+ providerLabel: config.name ?? "openai",
1619
+ init: {
1620
+ method: "POST",
1621
+ headers: createRequestHeaders({
1622
+ apiKeyHeaderName: "authorization",
1623
+ apiKey: `Bearer ${config.apiKey}`,
1624
+ extraHeaders: options.headers,
1625
+ }),
1626
+ body: JSON.stringify(body),
1627
+ signal: options.abortSignal,
1628
+ },
1629
+ }).then((responseStream) => ({
1630
+ stream: ReadableStream.from(streamOpenAICompatibleParts(responseStream)),
1631
+ }));
1632
+ },
1633
+ };
1634
+ }
1635
+
1636
+ export function createAnthropicModelRuntime(
1637
+ config: AnthropicRuntimeConfig,
1638
+ modelId: string,
1639
+ ): ModelRuntime {
1640
+ const fetchImpl = config.fetch ?? dntShim.dntGlobalThis.fetch;
1641
+ return {
1642
+ provider: config.name ?? "anthropic",
1643
+ modelId,
1644
+ specificationVersion: "v3",
1645
+ supportedUrls: {},
1646
+ doGenerate(optionsForRuntime: unknown) {
1647
+ const options = optionsForRuntime as OpenAICompatibleLanguageOptions;
1648
+ const url = getAnthropicMessagesUrl(config.baseURL);
1649
+ const body = buildAnthropicMessagesRequest(
1650
+ modelId,
1651
+ config.name ?? "anthropic",
1652
+ options,
1653
+ false,
1654
+ );
1655
+ return requestJson({
1656
+ url,
1657
+ fetchImpl,
1658
+ providerLabel: config.name ?? "anthropic",
1659
+ init: {
1660
+ method: "POST",
1661
+ headers: createAnthropicRequestHeaders({
1662
+ apiKey: config.apiKey,
1663
+ authToken: config.authToken,
1664
+ extraHeaders: options.headers,
1665
+ }),
1666
+ body: JSON.stringify(body),
1667
+ signal: options.abortSignal,
1668
+ },
1669
+ }).then(buildAnthropicGenerateResult);
1670
+ },
1671
+ doStream(optionsForRuntime: unknown) {
1672
+ const options = optionsForRuntime as OpenAICompatibleLanguageOptions;
1673
+ const url = getAnthropicMessagesUrl(config.baseURL);
1674
+ const body = buildAnthropicMessagesRequest(
1675
+ modelId,
1676
+ config.name ?? "anthropic",
1677
+ options,
1678
+ true,
1679
+ );
1680
+ return requestStream({
1681
+ url,
1682
+ fetchImpl,
1683
+ providerLabel: config.name ?? "anthropic",
1684
+ init: {
1685
+ method: "POST",
1686
+ headers: createAnthropicRequestHeaders({
1687
+ apiKey: config.apiKey,
1688
+ authToken: config.authToken,
1689
+ extraHeaders: options.headers,
1690
+ }),
1691
+ body: JSON.stringify(body),
1692
+ signal: options.abortSignal,
1693
+ },
1694
+ }).then((responseStream) => ({
1695
+ stream: ReadableStream.from(streamAnthropicCompatibleParts(responseStream)),
1696
+ }));
1697
+ },
1698
+ };
1699
+ }
1700
+
1701
+ export function createGoogleModelRuntime(
1702
+ config: GoogleRuntimeConfig,
1703
+ modelId: string,
1704
+ ): ModelRuntime {
1705
+ const fetchImpl = config.fetch ?? dntShim.dntGlobalThis.fetch;
1706
+ return {
1707
+ provider: config.name ?? "google",
1708
+ modelId,
1709
+ specificationVersion: "v3",
1710
+ supportedUrls: {},
1711
+ doGenerate(optionsForRuntime: unknown) {
1712
+ const options = optionsForRuntime as OpenAICompatibleLanguageOptions;
1713
+ const url = getGoogleGenerateContentUrl(config.baseURL, modelId);
1714
+ const body = buildGoogleGenerateContentRequest(config.name ?? "google", options);
1715
+ return requestJson({
1716
+ url,
1717
+ fetchImpl,
1718
+ providerLabel: config.name ?? "google",
1719
+ init: {
1720
+ method: "POST",
1721
+ headers: createRequestHeaders({
1722
+ apiKeyHeaderName: "x-goog-api-key",
1723
+ apiKey: config.apiKey,
1724
+ extraHeaders: options.headers,
1725
+ }),
1726
+ body: JSON.stringify(body),
1727
+ signal: options.abortSignal,
1728
+ },
1729
+ }).then(buildGoogleGenerateResult);
1730
+ },
1731
+ doStream(optionsForRuntime: unknown) {
1732
+ const options = optionsForRuntime as OpenAICompatibleLanguageOptions;
1733
+ const url = getGoogleStreamGenerateContentUrl(config.baseURL, modelId);
1734
+ const body = buildGoogleGenerateContentRequest(config.name ?? "google", options);
1735
+ return requestStream({
1736
+ url,
1737
+ fetchImpl,
1738
+ providerLabel: config.name ?? "google",
1739
+ init: {
1740
+ method: "POST",
1741
+ headers: createRequestHeaders({
1742
+ apiKeyHeaderName: "x-goog-api-key",
1743
+ apiKey: config.apiKey,
1744
+ extraHeaders: options.headers,
1745
+ }),
1746
+ body: JSON.stringify(body),
1747
+ signal: options.abortSignal,
1748
+ },
1749
+ }).then((responseStream) => ({
1750
+ stream: ReadableStream.from(streamGoogleCompatibleParts(responseStream)),
1751
+ }));
1752
+ },
1753
+ };
1754
+ }
1755
+
1756
+ export function createOpenAIEmbeddingRuntime(
1757
+ config: OpenAIRuntimeConfig,
1758
+ modelId: string,
1759
+ ): EmbeddingRuntime {
1760
+ const fetchImpl = config.fetch ?? dntShim.dntGlobalThis.fetch;
1761
+ return {
1762
+ provider: config.name ?? "openai",
1763
+ modelId,
1764
+ supportsParallelCalls: true,
1765
+ doEmbed({ values, abortSignal }) {
1766
+ if (values.length === 0) {
1767
+ return Promise.resolve({
1768
+ embeddings: [],
1769
+ warnings: [],
1770
+ rawResponse: { data: [] },
1771
+ });
1772
+ }
1773
+
1774
+ const url = getOpenAIEmbeddingUrl(config.baseURL);
1775
+ return requestJson({
1776
+ url,
1777
+ fetchImpl,
1778
+ providerLabel: config.name ?? "openai",
1779
+ init: {
1780
+ method: "POST",
1781
+ headers: {
1782
+ "content-type": "application/json",
1783
+ authorization: `Bearer ${config.apiKey}`,
1784
+ },
1785
+ body: JSON.stringify({
1786
+ model: modelId,
1787
+ input: values,
1788
+ }),
1789
+ signal: abortSignal,
1790
+ },
1791
+ }).then((payload) => ({
1792
+ embeddings: extractOpenAIEmbeddings(payload),
1793
+ usage: {
1794
+ tokens: extractOpenAIUsageTokens(payload),
1795
+ },
1796
+ rawResponse: payload,
1797
+ warnings: [],
1798
+ }));
1799
+ },
1800
+ };
1801
+ }
1802
+
1803
+ export function createGoogleEmbeddingRuntime(
1804
+ config: GoogleRuntimeConfig,
1805
+ modelId: string,
1806
+ ): EmbeddingRuntime {
1807
+ const fetchImpl = config.fetch ?? dntShim.dntGlobalThis.fetch;
1808
+ return {
1809
+ provider: config.name ?? "google",
1810
+ modelId,
1811
+ supportsParallelCalls: true,
1812
+ doEmbed({ values, abortSignal }) {
1813
+ if (values.length === 0) {
1814
+ return Promise.resolve({
1815
+ embeddings: [],
1816
+ warnings: [],
1817
+ rawResponse: { embeddings: [] },
1818
+ });
1819
+ }
1820
+
1821
+ const url = getGoogleEmbeddingUrl(config.baseURL, modelId);
1822
+ return Promise.all(values.map((value) =>
1823
+ requestJson({
1824
+ url,
1825
+ fetchImpl,
1826
+ providerLabel: config.name ?? "google",
1827
+ init: {
1828
+ method: "POST",
1829
+ headers: {
1830
+ "content-type": "application/json",
1831
+ "x-goog-api-key": config.apiKey,
1832
+ },
1833
+ body: JSON.stringify({
1834
+ content: {
1835
+ parts: [{ text: value }],
1836
+ },
1837
+ }),
1838
+ signal: abortSignal,
1839
+ },
1840
+ })
1841
+ )).then((payloads) => ({
1842
+ embeddings: payloads.map(extractGoogleEmbedding),
1843
+ usage: {
1844
+ tokens: payloads.reduce<number>(
1845
+ (total, payload) => total + (extractGoogleUsageTokens(payload) ?? 0),
1846
+ 0,
1847
+ ),
1848
+ },
1849
+ rawResponse: payloads,
1850
+ warnings: [],
1851
+ }));
1852
+ },
1853
+ };
1854
+ }