From 177c51b64086ae43c03534a77b13cc5e81892fff Mon Sep 17 00:00:00 2001 From: garnetlyx Date: Mon, 13 Apr 2026 23:40:51 -0700 Subject: [PATCH] fix: use in-process flag instead of existsSync for cache availability In OpenCode plugin sandbox, existsSync fails across different hook contexts (config vs chat.message) because each runs in an isolated virtual filesystem. Add writtenInCurrentProcess flags to track cache writes at the process level, eliminating spurious Model Cache Not Found toast warnings. Closes #3412 --- src/shared/connected-providers-cache.ts | 12 ++++++++++++ src/shared/json-file-cache-store.ts | 14 ++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/src/shared/connected-providers-cache.ts b/src/shared/connected-providers-cache.ts index 582c26f01..f27e9f76d 100644 --- a/src/shared/connected-providers-cache.ts +++ b/src/shared/connected-providers-cache.ts @@ -2,6 +2,10 @@ import { log } from "./logger" import * as dataPath from "./data-path" import { createJsonFileCacheStore } from "./json-file-cache-store" +// Track if provider models cache has been successfully written in the current process +// This helps in sandbox environments where filesystem state may not persist across contexts +let providerModelsCacheWrittenInCurrentProcess = false + const CONNECTED_PROVIDERS_CACHE_FILE = "connected-providers.json" const PROVIDER_MODELS_CACHE_FILE = "provider-models.json" @@ -84,6 +88,12 @@ export function createConnectedProvidersCacheStore( } function hasProviderModelsCache(): boolean { + // First check if we've written the cache in the current process + // This handles sandbox environments where filesystem state may not persist across contexts + if (providerModelsCacheWrittenInCurrentProcess) { + return true + } + // Fall back to the store's has() method (which also checks in-memory state) return providerModelsCacheStore.has() } @@ -92,6 +102,7 @@ export function createConnectedProvidersCacheStore( ...data, updatedAt: new Date().toISOString(), }) + providerModelsCacheWrittenInCurrentProcess = true } async function updateConnectedProvidersCache(client: { @@ -161,6 +172,7 @@ export function createConnectedProvidersCacheStore( function _resetMemCacheForTesting(): void { connectedProvidersCacheStore.resetMemory() providerModelsCacheStore.resetMemory() + providerModelsCacheWrittenInCurrentProcess = false } return { diff --git a/src/shared/json-file-cache-store.ts b/src/shared/json-file-cache-store.ts index 5561a66b9..18ee6c0d1 100644 --- a/src/shared/json-file-cache-store.ts +++ b/src/shared/json-file-cache-store.ts @@ -27,6 +27,7 @@ export function createJsonFileCacheStore( options: JsonFileCacheStoreOptions, ): JsonFileCacheStore { let memoryValue: TValue | null | undefined + let writtenInCurrentProcess = false function getCacheFilePath(): string { return join(options.getCacheDir(), options.filename) @@ -67,6 +68,17 @@ export function createJsonFileCacheStore( } function has(): boolean { + // First check if we have a valid in-memory cache value + // This handles sandbox environments where existsSync may fail across contexts + if (memoryValue !== undefined && memoryValue !== null) { + return true + } + // Check if we've written to this cache in the current process + // This helps in sandbox environments where filesystem state may not persist across contexts + if (writtenInCurrentProcess) { + return true + } + // Fall back to filesystem check return existsSync(getCacheFilePath()) } @@ -77,6 +89,7 @@ export function createJsonFileCacheStore( try { writeFileSync(cacheFile, options.serialize?.(value) ?? JSON.stringify(value, null, 2)) memoryValue = value + writtenInCurrentProcess = true log(`[${options.logPrefix}] ${options.cacheLabel} written`, options.describe(value)) } catch (error) { log(`[${options.logPrefix}] Error writing ${toLogLabel(options.cacheLabel)}`, { @@ -87,6 +100,7 @@ export function createJsonFileCacheStore( function resetMemory(): void { memoryValue = undefined + writtenInCurrentProcess = false } return {