Files
aiagent/frontend/public/sw.js
renjianbo beff3fac8d fix: delete agent 500 error + dynamic personality + deployment guide
- Fix delete agent 500: clean up FK records (agent_llm_logs, permissions,
  schedules, executions, team_members) and unbind goals/tasks before delete
- Remove hardcoded personality templates in Android, replace with dynamic
  system prompt generation from name + description
- Set promptSectionsEnabled=false to bypass PromptComposer for personality
- Add Tencent Cloud Linux deployment guide (Docker Compose)
- Accumulated backend service updates, frontend UI fixes, Android app changes

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-06-29 01:17:21 +08:00

109 lines
3.3 KiB
JavaScript

/**
* 天工智能体平台 — Service Worker
*
* - 离线缓存:静态资源 + API 响应
* - 推送通知
* - 安装后激活
*/
const CACHE_NAME = 'aiagent-v1.0.0';
const RUNTIME_CACHE = 'aiagent-runtime';
const PRECACHE_URLS = [
'/',
'/index.html',
'/manifest.json',
];
// ─── Install: 预缓存关键资源 ───────────────────────────────────
self.addEventListener('install', (event) => {
event.waitUntil(
caches.open(CACHE_NAME).then((cache) => {
return cache.addAll(PRECACHE_URLS);
}).then(() => self.skipWaiting())
);
});
// ─── Activate: 清理旧缓存 ──────────────────────────────────────
self.addEventListener('activate', (event) => {
event.waitUntil(
caches.keys().then((names) => {
return Promise.all(
names
.filter((n) => n !== CACHE_NAME && n !== RUNTIME_CACHE)
.map((n) => caches.delete(n))
);
}).then(() => self.clients.claim())
);
});
// ─── Fetch: 网络优先 + 缓存回退 ────────────────────────────────
self.addEventListener('fetch', (event) => {
const { request } = event;
if (request.method !== 'GET') return;
// API 请求:网络优先
if (request.url.includes('/api/')) {
event.respondWith(
fetch(request)
.then((response) => {
const clone = response.clone();
caches.open(RUNTIME_CACHE).then((cache) => {
cache.put(request, clone);
});
return response;
})
.catch(() => caches.match(request))
);
return;
}
// 静态资源:缓存优先
event.respondWith(
caches.match(request).then((cached) => {
const fetched = fetch(request).then((response) => {
const clone = response.clone();
caches.open(RUNTIME_CACHE).then((cache) => {
cache.put(request, clone);
});
return response;
});
return cached || fetched;
})
);
});
// ─── Push: 浏览器推送通知 ──────────────────────────────────────
self.addEventListener('push', (event) => {
if (!event.data) return;
const data = event.data.json().catch(() => ({ title: '天工智能体', body: event.data.text() }));
const options = {
body: data.body || '',
icon: '/icons/icon-192.png',
badge: '/icons/icon-192.png',
data: data.data || {},
vibrate: [200, 100, 200],
requireInteraction: data.requireInteraction || false,
};
event.waitUntil(
self.registration.showNotification(data.title || '天工智能体', options)
);
});
// ─── Notification Click ─────────────────────────────────────────
self.addEventListener('notificationclick', (event) => {
event.notification.close();
const url = event.notification.data?.url || '/';
event.waitUntil(
self.clients.matchAll({ type: 'window' }).then((clients) => {
for (const client of clients) {
if (client.url.includes(url) && 'focus' in client) {
return client.focus();
}
}
return self.clients.openWindow(url);
})
);
});