@@ -128,6 +128,52 @@ async function postJson(
128128}
129129
130130describe ( "Anthropic Messages adapter" , ( ) => {
131+ test ( "canonicalizes adjacent plain-text content blocks" , ( ) => {
132+ const result = JSON . parse (
133+ anthropicMessagesRequestToChatCompletion (
134+ JSON . stringify ( {
135+ model : "test-model" ,
136+ messages : [
137+ {
138+ role : "user" ,
139+ content : [
140+ { type : "text" , text : "First prompt" } ,
141+ { type : "text" , text : "Recovery prompt" } ,
142+ ] ,
143+ } ,
144+ ] ,
145+ } ) ,
146+ ) ,
147+ ) as {
148+ messages : Array < { role : string ; content : unknown } > ;
149+ } ;
150+
151+ expect ( result . messages ) . toEqual ( [
152+ {
153+ role : "user" ,
154+ content : "First prompt\n\n\nRecovery prompt" ,
155+ } ,
156+ ] ) ;
157+ } ) ;
158+
159+ test . each ( [
160+ [ "string content" , "Hello" ] ,
161+ [ "one text block" , [ { type : "text" , text : "Hello" } ] ] ,
162+ ] ) ( "preserves a single plain-text user block from %s" , ( _ , content ) => {
163+ const result = JSON . parse (
164+ anthropicMessagesRequestToChatCompletion (
165+ JSON . stringify ( {
166+ model : "test-model" ,
167+ messages : [ { role : "user" , content } ] ,
168+ } ) ,
169+ ) ,
170+ ) as {
171+ messages : Array < { role : string ; content : unknown } > ;
172+ } ;
173+
174+ expect ( result . messages ) . toEqual ( [ { role : "user" , content : "Hello" } ] ) ;
175+ } ) ;
176+
131177 test ( "normalizes messages, binary content, and tools" , ( ) => {
132178 const result = JSON . parse (
133179 anthropicMessagesRequestToChatCompletion (
@@ -589,6 +635,36 @@ describe("protocol-aware replay", () => {
589635 } ) ;
590636 } ) ;
591637
638+ test ( "canonicalizes Anthropic content blocks before coalescing user messages" , async ( ) => {
639+ await writeSnapshot ( [
640+ { role : "system" , content : "${system}" } ,
641+ { role : "user" , content : "First prompt" } ,
642+ { role : "user" , content : "Recovery prompt" } ,
643+ { role : "user" , content : "Final prompt" } ,
644+ { role : "assistant" , content : "Recovered" } ,
645+ ] ) ;
646+ const request = requestFor ( "anthropic-messages" , "Final prompt" ) ;
647+ request . messages = [
648+ {
649+ role : "user" ,
650+ content : [
651+ { type : "text" , text : "First prompt" } ,
652+ { type : "text" , text : "Recovery prompt" } ,
653+ ] ,
654+ } ,
655+ ...( request . messages as unknown [ ] ) ,
656+ ] ;
657+
658+ await withProxy ( "anthropic-messages" , async ( proxyUrl ) => {
659+ const response = await postJson (
660+ proxyUrl ,
661+ endpoints [ "anthropic-messages" ] ,
662+ request ,
663+ ) ;
664+ expect ( response . status ) . toBe ( 200 ) ;
665+ } ) ;
666+ } ) ;
667+
592668 test . each ( backends ) (
593669 "replays compaction responses through %s" ,
594670 async ( backend ) => {
0 commit comments