"use strict"; const systemPromptInput = document.getElementById("systemPromptInput"); const systemPromptPath = document.getElementById("systemPromptPath"); const saveSystemPromptBtn = document.getElementById("saveSystemPromptBtn"); const refreshSettingsBtn = document.getElementById("refreshSettingsBtn"); const settingsStatus = document.getElementById("settingsStatus"); const skillsList = document.getElementById("skillsList"); const skillsCount = document.getElementById("skillsCount"); const extensionsList = document.getElementById("extensionsList"); const extensionsMeta = document.getElementById("extensionsMeta"); const settingsNavBtns = document.querySelectorAll(".settings-nav-btn"); const settingsPanes = document.querySelectorAll(".settings-pane"); const SETTINGS_PANE_KEY = "sproutclaw-settings-pane"; function escHtml(s) { const div = document.createElement("div"); div.textContent = s; return div.innerHTML; } function setSettingsStatus(text, kind = "") { if (!settingsStatus) return; settingsStatus.textContent = text || ""; settingsStatus.className = `settings-status${kind ? ` ${kind}` : ""}`; } function showSettingsPane(paneId) { const id = ["prompt", "skills", "extensions"].includes(paneId) ? paneId : "prompt"; settingsNavBtns.forEach((btn) => { const active = btn.dataset.pane === id; btn.classList.toggle("is-active", active); btn.setAttribute("aria-selected", active ? "true" : "false"); }); settingsPanes.forEach((pane) => { const active = pane.id === `pane-${id}`; pane.classList.toggle("is-active", active); pane.toggleAttribute("hidden", !active); }); try { sessionStorage.setItem(SETTINGS_PANE_KEY, id); } catch { /* ignore */ } } function initSettingsNav() { settingsNavBtns.forEach((btn) => { btn.addEventListener("click", () => showSettingsPane(btn.dataset.pane)); }); let initial = "prompt"; try { const saved = sessionStorage.getItem(SETTINGS_PANE_KEY); if (["prompt", "skills", "extensions"].includes(saved)) initial = saved; } catch { /* ignore */ } showSettingsPane(initial); } async function loadSettings() { if (skillsList) skillsList.innerHTML = '
加载中...
'; if (extensionsList) extensionsList.innerHTML = '
加载中...
'; setSettingsStatus(""); try { const res = await fetch("/api/settings"); const data = await res.json().catch(() => ({})); if (!res.ok || data.error) throw new Error(data.error || res.statusText); if (systemPromptInput) systemPromptInput.value = data.systemPrompt || ""; if (systemPromptPath) systemPromptPath.textContent = data.systemPromptPath || ""; renderSkills(data.skills || []); renderExtensions(data.extensions || [], data.extensionsPath || ""); } catch (err) { if (skillsList) skillsList.innerHTML = `
加载失败: ${escHtml(err.message)}
`; if (extensionsList) extensionsList.innerHTML = `
加载失败: ${escHtml(err.message)}
`; setSettingsStatus(`加载设置失败: ${err.message}`, "error"); } } function renderSkills(skills) { if (!skillsList) return; if (skillsCount) skillsCount.textContent = `${skills.length} 个已加载`; if (!skills.length) { skillsList.innerHTML = '
暂无已加载 skills
'; return; } skillsList.innerHTML = skills.map((skill) => { const meta = [skill.scope, skill.source].filter(Boolean).join(" · "); const path = skill.path || ""; return `
${escHtml(skill.name || skill.command || "未命名")}
${meta ? `
${escHtml(meta)}
` : ""}
${skill.description ? `
${escHtml(skill.description)}
` : ""} ${path ? `
${escHtml(path)}
` : ""}
`; }).join(""); } function renderExtensions(extensions, extensionsPath) { if (!extensionsList) return; if (extensionsMeta) { extensionsMeta.textContent = extensionsPath ? `${extensions.length} 个已加载 · ${extensionsPath}` : `${extensions.length} 个已加载`; } if (!extensions.length) { extensionsList.innerHTML = '
暂无已加载插件扩展
'; return; } extensionsList.innerHTML = extensions.map((extension) => { const meta = extension.kind || [extension.scope, extension.source].filter(Boolean).join(" · "); const counts = [ [`命令`, extension.commands?.length || 0], [`工具`, extension.tools?.length || 0], [`事件`, extension.handlers?.length || 0], [`Flags`, extension.flags?.length || 0], [`快捷键`, extension.shortcuts?.length || 0], ].filter(([, count]) => count > 0); const hasDetails = ["commands", "tools", "handlers", "flags", "shortcuts"].some((key) => extension[key]?.length); return `
${escHtml(extension.name || extension.path || "未命名")}
${meta ? `
${escHtml(meta)}
` : ""}
${counts.length ? `
${counts.map(([label, count]) => `${escHtml(label)} ${count}`).join("")}
` : ""} ${hasDetails ? `
查看注册项 ${renderNameList("命令", extension.commands)} ${renderNameList("工具", extension.tools)} ${renderNameList("事件", extension.handlers)} ${renderNameList("Flags", extension.flags)} ${renderNameList("快捷键", extension.shortcuts)}
` : ""} ${extension.location ? `
${escHtml(extension.location)}
` : ""}
`; }).join(""); } function renderNameList(label, items) { if (!Array.isArray(items) || !items.length) return ""; return `
${escHtml(label)}
${items.map((item) => `${escHtml(item)}`).join("")}
`; } async function saveSystemPrompt() { if (!systemPromptInput || !saveSystemPromptBtn) return; saveSystemPromptBtn.disabled = true; setSettingsStatus("保存中..."); try { const res = await fetch("/api/settings/system-prompt", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ systemPrompt: systemPromptInput.value }), }); const data = await res.json().catch(() => ({})); if (!res.ok || data.error) throw new Error(data.error || res.statusText); if (systemPromptPath && data.systemPromptPath) systemPromptPath.textContent = data.systemPromptPath; setSettingsStatus("已保存,Agent 已重新加载", "ok"); } catch (err) { setSettingsStatus(`保存失败: ${err.message}`, "error"); } finally { saveSystemPromptBtn.disabled = false; } } initSettingsNav(); saveSystemPromptBtn?.addEventListener("click", saveSystemPrompt); refreshSettingsBtn?.addEventListener("click", loadSettings); document.getElementById("refreshExtensionsBtn")?.addEventListener("click", loadSettings); loadSettings();