Commit Graph

346 Commits

Author SHA1 Message Date
zhang-qiang
a2d7cbe8fe feat(compat): per-protocol model compatibility config (V5)
Add per-protocol compatibility options (compatByProtocol) allowing users to configure normalizeToolCallId and preserveOpenAIDeveloperRole per client request protocol (OpenAI Chat, Responses API, Anthropic Messages) instead of globally. Includes frontend Map lookup optimization, type safety improvements, and client-safe constant extraction.

Made-with: Cursor
2026-03-21 15:23:42 +08:00
diegosouzapw
0a5b005ce5 fix: resolve multiple issues (#493, #490, #452)
- #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()
2026-03-20 19:26:21 -03:00
zhang-qiang
aae2399631 fix(perf): resolve HMR singleton leaks, Edge warnings, and test stability
- Use globalThis singleton guards for DB connection, HealthCheck timers, console interceptor, and graceful shutdown to survive Webpack HMR re-evaluation (fixes 485+ leaked DB connections per session)

- Split instrumentation.ts into instrumentation-node.ts with computed import path to prevent Turbopack Edge bundler from tracing Node.js modules (eliminates 10+ spurious warnings per hot compile)

- Parallelize startup imports in instrumentation-node.ts (3 batch Promise.all instead of 9 serial awaits)

- Add OMNIROUTE_USE_TURBOPACK=1 env switch in run-next.mjs (default behavior unchanged)

- Replace node:crypto with crypto in proxies.ts and errorResponse.ts to fix UnhandledSchemeError

- Add unlinkFileWithRetry with EBUSY/EPERM retry for Windows file handle timing in backup restore

- Fix pre-restore backup to await completion before closing DB

- Fix bootstrap-env, domain-persistence, and fixes-p1 test stability on Windows

Made-with: Cursor
2026-03-21 00:50:07 +08:00
zhang-qiang
1a099ea2f2 feat(zws-v2): model compat, provider-models hardening, provider page types
- roleNormalizer/translator: ZWS v2 role handling and comments

- models + schemas: compat overrides, nullable preserveOpenAIDeveloperRole

- provider-models API: generic GET 500; compatOnly validates known provider

- providers [id] page: typed props; minimal saveModelCompatFlags PATCH

Made-with: Cursor
2026-03-20 23:03:52 +08:00
zhang-qiang
13c45807ef feat: protocol-scoped model compat (V3)
- compatByProtocol per openai/openai-responses/claude

- getters take sourceFormat; chatCore passes it

- UI: protocol selector in compat popover, dark mode select

- shared/constants/modelCompat for client-safe import (fix node:crypto build)

- ZWS_README_V3.md

Made-with: Cursor
2026-03-20 22:06:03 +08:00
zhang-qiang
a7fe369ea0 fix: resolve role param error for Responses API + MiniMax (developer→system)
- 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
2026-03-20 21:06:10 +08:00
diegosouzapw
601cc21a44 feat: call log response content, per-model tool call ID, key PATCH & validation (#470) 2026-03-19 08:41:01 -03:00
Regis
564e983c68 feat(search): add unified web search routing with 5 providers
Add POST /v1/search — a unified search endpoint routing queries across
5 providers (Serper, Brave, Perplexity Search, Exa, Tavily) with
automatic failover, in-memory caching, and request coalescing.

No open-source AI gateway offers unified search routing. This chains
free tiers for 5,500+ searches/month with zero downtime.

Providers: Serper ($0.001/q, 2500/mo free), Brave ($0.005/q, 1000/mo),
Perplexity Search ($0.005/q), Exa ($0.007/q, 1000/mo), Tavily
($0.008/q, 1000/mo). Auto-select picks cheapest with credentials.

Architecture follows existing patterns:
- searchRegistry.ts (same as embeddingRegistry.ts)
- search.ts handler (same as embeddings.ts)
- route.ts (same as /v1/embeddings/route.ts)
- searchCache.ts (bounded TTL cache + request coalescing)

Schema finalized — all future fields defined as optional with safe
defaults. No breaking changes when implementing content extraction,
answer synthesis, or ranking.

Key features:
- Per-provider request builders and response normalizers
- Enriched response: display_url, score, favicon_url, content block,
  metadata, answer block, errors array, upstream_latency_ms metrics
- Cost-sorted auto-select with failover on 429/5xx/timeout
- Credential fallback (perplexity-search reuses perplexity chat key)
- Cache key includes all result-affecting parameters
- max_results clamped to provider limits, sanitized error responses
- Factored validators (validateSearchProvider factory)
- CORS headers on all responses
- Dashboard: Search & Discovery section, search provider template
- DB migration 007: request_type column in call_logs
- 28 unit tests (registry, cache, coalescing, validation)
2026-03-17 18:28:35 +01:00
diegosouzapw
095c84ac16 fix(providerRegistry): remove duplicate claude-haiku-4-5-20251001 from anthropic provider to prevent ambiguous model resolution 2026-03-17 13:10:23 -03:00
diegosouzapw
d56fae0a7b feat: combo agents, auto-update UI, detailed logs, MITM Kiro (#399 #401 #320 #378 #336)
DB Migrations (zero-breaking, ADD COLUMN DEFAULT NULL + new table):
- 005_combo_agent_fields.sql: system_message, tool_filter_regex, context_cache_protection on combos
- 006_detailed_request_logs.sql: ring-buffer table (500 entries) for full pipeline body capture

Features:
- #399 System Message Override + Tool Filter Regex per Combo
  - applyComboAgentMiddleware() injected into handleComboChat/handleRoundRobinCombo
  - Supports both OpenAI and Anthropic tool name formats
- #401 Context Caching Protection (Stateless)
  - injectModelTag() appends <omniModel>provider/model</omniModel> to responses
  - extractPinnedModel() reads tag from history and pins model for session
- #320 Auto-Update via Settings
  - GET /api/system/version — current vs latest npm
  - POST /api/system/update — fire-and-forget npm install + pm2 restart
- #378 Detailed Request Logs
  - saveRequestDetailLog() captures bodies at 4 pipeline stages (opt-in toggle)
  - GET/POST /api/logs/detail — list logs + enable/disable toggle
- #336 MITM Kiro IDE
  - src/mitm/targets/kiro.ts: MitmTarget profile for api.anthropic.com interception
2026-03-17 08:53:41 -03:00
diegosouzapw
e9f31f7394 Merge pull request #429 from contributor branch 2026-03-17 08:14:05 -03:00
rexname
04b50329fc fix(proxy): address PR review findings for auth, credentials, and health stats 2026-03-17 16:58:44 +07:00
diegosouzapw
a9f69711c6 fix(build): remove node: protocol prefix from all src/ imports (#turbopack-compat)
Turbopack (Next.js 15) does not process node: URL prefixes correctly when
bundling server-side files that get transitively included. Removed the node:
prefix from 17 files:

- src/lib/db/migrationRunner.ts (node:fs, node:path, node:url)
- src/lib/db/core.ts (node:path, node:fs)
- src/lib/db/backup.ts (node:path, node:fs)
- src/lib/db/prompts.ts (node:fs)
- src/lib/dataPaths.ts (node:path, node:os)
- src/app/api/settings/route.ts
- src/app/api/storage/health/route.ts
- src/app/api/oauth/[provider]/[action]/route.ts
- src/app/api/db-backups/{exportAll,import,export}/route.ts
- src/shared/middleware/correlationId.ts
- src/shared/utils/requestId.ts
- src/lib/apiBridgeServer.ts
- src/lib/cacheLayer.ts
- src/lib/semanticCache.ts
- src/lib/oauth/providers/kimi-coding.ts

Also updated generate-release.md: Docker Hub sync and dual-VPS deploy
are now mandatory steps in every release.
2026-03-17 04:24:46 -03:00
rexname
8091b6b508 feat: implement proxy registry, management APIs, docs, and test hardening 2026-03-17 13:05:27 +07:00
Regis
e25029939d feat(api): add custom endpoint paths for compatible provider nodes
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.
2026-03-16 10:23:44 +01:00
Kfir Amar
8643f4015f fix(build): restore webpack production build 2026-03-15 20:25:11 +02:00
Kfir Amar
43bd529b78 fix(db): add provider connection group migration
Add the missing provider_connections.group column to both the
base schema and the runtime column backfill path.

Also add a regression test covering upgrade from an older
database that does not yet have the column.
2026-03-14 22:18:41 +02:00
Diego Rodrigues de Sa e Souza
e322376996 Merge pull request #363 from AndersonFirmino/feat/strict-random-i18n-ux
Merged! Excellent contribution @AndersonFirmino 🎉

This PR delivers four major improvements:
- **strict-random** strategy — Fisher-Yates shuffle deck with anti-repeat guarantee and mutex serialization for concurrent safety
- **API key controls** — allowedConnections, is_active, accessSchedule, autoResolve
- **Connection groups** — environment-based grouping view in Limits page with localStorage persistence  
- **i18n** — 30 languages fully updated, pt-BR fully translated

655 tests passing. Merged with main (v2.4.4) — no conflicts. Thank you for the exceptional quality!
2026-03-14 15:30:19 -03:00
Regis
7db280ee64 fix(api): address review feedback on pricing sync
- Add .catch() to initial and periodic sync promises (Gemini, Kilo)
- Wrap JSON.parse in try-catch for corrupted DB data (Kilo)
- Wrap response.json() in try-catch for invalid LiteLLM JSON (Kilo)
- Validate PRICING_SYNC_INTERVAL (guard against NaN/0 → tight loop) (Copilot)
- Validate and allowlist sources — reject unknown, prevent empty sync
  from clearing pricing_synced data (Copilot, Kilo)
- Extract merge loop into shared iteration to reduce duplication (Gemini)
- Add data/warnings fields to MCP output schema (Copilot)
- Remove unused z import in vitest (Copilot)
- Filter non-string entries from sources array in API route (Copilot)
- Track active interval for accurate getSyncStatus().nextSync (Copilot)
2026-03-14 19:01:27 +01:00
Regis
192c06cadf feat(api): add external pricing sync with LiteLLM source
Add a 3-tier pricing resolution system: user overrides > synced external > hardcoded defaults.

New files:
- src/lib/pricingSync.ts: sync engine (fetch LiteLLM, transform, store in pricing_synced namespace)
- src/app/api/pricing/sync/route.ts: POST (trigger sync), GET (status), DELETE (clear synced)
- tests/unit/pricing-sync.test.mjs: 12 unit tests for transform logic
- open-sse/mcp-server/__tests__/pricingSync.test.ts: 11 vitest tests for MCP schema

Modified files:
- src/lib/db/settings.ts: getPricing() now merges 3 layers (defaults → synced → user)
- src/server-init.ts: init pricing sync on startup when PRICING_SYNC_ENABLED=true
- src/lib/localDb.ts: re-export pricing sync functions
- open-sse/mcp-server/schemas/tools.ts: add omniroute_sync_pricing tool definition
- open-sse/mcp-server/tools/advancedTools.ts: add handleSyncPricing handler
- open-sse/mcp-server/server.ts: register omniroute_sync_pricing tool

Opt-in (PRICING_SYNC_ENABLED=false by default), user overrides are never touched,
graceful fallback on fetch failure, zero new dependencies.
2026-03-14 18:49:35 +01:00
Anderson Firmino
a8a29e17c5 feat: strict-random strategy, API key management, connection groups, Limits UX
- Combo layer: strict-random in combo.ts rotates models uniformly
- Credential layer: strict-random in auth.ts rotates connections/accounts
- Anti-repeat guarantee: last of previous cycle ≠ first of next
- Mutex serialization for concurrent request safety
- Independent decks per combo name and per provider

- allowedConnections: restrict which connections a key can use
- autoResolve: per-key toggle for ambiguous model disambiguation
- is_active: enable/disable key instantly (403 on disabled)
- accessSchedule: time-based access control (hours, days, timezone)
- Rename keys via PATCH /api/keys/:id
- Connection restriction badge in API keys table
- Auto-migration for all new columns

- Connection group field on provider connections
- Environment grouping view in Limits page (group by environment)
- Accordion UI with expand/collapse per group
- localStorage persistence for groupBy, autoRefresh, expandedGroups
- Smart default: auto-switches to environment view when groups exist
- Swap SessionsTab above RateLimitStatus

- strict-random option added to combo strategy dropdown (30 languages)
- strategyGuide.strict-random (when/avoid/example)
- pt-BR: translated all strategyRecommendations from English to Portuguese
- en: added API key management strings (accessSchedule, isActive, etc.)

- 11 tests: shuffle deck mechanics (Fisher-Yates, anti-repeat, decks)
- 6 tests: allowedConnections (schema, DB persistence, cache invalidation)
- 12 tests: API key policy (isActive, accessSchedule, autoResolve, budget)
2026-03-14 14:03:08 -03:00
Diego Rodrigues de Sa e Souza
eaddb6f0fa feat: improvements from 9router analysis (T01/T08-T13) (#351)
* fix: tool description null sanitization, clipboard HTTP fallback fixes

T10 - Sanitize tool.description null in claude-to-openai translator
- claude-to-openai.ts: tool.description defaults to empty string when null/undefined
- claude-to-openai.ts: filter out tools with empty/missing names
- Prevents 400 validation errors on providers like NVIDIA NIM (issue #276)

T11 - Fix copy buttons to work on HTTP/non-HTTPS deployments
- Add src/shared/utils/clipboard.ts with HTTPS+HTTP (execCommand) dual fallback
- Migrate useCopyToClipboard.ts to use shared utility
- Migrate ConsoleLogViewer.tsx, RequestLoggerV2.tsx to shared utility
- Migrate HomePageClient.tsx, endpoint/page.tsx, GetStarted.tsx
- Migrate DefaultToolCard.tsx to shared utility
- Fixes copy buttons when OmniRoute runs behind HTTP proxy (issue #296)

T02 - Verified SSE [DONE] sentinel handling already correct
- sseParser.ts filters [DONE] on line 13 (no change needed)
- stream.ts uses doneSent flag to prevent duplicate sentinel
- bypassHandler.ts correctly separates streaming/non-streaming responses

Issue triage comments posted to #340, #341, #344

* feat: DB read cache + Accept header stream negotiation (T09/T01)

T09 - In-memory TTL cache for hot DB read paths
- Add src/lib/db/readCache.ts with TTL cache (5s settings/connections, 30s pricing)
- Eliminates redundant SQLite reads on concurrent requests
- Integrate invalidation in settings.ts updateSettings() and updatePricing()
- Integrate invalidation in providers.ts create/update/delete operations
- Export getCachedSettings, getCachedPricing, getCachedProviderConnections,
  invalidateDbCache via localDb.ts for consumer migration
- Cache auto-busts on any write, preserving data consistency

T01 - Accept header stream negotiation
- src/sse/handlers/chat.ts: detect Accept: text/event-stream header
- Override body.stream=true when Accept header indicates streaming client
- Enables curl, httpx and SDK clients that use HTTP headers instead of JSON
  body field to trigger streaming responses
- Logs Accept override at DEBUG level for observability

* fix: auto-advance quota window on expiry to prevent stale blocking (T08)

T08 - Quota Window Rolling Auto-Advance
- quotaCache.ts: add windowDurationMs field to QuotaCacheEntry interface
  (optional field that callers can set when they know the window duration)
- Add advancedWindowResetAt() helper: if entry.nextResetAt is in the past,
  eagerly returns { exhausted: false } so requests are unblocked immediately
- isAccountQuotaExhausted() now uses advancedWindowResetAt() instead of
  the previous inline date check, and optimistically clears entry.exhausted
  flag to avoid re-checking the same stale entry on the next request

Before: exhausted accounts with an expired resetAt would wait up to 5
minutes for the background refresh before accepting new requests.
After:  the first request after resetAt passes will be immediately accepted
and will trigger a quota refresh on the next background tick.

* feat: manual OAuth token refresh UI (T12)

T12 - Manual Token Refresh UI
- Add POST /api/providers/[id]/refresh endpoint
  - Validates connection exists and is OAuth type
  - Calls getAccessToken() (same helper used in auto-refresh)
  - Persists new credentials via updateProviderCredentials()
  - Returns { success, expiresAt, refreshedAt } on success

- Update providers/[id]/page.tsx
  - handleRefreshToken() with loading state (refreshingId)
  - Pass onRefreshToken + isRefreshing props to ConnectionRow
  - ConnectionRow: add optional onRefreshToken/isRefreshing props
  - ConnectionRow: tokenMinsLeft state via lazy init (Date.now() in
    getter fn, not in render body - satisfies react-hooks/purity)
  - Token expiry badge: red 'expired' | amber '~Xm' (<30min) | hidden
  - 'Token' button (amber) next to 'Retest' for OAuth connections

- Add en.json i18n: tokenRefreshed, tokenRefreshFailed

* Initial plan

* feat: integrate wildcardRouter into model alias resolution (T13)

T13 - Wildcard Model Routing
- Import resolveWildcardAlias from wildcardRouter.ts into model.ts
- In getModelInfoCore(), after exact alias check fails, try glob wildcard
  alias matching (e.g., 'claude-sonnet-*' alias → 'anthropic/claude-sonnet-4')
- Returns { provider, model, extendedContext, wildcardPattern } on match
- Falls back to MODEL_TO_PROVIDERS lookup and openai default as before

* fix: clipboard cleanup and tool validation

* feat: media page UX + T04 playground uploads + T03 HuggingFace/Vertex AI

Media Page (MediaPageClient.tsx):
- Render images inline (img tags from b64_json or url)
- Show transcription as plain readable text (not raw JSON)
- Amber banner for credential errors with link to /dashboard/providers
- Detect empty transcription result and show credentials hint
- Provider credential hint below selector for non-local providers
- Extended provider/model lists: HuggingFace, Qwen TTS, Inworld, Cartesia, PlayHT, AssemblyAI

T04 - Playground File Uploads (playground/page.tsx):
- Audio file upload panel for transcription endpoint (multipart/form-data)
- Image upload panel for vision models (gpt-4o, claude-3, gemini, pixtral, llava...)
- Auto-detect vision models by name heuristic
- Inject uploaded images as base64 image_url in chat messages
- Inline image rendering for image generation results
- Readable text view for transcription results with copy button
- Preview thumbnails for attached images with individual remove

T03 - HuggingFace + Vertex AI Providers:
- HuggingFace: frontend providers.ts + backend providerRegistry.ts
  Uses HuggingFace Router OpenAI-compatible endpoint
- Vertex AI: frontend providers.ts + backend providerRegistry.ts
  Uses gemini format with generateContent API (urlBuilder fallback)

T07 - API Key Round-Robin: VERIFIED already implemented in auth.ts
  fill-first, round-robin, p2c, random, least-used, cost-optimized strategies

* feat: T05 task-aware routing + fix #302 stream override + fix #73 claude provider fallback

T05 - Task-Aware Smart Routing:
- New open-sse/services/taskAwareRouter.ts:
  Detects 7 task types: coding, creative, analysis, vision, summarization,
  background, chat from system/user message content and images
  Configurable taskModelMap per task type, stats tracking
  applyTaskAwareRouting() integrates with existing chat pipeline
- New src/app/api/settings/task-routing/route.ts:
  GET/PUT/POST API for task routing config + reset-stats + detect action
  Persists config via updateSettings('taskRouting')
- Integration in src/sse/handlers/chat.ts:
  applyTaskAwareRouting() called after policy enforcement, before combo resolve
  Logs task type detection and model overrides

Fix #302 - OpenAI SDK stream=False drops tool_calls:
- src/sse/handlers/chat.ts T01 Accept header negotiation:
  Changed condition from 'body.stream !== true' to 'body.stream === undefined'
  OpenAI Python SDK sends 'Accept: application/json, text/event-stream' in every
  request, even stream=False — the old code was incorrectly forcing stream=true,
  causing tool_calls to be dropped from non-streaming responses

Fix #73 - Claude Haiku routed to OpenAI provider instead of Antigravity:
- open-sse/services/model.ts getModelInfoCore():
  Added heuristic prefix detection before the blind 'openai' fallback:
  claude-* models → antigravity (Anthropic) provider
  gemini-*/gemma-* models → gemini provider
  Closes: #73, partially addresses #302

* fix: token counts 0 (#74), model import dup (#180), model route fallback (#73)

fix #74 - Token counts always 0 for Antigravity/Claude streaming:
- open-sse/utils/usageTracking.ts extractUsage():
  Add handler for 'message_start' SSE event which carries INPUT tokens in
  Antigravity/Claude streaming:
  { type: 'message_start', message: { usage: { input_tokens: N } } }
  This event was completely unhandled, causing ALL input token counts to be
  dropped for every Antigravity/Claude streaming request

fix #180 - Model import shows duplicates with no visual feedback:
- src/shared/components/ModelSelectModal.tsx:
  Added addedModelValues prop (string[]) to receive already-added model values
  Models already in the combo now shown with ✓ indicator + green highlight
  Makes it visually clear which models are already added vs new
- src/app/(dashboard)/dashboard/combos/page.tsx:
  Pass addedModelValues={models.map(m => m.model)} to ModelSelectModal

* Harden clipboard UX and Claude tool normalization (#360)

* Initial plan

* chore: plan updates for clipboard and translator fixes

* fix: clipboard cleanup, copy feedback, and claude tool validation

---------

Co-authored-by: openai-code-agent[bot] <242516109+Codex@users.noreply.github.com>
Co-authored-by: diegosouzapw <diegosouzapw@users.noreply.github.com>

---------

Co-authored-by: diegosouzapw <diegosouzapw@users.noreply.github.com>
Co-authored-by: openai-code-agent[bot] <242516109+Codex@users.noreply.github.com>
2026-03-14 10:59:15 -03:00
diegosouzapw
26f927f798 fix: replace sequential Account N with stable ID-based fallback for OAuth accounts
Remove Account cntValue+1 sequential naming (confusing when accounts deleted)
Leave name=null when no email → getAccountDisplayName returns Account ID-based label
2026-03-12 12:23:51 -03:00
jack
6cad4fae8e fix(providers): persist supported endpoints with explicit save for custom models 2026-03-11 11:20:25 +00:00
Diego Rodrigues de Sa e Souza
ce560ebe9d fix: resolve issues #273, #276, #277 — image routing, models route, missing-key error (#282)
Squash merge PR #282: bug fixes for #273 (Gemini image routing), #276 (Ollama Cloud models), #277 (missing apiKey error), lint fix, and all security code-scanning patches.
2026-03-10 09:48:50 -03:00
diegosouzapw
97a67b5d3e fix: persist lastUsedAt in provider_connections schema for round-robin (#218)
- Add last_used_at column to provider_connections CREATE TABLE schema
- Add ensureProviderConnectionsColumns migration for existing databases
- Add last_used_at to INSERT and UPDATE SQL in providers.ts
- Add last_used_at to JSON migration INSERT in core.ts
- Add zod to serverExternalPackages in next.config.mjs (#217)

Fixes #218: Round-robin routing strategy now correctly persists
the lastUsedAt timestamp, allowing rotation between accounts.

Fixes #217: zod module is now properly included in standalone/Docker
builds by declaring it as a server external package.
2026-03-05 23:22:10 -03:00
diegosouzapw
228ebf436e feat: endpoint-aware model management + fix 3 bugs (#212, #213, #200)
Bug Fixes:
- #212: Auto-generate API_KEY_SECRET at startup (like JWT_SECRET)
- #213: Circuit breaker now scoped per-model instead of per-provider
- #200: Connectivity fallback for custom providers (Ollama, LM Studio)

Features:
- #204: API Format selector (Chat Completions / Responses API) for custom models
- #205: Combo endpoint field (chat / embeddings / images) in schema
- #206: Supported Endpoints checkboxes (chat, embeddings, images, audio)
- Custom models with endpoint tags appear in /v1/embeddings and /v1/images/generations
- Model catalog includes api_format, type, and supported_endpoints metadata
- Provider detail page shows badges for non-default endpoint configurations

Files changed: instrumentation.ts, combo.ts, validation.ts, models.ts,
schemas.ts, provider-models/route.ts, providers/[id]/page.tsx,
catalog.ts, embeddings/route.ts, images/generations/route.ts
2026-03-05 18:49:07 -03:00
diegosouzapw
baa0208fa9 feat: v2.0.0 - MCP server, A2A agent, proxy improvements and docs update 2026-03-05 01:16:56 -03:00
diegosouzapw
85c6b63c8f feat: add error pages, harden DB layer and compliance module
- Add HTTP error pages (400, 401, 403, 408, 429, 500, 502, 503)
- Add maintenance, offline, and system status pages
- Harden db/core.ts, db/apiKeys.ts, db/cliToolState.ts, db/backup.ts
- Strengthen compliance/index.ts audit logging
- Improve container.ts DI registrations
- Fix dataPaths.ts and tokenHealthCheck.ts
2026-03-04 19:35:38 -03:00
diegosouzapw
052eb8d330 refactor: replace any types with generics and add Zod validation schemas
Eliminate `any` usage across the codebase by introducing proper generics,
typed interfaces (StatementLike, DbLike, PromptRow, etc.), and helper
conversion functions (toNumber, toString, parseVariables). Add
comprehensive Zod validation schemas for API endpoint inputs to enforce
runtime type safety alongside compile-time checks.
2026-03-04 18:59:27 -03:00
diegosouzapw
7eb45b2e19 feat: add MCP server mode with --mcp flag for IDE integration
Add stdio-based MCP server support to OmniRoute CLI, enabling AI agents
in VS Code, Cursor, Claude Desktop, and Copilot to interact with
OmniRoute tools (health, combos, quota, routing). Update help text,
gitignore vscode-extension subproject, and include MCP/A2A strategy report.
2026-03-03 17:42:24 -03:00
duongvdo
0e207dc5d2 fix: proxy logic bugs and Docker build failure
- URL-encode proxy credentials to handle special characters in passwords
- Decode URL-encoded credentials during legacy proxy migration
- Fix HTTPS proxy default port (443 instead of 8080) in frontend and migration
- Add dispatcher cache invalidation when proxy config changes
- Cast proxy port to number for SQLite INTEGER column in proxy logger
- Fix redundant .replace("//", "") in migration protocol parsing
- Copy postinstall script in Dockerfile before npm install

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 00:48:27 +07:00
diegosouzapw
d8bf4b1db8 chore(release): bump version to v1.6.3 2026-02-28 00:55:59 -03:00
diegosouzapw
12f7d2b484 fix: preserve database data on upgrade when old schema_migrations exists (#146)
Previously, the upgrade detection logic renamed the entire DB file when it
found a schema_migrations table (from older versions), causing data loss.
Now checks if the DB actually contains data (provider_connections) before
deciding to rename. If data exists, drops only the old migration tracking
table and lets the new CREATE TABLE IF NOT EXISTS schema take over.
2026-02-28 00:54:07 -03:00
diegosouzapw
62069dac98 fix: handle EACCES on restricted home directories (#133)
Wrap fs.mkdirSync(DATA_DIR) in try/catch so OmniRoute doesn't crash
when the user's home directory is not writable (e.g. restricted
environments, npm global install with different user).
Prints a clear warning with DATA_DIR env var recommendation.
2026-02-25 18:41:54 -03:00
diegosouzapw
bc55911d0f fix: allow multiple Codex accounts from same workspace (Team/Business)
Root cause: createProviderConnection() upsert logic for codex deduplicates
by workspaceId only (chatgpt_account_id from JWT). Two Pro Business accounts
from the same Team workspace resolve to the same workspaceId, causing the
second to silently overwrite the first.

Fix: compound uniqueness check using workspaceId + email, so different users
within the same workspace create separate connections. Includes backward-compat
fallback for old connections without email (they'll still be updated).
2026-02-25 15:32:23 -03:00
nyatoru
ac3d251a1a fix(db): clear prepared statements on backup restore 2026-02-24 00:35:29 +07:00
nyatoru
7ed40c2139 fix(db): enforce stricter validation for api key model access 2026-02-24 00:14:50 +07:00
nyatoru
d2bee37e76 feat(api-manager): implement API key management with new endpoints and UI
- Add GET/PATCH endpoints for retrieving and updating API key permissions

- Move API key management from Endpoint page to dedicated API Manager page

- Add allowed_models column to database schema for model-specific access

- Implement caching layer for improved API key validation performance
2026-02-23 23:59:34 +07:00
nyatoru
0610909116 feat(codex): add workspace binding via chatgpt-account-id header 2026-02-23 01:11:53 +07:00
diegosouzapw
03965bf768 fix(db): remove OAuth fallback overwrite when email is missing to natively support multiple accounts 2026-02-21 13:04:06 -03:00
diegosouzapw
340dcf9515 feat(core): api key protection, provider blocking, windows fix, ui and docs 2026-02-21 09:05:59 -03:00
diegosouzapw
5a645973eb fix(ui): correct Quick Start API key link to /dashboard/endpoint
- HomePageClient.tsx: 'Settings → API Keys' → 'Endpoint → Registered Keys'
- docs/page.tsx: same fix in Quick Start step 2
- Also includes user's manual fixes: bodySizeGuard, container imports, migrationRunner ESM compat
2026-02-18 16:40:33 -03:00
diegosouzapw
7efbfad9bd feat(phase2+3): DI container, plugins, PII sanitizer, tool policy, audit log, cache invalidation, ARIA, CSS vars
Phase 2 — Architecture & Quality:
- A-5: DI container (src/lib/container.ts)
- L-6: Prompt versioning (src/lib/db/prompts.ts)
- L-7: Eval scheduler (src/lib/evals/scheduler.ts)
- L-8: Plugin architecture (src/lib/plugins/index.ts)
- T-3: Integration tests (42 tests, 9 suites)

Phase 3 — UX & Polish:
- P-1: 500 error page (src/app/error.tsx)
- P-2: Audit log viewer (dashboard/audit-log/page.tsx)
- U-2: ARIA attributes on error pages
- U-5: Typed global-error.tsx params
- U-6: CSS variables for accent/semantic/traffic colors
- L-3: Output PII sanitization (src/lib/piiSanitizer.ts)
- L-4: Tool-calling allowlist/denylist (src/lib/toolPolicy.ts)
- L-9: Semantic cache invalidation API + auto-cleanup
- D-5: SECURITY.md updated to v1.0.x
- F-2: Deleted .env copy
2026-02-18 14:43:57 -03:00
diegosouzapw
3aca5fa691 feat: Implement initial database schema and centralize CORS configuration across API routes. 2026-02-18 13:44:08 -03:00
diegosouzapw
71d14209a4 feat: OmniRoute v1.0.0 — Intelligent AI Gateway & Universal LLM Proxy
OmniRoute is an intelligent API gateway that unifies 20+ AI providers behind a single
OpenAI-compatible endpoint. Features include intelligent routing with 6 strategies,
multi-format translation (OpenAI/Claude/Gemini/Responses API), circuit breakers,
semantic caching, combo fallback chains, real-time health monitoring, and a full
dashboard with provider management, analytics, and CLI tool integration.

Key highlights:
- 20+ providers (Claude Code, Codex, Gemini CLI, GitHub Copilot, iFlow, Qwen, Kiro, etc.)
- 6 routing strategies (Fill First, Round Robin, P2C, Random, Least Used, Cost Optimized)
- Export/Import database backup with full archive support
- Translator Playground with 4 modes (Playground, Chat Tester, Test Bench, Live Monitor)
- 100% TypeScript across src/ and open-sse/
- Docker support with multi-stage builds
- Comprehensive documentation and 9 dashboard screenshots
2026-02-18 00:02:15 -03:00