Commit Graph

184 Commits

Author SHA1 Message Date
ekko 65e712edfc fix: group chat UX polish and model switch cleanup (#205)
* fix(chat): clamp context remaining tokens to 0 instead of showing negative

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

* fix: group chat mention popup position, timestamp style, and model switch cleanup

- Move @ mention popup above input to avoid blocking the textarea
- Fix .msg-time scoping (was nested inside .msg-header, now top-level)
- Reduce timestamp opacity and set to 12px for subtler display
- Clean up stale base_url/api_key from config.yaml on model switch

Closes #204

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

* fix: remove unused variables in GroupChatInput

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

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-25 16:16:11 +08:00
ekko a2c57ccaf0 fix(chat): clamp context remaining tokens to 0 instead of showing negative (#202)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-25 14:23:37 +08:00
ww 4bdcaa6258 feat: add Alibaba Coding Plan provider with .env base_url support (#200)
* feat(providers): 新增 Alibaba Cloud (Coding Plan) 内置 provider

对齐 hermes-agent 上游 PR #15045(commit 727d1088),新增
alibaba-coding-plan provider,鉴权使用 ALIBABA_CODING_PLAN_API_KEY
环境变量,base_url 可通过 ALIBABA_CODING_PLAN_BASE_URL 覆盖。

默认 base_url 使用国际版端点 coding-intl.dashscope.aliyuncs.com/v1,
与上游 auth.py:255 保持一致。中国大陆 DashScope 账号
(dashscope.aliyun.com 颁发的 sk-sp-* 密钥)需要通过
ALIBABA_CODING_PLAN_BASE_URL=https://coding.dashscope.aliyuncs.com/v1
(不带 -intl)覆盖,因为 -intl 端点对该类密钥返回 HTTP 401。
该差异在源码注释中已说明。

模型列表覆盖 8 个 Coding Plan 支持的模型:qwen3.5-plus、
qwen3-max-2026-01-23、qwen3-coder-next/plus、glm-5、glm-4.7、
kimi-k2.5、MiniMax-M2.5(基于实测可用列表)。

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* feat(providers): Alibaba Coding Plan 添加国内/国际区域切换

在 ProviderFormModal 中针对 alibaba-coding-plan preset 增加一个
"区域"字段,可在国际版(coding-intl)与中国大陆(coding,无 -intl)
两个端点之间切换,切换时自动更新 base_url。

默认选中国际版以对齐上游 hermes-agent 默认值。中国大陆 DashScope
账号(dashscope.aliyun.com 颁发的 sk-sp-* 密钥)只需在表单里点一下
"中国大陆"即可,无需手动改 base_url 或设环境变量。

8 个 locale(zh/en/de/es/fr/ja/ko/pt)都补全了 region/regionIntl/
regionCn 三个 i18n key。

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix(providers): builtin provider 列表优先读取 base_url env override

之前服务端 getAvailable 在渲染 builtin provider 列表时直接
用 PROVIDER_PRESETS 里的默认 base_url,忽略了用户保存到 .env
的 base_url override。这导致用户在 Alibaba Coding Plan 选了"中国
大陆"保存后,列表里仍然显示国际版 URL。

修复:envMapping.base_url_env 如果存在且 .env 中有值,优先
使用该值;否则 fallback 到 preset 默认。

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-25 14:00:07 +08:00
356252190-star 12ae840234 fix: skip remote profiles in startAll() to prevent startup hang (#197) 2026-04-25 09:22:01 +08:00
ww 369001824e feat(chat): 支持思考块实时流式与历史展示 (#191)
* feat: 添加文件下载功能,支持多 Terminal Backend

实现基于 FileProvider 抽象的文件下载能力,支持 local、Docker、SSH、
Singularity 四种 backend。

主要变更:
- 新增 FileProvider 接口及四种后端实现(含 SSH 命令注入防护)
- 新增 GET /api/hermes/download 下载路由(含 MIME 类型检测)
- 前端 Markdown 文件链接拦截下载 + 附件下载按钮
- 中英文 i18n 翻译
- 更新 README、CLAUDE.md 和设计文档

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* feat: 添加文件浏览器与下载功能,支持目录浏览、文件编辑、预览和上传

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* build: add prepare script so 'npm install git+url' auto-builds dist/

Allows installing this package directly from git without a pre-built dist/.
When cloned via npm, prepare runs 'npm run build' if dist/ is missing,
producing the artifacts declared in the files[] field before packing.

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>

* i18n: backfill files/download translations for de, es, fr, ja, ko, pt

Add nav.files, files.* (39 keys), and download.* (9 keys) so the file
browser UI is fully localized in these six locales instead of falling
back to English.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix(files): close preview when navigating or affected file changes

Opening a preview and then navigating directories, deleting the
previewed file, or renaming it left the preview pane stuck on stale
content because previewFile was never cleared.

- stores/hermes/files.ts:
  - fetchEntries clears previewFile on path change (in-place refresh
    keeps the preview).
  - deleteEntry / renameEntry clear preview/editor state when the
    affected entry matches the previewed/edited file or its parent.
  - Add isAffected(target, changed, isDir) helper.
- components/hermes/files/FilePreview.vue: replace the misleading
  common.cancel close button with a dedicated files.closePreview key
  plus an X icon and quaternary style.
- i18n: add files.closePreview to all 8 locales.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* chore: 清理已完成功能的计划与设计文档

文件浏览器与文件下载功能均已被上游合并,对应的开发计划
与设计稿不再需要在 fork 中保留:
- plans/2025-07-20-file-browser.md
- plans/2026-04-20-file-download.md
- specs/2025-07-20-file-browser-design.md
- specs/2026-04-20-file-download-design.md

清理后本 fork 与 upstream/main 代码层面完全对齐。

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* docs: 添加 thinking 块分离与折叠展示设计稿(#164)

针对上游 issue #164,设计 assistant 消息中 <think>/<thinking>/<reasoning>
标签的识别、分离与可折叠展示方案。

关键决策(经 rubber-duck 审查修订):
- 不修改 Message.content 与持久化字段,确保 localStorage 向前兼容
- 耗时摘要改为纯运行时派生(store 内 Map),避免刷新/重连丢失
- 首版即实现代码块保护,避免误识别
- 流结束时未闭合标签降级为正文,防止吞答案
- 解析 computed 与 duration interval 分离,规避性能风险
- 解析器放置 packages/client/src/utils/ 避免反向依赖
- 显式不支持同名嵌套(罕见场景文档化)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* docs: 添加 thinking 块分离与折叠实施计划(#164)

12 Task TDD 计划:
- Task 1-7:utils/thinking-parser.ts 纯函数模块 + 单元测试
- Task 8-9:chat store thinkingObservation Map 接入 SSE
- Task 10:8 语言 i18n 新增 6 条 key
- Task 11:MessageItem.vue 渲染折叠 UI + SCSS
- Task 12:构建/测试/手动验证/推送

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* feat(thinking-parser): 首个闭合 <think> 标签拆分

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* test(thinking-parser): 覆盖多段/变体标签/大小写/空输入

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* test(thinking-parser): 流式 pending 与终止态降级

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* feat(thinking-parser): 代码块保护避免误识别伪标签

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* test(thinking-parser): 同名嵌套与 chunk 边界行为

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* feat(thinking-parser): countThinkingChars 辅助函数

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* feat(thinking-parser): detectThinkingBoundary 边界检测

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* feat(chat-store): 新增 thinkingObservation 运行时 Map

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* feat(chat-store): message.delta 写入 thinking 边界 + switchSession 清理

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* i18n: 新增 thinking 块 6 条 key(8 语言)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* feat(chat): MessageItem 渲染 thinking 折叠区

- 复用 tool-line 风格 chevron
- 两条响应链:parse computed + duration interval
- 流式+pending 强制展开
- show_reasoning 控制默认态

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* feat(chat): 支持思考块实时流式与历史展示

- 扩展 Message 接口增加 reasoning 字段,mapHermesMessages 从
  HermesMessage.reasoning 透传历史会话的思考内容。
- RunEvent 类型新增 text 字段,chat store 处理三个新 SSE 事件:
  reasoning.delta / thinking.delta / reasoning.available。
- 思考时长观察:仅在 reasoning.delta 累积时记录起始时间戳,
  reasoning.available 时记录结束时间戳;无实时 delta 时不显示时长。
- MessageItem 采用双源渲染(reasoning 字段优先,<think> 标签作
  fallback),duration > 0 才展示耗时。
- 新增 3 条单测覆盖三个 SSE 事件;测试 32/32 通过。

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix(chat): reasoning 块不再短暂展示正文

根因:上游 hermes-agent run_agent.py:11275 在每次模型响应结束时用
assistant content[:500] 作为 reasoning.available 的 preview 负载,
致使 Web UI 把正文写入 last.reasoning,思考块短暂显示正文直到会话
轮询/刷新从 session DB 读回正确的 reasoning 字段。

修复:
- reasoning.available 事件不再写入 last.reasoning,仅用于标记计时
  结束(noteReasoningEnd);真实推理由 reasoning.delta 或会话 DB
  提供
- 新增 scrubBuggyReasoningInCache:hydration 时治愈 localStorage 里
  已被污染的 assistant 消息(reasoning == content 或前缀时丢弃)
- 两个 cache 加载入口(loadSessions / switchSession)均接入 scrubber

测试:新增 4 条单测,全套 280/280 通过。

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-25 08:46:50 +08:00
ekko c1e72942ad fix(docker): skip prepare script during npm install (#196)
#142 added a `prepare` script that triggers `npm run build` when
dist/ is missing. During Docker build, `npm install` runs before
source files and tsconfig.json are copied, causing build failure.
Use --ignore-scripts to defer build to the explicit step.

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-24 23:52:54 +08:00
ekko 833fe06f92 fix: restore fetchAvailableModels to fix provider lost as custom (#194)
* fix: restore fetchAvailableModels to fix provider lost as custom (#174)

#174 replaced fetchAvailableModels with fetchConfigModels, but
config/models response lacks default_provider, label, base_url and
api_key fields. This caused selectedProvider to always be empty,
making all models appear as "custom" in the model selector.

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

* chore: bump version to 0.4.6

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

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
v0.4.6
2026-04-24 23:30:34 +08:00
ekko 70ed0e0dc2 revert: harden Hermes stream recovery around tool-call boundaries (#189) (#192)
Reverts #189 due to reported bugs.

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-24 22:18:32 +08:00
ekko bff6f844e6 docs: add group chat feature to README (#190)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-24 21:47:10 +08:00
Zhicheng Han 009acc1c28 fix: harden Hermes stream recovery around tool boundaries (#189) 2026-04-24 21:42:42 +08:00
ekko edd41e6eb7 fix: group chat mobile UX and UI polish (#188)
* fix: group chat UI background colors and replace console.log in context-engine

- Set message list background to $bg-card to match single chat
- Set status-bar background to transparent
- Replace all console.log/warn with logger in context-engine compressor

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

* fix: group chat mobile UX improvements

- Add backdrop overlay for mobile sidebar with tap-to-close
- Auto-collapse sidebar on room select in mobile
- Move timestamp below message bubble
- Widen msg-body max-width to 85% to match single chat
- Add left padding to chat-header to avoid hamburger overlap

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

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
v0.4.5
2026-04-24 21:28:06 +08:00
ekko 3df369afc0 chore: add changelog for v0.4.5 (#187)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-24 20:54:06 +08:00
ekko ba72264542 feat: group chat session lifecycle, typing recovery, mention highlighting (#186)
* feat: restore group chat system with Socket.IO and SQLite persistence

- GroupChatServer: Socket.IO server with room management, message history, typing indicators
- SQLite storage for rooms, messages, and agent configuration
- AgentClients: manages AI agent connections via socket.io-client, forwards @mentions to Hermes gateway
- REST API: room CRUD, agent management, invite codes
- Agent auto-restoration on server restart
- Tests for all REST endpoints

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

* docs: add context-engine design document for group chat compression

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

* fix: handle special-character session search

* fix: keep unicode dotted session search on quoted FTS path

* feat: add context engine and group chat frontend UI

- Context engine: three-zone compression (head/tail/summary) with LLM
  summarization, incremental updates, TTL cache, and graceful degradation
- Frontend: group chat page with Socket.IO client, room sidebar, message
  list, agent/member display, create/join-by-code modals
- Integration: wire context engine into agent-clients before /v1/runs
- Refactor ChatStorage to use global DB (getDb/ensureTable) with gc_ prefix
- Add i18n keys for group chat to all 8 locales
- Add sidebar nav entry and router for group chat page

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

* fix: remove leftover main branch code from merge conflict resolution

The `isNumericQuery`, `hasUnsafeChars`, and `runLikeContentSearch` functions
no longer exist — they were replaced by HEAD's `shouldUseLiteralContentSearch`
and `runLiteralContentSearch`. This dead code block caused a TypeScript
compile error after the merge.

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

* fix: install missing socket.io dep and type ack params

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

* fix: enable WebSocket proxy and fix socket.io transport for group chat

- Add ws: true to Vite proxy config so WebSocket upgrade requests
  are forwarded to the backend
- Allow both polling and websocket transports on server and client
  (polling as fallback when WebSocket upgrade fails through proxy)

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

* fix: separate socket.io path from REST routes for group chat

socket.io was mounted at /api/hermes/group-chat which intercepted all
REST requests to /api/hermes/group-chat/rooms etc, returning
"Transport unknown". Changed socket.io path to /api/hermes/group-chat/ws
to avoid conflicts.

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

* feat: improve group chat UI, agent management, and socket.io reliability

- Redesign GroupChatPanel with Naive UI, stacked agent avatars, and popover management
- Match GroupChatInput style with single chat input, add IME composition handling
- Add agent add/remove per room with profile selection and duplicate prevention
- Use @multiavatar for SVG avatar generation with caching
- Decouple joinRoom from socket.io, use REST API for data loading
- Switch socket.io to default path with /group-chat namespace to avoid proxy conflicts
- Restore agent connections after server is listening
- Add getRoomDetail REST endpoint and duplicate agent prevention (409)

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

* feat: server-side @mention routing with context compression status and queue

- Move @mention detection from agent socket listeners to server-side processMentions()
- Add per-room processing lock to block mention dispatch during compression
- Queue mentions during processing, drain only the latest when ready
- Emit context_status events (compressing/replying/ready) to room via Socket.IO
- Frontend displays compression status indicator above input
- Token-based compression trigger (100k threshold) with CJK-aware estimation
- Fix compressor type errors (countTokens parameter type)

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

* feat: improve group chat profile handling and session sync

Refine group chat room/session behavior with per-room compression controls, sidebar updates, and better stale session cleanup so multi-profile group chat state stays consistent.

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

* feat: group chat improvements — session lifecycle, typing recovery, mention highlighting

- Fix cross-profile session deletion with deferred delete queue
- Move saveSessionProfile to after gateway response confirmation
- Replace all console.log with logger in group-chat modules
- Add server-side typing/context_status state tracking for room rejoin
- Fix @ mention popup position to follow cursor
- Add @ mention highlighting (blue) in chat message content
- Fix mention regex to match all occurrences after HTML tags
- Enable esbuild minify and treeShaking
- Move @multiavatar/multiavatar to devDependencies
- Add i18n keys for group chat features
- Update tests for new functionality

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

* chore: bump version to 0.4.5 and move @multiavatar to devDependencies

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

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Zhicheng Han <zhicheng.han@mathematik.uni-goettingen.de>
2026-04-24 20:41:14 +08:00
ekko 82965ae6e2 refactor: rewrite model-context to use js-yaml, add context_length to provider form (#177)
* fix: context-length API returns 200K instead of actual model context

Two bugs cause the /api/hermes/sessions/context-length endpoint to
always return DEFAULT_CONTEXT_LENGTH (200K):

1. getModelContextLength ignores config.yaml model.context_length
   The function only checks models_dev_cache.json (which doesn't
   exist in default installations) and falls back to the hardcoded
   200K default, completely ignoring the user's explicit
   model.context_length setting in config.yaml.

2. getDefaultModel regex fails when api_key/base_url come before default
   The regex /^model:\s*\n\s+default:\s*(.+)$/m assumes 'default' is
   the first child key under 'model:', but when api_key or base_url
   appear first in the YAML, the match fails. This causes
   getModelContextLength to short-circuit to DEFAULT_CONTEXT_LENGTH
   before even reaching the cache lookup.

Fix:
- Add getDefaultModelRobust() that extracts the entire model: block
  first, then searches for default: within it
- Add getConfigContextLength() that reads model.context_length from
  config.yaml as a fallback (matching hermes-agent priority)
- Update getModelContextLength() resolution order:
  1. models_dev_cache.json (existing)
  2. config.yaml model.context_length (new)
  3. DEFAULT_CONTEXT_LENGTH (existing fallback)

Closes #169

* refactor: rewrite model-context to use js-yaml, add context_length to provider form

- Replace fragile regex-based YAML parsing with js-yaml for reliable config.yaml reads
- Fix context_length resolution priority: config.yaml override > custom_providers > models_dev_cache > 200K default
- Add context_length input field when adding custom providers in ProviderFormModal
- Backend: persist context_length to custom_providers models.<model>.context_length in config.yaml
- Add i18n keys (contextLength, contextLengthPlaceholder) to all 8 locales

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

* fix: use NInputNumber instead of NInput type=number for context_length

NInput does not support type="number" in Naive UI.

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

---------

Co-authored-by: devilardis <53129661@qq.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-24 11:18:11 +08:00
Zhicheng Han 30e88797ef fix: add gpt-5.5 to OpenAI Codex models (#175) 2026-04-24 10:11:21 +08:00
ekko f8283729ba refactor: replace jobs proxy with local controller and optimize model loading (#174)
* refactor: replace jobs proxy with local controller and optimize model loading

- Add local jobs controller that directly fetches upstream gateway with
  profile support and 30s timeout, replacing unreliable proxy catch-all
- Upstream errors (non-200) return 502 instead of leaking to frontend
- Switch loadModels() from fetchAvailableModels (slow, fetches all
  provider APIs) to fetchConfigModels (reads config.yaml only)
- Hide logo dance video in sidebar

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

* fix: resolve TypeScript errors from previous refactor

- Remove unused imports (danceVideo, useTheme) in AppSidebar
- Map ConfigModelsResponse.groups to AvailableModelGroup[] format

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

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-24 09:57:30 +08:00
ekko 88c7e25f78 fix(i18n): add i18n support for custom model feature in ModelSelector (#172)
* feat(models): add custom model name input with provider selector

- Add custom model input field at bottom of model selector modal
- Add provider dropdown to specify target provider for custom model
- Track custom models in app store and display with CUSTOM badge
- Merge custom model into provider group list
- Fix custom provider models being overwritten by API response (keep both)

* Upload screenshot

* fix(i18n): add i18n support for custom model feature in ModelSelector

Replace hardcoded English strings (CUSTOM badge, placeholder, hint) with
vue-i18n t() calls and add corresponding translation keys to all 8 locales
(en, zh, ja, ko, fr, es, de, pt).

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

---------

Co-authored-by: toller892 <892@users.noreply.github.com>
Co-authored-by: Tony <125938283+toller892@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-24 08:49:45 +08:00
Zhicheng Han 03c18c210d 修复侧边栏 i18n 缺失 key 警告 (#170)
* Fix i18n missing-key warnings

* Add locale translations for i18n warning keys
2026-04-24 08:31:42 +08:00
ekko b4359ccddb fix: clear all localStorage on logout (#161)
Previously only cleared the auth token, leaving server URL, active
profile, chat caches and other data behind.

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-23 19:52:06 +08:00
ekko 30c94b226a fix: add periodic log rotation to prevent unbounded log growth (#160)
Log rotation previously only ran at startup, causing logs to grow
indefinitely on long-running processes (reported up to 71GB/day).
Now checks file size every 60 seconds and truncates when exceeding 3MB.

Fixes #155

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-23 19:49:31 +08:00
ekko 14e9f4a870 docs: add sponsor (爱发电) link to README (#156)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-23 16:47:19 +08:00
ww a4bfd8edd3 fix(files): close preview on navigation/delete/rename + backfill i18n (#150)
* i18n: backfill files/download translations for de, es, fr, ja, ko, pt

Add nav.files, files.* (39 keys), and download.* (9 keys) so the file
browser UI is fully localized in these six locales instead of falling
back to English.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix(files): close preview when navigating or affected file changes

Opening a preview and then navigating directories, deleting the
previewed file, or renaming it left the preview pane stuck on stale
content because previewFile was never cleared.

- stores/hermes/files.ts:
  - fetchEntries clears previewFile on path change (in-place refresh
    keeps the preview).
  - deleteEntry / renameEntry clear preview/editor state when the
    affected entry matches the previewed/edited file or its parent.
  - Add isAffected(target, changed, isDir) helper.
- components/hermes/files/FilePreview.vue: replace the misleading
  common.cancel close button with a dedicated files.closePreview key
  plus an X icon and quaternary style.
- i18n: add files.closePreview to all 8 locales.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-23 14:10:14 +08:00
ekko 93719fb04b docs: update README and OpenAPI spec to v0.4.4 (#147)
- Add File Browser, Session search, Authentication sections to README (EN + ZH)
- Update Model Management with Nous Portal auth and non-v1 URL support
- Update OpenAPI spec from 0.2.6 to 0.4.4
- Add 30+ new endpoints: Auth, Files, Download, Gateways, Codex/Nous OAuth, Update
- Add PUT provider endpoint for updating existing providers
- Update HealthResponse with webui_version, webui_update_available, node_version fields

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-23 13:12:40 +08:00
ekko 1abe308742 feat: add Node.js version warning, fix provider URL detection, and add v0.4.4 changelog (#146)
- Display persistent warning bar when Node.js version < 23
- Fix provider model fetching to support non-v1 API versions (e.g. /v4)
- Add v0.4.4 changelog entries to frontend
- Bump version to 0.4.4

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
0.4.4
2026-04-23 12:57:42 +08:00
ww 0cc31ee999 feat: add file browser and file download with multi-backend support (#142)
* 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>
2026-04-23 12:09:39 +08:00
ekko 1f91b902da fix: handle special char search 500 & polish live badge (#144)
* 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>
2026-04-23 11:18:56 +08:00
Zhicheng Han 5f40ae6258 feat(chat): add direct Live badge and harden Live monitor backend (#138)
* 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
2026-04-23 10:49:00 +08:00
ekko 32dc084b66 fix: support both Codex and Nous auth structures in OAuth provider detection (#141)
The isOAuthAuthorized check only looked for Codex's nested
`providers.{key}.tokens.access_token` structure, missing Nous's flat
`providers.nous.access_token`. Now checks both paths so all OAuth
providers are correctly detected and displayed in the provider list.

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-23 08:48:06 +08:00
ekko df797d09b2 feat: add StepFun and Nous Portal provider support (#140)
- Add StepFun provider (API key auth, STEPFUN_API_KEY)
- Add Nous Portal provider with full OAuth device code flow
  (device code request → poll for token → mint agent key → save to auth.json)
- Add NousLoginModal component for OAuth UI (user code display + verification link)
- Update ProviderFormModal to handle Nous OAuth flow (hide API key fields)
- Add nous-auth backend controller and routes
- Update PROVIDER_ENV_MAP with stepfun and nous entries
- Add i18n translations for Nous OAuth in all 8 locales

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-23 08:39:19 +08:00
mysoul12138 696d19298e fix: avoid localStorage quota errors when switching chats\n\n- keep default profile legacy cache read compatibility\n- stop duplicating bulky session/message/in-flight cache into legacy keys\n- add best-effort quota recovery before persisting active session\n- cover legacy cache migration in chat store tests (#137) 2026-04-23 07:35:05 +08:00
ekko 5537383bdb chore: optimize npm keywords and description for GitHub search discoverability (#135)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-22 22:04:26 +08:00
ekko 70ddbd0bcd feat: add username/password login, account settings, and changelog (#133) (#134)
- Add username/password login as additional auth mechanism alongside existing token
- First login must use token; password can be configured in Settings > Account
- Password login returns the existing static token (no auth middleware changes)
- Add account settings: setup, change password, change username, remove password
- Add logout button to sidebar footer
- Add version changelog popup (click version number in sidebar)
- Support all 8 locales (en, zh, de, es, fr, ja, ko, pt)
- Bump version to 0.4.3

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-22 20:27:33 +08:00
ekko 6f69c69802 feat: add token usage tracking, context display, and dynamic context length (#132)
* 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>
2026-04-22 16:14:50 +08:00
ekko ce3bf5f3eb fix: specify TS_NODE_PROJECT for dev:server script (#129)
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>
2026-04-22 14:03:59 +08:00
cl1107 f27db3036a feat: add session search modal (#128) 2026-04-22 14:00:34 +08:00
Zhicheng Han ffd825afe2 fix: keep self-update on the active install path (#123) 2026-04-22 10:33:38 +08:00
ekko 42a5e4052a chore: bump version to 0.4.2-beta.1 and improve chat UX (#122)
* 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>
v0.4.2
2026-04-22 08:47:44 +08:00
Zhicheng Han 3f88553765 feat(web-ui): add pinned sessions and live monitor in Chat (#118)
* 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>
2026-04-22 08:09:58 +08:00
ekko 83ad9642e2 fix(models): fix builtin provider detection and model matching (#120)
- Add glm-coding-plan to PROVIDER_ENV_MAP for proper env mapping
- Rename GLMCodingPlan value from 'glm' to 'glm-coding-plan' (kebab-case)
- Match custom providers against PROVIDER_PRESETS to reuse builtin models
- Fix provider key matching in create/update (use entry.name consistently)
- Clear stale base_url/api_key from config on provider create
- Clear model config when all providers are removed
- Add gateway restart on provider remove

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-22 00:11:39 +08:00
ekko c4bea63a5e docs: update CLAUDE.md to reflect current project architecture (#115)
Sync CLAUDE.md with actual codebase structure:
- Add controller layer (thin-router, fat-controller pattern)
- Fix service paths (services/hermes/hermes-cli.ts)
- Document 8 locales, Vitest testing, esbuild bundling
- Add new modules: composables, profiles, gateways, codex-auth
- Fix route registration (routes/index.ts, not routes/hermes/index.ts)
- Add missing env vars (UPLOAD_DIR, CORS_ORIGINS, HERMES_BIN)
- Update bootstrap sequence and auth middleware docs

Also change docker-publish workflow to manual trigger only,
and remove dev branch from build workflow trigger.

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-21 19:39:02 +08:00
ekko 81dad4c939 fix(docker): use if/else to map amd64 to x64 for Node.js download (#110)
dpkg returns 'amd64' but nodejs.org uses 'x64' in tarball filenames.
Shell substitution may not work in all shells, use explicit if/else.

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-21 16:11:40 +08:00
ekko fd02c01148 fix(docker): map amd64 to x64 for Node.js download URL (#109)
dpkg returns 'amd64' but nodejs.org uses 'x64' in tarball filenames.
Without this mapping, AMD64 builds fail with curl 404.

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-21 15:59:51 +08:00
ekko ed1f7d8301 fix(docker): split RUN steps to fix Node.js install on multi-platform build (#108)
Separate apt-get install from Node.js download into two RUN layers.
The piped curl|tar command fails with 404 when ca-certificates from
apt layer is not yet available during parallel multi-platform build.

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-21 15:36:47 +08:00
ekko 832029a5b3 fix(docker): use tar.gz instead of tar.xz for Node.js binary (#107)
xz-utils is not available in the base image, causing ARM64 build to
fail with "File format not recognized".

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-21 15:21:28 +08:00
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>
v0.4.1
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