@strands-agents/sdk 0.2.2 → 0.4.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 (241) hide show
  1. package/README.md +43 -0
  2. package/dist/src/__fixtures__/mock-hook-provider.d.ts +3 -7
  3. package/dist/src/__fixtures__/mock-hook-provider.d.ts.map +1 -1
  4. package/dist/src/__fixtures__/mock-hook-provider.js +3 -9
  5. package/dist/src/__fixtures__/mock-hook-provider.js.map +1 -1
  6. package/dist/src/__fixtures__/mock-message-model.d.ts +8 -2
  7. package/dist/src/__fixtures__/mock-message-model.d.ts.map +1 -1
  8. package/dist/src/__fixtures__/mock-message-model.js +1 -0
  9. package/dist/src/__fixtures__/mock-message-model.js.map +1 -1
  10. package/dist/src/__fixtures__/mock-storage-provider.d.ts +37 -0
  11. package/dist/src/__fixtures__/mock-storage-provider.d.ts.map +1 -0
  12. package/dist/src/__fixtures__/mock-storage-provider.js +105 -0
  13. package/dist/src/__fixtures__/mock-storage-provider.js.map +1 -0
  14. package/dist/src/__fixtures__/slim-types.d.ts +50 -0
  15. package/dist/src/__fixtures__/slim-types.d.ts.map +1 -0
  16. package/dist/src/__fixtures__/slim-types.js +6 -0
  17. package/dist/src/__fixtures__/slim-types.js.map +1 -0
  18. package/dist/src/__fixtures__/tool-helpers.d.ts +8 -3
  19. package/dist/src/__fixtures__/tool-helpers.d.ts.map +1 -1
  20. package/dist/src/__fixtures__/tool-helpers.js +1 -1
  21. package/dist/src/__fixtures__/tool-helpers.js.map +1 -1
  22. package/dist/src/agent/__tests__/agent.hook.test.js +18 -18
  23. package/dist/src/agent/__tests__/agent.hook.test.js.map +1 -1
  24. package/dist/src/agent/__tests__/agent.test.js +124 -8
  25. package/dist/src/agent/__tests__/agent.test.js.map +1 -1
  26. package/dist/src/agent/__tests__/printer.test.js +5 -9
  27. package/dist/src/agent/__tests__/printer.test.js.map +1 -1
  28. package/dist/src/agent/__tests__/snapshot.test.d.ts +2 -0
  29. package/dist/src/agent/__tests__/snapshot.test.d.ts.map +1 -0
  30. package/dist/src/agent/__tests__/snapshot.test.js +249 -0
  31. package/dist/src/agent/__tests__/snapshot.test.js.map +1 -0
  32. package/dist/src/agent/__tests__/state.test.js +19 -0
  33. package/dist/src/agent/__tests__/state.test.js.map +1 -1
  34. package/dist/src/agent/agent.d.ts +19 -4
  35. package/dist/src/agent/agent.d.ts.map +1 -1
  36. package/dist/src/agent/agent.js +104 -34
  37. package/dist/src/agent/agent.js.map +1 -1
  38. package/dist/src/agent/printer.d.ts +4 -0
  39. package/dist/src/agent/printer.d.ts.map +1 -1
  40. package/dist/src/agent/printer.js +18 -6
  41. package/dist/src/agent/printer.js.map +1 -1
  42. package/dist/src/agent/snapshot.d.ts +132 -0
  43. package/dist/src/agent/snapshot.d.ts.map +1 -0
  44. package/dist/src/agent/snapshot.js +151 -0
  45. package/dist/src/agent/snapshot.js.map +1 -0
  46. package/dist/src/agent/state.d.ts +14 -1
  47. package/dist/src/agent/state.d.ts.map +1 -1
  48. package/dist/src/agent/state.js +21 -0
  49. package/dist/src/agent/state.js.map +1 -1
  50. package/dist/src/errors.d.ts +15 -0
  51. package/dist/src/errors.d.ts.map +1 -1
  52. package/dist/src/errors.js +18 -0
  53. package/dist/src/errors.js.map +1 -1
  54. package/dist/src/hooks/__tests__/events.test.js +102 -21
  55. package/dist/src/hooks/__tests__/events.test.js.map +1 -1
  56. package/dist/src/hooks/events.d.ts +156 -22
  57. package/dist/src/hooks/events.d.ts.map +1 -1
  58. package/dist/src/hooks/events.js +158 -18
  59. package/dist/src/hooks/events.js.map +1 -1
  60. package/dist/src/hooks/index.d.ts +12 -4
  61. package/dist/src/hooks/index.d.ts.map +1 -1
  62. package/dist/src/hooks/index.js +11 -3
  63. package/dist/src/hooks/index.js.map +1 -1
  64. package/dist/src/hooks/registry.d.ts +5 -5
  65. package/dist/src/hooks/registry.d.ts.map +1 -1
  66. package/dist/src/hooks/registry.js.map +1 -1
  67. package/dist/src/hooks/types.d.ts +5 -5
  68. package/dist/src/hooks/types.d.ts.map +1 -1
  69. package/dist/src/index.d.ts +4 -2
  70. package/dist/src/index.d.ts.map +1 -1
  71. package/dist/src/index.js +4 -3
  72. package/dist/src/index.js.map +1 -1
  73. package/dist/src/models/__tests__/anthropic.test.js +31 -42
  74. package/dist/src/models/__tests__/anthropic.test.js.map +1 -1
  75. package/dist/src/models/__tests__/bedrock.test.js +70 -107
  76. package/dist/src/models/__tests__/bedrock.test.js.map +1 -1
  77. package/dist/src/models/__tests__/gemini.test.js +438 -141
  78. package/dist/src/models/__tests__/gemini.test.js.map +1 -1
  79. package/dist/src/models/__tests__/model.test.js +14 -13
  80. package/dist/src/models/__tests__/model.test.js.map +1 -1
  81. package/dist/src/models/__tests__/openai.test.js +73 -83
  82. package/dist/src/models/__tests__/openai.test.js.map +1 -1
  83. package/dist/src/models/gemini/adapters.d.ts +2 -1
  84. package/dist/src/models/gemini/adapters.d.ts.map +1 -1
  85. package/dist/src/models/gemini/adapters.js +97 -10
  86. package/dist/src/models/gemini/adapters.js.map +1 -1
  87. package/dist/src/models/gemini/model.d.ts.map +1 -1
  88. package/dist/src/models/gemini/model.js +37 -1
  89. package/dist/src/models/gemini/model.js.map +1 -1
  90. package/dist/src/models/gemini/types.d.ts +9 -1
  91. package/dist/src/models/gemini/types.d.ts.map +1 -1
  92. package/dist/src/models/model.d.ts.map +1 -1
  93. package/dist/src/models/model.js +4 -0
  94. package/dist/src/models/model.js.map +1 -1
  95. package/dist/src/models/streaming.d.ts +13 -0
  96. package/dist/src/models/streaming.d.ts.map +1 -1
  97. package/dist/src/models/streaming.js +17 -0
  98. package/dist/src/models/streaming.js.map +1 -1
  99. package/dist/src/multiagent/__tests__/nodes.test.d.ts +2 -0
  100. package/dist/src/multiagent/__tests__/nodes.test.d.ts.map +1 -0
  101. package/dist/src/multiagent/__tests__/nodes.test.js +98 -0
  102. package/dist/src/multiagent/__tests__/nodes.test.js.map +1 -0
  103. package/dist/src/multiagent/events.d.ts +24 -0
  104. package/dist/src/multiagent/events.d.ts.map +1 -0
  105. package/dist/src/multiagent/events.js +19 -0
  106. package/dist/src/multiagent/events.js.map +1 -0
  107. package/dist/src/multiagent/index.d.ts +11 -0
  108. package/dist/src/multiagent/index.d.ts.map +1 -0
  109. package/dist/src/multiagent/index.js +7 -0
  110. package/dist/src/multiagent/index.js.map +1 -0
  111. package/dist/src/multiagent/nodes.d.ts +75 -0
  112. package/dist/src/multiagent/nodes.d.ts.map +1 -0
  113. package/dist/src/multiagent/nodes.js +101 -0
  114. package/dist/src/multiagent/nodes.js.map +1 -0
  115. package/dist/src/multiagent/state.d.ts +55 -0
  116. package/dist/src/multiagent/state.d.ts.map +1 -0
  117. package/dist/src/multiagent/state.js +43 -0
  118. package/dist/src/multiagent/state.js.map +1 -0
  119. package/dist/src/multiagent/types.d.ts +5 -0
  120. package/dist/src/multiagent/types.d.ts.map +1 -0
  121. package/dist/src/multiagent/types.js +2 -0
  122. package/dist/src/multiagent/types.js.map +1 -0
  123. package/dist/src/registry/tool-registry.d.ts +2 -1
  124. package/dist/src/registry/tool-registry.d.ts.map +1 -1
  125. package/dist/src/registry/tool-registry.js +4 -2
  126. package/dist/src/registry/tool-registry.js.map +1 -1
  127. package/dist/src/session/__tests__/file-storage.test.node.d.ts +2 -0
  128. package/dist/src/session/__tests__/file-storage.test.node.d.ts.map +1 -0
  129. package/dist/src/session/__tests__/file-storage.test.node.js +218 -0
  130. package/dist/src/session/__tests__/file-storage.test.node.js.map +1 -0
  131. package/dist/src/session/__tests__/s3-storage.test.node.d.ts +2 -0
  132. package/dist/src/session/__tests__/s3-storage.test.node.d.ts.map +1 -0
  133. package/dist/src/session/__tests__/s3-storage.test.node.js +375 -0
  134. package/dist/src/session/__tests__/s3-storage.test.node.js.map +1 -0
  135. package/dist/src/session/__tests__/validation.test.d.ts +2 -0
  136. package/dist/src/session/__tests__/validation.test.d.ts.map +1 -0
  137. package/dist/src/session/__tests__/validation.test.js +20 -0
  138. package/dist/src/session/__tests__/validation.test.js.map +1 -0
  139. package/dist/src/session/file-storage.d.ts +79 -0
  140. package/dist/src/session/file-storage.d.ts.map +1 -0
  141. package/dist/src/session/file-storage.js +144 -0
  142. package/dist/src/session/file-storage.js.map +1 -0
  143. package/dist/src/session/index.d.ts +19 -0
  144. package/dist/src/session/index.d.ts.map +1 -0
  145. package/dist/src/session/index.js +18 -0
  146. package/dist/src/session/index.js.map +1 -0
  147. package/dist/src/session/s3-storage.d.ts +93 -0
  148. package/dist/src/session/s3-storage.d.ts.map +1 -0
  149. package/dist/src/session/s3-storage.js +150 -0
  150. package/dist/src/session/s3-storage.js.map +1 -0
  151. package/dist/src/session/storage.d.ts +91 -0
  152. package/dist/src/session/storage.d.ts.map +1 -0
  153. package/dist/src/session/storage.js +2 -0
  154. package/dist/src/session/storage.js.map +1 -0
  155. package/dist/src/session/types.d.ts +49 -0
  156. package/dist/src/session/types.d.ts.map +1 -0
  157. package/dist/src/session/types.js +2 -0
  158. package/dist/src/session/types.js.map +1 -0
  159. package/dist/src/session/validation.d.ts +10 -0
  160. package/dist/src/session/validation.d.ts.map +1 -0
  161. package/dist/src/session/validation.js +16 -0
  162. package/dist/src/session/validation.js.map +1 -0
  163. package/dist/src/structured-output/__tests__/context.test.d.ts +2 -0
  164. package/dist/src/structured-output/__tests__/context.test.d.ts.map +1 -0
  165. package/dist/src/structured-output/__tests__/context.test.js +201 -0
  166. package/dist/src/structured-output/__tests__/context.test.js.map +1 -0
  167. package/dist/src/structured-output/__tests__/exceptions.test.d.ts +2 -0
  168. package/dist/src/structured-output/__tests__/exceptions.test.d.ts.map +1 -0
  169. package/dist/src/structured-output/__tests__/exceptions.test.js +103 -0
  170. package/dist/src/structured-output/__tests__/exceptions.test.js.map +1 -0
  171. package/dist/src/structured-output/__tests__/tool.test.d.ts +2 -0
  172. package/dist/src/structured-output/__tests__/tool.test.d.ts.map +1 -0
  173. package/dist/src/structured-output/__tests__/tool.test.js +256 -0
  174. package/dist/src/structured-output/__tests__/tool.test.js.map +1 -0
  175. package/dist/src/structured-output/__tests__/utils.test.d.ts +2 -0
  176. package/dist/src/structured-output/__tests__/utils.test.d.ts.map +1 -0
  177. package/dist/src/structured-output/__tests__/utils.test.js +183 -0
  178. package/dist/src/structured-output/__tests__/utils.test.js.map +1 -0
  179. package/dist/src/structured-output/context.d.ts +91 -0
  180. package/dist/src/structured-output/context.d.ts.map +1 -0
  181. package/dist/src/structured-output/context.js +112 -0
  182. package/dist/src/structured-output/context.js.map +1 -0
  183. package/dist/src/structured-output/exceptions.d.ts +18 -0
  184. package/dist/src/structured-output/exceptions.d.ts.map +1 -0
  185. package/dist/src/structured-output/exceptions.js +28 -0
  186. package/dist/src/structured-output/exceptions.js.map +1 -0
  187. package/dist/src/structured-output/tool.d.ts +33 -0
  188. package/dist/src/structured-output/tool.d.ts.map +1 -0
  189. package/dist/src/structured-output/tool.js +73 -0
  190. package/dist/src/structured-output/tool.js.map +1 -0
  191. package/dist/src/structured-output/utils.d.ts +23 -0
  192. package/dist/src/structured-output/utils.d.ts.map +1 -0
  193. package/dist/src/structured-output/utils.js +104 -0
  194. package/dist/src/structured-output/utils.js.map +1 -0
  195. package/dist/src/tools/zod-tool.d.ts.map +1 -1
  196. package/dist/src/tools/zod-tool.js +2 -5
  197. package/dist/src/tools/zod-tool.js.map +1 -1
  198. package/dist/src/tsconfig.tsbuildinfo +1 -1
  199. package/dist/src/types/__tests__/media.test.js +216 -1
  200. package/dist/src/types/__tests__/media.test.js.map +1 -1
  201. package/dist/src/types/__tests__/messages.test.js +193 -4
  202. package/dist/src/types/__tests__/messages.test.js.map +1 -1
  203. package/dist/src/types/agent.d.ts +13 -7
  204. package/dist/src/types/agent.d.ts.map +1 -1
  205. package/dist/src/types/agent.js +8 -1
  206. package/dist/src/types/agent.js.map +1 -1
  207. package/dist/src/types/json.d.ts +61 -0
  208. package/dist/src/types/json.d.ts.map +1 -1
  209. package/dist/src/types/json.js +24 -0
  210. package/dist/src/types/json.js.map +1 -1
  211. package/dist/src/types/media.d.ts +84 -4
  212. package/dist/src/types/media.d.ts.map +1 -1
  213. package/dist/src/types/media.js +194 -0
  214. package/dist/src/types/media.js.map +1 -1
  215. package/dist/src/types/messages.d.ts +158 -9
  216. package/dist/src/types/messages.d.ts.map +1 -1
  217. package/dist/src/types/messages.js +242 -7
  218. package/dist/src/types/messages.js.map +1 -1
  219. package/dist/src/types/serializable.d.ts +31 -0
  220. package/dist/src/types/serializable.d.ts.map +1 -0
  221. package/dist/src/types/serializable.js +19 -0
  222. package/dist/src/types/serializable.js.map +1 -0
  223. package/dist/src/utils/zod.d.ts +11 -0
  224. package/dist/src/utils/zod.d.ts.map +1 -0
  225. package/dist/src/utils/zod.js +14 -0
  226. package/dist/src/utils/zod.js.map +1 -0
  227. package/dist/src/vended-tools/bash/__tests__/bash.test.node.d.ts +2 -0
  228. package/dist/src/vended-tools/bash/__tests__/bash.test.node.d.ts.map +1 -0
  229. package/dist/src/vended-tools/bash/__tests__/{bash.test.js → bash.test.node.js} +3 -4
  230. package/dist/src/vended-tools/bash/__tests__/bash.test.node.js.map +1 -0
  231. package/dist/src/vended-tools/file_editor/__tests__/file-editor.test.node.d.ts +2 -0
  232. package/dist/src/vended-tools/file_editor/__tests__/file-editor.test.node.d.ts.map +1 -0
  233. package/dist/src/vended-tools/file_editor/__tests__/{file-editor.test.js → file-editor.test.node.js} +1 -1
  234. package/dist/src/vended-tools/file_editor/__tests__/file-editor.test.node.js.map +1 -0
  235. package/package.json +7 -2
  236. package/dist/src/vended-tools/bash/__tests__/bash.test.d.ts +0 -2
  237. package/dist/src/vended-tools/bash/__tests__/bash.test.d.ts.map +0 -1
  238. package/dist/src/vended-tools/bash/__tests__/bash.test.js.map +0 -1
  239. package/dist/src/vended-tools/file_editor/__tests__/file-editor.test.d.ts +0 -2
  240. package/dist/src/vended-tools/file_editor/__tests__/file-editor.test.d.ts.map +0 -1
  241. package/dist/src/vended-tools/file_editor/__tests__/file-editor.test.js.map +0 -1
