@@ -27,6 +27,24 @@ function assistant() {
2727 type : "assistant" ,
2828 time : { created : time ( 0 ) } ,
2929 content : [ ] ,
30+ retries : [ ] ,
31+ } )
32+ }
33+
34+ function retryError ( message : string ) {
35+ return new SessionEvent . RetryError ( {
36+ message,
37+ isRetryable : true ,
38+ } )
39+ }
40+
41+ function retry ( attempt : number , message : string , created : number ) {
42+ return new SessionEntry . AssistantRetry ( {
43+ attempt,
44+ error : retryError ( message ) ,
45+ time : {
46+ created : time ( created ) ,
47+ } ,
3048 } )
3149}
3250
@@ -78,6 +96,12 @@ function tool(state: SessionEntryStepper.MemoryState, callID: string) {
7896 return tools ( state ) . find ( ( x ) => x . callID === callID )
7997}
8098
99+ function retriesOf ( state : SessionEntryStepper . MemoryState ) {
100+ const entry = last ( state )
101+ if ( ! entry ) return [ ]
102+ return entry . retries ?? [ ]
103+ }
104+
81105function adapterStore ( ) {
82106 return {
83107 committed : [ ] as SessionEntry . Entry [ ] ,
@@ -168,6 +192,33 @@ describe("session-entry-stepper", () => {
168192 ] )
169193 expect ( store . committed [ 0 ] . time . completed ) . toEqual ( time ( 7 ) )
170194 } )
195+
196+ test ( "aggregates retry events onto the current assistant" , ( ) => {
197+ const store = adapterStore ( )
198+ store . committed . push ( assistant ( ) )
199+
200+ SessionEntryStepper . stepWith (
201+ adapterFor ( store ) ,
202+ SessionEvent . Retried . create ( {
203+ attempt : 1 ,
204+ error : retryError ( "rate limited" ) ,
205+ timestamp : time ( 1 ) ,
206+ } ) ,
207+ )
208+ SessionEntryStepper . stepWith (
209+ adapterFor ( store ) ,
210+ SessionEvent . Retried . create ( {
211+ attempt : 2 ,
212+ error : retryError ( "provider overloaded" ) ,
213+ timestamp : time ( 2 ) ,
214+ } ) ,
215+ )
216+
217+ expect ( store . committed [ 0 ] ?. type ) . toBe ( "assistant" )
218+ if ( store . committed [ 0 ] ?. type !== "assistant" ) return
219+
220+ expect ( store . committed [ 0 ] . retries ) . toEqual ( [ retry ( 1 , "rate limited" , 1 ) , retry ( 2 , "provider overloaded" , 2 ) ] )
221+ } )
171222 } )
172223
173224 describe ( "memory" , ( ) => {
@@ -231,6 +282,21 @@ describe("session-entry-stepper", () => {
231282
232283 expect ( reasons ( state ) ) . toEqual ( [ { type : "reasoning" , text : "final" } ] )
233284 } )
285+
286+ test ( "stepWith through memory records retries" , ( ) => {
287+ const state = active ( )
288+
289+ SessionEntryStepper . stepWith (
290+ SessionEntryStepper . memory ( state ) ,
291+ SessionEvent . Retried . create ( {
292+ attempt : 1 ,
293+ error : retryError ( "rate limited" ) ,
294+ timestamp : time ( 1 ) ,
295+ } ) ,
296+ )
297+
298+ expect ( retriesOf ( state ) ) . toEqual ( [ retry ( 1 , "rate limited" , 1 ) ] )
299+ } )
234300 } )
235301
236302 describe ( "step" , ( ) => {
0 commit comments