@@ -24,6 +24,7 @@
|
|||||||
|
|
||||||
### Fixed
|
### 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 `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 `--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))
|
- 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))
|
||||||
|
|||||||
@@ -289,7 +289,9 @@ export class SettingsManager {
|
|||||||
/** Create an in-memory SettingsManager (no file I/O) */
|
/** Create an in-memory SettingsManager (no file I/O) */
|
||||||
static inMemory(settings: Partial<Settings> = {}): SettingsManager {
|
static inMemory(settings: Partial<Settings> = {}): SettingsManager {
|
||||||
const storage = new InMemorySettingsStorage();
|
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 {
|
private static loadFromStorage(storage: SettingsStorage, scope: SettingsScope): Settings {
|
||||||
|
|||||||
@@ -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",
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user