mirror of
https://github.com/NanmiCoder/cc-haha
synced 2026-07-23 14:33:36 +08:00
fix(server): bound late permission waits (#1019)
This commit is contained in:
parent
948eb36b67
commit
1d8597fb7b
@ -430,6 +430,39 @@ describe('WebSocket handler session isolation', () => {
|
|||||||
expect(stopSession).toHaveBeenCalledWith(sessionId)
|
expect(stopSession).toHaveBeenCalledWith(sessionId)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('starts the permission cleanup bound when the prompt arrives after disconnect', () => {
|
||||||
|
const sessionId = `late-permission-disconnect-${crypto.randomUUID()}`
|
||||||
|
const ws = makeClientSocket(sessionId)
|
||||||
|
const setTimeoutSpy = spyOn(globalThis, 'setTimeout').mockImplementation(() => 0 as any)
|
||||||
|
const pendingRequests = spyOn(conversationService, 'getPendingPermissionRequests')
|
||||||
|
.mockReturnValue([])
|
||||||
|
let turnOutputCallback: ((cliMsg: any) => void) | null = null
|
||||||
|
spyOn(conversationService, 'onOutput').mockImplementation((_sid, callback) => {
|
||||||
|
turnOutputCallback = callback
|
||||||
|
})
|
||||||
|
spyOn(conversationService, 'removeOutputCallback').mockImplementation(() => {})
|
||||||
|
|
||||||
|
handleWebSocket.open(ws)
|
||||||
|
__markActiveTurnForTests(sessionId)
|
||||||
|
setTimeoutSpy.mockClear()
|
||||||
|
handleWebSocket.close(ws, 1006, 'renderer closed before permission prompt')
|
||||||
|
|
||||||
|
expect(setTimeoutSpy).not.toHaveBeenCalled()
|
||||||
|
pendingRequests.mockReturnValue([{
|
||||||
|
requestId: 'late-request-1',
|
||||||
|
toolName: 'Bash',
|
||||||
|
input: { command: 'echo later' },
|
||||||
|
}])
|
||||||
|
;(turnOutputCallback as ((cliMsg: any) => void) | null)?.({
|
||||||
|
type: 'control_request',
|
||||||
|
request_id: 'late-request-1',
|
||||||
|
request: { subtype: 'can_use_tool', tool_name: 'Bash' },
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(setTimeoutSpy).toHaveBeenCalledTimes(1)
|
||||||
|
expect(setTimeoutSpy.mock.calls[0]?.[1]).toBe(30 * 60_000)
|
||||||
|
})
|
||||||
|
|
||||||
it('does not forward prewarm startup status to a reconnecting client', async () => {
|
it('does not forward prewarm startup status to a reconnecting client', async () => {
|
||||||
const sessionId = `prewarm-reconnect-${crypto.randomUUID()}`
|
const sessionId = `prewarm-reconnect-${crypto.randomUUID()}`
|
||||||
const second = makeClientSocket(sessionId)
|
const second = makeClientSocket(sessionId)
|
||||||
|
|||||||
@ -2298,6 +2298,17 @@ function watchTurnCompletionForCleanup(sessionId: string): void {
|
|||||||
cancelSessionDisconnectWatcher(sessionId)
|
cancelSessionDisconnectWatcher(sessionId)
|
||||||
|
|
||||||
const onComplete = (cliMsg: any) => {
|
const onComplete = (cliMsg: any) => {
|
||||||
|
if (
|
||||||
|
cliMsg?.type === 'control_request' &&
|
||||||
|
cliMsg.request?.subtype === 'can_use_tool' &&
|
||||||
|
!hasActiveClients(sessionId)
|
||||||
|
) {
|
||||||
|
// The permission request may arrive after the renderer disconnected.
|
||||||
|
// ConversationService records it before notifying this callback, so the
|
||||||
|
// cleanup delay resolves to the bounded pending-permission window.
|
||||||
|
scheduleDisconnectCleanup(sessionId)
|
||||||
|
return
|
||||||
|
}
|
||||||
if (cliMsg?.type !== 'result') return
|
if (cliMsg?.type !== 'result') return
|
||||||
cancelSessionDisconnectWatcher(sessionId)
|
cancelSessionDisconnectWatcher(sessionId)
|
||||||
// The turn finished while still unobserved — fall back to the idle timer.
|
// The turn finished while still unobserved — fall back to the idle timer.
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user