feat(background-task): make taskCleanupDelayMs configurable

TASK_CLEANUP_DELAY_MS is the delay between a task reaching a terminal
state (completed/cancelled/errored) and its removal from the in-memory
task store. It is currently a hard-coded 10 minute constant, which is
too short for long-running background workflows: users routinely hit
'task not found' on background_output lookups when they inspect
results more than ~10 minutes after completion.

taskTtlMs (landed in #2825) already exposes the non-terminal task TTL
on BackgroundTaskConfigSchema. This PR mirrors that pattern for the
terminal-state cleanup delay:

- Add taskCleanupDelayMs: z.number().min(60000).optional() to
  BackgroundTaskConfigSchema with JSDoc matching taskTtlMs's style.
- BackgroundManager.scheduleCompletionRemoval() reads
  this.config?.taskCleanupDelayMs ?? TASK_CLEANUP_DELAY_MS, preserving
  the existing 10 min default for unconfigured users.
- Regenerate assets/oh-my-opencode.schema.json.

Default: 600000 ms (10 min, unchanged from current hard-coded value).
Minimum: 60000 ms (1 min).

bun run typecheck: clean.
bun test src/features/background-agent: 411/411 pass.
This commit is contained in:
cpkt9762
2026-04-06 12:44:12 +08:00
parent ed62f827e3
commit 14c25cbbf5
3 changed files with 7 additions and 1 deletions
+4
View File
@@ -5687,6 +5687,10 @@
"type": "number",
"minimum": 10000
},
"taskCleanupDelayMs": {
"type": "number",
"minimum": 60000
},
"syncPollTimeoutMs": {
"type": "number",
"minimum": 60000
+2
View File
@@ -20,6 +20,8 @@ export const BackgroundTaskConfigSchema = z.object({
taskTtlMs: z.number().min(300000).optional(),
/** Timeout for tasks whose session has completely disappeared from the status registry (default: 60000 = 1 minute, minimum: 10000 = 10 seconds). When a session is gone (likely crashed), this shorter timeout is used instead of the normal stale timeout. */
sessionGoneTimeoutMs: z.number().min(10000).optional(),
/** Delay before removing completed/cancelled/errored tasks from memory in milliseconds (default: 600000 = 10 minutes, minimum: 60000 = 1 minute). */
taskCleanupDelayMs: z.number().min(60000).optional(),
syncPollTimeoutMs: z.number().min(60000).optional(),
/** Maximum tool calls per subagent task before circuit breaker triggers (default: 200, minimum: 10). Prevents runaway loops from burning unlimited tokens. */
maxToolCalls: z.number().int().min(10).optional(),
+1 -1
View File
@@ -1510,7 +1510,7 @@ export class BackgroundManager {
SessionCategoryRegistry.remove(task.sessionID)
}
log("[background-agent] Removed completed task from memory:", taskId)
}, TASK_CLEANUP_DELAY_MS)
}, this.config?.taskCleanupDelayMs ?? TASK_CLEANUP_DELAY_MS)
this.completionTimers.set(taskId, timer)
}