@@ -327,6 +327,134 @@ describe("AIPex", () => {
327327 expect ( events [ 0 ] ?. type ) . toBe ( "session_created" ) ;
328328 expect ( agent . getConversationManager ( ) ) . toBe ( customManager ) ;
329329 } ) ;
330+
331+ it ( "should pass images as multimodal AgentInputItem[] to run()" , async ( ) => {
332+ vi . mocked ( run ) . mockResolvedValue (
333+ createMockRunResult ( {
334+ finalOutput : "I see a cat" ,
335+ streamEvents : [
336+ {
337+ type : "raw_model_stream_event" ,
338+ data : { type : "output_text_delta" , delta : "I see a cat" } ,
339+ } ,
340+ ] ,
341+ } ) ,
342+ ) ;
343+
344+ const agent = AIPex . create ( {
345+ instructions : "Describe images" ,
346+ model : mockModel ,
347+ } ) ;
348+
349+ const events : AgentEvent [ ] = [ ] ;
350+ for await ( const event of agent . chat ( "What is in this image?" , {
351+ images : [ { image : "data:image/png;base64,abc123" , detail : "high" } ] ,
352+ } ) ) {
353+ events . push ( event ) ;
354+ }
355+
356+ expect ( run ) . toHaveBeenCalledTimes ( 1 ) ;
357+ const runCallArgs = vi . mocked ( run ) . mock . calls [ 0 ] ! ;
358+ const input = runCallArgs [ 1 ] as Array < {
359+ type : string ;
360+ role : string ;
361+ content : Array < {
362+ type : string ;
363+ text ?: string ;
364+ image ?: string ;
365+ detail ?: string ;
366+ } > ;
367+ } > ;
368+
369+ expect ( Array . isArray ( input ) ) . toBe ( true ) ;
370+ expect ( input ) . toHaveLength ( 1 ) ;
371+ expect ( input [ 0 ] ! . role ) . toBe ( "user" ) ;
372+ expect ( input [ 0 ] ! . content ) . toHaveLength ( 2 ) ;
373+ expect ( input [ 0 ] ! . content [ 0 ] ) . toEqual ( {
374+ type : "input_text" ,
375+ text : "What is in this image?" ,
376+ } ) ;
377+ expect ( input [ 0 ] ! . content [ 1 ] ) . toEqual ( {
378+ type : "input_image" ,
379+ image : "data:image/png;base64,abc123" ,
380+ detail : "high" ,
381+ } ) ;
382+ } ) ;
383+
384+ it ( "should default image detail to 'auto' when not specified" , async ( ) => {
385+ vi . mocked ( run ) . mockResolvedValue (
386+ createMockRunResult ( { finalOutput : "OK" } ) ,
387+ ) ;
388+
389+ const agent = AIPex . create ( {
390+ instructions : "Test" ,
391+ model : mockModel ,
392+ } ) ;
393+
394+ for await ( const _ of agent . chat ( "Describe" , {
395+ images : [ { image : "https://example.com/img.png" } ] ,
396+ } ) ) {
397+ // consume
398+ }
399+
400+ const runCallArgs = vi . mocked ( run ) . mock . calls [ 0 ] ! ;
401+ const input = runCallArgs [ 1 ] as Array < {
402+ content : Array < { type : string ; detail ?: string } > ;
403+ } > ;
404+ const imagePart = input [ 0 ] ! . content [ 1 ] ! ;
405+ expect ( imagePart . detail ) . toBe ( "auto" ) ;
406+ } ) ;
407+
408+ it ( "should support multiple images in a single message" , async ( ) => {
409+ vi . mocked ( run ) . mockResolvedValue (
410+ createMockRunResult ( { finalOutput : "Two images" } ) ,
411+ ) ;
412+
413+ const agent = AIPex . create ( {
414+ instructions : "Test" ,
415+ model : mockModel ,
416+ } ) ;
417+
418+ for await ( const _ of agent . chat ( "Compare these" , {
419+ images : [
420+ { image : "img1_base64" } ,
421+ { image : "img2_base64" , detail : "low" } ,
422+ ] ,
423+ } ) ) {
424+ // consume
425+ }
426+
427+ const runCallArgs = vi . mocked ( run ) . mock . calls [ 0 ] ! ;
428+ const input = runCallArgs [ 1 ] as Array < {
429+ content : Array < { type : string ; image ?: string ; detail ?: string } > ;
430+ } > ;
431+ expect ( input [ 0 ] ! . content ) . toHaveLength ( 3 ) ;
432+ expect ( input [ 0 ] ! . content [ 0 ] ! . type ) . toBe ( "input_text" ) ;
433+ expect ( input [ 0 ] ! . content [ 1 ] ! . type ) . toBe ( "input_image" ) ;
434+ expect ( input [ 0 ] ! . content [ 1 ] ! . image ) . toBe ( "img1_base64" ) ;
435+ expect ( input [ 0 ] ! . content [ 2 ] ! . type ) . toBe ( "input_image" ) ;
436+ expect ( input [ 0 ] ! . content [ 2 ] ! . image ) . toBe ( "img2_base64" ) ;
437+ expect ( input [ 0 ] ! . content [ 2 ] ! . detail ) . toBe ( "low" ) ;
438+ } ) ;
439+
440+ it ( "should pass plain string to run() when no images provided" , async ( ) => {
441+ vi . mocked ( run ) . mockResolvedValue (
442+ createMockRunResult ( { finalOutput : "Reply" } ) ,
443+ ) ;
444+
445+ const agent = AIPex . create ( {
446+ instructions : "Test" ,
447+ model : mockModel ,
448+ } ) ;
449+
450+ for await ( const _ of agent . chat ( "Hello" ) ) {
451+ // consume
452+ }
453+
454+ const runCallArgs = vi . mocked ( run ) . mock . calls [ 0 ] ! ;
455+ expect ( typeof runCallArgs [ 1 ] ) . toBe ( "string" ) ;
456+ expect ( runCallArgs [ 1 ] ) . toBe ( "Hello" ) ;
457+ } ) ;
330458 } ) ;
331459
332460 describe ( "chat - continue conversation" , ( ) => {
0 commit comments