@@ -204,10 +204,11 @@ export class OpenAIResponsesCompactionSession
204204 const compacted = await this . client . responses . compact ( compactRequest ) ;
205205
206206 const outputItems = normalizeCompactionOutputItems ( compacted . output ?? [ ] ) ;
207- await this . underlyingSession . clearSession ( ) ;
208- if ( outputItems . length > 0 ) {
209- await this . underlyingSession . addItems ( outputItems ) ;
210- }
207+ const previousItems = await this . getAllUnderlyingSessionItems ( ) ;
208+ await this . replaceUnderlyingSessionItems ( {
209+ outputItems,
210+ previousItems,
211+ } ) ;
211212 this . compactionCandidateItems = selectCompactionCandidateItems ( outputItems ) ;
212213 this . sessionItems = outputItems ;
213214
@@ -287,6 +288,87 @@ export class OpenAIResponsesCompactionSession
287288 this . sessionItems = [ ] ;
288289 }
289290
291+ private async getAllUnderlyingSessionItems ( ) : Promise < AgentInputItem [ ] > {
292+ return this . underlyingSession . getItems ( ) ;
293+ }
294+
295+ private async replaceUnderlyingSessionItems ( {
296+ outputItems,
297+ previousItems,
298+ } : {
299+ outputItems : AgentInputItem [ ] ;
300+ previousItems : AgentInputItem [ ] ;
301+ } ) : Promise < void > {
302+ try {
303+ await this . underlyingSession . clearSession ( ) ;
304+ } catch ( error ) {
305+ await this . restoreUnderlyingSessionItemsAfterFailedClear (
306+ previousItems ,
307+ error ,
308+ ) ;
309+ throw error ;
310+ }
311+
312+ try {
313+ if ( outputItems . length > 0 ) {
314+ await this . underlyingSession . addItems ( outputItems ) ;
315+ }
316+ } catch ( error ) {
317+ await this . restoreUnderlyingSessionItems ( previousItems , error ) ;
318+ throw error ;
319+ }
320+ }
321+
322+ private async restoreUnderlyingSessionItemsAfterFailedClear (
323+ previousItems : AgentInputItem [ ] ,
324+ error : unknown ,
325+ ) : Promise < void > {
326+ let currentItems : AgentInputItem [ ] ;
327+ try {
328+ currentItems = await this . getAllUnderlyingSessionItems ( ) ;
329+ } catch ( inspectionError ) {
330+ logger . warn (
331+ 'Failed to inspect session history after compaction replacement clear failed.' ,
332+ inspectionError ,
333+ ) ;
334+ return ;
335+ }
336+
337+ if ( areAgentItemsEqual ( currentItems , previousItems ) ) {
338+ return ;
339+ }
340+
341+ await this . restoreUnderlyingSessionItems ( previousItems , error , {
342+ clearExistingItems : false ,
343+ } ) ;
344+ }
345+
346+ private async restoreUnderlyingSessionItems (
347+ previousItems : AgentInputItem [ ] ,
348+ error : unknown ,
349+ options : { clearExistingItems ?: boolean } = { } ,
350+ ) : Promise < void > {
351+ try {
352+ if ( options . clearExistingItems !== false ) {
353+ await this . underlyingSession . clearSession ( ) ;
354+ }
355+ if ( previousItems . length > 0 ) {
356+ await this . underlyingSession . addItems ( previousItems ) ;
357+ }
358+ } catch ( restoreError ) {
359+ logger . warn (
360+ 'Failed to restore session history after compaction replacement failed.' ,
361+ restoreError ,
362+ ) ;
363+ return ;
364+ }
365+
366+ logger . warn (
367+ 'Restored previous session history after compaction replacement failed.' ,
368+ error ,
369+ ) ;
370+ }
371+
290372 private async ensureCompactionCandidates ( ) : Promise < {
291373 compactionCandidateItems : AgentInputItem [ ] ;
292374 sessionItems : AgentInputItem [ ] ;
@@ -525,3 +607,10 @@ function isOpenAIConversationsSessionDelegate(
525607 ] === 'conversations'
526608 ) ;
527609}
610+
611+ function areAgentItemsEqual (
612+ left : AgentInputItem [ ] ,
613+ right : AgentInputItem [ ] ,
614+ ) : boolean {
615+ return JSON . stringify ( left ) === JSON . stringify ( right ) ;
616+ }
0 commit comments