@@ -1446,6 +1446,97 @@ describe("CL-9489 zero-verbatim fold", () => {
14461446 ) . toBe ( true ) ;
14471447 } ) ;
14481448
1449+ test ( "earlier live tool-use thinking is dropped when the last assistant is text-only" , async ( ) => {
1450+ const toolThinking = "tool-use-thinking-block" ;
1451+ const lastThinking = "text-only-thinking-block" ;
1452+ const filler = "x" . repeat ( 1_500 ) ;
1453+ const turns : ConversationTurn [ ] = [ ] ;
1454+ for ( let i = 0 ; i < 6 ; i ++ ) {
1455+ turns . push (
1456+ makeTurn ( {
1457+ role : "user" ,
1458+ content : [ { type : "text" , text : `dummy ask ${ i } ${ filler } ` } ] ,
1459+ } ) ,
1460+ ) ;
1461+ turns . push (
1462+ makeTurn ( {
1463+ role : "assistant" ,
1464+ content : [ { type : "text" , text : `dummy reply ${ i } ${ filler } ` } ] ,
1465+ } ) ,
1466+ ) ;
1467+ }
1468+ turns . push (
1469+ makeTurn ( {
1470+ role : "assistant" ,
1471+ content : [
1472+ {
1473+ type : "thinking" ,
1474+ thinking : toolThinking ,
1475+ signature : "sig-tool-use" ,
1476+ } ,
1477+ {
1478+ type : "tool_call" ,
1479+ id : "c-earlier" ,
1480+ name : "read_file" ,
1481+ arguments : { path : "src/app.ts" } ,
1482+ } ,
1483+ ] ,
1484+ } ) ,
1485+ ) ;
1486+ turns . push (
1487+ makeTurn ( {
1488+ role : "user" ,
1489+ content : [
1490+ {
1491+ type : "tool_result" ,
1492+ callId : "c-earlier" ,
1493+ content : [ { type : "text" , text : "export const app = 1;\n" } ] ,
1494+ } ,
1495+ ] ,
1496+ } ) ,
1497+ ) ;
1498+ turns . push (
1499+ makeTurn ( {
1500+ role : "assistant" ,
1501+ content : [
1502+ {
1503+ type : "thinking" ,
1504+ thinking : lastThinking ,
1505+ signature : "sig-text-only" ,
1506+ } ,
1507+ { type : "text" , text : "here is the answer" } ,
1508+ ] ,
1509+ } ) ,
1510+ ) ;
1511+
1512+ const result = await createPruningCompactor ( {
1513+ summarize : async ( ) =>
1514+ "Folded dummy pairs. Next: resume after a text reply." ,
1515+ } ) . apply ( turns , mockStrategyCtx ) ;
1516+
1517+ const liveTypes = result . output . flatMap ( ( t ) =>
1518+ t . content . map ( ( b ) => b . type ) ,
1519+ ) ;
1520+ expect ( liveTypes ) . not . toContain ( "thinking" ) ;
1521+ expect ( liveTypes ) . not . toContain ( "redacted_thinking" ) ;
1522+ expect (
1523+ result . output . some (
1524+ ( t ) =>
1525+ t . role === "assistant" &&
1526+ t . content . some ( ( b ) => b . type === "tool_call" && b . id === "c-earlier" ) ,
1527+ ) ,
1528+ ) . toBe ( true ) ;
1529+ expect (
1530+ result . output . some (
1531+ ( t ) =>
1532+ t . role === "assistant" &&
1533+ t . content . some (
1534+ ( b ) => b . type === "text" && b . text === "here is the answer" ,
1535+ ) ,
1536+ ) ,
1537+ ) . toBe ( true ) ;
1538+ } ) ;
1539+
14491540 test ( "a thinking-only live turn is replaced with THINKING_ONLY_OMITTED" , async ( ) => {
14501541 const thinking = "t" . repeat ( 20_000 ) ;
14511542 const filler = "x" . repeat ( 1_500 ) ;
0 commit comments