@@ -151,6 +151,21 @@ describe("stripAssistantInternalScaffolding", () => {
151151 expectVisibleText ( "Before\n<function_response>\nraw command output\n" , "Before\n" ) ;
152152 } ) ;
153153
154+ it ( "preserves inline multi-line function_response examples in prose" , ( ) => {
155+ expectVisibleText (
156+ [
157+ "Before <function_response>" ,
158+ 'Searching for: "what skills matter most in the age of AI"' ,
159+ "</function_response> After" ,
160+ ] . join ( "\n" ) ,
161+ [
162+ "Before <function_response>" ,
163+ 'Searching for: "what skills matter most in the age of AI"' ,
164+ "</function_response> After" ,
165+ ] . join ( "\n" ) ,
166+ ) ;
167+ } ) ;
168+
154169 it ( "strips <tool_result> closed with mismatched </tool_call> and preserves trailing text" , ( ) => {
155170 expectVisibleText (
156171 'Prefix\n<tool_result> {"output": "data"} </tool_call>\nSuffix' ,
@@ -411,6 +426,13 @@ describe("stripAssistantInternalScaffolding", () => {
411426 ) ;
412427 } ) ;
413428
429+ it ( "preserves inline closed function_response examples in prose" , ( ) => {
430+ expectVisibleText (
431+ "Use <function_response>ok</function_response> to describe the response wrapper." ,
432+ "Use <function_response>ok</function_response> to describe the response wrapper." ,
433+ ) ;
434+ } ) ;
435+
414436 it ( "preserves line-leading function_response prose examples" , ( ) => {
415437 expectVisibleText (
416438 "<function_response> is the response wrapper." ,
@@ -589,6 +611,142 @@ describe("stripToolCallXmlTags", () => {
589611 "prefix suffix" ,
590612 ) ;
591613 } ) ;
614+
615+ it ( "strips function_response adjacent to an opt-in stripped function_calls block" , ( ) => {
616+ const input = [
617+ '<function_calls><invoke name="exec">internal</invoke></function_calls><function_response>' ,
618+ 'Searching for: "what skills matter most in the age of AI"' ,
619+ "</function_response>" ,
620+ "After" ,
621+ ] . join ( "\n" ) ;
622+
623+ expect ( stripToolCallXmlTags ( input , { stripFunctionCallsXmlPayloads : true } ) ) . toBe ( "\nAfter" ) ;
624+ } ) ;
625+
626+ it ( "strips function_response adjacent to an inline stripped function_calls block" , ( ) => {
627+ const input = [
628+ 'Checking. <function_calls><invoke name="exec">internal</invoke></function_calls><function_response>' ,
629+ 'Searching for: "what skills matter most in the age of AI"' ,
630+ "</function_response>" ,
631+ "After" ,
632+ ] . join ( "\n" ) ;
633+
634+ expect ( stripToolCallXmlTags ( input , { stripFunctionCallsXmlPayloads : true } ) ) . toBe (
635+ "Checking. \nAfter" ,
636+ ) ;
637+ } ) ;
638+
639+ it ( "strips compact function_response after a newline-separated stripped function_calls block" , ( ) => {
640+ const input = [
641+ 'Checking. <function_calls><invoke name="exec">internal</invoke></function_calls>' ,
642+ "<function_response>ok</function_response>" ,
643+ "After" ,
644+ ] . join ( "\n" ) ;
645+
646+ expect ( stripToolCallXmlTags ( input , { stripFunctionCallsXmlPayloads : true } ) ) . toBe (
647+ "Checking. \n\nAfter" ,
648+ ) ;
649+ } ) ;
650+
651+ it ( "strips dangling function_response adjacent to a stripped function_calls block" , ( ) => {
652+ const input = [
653+ 'Checking. <function_calls><invoke name="exec">internal</invoke></function_calls><function_response>' ,
654+ 'Searching for: "what skills matter most in the age of AI"' ,
655+ ] . join ( "\n" ) ;
656+
657+ expect ( stripToolCallXmlTags ( input , { stripFunctionCallsXmlPayloads : true } ) ) . toBe ( "Checking. " ) ;
658+ } ) ;
659+
660+ it ( "strips compact dangling function_response adjacent to a stripped function_calls block" , ( ) => {
661+ const input =
662+ 'Checking. <function_calls><invoke name="exec">internal</invoke></function_calls><function_response>raw output' ;
663+
664+ expect ( stripToolCallXmlTags ( input , { stripFunctionCallsXmlPayloads : true } ) ) . toBe ( "Checking. " ) ;
665+ } ) ;
666+
667+ it ( "strips same-line function_response payloads with leading spaces" , ( ) => {
668+ const input =
669+ '<function_calls><invoke name="exec">internal</invoke></function_calls><function_response> raw output</function_response>\nAfter' ;
670+
671+ expect ( stripToolCallXmlTags ( input , { stripFunctionCallsXmlPayloads : true } ) ) . toBe ( "\nAfter" ) ;
672+ } ) ;
673+
674+ it ( "strips same-line function_response payloads that start like prose" , ( ) => {
675+ const input =
676+ '<function_calls><invoke name="exec">internal</invoke></function_calls><function_response> is enabled</function_response>\nAfter' ;
677+
678+ expect ( stripToolCallXmlTags ( input , { stripFunctionCallsXmlPayloads : true } ) ) . toBe ( "\nAfter" ) ;
679+ } ) ;
680+
681+ it ( "strips dangling same-line function_response payloads with leading spaces" , ( ) => {
682+ const input =
683+ '<function_calls><invoke name="exec">internal</invoke></function_calls><function_response> raw output' ;
684+
685+ expect ( stripToolCallXmlTags ( input , { stripFunctionCallsXmlPayloads : true } ) ) . toBe ( "" ) ;
686+ } ) ;
687+
688+ it ( "strips function_response-looking prose adjacent to a stripped tool-call block" , ( ) => {
689+ const input =
690+ '<tool_call>{"name":"exec"}</tool_call>\n\n<function_response> is the response wrapper.' ;
691+
692+ expect ( stripToolCallXmlTags ( input , { stripFunctionCallsXmlPayloads : true } ) ) . toBe ( "\n\n" ) ;
693+ } ) ;
694+
695+ it ( "strips closed function_response-looking prose adjacent to a stripped tool-call block" , ( ) => {
696+ const input =
697+ '<tool_call>{"name":"exec"}</tool_call>\n<function_response> is the response wrapper; close it with </function_response>.' ;
698+
699+ expect ( stripToolCallXmlTags ( input , { stripFunctionCallsXmlPayloads : true } ) ) . toBe ( "\n." ) ;
700+ } ) ;
701+
702+ it ( "strips adjacent function_response payloads that match explanation wording" , ( ) => {
703+ const input =
704+ '<function_calls><invoke name="exec">internal</invoke></function_calls><function_response> response wrapper secret</function_response>\nAfter' ;
705+
706+ expect ( stripToolCallXmlTags ( input , { stripFunctionCallsXmlPayloads : true } ) ) . toBe ( "\nAfter" ) ;
707+ } ) ;
708+
709+ it ( "strips compact function_response wrappers while preserving same-line prose tails" , ( ) => {
710+ const input =
711+ '<tool_call>{"name":"exec"}</tool_call>\n\n<function_response>ok</function_response> is the response wrapper.' ;
712+
713+ expect ( stripToolCallXmlTags ( input , { stripFunctionCallsXmlPayloads : true } ) ) . toBe (
714+ "\n\n is the response wrapper." ,
715+ ) ;
716+ } ) ;
717+
718+ it ( "strips chained function_response blocks adjacent to a stripped function_calls block" , ( ) => {
719+ const input = [
720+ 'Checking. <function_calls><invoke name="exec">internal</invoke></function_calls><function_response>' ,
721+ "first result" ,
722+ "</function_response><function_response>" ,
723+ "second result" ,
724+ "</function_response>" ,
725+ "After" ,
726+ ] . join ( "\n" ) ;
727+
728+ expect ( stripToolCallXmlTags ( input , { stripFunctionCallsXmlPayloads : true } ) ) . toBe (
729+ "Checking. \nAfter" ,
730+ ) ;
731+ } ) ;
732+
733+ it ( "strips compact chained function_response blocks adjacent to a stripped function_calls block" , ( ) => {
734+ const input =
735+ 'Checking. <function_calls><invoke name="exec">internal</invoke></function_calls><function_response>first</function_response><function_response>second</function_response>\nAfter' ;
736+
737+ expect ( stripToolCallXmlTags ( input , { stripFunctionCallsXmlPayloads : true } ) ) . toBe (
738+ "Checking. \nAfter" ,
739+ ) ;
740+ } ) ;
741+
742+ it ( "strips compact function_response before same-line visible replies" , ( ) => {
743+ const input =
744+ 'Checking. <function_calls><invoke name="exec">internal</invoke></function_calls><function_response>raw</function_response> Done.' ;
745+
746+ expect ( stripToolCallXmlTags ( input , { stripFunctionCallsXmlPayloads : true } ) ) . toBe (
747+ "Checking. Done." ,
748+ ) ;
749+ } ) ;
592750} ) ;
593751
594752describe ( "stripMinimaxToolCallXml" , ( ) => {
0 commit comments