Commit Graph

17 Commits

Author SHA1 Message Date
ekko 53dbe4b2b5 chore: update FUN-Codex and FUN-Claude provider models (#522)
FUN-Codex: add GPT models (5.5, 5.4, 5.4-mini, 5.3-codex, 5.3-codex-spark)
FUN-Claude: replace with actual Claude models from API (opus-4-7 down to 3-5-haiku)

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-07 22:16:52 +08:00
ekko df57f982f8 feat: add Xiaomi Token Plan provider and update MiMo models (#376)
Add new Xiaomi Token Plan provider with updated model catalog and refresh existing Xiaomi MiMo provider models to match actual API response.

Changes:
- Add new Xiaomi Token Plan provider (base_url: https://token-plan-sgp.xiaomimimo.com/v1)
- Update Xiaomi MiMo provider models: remove mimo-v2-flash, add v2.5 series and TTS variants
- Add environment variable mapping for xiaomi-token-plan provider

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-01 15:57:41 +08:00
TOM ed147d378d Add CLIProxyAPI provider support (#375) 2026-05-01 15:46:08 +08:00
ekko cd14bb1963 feat: add Anthropic format conversion for chat runs and improvements (#347)
* fix: improve chat compression and tool display

Context Compression Fixes:
- Remove duplicate token calculation in compress()
- Simplify compress() to only execute compression, not judge
- Add buildConversationHistory() to preserve tool calls in LLM context
- Remove unused estimateMessagesTokens() and contextLength parameter
- Move all judgment logic to chat-run-socket.ts (uses accurate DB tokens)

Tool Call Display Improvements:
- Add tool execution duration display (format: 1.272s)
- Add success/error status icons with circular backgrounds
- Replace text error with SVG icon (X in red circle)
- Replace old checkmark with polished green checkmark icon
- Add i18n key 'chat.executionDuration' for all locales

Bug Fixes:
- Fix streaming-indicator stuck by adding try-finally in handleEvent
- Add debug logging for compression flow diagnosis
- Fix template syntax error in MessageList.vue

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

* feat(chat): convert conversation history to Anthropic format before sending to Gateway

- Add convertToAnthropicFormat() to transform OpenAI format to Anthropic format
- Handle DeepSeek reasoning_content in thinking blocks
- Properly convert tool_use and tool_result blocks
- Add convertFromAnthropicFormat() for parsing SSE responses
- Handle stringified Python arrays in resume messages
- Record debug history files for troubleshooting (original vs converted)
- Fix tool_call_id validation to prevent empty ID errors
- Clean internal Hermes fields (call_id, response_item_id) from tool_calls

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

* fix(chat): optimize message parsing and add debug logging

- Only check for stringified arrays in assistant messages (performance)
- Improve parsing error handling: keep original content on parse failure
- Add debug logging for upstream events (reasoning/thinking tracking)
- Log run.completed event keys for troubleshooting

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

* feat(chat): add message pagination and reasoning sync improvements

**Message Pagination:**
- Add getSessionDetailPaginated() for paginated message loading
- Query with DESC order then reverse in code for optimal performance
- Remove listSessionsPaginated() (not needed)

**Reasoning Sync:**
- Add bidirectional reasoning merge in syncFromHermes
  - Memory → DB: preserve streamed reasoning from SSE events
  - DB → Memory: restore reasoning if Hermes Gateway fixes storage
- Send resumed event after sync completes with complete messages
- Fix reasoning field inconsistency: use unified 'reasoning' field

**Message Parsing:**
- Only parse stringified arrays for assistant messages (performance)
- Improve parse error handling: keep original content on failure
- Add debug logging for upstream reasoning/thinking events

**Bug Fixes:**
- Fix reasoning content display: now works on both SSE and resume
- Ensure reasoning is preserved across page refreshes via sync + resumed event

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

* fix: increase default pagination limit for messages to 500

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

* fix: remove auto-resumed event trigger and clean up debug code

- Remove automatic resumed event trigger in syncFromHermes to avoid timing issues
- Clean up unused imports (fs, join)
- Remove debug history file logging code
- Fix socket parameter passing in handleAbort, markCompleted, and syncFromHermes
- Change usage emit from room broadcast to socket-only emit
- Remove console.log debug statement

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

* fix: use reasoning field in convertToAnthropicFormat

Change convertToAnthropicFormat to read from reasoning field instead
of reasoning_content for consistency with database schema and frontend.

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

* feat: parse stringified array content and improve logs

- Parse stringified array format in run.completed to extract thinking/text/tool_use
- Send parsed content to frontend via parsed_content/parsed_reasoning/parsed_tool_calls
- Frontend updates last assistant message with parsed content
- Remove ellipsis from log messages, show full content
- Add detailed logging for conversion and parsing

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

* fix: move finalOutputTrimmed outside else block

* fix(chat): handle double-serialized content in resumeSession

- Remove outer quotes before parsing stringified array format
- Updated changelog for v0.5.2 and v0.5.3 with multilingual support
- Fixed message pagination with DESC query + array reverse

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

* fix(chat): improve error logging for resume parsing

- Add detailed logging for double-serialized content parsing
- Log content preview when parsing fails to diagnose issues

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

* revert(chat): use simple Python-to-JSON replacement

- Revert to simple .replace(/'/g, '"') approach
- Parsing failures will keep original content as-is

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

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-30 16:40:37 +08:00
ekko 0051092216 fix: improve model list layout in ProviderCard (#311)
* fix: add LongCat provider, OpenRouter free models, model list in cards

- Add longcat to PROVIDER_ENV_MAP and PROVIDER_PRESETS
- Add freeOnly param to fetchProviderModels, use for OpenRouter
- Show model list in ProviderCard with count
- Fix qq.ts import.meta.url → __dirname for CJS compat
- Add zh/en i18n keys for model count display

* fix: improve model list layout in ProviderCard

- Change models-list from max-height to fixed height (100px)
- Add align-content: flex-start to prevent vertical spacing
- Optimize gap to 4px vertical, 6px horizontal
- Fix model-tag height to 20px to prevent background stretching
- Use inline-flex for better tag alignment

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

---------

Co-authored-by: idle888 <546806917@qq.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-29 20:48:21 +08:00
ww 610f3eb9d0 feat(copilot): integrate GitHub Copilot provider with dynamic model list / 集成 GitHub Copilot provider 与动态模型列表 (#239)
* feat(copilot): integrate GitHub Copilot provider with dynamic model list

集成 GitHub Copilot provider 与动态模型列表

EN:
- New copilot-models service: fetch live model list from GitHub /models API
  - Filter noise IDs (accounts/, text-embedding, rerank prefixes)
  - Pass through preview/disabled metadata to frontend
  - Cache isolated per OAuth token (FNV-1a hash key) to prevent cross-account leak
  - Multi-source token resolution: env > apps.json > gh CLI
- ModelSelector renders PREVIEW (orange) and UNAVAILABLE (gray, non-selectable)
  badges with tooltips
- ProviderFormModal exposes Copilot OAuth login entry
- New CopilotLoginModal component: guides gh auth login device flow
- ProviderCard hides delete button for OAuth-only builtin providers
  (copilot/codex/nous) since their credentials live outside auth.json

ZH:
- 新增 copilot-models 服务:从 GitHub /models live API 拉取模型列表
  - 噪音 ID 过滤(accounts/、text-embedding、rerank 前缀)
  - preview/disabled 元数据透传至前端
  - 缓存按 OAuth token 隔离(FNV-1a hash key),避免切换 profile 串账号
  - 多源 token 解析优先级:env > apps.json > gh CLI
- ModelSelector 渲染 PREVIEW(橙色)/ UNAVAILABLE(灰色、不可选)badge,附 tooltip
- ProviderFormModal 提供 Copilot OAuth 登录入口
- 新增 CopilotLoginModal 组件:引导 gh auth login 设备流程
- ProviderCard 对 OAuth-only builtin(copilot/codex/nous)隐藏删除按钮
  其凭证不在 auth.json,删除按钮原本无效

Tests / 测试: new copilot-models suite (cache isolation, noise filter,
preview/disabled passthrough) + copilot-login-modal — 24/24 passed.
Pre-existing sessions-db-lineage failure on upstream/main is unrelated.

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

* refactor(copilot): switch to explicit opt-in per maintainer feedback

回应 PR #239 review:上一版会自动把系统级 GitHub OAuth 凭证(VS Code Copilot
插件、gh CLI 登录态)当作 hermes provider 拉到列表里,对未在 hermes 中注册过
Copilot 的用户造成困扰。本次改为显式 opt-in:用户必须通过 Add Provider 主动添加,
删除时按 token 来源决定是否清 ~/.hermes/.env,并避免误清理 VS Code / gh CLI 用户的
全局凭证。

Address PR #239 review feedback. Previously Copilot would silently appear in the
provider list whenever the host had any GitHub OAuth token (VS Code plugin, gh CLI
login). This caused confusion for users who never explicitly registered Copilot
in hermes. Now Copilot requires explicit opt-in via Add Provider; on delete we only
clear ~/.hermes/.env when the token actually originated there, leaving VS Code /
gh CLI credentials untouched.

What changed
- 新增 ~/.hermes-web-ui/config.json 的 copilotEnabled flag 控制可见性
- 即便能解析到 token,未启用时也不在列表中显示
- resolveCopilotOAuthTokenWithSource 区分 token 来源(env / gh-cli / apps-json)
- ProviderFormModal 增加 GitHub Copilot 入口;无 token 时进 device flow modal
- CopilotLoginModal 重写为 in-app device flow 状态机(不再要求用户在终端跑 gh)
- 删除 Copilot 时仅 source='env' 才清 ~/.hermes/.env,并自动 fallback 默认模型
- 老用户升级兼容:若 default 仍指向已禁用的 copilot,后端清空 default 让前端兜底

API
- POST /api/hermes/copilot-auth/check-token
- POST /api/hermes/copilot-auth/enable
- POST /api/hermes/copilot-auth/disable
- POST /api/hermes/copilot-auth/start  (device flow)
- POST /api/hermes/copilot-auth/poll   (device flow)

Tests
- tests/server/copilot-auth-controller.test.ts (11 cases)
- tests/server/copilot-device-flow.test.ts (12 cases)
- tests/client/copilot-login-modal.test.ts 重写覆盖状态机

Follow-ups (留作后续 PR)
- device flow session 未绑定 profile,登录中切 profile 会写到错的 .env
- copilot device-code 接口的 expires_in 字段未使用,硬编码 15 分钟超时

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

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-26 22:51:35 +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
Zhicheng Han 30e88797ef fix: add gpt-5.5 to OpenAI Codex models (#175) 2026-04-24 10:11:21 +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
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 477af66232 fix: auth bypass, SPA serving, and provider improvements (#97)
* feat(chat): polish syntax highlighting and tool payload rendering (#94)

* [verified] feat(chat): polish syntax highlighting and tool payload rendering

* [verified] fix(chat): tighten large tool payload rendering

* docs: update data volume path in Docker docs

Align documentation with docker-compose.yml change:
hermes-web-ui-data -> hermes-web-ui, /app/dist/data -> /root/.hermes-web-ui

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

* refactor: bundle server build and restructure service modules

- Add build-server.mjs script for standalone server compilation
- Add logger service with structured output
- Restructure auth, gateway-manager, hermes-cli, hermes services
- Update docker-compose volume mount path
- Update tsconfig and entry point for bundled server

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

* refactor: separate controllers from routes and centralize route registration

- Extract business logic from route handlers into controllers/
- Add centralized route registry in routes/index.ts with public/auth/protected layers
- Replace global auth whitelist with sequential middleware registration
- Extract shared helpers to services/config-helpers.ts
- Allow custom provider name to be user-editable in ProviderFormModal
- Deduplicate custom providers by poolKey instead of base_url in getAvailable

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

* fix: auth bypass via path case, SPA serving, and provider improvements

- Fix auth bypass: path case-insensitive check for /api, /v1, /upload
- Fix SPA returning 401: skip auth for non-API paths (static files)
- Fix profile switch: use local loading state instead of shared store ref
- Auto-append /v1 to base_url when fetching models (frontend + backend)
- Guard .env writing to built-in providers only
- Add builtin field to provider presets, enable base_url input in form
- Print auth token to console on startup (pino only writes to file)

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

---------

Co-authored-by: Zhicheng Han <43314240+hanzckernel@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-21 12:35:48 +08:00
ekko 562261d13f feat: multi-gateway profile support, provider management overhaul, and model settings tab
- Profile-aware proxy: inject API key from profile-specific .env, route requests via X-Hermes-Profile header
- Remove auth.json dependency: built-in providers use .env, custom providers use config.yaml
- Add allProviders field to available-models response with all hardcoded provider catalogs
- Add Models tab in Settings for editing provider API keys (built-in → .env, custom → config.yaml)
- Add PUT /api/config/providers/:poolKey for updating provider credentials
- ProviderFormModal uses backend allProviders for preset dropdown
- Gateway log format support: parse both agent and gateway log formats
- Add webui server.log to log viewer with log rotation at 3MB
- Fix provider delete loading state and OAuth provider cleanup
- Setup script: require Node.js 23+, auto-upgrade if version too low

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-19 20:59:25 +08:00
ekko 9979871550 feat: add Codex OAuth login and fix channel config display
- Add OpenAI Codex Device Code Flow login (backend polling + frontend modal)
- Codex provider integrated into preset dropdown (hides URL/API key fields)
- Sync provider model catalogs with Hermes system
- Fix channel config not displaying on first visit (wait for data load)
- Fix sidebar model list not refreshing after adding provider
- Add autocomplete="off" to API key input to prevent browser autofill

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-17 23:11:57 +08:00
ekko 26bb821e29 feat: support manual model input and sync provider catalogs
- Allow manual model name input when adding custom providers (NSelect tag mode)
- Sync provider model catalogs with Hermes _PROVIDER_MODELS
- Add new providers: kimi-coding-cn, moonshot, arcee
- Fix provider key naming to match Hermes (kilo→kilocode, vercel→ai-gateway, etc.)
- Ensure custom_providers from config.yaml always appear in available-models
- Append configured default model to model list if not in catalog
- Fix provider deletion with case-insensitive key matching
- Add selectOrInput i18n key to all 8 locales

Closes #24

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-17 22:05:06 +08:00
ekko 9a0b50f370 fix: add MiniMax highspeed variants and deduplicate model list
- Add MiniMax-M2.7/M2.5/M2.1/M2 -highspeed variants for both
  international and China providers (#17)
- Deduplicate models in /available-models response to fix
  repeated entries when using Copilot or other providers (#18)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-17 12:04:20 +08:00
ekko 99a47cf1ad feat: profile-aware routes, provider sync, channel settings improvements
- Add hermes-profile.ts for dynamic profile path resolution (all backend
  routes now read from active profile directory instead of hardcoded ~/.hermes/)
- Add profile switcher dropdown in sidebar, reload page on switch
- Sync PROVIDER_PRESETS with Hermes CLI (fix keys: kimi-coding→kimi-for-coding,
  kilocode→kilo, ai-gateway→vercel, opencode-zen→opencode; remove moonshot)
- Sync PROVIDER_ENV_MAP with Hermes models.dev + overlays (correct env var names)
- Add gateway restart after adding model provider
- Don't write GLM_BASE_URL/KIMI_BASE_URL for zai/kimi (let Hermes auto-detect)
- Write API keys to .env and credential_pool for all providers
- Built-in providers skip custom_providers in config.yaml
- Add debounce + per-field loading state for channel settings inputs
- Run hermes setup --reset for profiles without config.yaml
- Create empty .env for new profiles (not copied from default)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-16 13:51:42 +08:00
ekko 351c861777 refactor: restructure project for multi-agent extensibility
- Migrate source to packages/client and packages/server directories
- Namespace all Hermes-specific code under hermes/ subdirectories
  (api/hermes/, components/hermes/, views/hermes/, stores/hermes/)
- Add hermes.* route names and /hermes/* path prefixes
- Upgrade @koa/router to v15, adapt path-to-regexp v8 syntax
- Fix proxy path rewriting: /api/hermes/v1/* → /v1/*, /api/hermes/* → /api/*
- Fix frontend API paths to match backend /api/hermes/* routes
- Fix WebSocket terminal path to /api/hermes/terminal
- Add proxyMiddleware for reliable unmatched route proxying
- Add profiles route module and hermes-cli profile commands
- Update CLAUDE.md development guide with new architecture
- Add Chinese README (README_zh.md)
- Add Web Terminal feature to README

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-16 08:38:18 +08:00