fix(todo-continuation-enforcer): check isContinuationStopped in injectContinuation to close /stop-continuation race
fix(todo-continuation-enforcer): check isContinuationStopped in injectContinuation to close /stop-continuation race
This commit is contained in:
commit
fb596ed149
@ -37,6 +37,7 @@ export async function injectContinuation(args: {
|
|||||||
skipAgents?: string[]
|
skipAgents?: string[]
|
||||||
resolvedInfo?: ResolvedMessageInfo
|
resolvedInfo?: ResolvedMessageInfo
|
||||||
sessionStateStore: SessionStateStore
|
sessionStateStore: SessionStateStore
|
||||||
|
isContinuationStopped?: (sessionID: string) => boolean
|
||||||
}): Promise<void> {
|
}): Promise<void> {
|
||||||
const {
|
const {
|
||||||
ctx,
|
ctx,
|
||||||
@ -45,6 +46,7 @@ export async function injectContinuation(args: {
|
|||||||
skipAgents = DEFAULT_SKIP_AGENTS,
|
skipAgents = DEFAULT_SKIP_AGENTS,
|
||||||
resolvedInfo,
|
resolvedInfo,
|
||||||
sessionStateStore,
|
sessionStateStore,
|
||||||
|
isContinuationStopped,
|
||||||
} = args
|
} = args
|
||||||
|
|
||||||
const state = sessionStateStore.getExistingState(sessionID)
|
const state = sessionStateStore.getExistingState(sessionID)
|
||||||
@ -53,6 +55,11 @@ export async function injectContinuation(args: {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isContinuationStopped?.(sessionID)) {
|
||||||
|
log(`[${HOOK_NAME}] Skipped injection: continuation stopped for session`, { sessionID })
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
const hasRunningBgTasks = backgroundManager
|
const hasRunningBgTasks = backgroundManager
|
||||||
? backgroundManager.getTasksByParentSession(sessionID).some((task: { status: string }) => task.status === "running")
|
? backgroundManager.getTasksByParentSession(sessionID).some((task: { status: string }) => task.status === "running")
|
||||||
: false
|
: false
|
||||||
|
|||||||
@ -38,6 +38,7 @@ export function startCountdown(args: {
|
|||||||
backgroundManager?: BackgroundManager
|
backgroundManager?: BackgroundManager
|
||||||
skipAgents: string[]
|
skipAgents: string[]
|
||||||
sessionStateStore: SessionStateStore
|
sessionStateStore: SessionStateStore
|
||||||
|
isContinuationStopped?: (sessionID: string) => boolean
|
||||||
}): void {
|
}): void {
|
||||||
const {
|
const {
|
||||||
ctx,
|
ctx,
|
||||||
@ -47,6 +48,7 @@ export function startCountdown(args: {
|
|||||||
backgroundManager,
|
backgroundManager,
|
||||||
skipAgents,
|
skipAgents,
|
||||||
sessionStateStore,
|
sessionStateStore,
|
||||||
|
isContinuationStopped,
|
||||||
} = args
|
} = args
|
||||||
|
|
||||||
const state = sessionStateStore.getState(sessionID)
|
const state = sessionStateStore.getState(sessionID)
|
||||||
@ -72,6 +74,7 @@ export function startCountdown(args: {
|
|||||||
skipAgents,
|
skipAgents,
|
||||||
resolvedInfo,
|
resolvedInfo,
|
||||||
sessionStateStore,
|
sessionStateStore,
|
||||||
|
isContinuationStopped,
|
||||||
})
|
})
|
||||||
}, COUNTDOWN_SECONDS * 1000)
|
}, COUNTDOWN_SECONDS * 1000)
|
||||||
|
|
||||||
|
|||||||
@ -187,5 +187,6 @@ export async function handleSessionIdle(args: {
|
|||||||
backgroundManager,
|
backgroundManager,
|
||||||
skipAgents,
|
skipAgents,
|
||||||
sessionStateStore,
|
sessionStateStore,
|
||||||
|
isContinuationStopped,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1608,6 +1608,31 @@ describe("todo-continuation-enforcer", () => {
|
|||||||
expect(promptCalls).toHaveLength(0)
|
expect(promptCalls).toHaveLength(0)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test("should not inject when isContinuationStopped becomes true during countdown", async () => {
|
||||||
|
// given - session where continuation is not stopped at idle time but stops during countdown
|
||||||
|
const sessionID = "main-race-condition"
|
||||||
|
setMainSession(sessionID)
|
||||||
|
let stopped = false
|
||||||
|
|
||||||
|
const hook = createTodoContinuationEnforcer(createMockPluginInput(), {
|
||||||
|
isContinuationStopped: () => stopped,
|
||||||
|
})
|
||||||
|
|
||||||
|
// when - session goes idle with continuation not yet stopped
|
||||||
|
await hook.handler({
|
||||||
|
event: { type: "session.idle", properties: { sessionID } },
|
||||||
|
})
|
||||||
|
|
||||||
|
// when - stop-continuation fires during the 2s countdown window
|
||||||
|
stopped = true
|
||||||
|
|
||||||
|
// when - countdown elapses and injectContinuation fires
|
||||||
|
await fakeTimers.advanceBy(3000)
|
||||||
|
|
||||||
|
// then - no injection because isContinuationStopped became true before injectContinuation ran
|
||||||
|
expect(promptCalls).toHaveLength(0)
|
||||||
|
})
|
||||||
|
|
||||||
test("should inject when isContinuationStopped returns false", async () => {
|
test("should inject when isContinuationStopped returns false", async () => {
|
||||||
fakeTimers.restore()
|
fakeTimers.restore()
|
||||||
// given - session with continuation not stopped
|
// given - session with continuation not stopped
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user