fix: preserve compaction overrides across loader reloads

This commit is contained in:
Josh Lehman
2026-04-20 11:54:06 -07:00
parent c696718fc4
commit 9f8ab61a98
4 changed files with 78 additions and 38 deletions

View File

@@ -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,

View File

@@ -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),
}),
}),
);
});
});

View File

@@ -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", () => ({

View File

@@ -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();