auto-save 2026-05-11 16:26 (~5)
This commit is contained in:
@@ -1,12 +1,5 @@
|
||||
{
|
||||
"entries": [
|
||||
{
|
||||
"files_changed": 1,
|
||||
"hash": "b28763a",
|
||||
"message": "auto-save 2026-05-10 07:57 (~1)",
|
||||
"ts": "2026-05-10T07:57:28+08:00",
|
||||
"type": "commit"
|
||||
},
|
||||
{
|
||||
"files_changed": 1,
|
||||
"message": "Codex 会话活跃 · 最近命令:codex · 分支 master · 1 项未提交变更 · 最近提交:auto-save 2026-05-10 07:57 (~1)",
|
||||
@@ -3261,6 +3254,13 @@
|
||||
"type": "session-heartbeat",
|
||||
"message": "Codex 会话活跃 · 最近命令:codex · 分支 master · 1 项未提交变更 · 最近提交:auto-save 2026-05-11 16:14 (~1)",
|
||||
"files_changed": 1
|
||||
},
|
||||
{
|
||||
"ts": "2026-05-11T16:20:30+08:00",
|
||||
"type": "commit",
|
||||
"message": "auto-save 2026-05-11 16:20 (~1)",
|
||||
"hash": "b25e7e9",
|
||||
"files_changed": 1
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
2
RULES.md
2
RULES.md
@@ -20,7 +20,7 @@
|
||||
- 爱马仕前端「仪表盘」活动热力图已重做为带摘要、月份标尺、紧凑格子和细分色阶的活动卡片
|
||||
- 爱马仕前端「设置 → 连接」可自助维护 API 地址 / API Key 并测试连接;「对话 → 存周报」和「设置 → 周报记录」会在本地保存任务描述、上下文片段和最终周报
|
||||
- 爱马仕前端「设置 → AI 模型接入」和「设置 → MCP 工具接入」可分别维护 LXC 内 `/opt/hermes-agent/config.yaml` 的 `model` 与 `mcp_servers` 块,保存后重启 Docker `hermes-agent`
|
||||
- 当前前端静态壳缓存版本:`hermes-ui-v31`
|
||||
- 当前前端不再启用 Service Worker 静态壳缓存;`sw.js` 仅用于清理旧 `hermes-ui-*` 缓存并注销旧注册
|
||||
- 文档 / 解析:https://styles.kang-kang.com
|
||||
- 管理后台:待定
|
||||
- 代码仓:https://git.kang-kang.com/kangwan/hermes-glass-ui-personal
|
||||
|
||||
16
src/app.js
16
src/app.js
@@ -74,11 +74,21 @@ document.addEventListener("DOMContentLoaded", () => {
|
||||
fetchIP();
|
||||
setInterval(pingBackend, 30000);
|
||||
|
||||
if ("serviceWorker" in navigator) {
|
||||
navigator.serviceWorker.register("./sw.js").catch(() => {});
|
||||
}
|
||||
disableLegacyServiceWorkers();
|
||||
});
|
||||
|
||||
function disableLegacyServiceWorkers() {
|
||||
if (!("serviceWorker" in navigator)) return;
|
||||
navigator.serviceWorker.getRegistrations()
|
||||
.then((registrations) => Promise.all(registrations.map((registration) => registration.unregister())))
|
||||
.catch(() => {});
|
||||
if ("caches" in window) {
|
||||
caches.keys()
|
||||
.then((keys) => Promise.all(keys.filter((key) => key.startsWith("hermes-ui-")).map((key) => caches.delete(key))))
|
||||
.catch(() => {});
|
||||
}
|
||||
}
|
||||
|
||||
// ---------- 主题 ----------
|
||||
function loadTheme() {
|
||||
const theme = localStorage.getItem(LS_THEME) || "dark";
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
<link rel="icon" type="image/svg+xml" href="./icon.svg">
|
||||
<link rel="apple-touch-icon" href="./icon.svg">
|
||||
<title>爱马仕 · AI</title>
|
||||
<link rel="stylesheet" href="./styles.css?v=20260511-settings-v31">
|
||||
<link rel="stylesheet" href="./styles.css?v=20260511-whiteout-v32">
|
||||
</head>
|
||||
<body>
|
||||
|
||||
@@ -781,13 +781,13 @@ rsync -az src/ root@76.13.31.179:/var/www/hermes-kang/
|
||||
# Git
|
||||
git push # Gitea kangwan/hermes-glass-ui-personal
|
||||
|
||||
# 如果改了 JS/CSS 要让浏览器刷新,记得 bump sw.js 的 CACHE 版本号</code></pre>
|
||||
# 如果改了 JS/CSS 要让浏览器刷新,更新 index.html 里的资源 query 版本</code></pre>
|
||||
</div>
|
||||
|
||||
<div class="help-card">
|
||||
<h3>🛠 常见问题</h3>
|
||||
<ul>
|
||||
<li><b>新改的东西没显示</b> → Service Worker 缓存顽固,bump <code>sw.js</code> 里 <code>CACHE</code> 版本号,再 F12 → Application → Unregister</li>
|
||||
<li><b>新改的东西没显示</b> → 刷新页面;旧浏览器如果曾安装 Service Worker,当前 <code>sw.js</code> 会自动清理并注销</li>
|
||||
<li><b>VPS 后端换模型</b> → 改容器内 <code>/opt/hermes-agent/config.yaml + .env</code>,<code>docker restart hermes-agent</code></li>
|
||||
<li><b>记忆 tab 看不到最新会话</b> → systemd timer 1 分钟一次,急的话 <code>ssh root@76.13.31.179 /usr/local/bin/sync-hermes-memory.sh</code></li>
|
||||
<li><b>Cron 任务不触发</b> → 看 Hermes 容器日志 <code>docker logs hermes-agent</code></li>
|
||||
@@ -1408,6 +1408,6 @@ git push # Gitea kangwan/hermes-glass-ui-personal
|
||||
</main>
|
||||
</div>
|
||||
|
||||
<script src="./app.js?v=20260511-settings-v31"></script>
|
||||
<script src="./app.js?v=20260511-whiteout-v32"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
54
src/sw.js
54
src/sw.js
@@ -1,47 +1,23 @@
|
||||
// 爱马仕 Hermes · 轻量 Service Worker
|
||||
// 静态壳走 network-first(拿不到再回退缓存),API 直通
|
||||
const CACHE = "hermes-ui-v31";
|
||||
const ASSETS = [
|
||||
"./styles.css?v=20260511-settings-v31",
|
||||
"./app.js?v=20260511-settings-v31",
|
||||
"./manifest.webmanifest",
|
||||
"./icon.svg",
|
||||
];
|
||||
// 爱马仕 Hermes · Service Worker 退场脚本
|
||||
// 个人版有 cookie 门禁,旧 SW 拦截导航时会造成白屏;新版本不再离线缓存。
|
||||
const CACHE_PREFIX = "hermes-ui-";
|
||||
|
||||
self.addEventListener("install", (e) => {
|
||||
e.waitUntil(caches.open(CACHE).then((c) => c.addAll(ASSETS)));
|
||||
self.skipWaiting();
|
||||
e.waitUntil(self.skipWaiting());
|
||||
});
|
||||
|
||||
async function cleanup() {
|
||||
const keys = await caches.keys();
|
||||
await Promise.all(keys.filter((key) => key.startsWith(CACHE_PREFIX)).map((key) => caches.delete(key)));
|
||||
await self.registration.unregister();
|
||||
const clients = await self.clients.matchAll({ type: "window", includeUncontrolled: true });
|
||||
for (const client of clients) client.navigate(client.url);
|
||||
}
|
||||
|
||||
self.addEventListener("activate", (e) => {
|
||||
e.waitUntil(
|
||||
caches.keys().then((keys) =>
|
||||
Promise.all(keys.filter((k) => k !== CACHE).map((k) => caches.delete(k)))
|
||||
)
|
||||
);
|
||||
self.clients.claim();
|
||||
e.waitUntil(cleanup());
|
||||
});
|
||||
|
||||
self.addEventListener("fetch", (e) => {
|
||||
const url = new URL(e.request.url);
|
||||
// API / 鉴权 / skill 索引等动态资源全部直通
|
||||
if (url.pathname.startsWith("/api/")) return;
|
||||
if (url.pathname.startsWith("/_auth/")) return;
|
||||
if (url.pathname.startsWith("/feishu/")) return;
|
||||
if (url.pathname.startsWith("/hermes-skills/")) return;
|
||||
if (e.request.method !== "GET") return;
|
||||
if (e.request.mode === "navigate" || e.request.destination === "document") return;
|
||||
|
||||
// 静态资源:network-first,离线再回退缓存;HTML 导航始终交给 nginx。
|
||||
e.respondWith(
|
||||
fetch(e.request)
|
||||
.then((res) => {
|
||||
if (res && res.ok) {
|
||||
const copy = res.clone();
|
||||
caches.open(CACHE).then((c) => c.put(e.request, copy)).catch(() => {});
|
||||
}
|
||||
return res;
|
||||
})
|
||||
.catch(() => caches.match(e.request).then((hit) => hit || Response.error()))
|
||||
);
|
||||
self.addEventListener("fetch", () => {
|
||||
// Do not intercept anything.
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user