Commit Graph

86 Commits

Author SHA1 Message Date
ekko 529065f023 scope session search by selected profile (#889) 2026-05-21 09:48:31 +08:00
ekko 3612a76735 show chat run errors as agent messages (#887) 2026-05-21 09:05:17 +08:00
ekko 40109e9c42 [codex] fix profile scoped model selection (#881)
* fix profile scoped model selection

* test profile scoped provider refresh
2026-05-20 18:26:01 +08:00
Zhicheng Han 6578873d9e [verified] Fix group chat agent member sync (#877) 2026-05-20 17:13:15 +08:00
ekko c90eba226d [codex] add customizable profile avatars (#870)
* add customizable profile avatars

* keep profile avatar visible when sidebar collapses

* simplify collapsed profile avatar styling

* force managed gateway startup in docker

* limit gateway autostart to active profile

* restore all profile gateway autostart

* fix managed gateway runtime detection
2026-05-20 14:15:01 +08:00
Zhicheng Han 7f6b691238 [verified] Fix group chat final stream rendering (#859) 2026-05-20 10:31:30 +08:00
ekko 0547fd6b6a [codex] Harden context compression history handling (#848)
* Use token threshold for chat compression

* Add compression settings controls

* Use config for chat compression

* Cover protected messages in compression tests

* Remove message-count compression limit

* Harden compression window fallback

* Rebuild stale compression snapshots

* Harden stale compression snapshots

* Update changelog for compression hardening

* Prefer local history session details
2026-05-19 17:58:39 +08:00
ekko 9a9416c99c Fix bridge history, profile models, and Windows gateway handling (#845)
* feat: support profile-aware group chat bridge flows

* feat: route cron jobs through hermes cli

* Fix group chat routing and isolate bridge tests

* Add Grok image-to-video media skill

* Default Grok videos to media directory

* Fix bridge profile fallback and cron repeat clearing

* Refine bridge chat and gateway platform handling

* Filter bridge tool-call text deltas

* Preserve structured bridge chat history

* Prepare beta release build artifacts

* Fix Windows run profile resolution

* Fix Windows path compatibility checks

* Fix profile-scoped model page display

* Hide Windows subprocess windows for jobs and updates

* Hide Windows file backend subprocess windows

* Avoid Windows gateway restart lock conflicts

* Treat Windows gateway lock as running on startup

* Force release Windows gateway lock on restart

* Tighten Windows gateway lock cleanup

* Update chat e2e source expectation

* Bump package version to 0.5.30

---------

Co-authored-by: Codex <codex@openai.com>
2026-05-19 16:09:59 +08:00
ekko 6516d86dfc Limit run-time model list waiting (#812) 2026-05-17 12:51:23 +08:00
ekko 5e8f8bd4a1 Add session-level bridge model settings (#811) 2026-05-17 12:20:53 +08:00
ekko 0c2bafc619 [codex] Add local tool trace toggle (#806)
* test: harden tool approval browser contract

* test: cover tool trace display edge cases

* test: cover resumed tool trace edge cases

* feat: hide tool traces by default

* Add local tool trace toggle

---------

Co-authored-by: Zhicheng Han <zhicheng.han@mathematik.uni-goettingen.de>
2026-05-17 09:01:59 +08:00
ekko db0c23bf5e [codex] add QQBot and DingTalk channel settings (#787)
* add qqbot and dingtalk channel settings

* remove history session context menu
2026-05-16 13:54:38 +08:00
ekko 217b721648 clear stale compression status on run start (#783) 2026-05-16 11:15:29 +08:00
ekko 8196e49478 [codex] Add group chat room reset and clone (#756)
* Add group chat room reset and clone

* Clean npm cache before self update
2026-05-15 15:52:16 +08:00
ekko 3d49f778fb align compression token estimates (#749) 2026-05-15 13:50:27 +08:00
ekko 48dcaee6c2 feat: add bridge session commands (#743) 2026-05-15 12:04:03 +08:00
ekko d0f1e7d1f2 Fix bridge compression history handling (#726)
* feat(bridge): refactor compression to use DB history and add structured logging

- Extract buildDbHistory() to share message loading between buildCompressedHistory and forceCompressBridgeHistory
- forceCompressBridgeHistory now reads from local DB instead of using Python-provided messages, ensuring consistency with api_server path
- Pass sessionId to compressor for snapshot-aware compression
- Add force_compress flag to bridge chat requests
- Add bridgeLogger structured logging for compression lifecycle
- Simplify schemas, session-sync, and providers

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

* fix bridge compression history handling

---------

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-14 21:02:59 +08:00
memeflyfly bb83ac7d9e feat(settings): add debounce to NInputNumber in Memory/Agent/Session settings (#718) 2026-05-14 15:47:17 +08:00
ekko eae7195ba8 Update CLI chat session bridge (#697)
* feat: add CLI chat sessions with Python agent bridge

Introduce a new CLI chat mode that connects Web UI directly to Hermes
Agent's AIAgent via a Python bridge subprocess and Socket.IO, bypassing
the API Server /v1/responses path. Supports streaming, slash commands
(/new, /undo, /retry, /branch, /compress, /save, /title), interrupt,
and steer.

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

* feat: update CLI chat session bridge

* fix: extend agent bridge startup timeouts

* docs: update bridge chat session design

* feat: align bridge compression and provider registry

* chore: bump version to 0.5.20

---------

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-14 09:03:57 +08:00
Zhicheng Han c2068302c3 feat: enhance usage analytics dashboard (#666)
- visualize input, output, and cache token segments in usage charts
- add usage period selector for 7d, 30d, 90d, and 365d
- guard usage stats against stale overlapping period requests
- normalize blank model usage into unknown buckets
- add client and server coverage for usage analytics behavior
2026-05-13 07:41:49 +08:00
Zhicheng Han 57cdf87bef Kanban:补齐看板事件、链接与批量操作闭环 (#634)
* feat(kanban): add board-scoped event stream bridge

* test(kanban): align event refresh expectation

* feat(kanban): add links and partial bulk bridge

* test(kanban): align links bulk refresh expectation

* fix(kanban): treat mutation stderr as failed
2026-05-13 07:32:38 +08:00
ekko 73b919e07c fix: skip model API requests when no auth token is present (#643)
Prevents infinite retry loop on /api/hermes/available-models when
accessing the app without a token, which triggers server-side 429
rate limiting. Both loadModels() and fetchProviders() now bail out
early if hasApiKey() returns false.

Closes #606

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-12 10:19:14 +08:00
Zhicheng Han c36b320e18 fix: prompt reload for stale Web UI bundle (#641) 2026-05-12 09:03:07 +08:00
Zhicheng Han b8be47d8d6 feat(models): 增加模型显示名重命名 (#614)
* feat(models): add WUI model display aliases

Persist display-only model aliases in Web UI app config, surface them in the model selector/search, and keep canonical model IDs for Hermes calls.

* fix(models): improve WUI model alias editing

* fix(models): clarify unlisted model picker

* fix(models): scope aliases to providers
2026-05-11 22:18:13 +08:00
Zhicheng Han 6ff1c18ee2 Kanban:补齐任务操作链路,明确能力边界 (#615)
* [verified] fix(kanban): harden WUI parity bridge

- Align board slug normalization with canonical underscore/lowercase/64-char rules
- Validate malformed Kanban action bodies before CLI shell-out
- Narrow task log no-log handling and expose phase-1 capabilities
- Extend client/server regression coverage for parity actions

* fix(kanban): guard archived task detail actions

---------

Co-authored-by: ekko <152005280+EKKOLearnAI@users.noreply.github.com>
2026-05-11 21:26:24 +08:00
Zhicheng Han 3a1893d401 Models:支持在 Web UI 里管理可见模型 (#613)
* feat(models): add WUI model visibility filter

Store provider model visibility in Web UI app config and filter the WUI model picker/model page without rewriting Hermes CLI config or canonical model IDs.

* fix(models): sync sidebar after visibility changes
2026-05-11 21:24:45 +08:00
Zhicheng Han e0e4096605 fix(kanban): include archived tasks in board counts (#619) 2026-05-11 21:09:58 +08:00
Zhicheng Han 0d14afe9b4 fix: harden web ui self-update restart (#552) 2026-05-10 20:18:52 +08:00
Zhicheng Han 838791a740 修复 WUI Kanban 看板选择与隔离 (#594)
* fix: add explicit kanban board selection

* fix: tighten kanban board counts and management
2026-05-10 19:58:44 +08:00
ekko fc02348ebd fix: prevent message loss on abort by deferring DB writes to flush (#591)
Defer all non-user message DB writes until response completion or
abort, instead of writing tool calls immediately during streaming.
This ensures correct message ordering and prevents the abort handler
from overwriting displayed messages with incomplete DB data.

- Remove immediate addMessage() calls from response.output_item.done
- Remove immediate addMessage() from insertResponseTextOnce
- Add flushResponseRunToDb() to batch-write all run messages on
  both normal completion (markCompleted) and abort (handleAbort)
- Skip user messages in flush (already written in handleRun)
- Remove refreshActiveSession() from abort.completed frontend handler

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-10 04:10:01 +08:00
ekko 50122c5ff8 feat: v0.5.16 - migrate to Responses API (#586)
* refactor: migrate from /v1/runs to /v1/responses streaming API

Replace EventSource-based polling with direct SSE streaming via the
/v1/responses endpoint across all server-side callers (chat-run-socket,
context-compressor, gateway-client, agent-clients). Messages are now
written to DB in real-time during streaming, eliminating post-run sync.
Frontend chat store adds tool_call_id tracking for deduplication.

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

* chore: bump version to 0.5.16 and add changelog

- Persist real API usage to usage table on response.completed
- Remove unused codex_reasoning_items field from message schema
- Fix unused variable warnings in chat-run-socket
- Bump version to 0.5.16
- Add changelog entries for 0.5.16 (8 locales)

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

---------

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-10 02:49:58 +08:00
ekko 4f8f932d03 fix(mobile): improve mobile UI for kanban, group chat and page headers (#562)
- Fix kanban loading spinner flickering on auto-refresh (silent mode)
- Fix group chat room-list transparent background on mobile
- Fix group chat sidebar auto-opening on mobile entry
- Fix page-header title overlapped by hamburger button on mobile
- Move hamburger button position to top: 10px
- Add changelog note about upgrading hermes-agent for kanban support
- Add i18n translations for all 8 locales

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-09 12:18:26 +08:00
ekko 9045f2a987 Revert "修复审批请求在聊天中无提示且无法响应 (#467)" (#553)
This reverts commit 56c7b59eaf.
2026-05-09 08:36:13 +08:00
Zhicheng Han 56c7b59eaf 修复审批请求在聊天中无提示且无法响应 (#467)
* fix: support run approval prompts in chat

* fix(chat): render approval prompts

* fix(chat): dedupe approval pattern labels

* chore: sync approval flow with current main

- update Hermes Agent approval support guidance to PR #21899
- initialize Hermes table schemas in session-sync tests
2026-05-08 16:59:36 +02:00
ekko b0e03ae838 add hermes kanban board (#534) 2026-05-08 11:32:47 +08:00
ekko 424125843f feat: add message queue for sequential run processing (#501)
Allow sending multiple messages while a run is active. Messages are
queued on the server and processed sequentially after each run
completes. Each completed assistant message triggers speech playback
independently, and the UI shows queue status with a badge indicator.

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-07 10:34:58 +08:00
Zhicheng Han f338aeea18 fix: play completion sound in chat (#466) 2026-05-06 14:23:12 +08:00
ekko 1011c950be fix: improve chat message display and compression logic (#476)
Frontend:
- Filter out assistant messages with empty content in mapHermesMessages()
- Prevents displaying 194/585 empty messages in long sessions
- Reduces visual clutter and improves UX

Backend:
- Add message count limit (<= 200) to compression threshold checks
- Prevents compressing sessions with too many messages
- Improves compression performance and reliability

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-06 14:07:13 +08:00
ekko b52f28ffcb Clean chat frontend debug logs (#455) 2026-05-05 13:11:16 +08:00
ekko e3d28f4659 [codex] Handle chat run abort lifecycle (#454)
* feat: call upstream stop API when aborting a run

- Modified handleAbort to call POST /v1/runs/{run_id}/stop endpoint
- Use profile-specific upstream URL and API key from gatewayManager
- Add 5-second timeout with error handling and logging
- Keep local abortController.abort() for EventSource cleanup
- Change handleAbort to async method and update call site

This ensures the upstream Hermes gateway is properly notified
when a user aborts a run, allowing graceful termination.

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

* fix: close ChatRunSocket connections on shutdown to prevent hanging

- Add close() method to ChatRunSocket to abort all active runs
  and clear session state
- Pass chatRunServer to bindShutdown and close it before
  groupChatServer during shutdown
- This prevents EventSource connections and abort controllers
  from keeping the process alive during nodemon restart

Fixes the "still waiting for sub-process to finish" issue.

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

* Handle chat run abort lifecycle

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-05 13:03:14 +08:00
ekko d47abf1533 feat: add session authorization mode configuration (#446)
Add approvals.mode configuration to allow users to enable/disable
session operation authorization. Mode can be 'off' (no auth) or 'manual'
(require auth). Changes trigger automatic gateway restart for config
to take effect.

- Add ApprovalConfig type with mode: 'off' | 'manual'
- Add approvals section to settings store
- Add session authorization toggle in SessionSettings UI
- Add approvals to PLATFORM_SECTIONS for auto-restart
- Add i18n support for all 8 languages

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-04 21:29:39 +08:00
ekko 46bc2cf12e Release v0.5.9 (#435)
* fix: add missing i18n key and unify session data source (#408)

- Add `chat.sessionNotFound` translation key to all 8 locales
- Fix history page data source inconsistency:
  - Change `getHermesSession` to prioritize database over CLI
  - Now consistent with `listHermesSessions` behavior
  - Prevents "session in list but detail not found" issue
- Update CI workflow to trigger on base branch PRs
- Remove debug log from sessions-db

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix: filter special characters and emoji in speech playback (#409)

- Update extractReadableText to filter special characters like *#
- Only keep common punctuation marks for speech synthesis
- Remove emoji, symbols, and special unicode characters
- Improve text-to-speech readability

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat: add drawer panel with mobile sidebar support and customizable button (#412)

* feat: add drawer panel with mobile sidebar support

- Add DrawerPanel component with Terminal and Files tabs
- Extract TerminalPanel and FilesPanel from existing views
- Add mobile sidebar toggle functionality with overlay
- Add rainbow breathing light effect to drawer button
- Remove Tools section from AppSidebar (Terminal/Files entries)
- Add i18n support for drawer and file tree
- Optimize mobile button layout and spacing
- Fix z-index hierarchy for proper layering
- Add responsive sidebar behavior (PC: always visible, Mobile: toggle)

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

* feat: customize drawer button with arc rainbow border

- Change drawer button to semi-circle shape贴着右边
- Add arrow icon pointing left (向左箭头)
- Add rainbow border from top to bottom through semi-circle arc
- Slow down animation from 4s to 8s for smoother effect
- Move drawer button wrapper to messages area only (not贯穿header和input)
- Add semi-transparent accent color background to button

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

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix: resolve profile switching state sync issue (#414) (#415)

* fix: resolve profile switching state sync issue (#414)

Fix bug where switching to a different profile would still show the
old profile name in the UI and prevent switching back to default.

Root cause:
- Frontend relied entirely on fetchProfiles() return value to set
  activeProfileName
- Backend Hermes CLI may return stale active flag due to timing
  issues between profile use and profile list commands
- This caused frontend to display wrong profile and prevented
  switching back to default

Solution:
- Immediately set activeProfileName when switchProfile API succeeds
- Don't rely solely on listProfiles() result which may have stale data
- Use activeProfileName instead of activeProfile?.name in ProfileSelector

Changes:
- profiles store: Set activeProfileName immediately after successful switch
- ProfileSelector: Use activeProfileName computed property
- Add test to verify activeProfileName updates on switch

Fixes #414

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

* refine: improve error handling for profile switching failures

Add proper error handling for edge cases:
- If fetchProfiles() fails after successful switch, keep the updated
  activeProfileName (don't let fetchProfiles failure undo the switch)
- Add test cases to verify:
  1. API failure doesn't change state
  2. fetchProfiles failure doesn't affect successful switch

This ensures the UI remains consistent even when profile list refresh
fails after a successful profile switch.

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

* refine: add rollback mechanism for profile switching verification

Add backend verification after profile switch:
- Save old activeProfileName before setting new value
- After fetchProfiles, verify backend reports expected active profile
- If backend reports different profile, rollback frontend state and return false
- This handles edge case where API returns 200 but backend didn't actually switch

Test cases:
-  Normal switch: updates and verifies successfully
-  API failure: doesn't change state
-  fetchProfiles failure: assumes success (API returned 200)
-  Backend verification fails: rolls back to old profile

This ensures frontend state always matches backend reality, even in
edge cases where hermes profile use succeeded but gateway/cleanup
steps failed.

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

* refine: add user feedback for profile operations

Improve user experience with success/error messages:
- ProfileSelector: Add error message when switch fails
- ProfileCard: Add success message before reload on switch
- ProfileSelector: Use async/await for better error handling
- ProfileCard: Add 500ms delay before reload to show success message

Before: Silent failures, no feedback
After: Clear success/error messages for all operations

Example feedback:
- Success: "已切换到配置 qinghe"
- Failure: "切换配置失败,网关可能需要手动重启"

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

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>

* docs: update frontend changelog for v0.5.7 (#419)

* docs: update frontend changelog for v0.5.7

- Update changelog.ts with v0.5.7 release date and changes
- Add i18n translation keys for all languages (en, zh, de, es, fr, ja, ko, pt)
- Include v0.5.7 changelog entries:
  - Optimize context compression and session sync
  - Add startup delays to prevent database race conditions

Changes:
- packages/client/src/data/changelog.ts: Update v0.5.7 entry
- packages/client/src/i18n/locales/*.ts: Add changelog translation section

This enables the changelog modal in the UI to display v0.5.7 release notes.

* feat: add v0.5.7 changelog translations to all supported languages

Add new_0_5_7_1, new_0_5_7_2, and new_0_5_7_3 changelog entries to all
locale files (en, zh, de, es, fr, ja, ko, pt) with proper translations
for each language.

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

* fix: remove duplicate changelog sections causing syntax errors

Remove duplicate changelog object sections that were causing TypeScript
syntax errors in all locale files (en, zh, de, es, fr, ja, ko, pt).
The actual changelog entries are already correctly placed in the main
changelog section of each file.

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

* feat: add v0.5.8 changelog and fix profile parsing issue

Add v0.5.8 changelog entries based on PRs merged since v0.5.7:
- Drawer panel with mobile sidebar support (#412)
- Profile switching state sync fix (#414)
- Speech playback special character filtering (#409)
- Missing i18n key and session data source unification (#408)
- Vite build optimization for faster Docker builds (#403)

Also fix issue #417: Profile names with long hyphenated names fail
to parse in profile list regex. Change \s{2,} to \s+ to handle
compressed column spacing when profile names are long.

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

* fix: remove enter key submit from profile creation and rename modals

Remove @keyup.enter handlers from NInput components in:
- ProfileCreateModal: prevent accidental profile creation when pressing enter
- ProfileRenameModal: prevent accidental profile rename when pressing enter

Users must now explicitly click the confirm button to submit, preventing
unintended profile operations.

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

* feat: allow free text input for profile names

Remove frontend character filtering from profile creation and rename
modals. Users can now input any characters including spaces and
uppercase letters to test backend Hermes CLI validation.

Changes:
- ProfileCreateModal: Remove toLowerCase() and character filtering
- ProfileRenameModal: Remove toLowerCase() and character filtering
- Use v-model:value binding instead of :value with @input

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

* fix: improve error handling for profile creation

Display backend error messages when profile creation fails instead of
generic "failed" message. This helps users understand why their
profile name was rejected (e.g., invalid characters).

Changes:
- API layer: Capture and return error messages from backend
- ProfileCreateModal: Display specific error message from backend

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

* feat: add profile name validation with i18n support

Add client-side validation for profile names to prevent invalid input
before sending to backend. Only lowercase letters, numbers, underscores,
and hyphens are allowed.

Changes:
- ProfileCreateModal: Add input validation with real-time feedback
- ProfileRenameModal: Add input validation with real-time feedback
- Add nameValidation i18n key for all 8 languages
- Filter invalid characters on input and show warning message

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

* refactor: revert profile parsing regex changes

Revert the regex changes in hermes-cli.ts and gateway-manager.ts
back to requiring \s{2,} (at least 2 spaces). Since frontend now
validates profile names to only allow lowercase letters, numbers,
underscores, and hyphens, the relaxed regex is no longer needed.

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

* refactor: revert profile parsing regex changes

Revert the regex changes in gateway-manager.ts and hermes-cli.ts
back to requiring \s{2,} (at least 2 spaces). Since frontend now
validates profile names to only allow lowercase letters, numbers,
underscores, and hyphens, the relaxed regex is no longer needed.

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

* refactor: remove tooltip from drawer button

Remove the NTooltip wrapper from the floating drawer button.
The "Terminal & Files" tooltip is no longer shown on hover.

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

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>

* Update assets images (#421)

Updated two asset images in the client package.

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>

* chore: bump version to 0.5.8

Release v0.5.8

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

* fix: improve profile list parsing to handle long profile names (#425)

Fixed issue #423 where long profile names caused parsing failures.

Changes:
- gateway-manager.ts: Use `.+?` instead of `\S+` to match profile names, allowing names that overflow table column width
- hermes-cli.ts: Use `\s+` instead of `\s{2,}` for first delimiter to handle cases where long profile names reduce spacing to 1 space

The regex now correctly parses profile output even when profile names are long enough to compress table formatting, ensuring all profiles appear in the UI regardless of name length.

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat: add GitHub issue templates

Add structured issue templates to guide users when submitting issues:
- Bug Report template with version info, reproduction steps, and environment details
- Feature Request template with problem statement, solution, and priority
- General Issue template for questions that don't fit other categories
- Config to enable blank issues and provide contact links to documentation and discussions

Templates use YAML forms for better structure and validation of required fields.

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

* fix: unify profile management across the application (#432)

This commit addresses long-standing profile inconsistency issues by establishing
`~/.hermes/active_profile` file as the single source of truth for all profile
operations throughout the application.

## Changes

### Backend (Server)

**1. profiles.ts - Enhanced profile switching**
- Switch from CLI polling to direct file verification (Hermes CLI writes synchronously)
- Verify `active_profile` file with quick retry (max 2 attempts × 100ms = 300ms)
- Update GatewayManager only after file verification succeeds
- Add comprehensive logging for debugging

**2. profiles.ts - Authoritative API responses**
- Override CLI's active flag with `active_profile` file in `list()` endpoint
- Add warning when CLI output differs from file (detects inconsistencies)
- Ensures API responses always match actual runtime state

**3. jobs.ts - Use authoritative profile source**
- `resolveProfile()` falls back to `getActiveProfileName()` when no profile in request
- Ensures jobs operate on correct profile even if frontend doesn't specify

**4. cron-history.ts - Fix run history to respect active profile**
- Changed from fixed `~/.hermes/cron/output/` to `getActiveProfileDir()/cron/output/`
- Run history now correctly switches with profile (e.g., `~/.hermes/profiles/hermes/cron/output/`)

**5. proxy-handler.ts - Add fallback to authoritative source**
- If no profile in request headers/query, read from `getActiveProfileName()`
- Prevents proxy from using wrong default profile

### Frontend (Client)

**1. api/client.ts - Simplified profile resolution**
- Prioritize `useProfilesStore().activeProfileName` over localStorage
- localStorage fallback only for early initialization

**2. api/hermes/chat.ts - Consistent profile resolution**
- Same pattern: store first, localStorage fallback only during init

**3. stores/session-browser-prefs.ts - Clean up fallback logic**
- Prioritize store, remove redundant localStorage read

## Problem Solved

Previously, multiple components had different ways of determining the active profile:
- CLI output (◆ marker) - could be stale
- GatewayManager memory - startup cache only
- localStorage - frontend cache
- Various fallbacks scattered across codebase

This caused inconsistencies where:
- Frontend showed one profile but API used another
- Jobs ran on wrong profile
- Run history displayed wrong data
- Profile switches appeared to fail (but actually succeeded)

## Solution

All components now derive the active profile from the same authoritative source:
- `~/.hermes/active_profile` file (written synchronously by `hermes profile use`)
- `getActiveProfileName()` function (reads the file)
- Single source of truth = no inconsistencies

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>

* docs: add v0.5.9 changelog entries (#434)

- Add unified profile management across the application
- Add GitHub issue and pull request templates

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-04 12:46:26 +08:00
ekko 08e1a72793 Release v0.5.8 (#422)
* fix: add missing i18n key and unify session data source (#408)

- Add `chat.sessionNotFound` translation key to all 8 locales
- Fix history page data source inconsistency:
  - Change `getHermesSession` to prioritize database over CLI
  - Now consistent with `listHermesSessions` behavior
  - Prevents "session in list but detail not found" issue
- Update CI workflow to trigger on base branch PRs
- Remove debug log from sessions-db

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix: filter special characters and emoji in speech playback (#409)

- Update extractReadableText to filter special characters like *#
- Only keep common punctuation marks for speech synthesis
- Remove emoji, symbols, and special unicode characters
- Improve text-to-speech readability

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat: add drawer panel with mobile sidebar support and customizable button (#412)

* feat: add drawer panel with mobile sidebar support

- Add DrawerPanel component with Terminal and Files tabs
- Extract TerminalPanel and FilesPanel from existing views
- Add mobile sidebar toggle functionality with overlay
- Add rainbow breathing light effect to drawer button
- Remove Tools section from AppSidebar (Terminal/Files entries)
- Add i18n support for drawer and file tree
- Optimize mobile button layout and spacing
- Fix z-index hierarchy for proper layering
- Add responsive sidebar behavior (PC: always visible, Mobile: toggle)

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

* feat: customize drawer button with arc rainbow border

- Change drawer button to semi-circle shape贴着右边
- Add arrow icon pointing left (向左箭头)
- Add rainbow border from top to bottom through semi-circle arc
- Slow down animation from 4s to 8s for smoother effect
- Move drawer button wrapper to messages area only (not贯穿header和input)
- Add semi-transparent accent color background to button

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

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix: resolve profile switching state sync issue (#414) (#415)

* fix: resolve profile switching state sync issue (#414)

Fix bug where switching to a different profile would still show the
old profile name in the UI and prevent switching back to default.

Root cause:
- Frontend relied entirely on fetchProfiles() return value to set
  activeProfileName
- Backend Hermes CLI may return stale active flag due to timing
  issues between profile use and profile list commands
- This caused frontend to display wrong profile and prevented
  switching back to default

Solution:
- Immediately set activeProfileName when switchProfile API succeeds
- Don't rely solely on listProfiles() result which may have stale data
- Use activeProfileName instead of activeProfile?.name in ProfileSelector

Changes:
- profiles store: Set activeProfileName immediately after successful switch
- ProfileSelector: Use activeProfileName computed property
- Add test to verify activeProfileName updates on switch

Fixes #414

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

* refine: improve error handling for profile switching failures

Add proper error handling for edge cases:
- If fetchProfiles() fails after successful switch, keep the updated
  activeProfileName (don't let fetchProfiles failure undo the switch)
- Add test cases to verify:
  1. API failure doesn't change state
  2. fetchProfiles failure doesn't affect successful switch

This ensures the UI remains consistent even when profile list refresh
fails after a successful profile switch.

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

* refine: add rollback mechanism for profile switching verification

Add backend verification after profile switch:
- Save old activeProfileName before setting new value
- After fetchProfiles, verify backend reports expected active profile
- If backend reports different profile, rollback frontend state and return false
- This handles edge case where API returns 200 but backend didn't actually switch

Test cases:
-  Normal switch: updates and verifies successfully
-  API failure: doesn't change state
-  fetchProfiles failure: assumes success (API returned 200)
-  Backend verification fails: rolls back to old profile

This ensures frontend state always matches backend reality, even in
edge cases where hermes profile use succeeded but gateway/cleanup
steps failed.

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

* refine: add user feedback for profile operations

Improve user experience with success/error messages:
- ProfileSelector: Add error message when switch fails
- ProfileCard: Add success message before reload on switch
- ProfileSelector: Use async/await for better error handling
- ProfileCard: Add 500ms delay before reload to show success message

Before: Silent failures, no feedback
After: Clear success/error messages for all operations

Example feedback:
- Success: "已切换到配置 qinghe"
- Failure: "切换配置失败,网关可能需要手动重启"

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

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>

* docs: update frontend changelog for v0.5.7 (#419)

* docs: update frontend changelog for v0.5.7

- Update changelog.ts with v0.5.7 release date and changes
- Add i18n translation keys for all languages (en, zh, de, es, fr, ja, ko, pt)
- Include v0.5.7 changelog entries:
  - Optimize context compression and session sync
  - Add startup delays to prevent database race conditions

Changes:
- packages/client/src/data/changelog.ts: Update v0.5.7 entry
- packages/client/src/i18n/locales/*.ts: Add changelog translation section

This enables the changelog modal in the UI to display v0.5.7 release notes.

* feat: add v0.5.7 changelog translations to all supported languages

Add new_0_5_7_1, new_0_5_7_2, and new_0_5_7_3 changelog entries to all
locale files (en, zh, de, es, fr, ja, ko, pt) with proper translations
for each language.

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

* fix: remove duplicate changelog sections causing syntax errors

Remove duplicate changelog object sections that were causing TypeScript
syntax errors in all locale files (en, zh, de, es, fr, ja, ko, pt).
The actual changelog entries are already correctly placed in the main
changelog section of each file.

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

* feat: add v0.5.8 changelog and fix profile parsing issue

Add v0.5.8 changelog entries based on PRs merged since v0.5.7:
- Drawer panel with mobile sidebar support (#412)
- Profile switching state sync fix (#414)
- Speech playback special character filtering (#409)
- Missing i18n key and session data source unification (#408)
- Vite build optimization for faster Docker builds (#403)

Also fix issue #417: Profile names with long hyphenated names fail
to parse in profile list regex. Change \s{2,} to \s+ to handle
compressed column spacing when profile names are long.

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

* fix: remove enter key submit from profile creation and rename modals

Remove @keyup.enter handlers from NInput components in:
- ProfileCreateModal: prevent accidental profile creation when pressing enter
- ProfileRenameModal: prevent accidental profile rename when pressing enter

Users must now explicitly click the confirm button to submit, preventing
unintended profile operations.

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

* feat: allow free text input for profile names

Remove frontend character filtering from profile creation and rename
modals. Users can now input any characters including spaces and
uppercase letters to test backend Hermes CLI validation.

Changes:
- ProfileCreateModal: Remove toLowerCase() and character filtering
- ProfileRenameModal: Remove toLowerCase() and character filtering
- Use v-model:value binding instead of :value with @input

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

* fix: improve error handling for profile creation

Display backend error messages when profile creation fails instead of
generic "failed" message. This helps users understand why their
profile name was rejected (e.g., invalid characters).

Changes:
- API layer: Capture and return error messages from backend
- ProfileCreateModal: Display specific error message from backend

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

* feat: add profile name validation with i18n support

Add client-side validation for profile names to prevent invalid input
before sending to backend. Only lowercase letters, numbers, underscores,
and hyphens are allowed.

Changes:
- ProfileCreateModal: Add input validation with real-time feedback
- ProfileRenameModal: Add input validation with real-time feedback
- Add nameValidation i18n key for all 8 languages
- Filter invalid characters on input and show warning message

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

* refactor: revert profile parsing regex changes

Revert the regex changes in hermes-cli.ts and gateway-manager.ts
back to requiring \s{2,} (at least 2 spaces). Since frontend now
validates profile names to only allow lowercase letters, numbers,
underscores, and hyphens, the relaxed regex is no longer needed.

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

* refactor: revert profile parsing regex changes

Revert the regex changes in gateway-manager.ts and hermes-cli.ts
back to requiring \s{2,} (at least 2 spaces). Since frontend now
validates profile names to only allow lowercase letters, numbers,
underscores, and hyphens, the relaxed regex is no longer needed.

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

* refactor: remove tooltip from drawer button

Remove the NTooltip wrapper from the floating drawer button.
The "Terminal & Files" tooltip is no longer shown on hover.

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

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>

* Update assets images (#421)

Updated two asset images in the client package.

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-03 22:10:40 +08:00
ekko 793003fcf6 feat(chat): redesign attachments with ContentBlock format and file downloads (#397)
- Redesign attachment handling using Anthropic-style ContentBlock array format
  with discriminated unions (text, image, file types)
- Add frontend file download functionality supporting both ContentBlock
  and Markdown formats with authentication tokens
- Fix multi-process conflict causing SQLite database resets by eliminating
  redundant nodemon instances
- Update chat store to build ContentBlock arrays from attachments
- Improve image handling with base64 conversion for upstream API

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-02 15:39:01 +08:00
ekko caa9162f28 feat(chat): add voice playback with auto-play and visual effects (#396)
## Features

### Core Functionality
- **Web Speech API Integration**: Add TTS (text-to-speech) playback for assistant messages
- **Manual Playback**: Click-to-play button next to each assistant message (🔊 icon)
- **Auto-play Mode**: Toggle switch in input bar to auto-play responses
- **Playback Controls**: Play/pause/stop with visual feedback

### User Interface
- **Playback Button**: Hover-activated button in message meta area (next to copy button)
- **Auto-play Switch**: Voice icon toggle in input top bar with state persistence
- **Mobile Optimization**: Buttons always visible on mobile (≤768px width)
- **Visual Feedback**:
  - Rainbow glowing border during playback (2px border, 10px/20px glow)
  - 4-second animation cycle through 6 colors
  - Play/pause icon toggle

### Voice Customization
- **Pitch/Rate Control**: Low-pitched (0.5) fast-speaking (1.2) "male voice"
- **Auto Voice Selection**: Attempts to select male voices across platforms (macOS: Yaoyao, Windows: David/Daniel)
- **Platform Compatibility**: Works with system-provided voices on macOS, iOS, Android, Windows

### Content Filtering
- Smart text extraction: filters code blocks, `<thinking>` tags, HTML
- Only assistant messages are eligible for playback
- Tool and system messages are excluded

### Internationalization
- Added 8 language translations (en, zh, de, es, fr, ja, ko, pt)
- New keys: `playSpeech`, `pauseSpeech`, `resumeSpeech`, `stopSpeech`, `autoPlaySpeech`, `speechNotSupported`

## Technical Details

### New Files
- `packages/client/src/composables/useSpeech.ts`: Core speech synthesis composable
  - Voice loading and selection logic
  - Single-instance global speech manager
  - Event handling (onstart, onend, onerror, onboundary)
  - State management (isPlaying, isPaused, currentMessageId)

### Modified Components
- **ChatInput.vue**: Auto-play switch with localStorage persistence
- **MessageItem.vue**:
  - Playback button integration
  - Event listener for auto-play triggers
  - Mobile-first button visibility
  - Rainbow border animation during playback

### Store Changes
- `chat.ts`:
  - Added `autoPlaySpeechEnabled` state
  - `setAutoPlaySpeech()` method
  - `playMessageSpeech()` method for event-based playback
  - Auto-play trigger on `run.completed` event

## Browser Support
- Requires Web Speech API support (all modern browsers)
- Graceful degradation: button hidden if API not supported
- Voice availability varies by platform and OS

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-02 13:26:57 +08:00
Desmond Zhang 018053db19 feat(usage): expanded daily stats with detailed token breakdown (#385)
* feat(usage): expanded daily stats with detailed token breakdown

* feat(usage): separate cache read and cache write in daily trend table
2026-05-02 08:36:33 +08:00
ekko 3ba76ad19b feat: add History page for browsing Hermes sessions (v0.5.5) (#370)
Features:
- Add dedicated History page for browsing Hermes session history
- Independent session state (does not interfere with active chat)
- Auto-select first CLI session on page load
- Filter out api_server and cron sources

Components:
- New HistoryView.vue with isolated state management
- New HistoryMessageList.vue with session prop support
- Filters empty content and tool messages without toolName

Backend:
- Add GET /api/hermes/sessions/hermes endpoint (excludes api_server)
- Add GET /api/hermes/sessions/hermes/:id endpoint (404s for api_server)
- Add fetchHermesSessions() and fetchHermesSession() API functions

Cleanup:
- Remove localStorage session caching
- Simplify profile switching cache management
- Clean up废弃 cache cleanup calls

i18n:
- Add "History" translation to all 8 locales
- Add v0.5.5 changelog entries in all languages
- 🎉 Happy Labor Day!

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-01 11:27:43 +08:00
ekko f15deef3fc fix(chat): isolate concurrent session events by refactoring WebSocket event handling (#365)
Refactored the WebSocket event handling mechanism to use global listeners with session-specific event routing instead of per-session listeners. This prevents event cross-talk when multiple chat sessions run concurrently.

Key changes:
- Client: Added sessionEventHandlers Map to route events to appropriate sessions
- Client: Registered global listeners once per socket connection
- Server: Extracted message processing logic into handleMessage method
- Server: Improved Hermes session ID tracking with dedicated Map
- Server: Added replaceByHermesSessionId for targeted message replacement

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-01 08:13:55 +08:00
jsonet 7e7fe90483 fix(chat): isolate concurrent session events and workspace dialog i18n (#351)
* feat: per-session workspace with folder picker, HERMES_HOME support, esbuild fix

* fix(chat): isolate concurrent session events and workspace dialog i18n

Two user-visible bugs are fixed here:

1. Workspace dialog title showed the raw i18n key 'chat.setWorkspaceTitle' because the key was never added to en.ts / zh.ts. The dialog is opened from ChatPanel.vue but only 'setWorkspace' existed. Add the missing 'setWorkspaceTitle' translation in both locales.

2. With two concurrent runs the assistant text from session A would show up in session B (and vice versa). The /chat-run namespace uses a single shared Socket.IO connection on the client; every startRunViaSocket() call registers its own listeners on the same socket. The server fans events out via 'session:<id>' rooms, but a single socket can be in multiple rooms at once and there was no per-event filtering on the client. Each run's closure captured its own sid and wrote into the wrong session. The server already tags every payload with session_id, so the fix is a guard inside handleEvent() that drops events whose session_id does not match this run's body.session_id. Untagged events are still accepted for backwards compatibility.

3. Also fix a related crash where setting a workspace on a session that had not been persisted yet (no first message sent) threw because the row did not exist. Create the row on demand inside setWorkspace controller.

* fix: upgrade esbuild to 0.27+ for vite 8 compatibility

---------

Co-authored-by: ekko <fqsy1416@gmail.com>
2026-04-30 20:17:38 +08:00
Zhicheng Han dac9006b3e fix: align usage analytics with Hermes state db (#350) 2026-04-30 19:46:31 +08:00