compaction & branch summarization follow retry policy

fixes #6647

compaction (auto & manual) and branch summarization retry on transient failures.
use the same retry policy from settings.
emit events for the tui to show indication of retries
This commit is contained in:
David Brailovsky
2026-07-21 10:07:20 +00:00
parent 890b3547af
commit 8e53e0e49c
7 changed files with 546 additions and 16 deletions
@@ -41,6 +41,7 @@ import {
isContextOverflow,
isRetryableAssistantError,
modelsAreEqual,
type RetryCallbacks,
resetApiProviders,
streamSimple,
} from "@earendil-works/pi-ai/compat";
@@ -161,7 +162,21 @@ export type AgentSessionEvent =
errorMessage?: string;
}
| { type: "auto_retry_start"; attempt: number; maxAttempts: number; delayMs: number; errorMessage: string }
| { type: "auto_retry_end"; success: boolean; attempt: number; finalError?: string };
| { type: "auto_retry_end"; success: boolean; attempt: number; finalError?: string }
| {
type: "summarization_retry_start";
attempt: number;
maxAttempts: number;
delayMs: number;
errorMessage: string;
}
| { type: "summarization_retry_attempt_start"; source: "branchSummary" }
| {
type: "summarization_retry_attempt_start";
source: "compaction";
reason: "manual" | "threshold" | "overflow";
}
| { type: "summarization_retry_end" };
/** Listener function for agent session events */
export type AgentSessionEventListener = (event: AgentSessionEvent) => void;
@@ -1838,6 +1853,8 @@ export class AgentSession {
this.thinkingLevel,
this.agent.streamFunction,
env,
this.settingsManager.getRetrySettings(),
this._summarizationRetryCallbacks({ source: "compaction", reason: "manual" }),
);
summary = result.summary;
firstKeptEntryId = result.firstKeptEntryId;
@@ -2114,6 +2131,8 @@ export class AgentSession {
this.thinkingLevel,
this.agent.streamFunction,
env,
this.settingsManager.getRetrySettings(),
this._summarizationRetryCallbacks({ source: "compaction", reason }),
);
summary = compactResult.summary;
firstKeptEntryId = compactResult.firstKeptEntryId;
@@ -2620,6 +2639,37 @@ export class AgentSession {
return isRetryableAssistantError(message);
}
/**
* Retry policy + callbacks shared by compaction and branch-summary summarization calls.
* Uses the same `settings.retry` budget/backoff as agent-turn retries so a single transient
* stream drop no longer fails the whole operation. `source` carries the context
* the TUI needs to render the retry and recreate the underlying indicator.
*/
private _summarizationRetryCallbacks(
source: { source: "branchSummary" } | { source: "compaction"; reason: "manual" | "threshold" | "overflow" },
): RetryCallbacks {
return {
onRetry: (attempt, maxAttempts, delayMs, errorMessage) => {
this._emit({
type: "summarization_retry_start",
attempt,
maxAttempts,
delayMs,
errorMessage,
});
},
onRetryAttemptStart: () => {
this._emit({
type: "summarization_retry_attempt_start",
...source,
});
},
onRetryEnd: () => {
this._emit({ type: "summarization_retry_end" });
},
};
}
/**
* Prepare a retryable error for continuation with exponential backoff.
* @returns true if the caller should continue the agent, false otherwise
@@ -2934,6 +2984,8 @@ export class AgentSession {
replaceInstructions,
reserveTokens: branchSummarySettings.reserveTokens,
streamFn: this.agent.streamFunction,
retry: this.settingsManager.getRetrySettings(),
callbacks: this._summarizationRetryCallbacks({ source: "branchSummary" }),
});
if (result.aborted) {
return { cancelled: true, aborted: true };