From 8dc978ffde2f12f152240708607812630b168233 Mon Sep 17 00:00:00 2001 From: Ashton Anderson Date: Sat, 28 Mar 2026 12:19:58 -0400 Subject: [PATCH] fix: prompt download when maia3 cache is missing --- public/maia-worker.js | 6 ++++- src/lib/engine/storage.ts | 57 +++++++++++++++++++-------------------- 2 files changed, 33 insertions(+), 30 deletions(-) diff --git a/public/maia-worker.js b/public/maia-worker.js index 6a908068..7378b0f1 100644 --- a/public/maia-worker.js +++ b/public/maia-worker.js @@ -24,6 +24,10 @@ const DB_NAME = 'MaiaModels' const STORE_NAME = 'models' const MODEL_KEY = 'maia-rapid-model' +function isCompatibleModelCache(data, expectedUrl, expectedVersion) { + return data.url === expectedUrl && data.version === expectedVersion +} + function openDB() { return new Promise((resolve, reject) => { const request = indexedDB.open(DB_NAME, 1) @@ -51,7 +55,7 @@ async function getCachedModel(modelUrl, modelVersion) { if (!data) return null - if (data.version && data.version !== modelVersion) { + if (!isCompatibleModelCache(data, modelUrl, modelVersion)) { const rwTx = db.transaction([STORE_NAME], 'readwrite') rwTx.objectStore(STORE_NAME).delete(MODEL_KEY) return null diff --git a/src/lib/engine/storage.ts b/src/lib/engine/storage.ts index 701496bc..21b06825 100644 --- a/src/lib/engine/storage.ts +++ b/src/lib/engine/storage.ts @@ -7,6 +7,16 @@ interface ModelStorage { size: number } +const MODEL_STORAGE_KEY = 'maia-rapid-model' + +function isCompatibleModelCache( + modelData: ModelStorage, + modelUrl: string, + modelVersion: string, +): boolean { + return modelData.version === modelVersion && modelData.url === modelUrl +} + export class MaiaModelStorage { private dbName = 'MaiaModels' private storeName = 'models' @@ -46,7 +56,7 @@ export class MaiaModelStorage { const store = transaction.objectStore(this.storeName) const modelData: ModelStorage = { - id: 'maia-rapid-model', + id: MODEL_STORAGE_KEY, url: modelUrl, version: modelVersion, data: new Blob([buffer]), @@ -82,7 +92,7 @@ export class MaiaModelStorage { console.log('Storage: Requesting model data...') const modelData = await new Promise( (resolve, reject) => { - const request = store.get('maia-rapid-model') + const request = store.get(MODEL_STORAGE_KEY) request.onsuccess = () => { console.log( 'Storage: IndexedDB request successful, result:', @@ -104,36 +114,25 @@ export class MaiaModelStorage { return null } - // Version mismatch = genuinely new model, must re-download. - if (modelData.version && modelData.version !== modelVersion) { - console.log('Storage: Model version changed, clearing old cache') - console.log('Storage: Cached version:', modelData.version) + // Maia cache records must match both the expected model version and URL. + // Legacy Maia-2 downloads may not include a version field; treating those + // as incompatible forces the download modal to appear instead of leaving + // analysis in a broken "loaded old model" state. + if (!isCompatibleModelCache(modelData, modelUrl, modelVersion)) { + console.log( + 'Storage: Cached Maia model is incompatible, clearing old cache', + ) + console.log('Storage: Cached URL:', modelData.url || '(missing)') + console.log( + 'Storage: Cached version:', + modelData.version || '(missing)', + ) + console.log('Storage: Required URL:', modelUrl) console.log('Storage: Required version:', modelVersion) await this.deleteModel() return null } - // URL changed but same version (e.g. moved hosts) — keep the cache, - // just update the stored URL so future loads match immediately. - if (modelData.url !== modelUrl || modelData.version !== modelVersion) { - console.log('Storage: Updating stored URL/version') - try { - const rwTx = db.transaction([this.storeName], 'readwrite') - const rwStore = rwTx.objectStore(this.storeName) - await new Promise((resolve, reject) => { - const req = rwStore.put({ - ...modelData, - url: modelUrl, - version: modelVersion, - }) - req.onsuccess = () => resolve() - req.onerror = () => reject(req.error) - }) - } catch (e) { - console.warn('Storage: Failed to update stored URL/version:', e) - } - } - console.log('Storage: Converting Blob to ArrayBuffer...') // Convert Blob back to ArrayBuffer const buffer = await modelData.data.arrayBuffer() @@ -156,7 +155,7 @@ export class MaiaModelStorage { const store = transaction.objectStore(this.storeName) await new Promise((resolve, reject) => { - const request = store.delete('maia-rapid-model') + const request = store.delete(MODEL_STORAGE_KEY) request.onsuccess = () => resolve() request.onerror = () => reject(request.error) }) @@ -193,7 +192,7 @@ export class MaiaModelStorage { const modelData = await new Promise( (resolve, reject) => { - const request = store.get('maia-rapid-model') + const request = store.get(MODEL_STORAGE_KEY) request.onsuccess = () => resolve(request.result || null) request.onerror = () => reject(request.error) },