fix(background-agent): stabilize parent wakes
This commit is contained in:
@@ -109,6 +109,7 @@ type PendingParentWake = {
|
||||
notifications: string[]
|
||||
shouldReply: boolean
|
||||
dispatchedAt?: number
|
||||
toolCallDeferralStartedAt?: number
|
||||
}
|
||||
|
||||
type ParentWakeSessionMessage = {
|
||||
@@ -145,6 +146,7 @@ type ResumeTaskSnapshot = {
|
||||
const PENDING_PARENT_WAKE_RETRY_MS = 1_000
|
||||
const PENDING_PARENT_WAKE_DEBOUNCE_MS = 100
|
||||
const PARENT_WAKE_ACCEPTED_MESSAGE_SKEW_MS = 5_000
|
||||
const PARENT_WAKE_TOOL_CALL_DEFER_MAX_MS = 5_000
|
||||
|
||||
interface MessagePartInfo {
|
||||
id?: string
|
||||
@@ -1380,6 +1382,9 @@ The fallback retry session is now created and can be inspected directly.
|
||||
notifications: [...wake.notifications],
|
||||
shouldReply: wake.shouldReply,
|
||||
...(wake.dispatchedAt !== undefined ? { dispatchedAt: wake.dispatchedAt } : {}),
|
||||
...(wake.toolCallDeferralStartedAt !== undefined
|
||||
? { toolCallDeferralStartedAt: wake.toolCallDeferralStartedAt }
|
||||
: {}),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1410,6 +1415,8 @@ The fallback retry session is now created and can be inspected directly.
|
||||
return false
|
||||
}
|
||||
|
||||
await settleAfterSessionIdle()
|
||||
|
||||
if (await this.hasAcceptedMessageAfterDispatchedParentWake(sessionID, wake)) {
|
||||
this.clearDispatchedParentWake(sessionID)
|
||||
log("[background-agent] Ignored late parent wake failure after assistant output:", {
|
||||
@@ -1425,6 +1432,7 @@ The fallback retry session is now created and can be inspected directly.
|
||||
pendingWake.notifications.unshift(...wake.notifications)
|
||||
pendingWake.shouldReply = pendingWake.shouldReply || wake.shouldReply
|
||||
pendingWake.promptContext = wake.promptContext
|
||||
pendingWake.toolCallDeferralStartedAt ??= wake.toolCallDeferralStartedAt
|
||||
} else {
|
||||
this.pendingParentWakes.set(sessionID, this.cloneParentWake(wake))
|
||||
}
|
||||
@@ -1531,9 +1539,18 @@ The fallback retry session is now created and can be inspected directly.
|
||||
) ?? false
|
||||
}
|
||||
|
||||
private async shouldDeferParentWakeForSessionHistory(sessionID: string): Promise<boolean> {
|
||||
private async shouldDeferParentWakeForSessionHistory(sessionID: string, wake: PendingParentWake): Promise<boolean> {
|
||||
const messages = await this.loadParentWakeSessionMessages(sessionID)
|
||||
if (!this.latestAssistantTurnIsWaitingOnTools(messages)) {
|
||||
delete wake.toolCallDeferralStartedAt
|
||||
return false
|
||||
}
|
||||
const now = Date.now()
|
||||
wake.toolCallDeferralStartedAt ??= now
|
||||
if (wake.shouldReply && now - wake.toolCallDeferralStartedAt >= PARENT_WAKE_TOOL_CALL_DEFER_MAX_MS) {
|
||||
log("[background-agent] Sending parent wake after stale tool-call deferral window:", {
|
||||
sessionID,
|
||||
})
|
||||
return false
|
||||
}
|
||||
log("[background-agent] Deferred parent wake because latest assistant turn is waiting on tool results:", {
|
||||
@@ -2694,15 +2711,16 @@ The task was re-queued on a fallback model after a retryable failure.
|
||||
return
|
||||
}
|
||||
|
||||
if (await this.shouldDeferParentWakeForSessionHistory(sessionID)) {
|
||||
this.schedulePendingParentWakeFlush(sessionID)
|
||||
return
|
||||
}
|
||||
|
||||
const latestWake = this.pendingParentWakes.get(sessionID)
|
||||
if (!latestWake) {
|
||||
return
|
||||
}
|
||||
|
||||
if (await this.shouldDeferParentWakeForSessionHistory(sessionID, latestWake)) {
|
||||
this.schedulePendingParentWakeFlush(sessionID)
|
||||
return
|
||||
}
|
||||
|
||||
this.pendingParentWakes.delete(sessionID)
|
||||
|
||||
const notificationContent = latestWake.notifications.join("\n\n")
|
||||
@@ -2733,6 +2751,7 @@ The task was re-queued on a fallback model after a retryable failure.
|
||||
pendingWake.notifications.unshift(...latestWake.notifications)
|
||||
pendingWake.shouldReply = pendingWake.shouldReply || latestWake.shouldReply
|
||||
pendingWake.promptContext = latestWake.promptContext
|
||||
pendingWake.toolCallDeferralStartedAt ??= latestWake.toolCallDeferralStartedAt
|
||||
} else {
|
||||
this.pendingParentWakes.set(sessionID, latestWake)
|
||||
}
|
||||
@@ -2751,6 +2770,7 @@ The task was re-queued on a fallback model after a retryable failure.
|
||||
pendingWake.notifications.unshift(...latestWake.notifications)
|
||||
pendingWake.shouldReply = pendingWake.shouldReply || latestWake.shouldReply
|
||||
pendingWake.promptContext = latestWake.promptContext
|
||||
pendingWake.toolCallDeferralStartedAt ??= latestWake.toolCallDeferralStartedAt
|
||||
} else {
|
||||
this.pendingParentWakes.set(sessionID, latestWake)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user