fix(copilot): bound background compaction waits

This commit is contained in:
Vincent Koc
2026-06-19 14:21:37 +08:00
committed by Vincent Koc
parent ece7d0945c
commit 7d219bd6e7
2 changed files with 32 additions and 2 deletions

View File

@@ -441,6 +441,31 @@ describe("runCopilotAttempt", () => {
expect(beforeCompaction.mock.calls[0]?.[0]).not.toHaveProperty("messages");
});
it("bounds successful background compaction when the SDK omits completion", async () => {
vi.useFakeTimers();
const sdk = makeFakeSdk({
onCreateSession: (session) => {
session.sendAndWait.mockImplementationOnce(async () => {
session.emit("session.compaction_start", {});
return makeAssistantMessageEvent("done");
});
},
});
const pool = makeFakePool(sdk);
const attempt = runCopilotAttempt(makeParams(), { pool });
await vi.advanceTimersByTimeAsync(0);
await vi.advanceTimersByTimeAsync(180_000);
const result = await attempt;
expect(result.timedOut).toBe(false);
expect(result.promptError).toBeUndefined();
expect(sdk.sessions[0]?.rpc.history.cancelBackgroundCompaction).toHaveBeenCalledTimes(1);
expect(sdk.sessions[0]?.disconnect).toHaveBeenCalledTimes(1);
expect(sdk.client.deleteSession).toHaveBeenCalledWith("sess-1");
expect(pool.release).toHaveBeenCalledTimes(1);
});
it("defers and cancels compaction when the caller aborts after a turn result", async () => {
const controller = new AbortController();
const onDeferredCompaction = vi.fn();

View File

@@ -783,7 +783,11 @@ export async function runCopilotAttempt(
settled = true;
const compactionCompletionOutcome =
waitForCompactionCompletion && !aborted && !params.abortSignal?.aborted
? await awaitCompactionCompletionOrAbort(bridge!, params.abortSignal)
? await awaitCompactionCompletionBeforeDeadline({
abortSignal: params.abortSignal,
bridge: bridge!,
timeoutMs: resolveCompactionTimeoutMs(input.config),
})
: undefined;
const deferCompactionCleanup =
bridge?.isCompacting() &&
@@ -791,12 +795,13 @@ export async function runCopilotAttempt(
handle &&
(timedOut ||
compactionCompletionOutcome === "aborted" ||
compactionCompletionOutcome === "deadline" ||
params.abortSignal?.aborted === true);
if (deferCompactionCleanup && bridge && session && handle) {
timedOutDuringCompaction ||= timedOut;
const cleanupAbort = new AbortController();
const abortCleanup = () => cleanupAbort.abort();
if (params.abortSignal?.aborted) {
if (params.abortSignal?.aborted || compactionCompletionOutcome === "deadline") {
abortCleanup();
} else {
params.abortSignal?.addEventListener("abort", abortCleanup, { once: true });