- Remove ComplianceTab from settings page (tab definition, import, rendering)
- Replace self-referential HTTP calls in /api/cli-tools/status with direct
file reads via getCliPrimaryConfigPath, eliminating ~6 redundant HTTP
roundtrips and ~6 duplicate process healthchecks per page load
Previously, validateOpenAICompatibleProvider and validateAnthropicCompatibleProvider
only tried GET /models. Many compatible providers don't expose this endpoint,
causing the Check button to show 'Invalid' even with valid credentials.
Now both validators follow a 2-step approach:
1. Try GET /models (fast path)
2. If that fails, try a minimal chat/messages request as fallback
Any non-auth 4xx response (400, 422) is treated as valid since it means
the API key was accepted but the test model wasn't recognized.
- Update 294 import paths across 99 files
- Fix 'Module not found' errors from stale .js extensions
- Covers: from '.../.js', bare import '.../.js', @omniroute/open-sse/*.js
- Build now passes: npm run build exits with code 0
- refreshQwenToken now detects 'invalid_request' and returns sentinel error
- isUnrecoverableRefreshError expanded to match invalid_request
- Switched Qwen, IFlow, Cline test configs to checkExpiry mode (endpoints were returning 404/400/stale-auth)
- Fixed TypeScript errors in testSingleConnection (union type casts, Record<string,any>)
- Add saveCallLog + logProxyEvent to testSingleConnection() so provider
tests, API key tests, and batch tests all log to both Logger and Proxy
tabs in the Usage dashboard
- Fix combo test getBaseUrl() to respect x-forwarded-host/proto headers,
preventing localhost resolution behind reverse proxy on VPS
- All test flows now produce entries in both call_logs and proxy_logs
tables alongside the existing chat/SSE pipeline logging
- Extract testSingleConnection() from [id]/test/route.js as reusable export
- Rewrite test-batch/route.js to call testSingleConnection() directly
instead of fetch(${request.nextUrl.origin}/api/...) which resolves to
localhost behind reverse proxy, causing NETWORK_ERROR on VPS
- Add NEXT_PUBLIC_APP_URL to cloudSyncScheduler.js fallback chain
- POST handler in [id]/test/route.js now delegates to testSingleConnection()
Fixes: all 34 providers failing with NETWORK_ERROR on llms.omniroute.online
- Add proxy_logs table to db/core.js schema (18 columns + 3 indexes)
- Rewrite proxyLogger.js with hybrid dual storage:
- In-memory ring buffer for real-time performance
- SQLite persistence for surviving server restarts
- On startup, hydrates from DB (last 500 entries)
- Each event writes to both memory and SQLite
- Auto-trim keeps max 500 rows in DB
- Same external API (getProxyLogs, clearProxyLogs, etc.)
- Zero changes needed in API route or frontend
- getSettings() auto-sets setupComplete=true when INITIAL_PASSWORD env is set
- proxy.js middleware enforces login when INITIAL_PASSWORD exists (even without DB hash)
- Settings API reports hasPassword=true when INITIAL_PASSWORD is configured
- Login page hides '123456' default hint when a custom password is set
Fixes fresh Docker/VM deployments getting stuck on onboarding wizard
and being accessible without authentication.
- Create shared CliStatusBadge component with support for configured,
not_configured, not_installed, other, and unknown statuses
- Replace inline status badge markup in ClaudeToolCard and ClineToolCard
with the new reusable component
- Add colored status dot indicator alongside badge text
- Support batch status fallback so badges render even when cards are collapsed
- Refactor model/provider selection logic in tool card configuration
- Add GET handler to /api/sync/cloud for real-time status polling
- Rewrite CloudSyncStatus: clickable, event-driven updates, clearer labels
- Add inline status toast with auto-dismiss after enable/disable
- Show success animation in modal before auto-closing
- Dispatch cloud-status-changed event for instant sidebar updates
Add dedicated Costs page combining Budget and Pricing tabs with a
sidebar navigation layout. Improve Health page provider section with
status legend (Healthy/Recovering/Down) and import AI_PROVIDERS
constants for richer provider display.
- Fetch and display request metrics (success rate, latency, total requests) on provider overview cards
- Create /api/provider-metrics endpoint to aggregate stats from request logs
- Add /api/providers/[id]/import-models endpoint to import models from provider's /models API
- Add "Import from /models" button on passthrough provider detail pages
- Include proper PropTypes for new metrics and alias fields
Replace text-based "9" favicon with a network/router node graph design
across all icon sizes. Add apple-touch-icon and icon-192 SVG assets.
Update brand gradient from orange (#f97815) to red (#E54D5E).
Introduce built-in eval system for testing LLM response quality against
golden sets. Includes eval runner with 4 match strategies (exact,
contains, regex, custom), a pre-loaded 10-case golden set, REST API
endpoints for managing and running suites, and a dashboard UI under
Analytics → Evals with real-time progress tracking and pass rate
summaries. Also adds OpenAPI tags for Audio, Moderations, and Rerank.
Extend combo routing with 3 new model selection strategies beyond the
existing priority, weighted, and round-robin options:
- random: Fisher-Yates shuffle for uniform distribution
- least-used: sorts models by request count via comboMetrics
- cost-optimized: sorts models by pricing (cheapest first)
Also enhance the dashboard provider cards with model counts and
clickable detail views for selected providers.
- Add compact ModelAvailabilityBadge with popover for model status
monitoring, cooldown clearing, and auto-refresh polling
- Retheme landing page from warm orange tones to cool blue-grey palette
across FlowAnimation, Footer, and related components
- Update accent color from orange (#f97815) to rose (#E54D5E)
Introduce reusable shared components (Button, Card, Modal, Table,
StatusBadge, EmptyState) and refactor dashboard pages to use them.
Extract client components from server pages, centralize provider
constants, and update CI Node.js matrix from 18 to 20.
initTranslators() is a no-op stub (translators self-register via static
imports). Wrapping the call with Promise.resolve() ensures .then() works
even when the function returns undefined instead of a Promise.
chatHelpers.js imported detectFormat/getTargetFormat/getModelTargetFormat
from '../services/translator.js' which does not exist.
Fixed to import from canonical sources:
- detectFormat, getTargetFormat → @omniroute/open-sse/services/provider.js
- getModelTargetFormat, PROVIDER_ID_TO_ALIAS → @omniroute/open-sse/config/providerModels.js
Phase 6.6 analysis: src/sse/ is an intentional adapter layer over
open-sse/ (not duplication). No further deduplication needed.