spb/prisme Public MIT
Navigateur iOS intelligent — chaque page comprise localement avant d'être affichée. SwiftUI · WebKit · Foundation Models, 100% on-device.
Swift 96.7%
JavaScript 3.3%
1//2// DigestCache.swift3// Prisme4//5// Author: Simon-Pierre Boucher <contact@spboucher.ai>6//78import CryptoKit9import Foundation1011/// Content-addressed digest cache (CLAUDE.md §4: a page is never distilled12/// twice). Keys are hashes of the extracted text, so a reloaded page with13/// identical content is a hit even if the URL differs. Digests are durable14/// artefacts: kept in memory and on disk, ready to feed history and diffs.15actor DigestCache {16 private struct Entry: Codable {17 let digest: PageDigest18 let blocks: [ContentBlock]19 }2021 private var memory: [String: Entry] = [:]22 private let directory: URL2324 init() {25 let base = FileManager.default.urls(for: .applicationSupportDirectory, in: .userDomainMask)[0]26 directory = base.appendingPathComponent("Digests", isDirectory: true)27 try? FileManager.default.createDirectory(at: directory, withIntermediateDirectories: true)28 }2930 static func key(for content: ExtractedContent) -> String {31 var hasher = SHA256()32 hasher.update(data: Data(content.title.utf8))33 for block in content.blocks {34 hasher.update(data: Data(block.text.utf8))35 }36 return hasher.finalize().map { String(format: "%02x", $0) }.joined()37 }3839 func lookup(_ key: String) -> (PageDigest, [ContentBlock])? {40 if let entry = memory[key] {41 return (entry.digest, entry.blocks)42 }43 let file = directory.appendingPathComponent("\(key).json")44 guard let data = try? Data(contentsOf: file),45 let entry = try? JSONDecoder().decode(Entry.self, from: data)46 else { return nil }47 memory[key] = entry48 return (entry.digest, entry.blocks)49 }5051 func store(_ digest: PageDigest, blocks: [ContentBlock], key: String) {52 let entry = Entry(digest: digest, blocks: blocks)53 memory[key] = entry54 if memory.count > 64 {55 // Cheap pressure valve; disk keeps the long tail.56 memory.removeValue(forKey: memory.keys.first!)57 }58 let file = directory.appendingPathComponent("\(key).json")59 if let data = try? JSONEncoder().encode(entry) {60 try? data.write(to: file, options: .atomic)61 }62 }63}64