@@ -1107,11 +1107,14 @@ export class DefaultMessageService implements IMessageService {
11071107 runtime . character . templates ?. multiStepDecisionTemplate || multiStepDecisionTemplate ,
11081108 } ) ;
11091109
1110- // Retry logic for parsing failures
1111- const maxParseRetries = parseInt (
1112- runtime . getSetting ( 'MULTISTEP_PARSE_RETRIES' ) || '5' ,
1110+ // Retry logic for parsing failures with bounds checking
1111+ const parseRetriesSetting = runtime . getSetting ( 'MULTISTEP_PARSE_RETRIES' ) ;
1112+ const rawParseRetries = parseInt (
1113+ String ( parseRetriesSetting ?? '5' ) ,
11131114 10
11141115 ) ;
1116+ // Validate retry count is within reasonable bounds (1-10)
1117+ const maxParseRetries = Math . max ( 1 , Math . min ( 10 , isNaN ( rawParseRetries ) ? 5 : rawParseRetries ) ) ;
11151118 let stepResultRaw : string = '' ;
11161119 let parsedStep : Record < string , unknown > | null = null ;
11171120
@@ -1148,7 +1151,9 @@ export class DefaultMessageService implements IMessageService {
11481151 ) ;
11491152
11501153 if ( parseAttempt < maxParseRetries ) {
1151- await new Promise ( ( resolve ) => setTimeout ( resolve , 1000 ) ) ;
1154+ // Exponential backoff: 1s, 2s, 4s, etc. (capped at 8s)
1155+ const backoffMs = Math . min ( 1000 * Math . pow ( 2 , parseAttempt - 1 ) , 8000 ) ;
1156+ await new Promise ( ( resolve ) => setTimeout ( resolve , backoffMs ) ) ;
11521157 }
11531158 }
11541159 } catch ( error ) {
@@ -1165,7 +1170,9 @@ export class DefaultMessageService implements IMessageService {
11651170 if ( parseAttempt >= maxParseRetries ) {
11661171 throw error ;
11671172 }
1168- await new Promise ( ( resolve ) => setTimeout ( resolve , 1000 ) ) ;
1173+ // Exponential backoff on error
1174+ const backoffMs = Math . min ( 1000 * Math . pow ( 2 , parseAttempt - 1 ) , 8000 ) ;
1175+ await new Promise ( ( resolve ) => setTimeout ( resolve , backoffMs ) ) ;
11691176 }
11701177 }
11711178
@@ -1386,11 +1393,14 @@ export class DefaultMessageService implements IMessageService {
13861393 template : runtime . character . templates ?. multiStepSummaryTemplate || multiStepSummaryTemplate ,
13871394 } ) ;
13881395
1389- // Retry logic for summary parsing failures
1390- const maxSummaryRetries = parseInt (
1391- runtime . getSetting ( 'MULTISTEP_SUMMARY_PARSE_RETRIES' ) || '5' ,
1396+ // Retry logic for summary parsing failures with bounds checking
1397+ const summaryRetriesSetting = runtime . getSetting ( 'MULTISTEP_SUMMARY_PARSE_RETRIES' ) ;
1398+ const rawSummaryRetries = parseInt (
1399+ String ( summaryRetriesSetting ?? '5' ) ,
13921400 10
13931401 ) ;
1402+ // Validate retry count is within reasonable bounds (1-10)
1403+ const maxSummaryRetries = Math . max ( 1 , Math . min ( 10 , isNaN ( rawSummaryRetries ) ? 5 : rawSummaryRetries ) ) ;
13941404 let finalOutput : string = '' ;
13951405 let summary : Record < string , unknown > | null = null ;
13961406
@@ -1427,7 +1437,9 @@ export class DefaultMessageService implements IMessageService {
14271437 ) ;
14281438
14291439 if ( summaryAttempt < maxSummaryRetries ) {
1430- await new Promise ( ( resolve ) => setTimeout ( resolve , 1000 ) ) ;
1440+ // Exponential backoff: 1s, 2s, 4s, etc. (capped at 8s)
1441+ const backoffMs = Math . min ( 1000 * Math . pow ( 2 , summaryAttempt - 1 ) , 8000 ) ;
1442+ await new Promise ( ( resolve ) => setTimeout ( resolve , backoffMs ) ) ;
14311443 }
14321444 }
14331445 } catch ( error ) {
@@ -1447,19 +1459,22 @@ export class DefaultMessageService implements IMessageService {
14471459 ) ;
14481460 break ;
14491461 }
1450- await new Promise ( ( resolve ) => setTimeout ( resolve , 1000 ) ) ;
1462+ // Exponential backoff on error
1463+ const backoffMs = Math . min ( 1000 * Math . pow ( 2 , summaryAttempt - 1 ) , 8000 ) ;
1464+ await new Promise ( ( resolve ) => setTimeout ( resolve , backoffMs ) ) ;
14511465 }
14521466 }
14531467
14541468 let responseContent : Content | null = null ;
14551469 const summaryText = summary ?. text ;
14561470 if ( typeof summaryText === 'string' && summaryText ) {
1471+ const summaryThought = summary ?. thought ;
14571472 responseContent = {
14581473 actions : [ 'MULTI_STEP_SUMMARY' ] ,
14591474 text : summaryText ,
14601475 thought :
1461- ( typeof summary . thought === 'string'
1462- ? summary . thought
1476+ ( typeof summaryThought === 'string'
1477+ ? summaryThought
14631478 : 'Final user-facing message after task completion.' ) ||
14641479 'Final user-facing message after task completion.' ,
14651480 simple : true ,
0 commit comments