Replace stub getGeminiUsage() with per-model quota fetching from Google
Cloud Code Assist's retrieveUserQuota endpoint (same API the official
Gemini CLI /stats command uses). Fixes OAuth env var name, aligns model
list with official Gemini CLI VALID_GEMINI_MODELS, and makes "Import
from /models" discover new models via the quota endpoint.
- 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.
* feat: auto-disable banned accounts setting with UI toggle
Add a configurable setting to automatically disable provider accounts
that return permanent/terminal errors (403 banned, ToS violation, etc.)
Changes:
- open-sse/services/accountFallback.ts: extend ACCOUNT_DEACTIVATED_SIGNALS
with AG-specific ban messages ('verify your account', 'service disabled
for violation')
- src/app/api/settings/auto-disable-accounts/route.ts: new GET/PUT endpoint
for the setting (enabled bool + threshold int)
- src/shared/validation/schemas.ts: updateAutoDisableAccountsSchema
- src/sse/services/auth.ts: in markAccountUnavailable(), capture result.permanent
from checkFallbackError() and — when autoDisableBannedAccounts is enabled and
backoffLevel >= threshold — set isActive=false on the connection
Default: disabled (backward-compatible). Enable via Settings UI or PUT
/api/settings/auto-disable-accounts { "enabled": true, "threshold": 3 }
Fixes: antigravity accounts with 403/Verify-your-account errors being
retried indefinitely in the rotation pool.
Co-authored-by: oyi77 <oyi77@users.noreply.github.com>
* fix: address reviewer comments for auto-disable (use getCachedSettings, immediate disable on permanent bans)
---------
Co-authored-by: oyi77 <oyi77@github.com>
Co-authored-by: oyi77 <oyi77@users.noreply.github.com>
* 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>
1. Fixed crash in /api/cli-tools/status when statuses[toolId] is undefined
- Added null check before accessing statuses[toolId] properties
- Prevents "Cannot set property of undefined" error
2. Added support for droid.exe detection in ~/bin directory
- Added ~/bin and ~/.local/bin to EXPECTED_PARENT_PATHS
- Added droid.exe variant to toolBins for Windows
- Added specific path check for droid in ~/bin/droid.exe
These fixes resolve issues where CLI tools (Claude Code, Codex, Droid)
were showing as "not installed" even when properly installed.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Adds a new /dashboard/cache page that surfaces the existing but UI-less
semantic cache infrastructure.
Changes:
- New page: src/app/(dashboard)/dashboard/cache/page.tsx
- Live stats: memory entries, DB entries, cache hits, tokens saved
- Hit rate progress bar with color coding (green/yellow/red)
- Hits/Misses/Total breakdown
- Idempotency layer stats (active dedup keys + window)
- Cache behavior info panel
- Clear All button
- Auto-refresh every 10s
- Enhanced API: src/app/api/cache/route.ts
- DELETE ?model=<name> — invalidate by model
- DELETE ?signature=<hex> — invalidate single entry
- DELETE ?staleMs=<ms> — invalidate entries older than N ms
- DELETE (no params) — clear all (existing behavior)
- Sidebar: added Cache nav item (icon: cached)
- i18n: added cache + sidebar.cache keys for all 31 supported locales
No new dependencies. All functionality builds on existing semanticCache.ts,
cacheLayer.ts, and idempotencyLayer.ts modules.
Co-authored-by: oyi77 <oyi77@users.noreply.github.com>
- introduce open-sse/translator/helpers/schemaCoercion.ts to coerce
numeric JSON Schema fields encoded as strings
- wire coerceToolSchemas and sanitizeToolDescriptions into translator
pipeline; ensure tool descriptions are sanitized
- inject empty reasoning content for tool calls when target is OpenAI
format
- update qwen base URL to DashScope-compatible endpoint
- extend antigravity static catalog with Gemini 3.1 pro preview models and
update Gemini model specs with preview aliases
- implement call log max cap caching with TTL; expose invalidateCallLogsMaxCache
and invalidate on settings PATCH
- add tests: call-log-cap.test.mjs and tool-request-sanitization.test.mjs;
extend tests for Windsurf integration and gemini previews
- update CLI runtime and tools to include Windsurf as a guide-only tool
- add maxCallLogs to validation schemas (settings and updateSettings)
- add Czech README (README.cs.md) to repository
- Add glm-5.1 model to GLM Coding provider with fitness scores
- Update glm-5 pricing to match Z.AI API page ($1/$3.2/$0.2)
- Set glm-5.1 pricing to $1.2/$5/$0.3 per Z.AI
- Remove glm-4-32b (deprecated, returns empty from upstream)
- Rename Z.AI provider display name from "Z.AI (GLM-5)" to "Z.AI"
- Update zai pricing section to match glm pricing
## Proxy UI Bug Fixes
- fix: proxy badge on connection cards now uses resolveProxyForConnection()
per-connection (covers registry + config-file assignments)
- fix: Test Connection button now works in 'saved' proxy mode by resolving
proxy config from savedProxies list
- fix: ProxyConfigModal now calls onClose() after save/clear (fixes UI freeze)
- fix: ProxyRegistryManager loads usage eagerly on mount with deduplication
by scope+scopeId to prevent double-counting; adds per-row Test button
## Connection Tag Grouping (new feature)
- feat: add Tag/Group field to EditConnectionModal (stored in
providerSpecificData.tag, no DB schema change)
- feat: connections list groups by tag with visual dividers when any account
has a tag; untagged accounts appear first without header
## Post-merge fix from PR #607 review
- fix: function_call blocks in translateNonStreamingResponse now also strip
Claude OAuth proxy_ prefix via toolNameMap (kilo-code-bot #607 warning)
Affects OpenAI Responses API format path — tool_use was fixed in PR #607
but function_call was missed
Use connection.name instead of the raw provider node ID
(e.g. "BltCy API" instead of "openai-compatible-chat-09fdb807-...")
in call logs and scheduler console output.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add POST /api/providers/[id]/sync-models endpoint that fetches models
from a provider's /models API and replaces the full custom models list,
preserving per-model compatibility overrides
- Rewrite modelSyncScheduler to dynamically discover connections with
autoSync enabled in providerSpecificData instead of a hardcoded list
- Add replaceCustomModels() to db/models.ts for full list replacement
while preserving existing compat flags
- Log each model sync operation to call_logs for visibility in the
Logs page
- Add Auto-Sync toggle button next to "Import from /models" in the
provider detail page UI
- Add en/zh-CN i18n translations for auto-sync strings
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add stripModelPrefix boolean setting that, when enabled, strips
provider prefixes (e.g. openai/, anthropic/) from incoming model
names and re-resolves the bare model name using existing heuristics.
This allows tools to send prefixed model names while OmniRoute
handles provider routing at the proxy layer.
- Add stripModelPrefix to settings validation schema (Zod)
- Check setting in getModelInfo() after custom node matching fails
- Falls through to normal resolution on error or when disabled
- Backward compatible: opt-in, default behavior unchanged
- Add contextLength field to RegistryModel interface for per-model overrides
- Add defaultContextLength to RegistryEntry for provider-level defaults
- Set context lengths for major providers:
- Claude: 200k
- Codex: 400k (fixes combo context display)
- Gemini: 1M
- OpenAI: 128k
- GitHub Copilot: 128k
- Kiro/Cursor: 200k
- OpenCode: 200k
- Include context_length in /v1/models API response
- Add context_length field to combo schema for custom combo context
- Update contextManager to use registry defaults and support env overrides
- CONTEXT_LENGTH_<PROVIDER> for per-provider override
- CONTEXT_LENGTH_DEFAULT for global override
This allows clients like OpenClaw to display accurate context windows
for combo models instead of guessing based on model name patterns.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add model-pattern → combo mapping feature that automatically routes requests
to specific combos based on model name patterns (glob matching).
Implementation:
- New migration 010: model_combo_mappings table with pattern, combo_id, priority
- DB module with CRUD + resolveComboForModel() using glob-to-regex matching
- getComboForModel() in model.ts: augments getCombo() with pattern fallback
- chat.ts: replaced getCombo() → getComboForModel() at routing decision point
- API endpoints: GET/POST /api/model-combo-mappings, GET/PUT/DELETE by [id]
- ModelRoutingSection.tsx: dashboard UI with inline add/edit/toggle/delete
- Integrated into Combos page
- 15 new unit tests (glob matching, priority ordering, disabled filtering)
- Full test suite: 923/923 pass
Examples:
claude-sonnet* → code-combo
claude-*-opus* → frontier-combo
gpt-4o* → openai-combo
gemini-* → google-combo
Resolves: #563
Cherry-pick from codex/omniroute-fixes-20260324:
- Replace MCP singleton transport with per-session architecture for Streamable HTTP
- Fix Claude passthrough via OpenAI round-trip normalization
- Add detectFormatFromEndpoint() for endpoint-aware format detection
- Support raw code#state in OAuth modal for Claude Code remote auth
- Expose cloudConfigured/cloudUrl/machineId in settings API
- Switch docker-compose.prod.yml target to runner-cli
- Add 3 new tests for round-trip and detectFormat
PR: #562
T01 (P1): requested_model column in call_logs
- Migration 009_requested_model.sql: ALTER TABLE call_logs ADD COLUMN requested_model
- callLogs.ts: INSERT + SELECT updated to include requestedModel field
T02 (P1): Strip empty text blocks from nested tool_result.content
- New stripEmptyTextBlocks() recursive helper in openai-to-claude.ts
- Applied on tool_result content before forwarding to Anthropic
- Prevents 400 'text content blocks must be non-empty' errors
T03 (P1): Parse x-codex-5h-*/x-codex-7d-* headers for precise quota reset
- parseCodexQuotaHeaders() in codex.ts extracts usage/limit/resetAt
- getCodexResetTime() returns furthest-out reset timestamp for safe unblocking
T04 (P1): X-Session-Id header for external sticky routing
- extractExternalSessionId() in sessionManager.ts reads x-session-id,
x-omniroute-session, session-id headers with 'ext:' prefix to avoid collisions
T06 (P2): account_deactivated permanent expired status on 401
- ACCOUNT_DEACTIVATED_SIGNALS constant + isAccountDeactivated() in accountFallback.ts
- Returns 1-year cooldown (effectively permanent) to prevent retrying dead accounts
T07 (P2): X-Forwarded-For IP validation
- New src/lib/ipUtils.ts with extractClientIp() and getClientIpFromRequest()
- Skips 'unknown'/non-IP entries in X-Forwarded-For chain
T10 (P2): credits_exhausted distinct account status
- CREDITS_EXHAUSTED_SIGNALS + isCreditsExhausted() in accountFallback.ts
- Returns 1h cooldown with creditsExhausted flag, distinct from rate_limit 429
T11 (P1): max reasoning_effort -> budget_tokens: 131072
- EFFORT_BUDGETS and THINKING_LEVEL_MAP updated with max: 131072, xhigh: 131072
- Reverse mapping now returns 'max' for full-budget responses
- Unit test updated to expect 'max' (was 'high')
T12 (P3): Model pricing updates
- MiniMax M2.7 / MiniMax-M2.7 / minimax-m2.7-highspeed pricing added
T15 (P1): Array content normalization for system/tool messages
- normalizeContentToString() helper exported from openai-to-claude.ts
- System messages with array content now correctly collapsed to string