Commit Graph

61 Commits

Author SHA1 Message Date
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
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 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
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
cl1107 f27db3036a feat: add session search modal (#128) 2026-04-22 14:00:34 +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 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