@@ -624,8 +624,8 @@ test("getBufferString can handle complex messages", () => {
624624 expect ( bufferString2 ) . toBe ( "AI: Hello there!" ) ;
625625
626626 const bufferString3 = getBufferString ( messageArr3 ) ;
627- // Image content should return empty string for text property
628- expect ( bufferString3 ) . toBe ( "Human: " ) ;
627+ // Image-only content should produce placeholders, not empty string
628+ expect ( bufferString3 ) . toBe ( "Human: [image][image] " ) ;
629629} ) ;
630630
631631test ( "getBufferString includes tool_calls for AI messages" , ( ) => {
@@ -700,6 +700,75 @@ test("getBufferString uses text property to avoid metadata inflation", () => {
700700 expect ( bufferString ) . not . toContain ( "additional_kwargs" ) ;
701701} ) ;
702702
703+ test ( "getBufferString preserves non-text content block placeholders" , ( ) => {
704+ // image and image_url -> [image]
705+ const imgMsg = new HumanMessage ( {
706+ content : [
707+ { type : "image" , source : { type : "base64" , data : "abc" } } ,
708+ {
709+ type : "image_url" ,
710+ image_url : { url : "https://example.com/img.png" } ,
711+ } ,
712+ ] ,
713+ } ) ;
714+ expect ( getBufferString ( [ imgMsg ] ) ) . toBe ( "Human: [image][image]" ) ;
715+
716+ // audio and input_audio -> [audio]
717+ const audioMsg = new HumanMessage ( {
718+ content : [
719+ { type : "audio" , source : { type : "base64" , data : "abc" } } ,
720+ { type : "input_audio" , data : "abc" , format : "wav" } ,
721+ ] ,
722+ } ) ;
723+ expect ( getBufferString ( [ audioMsg ] ) ) . toBe ( "Human: [audio][audio]" ) ;
724+
725+ // video -> [video]
726+ const videoMsg = new HumanMessage ( {
727+ content : [ { type : "video" , source : { type : "base64" , data : "abc" } } ] ,
728+ } ) ;
729+ expect ( getBufferString ( [ videoMsg ] ) ) . toBe ( "Human: [video]" ) ;
730+
731+ // file -> [file]
732+ const fileMsg = new HumanMessage ( {
733+ content : [
734+ {
735+ type : "file" ,
736+ source : { type : "base64" , data : "abc" } ,
737+ mimeType : "application/pdf" ,
738+ } ,
739+ ] ,
740+ } ) ;
741+ expect ( getBufferString ( [ fileMsg ] ) ) . toBe ( "Human: [file]" ) ;
742+
743+ // text-plain -> extracts text
744+ const textPlainMsg = new HumanMessage ( {
745+ content : [ { type : "text-plain" , text : "hello world" } ] ,
746+ } ) ;
747+ expect ( getBufferString ( [ textPlainMsg ] ) ) . toBe ( "Human: hello world" ) ;
748+
749+ // reasoning -> excluded (empty string, filtered out)
750+ const reasoningMsg = new AIMessage ( {
751+ content : [
752+ { type : "reasoning" , reasoning : "thinking..." } ,
753+ { type : "text" , text : "answer" } ,
754+ ] ,
755+ } ) ;
756+ expect ( getBufferString ( [ reasoningMsg ] ) ) . toBe ( "AI: answer" ) ;
757+
758+ // Mixed content: text + multimodal
759+ const mixedMsg = new HumanMessage ( {
760+ content : [
761+ { type : "text" , text : "Look at this: " } ,
762+ { type : "image" , source : { type : "base64" , data : "abc" } } ,
763+ { type : "text" , text : " and listen to this: " } ,
764+ { type : "audio" , source : { type : "base64" , data : "def" } } ,
765+ ] ,
766+ } ) ;
767+ expect ( getBufferString ( [ mixedMsg ] ) ) . toBe (
768+ "Human: Look at this: [image] and listen to this: [audio]"
769+ ) ;
770+ } ) ;
771+
703772describe ( "chat message conversions" , ( ) => {
704773 it ( "can convert a chat message to a stored message and back" , ( ) => {
705774 const originalMessages = [
0 commit comments