From 9f8ab61a98a6d48de3f9e0053ba6312ef2311fd2 Mon Sep 17 00:00:00 2001 From: Josh Lehman Date: Mon, 20 Apr 2026 11:54:06 -0700 Subject: [PATCH] fix: preserve compaction overrides across loader reloads --- src/agents/pi-embedded-runner/compact.ts | 33 ++++++-------- ...pt.spawn-workspace.resource-loader.test.ts | 43 +++++++++++++++++++ .../attempt.spawn-workspace.test-support.ts | 7 +++ src/agents/pi-embedded-runner/run/attempt.ts | 33 ++++++-------- 4 files changed, 78 insertions(+), 38 deletions(-) create mode 100644 src/agents/pi-embedded-runner/run/attempt.spawn-workspace.resource-loader.test.ts diff --git a/src/agents/pi-embedded-runner/compact.ts b/src/agents/pi-embedded-runner/compact.ts index 7dbe5329569..39948d67111 100644 --- a/src/agents/pi-embedded-runner/compact.ts +++ b/src/agents/pi-embedded-runner/compact.ts @@ -824,25 +824,20 @@ export async function compactEmbeddedPiSessionDirect( modelId, model, }); - // Only create an explicit resource loader when there are extension factories - // to register; otherwise let createAgentSession use its built-in default. - let resourceLoader: DefaultResourceLoader | undefined; - if (extensionFactories.length > 0) { - resourceLoader = new DefaultResourceLoader({ - cwd: resolvedWorkspace, - agentDir, - settingsManager, - extensionFactories, - }); - await resourceLoader.reload(); - // DefaultResourceLoader.reload() rehydrates settings from disk and can drop OpenClaw - // compaction overrides applied in createPreparedEmbeddedPiSettingsManager. - applyPiCompactionSettingsFromConfig({ - settingsManager, - cfg: params.config, - contextTokenBudget: ctxInfo.tokens, - }); - } + const resourceLoader = new DefaultResourceLoader({ + cwd: resolvedWorkspace, + agentDir, + settingsManager, + extensionFactories, + }); + await resourceLoader.reload(); + // DefaultResourceLoader.reload() rehydrates settings from disk and can drop OpenClaw + // compaction overrides applied in createPreparedEmbeddedPiSettingsManager. + applyPiCompactionSettingsFromConfig({ + settingsManager, + cfg: params.config, + contextTokenBudget: ctxInfo.tokens, + }); const { builtInTools, customTools } = splitSdkTools({ tools: effectiveTools, diff --git a/src/agents/pi-embedded-runner/run/attempt.spawn-workspace.resource-loader.test.ts b/src/agents/pi-embedded-runner/run/attempt.spawn-workspace.resource-loader.test.ts new file mode 100644 index 00000000000..cda4d3d7d80 --- /dev/null +++ b/src/agents/pi-embedded-runner/run/attempt.spawn-workspace.resource-loader.test.ts @@ -0,0 +1,43 @@ +import { afterEach, beforeEach, describe, expect, it } from "vitest"; +import { + cleanupTempPaths, + createContextEngineAttemptRunner, + getHoisted, + resetEmbeddedAttemptHarness, +} from "./attempt.spawn-workspace.test-support.js"; + +const hoisted = getHoisted(); + +describe("runEmbeddedAttempt resource loader wiring", () => { + const tempPaths: string[] = []; + + beforeEach(() => { + resetEmbeddedAttemptHarness(); + }); + + afterEach(async () => { + await cleanupTempPaths(tempPaths); + }); + + it("passes an explicit resourceLoader to createAgentSession even without extension factories", async () => { + await createContextEngineAttemptRunner({ + sessionKey: "agent:main:discord:dm:test-resource-loader", + tempPaths, + contextEngine: { + assemble: async ({ messages }) => ({ + messages, + estimatedTokens: 1, + }), + }, + }); + + expect(hoisted.createAgentSessionMock).toHaveBeenCalled(); + expect(hoisted.createAgentSessionMock).toHaveBeenCalledWith( + expect.objectContaining({ + resourceLoader: expect.objectContaining({ + reload: expect.any(Function), + }), + }), + ); + }); +}); diff --git a/src/agents/pi-embedded-runner/run/attempt.spawn-workspace.test-support.ts b/src/agents/pi-embedded-runner/run/attempt.spawn-workspace.test-support.ts index 9aa30e1db83..b760e74ebd0 100644 --- a/src/agents/pi-embedded-runner/run/attempt.spawn-workspace.test-support.ts +++ b/src/agents/pi-embedded-runner/run/attempt.spawn-workspace.test-support.ts @@ -284,6 +284,13 @@ vi.mock("../../pi-project-settings.js", () => ({ vi.mock("../../pi-settings.js", () => ({ applyPiAutoCompactionGuard: () => {}, + applyPiCompactionSettingsFromConfig: () => ({ + didOverride: false, + compaction: { + reserveTokens: 0, + keepRecentTokens: 40_000, + }, + }), })); vi.mock("../extensions.js", () => ({ diff --git a/src/agents/pi-embedded-runner/run/attempt.ts b/src/agents/pi-embedded-runner/run/attempt.ts index 9e0cfe69a9d..20685b2d1f3 100644 --- a/src/agents/pi-embedded-runner/run/attempt.ts +++ b/src/agents/pi-embedded-runner/run/attempt.ts @@ -1022,25 +1022,20 @@ export async function runEmbeddedAttempt( modelId: params.modelId, model: params.model, }); - // Only create an explicit resource loader when there are extension factories - // to register; otherwise let createAgentSession use its built-in default. - let resourceLoader: DefaultResourceLoader | undefined; - if (extensionFactories.length > 0) { - resourceLoader = new DefaultResourceLoader({ - cwd: resolvedWorkspace, - agentDir, - settingsManager, - extensionFactories, - }); - await resourceLoader.reload(); - // DefaultResourceLoader.reload() rehydrates settings from disk and can drop OpenClaw - // compaction overrides applied in createPreparedEmbeddedPiSettingsManager. - applyPiCompactionSettingsFromConfig({ - settingsManager, - cfg: params.config, - contextTokenBudget: params.contextTokenBudget, - }); - } + const resourceLoader = new DefaultResourceLoader({ + cwd: resolvedWorkspace, + agentDir, + settingsManager, + extensionFactories, + }); + await resourceLoader.reload(); + // DefaultResourceLoader.reload() rehydrates settings from disk and can drop OpenClaw + // compaction overrides applied in createPreparedEmbeddedPiSettingsManager. + applyPiCompactionSettingsFromConfig({ + settingsManager, + cfg: params.config, + contextTokenBudget: params.contextTokenBudget, + }); // Get hook runner early so it's available when creating tools const hookRunner = getGlobalHookRunner();