mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-07-31 04:12:10 +03:00
* 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>
168 lines
5.9 KiB
JSON
168 lines
5.9 KiB
JSON
{
|
|
"name": "omniroute",
|
|
"version": "3.2.8",
|
|
"description": "Smart AI Router with auto fallback — route to FREE & cheap models, zero downtime. Works with Cursor, Cline, Claude Desktop, Codex, and any OpenAI-compatible tool.",
|
|
"type": "module",
|
|
"bin": {
|
|
"omniroute": "bin/omniroute.mjs",
|
|
"omniroute-reset-password": "bin/reset-password.mjs"
|
|
},
|
|
"files": [
|
|
"bin/",
|
|
"app/",
|
|
"open-sse/mcp-server/",
|
|
"src/shared/contracts/",
|
|
"scripts/postinstall.mjs",
|
|
"scripts/native-binary-compat.mjs",
|
|
"README.md",
|
|
"LICENSE"
|
|
],
|
|
"workspaces": [
|
|
"open-sse"
|
|
],
|
|
"engines": {
|
|
"node": ">=18.0.0 <24.0.0"
|
|
},
|
|
"keywords": [
|
|
"ai",
|
|
"router",
|
|
"proxy",
|
|
"openai",
|
|
"claude",
|
|
"anthropic",
|
|
"gemini",
|
|
"fallback",
|
|
"cursor",
|
|
"cline",
|
|
"codex",
|
|
"llm",
|
|
"auto-fallback"
|
|
],
|
|
"license": "MIT",
|
|
"author": "diegosouzapw",
|
|
"repository": {
|
|
"type": "git",
|
|
"url": "https://github.com/diegosouzapw/OmniRoute"
|
|
},
|
|
"homepage": "https://omniroute.online",
|
|
"scripts": {
|
|
"dev": "node scripts/run-next.mjs dev",
|
|
"build": "node scripts/build-next-isolated.mjs",
|
|
"build:cli": "node scripts/prepublish.mjs",
|
|
"start": "node scripts/run-next.mjs start",
|
|
"lint": "eslint .",
|
|
"electron:dev": "concurrently \"npm run dev\" \"wait-on http://localhost:20128 && cd electron && npm run dev\"",
|
|
"electron:build": "npm run build && cd electron && npm run build",
|
|
"electron:build:win": "npm run build && cd electron && npm run build:win",
|
|
"electron:build:mac": "npm run build && cd electron && npm run build:mac",
|
|
"electron:build:linux": "npm run build && cd electron && npm run build:linux",
|
|
"test": "node --import tsx/esm --test tests/unit/*.test.mjs",
|
|
"test:unit": "node --import tsx/esm --test tests/unit/*.test.mjs",
|
|
"test:plan3": "node --import tsx/esm --test tests/unit/plan3-p0.test.mjs",
|
|
"test:fixes": "node --import tsx/esm --test tests/unit/fixes-p1.test.mjs",
|
|
"test:security": "node --import tsx/esm --test tests/unit/security-fase01.test.mjs",
|
|
"check:cycles": "node scripts/check-cycles.mjs",
|
|
"check:route-validation:t06": "node scripts/check-route-validation.mjs",
|
|
"check:any-budget:t11": "node scripts/check-t11-any-budget.mjs",
|
|
"check:docs-sync": "node scripts/check-docs-sync.mjs",
|
|
"typecheck:core": "tsc --pretty false -p tsconfig.typecheck-core.json",
|
|
"typecheck:noimplicit:core": "tsc --pretty false -p tsconfig.typecheck-noimplicit-core.json",
|
|
"test:integration": "node --import tsx/esm --test tests/integration/*.test.mjs",
|
|
"test:e2e": "node scripts/run-playwright-tests.mjs test tests/e2e/*.spec.ts",
|
|
"test:protocols:e2e": "node scripts/run-protocol-clients-tests.mjs",
|
|
"test:vitest": "vitest run open-sse/mcp-server/__tests__/*.test.ts open-sse/services/autoCombo/__tests__/*.test.ts",
|
|
"test:ecosystem": "node scripts/run-ecosystem-tests.mjs",
|
|
"test:coverage": "c8 --exclude=tests/** --exclude=**/*.test.* --reporter=text-summary --reporter=html --reporter=json-summary --reporter=lcov --check-coverage --statements 55 --lines 55 --functions 55 --branches 60 node --import tsx/esm --test tests/unit/*.test.mjs",
|
|
"test:coverage:legacy": "c8 --exclude=open-sse --check-coverage --lines 50 --functions 50 --branches 50 node --import tsx/esm --test tests/unit/*.test.mjs",
|
|
"coverage:report": "c8 report --exclude=tests/** --exclude=**/*.test.* --reporter=text --reporter=text-summary --reporter=html --reporter=json-summary --reporter=lcov",
|
|
"coverage:report:legacy": "c8 report --exclude=open-sse --reporter=text --reporter=text-summary",
|
|
"test:all": "npm run test:unit && npm run test:vitest && npm run test:ecosystem && npm run test:e2e",
|
|
"check": "npm run lint && npm run test",
|
|
"prepublishOnly": "npm run build:cli",
|
|
"postinstall": "node scripts/postinstall.mjs",
|
|
"prepare": "husky",
|
|
"system-info": "node scripts/system-info.mjs"
|
|
},
|
|
"dependencies": {
|
|
"@lobehub/icons": "^5.0.1",
|
|
"@modelcontextprotocol/sdk": "^1.27.1",
|
|
"@monaco-editor/react": "^4.7.0",
|
|
"@swc/helpers": "0.5.19",
|
|
"bcryptjs": "^3.0.3",
|
|
"better-sqlite3": "^12.6.2",
|
|
"bottleneck": "^2.19.5",
|
|
"dompurify": "^3.3.2",
|
|
"express": "^5.2.1",
|
|
"fetch-socks": "^1.3.2",
|
|
"http-proxy-middleware": "^3.0.5",
|
|
"https-proxy-agent": "^8.0.0",
|
|
"jose": "^6.1.3",
|
|
"keytar": "^7.9.0",
|
|
"lowdb": "^7.0.1",
|
|
"monaco-editor": "^0.55.1",
|
|
"next": "^16.0.10",
|
|
"next-intl": "^4.8.3",
|
|
"node-machine-id": "^1.1.12",
|
|
"open": "^11.0.0",
|
|
"ora": "^9.1.0",
|
|
"pino": "^10.3.1",
|
|
"pino-pretty": "^13.1.3",
|
|
"react": "19.2.4",
|
|
"react-dom": "19.2.4",
|
|
"recharts": "^3.7.0",
|
|
"selfsigned": "^5.5.0",
|
|
"tsx": "^4.21.0",
|
|
"undici": "^7.19.2",
|
|
"uuid": "^13.0.0",
|
|
"wreq-js": "^2.0.1",
|
|
"zod": "^4.3.6",
|
|
"zustand": "^5.0.10"
|
|
},
|
|
"devDependencies": {
|
|
"@playwright/test": "^1.58.2",
|
|
"@tailwindcss/postcss": "^4.1.18",
|
|
"@types/bcryptjs": "^3.0.0",
|
|
"@types/better-sqlite3": "^7.6.13",
|
|
"@types/keytar": "^4.4.0",
|
|
"@types/node": "^25.2.3",
|
|
"@types/react": "^19.2.14",
|
|
"@types/react-dom": "^19.2.3",
|
|
"c8": "^11.0.0",
|
|
"concurrently": "^9.2.1",
|
|
"cross-env": "^10.1.0",
|
|
"eslint": "^9.39.2",
|
|
"eslint-config-next": "^16.0.10",
|
|
"husky": "^9.1.7",
|
|
"lint-staged": "^16.2.7",
|
|
"prettier": "^3.8.1",
|
|
"tailwindcss": "^4",
|
|
"typescript": "^5.9.3",
|
|
"typescript-eslint": "^8.56.0",
|
|
"vitest": "^4.0.18",
|
|
"wait-on": "^9.0.4"
|
|
},
|
|
"lint-staged": {
|
|
"*.{js,jsx,ts,tsx,mjs}": [
|
|
"prettier --write",
|
|
"eslint --fix --no-error-on-unmatched-pattern"
|
|
],
|
|
"*.{json,md,yml,yaml,css}": [
|
|
"prettier --write"
|
|
]
|
|
},
|
|
"pnpm": {
|
|
"onlyBuiltDependencies": [
|
|
"@parcel/watcher",
|
|
"@swc/core",
|
|
"better-sqlite3",
|
|
"esbuild",
|
|
"omniroute",
|
|
"sharp"
|
|
]
|
|
},
|
|
"overrides": {
|
|
"dompurify": "^3.3.2",
|
|
"path-to-regexp": "^8.4.0"
|
|
}
|
|
}
|