diff --git a/CHANGELOG.md b/CHANGELOG.md index e9a540b531b..e3d45bd71c6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ Docs: https://docs.openclaw.ai - Plugins/install: repair active and default-enabled bundled plugin runtime dependencies before import in packaged installs, so bundled Discord, WhatsApp, Slack, Telegram, and provider plugins work without putting their dependency trees in core. - BlueBubbles: raise the outbound `/api/v1/message/text` send timeout default from 10s to 30s, and add a configurable `channels.bluebubbles.sendTimeoutMs` (also per-account) so macOS 26 setups where Private API iMessage sends stall for 60+ seconds no longer silently lose messages at the 10s abort. Probes, chat lookups, and health checks keep the shorter 10s default. Fixes #67486. (#69193) Thanks @omarshahine. - Context engine/plugins: stop rejecting third-party context engines whose `info.id` differs from the registered plugin slot id. The strict-match contract added in 2026.4.14 broke `lossless-claw` and other plugins whose internal engine id does not equal the slot id they are registered under, producing repeated `info.id must match registered id` lane failures on every turn. Fixes #66601. (#66678) Thanks @GodsBoy. +- Agents/compaction: rename embedded Pi compaction lifecycle events to `compaction_start` / `compaction_end` so OpenClaw stays aligned with `pi-coding-agent` 0.66.1 event naming. (#67713) Thanks @mpz4life. ## 2026.4.20 diff --git a/docs/pi.md b/docs/pi.md index 72d6744c0fd..f7194c19c78 100644 --- a/docs/pi.md +++ b/docs/pi.md @@ -225,7 +225,7 @@ Events handled include: - `tool_execution_start` / `tool_execution_update` / `tool_execution_end` - `turn_start` / `turn_end` - `agent_start` / `agent_end` -- `auto_compaction_start` / `auto_compaction_end` +- `compaction_start` / `compaction_end` ### 4. Prompting diff --git a/src/agents/pi-embedded-subscribe.handlers.compaction.test.ts b/src/agents/pi-embedded-subscribe.handlers.compaction.test.ts index 059143e17ca..95f2bc6d6e7 100644 --- a/src/agents/pi-embedded-subscribe.handlers.compaction.test.ts +++ b/src/agents/pi-embedded-subscribe.handlers.compaction.test.ts @@ -13,7 +13,7 @@ import { waitForCompactionCount, } from "./pi-embedded-subscribe.compaction-test-helpers.js"; import { - handleAutoCompactionEnd, + handleCompactionEnd, reconcileSessionStoreCompactionCountAfterSuccess, } from "./pi-embedded-subscribe.handlers.compaction.js"; import type { EmbeddedPiSubscribeContext } from "./pi-embedded-subscribe.handlers.types.js"; @@ -112,7 +112,7 @@ describe("reconcileSessionStoreCompactionCountAfterSuccess", () => { }); }); -describe("handleAutoCompactionEnd", () => { +describe("handleCompactionEnd", () => { it("reconciles the session store after a successful compaction end event", async () => { const tmp = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-compaction-handler-")); const storePath = path.join(tmp, "sessions.json"); @@ -129,8 +129,8 @@ describe("handleAutoCompactionEnd", () => { initialCount: 1, }); - handleAutoCompactionEnd(ctx, { - type: "auto_compaction_end", + handleCompactionEnd(ctx, { + type: "compaction_end", result: { kept: 12 }, willRetry: false, aborted: false, diff --git a/src/agents/pi-embedded-subscribe.handlers.compaction.ts b/src/agents/pi-embedded-subscribe.handlers.compaction.ts index 6b94b9af326..f7f5caf5bf8 100644 --- a/src/agents/pi-embedded-subscribe.handlers.compaction.ts +++ b/src/agents/pi-embedded-subscribe.handlers.compaction.ts @@ -4,7 +4,7 @@ import { getGlobalHookRunner } from "../plugins/hook-runner-global.js"; import type { EmbeddedPiSubscribeContext } from "./pi-embedded-subscribe.handlers.types.js"; import { makeZeroUsageSnapshot } from "./usage.js"; -export function handleAutoCompactionStart(ctx: EmbeddedPiSubscribeContext) { +export function handleCompactionStart(ctx: EmbeddedPiSubscribeContext) { ctx.state.compactionInFlight = true; ctx.state.livenessState = "paused"; ctx.ensureCompactionPromise(); @@ -39,7 +39,7 @@ export function handleAutoCompactionStart(ctx: EmbeddedPiSubscribeContext) { } } -export function handleAutoCompactionEnd( +export function handleCompactionEnd( ctx: EmbeddedPiSubscribeContext, evt: AgentEvent & { willRetry?: unknown; result?: unknown; aborted?: unknown }, ) { diff --git a/src/agents/pi-embedded-subscribe.handlers.lifecycle.ts b/src/agents/pi-embedded-subscribe.handlers.lifecycle.ts index 58275c0c051..193df06b654 100644 --- a/src/agents/pi-embedded-subscribe.handlers.lifecycle.ts +++ b/src/agents/pi-embedded-subscribe.handlers.lifecycle.ts @@ -16,8 +16,8 @@ import { isPromiseLike } from "./pi-embedded-subscribe.promise.js"; import { isAssistantMessage } from "./pi-embedded-utils.js"; export { - handleAutoCompactionEnd, - handleAutoCompactionStart, + handleCompactionEnd, + handleCompactionStart, } from "./pi-embedded-subscribe.handlers.compaction.js"; export function handleAgentStart(ctx: EmbeddedPiSubscribeContext) { diff --git a/src/agents/pi-embedded-subscribe.handlers.ts b/src/agents/pi-embedded-subscribe.handlers.ts index 00ecb8654f9..09138d660c8 100644 --- a/src/agents/pi-embedded-subscribe.handlers.ts +++ b/src/agents/pi-embedded-subscribe.handlers.ts @@ -1,8 +1,8 @@ import { handleAgentEnd, handleAgentStart, - handleAutoCompactionEnd, - handleAutoCompactionStart, + handleCompactionEnd, + handleCompactionStart, } from "./pi-embedded-subscribe.handlers.lifecycle.js"; import { handleMessageEnd, @@ -113,14 +113,14 @@ export function createEmbeddedPiSessionEventHandler(ctx: EmbeddedPiSubscribeCont handleAgentStart(ctx); }); return; - case "auto_compaction_start": + case "compaction_start": scheduleEvent(evt, () => { - handleAutoCompactionStart(ctx); + handleCompactionStart(ctx); }); return; - case "auto_compaction_end": + case "compaction_end": scheduleEvent(evt, () => { - handleAutoCompactionEnd(ctx, evt as never); + handleCompactionEnd(ctx, evt as never); }); return; case "agent_end": diff --git a/src/agents/pi-embedded-subscribe.subscribe-embedded-pi-session.splits-long-single-line-fenced-blocks-reopen.test.ts b/src/agents/pi-embedded-subscribe.subscribe-embedded-pi-session.splits-long-single-line-fenced-blocks-reopen.test.ts index f2c260ca0d0..057898f7f4c 100644 --- a/src/agents/pi-embedded-subscribe.subscribe-embedded-pi-session.splits-long-single-line-fenced-blocks-reopen.test.ts +++ b/src/agents/pi-embedded-subscribe.subscribe-embedded-pi-session.splits-long-single-line-fenced-blocks-reopen.test.ts @@ -58,7 +58,7 @@ describe("subscribeEmbeddedPiSession", () => { for (const listener of listeners) { listener({ - type: "auto_compaction_end", + type: "compaction_end", willRetry: true, }); } @@ -96,7 +96,7 @@ describe("subscribeEmbeddedPiSession", () => { }); for (const listener of listeners) { - listener({ type: "auto_compaction_start" }); + listener({ type: "compaction_start" }); } expect(subscription.isCompacting()).toBe(true); @@ -110,7 +110,7 @@ describe("subscribeEmbeddedPiSession", () => { expect(resolved).toBe(false); for (const listener of listeners) { - listener({ type: "auto_compaction_end", willRetry: false }); + listener({ type: "compaction_end", willRetry: false }); } await waitPromise; @@ -147,7 +147,7 @@ describe("subscribeEmbeddedPiSession", () => { }); for (const listener of listeners) { - listener({ type: "auto_compaction_end", willRetry: false }); + listener({ type: "compaction_end", willRetry: false }); } const usage = (session.messages?.[0] as { usage?: unknown } | undefined)?.usage; diff --git a/src/agents/pi-embedded-subscribe.subscribe-embedded-pi-session.subscribeembeddedpisession.test.ts b/src/agents/pi-embedded-subscribe.subscribe-embedded-pi-session.subscribeembeddedpisession.test.ts index cb52ad68b02..2b069a4c001 100644 --- a/src/agents/pi-embedded-subscribe.subscribe-embedded-pi-session.subscribeembeddedpisession.test.ts +++ b/src/agents/pi-embedded-subscribe.subscribe-embedded-pi-session.subscribeembeddedpisession.test.ts @@ -602,7 +602,7 @@ describe("subscribeEmbeddedPiSession", () => { isError: false, result: { ok: true }, }); - emit({ type: "auto_compaction_end", willRetry: true, result: { summary: "compacted" } }); + emit({ type: "compaction_end", willRetry: true, result: { summary: "compacted" } }); emit({ type: "agent_end" }); expect(subscription.getReplayState()).toEqual({ @@ -638,7 +638,7 @@ describe("subscribeEmbeddedPiSession", () => { isError: false, result: { details: { status: "ok" } }, }); - emit({ type: "auto_compaction_end", willRetry: true, result: { summary: "compacted" } }); + emit({ type: "compaction_end", willRetry: true, result: { summary: "compacted" } }); emit({ type: "agent_end" }); const payloads = extractAgentEventPayloads(onAgentEvent.mock.calls); diff --git a/src/agents/pi-embedded-subscribe.subscribe-embedded-pi-session.waits-multiple-compaction-retries-before-resolving.test.ts b/src/agents/pi-embedded-subscribe.subscribe-embedded-pi-session.waits-multiple-compaction-retries-before-resolving.test.ts index 22d0a30bfde..3ffa502c4e4 100644 --- a/src/agents/pi-embedded-subscribe.subscribe-embedded-pi-session.waits-multiple-compaction-retries-before-resolving.test.ts +++ b/src/agents/pi-embedded-subscribe.subscribe-embedded-pi-session.waits-multiple-compaction-retries-before-resolving.test.ts @@ -8,8 +8,8 @@ describe("subscribeEmbeddedPiSession", () => { runId: "run-3", }); - emit({ type: "auto_compaction_end", willRetry: true }); - emit({ type: "auto_compaction_end", willRetry: true }); + emit({ type: "compaction_end", willRetry: true }); + emit({ type: "compaction_end", willRetry: true }); let resolved = false; const waitPromise = subscription.waitForCompactionRetry().then(() => { @@ -35,15 +35,15 @@ describe("subscribeEmbeddedPiSession", () => { runId: "run-compaction-count", }); - emit({ type: "auto_compaction_start" }); + emit({ type: "compaction_start" }); expect(subscription.getCompactionCount()).toBe(0); // willRetry with result — counter IS incremented (overflow compaction succeeded) - emit({ type: "auto_compaction_end", willRetry: true, result: { summary: "s" } }); + emit({ type: "compaction_end", willRetry: true, result: { summary: "s" } }); expect(subscription.getCompactionCount()).toBe(1); // willRetry=false with result — counter incremented again - emit({ type: "auto_compaction_end", willRetry: false, result: { summary: "s2" } }); + emit({ type: "compaction_end", willRetry: false, result: { summary: "s2" } }); expect(subscription.getCompactionCount()).toBe(2); }); @@ -53,10 +53,10 @@ describe("subscribeEmbeddedPiSession", () => { }); // No result (e.g. aborted or cancelled) — counter stays at 0 - emit({ type: "auto_compaction_end", willRetry: false, result: undefined }); + emit({ type: "compaction_end", willRetry: false, result: undefined }); expect(subscription.getCompactionCount()).toBe(0); - emit({ type: "auto_compaction_end", willRetry: false, aborted: true }); + emit({ type: "compaction_end", willRetry: false, aborted: true }); expect(subscription.getCompactionCount()).toBe(0); }); @@ -79,9 +79,9 @@ describe("subscribeEmbeddedPiSession", () => { }); }); - emit({ type: "auto_compaction_start" }); - emit({ type: "auto_compaction_end", willRetry: true }); - emit({ type: "auto_compaction_end", willRetry: false }); + emit({ type: "compaction_start" }); + emit({ type: "compaction_end", willRetry: true }); + emit({ type: "compaction_end", willRetry: false }); stop(); @@ -99,7 +99,7 @@ describe("subscribeEmbeddedPiSession", () => { sessionExtras: { isCompacting: true, abortCompaction }, }); - emit({ type: "auto_compaction_start" }); + emit({ type: "compaction_start" }); const waitPromise = subscription.waitForCompactionRetry(); subscription.unsubscribe(); diff --git a/src/plugins/wired-hooks-compaction.test.ts b/src/plugins/wired-hooks-compaction.test.ts index 3978171c7aa..7286cc6d1f5 100644 --- a/src/plugins/wired-hooks-compaction.test.ts +++ b/src/plugins/wired-hooks-compaction.test.ts @@ -22,8 +22,8 @@ vi.mock("../infra/agent-events.js", () => ({ })); import { - handleAutoCompactionEnd, - handleAutoCompactionStart, + handleCompactionEnd, + handleCompactionStart, } from "../agents/pi-embedded-subscribe.handlers.compaction.js"; describe("compaction hook wiring", () => { @@ -111,16 +111,16 @@ describe("compaction hook wiring", () => { aborted?: boolean; }, ) { - handleAutoCompactionEnd( + handleCompactionEnd( ctx as never, { - type: "auto_compaction_end", + type: "compaction_end", ...event, } as never, ); } - it("calls runBeforeCompaction in handleAutoCompactionStart", () => { + it("calls runBeforeCompaction in handleCompactionStart", () => { hookMocks.runner.hasHooks.mockReturnValue(true); const ctx = { @@ -136,7 +136,7 @@ describe("compaction hook wiring", () => { ensureCompactionPromise: vi.fn(), }; - handleAutoCompactionStart(ctx as never); + handleCompactionStart(ctx as never); expect(hookMocks.runner.runBeforeCompaction).toHaveBeenCalledTimes(1); expectCompactionEvent({