@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,1161 @@
1
+ import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
2
+ import { BedrockRuntimeClient } from '@aws-sdk/client-bedrock-runtime';
3
+ import { BedrockModel } from '../bedrock';
4
+ import { ContextWindowOverflowError } from '../../errors';
5
+ import { collectIterator } from '../../__fixtures__/model-test-helpers';
6
+ // Environment detection
7
+ const isNode = typeof process !== 'undefined' && typeof process.versions !== 'undefined' && !!process.versions.node;
8
+ /**
9
+ * Helper function to setup mock send with custom stream generator.
10
+ */
11
+ function setupMockSend(streamGenerator) {
12
+ vi.clearAllMocks();
13
+ const mockSend = vi.fn(async () => ({
14
+ stream: streamGenerator(),
15
+ }));
16
+ vi.mocked(BedrockRuntimeClient).mockImplementation(() => ({ send: mockSend }));
17
+ }
18
+ // Mock the AWS SDK
19
+ vi.mock('@aws-sdk/client-bedrock-runtime', async (importOriginal) => {
20
+ const originalModule = await importOriginal();
21
+ // Mock command classes that the code under test will instantiate
22
+ const ConverseStreamCommand = vi.fn();
23
+ const ConverseCommand = vi.fn();
24
+ const mockSend = vi.fn(async (command) => {
25
+ // Check which constructor was used to create the command object
26
+ if (command instanceof ConverseStreamCommand) {
27
+ // Return a streaming response
28
+ return {
29
+ stream: (async function* () {
30
+ yield { messageStart: { role: 'assistant' } };
31
+ yield { contentBlockStart: { contentBlockIndex: 0 } };
32
+ yield { contentBlockDelta: { delta: { text: 'Hello' }, contentBlockIndex: 0 } };
33
+ yield { contentBlockStop: { contentBlockIndex: 0 } };
34
+ yield { messageStop: { stopReason: 'end_turn' } };
35
+ yield {
36
+ metadata: {
37
+ usage: { inputTokens: 10, outputTokens: 5, totalTokens: 15 },
38
+ metrics: { latencyMs: 100 },
39
+ },
40
+ };
41
+ })(),
42
+ };
43
+ }
44
+ if (command instanceof ConverseCommand) {
45
+ // Return a non-streaming (full) response for the non-streaming API
46
+ return {
47
+ output: {
48
+ message: {
49
+ role: 'assistant',
50
+ content: [{ text: 'Hello' }],
51
+ },
52
+ },
53
+ stopReason: 'end_turn',
54
+ usage: { inputTokens: 10, outputTokens: 5, totalTokens: 15 },
55
+ metrics: { latencyMs: 100 },
56
+ };
57
+ }
58
+ throw new Error('Unhandled command type in mock');
59
+ });
60
+ // Create a mock ValidationException class
61
+ class MockValidationException extends Error {
62
+ constructor(opts) {
63
+ super(opts.message);
64
+ this.name = 'ValidationException';
65
+ }
66
+ }
67
+ return {
68
+ ...originalModule,
69
+ BedrockRuntimeClient: vi.fn().mockImplementation(() => ({
70
+ send: mockSend,
71
+ })),
72
+ ConverseStreamCommand,
73
+ ConverseCommand,
74
+ ValidationException: MockValidationException,
75
+ };
76
+ });
77
+ describe('BedrockModel', () => {
78
+ beforeEach(() => {
79
+ vi.clearAllMocks();
80
+ // Clean up AWS_REGION env var in Node.js only
81
+ if (isNode && process.env) {
82
+ delete process.env.AWS_REGION;
83
+ }
84
+ });
85
+ afterEach(() => {
86
+ vi.clearAllMocks();
87
+ });
88
+ describe('constructor', () => {
89
+ it('creates an instance with default configuration', () => {
90
+ const provider = new BedrockModel();
91
+ const config = provider.getConfig();
92
+ expect(config.modelId).toBeDefined();
93
+ });
94
+ it('uses provided model ID ', () => {
95
+ const customModelId = 'us.anthropic.claude-3-5-sonnet-20241022-v2:0';
96
+ const provider = new BedrockModel({ modelId: customModelId });
97
+ expect(provider.getConfig()).toStrictEqual({
98
+ modelId: customModelId,
99
+ });
100
+ });
101
+ it('uses provided region', () => {
102
+ const customRegion = 'eu-west-1';
103
+ new BedrockModel({ region: customRegion });
104
+ expect(BedrockRuntimeClient).toHaveBeenCalledWith({
105
+ region: customRegion,
106
+ customUserAgent: 'strands-agents-ts-sdk',
107
+ });
108
+ });
109
+ it('extends custom user agent if provided', () => {
110
+ const customAgent = 'my-app/1.0';
111
+ new BedrockModel({ region: 'us-west-2', clientConfig: { customUserAgent: customAgent } });
112
+ expect(BedrockRuntimeClient).toHaveBeenCalledWith({
113
+ region: 'us-west-2',
114
+ customUserAgent: 'my-app/1.0 strands-agents-ts-sdk',
115
+ });
116
+ });
117
+ it('passes custom endpoint to client', () => {
118
+ const endpoint = 'https://vpce-abc.bedrock-runtime.us-west-2.vpce.amazonaws.com';
119
+ const region = 'us-west-2';
120
+ new BedrockModel({ region, clientConfig: { endpoint } });
121
+ expect(BedrockRuntimeClient).toHaveBeenCalledWith({
122
+ region,
123
+ endpoint,
124
+ customUserAgent: 'strands-agents-ts-sdk',
125
+ });
126
+ });
127
+ it('passes custom credentials to client', () => {
128
+ const credentials = {
129
+ accessKeyId: 'AKIAIOSFODNN7EXAMPLE',
130
+ secretAccessKey: 'wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY',
131
+ };
132
+ const region = 'us-west-2';
133
+ new BedrockModel({ region, clientConfig: { credentials } });
134
+ expect(BedrockRuntimeClient).toHaveBeenCalledWith({
135
+ region,
136
+ credentials,
137
+ customUserAgent: 'strands-agents-ts-sdk',
138
+ });
139
+ });
140
+ });
141
+ describe('updateConfig', () => {
142
+ it('merges new config with existing config', () => {
143
+ const provider = new BedrockModel({ region: 'us-west-2', temperature: 0.5 });
144
+ provider.updateConfig({ temperature: 0.8, maxTokens: 2048 });
145
+ expect(provider.getConfig()).toStrictEqual({
146
+ modelId: 'global.anthropic.claude-sonnet-4-5-20250929-v1:0',
147
+ temperature: 0.8,
148
+ maxTokens: 2048,
149
+ });
150
+ });
151
+ it('preserves fields not included in the update', () => {
152
+ const provider = new BedrockModel({
153
+ region: 'us-west-2',
154
+ modelId: 'custom-model',
155
+ temperature: 0.5,
156
+ maxTokens: 1024,
157
+ });
158
+ provider.updateConfig({ temperature: 0.8 });
159
+ expect(provider.getConfig()).toStrictEqual({
160
+ modelId: 'custom-model',
161
+ temperature: 0.8,
162
+ maxTokens: 1024,
163
+ });
164
+ });
165
+ });
166
+ describe('getConfig', () => {
167
+ it('returns the current configuration', () => {
168
+ const provider = new BedrockModel({
169
+ region: 'us-west-2',
170
+ modelId: 'test-model',
171
+ maxTokens: 1024,
172
+ temperature: 0.7,
173
+ });
174
+ expect(provider.getConfig()).toStrictEqual({
175
+ modelId: 'test-model',
176
+ maxTokens: 1024,
177
+ temperature: 0.7,
178
+ });
179
+ });
180
+ });
181
+ describe('format_message', async () => {
182
+ const { ConverseStreamCommand } = await import('@aws-sdk/client-bedrock-runtime');
183
+ const mockConverseStreamCommand = vi.mocked(ConverseStreamCommand);
184
+ it('formats the request to bedrock properly', async () => {
185
+ const provider = new BedrockModel({
186
+ region: 'us-west-2',
187
+ modelId: 'test-model',
188
+ maxTokens: 1024,
189
+ temperature: 0.7,
190
+ topP: 0.9,
191
+ stopSequences: ['STOP'],
192
+ cachePrompt: 'default',
193
+ cacheTools: 'default',
194
+ additionalResponseFieldPaths: ['Hello!'],
195
+ additionalRequestFields: ['World!'],
196
+ additionalArgs: {
197
+ MyExtraArg: 'ExtraArg',
198
+ },
199
+ });
200
+ const messages = [{ type: 'message', role: 'user', content: [{ type: 'textBlock', text: 'Hello' }] }];
201
+ const options = {
202
+ systemPrompt: 'You are a helpful assistant',
203
+ toolSpecs: [
204
+ {
205
+ name: 'calculator',
206
+ description: 'Perform calculations',
207
+ inputSchema: { type: 'object', properties: { expression: { type: 'string' } } },
208
+ },
209
+ ],
210
+ toolChoice: { auto: {} },
211
+ };
212
+ // Trigger the stream to make the request, but ignore the events for now
213
+ collectIterator(provider.stream(messages, options));
214
+ // Verify ConverseStreamCommand was called with properly formatted request
215
+ expect(mockConverseStreamCommand).toHaveBeenLastCalledWith({
216
+ MyExtraArg: 'ExtraArg',
217
+ additionalModelRequestFields: ['World!'],
218
+ additionalModelResponseFieldPaths: ['Hello!'],
219
+ modelId: 'test-model',
220
+ messages: [
221
+ {
222
+ role: 'user',
223
+ content: [{ text: 'Hello' }],
224
+ },
225
+ ],
226
+ system: [{ text: 'You are a helpful assistant' }, { cachePoint: { type: 'default' } }],
227
+ toolConfig: {
228
+ toolChoice: { auto: {} },
229
+ tools: [
230
+ {
231
+ toolSpec: {
232
+ name: 'calculator',
233
+ description: 'Perform calculations',
234
+ inputSchema: { json: { type: 'object', properties: { expression: { type: 'string' } } } },
235
+ },
236
+ },
237
+ { cachePoint: { type: 'default' } },
238
+ ],
239
+ },
240
+ inferenceConfig: {
241
+ maxTokens: 1024,
242
+ temperature: 0.7,
243
+ topP: 0.9,
244
+ stopSequences: ['STOP'],
245
+ },
246
+ });
247
+ });
248
+ it('formats tool use messages', async () => {
249
+ const { ConverseStreamCommand } = await import('@aws-sdk/client-bedrock-runtime');
250
+ const mockConverseStreamCommand = vi.mocked(ConverseStreamCommand);
251
+ const provider = new BedrockModel();
252
+ const messages = [
253
+ {
254
+ type: 'message',
255
+ role: 'assistant',
256
+ content: [
257
+ {
258
+ type: 'toolUseBlock',
259
+ name: 'calculator',
260
+ toolUseId: 'tool-123',
261
+ input: { a: 5, b: 3 },
262
+ },
263
+ ],
264
+ },
265
+ ];
266
+ // Run the stream but ignore the output
267
+ collectIterator(provider.stream(messages));
268
+ // Verify ConverseStreamCommand was called with properly formatted request
269
+ expect(mockConverseStreamCommand).toHaveBeenLastCalledWith(expect.objectContaining({
270
+ messages: expect.arrayContaining([
271
+ expect.objectContaining({
272
+ role: 'assistant',
273
+ content: expect.arrayContaining([
274
+ expect.objectContaining({
275
+ toolUse: expect.objectContaining({
276
+ name: 'calculator',
277
+ toolUseId: 'tool-123',
278
+ input: { a: 5, b: 3 },
279
+ }),
280
+ }),
281
+ ]),
282
+ }),
283
+ ]),
284
+ }));
285
+ });
286
+ it('formats tool result messages', async () => {
287
+ const provider = new BedrockModel();
288
+ const messages = [
289
+ {
290
+ type: 'message',
291
+ role: 'user',
292
+ content: [
293
+ {
294
+ type: 'toolResultBlock',
295
+ toolUseId: 'tool-123',
296
+ status: 'success',
297
+ content: [
298
+ { type: 'toolResultTextContent', text: 'Result: 8' },
299
+ { type: 'toolResultJsonContent', json: { hello: 'world' } },
300
+ ],
301
+ },
302
+ ],
303
+ },
304
+ ];
305
+ // Start the stream
306
+ collectIterator(provider.stream(messages));
307
+ // Verify ConverseStreamCommand was called with properly formatted request
308
+ expect(mockConverseStreamCommand).toHaveBeenLastCalledWith({
309
+ messages: [
310
+ {
311
+ content: [
312
+ {
313
+ toolResult: {
314
+ content: [
315
+ {
316
+ text: 'Result: 8',
317
+ },
318
+ {
319
+ json: {
320
+ hello: 'world',
321
+ },
322
+ },
323
+ ],
324
+ status: 'success',
325
+ toolUseId: 'tool-123',
326
+ },
327
+ },
328
+ ],
329
+ role: 'user',
330
+ },
331
+ ],
332
+ modelId: expect.any(String),
333
+ });
334
+ });
335
+ it('formats reasoning messages properly', async () => {
336
+ const provider = new BedrockModel();
337
+ const messages = [
338
+ {
339
+ type: 'message',
340
+ role: 'user',
341
+ content: [
342
+ {
343
+ type: 'reasoningBlock',
344
+ text: 'Hello',
345
+ signature: 'World',
346
+ },
347
+ {
348
+ type: 'reasoningBlock',
349
+ redactedContent: new Uint8Array(1),
350
+ },
351
+ ],
352
+ },
353
+ ];
354
+ // Start the stream but don't await it
355
+ collectIterator(provider.stream(messages));
356
+ // Verify ConverseStreamCommand was called with properly formatted request
357
+ expect(mockConverseStreamCommand).toHaveBeenLastCalledWith({
358
+ messages: [
359
+ {
360
+ role: 'user',
361
+ content: [
362
+ {
363
+ reasoningContent: {
364
+ reasoningText: {
365
+ signature: 'World',
366
+ text: 'Hello',
367
+ },
368
+ },
369
+ },
370
+ {
371
+ reasoningContent: {
372
+ redactedContent: new Uint8Array(1),
373
+ },
374
+ },
375
+ ],
376
+ },
377
+ ],
378
+ modelId: expect.any(String),
379
+ });
380
+ });
381
+ it('formats cache point blocks in messages', async () => {
382
+ const provider = new BedrockModel();
383
+ const messages = [
384
+ {
385
+ type: 'message',
386
+ role: 'user',
387
+ content: [
388
+ { type: 'textBlock', text: 'Message with cache point' },
389
+ { type: 'cachePointBlock', cacheType: 'default' },
390
+ ],
391
+ },
392
+ ];
393
+ collectIterator(provider.stream(messages));
394
+ // Verify ConverseStreamCommand was called with properly formatted request
395
+ expect(mockConverseStreamCommand).toHaveBeenLastCalledWith({
396
+ messages: [
397
+ {
398
+ role: 'user',
399
+ content: [{ text: 'Message with cache point' }, { cachePoint: { type: 'default' } }],
400
+ },
401
+ ],
402
+ modelId: expect.any(String),
403
+ });
404
+ });
405
+ });
406
+ describe.each([
407
+ { mode: 'streaming', stream: true },
408
+ { mode: 'non-streaming', stream: false },
409
+ ])('BedrockModel in $mode mode', ({ stream }) => {
410
+ it('yields and validates text events correctly', async () => {
411
+ const mockSend = vi.fn(async () => {
412
+ if (stream) {
413
+ return {
414
+ stream: (async function* () {
415
+ yield { messageStart: { role: 'assistant' } };
416
+ yield { contentBlockStart: { contentBlockIndex: 0 } };
417
+ yield { contentBlockDelta: { delta: { text: 'Hello' }, contentBlockIndex: 0 } };
418
+ yield { contentBlockStop: { contentBlockIndex: 0 } };
419
+ yield { messageStop: { stopReason: 'end_turn' } };
420
+ yield {
421
+ metadata: { usage: { inputTokens: 10, outputTokens: 5, totalTokens: 15 }, metrics: { latencyMs: 100 } },
422
+ };
423
+ })(),
424
+ };
425
+ }
426
+ else {
427
+ return {
428
+ output: { message: { role: 'assistant', content: [{ text: 'Hello' }] } },
429
+ stopReason: 'end_turn',
430
+ usage: { inputTokens: 10, outputTokens: 5, totalTokens: 15 },
431
+ metrics: { latencyMs: 100 },
432
+ };
433
+ }
434
+ });
435
+ vi.mocked(BedrockRuntimeClient).mockImplementation(() => ({ send: mockSend }));
436
+ const provider = new BedrockModel({ stream });
437
+ const messages = [{ type: 'message', role: 'user', content: [{ type: 'textBlock', text: 'Hello' }] }];
438
+ const events = await collectIterator(provider.stream(messages));
439
+ expect(events).toContainEqual({ role: 'assistant', type: 'modelMessageStartEvent' });
440
+ expect(events).toContainEqual({ type: 'modelContentBlockStartEvent', contentBlockIndex: 0 });
441
+ expect(events).toContainEqual({
442
+ type: 'modelContentBlockDeltaEvent',
443
+ contentBlockIndex: 0,
444
+ delta: { type: 'textDelta', text: 'Hello' },
445
+ });
446
+ expect(events).toContainEqual({ type: 'modelContentBlockStopEvent', contentBlockIndex: 0 });
447
+ expect(events).toContainEqual({ type: 'modelMessageStopEvent', stopReason: 'endTurn' });
448
+ expect(events).toContainEqual({
449
+ type: 'modelMetadataEvent',
450
+ usage: { inputTokens: 10, outputTokens: 5, totalTokens: 15 },
451
+ metrics: { latencyMs: 100 },
452
+ });
453
+ });
454
+ it('yields and validates toolUse events correctly', async () => {
455
+ const mockSend = vi.fn(async () => {
456
+ if (stream) {
457
+ return {
458
+ stream: (async function* () {
459
+ yield { messageStart: { role: 'assistant' } };
460
+ yield {
461
+ contentBlockStart: {
462
+ contentBlockIndex: 0,
463
+ start: { toolUse: { toolUseId: 'tool-use-123', name: 'get_weather' } },
464
+ },
465
+ };
466
+ yield {
467
+ contentBlockDelta: {
468
+ contentBlockIndex: 0,
469
+ delta: { toolUse: { input: '{"location":"San Francisco"}' } },
470
+ },
471
+ };
472
+ yield { contentBlockStop: { contentBlockIndex: 0 } };
473
+ yield { messageStop: { stopReason: 'tool_use' } };
474
+ yield {
475
+ metadata: {
476
+ usage: { inputTokens: 10, outputTokens: 25, totalTokens: 35 },
477
+ metrics: { latencyMs: 120 },
478
+ },
479
+ };
480
+ })(),
481
+ };
482
+ }
483
+ else {
484
+ return {
485
+ output: {
486
+ message: {
487
+ role: 'assistant',
488
+ content: [
489
+ { toolUse: { toolUseId: 'tool-use-123', name: 'get_weather', input: { location: 'San Francisco' } } },
490
+ ],
491
+ },
492
+ },
493
+ stopReason: 'tool_use',
494
+ usage: { inputTokens: 10, outputTokens: 25, totalTokens: 35 },
495
+ metrics: { latencyMs: 120 },
496
+ };
497
+ }
498
+ });
499
+ vi.mocked(BedrockRuntimeClient).mockImplementation(() => ({ send: mockSend }));
500
+ const provider = new BedrockModel({ stream });
501
+ const messages = [
502
+ { type: 'message', role: 'user', content: [{ type: 'textBlock', text: 'Weather?' }] },
503
+ ];
504
+ const events = await collectIterator(provider.stream(messages));
505
+ const startEvent = events.find((e) => e.type === 'modelContentBlockStartEvent');
506
+ const inputDeltaEvent = events.find((e) => e.type === 'modelContentBlockDeltaEvent' && e.delta.type === 'toolUseInputDelta');
507
+ expect(events).toContainEqual({ role: 'assistant', type: 'modelMessageStartEvent' });
508
+ expect(startEvent).toStrictEqual({
509
+ type: 'modelContentBlockStartEvent',
510
+ contentBlockIndex: 0,
511
+ start: { type: 'toolUseStart', name: 'get_weather', toolUseId: 'tool-use-123' },
512
+ });
513
+ expect(inputDeltaEvent).toStrictEqual({
514
+ type: 'modelContentBlockDeltaEvent',
515
+ contentBlockIndex: 0,
516
+ delta: { type: 'toolUseInputDelta', input: '{"location":"San Francisco"}' },
517
+ });
518
+ expect(events).toContainEqual({ type: 'modelContentBlockStopEvent', contentBlockIndex: 0 });
519
+ expect(events).toContainEqual({ stopReason: 'toolUse', type: 'modelMessageStopEvent' });
520
+ expect(events).toContainEqual({
521
+ type: 'modelMetadataEvent',
522
+ usage: { inputTokens: 10, outputTokens: 25, totalTokens: 35 },
523
+ metrics: { latencyMs: 120 },
524
+ });
525
+ });
526
+ it('yields and validates reasoningText events correctly', async () => {
527
+ const mockSend = vi.fn(async () => {
528
+ if (stream) {
529
+ return {
530
+ stream: (async function* () {
531
+ yield { messageStart: { role: 'assistant' } };
532
+ yield { contentBlockStart: { contentBlockIndex: 0 } };
533
+ yield {
534
+ contentBlockDelta: { contentBlockIndex: 0, delta: { reasoningContent: { text: 'Thinking...' } } },
535
+ };
536
+ yield { contentBlockStop: { contentBlockIndex: 0 } };
537
+ yield { messageStop: { stopReason: 'end_turn' } };
538
+ yield {
539
+ metadata: {
540
+ usage: { inputTokens: 15, outputTokens: 30, totalTokens: 45 },
541
+ metrics: { latencyMs: 150 },
542
+ },
543
+ };
544
+ })(),
545
+ };
546
+ }
547
+ else {
548
+ return {
549
+ output: {
550
+ message: {
551
+ role: 'assistant',
552
+ content: [{ reasoningContent: { reasoningText: { text: 'Thinking...' } } }],
553
+ },
554
+ },
555
+ stopReason: 'end_turn',
556
+ usage: { inputTokens: 15, outputTokens: 30, totalTokens: 45 },
557
+ metrics: { latencyMs: 150 },
558
+ };
559
+ }
560
+ });
561
+ vi.mocked(BedrockRuntimeClient).mockImplementation(() => ({ send: mockSend }));
562
+ const provider = new BedrockModel({ stream });
563
+ const messages = [
564
+ { type: 'message', role: 'user', content: [{ type: 'textBlock', text: 'A question.' }] },
565
+ ];
566
+ const events = await collectIterator(provider.stream(messages));
567
+ expect(events).toContainEqual({ role: 'assistant', type: 'modelMessageStartEvent' });
568
+ expect(events).toContainEqual({ type: 'modelContentBlockStartEvent', contentBlockIndex: 0 });
569
+ expect(events).toContainEqual({
570
+ type: 'modelContentBlockDeltaEvent',
571
+ contentBlockIndex: 0,
572
+ delta: { type: 'reasoningContentDelta', text: 'Thinking...' },
573
+ });
574
+ expect(events).toContainEqual({ type: 'modelContentBlockStopEvent', contentBlockIndex: 0 });
575
+ expect(events).toContainEqual({ stopReason: 'endTurn', type: 'modelMessageStopEvent' });
576
+ expect(events).toContainEqual({
577
+ type: 'modelMetadataEvent',
578
+ usage: { inputTokens: 15, outputTokens: 30, totalTokens: 45 },
579
+ metrics: { latencyMs: 150 },
580
+ });
581
+ });
582
+ it('yields and validates redactedContent events correctly', async () => {
583
+ const redactedBytes = new Uint8Array([1, 2, 3]);
584
+ const mockSend = vi.fn(async () => {
585
+ if (stream) {
586
+ return {
587
+ stream: (async function* () {
588
+ yield { messageStart: { role: 'assistant' } };
589
+ yield { contentBlockStart: { contentBlockIndex: 0 } };
590
+ yield {
591
+ contentBlockDelta: {
592
+ contentBlockIndex: 0,
593
+ delta: { reasoningContent: { redactedContent: redactedBytes } },
594
+ },
595
+ };
596
+ yield { contentBlockStop: { contentBlockIndex: 0 } };
597
+ yield { messageStop: { stopReason: 'end_turn' } };
598
+ yield {
599
+ metadata: { usage: { inputTokens: 15, outputTokens: 5, totalTokens: 20 }, metrics: { latencyMs: 110 } },
600
+ };
601
+ })(),
602
+ };
603
+ }
604
+ else {
605
+ return {
606
+ output: {
607
+ message: {
608
+ role: 'assistant',
609
+ content: [{ reasoningContent: { redactedContent: redactedBytes } }],
610
+ },
611
+ },
612
+ stopReason: 'end_turn',
613
+ usage: { inputTokens: 15, outputTokens: 5, totalTokens: 20 },
614
+ metrics: { latencyMs: 110 },
615
+ };
616
+ }
617
+ });
618
+ vi.mocked(BedrockRuntimeClient).mockImplementation(() => ({ send: mockSend }));
619
+ const provider = new BedrockModel({ stream });
620
+ const messages = [
621
+ { type: 'message', role: 'user', content: [{ type: 'textBlock', text: 'A sensitive question.' }] },
622
+ ];
623
+ const events = await collectIterator(provider.stream(messages));
624
+ expect(events).toContainEqual({ role: 'assistant', type: 'modelMessageStartEvent' });
625
+ expect(events).toContainEqual({ type: 'modelContentBlockStartEvent', contentBlockIndex: 0 });
626
+ expect(events).toContainEqual({
627
+ type: 'modelContentBlockDeltaEvent',
628
+ contentBlockIndex: 0,
629
+ delta: { type: 'reasoningContentDelta', redactedContent: redactedBytes },
630
+ });
631
+ expect(events).toContainEqual({ type: 'modelContentBlockStopEvent', contentBlockIndex: 0 });
632
+ expect(events).toContainEqual({ stopReason: 'endTurn', type: 'modelMessageStopEvent' });
633
+ expect(events).toContainEqual({
634
+ type: 'modelMetadataEvent',
635
+ usage: { inputTokens: 15, outputTokens: 5, totalTokens: 20 },
636
+ metrics: { latencyMs: 110 },
637
+ });
638
+ });
639
+ describe('error handling', async () => {
640
+ const { ValidationException } = await import('@aws-sdk/client-bedrock-runtime');
641
+ it.each([
642
+ {
643
+ name: 'ContextWindowOverflowError for context overflow',
644
+ error: new Error('Input is too long for requested model'),
645
+ expected: ContextWindowOverflowError,
646
+ },
647
+ {
648
+ name: 'ValidationException for invalid input',
649
+ error: new ValidationException({ message: 'ValidationException', $metadata: {} }),
650
+ expected: ValidationException,
651
+ },
652
+ ])('throws $name', async ({ error, expected }) => {
653
+ vi.clearAllMocks();
654
+ const mockSendError = vi.fn().mockRejectedValue(error);
655
+ vi.mocked(BedrockRuntimeClient).mockImplementation(() => ({ send: mockSendError }));
656
+ const provider = new BedrockModel();
657
+ const messages = [{ type: 'message', role: 'user', content: [{ type: 'textBlock', text: 'Hello' }] }];
658
+ await expect(collectIterator(provider.stream(messages))).rejects.toThrow(expected);
659
+ });
660
+ });
661
+ });
662
+ describe('stream', () => {
663
+ it('handles tool use input delta', async () => {
664
+ setupMockSend(async function* () {
665
+ yield { messageStart: { role: 'assistant' } };
666
+ yield {
667
+ contentBlockStart: { contentBlockIndex: 0, start: { toolUse: { name: 'calc', toolUseId: 'id' } } },
668
+ };
669
+ yield { contentBlockDelta: { delta: { toolUse: { input: '{"a": 1}' } }, contentBlockIndex: 0 } };
670
+ yield { contentBlockStop: { contentBlockIndex: 0 } };
671
+ yield { messageStop: { stopReason: 'tool_use' } };
672
+ yield { metadata: { usage: { inputTokens: 10, outputTokens: 5, totalTokens: 15 } } };
673
+ });
674
+ const provider = new BedrockModel();
675
+ const messages = [{ type: 'message', role: 'user', content: [{ type: 'textBlock', text: 'Hello' }] }];
676
+ const events = await collectIterator(provider.stream(messages));
677
+ expect(events).toContainEqual({
678
+ type: 'modelContentBlockDeltaEvent',
679
+ contentBlockIndex: 0,
680
+ delta: {
681
+ type: 'toolUseInputDelta',
682
+ input: '{"a": 1}',
683
+ },
684
+ });
685
+ });
686
+ it('handles reasoning content delta with both text and signature, as well as redactedContent', async () => {
687
+ setupMockSend(async function* () {
688
+ yield { messageStart: { role: 'assistant' } };
689
+ yield { contentBlockStart: { contentBlockIndex: 0 } };
690
+ yield {
691
+ contentBlockDelta: {
692
+ delta: { reasoningContent: { text: 'thinking...', signature: 'sig123' } },
693
+ contentBlockIndex: 0,
694
+ },
695
+ };
696
+ yield {
697
+ contentBlockDelta: {
698
+ delta: { reasoningContent: { redactedContent: new Uint8Array(1) } },
699
+ contentBlockIndex: 0,
700
+ },
701
+ };
702
+ yield { contentBlockStop: { contentBlockIndex: 0 } };
703
+ yield { messageStop: { stopReason: 'end_turn' } };
704
+ yield { metadata: { usage: { inputTokens: 10, outputTokens: 5, totalTokens: 15 } } };
705
+ });
706
+ const provider = new BedrockModel();
707
+ const messages = [{ type: 'message', role: 'user', content: [{ type: 'textBlock', text: 'Hello' }] }];
708
+ const events = await collectIterator(provider.stream(messages));
709
+ expect(events).toContainEqual({
710
+ type: 'modelContentBlockDeltaEvent',
711
+ contentBlockIndex: 0,
712
+ delta: {
713
+ type: 'reasoningContentDelta',
714
+ text: 'thinking...',
715
+ signature: 'sig123',
716
+ },
717
+ });
718
+ expect(events).toContainEqual({
719
+ type: 'modelContentBlockDeltaEvent',
720
+ contentBlockIndex: 0,
721
+ delta: {
722
+ type: 'reasoningContentDelta',
723
+ redactedContent: new Uint8Array(1),
724
+ },
725
+ });
726
+ });
727
+ it('handles reasoning content delta with only text, skips unsupported types', async () => {
728
+ setupMockSend(async function* () {
729
+ yield { messageStart: { role: 'assistant' } };
730
+ yield { contentBlockStart: { contentBlockIndex: 0 } };
731
+ yield {
732
+ contentBlockDelta: {
733
+ delta: { reasoningContent: { text: 'thinking...' } },
734
+ contentBlockIndex: 0,
735
+ },
736
+ };
737
+ yield {
738
+ contentBlockDelta: {
739
+ delta: { unknown: 'type' },
740
+ contentBlockIndex: 0,
741
+ },
742
+ };
743
+ yield { contentBlockStop: { contentBlockIndex: 0 } };
744
+ yield { messageStop: { stopReason: 'end_turn' } };
745
+ yield { metadata: { usage: { inputTokens: 10, outputTokens: 5, totalTokens: 15 } } };
746
+ yield { unknown: 'type' };
747
+ });
748
+ const provider = new BedrockModel();
749
+ const messages = [{ type: 'message', role: 'user', content: [{ type: 'textBlock', text: 'Hello' }] }];
750
+ const events = await collectIterator(provider.stream(messages));
751
+ const reasoningDelta = events.find((e) => e.type === 'modelContentBlockDeltaEvent' && e.delta.type === 'reasoningContentDelta');
752
+ expect(reasoningDelta).toBeDefined();
753
+ if (reasoningDelta?.type === 'modelContentBlockDeltaEvent' &&
754
+ reasoningDelta.delta.type === 'reasoningContentDelta') {
755
+ expect(reasoningDelta.delta.text).toBe('thinking...');
756
+ expect(reasoningDelta.delta.signature).toBeUndefined();
757
+ }
758
+ });
759
+ it('handles reasoning content delta with only signature', async () => {
760
+ setupMockSend(async function* () {
761
+ yield { messageStart: { role: 'assistant' } };
762
+ yield { contentBlockStart: { contentBlockIndex: 0 } };
763
+ yield {
764
+ contentBlockDelta: {
765
+ delta: { reasoningContent: { signature: 'sig123' } },
766
+ contentBlockIndex: 0,
767
+ },
768
+ };
769
+ yield { contentBlockStop: { contentBlockIndex: 0 } };
770
+ yield { messageStop: { stopReason: 'end_turn' } };
771
+ yield { metadata: { usage: { inputTokens: 10, outputTokens: 5, totalTokens: 15 } } };
772
+ });
773
+ const provider = new BedrockModel();
774
+ const messages = [{ type: 'message', role: 'user', content: [{ type: 'textBlock', text: 'Hello' }] }];
775
+ const events = await collectIterator(provider.stream(messages));
776
+ const reasoningDelta = events.find((e) => e.type === 'modelContentBlockDeltaEvent' && e.delta.type === 'reasoningContentDelta');
777
+ expect(reasoningDelta).toBeDefined();
778
+ if (reasoningDelta?.type === 'modelContentBlockDeltaEvent' &&
779
+ reasoningDelta.delta.type === 'reasoningContentDelta') {
780
+ expect(reasoningDelta.delta.text).toBeUndefined();
781
+ expect(reasoningDelta.delta.signature).toBe('sig123');
782
+ }
783
+ });
784
+ it('handles cache usage metrics', async () => {
785
+ setupMockSend(async function* () {
786
+ yield { messageStart: { role: 'assistant' } };
787
+ yield { contentBlockStart: { contentBlockIndex: 0 } };
788
+ yield { contentBlockDelta: { delta: { text: 'Hello' }, contentBlockIndex: 0 } };
789
+ yield { contentBlockStop: { contentBlockIndex: 0 } };
790
+ yield { messageStop: { stopReason: 'end_turn' } };
791
+ yield {
792
+ metadata: {
793
+ usage: {
794
+ inputTokens: 100,
795
+ outputTokens: 50,
796
+ totalTokens: 150,
797
+ cacheReadInputTokens: 80,
798
+ cacheWriteInputTokens: 20,
799
+ },
800
+ },
801
+ };
802
+ });
803
+ const provider = new BedrockModel();
804
+ const messages = [{ type: 'message', role: 'user', content: [{ type: 'textBlock', text: 'Hello' }] }];
805
+ const events = await collectIterator(provider.stream(messages));
806
+ const metadataEvent = events.find((e) => e.type === 'modelMetadataEvent');
807
+ expect(metadataEvent).toBeDefined();
808
+ if (metadataEvent?.type === 'modelMetadataEvent') {
809
+ expect(metadataEvent.usage?.cacheReadInputTokens).toBe(80);
810
+ expect(metadataEvent.usage?.cacheWriteInputTokens).toBe(20);
811
+ }
812
+ });
813
+ it('handles trace in metadata', async () => {
814
+ setupMockSend(async function* () {
815
+ yield { messageStart: { role: 'assistant' } };
816
+ yield { contentBlockStart: { contentBlockIndex: 0 } };
817
+ yield { contentBlockDelta: { delta: { text: 'Hello' }, contentBlockIndex: 0 } };
818
+ yield { contentBlockStop: { contentBlockIndex: 0 } };
819
+ yield { messageStop: { stopReason: 'end_turn' } };
820
+ yield {
821
+ metadata: {
822
+ usage: { inputTokens: 10, outputTokens: 5, totalTokens: 15 },
823
+ trace: { guardrail: { action: 'INTERVENED' } },
824
+ },
825
+ };
826
+ });
827
+ const provider = new BedrockModel();
828
+ const messages = [{ type: 'message', role: 'user', content: [{ type: 'textBlock', text: 'Hello' }] }];
829
+ const events = await collectIterator(provider.stream(messages));
830
+ const metadataEvent = events.find((e) => e.type === 'modelMetadataEvent');
831
+ expect(metadataEvent).toBeDefined();
832
+ if (metadataEvent?.type === 'modelMetadataEvent') {
833
+ expect(metadataEvent.trace).toBeDefined();
834
+ }
835
+ });
836
+ it('handles additionalModelResponseFields', async () => {
837
+ setupMockSend(async function* () {
838
+ yield { messageStart: { role: 'assistant' } };
839
+ yield { contentBlockStart: { contentBlockIndex: 0 } };
840
+ yield { contentBlockDelta: { delta: { text: 'Hello' }, contentBlockIndex: 0 } };
841
+ yield { contentBlockStop: { contentBlockIndex: 0 } };
842
+ yield { messageStop: { stopReason: 'end_turn', additionalModelResponseFields: { customField: 'value' } } };
843
+ yield { metadata: { usage: { inputTokens: 10, outputTokens: 5, totalTokens: 15 } } };
844
+ });
845
+ const provider = new BedrockModel();
846
+ const messages = [{ type: 'message', role: 'user', content: [{ type: 'textBlock', text: 'Hello' }] }];
847
+ const events = await collectIterator(provider.stream(messages));
848
+ const stopEvent = events.find((e) => e.type === 'modelMessageStopEvent');
849
+ expect(stopEvent).toBeDefined();
850
+ if (stopEvent?.type === 'modelMessageStopEvent') {
851
+ expect(stopEvent.additionalModelResponseFields).toStrictEqual({ customField: 'value' });
852
+ }
853
+ });
854
+ describe('handles all stop reason types', () => {
855
+ const stopReasons = [
856
+ ['end_turn', 'endTurn'],
857
+ ['tool_use', 'toolUse'],
858
+ ['max_tokens', 'maxTokens'],
859
+ ['stop_sequence', 'stopSequence'],
860
+ ['content_filtered', 'contentFiltered'],
861
+ ['guardrail_intervened', 'guardrailIntervened'],
862
+ ['model_context_window_exceeded', 'modelContextWindowExceeded'],
863
+ ['new_stop_reason', 'newStopReason'],
864
+ ];
865
+ for (const [bedrockReason, expectedReason] of stopReasons) {
866
+ it(`handles ${bedrockReason} stop reason types`, async () => {
867
+ setupMockSend(async function* () {
868
+ yield { messageStart: { role: 'assistant' } };
869
+ yield { messageStop: { stopReason: bedrockReason } };
870
+ yield { metadata: { usage: { inputTokens: 10, outputTokens: 5, totalTokens: 15 } } };
871
+ });
872
+ const provider = new BedrockModel();
873
+ const messages = [
874
+ { type: 'message', role: 'user', content: [{ type: 'textBlock', text: 'Hello' }] },
875
+ ];
876
+ const events = [];
877
+ for await (const event of provider.stream(messages)) {
878
+ events.push(event);
879
+ }
880
+ const stopEvent = events.find((e) => e.type === 'modelMessageStopEvent');
881
+ expect(stopEvent).toBeDefined();
882
+ if (stopEvent?.type === 'modelMessageStopEvent') {
883
+ expect(stopEvent.stopReason).toBe(expectedReason);
884
+ }
885
+ });
886
+ }
887
+ });
888
+ });
889
+ describe('system prompt formatting', async () => {
890
+ const { ConverseStreamCommand } = await import('@aws-sdk/client-bedrock-runtime');
891
+ const mockConverseStreamCommand = vi.mocked(ConverseStreamCommand);
892
+ beforeEach(() => {
893
+ vi.clearAllMocks();
894
+ });
895
+ it('formats string system prompt with cachePrompt config', async () => {
896
+ const provider = new BedrockModel({ cachePrompt: 'default' });
897
+ const messages = [{ type: 'message', role: 'user', content: [{ type: 'textBlock', text: 'Hello' }] }];
898
+ const options = {
899
+ systemPrompt: 'You are a helpful assistant',
900
+ };
901
+ collectIterator(provider.stream(messages, options));
902
+ expect(mockConverseStreamCommand).toHaveBeenLastCalledWith({
903
+ modelId: 'global.anthropic.claude-sonnet-4-5-20250929-v1:0',
904
+ messages: [
905
+ {
906
+ role: 'user',
907
+ content: [{ text: 'Hello' }],
908
+ },
909
+ ],
910
+ system: [{ text: 'You are a helpful assistant' }, { cachePoint: { type: 'default' } }],
911
+ });
912
+ });
913
+ it('formats array system prompt with text blocks only', async () => {
914
+ const provider = new BedrockModel();
915
+ const messages = [{ type: 'message', role: 'user', content: [{ type: 'textBlock', text: 'Hello' }] }];
916
+ const options = {
917
+ systemPrompt: [
918
+ { type: 'textBlock', text: 'You are a helpful assistant' },
919
+ { type: 'textBlock', text: 'Additional context here' },
920
+ ],
921
+ };
922
+ collectIterator(provider.stream(messages, options));
923
+ expect(mockConverseStreamCommand).toHaveBeenLastCalledWith({
924
+ modelId: 'global.anthropic.claude-sonnet-4-5-20250929-v1:0',
925
+ messages: [
926
+ {
927
+ role: 'user',
928
+ content: [{ text: 'Hello' }],
929
+ },
930
+ ],
931
+ system: [{ text: 'You are a helpful assistant' }, { text: 'Additional context here' }],
932
+ });
933
+ });
934
+ it('formats array system prompt with cache points', async () => {
935
+ const provider = new BedrockModel();
936
+ const messages = [{ type: 'message', role: 'user', content: [{ type: 'textBlock', text: 'Hello' }] }];
937
+ const options = {
938
+ systemPrompt: [
939
+ { type: 'textBlock', text: 'You are a helpful assistant' },
940
+ { type: 'textBlock', text: 'Large context document' },
941
+ { type: 'cachePointBlock', cacheType: 'default' },
942
+ ],
943
+ };
944
+ collectIterator(provider.stream(messages, options));
945
+ expect(mockConverseStreamCommand).toHaveBeenLastCalledWith({
946
+ modelId: 'global.anthropic.claude-sonnet-4-5-20250929-v1:0',
947
+ messages: [
948
+ {
949
+ role: 'user',
950
+ content: [{ text: 'Hello' }],
951
+ },
952
+ ],
953
+ system: [
954
+ { text: 'You are a helpful assistant' },
955
+ { text: 'Large context document' },
956
+ { cachePoint: { type: 'default' } },
957
+ ],
958
+ });
959
+ });
960
+ it('warns when both array system prompt and cachePrompt config are provided', async () => {
961
+ const warnSpy = vi.spyOn(console, 'warn').mockImplementation(() => { });
962
+ const provider = new BedrockModel({ cachePrompt: 'default' });
963
+ const messages = [{ type: 'message', role: 'user', content: [{ type: 'textBlock', text: 'Hello' }] }];
964
+ const options = {
965
+ systemPrompt: [
966
+ { type: 'textBlock', text: 'You are a helpful assistant' },
967
+ { type: 'cachePointBlock', cacheType: 'default' },
968
+ ],
969
+ };
970
+ collectIterator(provider.stream(messages, options));
971
+ // Verify warning was logged
972
+ expect(warnSpy).toHaveBeenCalledWith('cachePrompt config is ignored when systemPrompt is an array. Use explicit cache points in the array instead.');
973
+ // Verify array is used as-is (cachePrompt config ignored)
974
+ expect(mockConverseStreamCommand).toHaveBeenLastCalledWith({
975
+ modelId: 'global.anthropic.claude-sonnet-4-5-20250929-v1:0',
976
+ messages: [
977
+ {
978
+ role: 'user',
979
+ content: [{ text: 'Hello' }],
980
+ },
981
+ ],
982
+ system: [{ text: 'You are a helpful assistant' }, { cachePoint: { type: 'default' } }],
983
+ });
984
+ warnSpy.mockRestore();
985
+ });
986
+ it('handles empty array system prompt', async () => {
987
+ const provider = new BedrockModel();
988
+ const messages = [{ type: 'message', role: 'user', content: [{ type: 'textBlock', text: 'Hello' }] }];
989
+ const options = {
990
+ systemPrompt: [],
991
+ };
992
+ collectIterator(provider.stream(messages, options));
993
+ // Empty array should not set system field
994
+ expect(mockConverseStreamCommand).toHaveBeenLastCalledWith({
995
+ modelId: 'global.anthropic.claude-sonnet-4-5-20250929-v1:0',
996
+ messages: [
997
+ {
998
+ role: 'user',
999
+ content: [{ text: 'Hello' }],
1000
+ },
1001
+ ],
1002
+ });
1003
+ });
1004
+ });
1005
+ describe('includeToolResultStatus configuration', async () => {
1006
+ const { ConverseStreamCommand } = await import('@aws-sdk/client-bedrock-runtime');
1007
+ const mockConverseStreamCommand = vi.mocked(ConverseStreamCommand);
1008
+ describe('when includeToolResultStatus is true', () => {
1009
+ it('always includes status field in tool results', async () => {
1010
+ const provider = new BedrockModel({ includeToolResultStatus: true });
1011
+ const messages = [
1012
+ {
1013
+ type: 'message',
1014
+ role: 'user',
1015
+ content: [
1016
+ {
1017
+ type: 'toolResultBlock',
1018
+ toolUseId: 'tool-123',
1019
+ status: 'success',
1020
+ content: [{ type: 'toolResultTextContent', text: 'Result' }],
1021
+ },
1022
+ ],
1023
+ },
1024
+ ];
1025
+ collectIterator(provider.stream(messages));
1026
+ expect(mockConverseStreamCommand).toHaveBeenLastCalledWith({
1027
+ messages: [
1028
+ {
1029
+ content: [
1030
+ {
1031
+ toolResult: {
1032
+ content: [{ text: 'Result' }],
1033
+ status: 'success',
1034
+ toolUseId: 'tool-123',
1035
+ },
1036
+ },
1037
+ ],
1038
+ role: 'user',
1039
+ },
1040
+ ],
1041
+ modelId: expect.any(String),
1042
+ });
1043
+ });
1044
+ });
1045
+ describe('when includeToolResultStatus is false', () => {
1046
+ it('never includes status field in tool results', async () => {
1047
+ const provider = new BedrockModel({ includeToolResultStatus: false });
1048
+ const messages = [
1049
+ {
1050
+ type: 'message',
1051
+ role: 'user',
1052
+ content: [
1053
+ {
1054
+ type: 'toolResultBlock',
1055
+ toolUseId: 'tool-123',
1056
+ status: 'success',
1057
+ content: [{ type: 'toolResultTextContent', text: 'Result' }],
1058
+ },
1059
+ ],
1060
+ },
1061
+ ];
1062
+ collectIterator(provider.stream(messages));
1063
+ expect(mockConverseStreamCommand).toHaveBeenLastCalledWith({
1064
+ messages: [
1065
+ {
1066
+ content: [
1067
+ {
1068
+ toolResult: {
1069
+ content: [{ text: 'Result' }],
1070
+ toolUseId: 'tool-123',
1071
+ },
1072
+ },
1073
+ ],
1074
+ role: 'user',
1075
+ },
1076
+ ],
1077
+ modelId: expect.any(String),
1078
+ });
1079
+ });
1080
+ });
1081
+ describe('when includeToolResultStatus is auto', () => {
1082
+ it('includes status field for Claude models', async () => {
1083
+ const provider = new BedrockModel({
1084
+ modelId: 'anthropic.claude-3-5-sonnet-20241022-v2:0',
1085
+ includeToolResultStatus: 'auto',
1086
+ });
1087
+ const messages = [
1088
+ {
1089
+ type: 'message',
1090
+ role: 'user',
1091
+ content: [
1092
+ {
1093
+ type: 'toolResultBlock',
1094
+ toolUseId: 'tool-123',
1095
+ status: 'success',
1096
+ content: [{ type: 'toolResultTextContent', text: 'Result' }],
1097
+ },
1098
+ ],
1099
+ },
1100
+ ];
1101
+ collectIterator(provider.stream(messages));
1102
+ expect(mockConverseStreamCommand).toHaveBeenLastCalledWith({
1103
+ messages: [
1104
+ {
1105
+ content: [
1106
+ {
1107
+ toolResult: {
1108
+ content: [{ text: 'Result' }],
1109
+ status: 'success',
1110
+ toolUseId: 'tool-123',
1111
+ },
1112
+ },
1113
+ ],
1114
+ role: 'user',
1115
+ },
1116
+ ],
1117
+ modelId: 'anthropic.claude-3-5-sonnet-20241022-v2:0',
1118
+ });
1119
+ });
1120
+ });
1121
+ describe('when includeToolResultStatus is undefined (default)', () => {
1122
+ it('follows auto logic for non-Claude models', async () => {
1123
+ const provider = new BedrockModel({
1124
+ modelId: 'amazon.nova-lite-v1:0',
1125
+ });
1126
+ const messages = [
1127
+ {
1128
+ type: 'message',
1129
+ role: 'user',
1130
+ content: [
1131
+ {
1132
+ type: 'toolResultBlock',
1133
+ toolUseId: 'tool-123',
1134
+ status: 'success',
1135
+ content: [{ type: 'toolResultTextContent', text: 'Result' }],
1136
+ },
1137
+ ],
1138
+ },
1139
+ ];
1140
+ collectIterator(provider.stream(messages));
1141
+ expect(mockConverseStreamCommand).toHaveBeenLastCalledWith({
1142
+ messages: [
1143
+ {
1144
+ content: [
1145
+ {
1146
+ toolResult: {
1147
+ content: [{ text: 'Result' }],
1148
+ toolUseId: 'tool-123',
1149
+ },
1150
+ },
1151
+ ],
1152
+ role: 'user',
1153
+ },
1154
+ ],
1155
+ modelId: 'amazon.nova-lite-v1:0',
1156
+ });
1157
+ });
1158
+ });
1159
+ });
1160
+ });
1161
+ //# sourceMappingURL=bedrock.test.js.map