@@ -46,10 +46,23 @@ function insertAssistant(
4646 sessionId : string ,
4747 id : string ,
4848 data : Record < string , unknown > ,
49+ timeCreated = Date . now ( ) ,
4950) : void {
5051 db . prepare (
5152 "INSERT INTO message (id, session_id, time_created, time_updated, data) VALUES (?, ?, ?, ?, ?)" ,
52- ) . run ( id , sessionId , Date . now ( ) , Date . now ( ) , JSON . stringify ( { role : "assistant" , ...data } ) ) ;
53+ ) . run ( id , sessionId , timeCreated , timeCreated , JSON . stringify ( { role : "assistant" , ...data } ) ) ;
54+ }
55+
56+ function insertUser (
57+ db : Database ,
58+ sessionId : string ,
59+ id : string ,
60+ data : Record < string , unknown > ,
61+ timeCreated : number ,
62+ ) : void {
63+ db . prepare (
64+ "INSERT INTO message (id, session_id, time_created, time_updated, data) VALUES (?, ?, ?, ?, ?)" ,
65+ ) . run ( id , sessionId , timeCreated , timeCreated , JSON . stringify ( { role : "user" , ...data } ) ) ;
5366}
5467
5568function insertPart (
@@ -67,14 +80,30 @@ function insertPart(
6780describe ( "isMidTurnFromOpenCodeDb" , ( ) => {
6881 it ( "is mid-turn when the latest assistant finished with tool-calls" , ( ) => {
6982 const db = createMidTurnDb ( ) ;
70- insertAssistant ( db , "session-1" , "assistant-1" , { finish : "tool-calls" } ) ;
83+ insertAssistant ( db , "session-1" , "assistant-1" , { finish : "tool-calls" } , 100 ) ;
84+
85+ expect ( isMidTurnFromOpenCodeDb ( db , "session-1" ) ) . toBe ( true ) ;
86+ } ) ;
87+
88+ it ( "is not mid-turn when a newer real user message ends a stale tool-calls tail" , ( ) => {
89+ const db = createMidTurnDb ( ) ;
90+ insertAssistant ( db , "session-1" , "assistant-1" , { finish : "tool-calls" } , 100 ) ;
91+ insertUser ( db , "session-1" , "user-1" , { content : "new turn" } , 200 ) ;
92+
93+ expect ( isMidTurnFromOpenCodeDb ( db , "session-1" ) ) . toBe ( false ) ;
94+ } ) ;
95+
96+ it ( "does not release mid-turn for synthetic user messages after a stale tool-calls tail" , ( ) => {
97+ const db = createMidTurnDb ( ) ;
98+ insertAssistant ( db , "session-1" , "assistant-1" , { finish : "tool-calls" } , 100 ) ;
99+ insertUser ( db , "session-1" , "user-1" , { content : "agent nudge" , synthetic : true } , 200 ) ;
71100
72101 expect ( isMidTurnFromOpenCodeDb ( db , "session-1" ) ) . toBe ( true ) ;
73102 } ) ;
74103
75104 it ( "is mid-turn when the latest assistant has a non-provider-executed tool part" , ( ) => {
76105 const db = createMidTurnDb ( ) ;
77- insertAssistant ( db , "session-1" , "assistant-1" , { finish : "stop" } ) ;
106+ insertAssistant ( db , "session-1" , "assistant-1" , { finish : "stop" } , 100 ) ;
78107 insertPart ( db , "session-1" , "assistant-1" , "part-1" , {
79108 type : "tool" ,
80109 providerExecuted : false ,
@@ -83,6 +112,18 @@ describe("isMidTurnFromOpenCodeDb", () => {
83112 expect ( isMidTurnFromOpenCodeDb ( db , "session-1" ) ) . toBe ( true ) ;
84113 } ) ;
85114
115+ it ( "is not mid-turn when a newer real user message ends an unexecuted tool tail" , ( ) => {
116+ const db = createMidTurnDb ( ) ;
117+ insertAssistant ( db , "session-1" , "assistant-1" , { finish : "stop" } , 100 ) ;
118+ insertPart ( db , "session-1" , "assistant-1" , "part-1" , {
119+ type : "tool" ,
120+ providerExecuted : false ,
121+ } ) ;
122+ insertUser ( db , "session-1" , "user-1" , { content : "new turn" } , 200 ) ;
123+
124+ expect ( isMidTurnFromOpenCodeDb ( db , "session-1" ) ) . toBe ( false ) ;
125+ } ) ;
126+
86127 it ( "is not mid-turn for provider-executed tool parts" , ( ) => {
87128 const db = createMidTurnDb ( ) ;
88129 insertAssistant ( db , "session-1" , "assistant-1" , { finish : "stop" } ) ;
0 commit comments