* feat: add file browser and file download with multi-backend support
Adds a built-in File Browser page and a File Download system to Hermes
Web UI, enabling users to browse, edit, preview, upload, and download
files from the workspace directly from the web dashboard.
File Browser (/hermes/files):
- New view FilesView.vue plus components under components/hermes/files/
(FileTree, FileList, FileBreadcrumb, FileToolbar, FileContextMenu,
FileEditor, FilePreview, FileRenameModal, FileUploadModal)
- New Pinia store stores/hermes/files.ts for directory tree, selection,
and editing state
- New API module api/hermes/files.ts
- New server routes routes/hermes/files.ts with CRUD, rename, upload,
and directory listing
- New service services/hermes/file-provider.ts with a pluggable
provider architecture (local filesystem + multi-terminal backends)
File Download:
- New server route routes/hermes/download.ts and client API
api/hermes/download.ts
- Integration in chat messages (MessageItem.vue, MarkdownRenderer.vue)
to surface downloadable file references
Packaging:
- package.json: add a prepare script so the package can be installed
directly from a git URL with dist/ built automatically
i18n: add files/download translations to en.ts and zh.ts.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix: use clipboard fallback for non-secure HTTP contexts
navigator.clipboard is undefined on HTTP intranet deployments (only
available in secure contexts). The previous synchronous calls threw
silently and the success toast still fired, making 'copy' actions
appear broken.
- Add packages/client/src/utils/clipboard.ts with execCommand fallback
via a hidden textarea
- Use the helper in FileContextMenu (copy file path), CodexLoginModal
(copy user code), NousLoginModal (copy user code), ChatPanel (copy
session id)
- Each call now awaits the result and shows success/failure based on
the actual outcome
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix(search): handle numeric query FTS errors regardless of table existence
Remove the `no such table: messages_fts` condition so numeric queries
fall back to LIKE search on any FTS failure (malformed MATCH, missing
table, etc.).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix(search): handle special char queries, polish live badge UI
- Add hasUnsafeChars() to catch FTS5-breaking queries (¥, @, #, etc.)
and fall back to LIKE search, preventing 500 errors
- Polish session live badge: smaller size, remove border/shadow,
add pulsing dot indicator for a cleaner look
- Remove spinner drop-shadow glow effect
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* feat(chat): add direct live badge to session rows
* fix(live): use session DB for conversations monitor
* docs: add chat vs live monitor direction plan
* fix(search): avoid numeric session search 500 without FTS table
* fix: specify TS_NODE_PROJECT for dev:server script
ts-node/register resolves tsconfig from the entry file upward,
finding the root solution-style tsconfig.json (no compilerOptions).
This causes target to default to ES3, breaking MapIterator spread
syntax (TS2802). Set TS_NODE_PROJECT env var to point to the server
tsconfig which targets ES2024.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat: add token usage tracking, context display, and dynamic context length
- Intercept SSE proxy to capture run.completed events and persist token
usage (input_tokens, output_tokens) per session to SQLite/JSON store
- Display context usage bar in ChatInput showing used/total/remaining tokens
- Resolve actual context length from Hermes models_dev_cache.json based
on the active profile's default model (fallback 200K), with 5min in-memory cache
- Move sessions-db.ts to db/hermes/ for unified database layer
- Add usage store with SQLite + JSON fallback (auto-migration via ensureTable)
- Fix proxy SSE path regex to match rewritten upstream path
- Fix route ordering: /sessions/usage before /sessions/:id to avoid 404
- Fetch per-session usage on session enter instead of batch
- Add unit tests for usage-store, db index, and proxy SSE interception
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* chore: bump version to 0.4.2-beta.1 and improve chat UX
- Bump version to 0.4.2-beta.1
- Fix live monitor session selected style to match chat session style
- Add thin scrollbar with stable gutter to live monitor sidebar
- Fix live monitor detail scroll on mobile
- Show new chat button as icon-only on mobile using JS detection
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* chore: fix version to 0.4.2
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* feat: add single-page live session monitor and chat pinning
* fix: restore full test green after main merge
* fix: use Array.from instead of Set spread for ts-node compatibility
[...new Set()] requires downlevelIteration which isn't enabled in
ts-node dev mode, causing sonic-boom crash on startup.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: ekko <fqsy1416@gmail.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* feat(chat): polish syntax highlighting and tool payload rendering (#94)
* [verified] feat(chat): polish syntax highlighting and tool payload rendering
* [verified] fix(chat): tighten large tool payload rendering
* docs: update data volume path in Docker docs
Align documentation with docker-compose.yml change:
hermes-web-ui-data -> hermes-web-ui, /app/dist/data -> /root/.hermes-web-ui
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* refactor: bundle server build and restructure service modules
- Add build-server.mjs script for standalone server compilation
- Add logger service with structured output
- Restructure auth, gateway-manager, hermes-cli, hermes services
- Update docker-compose volume mount path
- Update tsconfig and entry point for bundled server
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* refactor: separate controllers from routes and centralize route registration
- Extract business logic from route handlers into controllers/
- Add centralized route registry in routes/index.ts with public/auth/protected layers
- Replace global auth whitelist with sequential middleware registration
- Extract shared helpers to services/config-helpers.ts
- Allow custom provider name to be user-editable in ProviderFormModal
- Deduplicate custom providers by poolKey instead of base_url in getAvailable
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: auth bypass via path case, SPA serving, and provider improvements
- Fix auth bypass: path case-insensitive check for /api, /v1, /upload
- Fix SPA returning 401: skip auth for non-API paths (static files)
- Fix profile switch: use local loading state instead of shared store ref
- Auto-append /v1 to base_url when fetching models (frontend + backend)
- Guard .env writing to built-in providers only
- Add builtin field to provider presets, enable base_url input in form
- Print auth token to console on startup (pino only writes to file)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Zhicheng Han <43314240+hanzckernel@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Use `last_active` from SQLite (max message timestamp) for accurate
sorting, with fallback chain: last_active → ended_at → started_at.
CLI mode lacks last_active so falls back to ended_at.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The PR changed `.active` class to bind on `isSessionLive()`, which
removed the visual selection state when clicking a non-live session.
Split into two classes: `.active` for selection, `.live` for streaming.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Smart auto-scroll: only follow SSE stream when user is near bottom (200px threshold), scroll once on send/switch session
- Brighten dark mode text colors (primary #e0→#f0, secondary #a0→#c0, muted #66→#88)
- Fix tool-call panel height to match thinking video (120px→213px)
- Fix tool-call item background invisible in dark mode
- Fix gateway start button using hardcoded dark color
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add Japanese, Korean, French, Spanish, German, Portuguese translations
- Improve session active state visibility in both themes
- Static language labels in LanguageSwitch component
- Dark theme: lighten chat input background for better contrast
- Fix system theme listener not toggling back to light
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Fix sidebar footer layout: separate update button from version row
- Replace custom update-hint with NButton for proper dark mode support
- Darken chat input background in dark theme for better contrast
- Fix system theme listener always applying dark mode
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace video assets with processed versions, update sidebar logo
dark background to #393939, restore streaming indicator with
theme-aware video switching.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Implement runtime theme switching using CSS custom properties delegated through SCSS variables, with light/dark/system modes, FOUC prevention, sidebar toggle, and settings selector. Add theme-aware video assets for sidebar and chat thinking indicator.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>