In Hermes mode JBOT is a pure voice UI — memory is owned by the Agent:
- Backend: sys prompt excludes local memories when backend_mode=hermes
- Backend: config_view now returns backendMode so the frontend can adapt
- Frontend: App.jsx loads backendMode on mount via apiConfig()
- Frontend: memories not passed to apiChat() when isHermesMode
- Frontend: memory extraction (apiExtractMemory) skipped when isHermesMode
- Frontend: MemoryPanel hidden in Hermes mode; replaced by subtle
'🧠 Hermes Agent 模式 · 记忆由 Agent 管理' badge
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- New DB fields: hermes_url, hermes_api_key, backend_mode (openrouter/hermes)
- Migration 0002 adds the three fields to JbotApiConfig
- _do_hermes_chat(): streams /v1/chat/completions from Hermes Agent,
collects hermes.tool.progress SSE events, returns (final_text, tool_calls)
- chat_view branches on backend_mode; Hermes response includes toolCalls list
- Settings page: new '🧠 AI 后端模式' section — radio to toggle mode,
conditional Hermes URL + API key fields, LLM model field moved under
OpenRouter mode
- ChatPanel: ToolCallsList component renders collapsible '🔧 Hermes 使用了
N 个工具' widget before the bot reply — tool calls are NOT spoken via TTS
- CSS: .tool-calls, .tool-calls-* styles for the tool progress widget
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
right-footer served no purpose after hint text was removed. vbtn-wrap
is now a direct flex child of right-col: white bar at the bottom on
desktop, position:fixed on mobile — no stray white boxes anywhere.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Merged hint text + VoiceButton into a single .right-footer div
(flex column, white bg, border-top) so they form one solid footer bar
visually anchored to the bottom of the right column — no more floating
- .right-col gets min-height:0 so flex children can shrink properly
- .vbtn-wrap is now a transparent width:100% wrapper inside right-footer
(desktop); mobile keeps its own fixed-position overlay
- .right-footer { display: none } on mobile (fixed vbtn-wrap takes over)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Remove 'overflow:hidden' from html/body in index.css — it was blocking
scroll on all pages (Settings, History). The chat page is self-contained
via .app {height:100dvh; overflow:hidden} so body lock is unnecessary.
.app reverted back to height:100dvh (self-sufficient, not body-relative)
- Remove duplicate 历史记录 link from the right-column hint bar; it
already appears in the ChatPanel header, so three links was redundant
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Move MemoryPanel from bottom of left column to top of right column
(above chat messages, with a clean border-bottom separator)
- Move hint text ('按住 Space 或按钮说话 · 音色') from left column
to a compact bar on the right column between chat and voice button;
hidden on mobile to save space
- Remove 切换间隔 slider from left column; add it to Settings page
under 🤖 机器人身份 section with proper slider+value layout
- Add switchIntervalMs:10000 to DEFAULT_SETTINGS in settingsStore so
the value persists across sessions; App.jsx reads it on mount
- Left column is now much leaner: face + interaction buttons + micro
expression grid + auto-rotate toggle only
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Left column: scrollbar-width:none + ::-webkit-scrollbar:none to
hide the scrollbar chrome while keeping overflow-y:auto for tall
viewports; tightened padding (14→10px top, 20→14px bottom) and
panel/section gaps (14→10px, 12→8px, h3 margin 7→5px) to help
content fit without scrolling on typical laptop heights
- Header: added 🏠 home anchor linking to '/' (Links homepage) next
to the JBOT logo; styled as a small icon button
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
.chat-panel was using height:100% which consumed all right-col space,
pushing VoiceButton out of view (clipped by overflow:hidden).
Fix: switch .chat-panel to flex:1 + min-height:0 so it participates
in flex layout and leaves room for the VoiceButton below it.
Also moved VoiceButton component outside App() to avoid React
component-identity churn on every render.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Added VoiceButton component (inline in App.jsx) with full
mousedown/mouseup/mouseleave + touchstart/touchend/touchcancel support
- Shows context-aware label: 🎙 按住说话 / ⏳ 准备中 / 🔴 松开发送 / ⚙ 思考中 / 🔊 播放中
- Pulsing red animation while recording, amber pulse while acquiring mic
- Disabled (gray) while AI is thinking or speaking
- Desktop: pill button docked at bottom of chat panel (max-width 380px)
- Mobile: fixed to bottom of viewport with safe-area-inset support,
height 60px for easy thumb tap; right-col padded so messages aren't hidden
- Updated hint text and listening status to be input-agnostic
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>