@@ -4,6 +4,7 @@ import { isNode } from '../../__fixtures__/environment.js';
4
4
  import { OpenAIModel } from '../openai.js';
5
5
  import { ContextWindowOverflowError, ModelThrottledError } from '../../errors.js';
6
6
  import { collectIterator } from '../../__fixtures__/model-test-helpers.js';
7
+ import { Message, TextBlock, ToolUseBlock, ToolResultBlock, GuardContentBlock } from '../../types/messages.js';
7
8
  /**
8
9
  * Helper to create a mock OpenAI client with streaming support
9
10
  */
@@ -204,7 +205,7 @@ describe('OpenAIModel', () => {
204
205
  };
205
206
  });
206
207
  const provider = new OpenAIModel({ modelId: 'gpt-4o', client: mockClient });
207
- const messages = [{ type: 'message', role: 'user', content: [{ type: 'textBlock', text: 'Hi' }] }];
208
+ const messages = [new Message({ role: 'user', content: [new TextBlock('Hi')] })];
208
209
  // System prompt that's only whitespace should not be sent
209
210
  const events = await collectIterator(provider.stream(messages, { systemPrompt: ' ' }));
210
211
  // Should still get valid events
@@ -218,7 +219,7 @@ describe('OpenAIModel', () => {
218
219
  client: mockClient,
219
220
  params: { n: 2 },
220
221
  });
