Merge pull request #10109 from IamCoder18/fix/session-prompt-queue-memory-leak

fix: prevent memory leak in KiloSessionPromptQueue.cancel for sessions without active tails
This commit is contained in:
Marius
2026-06-09 09:29:05 +02:00
committed by GitHub
3 changed files with 36 additions and 0 deletions
@@ -0,0 +1,5 @@
---
"@kilocode/cli": patch
---
Prevent memory leak in KiloSessionPromptQueue.cancel for sessions without active tails
@@ -27,6 +27,11 @@ export namespace KiloSessionPromptQueue {
const activeSince = new Map<SessionID, number>()
let seq = 0
/** @internal - test-only helper */
export function _hasInternalState(sessionID: SessionID): boolean {
return versions.has(sessionID) || targets.has(sessionID) || latest.has(sessionID) || activeSince.has(sessionID)
}
const version = (sessionID: SessionID) => versions.get(sessionID) ?? 0
const settle = (promise: Promise<void>) =>
promise.then(
@@ -36,6 +41,13 @@ export namespace KiloSessionPromptQueue {
export function cancel(sessionID: SessionID) {
return Effect.sync(() => {
if (!tails.has(sessionID)) {
versions.delete(sessionID)
targets.delete(sessionID)
latest.delete(sessionID)
activeSince.delete(sessionID)
return
}
versions.set(sessionID, version(sessionID) + 1)
})
}
@@ -599,6 +599,25 @@ describe("session prompt queue", () => {
}
})
test("cancel on a session with no active tail is a no-op and does not leak state", async () => {
const sessionID = SessionID.make("session_cancel_noop")
await Effect.runPromise(KiloSessionPromptQueue.cancel(sessionID))
expect(KiloSessionPromptQueue._hasInternalState(sessionID)).toBe(false)
const result = await Effect.runPromise(
KiloSessionPromptQueue.enqueue(
sessionID,
MessageID.make("message_probe"),
Effect.succeed("work executed"),
Effect.succeed("cancelled returned"),
),
)
expect(result).toBe("work executed")
})
test("cancel drops queued prompts and resets internal state", async () => {
const ready = Promise.withResolvers<void>()
const calls: number[] = []