@@ -669,7 +669,7 @@ describe('assistant messages', () => {
669669 } ) ;
670670 } ) ;
671671
672- it ( 'should trim trailing whitespace from reasoning content when it is the last part ' , async ( ) => {
672+ it ( 'should not trim reasoning text when a signature is present ' , async ( ) => {
673673 const result = await convertToBedrockChatMessages ( [
674674 {
675675 role : 'user' ,
@@ -691,28 +691,263 @@ describe('assistant messages', () => {
691691 } ,
692692 ] ) ;
693693
694- expect ( result ) . toEqual ( {
695- messages : [
696- {
697- role : 'user' ,
698- content : [ { text : 'Explain your reasoning' } ] ,
699- } ,
700- {
701- role : 'assistant' ,
702- content : [
703- {
704- reasoningContent : {
705- reasoningText : {
706- text : 'This is my reasoning with trailing space' ,
707- signature : 'test-signature' ,
694+ expect ( result ) . toMatchInlineSnapshot ( `
695+ {
696+ "messages": [
697+ {
698+ "content": [
699+ {
700+ "text": "Explain your reasoning",
701+ },
702+ ],
703+ "role": "user",
704+ },
705+ {
706+ "content": [
707+ {
708+ "reasoningContent": {
709+ "reasoningText": {
710+ "signature": "test-signature",
711+ "text": "This is my reasoning with trailing space ",
712+ },
713+ },
714+ },
715+ ],
716+ "role": "assistant",
717+ },
718+ ],
719+ "system": [],
720+ }
721+ ` ) ;
722+ } ) ;
723+
724+ it ( 'should trim trailing whitespace from reasoning content without signature when it is the last part' , async ( ) => {
725+ const result = await convertToBedrockChatMessages ( [
726+ {
727+ role : 'user' ,
728+ content : [ { type : 'text' , text : 'Explain your reasoning' } ] ,
729+ } ,
730+ {
731+ role : 'assistant' ,
732+ content : [
733+ {
734+ type : 'reasoning' ,
735+ text : 'This is my reasoning with trailing space ' ,
736+ } ,
737+ ] ,
738+ } ,
739+ ] ) ;
740+
741+ expect ( result ) . toMatchInlineSnapshot ( `
742+ {
743+ "messages": [
744+ {
745+ "content": [
746+ {
747+ "text": "Explain your reasoning",
748+ },
749+ ],
750+ "role": "user",
751+ },
752+ {
753+ "content": [
754+ {
755+ "reasoningContent": {
756+ "reasoningText": {
757+ "text": "This is my reasoning with trailing space",
758+ },
759+ },
760+ },
761+ ],
762+ "role": "assistant",
763+ },
764+ ],
765+ "system": [],
766+ }
767+ ` ) ;
768+ } ) ;
769+
770+ it ( 'should only trim last reasoning part when multiple reasoning parts have trailing spaces' , async ( ) => {
771+ const result = await convertToBedrockChatMessages ( [
772+ {
773+ role : 'user' ,
774+ content : [ { type : 'text' , text : 'Explain your reasoning' } ] ,
775+ } ,
776+ {
777+ role : 'assistant' ,
778+ content : [
779+ {
780+ type : 'reasoning' ,
781+ text : 'First reasoning with trailing space ' ,
782+ } ,
783+ {
784+ type : 'reasoning' ,
785+ text : 'Second reasoning with trailing space ' ,
786+ } ,
787+ ] ,
788+ } ,
789+ ] ) ;
790+
791+ expect ( result ) . toMatchInlineSnapshot ( `
792+ {
793+ "messages": [
794+ {
795+ "content": [
796+ {
797+ "text": "Explain your reasoning",
798+ },
799+ ],
800+ "role": "user",
801+ },
802+ {
803+ "content": [
804+ {
805+ "reasoningContent": {
806+ "reasoningText": {
807+ "text": "First reasoning with trailing space ",
808+ },
809+ },
810+ },
811+ {
812+ "reasoningContent": {
813+ "reasoningText": {
814+ "text": "Second reasoning with trailing space",
815+ },
708816 },
709817 },
818+ ],
819+ "role": "assistant",
820+ },
821+ ],
822+ "system": [],
823+ }
824+ ` ) ;
825+ } ) ;
826+
827+ it ( 'should preserve reasoning text with signature in multi-turn tool use' , async ( ) => {
828+ const result = await convertToBedrockChatMessages ( [
829+ {
830+ role : 'user' ,
831+ content : [ { type : 'text' , text : 'What is the weather?' } ] ,
832+ } ,
833+ {
834+ role : 'assistant' ,
835+ content : [
836+ {
837+ type : 'reasoning' ,
838+ text : 'Let me check the weather API.\n' ,
839+ providerOptions : {
840+ bedrock : {
841+ signature : 'sig-abc123' ,
842+ } satisfies BedrockReasoningMetadata ,
710843 } ,
711- ] ,
712- } ,
713- ] ,
714- system : [ ] ,
715- } ) ;
844+ } ,
845+ {
846+ type : 'tool-call' ,
847+ toolCallId : 'call-1' ,
848+ toolName : 'getWeather' ,
849+ input : { city : 'SF' } ,
850+ } ,
851+ ] ,
852+ } ,
853+ {
854+ role : 'tool' ,
855+ content : [
856+ {
857+ type : 'tool-result' ,
858+ toolCallId : 'call-1' ,
859+ toolName : 'getWeather' ,
860+ output : { type : 'text' , value : 'Sunny, 72F' } ,
861+ } ,
862+ ] ,
863+ } ,
864+ {
865+ role : 'assistant' ,
866+ content : [
867+ {
868+ type : 'reasoning' ,
869+ text : 'The weather is sunny and warm.\n' ,
870+ providerOptions : {
871+ bedrock : {
872+ signature : 'sig-def456' ,
873+ } satisfies BedrockReasoningMetadata ,
874+ } ,
875+ } ,
876+ { type : 'text' , text : 'It is sunny and 72F in SF.' } ,
877+ ] ,
878+ } ,
879+ ] ) ;
880+
881+ expect ( result ) . toMatchInlineSnapshot ( `
882+ {
883+ "messages": [
884+ {
885+ "content": [
886+ {
887+ "text": "What is the weather?",
888+ },
889+ ],
890+ "role": "user",
891+ },
892+ {
893+ "content": [
894+ {
895+ "reasoningContent": {
896+ "reasoningText": {
897+ "signature": "sig-abc123",
898+ "text": "Let me check the weather API.
899+ ",
900+ },
901+ },
902+ },
903+ {
904+ "toolUse": {
905+ "input": {
906+ "city": "SF",
907+ },
908+ "name": "getWeather",
909+ "toolUseId": "call-1",
910+ },
911+ },
912+ ],
913+ "role": "assistant",
914+ },
915+ {
916+ "content": [
917+ {
918+ "toolResult": {
919+ "content": [
920+ {
921+ "text": "Sunny, 72F",
922+ },
923+ ],
924+ "toolUseId": "call-1",
925+ },
926+ },
927+ ],
928+ "role": "user",
929+ },
930+ {
931+ "content": [
932+ {
933+ "reasoningContent": {
934+ "reasoningText": {
935+ "signature": "sig-def456",
936+ "text": "The weather is sunny and warm.
937+ ",
938+ },
939+ },
940+ },
941+ {
942+ "text": "It is sunny and 72F in SF.",
943+ },
944+ ],
945+ "role": "assistant",
946+ },
947+ ],
948+ "system": [],
949+ }
950+ ` ) ;
716951 } ) ;
717952
718953 it ( 'should handle a mix of text and reasoning content types' , async ( ) => {
0 commit comments