- 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>
109 lines
3.3 KiB
JavaScript
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);
|
|
})
|
|
);
|
|
});
|