MCPcopy
hub / github.com/coder/mux / dispatchPendingFollowUp

Method dispatchPendingFollowUp

src/node/services/agentSession.ts:5315–5473  ·  view source on GitHub ↗

* Dispatch the pending follow-up from a compaction summary message. * Called after compaction completes - the follow-up is stored on the summary * for crash safety. The user message persisted by sendMessage() serves as * proof of dispatch (no history rewrite needed).

(summaryMessageId?: string)

Source from the content-addressed store, hash-verified

5313 * proof of dispatch (no history rewrite needed).
5314 */
5315 private async dispatchPendingFollowUp(summaryMessageId?: string): Promise<boolean> {
5316 if (this.disposed) {
5317 return false;
5318 }
5319
5320 let summaryMessage: MuxMessage | undefined;
5321 if (summaryMessageId) {
5322 const historyResult = await this.historyService.getHistoryFromLatestBoundary(
5323 this.workspaceId
5324 );
5325 if (!historyResult.success) {
5326 throw new Error(
5327 `Failed to read history for targeted follow-up recovery: ${historyResult.error}`
5328 );
5329 }
5330 summaryMessage = historyResult.data.find((message) => message.id === summaryMessageId);
5331 if (!summaryMessage) {
5332 return false;
5333 }
5334 } else {
5335 // Read the last message from history — only need 1 message, avoid full-file read.
5336 // Startup recovery must retry on transient read failures, so bubble errors.
5337 const historyResult = await this.historyService.getLastMessages(this.workspaceId, 1);
5338 if (!historyResult.success) {
5339 const historyError =
5340 typeof historyResult.error === "string"
5341 ? historyResult.error
5342 : getErrorMessage(historyResult.error);
5343 throw new Error(`Failed to read history for startup follow-up recovery: ${historyError}`);
5344 }
5345
5346 if (historyResult.data.length === 0) {
5347 return false;
5348 }
5349 summaryMessage = historyResult.data[0];
5350 }
5351
5352 const lastMessage = summaryMessage;
5353 const muxMeta = lastMessage.metadata?.muxMetadata;
5354
5355 // Check if it's a compaction summary with a pending follow-up
5356 if (!isCompactionSummaryMetadata(muxMeta) || !muxMeta.pendingFollowUp) {
5357 return false;
5358 }
5359
5360 // Handle legacy formats: older persisted requests may have `mode` instead of `agentId`,
5361 // and `imageParts` instead of `fileParts`.
5362 const followUp = muxMeta.pendingFollowUp as typeof muxMeta.pendingFollowUp & {
5363 mode?: "exec" | "plan";
5364 imageParts?: FilePart[];
5365 };
5366
5367 const hasQueuedMessages = this.hasPendingManualFollowUp();
5368 const hasActiveNonCompletingTurn = this.isBusy() && this.turnPhase !== TurnPhase.COMPLETING;
5369 if (
5370 followUp.dispatchOptions?.requireIdle === true &&
5371 (hasQueuedMessages || hasActiveNonCompletingTurn)
5372 ) {

Calls 13

isBusyMethod · 0.95
sendMessageMethod · 0.95
getErrorMessageFunction · 0.90
getLastMessagesMethod · 0.80

Tested by

no test coverage detected