fix(rpc): stripped snapcompact archive from auto compaction event too
The auto_compaction_end event and its frame-rescue variant emitted the unstripped snapcompact preserveData, forcing the RPC shrink ladder on every unattended pass and risking a silently dropped event. Strip the archive from both event payloads while keeping it in the persisted compaction entry. Fixes #8168
This commit is contained in:
@@ -4,7 +4,7 @@
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fixed RPC v1 manual snapcompact compaction reporting a transport failure after the compaction had already persisted by omitting the redundant frame archive from the response ([#8168](https://github.com/can1357/oh-my-pi/issues/8168)).
|
||||
- Fixed snapcompact compaction shipping its redundant frame archive out of `SessionMaintenance.compact()` on both the manual RPC response (which hard-failed protocol v1 with a transport error after the compaction had already persisted) and the `auto_compaction_end` event payload (which forced the shrink ladder on every unattended pass); the archive is now stripped from both exits while the persisted compaction entry keeps it ([#8168](https://github.com/can1357/oh-my-pi/issues/8168)).
|
||||
|
||||
## [17.2.12] - 2026-08-08
|
||||
|
||||
|
||||
@@ -2390,7 +2390,10 @@ export class SessionMaintenance {
|
||||
await this.#host.emitSessionEvent({
|
||||
type: "auto_compaction_end",
|
||||
action,
|
||||
result: frameRescueResult,
|
||||
result: frameRescueResult && {
|
||||
...frameRescueResult,
|
||||
preserveData: snapcompact.stripPreservedArchive(frameRescueResult.preserveData),
|
||||
},
|
||||
aborted: false,
|
||||
willRetry: false,
|
||||
skipped: frameRescueResult === undefined,
|
||||
@@ -2790,7 +2793,7 @@ export class SessionMaintenance {
|
||||
firstKeptEntryId,
|
||||
tokensBefore,
|
||||
details,
|
||||
preserveData,
|
||||
preserveData: snapcompact.stripPreservedArchive(preserveData),
|
||||
};
|
||||
// Post-maintenance progress guard — evaluated BEFORE emitting
|
||||
// auto_compaction_end so the TUI rebuild triggered by that event
|
||||
|
||||
@@ -27,7 +27,7 @@ import { ModelRegistry } from "@oh-my-pi/pi-coding-agent/config/model-registry";
|
||||
import { Settings } from "@oh-my-pi/pi-coding-agent/config/settings";
|
||||
import { encodeRpcFrame, MAX_RPC_FRAME_BYTES } from "@oh-my-pi/pi-coding-agent/modes/rpc/rpc-frame";
|
||||
import { computeNonMessageTokens } from "@oh-my-pi/pi-coding-agent/modes/utils/context-usage";
|
||||
import { AgentSession } from "@oh-my-pi/pi-coding-agent/session/agent-session";
|
||||
import { AgentSession, type AgentSessionEvent } from "@oh-my-pi/pi-coding-agent/session/agent-session";
|
||||
import { AuthStorage } from "@oh-my-pi/pi-coding-agent/session/auth-storage";
|
||||
import { SessionManager } from "@oh-my-pi/pi-coding-agent/session/session-manager";
|
||||
import { TempDir } from "@oh-my-pi/pi-utils";
|
||||
@@ -328,4 +328,41 @@ describe("AgentSession snapcompact frame-budget sizing", () => {
|
||||
[snapcompact.PRESERVE_KEY]: archive,
|
||||
});
|
||||
});
|
||||
|
||||
it("keeps the frame archive out of the auto_compaction_end event after persisting it", async () => {
|
||||
const branchEntries = sessionManager.getBranch();
|
||||
const lastEntry = branchEntries[branchEntries.length - 1];
|
||||
if (!lastEntry?.id) throw new Error("Expected branch entry with id");
|
||||
// A zero-frame archive clears the payload/projection gates on the auto
|
||||
// path while still carrying PRESERVE_KEY, so the strip is what removes it.
|
||||
const archive = { frames: [], totalChars: 1000, truncatedChars: 0 };
|
||||
vi.spyOn(snapcompact, "compact").mockResolvedValue({
|
||||
summary: "stubbed snapcompact",
|
||||
shortSummary: "stub",
|
||||
firstKeptEntryId: lastEntry.id,
|
||||
tokensBefore: 100_000,
|
||||
details: { readFiles: [], modifiedFiles: [] },
|
||||
preserveData: {
|
||||
extensionState: "keep-me",
|
||||
[snapcompact.PRESERVE_KEY]: archive,
|
||||
},
|
||||
});
|
||||
const events: AgentSessionEvent[] = [];
|
||||
session.subscribe(event => events.push(event));
|
||||
|
||||
await session.runIdleCompaction();
|
||||
|
||||
const endEvent = events.find(
|
||||
(event): event is Extract<AgentSessionEvent, { type: "auto_compaction_end" }> =>
|
||||
event.type === "auto_compaction_end" && event.result !== undefined,
|
||||
);
|
||||
if (!endEvent?.result) throw new Error("Expected a result-carrying auto_compaction_end event");
|
||||
expect(endEvent.result.preserveData).toEqual({ extensionState: "keep-me" });
|
||||
const compactionEntry = sessionManager.getEntries().find(entry => entry.type === "compaction");
|
||||
if (compactionEntry?.type !== "compaction") throw new Error("Expected persisted compaction entry");
|
||||
expect(compactionEntry.preserveData).toEqual({
|
||||
extensionState: "keep-me",
|
||||
[snapcompact.PRESERVE_KEY]: archive,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user