221
- const messages = [{ type: 'message', role: 'user', content: [{ type: 'textBlock', text: 'Hi' }] }];
222
+ const messages = [new Message({ role: 'user', content: [new TextBlock('Hi')] })];
222
223
  await expect(async () => {
223
224
  for await (const _ of provider.stream(messages)) {
224
225
  // Should not reach here
@@ -228,7 +229,7 @@ describe('OpenAIModel', () => {
228
229
  it('throws error for tool spec without name or description', async () => {
229
230
  const mockClient = createMockClient(async function* () { });
230
231
  const provider = new OpenAIModel({ modelId: 'gpt-4o', client: mockClient });
231
- const messages = [{ type: 'message', role: 'user', content: [{ type: 'textBlock', text: 'Hi' }] }];
232
+ const messages = [new Message({ role: 'user', content: [new TextBlock('Hi')] })];
232
233
  await expect(async () => {
233
234
  for await (const _ of provider.stream(messages, {
234
235
  toolSpecs: [{ name: '', description: 'test', inputSchema: {} }],
@@ -241,11 +242,16 @@ describe('OpenAIModel', () => {
241
242
  const mockClient = createMockClient(async function* () { });
242
243
  const provider = new OpenAIModel({ modelId: 'gpt-4o', client: mockClient });
243
244
  const messages = [
244
- {
245
- type: 'message',
245
+ new Message({
246
246
  role: 'user',
247
- content: [{ type: 'toolResultBlock', toolUseId: 'tool-123', status: 'success', content: [] }],
248
- },
247
+ content: [
248
+ new ToolResultBlock({
249
+ toolUseId: 'tool-123',
250
+ status: 'success',
251
+ content: [],
252
+ }),
253
+ ],
254
+ }),
249
255
  ];
250
256
  await expect(async () => {
251
257
  for await (const _ of provider.stream(messages)) {
@@ -264,31 +270,27 @@ describe('OpenAIModel', () => {
264
270
  });
265
271
  const provider = new OpenAIModel({ modelId: 'gpt-4o', client: mockClient });
266
272
  const messages = [
267
- { type: 'message', role: 'user', content: [{ type: 'textBlock', text: 'Run tool' }] },
268
- {
269
- type: 'message',
273
+ new Message({ role: 'user', content: [new TextBlock('Run tool')] }),
274
+ new Message({
270
275
  role: 'assistant',
271
276
  content: [
272
- {
273
- type: 'toolUseBlock',
277
+ new ToolUseBlock({
274
278
  name: 'calculator',
275
279
  toolUseId: 'tool-123',
276
280
  input: { expr: 'invalid' },
277
- },
281
+ }),
278
282
  ],
279
- },
280
- {
281
- type: 'message',
283
+ }),
284
+ new Message({
282
285
  role: 'user',
283
286
  content: [
284
- {
285
- type: 'toolResultBlock',
287
+ new ToolResultBlock({
286
288
  toolUseId: 'tool-123',
287
289
  status: 'error',
288
- content: [{ type: 'textBlock', text: 'Division by zero' }],
289
- },
290
+ content: [new TextBlock('Division by zero')],
291
+ }),
290
292
  ],
291
- },
293
+ }),
292
294
  ];
293
295
  // Should not throw - error status is handled by prepending [ERROR]
294
296
  const events = await collectIterator(provider.stream(messages));
@@ -302,19 +304,17 @@ describe('OpenAIModel', () => {
302
304
  const circular = { a: 1 };
303
305
  circular.self = circular;
304
306
  const messages = [
305
- { type: 'message', role: 'user', content: [{ type: 'textBlock', text: 'Hi' }] },
306
- {
307
- type: 'message',
307
+ new Message({ role: 'user', content: [new TextBlock('Hi')] }),
308
+ new Message({
308
309
  role: 'assistant',
309
310
  content: [
310
- {
311
- type: 'toolUseBlock',
311
+ new ToolUseBlock({
312
312
  name: 'test',
313
313
  toolUseId: 'tool-1',
314
314
  input: circular,
315
- },
315
+ }),
316
316
  ],
317
- },
317
+ }),
318
318
  ];
319
319
  await expect(async () => {
320
320
  for await (const _ of provider.stream(messages)) {
@@ -340,7 +340,7 @@ describe('OpenAIModel', () => {
340
340
  };
341
341
  });
342
342
  const provider = new OpenAIModel({ modelId: 'gpt-4o', client: mockClient });
343
- const messages = [{ type: 'message', role: 'user', content: [{ type: 'textBlock', text: 'Hi' }] }];
343
+ const messages = [new Message({ role: 'user', content: [new TextBlock('Hi')] })];
344
344
  const events = await collectIterator(provider.stream(messages));
345
345
  // Now includes complete content block lifecycle: start, deltas, stop
346
346
  expect(events).toHaveLength(6);
@@ -376,7 +376,7 @@ describe('OpenAIModel', () => {
376
376
  };
377
377
  });
378
378
  const provider = new OpenAIModel({ modelId: 'gpt-4o', client: mockClient });
379
- const messages = [{ type: 'message', role: 'user', content: [{ type: 'textBlock', text: 'Hi' }] }];
379
+ const messages = [new Message({ role: 'user', content: [new TextBlock('Hi')] })];
380
380
  const events = await collectIterator(provider.stream(messages));
381
381
  const metadataEvent = events.find((e) => e.type === 'modelMetadataEvent');
382
382
  expect(metadataEvent).toBeDefined();
@@ -403,7 +403,7 @@ describe('OpenAIModel', () => {
403
403
  };
404
404
  });
405
405
  const provider = new OpenAIModel({ modelId: 'gpt-4o', client: mockClient });
406
- const messages = [{ type: 'message', role: 'user', content: [{ type: 'textBlock', text: 'Hi' }] }];
406
+ const messages = [new Message({ role: 'user', content: [new TextBlock('Hi')] })];
407
407
  const events = await collectIterator(provider.stream(messages));
408
408
  const metadataEvent = events.find((e) => e.type === 'modelMetadataEvent');
409
409
  expect(metadataEvent).toBeDefined();
@@ -432,7 +432,7 @@ describe('OpenAIModel', () => {
432
432
  };
433
433
  });
434
434
  const provider = new OpenAIModel({ modelId: 'gpt-4o', client: mockClient });
435
- const messages = [{ type: 'message', role: 'user', content: [{ type: 'textBlock', text: 'Hi' }] }];
435
+ const messages = [new Message({ role: 'user', content: [new TextBlock('Hi')] })];
436
436
  const events = await collectIterator(provider.stream(messages));
437
437
  // Should not emit event for empty content
438
438
  const contentEvents = events.filter((e) => e.type === 'modelContentBlockDeltaEvent');
@@ -452,7 +452,7 @@ describe('OpenAIModel', () => {
452
452
  };
453
453
  });
454
454
  const provider = new OpenAIModel({ modelId: 'gpt-4o', client: mockClient });
455
- const messages = [{ type: 'message', role: 'user', content: [{ type: 'textBlock', text: 'Hi' }] }];
455
+ const messages = [new Message({ role: 'user', content: [new TextBlock('Hi')] })];
456
456
  // Suppress console.warn for this test
457
457
  vi.spyOn(console, 'warn').mockImplementation(() => { });
458
458
  const events = await collectIterator(provider.stream(messages));
@@ -509,9 +509,7 @@ describe('OpenAIModel', () => {
509
509
  };
510
510
  });
511
511
  const provider = new OpenAIModel({ modelId: 'gpt-4o', client: mockClient });
512
- const messages = [
513
- { type: 'message', role: 'user', content: [{ type: 'textBlock', text: 'Calculate 2+2' }] },
514
- ];
512
+ const messages = [new Message({ role: 'user', content: [new TextBlock('Calculate 2+2')] })];
515
513
  const events = await collectIterator(provider.stream(messages));
516
514
  // Verify key events in sequence
517
515
  expect(events[0]).toEqual({ type: 'modelMessageStartEvent', role: 'assistant' });
@@ -586,7 +584,7 @@ describe('OpenAIModel', () => {
586
584
  };
587
585
  });
588
586
  const provider = new OpenAIModel({ modelId: 'gpt-4o', client: mockClient });
589
- const messages = [{ type: 'message', role: 'user', content: [{ type: 'textBlock', text: 'Hi' }] }];
587
+ const messages = [new Message({ role: 'user', content: [new TextBlock('Hi')] })];
590
588
  const events = await collectIterator(provider.stream(messages));
591
589
  // Should emit stop events for both tool calls
592
590
  const stopEvents = events.filter((e) => e.type === 'modelContentBlockStopEvent');
@@ -621,7 +619,7 @@ describe('OpenAIModel', () => {
621
619
  };
622
620
  });
623
621
  const provider = new OpenAIModel({ modelId: 'gpt-4o', client: mockClient });
624
- const messages = [{ type: 'message', role: 'user', content: [{ type: 'textBlock', text: 'Hi' }] }];
622
+ const messages = [new Message({ role: 'user', content: [new TextBlock('Hi')] })];
625
623
  // Suppress console.warn for this test
626
624
  vi.spyOn(console, 'warn').mockImplementation(() => { });
627
625
  const events = await collectIterator(provider.stream(messages));
@@ -661,7 +659,7 @@ describe('OpenAIModel', () => {
661
659
  yield { choices: [{ finish_reason: 'tool_calls', delta: {}, index: 0 }] };
662
660
  });
663
661
  const provider = new OpenAIModel({ modelId: 'gpt-4o', client: mockClient });
664
- const messages = [{ type: 'message', role: 'user', content: [{ type: 'textBlock', text: 'Hi' }] }];
662
+ const messages = [new Message({ role: 'user', content: [new TextBlock('Hi')] })];
665
663
  const events = await collectIterator(provider.stream(messages));
666
664
  // Extract and concatenate all tool input deltas
667
665
  const inputDeltas = events
@@ -699,9 +697,7 @@ describe('OpenAIModel', () => {
699
697
  yield { choices: [{ finish_reason: 'tool_calls', delta: {}, index: 0 }] };
700
698
  });
701
699
  const provider = new OpenAIModel({ modelId: 'gpt-4o', client: mockClient });
702
- const messages = [
703
- { type: 'message', role: 'user', content: [{ type: 'textBlock', text: 'Calculate 2+2' }] },
704
- ];
700
+ const messages = [new Message({ role: 'user', content: [new TextBlock('Calculate 2+2')] })];
705
701
  const events = await collectIterator(provider.stream(messages));
706
702
  // Should have text deltas followed by tool events
707
703
  expect(events[0]?.type).toBe('modelMessageStartEvent');
@@ -737,7 +733,7 @@ describe('OpenAIModel', () => {
737
733
  };
738
734
  });
739
735
  const provider = new OpenAIModel({ modelId: 'gpt-4o', client: mockClient });
740
- const messages = [{ type: 'message', role: 'user', content: [{ type: 'textBlock', text: 'Hi' }] }];
736
+ const messages = [new Message({ role: 'user', content: [new TextBlock('Hi')] })];
741
737
  const events = await collectIterator(provider.stream(messages));
742
738
  const stopEvent = events.find((e) => e.type === 'modelMessageStopEvent');
743
739
  expect(stopEvent).toBeDefined();
@@ -754,7 +750,7 @@ describe('OpenAIModel', () => {
754
750
  };
755
751
  });
756
752
  const provider = new OpenAIModel({ modelId: 'gpt-4o', client: mockClient });
757
- const messages = [{ type: 'message', role: 'user', content: [{ type: 'textBlock', text: 'Hi' }] }];
753
+ const messages = [new Message({ role: 'user', content: [new TextBlock('Hi')] })];
758
754
  const events = await collectIterator(provider.stream(messages));
759
755
  // Should convert unknown stop reason to camelCase
760
756
  const stopEvent = events.find((e) => e.type === 'modelMessageStopEvent');
@@ -789,7 +785,7 @@ describe('OpenAIModel', () => {
789
785
  temperature: 0.7,
790
786
  maxTokens: 1000,
791
787
  });
792
- const messages = [{ type: 'message', role: 'user', content: [{ type: 'textBlock', text: 'Hi' }] }];
788
+ const messages = [new Message({ role: 'user', content: [new TextBlock('Hi')] })];
793
789
  const toolSpecs = [
794
790
  {
795
791
  name: 'calculator',
@@ -850,7 +846,7 @@ describe('OpenAIModel', () => {
850
846
  const captured = { request: null };
851
847
  const mockClient = createMockClientWithCapture(captured);
852
848
  const provider = new OpenAIModel({ modelId: 'gpt-4o', client: mockClient });
853
- const messages = [{ type: 'message', role: 'user', content: [{ type: 'textBlock', text: 'Hello' }] }];
849
+ const messages = [new Message({ role: 'user', content: [new TextBlock('Hello')] })];
854
850
  await collectIterator(provider.stream(messages, {
855
851
  systemPrompt: [
856
852
  { type: 'textBlock', text: 'You are a helpful assistant' },
@@ -868,7 +864,7 @@ describe('OpenAIModel', () => {
868
864
  const captured = { request: null };
869
865
  const mockClient = createMockClientWithCapture(captured);
870
866
  const provider = new OpenAIModel({ modelId: 'gpt-4o', client: mockClient });
871
- const messages = [{ type: 'message', role: 'user', content: [{ type: 'textBlock', text: 'Hello' }] }];
867
+ const messages = [new Message({ role: 'user', content: [new TextBlock('Hello')] })];
872
868
  collectIterator(provider.stream(messages, {
873
869
  systemPrompt: [
874
870
  { type: 'textBlock', text: 'You are a helpful assistant' },
@@ -890,7 +886,7 @@ describe('OpenAIModel', () => {
890
886
  const captured = { request: null };
891
887
  const mockClient = createMockClientWithCapture(captured);
892
888
  const provider = new OpenAIModel({ modelId: 'gpt-4o', client: mockClient });
893
- const messages = [{ type: 'message', role: 'user', content: [{ type: 'textBlock', text: 'Hello' }] }];
889
+ const messages = [new Message({ role: 'user', content: [new TextBlock('Hello')] })];
894
890
  await collectIterator(provider.stream(messages, {
895
891
  systemPrompt: [],
896
892
  }));
@@ -902,7 +898,7 @@ describe('OpenAIModel', () => {
902
898
  const captured = { request: null };
903
899
  const mockClient = createMockClientWithCapture(captured);
904
900
  const provider = new OpenAIModel({ modelId: 'gpt-4o', client: mockClient });
905
- const messages = [{ type: 'message', role: 'user', content: [{ type: 'textBlock', text: 'Hello' }] }];
901
+ const messages = [new Message({ role: 'user', content: [new TextBlock('Hello')] })];
906
902
  await collectIterator(provider.stream(messages, {
907
903
  systemPrompt: [{ type: 'textBlock', text: 'You are a helpful assistant' }],
908
904
  }));
@@ -917,7 +913,7 @@ describe('OpenAIModel', () => {
917
913
  const captured = { request: null };
918
914
  const mockClient = createMockClientWithCapture(captured);
919
915
  const provider = new OpenAIModel({ modelId: 'gpt-4o', client: mockClient });
920
- const messages = [{ type: 'message', role: 'user', content: [{ type: 'textBlock', text: 'Hello' }] }];
916
+ const messages = [new Message({ role: 'user', content: [new TextBlock('Hello')] })];
921
917
  await collectIterator(provider.stream(messages, {
922
918
  systemPrompt: [
923
919
  { type: 'textBlock', text: 'You are a helpful assistant' },
@@ -945,7 +941,7 @@ describe('OpenAIModel', () => {
945
941
  const captured = { request: null };
946
942
  const mockClient = createMockClientWithCapture(captured);
947
943
  const provider = new OpenAIModel({ modelId: 'gpt-4o', client: mockClient });
948
- const messages = [{ type: 'message', role: 'user', content: [{ type: 'textBlock', text: 'Hello' }] }];
944
+ const messages = [new Message({ role: 'user', content: [new TextBlock('Hello')] })];
949
945
  await collectIterator(provider.stream(messages, {
950
946
  systemPrompt: [
951
947
  { type: 'textBlock', text: 'First text' },
@@ -974,7 +970,7 @@ describe('OpenAIModel', () => {
974
970
  const captured = { request: null };
975
971
  const mockClient = createMockClientWithCapture(captured);
976
972
  const provider = new OpenAIModel({ modelId: 'gpt-4o', client: mockClient });
977
- const messages = [{ type: 'message', role: 'user', content: [{ type: 'textBlock', text: 'Hello' }] }];
973
+ const messages = [new Message({ role: 'user', content: [new TextBlock('Hello')] })];
978
974
  await collectIterator(provider.stream(messages, {
979
975
  systemPrompt: [
980
976
  {
@@ -1017,21 +1013,19 @@ describe('OpenAIModel', () => {
1017
1013
  const mockClient = createMockClientWithCapture(captured);
1018
1014
  const provider = new OpenAIModel({ modelId: 'gpt-4o', client: mockClient });
1019
1015
  const messages = [
1020
- {
1021
- type: 'message',
1016
+ new Message({
1022
1017
  role: 'user',
1023
1018
  content: [
1024
- { type: 'textBlock', text: 'Verify this:' },
1025
- {
1026
- type: 'guardContentBlock',
1019
+ new TextBlock('Verify this:'),
1020
+ new GuardContentBlock({
1027
1021
  text: {
1028
1022
  qualifiers: ['grounding_source'],
1029
1023
  text: 'Guard content',
1030
1024
  },
1031
- },
1032
- { type: 'textBlock', text: 'Is it correct?' },
1025
+ }),
1026
+ new TextBlock('Is it correct?'),
1033
1027
  ],
1034
- },
1028
+ }),
1035
1029
  ];
1036
1030
  await collectIterator(provider.stream(messages));
1037
1031
  // Verify warning was logged
@@ -1056,20 +1050,18 @@ describe('OpenAIModel', () => {
1056
1050
  const provider = new OpenAIModel({ modelId: 'gpt-4o', client: mockClient });
1057
1051
  const imageBytes = new Uint8Array([1, 2, 3, 4]);
1058
1052
  const messages = [
1059
- {
1060
- type: 'message',
1053
+ new Message({
1061
1054
  role: 'user',
1062
1055
  content: [
1063
- { type: 'textBlock', text: 'Check this image:' },
1064
- {
1065
- type: 'guardContentBlock',
1056
+ new TextBlock('Check this image:'),
1057
+ new GuardContentBlock({
1066
1058
  image: {
1067
1059
  format: 'jpeg',
1068
1060
  source: { bytes: imageBytes },
1069
1061
  },
1070
- },
1062
+ }),
1071
1063
  ],
1072
- },
1064
+ }),
1073
1065
  ];
1074
1066
  await collectIterator(provider.stream(messages));
1075
1067
  // Verify warning was logged
@@ -1087,19 +1079,17 @@ describe('OpenAIModel', () => {
1087
1079
  const mockClient = createMockClientWithCapture(captured);
1088
1080
  const provider = new OpenAIModel({ modelId: 'gpt-4o', client: mockClient });
1089
1081
  const messages = [
1090
- {
1091
- type: 'message',
1082
+ new Message({
1092
1083
  role: 'user',
1093
1084
  content: [
1094
- {
1095
- type: 'guardContentBlock',
1085
+ new GuardContentBlock({
1096
1086
  text: {
1097
1087
  qualifiers: ['guard_content'],
1098
1088
  text: 'Only guard content',
1099
1089
  },
1100
- },
1090
+ }),
1101
1091
  ],
1102
- },
1092
+ }),
1103
1093
  ];
1104
1094
  await collectIterator(provider.stream(messages));
1105
1095
  // Verify warning was logged
@@ -1124,7 +1114,7 @@ describe('OpenAIModel', () => {
1124
1114
  },
1125
1115
  };
1126
1116
  const provider = new OpenAIModel({ modelId: 'gpt-4o', client: mockClient });
1127
- const messages = [{ type: 'message', role: 'user', content: [{ type: 'textBlock', text: 'Hi' }] }];
1117
+ const messages = [new Message({ role: 'user', content: [new TextBlock('Hi')] })];
1128
1118
  await expect(async () => {
1129
1119
  for await (const _ of provider.stream(messages)) {
1130
1120
  // Should not reach here
@@ -1142,7 +1132,7 @@ describe('OpenAIModel', () => {
1142
1132
  },
1143
1133
  };
1144
1134
  const provider = new OpenAIModel({ modelId: 'gpt-4o', client: mockClient });
1145
- const messages = [{ type: 'message', role: 'user', content: [{ type: 'textBlock', text: 'Hi' }] }];
1135
+ const messages = [new Message({ role: 'user', content: [new TextBlock('Hi')] })];
1146
1136
  await expect(async () => {
1147
1137
  for await (const _ of provider.stream(messages)) {
1148
1138
  // Should not reach here
@@ -1167,7 +1157,7 @@ describe('OpenAIModel', () => {
1167
1157
  },
1168
1158
  };
1169
1159
  const provider = new OpenAIModel({ modelId: 'gpt-4o', client: mockClient });
1170
- const messages = [{ type: 'message', role: 'user', content: [{ type: 'textBlock', text: 'Hi' }] }];
1160
+ const messages = [new Message({ role: 'user', content: [new TextBlock('Hi')] })];
1171
1161
  await expect(async () => {
1172
1162
  for await (const _ of provider.stream(messages)) {
1173
1163
  // Should not reach here
@@ -1185,7 +1175,7 @@ describe('OpenAIModel', () => {
1185
1175
  },
1186
1176
  };
1187
1177
  const provider = new OpenAIModel({ modelId: 'gpt-4o', client: mockClient });
1188
- const messages = [{ type: 'message', role: 'user', content: [{ type: 'textBlock', text: 'Hi' }] }];
1178
+ const messages = [new Message({ role: 'user', content: [new TextBlock('Hi')] })];
1189
1179
  await expect(async () => {
1190
1180
  for await (const _ of provider.stream(messages)) {
1191
1181
  // Should not reach here
@@ -1200,7 +1190,7 @@ describe('OpenAIModel', () => {
1200
1190
  throw new Error('Network connection lost');
1201
1191
  });
1202
1192
  const provider = new OpenAIModel({ modelId: 'gpt-4o', client: mockClient });
1203
- const messages = [{ type: 'message', role: 'user', content: [{ type: 'textBlock', text: 'Hi' }] }];
1193
+ const messages = [new Message({ role: 'user', content: [new TextBlock('Hi')] })];
1204
1194
  await expect(async () => {
1205
1195
  for await (const _ of provider.stream(messages)) {
1206
1196
  // Stream will be interrupted
@@ -1220,7 +1210,7 @@ describe('OpenAIModel', () => {
1220
1210
  },
1221
1211
  };
1222
1212
  const provider = new OpenAIModel({ modelId: 'gpt-4o', client: mockClient });
1223
- const messages = [{ type: 'message', role: 'user', content: [{ type: 'textBlock', text: 'Hi' }] }];
1213
+ const messages = [new Message({ role: 'user', content: [new TextBlock('Hi')] })];
1224
1214
  await expect(async () => {
1225
1215
  for await (const _ of provider.stream(messages)) {
1226
1216
  // Should not reach here
@@ -1240,7 +1230,7 @@ describe('OpenAIModel', () => {
1240
1230
  },
1241
1231
  };
1242
1232
  const provider = new OpenAIModel({ modelId: 'gpt-4o', client: mockClient });
1243
- const messages = [{ type: 'message', role: 'user', content: [{ type: 'textBlock', text: 'Hi' }] }];
1233
+ const messages = [new Message({ role: 'user', content: [new TextBlock('Hi')] })];
1244
1234
  await expect(async () => {
1245
1235
  for await (const _ of provider.stream(messages)) {
1246
1236
  // Should not reach here
@@ -1258,7 +1248,7 @@ describe('OpenAIModel', () => {
1258
1248
  },
1259
1249
  };
1260
1250
  const provider = new OpenAIModel({ modelId: 'gpt-4o', client: mockClient });
1261
- const messages = [{ type: 'message', role: 'user', content: [{ type: 'textBlock', text: 'Hi' }] }];
1251
+ const messages = [new Message({ role: 'user', content: [new TextBlock('Hi')] })];
1262
1252
  await expect(async () => {
1263
1253
  for await (const _ of provider.stream(messages)) {
1264
1254
  // Should not reach here
@@ -1276,7 +1266,7 @@ describe('OpenAIModel', () => {
1276
1266
  },
1277
1267
  };
1278
1268
  const provider = new OpenAIModel({ modelId: 'gpt-4o', client: mockClient });
1279
- const messages = [{ type: 'message', role: 'user', content: [{ type: 'textBlock', text: 'Hi' }] }];
1269
+ const messages = [new Message({ role: 'user', content: [new TextBlock('Hi')] })];
1280
1270
  await expect(async () => {
1281
1271
  for await (const _ of provider.stream(messages)) {
1282
1272
  // Should not reach here
@@ -1296,7 +1286,7 @@ describe('OpenAIModel', () => {
1296
1286
  },
1297
1287
  };
1298
1288
  const provider = new OpenAIModel({ modelId: 'gpt-4o', client: mockClient });
1299
- const messages = [{ type: 'message', role: 'user', content: [{ type: 'textBlock', text: 'Hi' }] }];
1289
+ const messages = [new Message({ role: 'user', content: [new TextBlock('Hi')] })];
1300
1290
  try {
1301
1291
  for await (const _ of provider.stream(messages)) {
1302
1292
  // Should not reach here