getModelFilePaths method
Gets the file paths for an installed model
Implementation
@override
Future<Map<String, String>?> getModelFilePaths(ModelSpec spec) async {
await _ensureInitialized();
// Phase 5: Delegate to Modern API
final registry = ServiceRegistry.instance;
final repository = registry.modelRepository;
final fileSystem = registry.fileSystemService as WebFileSystemService;
// Check installation via repository
bool allFilesInstalled = true;
for (final file in spec.files) {
if (!await repository.isInstalled(file.filename)) {
allFilesInstalled = false;
break;
}
}
if (!allFilesInstalled) {
return null;
}
final filePaths = <String, String>{};
for (final file in spec.files) {
// Get URL from WebFileSystemService based on source type
final String path;
if (file.source is NetworkSource) {
// Web: Get registered URL (blob URL for auth downloads)
// If URL lost (page reload), restore from Cache API
var url = fileSystem.getUrl(file.filename);
if (url == null) {
gemmaLog(
'[WebModelManager] Blob URL lost for ${file.filename}, restoring from cache...');
// Try to restore from Cache API
final networkSource = file.source as NetworkSource;
final downloadService =
registry.downloadService as WebDownloadService;
final cacheService = downloadService.cacheService;
// Get cached blob URL (cache service handles URL normalization internally)
final cachedBlobUrl =
await cacheService.getCachedBlobUrl(networkSource.url);
if (cachedBlobUrl != null) {
gemmaLog(
'[WebModelManager] ✅ Restored blob URL from cache: $cachedBlobUrl');
// Re-register the blob URL
fileSystem.registerUrl(file.filename, cachedBlobUrl);
url = cachedBlobUrl;
} else {
// Cached blob is gone and the auth token is not persisted across
// restarts (ModelSource.encode drops it). Falling back to the
// original URL works for PUBLIC models but a GATED model will fail
// the fetch later with an opaque network error. Surface it now at a
// visible level so the cause (re-auth / re-install needed) is clear.
gemmaLog(
'[WebModelManager] ⚠️ "${file.filename}" not in cache; falling back to original URL ${networkSource.url}. '
'If this model is gated/private, the load will fail (auth token is not restored) — re-install the model to re-authenticate.');
}
}
path = url ?? (file.source as NetworkSource).url;
} else if (file.source is BundledSource) {
// Web: Bundled resources
path = await fileSystem.getBundledResourcePath(
(file.source as BundledSource).resourceName);
} else if (file.source is AssetSource) {
// Web: Get registered Blob URL (created by WebAssetSourceHandler)
// If URL lost (page reload), recreate it
var url = fileSystem.getUrl(file.filename);
if (url == null) {
gemmaLog(
'[WebModelManager] Blob URL lost for ${file.filename}, recreating from asset...');
// Recreate Blob URL by reinstalling
final handler =
registry.sourceHandlerRegistry.getHandler(file.source);
if (handler != null) {
await handler.install(file.source);
url = fileSystem.getUrl(file.filename);
}
}
path = url ?? (file.source as AssetSource).normalizedPath;
} else if (file.source is FileSource) {
// Web: External URL or registered path
final fileSource = file.source as FileSource;
path = fileSystem.getUrl(file.filename) ?? fileSource.path;
} else {
// Fallback: use getTargetPath
path = await fileSystem.getTargetPath(file.filename);
}
filePaths[file.prefsKey] = path;
}
return filePaths.isNotEmpty ? filePaths : null;
}