Something went wrong. Try again.
ATProto-based AI Assistant Chat interface.
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263// The service worker, which keeps the build's files and shows an offline page when the app is// opened without a connection. It caches nothing else: chats live on the user's PDS and in the// browser's local copy, and the API, streams, sign-in, and blobs always go to the network. It is// plain JavaScript, since TypeScript's worker types clash with the DOM's.
// The build writes this file to /sw.js with the placeholder replaced by a name for the build, so// each build installs a new worker with a fresh cache.const cacheName = 'scn-chat-__BUILD__'const offlinePage = '/offline.html'
/** Paths the worker never answers, even as a page load: sign-in, a blob opened in a tab, XRPC. */const passThrough = ['/api/', '/oauth/', '/xrpc/']
self.addEventListener('install', (event) => { event.waitUntil( caches .open(cacheName) .then((cache) => cache.add(offlinePage)) .then(() => self.skipWaiting()), )})
self.addEventListener('activate', (event) => { event.waitUntil( (async () => { for (const name of await caches.keys()) { if (name.startsWith('scn-chat-') && name !== cacheName) await caches.delete(name) } // A page load starts while the worker wakes up, rather than after. await self.registration.navigationPreload?.enable() await self.clients.claim() })(), )})
self.addEventListener('fetch', (event) => { const request = event.request const url = new URL(request.url) if (request.method !== 'GET' || url.origin !== self.location.origin) return if (passThrough.some((prefix) => url.pathname.startsWith(prefix))) return if (url.pathname.startsWith('/assets/')) event.respondWith(buildFile(request)) else if (request.mode === 'navigate') event.respondWith(pageOrOffline(event))})
/** A build file, named by a hash of its content, so a kept copy never goes stale. */async function buildFile(request) { const cache = await caches.open(cacheName) const kept = await cache.match(request) if (kept) return kept const response = await fetch(request) if (response.ok) await cache.put(request, response.clone()) return response}
/** A page from the network, or the offline page when the network can't be reached. */async function pageOrOffline(event) { try { return (await event.preloadResponse) ?? (await fetch(event.request)) } catch { return (await caches.match(offlinePage)) ?? Response.error() }}