* 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>
* refactor: extract inline middleware from index.ts into separate modules
- Extract update middleware to routes/update.ts
- Extract health middleware and version logic to routes/health.ts
- Extract shutdown logic to services/shutdown.ts
- Extract gateway init to services/gateway-bootstrap.ts
- Remove unused variables, fix duplicate app creation
- Bump version to 0.4.0
index.ts: 260 lines → 80 lines
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: require auth for file upload and add 50MB size limit
Fixes#86
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
- Extract update middleware to routes/update.ts
- Extract health middleware and version logic to routes/health.ts
- Extract shutdown logic to services/shutdown.ts
- Extract gateway init to services/gateway-bootstrap.ts
- Remove unused variables, fix duplicate app creation
- Bump version to 0.4.0
index.ts: 260 lines → 80 lines
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
- Normalize request path to lowercase before auth check to prevent
bypassing authentication with uppercase paths like /API/hermes/sessions
- Auto-restart server after in-page update via detached hermes-web-ui restart
Closes#77
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Fix multipart upload parsing to use Buffer operations instead of latin1
string conversion, preserving multi-byte characters in filenames (#72)
- Support RFC 5987 filename* encoding for cross-platform compatibility
- Fix in-page update by running npm install directly instead of CLI command
that kills the server process before response is sent (#71)
- Add no-cache header to version check to avoid stale latest version
- Change version check interval from 4 hours to 1 hour
Closes#72, Closes#71
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Profile-aware proxy: inject API key from profile-specific .env, route requests via X-Hermes-Profile header
- Remove auth.json dependency: built-in providers use .env, custom providers use config.yaml
- Add allProviders field to available-models response with all hardcoded provider catalogs
- Add Models tab in Settings for editing provider API keys (built-in → .env, custom → config.yaml)
- Add PUT /api/config/providers/:poolKey for updating provider credentials
- ProviderFormModal uses backend allProviders for preset dropdown
- Gateway log format support: parse both agent and gateway log formats
- Add webui server.log to log viewer with log rotation at 3MB
- Fix provider delete loading state and OAuth provider cleanup
- Setup script: require Node.js 23+, auto-upgrade if version too low
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
When multiple providers share the same model name, the selector now
uses both model ID and provider as the unique identifier instead of
model name alone. Backend returns default_provider alongside default
model, and model switching sends provider to the config.
Fixes#52
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Fix chat store cache keys to include profile name, prevent data leaking between profiles
- Defer cache hydration to after profile load to avoid race condition
- Remove collapsible sidebar feature (not needed)
- Remove confirmation dialog on profile switch (direct reload)
- Auto-start gateway when creating new profile
- Clear profile-specific localStorage cache on profile delete (safe prefix matching)
- Clean up unused imports in SettingsView
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add GatewayManager for multi-profile gateway lifecycle management
- Auto-detect running gateways on startup via PID + health check
- Port conflict detection: check managed gateways, allocated ports, and
system-level port availability (TCP bind test)
- Two-phase startup: sequential port resolution, parallel process launch
- Use `gateway start/restart` on normal systems, `gateway run --replace`
on WSL/Docker
- Wait for health check before returning start/stop responses
- Add Gateways page with card-based layout showing profile status
- Reorganize sidebar navigation into collapsible groups
- Hide API server settings (now auto-managed by GatewayManager)
- Profile switch reloads page; Ctrl+C no longer stops gateways
- Remove redundant ensureApiServerConfig from index.ts and profiles.ts
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace static top-level import with runtime version check and dynamic
import() so Node < 22.5 gracefully falls back to CLI path instead of
crashing at module load time.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
SQLite path was returning null title for sessions without an explicit
title, while the CLI path derives it from the first user message.
Now uses the preview (first user message content) as title fallback,
matching the original CLI behavior.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add OpenAI Codex Device Code Flow login (backend polling + frontend modal)
- Codex provider integrated into preset dropdown (hides URL/API key fields)
- Sync provider model catalogs with Hermes system
- Fix channel config not displaying on first visit (wait for data load)
- Fix sidebar model list not refreshing after adding provider
- Add autocomplete="off" to API key input to prevent browser autofill
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Allow manual model name input when adding custom providers (NSelect tag mode)
- Sync provider model catalogs with Hermes _PROVIDER_MODELS
- Add new providers: kimi-coding-cn, moonshot, arcee
- Fix provider key naming to match Hermes (kilo→kilocode, vercel→ai-gateway, etc.)
- Ensure custom_providers from config.yaml always appear in available-models
- Append configured default model to model list if not in catalog
- Fix provider deletion with case-insensitive key matching
- Add selectOrInput i18n key to all 8 locales
Closes#24
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Backend: replace shallow merge with recursive deepMerge in PUT /api/hermes/config
to prevent nested config fields from being lost when updating partial values
- Frontend: switch all NInput fields to default-value + @change (save on blur)
instead of :value + @update:value (save on every keystroke) in both
PlatformSettings.vue and SettingsView.vue api_server tab
- Remove unused debounce logic and dead changeKey function
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Fix#25: job update sends schedule as plain string but upstream expects
{ kind, expr, display } object, causing "'str' object has no attribute 'get'"
- Move hermes-cli.ts, hermes.ts, hermes-profile.ts into services/hermes/
for multi-agent namespacing consistency
- Fix ts-node Set spread compatibility in filesystem.ts
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add MiniMax-M2.7/M2.5/M2.1/M2 -highspeed variants for both
international and China providers (#17)
- Deduplicate models in /available-models response to fix
repeated entries when using Copilot or other providers (#18)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- add docker-compose setup with hermes-agent + hermes-webui
- make runtime config env-driven (compose vars + HERMES_BIN)
- improve gateway startup/restart resilience in docker
- make base image configurable via BASE_IMAGE/HERMES_AGENT_IMAGE
Closes https://github.com/EKKOLearnAI/hermes-web-ui/issues/14
Node-pty's darwin helper can lose its execute bit in local installs, which leaves the module loadable but causes terminal session creation to fail with posix_spawnp errors. Normalize helper permissions before loading node-pty and remove the rebuild-only hint so startup repairs the real failure mode automatically.
Constraint: Must preserve Node 24 and the existing node-pty integration path
Rejected: Pipe fallback transport | loses true PTY behavior such as proper terminal semantics
Rejected: Tell users to run npm rebuild node-pty | rebuild alone did not restore the helper execute bit here
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: If a future node-pty release changes helper locations, update the helperCandidates list before touching terminal startup again
Tested: npm run build
Tested: WebSocket terminal session create + echo command on localhost:8648 under Node 24/macOS
Not-tested: Non-macOS helper layouts
- Set up Vitest with jsdom for client tests, node for server tests
- Add tests for auth service, proxy handler, API client, and profiles store
- Strip Authorization header in proxy to prevent web-ui token leaking to gateway
- Distinguish local BFF vs proxied gateway 401s to avoid false logouts
- Remove unused hero.png asset
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Change profile import from server path input to browser file upload (multipart)
- Fix startup script to wait for health check before opening browser
- Add overflow scroll with hidden scrollbar to sidebar nav
- Graceful degradation when node-pty fails to load (WSL compatibility)
- Remove rename button from profile cards
- Restrict profile name input to English letters, numbers, hyphens
- Use raw.githubusercontent.com URLs in README setup script
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add hermes-profile.ts for dynamic profile path resolution (all backend
routes now read from active profile directory instead of hardcoded ~/.hermes/)
- Add profile switcher dropdown in sidebar, reload page on switch
- Sync PROVIDER_PRESETS with Hermes CLI (fix keys: kimi-coding→kimi-for-coding,
kilocode→kilo, ai-gateway→vercel, opencode-zen→opencode; remove moonshot)
- Sync PROVIDER_ENV_MAP with Hermes models.dev + overlays (correct env var names)
- Add gateway restart after adding model provider
- Don't write GLM_BASE_URL/KIMI_BASE_URL for zai/kimi (let Hermes auto-detect)
- Write API keys to .env and credential_pool for all providers
- Built-in providers skip custom_providers in config.yaml
- Add debounce + per-field loading state for channel settings inputs
- Run hermes setup --reset for profiles without config.yaml
- Create empty .env for new profiles (not copied from default)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Simplify ensureApiServerConfig to unconditionally write default
platforms.api_server values, preventing missing config issues.
Bump version to 0.2.7.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add frontend API layer, Pinia store, and 5 components (ProfileCard, ProfilesPanel, ProfileCreateModal, ProfileRenameModal, ProfileImportModal)
- Add ProfilesView page with card grid layout and expandable details
- Modify export endpoint to stream file as browser download instead of returning server path
- Add sidebar nav entry, router route, and i18n translations (en/zh)
- Support create, rename, delete, switch (with gateway restart), export, and import profiles
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>