@strands-agents/sdk 1.0.0-rc.5 → 1.0.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 (250) hide show
  1. package/LICENSE +175 -0
  2. package/README.md +340 -0
  3. package/dist/src/__fixtures__/agent-helpers.d.ts +6 -0
  4. package/dist/src/__fixtures__/agent-helpers.d.ts.map +1 -1
  5. package/dist/src/__fixtures__/agent-helpers.js +3 -1
  6. package/dist/src/__fixtures__/agent-helpers.js.map +1 -1
  7. package/dist/src/__fixtures__/mock-plugin.d.ts.map +1 -1
  8. package/dist/src/__fixtures__/mock-plugin.js +3 -1
  9. package/dist/src/__fixtures__/mock-plugin.js.map +1 -1
  10. package/dist/src/__fixtures__/tool-helpers.d.ts +3 -1
  11. package/dist/src/__fixtures__/tool-helpers.d.ts.map +1 -1
  12. package/dist/src/__fixtures__/tool-helpers.js +3 -1
  13. package/dist/src/__fixtures__/tool-helpers.js.map +1 -1
  14. package/dist/src/__tests__/mcp.test.js +222 -2
  15. package/dist/src/__tests__/mcp.test.js.map +1 -1
  16. package/dist/src/a2a/__tests__/events.test.js +2 -0
  17. package/dist/src/a2a/__tests__/events.test.js.map +1 -1
  18. package/dist/src/a2a/__tests__/executor.test.js +16 -5
  19. package/dist/src/a2a/__tests__/executor.test.js.map +1 -1
  20. package/dist/src/a2a/a2a-agent.d.ts +8 -3
  21. package/dist/src/a2a/a2a-agent.d.ts.map +1 -1
  22. package/dist/src/a2a/a2a-agent.js +12 -6
  23. package/dist/src/a2a/a2a-agent.js.map +1 -1
  24. package/dist/src/a2a/executor.d.ts +13 -0
  25. package/dist/src/a2a/executor.d.ts.map +1 -1
  26. package/dist/src/a2a/executor.js +19 -1
  27. package/dist/src/a2a/executor.js.map +1 -1
  28. package/dist/src/agent/__tests__/agent-as-tool.invocation-state.test.d.ts +2 -0
  29. package/dist/src/agent/__tests__/agent-as-tool.invocation-state.test.d.ts.map +1 -0
  30. package/dist/src/agent/__tests__/agent-as-tool.invocation-state.test.js +23 -0
  31. package/dist/src/agent/__tests__/agent-as-tool.invocation-state.test.js.map +1 -0
  32. package/dist/src/agent/__tests__/agent.cancel.test.js +1 -1
  33. package/dist/src/agent/__tests__/agent.cancel.test.js.map +1 -1
  34. package/dist/src/agent/__tests__/agent.concurrent.test.d.ts +2 -0
  35. package/dist/src/agent/__tests__/agent.concurrent.test.d.ts.map +1 -0
  36. package/dist/src/agent/__tests__/agent.concurrent.test.js +488 -0
  37. package/dist/src/agent/__tests__/agent.concurrent.test.js.map +1 -0
  38. package/dist/src/agent/__tests__/agent.hook.test.js +174 -12
  39. package/dist/src/agent/__tests__/agent.hook.test.js.map +1 -1
  40. package/dist/src/agent/__tests__/agent.invocation-state.test.d.ts +2 -0
  41. package/dist/src/agent/__tests__/agent.invocation-state.test.d.ts.map +1 -0
  42. package/dist/src/agent/__tests__/agent.invocation-state.test.js +219 -0
  43. package/dist/src/agent/__tests__/agent.invocation-state.test.js.map +1 -0
  44. package/dist/src/agent/__tests__/agent.stateful-model.test.d.ts +2 -0
  45. package/dist/src/agent/__tests__/agent.stateful-model.test.d.ts.map +1 -0
  46. package/dist/src/agent/__tests__/agent.stateful-model.test.js +169 -0
  47. package/dist/src/agent/__tests__/agent.stateful-model.test.js.map +1 -0
  48. package/dist/src/agent/__tests__/agent.test.js +99 -2
  49. package/dist/src/agent/__tests__/agent.test.js.map +1 -1
  50. package/dist/src/agent/__tests__/agent.tracer.test.node.js +39 -0
  51. package/dist/src/agent/__tests__/agent.tracer.test.node.js.map +1 -1
  52. package/dist/src/agent/__tests__/snapshot.test.js +5 -4
  53. package/dist/src/agent/__tests__/snapshot.test.js.map +1 -1
  54. package/dist/src/agent/agent-as-tool.d.ts.map +1 -1
  55. package/dist/src/agent/agent-as-tool.js +4 -2
  56. package/dist/src/agent/agent-as-tool.js.map +1 -1
  57. package/dist/src/agent/agent.d.ts +75 -1
  58. package/dist/src/agent/agent.d.ts.map +1 -1
  59. package/dist/src/agent/agent.js +323 -83
  60. package/dist/src/agent/agent.js.map +1 -1
  61. package/dist/src/agent/snapshot.d.ts +2 -2
  62. package/dist/src/agent/snapshot.d.ts.map +1 -1
  63. package/dist/src/agent/snapshot.js +8 -2
  64. package/dist/src/agent/snapshot.js.map +1 -1
  65. package/dist/src/conversation-manager/__tests__/conversation-manager.test.js +4 -4
  66. package/dist/src/conversation-manager/__tests__/conversation-manager.test.js.map +1 -1
  67. package/dist/src/conversation-manager/__tests__/null-conversation-manager.test.js +2 -2
  68. package/dist/src/conversation-manager/__tests__/null-conversation-manager.test.js.map +1 -1
  69. package/dist/src/conversation-manager/__tests__/sliding-window-conversation-manager.test.js +8 -3
  70. package/dist/src/conversation-manager/__tests__/sliding-window-conversation-manager.test.js.map +1 -1
  71. package/dist/src/conversation-manager/__tests__/summarizing-conversation-manager.test.js +1 -0
  72. package/dist/src/conversation-manager/__tests__/summarizing-conversation-manager.test.js.map +1 -1
  73. package/dist/src/errors.d.ts +11 -0
  74. package/dist/src/errors.d.ts.map +1 -1
  75. package/dist/src/errors.js +12 -0
  76. package/dist/src/errors.js.map +1 -1
  77. package/dist/src/hooks/__tests__/events.test.js +177 -70
  78. package/dist/src/hooks/__tests__/events.test.js.map +1 -1
  79. package/dist/src/hooks/__tests__/registry.test.js +16 -16
  80. package/dist/src/hooks/__tests__/registry.test.js.map +1 -1
  81. package/dist/src/hooks/events.d.ts +95 -25
  82. package/dist/src/hooks/events.d.ts.map +1 -1
  83. package/dist/src/hooks/events.js +98 -23
  84. package/dist/src/hooks/events.js.map +1 -1
  85. package/dist/src/index.d.ts +5 -4
  86. package/dist/src/index.d.ts.map +1 -1
  87. package/dist/src/index.js.map +1 -1
  88. package/dist/src/logging/__tests__/warn-once.test.d.ts +2 -0
  89. package/dist/src/logging/__tests__/warn-once.test.d.ts.map +1 -0
  90. package/dist/src/logging/__tests__/warn-once.test.js +30 -0
  91. package/dist/src/logging/__tests__/warn-once.test.js.map +1 -0
  92. package/dist/src/logging/warn-once.d.ts +13 -0
  93. package/dist/src/logging/warn-once.d.ts.map +1 -0
  94. package/dist/src/logging/warn-once.js +18 -0
  95. package/dist/src/logging/warn-once.js.map +1 -0
  96. package/dist/src/mcp.d.ts +20 -1
  97. package/dist/src/mcp.d.ts.map +1 -1
  98. package/dist/src/mcp.js +10 -1
  99. package/dist/src/mcp.js.map +1 -1
  100. package/dist/src/mime.d.ts +2 -1
  101. package/dist/src/mime.d.ts.map +1 -1
  102. package/dist/src/mime.js +1 -0
  103. package/dist/src/mime.js.map +1 -1
  104. package/dist/src/models/__tests__/anthropic.test.js +92 -3
  105. package/dist/src/models/__tests__/anthropic.test.js.map +1 -1
  106. package/dist/src/models/__tests__/bedrock.test.js +113 -2
  107. package/dist/src/models/__tests__/bedrock.test.js.map +1 -1
  108. package/dist/src/models/__tests__/google.test.js +77 -0
  109. package/dist/src/models/__tests__/google.test.js.map +1 -1
  110. package/dist/src/models/__tests__/model.test.js +149 -1
  111. package/dist/src/models/__tests__/model.test.js.map +1 -1
  112. package/dist/src/models/anthropic.d.ts +12 -1
  113. package/dist/src/models/anthropic.d.ts.map +1 -1
  114. package/dist/src/models/anthropic.js +38 -6
  115. package/dist/src/models/anthropic.js.map +1 -1
  116. package/dist/src/models/bedrock.d.ts +12 -1
  117. package/dist/src/models/bedrock.d.ts.map +1 -1
  118. package/dist/src/models/bedrock.js +45 -11
  119. package/dist/src/models/bedrock.js.map +1 -1
  120. package/dist/src/models/defaults.d.ts +37 -0
  121. package/dist/src/models/defaults.d.ts.map +1 -0
  122. package/dist/src/models/defaults.js +41 -0
  123. package/dist/src/models/defaults.js.map +1 -0
  124. package/dist/src/models/google/model.d.ts +14 -1
  125. package/dist/src/models/google/model.d.ts.map +1 -1
  126. package/dist/src/models/google/model.js +50 -6
  127. package/dist/src/models/google/model.js.map +1 -1
  128. package/dist/src/models/model.d.ts +50 -0
  129. package/dist/src/models/model.d.ts.map +1 -1
  130. package/dist/src/models/model.js +120 -0
  131. package/dist/src/models/model.js.map +1 -1
  132. package/dist/src/models/openai/__tests__/chat.test.d.ts +2 -0
  133. package/dist/src/models/openai/__tests__/chat.test.d.ts.map +1 -0
  134. package/dist/src/models/{__tests__/openai.test.js → openai/__tests__/chat.test.js} +72 -7
  135. package/dist/src/models/openai/__tests__/chat.test.js.map +1 -0
  136. package/dist/src/models/openai/__tests__/responses.test.d.ts +2 -0
  137. package/dist/src/models/openai/__tests__/responses.test.d.ts.map +1 -0
  138. package/dist/src/models/openai/__tests__/responses.test.js +668 -0
  139. package/dist/src/models/openai/__tests__/responses.test.js.map +1 -0
  140. package/dist/src/models/openai/chat-adapter.d.ts +33 -0
  141. package/dist/src/models/openai/chat-adapter.d.ts.map +1 -0
  142. package/dist/src/models/openai/chat-adapter.js +383 -0
  143. package/dist/src/models/openai/chat-adapter.js.map +1 -0
  144. package/dist/src/models/openai/errors.d.ts +16 -0
  145. package/dist/src/models/openai/errors.d.ts.map +1 -0
  146. package/dist/src/models/openai/errors.js +40 -0
  147. package/dist/src/models/openai/errors.js.map +1 -0
  148. package/dist/src/models/openai/formatting.d.ts +18 -0
  149. package/dist/src/models/openai/formatting.d.ts.map +1 -0
  150. package/dist/src/models/openai/formatting.js +38 -0
  151. package/dist/src/models/openai/formatting.js.map +1 -0
  152. package/dist/src/models/openai/index.d.ts +19 -0
  153. package/dist/src/models/openai/index.d.ts.map +1 -0
  154. package/dist/src/models/openai/index.js +18 -0
  155. package/dist/src/models/openai/index.js.map +1 -0
  156. package/dist/src/models/openai/model.d.ts +77 -0
  157. package/dist/src/models/openai/model.d.ts.map +1 -0
  158. package/dist/src/models/openai/model.js +211 -0
  159. package/dist/src/models/openai/model.js.map +1 -0
  160. package/dist/src/models/openai/responses-adapter.d.ts +78 -0
  161. package/dist/src/models/openai/responses-adapter.d.ts.map +1 -0
  162. package/dist/src/models/openai/responses-adapter.js +467 -0
  163. package/dist/src/models/openai/responses-adapter.js.map +1 -0
  164. package/dist/src/models/openai/types.d.ts +131 -0
  165. package/dist/src/models/openai/types.d.ts.map +1 -0
  166. package/dist/src/models/openai/types.js +5 -0
  167. package/dist/src/models/openai/types.js.map +1 -0
  168. package/dist/src/multiagent/__tests__/events.test.js +122 -28
  169. package/dist/src/multiagent/__tests__/events.test.js.map +1 -1
  170. package/dist/src/multiagent/__tests__/graph.invocation-state.test.d.ts +2 -0
  171. package/dist/src/multiagent/__tests__/graph.invocation-state.test.d.ts.map +1 -0
  172. package/dist/src/multiagent/__tests__/graph.invocation-state.test.js +95 -0
  173. package/dist/src/multiagent/__tests__/graph.invocation-state.test.js.map +1 -0
  174. package/dist/src/multiagent/__tests__/nodes.test.js +5 -2
  175. package/dist/src/multiagent/__tests__/nodes.test.js.map +1 -1
  176. package/dist/src/multiagent/__tests__/swarm.invocation-state.test.d.ts +2 -0
  177. package/dist/src/multiagent/__tests__/swarm.invocation-state.test.d.ts.map +1 -0
  178. package/dist/src/multiagent/__tests__/swarm.invocation-state.test.js +56 -0
  179. package/dist/src/multiagent/__tests__/swarm.invocation-state.test.js.map +1 -0
  180. package/dist/src/multiagent/events.d.ts +19 -1
  181. package/dist/src/multiagent/events.d.ts.map +1 -1
  182. package/dist/src/multiagent/events.js +18 -0
  183. package/dist/src/multiagent/events.js.map +1 -1
  184. package/dist/src/multiagent/graph.d.ts +5 -3
  185. package/dist/src/multiagent/graph.d.ts.map +1 -1
  186. package/dist/src/multiagent/graph.js +22 -15
  187. package/dist/src/multiagent/graph.js.map +1 -1
  188. package/dist/src/multiagent/index.d.ts +1 -1
  189. package/dist/src/multiagent/index.d.ts.map +1 -1
  190. package/dist/src/multiagent/multiagent.d.ts +16 -3
  191. package/dist/src/multiagent/multiagent.d.ts.map +1 -1
  192. package/dist/src/multiagent/nodes.d.ts +10 -3
  193. package/dist/src/multiagent/nodes.d.ts.map +1 -1
  194. package/dist/src/multiagent/nodes.js +28 -6
  195. package/dist/src/multiagent/nodes.js.map +1 -1
  196. package/dist/src/multiagent/swarm.d.ts +5 -3
  197. package/dist/src/multiagent/swarm.d.ts.map +1 -1
  198. package/dist/src/multiagent/swarm.js +22 -16
  199. package/dist/src/multiagent/swarm.js.map +1 -1
  200. package/dist/src/plugins/__tests__/registry.test.js +1 -1
  201. package/dist/src/plugins/__tests__/registry.test.js.map +1 -1
  202. package/dist/src/plugins/model-plugin.d.ts +20 -0
  203. package/dist/src/plugins/model-plugin.d.ts.map +1 -0
  204. package/dist/src/plugins/model-plugin.js +29 -0
  205. package/dist/src/plugins/model-plugin.js.map +1 -0
  206. package/dist/src/session/__tests__/session-manager.test.js +13 -11
  207. package/dist/src/session/__tests__/session-manager.test.js.map +1 -1
  208. package/dist/src/session/session-manager.d.ts.map +1 -1
  209. package/dist/src/session/session-manager.js +9 -0
  210. package/dist/src/session/session-manager.js.map +1 -1
  211. package/dist/src/telemetry/__tests__/meter.test.js +23 -0
  212. package/dist/src/telemetry/__tests__/meter.test.js.map +1 -1
  213. package/dist/src/telemetry/meter.d.ts +15 -0
  214. package/dist/src/telemetry/meter.d.ts.map +1 -1
  215. package/dist/src/telemetry/meter.js +14 -0
  216. package/dist/src/telemetry/meter.js.map +1 -1
  217. package/dist/src/tools/mcp-tool.d.ts +24 -3
  218. package/dist/src/tools/mcp-tool.d.ts.map +1 -1
  219. package/dist/src/tools/mcp-tool.js +103 -31
  220. package/dist/src/tools/mcp-tool.js.map +1 -1
  221. package/dist/src/tools/tool.d.ts +11 -1
  222. package/dist/src/tools/tool.d.ts.map +1 -1
  223. package/dist/src/tools/tool.js.map +1 -1
  224. package/dist/src/tsconfig.tsbuildinfo +1 -1
  225. package/dist/src/types/__tests__/agent.test.js +48 -0
  226. package/dist/src/types/__tests__/agent.test.js.map +1 -1
  227. package/dist/src/types/agent.d.ts +55 -6
  228. package/dist/src/types/agent.d.ts.map +1 -1
  229. package/dist/src/types/agent.js +22 -6
  230. package/dist/src/types/agent.js.map +1 -1
  231. package/dist/src/types/elicitation.d.ts +15 -0
  232. package/dist/src/types/elicitation.d.ts.map +1 -0
  233. package/dist/src/types/elicitation.js +2 -0
  234. package/dist/src/types/elicitation.js.map +1 -0
  235. package/dist/src/vended-plugins/skills/__tests__/agent-skills.test.node.js +9 -5
  236. package/dist/src/vended-plugins/skills/__tests__/agent-skills.test.node.js.map +1 -1
  237. package/dist/src/vended-tools/bash/__tests__/bash.test.node.js +1 -0
  238. package/dist/src/vended-tools/bash/__tests__/bash.test.node.js.map +1 -1
  239. package/dist/src/vended-tools/file-editor/__tests__/file-editor.test.node.js +1 -0
  240. package/dist/src/vended-tools/file-editor/__tests__/file-editor.test.node.js.map +1 -1
  241. package/dist/src/vended-tools/notebook/__tests__/notebook.test.js +1 -0
  242. package/dist/src/vended-tools/notebook/__tests__/notebook.test.js.map +1 -1
  243. package/package.json +9 -5
  244. package/dist/src/models/__tests__/openai.test.d.ts +0 -2
  245. package/dist/src/models/__tests__/openai.test.d.ts.map +0 -1
  246. package/dist/src/models/__tests__/openai.test.js.map +0 -1
  247. package/dist/src/models/openai.d.ts +0 -312
  248. package/dist/src/models/openai.d.ts.map +0 -1
  249. package/dist/src/models/openai.js +0 -789
  250. package/dist/src/models/openai.js.map +0 -1
