diff --git a/.memory/worklog.json b/.memory/worklog.json index 47a5fe2..d9cd030 100644 --- a/.memory/worklog.json +++ b/.memory/worklog.json @@ -1,12 +1,5 @@ { "entries": [ - { - "files_changed": 1, - "hash": "a72c5bb", - "message": "auto-save 2026-05-10 07:33 (~1)", - "ts": "2026-05-10T07:33:56+08:00", - "type": "commit" - }, { "files_changed": 1, "message": "Codex 会话活跃 · 最近命令:codex · 分支 master · 1 项未提交变更 · 最近提交:auto-save 2026-05-10 07:33 (~1)", @@ -3259,6 +3252,13 @@ "type": "session-heartbeat", "message": "Codex 会话活跃 · 最近命令:codex · 分支 master · 6 项未提交变更 · 最近提交:auto-save 2026-05-11 15:41 (~1)", "files_changed": 6 + }, + { + "ts": "2026-05-11T15:47:02+08:00", + "type": "commit", + "message": "auto-save 2026-05-11 15:46 (~6)", + "hash": "3bb30ae", + "files_changed": 6 } ] } diff --git a/RULES.md b/RULES.md index dc0b001..f3a16a4 100644 --- a/RULES.md +++ b/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-v27` +- 当前前端静态壳缓存版本:`hermes-ui-v28` - 文档 / 解析:https://styles.kang-kang.com - 管理后台:待定 - 代码仓:https://git.kang-kang.com/kangwan/hermes-glass-ui-personal diff --git a/src/app.js b/src/app.js index 7d7204d..71da269 100644 --- a/src/app.js +++ b/src/app.js @@ -11,12 +11,14 @@ const LS_CUSTOM_SKILLS = "hermes-ui-custom-skills-v1"; const LS_FLOWS = "hermes-ui-flows-v1"; const LS_TAB = "hermes-ui-active-tab-v1"; const LS_WEEKLY_REPORTS = "hermes-ui-weekly-reports-v1"; +const DEFAULT_MODEL_ID = "google/gemini-3.1-pro-preview"; +const LEGACY_DEFAULT_MODEL_ID = "gemini-3-pro-preview"; const state = { apiBase: "/api/v1", apiKey: "hermes-mini-local-key-2026", stream: true, - model: "gemini-3-pro-preview", + model: DEFAULT_MODEL_ID, // 所有会话 conversations: {}, // {id: {id, title, messages, agentId, tags, createdAt, updatedAt}} @@ -680,7 +682,7 @@ function snapshotModelOrFields() { const fields = readModelConfigFields(); if (fields.default) return fields; return { - default: state.model || "gemini-3-pro-preview", + default: state.model || DEFAULT_MODEL_ID, provider: fields.provider || "openrouter", base_url: fields.base_url || "", }; @@ -1995,7 +1997,7 @@ const DEFAULT_AGENTS = [ emoji: "H", name: "通用助手", desc: "什么都能聊,默认的爱马仕,适合日常问答和闲聊。", - model: "gemini-3-pro-preview", + model: DEFAULT_MODEL_ID, systemPrompt: "你是爱马仕,一个友好、专业、简洁的 AI 助手。用中文回答,除非用户明确要求其他语言。", skills: ["brief", "goal"], }, @@ -2003,7 +2005,7 @@ const DEFAULT_AGENTS = [ emoji: "💻", name: "代码专家", desc: "精通各类编程语言和框架,擅长排 bug、写代码、解读架构。", - model: "gemini-3-pro-preview", + model: DEFAULT_MODEL_ID, systemPrompt: "你是一位资深的软件工程师,擅长多种编程语言和框架。回答要准确、实用,提供可运行的代码示例,并解释关键点。遇到 bug 时先定位根因再提出修复方案。", skills: ["runnable", "rigor", "steps"], }, @@ -2011,7 +2013,7 @@ const DEFAULT_AGENTS = [ emoji: "✍️", name: "写作助手", desc: "中英文写作、润色、翻译、摘要,文风可调。", - model: "gemini-3-pro-preview", + model: DEFAULT_MODEL_ID, systemPrompt: "你是一位专业的中英文写作助手,擅长润色、翻译、摘要、改写。注重逻辑清晰、语言流畅、风格贴合语境。先理解用户的目标受众再动笔。", skills: ["bilingual", "plain", "structured"], }, @@ -2019,7 +2021,7 @@ const DEFAULT_AGENTS = [ emoji: "🔍", name: "研究员", desc: "深度调研、信息整合、结构化输出报告。", - model: "gemini-3-pro-preview", + model: DEFAULT_MODEL_ID, systemPrompt: "你是一名严谨的研究员。接到主题后先拆解问题、列出要调研的子问题、给出结构化的研究报告。引用时标注来源,对不确定的内容明确说明。", skills: ["steps", "rigor", "cite", "structured"], }, @@ -2039,6 +2041,16 @@ function loadAgents() { } saveAgents(); } + let migrated = false; + for (const agent of Object.values(state.agents || {})) { + const builtin = DEFAULT_AGENTS.find(item => item.name === agent.name && item.systemPrompt === agent.systemPrompt); + if (builtin && agent.model === LEGACY_DEFAULT_MODEL_ID) { + agent.model = DEFAULT_MODEL_ID; + migrated = true; + } + ensureModelChoice(agent.model || DEFAULT_MODEL_ID); + } + if (migrated) saveAgents(); } function saveAgents() { localStorage.setItem(LS_AGENTS, JSON.stringify(state.agents)); @@ -2284,7 +2296,8 @@ function openAgentModal(id) { document.getElementById("agentEmojiPreview").textContent = a.emoji || "🤖"; document.getElementById("agentName").value = a.name || ""; document.getElementById("agentDesc").value = a.desc || ""; - document.getElementById("agentModel").value = a.model || "gemini-3-pro-preview"; + ensureModelChoice(a.model || DEFAULT_MODEL_ID); + document.getElementById("agentModel").value = a.model || DEFAULT_MODEL_ID; document.getElementById("agentPrompt").value = a.systemPrompt || ""; renderSkillsPicker(a.skills || []); } else { @@ -2292,7 +2305,7 @@ function openAgentModal(id) { document.getElementById("agentEmojiPreview").textContent = "🤖"; document.getElementById("agentName").value = ""; document.getElementById("agentDesc").value = ""; - document.getElementById("agentModel").value = "gemini-3-pro-preview"; + document.getElementById("agentModel").value = state.model || DEFAULT_MODEL_ID; document.getElementById("agentPrompt").value = ""; renderSkillsPicker([]); } @@ -2307,10 +2320,12 @@ function saveAgent() { const emoji = document.getElementById("agentEmoji").value.trim() || "🤖"; const name = document.getElementById("agentName").value.trim(); const desc = document.getElementById("agentDesc").value.trim(); - const model = document.getElementById("agentModel").value; + const model = document.getElementById("agentModel").value.trim(); const systemPrompt = document.getElementById("agentPrompt").value.trim(); if (!name) { toast("请填写名称"); return; } + if (!model) { toast("请填写模型 ID"); return; } if (!systemPrompt) { toast("请填写角色设定"); return; } + ensureModelChoice(model); const skills = readSkillsPicker(); diff --git a/src/index.html b/src/index.html index 9df1be1..db8e76f 100644 --- a/src/index.html +++ b/src/index.html @@ -11,7 +11,7 @@ 爱马仕 · AI - + @@ -1408,6 +1408,6 @@ git push # Gitea kangwan/hermes-glass-ui-personal - + diff --git a/src/sw.js b/src/sw.js index 978520b..0a62490 100644 --- a/src/sw.js +++ b/src/sw.js @@ -1,11 +1,11 @@ // 爱马仕 Hermes · 轻量 Service Worker // 静态壳走 network-first(拿不到再回退缓存),API 直通 -const CACHE = "hermes-ui-v27"; +const CACHE = "hermes-ui-v28"; const ASSETS = [ "./", "./index.html", - "./styles.css?v=20260511-settings-v27", - "./app.js?v=20260511-settings-v27", + "./styles.css?v=20260511-settings-v28", + "./app.js?v=20260511-settings-v28", "./manifest.webmanifest", "./icon.svg", ];