Commit Graph

189 Commits

Author SHA1 Message Date
diegosouzapw
2f765529e5 Merge PR #851: feat(logging): unify request log retention and artifacts 2026-03-31 09:11:57 -03:00
diegosouzapw
56ef849868 Merge PR #850: test: add unit and E2E tests for settings toggles 2026-03-31 09:11:11 -03:00
diegosouzapw
2a0c4d2b0d Merge PR #853: fix(model-sync): log only real channel model changes 2026-03-31 09:11:10 -03:00
diegosouzapw
f695559379 Merge PR #856: fix: preserve client cache_control for all Claude-protocol providers 2026-03-31 09:11:02 -03:00
diegosouzapw
3fa7828324 Merge PR #859: fix(429): parse long quota reset times from error body 2026-03-31 09:10:56 -03:00
oyi77
a405f2e81e fix(429): parse long quota reset times from error body
- Parse XhYmZs format from antigravity error messages (e.g., 27h41m36s)
- Dynamic retry-after threshold (60s default) instead of hardcoded 10s
- Add parseRetryFromErrorText() in accountFallback.ts for body parsing
- Fix 403 'verify your account' to trigger permanent deactivation
- Add keyword matching for 'quota will reset', 'exhausted capacity'
- Add unit tests for retry parsing and keyword matching

Fixes #858 (Antigravity 429 handling)
Fixes #832 (Qwen quota 429 - same underlying bug)
2026-03-31 17:59:54 +07:00
diegosouzapw
afc0bc9323 fix: resolve CLI detection regression and model catalog tests 2026-03-31 07:57:43 -03:00
tombii
75425ab1a9 fix: preserve client cache_control for all Claude-protocol providers
Previously, the cache control preservation logic only recognized a
hardcoded list of providers (claude, anthropic, zai, qwen, deepseek).
This caused OmniRoute to inject its own cache_control markers for
Claude-protocol providers not in that list (bailian-coding-plan, glm,
minimax, minimax-cn, etc.), overwriting the client's cache markers.

The fix checks both:
1. Known caching providers list (existing behavior)
2. Whether targetFormat === 'claude' (all Claude-protocol providers)

This ensures all Claude-compatible providers properly preserve client
cache_control headers when appropriate (Claude Code client, deterministic
routing, etc.).

Also removes unused CacheStatsCard from settings/components (duplicate
of the one in cache/ page).

