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
This commit is contained in:
garnetlyx
2026-04-13 23:40:51 -07:00
parent f98f7ec7a4
commit 177c51b640
2 changed files with 26 additions and 0 deletions
+12
View File
@@ -2,6 +2,10 @@ import { log } from "./logger"
import * as dataPath from "./data-path" import * as dataPath from "./data-path"
import { createJsonFileCacheStore } from "./json-file-cache-store" 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 CONNECTED_PROVIDERS_CACHE_FILE = "connected-providers.json"
const PROVIDER_MODELS_CACHE_FILE = "provider-models.json" const PROVIDER_MODELS_CACHE_FILE = "provider-models.json"
@@ -84,6 +88,12 @@ export function createConnectedProvidersCacheStore(
} }
function hasProviderModelsCache(): boolean { 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() return providerModelsCacheStore.has()
} }
@@ -92,6 +102,7 @@ export function createConnectedProvidersCacheStore(
...data, ...data,
updatedAt: new Date().toISOString(), updatedAt: new Date().toISOString(),
}) })
providerModelsCacheWrittenInCurrentProcess = true
} }
async function updateConnectedProvidersCache(client: { async function updateConnectedProvidersCache(client: {
@@ -161,6 +172,7 @@ export function createConnectedProvidersCacheStore(
function _resetMemCacheForTesting(): void { function _resetMemCacheForTesting(): void {
connectedProvidersCacheStore.resetMemory() connectedProvidersCacheStore.resetMemory()
providerModelsCacheStore.resetMemory() providerModelsCacheStore.resetMemory()
providerModelsCacheWrittenInCurrentProcess = false
} }
return { return {
+14
View File
@@ -27,6 +27,7 @@ export function createJsonFileCacheStore<TValue>(
options: JsonFileCacheStoreOptions<TValue>, options: JsonFileCacheStoreOptions<TValue>,
): JsonFileCacheStore<TValue> { ): JsonFileCacheStore<TValue> {
let memoryValue: TValue | null | undefined let memoryValue: TValue | null | undefined
let writtenInCurrentProcess = false
function getCacheFilePath(): string { function getCacheFilePath(): string {
return join(options.getCacheDir(), options.filename) return join(options.getCacheDir(), options.filename)
@@ -67,6 +68,17 @@ export function createJsonFileCacheStore<TValue>(
} }
function has(): boolean { 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()) return existsSync(getCacheFilePath())
} }
@@ -77,6 +89,7 @@ export function createJsonFileCacheStore<TValue>(
try { try {
writeFileSync(cacheFile, options.serialize?.(value) ?? JSON.stringify(value, null, 2)) writeFileSync(cacheFile, options.serialize?.(value) ?? JSON.stringify(value, null, 2))
memoryValue = value memoryValue = value
writtenInCurrentProcess = true
log(`[${options.logPrefix}] ${options.cacheLabel} written`, options.describe(value)) log(`[${options.logPrefix}] ${options.cacheLabel} written`, options.describe(value))
} catch (error) { } catch (error) {
log(`[${options.logPrefix}] Error writing ${toLogLabel(options.cacheLabel)}`, { log(`[${options.logPrefix}] Error writing ${toLogLabel(options.cacheLabel)}`, {
@@ -87,6 +100,7 @@ export function createJsonFileCacheStore<TValue>(
function resetMemory(): void { function resetMemory(): void {
memoryValue = undefined memoryValue = undefined
writtenInCurrentProcess = false
} }
return { return {