@@ -63,6 +63,28 @@ describe("addTurn", () => {
6363 expect ( history [ 2 ] . content ) . toBe ( "new response" ) ;
6464 } ) ;
6565
66+ it ( "does not orphan a tool_result when an unpaired tool_use precedes a complete pair" , ( ) => {
67+ // Scenario: abort interrupted a previous run between tool_use(A) and
68+ // tool_result(A), leaving an orphaned assistant tool_use. A later run
69+ // completed a full tool_use(B) → tool_result(B) pair. Trimming must
70+ // drop only the orphan, not consume tool_use(B) as if it were
71+ // tool_result(A).
72+ const history : ConversationTurn [ ] = [
73+ { role : "assistant" , content : "tool_use(A)" , isToolCall : true } ,
74+ { role : "assistant" , content : "tool_use(B)" , isToolCall : true } ,
75+ { role : "user" , content : "tool_result(B)" , isToolCall : true } ,
76+ { role : "assistant" , content : "response" } ,
77+ ] ;
78+
79+ addTurn ( history , { role : "user" , content : "next" } , 4 ) ;
80+
81+ expect ( history ) . toHaveLength ( 4 ) ;
82+ expect ( history [ 0 ] . content ) . toBe ( "tool_use(B)" ) ;
83+ expect ( history [ 1 ] . content ) . toBe ( "tool_result(B)" ) ;
84+ expect ( history [ 2 ] . content ) . toBe ( "response" ) ;
85+ expect ( history [ 3 ] . content ) . toBe ( "next" ) ;
86+ } ) ;
87+
6688 it ( "does not split a tool call pair when trimming" , ( ) => {
6789 const history : ConversationTurn [ ] = [
6890 { role : "user" , content : "regular" } ,
0 commit comments