36468b118d
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
72 lines
1.7 KiB
TypeScript
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)
|
|
})
|
|
})
|