This repository was archived by the owner on Jun 3, 2026. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 103
Expand file tree
/
Copy pathagent.test.ts
More file actions
178 lines (155 loc) · 6.34 KB
/
Copy pathagent.test.ts
File metadata and controls
178 lines (155 loc) · 6.34 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
import { describe, it, expect } from 'vitest'
import { Agent, DocumentBlock, ImageBlock, Message, TextBlock, tool } from '@strands-agents/sdk'
import { BedrockModel } from '@strands-agents/sdk/bedrock'
import { notebook } from '@strands-agents/sdk/vended_tools/notebook'
import { httpRequest } from '@strands-agents/sdk/vended_tools/http_request'
import { OpenAIModel } from '@strands-agents/sdk/openai'
import { z } from 'zod'
// eslint-disable-next-line no-restricted-imports
import { collectGenerator } from '../src/__fixtures__/model-test-helpers.js'
import { shouldRunTests } from './__fixtures__/model-test-helpers.js'
import { loadFixture, shouldSkipOpenAITests } from './__fixtures__/test-helpers.js'
// Import fixtures using Vite's ?url suffix
import yellowPngUrl from './__resources__/yellow.png?url'
// Calculator tool for testing
const calculatorTool = tool({
name: 'calculator',
description: 'Performs basic arithmetic operations',
inputSchema: z.object({
operation: z.enum(['add', 'subtract', 'multiply', 'divide']),
a: z.number(),
b: z.number(),
}),
callback: async ({ operation, a, b }) => {
const ops = {
add: a + b,
subtract: a - b,
multiply: a * b,
divide: a / b,
}
return `Result: ${ops[operation]}`
},
})
// Provider configurations
const providers = [
{
name: 'BedrockModel',
skip: !(await shouldRunTests()),
createModel: () => new BedrockModel(),
},
{
name: 'OpenAIModel',
skip: shouldSkipOpenAITests(),
createModel: () => new OpenAIModel(),
},
]
describe.each(providers)('Agent with $name', ({ name, skip, createModel }) => {
describe.skipIf(skip)(`${name} Integration Tests`, () => {
describe('Basic Functionality', () => {
it('handles invocation, streaming, system prompts, and tool use', async () => {
// Test basic invocation with system prompt and tool
const agent = new Agent({
model: createModel(),
printer: false,
systemPrompt: 'Use the calculator tool to solve math problems. Respond with only the numeric result.',
tools: [calculatorTool],
})
// Test streaming with event collection
const { items, result } = await collectGenerator(agent.stream('What is 123 * 456?'))
// Verify high-level agent events are yielded
expect(items.some((item) => item.type === 'beforeInvocationEvent')).toBe(true)
// Verify result structure and stop reason
expect(result.stopReason).toBe('endTurn')
expect(result.lastMessage.role).toBe('assistant')
expect(result.lastMessage.content.length).toBeGreaterThan(0)
// Verify tool was used by checking message history
const toolUseMessage = agent.messages.find((msg) => msg.content.some((block) => block.type === 'toolUseBlock'))
expect(toolUseMessage).toBeDefined()
// Verify final response contains the result (123 * 456 = 56088)
const textContent = result.lastMessage.content.find((block) => block.type === 'textBlock')
expect(textContent).toBeDefined()
expect(textContent?.text).toMatch(/56088/)
})
})
describe('Multi-turn Conversations', () => {
it('maintains message history and conversation context', async () => {
const agent = new Agent({ model: createModel(), printer: false })
// First turn
await agent.invoke('My name is Alice')
expect(agent.messages).toHaveLength(2) // user + assistant
// Second turn
await agent.invoke('What is my name?')
expect(agent.messages).toHaveLength(4) // 2 user + 2 assistant
// Verify message ordering
expect(agent.messages[0].role).toBe('user')
expect(agent.messages[1].role).toBe('assistant')
expect(agent.messages[2].role).toBe('user')
expect(agent.messages[3].role).toBe('assistant')
// Verify conversation context is preserved
const lastMessage = agent.messages[agent.messages.length - 1]
const textContent = lastMessage.content.find((block) => block.type === 'textBlock')
expect(textContent?.text).toMatch(/Alice/i)
})
})
describe('Media Blocks', () => {
it('handles multiple media blocks in single request', async () => {
// Create document block
const docBlock = new DocumentBlock({
name: 'test-document',
format: 'txt',
source: { text: 'The document contains the word ZEBRA.' },
})
// Create image block
const imageBytes = await loadFixture(yellowPngUrl)
const imageBlock = new ImageBlock({
format: 'png',
source: { bytes: imageBytes },
})
// Initialize agent with messages array containing Message instance
// Note: Bedrock requires a text block when using documents
const agent = new Agent({
model: createModel(),
messages: [
new Message({
role: 'user',
content: [
docBlock,
imageBlock,
new TextBlock(
'I shared a document and an image. What animal is in the document and what color is the image? Answer briefly.'
),
],
}),
],
printer: false,
})
const result = await agent.invoke()
expect(result.stopReason).toBe('endTurn')
expect(result.lastMessage.role).toBe('assistant')
// Response should reference both the document content and image color
const textContent = result.lastMessage.content.find((block) => block.type === 'textBlock')
expect(textContent).toBeDefined()
expect(textContent?.text).toMatch(/zebra/i)
expect(textContent?.text).toMatch(/yellow/i)
})
})
})
it('handles tool invocation', async () => {
const agent = new Agent({
model: await createModel(),
tools: [notebook, httpRequest],
printer: false,
})
await agent.invoke('Call Open-Meteo to get the weather in NYC, and take a note of what you did')
expect(
agent.messages.some((message) =>
message.content.some((block) => block.type == 'toolUseBlock' && block.name == 'notebook')
)
).toBe(true)
expect(
agent.messages.some((message) =>
message.content.some((block) => block.type == 'toolUseBlock' && block.name == 'http_request')
)
).toBe(true)
})
})