Skip to content

Commit 4a70901

Browse files
wtfsayoclaude
andcommitted
fix(core): resolve TypeScript errors in multi-step workflow
- Fix parseInt type errors by casting getSetting result to string - Add bounds checking for retry counts (1-10 range) - Add exponential backoff for retries (1s, 2s, 4s... capped at 8s) - Fix null check for summary.thought access 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <[email protected]>
1 parent ff4af56 commit 4a70901

File tree

1 file changed

+27
-12
lines changed

1 file changed

+27
-12
lines changed

packages/core/src/services/default-message-service.ts

Lines changed: 27 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)