Replace Image-based provider icons in ProviderOverviewCard with the same
ProviderIcon component used on the providers page (@lobehub/icons SVG
with PNG → generic fallback chain).
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
- Added MAX_TRANSCRIPTION_FILE_SIZE constant (4GB)
- Added formatFileSize() helper for human-readable display (KB/MB/GB)
- Frontend validation rejects files > 4GB with error message
- Changed label from 'Audio File' to 'Audio / Video File'
- Shows 'Supports audio and video files up to 4 GB' hint
- 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>
When users skip password setup during onboarding (either via 'Skip Password'
checkbox or 'Skip Wizard' button), the app now explicitly sets requireLogin=false.
Previously, requireLogin defaulted to true with no password hash stored,
leaving users permanently stuck on the login page.
Two code paths fixed in onboarding/page.tsx:
- handleSetPassword() with skipSecurity=true
- handleFinish() when no password was configured
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
- Implement keychain-based credential extractor for Zed IDE
- Support macOS (Keychain), Windows (Credential Manager), Linux (libsecret)
- Add API endpoint: POST /api/providers/zed/import
- Auto-discover OAuth tokens for OpenAI, Anthropic, Google, Mistral, xAI, etc.
- Cross-platform support via keytar library
- Complete documentation with security considerations
Closes community request from OmniRoute Telegram group.
Follows proven pattern used by VS Code, GitHub Copilot CLI, Claude Code.
CLI settings routes (codex-settings, droid-settings, kilo-settings) were
writing the masked API key string directly to config files when the
dashboard sent a keyId. Now resolves the real key from the database via
getApiKeyById() before writing, matching the pattern already implemented
in claude-settings, openclaw-settings, and cline-settings.
Closes#549
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
Registrar o provedor Puter como gateway OpenAI-compatible que expõe
modelos de múltiplos fornecedores (GPT, Claude, Gemini, Grok, DeepSeek,
Qwen, Mistral, Llama) através de um único endpoint REST.
- Criar PuterExecutor com autenticação Bearer token
- Adicionar entrada no providerRegistry com 40+ modelos curados
- Habilitar passthroughModels para acesso aos 500+ modelos do catálogo
- Registrar alias "pu" para acesso rápido
- Adicionar metadados do provedor em shared/constants/providers.ts
feat(ui): ProviderIcon component with @lobehub/icons + PNG fallback (#529)
- 130+ providers covered by Lobehub SVG components via LobehubErrorBoundary
- Falls back to existing /providers/{id}.png, then generic icon
- Replaces manual img state machine in ProviderCard + ApiKeyProviderCard
feat(scheduler): modelSyncScheduler — 24h model list auto-update (#488)
- Syncs 16 major providers every 24h (MODEL_SYNC_INTERVAL_HOURS configurable)
- Wired into POST /api/sync/initialize startup hook
fix(oauth): Gemini CLI — clear error when client_secret missing in Docker (#537)
fix(cli): normalize MSYS2/Git-Bash paths in cliRuntime.ts (#510)
- Add normalizeMsys2Path() helper: /c/Program Files/... → C:\Program Files\...
- Apply to both Windows 'where' and Unix 'command -v' path resolution
- Fixes 'CLI not detected' on Windows when running Git Bash / MSYS2
fix(cli-launcher): detect mise/nvm on server.js not found error (#492)
- Show targeted fix instructions based on which Node manager is in use
- mise users: told to use npx or mise exec
- nvm users: reminded to nvm use --lts before reinstalling
docs(issues): add pnpm bindings workaround comment (#520)
docs(issues): note OpenCode/Lobehub icons coming in v3.0.0 (#529)
fix(login): redirect to /dashboard/onboarding when API returns needsSetup:true (#521)
- Handle the case where user skips password setup and lands on login
- Instead of showing a cryptic error, redirect to onboarding flow
fix(api-manager): replace useless 'copy masked key' button with lock tooltip (#522)
- Copying a masked key (sk-proj123****abcd) is misleading and useless
- Show a lock icon on hover explaining key is only available at creation time
- Add i18n key 'keyOnlyAvailableAtCreation'
fix(opencode-go): use zen/v1 for API key validation, not zen/go/v1 (#532)
- Added testKeyBaseUrl field to RegistryEntry interface
- opencode-go: testKeyBaseUrl → zen/v1 (same key authenticates both tiers)
- validation.ts: resolveBaseUrl for key testing now prefers testKeyBaseUrl
fix(antigravity): return structured 422 error when projectId is missing (#489)
- Instead of throwing (crash), executor returns an OpenAI-format error JSON
- Client receives message with instruction to reconnect OAuth
- Prevents opaque 500 errors in the proxy logs
chore: close#525 (OmniRoute = 9router — same project, different name)
docs: add Docker password reset comment on #513 with INITIAL_PASSWORD workaround
- Register OpencodeExecutor for 'opencode-zen' and 'opencode-go' in executors map
- Add OpencodeExecutor export in index.ts
- Add UI metadata for both providers in APIKEY_PROVIDERS:
- OpenCode Zen: https://opencode.ai/zen
- OpenCode Go: https://opencode.ai/zen/go
- Both use 'opencode' icon with #6366f1 color
fix(cli-tools): save real API key to CLI config files instead of masked string (#523, #526)
- claude-settings/route.ts: accept keyId, look up real key from DB (getApiKeyById)
- cline-settings/route.ts: same keyId resolution pattern
- openclaw-settings/route.ts: same keyId resolution pattern
- ClaudeToolCard.tsx: store key.id as selected value, send keyId in POST body
The /api/keys endpoint returns masked strings (first8+****+last4) which were being
written verbatim to ~/.claude/settings.json and similar config files, causing auth
failures on CLI tool launch.
fix(combo): update CACHE_TAG_PATTERN to strip surrounding \\n sequences (#531)
- comboAgentMiddleware.ts: non-global regex now matches literal \\n (backslash-n)
and actual newline U+000A that combo.ts injects around the <omniModel> tag.
- fix(translator): preserve prompt_cache_key in Responses API translation (#517)
- fix(combo): escape \n in tagContent for valid JSON injection (#515)
- fix(usage): sync expired token status back to DB on live auth failure (#491)
- chore: bump version to 2.9.4 in package.json + docs/openapi.yaml
- docs: update CHANGELOG.md with v2.9.4 release notes