auto-save 2026-05-09 19:04 (~6)

This commit is contained in:
2026-05-09 19:04:28 +08:00
parent 9f4d1d24ad
commit 385ecbb8da
6 changed files with 254 additions and 60 deletions

View File

@@ -1,12 +1,5 @@
{
"entries": [
{
"files_changed": 1,
"hash": "bf5eb1e",
"message": "auto-save 2026-05-07 18:06 (~1)",
"ts": "2026-05-07T18:06:58+08:00",
"type": "commit"
},
{
"files_changed": 1,
"hash": "d05884a",
@@ -3459,6 +3452,13 @@
"type": "session-heartbeat",
"message": "Codex 会话活跃 · 最近命令codex · 分支 master · 2 项未提交变更 · 最近提交auto-save 2026-05-09 18:53 (~1)",
"files_changed": 2
},
{
"ts": "2026-05-09T18:58:57+08:00",
"type": "commit",
"message": "auto-save 2026-05-09 18:58 (~2)",
"hash": "9f4d1d2",
"files_changed": 2
}
]
}

View File

@@ -14,9 +14,9 @@
- 飞书事件回调(`cli_a97764e101b95be9`https://hermes.kang-kang.com/feishu/events/cli_a97764e101b95be9
- 飞书主动通知https://hermes.kang-kang.com/feishu/notify
- 飞书机器人列表https://hermes.kang-kang.com/feishu/apps只读展示 App ID / 回调地址,不含 Secret / Token
- 爱马仕前端「设置 → 飞书集成」可自助添加 / 更新飞书机器人Secret / Token 只写入服务器 `/etc/hermes-feishu-bridge.env`
- 爱马仕前端「集成 → 飞书集成」可自助添加 / 更新飞书机器人Secret / Token 只写入服务器 `/etc/hermes-feishu-bridge.env`
- 爱马仕前端「设置 → 连接」可自助维护 API 地址 / API Key 并测试连接;「对话 → 存周报」和「设置 → 周报记录」会在本地保存任务描述、上下文片段和最终周报
- 当前前端静态壳缓存版本:`hermes-ui-v13`
- 当前前端静态壳缓存版本:`hermes-ui-v14`
- 文档 / 解析https://styles.kang-kang.com
- 管理后台:待定
- 代码仓https://git.kang-kang.com/kangwan/hermes-glass-ui-personal

View File

@@ -358,10 +358,8 @@ function switchTab(name, options = {}) {
if (name === "cron") refreshCron();
if (name === "memory") refreshMemory();
if (name === "tools") refreshTools();
if (name === "settings") {
renderWeeklyReports();
refreshFeishuApps();
}
if (name === "integrations") refreshFeishuApps();
if (name === "settings") renderWeeklyReports();
if (name === "runs") setTimeout(() => document.getElementById("runPrompt")?.focus(), 50);
if (name === "dashboard" && _dashboardDirty) {
// 推迟到下一帧,避免阻塞切换动画

View File

@@ -62,6 +62,10 @@
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 2a5 5 0 0 0-5 5v2H5a2 2 0 0 0-2 2v9a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-9a2 2 0 0 0-2-2h-2V7a5 5 0 0 0-5-5z"/><circle cx="9" cy="14" r="1"/><circle cx="15" cy="14" r="1"/></svg>
<span>Agent</span>
</button>
<button class="side-item" data-tab="integrations">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="3" width="7" height="7" rx="1"/><rect x="14" y="3" width="7" height="7" rx="1"/><rect x="3" y="14" width="7" height="7" rx="1"/><rect x="14" y="14" width="7" height="7" rx="1"/><path d="M10 6.5h4"/><path d="M6.5 10v4"/><path d="M17.5 10v4"/><path d="M10 17.5h4"/></svg>
<span>集成</span>
</button>
<button class="side-item" data-tab="studio">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 2L2 7v10l10 5 10-5V7L12 2z"/><path d="M2 7l10 5 10-5"/><path d="M12 12v10"/></svg>
<span>Skill Studio</span>
@@ -981,6 +985,115 @@ git push # Gitea kangwan/hermes-glass-ui-personal
</div>
</section>
<!-- TAB: 集成 -->
<section class="tab-panel" id="tab-integrations">
<div class="panel-head">
<h2>机器人集成</h2>
<p>统一管理飞书、微信、WhatsApp、Telegram、Discord 等外部消息入口。</p>
</div>
<div class="integrations-scroll">
<div class="integration-grid">
<div class="integration-channel-card active">
<div class="integration-channel-head">
<div class="integration-channel-icon">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 15a4 4 0 0 1-4 4H8l-5 3V7a4 4 0 0 1 4-4h10a4 4 0 0 1 4 4z"/><path d="M8 9h8"/><path d="M8 13h5"/></svg>
</div>
<span class="integration-status ready">已接入</span>
</div>
<div class="integration-channel-title">飞书机器人</div>
<div class="integration-channel-desc">接收私聊、群聊、进群和消息事件,支持多个飞书 App。</div>
</div>
<div class="integration-channel-card muted">
<div class="integration-channel-head">
<div class="integration-channel-icon">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M7 10a5 5 0 0 1 9.6-2"/><path d="M17 14a5 5 0 0 1-9.6 2"/><path d="M3 14a6 6 0 0 0 6 6h2"/><path d="M21 10a6 6 0 0 0-6-6h-2"/></svg>
</div>
<span class="integration-status pending">待接入</span>
</div>
<div class="integration-channel-title">微信</div>
<div class="integration-channel-desc">预留企业微信或个人微信网关入口。</div>
</div>
<div class="integration-channel-card muted">
<div class="integration-channel-head">
<div class="integration-channel-icon">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12a7 7 0 1 1 3 5.74L4 19l1.26-4A6.98 6.98 0 0 1 5 12z"/><path d="M9 10h.01"/><path d="M12 10h.01"/><path d="M15 10h.01"/></svg>
</div>
<span class="integration-status pending">待接入</span>
</div>
<div class="integration-channel-title">WhatsApp</div>
<div class="integration-channel-desc">预留 WhatsApp Business Webhook。</div>
</div>
<div class="integration-channel-card muted">
<div class="integration-channel-head">
<div class="integration-channel-icon">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21.5 4.5 3 11.5l7 2 2 7 9.5-16z"/><path d="m10 13.5 5-5"/></svg>
</div>
<span class="integration-status pending">待接入</span>
</div>
<div class="integration-channel-title">Telegram</div>
<div class="integration-channel-desc">预留 Bot Token、Webhook 和群组授权。</div>
</div>
<div class="integration-channel-card muted">
<div class="integration-channel-head">
<div class="integration-channel-icon">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="4" y="5" width="16" height="13" rx="4"/><path d="M8 18 6 21"/><path d="m16 18 2 3"/><path d="M9 11h.01"/><path d="M15 11h.01"/><path d="M10 14h4"/></svg>
</div>
<span class="integration-status pending">待接入</span>
</div>
<div class="integration-channel-title">Discord</div>
<div class="integration-channel-desc">预留 Discord Bot、频道事件和 Slash Commands。</div>
</div>
</div>
<div class="integration-panel" id="feishuSettingsGroup">
<div class="integration-panel-head">
<div>
<div class="integration-panel-title">飞书集成</div>
<div class="integration-panel-desc">当前已接入的飞书机器人和事件回调地址</div>
</div>
<button class="glass-btn-sm" onclick="refreshFeishuApps()">
<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><path d="M3 12a9 9 0 0 1 15.5-6.3L21 8"/><path d="M21 3v5h-5"/><path d="M21 12a9 9 0 0 1-15.5 6.3L3 16"/><path d="M3 21v-5h5"/></svg>
刷新
</button>
</div>
<div class="integration-panel-body">
<div class="feishu-toolbar">
<div class="settings-help">只显示 App ID、回调地址和服务状态Secret 与 Token 只保存在服务器环境文件。</div>
</div>
<div class="feishu-apps" id="feishuApps">
<div class="settings-help">打开集成页后自动读取飞书桥接服务。</div>
</div>
<form class="feishu-form" id="feishuAddForm" onsubmit="saveFeishuApp(event)">
<div class="settings-field">
<label for="feishuAppId">App ID</label>
<input type="text" id="feishuAppId" placeholder="cli_xxxxxxxxxxxxxxxx" autocomplete="off">
</div>
<div class="settings-field">
<label for="feishuAppSecret">App Secret</label>
<input type="password" id="feishuAppSecret" placeholder="只写入服务器,不保存在浏览器" autocomplete="off">
</div>
<div class="settings-field">
<label for="feishuVerifyToken">Verification Token</label>
<input type="password" id="feishuVerifyToken" placeholder="飞书加密策略里的 Verification Token" autocomplete="off">
</div>
<div class="feishu-form-actions">
<button class="glass-btn-sm primary" type="submit">
<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.3" stroke-linecap="round" stroke-linejoin="round"><path d="M12 5v14"/><path d="M5 12h14"/></svg>
添加 / 更新机器人
</button>
<div class="settings-help">保存前会校验 App ID / Secret成功后复制回调地址到飞书事件配置。</div>
</div>
</form>
</div>
</div>
</div>
</section>
<!-- TAB: 设置 -->
<section class="tab-panel" id="tab-settings">
<div class="panel-head">
@@ -1115,52 +1228,6 @@ git push # Gitea kangwan/hermes-glass-ui-personal
</div>
</div>
<!-- 飞书集成 -->
<div class="settings-group wide" id="feishuSettingsGroup">
<div class="settings-group-head">
<div class="settings-group-icon">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 15a4 4 0 0 1-4 4H8l-5 3V7a4 4 0 0 1 4-4h10a4 4 0 0 1 4 4z"/><path d="M8 9h8"/><path d="M8 13h5"/></svg>
</div>
<div>
<div class="settings-group-title">飞书集成</div>
<div class="settings-group-desc">当前已接入的飞书机器人和事件回调地址</div>
</div>
</div>
<div class="settings-group-body">
<div class="feishu-toolbar">
<div class="settings-help">只显示 App ID、回调地址和服务状态Secret 与 Token 只保存在服务器环境文件。</div>
<button class="glass-btn-sm" onclick="refreshFeishuApps()">
<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><path d="M3 12a9 9 0 0 1 15.5-6.3L21 8"/><path d="M21 3v5h-5"/><path d="M21 12a9 9 0 0 1-15.5 6.3L3 16"/><path d="M3 21v-5h5"/></svg>
刷新
</button>
</div>
<div class="feishu-apps" id="feishuApps">
<div class="settings-help">打开设置页后自动读取飞书桥接服务。</div>
</div>
<form class="feishu-form" id="feishuAddForm" onsubmit="saveFeishuApp(event)">
<div class="settings-field">
<label for="feishuAppId">App ID</label>
<input type="text" id="feishuAppId" placeholder="cli_xxxxxxxxxxxxxxxx" autocomplete="off">
</div>
<div class="settings-field">
<label for="feishuAppSecret">App Secret</label>
<input type="password" id="feishuAppSecret" placeholder="只写入服务器,不保存在浏览器" autocomplete="off">
</div>
<div class="settings-field">
<label for="feishuVerifyToken">Verification Token</label>
<input type="password" id="feishuVerifyToken" placeholder="飞书加密策略里的 Verification Token" autocomplete="off">
</div>
<div class="feishu-form-actions">
<button class="glass-btn-sm primary" type="submit">
<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.3" stroke-linecap="round" stroke-linejoin="round"><path d="M12 5v14"/><path d="M5 12h14"/></svg>
添加 / 更新机器人
</button>
<div class="settings-help">保存前会校验 App ID / Secret成功后复制回调地址到飞书事件配置。</div>
</div>
</form>
</div>
</div>
<!-- 关于 -->
<div class="settings-group wide">
<div class="settings-group-head">

View File

@@ -2136,6 +2136,135 @@ a { color: var(--orange-3); text-decoration: none; }
overflow-wrap: anywhere;
}
/* ========== 机器人集成 ========== */
.integrations-scroll {
flex: 1 1 auto;
min-height: 0;
overflow-y: auto;
padding: 4px 8px 8px 0;
display: grid;
grid-template-columns: minmax(260px, 320px) minmax(0, 1fr);
gap: 16px;
align-content: start;
}
.integration-grid {
display: grid;
grid-template-columns: 1fr;
gap: 12px;
align-content: start;
}
.integration-channel-card,
.integration-panel {
background: var(--card-bg);
border: 1px solid var(--line);
border-radius: 18px;
min-width: 0;
}
.integration-channel-card {
padding: 16px;
display: flex;
flex-direction: column;
gap: 10px;
transition: border-color 0.2s, background 0.2s;
}
.integration-channel-card.active {
border-color: rgba(255,105,0,0.4);
background: rgba(255,105,0,0.08);
box-shadow: inset 0 0 0 1px rgba(255,105,0,0.12);
}
.integration-channel-card.muted {
opacity: 0.72;
}
.integration-channel-head {
display: flex;
align-items: flex-start;
justify-content: space-between;
gap: 10px;
}
.integration-channel-icon {
width: 38px;
height: 38px;
border-radius: 12px;
background: linear-gradient(135deg, rgba(255,105,0,0.18), rgba(255,136,48,0.06));
border: 1px solid var(--line-strong);
color: var(--orange-3);
display: flex;
align-items: center;
justify-content: center;
flex: 0 0 38px;
}
.integration-channel-icon svg { width: 20px; height: 20px; }
.integration-status {
flex: 0 0 auto;
border-radius: 999px;
padding: 4px 8px;
font-size: 11px;
font-weight: 800;
}
.integration-status.ready {
border: 1px solid rgba(80,220,140,0.32);
background: rgba(80,220,140,0.1);
color: #68d391;
}
.integration-status.pending {
border: 1px solid var(--line);
background: rgba(255,255,255,0.035);
color: var(--text-dim2);
}
.integration-channel-title {
color: var(--text);
font-size: 15px;
font-weight: 800;
letter-spacing: -0.2px;
}
.integration-channel-desc {
color: var(--text-dim2);
font-size: 12px;
line-height: 1.55;
overflow-wrap: anywhere;
}
.integration-panel {
display: flex;
flex-direction: column;
min-height: 0;
}
.integration-panel-head {
display: flex;
align-items: flex-start;
justify-content: space-between;
gap: 16px;
padding: 18px 22px 16px;
border-bottom: 1px solid var(--line);
min-width: 0;
}
.integration-panel-title {
color: var(--text);
font-size: 16px;
font-weight: 800;
letter-spacing: -0.25px;
}
.integration-panel-desc {
color: var(--text-dim2);
font-size: 12px;
line-height: 1.45;
margin-top: 3px;
}
.integration-panel-body {
padding: 18px 22px 22px;
display: flex;
flex-direction: column;
gap: 16px;
min-width: 0;
}
@media (max-width: 980px) {
.integrations-scroll {
grid-template-columns: 1fr;
}
.integration-grid {
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
}
}
/* ========== 设置 ========== */
.settings-scroll {
flex: 1 1 auto;

View File

@@ -1,6 +1,6 @@
// 爱马仕 Hermes · 轻量 Service Worker
// 静态壳走 network-first拿不到再回退缓存API 直通
const CACHE = "hermes-ui-v13";
const CACHE = "hermes-ui-v14";
const ASSETS = [
"./",
"./index.html",