Files
oh-my-opencode/src/hooks/shared/session-idle-settle.test.ts
T
YeonGyu-Kim 36468b118d fix(shared): add timeout to isSessionActive to prevent infinite hang
The SDK client disables fetch timeout (req.timeout = false). When the
opencode server is slow or unresponsive, client.session.status() hangs
forever, blocking the entire dispatchToHooks chain (sequential await)
and deadlocking the plugin.

Add a 5s timeout wrapper around the status call in isSessionActive().
On timeout, the catch block returns false (treat as inactive), letting
the caller proceed instead of hanging indefinitely.

The timeout parameter is exposed for testing to avoid 5s test delays.

Refs: .debugging/status-timeout-hang.md
2026-05-17 03:40:17 +09:00

72 lines
1.7 KiB
TypeScript

import { describe, expect, test } from "bun:test"
import {
isSessionActive,
shouldPromptAfterSessionIdle,
} from "./session-idle-settle"
describe("session idle prompt guard", () => {
test("#given session.status reports busy #when checking active session #then it returns true", async () => {
// given
const client = {
session: {
status: async () => ({
data: {
"ses-active": { type: "busy" },
},
}),
},
}
// when
const active = await isSessionActive(client, "ses-active")
// then
expect(active).toBe(true)
})
test("#given a stale idle event but session became busy #when settling before prompt #then it blocks the wake", async () => {
// given
const client = {
session: {
status: async () => ({
"ses-active": { type: "busy" },
}),
},
}
// when
const shouldPrompt = await shouldPromptAfterSessionIdle(client, "ses-active", 0)
// then
expect(shouldPrompt).toBe(false)
})
test("#given session.status is unavailable #when settling before prompt #then it preserves legacy prompt behavior", async () => {
// given
const client = { session: {} }
// when
const shouldPrompt = await shouldPromptAfterSessionIdle(client, "ses-legacy", 0)
// then
expect(shouldPrompt).toBe(true)
})
test("#given session.status hangs forever #when checking active session #then it returns false after timeout", async () => {
// given
const neverSettles = new Promise<never>(() => {})
const client = {
session: {
status: () => neverSettles,
},
}
// when
const active = await isSessionActive(client, "ses-hang", 50)
// then
expect(active).toBe(false)
})
})