({
messages,
summaryRequest,
appState,
context,
preCompactTokenCount,
cacheSafeParams,
}: {
messages: Message[]
summaryRequest: UserMessage
appState: Awaited<ReturnType<ToolUseContext['getAppState']>>
context: ToolUseContext
preCompactTokenCount: number
cacheSafeParams: CacheSafeParams
})
| 1146 | } |
| 1147 | |
| 1148 | async function streamCompactSummary({ |
| 1149 | messages, |
| 1150 | summaryRequest, |
| 1151 | appState, |
| 1152 | context, |
| 1153 | preCompactTokenCount, |
| 1154 | cacheSafeParams, |
| 1155 | }: { |
| 1156 | messages: Message[] |
| 1157 | summaryRequest: UserMessage |
| 1158 | appState: Awaited<ReturnType<ToolUseContext['getAppState']>> |
| 1159 | context: ToolUseContext |
| 1160 | preCompactTokenCount: number |
| 1161 | cacheSafeParams: CacheSafeParams |
| 1162 | }): Promise<AssistantMessage> { |
| 1163 | // Send keep-alive signals during compaction to prevent remote session |
| 1164 | // WebSocket idle timeouts from dropping bridge connections. Compaction |
| 1165 | // API calls can take 5-10+ seconds, during which no other messages |
| 1166 | // flow through the transport — without keep-alives, the server may |
| 1167 | // close the WebSocket for inactivity. |
| 1168 | // Two signals: (1) PUT /worker heartbeat via sessionActivity, and |
| 1169 | // (2) re-emit 'compacting' status so the SDK event stream stays active |
| 1170 | // and the server doesn't consider the session stale. |
| 1171 | const activityInterval = isSessionActivityTrackingActive() |
| 1172 | ? setInterval( |
| 1173 | (statusSetter?: (status: 'compacting' | null) => void) => { |
| 1174 | sendSessionActivitySignal() |
| 1175 | statusSetter?.('compacting') |
| 1176 | }, |
| 1177 | 30_000, |
| 1178 | context.setSDKStatus, |
| 1179 | ) |
| 1180 | : undefined |
| 1181 | |
| 1182 | try { |
| 1183 | const summary = await withTimeout( |
| 1184 | streamCompactSummaryInner( |
| 1185 | messages, |
| 1186 | summaryRequest, |
| 1187 | appState, |
| 1188 | context, |
| 1189 | preCompactTokenCount, |
| 1190 | cacheSafeParams, |
| 1191 | ), |
| 1192 | COMPACT_SUMMARY_TIMEOUT_MS, |
| 1193 | 'compact summary exceeded timeout', |
| 1194 | ) |
| 1195 | return summary |
| 1196 | } catch (error) { |
| 1197 | if ( |
| 1198 | error instanceof Error && |
| 1199 | error.message === 'compact summary exceeded timeout' |
| 1200 | ) { |
| 1201 | // Mirror the SDK timeout shape so upstream error handling maps this to |
| 1202 | // API_TIMEOUT_ERROR_MESSAGE and the PTL retry logic treats it as a |
| 1203 | // retriable API failure rather than a successful empty summary. |
| 1204 | throw new APIConnectionTimeoutError({ message: 'Request timed out' }) |
| 1205 | } |
no test coverage detected