@@ -6,6 +6,7 @@ import type { Message } from '@strands-agents/sdk'
66import type { ToolSpec } from '@strands-agents/sdk'
77import type { ModelStreamEvent } from '@strands-agents/sdk'
88import { ValidationException } from '@aws-sdk/client-bedrock-runtime'
9+ import { fail } from 'assert/strict'
910
1011/**
1112 * Helper function to collect all events from a stream.
@@ -30,6 +31,104 @@ try {
3031 console . log ( '⏭️ AWS credentials not available - integration tests will be skipped' )
3132}
3233
34+ describe . skipIf ( ! hasCredentials ) ( 'BedrockModel Integration Tests (Non-Streaming)' , ( ) => {
35+ it ( 'gets a simple text response' , async ( ) => {
36+ const provider = new BedrockModel ( {
37+ stream : false ,
38+ maxTokens : 100 ,
39+ } )
40+
41+ const messages : Message [ ] = [
42+ {
43+ role : 'user' ,
44+ content : [ { type : 'textBlock' , text : 'Say hello in exactly one word.' } ] ,
45+ } ,
46+ ]
47+
48+ const events = await collectEvents ( provider . stream ( messages ) )
49+
50+ expect ( events [ 0 ] ?. type ) . toBe ( 'modelMessageStartEvent' )
51+ expect ( events [ 1 ] ?. type ) . toBe ( 'modelContentBlockStartEvent' )
52+ expect ( events [ 2 ] ?. type ) . toBe ( 'modelContentBlockDeltaEvent' )
53+ expect ( events [ 3 ] ?. type ) . toBe ( 'modelContentBlockStopEvent' )
54+ expect ( events [ 4 ] ?. type ) . toBe ( 'modelMessageStopEvent' )
55+ expect ( events [ 5 ] ?. type ) . toBe ( 'modelMetadataEvent' )
56+
57+ let responseText = ''
58+ for ( const event of events ) {
59+ if ( event . type === 'modelContentBlockDeltaEvent' && event . delta . type === 'textDelta' ) {
60+ responseText += event . delta . text
61+ }
62+ }
63+ expect ( responseText . trim ( ) . toUpperCase ( ) ) . toContain ( 'HELLO' )
64+
65+ const stopEvent = events . find ( ( e ) => e . type === 'modelMessageStopEvent' )
66+ expect ( stopEvent ?. stopReason ) . toBe ( 'endTurn' )
67+
68+ const metadataEvent = events . find ( ( e ) => e . type === 'modelMetadataEvent' )
69+ if ( metadataEvent ?. type === 'modelMetadataEvent' ) {
70+ expect ( metadataEvent . usage ?. outputTokens ) . toBeGreaterThan ( 0 )
71+ } else {
72+ fail ( 'Metadata event not found' )
73+ }
74+ } )
75+
76+ it ( 'requests tool use when appropriate' , async ( ) => {
77+ const provider = new BedrockModel ( {
78+ stream : false ,
79+ maxTokens : 200 ,
80+ } )
81+
82+ const calculatorTool : ToolSpec = {
83+ name : 'calculator' ,
84+ description : 'Performs basic arithmetic operations' ,
85+ inputSchema : {
86+ type : 'object' ,
87+ properties : {
88+ operation : { type : 'string' , enum : [ 'add' , 'subtract' , 'multiply' , 'divide' ] } ,
89+ a : { type : 'number' } ,
90+ b : { type : 'number' } ,
91+ } ,
92+ required : [ 'operation' , 'a' , 'b' ] ,
93+ } ,
94+ }
95+
96+ const messages : Message [ ] = [
97+ {
98+ role : 'user' ,
99+ content : [ { type : 'textBlock' , text : 'What is 15 plus 27?' } ] ,
100+ } ,
101+ ]
102+
103+ const events = await collectEvents ( provider . stream ( messages , { toolSpecs : [ calculatorTool ] } ) )
104+
105+ const startEvent = events . find ( ( e ) => e . type === 'modelContentBlockStartEvent' )
106+ expect ( startEvent ) . toBeDefined ( )
107+
108+ if ( startEvent ?. type === 'modelContentBlockStartEvent' ) {
109+ expect ( startEvent . start ?. type ) . toBe ( 'toolUseStart' )
110+ expect ( startEvent . start ?. name ) . toBe ( 'calculator' )
111+ } else {
112+ fail ( 'Content block start event not found' )
113+ }
114+
115+ const deltaEvent = events . find ( ( e ) => e . type === 'modelContentBlockDeltaEvent' )
116+ expect ( deltaEvent ) . toBeDefined ( )
117+
118+ if ( deltaEvent ?. type === 'modelContentBlockDeltaEvent' && deltaEvent . delta . type === 'toolUseInputDelta' ) {
119+ const input = JSON . parse ( deltaEvent . delta . input )
120+ expect ( input . operation ) . toBe ( 'add' )
121+ expect ( input . a ) . toBe ( 15 )
122+ expect ( input . b ) . toBe ( 27 )
123+ } else {
124+ fail ( 'Tool use input delta event not found' )
125+ }
126+
127+ const stopEvent = events . find ( ( e ) => e . type === 'modelMessageStopEvent' )
128+ expect ( stopEvent ?. stopReason ) . toBe ( 'toolUse' )
129+ } )
130+ } )
131+
33132describe . skipIf ( ! hasCredentials ) ( 'BedrockModel Integration Tests' , ( ) => {
34133 describe ( 'Basic Streaming' , ( ) => {
35134 it . concurrent ( 'streams a simple text response' , async ( ) => {
0 commit comments