(() => { const PASSTHROUGH = [ "retry", "undo", "title", "branch", "stop", "background", "btw", "queue", "status", "profile", "resume", "snapshot", "rollback", "provider", "yolo", "reasoning", "fast", "voice", "reload", "reload-mcp", "cron", "browser", "plugins", "insights", "platforms", "debug", "update", "image", "inbox" ]; let COMMANDS = []; const AGENT_INFO = { "sunflower": { emoji: "\u{1F33B}", name: "Sunflower", file: "sunflower/soul.md", domain: "Finance, Wealth & Subscriptions" }, "lotus": { emoji: "\u{1F9D7}", name: "Lotus", file: "lotus/soul.md", domain: "Health, Fitness & Recovery" }, "forget-me-not": { emoji: "\u{1F33C}", name: "Forget-me-not", file: "forget-me-not/soul.md", domain: "Calendar, Time & Social" }, "iris": { emoji: "\u2695\uFE0F", name: "Iris", file: "iris/soul.md", domain: "Career, Learning & Focus" }, "ivy": { emoji: "\u{1F33F}", name: "Ivy", file: "ivy/soul.md", domain: "Smart Home & Environment" }, "dandelion": { emoji: "\u{1F6E1}", name: "Dandelion", file: "dandelion/soul.md", domain: "Communication Triage & Gatekeeping" }, "root": { emoji: "\u{1F333}", name: "Root", file: "root/soul.md", domain: "DevOps, Logs & System Health" }, "back": { emoji: "\u{1F339}", name: "Rose", file: "rose/soul.md", domain: "Orchestrator (return from agent)" } }; function _fnFor(name) { if (name === "help" || name === "commands") return cmdHelp; if (name === "clear") return cmdClear; if (name === "compact" || name === "compress") return cmdCompact; if (name === "model") return cmdModel; if (name === "workspace") return cmdWorkspace; if (name === "new") return cmdNew; if (name === "usage") return cmdUsage; if (name === "theme") return cmdTheme; if (name === "skills") return cmdSkills; if (name === "personality") return cmdPersonality; if (PASSTHROUGH.includes(name)) return cmdPassthrough; return cmdPassthrough; } async function loadCommands() { try { const data = await api("/api/commands"); if (data.error) throw new Error(data.error); const cats = data.categories || {}; const merged = []; for (const [, cmds] of Object.entries(cats)) { for (const c of cmds) { merged.push({ name: c.name, desc: c.desc, arg: c.arg || "(none)", aliases: c.aliases || [], fn: _fnFor(c.name) }); } } const agentNames = ["sunflower", "lotus", "forget-me-not", "iris", "ivy", "dandelion", "root", "back", "inbox"]; const filtered = merged.filter((c) => !agentNames.includes(c.name)); filtered.push( { name: "sunflower", desc: "\u{1F33B} Finance, Wealth & Subscriptions", fn: cmdAgent, arg: "message", aliases: [] }, { name: "lotus", desc: "\u{1F9D7} Health, Fitness & Recovery", fn: cmdAgent, arg: "message", aliases: [] }, { name: "forget-me-not", desc: "\u{1F33C} Calendar, Time & Social", fn: cmdAgent, arg: "message", aliases: [] }, { name: "iris", desc: "\u2695\uFE0F Career, Learning & Focus", fn: cmdAgent, arg: "message", aliases: [] }, { name: "ivy", desc: "\u{1F33F} Smart Home & Environment", fn: cmdAgent, arg: "message", aliases: [] }, { name: "dandelion", desc: "\u{1F6E1} Communication Triage & Gatekeeping", fn: cmdAgent, arg: "message", aliases: [] }, { name: "root", desc: "\u{1F333} DevOps, Logs & System Health", fn: cmdAgent, arg: "message", aliases: [] }, { name: "back", desc: "\u{1F339} Return to Rose (orchestrator)", fn: cmdAgent, arg: "message", aliases: [] } ); COMMANDS = filtered; } catch (e) { console.warn("[commands] Failed to load from API, using fallback:", e instanceof Error ? e.message : String(e)); COMMANDS = []; } } function parseCommand(text) { if (!text.startsWith("/")) return null; const parts = text.slice(1).split(/\s+/); const name = parts[0].toLowerCase(); const args = parts.slice(1).join(" ").trim(); return { name, args }; } function executeCommand(text) { const parsed = parseCommand(text); if (!parsed) return false; const cmd = COMMANDS.find((c) => c.name === parsed.name); if (!cmd) return false; cmd.fn(parsed.args); return true; } function getMatchingCommands(prefix) { const q = prefix.toLowerCase(); return COMMANDS.filter((c) => { if (c.name.startsWith(q)) return true; if (c.aliases && c.aliases.some((a) => a.startsWith(q))) return true; return false; }); } function cmdPassthrough(_args) { const msgEl = $("msg"); if (!msgEl) return; const parsed = parseCommand(msgEl.value); if (!parsed) return; send(); } function cmdHelp() { const categories = { "Session": [], "Configuration": [], "Tools & Skills": [], "Info": [], "Agents": [] }; COMMANDS.forEach((c) => { let cat = "Info"; if (["new", "clear", "compact", "compress", "retry", "undo", "title", "branch", "stop", "background", "btw", "queue", "status", "profile", "resume", "snapshot", "rollback"].includes(c.name)) cat = "Session"; else if (["model", "provider", "personality", "workspace", "theme", "yolo", "reasoning", "fast", "voice", "reload", "reload-mcp"].includes(c.name)) cat = "Configuration"; else if (["skills", "cron", "browser", "plugins"].includes(c.name)) cat = "Tools & Skills"; else if (["sunflower", "lotus", "forget-me-not", "iris", "ivy", "dandelion", "root", "back", "inbox"].includes(c.name)) cat = "Agents"; if (!categories[cat]) categories[cat] = []; categories[cat].push(c); }); const lines = []; for (const [cat, cmds] of Object.entries(categories)) { if (!cmds.length) continue; lines.push(` **${cat}**`); cmds.forEach((c) => { const usage = c.arg && c.arg !== "(none)" ? ` <${c.arg}>` : ""; lines.push(` /${c.name}${usage} \u2014 ${c.desc}`); }); } const msg = { role: "assistant", content: "Available commands:\n" + lines.join("\n") }; S.messages.push(msg); renderMessages(); showToast(t("type_slash")); } function cmdClear() { if (!S.session) return; S.messages = []; S.toolCalls = []; clearLiveToolCards(); renderMessages(); const emptyState = $("emptyState"); if (emptyState) emptyState.style.display = ""; showToast(t("conversation_cleared")); } async function cmdModel(args) { if (!args) { showToast("Usage: /model "); return; } const sel = $("modelSelect"); if (!sel) return; const q = args.toLowerCase(); let match = null; for (const opt of sel.options) { if (opt.value.toLowerCase().includes(q) || (opt.textContent || "").toLowerCase().includes(q)) { match = opt.value; break; } } if (!match) { showToast('No model matching "' + args + '"'); return; } sel.value = match; if (sel.onchange) await sel.onchange(null); showToast(t("switched_to") + match); } async function cmdWorkspace(args) { if (!args) { showToast("Usage: /workspace "); return; } try { const data = await api("/api/workspaces"); const q = args.toLowerCase(); const ws = (data.workspaces || []).find( (w) => (w.name || "").toLowerCase().includes(q) || w.path.toLowerCase().includes(q) ); if (!ws) { showToast('No workspace matching "' + args + '"'); return; } if (typeof switchToWorkspace === "function") await switchToWorkspace(ws.path, ws.name || ws.path); else showToast(t("switched_workspace") + (ws.name || ws.path)); } catch (e) { showToast(t("workspace_switch_failed") + (e instanceof Error ? e.message : String(e))); } } async function cmdNew() { await newSession(); await renderSessionList(); const msgEl = $("msg"); if (msgEl) msgEl.focus(); showToast(t("new_session")); } function cmdCompact() { const msgEl = $("msg"); if (msgEl) msgEl.value = "Please compress and summarize the conversation context to free up space."; send(); showToast(t("compressing")); } async function cmdUsage() { const next = !window._showTokenUsage; window._showTokenUsage = next; try { await api("/api/settings", { method: "POST", body: JSON.stringify({ show_token_usage: next }) }); } catch { } const cb = $("settingsShowTokenUsage"); if (cb) cb.checked = next; renderMessages(); showToast(next ? t("token_usage_on") : t("token_usage_off")); } async function cmdTheme(args) { const themes = ["system", "dark", "light", "slate", "solarized", "monokai", "nord", "oled"]; if (!args || !themes.includes(args.toLowerCase())) { showToast("Themes: " + themes.join(" | ")); return; } const themeName = args.toLowerCase(); localStorage.setItem("hermes-theme", themeName); _applyTheme(themeName); try { await api("/api/settings", { method: "POST", body: JSON.stringify({ theme: themeName }) }); } catch { } const sel = $("settingsTheme"); if (sel) sel.value = themeName; showToast(t("theme_set") + themeName); } async function cmdSkills(args) { try { const data = await api("/api/skills"); let skills = data.skills || []; if (args) { const q = args.toLowerCase(); skills = skills.filter( (s) => (s.name || "").toLowerCase().includes(q) || (s.description || "").toLowerCase().includes(q) || (s.category || "").toLowerCase().includes(q) ); } if (!skills.length) { const msg = { role: "assistant", content: args ? `No skills matching "${args}".` : "No skills found." }; S.messages.push(msg); renderMessages(); return; } const byCategory = {}; skills.forEach((s) => { const cat = s.category || "General"; if (!byCategory[cat]) byCategory[cat] = []; byCategory[cat].push(s); }); const lines = []; for (const [cat, items] of Object.entries(byCategory).sort()) { lines.push(`**${cat}**`); items.forEach((s) => { const desc = s.description ? ` \u2014 ${s.description.slice(0, 80)}${s.description.length > 80 ? "..." : ""}` : ""; lines.push(` \`${s.name}\`${desc}`); }); lines.push(""); } const header = args ? `Skills matching "${args}" (${skills.length}): ` : `Available skills (${skills.length}): `; S.messages.push({ role: "assistant", content: header + lines.join("\n") }); renderMessages(); } catch (e) { showToast("Failed to load skills: " + (e instanceof Error ? e.message : String(e))); } } async function cmdPersonality(args) { if (!S.session) { showToast(t("no_active_session")); return; } if (!args) { try { const data = await api("/api/personalities"); if (!data.personalities || !data.personalities.length) { showToast(t("no_personalities")); return; } const list = data.personalities.map((p) => ` **${p.name}**${p.description ? " \u2014 " + p.description : ""}`).join("\n"); S.messages.push({ role: "assistant", content: t("available_personalities") + "\n\n" + list + "\n\nSwitch with: /personality " }); renderMessages(); } catch { showToast(t("personalities_load_failed")); } return; } const name = args.trim(); if (["none", "default", "clear"].includes(name.toLowerCase())) { try { await api("/api/personality/set", { method: "POST", body: JSON.stringify({ session_id: S.session.session_id, name: "" }) }); showToast(t("personality_cleared")); } catch (e) { showToast(t("failed_colon") + (e instanceof Error ? e.message : String(e))); } return; } try { await api("/api/personality/set", { method: "POST", body: JSON.stringify({ session_id: S.session.session_id, name }) }); showToast(t("personality_set") + name); } catch (e) { showToast(t("failed_colon") + (e instanceof Error ? e.message : String(e))); } } function cmdAgent(_args) { const msgEl = $("msg"); if (!msgEl) return; const parsed = parseCommand(msgEl.value); if (!parsed) return; const agentKey = parsed.name; const info = AGENT_INFO[agentKey]; if (!info) { showToast("Unknown agent: " + agentKey); return; } const userMsg = _args || ""; const contextMsg = `[Agent Switch: ${info.emoji} ${info.name}] Load ~/.hermes/agents/${info.file} and handle this request as ${info.name} (${info.domain}).${userMsg ? "\n\nUser message: " + userMsg : ""}`; msgEl.value = contextMsg; send(); } let _cmdSelectedIdx = -1; function showCmdDropdown(matches) { const dd = $("cmdDropdown"); if (!dd) return; dd.innerHTML = ""; _cmdSelectedIdx = -1; for (let i = 0; i < matches.length; i++) { const c = matches[i]; const el = document.createElement("div"); el.className = "cmd-item"; el.dataset.idx = String(i); const usage = c.arg && c.arg !== "(none)" ? ` ${esc(c.arg)}` : ""; el.innerHTML = `
/${esc(c.name)}${usage}
${esc(c.desc)}
`; el.addEventListener("mousedown", (e) => { e.preventDefault(); const msgEl2 = $("msg"); if (msgEl2) { msgEl2.value = "/" + c.name + (c.arg && c.arg !== "(none)" ? " " : ""); msgEl2.focus(); } hideCmdDropdown(); }); dd.appendChild(el); } dd.classList.add("open"); } function hideCmdDropdown() { const dd = $("cmdDropdown"); if (dd) dd.classList.remove("open"); _cmdSelectedIdx = -1; } function navigateCmdDropdown(dir) { const dd = $("cmdDropdown"); if (!dd) return; const items = dd.querySelectorAll(".cmd-item"); if (!items.length) return; items.forEach((el) => el.classList.remove("selected")); _cmdSelectedIdx += dir; if (_cmdSelectedIdx < 0) _cmdSelectedIdx = items.length - 1; if (_cmdSelectedIdx >= items.length) _cmdSelectedIdx = 0; items[_cmdSelectedIdx].classList.add("selected"); } function selectCmdDropdownItem() { const dd = $("cmdDropdown"); if (!dd) return; const items = dd.querySelectorAll(".cmd-item"); if (_cmdSelectedIdx >= 0 && _cmdSelectedIdx < items.length) { const item = items[_cmdSelectedIdx]; const ev = new MouseEvent("mousedown", { bubbles: true, cancelable: true }); Object.defineProperty(ev, "preventDefault", { value: () => { } }); item.dispatchEvent(ev); } else if (items.length === 1) { const ev = new MouseEvent("mousedown", { bubbles: true, cancelable: true }); Object.defineProperty(ev, "preventDefault", { value: () => { } }); items[0].dispatchEvent(ev); } hideCmdDropdown(); } function _applyTheme(themeName) { document.documentElement.dataset.theme = themeName; } window.loadCommands = loadCommands; })(); //# sourceMappingURL=commands.js.map