diff --git a/src/config.ts b/src/config.ts index 7968228..591d2a9 100644 --- a/src/config.ts +++ b/src/config.ts @@ -583,6 +583,21 @@ function buildConfig(fileConfig: OpenCodeMemConfig) { } const _globalFileConfig = loadConfigFromPaths(CONFIG_FILES); +let lastKnownGlobalConfig = _globalFileConfig; + +function isCurrentConfigFromLastKnownGlobal(): boolean { + if (Object.keys(lastKnownGlobalConfig).length === 0) return false; + const globalConfig = buildConfig(lastKnownGlobalConfig); + return ( + CONFIG.embeddingModel === globalConfig.embeddingModel && + CONFIG.embeddingDimensions === globalConfig.embeddingDimensions && + CONFIG.embeddingApiUrl === globalConfig.embeddingApiUrl && + CONFIG.embeddingApiKey === globalConfig.embeddingApiKey && + CONFIG.opencodeProvider === globalConfig.opencodeProvider && + CONFIG.opencodeModel === globalConfig.opencodeModel && + CONFIG.autoCaptureEnabled === globalConfig.autoCaptureEnabled + ); +} /** * Global CONFIG singleton — resolves from opencode-mem0.json and env. @@ -617,6 +632,17 @@ export function initConfig(directory: string): void { ]; const globalConfig = loadConfigFromPaths(CONFIG_FILES); const projectConfig = loadConfigFromPaths(projectPaths); + if (Object.keys(globalConfig).length > 0) { + lastKnownGlobalConfig = globalConfig; + } + if (Object.keys(globalConfig).length === 0 && Object.keys(projectConfig).length === 0) { + if (isCurrentConfigFromLastKnownGlobal()) { + Object.assign(CONFIG, buildConfig(lastKnownGlobalConfig)); + } else { + Object.assign(CONFIG, buildConfig({})); + } + return; + } const merged = deepMerge(globalConfig, projectConfig); Object.assign(CONFIG, buildConfig(merged)); } diff --git a/tests/config-resolution.test.ts b/tests/config-resolution.test.ts index 85e900b..5d3b476 100644 --- a/tests/config-resolution.test.ts +++ b/tests/config-resolution.test.ts @@ -81,4 +81,24 @@ describe("project-scoped config resolution", () => { expect(CONFIG.autoCaptureEnabled).toBe(true); // default value expect(CONFIG.opencodeProvider).toBeUndefined(); }); + + it("uses the last known global config when config paths are temporarily unavailable", () => { + (globalThis as any).__mockFs.existsSync = (p: unknown) => { + const path = String(p); + return path.includes(".config/opencode/opencode-mem0"); + }; + (globalThis as any).__mockFs.readFileSync = () => + JSON.stringify({ + embeddingModel: "text-embedding-3-small", + embeddingDimensions: 1536, + }); + initConfig("/some/project"); + expect(CONFIG.embeddingModel).toBe("text-embedding-3-small"); + expect(CONFIG.embeddingDimensions).toBe(1536); + + (globalThis as any).__mockFs.existsSync = () => false; + initConfig("/some/project"); + expect(CONFIG.embeddingModel).toBe("text-embedding-3-small"); + expect(CONFIG.embeddingDimensions).toBe(1536); + }); });