@strands-agents/sdk 1.6.0 → 1.8.0

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 (708) hide show
  1. package/dist/src/agent/agent.d.ts +1 -1
  2. package/dist/src/agent/agent.d.ts.map +1 -1
  3. package/dist/src/agent/agent.js +1 -1
  4. package/dist/src/agent/agent.js.map +1 -1
  5. package/dist/src/context-manager/modes/agentic/agentic-context.d.ts +3 -3
  6. package/dist/src/context-manager/modes/agentic/agentic-context.d.ts.map +1 -1
  7. package/dist/src/index.d.ts +1 -1
  8. package/dist/src/index.d.ts.map +1 -1
  9. package/dist/src/index.js +1 -1
  10. package/dist/src/index.js.map +1 -1
  11. package/dist/src/index.node.d.ts.map +1 -1
  12. package/dist/src/index.node.js +3 -0
  13. package/dist/src/index.node.js.map +1 -1
  14. package/dist/src/interventions/actions.d.ts.map +1 -1
  15. package/dist/src/interventions/actions.js.map +1 -1
  16. package/dist/src/{mcp.d.ts → mcp/client.d.ts} +13 -4
  17. package/dist/src/mcp/client.d.ts.map +1 -0
  18. package/dist/src/{mcp.js → mcp/client.js} +15 -3
  19. package/dist/src/mcp/client.js.map +1 -0
  20. package/dist/src/mcp/config.d.ts +52 -0
  21. package/dist/src/mcp/config.d.ts.map +1 -0
  22. package/dist/src/mcp/config.js +12 -0
  23. package/dist/src/mcp/config.js.map +1 -0
  24. package/dist/src/mcp/config.node.d.ts +16 -0
  25. package/dist/src/mcp/config.node.d.ts.map +1 -0
  26. package/dist/src/mcp/config.node.js +145 -0
  27. package/dist/src/mcp/config.node.js.map +1 -0
  28. package/dist/src/mcp/index.d.ts +3 -0
  29. package/dist/src/mcp/index.d.ts.map +1 -0
  30. package/dist/src/mcp/index.js +2 -0
  31. package/dist/src/mcp/index.js.map +1 -0
  32. package/dist/src/memory/extraction/coordinator.d.ts +6 -1
  33. package/dist/src/memory/extraction/coordinator.d.ts.map +1 -1
  34. package/dist/src/memory/extraction/coordinator.js +48 -10
  35. package/dist/src/memory/extraction/coordinator.js.map +1 -1
  36. package/dist/src/memory/extraction/model-extractor.d.ts.map +1 -1
  37. package/dist/src/memory/extraction/model-extractor.js +30 -9
  38. package/dist/src/memory/extraction/model-extractor.js.map +1 -1
  39. package/dist/src/memory/extraction/types.d.ts +7 -0
  40. package/dist/src/memory/extraction/types.d.ts.map +1 -1
  41. package/dist/src/memory/extraction/types.js.map +1 -1
  42. package/dist/src/memory/memory-manager.d.ts +15 -2
  43. package/dist/src/memory/memory-manager.d.ts.map +1 -1
  44. package/dist/src/memory/memory-manager.js +123 -45
  45. package/dist/src/memory/memory-manager.js.map +1 -1
  46. package/dist/src/memory/types.d.ts +7 -0
  47. package/dist/src/memory/types.d.ts.map +1 -1
  48. package/dist/src/models/google/adapters.d.ts.map +1 -1
  49. package/dist/src/models/google/adapters.js +21 -3
  50. package/dist/src/models/google/adapters.js.map +1 -1
  51. package/dist/src/models/model.d.ts.map +1 -1
  52. package/dist/src/models/model.js +2 -1
  53. package/dist/src/models/model.js.map +1 -1
  54. package/dist/src/models/openai/errors.d.ts.map +1 -1
  55. package/dist/src/models/openai/errors.js +4 -1
  56. package/dist/src/models/openai/errors.js.map +1 -1
  57. package/dist/src/models/openai/responses-adapter.d.ts +1 -0
  58. package/dist/src/models/openai/responses-adapter.d.ts.map +1 -1
  59. package/dist/src/models/openai/responses-adapter.js +24 -10
  60. package/dist/src/models/openai/responses-adapter.js.map +1 -1
  61. package/dist/src/multiagent/graph.d.ts +7 -0
  62. package/dist/src/multiagent/graph.d.ts.map +1 -1
  63. package/dist/src/multiagent/graph.js +26 -2
  64. package/dist/src/multiagent/graph.js.map +1 -1
  65. package/dist/src/multiagent/nodes.d.ts +5 -0
  66. package/dist/src/multiagent/nodes.d.ts.map +1 -1
  67. package/dist/src/multiagent/nodes.js +15 -0
  68. package/dist/src/multiagent/nodes.js.map +1 -1
  69. package/dist/src/multiagent/state.d.ts.map +1 -1
  70. package/dist/src/multiagent/state.js.map +1 -1
  71. package/dist/src/telemetry/tracer.d.ts +82 -2
  72. package/dist/src/telemetry/tracer.d.ts.map +1 -1
  73. package/dist/src/telemetry/tracer.js +242 -3
  74. package/dist/src/telemetry/tracer.js.map +1 -1
  75. package/dist/src/telemetry/types.d.ts +86 -1
  76. package/dist/src/telemetry/types.d.ts.map +1 -1
  77. package/dist/src/tools/function-tool.d.ts +1 -1
  78. package/dist/src/tools/function-tool.d.ts.map +1 -1
  79. package/dist/src/tools/function-tool.js +4 -12
  80. package/dist/src/tools/function-tool.js.map +1 -1
  81. package/dist/src/tools/mcp-tool.d.ts +2 -1
  82. package/dist/src/tools/mcp-tool.d.ts.map +1 -1
  83. package/dist/src/tools/mcp-tool.js +1 -0
  84. package/dist/src/tools/mcp-tool.js.map +1 -1
  85. package/dist/src/tools/tool-factory.d.ts +1 -1
  86. package/dist/src/tools/tool-factory.d.ts.map +1 -1
  87. package/dist/src/tools/types.d.ts +4 -0
  88. package/dist/src/tools/types.d.ts.map +1 -1
  89. package/dist/src/tools/zod-tool.d.ts +4 -2
  90. package/dist/src/tools/zod-tool.d.ts.map +1 -1
  91. package/dist/src/tools/zod-tool.js.map +1 -1
  92. package/dist/src/tsconfig.tsbuildinfo +1 -1
  93. package/dist/src/types/json.js +2 -2
  94. package/dist/src/types/json.js.map +1 -1
  95. package/dist/src/types/media.d.ts.map +1 -1
  96. package/dist/src/types/media.js.map +1 -1
  97. package/dist/src/types/messages.d.ts.map +1 -1
  98. package/dist/src/types/messages.js.map +1 -1
  99. package/dist/src/vended-interventions/cedar/cedar.d.ts +12 -0
  100. package/dist/src/vended-interventions/cedar/cedar.d.ts.map +1 -1
  101. package/dist/src/vended-interventions/cedar/cedar.js +15 -4
  102. package/dist/src/vended-interventions/cedar/cedar.js.map +1 -1
  103. package/dist/src/vended-interventions/cedar/schema-generator.d.ts +1 -1
  104. package/dist/src/vended-interventions/cedar/schema-generator.d.ts.map +1 -1
  105. package/dist/src/vended-interventions/cedar/schema-generator.js +8 -3
  106. package/dist/src/vended-interventions/cedar/schema-generator.js.map +1 -1
  107. package/dist/src/vended-memory-stores/bedrock-knowledge-base/index.d.ts +1 -1
  108. package/dist/src/vended-memory-stores/bedrock-knowledge-base/index.d.ts.map +1 -1
  109. package/dist/src/vended-memory-stores/bedrock-knowledge-base/index.js.map +1 -1
  110. package/dist/src/vended-memory-stores/bedrock-knowledge-base/store.d.ts +57 -0
  111. package/dist/src/vended-memory-stores/bedrock-knowledge-base/store.d.ts.map +1 -1
  112. package/dist/src/vended-memory-stores/bedrock-knowledge-base/store.js +86 -11
  113. package/dist/src/vended-memory-stores/bedrock-knowledge-base/store.js.map +1 -1
  114. package/dist/src/vended-memory-stores/local/index.d.ts +2 -0
  115. package/dist/src/vended-memory-stores/local/index.d.ts.map +1 -0
  116. package/dist/src/vended-memory-stores/local/index.js +2 -0
  117. package/dist/src/vended-memory-stores/local/index.js.map +1 -0
  118. package/dist/src/vended-memory-stores/local/store.d.ts +122 -0
  119. package/dist/src/vended-memory-stores/local/store.d.ts.map +1 -0
  120. package/dist/src/vended-memory-stores/local/store.js +281 -0
  121. package/dist/src/vended-memory-stores/local/store.js.map +1 -0
  122. package/dist/src/vended-plugins/context-offloader/search.d.ts.map +1 -1
  123. package/dist/src/vended-plugins/context-offloader/search.js +4 -2
  124. package/dist/src/vended-plugins/context-offloader/search.js.map +1 -1
  125. package/dist/src/vended-plugins/context-offloader/storage.d.ts.map +1 -1
  126. package/dist/src/vended-plugins/context-offloader/storage.js +16 -3
  127. package/dist/src/vended-plugins/context-offloader/storage.js.map +1 -1
  128. package/dist/src/vended-plugins/skills/skill.d.ts.map +1 -1
  129. package/dist/src/vended-plugins/skills/skill.js +4 -2
  130. package/dist/src/vended-plugins/skills/skill.js.map +1 -1
  131. package/dist/src/vended-tools/http-request/http-request.js +1 -1
  132. package/dist/src/vended-tools/http-request/http-request.js.map +1 -1
  133. package/dist/src/vended-tools/notebook/notebook.d.ts +1 -1
  134. package/package.json +46 -39
  135. package/dist/src/__fixtures__/agent-helpers.d.ts +0 -136
  136. package/dist/src/__fixtures__/agent-helpers.d.ts.map +0 -1
  137. package/dist/src/__fixtures__/agent-helpers.js +0 -156
  138. package/dist/src/__fixtures__/agent-helpers.js.map +0 -1
  139. package/dist/src/__fixtures__/environment.d.ts +0 -12
  140. package/dist/src/__fixtures__/environment.d.ts.map +0 -1
  141. package/dist/src/__fixtures__/environment.js +0 -12
  142. package/dist/src/__fixtures__/environment.js.map +0 -1
  143. package/dist/src/__fixtures__/metrics-helpers.d.ts +0 -55
  144. package/dist/src/__fixtures__/metrics-helpers.d.ts.map +0 -1
  145. package/dist/src/__fixtures__/metrics-helpers.js +0 -57
  146. package/dist/src/__fixtures__/metrics-helpers.js.map +0 -1
  147. package/dist/src/__fixtures__/mock-message-model.d.ts +0 -103
  148. package/dist/src/__fixtures__/mock-message-model.d.ts.map +0 -1
  149. package/dist/src/__fixtures__/mock-message-model.js +0 -245
  150. package/dist/src/__fixtures__/mock-message-model.js.map +0 -1
  151. package/dist/src/__fixtures__/mock-meter.d.ts +0 -32
  152. package/dist/src/__fixtures__/mock-meter.d.ts.map +0 -1
  153. package/dist/src/__fixtures__/mock-meter.js +0 -47
  154. package/dist/src/__fixtures__/mock-meter.js.map +0 -1
  155. package/dist/src/__fixtures__/mock-plugin.d.ts +0 -13
  156. package/dist/src/__fixtures__/mock-plugin.d.ts.map +0 -1
  157. package/dist/src/__fixtures__/mock-plugin.js +0 -35
  158. package/dist/src/__fixtures__/mock-plugin.js.map +0 -1
  159. package/dist/src/__fixtures__/mock-span.d.ts +0 -78
  160. package/dist/src/__fixtures__/mock-span.d.ts.map +0 -1
  161. package/dist/src/__fixtures__/mock-span.js +0 -93
  162. package/dist/src/__fixtures__/mock-span.js.map +0 -1
  163. package/dist/src/__fixtures__/mock-storage-provider.d.ts +0 -42
  164. package/dist/src/__fixtures__/mock-storage-provider.d.ts.map +0 -1
  165. package/dist/src/__fixtures__/mock-storage-provider.js +0 -122
  166. package/dist/src/__fixtures__/mock-storage-provider.js.map +0 -1
  167. package/dist/src/__fixtures__/model-test-helpers.d.ts +0 -56
  168. package/dist/src/__fixtures__/model-test-helpers.d.ts.map +0 -1
  169. package/dist/src/__fixtures__/model-test-helpers.js +0 -85
  170. package/dist/src/__fixtures__/model-test-helpers.js.map +0 -1
  171. package/dist/src/__fixtures__/register-node-defaults.d.ts +0 -2
  172. package/dist/src/__fixtures__/register-node-defaults.d.ts.map +0 -1
  173. package/dist/src/__fixtures__/register-node-defaults.js +0 -6
  174. package/dist/src/__fixtures__/register-node-defaults.js.map +0 -1
  175. package/dist/src/__fixtures__/slim-types.d.ts +0 -51
  176. package/dist/src/__fixtures__/slim-types.d.ts.map +0 -1
  177. package/dist/src/__fixtures__/slim-types.js +0 -6
  178. package/dist/src/__fixtures__/slim-types.js.map +0 -1
  179. package/dist/src/__fixtures__/test-sandbox.node.d.ts +0 -15
  180. package/dist/src/__fixtures__/test-sandbox.node.d.ts.map +0 -1
  181. package/dist/src/__fixtures__/test-sandbox.node.js +0 -23
  182. package/dist/src/__fixtures__/test-sandbox.node.js.map +0 -1
  183. package/dist/src/__fixtures__/tool-helpers.d.ts +0 -45
  184. package/dist/src/__fixtures__/tool-helpers.d.ts.map +0 -1
  185. package/dist/src/__fixtures__/tool-helpers.js +0 -101
  186. package/dist/src/__fixtures__/tool-helpers.js.map +0 -1
  187. package/dist/src/__tests__/default-slot.test.d.ts +0 -2
  188. package/dist/src/__tests__/default-slot.test.d.ts.map +0 -1
  189. package/dist/src/__tests__/default-slot.test.js +0 -33
  190. package/dist/src/__tests__/default-slot.test.js.map +0 -1
  191. package/dist/src/__tests__/errors.test.d.ts +0 -2
  192. package/dist/src/__tests__/errors.test.d.ts.map +0 -1
  193. package/dist/src/__tests__/errors.test.js +0 -170
  194. package/dist/src/__tests__/errors.test.js.map +0 -1
  195. package/dist/src/__tests__/index.test.d.ts +0 -2
  196. package/dist/src/__tests__/index.test.d.ts.map +0 -1
  197. package/dist/src/__tests__/index.test.js +0 -48
  198. package/dist/src/__tests__/index.test.js.map +0 -1
  199. package/dist/src/__tests__/interrupt.test.d.ts +0 -2
  200. package/dist/src/__tests__/interrupt.test.d.ts.map +0 -1
  201. package/dist/src/__tests__/interrupt.test.js +0 -264
  202. package/dist/src/__tests__/interrupt.test.js.map +0 -1
  203. package/dist/src/__tests__/mcp.test.d.ts +0 -2
  204. package/dist/src/__tests__/mcp.test.d.ts.map +0 -1
  205. package/dist/src/__tests__/mcp.test.js +0 -1003
  206. package/dist/src/__tests__/mcp.test.js.map +0 -1
  207. package/dist/src/__tests__/mime.test.d.ts +0 -2
  208. package/dist/src/__tests__/mime.test.d.ts.map +0 -1
  209. package/dist/src/__tests__/mime.test.js +0 -83
  210. package/dist/src/__tests__/mime.test.js.map +0 -1
  211. package/dist/src/__tests__/state-store.test.d.ts +0 -2
  212. package/dist/src/__tests__/state-store.test.d.ts.map +0 -1
  213. package/dist/src/__tests__/state-store.test.js +0 -285
  214. package/dist/src/__tests__/state-store.test.js.map +0 -1
  215. package/dist/src/a2a/__tests__/a2a-agent.test.d.ts +0 -2
  216. package/dist/src/a2a/__tests__/a2a-agent.test.d.ts.map +0 -1
  217. package/dist/src/a2a/__tests__/a2a-agent.test.js +0 -383
  218. package/dist/src/a2a/__tests__/a2a-agent.test.js.map +0 -1
  219. package/dist/src/a2a/__tests__/adapters.test.d.ts +0 -2
  220. package/dist/src/a2a/__tests__/adapters.test.d.ts.map +0 -1
  221. package/dist/src/a2a/__tests__/adapters.test.js +0 -151
  222. package/dist/src/a2a/__tests__/adapters.test.js.map +0 -1
  223. package/dist/src/a2a/__tests__/async-lock.test.d.ts +0 -2
  224. package/dist/src/a2a/__tests__/async-lock.test.d.ts.map +0 -1
  225. package/dist/src/a2a/__tests__/async-lock.test.js +0 -137
  226. package/dist/src/a2a/__tests__/async-lock.test.js.map +0 -1
  227. package/dist/src/a2a/__tests__/events.test.d.ts +0 -2
  228. package/dist/src/a2a/__tests__/events.test.d.ts.map +0 -1
  229. package/dist/src/a2a/__tests__/events.test.js +0 -68
  230. package/dist/src/a2a/__tests__/events.test.js.map +0 -1
  231. package/dist/src/a2a/__tests__/executor.test.d.ts +0 -2
  232. package/dist/src/a2a/__tests__/executor.test.d.ts.map +0 -1
  233. package/dist/src/a2a/__tests__/executor.test.js +0 -345
  234. package/dist/src/a2a/__tests__/executor.test.js.map +0 -1
  235. package/dist/src/a2a/__tests__/server.test.d.ts +0 -2
  236. package/dist/src/a2a/__tests__/server.test.d.ts.map +0 -1
  237. package/dist/src/a2a/__tests__/server.test.js +0 -71
  238. package/dist/src/a2a/__tests__/server.test.js.map +0 -1
  239. package/dist/src/a2a/__tests__/server.test.node.d.ts +0 -2
  240. package/dist/src/a2a/__tests__/server.test.node.d.ts.map +0 -1
  241. package/dist/src/a2a/__tests__/server.test.node.js +0 -110
  242. package/dist/src/a2a/__tests__/server.test.node.js.map +0 -1
  243. package/dist/src/agent/__tests__/agent-as-tool.invocation-state.test.d.ts +0 -2
  244. package/dist/src/agent/__tests__/agent-as-tool.invocation-state.test.d.ts.map +0 -1
  245. package/dist/src/agent/__tests__/agent-as-tool.invocation-state.test.js +0 -23
  246. package/dist/src/agent/__tests__/agent-as-tool.invocation-state.test.js.map +0 -1
  247. package/dist/src/agent/__tests__/agent-as-tool.test.d.ts +0 -2
  248. package/dist/src/agent/__tests__/agent-as-tool.test.d.ts.map +0 -1
  249. package/dist/src/agent/__tests__/agent-as-tool.test.js +0 -347
  250. package/dist/src/agent/__tests__/agent-as-tool.test.js.map +0 -1
  251. package/dist/src/agent/__tests__/agent.cancel.test.d.ts +0 -2
  252. package/dist/src/agent/__tests__/agent.cancel.test.d.ts.map +0 -1
  253. package/dist/src/agent/__tests__/agent.cancel.test.js +0 -337
  254. package/dist/src/agent/__tests__/agent.cancel.test.js.map +0 -1
  255. package/dist/src/agent/__tests__/agent.concurrent.test.d.ts +0 -2
  256. package/dist/src/agent/__tests__/agent.concurrent.test.d.ts.map +0 -1
  257. package/dist/src/agent/__tests__/agent.concurrent.test.js +0 -488
  258. package/dist/src/agent/__tests__/agent.concurrent.test.js.map +0 -1
  259. package/dist/src/agent/__tests__/agent.context-manager.test.d.ts +0 -2
  260. package/dist/src/agent/__tests__/agent.context-manager.test.d.ts.map +0 -1
  261. package/dist/src/agent/__tests__/agent.context-manager.test.js +0 -107
  262. package/dist/src/agent/__tests__/agent.context-manager.test.js.map +0 -1
  263. package/dist/src/agent/__tests__/agent.hook.test.d.ts +0 -2
  264. package/dist/src/agent/__tests__/agent.hook.test.d.ts.map +0 -1
  265. package/dist/src/agent/__tests__/agent.hook.test.js +0 -1332
  266. package/dist/src/agent/__tests__/agent.hook.test.js.map +0 -1
  267. package/dist/src/agent/__tests__/agent.interrupt.test.d.ts +0 -2
  268. package/dist/src/agent/__tests__/agent.interrupt.test.d.ts.map +0 -1
  269. package/dist/src/agent/__tests__/agent.interrupt.test.js +0 -779
  270. package/dist/src/agent/__tests__/agent.interrupt.test.js.map +0 -1
  271. package/dist/src/agent/__tests__/agent.invocation-state.test.d.ts +0 -2
  272. package/dist/src/agent/__tests__/agent.invocation-state.test.d.ts.map +0 -1
  273. package/dist/src/agent/__tests__/agent.invocation-state.test.js +0 -219
  274. package/dist/src/agent/__tests__/agent.invocation-state.test.js.map +0 -1
  275. package/dist/src/agent/__tests__/agent.model-retry.test.d.ts +0 -2
  276. package/dist/src/agent/__tests__/agent.model-retry.test.d.ts.map +0 -1
  277. package/dist/src/agent/__tests__/agent.model-retry.test.js +0 -161
  278. package/dist/src/agent/__tests__/agent.model-retry.test.js.map +0 -1
  279. package/dist/src/agent/__tests__/agent.stateful-model.test.d.ts +0 -2
  280. package/dist/src/agent/__tests__/agent.stateful-model.test.d.ts.map +0 -1
  281. package/dist/src/agent/__tests__/agent.stateful-model.test.js +0 -169
  282. package/dist/src/agent/__tests__/agent.stateful-model.test.js.map +0 -1
  283. package/dist/src/agent/__tests__/agent.test.d.ts +0 -2
  284. package/dist/src/agent/__tests__/agent.test.d.ts.map +0 -1
  285. package/dist/src/agent/__tests__/agent.test.js +0 -1624
  286. package/dist/src/agent/__tests__/agent.test.js.map +0 -1
  287. package/dist/src/agent/__tests__/agent.tracer.test.node.d.ts +0 -2
  288. package/dist/src/agent/__tests__/agent.tracer.test.node.d.ts.map +0 -1
  289. package/dist/src/agent/__tests__/agent.tracer.test.node.js +0 -535
  290. package/dist/src/agent/__tests__/agent.tracer.test.node.js.map +0 -1
  291. package/dist/src/agent/__tests__/printer.test.d.ts +0 -2
  292. package/dist/src/agent/__tests__/printer.test.d.ts.map +0 -1
  293. package/dist/src/agent/__tests__/printer.test.js +0 -188
  294. package/dist/src/agent/__tests__/printer.test.js.map +0 -1
  295. package/dist/src/agent/__tests__/snapshot.test.d.ts +0 -2
  296. package/dist/src/agent/__tests__/snapshot.test.d.ts.map +0 -1
  297. package/dist/src/agent/__tests__/snapshot.test.js +0 -442
  298. package/dist/src/agent/__tests__/snapshot.test.js.map +0 -1
  299. package/dist/src/agent/__tests__/tool-caller.test.d.ts +0 -2
  300. package/dist/src/agent/__tests__/tool-caller.test.d.ts.map +0 -1
  301. package/dist/src/agent/__tests__/tool-caller.test.js +0 -459
  302. package/dist/src/agent/__tests__/tool-caller.test.js.map +0 -1
  303. package/dist/src/conversation-manager/__tests__/agentic-context.test.d.ts +0 -2
  304. package/dist/src/conversation-manager/__tests__/agentic-context.test.d.ts.map +0 -1
  305. package/dist/src/conversation-manager/__tests__/agentic-context.test.js +0 -332
  306. package/dist/src/conversation-manager/__tests__/agentic-context.test.js.map +0 -1
  307. package/dist/src/conversation-manager/__tests__/context-compression.test.d.ts +0 -2
  308. package/dist/src/conversation-manager/__tests__/context-compression.test.d.ts.map +0 -1
  309. package/dist/src/conversation-manager/__tests__/context-compression.test.js +0 -176
  310. package/dist/src/conversation-manager/__tests__/context-compression.test.js.map +0 -1
  311. package/dist/src/conversation-manager/__tests__/conversation-manager.test.d.ts +0 -2
  312. package/dist/src/conversation-manager/__tests__/conversation-manager.test.d.ts.map +0 -1
  313. package/dist/src/conversation-manager/__tests__/conversation-manager.test.js +0 -321
  314. package/dist/src/conversation-manager/__tests__/conversation-manager.test.js.map +0 -1
  315. package/dist/src/conversation-manager/__tests__/null-conversation-manager.test.d.ts +0 -2
  316. package/dist/src/conversation-manager/__tests__/null-conversation-manager.test.d.ts.map +0 -1
  317. package/dist/src/conversation-manager/__tests__/null-conversation-manager.test.js +0 -64
  318. package/dist/src/conversation-manager/__tests__/null-conversation-manager.test.js.map +0 -1
  319. package/dist/src/conversation-manager/__tests__/pin.test.d.ts +0 -2
  320. package/dist/src/conversation-manager/__tests__/pin.test.d.ts.map +0 -1
  321. package/dist/src/conversation-manager/__tests__/pin.test.js +0 -119
  322. package/dist/src/conversation-manager/__tests__/pin.test.js.map +0 -1
  323. package/dist/src/conversation-manager/__tests__/sliding-window-conversation-manager.test.d.ts +0 -2
  324. package/dist/src/conversation-manager/__tests__/sliding-window-conversation-manager.test.d.ts.map +0 -1
  325. package/dist/src/conversation-manager/__tests__/sliding-window-conversation-manager.test.js +0 -1080
  326. package/dist/src/conversation-manager/__tests__/sliding-window-conversation-manager.test.js.map +0 -1
  327. package/dist/src/conversation-manager/__tests__/summarizing-conversation-manager.test.d.ts +0 -2
  328. package/dist/src/conversation-manager/__tests__/summarizing-conversation-manager.test.d.ts.map +0 -1
  329. package/dist/src/conversation-manager/__tests__/summarizing-conversation-manager.test.js +0 -400
  330. package/dist/src/conversation-manager/__tests__/summarizing-conversation-manager.test.js.map +0 -1
  331. package/dist/src/conversation-manager/__tests__/token-usage-middleware.test.d.ts +0 -2
  332. package/dist/src/conversation-manager/__tests__/token-usage-middleware.test.d.ts.map +0 -1
  333. package/dist/src/conversation-manager/__tests__/token-usage-middleware.test.js +0 -138
  334. package/dist/src/conversation-manager/__tests__/token-usage-middleware.test.js.map +0 -1
  335. package/dist/src/hooks/__tests__/events.test.d.ts +0 -2
  336. package/dist/src/hooks/__tests__/events.test.d.ts.map +0 -1
  337. package/dist/src/hooks/__tests__/events.test.js +0 -1060
  338. package/dist/src/hooks/__tests__/events.test.js.map +0 -1
  339. package/dist/src/hooks/__tests__/registry.test.d.ts +0 -2
  340. package/dist/src/hooks/__tests__/registry.test.d.ts.map +0 -1
  341. package/dist/src/hooks/__tests__/registry.test.js +0 -325
  342. package/dist/src/hooks/__tests__/registry.test.js.map +0 -1
  343. package/dist/src/injection/__tests__/message-injection.test.d.ts +0 -2
  344. package/dist/src/injection/__tests__/message-injection.test.d.ts.map +0 -1
  345. package/dist/src/injection/__tests__/message-injection.test.js +0 -200
  346. package/dist/src/injection/__tests__/message-injection.test.js.map +0 -1
  347. package/dist/src/interventions/__tests__/handler.test.d.ts +0 -2
  348. package/dist/src/interventions/__tests__/handler.test.d.ts.map +0 -1
  349. package/dist/src/interventions/__tests__/handler.test.js +0 -35
  350. package/dist/src/interventions/__tests__/handler.test.js.map +0 -1
  351. package/dist/src/interventions/__tests__/registry.test.d.ts +0 -2
  352. package/dist/src/interventions/__tests__/registry.test.d.ts.map +0 -1
  353. package/dist/src/interventions/__tests__/registry.test.js +0 -692
  354. package/dist/src/interventions/__tests__/registry.test.js.map +0 -1
  355. package/dist/src/logging/__tests__/logger.test.d.ts +0 -2
  356. package/dist/src/logging/__tests__/logger.test.d.ts.map +0 -1
  357. package/dist/src/logging/__tests__/logger.test.js +0 -70
  358. package/dist/src/logging/__tests__/logger.test.js.map +0 -1
  359. package/dist/src/logging/__tests__/warn-once.test.d.ts +0 -2
  360. package/dist/src/logging/__tests__/warn-once.test.d.ts.map +0 -1
  361. package/dist/src/logging/__tests__/warn-once.test.js +0 -30
  362. package/dist/src/logging/__tests__/warn-once.test.js.map +0 -1
  363. package/dist/src/mcp.d.ts.map +0 -1
  364. package/dist/src/mcp.js.map +0 -1
  365. package/dist/src/memory/__tests__/memory-manager.test.d.ts +0 -2
  366. package/dist/src/memory/__tests__/memory-manager.test.d.ts.map +0 -1
  367. package/dist/src/memory/__tests__/memory-manager.test.js +0 -679
  368. package/dist/src/memory/__tests__/memory-manager.test.js.map +0 -1
  369. package/dist/src/memory/extraction/__tests__/extraction.test.d.ts +0 -2
  370. package/dist/src/memory/extraction/__tests__/extraction.test.d.ts.map +0 -1
  371. package/dist/src/memory/extraction/__tests__/extraction.test.js +0 -637
  372. package/dist/src/memory/extraction/__tests__/extraction.test.js.map +0 -1
  373. package/dist/src/memory/extraction/__tests__/model-extractor.test.d.ts +0 -2
  374. package/dist/src/memory/extraction/__tests__/model-extractor.test.d.ts.map +0 -1
  375. package/dist/src/memory/extraction/__tests__/model-extractor.test.js +0 -68
  376. package/dist/src/memory/extraction/__tests__/model-extractor.test.js.map +0 -1
  377. package/dist/src/memory/extraction/__tests__/resolve-extraction-config.test.d.ts +0 -2
  378. package/dist/src/memory/extraction/__tests__/resolve-extraction-config.test.d.ts.map +0 -1
  379. package/dist/src/memory/extraction/__tests__/resolve-extraction-config.test.js +0 -81
  380. package/dist/src/memory/extraction/__tests__/resolve-extraction-config.test.js.map +0 -1
  381. package/dist/src/middleware/__tests__/agent-middleware.test.d.ts +0 -2
  382. package/dist/src/middleware/__tests__/agent-middleware.test.d.ts.map +0 -1
  383. package/dist/src/middleware/__tests__/agent-middleware.test.js +0 -1206
  384. package/dist/src/middleware/__tests__/agent-middleware.test.js.map +0 -1
  385. package/dist/src/middleware/__tests__/copy-on-input.test.d.ts +0 -2
  386. package/dist/src/middleware/__tests__/copy-on-input.test.d.ts.map +0 -1
  387. package/dist/src/middleware/__tests__/copy-on-input.test.js +0 -379
  388. package/dist/src/middleware/__tests__/copy-on-input.test.js.map +0 -1
  389. package/dist/src/middleware/__tests__/custom-stages.test.d.ts +0 -2
  390. package/dist/src/middleware/__tests__/custom-stages.test.d.ts.map +0 -1
  391. package/dist/src/middleware/__tests__/custom-stages.test.js +0 -97
  392. package/dist/src/middleware/__tests__/custom-stages.test.js.map +0 -1
  393. package/dist/src/middleware/__tests__/middleware-interrupts.test.d.ts +0 -2
  394. package/dist/src/middleware/__tests__/middleware-interrupts.test.d.ts.map +0 -1
  395. package/dist/src/middleware/__tests__/middleware-interrupts.test.js +0 -267
  396. package/dist/src/middleware/__tests__/middleware-interrupts.test.js.map +0 -1
  397. package/dist/src/middleware/__tests__/registry.test.d.ts +0 -2
  398. package/dist/src/middleware/__tests__/registry.test.d.ts.map +0 -1
  399. package/dist/src/middleware/__tests__/registry.test.js +0 -525
  400. package/dist/src/middleware/__tests__/registry.test.js.map +0 -1
  401. package/dist/src/models/__tests__/anthropic.test.d.ts +0 -2
  402. package/dist/src/models/__tests__/anthropic.test.d.ts.map +0 -1
  403. package/dist/src/models/__tests__/anthropic.test.js +0 -793
  404. package/dist/src/models/__tests__/anthropic.test.js.map +0 -1
  405. package/dist/src/models/__tests__/bedrock.test.d.ts +0 -2
  406. package/dist/src/models/__tests__/bedrock.test.d.ts.map +0 -1
  407. package/dist/src/models/__tests__/bedrock.test.js +0 -3964
  408. package/dist/src/models/__tests__/bedrock.test.js.map +0 -1
  409. package/dist/src/models/__tests__/defaults.test.d.ts +0 -2
  410. package/dist/src/models/__tests__/defaults.test.d.ts.map +0 -1
  411. package/dist/src/models/__tests__/defaults.test.js +0 -36
  412. package/dist/src/models/__tests__/defaults.test.js.map +0 -1
  413. package/dist/src/models/__tests__/google.test.d.ts +0 -2
  414. package/dist/src/models/__tests__/google.test.d.ts.map +0 -1
  415. package/dist/src/models/__tests__/google.test.js +0 -1104
  416. package/dist/src/models/__tests__/google.test.js.map +0 -1
  417. package/dist/src/models/__tests__/model.test.d.ts +0 -2
  418. package/dist/src/models/__tests__/model.test.d.ts.map +0 -1
  419. package/dist/src/models/__tests__/model.test.js +0 -921
  420. package/dist/src/models/__tests__/model.test.js.map +0 -1
  421. package/dist/src/models/__tests__/streaming.test.d.ts +0 -2
  422. package/dist/src/models/__tests__/streaming.test.d.ts.map +0 -1
  423. package/dist/src/models/__tests__/streaming.test.js +0 -50
  424. package/dist/src/models/__tests__/streaming.test.js.map +0 -1
  425. package/dist/src/models/__tests__/test-utils.d.ts +0 -10
  426. package/dist/src/models/__tests__/test-utils.d.ts.map +0 -1
  427. package/dist/src/models/__tests__/test-utils.js +0 -17
  428. package/dist/src/models/__tests__/test-utils.js.map +0 -1
  429. package/dist/src/models/__tests__/vercel.test.d.ts +0 -2
  430. package/dist/src/models/__tests__/vercel.test.d.ts.map +0 -1
  431. package/dist/src/models/__tests__/vercel.test.js +0 -740
  432. package/dist/src/models/__tests__/vercel.test.js.map +0 -1
  433. package/dist/src/models/openai/__tests__/chat.test.d.ts +0 -2
  434. package/dist/src/models/openai/__tests__/chat.test.d.ts.map +0 -1
  435. package/dist/src/models/openai/__tests__/chat.test.js +0 -1586
  436. package/dist/src/models/openai/__tests__/chat.test.js.map +0 -1
  437. package/dist/src/models/openai/__tests__/errors.test.d.ts +0 -2
  438. package/dist/src/models/openai/__tests__/errors.test.d.ts.map +0 -1
  439. package/dist/src/models/openai/__tests__/errors.test.js +0 -30
  440. package/dist/src/models/openai/__tests__/errors.test.js.map +0 -1
  441. package/dist/src/models/openai/__tests__/mantle.test.d.ts +0 -2
  442. package/dist/src/models/openai/__tests__/mantle.test.d.ts.map +0 -1
  443. package/dist/src/models/openai/__tests__/mantle.test.js +0 -189
  444. package/dist/src/models/openai/__tests__/mantle.test.js.map +0 -1
  445. package/dist/src/models/openai/__tests__/responses.test.d.ts +0 -2
  446. package/dist/src/models/openai/__tests__/responses.test.d.ts.map +0 -1
  447. package/dist/src/models/openai/__tests__/responses.test.js +0 -662
  448. package/dist/src/models/openai/__tests__/responses.test.js.map +0 -1
  449. package/dist/src/multiagent/__tests__/events.test.d.ts +0 -2
  450. package/dist/src/multiagent/__tests__/events.test.d.ts.map +0 -1
  451. package/dist/src/multiagent/__tests__/events.test.js +0 -493
  452. package/dist/src/multiagent/__tests__/events.test.js.map +0 -1
  453. package/dist/src/multiagent/__tests__/graph.invocation-state.test.d.ts +0 -2
  454. package/dist/src/multiagent/__tests__/graph.invocation-state.test.d.ts.map +0 -1
  455. package/dist/src/multiagent/__tests__/graph.invocation-state.test.js +0 -95
  456. package/dist/src/multiagent/__tests__/graph.invocation-state.test.js.map +0 -1
  457. package/dist/src/multiagent/__tests__/graph.test.d.ts +0 -2
  458. package/dist/src/multiagent/__tests__/graph.test.d.ts.map +0 -1
  459. package/dist/src/multiagent/__tests__/graph.test.js +0 -677
  460. package/dist/src/multiagent/__tests__/graph.test.js.map +0 -1
  461. package/dist/src/multiagent/__tests__/graph.tracer.test.d.ts +0 -2
  462. package/dist/src/multiagent/__tests__/graph.tracer.test.d.ts.map +0 -1
  463. package/dist/src/multiagent/__tests__/graph.tracer.test.js +0 -218
  464. package/dist/src/multiagent/__tests__/graph.tracer.test.js.map +0 -1
  465. package/dist/src/multiagent/__tests__/interrupts.test.d.ts +0 -2
  466. package/dist/src/multiagent/__tests__/interrupts.test.d.ts.map +0 -1
  467. package/dist/src/multiagent/__tests__/interrupts.test.js +0 -390
  468. package/dist/src/multiagent/__tests__/interrupts.test.js.map +0 -1
  469. package/dist/src/multiagent/__tests__/nodes.test.d.ts +0 -2
  470. package/dist/src/multiagent/__tests__/nodes.test.d.ts.map +0 -1
  471. package/dist/src/multiagent/__tests__/nodes.test.js +0 -321
  472. package/dist/src/multiagent/__tests__/nodes.test.js.map +0 -1
  473. package/dist/src/multiagent/__tests__/queue.test.d.ts +0 -2
  474. package/dist/src/multiagent/__tests__/queue.test.d.ts.map +0 -1
  475. package/dist/src/multiagent/__tests__/queue.test.js +0 -118
  476. package/dist/src/multiagent/__tests__/queue.test.js.map +0 -1
  477. package/dist/src/multiagent/__tests__/snapshot.test.d.ts +0 -2
  478. package/dist/src/multiagent/__tests__/snapshot.test.d.ts.map +0 -1
  479. package/dist/src/multiagent/__tests__/snapshot.test.js +0 -161
  480. package/dist/src/multiagent/__tests__/snapshot.test.js.map +0 -1
  481. package/dist/src/multiagent/__tests__/state.test.d.ts +0 -2
  482. package/dist/src/multiagent/__tests__/state.test.d.ts.map +0 -1
  483. package/dist/src/multiagent/__tests__/state.test.js +0 -526
  484. package/dist/src/multiagent/__tests__/state.test.js.map +0 -1
  485. package/dist/src/multiagent/__tests__/swarm.invocation-state.test.d.ts +0 -2
  486. package/dist/src/multiagent/__tests__/swarm.invocation-state.test.d.ts.map +0 -1
  487. package/dist/src/multiagent/__tests__/swarm.invocation-state.test.js +0 -56
  488. package/dist/src/multiagent/__tests__/swarm.invocation-state.test.js.map +0 -1
  489. package/dist/src/multiagent/__tests__/swarm.test.d.ts +0 -2
  490. package/dist/src/multiagent/__tests__/swarm.test.d.ts.map +0 -1
  491. package/dist/src/multiagent/__tests__/swarm.test.js +0 -477
  492. package/dist/src/multiagent/__tests__/swarm.test.js.map +0 -1
  493. package/dist/src/multiagent/__tests__/swarm.tracer.test.d.ts +0 -2
  494. package/dist/src/multiagent/__tests__/swarm.tracer.test.d.ts.map +0 -1
  495. package/dist/src/multiagent/__tests__/swarm.tracer.test.js +0 -235
  496. package/dist/src/multiagent/__tests__/swarm.tracer.test.js.map +0 -1
  497. package/dist/src/plugins/__tests__/plugin.test.d.ts +0 -2
  498. package/dist/src/plugins/__tests__/plugin.test.d.ts.map +0 -1
  499. package/dist/src/plugins/__tests__/plugin.test.js +0 -114
  500. package/dist/src/plugins/__tests__/plugin.test.js.map +0 -1
  501. package/dist/src/plugins/__tests__/registry.test.d.ts +0 -2
  502. package/dist/src/plugins/__tests__/registry.test.d.ts.map +0 -1
  503. package/dist/src/plugins/__tests__/registry.test.js +0 -147
  504. package/dist/src/plugins/__tests__/registry.test.js.map +0 -1
  505. package/dist/src/registry/__tests__/tool-registry.test.d.ts +0 -2
  506. package/dist/src/registry/__tests__/tool-registry.test.d.ts.map +0 -1
  507. package/dist/src/registry/__tests__/tool-registry.test.js +0 -210
  508. package/dist/src/registry/__tests__/tool-registry.test.js.map +0 -1
  509. package/dist/src/retry/__tests__/backoff-strategy.test.d.ts +0 -2
  510. package/dist/src/retry/__tests__/backoff-strategy.test.d.ts.map +0 -1
  511. package/dist/src/retry/__tests__/backoff-strategy.test.js +0 -116
  512. package/dist/src/retry/__tests__/backoff-strategy.test.js.map +0 -1
  513. package/dist/src/retry/__tests__/default-model-retry-strategy.test.d.ts +0 -2
  514. package/dist/src/retry/__tests__/default-model-retry-strategy.test.d.ts.map +0 -1
  515. package/dist/src/retry/__tests__/default-model-retry-strategy.test.js +0 -225
  516. package/dist/src/retry/__tests__/default-model-retry-strategy.test.js.map +0 -1
  517. package/dist/src/sandbox/__tests__/default.test.browser.d.ts +0 -2
  518. package/dist/src/sandbox/__tests__/default.test.browser.d.ts.map +0 -1
  519. package/dist/src/sandbox/__tests__/default.test.browser.js +0 -11
  520. package/dist/src/sandbox/__tests__/default.test.browser.js.map +0 -1
  521. package/dist/src/sandbox/__tests__/default.test.node.d.ts +0 -2
  522. package/dist/src/sandbox/__tests__/default.test.node.d.ts.map +0 -1
  523. package/dist/src/sandbox/__tests__/default.test.node.js +0 -23
  524. package/dist/src/sandbox/__tests__/default.test.node.js.map +0 -1
  525. package/dist/src/sandbox/__tests__/docker.test.node.d.ts +0 -2
  526. package/dist/src/sandbox/__tests__/docker.test.node.d.ts.map +0 -1
  527. package/dist/src/sandbox/__tests__/docker.test.node.js +0 -89
  528. package/dist/src/sandbox/__tests__/docker.test.node.js.map +0 -1
  529. package/dist/src/sandbox/__tests__/errors.test.node.d.ts +0 -2
  530. package/dist/src/sandbox/__tests__/errors.test.node.d.ts.map +0 -1
  531. package/dist/src/sandbox/__tests__/errors.test.node.js +0 -33
  532. package/dist/src/sandbox/__tests__/errors.test.node.js.map +0 -1
  533. package/dist/src/sandbox/__tests__/not-a-sandbox-local-environment.test.node.d.ts +0 -2
  534. package/dist/src/sandbox/__tests__/not-a-sandbox-local-environment.test.node.d.ts.map +0 -1
  535. package/dist/src/sandbox/__tests__/not-a-sandbox-local-environment.test.node.js +0 -124
  536. package/dist/src/sandbox/__tests__/not-a-sandbox-local-environment.test.node.js.map +0 -1
  537. package/dist/src/sandbox/__tests__/posix-shell.test.node.d.ts +0 -2
  538. package/dist/src/sandbox/__tests__/posix-shell.test.node.d.ts.map +0 -1
  539. package/dist/src/sandbox/__tests__/posix-shell.test.node.js +0 -298
  540. package/dist/src/sandbox/__tests__/posix-shell.test.node.js.map +0 -1
  541. package/dist/src/sandbox/__tests__/ssh.test.node.d.ts +0 -2
  542. package/dist/src/sandbox/__tests__/ssh.test.node.d.ts.map +0 -1
  543. package/dist/src/sandbox/__tests__/ssh.test.node.js +0 -262
  544. package/dist/src/sandbox/__tests__/ssh.test.node.js.map +0 -1
  545. package/dist/src/session/__tests__/file-storage.test.node.d.ts +0 -2
  546. package/dist/src/session/__tests__/file-storage.test.node.d.ts.map +0 -1
  547. package/dist/src/session/__tests__/file-storage.test.node.js +0 -278
  548. package/dist/src/session/__tests__/file-storage.test.node.js.map +0 -1
  549. package/dist/src/session/__tests__/s3-storage.test.d.ts +0 -2
  550. package/dist/src/session/__tests__/s3-storage.test.d.ts.map +0 -1
  551. package/dist/src/session/__tests__/s3-storage.test.js +0 -461
  552. package/dist/src/session/__tests__/s3-storage.test.js.map +0 -1
  553. package/dist/src/session/__tests__/session-manager.test.d.ts +0 -2
  554. package/dist/src/session/__tests__/session-manager.test.d.ts.map +0 -1
  555. package/dist/src/session/__tests__/session-manager.test.js +0 -832
  556. package/dist/src/session/__tests__/session-manager.test.js.map +0 -1
  557. package/dist/src/session/__tests__/validation.test.d.ts +0 -2
  558. package/dist/src/session/__tests__/validation.test.d.ts.map +0 -1
  559. package/dist/src/session/__tests__/validation.test.js +0 -47
  560. package/dist/src/session/__tests__/validation.test.js.map +0 -1
  561. package/dist/src/telemetry/__tests__/config.test.d.ts +0 -2
  562. package/dist/src/telemetry/__tests__/config.test.d.ts.map +0 -1
  563. package/dist/src/telemetry/__tests__/config.test.js +0 -64
  564. package/dist/src/telemetry/__tests__/config.test.js.map +0 -1
  565. package/dist/src/telemetry/__tests__/config.test.node.d.ts +0 -2
  566. package/dist/src/telemetry/__tests__/config.test.node.d.ts.map +0 -1
  567. package/dist/src/telemetry/__tests__/config.test.node.js +0 -164
  568. package/dist/src/telemetry/__tests__/config.test.node.js.map +0 -1
  569. package/dist/src/telemetry/__tests__/json.test.d.ts +0 -2
  570. package/dist/src/telemetry/__tests__/json.test.d.ts.map +0 -1
  571. package/dist/src/telemetry/__tests__/json.test.js +0 -89
  572. package/dist/src/telemetry/__tests__/json.test.js.map +0 -1
  573. package/dist/src/telemetry/__tests__/local-trace.test.d.ts +0 -2
  574. package/dist/src/telemetry/__tests__/local-trace.test.d.ts.map +0 -1
  575. package/dist/src/telemetry/__tests__/local-trace.test.js +0 -158
  576. package/dist/src/telemetry/__tests__/local-trace.test.js.map +0 -1
  577. package/dist/src/telemetry/__tests__/meter.test.d.ts +0 -2
  578. package/dist/src/telemetry/__tests__/meter.test.d.ts.map +0 -1
  579. package/dist/src/telemetry/__tests__/meter.test.js +0 -695
  580. package/dist/src/telemetry/__tests__/meter.test.js.map +0 -1
  581. package/dist/src/telemetry/__tests__/tracer.test.node.d.ts +0 -2
  582. package/dist/src/telemetry/__tests__/tracer.test.node.d.ts.map +0 -1
  583. package/dist/src/telemetry/__tests__/tracer.test.node.js +0 -760
  584. package/dist/src/telemetry/__tests__/tracer.test.node.js.map +0 -1
  585. package/dist/src/tools/__tests__/structured-output-tool.test.d.ts +0 -2
  586. package/dist/src/tools/__tests__/structured-output-tool.test.d.ts.map +0 -1
  587. package/dist/src/tools/__tests__/structured-output-tool.test.js +0 -84
  588. package/dist/src/tools/__tests__/structured-output-tool.test.js.map +0 -1
  589. package/dist/src/tools/__tests__/tool-factory.test.d.ts +0 -2
  590. package/dist/src/tools/__tests__/tool-factory.test.d.ts.map +0 -1
  591. package/dist/src/tools/__tests__/tool-factory.test.js +0 -98
  592. package/dist/src/tools/__tests__/tool-factory.test.js.map +0 -1
  593. package/dist/src/tools/__tests__/tool.test.d.ts +0 -2
  594. package/dist/src/tools/__tests__/tool.test.d.ts.map +0 -1
  595. package/dist/src/tools/__tests__/tool.test.js +0 -1043
  596. package/dist/src/tools/__tests__/tool.test.js.map +0 -1
  597. package/dist/src/tools/__tests__/zod-tool.test-d.d.ts +0 -2
  598. package/dist/src/tools/__tests__/zod-tool.test-d.d.ts.map +0 -1
  599. package/dist/src/tools/__tests__/zod-tool.test-d.js +0 -227
  600. package/dist/src/tools/__tests__/zod-tool.test-d.js.map +0 -1
  601. package/dist/src/tools/__tests__/zod-tool.test.d.ts +0 -2
  602. package/dist/src/tools/__tests__/zod-tool.test.d.ts.map +0 -1
  603. package/dist/src/tools/__tests__/zod-tool.test.js +0 -563
  604. package/dist/src/tools/__tests__/zod-tool.test.js.map +0 -1
  605. package/dist/src/types/__tests__/agent.test.d.ts +0 -2
  606. package/dist/src/types/__tests__/agent.test.d.ts.map +0 -1
  607. package/dist/src/types/__tests__/agent.test.js +0 -476
  608. package/dist/src/types/__tests__/agent.test.js.map +0 -1
  609. package/dist/src/types/__tests__/citations.test.d.ts +0 -2
  610. package/dist/src/types/__tests__/citations.test.d.ts.map +0 -1
  611. package/dist/src/types/__tests__/citations.test.js +0 -104
  612. package/dist/src/types/__tests__/citations.test.js.map +0 -1
  613. package/dist/src/types/__tests__/json.test.d.ts +0 -2
  614. package/dist/src/types/__tests__/json.test.d.ts.map +0 -1
  615. package/dist/src/types/__tests__/json.test.js +0 -298
  616. package/dist/src/types/__tests__/json.test.js.map +0 -1
  617. package/dist/src/types/__tests__/media.test.d.ts +0 -2
  618. package/dist/src/types/__tests__/media.test.d.ts.map +0 -1
  619. package/dist/src/types/__tests__/media.test.js +0 -478
  620. package/dist/src/types/__tests__/media.test.js.map +0 -1
  621. package/dist/src/types/__tests__/messages.test.d.ts +0 -2
  622. package/dist/src/types/__tests__/messages.test.d.ts.map +0 -1
  623. package/dist/src/types/__tests__/messages.test.js +0 -681
  624. package/dist/src/types/__tests__/messages.test.js.map +0 -1
  625. package/dist/src/types/__tests__/validation.test.d.ts +0 -2
  626. package/dist/src/types/__tests__/validation.test.d.ts.map +0 -1
  627. package/dist/src/types/__tests__/validation.test.js +0 -30
  628. package/dist/src/types/__tests__/validation.test.js.map +0 -1
  629. package/dist/src/vended-interventions/cedar/__tests__/cedar.test.node.d.ts +0 -2
  630. package/dist/src/vended-interventions/cedar/__tests__/cedar.test.node.d.ts.map +0 -1
  631. package/dist/src/vended-interventions/cedar/__tests__/cedar.test.node.js +0 -675
  632. package/dist/src/vended-interventions/cedar/__tests__/cedar.test.node.js.map +0 -1
  633. package/dist/src/vended-interventions/hitl/__tests__/hitl.test.d.ts +0 -2
  634. package/dist/src/vended-interventions/hitl/__tests__/hitl.test.d.ts.map +0 -1
  635. package/dist/src/vended-interventions/hitl/__tests__/hitl.test.js +0 -358
  636. package/dist/src/vended-interventions/hitl/__tests__/hitl.test.js.map +0 -1
  637. package/dist/src/vended-interventions/steering/__tests__/handler.test.d.ts +0 -2
  638. package/dist/src/vended-interventions/steering/__tests__/handler.test.d.ts.map +0 -1
  639. package/dist/src/vended-interventions/steering/__tests__/handler.test.js +0 -163
  640. package/dist/src/vended-interventions/steering/__tests__/handler.test.js.map +0 -1
  641. package/dist/src/vended-interventions/steering/__tests__/llm.test.d.ts +0 -2
  642. package/dist/src/vended-interventions/steering/__tests__/llm.test.d.ts.map +0 -1
  643. package/dist/src/vended-interventions/steering/__tests__/llm.test.js +0 -60
  644. package/dist/src/vended-interventions/steering/__tests__/llm.test.js.map +0 -1
  645. package/dist/src/vended-interventions/steering/__tests__/tool-ledger.test.d.ts +0 -2
  646. package/dist/src/vended-interventions/steering/__tests__/tool-ledger.test.d.ts.map +0 -1
  647. package/dist/src/vended-interventions/steering/__tests__/tool-ledger.test.js +0 -94
  648. package/dist/src/vended-interventions/steering/__tests__/tool-ledger.test.js.map +0 -1
  649. package/dist/src/vended-memory-stores/bedrock-knowledge-base/__tests__/bedrock-knowledge-base-store.test.d.ts +0 -2
  650. package/dist/src/vended-memory-stores/bedrock-knowledge-base/__tests__/bedrock-knowledge-base-store.test.d.ts.map +0 -1
  651. package/dist/src/vended-memory-stores/bedrock-knowledge-base/__tests__/bedrock-knowledge-base-store.test.js +0 -611
  652. package/dist/src/vended-memory-stores/bedrock-knowledge-base/__tests__/bedrock-knowledge-base-store.test.js.map +0 -1
  653. package/dist/src/vended-plugins/context-injector/__tests__/plugin.test.d.ts +0 -2
  654. package/dist/src/vended-plugins/context-injector/__tests__/plugin.test.d.ts.map +0 -1
  655. package/dist/src/vended-plugins/context-injector/__tests__/plugin.test.js +0 -96
  656. package/dist/src/vended-plugins/context-injector/__tests__/plugin.test.js.map +0 -1
  657. package/dist/src/vended-plugins/context-offloader/__tests__/file-storage-sandbox.test.node.d.ts +0 -2
  658. package/dist/src/vended-plugins/context-offloader/__tests__/file-storage-sandbox.test.node.d.ts.map +0 -1
  659. package/dist/src/vended-plugins/context-offloader/__tests__/file-storage-sandbox.test.node.js +0 -68
  660. package/dist/src/vended-plugins/context-offloader/__tests__/file-storage-sandbox.test.node.js.map +0 -1
  661. package/dist/src/vended-plugins/context-offloader/__tests__/plugin.test.d.ts +0 -2
  662. package/dist/src/vended-plugins/context-offloader/__tests__/plugin.test.d.ts.map +0 -1
  663. package/dist/src/vended-plugins/context-offloader/__tests__/plugin.test.js +0 -539
  664. package/dist/src/vended-plugins/context-offloader/__tests__/plugin.test.js.map +0 -1
  665. package/dist/src/vended-plugins/context-offloader/__tests__/plugin.test.node.d.ts +0 -2
  666. package/dist/src/vended-plugins/context-offloader/__tests__/plugin.test.node.d.ts.map +0 -1
  667. package/dist/src/vended-plugins/context-offloader/__tests__/plugin.test.node.js +0 -93
  668. package/dist/src/vended-plugins/context-offloader/__tests__/plugin.test.node.js.map +0 -1
  669. package/dist/src/vended-plugins/context-offloader/__tests__/search.test.d.ts +0 -2
  670. package/dist/src/vended-plugins/context-offloader/__tests__/search.test.d.ts.map +0 -1
  671. package/dist/src/vended-plugins/context-offloader/__tests__/search.test.js +0 -149
  672. package/dist/src/vended-plugins/context-offloader/__tests__/search.test.js.map +0 -1
  673. package/dist/src/vended-plugins/context-offloader/__tests__/storage.test.d.ts +0 -2
  674. package/dist/src/vended-plugins/context-offloader/__tests__/storage.test.d.ts.map +0 -1
  675. package/dist/src/vended-plugins/context-offloader/__tests__/storage.test.js +0 -216
  676. package/dist/src/vended-plugins/context-offloader/__tests__/storage.test.js.map +0 -1
  677. package/dist/src/vended-plugins/context-offloader/__tests__/storage.test.node.d.ts +0 -2
  678. package/dist/src/vended-plugins/context-offloader/__tests__/storage.test.node.d.ts.map +0 -1
  679. package/dist/src/vended-plugins/context-offloader/__tests__/storage.test.node.js +0 -78
  680. package/dist/src/vended-plugins/context-offloader/__tests__/storage.test.node.js.map +0 -1
  681. package/dist/src/vended-plugins/goal/__tests__/plugin.test.d.ts +0 -2
  682. package/dist/src/vended-plugins/goal/__tests__/plugin.test.d.ts.map +0 -1
  683. package/dist/src/vended-plugins/goal/__tests__/plugin.test.js +0 -736
  684. package/dist/src/vended-plugins/goal/__tests__/plugin.test.js.map +0 -1
  685. package/dist/src/vended-plugins/skills/__tests__/agent-skills.test.node.d.ts +0 -2
  686. package/dist/src/vended-plugins/skills/__tests__/agent-skills.test.node.d.ts.map +0 -1
  687. package/dist/src/vended-plugins/skills/__tests__/agent-skills.test.node.js +0 -482
  688. package/dist/src/vended-plugins/skills/__tests__/agent-skills.test.node.js.map +0 -1
  689. package/dist/src/vended-plugins/skills/__tests__/skill.test.node.d.ts +0 -2
  690. package/dist/src/vended-plugins/skills/__tests__/skill.test.node.d.ts.map +0 -1
  691. package/dist/src/vended-plugins/skills/__tests__/skill.test.node.js +0 -476
  692. package/dist/src/vended-plugins/skills/__tests__/skill.test.node.js.map +0 -1
  693. package/dist/src/vended-tools/bash/__tests__/bash.test.node.d.ts +0 -2
  694. package/dist/src/vended-tools/bash/__tests__/bash.test.node.d.ts.map +0 -1
  695. package/dist/src/vended-tools/bash/__tests__/bash.test.node.js +0 -390
  696. package/dist/src/vended-tools/bash/__tests__/bash.test.node.js.map +0 -1
  697. package/dist/src/vended-tools/file-editor/__tests__/file-editor.test.node.d.ts +0 -2
  698. package/dist/src/vended-tools/file-editor/__tests__/file-editor.test.node.d.ts.map +0 -1
  699. package/dist/src/vended-tools/file-editor/__tests__/file-editor.test.node.js +0 -452
  700. package/dist/src/vended-tools/file-editor/__tests__/file-editor.test.node.js.map +0 -1
  701. package/dist/src/vended-tools/http-request/__tests__/http-request.test.d.ts +0 -2
  702. package/dist/src/vended-tools/http-request/__tests__/http-request.test.d.ts.map +0 -1
  703. package/dist/src/vended-tools/http-request/__tests__/http-request.test.js +0 -189
  704. package/dist/src/vended-tools/http-request/__tests__/http-request.test.js.map +0 -1
  705. package/dist/src/vended-tools/notebook/__tests__/notebook.test.d.ts +0 -2
  706. package/dist/src/vended-tools/notebook/__tests__/notebook.test.d.ts.map +0 -1
  707. package/dist/src/vended-tools/notebook/__tests__/notebook.test.js +0 -388
  708. package/dist/src/vended-tools/notebook/__tests__/notebook.test.js.map +0 -1
