auto-save 2026-05-11 17:10 (~3)

This commit is contained in:
2026-05-11 17:10:40 +08:00
parent 60c44cfaae
commit 90322e1c4f
3 changed files with 50 additions and 19 deletions

View File

@@ -11,6 +11,7 @@ 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 LS_MODEL_PROFILES = "hermes-ui-model-profiles-v1";
const UI_CONFIG_ENDPOINT = "/feishu/ui-config";
const DEFAULT_MODEL_ID = "google/gemini-3.1-pro-preview";
const LEGACY_DEFAULT_MODEL_ID = "gemini-3-pro-preview";
@@ -113,6 +114,10 @@ document.addEventListener("DOMContentLoaded", () => {
safeBoot("渲染侧栏", renderSidebar);
safeBoot("渲染对话", renderChat);
safeBoot("渲染智能体", renderAgents);
safeBoot("初始化模型 Profiles", () => {
state.modelProfiles = normalizeModelProfiles(state.modelProfiles);
renderModelProfiles();
});
safeBoot("恢复页面", restoreActiveTab);
refreshUiConfig({ migrateLocalAgents: true }).catch((error) => {
console.warn("[ui-config] fallback to local config", error);
@@ -168,6 +173,12 @@ function loadSettings() {
if (sm) sm.checked = state.stream;
}
} catch (e) {}
try {
const rawProfiles = localStorage.getItem(LS_MODEL_PROFILES);
if (rawProfiles) state.modelProfiles = normalizeModelProfiles(JSON.parse(rawProfiles));
} catch (e) {
state.modelProfiles = [];
}
syncModelPick(state.model);
}
function saveSettings(options = {}) {
@@ -226,6 +237,10 @@ function syncModelPick(modelValue, providerValue = "") {
updateModelDisplay(model, providerValue);
}
function saveModelProfilesToLS() {
localStorage.setItem(LS_MODEL_PROFILES, JSON.stringify(normalizeModelProfiles(state.modelProfiles)));
}
function makeId(prefix) {
return prefix + "_" + Date.now().toString(36) + Math.random().toString(36).slice(2, 6);
}
@@ -327,6 +342,7 @@ function upsertRuntimeModelProfile(model) {
next,
...state.modelProfiles.filter(profile => profile.id !== next.id).map(profile => ({ ...profile, isDefault: false })),
]);
saveModelProfilesToLS();
syncModelOptionsFromProfiles();
renderModelProfiles();
}
@@ -594,6 +610,10 @@ function switchTab(name, options = {}) {
if (name === "integrations") refreshFeishuApps();
if (name === "settings") {
renderWeeklyReports();
renderModelProfiles();
refreshUiConfig().catch((error) => {
setSharedConfigStatus("共享配置读取失败: " + (error.message || error), true);
});
refreshHermesConfig();
}
if (name === "runs") setTimeout(() => document.getElementById("runPrompt")?.focus(), 50);
@@ -976,6 +996,7 @@ async function saveSharedConfig(options = {}) {
if (!res.ok || data.code !== 0) throw new Error(data.msg || ("HTTP " + res.status));
const saved = data.config || config;
state.modelProfiles = normalizeModelProfiles(saved.modelProfiles);
saveModelProfilesToLS();
state.sharedConfigLoaded = true;
state.sharedConfigAvailable = true;
syncModelOptionsFromProfiles();
@@ -1007,6 +1028,7 @@ async function refreshUiConfig(options = {}) {
const config = await fetchUiConfig();
const profiles = normalizeModelProfiles(config.modelProfiles);
state.modelProfiles = profiles;
saveModelProfilesToLS();
state.sharedConfigLoaded = true;
state.sharedConfigAvailable = true;
syncModelOptionsFromProfiles();
@@ -1052,6 +1074,7 @@ function modelProfileCard(profile) {
function renderModelProfiles() {
state.modelProfiles = normalizeModelProfiles(state.modelProfiles);
saveModelProfilesToLS();
const list = document.getElementById("modelProfilesList");
if (list) {
list.innerHTML = state.modelProfiles.map(modelProfileCard).join("");
@@ -1142,6 +1165,7 @@ async function saveModelProfile() {
}
state.modelProfiles.push(next);
state.modelProfiles = normalizeModelProfiles(state.modelProfiles);
saveModelProfilesToLS();
syncModelOptionsFromProfiles();
renderModelProfiles();
clearModelProfileForm();
@@ -1161,6 +1185,7 @@ async function makeModelProfileDefault(id) {
...item,
isDefault: item.id === id,
})));
saveModelProfilesToLS();
syncModelOptionsFromProfiles();
renderModelProfiles();
try {
@@ -1193,6 +1218,7 @@ async function deleteModelProfile(id) {
if (agent.modelProfileId === id) agent.modelProfileId = "";
}
state.modelProfiles = normalizeModelProfiles(state.modelProfiles);
saveModelProfilesToLS();
syncModelOptionsFromProfiles();
renderModelProfiles();
renderAgents();
@@ -1271,14 +1297,15 @@ async function saveMcpConfig() {
mcp_servers_yaml: mcpServersYaml,
restart: true,
});
const savedModel = saved.model || snapshotModelOrFields();
if (savedModel.default) syncModelPick(savedModel.default, savedModel.provider || model.provider || "");
const fallbackModel = snapshotModelOrFields();
const savedModel = saved.model || fallbackModel;
if (savedModel.default) syncModelPick(savedModel.default, savedModel.provider || fallbackModel.provider || "");
document.getElementById("mcpServersYaml").value = saved.mcp_servers_yaml || "";
_hermesConfigSnapshot = {
model: {
default: savedModel.default || model.default,
provider: savedModel.provider || model.provider,
base_url: savedModel.base_url || model.base_url,
default: savedModel.default || fallbackModel.default,
provider: savedModel.provider || fallbackModel.provider,
base_url: savedModel.base_url || fallbackModel.base_url,
},
mcp_servers_yaml: saved.mcp_servers_yaml || "",
};
@@ -4368,7 +4395,10 @@ function importData(event) {
saveWeeklyReports();
}
if (data.agents) state.agents = data.agents;
if (Array.isArray(data.modelProfiles)) state.modelProfiles = normalizeModelProfiles(data.modelProfiles);
if (Array.isArray(data.modelProfiles)) {
state.modelProfiles = normalizeModelProfiles(data.modelProfiles);
saveModelProfilesToLS();
}
if (data.customSkills) { state.customSkills = data.customSkills; saveCustomSkillsToLS(); }
if (data.flows) { state.flows = data.flows; saveFlowsToLS(); }
if (data.settings) {