diff --git a/CHANGELOG.md b/CHANGELOG.md index 1dd11adfede..661dac6d613 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -203,6 +203,7 @@ Docs: https://docs.openclaw.ai - Auth/login lockout recovery: clear stale `auth_permanent` and `billing` disabled state for all profiles matching the target provider when `openclaw models auth login` is invoked, so users locked out by expired or revoked OAuth tokens can recover by re-authenticating instead of waiting for the cooldown timer to expire. (#43057) - Auto-reply/context-engine compaction: persist the exact embedded-run metadata compaction count for main and followup runner session accounting, so metadata-only auto-compactions no longer undercount multi-compaction runs. (#42629) thanks @uf-hy. - Auth/Codex CLI reuse: sync reused Codex CLI credentials into the supported `openai-codex:default` OAuth profile instead of reviving the deprecated `openai-codex:codex-cli` slot, so doctor cleanup no longer loops. (#45353) thanks @Gugu-sugar. +- Hooks/after_compaction: forward `sessionFile` for direct/manual compaction events and add `sessionFile` plus `sessionKey` to wired auto-compaction hook context so plugins receive the session metadata already declared in the hook types. (#40781) Thanks @jarimustonen. ## 2026.3.12 diff --git a/src/agents/pi-embedded-runner/compact.hooks.test.ts b/src/agents/pi-embedded-runner/compact.hooks.test.ts index 54ad50539e3..72b16ad003f 100644 --- a/src/agents/pi-embedded-runner/compact.hooks.test.ts +++ b/src/agents/pi-embedded-runner/compact.hooks.test.ts @@ -529,6 +529,7 @@ describe("compactEmbeddedPiSessionDirect hooks", () => { messageCount: 1, tokenCount: 10, compactedCount: 1, + sessionFile: "/tmp/session.jsonl", }, expect.objectContaining({ sessionKey: "agent:main:session-1", messageProvider: "telegram" }), ); diff --git a/src/agents/pi-embedded-runner/compact.ts b/src/agents/pi-embedded-runner/compact.ts index 98a3b438d21..4e967730667 100644 --- a/src/agents/pi-embedded-runner/compact.ts +++ b/src/agents/pi-embedded-runner/compact.ts @@ -1039,6 +1039,7 @@ export async function compactEmbeddedPiSessionDirect( messageCount: messageCountAfter, tokenCount: tokensAfter, compactedCount, + sessionFile: params.sessionFile, }, { sessionId: params.sessionId, diff --git a/src/agents/pi-embedded-subscribe.handlers.compaction.ts b/src/agents/pi-embedded-subscribe.handlers.compaction.ts index 7b9c4499eff..f0717f140cf 100644 --- a/src/agents/pi-embedded-subscribe.handlers.compaction.ts +++ b/src/agents/pi-embedded-subscribe.handlers.compaction.ts @@ -80,8 +80,9 @@ export function handleAutoCompactionEnd( { messageCount: ctx.params.session.messages?.length ?? 0, compactedCount: ctx.getCompactionCount(), + sessionFile: ctx.params.session.sessionFile, }, - {}, + { sessionKey: ctx.params.sessionKey }, ) .catch((err) => { ctx.log.warn(`after_compaction hook failed: ${String(err)}`); diff --git a/src/plugins/wired-hooks-compaction.test.ts b/src/plugins/wired-hooks-compaction.test.ts index f8ce4d0a668..1fc258d4cef 100644 --- a/src/plugins/wired-hooks-compaction.test.ts +++ b/src/plugins/wired-hooks-compaction.test.ts @@ -39,11 +39,20 @@ describe("compaction hook wiring", () => { function createCompactionEndCtx(params: { runId: string; messages?: unknown[]; + sessionFile?: string; + sessionKey?: string; compactionCount?: number; withRetryHooks?: boolean; }) { return { - params: { runId: params.runId, session: { messages: params.messages ?? [] } }, + params: { + runId: params.runId, + sessionKey: params.sessionKey, + session: { + messages: params.messages ?? [], + sessionFile: params.sessionFile, + }, + }, state: { compactionInFlight: true }, log: { debug: vi.fn(), warn: vi.fn() }, maybeResolveCompactionWait: vi.fn(), @@ -107,6 +116,8 @@ describe("compaction hook wiring", () => { const ctx = createCompactionEndCtx({ runId: "r2", messages: [1, 2], + sessionFile: "/tmp/session.jsonl", + sessionKey: "agent:main:web-xyz", compactionCount: 1, }); @@ -122,13 +133,16 @@ describe("compaction hook wiring", () => { expect(hookMocks.runner.runAfterCompaction).toHaveBeenCalledTimes(1); const afterCalls = hookMocks.runner.runAfterCompaction.mock.calls as unknown as Array< - [unknown] + [unknown, unknown] >; const event = afterCalls[0]?.[0] as - | { messageCount?: number; compactedCount?: number } + | { messageCount?: number; compactedCount?: number; sessionFile?: string } | undefined; expect(event?.messageCount).toBe(2); expect(event?.compactedCount).toBe(1); + expect(event?.sessionFile).toBe("/tmp/session.jsonl"); + const hookCtx = afterCalls[0]?.[1] as { sessionKey?: string } | undefined; + expect(hookCtx?.sessionKey).toBe("agent:main:web-xyz"); expect(ctx.incrementCompactionCount).toHaveBeenCalledTimes(1); expect(ctx.maybeResolveCompactionWait).toHaveBeenCalledTimes(1); expect(hookMocks.emitAgentEvent).toHaveBeenCalledWith({