@@ -1,1332 +0,0 @@
1
- import { beforeEach, describe, expect, it } from 'vitest';
2
- import { Agent } from '../agent.js';
3
- import { AfterInvocationEvent, AfterModelCallEvent, AfterToolCallEvent, AfterToolsEvent, AgentResultEvent, BeforeInvocationEvent, BeforeModelCallEvent, BeforeToolCallEvent, BeforeToolsEvent, MessageAddedEvent, ModelStreamUpdateEvent, InitializedEvent, HookableEvent, ModelMessageEvent, } from '../../hooks/index.js';
4
- import { MockMessageModel } from '../../__fixtures__/mock-message-model.js';
5
- import { MockPlugin } from '../../__fixtures__/mock-plugin.js';
6
- import { collectIterator } from '../../__fixtures__/model-test-helpers.js';
7
- import { createMockTool } from '../../__fixtures__/tool-helpers.js';
8
- import { expectAgentResult } from '../../__fixtures__/agent-helpers.js';
9
- import { Message, TextBlock, ToolResultBlock } from '../../types/messages.js';
10
- describe('Agent Hooks Integration', () => {
11
- let mockPlugin;
12
- beforeEach(() => {
13
- mockPlugin = new MockPlugin();
14
- });
15
- describe('invocation lifecycle', () => {
16
- it('fires hooks during invoke', async () => {
17
- const lifecyclePlugin = new MockPlugin();
18
- const model = new MockMessageModel().addTurn({ type: 'textBlock', text: 'Hello' });
19
- const agent = new Agent({ model, plugins: [lifecyclePlugin] });
20
- await agent.invoke('Hi');
21
- expect(lifecyclePlugin.invocations).toHaveLength(7);
22
- expect(lifecyclePlugin.invocations[0]).toEqual(new InitializedEvent({ agent }));
23
- expect(lifecyclePlugin.invocations[1]).toEqual(new BeforeInvocationEvent({ agent, invocationState: {} }));
24
- expect(lifecyclePlugin.invocations[2]).toEqual(new MessageAddedEvent({
25
- agent,
26
- message: new Message({ role: 'user', content: [new TextBlock('Hi')] }),
27
- invocationState: {},
28
- }));
29
- expect(lifecyclePlugin.invocations[3]).toEqual(new BeforeModelCallEvent({
30
- agent,
31
- model: agent.model,
32
- invocationState: {},
33
- projectedInputTokens: expect.any(Number),
34
- }));
35
- expect(lifecyclePlugin.invocations[4]).toEqual(new AfterModelCallEvent({
36
- agent,
37
- model: agent.model,
38
- invocationState: {},
39
- attemptCount: 1,
40
- stopData: {
41
- stopReason: 'endTurn',
42
- message: new Message({ role: 'assistant', content: [new TextBlock('Hello')] }),
43
- },
44
- }));
45
- expect(lifecyclePlugin.invocations[5]).toEqual(new MessageAddedEvent({
46
- agent,
47
- message: new Message({ role: 'assistant', content: [new TextBlock('Hello')] }),
48
- invocationState: {},
49
- }));
50
- expect(lifecyclePlugin.invocations[6]).toEqual(new AfterInvocationEvent({ agent, invocationState: {} }));
51
- });
52
- it('fires hooks during stream', async () => {
53
- const lifecyclePlugin = new MockPlugin();
54
- const model = new MockMessageModel().addTurn({ type: 'textBlock', text: 'Hello' });
55
- const agent = new Agent({ model, plugins: [lifecyclePlugin] });
56
- await collectIterator(agent.stream('Hi'));
57
- expect(lifecyclePlugin.invocations).toHaveLength(7);
58
- expect(lifecyclePlugin.invocations[0]).toEqual(new InitializedEvent({ agent }));
59
- expect(lifecyclePlugin.invocations[1]).toEqual(new BeforeInvocationEvent({ agent, invocationState: {} }));
60
- expect(lifecyclePlugin.invocations[2]).toEqual(new MessageAddedEvent({
61
- agent,
62
- message: new Message({ role: 'user', content: [new TextBlock('Hi')] }),
63
- invocationState: {},
64
- }));
65
- expect(lifecyclePlugin.invocations[3]).toEqual(new BeforeModelCallEvent({
66
- agent,
67
- model: agent.model,
68
- invocationState: {},
69
- projectedInputTokens: expect.any(Number),
70
- }));
71
- expect(lifecyclePlugin.invocations[4]).toEqual(new AfterModelCallEvent({
72
- agent,
73
- model: agent.model,
74
- invocationState: {},
75
- attemptCount: 1,
76
- stopData: {
77
- stopReason: 'endTurn',
78
- message: new Message({ role: 'assistant', content: [new TextBlock('Hello')] }),
79
- },
80
- }));
81
- expect(lifecyclePlugin.invocations[5]).toEqual(new MessageAddedEvent({
82
- agent,
83
- message: new Message({ role: 'assistant', content: [new TextBlock('Hello')] }),
84
- invocationState: {},
85
- }));
86
- expect(lifecyclePlugin.invocations[6]).toEqual(new AfterInvocationEvent({ agent, invocationState: {} }));
87
- });
88
- });
89
- describe('runtime hook registration', () => {
90
- it('allows adding hooks after agent creation via addHook', async () => {
91
- const model = new MockMessageModel().addTurn({ type: 'textBlock', text: 'Hello' });
92
- const agent = new Agent({ model });
93
- // Track events via individual hook registrations
94
- const invocations = [];
95
- agent.addHook(BeforeInvocationEvent, (e) => {
96
- invocations.push(e);
97
- });
98
- agent.addHook(AfterInvocationEvent, (e) => {
99
- invocations.push(e);
100
- });
101
- await agent.invoke('Hi');
102
- expect(invocations).toHaveLength(2);
103
- expect(invocations[0]).toEqual(new BeforeInvocationEvent({ agent, invocationState: {} }));
104
- expect(invocations[1]).toEqual(new AfterInvocationEvent({ agent, invocationState: {} }));
105
- });
106
- });
107
- describe('multi-turn conversations', () => {
108
- it('fires hooks for each invoke call', async () => {
109
- const lifecyclePlugin = new MockPlugin();
110
- const model = new MockMessageModel()
111
- .addTurn({ type: 'textBlock', text: 'First response' })
112
- .addTurn({ type: 'textBlock', text: 'Second response' });
113
- const agent = new Agent({ model, plugins: [lifecyclePlugin] });
114
- await agent.invoke('First message');
115
- // First turn: InitializedEvent + BeforeInvocation, MessageAdded, BeforeModelCall, AfterModelCall, MessageAdded, AfterInvocation
116
- expect(lifecyclePlugin.invocations).toHaveLength(7);
117
- await agent.invoke('Second message');
118
- // Should have 13 events total (7 for first turn + 6 for second turn, no InitializedEvent on second)
119
- expect(lifecyclePlugin.invocations).toHaveLength(13);
120
- // Filter for just Invocation events to verify they fire for each turn
121
- const invocationEvents = lifecyclePlugin.invocations.filter((e) => e instanceof BeforeInvocationEvent || e instanceof AfterInvocationEvent);
122
- expect(invocationEvents).toHaveLength(4); // 2 for each turn
123
- });
124
- });
125
- describe('tool execution hooks', () => {
126
- it('fires tool hooks during tool execution', async () => {
127
- const tool = createMockTool('testTool', () => {
128
- return new ToolResultBlock({ toolUseId: 'tool-1', status: 'success', content: [new TextBlock('Tool result')] });
129
- });
130
- const model = new MockMessageModel()
131
- .addTurn({ type: 'toolUseBlock', name: 'testTool', toolUseId: 'tool-1', input: {} })
132
- .addTurn({ type: 'textBlock', text: 'Final response' });
133
- const agent = new Agent({
134
- model,
135
- tools: [tool],
136
- plugins: [mockPlugin],
137
- });
138
- await agent.invoke('Test with tool');
139
- // Find key events
140
- const beforeToolCallEvents = mockPlugin.invocations.filter((e) => e instanceof BeforeToolCallEvent);
141
- const afterToolCallEvents = mockPlugin.invocations.filter((e) => e instanceof AfterToolCallEvent);
142
- const messageAddedEvents = mockPlugin.invocations.filter((e) => e instanceof MessageAddedEvent);
143
- // Verify tool hooks fired
144
- expect(beforeToolCallEvents.length).toBe(1);
145
- expect(afterToolCallEvents.length).toBe(1);
146
- // Verify 3 MessageAdded events: input message, assistant with tool use, tool result, final assistant
147
- expect(messageAddedEvents.length).toBe(4);
148
- // Verify BeforeToolCallEvent
149
- const beforeToolCall = beforeToolCallEvents[0];
150
- expect(beforeToolCall).toEqual(new BeforeToolCallEvent({
151
- agent,
152
- toolUse: { name: 'testTool', toolUseId: 'tool-1', input: {} },
153
- tool,
154
- invocationState: {},
155
- }));
156
- // Verify AfterToolCallEvent
157
- const afterToolCall = afterToolCallEvents[0];
158
- expect(afterToolCall).toEqual(new AfterToolCallEvent({
159
- agent,
160
- toolUse: { name: 'testTool', toolUseId: 'tool-1', input: {} },
161
- tool,
162
- result: new ToolResultBlock({
163
- toolUseId: 'tool-1',
164
- status: 'success',
165
- content: [new TextBlock('Tool result')],
166
- }),
167
- invocationState: {},
168
- }));
169
- });
170
- it('fires AfterToolCallEvent with error when tool fails', async () => {
171
- const tool = createMockTool('failingTool', () => {
172
- throw new Error('Tool execution failed');
173
- });
174
- const model = new MockMessageModel()
175
- .addTurn({ type: 'toolUseBlock', name: 'failingTool', toolUseId: 'tool-1', input: {} })
176
- .addTurn({ type: 'textBlock', text: 'Handled error' });
177
- const agent = new Agent({
178
- model,
179
- tools: [tool],
180
- plugins: [mockPlugin],
181
- });
182
- // Agent should complete successfully (tool errors are handled gracefully)
183
- const result = await agent.invoke('Test with failing tool');
184
- expect(result.stopReason).toBe('endTurn');
185
- // Find AfterToolCallEvent
186
- const afterToolCallEvents = mockPlugin.invocations.filter((e) => e instanceof AfterToolCallEvent);
187
- expect(afterToolCallEvents.length).toBe(1);
188
- const afterToolCall = afterToolCallEvents[0];
189
- expect(afterToolCall).toEqual(new AfterToolCallEvent({
190
- agent,
191
- toolUse: { name: 'failingTool', toolUseId: 'tool-1', input: {} },
192
- tool,
193
- result: new ToolResultBlock({
194
- error: new Error('Tool execution failed'),
195
- toolUseId: 'tool-1',
196
- status: 'error',
197
- content: [new TextBlock('Tool execution failed')],
198
- }),
199
- error: new Error('Tool execution failed'),
200
- invocationState: {},
201
- }));
202
- });
203
- });
204
- describe('ModelStreamUpdateEvent', () => {
205
- it('is yielded in the stream and dispatched to hooks', async () => {
206
- const model = new MockMessageModel().addTurn({ type: 'textBlock', text: 'Hello' });
207
- const streamUpdateEvents = [];
208
- const agent = new Agent({ model });
209
- agent.addHook(ModelStreamUpdateEvent, (event) => {
210
- streamUpdateEvents.push(event);
211
- });
212
- // Collect all stream events
213
- const allStreamEvents = [];
214
- for await (const event of agent.stream('Test')) {
215
- allStreamEvents.push(event);
216
- }
217
- // Should be yielded in the stream
218
- const streamUpdates = allStreamEvents.filter((e) => e instanceof ModelStreamUpdateEvent);
219
- expect(streamUpdates.length).toBeGreaterThan(0);
220
- // Should also fire as hook
221
- expect(streamUpdateEvents.length).toBeGreaterThan(0);
222
- // Stream and hook should receive the same event instances
223
- expect(streamUpdates).toStrictEqual(streamUpdateEvents);
224
- });
225
- });
226
- describe('MessageAddedEvent', () => {
227
- it('fires for initial user input', async () => {
228
- const initialMessage = { role: 'user', content: [{ type: 'textBlock', text: 'Initial' }] };
229
- const model = new MockMessageModel().addTurn({ type: 'textBlock', text: 'Response' });
230
- const agent = new Agent({
231
- model,
232
- messages: [initialMessage],
233
- plugins: [mockPlugin],
234
- });
235
- await agent.invoke('New message');
236
- const messageAddedEvents = mockPlugin.invocations.filter((e) => e instanceof MessageAddedEvent);
237
- // Should have 2 MessageAdded event
238
- expect(messageAddedEvents).toHaveLength(2);
239
- expect(messageAddedEvents[0]).toEqual(new MessageAddedEvent({
240
- agent,
241
- message: new Message({ role: 'user', content: [new TextBlock('New message')] }),
242
- invocationState: {},
243
- }));
244
- expect(messageAddedEvents[1]).toEqual(new MessageAddedEvent({
245
- agent,
246
- message: new Message({ role: 'assistant', content: [new TextBlock('Response')] }),
247
- invocationState: {},
248
- }));
249
- });
250
- });
251
- describe('AfterModelCallEvent retry', () => {
252
- it('does not duplicate user messages on error retry', async () => {
253
- const model = new MockMessageModel()
254
- .addTurn(new Error('context overflow'))
255
- .addTurn({ type: 'textBlock', text: 'Success' });
256
- const agent = new Agent({ model, printer: false });
257
- agent.addHook(AfterModelCallEvent, (event) => {
258
- if (event.error) {
259
- event.retry = true;
260
- }
261
- });
262
- await agent.invoke('Hello');
263
- // Count user messages with "Hello" — should be exactly 1
264
- const userMessages = agent.messages.filter((m) => m.role === 'user' && m.content.some((b) => b.type === 'textBlock' && b.text === 'Hello'));
265
- expect(userMessages).toHaveLength(1);
266
- });
267
- it('does not duplicate user messages on success retry', async () => {
268
- let callCount = 0;
269
- const model = new MockMessageModel()
270
- .addTurn({ type: 'textBlock', text: 'First' })
271
- .addTurn({ type: 'textBlock', text: 'Second' });
272
- const agent = new Agent({ model, printer: false });
273
- agent.addHook(AfterModelCallEvent, (event) => {
274
- callCount++;
275
- if (callCount === 1 && !event.error) {
276
- event.retry = true;
277
- }
278
- });
279
- await agent.invoke('Hello');
280
- const userMessages = agent.messages.filter((m) => m.role === 'user' && m.content.some((b) => b.type === 'textBlock' && b.text === 'Hello'));
281
- expect(userMessages).toHaveLength(1);
282
- });
283
- it('retries model call when hook sets retry', async () => {
284
- let callCount = 0;
285
- const model = new MockMessageModel()
286
- .addTurn(new Error('First attempt failed'))
287
- .addTurn({ type: 'textBlock', text: 'Success after retry' });
288
- const agent = new Agent({ model });
289
- agent.addHook(AfterModelCallEvent, (event) => {
290
- callCount++;
291
- if (callCount === 1 && event.error) {
292
- event.retry = true;
293
- }
294
- });
295
- const result = await agent.invoke('Test');
296
- expect(result.lastMessage.content[0]).toEqual({ type: 'textBlock', text: 'Success after retry' });
297
- expect(callCount).toBe(2);
298
- });
299
- it('does not retry when retry is not set', async () => {
300
- const model = new MockMessageModel().addTurn(new Error('Failure'));
301
- const agent = new Agent({ model });
302
- await expect(agent.invoke('Test')).rejects.toThrow('Failure');
303
- });
304
- it('retries model call on success when hook requests it', async () => {
305
- let callCount = 0;
306
- const model = new MockMessageModel()
307
- .addTurn({ type: 'textBlock', text: 'First response' })
308
- .addTurn({ type: 'textBlock', text: 'Second response after retry' });
309
- const agent = new Agent({ model });
310
- agent.addHook(AfterModelCallEvent, (event) => {
311
- callCount++;
312
- if (callCount === 1 && !event.error) {
313
- event.retry = true;
314
- }
315
- });
316
- const result = await agent.invoke('Test');
317
- expect(result.lastMessage.content[0]).toEqual({ type: 'textBlock', text: 'Second response after retry' });
318
- expect(callCount).toBe(2);
319
- });
320
- });
321
- describe('AfterToolCallEvent retry', () => {
322
- it('retries tool call when hook sets retry', async () => {
323
- let toolCallCount = 0;
324
- const tool = createMockTool('retryableTool', () => {
325
- toolCallCount++;
326
- if (toolCallCount === 1) {
327
- throw new Error('First attempt failed');
328
- }
329
- return new ToolResultBlock({ toolUseId: 'tool-1', status: 'success', content: [new TextBlock('Success')] });
330
- });
331
- let hookCallCount = 0;
332
- const model = new MockMessageModel()
333
- .addTurn({ type: 'toolUseBlock', name: 'retryableTool', toolUseId: 'tool-1', input: {} })
334
- .addTurn({ type: 'textBlock', text: 'Done' });
335
- const agent = new Agent({ model, tools: [tool] });
336
- agent.addHook(AfterToolCallEvent, (event) => {
337
- hookCallCount++;
338
- if (hookCallCount === 1 && event.error) {
339
- event.retry = true;
340
- }
341
- });
342
- const result = await agent.invoke('Test');
343
- expect(result.stopReason).toBe('endTurn');
344
- expect(toolCallCount).toBe(2);
345
- expect(hookCallCount).toBe(2);
346
- });
347
- it('does not retry tool call when retry is not set', async () => {
348
- let toolCallCount = 0;
349
- const tool = createMockTool('failingTool', () => {
350
- toolCallCount++;
351
- throw new Error('Tool failed');
352
- });
353
- const model = new MockMessageModel()
354
- .addTurn({ type: 'toolUseBlock', name: 'failingTool', toolUseId: 'tool-1', input: {} })
355
- .addTurn({ type: 'textBlock', text: 'Handled error' });
356
- const agent = new Agent({ model, tools: [tool] });
357
- const result = await agent.invoke('Test');
358
- expect(result.stopReason).toBe('endTurn');
359
- expect(toolCallCount).toBe(1);
360
- });
361
- it('fires BeforeToolCallEvent on each retry', async () => {
362
- let toolCallCount = 0;
363
- const tool = createMockTool('retryableTool', () => {
364
- toolCallCount++;
365
- return new ToolResultBlock({
366
- toolUseId: 'tool-1',
367
- status: 'success',
368
- content: [new TextBlock(`Result ${toolCallCount}`)],
369
- });
370
- });
371
- let beforeCount = 0;
372
- let afterCount = 0;
373
- const model = new MockMessageModel()
374
- .addTurn({ type: 'toolUseBlock', name: 'retryableTool', toolUseId: 'tool-1', input: {} })
375
- .addTurn({ type: 'textBlock', text: 'Done' });
376
- const agent = new Agent({ model, tools: [tool] });
377
- agent.addHook(BeforeToolCallEvent, () => {
378
- beforeCount++;
379
- });
380
- agent.addHook(AfterToolCallEvent, (event) => {
381
- afterCount++;
382
- if (afterCount === 1) {
383
- event.retry = true;
384
- }
385
- });
386
- await agent.invoke('Test');
387
- expect(beforeCount).toBe(2);
388
- expect(afterCount).toBe(2);
389
- expect(toolCallCount).toBe(2);
390
- });
391
- it('retries tool call on success when hook requests it', async () => {
392
- let toolCallCount = 0;
393
- const tool = createMockTool('successTool', () => {
394
- toolCallCount++;
395
- return new ToolResultBlock({
396
- toolUseId: 'tool-1',
397
- status: 'success',
398
- content: [new TextBlock(`Result ${toolCallCount}`)],
399
- });
400
- });
401
- let hookCallCount = 0;
402
- const model = new MockMessageModel()
403
- .addTurn({ type: 'toolUseBlock', name: 'successTool', toolUseId: 'tool-1', input: {} })
404
- .addTurn({ type: 'textBlock', text: 'Done' });
405
- const agent = new Agent({ model, tools: [tool] });
406
- agent.addHook(AfterToolCallEvent, (event) => {
407
- hookCallCount++;
408
- if (hookCallCount === 1) {
409
- event.retry = true;
410
- }
411
- });
412
- const result = await agent.invoke('Test');
413
- expect(result.stopReason).toBe('endTurn');
414
- expect(toolCallCount).toBe(2);
415
- expect(hookCallCount).toBe(2);
416
- });
417
- });
418
- describe('cancel tool via hooks', () => {
419
- it('cancels individual tool call with default message when cancel is true', async () => {
420
- let toolExecuted = false;
421
- const tool = createMockTool('blockedTool', () => {
422
- toolExecuted = true;
423
- return new ToolResultBlock({ toolUseId: 'tool-1', status: 'success', content: [new TextBlock('Success')] });
424
- });
425
- const model = new MockMessageModel()
426
- .addTurn({ type: 'toolUseBlock', name: 'blockedTool', toolUseId: 'tool-1', input: {} })
427
- .addTurn({ type: 'textBlock', text: 'Done' });
428
- const agent = new Agent({ model, tools: [tool], plugins: [mockPlugin] });
429
- agent.addHook(BeforeToolCallEvent, (event) => {
430
- event.cancel = true;
431
- });
432
- const result = await agent.invoke('Test');
433
- expect(result.stopReason).toBe('endTurn');
434
- expect(toolExecuted).toBe(false);
435
- const afterToolCallEvents = mockPlugin.invocations.filter((e) => e instanceof AfterToolCallEvent);
436
- expect(afterToolCallEvents).toHaveLength(1);
437
- const afterEvent = afterToolCallEvents[0];
438
- expect(afterEvent.result).toEqual(new ToolResultBlock({
439
- toolUseId: 'tool-1',
440
- status: 'error',
441
- content: [new TextBlock('Tool cancelled by hook')],
442
- }));
443
- });
444
- it('cancels individual tool call with custom message when cancel is a string', async () => {
445
- let toolExecuted = false;
446
- const tool = createMockTool('blockedTool', () => {
447
- toolExecuted = true;
448
- return new ToolResultBlock({ toolUseId: 'tool-1', status: 'success', content: [new TextBlock('Success')] });
449
- });
450
- const model = new MockMessageModel()
451
- .addTurn({ type: 'toolUseBlock', name: 'blockedTool', toolUseId: 'tool-1', input: {} })
452
- .addTurn({ type: 'textBlock', text: 'Done' });
453
- const agent = new Agent({ model, tools: [tool], plugins: [mockPlugin] });
454
- agent.addHook(BeforeToolCallEvent, (event) => {
455
- event.cancel = 'Tool call limit exceeded';
456
- });
457
- const result = await agent.invoke('Test');
458
- expect(result.stopReason).toBe('endTurn');
459
- expect(toolExecuted).toBe(false);
460
- const afterToolCallEvents = mockPlugin.invocations.filter((e) => e instanceof AfterToolCallEvent);
461
- expect(afterToolCallEvents).toHaveLength(1);
462
- const afterEvent = afterToolCallEvents[0];
463
- expect(afterEvent.result).toEqual(new ToolResultBlock({
464
- toolUseId: 'tool-1',
465
- status: 'error',
466
- content: [new TextBlock('Tool call limit exceeded')],
467
- }));
468
- });
469
- it('cancels only specific tools when BeforeToolCallEvent selectively cancels', async () => {
470
- const executedTools = [];
471
- const tool1 = createMockTool('allowedTool', () => {
472
- executedTools.push('allowedTool');
473
- return new ToolResultBlock({ toolUseId: 'tool-1', status: 'success', content: [new TextBlock('Allowed')] });
474
- });
475
- const tool2 = createMockTool('blockedTool', () => {
476
- executedTools.push('blockedTool');
477
- return new ToolResultBlock({ toolUseId: 'tool-2', status: 'success', content: [new TextBlock('Blocked')] });
478
- });
479
- const model = new MockMessageModel()
480
- .addTurn([
481
- { type: 'toolUseBlock', name: 'allowedTool', toolUseId: 'tool-1', input: {} },
482
- { type: 'toolUseBlock', name: 'blockedTool', toolUseId: 'tool-2', input: {} },
483
- ])
484
- .addTurn({ type: 'textBlock', text: 'Done' });
485
- const agent = new Agent({ model, tools: [tool1, tool2], plugins: [mockPlugin] });
486
- agent.addHook(BeforeToolCallEvent, (event) => {
487
- if (event.toolUse.name === 'blockedTool') {
488
- event.cancel = 'This tool is blocked';
489
- }
490
- });
491
- const result = await agent.invoke('Test');
492
- expect(result.stopReason).toBe('endTurn');
493
- expect(executedTools).toEqual(['allowedTool']);
494
- const afterToolCallEvents = mockPlugin.invocations.filter((e) => e instanceof AfterToolCallEvent);
495
- expect(afterToolCallEvents).toHaveLength(2);
496
- expect(afterToolCallEvents[0].result).toEqual(new ToolResultBlock({ toolUseId: 'tool-1', status: 'success', content: [new TextBlock('Allowed')] }));
497
- expect(afterToolCallEvents[1].result).toEqual(new ToolResultBlock({
498
- toolUseId: 'tool-2',
499
- status: 'error',
500
- content: [new TextBlock('This tool is blocked')],
501
- }));
502
- });
503
- it('cancels all tools with default message when BeforeToolsEvent.cancel is true', async () => {
504
- let toolExecuted = false;
505
- const tool = createMockTool('blockedTool', () => {
506
- toolExecuted = true;
507
- return new ToolResultBlock({ toolUseId: 'tool-1', status: 'success', content: [new TextBlock('Success')] });
508
- });
509
- const model = new MockMessageModel()
510
- .addTurn({ type: 'toolUseBlock', name: 'blockedTool', toolUseId: 'tool-1', input: {} })
511
- .addTurn({ type: 'textBlock', text: 'Done' });
512
- const agent = new Agent({ model, tools: [tool], plugins: [mockPlugin] });
513
- agent.addHook(BeforeToolsEvent, (event) => {
514
- event.cancel = true;
515
- });
516
- const result = await agent.invoke('Test');
517
- expect(result.stopReason).toBe('endTurn');
518
- expect(toolExecuted).toBe(false);
519
- const afterToolsEvents = mockPlugin.invocations.filter((e) => e instanceof AfterToolsEvent);
520
- expect(afterToolsEvents).toHaveLength(1);
521
- const afterEvent = afterToolsEvents[0];
522
- expect(afterEvent.message.content[0]).toEqual(new ToolResultBlock({
523
- toolUseId: 'tool-1',
524
- status: 'error',
525
- content: [new TextBlock('Tool cancelled by hook')],
526
- }));
527
- });
528
- it('cancels all tools with custom message when BeforeToolsEvent.cancel is a string', async () => {
529
- let toolExecuted = false;
530
- const tool = createMockTool('blockedTool', () => {
531
- toolExecuted = true;
532
- return new ToolResultBlock({ toolUseId: 'tool-1', status: 'success', content: [new TextBlock('Success')] });
533
- });
534
- const model = new MockMessageModel()
535
- .addTurn({ type: 'toolUseBlock', name: 'blockedTool', toolUseId: 'tool-1', input: {} })
536
- .addTurn({ type: 'textBlock', text: 'Done' });
537
- const agent = new Agent({ model, tools: [tool], plugins: [mockPlugin] });
538
- agent.addHook(BeforeToolsEvent, (event) => {
539
- event.cancel = 'All tools blocked';
540
- });
541
- const result = await agent.invoke('Test');
542
- expect(result.stopReason).toBe('endTurn');
543
- expect(toolExecuted).toBe(false);
544
- const afterToolsEvents = mockPlugin.invocations.filter((e) => e instanceof AfterToolsEvent);
545
- expect(afterToolsEvents).toHaveLength(1);
546
- const afterEvent = afterToolsEvents[0];
547
- expect(afterEvent.message.content[0]).toEqual(new ToolResultBlock({
548
- toolUseId: 'tool-1',
549
- status: 'error',
550
- content: [new TextBlock('All tools blocked')],
551
- }));
552
- });
553
- it('cancels all tools in a batch via BeforeToolsEvent with correct toolUseIds', async () => {
554
- const executedTools = [];
555
- const tool1 = createMockTool('tool1', () => {
556
- executedTools.push('tool1');
557
- return new ToolResultBlock({ toolUseId: 'tool-1', status: 'success', content: [new TextBlock('Result 1')] });
558
- });
559
- const tool2 = createMockTool('tool2', () => {
560
- executedTools.push('tool2');
561
- return new ToolResultBlock({ toolUseId: 'tool-2', status: 'success', content: [new TextBlock('Result 2')] });
562
- });
563
- const model = new MockMessageModel()
564
- .addTurn([
565
- { type: 'toolUseBlock', name: 'tool1', toolUseId: 'tool-1', input: {} },
566
- { type: 'toolUseBlock', name: 'tool2', toolUseId: 'tool-2', input: {} },
567
- ])
568
- .addTurn({ type: 'textBlock', text: 'Done' });
569
- const agent = new Agent({ model, tools: [tool1, tool2], plugins: [mockPlugin] });
570
- agent.addHook(BeforeToolsEvent, (event) => {
571
- event.cancel = 'Batch cancelled';
572
- });
573
- const result = await agent.invoke('Test');
574
- expect(result.stopReason).toBe('endTurn');
575
- expect(executedTools).toEqual([]);
576
- const afterToolsEvents = mockPlugin.invocations.filter((e) => e instanceof AfterToolsEvent);
577
- expect(afterToolsEvents).toHaveLength(1);
578
- const afterEvent = afterToolsEvents[0];
579
- expect(afterEvent.message.content).toEqual([
580
- new ToolResultBlock({
581
- toolUseId: 'tool-1',
582
- status: 'error',
583
- content: [new TextBlock('Batch cancelled')],
584
- }),
585
- new ToolResultBlock({
586
- toolUseId: 'tool-2',
587
- status: 'error',
588
- content: [new TextBlock('Batch cancelled')],
589
- }),
590
- ]);
591
- });
592
- it('emits cancel events correctly via stream()', async () => {
593
- let toolExecuted = false;
594
- const tool = createMockTool('blockedTool', () => {
595
- toolExecuted = true;
596
- return new ToolResultBlock({ toolUseId: 'tool-1', status: 'success', content: [new TextBlock('Success')] });
597
- });
598
- const model = new MockMessageModel()
599
- .addTurn({ type: 'toolUseBlock', name: 'blockedTool', toolUseId: 'tool-1', input: {} })
600
- .addTurn({ type: 'textBlock', text: 'Done' });
601
- const agent = new Agent({ model, tools: [tool] });
602
- agent.addHook(BeforeToolCallEvent, (event) => {
603
- event.cancel = 'Cancelled via stream';
604
- });
605
- const items = await collectIterator(agent.stream('Test'));
606
- expect(toolExecuted).toBe(false);
607
- const beforeToolCallEvents = items.filter((e) => e instanceof BeforeToolCallEvent);
608
- const afterToolCallEvents = items.filter((e) => e instanceof AfterToolCallEvent);
609
- expect(beforeToolCallEvents).toHaveLength(1);
610
- expect(afterToolCallEvents).toHaveLength(1);
611
- const afterEvent = afterToolCallEvents[0];
612
- expect(afterEvent.result).toEqual(new ToolResultBlock({
613
- toolUseId: 'tool-1',
614
- status: 'error',
615
- content: [new TextBlock('Cancelled via stream')],
616
- }));
617
- });
618
- it('allows retry after cancel on BeforeToolCallEvent', async () => {
619
- let toolCallCount = 0;
620
- const tool = createMockTool('retryTool', () => {
621
- toolCallCount++;
622
- return new ToolResultBlock({ toolUseId: 'tool-1', status: 'success', content: [new TextBlock('Success')] });
623
- });
624
- let beforeCount = 0;
625
- const model = new MockMessageModel()
626
- .addTurn({ type: 'toolUseBlock', name: 'retryTool', toolUseId: 'tool-1', input: {} })
627
- .addTurn({ type: 'textBlock', text: 'Done' });
628
- const agent = new Agent({ model, tools: [tool] });
629
- agent.addHook(BeforeToolCallEvent, (event) => {
630
- beforeCount++;
631
- if (beforeCount === 1) {
632
- event.cancel = 'Not yet';
633
- }
634
- });
635
- agent.addHook(AfterToolCallEvent, (event) => {
636
- if (event.result.status === 'error' && beforeCount === 1) {
637
- event.retry = true;
638
- }
639
- });
640
- const result = await agent.invoke('Test');
641
- expect(result.stopReason).toBe('endTurn');
642
- expect(beforeCount).toBe(2);
643
- expect(toolCallCount).toBe(1); // Only executed on second attempt
644
- });
645
- it('allows hooks to replace result on AfterToolCallEvent', async () => {
646
- const tool = createMockTool('myTool', () => {
647
- return new ToolResultBlock({
648
- toolUseId: 'tool-1',
649
- status: 'success',
650
- content: [new TextBlock('original result')],
651
- });
652
- });
653
- const model = new MockMessageModel()
654
- .addTurn({ type: 'toolUseBlock', name: 'myTool', toolUseId: 'tool-1', input: {} })
655
- .addTurn({ type: 'textBlock', text: 'Done' });
656
- const agent = new Agent({ model, tools: [tool] });
657
- agent.addHook(AfterToolCallEvent, (event) => {
658
- event.result = new ToolResultBlock({
659
- toolUseId: event.result.toolUseId,
660
- status: 'success',
661
- content: [new TextBlock('replaced result')],
662
- });
663
- });
664
- await agent.invoke('Test');
665
- const toolResultMessage = agent.messages.find((m) => m.role === 'user' && m.content.some((b) => b.type === 'toolResultBlock'));
666
- const toolResultBlock = toolResultMessage.content.find((b) => b.type === 'toolResultBlock');
667
- expect(toolResultBlock).toStrictEqual(new ToolResultBlock({
668
- toolUseId: 'tool-1',
669
- status: 'success',
670
- content: [new TextBlock('replaced result')],
671
- }));
672
- });
673
- });
674
- describe('AfterToolsEvent.endTurn', () => {
675
- const makeSingleToolSetup = () => ({
676
- tool: createMockTool('myTool', () => {
677
- return new ToolResultBlock({ toolUseId: 'tool-1', status: 'success', content: [new TextBlock('result')] });
678
- }),
679
- model: new MockMessageModel()
680
- .addTurn({ type: 'toolUseBlock', name: 'myTool', toolUseId: 'tool-1', input: {} })
681
- .addTurn({ type: 'textBlock', text: 'Should not reach this' }),
682
- });
683
- it('halts the loop when endTurn is true with default message', async () => {
684
- const { tool, model } = makeSingleToolSetup();
685
- const agent = new Agent({ model, tools: [tool], plugins: [mockPlugin] });
686
- agent.addHook(AfterToolsEvent, (event) => {
687
- event.endTurn = true;
688
- });
689
- const result = await agent.invoke('Test');
690
- expect(result).toEqual(expect.objectContaining({
691
- type: 'agentResult',
692
- stopReason: 'endTurn',
693
- lastMessage: expect.objectContaining({
694
- role: 'assistant',
695
- content: expect.arrayContaining([
696
- expect.objectContaining({ type: 'textBlock', text: 'Turn ended early by hook after tool execution' }),
697
- ]),
698
- }),
699
- }));
700
- expect(model.callCount).toBe(1);
701
- });
702
- it('halts the loop with custom assistant message when endTurn is a string', async () => {
703
- const { tool, model } = makeSingleToolSetup();
704
- const agent = new Agent({ model, tools: [tool] });
705
- agent.addHook(AfterToolsEvent, (event) => {
706
- event.endTurn = 'enough information gathered';
707
- });
708
- const result = await agent.invoke('Test');
709
- expect(result).toEqual(expect.objectContaining({
710
- type: 'agentResult',
711
- stopReason: 'endTurn',
712
- lastMessage: expect.objectContaining({
713
- role: 'assistant',
714
- content: expect.arrayContaining([
715
- expect.objectContaining({ type: 'textBlock', text: 'enough information gathered' }),
716
- ]),
717
- }),
718
- }));
719
- expect(model.callCount).toBe(1);
720
- });
721
- it('does not halt when endTurn is false (default)', async () => {
722
- const { tool, model } = makeSingleToolSetup();
723
- const agent = new Agent({ model, tools: [tool] });
724
- const result = await agent.invoke('Test');
725
- expect(result).toEqual(expect.objectContaining({
726
- type: 'agentResult',
727
- stopReason: 'endTurn',
728
- lastMessage: expect.objectContaining({ role: 'assistant' }),
729
- }));
730
- expect(model.callCount).toBe(2);
731
- });
732
- it('treats empty string endTurn as falsy (does not halt)', async () => {
733
- const { tool, model } = makeSingleToolSetup();
734
- const agent = new Agent({ model, tools: [tool] });
735
- agent.addHook(AfterToolsEvent, (event) => {
736
- event.endTurn = '';
737
- });
738
- const result = await agent.invoke('Test');
739
- expect(result).toEqual(expect.objectContaining({
740
- type: 'agentResult',
741
- stopReason: 'endTurn',
742
- lastMessage: expect.objectContaining({ role: 'assistant' }),
743
- }));
744
- expect(model.callCount).toBe(2);
745
- });
746
- it('appends tool results and default endTurn message to conversation history', async () => {
747
- const { tool, model } = makeSingleToolSetup();
748
- const agent = new Agent({ model, tools: [tool] });
749
- agent.addHook(AfterToolsEvent, (event) => {
750
- event.endTurn = true;
751
- });
752
- await agent.invoke('Test');
753
- expect(agent.messages).toHaveLength(4);
754
- expect(agent.messages[0].role).toBe('user');
755
- expect(agent.messages[1].role).toBe('assistant');
756
- expect(agent.messages[1].content).toEqual(expect.arrayContaining([expect.objectContaining({ type: 'toolUseBlock' })]));
757
- expect(agent.messages[2].role).toBe('user');
758
- expect(agent.messages[2].content).toEqual(expect.arrayContaining([expect.objectContaining({ type: 'toolResultBlock' })]));
759
- expect(agent.messages[3].role).toBe('assistant');
760
- expect(agent.messages[3].content).toEqual(expect.arrayContaining([
761
- expect.objectContaining({ type: 'textBlock', text: 'Turn ended early by hook after tool execution' }),
762
- ]));
763
- });
764
- it('halts the loop with concurrent tool execution', async () => {
765
- const tool1 = createMockTool('tool1', () => {
766
- return new ToolResultBlock({ toolUseId: 'tool-1', status: 'success', content: [new TextBlock('Result 1')] });
767
- });
768
- const tool2 = createMockTool('tool2', () => {
769
- return new ToolResultBlock({ toolUseId: 'tool-2', status: 'success', content: [new TextBlock('Result 2')] });
770
- });
771
- const model = new MockMessageModel()
772
- .addTurn([
773
- { type: 'toolUseBlock', name: 'tool1', toolUseId: 'tool-1', input: {} },
774
- { type: 'toolUseBlock', name: 'tool2', toolUseId: 'tool-2', input: {} },
775
- ])
776
- .addTurn({ type: 'textBlock', text: 'Should not reach this' });
777
- const agent = new Agent({ model, tools: [tool1, tool2], toolExecutor: 'concurrent' });
778
- agent.addHook(AfterToolsEvent, (event) => {
779
- event.endTurn = true;
780
- });
781
- const result = await agent.invoke('Test');
782
- expect(result).toEqual(expect.objectContaining({
783
- type: 'agentResult',
784
- stopReason: 'endTurn',
785
- lastMessage: expect.objectContaining({ role: 'assistant' }),
786
- }));
787
- expect(model.callCount).toBe(1);
788
- });
789
- it('emits AfterToolsEvent with endTurn via stream()', async () => {
790
- const { tool, model } = makeSingleToolSetup();
791
- const agent = new Agent({ model, tools: [tool] });
792
- agent.addHook(AfterToolsEvent, (event) => {
793
- event.endTurn = true;
794
- });
795
- const items = await collectIterator(agent.stream('Test'));
796
- const afterToolsEvents = items.filter((e) => e instanceof AfterToolsEvent);
797
- expect(afterToolsEvents).toHaveLength(1);
798
- expect(afterToolsEvents[0].endTurn).toBe(true);
799
- const resultEvents = items.filter((e) => e instanceof AgentResultEvent);
800
- expect(resultEvents).toHaveLength(1);
801
- expect(resultEvents[0].result.stopReason).toBe('endTurn');
802
- });
803
- it('halts even when set on a cancelled-tools AfterToolsEvent', async () => {
804
- const { tool, model } = makeSingleToolSetup();
805
- const agent = new Agent({ model, tools: [tool] });
806
- agent.addHook(BeforeToolsEvent, (event) => {
807
- event.cancel = true;
808
- });
809
- agent.addHook(AfterToolsEvent, (event) => {
810
- event.endTurn = true;
811
- });
812
- const result = await agent.invoke('Test');
813
- expect(result).toEqual(expect.objectContaining({
814
- type: 'agentResult',
815
- stopReason: 'endTurn',
816
- lastMessage: expect.objectContaining({ role: 'assistant' }),
817
- }));
818
- expect(model.callCount).toBe(1);
819
- });
820
- });
821
- describe('cancel invocation via hooks', () => {
822
- it('cancels invocation with default message when cancel is true', async () => {
823
- const model = new MockMessageModel().addTurn({ type: 'textBlock', text: 'Hello' });
824
- const agent = new Agent({ model, plugins: [mockPlugin] });
825
- agent.addHook(BeforeInvocationEvent, (event) => {
826
- event.cancel = true;
827
- });
828
- const result = await agent.invoke('Test');
829
- expect(result.stopReason).toBe('endTurn');
830
- expect(result.lastMessage.content[0]).toEqual(new TextBlock('invocation denied by hook'));
831
- const beforeModelCallEvents = mockPlugin.invocations.filter((e) => e instanceof BeforeModelCallEvent);
832
- expect(beforeModelCallEvents).toHaveLength(0);
833
- });
834
- it('cancels invocation with custom message when cancel is a string', async () => {
835
- const model = new MockMessageModel().addTurn({ type: 'textBlock', text: 'Hello' });
836
- const agent = new Agent({ model, plugins: [mockPlugin] });
837
- agent.addHook(BeforeInvocationEvent, (event) => {
838
- event.cancel = 'Unauthorized user';
839
- });
840
- const result = await agent.invoke('Test');
841
- expect(result.stopReason).toBe('endTurn');
842
- expect(result.lastMessage.content[0]).toEqual(new TextBlock('Unauthorized user'));
843
- });
844
- it('does not append user message when invocation is cancelled', async () => {
845
- const model = new MockMessageModel().addTurn({ type: 'textBlock', text: 'Hello' });
846
- const agent = new Agent({ model });
847
- agent.addHook(BeforeInvocationEvent, (event) => {
848
- event.cancel = true;
849
- });
850
- await agent.invoke('Test');
851
- expect(agent.messages).toHaveLength(1);
852
- expect(agent.messages[0].role).toBe('assistant');
853
- });
854
- it('emits AfterInvocationEvent when invocation is cancelled', async () => {
855
- const model = new MockMessageModel().addTurn({ type: 'textBlock', text: 'Hello' });
856
- const agent = new Agent({ model, plugins: [mockPlugin] });
857
- agent.addHook(BeforeInvocationEvent, (event) => {
858
- event.cancel = true;
859
- });
860
- await agent.invoke('Test');
861
- const beforeInvocationEvents = mockPlugin.invocations.filter((e) => e instanceof BeforeInvocationEvent);
862
- const afterInvocationEvents = mockPlugin.invocations.filter((e) => e instanceof AfterInvocationEvent);
863
- expect(beforeInvocationEvents).toHaveLength(1);
864
- expect(afterInvocationEvents).toHaveLength(1);
865
- });
866
- });
867
- describe('cancel model call via hooks', () => {
868
- it('cancels model call with default message when cancel is true', async () => {
869
- const model = new MockMessageModel().addTurn({ type: 'textBlock', text: 'Hello' });
870
- const agent = new Agent({ model, plugins: [mockPlugin] });
871
- agent.addHook(BeforeModelCallEvent, (event) => {
872
- event.cancel = true;
873
- });
874
- const result = await agent.invoke('Test');
875
- expect(result.stopReason).toBe('endTurn');
876
- expect(result.lastMessage.content[0]).toEqual(new TextBlock('model call denied by hook'));
877
- });
878
- it('cancels model call with custom message when cancel is a string', async () => {
879
- const model = new MockMessageModel().addTurn({ type: 'textBlock', text: 'Hello' });
880
- const agent = new Agent({ model, plugins: [mockPlugin] });
881
- agent.addHook(BeforeModelCallEvent, (event) => {
882
- event.cancel = 'Rate limited';
883
- });
884
- const result = await agent.invoke('Test');
885
- expect(result.stopReason).toBe('endTurn');
886
- expect(result.lastMessage.content[0]).toEqual(new TextBlock('Rate limited'));
887
- });
888
- it('emits AfterModelCallEvent when model call is cancelled', async () => {
889
- const model = new MockMessageModel().addTurn({ type: 'textBlock', text: 'Hello' });
890
- const agent = new Agent({ model, plugins: [mockPlugin] });
891
- agent.addHook(BeforeModelCallEvent, (event) => {
892
- event.cancel = true;
893
- });
894
- await agent.invoke('Test');
895
- const beforeModelCallEvents = mockPlugin.invocations.filter((e) => e instanceof BeforeModelCallEvent);
896
- const afterModelCallEvents = mockPlugin.invocations.filter((e) => e instanceof AfterModelCallEvent);
897
- expect(beforeModelCallEvents).toHaveLength(1);
898
- expect(afterModelCallEvents).toHaveLength(1);
899
- });
900
- it('does not emit ModelMessageEvent when model call is cancelled', async () => {
901
- const model = new MockMessageModel().addTurn({ type: 'textBlock', text: 'Hello' });
902
- const agent = new Agent({ model, plugins: [mockPlugin] });
903
- agent.addHook(BeforeModelCallEvent, (event) => {
904
- event.cancel = true;
905
- });
906
- await agent.invoke('Test');
907
- const modelMessageEvents = mockPlugin.invocations.filter((e) => e instanceof ModelMessageEvent);
908
- expect(modelMessageEvents).toHaveLength(0);
909
- });
910
- it('allows retry after cancel on model call', async () => {
911
- let beforeCount = 0;
912
- const model = new MockMessageModel().addTurn({ type: 'textBlock', text: 'Hello' });
913
- const agent = new Agent({ model, plugins: [mockPlugin] });
914
- agent.addHook(BeforeModelCallEvent, (event) => {
915
- beforeCount++;
916
- if (beforeCount === 1) {
917
- event.cancel = 'Not yet';
918
- }
919
- });
920
- agent.addHook(AfterModelCallEvent, (event) => {
921
- if (beforeCount === 1) {
922
- event.retry = true;
923
- }
924
- });
925
- const result = await agent.invoke('Test');
926
- expect(result.stopReason).toBe('endTurn');
927
- expect(beforeCount).toBe(2);
928
- expect(result.lastMessage.content[0]).toEqual(new TextBlock('Hello'));
929
- });
930
- });
931
- describe('BeforeToolCallEvent selectedTool', () => {
932
- it('invokes the replacement tool instead of the registry tool', async () => {
933
- let originalExecuted = false;
934
- let replacementExecuted = false;
935
- const originalTool = createMockTool('originalTool', () => {
936
- originalExecuted = true;
937
- return new ToolResultBlock({ toolUseId: 'tool-1', status: 'success', content: [new TextBlock('original')] });
938
- });
939
- const replacementTool = createMockTool('replacementTool', () => {
940
- replacementExecuted = true;
941
- return new ToolResultBlock({ toolUseId: 'tool-1', status: 'success', content: [new TextBlock('replacement')] });
942
- });
943
- const model = new MockMessageModel()
944
- .addTurn({ type: 'toolUseBlock', name: 'originalTool', toolUseId: 'tool-1', input: {} })
945
- .addTurn({ type: 'textBlock', text: 'Done' });
946
- const agent = new Agent({ model, tools: [originalTool], plugins: [mockPlugin] });
947
- agent.addHook(BeforeToolCallEvent, (event) => {
948
- event.selectedTool = replacementTool;
949
- });
950
- await agent.invoke('Test');
951
- expect(originalExecuted).toBe(false);
952
- expect(replacementExecuted).toBe(true);
953
- const afterToolCallEvents = mockPlugin.invocations.filter((e) => e instanceof AfterToolCallEvent);
954
- expect(afterToolCallEvents).toHaveLength(1);
955
- expect(afterToolCallEvents[0].result.content).toEqual([new TextBlock('replacement')]);
956
- });
957
- it('cancel wins over selectedTool', async () => {
958
- let replacementExecuted = false;
959
- const replacementTool = createMockTool('replacementTool', () => {
960
- replacementExecuted = true;
961
- return new ToolResultBlock({ toolUseId: 'tool-1', status: 'success', content: [new TextBlock('replacement')] });
962
- });
963
- const registryTool = createMockTool('registryTool', () => {
964
- return new ToolResultBlock({ toolUseId: 'tool-1', status: 'success', content: [new TextBlock('registry')] });
965
- });
966
- const model = new MockMessageModel()
967
- .addTurn({ type: 'toolUseBlock', name: 'registryTool', toolUseId: 'tool-1', input: {} })
968
- .addTurn({ type: 'textBlock', text: 'Done' });
969
- const agent = new Agent({ model, tools: [registryTool], plugins: [mockPlugin] });
970
- agent.addHook(BeforeToolCallEvent, (event) => {
971
- event.selectedTool = replacementTool;
972
- event.cancel = 'blocked';
973
- });
974
- await agent.invoke('Test');
975
- expect(replacementExecuted).toBe(false);
976
- // AfterToolCallEvent.tool should report the selectedTool even on the cancel path,
977
- // so observability hooks see a consistent `tool` value regardless of branch.
978
- const afterToolCallEvents = mockPlugin.invocations.filter((e) => e instanceof AfterToolCallEvent);
979
- expect(afterToolCallEvents).toHaveLength(1);
980
- expect(afterToolCallEvents[0].tool).toBe(replacementTool);
981
- });
982
- it('works with concurrent tool executor', async () => {
983
- let originalExecuted = false;
984
- let replacementExecuted = false;
985
- const originalTool = createMockTool('originalTool', () => {
986
- originalExecuted = true;
987
- return new ToolResultBlock({ toolUseId: 'tool-1', status: 'success', content: [new TextBlock('original')] });
988
- });
989
- const replacementTool = createMockTool('replacementTool', () => {
990
- replacementExecuted = true;
991
- return new ToolResultBlock({ toolUseId: 'tool-1', status: 'success', content: [new TextBlock('replacement')] });
992
- });
993
- const otherTool = createMockTool('otherTool', () => {
994
- return new ToolResultBlock({ toolUseId: 'tool-2', status: 'success', content: [new TextBlock('other')] });
995
- });
996
- const model = new MockMessageModel()
997
- .addTurn([
998
- { type: 'toolUseBlock', name: 'originalTool', toolUseId: 'tool-1', input: {} },
999
- { type: 'toolUseBlock', name: 'otherTool', toolUseId: 'tool-2', input: {} },
1000
- ])
1001
- .addTurn({ type: 'textBlock', text: 'Done' });
1002
- const agent = new Agent({
1003
- model,
1004
- tools: [originalTool, otherTool],
1005
- toolExecutor: 'concurrent',
1006
- });
1007
- agent.addHook(BeforeToolCallEvent, (event) => {
1008
- if (event.toolUse.name === 'originalTool') {
1009
- event.selectedTool = replacementTool;
1010
- }
1011
- });
1012
- await agent.invoke('Test');
1013
- expect(originalExecuted).toBe(false);
1014
- expect(replacementExecuted).toBe(true);
1015
- });
1016
- });
1017
- describe('BeforeToolCallEvent toolUse mutation', () => {
1018
- it('passes mutated input to the tool', async () => {
1019
- const capturedInputs = [];
1020
- const tool = createMockTool('tool', () => {
1021
- return new ToolResultBlock({ toolUseId: 'tool-1', status: 'success', content: [new TextBlock('ok')] });
1022
- });
1023
- // Wrap to capture input via the context the tool receives.
1024
- const capturingTool = {
1025
- ...tool,
1026
- async *stream(context) {
1027
- capturedInputs.push(context.toolUse.input);
1028
- return yield* tool.stream(context);
1029
- },
1030
- };
1031
- const model = new MockMessageModel()
1032
- .addTurn({ type: 'toolUseBlock', name: 'tool', toolUseId: 'tool-1', input: { a: 1 } })
1033
- .addTurn({ type: 'textBlock', text: 'Done' });
1034
- const agent = new Agent({ model, tools: [capturingTool] });
1035
- agent.addHook(BeforeToolCallEvent, (event) => {
1036
- event.toolUse.input = { a: 2, injected: true };
1037
- });
1038
- await agent.invoke('Test');
1039
- expect(capturedInputs).toEqual([{ a: 2, injected: true }]);
1040
- });
1041
- it('re-resolves the tool when hook renames toolUse.name', async () => {
1042
- let origExecuted = false;
1043
- let renamedExecuted = false;
1044
- const origTool = createMockTool('orig', () => {
1045
- origExecuted = true;
1046
- return new ToolResultBlock({ toolUseId: 'tool-1', status: 'success', content: [new TextBlock('orig')] });
1047
- });
1048
- const renamedTool = createMockTool('renamed', () => {
1049
- renamedExecuted = true;
1050
- return new ToolResultBlock({ toolUseId: 'tool-1', status: 'success', content: [new TextBlock('renamed')] });
1051
- });
1052
- const model = new MockMessageModel()
1053
- .addTurn({ type: 'toolUseBlock', name: 'orig', toolUseId: 'tool-1', input: {} })
1054
- .addTurn({ type: 'textBlock', text: 'Done' });
1055
- const agent = new Agent({ model, tools: [origTool, renamedTool] });
1056
- agent.addHook(BeforeToolCallEvent, (event) => {
1057
- event.toolUse.name = 'renamed';
1058
- });
1059
- await agent.invoke('Test');
1060
- expect(origExecuted).toBe(false);
1061
- expect(renamedExecuted).toBe(true);
1062
- });
1063
- it('works with concurrent tool executor', async () => {
1064
- const capturedInputs = {};
1065
- const baseA = createMockTool('toolA', () => {
1066
- return new ToolResultBlock({ toolUseId: 'a', status: 'success', content: [new TextBlock('a done')] });
1067
- });
1068
- const baseB = createMockTool('toolB', () => {
1069
- return new ToolResultBlock({ toolUseId: 'b', status: 'success', content: [new TextBlock('b done')] });
1070
- });
1071
- const toolA = {
1072
- ...baseA,
1073
- async *stream(context) {
1074
- capturedInputs[context.toolUse.name] = context.toolUse.input;
1075
- return yield* baseA.stream(context);
1076
- },
1077
- };
1078
- const toolB = {
1079
- ...baseB,
1080
- async *stream(context) {
1081
- capturedInputs[context.toolUse.name] = context.toolUse.input;
1082
- return yield* baseB.stream(context);
1083
- },
1084
- };
1085
- const model = new MockMessageModel()
1086
- .addTurn([
1087
- { type: 'toolUseBlock', name: 'toolA', toolUseId: 'a', input: { original: 'a' } },
1088
- { type: 'toolUseBlock', name: 'toolB', toolUseId: 'b', input: { original: 'b' } },
1089
- ])
1090
- .addTurn({ type: 'textBlock', text: 'Done' });
1091
- const agent = new Agent({ model, tools: [toolA, toolB], toolExecutor: 'concurrent' });
1092
- agent.addHook(BeforeToolCallEvent, (event) => {
1093
- event.toolUse.input = { mutated: event.toolUse.name };
1094
- });
1095
- await agent.invoke('Test');
1096
- expect(capturedInputs).toEqual({
1097
- toolA: { mutated: 'toolA' },
1098
- toolB: { mutated: 'toolB' },
1099
- });
1100
- });
1101
- });
1102
- describe('AfterToolCallEvent result mutation', () => {
1103
- it('propagates mutated result into the conversation message', async () => {
1104
- const tool = createMockTool('tool', () => {
1105
- return new ToolResultBlock({
1106
- toolUseId: 'tool-1',
1107
- status: 'success',
1108
- content: [new TextBlock('SECRET_VALUE')],
1109
- });
1110
- });
1111
- const model = new MockMessageModel()
1112
- .addTurn({ type: 'toolUseBlock', name: 'tool', toolUseId: 'tool-1', input: {} })
1113
- .addTurn({ type: 'textBlock', text: 'Done' });
1114
- const agent = new Agent({ model, tools: [tool] });
1115
- agent.addHook(AfterToolCallEvent, (event) => {
1116
- event.result = new ToolResultBlock({
1117
- toolUseId: 'tool-1',
1118
- status: 'success',
1119
- content: [new TextBlock('[REDACTED]')],
1120
- });
1121
- });
1122
- await agent.invoke('Test');
1123
- const toolResultMessage = agent.messages.find((m) => m.content.some((b) => b.type === 'toolResultBlock' && b.toolUseId === 'tool-1'));
1124
- expect(toolResultMessage).toBeDefined();
1125
- const block = toolResultMessage.content.find((b) => b.type === 'toolResultBlock' && b.toolUseId === 'tool-1');
1126
- expect(block.content).toEqual([new TextBlock('[REDACTED]')]);
1127
- });
1128
- it('propagates mutated result into AfterToolsEvent', async () => {
1129
- const tool = createMockTool('tool', () => {
1130
- return new ToolResultBlock({
1131
- toolUseId: 'tool-1',
1132
- status: 'success',
1133
- content: [new TextBlock('SECRET_VALUE')],
1134
- });
1135
- });
1136
- const model = new MockMessageModel()
1137
- .addTurn({ type: 'toolUseBlock', name: 'tool', toolUseId: 'tool-1', input: {} })
1138
- .addTurn({ type: 'textBlock', text: 'Done' });
1139
- const agent = new Agent({ model, tools: [tool], plugins: [mockPlugin] });
1140
- agent.addHook(AfterToolCallEvent, (event) => {
1141
- event.result = new ToolResultBlock({
1142
- toolUseId: 'tool-1',
1143
- status: 'success',
1144
- content: [new TextBlock('[REDACTED]')],
1145
- });
1146
- });
1147
- await agent.invoke('Test');
1148
- const afterToolsEvents = mockPlugin.invocations.filter((e) => e instanceof AfterToolsEvent);
1149
- expect(afterToolsEvents).toHaveLength(1);
1150
- const block = afterToolsEvents[0].message.content.find((b) => b.type === 'toolResultBlock' && b.toolUseId === 'tool-1');
1151
- expect(block.content).toEqual([new TextBlock('[REDACTED]')]);
1152
- });
1153
- });
1154
- describe('AfterInvocationEvent resume', () => {
1155
- it('re-invokes the agent with the resume args', async () => {
1156
- const model = new MockMessageModel()
1157
- .addTurn({ type: 'textBlock', text: 'first' })
1158
- .addTurn({ type: 'textBlock', text: 'second' });
1159
- let invocationCount = 0;
1160
- const agent = new Agent({ model });
1161
- agent.addHook(AfterInvocationEvent, (event) => {
1162
- invocationCount++;
1163
- if (invocationCount === 1) {
1164
- event.resume = 'follow-up';
1165
- }
1166
- });
1167
- const result = await agent.invoke('initial');
1168
- expect(invocationCount).toBe(2);
1169
- expect(result).toEqual(expectAgentResult({
1170
- stopReason: 'endTurn',
1171
- messageText: 'second',
1172
- // Meter cycleCount is cumulative across the resume chain (1 cycle per invocation x 2).
1173
- cycleCount: 2,
1174
- }));
1175
- });
1176
- it('chains multiple resumes', async () => {
1177
- const model = new MockMessageModel()
1178
- .addTurn({ type: 'textBlock', text: 'a' })
1179
- .addTurn({ type: 'textBlock', text: 'b' })
1180
- .addTurn({ type: 'textBlock', text: 'c' });
1181
- let invocationCount = 0;
1182
- const agent = new Agent({ model });
1183
- agent.addHook(AfterInvocationEvent, (event) => {
1184
- invocationCount++;
1185
- if (invocationCount === 1)
1186
- event.resume = 'second';
1187
- else if (invocationCount === 2)
1188
- event.resume = 'third';
1189
- });
1190
- const result = await agent.invoke('first');
1191
- expect(invocationCount).toBe(3);
1192
- expect(result.lastMessage.content[0]).toEqual({ type: 'textBlock', text: 'c' });
1193
- });
1194
- it('does not resume when resume is left undefined', async () => {
1195
- const model = new MockMessageModel().addTurn({ type: 'textBlock', text: 'only' });
1196
- let invocationCount = 0;
1197
- const agent = new Agent({ model });
1198
- agent.addHook(AfterInvocationEvent, () => {
1199
- invocationCount++;
1200
- });
1201
- await agent.invoke('hi');
1202
- expect(invocationCount).toBe(1);
1203
- });
1204
- it('does not resume when the invocation errors', async () => {
1205
- const model = new MockMessageModel().addTurn(new Error('boom'));
1206
- let invocationCount = 0;
1207
- const agent = new Agent({ model });
1208
- agent.addHook(AfterInvocationEvent, (event) => {
1209
- invocationCount++;
1210
- event.resume = 'should-not-run';
1211
- });
1212
- await expect(agent.invoke('hi')).rejects.toThrow('boom');
1213
- expect(invocationCount).toBe(1);
1214
- });
1215
- it('first-registered hook wins when multiple hooks set resume', async () => {
1216
- // AfterInvocationEvent reverses callback order (_shouldReverseCallbacks=true),
1217
- // so the first-registered hook fires last and its resume value wins.
1218
- const model = new MockMessageModel()
1219
- .addTurn({ type: 'textBlock', text: 'first' })
1220
- .addTurn({ type: 'textBlock', text: 'second' });
1221
- let invocationCount = 0;
1222
- const agent = new Agent({ model });
1223
- agent.addHook(BeforeInvocationEvent, () => {
1224
- invocationCount++;
1225
- });
1226
- agent.addHook(AfterInvocationEvent, (event) => {
1227
- if (invocationCount === 1)
1228
- event.resume = 'first-registered wins';
1229
- });
1230
- agent.addHook(AfterInvocationEvent, (event) => {
1231
- if (invocationCount === 1)
1232
- event.resume = 'second-registered loses';
1233
- });
1234
- await agent.invoke('initial');
1235
- const userTexts = agent.messages
1236
- .filter((m) => m.role === 'user')
1237
- .flatMap((m) => m.content.filter((b) => b.type === 'textBlock').map((b) => b.text));
1238
- expect(userTexts).toEqual(['initial', 'first-registered wins']);
1239
- });
1240
- it('ignores resume set during an erroring invocation', async () => {
1241
- // Resume should not fire when the invocation ends with an error, even if
1242
- // AfterInvocationEvent (which fires in _stream's finally) still runs.
1243
- const model = new MockMessageModel().addTurn(new Error('boom'));
1244
- let resumeFired = false;
1245
- const agent = new Agent({ model });
1246
- agent.addHook(AfterInvocationEvent, (event) => {
1247
- event.resume = 'should not run';
1248
- });
1249
- agent.addHook(BeforeInvocationEvent, () => {
1250
- // Track whether BeforeInvocationEvent fires a second time (would indicate resume ran).
1251
- if (resumeFired)
1252
- throw new Error('unexpected second invocation');
1253
- resumeFired = true;
1254
- });
1255
- await expect(agent.invoke('hi')).rejects.toThrow('boom');
1256
- });
1257
- it('emits only one AgentResultEvent for a resumed chain', async () => {
1258
- const model = new MockMessageModel()
1259
- .addTurn({ type: 'textBlock', text: 'first' })
1260
- .addTurn({ type: 'textBlock', text: 'second' });
1261
- let invocationCount = 0;
1262
- const agent = new Agent({ model });
1263
- agent.addHook(AfterInvocationEvent, (event) => {
1264
- invocationCount++;
1265
- if (invocationCount === 1) {
1266
- event.resume = 'follow-up';
1267
- }
1268
- });
1269
- const items = await collectIterator(agent.stream('initial'));
1270
- const agentResults = items.filter((e) => e instanceof AgentResultEvent);
1271
- expect(agentResults).toHaveLength(1);
1272
- const afterInvocations = items.filter((e) => e instanceof AfterInvocationEvent);
1273
- expect(afterInvocations).toHaveLength(2);
1274
- });
1275
- });
1276
- describe('queue-based lifecycle plugin (WASM bridge pattern)', () => {
1277
- function createLifecycleBridgePlugin(queue) {
1278
- return {
1279
- name: 'strands:lifecycle-bridge',
1280
- initAgent(agent) {
1281
- agent.addHook(InitializedEvent, () => {
1282
- queue.push('initialized');
1283
- });
1284
- agent.addHook(BeforeInvocationEvent, () => {
1285
- queue.push('before-invocation');
1286
- });
1287
- agent.addHook(AfterInvocationEvent, () => {
1288
- queue.push('after-invocation');
1289
- });
1290
- agent.addHook(BeforeModelCallEvent, () => {
1291
- queue.push('before-model-call');
1292
- });
1293
- agent.addHook(AfterModelCallEvent, () => {
1294
- queue.push('after-model-call');
1295
- });
1296
- agent.addHook(MessageAddedEvent, () => {
1297
- queue.push('message-added');
1298
- });
1299
- agent.addHook(BeforeToolCallEvent, () => {
1300
- queue.push('before-tool-call');
1301
- });
1302
- agent.addHook(AfterToolCallEvent, () => {
1303
- queue.push('after-tool-call');
1304
- });
1305
- },
1306
- };
1307
- }
1308
- it('receives lifecycle events when registered via plugins config', async () => {
1309
- const queue = [];
1310
- const model = new MockMessageModel().addTurn({ type: 'textBlock', text: 'Hello' });
1311
- const agent = new Agent({ model, plugins: [createLifecycleBridgePlugin(queue)] });
1312
- await agent.invoke('Hi');
1313
- expect(queue).toStrictEqual([
1314
- 'initialized',
1315
- 'before-invocation',
1316
- 'message-added',
1317
- 'before-model-call',
1318
- 'after-model-call',
1319
- 'message-added',
1320
- 'after-invocation',
1321
- ]);
1322
- });
1323
- it('receives no events when passed via non-existent hooks config field', async () => {
1324
- const queue = [];
1325
- const model = new MockMessageModel().addTurn({ type: 'textBlock', text: 'Hello' });
1326
- const agent = new Agent({ model, hooks: [createLifecycleBridgePlugin(queue)] });
1327
- await agent.invoke('Hi');
1328
- expect(queue).toHaveLength(0);
1329
- });
1330
- });
1331
- });
1332
- //# sourceMappingURL=agent.hook.test.js.map