






















@@ -10,6 +10,7 @@ import {
1010} from "./pi-embedded-subscribe.compaction-test-helpers.js";
1111import {
1212handleCompactionEnd,
13+handleCompactionStart,
1314reconcileSessionStoreCompactionCountAfterSuccess,
1415} from "./pi-embedded-subscribe.handlers.compaction.js";
1516import type { EmbeddedPiSubscribeContext } from "./pi-embedded-subscribe.handlers.types.js";
@@ -19,6 +20,7 @@ function createCompactionContext(params: {
1920sessionKey: string;
2021agentId?: string;
2122initialCount: number;
23+info?: (message: string, meta?: Record<string, unknown>) => void;
2224}): EmbeddedPiSubscribeContext {
2325let compactionCount = params.initialCount;
2426return {
@@ -37,6 +39,7 @@ function createCompactionContext(params: {
3739} as never,
3840log: {
3941debug: vi.fn(),
42+info: params.info ?? vi.fn(),
4043warn: vi.fn(),
4144},
4245ensureCompactionPromise: vi.fn(),
@@ -103,6 +106,168 @@ describe("reconcileSessionStoreCompactionCountAfterSuccess", () => {
103106});
104107});
105108109+describe("compaction lifecycle logging", () => {
110+it("logs lifecycle events at info level for gateway watch visibility", async () => {
111+const tmp = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-compaction-log-"));
112+const storePath = path.join(tmp, "sessions.json");
113+const sessionKey = "main";
114+await seedSessionStore({
115+ storePath,
116+ sessionKey,
117+compactionCount: 0,
118+});
119+const info = vi.fn();
120+const ctx = createCompactionContext({
121+ storePath,
122+ sessionKey,
123+initialCount: 0,
124+ info,
125+});
126+127+handleCompactionStart(ctx, {
128+type: "compaction_start",
129+reason: "threshold",
130+});
131+handleCompactionEnd(ctx, {
132+type: "compaction_end",
133+reason: "threshold",
134+result: { kept: 12 },
135+willRetry: false,
136+aborted: false,
137+});
138+139+expect(info).toHaveBeenNthCalledWith(
140+1,
141+"embedded run auto-compaction start",
142+expect.objectContaining({
143+event: "embedded_run_compaction_start",
144+reason: "threshold",
145+runId: "run-test",
146+consoleMessage: "embedded run auto-compaction start: runId=run-test reason=threshold",
147+}),
148+);
149+expect(info).toHaveBeenNthCalledWith(
150+2,
151+"embedded run auto-compaction complete",
152+expect.objectContaining({
153+event: "embedded_run_compaction_end",
154+reason: "threshold",
155+runId: "run-test",
156+completed: true,
157+compactionCount: 1,
158+consoleMessage:
159+"embedded run auto-compaction complete: runId=run-test reason=threshold compactionCount=1 willRetry=false",
160+}),
161+);
162+});
163+164+it("logs manual compaction as incomplete when no result is produced", async () => {
165+const tmp = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-compaction-incomplete-log-"));
166+const storePath = path.join(tmp, "sessions.json");
167+const sessionKey = "main";
168+await seedSessionStore({
169+ storePath,
170+ sessionKey,
171+compactionCount: 0,
172+});
173+const info = vi.fn();
174+const ctx = createCompactionContext({
175+ storePath,
176+ sessionKey,
177+initialCount: 0,
178+ info,
179+});
180+181+handleCompactionStart(ctx, {
182+type: "compaction_start",
183+reason: "manual",
184+});
185+handleCompactionEnd(ctx, {
186+type: "compaction_end",
187+reason: "manual",
188+result: undefined,
189+willRetry: false,
190+aborted: false,
191+});
192+193+expect(info).toHaveBeenNthCalledWith(
194+1,
195+"embedded run manual compaction start",
196+expect.objectContaining({
197+event: "embedded_run_compaction_start",
198+reason: "manual",
199+runId: "run-test",
200+consoleMessage: "embedded run manual compaction start: runId=run-test reason=manual",
201+}),
202+);
203+expect(info).toHaveBeenNthCalledWith(
204+2,
205+"embedded run manual compaction incomplete",
206+expect.objectContaining({
207+event: "embedded_run_compaction_end",
208+reason: "manual",
209+runId: "run-test",
210+completed: false,
211+aborted: false,
212+consoleMessage:
213+"embedded run manual compaction incomplete: runId=run-test reason=manual aborted=false willRetry=false",
214+}),
215+);
216+});
217+218+it("defaults legacy synthetic compaction events to threshold logs", async () => {
219+const tmp = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-compaction-legacy-log-"));
220+const storePath = path.join(tmp, "sessions.json");
221+const sessionKey = "main";
222+await seedSessionStore({
223+ storePath,
224+ sessionKey,
225+compactionCount: 0,
226+});
227+const info = vi.fn();
228+const ctx = createCompactionContext({
229+ storePath,
230+ sessionKey,
231+initialCount: 0,
232+ info,
233+});
234+235+handleCompactionStart(ctx, {
236+type: "compaction_start",
237+});
238+handleCompactionEnd(ctx, {
239+type: "compaction_end",
240+result: { kept: 12 },
241+willRetry: false,
242+aborted: false,
243+});
244+245+expect(info).toHaveBeenNthCalledWith(
246+1,
247+"embedded run auto-compaction start",
248+expect.objectContaining({
249+event: "embedded_run_compaction_start",
250+reason: "threshold",
251+runId: "run-test",
252+consoleMessage: "embedded run auto-compaction start: runId=run-test reason=threshold",
253+}),
254+);
255+expect(info).toHaveBeenNthCalledWith(
256+2,
257+"embedded run auto-compaction complete",
258+expect.objectContaining({
259+event: "embedded_run_compaction_end",
260+reason: "threshold",
261+runId: "run-test",
262+completed: true,
263+compactionCount: 1,
264+consoleMessage:
265+"embedded run auto-compaction complete: runId=run-test reason=threshold compactionCount=1 willRetry=false",
266+}),
267+);
268+});
269+});
270+106271describe("handleCompactionEnd", () => {
107272it("reconciles the session store after a successful compaction end event", async () => {
108273const tmp = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-compaction-handler-"));
@@ -122,10 +287,11 @@ describe("handleCompactionEnd", () => {
122287123288handleCompactionEnd(ctx, {
124289type: "compaction_end",
290+reason: "threshold",
125291result: { kept: 12 },
126292willRetry: false,
127293aborted: false,
128-} as never);
294+});
129295130296await waitForCompactionCount({
131297 storePath,
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。