fix(hooks): guard stale idle prompts

This commit is contained in:
YeonGyu-Kim
2026-05-13 16:44:52 +09:00
parent a337635e3b
commit 3b4d2431ee
7 changed files with 94 additions and 11 deletions
@@ -184,6 +184,41 @@ describe("createTeamIdleWakeHint", () => {
expect(promptInput.body.parts[0]?.text).not.toContain("second message body")
})
test("#given stale idle event but member session is busy #when wake hint checks status #then it does not start an overlapping reply", async () => {
// given
const baseDir = await createTemporaryBaseDir()
const config = createConfig(baseDir)
const teamRunId = randomUUID()
await seedRuntimeState(createRuntimeState(teamRunId), config)
await seedUnreadMessage(teamRunId, config, randomUUID(), "first message body", 100)
const promptAsyncSpy = mock(async (_input: WakeHintPromptInput) => ({}))
const handler = createTeamIdleWakeHint({
directory: "/tmp/project",
client: {
session: {
promptAsync: promptAsyncSpy,
status: async () => ({
data: {
"member-session": { type: "busy" },
},
}),
},
},
}, config, { idleSettleMs: 0 })
// when
await handler({
event: {
type: "session.idle",
properties: { sessionID: "member-session" },
},
})
// then
expect(promptAsyncSpy).toHaveBeenCalledTimes(0)
})
test("pins the recipient's resolved subagent_type and model on the wake-hint promptAsync", async () => {
// given
const baseDir = await createTemporaryBaseDir()
@@ -9,7 +9,7 @@ import {
} from "../../features/team-mode/member-session-routing"
import { resolveSessionEventID } from "../../shared/event-session-id"
import { log } from "../../shared/logger"
import { settleAfterSessionIdle } from "../shared/session-idle-settle"
import { shouldPromptAfterSessionIdle } from "../shared/session-idle-settle"
type PromptAsyncInput = {
path: { id: string }
@@ -27,6 +27,7 @@ type TeamIdleWakeHintContext = {
client: {
session: {
promptAsync?: (input: PromptAsyncInput) => Promise<unknown>
status?: () => Promise<unknown>
}
}
}
@@ -99,7 +100,16 @@ export function createTeamIdleWakeHint(ctx: TeamIdleWakeHintContext, config: Tea
}
applyMemberSessionRouting(sessionID, memberEntry)
await settleAfterSessionIdle(options?.idleSettleMs)
if (!(await shouldPromptAfterSessionIdle(ctx.client, sessionID, options?.idleSettleMs))) {
log("team idle wake hint skipped because session is active", {
event: "team-mode-idle-wake-hint-active-session",
teamRunId: runtimeState.teamRunId,
memberName: memberEntry.name,
sessionID,
unreadCount: unreadMessages.length,
})
return
}
await ctx.client.session.promptAsync({
path: { id: sessionID },