fix(coding-agent): preserve in-memory settings on reload

closes #3616
This commit is contained in:
Mario Zechner
2026-04-23 23:47:49 +02:00
parent 4cd4cfd98e
commit 86ba08a2e3
3 changed files with 90 additions and 1 deletions

View File

@@ -24,6 +24,7 @@
### Fixed
- Fixed `SettingsManager.inMemory()` initial settings being lost after reloads triggered by SDK resource loading ([#3616](https://github.com/badlogic/pi-mono/issues/3616))
- Fixed `models.json` provider compatibility to accept `compat.supportsLongCacheRetention`, allowing proxies to opt out of long-retention cache fields when needed while long retention is enabled by default when requested ([#3543](https://github.com/badlogic/pi-mono/issues/3543))
- Fixed `--thinking xhigh` for `openai-codex` `gpt-5.5` so it is no longer downgraded to `high`.
- Fixed git package installs with custom `npmCommand` values such as `pnpm` by avoiding npm-specific production flags in that compatibility path ([#3604](https://github.com/badlogic/pi-mono/issues/3604))

View File

@@ -289,7 +289,9 @@ export class SettingsManager {
/** Create an in-memory SettingsManager (no file I/O) */
static inMemory(settings: Partial<Settings> = {}): SettingsManager {
const storage = new InMemorySettingsStorage();
return new SettingsManager(storage, settings, {});
const initialSettings = SettingsManager.migrateSettings(structuredClone(settings) as Record<string, unknown>);
storage.withLock("global", () => JSON.stringify(initialSettings, null, 2));
return SettingsManager.fromStorage(storage);
}
private static loadFromStorage(storage: SettingsStorage, scope: SettingsScope): Settings {

View File

@@ -0,0 +1,86 @@
import { existsSync, mkdirSync, rmSync } from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { afterEach, beforeEach, describe, expect, it } from "vitest";
import { DefaultResourceLoader } from "../../../src/core/resource-loader.js";
import { SettingsManager } from "../../../src/core/settings-manager.js";
describe("regression #3616: in-memory settings survive reload", () => {
let tempDir: string;
let agentDir: string;
beforeEach(() => {
tempDir = join(tmpdir(), `pi-settings-inmemory-${Date.now()}-${Math.random().toString(36).slice(2)}`);
agentDir = join(tempDir, "agent");
mkdirSync(agentDir, { recursive: true });
});
afterEach(() => {
if (tempDir && existsSync(tempDir)) {
rmSync(tempDir, { recursive: true, force: true });
}
});
it("preserves initial settings after direct reload", async () => {
const settingsManager = SettingsManager.inMemory({
defaultThinkingLevel: "high",
images: { autoResize: false },
compaction: { enabled: false },
});
await settingsManager.reload();
expect(settingsManager.getDefaultThinkingLevel()).toBe("high");
expect(settingsManager.getImageAutoResize()).toBe(false);
expect(settingsManager.getCompactionEnabled()).toBe(false);
expect(settingsManager.getGlobalSettings()).toEqual({
defaultThinkingLevel: "high",
images: { autoResize: false },
compaction: { enabled: false },
});
});
it("preserves initial settings when DefaultResourceLoader reloads", async () => {
const settingsManager = SettingsManager.inMemory({
defaultThinkingLevel: "high",
images: { autoResize: false },
compaction: { enabled: false },
});
const resourceLoader = new DefaultResourceLoader({
cwd: tempDir,
agentDir,
settingsManager,
noExtensions: true,
noSkills: true,
noPromptTemplates: true,
noThemes: true,
noContextFiles: true,
});
await resourceLoader.reload();
expect(settingsManager.getDefaultThinkingLevel()).toBe("high");
expect(settingsManager.getImageAutoResize()).toBe(false);
expect(settingsManager.getCompactionEnabled()).toBe(false);
});
it("preserves initial settings after an unrelated setter, flush, and reload", async () => {
const settingsManager = SettingsManager.inMemory({
images: { autoResize: false },
compaction: { enabled: false },
});
settingsManager.setTheme("dark");
await settingsManager.flush();
await settingsManager.reload();
expect(settingsManager.getTheme()).toBe("dark");
expect(settingsManager.getImageAutoResize()).toBe(false);
expect(settingsManager.getCompactionEnabled()).toBe(false);
expect(settingsManager.getGlobalSettings()).toEqual({
images: { autoResize: false },
compaction: { enabled: false },
theme: "dark",
});
});
});