* feat(chat): redesign attachments with ContentBlock format and file downloads
- 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>
* fix(db): add startup delays to prevent resource race conditions
- Add 1 second delay after gateway manager initialization
- Add 1 second delay after store initialization before session sync
- Code formatting cleanup in schemas.ts
These delays ensure all resources are fully initialized before
proceeding to the next startup step, preventing potential race
conditions and database access issues during server bootstrap.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Add robust LLM JSON parsing utilities to handle unreliable model output:
- Parse tool arguments with tolerance for Python format (single quotes, trailing commas)
- Extract text from Anthropic-style content arrays in streaming events
- Normalize tool_result content to string format per Hermes spec
- Parse message.delta and run.completed output to avoid displaying JSON strings
Fix Group Chat database schema errors:
- Add id column as PRIMARY KEY to gc_room_agents and gc_room_members tables
- Change from composite primary keys to single-column id keys
- Update tests to match new schema structure
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* 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>