Commit Graph

140 Commits

Author SHA1 Message Date
ekko fdafb4e842 fix(docker): use official Node.js binary and remove unnecessary deps (#103)
* 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>

* fix(docker): correct volume mount path and update Node.js to 23

- Fix webui volume mount from /root/.hermes-web-ui to /home/agent/.hermes-web-ui
  (container runs as agent user, homedir() returns /home/agent)
- Update Node.js from 22 to 23 in Dockerfile

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* ci: add ARM64 support for Docker image build

Add QEMU and multi-platform build (linux/amd64,linux/arm64) so
the image works on Apple Silicon and ARM-based NAS devices.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(docker): use official Node.js binary and remove unnecessary deps

- Replace NodeSource with official Node.js binary (fixes ARM64 GPG error)
- Remove python3/python3-yaml (not needed, base image already has Python)
- Keep make/g++ for node-pty native compilation

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>
2026-04-21 14:44:51 +08:00
ekko 7e739b70a2 ci: add ARM64 support for Docker image build (#101)
* 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>

* fix(docker): correct volume mount path and update Node.js to 23

- Fix webui volume mount from /root/.hermes-web-ui to /home/agent/.hermes-web-ui
  (container runs as agent user, homedir() returns /home/agent)
- Update Node.js from 22 to 23 in Dockerfile

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* ci: add ARM64 support for Docker image build

Add QEMU and multi-platform build (linux/amd64,linux/arm64) so
the image works on Apple Silicon and ARM-based NAS devices.

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>
2026-04-21 14:22:22 +08:00
ekko 5a114d97f6 fix(docker): correct volume mount path and update Node.js to 23 (#99)
* 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>

* fix(docker): correct volume mount path and update Node.js to 23

- Fix webui volume mount from /root/.hermes-web-ui to /home/agent/.hermes-web-ui
  (container runs as agent user, homedir() returns /home/agent)
- Update Node.js from 22 to 23 in Dockerfile

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>
2026-04-21 13:19:25 +08:00
ekko 477af66232 fix: auth bypass, SPA serving, and provider improvements (#97)
* 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>
2026-04-21 12:35:48 +08:00
ekko 21296a416b fix: require auth for file upload and add 50MB size limit (#87)
* 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>
2026-04-21 07:43:05 +08:00
ekko c1b4e6d596 refactor: extract inline middleware from index.ts into separate modules (#85)
- 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>
2026-04-20 20:37:32 +08:00
ekko aa8dd65f95 Merge pull request #83 from EKKOLearnAI/dev
ci: add PR build check workflow and PR template
2026-04-20 20:11:33 +08:00
ekko 89e386593c ci: update Node.js version to 23 in build workflow
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-20 20:11:17 +08:00
ekko 521a9edb86 ci: add PR build check workflow and PR template
- Add build.yml workflow that runs npm run build on PRs to main/dev
- Add PR template with summary, type, changes, test plan sections
- Required by branch protection rules on main

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-20 20:05:50 +08:00
ekko 8ad0723b00 docs: update Docker deployment guide and compose config
- Update docker-compose.yml: use hermes-agent internal hostname for UPSTREAM,
  expose ports 8642-8670, add server data volume mapping
- Rewrite docs/docker.md with pre-built image usage, env var table,
  data persistence (token location), port mapping, and common operations
- Update README.md and README_zh.md Docker section with pre-built image
  instructions and token location

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-20 19:55:31 +08:00
ekko 4c35225591 Merge pull request #80 from EKKOLearnAI/dev
fix: workflow trigger and server data volume mapping
2026-04-20 19:17:51 +08:00
ekko 4b306c3caa fix: only trigger Docker build on main branch and add server data volume mapping
- Workflow trigger branches reduced to main only (dev can use manual dispatch)
- Add server data volume mapping to persist Koa auth token

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-20 19:17:06 +08:00
ekko ef39a69d11 fix: clean up workflow trigger branches
Remove personal branch names (dev-custom, my-custom), keep only main and dev.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-20 19:01:04 +08:00
ekko dca52061bd Merge pull request #76 from lingganwu/my-custom
Add GitHub Actions workflow for Docker image build
2026-04-20 18:52:27 +08:00
灵感屋 7477f18abe Update Dockerfile 2026-04-20 15:59:09 +08:00
ekko f4aee59e39 Merge branch 'dev' 2026-04-20 15:22:05 +08:00
ekko f3a980bb2e fix: patch auth bypass via case-sensitive path matching (#77)
- 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>
2026-04-20 15:21:47 +08:00
灵感屋 11621246d0 Add GitHub Actions workflow for Docker image build 2026-04-20 14:09:42 +08:00
ekko 5430d02787 Merge branch 'dev' 2026-04-20 12:16:07 +08:00
ekko eb6c2dc9f6 fix: resolve Chinese filename garbling on upload and page update failure (#72, #71)
- 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>
2026-04-20 12:15:47 +08:00
ekko 47ccb751f4 Merge branch 'dev' 2026-04-19 23:41:07 +08:00
ekko 5d16d56d9f docs: add fallback comment for star history chart rate limiting
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-19 23:41:01 +08:00
ekko cea7a17913 Merge branch 'dev' 2026-04-19 23:36:37 +08:00
ekko 717549bc85 docs: update README with multi-profile, gateway, provider management and star history
- Add active session indicator and latest-message sorting to AI Chat
- Expand Model Management with provider CRUD and Codex OAuth
- Add Multi-Profile & Gateway section
- Add Model Settings to Settings section
- Add Star History chart to both EN and ZH READMEs

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-19 23:36:28 +08:00
ekko f96e94c44c Merge branch 'dev' 2026-04-19 23:32:09 +08:00
ekko d3817556ac feat: sort sessions by latest message time instead of creation time
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>
2026-04-19 23:32:01 +08:00
ekko 969e56b45e fix: restore selected session highlight alongside live indicator
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>
2026-04-19 23:13:34 +08:00
ekko 72f238703d Merge branch 'codex/active-session-live-state' into dev 2026-04-19 22:52:41 +08:00
mysoul12138 7c4b025e6a refine active session live state 2026-04-19 21:51:25 +08:00
ekko 5b9c1aa77f Merge branch 'dev' 2026-04-19 20:59:39 +08:00
ekko 562261d13f feat: multi-gateway profile support, provider management overhaul, and model settings tab
- 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>
2026-04-19 20:59:25 +08:00
mysoul12138 2ea20fc128 merge active session indicator feature 2026-04-19 19:34:29 +08:00
mysoul12138 0da5e91329 feat: surface active chat sessions 2026-04-19 19:34:14 +08:00
ekko a3d38fa5d5 Merge pull request #58 from EKKOLearnAI/dev
fix: provider-aware model selection (#52)
2026-04-19 15:08:12 +08:00
ekko e7e4c386c3 chore: bump version to 0.3.6 and fix unused import
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-19 15:07:59 +08:00
ekko 8a4ab2d69d fix: provider-aware model selection to prevent cross-provider conflicts
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>
2026-04-19 15:05:05 +08:00
ekko b4f809d8b5 fix: improve chat scroll behavior and dark mode readability
- 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>
2026-04-19 10:46:33 +08:00
ekko 4f923da490 feat: replace ModelSelector dropdown with modal picker
NSelect dropdown is unusable with providers that have hundreds of models.
Replaced with a modal dialog featuring search filter, collapsible provider
groups, and click-to-select.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-18 22:08:34 +08:00
ekko aa34b02b09 chore: bump version to 0.3.5
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-18 14:34:50 +08:00
ekko 07d36297d6 Merge remote-tracking branch 'origin/main' into feat/multi-gateway 2026-04-18 14:33:04 +08:00
ekko 27051dcb32 feat: profile-aware cache isolation and UX improvements
- 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>
2026-04-18 14:32:54 +08:00
ekko da7910f934 Merge pull request #44 from 0xnuu/pr/chat-resilience-sidebar
feat(chat): improve resilience and collapsible sidebar
2026-04-18 14:32:36 +08:00
Shentar 0df3303f8f feat: add terminal theme selector with 15 presets
Add NSelect dropdown in terminal toolbar to switch themes dynamically.
Includes 9 dark themes (Default, Solarized Dark, Monokai, Dracula, Nord,
One Dark, GitHub Dark, Tokyo Night) and 6 light themes (Solarized Light,
GitHub Light, Catppuccin Latte, Alabaster, XTerm Light, One Light,
Gruvbox Light). Theme choice persists via localStorage.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-18 13:14:20 +08:00
ekko 17f0cdc1de Merge branch 'pr-44' into feat/multi-gateway
# Conflicts:
#	packages/client/src/components/layout/AppSidebar.vue
2026-04-18 13:12:42 +08:00
ekko b9e0aefec3 Merge branch 'pr-43' into feat/multi-gateway 2026-04-18 13:09:21 +08:00
ekko 4b6de351bd feat: add multi-gateway management with auto port detection
- 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>
2026-04-18 13:07:12 +08:00
Shentar 40d4b9ac4b feat: add terminal theme selector with 15 presets
Add NSelect dropdown in terminal toolbar to switch themes dynamically.
Includes 9 dark themes (Default, Solarized Dark, Monokai, Dracula, Nord,
One Dark, GitHub Dark, Tokyo Night) and 6 light themes (Solarized Light,
GitHub Light, Catppuccin Latte, Alabaster, XTerm Light, One Light,
Gruvbox Light). Theme choice persists via localStorage.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-18 11:26:09 +08:00
ekko 7264eabfe2 Merge dev into main
- fix: avoid full session export in session list (#38)
- fix: fallback title from preview when session has no explicit title
- fix: use dynamic import for node:sqlite with Node version guard

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-18 09:35:03 +08:00
ekko 35481e452d fix: use dynamic import for node:sqlite with Node version guard
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>
2026-04-18 09:34:59 +08:00
ekko fd7071b75d fix: fallback title from preview when session has no explicit title
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>
2026-04-18 08:53:45 +08:00