Subagents: restore announce chain + fix nested retry/drop regressions (#22223)

* Subagents: restore announce flow and fix nested delivery retries

* fix: prep subagent announce + docs alignment (#22223) (thanks @tyler6204)
This commit is contained in:
Tyler Yust
2026-02-20 15:39:09 -08:00
committed by GitHub
parent 086af56867
commit fe57bea088
21 changed files with 579 additions and 985 deletions

View File

@@ -102,7 +102,6 @@ function startSubagentAnnounceCleanupFlow(runId: string, entry: SubagentRunRecor
requesterOrigin,
requesterDisplayKey: entry.requesterDisplayKey,
task: entry.task,
expectsCompletionMessage: entry.expectsCompletionMessage,
timeoutMs: SUBAGENT_ANNOUNCE_TIMEOUT_MS,
cleanup: entry.cleanup,
waitForCompletion: false,
@@ -324,12 +323,34 @@ function finalizeSubagentCleanup(runId: string, cleanup: "delete" | "keep", didA
}
if (!didAnnounce) {
const now = Date.now();
const endedAgo = typeof entry.endedAt === "number" ? now - entry.endedAt : 0;
// Normal defer: the run ended, but descendant runs are still active.
// Don't consume retry budget in this state or we can give up before
// descendants finish and before the parent synthesizes the final reply.
const activeDescendantRuns = Math.max(0, countActiveDescendantRuns(entry.childSessionKey));
if (entry.expectsCompletionMessage === true && activeDescendantRuns > 0) {
if (endedAgo > ANNOUNCE_EXPIRY_MS) {
logAnnounceGiveUp(entry, "expiry");
entry.cleanupCompletedAt = now;
persistSubagentRuns();
retryDeferredCompletedAnnounces(runId);
return;
}
entry.lastAnnounceRetryAt = now;
entry.cleanupHandled = false;
resumedRuns.delete(runId);
persistSubagentRuns();
setTimeout(() => {
resumeSubagentRun(runId);
}, MIN_ANNOUNCE_RETRY_DELAY_MS).unref?.();
return;
}
const retryCount = (entry.announceRetryCount ?? 0) + 1;
entry.announceRetryCount = retryCount;
entry.lastAnnounceRetryAt = now;
// Check if the announce has exceeded retry limits or expired (#18264).
const endedAgo = typeof entry.endedAt === "number" ? now - entry.endedAt : 0;
if (retryCount >= MAX_ANNOUNCE_RETRY_COUNT || endedAgo > ANNOUNCE_EXPIRY_MS) {
// Give up: mark as completed to break the infinite retry loop.
logAnnounceGiveUp(entry, retryCount >= MAX_ANNOUNCE_RETRY_COUNT ? "retry-limit" : "expiry");