Fixes cache token calculation for GLM, Minimax, and other Claude-compatible providers.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-31 11:17:05 +02:00
R.D.
715101cf5e fix(model-sync): log only channel-level model changes 2026-03-31 00:44:38 -04:00
R.D.
f8d4e1a307 feat(logging): unify request log retention and artifacts 2026-03-31 00:19:55 -04:00
oyi77
b98d6984a1 fix(tests): address code review issues
- Unit tests: fix async/await for getSettings, use direct db functions
- E2E tests: remove conditional logic, use Playwright auto-waiting assertions
2026-03-31 11:15:54 +07:00
oyi77
8f5c9a3c72 test(e2e): add Playwright tests for settings toggles
Tests cover:
- Debug mode toggle on/off
- Sidebar visibility toggle
- Settings persistence after page reload
2026-03-31 10:54:07 +07:00
Owen
9227964cb6 feat(analytics): add subscription utilization analytics (#847)
- Add quota_snapshots table for time-series quota tracking
- Add QuotaSnapshot DB module with CRUD + cleanup (6h gate)
- Add snapshot save hook in quotaCache.setQuotaCache()
- Add Provider Utilization API: GET /api/usage/utilization
- Add Combo Health API: GET /api/usage/combo-health
- Add ProviderUtilizationTab with recharts LineChart
- Add ComboHealthTab with quota/skew/performance metrics
- Add TimeRangeSelector component (1h/24h/7d/30d)
- Integrate tabs into /dashboard/analytics
- Add unit tests for quotaSnapshots module
- Add E2E tests for analytics tabs
- Add i18n keys for 33 languages
2026-03-31 00:12:27 -03:00
diegosouzapw
49e1d51be9 chore(release): v3.3.8 2026-03-30 20:54:02 -03:00
diegosouzapw
23e47a74ee Merge remote main 2026-03-30 20:48:25 -03:00
Diego Rodrigues de Sa e Souza
fce7f6ce47 Merge pull request #830 from rdself/coder/fix-openrouter-available-models
fix: align OpenRouter auto-sync with available models
2026-03-30 20:47:59 -03:00
diegosouzapw
28123355b4 Merge branch 'feat/issue-660-qoder' into main
# Conflicts:
#	docs/i18n/ar/README.md
#	docs/i18n/bg/README.md
#	docs/i18n/da/README.md
#	docs/i18n/de/README.md
#	docs/i18n/es/README.md
#	docs/i18n/fi/README.md
#	docs/i18n/fr/README.md
#	docs/i18n/he/README.md
#	docs/i18n/hu/README.md
#	docs/i18n/id/README.md
#	docs/i18n/in/README.md
#	docs/i18n/it/README.md
#	docs/i18n/ja/README.md
#	docs/i18n/ko/README.md
#	docs/i18n/ms/README.md
#	docs/i18n/nl/README.md
#	docs/i18n/no/README.md
#	docs/i18n/phi/README.md
#	docs/i18n/pl/README.md
#	docs/i18n/pt-BR/README.md
#	docs/i18n/pt/README.md
#	docs/i18n/ro/README.md
#	docs/i18n/ru/README.md
#	docs/i18n/sk/README.md
#	docs/i18n/sv/README.md
#	docs/i18n/th/README.md
#	docs/i18n/uk-UA/README.md
#	docs/i18n/vi/README.md
#	docs/i18n/zh-CN/README.md
2026-03-30 20:39:31 -03:00
oyi77
981c1c1263 test(settings): add unit tests for debugMode and hiddenSidebarItems
Tests cover:
- PATCH debugMode=true/false
- PATCH hiddenSidebarItems with array values
- Combined updates with both fields
2026-03-31 05:54:48 +07:00
diegosouzapw
3591a3fe5c fix: resolve opencode json structure to use record mapping instead of array (#816) 2026-03-30 19:23:25 -03:00
diegosouzapw
76e135077b Resolve merge conflicts with main natively built Prompt Cache UI 2026-03-30 18:20:19 -03:00
Diego Rodrigues de Sa e Souza
6078cd2eab Merge pull request #829 from rdself/coder/fix-cloudflared-startup
Fix cloudflared quick tunnel startup in Docker
2026-03-30 18:18:03 -03:00
R.D.
ff73de5716 fix openrouter available models sync 2026-03-30 17:07:46 -04:00
R.D.
ba227c5ec3 Run combo health probes concurrently 2026-03-30 16:49:01 -04:00
R.D.
b492c5ac1a Fix cloudflared startup TLS handling 2026-03-30 16:31:07 -04:00
R.D.
03a860dd6f Fix combo smoke tests for reasoning responses 2026-03-30 16:23:53 -04:00
tombii
007b5d7f50 fix(test): split CacheStatsCard check into cache page test
Integration test was failing because CacheStatsCard was moved from
settings page to cache page in previous commit. Split the test into
two separate describe blocks for accurate page-specific verification.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-30 19:49:57 +02:00
Diego Rodrigues de Sa e Souza
db3753d611 Merge PR 811: fix UI fallbacks and Electron release workflow
fix: UI fallbacks and Electron release workflow
2026-03-30 11:04:02 -03:00
diegosouzapw
5ad687c6d8 fix(ui/ci): use ProviderIcon for Provider header breadcrumbs and add permissions to electron-release.yml (#745, #761)
- Use ProviderIcon for internal .png paths solving SVG provider 404 images (#745).
- Add id-token: write and packages: write permissions to .github/workflows/electron-release.yml to fix permissions denied failure when calling the reusable workflow npm-publish.yml (#761).
- Fix tests and ESM resolution for autoUpdate.ts override logic.
2026-03-30 07:38:30 -03:00
R.D.
179c03e79d Isolate cloudflared runtime environment 2026-03-29 22:30:07 -04:00
Diego Rodrigues de Sa e Souza
7837fcc657 Merge pull request #772 from rdself/coder/cloudflared-tunnel-endpoint
Add Cloudflare Quick Tunnel controls to endpoint page
2026-03-29 19:37:03 -03:00
Diego Rodrigues de Sa e Souza
f9690d40d3 Merge pull request #778 from christopher-s/glm-coding-audit
feat: GLM Coding provider enhancements and fixes
2026-03-29 19:36:52 -03:00
Diego Rodrigues de Sa e Souza
5de6cd77dc Merge pull request #773 from rdself/codex/fix-combo-live-test-no-cache
Bypass semantic cache in combo live tests
2026-03-29 19:36:40 -03:00
Diego Rodrigues de Sa e Souza
aa5ab55b14 Merge pull request #777 from diegosouzapw/release/v3.3.1
chore(release): v3.3.1 — bug fixes and schema adjustments
2026-03-29 19:36:11 -03:00
Chris Staley
fe3f9c86d5 fix: use GLM Coding API endpoints for model import with region-aware URLs
The "Import from /models" button was using the wrong Z.AI API surface
(Anthropic-compatible /api/anthropic/v1/models with x-api-key auth).
Switched to the correct Coding API endpoints with Authorization: Bearer
auth, matching the pattern used by the quota/usage tracking code.

- International: https://api.z.ai/api/coding/paas/v4/models
- China: https://open.bigmodel.cn/api/coding/paas/v4/models
- Auth: Authorization: Bearer <token> (not x-api-key)
- Region sourced from providerSpecificData.apiRegion

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-29 15:13:07 -06:00
diegosouzapw
6e9c97fbff chore(release): v3.3.1 — bug fixes and schema adjustments 2026-03-29 16:39:10 -03:00
mikhailsal
370070f489 fix(stream): normalize delta.reasoning alias and separate reasoning in client response (#771)
* fix(stream): normalize delta.reasoning to reasoning_content in SSE streaming

NVIDIA kimi-k2.5 (and potentially other providers) send reasoning
tokens as `delta.reasoning` in SSE streaming chunks instead of the
standard OpenAI `delta.reasoning_content` field. This caused reasoning
content to be silently dropped during stream passthrough — clients
received only the final answer with no reasoning separation.

The non-streaming sanitizer (responseSanitizer.ts) already handled this
alias, but the streaming pipeline did not.

Fix applied in 4 locations:
- stream.ts passthrough: normalize + force re-serialize sanitized chunk
- stream.ts translate: accumulate reasoning from delta.reasoning
- sseParser.ts: collect delta.reasoning in parseSSEToOpenAIResponse
- streamPayloadCollector.ts: collect delta.reasoning in buildOpenAISummary

* fix: eliminate injectedUsage reuse bug and add reasoning alias tests

- Detect delta.reasoning alias before sanitizeStreamingChunk() which
  already normalizes it, removing dead post-sanitization normalization
- Replace injectedUsage reuse with separate needsReserialization flag
  so reasoning re-serialization cannot block finish_reason/usage
  mutations on the same SSE chunk (fixes CRITICAL review finding)
- Add unit test for parseSSEToOpenAIResponse reasoning alias
- Add unit test for buildStreamSummaryFromEvents reasoning alias

* fix(stream): separate reasoning from content in passthrough response body

The passthroughAccumulatedContent variable was mixing delta.content and
delta.reasoning_content into one string, causing the client_response
log and responseBody to lose reasoning separation.

- Add passthroughAccumulatedReasoning accumulator for reasoning deltas
- Set message.reasoning_content in responseBody when reasoning exists
- Only accumulate delta.content into passthroughAccumulatedContent

* fix: trim leading whitespace from assembled content in log summaries

NVIDIA and other providers emit token deltas with leading spaces
(e.g. ' The', ' user'). When joined, these produce a leading space in
the provider_response and parsed non-streaming response logs. Trim
the joined content and reasoning_content in both buildOpenAISummary
and parseSSEToOpenAIResponse for consistent log output.

* fix(stream): split combined reasoning+content deltas into separate SSE events

Some providers (e.g. NVIDIA NIM) send transition chunks with both
`delta.reasoning` and `delta.content` in the same SSE event.
After sanitization this becomes `reasoning_content` + `content`,
which violates the standard OpenAI streaming contract where these
fields are never mixed. Clients using if/else logic (LobeChat, etc.)
skip content when reasoning_content is present, losing the first
content token.

Split such combined chunks into two separate SSE events:
1. Reasoning-only event (finish_reason=null, no usage)
2. Content-only event (carries finish_reason and usage)
2026-03-29 16:12:22 -03:00
R.D.
cf36972969 Harden cloudflared child process environment 2026-03-29 14:25:07 -04:00
R.D.
40862f26e6 Bypass semantic cache in combo live tests 2026-03-29 14:21:39 -04:00
R.D.
3cb34ad827 Add Cloudflare Quick Tunnel controls to endpoint page 2026-03-29 14:04:50 -04:00
diegosouzapw
6fad06f659 chore(release): v3.3.0 — test stability, release consolidation 2026-03-29 14:22:25 -03:00
diegosouzapw
1d51d8ff27 chore(release): v3.2.9 — combo diagnostics, quality gates, Gemini tool fix 2026-03-29 14:16:37 -03:00
Randi
8af9bd1ac3 Force real upstream combo live tests (#759) 2026-03-29 13:21:53 -03:00
Diego Rodrigues de Sa e Souza
46acd16999 chore(release): v3.2.8 — Docker Auto-Update & Analytics Fixes (#755)
* chore(release): v3.2.8 — Docker auto-update UI and cache analytics fixes

* fix(sse): remove race condition in cache metrics tracking (#758)

- Remove in-memory metrics tracking (currentMetrics, trackCacheMetrics, updateCacheMetrics)
- Cache metrics now computed on-the-fly from usage_history table (single source of truth)
- Fixes CRITICAL issue from code review: concurrent requests overwriting metrics
- Fixes WARNING: duplicate metric tracking logic in streaming/non-streaming paths

Ref: PR #752 (merged before this fix was included)

* fix: handle allRateLimited credentials & forward extra body keys in embeddings/images routes (#757)

* fix: handle allRateLimited credentials in embeddings and images routes

When getProviderCredentials() returns an allRateLimited object (truthy,
but without apiKey/accessToken), the embeddings and images routes
incorrectly passed it to handlers as valid credentials. The handlers
then sent upstream requests without Authorization headers, causing
401 errors from providers (e.g. NVIDIA NIM).

This only manifested under concurrent requests: a chat/completions
call could trigger rate limiting on a provider account, and a
simultaneous embeddings request would receive the allRateLimited
sentinel — but treat it as valid credentials.

The chat pipeline already handled this case correctly. This commit
adds the same allRateLimited guard to all affected routes:
- POST /v1/embeddings
- POST /v1/providers/{provider}/embeddings
- POST /v1/images/generations
- POST /v1/providers/{provider}/images/generations

Also adds a defense-in-depth guard in the embeddings handler itself:
if no auth token is available for a non-local provider, return 401
immediately instead of sending an unauthenticated request upstream.

Made-with: Cursor

* fix(embeddings): forward extra body keys to upstream providers

The embeddings handler only forwarded model, input, dimensions, and
encoding_format to upstream providers, silently dropping any additional
fields. This broke asymmetric embedding APIs (e.g. NVIDIA NIM
nv-embedqa-e5-v5) that require input_type, and other providers
expecting user or truncate parameters.

Add a KNOWN_FIELDS exclusion set and forward all unrecognized body
keys to the upstream request, matching the passthrough pattern used
by the chat pipeline's DefaultExecutor.transformRequest().

Made-with: Cursor

* fix(auth): redirect and unconditional 401 on disabled requireLogin + fix test cases

* fix(build): remove legacy proxy.ts causing Next.js build collision

* fix(build): revert middleware.ts rename to proxy.ts because of Next.js Edge constraints

---------

Co-authored-by: diegosouzapw <diegosouzapw@users.noreply.github.com>
Co-authored-by: tombii <tombii@users.noreply.github.com>
Co-authored-by: Gorchakov-Pressure <117600961+Gorchakov-Pressure@users.noreply.github.com>
2026-03-29 13:09:38 -03:00
diegosouzapw
5ad2c6abf6 Fix merge conflicts 2026-03-29 11:26:17 -03:00
Diego Rodrigues de Sa e Souza
d5781d60bd Merge pull request #752 from tombii/feat/preserve-client-cache-control
feat: preserve client cache_control with deterministic routing + metrics dashboard
2026-03-29 11:23:22 -03:00
Diego Rodrigues de Sa e Souza
e464a95c5a Merge pull request #747 from AveryanAlex/fix/responses-chat-translation-bugs
Improve responses<->chat translation
2026-03-29 11:23:19 -03:00
tombii
319018f055 test: fix cache metrics tests with usage_history table
- Add usage_history table creation in test setup
- Simplify byStrategy query to avoid non-existent combo_strategy column
- Update test assertions to work with existing test data
2026-03-29 16:05:32 +02:00
tombii
26f7b36ce4 feat: add cache control settings and token-based metrics
Settings:
- Add `alwaysPreserveClientCache` setting with modes: auto/always/never
- UI toggle in Dashboard > Settings > Routing tab
- Auto mode preserves cache_control for Claude Code clients with deterministic routing

Metrics:
- Track prompt cache token usage (input, cached, creation)
- Display cache reuse ratio (cached/input tokens)
- Breakdown by provider and routing strategy
- Shows tokens saved and estimated cost savings

API Endpoints:
- GET /api/settings/cache-metrics - retrieve metrics
- DELETE /api/settings/cache-metrics - reset metrics

Files:
- open-sse/utils/cacheControlPolicy.ts: CacheControlMetrics interface, trackCacheMetrics, updateCacheTokenMetrics
- open-sse/handlers/chatCore.ts: Track cache tokens from provider responses
- src/lib/db/settings.ts: Database functions for metrics persistence
- src/lib/cacheControlSettings.ts: Cached settings accessor
- src/app/(dashboard)/dashboard/settings/components/CacheStatsCard.tsx: Metrics dashboard UI
- tests/unit/*.test.mjs: Unit tests (41 tests pass)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-29 14:37:55 +02:00
cai kerui
f0daad10ce Add Docker-aware dashboard auto-update flow 2026-03-29 20:25:14 +09:00
tombii
0bc557fb8b feat(sse): preserve client cache_control for Claude Code with deterministic routing
Adds intelligent cache control preservation for Claude Code clients:

- New cacheControlPolicy.ts module with detection logic:
  - isClaudeCodeClient(): Detects Claude Code via User-Agent
  - providerSupportsCaching(): Checks provider (claude, anthropic, zai, qwen)
  - isDeterministicStrategy(): Identifies priority/cost-optimized strategies
  - shouldPreserveCacheControl(): Main policy decision

- Cache control is preserved when:
  1. Client is Claude Code (detected via User-Agent)
  2. Provider supports prompt caching
  3. Request routing is deterministic:
     - Single model requests (always)
     - Combo with priority or cost-optimized strategy only

- Updated translator to accept preserveCacheControl option
- Updated chatCore and chat handler to propagate combo strategy
- Added comprehensive unit tests (24 tests)

Non-deterministic combo strategies (weighted, round-robin, random, etc.)
continue to use OmniRoute's managed caching strategy.

Refs: #cache-control-preservation
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-29 12:24:44 +02:00