@@ -26,34 +26,50 @@ describe('InitializedEvent', () => {
26
26
  describe('BeforeInvocationEvent', () => {
27
27
  it('creates instance with correct properties', () => {
28
28
  const agent = new Agent();
29
- const event = new BeforeInvocationEvent({ agent });
29
+ const event = new BeforeInvocationEvent({ agent, invocationState: {} });
30
30
  expect(event).toEqual({
31
31
  type: 'beforeInvocationEvent',
32
32
  agent: agent,
33
+ cancel: false,
34
+ invocationState: {},
33
35
  });
34
36
  // @ts-expect-error verifying that property is readonly
35
37
  event.agent = new Agent();
36
38
  });
37
39
  it('returns false for _shouldReverseCallbacks', () => {
38
40
  const agent = new Agent();
39
- const event = new BeforeInvocationEvent({ agent });
41
+ const event = new BeforeInvocationEvent({ agent, invocationState: {} });
40
42
  expect(event._shouldReverseCallbacks()).toBe(false);
41
43
  });
44
+ it('allows cancel to be set to true', () => {
45
+ const agent = new Agent();
46
+ const event = new BeforeInvocationEvent({ agent, invocationState: {} });
47
+ expect(event.cancel).toBe(false);
48
+ event.cancel = true;
49
+ expect(event.cancel).toBe(true);
50
+ });
51
+ it('allows cancel to be set to a string message', () => {
52
+ const agent = new Agent();
53
+ const event = new BeforeInvocationEvent({ agent, invocationState: {} });
54
+ event.cancel = 'unauthorized';
55
+ expect(event.cancel).toBe('unauthorized');
56
+ });
42
57
  });
43
58
  describe('AfterInvocationEvent', () => {
44
59
  it('creates instance with correct properties', () => {
45
60
  const agent = new Agent();
46
- const event = new AfterInvocationEvent({ agent });
61
+ const event = new AfterInvocationEvent({ agent, invocationState: {} });
47
62
  expect(event).toEqual({
48
63
  type: 'afterInvocationEvent',
49
64
  agent: agent,
65
+ invocationState: {},
50
66
  });
51
67
  // @ts-expect-error verifying that property is readonly
52
68
  event.agent = new Agent();
53
69
  });
54
70
  it('returns true for _shouldReverseCallbacks', () => {
55
71
  const agent = new Agent();
56
- const event = new AfterInvocationEvent({ agent });
72
+ const event = new AfterInvocationEvent({ agent, invocationState: {} });
57
73
  expect(event._shouldReverseCallbacks()).toBe(true);
58
74
  });
59
75
  });
@@ -61,11 +77,12 @@ describe('MessageAddedEvent', () => {
61
77
  it('creates instance with correct properties', () => {
62
78
  const agent = new Agent();
63
79
  const message = new Message({ role: 'assistant', content: [new TextBlock('Hello')] });
64
- const event = new MessageAddedEvent({ agent, message });
80
+ const event = new MessageAddedEvent({ agent, message, invocationState: {} });
65
81
  expect(event).toEqual({
66
82
  type: 'messageAddedEvent',
67
83
  agent: agent,
68
84
  message: message,
85
+ invocationState: {},
69
86
  });
70
87
  // @ts-expect-error verifying that property is readonly
71
88
  event.agent = new Agent();
@@ -75,7 +92,7 @@ describe('MessageAddedEvent', () => {
75
92
  it('returns false for _shouldReverseCallbacks', () => {
76
93
  const agent = new Agent();
77
94
  const message = new Message({ role: 'assistant', content: [] });
78
- const event = new MessageAddedEvent({ agent, message });
95
+ const event = new MessageAddedEvent({ agent, message, invocationState: {} });
79
96
  expect(event._shouldReverseCallbacks()).toBe(false);
80
97
  });
81
98
  });
@@ -93,13 +110,14 @@ describe('BeforeToolCallEvent', () => {
93
110
  toolUseId: 'test-id',
94
111
  input: { arg: 'value' },
95
112
  };
96
- const event = new BeforeToolCallEvent({ agent, toolUse, tool });
113
+ const event = new BeforeToolCallEvent({ agent, toolUse, tool, invocationState: {} });
97
114
  expect(event).toEqual({
98
115
  type: 'beforeToolCallEvent',
99
116
  agent: agent,
100
117
  toolUse: toolUse,
101
118
  tool: tool,
102
119
  cancel: false,
120
+ invocationState: {},
103
121
  });
104
122
  // @ts-expect-error verifying that property is readonly
105
123
  event.agent = new Agent();
@@ -115,25 +133,26 @@ describe('BeforeToolCallEvent', () => {
115
133
  toolUseId: 'test-id',
116
134
  input: {},
117
135
  };
118
- const event = new BeforeToolCallEvent({ agent, toolUse, tool: undefined });
136
+ const event = new BeforeToolCallEvent({ agent, toolUse, tool: undefined, invocationState: {} });
119
137
  expect(event).toEqual({
120
138
  type: 'beforeToolCallEvent',
121
139
  agent: agent,
122
140
  toolUse: toolUse,
123
141
  tool: undefined,
124
142
  cancel: false,
143
+ invocationState: {},
125
144
  });
126
145
  });
127
146
  it('returns false for _shouldReverseCallbacks', () => {
128
147
  const agent = new Agent();
129
148
  const toolUse = { name: 'test', toolUseId: 'id', input: {} };
130
- const event = new BeforeToolCallEvent({ agent, toolUse, tool: undefined });
149
+ const event = new BeforeToolCallEvent({ agent, toolUse, tool: undefined, invocationState: {} });
131
150
  expect(event._shouldReverseCallbacks()).toBe(false);
132
151
  });
133
152
  it('allows cancel to be set to true', () => {
134
153
  const agent = new Agent();
135
154
  const toolUse = { name: 'test', toolUseId: 'id', input: {} };
136
- const event = new BeforeToolCallEvent({ agent, toolUse, tool: undefined });
155
+ const event = new BeforeToolCallEvent({ agent, toolUse, tool: undefined, invocationState: {} });
137
156
  expect(event.cancel).toBe(false);
138
157
  event.cancel = true;
139
158
  expect(event.cancel).toBe(true);
@@ -141,7 +160,7 @@ describe('BeforeToolCallEvent', () => {
141
160
  it('allows cancel to be set to a string message', () => {
142
161
  const agent = new Agent();
143
162
  const toolUse = { name: 'test', toolUseId: 'id', input: {} };
144
- const event = new BeforeToolCallEvent({ agent, toolUse, tool: undefined });
163
+ const event = new BeforeToolCallEvent({ agent, toolUse, tool: undefined, invocationState: {} });
145
164
  event.cancel = 'tool not allowed';
146
165
  expect(event.cancel).toBe('tool not allowed');
147
166
  });
@@ -165,7 +184,7 @@ describe('AfterToolCallEvent', () => {
165
184
  status: 'success',
166
185
  content: [new TextBlock('Success')],
167
186
  });
168
- const event = new AfterToolCallEvent({ agent, toolUse, tool, result });
187
+ const event = new AfterToolCallEvent({ agent, toolUse, tool, result, invocationState: {} });
169
188
  expect(event).toEqual({
170
189
  type: 'afterToolCallEvent',
171
190
  agent: agent,
@@ -173,6 +192,7 @@ describe('AfterToolCallEvent', () => {
173
192
  tool: tool,
174
193
  result: result,
175
194
  error: undefined,
195
+ invocationState: {},
176
196
  });
177
197
  // @ts-expect-error verifying that property is readonly
178
198
  event.agent = new Agent();
@@ -180,8 +200,19 @@ describe('AfterToolCallEvent', () => {
180
200
  event.toolUse = toolUse;
181
201
  // @ts-expect-error verifying that property is readonly
182
202
  event.tool = tool;
183
- // @ts-expect-error verifying that property is readonly
184
- event.result = result;
203
+ });
204
+ it('allows result to be replaced', () => {
205
+ const agent = new Agent();
206
+ const toolUse = { name: 'test', toolUseId: 'id', input: {} };
207
+ const result = new ToolResultBlock({ toolUseId: 'id', status: 'success', content: [new TextBlock('original')] });
208
+ const event = new AfterToolCallEvent({ agent, toolUse, tool: undefined, result, invocationState: {} });
209
+ const replacedResult = new ToolResultBlock({
210
+ toolUseId: 'id',
211
+ status: 'success',
212
+ content: [new TextBlock('replaced')],
213
+ });
214
+ event.result = replacedResult;
215
+ expect(event.result).toBe(replacedResult);
185
216
  });
186
217
  it('creates instance with error property when tool execution fails', () => {
187
218
  const agent = new Agent();
@@ -192,7 +223,7 @@ describe('AfterToolCallEvent', () => {
192
223
  content: [new TextBlock('Error')],
193
224
  });
194
225
  const error = new Error('Tool failed');
195
- const event = new AfterToolCallEvent({ agent, toolUse, tool: undefined, result, error });
226
+ const event = new AfterToolCallEvent({ agent, toolUse, tool: undefined, result, error, invocationState: {} });
196
227
  expect(event).toEqual({
197
228
  type: 'afterToolCallEvent',
198
229
  agent: agent,
@@ -200,6 +231,7 @@ describe('AfterToolCallEvent', () => {
200
231
  tool: undefined,
201
232
  result: result,
202
233
  error: error,
234
+ invocationState: {},
203
235
  });
204
236
  });
205
237
  it('returns true for _shouldReverseCallbacks', () => {
@@ -210,7 +242,7 @@ describe('AfterToolCallEvent', () => {
210
242
  status: 'success',
211
243
  content: [],
212
244
  });
213
- const event = new AfterToolCallEvent({ agent, toolUse, tool: undefined, result });
245
+ const event = new AfterToolCallEvent({ agent, toolUse, tool: undefined, result, invocationState: {} });
214
246
  expect(event._shouldReverseCallbacks()).toBe(true);
215
247
  });
216
248
  it('allows retry to be set when error is present', () => {
@@ -222,7 +254,7 @@ describe('AfterToolCallEvent', () => {
222
254
  content: [new TextBlock('Error')],
223
255
  });
224
256
  const error = new Error('Tool failed');
225
- const event = new AfterToolCallEvent({ agent, toolUse, tool: undefined, result, error });
257
+ const event = new AfterToolCallEvent({ agent, toolUse, tool: undefined, result, error, invocationState: {} });
226
258
  expect(event.retry).toBeUndefined();
227
259
  event.retry = true;
228
260
  expect(event.retry).toBe(true);
@@ -237,7 +269,7 @@ describe('AfterToolCallEvent', () => {
237
269
  status: 'success',
238
270
  content: [new TextBlock('Success')],
239
271
  });
240
- const event = new AfterToolCallEvent({ agent, toolUse, tool: undefined, result });
272
+ const event = new AfterToolCallEvent({ agent, toolUse, tool: undefined, result, invocationState: {} });
241
273
  expect(event.retry).toBeUndefined();
242
274
  event.retry = true;
243
275
  expect(event.retry).toBe(true);
@@ -246,20 +278,62 @@ describe('AfterToolCallEvent', () => {
246
278
  describe('BeforeModelCallEvent', () => {
247
279
  it('creates instance with correct properties', () => {
248
280
  const agent = new Agent();
249
- const event = new BeforeModelCallEvent({ agent, model: agent.model });
281
+ const event = new BeforeModelCallEvent({ agent, model: agent.model, invocationState: {} });
250
282
  expect(event).toEqual({
251
283
  type: 'beforeModelCallEvent',
252
284
  agent: agent,
253
285
  model: agent.model,
286
+ cancel: false,
287
+ invocationState: {},
254
288
  });
255
289
  // @ts-expect-error verifying that property is readonly
256
290
  event.agent = new Agent();
257
291
  });
292
+ it('includes projectedInputTokens when provided', () => {
293
+ const agent = new Agent();
294
+ const event = new BeforeModelCallEvent({
295
+ agent,
296
+ model: agent.model,
297
+ invocationState: {},
298
+ projectedInputTokens: 500,
299
+ });
300
+ expect(event).toEqual({
301
+ type: 'beforeModelCallEvent',
302
+ agent,
303
+ model: agent.model,
304
+ cancel: false,
305
+ invocationState: {},
306
+ projectedInputTokens: 500,
307
+ });
308
+ expect(event.toJSON()).toStrictEqual({
309
+ type: 'beforeModelCallEvent',
310
+ projectedInputTokens: 500,
311
+ });
312
+ });
313
+ it('excludes projectedInputTokens from toJSON when not provided', () => {
314
+ const agent = new Agent();
315
+ const event = new BeforeModelCallEvent({ agent, model: agent.model, invocationState: {} });
316
+ expect(event.projectedInputTokens).toBeUndefined();
317
+ expect(event.toJSON()).toStrictEqual({ type: 'beforeModelCallEvent' });
318
+ });
258
319
  it('returns false for _shouldReverseCallbacks', () => {
259
320
  const agent = new Agent();
260
- const event = new BeforeModelCallEvent({ agent, model: agent.model });
321
+ const event = new BeforeModelCallEvent({ agent, model: agent.model, invocationState: {} });
261
322
  expect(event._shouldReverseCallbacks()).toBe(false);
262
323
  });
324
+ it('allows cancel to be set to true', () => {
325
+ const agent = new Agent();
326
+ const event = new BeforeModelCallEvent({ agent, model: agent.model, invocationState: {} });
327
+ expect(event.cancel).toBe(false);
328
+ event.cancel = true;
329
+ expect(event.cancel).toBe(true);
330
+ });
331
+ it('allows cancel to be set to a string message', () => {
332
+ const agent = new Agent();
333
+ const event = new BeforeModelCallEvent({ agent, model: agent.model, invocationState: {} });
334
+ event.cancel = 'rate limited';
335
+ expect(event.cancel).toBe('rate limited');
336
+ });
263
337
  });
264
338
  describe('AfterModelCallEvent', () => {
265
339
  it('creates instance with correct properties on success', () => {
@@ -267,13 +341,14 @@ describe('AfterModelCallEvent', () => {
267
341
  const message = new Message({ role: 'assistant', content: [new TextBlock('Response')] });
268
342
  const stopReason = 'endTurn';
269
343
  const response = { message, stopReason };
270
- const event = new AfterModelCallEvent({ agent, model: agent.model, stopData: response });
344
+ const event = new AfterModelCallEvent({ agent, model: agent.model, stopData: response, invocationState: {} });
271
345
  expect(event).toEqual({
272
346
  type: 'afterModelCallEvent',
273
347
  agent: agent,
274
348
  model: agent.model,
275
349
  stopData: response,
276
350
  error: undefined,
351
+ invocationState: {},
277
352
  });
278
353
  // @ts-expect-error verifying that property is readonly
279
354
  event.agent = new Agent();
@@ -285,26 +360,27 @@ describe('AfterModelCallEvent', () => {
285
360
  const message = new Message({ role: 'assistant', content: [] });
286
361
  const error = new Error('Model failed');
287
362
  const response = { message, stopReason: 'error' };
288
- const event = new AfterModelCallEvent({ agent, model: agent.model, stopData: response, error });
363
+ const event = new AfterModelCallEvent({ agent, model: agent.model, stopData: response, error, invocationState: {} });
289
364
  expect(event).toEqual({
290
365
  type: 'afterModelCallEvent',
291
366
  agent: agent,
292
367
  model: agent.model,
293
368
  stopData: response,
294
369
  error: error,
370
+ invocationState: {},
295
371
  });
296
372
  });
297
373
  it('returns true for _shouldReverseCallbacks', () => {
298
374
  const agent = new Agent();
299
375
  const message = new Message({ role: 'assistant', content: [] });
300
376
  const response = { message, stopReason: 'endTurn' };
301
- const event = new AfterModelCallEvent({ agent, model: agent.model, stopData: response });
377
+ const event = new AfterModelCallEvent({ agent, model: agent.model, stopData: response, invocationState: {} });
302
378
  expect(event._shouldReverseCallbacks()).toBe(true);
303
379
  });
304
380
  it('allows retry to be set when error is present', () => {
305
381
  const agent = new Agent();
306
382
  const error = new Error('Model failed');
307
- const event = new AfterModelCallEvent({ agent, model: agent.model, error });
383
+ const event = new AfterModelCallEvent({ agent, model: agent.model, error, invocationState: {} });
308
384
  // Initially undefined
309
385
  expect(event.retry).toBeUndefined();
310
386
  // Can be set to true
@@ -317,7 +393,7 @@ describe('AfterModelCallEvent', () => {
317
393
  it('retry is optional and defaults to undefined', () => {
318
394
  const agent = new Agent();
319
395
  const error = new Error('Model failed');
320
- const event = new AfterModelCallEvent({ agent, model: agent.model, error });
396
+ const event = new AfterModelCallEvent({ agent, model: agent.model, error, invocationState: {} });
321
397
  expect(event.retry).toBeUndefined();
322
398
  });
323
399
  });
@@ -328,11 +404,12 @@ describe('ModelStreamUpdateEvent', () => {
328
404
  type: 'modelMessageStartEvent',
329
405
  role: 'assistant',
330
406
  };
331
- const hookEvent = new ModelStreamUpdateEvent({ agent, event: streamEvent });
407
+ const hookEvent = new ModelStreamUpdateEvent({ agent, event: streamEvent, invocationState: {} });
332
408
  expect(hookEvent).toEqual({
333
409
  type: 'modelStreamUpdateEvent',
334
410
  agent: agent,
335
411
  event: streamEvent,
412
+ invocationState: {},
336
413
  });
337
414
  // @ts-expect-error verifying that property is readonly
338
415
  hookEvent.agent = new Agent();
@@ -344,11 +421,12 @@ describe('ContentBlockEvent', () => {
344
421
  it('creates instance with correct properties', () => {
345
422
  const agent = new Agent();
346
423
  const contentBlock = new TextBlock('Hello');
347
- const event = new ContentBlockEvent({ agent, contentBlock });
424
+ const event = new ContentBlockEvent({ agent, contentBlock, invocationState: {} });
348
425
  expect(event).toEqual({
349
426
  type: 'contentBlockEvent',
350
427
  agent: agent,
351
428
  contentBlock: contentBlock,
429
+ invocationState: {},
352
430
  });
353
431
  // @ts-expect-error verifying that property is readonly
354
432
  event.agent = new Agent();
@@ -360,12 +438,13 @@ describe('ModelMessageEvent', () => {
360
438
  it('creates instance with correct properties', () => {
361
439
  const agent = new Agent();
362
440
  const message = new Message({ role: 'assistant', content: [new TextBlock('Hello')] });
363
- const event = new ModelMessageEvent({ agent, message, stopReason: 'endTurn' });
441
+ const event = new ModelMessageEvent({ agent, message, stopReason: 'endTurn', invocationState: {} });
364
442
  expect(event).toEqual({
365
443
  type: 'modelMessageEvent',
366
444
  agent: agent,
367
445
  message: message,
368
446
  stopReason: 'endTurn',
447
+ invocationState: {},
369
448
  });
370
449
  // @ts-expect-error verifying that property is readonly
371
450
  event.agent = new Agent();
@@ -383,11 +462,12 @@ describe('ToolResultEvent', () => {
383
462
  status: 'success',
384
463
  content: [new TextBlock('Result')],
385
464
  });
386
- const event = new ToolResultEvent({ agent, result: toolResult });
465
+ const event = new ToolResultEvent({ agent, result: toolResult, invocationState: {} });
387
466
  expect(event).toEqual({
388
467
  type: 'toolResultEvent',
389
468
  agent: agent,
390
469
  result: toolResult,
470
+ invocationState: {},
391
471
  });
392
472
  // @ts-expect-error verifying that property is readonly
393
473
  event.agent = new Agent();
@@ -399,11 +479,12 @@ describe('ToolStreamUpdateEvent', () => {
399
479
  it('creates instance with correct properties', () => {
400
480
  const agent = new Agent();
401
481
  const toolStreamEvent = new ToolStreamEvent({ data: 'progress' });
402
- const event = new ToolStreamUpdateEvent({ agent, event: toolStreamEvent });
482
+ const event = new ToolStreamUpdateEvent({ agent, event: toolStreamEvent, invocationState: {} });
403
483
  expect(event).toEqual({
404
484
  type: 'toolStreamUpdateEvent',
405
485
  agent: agent,
406
486
  event: toolStreamEvent,
487
+ invocationState: {},
407
488
  });
408
489
  // @ts-expect-error verifying that property is readonly
409
490
  event.agent = new Agent();
@@ -418,12 +499,14 @@ describe('AgentResultEvent', () => {
418
499
  stopReason: 'endTurn',
419
500
  lastMessage: new Message({ role: 'assistant', content: [new TextBlock('Done')] }),
420
501
  metrics: new AgentMetrics(),
502
+ invocationState: {},
421
503
  });
422
- const event = new AgentResultEvent({ agent, result });
504
+ const event = new AgentResultEvent({ agent, result, invocationState: {} });
423
505
  expect(event).toEqual({
424
506
  type: 'agentResultEvent',
425
507
  agent: agent,
426
508
  result: result,
509
+ invocationState: {},
427
510
  });
428
511
  // @ts-expect-error verifying that property is readonly
429
512
  event.agent = new Agent();
@@ -444,12 +527,13 @@ describe('BeforeToolsEvent', () => {
444
527
  }),
445
528
  ],
446
529
  });
447
- const event = new BeforeToolsEvent({ agent, message });
530
+ const event = new BeforeToolsEvent({ agent, message, invocationState: {} });
448
531
  expect(event).toEqual({
449
532
  type: 'beforeToolsEvent',
450
533
  agent: agent,
451
534
  message: message,
452
535
  cancel: false,
536
+ invocationState: {},
453
537
  });
454
538
  // @ts-expect-error verifying that property is readonly
455
539
  event.agent = new Agent();
@@ -459,13 +543,13 @@ describe('BeforeToolsEvent', () => {
459
543
  it('returns false for _shouldReverseCallbacks', () => {
460
544
  const agent = new Agent();
461
545
  const message = new Message({ role: 'assistant', content: [] });
462
- const event = new BeforeToolsEvent({ agent, message });
546
+ const event = new BeforeToolsEvent({ agent, message, invocationState: {} });
463
547
  expect(event._shouldReverseCallbacks()).toBe(false);
464
548
  });
465
549
  it('allows cancel to be set to true', () => {
466
550
  const agent = new Agent();
467
551
  const message = new Message({ role: 'assistant', content: [] });
468
- const event = new BeforeToolsEvent({ agent, message });
552
+ const event = new BeforeToolsEvent({ agent, message, invocationState: {} });
469
553
  expect(event.cancel).toBe(false);
470
554
  event.cancel = true;
471
555
  expect(event.cancel).toBe(true);
@@ -473,7 +557,7 @@ describe('BeforeToolsEvent', () => {
473
557
  it('allows cancel to be set to a string message', () => {
474
558
  const agent = new Agent();
475
559
  const message = new Message({ role: 'assistant', content: [] });
476
- const event = new BeforeToolsEvent({ agent, message });
560
+ const event = new BeforeToolsEvent({ agent, message, invocationState: {} });
477
561
  event.cancel = 'tools not allowed';
478
562
  expect(event.cancel).toBe('tools not allowed');
479
563
  });
@@ -491,11 +575,12 @@ describe('AfterToolsEvent', () => {
491
575
  }),
492
576
  ],
493
577
  });
494
- const event = new AfterToolsEvent({ agent, message });
578
+ const event = new AfterToolsEvent({ agent, message, invocationState: {} });
495
579
  expect(event).toEqual({
496
580
  type: 'afterToolsEvent',
497
581
  agent: agent,
498
582
  message: message,
583
+ invocationState: {},
499
584
  });
500
585
  // @ts-expect-error verifying that property is readonly
501
586
  event.agent = new Agent();
@@ -505,7 +590,7 @@ describe('AfterToolsEvent', () => {
505
590
  it('returns true for _shouldReverseCallbacks', () => {
506
591
  const agent = new Agent();
507
592
  const message = new Message({ role: 'user', content: [] });
508
- const event = new AfterToolsEvent({ agent, message });
593
+ const event = new AfterToolsEvent({ agent, message, invocationState: {} });
509
594
  expect(event._shouldReverseCallbacks()).toBe(true);
510
595
  });
511
596
  });
@@ -522,7 +607,7 @@ describe('toJSON serialization', () => {
522
607
  describe('BeforeInvocationEvent', () => {
523
608
  it('excludes agent and returns only type', () => {
524
609
  const agent = new Agent();
525
- const event = new BeforeInvocationEvent({ agent });
610
+ const event = new BeforeInvocationEvent({ agent, invocationState: {} });
526
611
  const json = JSON.parse(JSON.stringify(event));
527
612
  expect(json).toStrictEqual({ type: 'beforeInvocationEvent' });
528
613
  });
@@ -530,7 +615,7 @@ describe('toJSON serialization', () => {
530
615
  describe('AfterInvocationEvent', () => {
531
616
  it('excludes agent and returns only type', () => {
532
617
  const agent = new Agent();
533
- const event = new AfterInvocationEvent({ agent });
618
+ const event = new AfterInvocationEvent({ agent, invocationState: {} });
534
619
  const json = JSON.parse(JSON.stringify(event));
535
620
  expect(json).toStrictEqual({ type: 'afterInvocationEvent' });
536
621
  });
@@ -538,7 +623,7 @@ describe('toJSON serialization', () => {
538
623
  describe('BeforeModelCallEvent', () => {
539
624
  it('excludes agent and model and returns only type', () => {
540
625
  const agent = new Agent();
541
- const event = new BeforeModelCallEvent({ agent, model: agent.model });
626
+ const event = new BeforeModelCallEvent({ agent, model: agent.model, invocationState: {} });
542
627
  const json = JSON.parse(JSON.stringify(event));
543
628
  expect(json).toStrictEqual({ type: 'beforeModelCallEvent' });
544
629
  });
@@ -547,7 +632,7 @@ describe('toJSON serialization', () => {
547
632
  it('includes message and excludes agent', () => {
548
633
  const agent = new Agent();
549
634
  const message = new Message({ role: 'assistant', content: [new TextBlock('Hello')] });
550
- const event = new MessageAddedEvent({ agent, message });
635
+ const event = new MessageAddedEvent({ agent, message, invocationState: {} });
551
636
  const json = JSON.parse(JSON.stringify(event));
552
637
  expect(json).toStrictEqual({
553
638
  type: 'messageAddedEvent',
@@ -562,7 +647,7 @@ describe('toJSON serialization', () => {
562
647
  type: 'modelContentBlockDeltaEvent',
563
648
  delta: { type: 'textDelta', text: 'Hi' },
564
649
  };
565
- const event = new ModelStreamUpdateEvent({ agent, event: streamEvent });
650
+ const event = new ModelStreamUpdateEvent({ agent, event: streamEvent, invocationState: {} });
566
651
  const json = JSON.parse(JSON.stringify(event));
567
652
  expect(json).toStrictEqual({
568
653
  type: 'modelStreamUpdateEvent',
@@ -574,7 +659,7 @@ describe('toJSON serialization', () => {
574
659
  it('includes content block and excludes agent', () => {
575
660
  const agent = new Agent();
576
661
  const contentBlock = new TextBlock('Hello world');
577
- const event = new ContentBlockEvent({ agent, contentBlock });
662
+ const event = new ContentBlockEvent({ agent, contentBlock, invocationState: {} });
578
663
  const json = JSON.parse(JSON.stringify(event));
579
664
  expect(json).toStrictEqual({
580
665
  type: 'contentBlockEvent',
@@ -586,7 +671,7 @@ describe('toJSON serialization', () => {
586
671
  it('includes message and stopReason, excludes agent', () => {
587
672
  const agent = new Agent();
588
673
  const message = new Message({ role: 'assistant', content: [new TextBlock('Done')] });
589
- const event = new ModelMessageEvent({ agent, message, stopReason: 'endTurn' });
674
+ const event = new ModelMessageEvent({ agent, message, stopReason: 'endTurn', invocationState: {} });
590
675
  const json = JSON.parse(JSON.stringify(event));
591
676
  expect(json).toStrictEqual({
592
677
  type: 'modelMessageEvent',
@@ -603,7 +688,7 @@ describe('toJSON serialization', () => {
603
688
  status: 'success',
604
689
  content: [new TextBlock('42')],
605
690
  });
606
- const event = new ToolResultEvent({ agent, result });
691
+ const event = new ToolResultEvent({ agent, result, invocationState: {} });
607
692
  const json = JSON.parse(JSON.stringify(event));
608
693
  expect(json).toStrictEqual({
609
694
  type: 'toolResultEvent',
@@ -615,7 +700,7 @@ describe('toJSON serialization', () => {
615
700
  it('includes tool stream event and excludes agent', () => {
616
701
  const agent = new Agent();
617
702
  const toolStreamEvent = new ToolStreamEvent({ data: { progress: 50 } });
618
- const event = new ToolStreamUpdateEvent({ agent, event: toolStreamEvent });
703
+ const event = new ToolStreamUpdateEvent({ agent, event: toolStreamEvent, invocationState: {} });
619
704
  const json = JSON.parse(JSON.stringify(event));
620
705
  expect(json).toStrictEqual({
621
706
  type: 'toolStreamUpdateEvent',
@@ -630,8 +715,9 @@ describe('toJSON serialization', () => {
630
715
  stopReason: 'endTurn',
631
716
  lastMessage: new Message({ role: 'assistant', content: [new TextBlock('Done')] }),
632
717
  metrics: new AgentMetrics(),
718
+ invocationState: {},
633
719
  });
634
- const event = new AgentResultEvent({ agent, result });
720
+ const event = new AgentResultEvent({ agent, result, invocationState: {} });
635
721
  const json = JSON.parse(JSON.stringify(event));
636
722
  expect(json).toStrictEqual({
637
723
  type: 'agentResultEvent',
@@ -653,7 +739,7 @@ describe('toJSON serialization', () => {
653
739
  callback: () => 'result',
654
740
  });
655
741
  const toolUse = { name: 'testTool', toolUseId: 'id-1', input: { query: 'hello' } };
656
- const event = new BeforeToolCallEvent({ agent, toolUse, tool });
742
+ const event = new BeforeToolCallEvent({ agent, toolUse, tool, invocationState: {} });
657
743
  const json = JSON.parse(JSON.stringify(event));
658
744
  expect(json).toStrictEqual({
659
745
  type: 'beforeToolCallEvent',
@@ -670,7 +756,7 @@ describe('toJSON serialization', () => {
670
756
  status: 'success',
671
757
  content: [new TextBlock('42')],
672
758
  });
673
- const event = new AfterToolCallEvent({ agent, toolUse, tool: undefined, result });
759
+ const event = new AfterToolCallEvent({ agent, toolUse, tool: undefined, result, invocationState: {} });
674
760
  const json = JSON.parse(JSON.stringify(event));
675
761
  expect(json).toStrictEqual({
676
762
  type: 'afterToolCallEvent',
@@ -687,7 +773,7 @@ describe('toJSON serialization', () => {
687
773
  content: [new TextBlock('Error')],
688
774
  });
689
775
  const error = new Error('Tool crashed');
690
- const event = new AfterToolCallEvent({ agent, toolUse, tool: undefined, result, error });
776
+ const event = new AfterToolCallEvent({ agent, toolUse, tool: undefined, result, error, invocationState: {} });
691
777
  event.retry = true;
692
778
  const json = JSON.parse(JSON.stringify(event));
693
779
  expect(json).toStrictEqual({
@@ -703,7 +789,7 @@ describe('toJSON serialization', () => {
703
789
  const agent = new Agent();
704
790
  const message = new Message({ role: 'assistant', content: [new TextBlock('Hi')] });
705
791
  const stopData = { message, stopReason: 'endTurn' };
706
- const event = new AfterModelCallEvent({ agent, model: agent.model, stopData });
792
+ const event = new AfterModelCallEvent({ agent, model: agent.model, stopData, invocationState: {} });
707
793
  const json = JSON.parse(JSON.stringify(event));
708
794
  expect(json).toStrictEqual({
709
795
  type: 'afterModelCallEvent',
@@ -716,7 +802,7 @@ describe('toJSON serialization', () => {
716
802
  it('converts error to message string and excludes retry', () => {
717
803
  const agent = new Agent();
718
804
  const error = new Error('Model failed');
719
- const event = new AfterModelCallEvent({ agent, model: agent.model, error });
805
+ const event = new AfterModelCallEvent({ agent, model: agent.model, error, invocationState: {} });
720
806
  event.retry = true;
721
807
  const json = JSON.parse(JSON.stringify(event));
722
808
  expect(json).toStrictEqual({
@@ -732,7 +818,7 @@ describe('toJSON serialization', () => {
732
818
  role: 'assistant',
733
819
  content: [new ToolUseBlock({ name: 'calc', toolUseId: 'id-1', input: {} })],
734
820
  });
735
- const event = new BeforeToolsEvent({ agent, message });
821
+ const event = new BeforeToolsEvent({ agent, message, invocationState: {} });
736
822
  event.cancel = 'not allowed';
737
823
  const json = JSON.parse(JSON.stringify(event));
738
824
  expect(json).toStrictEqual({
@@ -754,7 +840,7 @@ describe('toJSON serialization', () => {
754
840
  }),
755
841
  ],
756
842
  });
757
- const event = new AfterToolsEvent({ agent, message });
843
+ const event = new AfterToolsEvent({ agent, message, invocationState: {} });
758
844
  const json = JSON.parse(JSON.stringify(event));
759
845
  expect(json).toStrictEqual({
760
846
  type: 'afterToolsEvent',
@@ -773,6 +859,7 @@ describe('toJSON serialization', () => {
773
859
  const event = new ModelStreamUpdateEvent({
774
860
  agent,
775
861
  event: { type: 'modelContentBlockDeltaEvent', delta: { type: 'textDelta', text: 'Hi' } },
862
+ invocationState: {},
776
863
  });
777
864
  const json = JSON.stringify(event);
778
865
  // Should be small (no agent serialized)
@@ -792,7 +879,7 @@ describe('toJSON serialization completeness', () => {
792
879
  * If you add a new field to an event and it should be excluded from wire serialization,
793
880
  * add it here. Otherwise, add it to toJSON() so it gets serialized.
794
881
  */
795
- const EXCLUDED_FIELDS = new Set(['agent', 'model', 'tool', 'cancel', 'retry']);
882
+ const EXCLUDED_FIELDS = new Set(['agent', 'model', 'tool', 'cancel', 'retry', 'invocationState']);
796
883
  /**
797
884
  * Fields where toJSON() transforms the value (e.g., Error to message object).
798
885
  * These appear in both instance and JSON but with different shapes.
@@ -817,30 +904,50 @@ describe('toJSON serialization completeness', () => {
817
904
  stopReason: 'endTurn',
818
905
  lastMessage: message,
819
906
  metrics: new AgentMetrics(),
907
+ invocationState: {},
820
908
  });
821
909
  return [
822
910
  { name: 'InitializedEvent', event: new InitializedEvent({ agent }) },
823
- { name: 'BeforeInvocationEvent', event: new BeforeInvocationEvent({ agent }) },
824
- { name: 'AfterInvocationEvent', event: new AfterInvocationEvent({ agent }) },
825
- { name: 'BeforeModelCallEvent', event: new BeforeModelCallEvent({ agent, model: agent.model }) },
911
+ { name: 'BeforeInvocationEvent', event: new BeforeInvocationEvent({ agent, invocationState: {} }) },
912
+ { name: 'AfterInvocationEvent', event: new AfterInvocationEvent({ agent, invocationState: {} }) },
913
+ {
914
+ name: 'BeforeModelCallEvent',
915
+ event: new BeforeModelCallEvent({
916
+ agent,
917
+ model: agent.model,
918
+ invocationState: {},
919
+ projectedInputTokens: 100,
920
+ }),
921
+ },
826
922
  {
827
923
  name: 'AfterModelCallEvent',
828
- event: Object.assign(new AfterModelCallEvent({ agent, model: agent.model, stopData, error }), { retry: true }),
924
+ event: Object.assign(new AfterModelCallEvent({ agent, model: agent.model, stopData, error, invocationState: {} }), { retry: true }),
925
+ },
926
+ { name: 'MessageAddedEvent', event: new MessageAddedEvent({ agent, message, invocationState: {} }) },
927
+ {
928
+ name: 'ModelStreamUpdateEvent',
929
+ event: new ModelStreamUpdateEvent({ agent, event: streamEvent, invocationState: {} }),
930
+ },
931
+ { name: 'ContentBlockEvent', event: new ContentBlockEvent({ agent, contentBlock, invocationState: {} }) },
932
+ {
933
+ name: 'ModelMessageEvent',
934
+ event: new ModelMessageEvent({ agent, message, stopReason: 'endTurn', invocationState: {} }),
829
935
  },
830
- { name: 'MessageAddedEvent', event: new MessageAddedEvent({ agent, message }) },
831
- { name: 'ModelStreamUpdateEvent', event: new ModelStreamUpdateEvent({ agent, event: streamEvent }) },
832
- { name: 'ContentBlockEvent', event: new ContentBlockEvent({ agent, contentBlock }) },
833
- { name: 'ModelMessageEvent', event: new ModelMessageEvent({ agent, message, stopReason: 'endTurn' }) },
834
- { name: 'ToolResultEvent', event: new ToolResultEvent({ agent, result }) },
835
- { name: 'ToolStreamUpdateEvent', event: new ToolStreamUpdateEvent({ agent, event: toolStreamEvent }) },
836
- { name: 'AgentResultEvent', event: new AgentResultEvent({ agent, result: agentResult }) },
837
- { name: 'BeforeToolCallEvent', event: new BeforeToolCallEvent({ agent, toolUse, tool }) },
936
+ { name: 'ToolResultEvent', event: new ToolResultEvent({ agent, result, invocationState: {} }) },
937
+ {
938
+ name: 'ToolStreamUpdateEvent',
939
+ event: new ToolStreamUpdateEvent({ agent, event: toolStreamEvent, invocationState: {} }),
940
+ },
941
+ { name: 'AgentResultEvent', event: new AgentResultEvent({ agent, result: agentResult, invocationState: {} }) },
942
+ { name: 'BeforeToolCallEvent', event: new BeforeToolCallEvent({ agent, toolUse, tool, invocationState: {} }) },
838
943
  {
839
944
  name: 'AfterToolCallEvent',
840
- event: Object.assign(new AfterToolCallEvent({ agent, toolUse, tool, result, error }), { retry: true }),
945
+ event: Object.assign(new AfterToolCallEvent({ agent, toolUse, tool, result, error, invocationState: {} }), {
946
+ retry: true,
947
+ }),
841
948
  },
842
- { name: 'BeforeToolsEvent', event: new BeforeToolsEvent({ agent, message }) },
843
- { name: 'AfterToolsEvent', event: new AfterToolsEvent({ agent, message }) },
949
+ { name: 'BeforeToolsEvent', event: new BeforeToolsEvent({ agent, message, invocationState: {} }) },
950
+ { name: 'AfterToolsEvent', event: new AfterToolsEvent({ agent, message, invocationState: {} }) },
844
951
  ];
845
952
  }
846
953
  const eventInstances = createEventInstances();