diff --git a/src/features/background-agent/manager.ts b/src/features/background-agent/manager.ts index c4ea7528b..4de7298d6 100644 --- a/src/features/background-agent/manager.ts +++ b/src/features/background-agent/manager.ts @@ -543,6 +543,9 @@ export class BackgroundManager { existingTask.error = errorMessage } existingTask.completedAt = new Date() + if (existingTask.rootSessionID) { + this.unregisterRootDescendant(existingTask.rootSessionID) + } if (existingTask.concurrencyKey) { this.concurrencyManager.release(existingTask.concurrencyKey) existingTask.concurrencyKey = undefined @@ -813,6 +816,9 @@ export class BackgroundManager { const errorMessage = error instanceof Error ? error.message : String(error) existingTask.error = errorMessage existingTask.completedAt = new Date() + if (existingTask.rootSessionID) { + this.unregisterRootDescendant(existingTask.rootSessionID) + } // Release concurrency on error to prevent slot leaks if (existingTask.concurrencyKey) { @@ -1009,6 +1015,9 @@ export class BackgroundManager { task.status = "error" task.error = errorMsg task.completedAt = new Date() + if (task.rootSessionID) { + this.unregisterRootDescendant(task.rootSessionID) + } this.taskHistory.record(task.parentSessionID, { id: task.id, sessionID: task.sessionID, agent: task.agent, description: task.description, status: "error", category: task.category, startedAt: task.startedAt, completedAt: task.completedAt }) if (task.concurrencyKey) { @@ -1341,8 +1350,12 @@ export class BackgroundManager { log("[background-agent] Cancelled pending task:", { taskId, key }) } + const wasRunning = task.status === "running" task.status = "cancelled" task.completedAt = new Date() + if (wasRunning && task.rootSessionID) { + this.unregisterRootDescendant(task.rootSessionID) + } if (reason) { task.error = reason } @@ -1463,6 +1476,10 @@ export class BackgroundManager { task.completedAt = new Date() this.taskHistory.record(task.parentSessionID, { id: task.id, sessionID: task.sessionID, agent: task.agent, description: task.description, status: "completed", category: task.category, startedAt: task.startedAt, completedAt: task.completedAt }) + if (task.rootSessionID) { + this.unregisterRootDescendant(task.rootSessionID) + } + removeTaskToastTracking(task.id) // Release concurrency BEFORE any async operations to prevent slot leaks @@ -1701,6 +1718,9 @@ Use \`background_output(task_id="${task.id}")\` to retrieve this result when rea task.status = "error" task.error = errorMessage task.completedAt = new Date() + if (!wasPending && task.rootSessionID) { + this.unregisterRootDescendant(task.rootSessionID) + } this.taskHistory.record(task.parentSessionID, { id: task.id, sessionID: task.sessionID, agent: task.agent, description: task.description, status: "error", category: task.category, startedAt: task.startedAt, completedAt: task.completedAt }) if (task.concurrencyKey) { this.concurrencyManager.release(task.concurrencyKey)