fix(background-agent): extend default no-progress stale timeout to 30 minutes

Give never-updated background tasks a longer default window and keep the default-threshold regression coverage aligned with that behavior.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
YeonGyu-Kim
2026-03-12 01:14:35 +09:00
parent 6d5175b9b0
commit aaa54858a3
3 changed files with 64 additions and 4 deletions

View File

@@ -4,7 +4,7 @@ import type { BackgroundTask, LaunchInput } from "./types"
export const TASK_TTL_MS = 30 * 60 * 1000
export const MIN_STABILITY_TIME_MS = 10 * 1000
export const DEFAULT_STALE_TIMEOUT_MS = 180_000
export const DEFAULT_MESSAGE_STALENESS_TIMEOUT_MS = 600_000
export const DEFAULT_MESSAGE_STALENESS_TIMEOUT_MS = 1_800_000
export const MIN_RUNTIME_BEFORE_STALE_MS = 30_000
export const MIN_IDLE_TIME_MS = 5000
export const POLLING_INTERVAL_MS = 3000

View File

@@ -0,0 +1,60 @@
declare const require: (name: string) => any
const { describe, expect, test, mock } = require("bun:test")
import { DEFAULT_MESSAGE_STALENESS_TIMEOUT_MS } from "./constants"
import { checkAndInterruptStaleTasks } from "./task-poller"
import type { BackgroundTask } from "./types"
function createRunningTask(startedAt: Date): BackgroundTask {
return {
id: "task-1",
sessionID: "ses-1",
parentSessionID: "parent-ses-1",
parentMessageID: "msg-1",
description: "test",
prompt: "test",
agent: "explore",
status: "running",
startedAt,
progress: undefined,
}
}
describe("DEFAULT_MESSAGE_STALENESS_TIMEOUT_MS", () => {
test("uses a 30 minute default", () => {
// #given
const expectedTimeout = 30 * 60 * 1000
// #when
const timeout = DEFAULT_MESSAGE_STALENESS_TIMEOUT_MS
// #then
expect(timeout).toBe(expectedTimeout)
})
test("does not interrupt a never-updated task after 15 minutes when config is omitted", async () => {
// #given
const task = createRunningTask(new Date(Date.now() - 15 * 60 * 1000))
const client = {
session: {
abort: mock(() => Promise.resolve()),
},
}
const concurrencyManager = {
release: mock(() => {}),
}
const notifyParentSession = mock(() => Promise.resolve())
// #when
await checkAndInterruptStaleTasks({
tasks: [task],
client: client as never,
config: undefined,
concurrencyManager: concurrencyManager as never,
notifyParentSession,
})
// #then
expect(task.status).toBe("running")
})
})

View File

@@ -117,13 +117,13 @@ describe("checkAndInterruptStaleTasks", () => {
})
it("should use DEFAULT_MESSAGE_STALENESS_TIMEOUT_MS when messageStalenessTimeoutMs is not configured", async () => {
//#given — task started 15 minutes ago, no config for messageStalenessTimeoutMs
//#given — task started 35 minutes ago, no config for messageStalenessTimeoutMs
const task = createRunningTask({
startedAt: new Date(Date.now() - 15 * 60 * 1000),
startedAt: new Date(Date.now() - 35 * 60 * 1000),
progress: undefined,
})
//#when — default is 10 minutes (600_000ms)
//#when — default is 30 minutes (1_800_000ms)
await checkAndInterruptStaleTasks({
tasks: [task],
client: mockClient as never,