feat(hermes): replace Prompts entry with Memory panel

Hermes has no slash-prompt concept (templates live as Skills), so the
Prompts tab for the Hermes app was always empty. Swap the toolbar Book
button for a Brain button that opens a new Memory panel editing
~/.hermes/memories/{MEMORY,USER}.md — Hermes' first-class memory store
which its Web UI exposes only as on/off toggles, never as an editor.

The panel shows each file in its own tab with a character-budget bar
read from config.yaml's nested memory.* section (memory_char_limit /
user_char_limit, default 2200 / 1375). Edits are written atomically;
Hermes picks them up on the next session start per MemoryStore.

Also extract useDarkMode to src/hooks/useDarkMode.ts — the codebase
already repeats the same MutationObserver pattern in 12+ places; this
PR introduces the shared hook and uses it once, leaving the migration
of the other copies to a follow-up.
This commit is contained in:
Jason
2026-04-19 21:49:27 +08:00
parent 088b47b08a
commit acc6d795e4
12 changed files with 552 additions and 6 deletions
+29
View File
@@ -0,0 +1,29 @@
import { useEffect, useState } from "react";
/**
* Subscribe to the presence of `class="dark"` on `<html>`. The theme-provider
* toggles this class whenever the effective theme changes (including when the
* OS changes theme while the app is in "system" mode), so observing the class
* is the simplest way to drive components that need a boolean `darkMode` prop
* (e.g. CodeMirror-based editors that don't consume the theme context).
*/
export function useDarkMode(): boolean {
const [isDark, setIsDark] = useState(() =>
typeof document !== "undefined"
? document.documentElement.classList.contains("dark")
: false,
);
useEffect(() => {
const observer = new MutationObserver(() => {
setIsDark(document.documentElement.classList.contains("dark"));
});
observer.observe(document.documentElement, {
attributes: true,
attributeFilter: ["class"],
});
return () => observer.disconnect();
}, []);
return isDark;
}