Merge pull request #3825 from tw-yshuang/fix/delegated-child-session-early-failure-fallback
fix(delegate-task): harden child-session first-prompt fallback recovery
This commit is contained in:
@@ -95,6 +95,11 @@ import {
|
||||
resolveSubagentSpawnContext,
|
||||
type SubagentSpawnContext,
|
||||
} from "./subagent-spawn-limits"
|
||||
import {
|
||||
clearDelegatedChildSessionBootstrap,
|
||||
registerDelegatedChildSessionBootstrap,
|
||||
} from "../../shared/delegated-child-session-bootstrap"
|
||||
import { settleAfterSessionIdle } from "../../hooks/shared/session-idle-settle"
|
||||
type OpencodeClient = PluginInput["client"]
|
||||
|
||||
type ParentWakePromptContext = {
|
||||
@@ -318,6 +323,12 @@ export class BackgroundManager {
|
||||
}
|
||||
}
|
||||
|
||||
private cleanupDelegatedSessionContext(sessionID: string): void {
|
||||
clearDelegatedChildSessionBootstrap(sessionID)
|
||||
this.modelFallbackControllerAccessor?.clearSessionFallbackChain(sessionID)
|
||||
SessionCategoryRegistry.remove(sessionID)
|
||||
}
|
||||
|
||||
async assertCanSpawn(parentSessionID: string): Promise<SubagentSpawnContext> {
|
||||
const spawnContext = await resolveSubagentSpawnContext(this.client, parentSessionID, this.directory)
|
||||
const maxDepth = getMaxSubagentDepth(this.config)
|
||||
@@ -796,6 +807,14 @@ export class BackgroundManager {
|
||||
return
|
||||
}
|
||||
|
||||
registerDelegatedChildSessionBootstrap({
|
||||
sessionID,
|
||||
promptText: input.prompt,
|
||||
fallbackChain: input.fallbackChain,
|
||||
category: input.category,
|
||||
modelFallbackControllerAccessor: this.modelFallbackControllerAccessor,
|
||||
})
|
||||
|
||||
task.progress = {
|
||||
toolCalls: 0,
|
||||
lastUpdate: new Date(),
|
||||
@@ -963,6 +982,7 @@ The fallback retry session is now created and can be inspected directly.
|
||||
// Abort the session to prevent infinite polling hang
|
||||
// Awaited to prevent dangling promise during subagent teardown (Bun/WebKit SIGABRT)
|
||||
await this.abortSessionWithLogging(sessionID, "launch error cleanup")
|
||||
this.cleanupDelegatedSessionContext(sessionID)
|
||||
|
||||
this.markForNotification(existingTask)
|
||||
this.enqueueNotificationForParent(existingTask.parentSessionId, () => this.notifyParentSession(existingTask)).catch(err => {
|
||||
@@ -1863,7 +1883,7 @@ The fallback retry session is now created and can be inspected directly.
|
||||
}
|
||||
|
||||
this.rootDescendantCounts.delete(sessionID)
|
||||
SessionCategoryRegistry.remove(sessionID)
|
||||
this.cleanupDelegatedSessionContext(sessionID)
|
||||
}
|
||||
|
||||
if (event.type === "session.status") {
|
||||
@@ -2051,7 +2071,7 @@ The fallback retry session is now created and can be inspected directly.
|
||||
}
|
||||
this.scheduleTaskRemoval(task.id)
|
||||
if (task.sessionId) {
|
||||
SessionCategoryRegistry.remove(task.sessionId)
|
||||
this.cleanupDelegatedSessionContext(task.sessionId)
|
||||
}
|
||||
|
||||
// Update continuation marker for CLI run mode
|
||||
@@ -2109,6 +2129,7 @@ The task was re-queued on a fallback model after a retryable failure.
|
||||
this.clearSessionOutputObserved(previousSessionID)
|
||||
this.clearSessionTodoObservation(previousSessionID)
|
||||
subagentSessions.delete(previousSessionID)
|
||||
this.cleanupDelegatedSessionContext(previousSessionID)
|
||||
}
|
||||
return retried
|
||||
}
|
||||
@@ -2272,7 +2293,7 @@ The task was re-queued on a fallback model after a retryable failure.
|
||||
this.clearTaskHistoryWhenParentTasksGone(task.parentSessionId)
|
||||
if (task.sessionId) {
|
||||
subagentSessions.delete(task.sessionId)
|
||||
SessionCategoryRegistry.remove(task.sessionId)
|
||||
this.cleanupDelegatedSessionContext(task.sessionId)
|
||||
}
|
||||
log("[background-agent] Removed completed task from memory:", taskId)
|
||||
}, TASK_CLEANUP_DELAY_MS)
|
||||
@@ -2347,7 +2368,7 @@ The task was re-queued on a fallback model after a retryable failure.
|
||||
// Awaited to prevent dangling promise during subagent teardown (Bun/WebKit SIGABRT)
|
||||
await this.abortSessionWithLogging(task.sessionId, `task cancellation (${source})`)
|
||||
|
||||
SessionCategoryRegistry.remove(task.sessionId)
|
||||
this.cleanupDelegatedSessionContext(task.sessionId)
|
||||
}
|
||||
|
||||
removeTaskToastTracking(task.id)
|
||||
@@ -2472,7 +2493,7 @@ The task was re-queued on a fallback model after a retryable failure.
|
||||
// Awaited to prevent dangling promise during subagent teardown (Bun/WebKit SIGABRT)
|
||||
await this.abortSessionWithLogging(task.sessionId, `task completion (${source})`)
|
||||
|
||||
SessionCategoryRegistry.remove(task.sessionId)
|
||||
this.cleanupDelegatedSessionContext(task.sessionId)
|
||||
}
|
||||
|
||||
// Update continuation marker for CLI run mode
|
||||
@@ -2921,7 +2942,7 @@ The task was re-queued on a fallback model after a retryable failure.
|
||||
removeTaskToastTracking(task.id)
|
||||
this.scheduleTaskRemoval(task.id)
|
||||
if (task.sessionId) {
|
||||
SessionCategoryRegistry.remove(task.sessionId)
|
||||
this.cleanupDelegatedSessionContext(task.sessionId)
|
||||
}
|
||||
|
||||
// Update continuation marker for CLI run mode
|
||||
@@ -3136,7 +3157,7 @@ The task was re-queued on a fallback model after a retryable failure.
|
||||
|
||||
for (const sessionID of trackedSessionIDs) {
|
||||
subagentSessions.delete(sessionID)
|
||||
SessionCategoryRegistry.remove(sessionID)
|
||||
this.cleanupDelegatedSessionContext(sessionID)
|
||||
}
|
||||
|
||||
this.concurrencyManager.clear()
|
||||
|
||||
Reference in New Issue
Block a user