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)
- 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
Rewrite getMachineIdRaw() to use a try/catch waterfall instead of
process.platform conditionals. Next.js SWC bundler evaluates
process.platform at BUILD time, so when built on Linux, the win32
branch was dead-code-eliminated — causing 'head is not recognized'
errors on Windows.
New approach:
1. Try Windows REG.exe (existsSync check, not platform check)
2. Try macOS ioreg command
3. Try reading /etc/machine-id directly (no head/pipe)
4. Try hostname command
5. Fallback to os.hostname()
Also eliminates the patch-machine-id.cjs post-install workaround.
- #493: Fix custom provider model naming — removed incorrect prefix
stripping in DefaultExecutor.transformRequest() that broke org-scoped
model IDs like 'zai-org/GLM-5-FP8'
- #490: Enable context cache protection for streaming responses using
TransformStream to inject omniModel tag as final SSE content delta
before [DONE] marker
- #452: Add per-API-key request-count limits (max_requests_per_day,
max_requests_per_minute) with in-memory sliding window counter,
schema auto-migration, and Check 5 in enforceApiKeyPolicy()
- Replace execSync template string with execFileSync + args array on Windows
to prevent command injection via SystemRoot/windir environment variables
- Add optional chaining (?.) and nullish coalescing (?? "") on Windows
REG_SZ output parsing to prevent crash if REG.exe output is unexpected
- Add optional chaining on macOS IOPlatformUUID parsing for the same reason
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Problem:
node-machine-id constructs the REG.exe command path at module load time
using process.platform. When Next.js bundles this module, process.platform
is "" (not "win32") in the webpack/build context, so the lookup returns
undefined and bakes "undefined\REG.exe ..." permanently into the compiled
chunk. At runtime on Windows this causes:
Error: Command failed: undefined\REG.exe QUERY HKEY_LOCAL_MACHINE\...
The system cannot find the path specified.
Fix:
Remove the node-machine-id dependency from machineId.ts and replace it
with a direct execSync implementation that resolves process.env.SystemRoot
at call time (not load time), so the correct Windows path is always used
regardless of when or how the module was bundled.
Platform support is preserved for Windows, macOS, and Linux/FreeBSD using
the same underlying OS queries that node-machine-id used internally.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add preserveDeveloperRole option and model compat override
- Normalize developer→system in roleNormalizer when not preserving
- Translator runs normalizeRoles for Responses API with option
- UI: ModelCompatPopover with do not preserve developer toggle
- Add ZWS_README_V2 documenting cause and fix
Made-with: Cursor
- #462: Mark gemini-cli provider as deprecated in providers.ts
Add deprecated, deprecationReason, hasFree, freeNote, authHint, apiHint
to Zod provider schema
- #471: Add VM_DEPLOYMENT_GUIDE.md to DOC_SOURCE_FILES in generate-multilang.mjs
Delete 29 stale PT-language copies and regenerate from EN source
for all 30 locales (29 auto-translated + 1 Czech from PR #482)
* feat: add api-key Kimi Coding provider support
* fix(kimi-coding): honor apikey auth header in executor
Ensure DefaultExecutor sends x-api-key for kimi-coding-apikey at runtime
and deduplicate shared kimi coding config blocks in registry and models
config to reduce drift between oauth and apikey variants.
---------
Co-authored-by: OmniRoute Agent <agent@omniroute.local>
- fix(ux): add default password hint on login page for first-time users (#437)
The fallback password (123456) is now shown as a hint below the
password input so users don't get locked out during initial setup.
- fix(cli): add shell:true to spawn on Windows so .cmd wrappers are
resolved correctly via PATHEXT (#447). Claude, opencode, and other
npm-installed CLIs show as 'not runnable' on Windows even when
installed because spawn() cannot find .cmd files without shell:true.
- i18n: add defaultPasswordHint key to en.json auth namespace
Search Playground (Phase 1):
- Web Search as 10th endpoint in Playground with isolated SearchPlayground component
- Endpoint selector moved first; Provider/Model/Send hidden when search selected
- Provider dropdown via GET /api/search/providers, formatted results with cache indicator
Search Tools page (Phase 2) at /dashboard/search-tools:
- Split panel: SearchForm (left) with query, provider, filters + ResultsPanel (right)
- Compare Providers: parallel queries with latency, cost, response size, URL overlap
- Rerank Pipeline: model selector from /v1/models, results with position delta
- Search History: last 10 searches from call_logs with replay
- Sidebar entry under Debug section
Backend:
- GET /api/search/providers — list providers with auth guard + SEARCH_CREDENTIAL_FALLBACKS
- GET /api/search/stats — cache stats, provider aggregates, recent searches (auth guard)
- Add local provider_nodes routing for /v1/rerank (oMLX, vLLM support)
Bug fixes (from F-27 PR #432):
- Fix Brave news normalizer: data.results directly, not data.news.results
- Enforce max_results truncation after normalization for all providers
- Fix EndpointPageClient: use /api/search/providers instead of /api/v1/search
- Add isAuthenticated() guards on /api/search/providers and /api/search/stats
Response size metric in results meta bar and compare table.
i18n: 30+ keys in search namespace (en.json)
Kilo Gateway (api.kilo.ai/api/gateway) is an OpenAI-compatible API
offering 335+ models via a single API key, including 6 free models
and 3 auto-routing models (frontier/balanced/free).
This is distinct from the existing KiloCode provider which uses
OAuth + /api/openrouter/ endpoint.
- Register kilo-gateway in providerRegistry.ts (alias: kg)
- Add to APIKEY_PROVIDERS in providers.ts
- Add models endpoint config in route.ts
- Add official Kilo AI icon (favicon)
Add Synthetic (synthetic.new) as a privacy-focused LLM provider
with OpenAI-compatible API, dynamic model catalog via /models
endpoint, and passthrough model support.
- Register provider in providerRegistry.ts with 6 initial models
- Add APIKEY_PROVIDERS entry with verified_user icon (#6366F1)
- Add models listing config for /api/providers/[id]/models endpoint
- passthroughModels enabled for dynamic model catalog
Allow provider_nodes to configure custom chat and models endpoint
paths via chatPath/modelsPath fields. This enables providers with
non-standard versioned APIs (e.g. /v4/chat/completions) to work
without embedding the version prefix in base_url.
- Add migration 003: chat_path and models_path columns
- Update Zod schemas (create, update, validate)
- Update CRUD in providers.ts (INSERT/UPDATE)
- Wire chatPath/modelsPath through API routes and providerSpecificData cascade
- Read chatPath in DefaultExecutor and BaseExecutor buildUrl()
- Use modelsPath in validate endpoint
- Add Advanced Settings UI section (collapsible) in create/edit modals
- Update base URL hint to reference Advanced Settings
- Add i18n keys across all 30 locales
- Add unit tests for buildUrl with custom paths
Backward compatible: NULL chatPath/modelsPath = default behavior.