fix(copilot): isolate root compaction events

This commit is contained in:
Vincent Koc
2026-06-19 14:57:36 +08:00
committed by Vincent Koc
parent 8ff1d3e67b
commit d20e96a650
2 changed files with 40 additions and 1 deletions

View File

@@ -662,6 +662,33 @@ describe("attachEventBridge", () => {
expect(bridge.isCompacting()).toBe(false);
});
it("ignores subagent compaction events when tracking the root session", async () => {
const session = createFakeSession();
const onCompactionStart = vi.fn();
const onCompactionComplete = vi.fn();
const bridge = attachEventBridge(session, {
getSdkSessionId: () => "sdk-session-id",
isAborted: () => false,
onCompactionStart,
onCompactionComplete,
});
session.emit("session.compaction_start", {
...makeEvent("session.compaction_start", {}),
agentId: "subagent-1",
});
session.emit("session.compaction_complete", {
...makeEvent("session.compaction_complete", { success: true }),
agentId: "subagent-1",
});
await bridge.awaitCompactionCompletion();
expect(bridge.hasObservedCompaction()).toBe(false);
expect(bridge.isCompacting()).toBe(false);
expect(onCompactionStart).not.toHaveBeenCalled();
expect(onCompactionComplete).not.toHaveBeenCalled();
});
it("session.error populates streamError with errorCode or errorType only when not aborted", () => {
const activeSession = createFakeSession();
const activeBridge = attachEventBridge(activeSession, {

View File

@@ -183,7 +183,10 @@ export function attachEventBridge(
}
});
registerListener(session, unsubscribeFns, "session.compaction_start", () => {
registerListener(session, unsubscribeFns, "session.compaction_start", (event) => {
if (!isRootCompactionEvent(event)) {
return;
}
observedCompaction = true;
if (activeCompactionCount === 0) {
compactionIdle = new Promise<void>((resolve) => {
@@ -195,6 +198,9 @@ export function attachEventBridge(
});
registerListener(session, unsubscribeFns, "session.compaction_complete", (event) => {
if (!isRootCompactionEvent(event)) {
return;
}
activeCompactionCount = Math.max(0, activeCompactionCount - 1);
enqueueCompactionCallback(() =>
options.onCompactionComplete?.({
@@ -410,6 +416,12 @@ function isAssistantMessageEvent(
return event?.type === "assistant.message";
}
function isRootCompactionEvent(event: { agentId?: string }): boolean {
// SDK session events include subagent compaction; only root compaction
// affects the pooled root session's cleanup and reuse lifecycle.
return event.agentId === undefined;
}
function joinReasoning(order: string[], reasoningById: Map<string, string>): string {
return order.map((reasoningId) => reasoningById.get(reasoningId) ?? "").join("");
}