@strands-agents/sdk 0.0.1

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 (423) hide show
  1. package/LICENSE +175 -0
  2. package/README.md +185 -0
  3. package/dist/__fixtures__/model-test-helpers.d.ts +56 -0
  4. package/dist/__fixtures__/model-test-helpers.d.ts.map +1 -0
  5. package/dist/__fixtures__/model-test-helpers.js +85 -0
  6. package/dist/__fixtures__/model-test-helpers.js.map +1 -0
  7. package/dist/__fixtures__/tool-helpers.d.ts +15 -0
  8. package/dist/__fixtures__/tool-helpers.d.ts.map +1 -0
  9. package/dist/__fixtures__/tool-helpers.js +22 -0
  10. package/dist/__fixtures__/tool-helpers.js.map +1 -0
  11. package/dist/__tests__/errors.test.d.ts +2 -0
  12. package/dist/__tests__/errors.test.d.ts.map +1 -0
  13. package/dist/__tests__/errors.test.js +20 -0
  14. package/dist/__tests__/errors.test.js.map +1 -0
  15. package/dist/__tests__/index.test.d.ts +2 -0
  16. package/dist/__tests__/index.test.d.ts.map +1 -0
  17. package/dist/__tests__/index.test.js +27 -0
  18. package/dist/__tests__/index.test.js.map +1 -0
  19. package/dist/errors.d.ts +22 -0
  20. package/dist/errors.d.ts.map +1 -0
  21. package/dist/errors.js +25 -0
  22. package/dist/errors.js.map +1 -0
  23. package/dist/index.d.ts +19 -0
  24. package/dist/index.d.ts.map +1 -0
  25. package/dist/index.js +17 -0
  26. package/dist/index.js.map +1 -0
  27. package/dist/models/__tests__/bedrock.test.d.ts +2 -0
  28. package/dist/models/__tests__/bedrock.test.d.ts.map +1 -0
  29. package/dist/models/__tests__/bedrock.test.js +1161 -0
  30. package/dist/models/__tests__/bedrock.test.js.map +1 -0
  31. package/dist/models/__tests__/model.test.d.ts +2 -0
  32. package/dist/models/__tests__/model.test.d.ts.map +1 -0
  33. package/dist/models/__tests__/model.test.js +297 -0
  34. package/dist/models/__tests__/model.test.js.map +1 -0
  35. package/dist/models/__tests__/openai.test.d.ts +2 -0
  36. package/dist/models/__tests__/openai.test.d.ts.map +1 -0
  37. package/dist/models/__tests__/openai.test.js +1016 -0
  38. package/dist/models/__tests__/openai.test.js.map +1 -0
  39. package/dist/models/__tests__/test-utils.d.ts +10 -0
  40. package/dist/models/__tests__/test-utils.d.ts.map +1 -0
  41. package/dist/models/__tests__/test-utils.js +17 -0
  42. package/dist/models/__tests__/test-utils.js.map +1 -0
  43. package/dist/models/bedrock.d.ts +272 -0
  44. package/dist/models/bedrock.d.ts.map +1 -0
  45. package/dist/models/bedrock.js +679 -0
  46. package/dist/models/bedrock.js.map +1 -0
  47. package/dist/models/model.d.ts +89 -0
  48. package/dist/models/model.d.ts.map +1 -0
  49. package/dist/models/model.js +122 -0
  50. package/dist/models/model.js.map +1 -0
  51. package/dist/models/openai.d.ts +262 -0
  52. package/dist/models/openai.d.ts.map +1 -0
  53. package/dist/models/openai.js +625 -0
  54. package/dist/models/openai.js.map +1 -0
  55. package/dist/models/streaming.d.ts +226 -0
  56. package/dist/models/streaming.d.ts.map +1 -0
  57. package/dist/models/streaming.js +2 -0
  58. package/dist/models/streaming.js.map +1 -0
  59. package/dist/src/__fixtures__/agent-helpers.d.ts +29 -0
  60. package/dist/src/__fixtures__/agent-helpers.d.ts.map +1 -0
  61. package/dist/src/__fixtures__/agent-helpers.js +19 -0
  62. package/dist/src/__fixtures__/agent-helpers.js.map +1 -0
  63. package/dist/src/__fixtures__/environment.d.ts +12 -0
  64. package/dist/src/__fixtures__/environment.d.ts.map +1 -0
  65. package/dist/src/__fixtures__/environment.js +12 -0
  66. package/dist/src/__fixtures__/environment.js.map +1 -0
  67. package/dist/src/__fixtures__/mock-hook-provider.d.ts +14 -0
  68. package/dist/src/__fixtures__/mock-hook-provider.d.ts.map +1 -0
  69. package/dist/src/__fixtures__/mock-hook-provider.js +33 -0
  70. package/dist/src/__fixtures__/mock-hook-provider.js.map +1 -0
  71. package/dist/src/__fixtures__/mock-message-model.d.ts +93 -0
  72. package/dist/src/__fixtures__/mock-message-model.d.ts.map +1 -0
  73. package/dist/src/__fixtures__/mock-message-model.js +226 -0
  74. package/dist/src/__fixtures__/mock-message-model.js.map +1 -0
  75. package/dist/src/__fixtures__/model-test-helpers.d.ts +56 -0
  76. package/dist/src/__fixtures__/model-test-helpers.d.ts.map +1 -0
  77. package/dist/src/__fixtures__/model-test-helpers.js +85 -0
  78. package/dist/src/__fixtures__/model-test-helpers.js.map +1 -0
  79. package/dist/src/__fixtures__/tool-helpers.d.ts +37 -0
  80. package/dist/src/__fixtures__/tool-helpers.d.ts.map +1 -0
  81. package/dist/src/__fixtures__/tool-helpers.js +78 -0
  82. package/dist/src/__fixtures__/tool-helpers.js.map +1 -0
  83. package/dist/src/__tests__/errors.test.d.ts +2 -0
  84. package/dist/src/__tests__/errors.test.d.ts.map +1 -0
  85. package/dist/src/__tests__/errors.test.js +64 -0
  86. package/dist/src/__tests__/errors.test.js.map +1 -0
  87. package/dist/src/__tests__/index.test.d.ts +2 -0
  88. package/dist/src/__tests__/index.test.d.ts.map +1 -0
  89. package/dist/src/__tests__/index.test.js +27 -0
  90. package/dist/src/__tests__/index.test.js.map +1 -0
  91. package/dist/src/__tests__/mcp.test.d.ts +2 -0
  92. package/dist/src/__tests__/mcp.test.d.ts.map +1 -0
  93. package/dist/src/__tests__/mcp.test.js +166 -0
  94. package/dist/src/__tests__/mcp.test.js.map +1 -0
  95. package/dist/src/agent/__tests__/agent.hook.test.d.ts +2 -0
  96. package/dist/src/agent/__tests__/agent.hook.test.d.ts.map +1 -0
  97. package/dist/src/agent/__tests__/agent.hook.test.js +250 -0
  98. package/dist/src/agent/__tests__/agent.hook.test.js.map +1 -0
  99. package/dist/src/agent/__tests__/agent.test.d.ts +2 -0
  100. package/dist/src/agent/__tests__/agent.test.d.ts.map +1 -0
  101. package/dist/src/agent/__tests__/agent.test.js +414 -0
  102. package/dist/src/agent/__tests__/agent.test.js.map +1 -0
  103. package/dist/src/agent/__tests__/printer.test.d.ts +2 -0
  104. package/dist/src/agent/__tests__/printer.test.d.ts.map +1 -0
  105. package/dist/src/agent/__tests__/printer.test.js +152 -0
  106. package/dist/src/agent/__tests__/printer.test.js.map +1 -0
  107. package/dist/src/agent/__tests__/state.test.d.ts +2 -0
  108. package/dist/src/agent/__tests__/state.test.d.ts.map +1 -0
  109. package/dist/src/agent/__tests__/state.test.js +231 -0
  110. package/dist/src/agent/__tests__/state.test.js.map +1 -0
  111. package/dist/src/agent/agent.d.ts +207 -0
  112. package/dist/src/agent/agent.d.ts.map +1 -0
  113. package/dist/src/agent/agent.js +481 -0
  114. package/dist/src/agent/agent.js.map +1 -0
  115. package/dist/src/agent/printer.d.ts +73 -0
  116. package/dist/src/agent/printer.d.ts.map +1 -0
  117. package/dist/src/agent/printer.js +145 -0
  118. package/dist/src/agent/printer.js.map +1 -0
  119. package/dist/src/agent/state.d.ts +102 -0
  120. package/dist/src/agent/state.d.ts.map +1 -0
  121. package/dist/src/agent/state.js +73 -0
  122. package/dist/src/agent/state.js.map +1 -0
  123. package/dist/src/agent/streaming.d.ts +91 -0
  124. package/dist/src/agent/streaming.d.ts.map +1 -0
  125. package/dist/src/agent/streaming.js +2 -0
  126. package/dist/src/agent/streaming.js.map +1 -0
  127. package/dist/src/conversation-manager/__tests__/conversation-manager.test.d.ts +2 -0
  128. package/dist/src/conversation-manager/__tests__/conversation-manager.test.d.ts.map +1 -0
  129. package/dist/src/conversation-manager/__tests__/conversation-manager.test.js +10 -0
  130. package/dist/src/conversation-manager/__tests__/conversation-manager.test.js.map +1 -0
  131. package/dist/src/conversation-manager/__tests__/null-conversation-manager.test.d.ts +2 -0
  132. package/dist/src/conversation-manager/__tests__/null-conversation-manager.test.d.ts.map +1 -0
  133. package/dist/src/conversation-manager/__tests__/null-conversation-manager.test.js +35 -0
  134. package/dist/src/conversation-manager/__tests__/null-conversation-manager.test.js.map +1 -0
  135. package/dist/src/conversation-manager/__tests__/sliding-window-conversation-manager.test.d.ts +2 -0
  136. package/dist/src/conversation-manager/__tests__/sliding-window-conversation-manager.test.d.ts.map +1 -0
  137. package/dist/src/conversation-manager/__tests__/sliding-window-conversation-manager.test.js +553 -0
  138. package/dist/src/conversation-manager/__tests__/sliding-window-conversation-manager.test.js.map +1 -0
  139. package/dist/src/conversation-manager/conversation-manager.d.ts +73 -0
  140. package/dist/src/conversation-manager/conversation-manager.d.ts.map +1 -0
  141. package/dist/src/conversation-manager/conversation-manager.js +24 -0
  142. package/dist/src/conversation-manager/conversation-manager.js.map +1 -0
  143. package/dist/src/conversation-manager/index.d.ts +8 -0
  144. package/dist/src/conversation-manager/index.d.ts.map +1 -0
  145. package/dist/src/conversation-manager/index.js +8 -0
  146. package/dist/src/conversation-manager/index.js.map +1 -0
  147. package/dist/src/conversation-manager/null-conversation-manager.d.ts +23 -0
  148. package/dist/src/conversation-manager/null-conversation-manager.d.ts.map +1 -0
  149. package/dist/src/conversation-manager/null-conversation-manager.js +23 -0
  150. package/dist/src/conversation-manager/null-conversation-manager.js.map +1 -0
  151. package/dist/src/conversation-manager/sliding-window-conversation-manager.d.ts +105 -0
  152. package/dist/src/conversation-manager/sliding-window-conversation-manager.d.ts.map +1 -0
  153. package/dist/src/conversation-manager/sliding-window-conversation-manager.js +212 -0
  154. package/dist/src/conversation-manager/sliding-window-conversation-manager.js.map +1 -0
  155. package/dist/src/errors.d.ts +83 -0
  156. package/dist/src/errors.d.ts.map +1 -0
  157. package/dist/src/errors.js +97 -0
  158. package/dist/src/errors.js.map +1 -0
  159. package/dist/src/hooks/__tests__/events.test.d.ts +2 -0
  160. package/dist/src/hooks/__tests__/events.test.d.ts.map +1 -0
  161. package/dist/src/hooks/__tests__/events.test.js +347 -0
  162. package/dist/src/hooks/__tests__/events.test.js.map +1 -0
  163. package/dist/src/hooks/__tests__/registry.test.d.ts +2 -0
  164. package/dist/src/hooks/__tests__/registry.test.d.ts.map +1 -0
  165. package/dist/src/hooks/__tests__/registry.test.js +154 -0
  166. package/dist/src/hooks/__tests__/registry.test.js.map +1 -0
  167. package/dist/src/hooks/events.d.ts +199 -0
  168. package/dist/src/hooks/events.d.ts.map +1 -0
  169. package/dist/src/hooks/events.js +191 -0
  170. package/dist/src/hooks/events.js.map +1 -0
  171. package/dist/src/hooks/index.d.ts +11 -0
  172. package/dist/src/hooks/index.d.ts.map +1 -0
  173. package/dist/src/hooks/index.js +11 -0
  174. package/dist/src/hooks/index.js.map +1 -0
  175. package/dist/src/hooks/registry.d.ts +65 -0
  176. package/dist/src/hooks/registry.d.ts.map +1 -0
  177. package/dist/src/hooks/registry.js +65 -0
  178. package/dist/src/hooks/registry.js.map +1 -0
  179. package/dist/src/hooks/types.d.ts +49 -0
  180. package/dist/src/hooks/types.d.ts.map +1 -0
  181. package/dist/src/hooks/types.js +2 -0
  182. package/dist/src/hooks/types.js.map +1 -0
  183. package/dist/src/index.d.ts +32 -0
  184. package/dist/src/index.d.ts.map +1 -0
  185. package/dist/src/index.js +29 -0
  186. package/dist/src/index.js.map +1 -0
  187. package/dist/src/mcp.d.ts +51 -0
  188. package/dist/src/mcp.d.ts.map +1 -0
  189. package/dist/src/mcp.js +91 -0
  190. package/dist/src/mcp.js.map +1 -0
  191. package/dist/src/models/__tests__/bedrock.test.d.ts +2 -0
  192. package/dist/src/models/__tests__/bedrock.test.d.ts.map +1 -0
  193. package/dist/src/models/__tests__/bedrock.test.js +1388 -0
  194. package/dist/src/models/__tests__/bedrock.test.js.map +1 -0
  195. package/dist/src/models/__tests__/model.test.d.ts +2 -0
  196. package/dist/src/models/__tests__/model.test.d.ts.map +1 -0
  197. package/dist/src/models/__tests__/model.test.js +342 -0
  198. package/dist/src/models/__tests__/model.test.js.map +1 -0
  199. package/dist/src/models/__tests__/openai.test.d.ts +2 -0
  200. package/dist/src/models/__tests__/openai.test.d.ts.map +1 -0
  201. package/dist/src/models/__tests__/openai.test.js +1189 -0
  202. package/dist/src/models/__tests__/openai.test.js.map +1 -0
  203. package/dist/src/models/__tests__/test-utils.d.ts +10 -0
  204. package/dist/src/models/__tests__/test-utils.d.ts.map +1 -0
  205. package/dist/src/models/__tests__/test-utils.js +17 -0
  206. package/dist/src/models/__tests__/test-utils.js.map +1 -0
  207. package/dist/src/models/bedrock.d.ts +289 -0
  208. package/dist/src/models/bedrock.d.ts.map +1 -0
  209. package/dist/src/models/bedrock.js +804 -0
  210. package/dist/src/models/bedrock.js.map +1 -0
  211. package/dist/src/models/model.d.ts +99 -0
  212. package/dist/src/models/model.d.ts.map +1 -0
  213. package/dist/src/models/model.js +169 -0
  214. package/dist/src/models/model.js.map +1 -0
  215. package/dist/src/models/openai.d.ts +262 -0
  216. package/dist/src/models/openai.d.ts.map +1 -0
  217. package/dist/src/models/openai.js +752 -0
  218. package/dist/src/models/openai.js.map +1 -0
  219. package/dist/src/models/streaming.d.ts +318 -0
  220. package/dist/src/models/streaming.d.ts.map +1 -0
  221. package/dist/src/models/streaming.js +122 -0
  222. package/dist/src/models/streaming.js.map +1 -0
  223. package/dist/src/registry/registry.d.ts +117 -0
  224. package/dist/src/registry/registry.d.ts.map +1 -0
  225. package/dist/src/registry/registry.js +298 -0
  226. package/dist/src/registry/registry.js.map +1 -0
  227. package/dist/src/registry/tool-registry.d.ts +34 -0
  228. package/dist/src/registry/tool-registry.d.ts.map +1 -0
  229. package/dist/src/registry/tool-registry.js +178 -0
  230. package/dist/src/registry/tool-registry.js.map +1 -0
  231. package/dist/src/tools/__tests__/tool.test.d.ts +2 -0
  232. package/dist/src/tools/__tests__/tool.test.d.ts.map +1 -0
  233. package/dist/src/tools/__tests__/tool.test.js +877 -0
  234. package/dist/src/tools/__tests__/tool.test.js.map +1 -0
  235. package/dist/src/tools/__tests__/zod-tool.test-d.d.ts +2 -0
  236. package/dist/src/tools/__tests__/zod-tool.test-d.d.ts.map +1 -0
  237. package/dist/src/tools/__tests__/zod-tool.test-d.js +227 -0
  238. package/dist/src/tools/__tests__/zod-tool.test-d.js.map +1 -0
  239. package/dist/src/tools/__tests__/zod-tool.test.d.ts +2 -0
  240. package/dist/src/tools/__tests__/zod-tool.test.d.ts.map +1 -0
  241. package/dist/src/tools/__tests__/zod-tool.test.js +372 -0
  242. package/dist/src/tools/__tests__/zod-tool.test.js.map +1 -0
  243. package/dist/src/tools/function-tool.d.ts +146 -0
  244. package/dist/src/tools/function-tool.d.ts.map +1 -0
  245. package/dist/src/tools/function-tool.js +188 -0
  246. package/dist/src/tools/function-tool.js.map +1 -0
  247. package/dist/src/tools/mcp-tool.d.ts +36 -0
  248. package/dist/src/tools/mcp-tool.d.ts.map +1 -0
  249. package/dist/src/tools/mcp-tool.js +78 -0
  250. package/dist/src/tools/mcp-tool.js.map +1 -0
  251. package/dist/src/tools/tool.d.ts +167 -0
  252. package/dist/src/tools/tool.d.ts.map +1 -0
  253. package/dist/src/tools/tool.js +68 -0
  254. package/dist/src/tools/tool.js.map +1 -0
  255. package/dist/src/tools/types.d.ts +62 -0
  256. package/dist/src/tools/types.d.ts.map +1 -0
  257. package/dist/src/tools/types.js +2 -0
  258. package/dist/src/tools/types.js.map +1 -0
  259. package/dist/src/tools/zod-tool.d.ts +70 -0
  260. package/dist/src/tools/zod-tool.d.ts.map +1 -0
  261. package/dist/src/tools/zod-tool.js +149 -0
  262. package/dist/src/tools/zod-tool.js.map +1 -0
  263. package/dist/src/types/__tests__/agent.test.d.ts +2 -0
  264. package/dist/src/types/__tests__/agent.test.d.ts.map +1 -0
  265. package/dist/src/types/__tests__/agent.test.js +155 -0
  266. package/dist/src/types/__tests__/agent.test.js.map +1 -0
  267. package/dist/src/types/__tests__/json.test.d.ts +2 -0
  268. package/dist/src/types/__tests__/json.test.d.ts.map +1 -0
  269. package/dist/src/types/__tests__/json.test.js +298 -0
  270. package/dist/src/types/__tests__/json.test.js.map +1 -0
  271. package/dist/src/types/__tests__/media.test.d.ts +2 -0
  272. package/dist/src/types/__tests__/media.test.d.ts.map +1 -0
  273. package/dist/src/types/__tests__/media.test.js +257 -0
  274. package/dist/src/types/__tests__/media.test.js.map +1 -0
  275. package/dist/src/types/__tests__/messages.test.d.ts +2 -0
  276. package/dist/src/types/__tests__/messages.test.d.ts.map +1 -0
  277. package/dist/src/types/__tests__/messages.test.js +364 -0
  278. package/dist/src/types/__tests__/messages.test.js.map +1 -0
  279. package/dist/src/types/__tests__/validation.test.d.ts +2 -0
  280. package/dist/src/types/__tests__/validation.test.d.ts.map +1 -0
  281. package/dist/src/types/__tests__/validation.test.js +30 -0
  282. package/dist/src/types/__tests__/validation.test.js.map +1 -0
  283. package/dist/src/types/agent.d.ts +57 -0
  284. package/dist/src/types/agent.d.ts.map +1 -0
  285. package/dist/src/types/agent.js +47 -0
  286. package/dist/src/types/agent.js.map +1 -0
  287. package/dist/src/types/json.d.ts +55 -0
  288. package/dist/src/types/json.d.ts.map +1 -0
  289. package/dist/src/types/json.js +72 -0
  290. package/dist/src/types/json.js.map +1 -0
  291. package/dist/src/types/media.d.ts +249 -0
  292. package/dist/src/types/media.d.ts.map +1 -0
  293. package/dist/src/types/media.js +173 -0
  294. package/dist/src/types/media.js.map +1 -0
  295. package/dist/src/types/messages.d.ts +438 -0
  296. package/dist/src/types/messages.d.ts.map +1 -0
  297. package/dist/src/types/messages.js +286 -0
  298. package/dist/src/types/messages.js.map +1 -0
  299. package/dist/src/types/validation.d.ts +10 -0
  300. package/dist/src/types/validation.d.ts.map +1 -0
  301. package/dist/src/types/validation.js +15 -0
  302. package/dist/src/types/validation.js.map +1 -0
  303. package/dist/tools/__tests__/registry.test.d.ts +2 -0
  304. package/dist/tools/__tests__/registry.test.d.ts.map +1 -0
  305. package/dist/tools/__tests__/registry.test.js +253 -0
  306. package/dist/tools/__tests__/registry.test.js.map +1 -0
  307. package/dist/tools/__tests__/tool.test.d.ts +2 -0
  308. package/dist/tools/__tests__/tool.test.d.ts.map +1 -0
  309. package/dist/tools/__tests__/tool.test.js +761 -0
  310. package/dist/tools/__tests__/tool.test.js.map +1 -0
  311. package/dist/tools/__tests__/zod-tool.test-d.d.ts +2 -0
  312. package/dist/tools/__tests__/zod-tool.test-d.d.ts.map +1 -0
  313. package/dist/tools/__tests__/zod-tool.test-d.js +227 -0
  314. package/dist/tools/__tests__/zod-tool.test-d.js.map +1 -0
  315. package/dist/tools/__tests__/zod-tool.test.d.ts +2 -0
  316. package/dist/tools/__tests__/zod-tool.test.d.ts.map +1 -0
  317. package/dist/tools/__tests__/zod-tool.test.js +342 -0
  318. package/dist/tools/__tests__/zod-tool.test.js.map +1 -0
  319. package/dist/tools/function-tool.d.ts +156 -0
  320. package/dist/tools/function-tool.d.ts.map +1 -0
  321. package/dist/tools/function-tool.js +237 -0
  322. package/dist/tools/function-tool.js.map +1 -0
  323. package/dist/tools/registry.d.ts +43 -0
  324. package/dist/tools/registry.d.ts.map +1 -0
  325. package/dist/tools/registry.js +82 -0
  326. package/dist/tools/registry.js.map +1 -0
  327. package/dist/tools/tool.d.ts +157 -0
  328. package/dist/tools/tool.d.ts.map +1 -0
  329. package/dist/tools/tool.js +2 -0
  330. package/dist/tools/tool.js.map +1 -0
  331. package/dist/tools/types.d.ts +119 -0
  332. package/dist/tools/types.d.ts.map +1 -0
  333. package/dist/tools/types.js +2 -0
  334. package/dist/tools/types.js.map +1 -0
  335. package/dist/tools/zod-tool.d.ts +70 -0
  336. package/dist/tools/zod-tool.d.ts.map +1 -0
  337. package/dist/tools/zod-tool.js +96 -0
  338. package/dist/tools/zod-tool.js.map +1 -0
  339. package/dist/types/__tests__/json.test.d.ts +2 -0
  340. package/dist/types/__tests__/json.test.d.ts.map +1 -0
  341. package/dist/types/__tests__/json.test.js +129 -0
  342. package/dist/types/__tests__/json.test.js.map +1 -0
  343. package/dist/types/__tests__/validation.test.d.ts +2 -0
  344. package/dist/types/__tests__/validation.test.d.ts.map +1 -0
  345. package/dist/types/__tests__/validation.test.js +30 -0
  346. package/dist/types/__tests__/validation.test.js.map +1 -0
  347. package/dist/types/json.d.ts +45 -0
  348. package/dist/types/json.d.ts.map +1 -0
  349. package/dist/types/json.js +17 -0
  350. package/dist/types/json.js.map +1 -0
  351. package/dist/types/messages.d.ts +160 -0
  352. package/dist/types/messages.d.ts.map +1 -0
  353. package/dist/types/messages.js +2 -0
  354. package/dist/types/messages.js.map +1 -0
  355. package/dist/types/validation.d.ts +10 -0
  356. package/dist/types/validation.d.ts.map +1 -0
  357. package/dist/types/validation.js +15 -0
  358. package/dist/types/validation.js.map +1 -0
  359. package/dist/vended_tools/bash/__tests__/bash.test.d.ts +2 -0
  360. package/dist/vended_tools/bash/__tests__/bash.test.d.ts.map +1 -0
  361. package/dist/vended_tools/bash/__tests__/bash.test.js +333 -0
  362. package/dist/vended_tools/bash/__tests__/bash.test.js.map +1 -0
  363. package/dist/vended_tools/bash/bash.d.ts +33 -0
  364. package/dist/vended_tools/bash/bash.d.ts.map +1 -0
  365. package/dist/vended_tools/bash/bash.js +264 -0
  366. package/dist/vended_tools/bash/bash.js.map +1 -0
  367. package/dist/vended_tools/bash/index.d.ts +7 -0
  368. package/dist/vended_tools/bash/index.d.ts.map +1 -0
  369. package/dist/vended_tools/bash/index.js +6 -0
  370. package/dist/vended_tools/bash/index.js.map +1 -0
  371. package/dist/vended_tools/bash/types.d.ts +65 -0
  372. package/dist/vended_tools/bash/types.d.ts.map +1 -0
  373. package/dist/vended_tools/bash/types.js +22 -0
  374. package/dist/vended_tools/bash/types.js.map +1 -0
  375. package/dist/vended_tools/file_editor/__tests__/file-editor.test.d.ts +2 -0
  376. package/dist/vended_tools/file_editor/__tests__/file-editor.test.d.ts.map +1 -0
  377. package/dist/vended_tools/file_editor/__tests__/file-editor.test.js +359 -0
  378. package/dist/vended_tools/file_editor/__tests__/file-editor.test.js.map +1 -0
  379. package/dist/vended_tools/file_editor/file-editor.d.ts +31 -0
  380. package/dist/vended_tools/file_editor/file-editor.d.ts.map +1 -0
  381. package/dist/vended_tools/file_editor/file-editor.js +353 -0
  382. package/dist/vended_tools/file_editor/file-editor.js.map +1 -0
  383. package/dist/vended_tools/file_editor/index.d.ts +6 -0
  384. package/dist/vended_tools/file_editor/index.d.ts.map +1 -0
  385. package/dist/vended_tools/file_editor/index.js +5 -0
  386. package/dist/vended_tools/file_editor/index.js.map +1 -0
  387. package/dist/vended_tools/file_editor/types.d.ts +61 -0
  388. package/dist/vended_tools/file_editor/types.d.ts.map +1 -0
  389. package/dist/vended_tools/file_editor/types.js +2 -0
  390. package/dist/vended_tools/file_editor/types.js.map +1 -0
  391. package/dist/vended_tools/http_request/__tests__/http-request.test.d.ts +2 -0
  392. package/dist/vended_tools/http_request/__tests__/http-request.test.d.ts.map +1 -0
  393. package/dist/vended_tools/http_request/__tests__/http-request.test.js +189 -0
  394. package/dist/vended_tools/http_request/__tests__/http-request.test.js.map +1 -0
  395. package/dist/vended_tools/http_request/http-request.d.ts +35 -0
  396. package/dist/vended_tools/http_request/http-request.d.ts.map +1 -0
  397. package/dist/vended_tools/http_request/http-request.js +95 -0
  398. package/dist/vended_tools/http_request/http-request.js.map +1 -0
  399. package/dist/vended_tools/http_request/index.d.ts +6 -0
  400. package/dist/vended_tools/http_request/index.d.ts.map +1 -0
  401. package/dist/vended_tools/http_request/index.js +5 -0
  402. package/dist/vended_tools/http_request/index.js.map +1 -0
  403. package/dist/vended_tools/http_request/types.d.ts +47 -0
  404. package/dist/vended_tools/http_request/types.d.ts.map +1 -0
  405. package/dist/vended_tools/http_request/types.js +2 -0
  406. package/dist/vended_tools/http_request/types.js.map +1 -0
  407. package/dist/vended_tools/notebook/__tests__/notebook.test.d.ts +2 -0
  408. package/dist/vended_tools/notebook/__tests__/notebook.test.d.ts.map +1 -0
  409. package/dist/vended_tools/notebook/__tests__/notebook.test.js +371 -0
  410. package/dist/vended_tools/notebook/__tests__/notebook.test.js.map +1 -0
  411. package/dist/vended_tools/notebook/index.d.ts +6 -0
  412. package/dist/vended_tools/notebook/index.d.ts.map +1 -0
  413. package/dist/vended_tools/notebook/index.js +5 -0
  414. package/dist/vended_tools/notebook/index.js.map +1 -0
  415. package/dist/vended_tools/notebook/notebook.d.ts +29 -0
  416. package/dist/vended_tools/notebook/notebook.d.ts.map +1 -0
  417. package/dist/vended_tools/notebook/notebook.js +215 -0
  418. package/dist/vended_tools/notebook/notebook.js.map +1 -0
  419. package/dist/vended_tools/notebook/types.d.ts +79 -0
  420. package/dist/vended_tools/notebook/types.d.ts.map +1 -0
  421. package/dist/vended_tools/notebook/types.js +2 -0
  422. package/dist/vended_tools/notebook/types.js.map +1 -0
  423. package/package.json +112 -0
@@ -0,0 +1,752 @@
1
+ /**
2
+ * OpenAI model provider implementation.
3
+ *
4
+ * This module provides integration with OpenAI's Chat Completions API,
5
+ * supporting streaming responses, tool use, and configurable model parameters.
6
+ *
7
+ * @see https://platform.openai.com/docs/api-reference/chat/create
8
+ */
9
+ import OpenAI, {} from 'openai';
10
+ import { Model } from '../models/model.js';
11
+ import { encodeBase64 } from '../types/media.js';
12
+ import { ContextWindowOverflowError } from '../errors.js';
13
+ /**
14
+ * Browser-compatible MIME type lookup.
15
+ * Maps file extensions to MIME types without using Node.js path module.
16
+ */
17
+ const mimeTypeLookup = (format) => {
18
+ const mimeTypes = {
19
+ // Video
20
+ mkv: 'video/x-matroska',
21
+ mov: 'video/quicktime',
22
+ mp4: 'application/mp4',
23
+ webm: 'video/webm',
24
+ flv: 'video/x-flv',
25
+ mpeg: 'video/mpeg',
26
+ mpg: 'video/mpeg',
27
+ wmv: 'video/x-ms-wmv',
28
+ '3gp': 'video/3gpp',
29
+ // Images
30
+ png: 'image/png',
31
+ jpg: 'image/jpeg',
32
+ jpeg: 'image/jpeg',
33
+ gif: 'image/gif',
34
+ webp: 'image/webp',
35
+ // Documents
36
+ pdf: 'application/pdf',
37
+ csv: 'text/csv',
38
+ doc: 'application/msword',
39
+ docx: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
40
+ xlsx: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
41
+ xls: 'application/vnd.ms-excel',
42
+ txt: 'text/plain',
43
+ json: 'application/json',
44
+ xml: 'application/xml',
45
+ html: 'text/html',
46
+ md: 'text/markdown',
47
+ };
48
+ return mimeTypes[format.toLowerCase()] || false;
49
+ };
50
+ const DEFAULT_OPENAI_MODEL_ID = 'gpt-4o';
51
+ /**
52
+ * Error message patterns that indicate context window overflow.
53
+ * Used to detect when input exceeds the model's context window.
54
+ *
55
+ * @see https://platform.openai.com/docs/guides/error-codes
56
+ */
57
+ const OPENAI_CONTEXT_WINDOW_OVERFLOW_PATTERNS = [
58
+ 'maximum context length',
59
+ 'context_length_exceeded',
60
+ 'too many tokens',
61
+ 'context length',
62
+ ];
63
+ /**
64
+ * OpenAI model provider implementation.
65
+ *
66
+ * Implements the Model interface for OpenAI using the Chat Completions API.
67
+ * Supports streaming responses, tool use, and comprehensive configuration.
68
+ *
69
+ * @example
70
+ * ```typescript
71
+ * const provider = new OpenAIModel({
72
+ * apiKey: 'sk-...',
73
+ * modelId: 'gpt-4o',
74
+ * temperature: 0.7,
75
+ * maxTokens: 1024
76
+ * })
77
+ *
78
+ * const messages: Message[] = [
79
+ * { role: 'user', content: [{ type: 'textBlock', text: 'Hello!' }] }
80
+ * ]
81
+ *
82
+ * for await (const event of provider.stream(messages)) {
83
+ * if (event.type === 'modelContentBlockDeltaEvent' && event.delta.type === 'textDelta') {
84
+ * process.stdout.write(event.delta.text)
85
+ * }
86
+ * }
87
+ * ```
88
+ */
89
+ export class OpenAIModel extends Model {
90
+ _config;
91
+ _client;
92
+ /**
93
+ * Creates a new OpenAIModel instance.
94
+ *
95
+ * @param options - Configuration for model and client (modelId is required)
96
+ *
97
+ * @example
98
+ * ```typescript
99
+ * // Minimal configuration with API key and model ID
100
+ * const provider = new OpenAIModel({
101
+ * modelId: 'gpt-4o',
102
+ * apiKey: 'sk-...'
103
+ * })
104
+ *
105
+ * // With additional model configuration
106
+ * const provider = new OpenAIModel({
107
+ * modelId: 'gpt-4o',
108
+ * apiKey: 'sk-...',
109
+ * temperature: 0.8,
110
+ * maxTokens: 2048
111
+ * })
112
+ *
113
+ * // Using environment variable for API key
114
+ * const provider = new OpenAIModel({
115
+ * modelId: 'gpt-3.5-turbo'
116
+ * })
117
+ *
118
+ * // Using a pre-configured client instance
119
+ * const client = new OpenAI({ apiKey: 'sk-...', timeout: 60000 })
120
+ * const provider = new OpenAIModel({
121
+ * modelId: 'gpt-4o',
122
+ * client
123
+ * })
124
+ * ```
125
+ */
126
+ constructor(options) {
127
+ super();
128
+ const { apiKey, client, clientConfig, ...modelConfig } = options || {};
129
+ // Initialize model config
130
+ this._config = modelConfig;
131
+ // Use provided client or create a new one
132
+ if (client) {
133
+ this._client = client;
134
+ }
135
+ else {
136
+ // Check if API key is available when creating a new client
137
+ // In browsers, apiKey must be provided directly
138
+ // In Node.js, can use OPENAI_API_KEY environment variable as fallback
139
+ const hasEnvKey = typeof process !== 'undefined' && typeof process.env !== 'undefined' && process.env.OPENAI_API_KEY;
140
+ if (!apiKey && !hasEnvKey) {
141
+ throw new Error("OpenAI API key is required. Provide it via the 'apiKey' option or set the OPENAI_API_KEY environment variable.");
142
+ }
143
+ // Initialize OpenAI client
144
+ // Only include apiKey if explicitly provided, otherwise let client use env var
145
+ this._client = new OpenAI({
146
+ ...(apiKey ? { apiKey } : {}),
147
+ ...clientConfig,
148
+ });
149
+ }
150
+ }
151
+ /**
152
+ * Updates the model configuration.
153
+ * Merges the provided configuration with existing settings.
154
+ *
155
+ * @param modelConfig - Configuration object with model-specific settings to update
156
+ *
157
+ * @example
158
+ * ```typescript
159
+ * // Update temperature and maxTokens
160
+ * provider.updateConfig({
161
+ * temperature: 0.9,
162
+ * maxTokens: 2048
163
+ * })
164
+ * ```
165
+ */
166
+ updateConfig(modelConfig) {
167
+ this._config = { ...this._config, ...modelConfig };
168
+ }
169
+ /**
170
+ * Retrieves the current model configuration.
171
+ *
172
+ * @returns The current configuration object
173
+ *
174
+ * @example
175
+ * ```typescript
176
+ * const config = provider.getConfig()
177
+ * console.log(config.modelId)
178
+ * ```
179
+ */
180
+ getConfig() {
181
+ return this._config;
182
+ }
183
+ /**
184
+ * Streams a conversation with the OpenAI model.
185
+ * Returns an async iterable that yields streaming events as they occur.
186
+ *
187
+ * @param messages - Array of conversation messages
188
+ * @param options - Optional streaming configuration
189
+ * @returns Async iterable of streaming events
190
+ *
191
+ * @throws \{ContextWindowOverflowError\} When input exceeds the model's context window
192
+ *
193
+ * @example
194
+ * ```typescript
195
+ * const provider = new OpenAIModel({ modelId: 'gpt-4o', apiKey: 'sk-...' })
196
+ * const messages: Message[] = [
197
+ * { role: 'user', content: [{ type: 'textBlock', text: 'What is 2+2?' }] }
198
+ * ]
199
+ *
200
+ * for await (const event of provider.stream(messages)) {
201
+ * if (event.type === 'modelContentBlockDeltaEvent' && event.delta.type === 'textDelta') {
202
+ * process.stdout.write(event.delta.text)
203
+ * }
204
+ * }
205
+ * ```
206
+ *
207
+ * @example
208
+ * ```typescript
209
+ * // With tool use
210
+ * const options: StreamOptions = {
211
+ * systemPrompt: 'You are a helpful assistant',
212
+ * toolSpecs: [calculatorTool]
213
+ * }
214
+ *
215
+ * for await (const event of provider.stream(messages, options)) {
216
+ * if (event.type === 'modelMessageStopEvent' && event.stopReason === 'toolUse') {
217
+ * console.log('Model wants to use a tool')
218
+ * }
219
+ * }
220
+ * ```
221
+ */
222
+ async *stream(messages, options) {
223
+ // Validate messages array is not empty
224
+ if (!messages || messages.length === 0) {
225
+ throw new Error('At least one message is required');
226
+ }
227
+ try {
228
+ // Format the request
229
+ const request = this._formatRequest(messages, options);
230
+ // Create streaming request with usage tracking
231
+ const stream = await this._client.chat.completions.create(request);
232
+ // Track streaming state (Use mutable object for proper state tracking)
233
+ const streamState = {
234
+ messageStarted: false,
235
+ textContentBlockStarted: false,
236
+ };
237
+ // Track active tool calls for stop events
238
+ const activeToolCalls = new Map();
239
+ // Buffer usage to emit before message stop
240
+ let bufferedUsage = null;
241
+ // Process streaming response
242
+ for await (const chunk of stream) {
243
+ if (!chunk.choices || chunk.choices.length === 0) {
244
+ // Handle usage chunk (no choices)
245
+ // Buffer usage to emit before message stop
246
+ if (chunk.usage) {
247
+ bufferedUsage = {
248
+ type: 'modelMetadataEvent',
249
+ usage: {
250
+ inputTokens: chunk.usage.prompt_tokens ?? 0,
251
+ outputTokens: chunk.usage.completion_tokens ?? 0,
252
+ totalTokens: chunk.usage.total_tokens ?? 0,
253
+ },
254
+ };
255
+ }
256
+ continue;
257
+ }
258
+ // Map chunk to SDK events
259
+ const events = this._mapOpenAIChunkToSDKEvents(chunk, streamState, activeToolCalls);
260
+ for (const event of events) {
261
+ // Emit buffered usage before message stop
262
+ if (event.type === 'modelMessageStopEvent' && bufferedUsage) {
263
+ yield bufferedUsage;
264
+ bufferedUsage = null;
265
+ }
266
+ yield event;
267
+ }
268
+ }
269
+ // Emit any remaining buffered usage
270
+ if (bufferedUsage) {
271
+ yield bufferedUsage;
272
+ }
273
+ }
274
+ catch (error) {
275
+ const err = error;
276
+ // Check for context window overflow using simple pattern matching
277
+ if (OPENAI_CONTEXT_WINDOW_OVERFLOW_PATTERNS.some((pattern) => err.message?.toLowerCase().includes(pattern))) {
278
+ throw new ContextWindowOverflowError(err.message);
279
+ }
280
+ // Re-throw other errors unchanged
281
+ throw err;
282
+ }
283
+ }
284
+ /**
285
+ * Formats a request for the OpenAI Chat Completions API.
286
+ *
287
+ * @param messages - Conversation messages
288
+ * @param options - Stream options
289
+ * @returns Formatted OpenAI request
290
+ */
291
+ _formatRequest(messages, options) {
292
+ // Start with required fields
293
+ const request = {
294
+ model: this._config.modelId ?? DEFAULT_OPENAI_MODEL_ID,
295
+ messages: [],
296
+ stream: true,
297
+ stream_options: { include_usage: true },
298
+ };
299
+ // Handle system prompt (string or array format)
300
+ if (options?.systemPrompt !== undefined) {
301
+ if (typeof options.systemPrompt === 'string') {
302
+ // String path: validate and add as-is
303
+ if (options.systemPrompt.trim().length > 0) {
304
+ request.messages.push({
305
+ role: 'system',
306
+ content: options.systemPrompt,
307
+ });
308
+ }
309
+ }
310
+ else if (Array.isArray(options.systemPrompt) && options.systemPrompt.length > 0) {
311
+ // Array path: extract text blocks and warn about cache points
312
+ const textBlocks = [];
313
+ let hasCachePoints = false;
314
+ let hasGuardContent = false;
315
+ for (const block of options.systemPrompt) {
316
+ if (block.type === 'textBlock') {
317
+ textBlocks.push(block.text);
318
+ }
319
+ else if (block.type === 'cachePointBlock') {
320
+ hasCachePoints = true;
321
+ }
322
+ else if (block.type === 'guardContentBlock') {
323
+ hasGuardContent = true;
324
+ }
325
+ }
326
+ if (hasCachePoints) {
327
+ console.warn('Cache points are not supported in OpenAI system prompts and will be ignored.');
328
+ }
329
+ if (hasGuardContent) {
330
+ console.warn('OpenAI does not support guard content in system prompts. Removing guard content block.');
331
+ }
332
+ if (textBlocks.length > 0) {
333
+ request.messages.push({
334
+ role: 'system',
335
+ content: textBlocks.join(''),
336
+ });
337
+ }
338
+ }
339
+ }
340
+ // Add formatted messages
341
+ const formattedMessages = this._formatMessages(messages);
342
+ request.messages.push(...formattedMessages);
343
+ // Add model configuration parameters
344
+ if (this._config.temperature !== undefined) {
345
+ request.temperature = this._config.temperature;
346
+ }
347
+ if (this._config.maxTokens !== undefined) {
348
+ request.max_tokens = this._config.maxTokens;
349
+ }
350
+ if (this._config.topP !== undefined) {
351
+ request.top_p = this._config.topP;
352
+ }
353
+ if (this._config.frequencyPenalty !== undefined) {
354
+ request.frequency_penalty = this._config.frequencyPenalty;
355
+ }
356
+ if (this._config.presencePenalty !== undefined) {
357
+ request.presence_penalty = this._config.presencePenalty;
358
+ }
359
+ // Add tool specifications with validation
360
+ if (options?.toolSpecs && options.toolSpecs.length > 0) {
361
+ request.tools = options.toolSpecs.map((spec) => {
362
+ if (!spec.name || !spec.description) {
363
+ throw new Error('Tool specification must have both name and description');
364
+ }
365
+ return {
366
+ type: 'function',
367
+ function: {
368
+ name: spec.name,
369
+ description: spec.description,
370
+ parameters: spec.inputSchema,
371
+ },
372
+ };
373
+ });
374
+ // Add tool choice if specified
375
+ if (options.toolChoice) {
376
+ if ('auto' in options.toolChoice) {
377
+ request.tool_choice = 'auto';
378
+ }
379
+ else if ('any' in options.toolChoice) {
380
+ request.tool_choice = 'required';
381
+ }
382
+ else if ('tool' in options.toolChoice) {
383
+ request.tool_choice = {
384
+ type: 'function',
385
+ function: { name: options.toolChoice.tool.name },
386
+ };
387
+ }
388
+ }
389
+ }
390
+ // Spread params object last for forward compatibility
391
+ if (this._config.params) {
392
+ Object.assign(request, this._config.params);
393
+ }
394
+ // Validate n parameter (number of completions) - only n=1 supported for streaming
395
+ if ('n' in request && request.n !== undefined && request.n !== null && request.n > 1) {
396
+ throw new Error('Streaming with n > 1 is not supported');
397
+ }
398
+ return request;
399
+ }
400
+ /**
401
+ * Formats messages for OpenAI API.
402
+ * Handles splitting tool results into separate messages.
403
+ *
404
+ * @param messages - SDK messages
405
+ * @returns OpenAI-formatted messages
406
+ */
407
+ _formatMessages(messages) {
408
+ const openAIMessages = [];
409
+ for (const message of messages) {
410
+ if (message.role === 'user') {
411
+ // Separate tool results from other content
412
+ const toolResults = message.content.filter((b) => b.type === 'toolResultBlock');
413
+ const otherContent = message.content.filter((b) => b.type !== 'toolResultBlock');
414
+ // Add non-tool-result content as user message
415
+ if (otherContent.length > 0) {
416
+ const contentParts = [];
417
+ for (const block of otherContent) {
418
+ switch (block.type) {
419
+ case 'textBlock': {
420
+ contentParts.push({
421
+ type: 'text',
422
+ text: block.text,
423
+ });
424
+ break;
425
+ }
426
+ case 'imageBlock': {
427
+ const imageBlock = block;
428
+ switch (imageBlock.source.type) {
429
+ case 'imageSourceUrl': {
430
+ contentParts.push({
431
+ type: 'image_url',
432
+ image_url: {
433
+ url: imageBlock.source.url,
434
+ },
435
+ });
436
+ break;
437
+ }
438
+ case 'imageSourceBytes': {
439
+ const base64 = encodeBase64(String.fromCharCode(...imageBlock.source.bytes));
440
+ const mimeType = mimeTypeLookup(imageBlock.format) || `image/${imageBlock.format}`;
441
+ contentParts.push({
442
+ type: 'image_url',
443
+ image_url: {
444
+ url: `data:${mimeType};base64,${base64}`,
445
+ },
446
+ });
447
+ break;
448
+ }
449
+ default: {
450
+ console.warn(`OpenAI ChatCompletions API does not support image block type: ${imageBlock.source.type}.`);
451
+ break;
452
+ }
453
+ }
454
+ break;
455
+ }
456
+ case 'documentBlock': {
457
+ const docBlock = block;
458
+ switch (docBlock.source.type) {
459
+ case 'documentSourceBytes': {
460
+ const mimeType = mimeTypeLookup(docBlock.format) || `application/${docBlock.format}`;
461
+ const base64 = encodeBase64(String.fromCharCode(...docBlock.source.bytes));
462
+ const file = {
463
+ type: 'file',
464
+ file: {
465
+ file_data: `data:${mimeType};base64,${base64}`,
466
+ filename: docBlock.name,
467
+ },
468
+ };
469
+ contentParts.push(file);
470
+ break;
471
+ }
472
+ case 'documentSourceText': {
473
+ // Text documents can be added directly
474
+ console.warn('OpenAI does not support text document sources directly. Converting this text document to string content.');
475
+ contentParts.push({
476
+ type: 'text',
477
+ text: docBlock.source.text,
478
+ });
479
+ break;
480
+ }
481
+ case 'documentSourceContentBlock': {
482
+ // Push each content block as a content part
483
+ contentParts.push(...docBlock.source.content.map((block) => {
484
+ return {
485
+ type: 'text',
486
+ text: block.text,
487
+ };
488
+ }));
489
+ break;
490
+ }
491
+ default: {
492
+ console.warn(`OpenAI ChatCompletions API only supports text content in user messages. Skipping document block type: ${docBlock.source.type}.`);
493
+ break;
494
+ }
495
+ }
496
+ break;
497
+ }
498
+ default: {
499
+ console.warn(`OpenAI ChatCompletions API does not support content type: ${block.type}.`);
500
+ break;
501
+ }
502
+ }
503
+ }
504
+ // Validate content is not empty before adding
505
+ if (contentParts.length > 0) {
506
+ openAIMessages.push({
507
+ role: 'user',
508
+ content: contentParts,
509
+ });
510
+ }
511
+ }
512
+ // Add each tool result as separate tool message
513
+ // OpenAI only supports text content in tool result messages, not JSON
514
+ for (const toolResult of toolResults) {
515
+ if (toolResult.type === 'toolResultBlock') {
516
+ // Format tool result content - convert all to text string
517
+ // Note: OpenAI tool messages only accept string content (not structured JSON)
518
+ const contentText = toolResult.content
519
+ .map((c) => {
520
+ if (c.type === 'textBlock') {
521
+ return c.text;
522
+ }
523
+ else if (c.type === 'jsonBlock') {
524
+ try {
525
+ return JSON.stringify(c.json);
526
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
527
+ }
528
+ catch (error) {
529
+ const dataPreview = typeof c.json === 'object' && c.json !== null
530
+ ? `object with keys: ${Object.keys(c.json).slice(0, 5).join(', ')}`
531
+ : typeof c.json;
532
+ return `[JSON Serialization Error: ${error.message}. Data type: ${dataPreview}]`;
533
+ }
534
+ }
535
+ return '';
536
+ })
537
+ .join('');
538
+ // Validate content is not empty
539
+ if (!contentText || contentText.trim().length === 0) {
540
+ throw new Error(`Tool result for toolUseId "${toolResult.toolUseId}" has empty content. ` +
541
+ 'OpenAI requires tool messages to have non-empty content.');
542
+ }
543
+ // Prepend error indicator if status is error
544
+ const finalContent = toolResult.status === 'error' ? `[ERROR] ${contentText}` : contentText;
545
+ openAIMessages.push({
546
+ role: 'tool',
547
+ tool_call_id: toolResult.toolUseId,
548
+ content: finalContent,
549
+ });
550
+ }
551
+ }
552
+ }
553
+ else {
554
+ // Handle assistant messages
555
+ const toolUseCalls = [];
556
+ // Use array + join pattern for efficient string concatenation
557
+ const textParts = [];
558
+ for (const block of message.content) {
559
+ switch (block.type) {
560
+ case 'textBlock': {
561
+ textParts.push(block.text);
562
+ break;
563
+ }
564
+ case 'toolUseBlock': {
565
+ try {
566
+ toolUseCalls.push({
567
+ id: block.toolUseId,
568
+ type: 'function',
569
+ function: {
570
+ name: block.name,
571
+ arguments: JSON.stringify(block.input),
572
+ },
573
+ });
574
+ }
575
+ catch (error) {
576
+ if (error instanceof Error) {
577
+ throw new Error(`Failed to serialize tool input for "${block.name}`, error);
578
+ }
579
+ throw error;
580
+ }
581
+ break;
582
+ }
583
+ case 'reasoningBlock': {
584
+ if (block.text) {
585
+ console.warn('Reasoning blocks are not supported by OpenAI Chat Completions API. Converting to text.');
586
+ textParts.push(block.text);
587
+ }
588
+ break;
589
+ }
590
+ default: {
591
+ console.warn(`OpenAI ChatCompletions API does not support ${block.type} content in assistant messages. Skipping this block.`);
592
+ }
593
+ }
594
+ }
595
+ // Trim text content to avoid whitespace-only messages
596
+ const textContent = textParts.join('').trim();
597
+ const assistantMessage = {
598
+ role: 'assistant',
599
+ content: textContent,
600
+ };
601
+ if (toolUseCalls.length > 0) {
602
+ assistantMessage.tool_calls = toolUseCalls;
603
+ }
604
+ // Only add if message has content or tool calls
605
+ if (textContent.length > 0 || toolUseCalls.length > 0) {
606
+ openAIMessages.push(assistantMessage);
607
+ }
608
+ }
609
+ }
610
+ return openAIMessages;
611
+ }
612
+ /**
613
+ * Converts a snake_case string to camelCase.
614
+ * Used for mapping OpenAI stop reasons to SDK format.
615
+ *
616
+ * @param str - Snake case string (e.g., 'content_filter')
617
+ * @returns Camel case string (e.g., 'contentFilter')
618
+ *
619
+ * @example
620
+ * ```typescript
621
+ * _snakeToCamel('context_length_exceeded') // => 'contextLengthExceeded'
622
+ * _snakeToCamel('tool_calls') // => 'toolCalls'
623
+ * ```
624
+ */
625
+ _snakeToCamel(str) {
626
+ return str.replace(/_([a-z])/g, (_, letter) => letter.toUpperCase());
627
+ }
628
+ /**
629
+ * Maps an OpenAI chunk to SDK streaming events.
630
+ *
631
+ * @param chunk - OpenAI chunk
632
+ * @param streamState - Mutable state object tracking message and content block state
633
+ * @param activeToolCalls - Map tracking active tool calls by index
634
+ * @returns Array of SDK streaming events
635
+ */
636
+ _mapOpenAIChunkToSDKEvents(chunk, streamState, activeToolCalls) {
637
+ const events = [];
638
+ // Validate choices array has at least one element
639
+ if (!chunk.choices || chunk.choices.length === 0) {
640
+ return events;
641
+ }
642
+ const choice = chunk.choices[0];
643
+ // Validate choice is an object
644
+ if (!choice || typeof choice !== 'object') {
645
+ console.warn('Invalid choice format in OpenAI chunk:', choice);
646
+ return events;
647
+ }
648
+ // Process first choice (OpenAI typically returns one choice in streaming)
649
+ const typedChoice = choice;
650
+ if (!typedChoice.delta && !typedChoice.finish_reason) {
651
+ return events;
652
+ }
653
+ const delta = typedChoice.delta;
654
+ // Handle message start (role appears) - update mutable state
655
+ if (delta?.role && !streamState.messageStarted) {
656
+ streamState.messageStarted = true;
657
+ events.push({
658
+ type: 'modelMessageStartEvent',
659
+ role: delta.role,
660
+ });
661
+ }
662
+ // Handle text content delta and start event
663
+ if (delta?.content && delta.content.length > 0) {
664
+ // Emit start event on first text delta
665
+ if (!streamState.textContentBlockStarted) {
666
+ streamState.textContentBlockStarted = true;
667
+ events.push({
668
+ type: 'modelContentBlockStartEvent',
669
+ });
670
+ }
671
+ events.push({
672
+ type: 'modelContentBlockDeltaEvent',
673
+ delta: {
674
+ type: 'textDelta',
675
+ text: delta.content,
676
+ },
677
+ });
678
+ }
679
+ // Handle tool calls
680
+ if (delta?.tool_calls && delta.tool_calls.length > 0) {
681
+ for (const toolCall of delta.tool_calls) {
682
+ // Validate tool call index
683
+ if (toolCall.index === undefined || typeof toolCall.index !== 'number') {
684
+ console.warn('Received tool call with invalid index:', toolCall);
685
+ continue;
686
+ }
687
+ // If tool call has id and name, it's the start of a new tool call
688
+ if (toolCall.id && toolCall.function?.name) {
689
+ events.push({
690
+ type: 'modelContentBlockStartEvent',
691
+ start: {
692
+ type: 'toolUseStart',
693
+ name: toolCall.function.name,
694
+ toolUseId: toolCall.id,
695
+ },
696
+ });
697
+ // Track active tool calls
698
+ activeToolCalls.set(toolCall.index, true);
699
+ }
700
+ // If tool call has arguments, it's a delta
701
+ if (toolCall.function?.arguments) {
702
+ events.push({
703
+ type: 'modelContentBlockDeltaEvent',
704
+ delta: {
705
+ type: 'toolUseInputDelta',
706
+ input: toolCall.function.arguments,
707
+ },
708
+ });
709
+ }
710
+ }
711
+ }
712
+ // Handle finish reason (message stop)
713
+ if (typedChoice.finish_reason) {
714
+ // Emit stop event for text content if it was started
715
+ if (streamState.textContentBlockStarted) {
716
+ events.push({
717
+ type: 'modelContentBlockStopEvent',
718
+ });
719
+ streamState.textContentBlockStarted = false;
720
+ }
721
+ // Emit stop events for all active tool calls and delete during iteration
722
+ for (const [index] of activeToolCalls) {
723
+ events.push({
724
+ type: 'modelContentBlockStopEvent',
725
+ });
726
+ activeToolCalls.delete(index);
727
+ }
728
+ // Map OpenAI stop reason to SDK stop reason
729
+ const stopReasonMap = {
730
+ stop: 'endTurn',
731
+ tool_calls: 'toolUse',
732
+ length: 'maxTokens',
733
+ content_filter: 'contentFiltered',
734
+ };
735
+ // Log unknown stop reasons
736
+ let stopReason = stopReasonMap[typedChoice.finish_reason];
737
+ if (!stopReason) {
738
+ const fallbackReason = this._snakeToCamel(typedChoice.finish_reason);
739
+ console.warn(`Unknown OpenAI stop reason: "${typedChoice.finish_reason}". ` +
740
+ `Using camelCase conversion as fallback: "${fallbackReason}". ` +
741
+ 'Please report this to update the stop reason mapping.');
742
+ stopReason = fallbackReason;
743
+ }
744
+ events.push({
745
+ type: 'modelMessageStopEvent',
746
+ stopReason,
747
+ });
748
+ }
749
+ return events;
750
+ }
751
+ }
752
+ //# sourceMappingURL=openai.js.map