mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-07-26 09:52:11 +03:00
- 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
This commit is contained in:
21
CHANGELOG.md
21
CHANGELOG.md
@@ -4,6 +4,27 @@
|
||||
|
||||
---
|
||||
|
||||
## [2.9.4] — 2026-03-21
|
||||
|
||||
> Sprint: Bug fixes — preserve Codex prompt cache key, fix tagContent JSON escaping, sync expired token status to DB.
|
||||
|
||||
### 🐛 Bug Fixes
|
||||
|
||||
- **fix(translator)**: Preserve `prompt_cache_key` in Responses API → Chat Completions translation (#517)
|
||||
— The field is a cache-affinity signal used by Codex; stripping it was preventing prompt cache hits.
|
||||
Fixed in `openai-responses.ts` and `responsesApiHelper.ts`.
|
||||
|
||||
- **fix(combo)**: Escape `\n` in `tagContent` so injected JSON string is valid (#515)
|
||||
— Template literal newlines (U+000A) are not allowed unescaped inside JSON string values.
|
||||
Replaced with `\\n` literal sequences in `open-sse/services/combo.ts`.
|
||||
|
||||
- **fix(usage)**: Sync expired token status back to DB on live auth failure (#491)
|
||||
— When the Limits & Quotas live check returns 401/403, the connection `testStatus` is now updated
|
||||
to `"expired"` in the database so the Providers page reflects the same degraded state.
|
||||
Fixed in `src/app/api/usage/[connectionId]/route.ts`.
|
||||
|
||||
---
|
||||
|
||||
## [2.9.3] — 2026-03-21
|
||||
|
||||
> Sprint: Add 5 new free AI providers — LongCat, Pollinations, Cloudflare AI, Scaleway, AI/ML API.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
openapi: 3.1.0
|
||||
info:
|
||||
title: OmniRoute API
|
||||
version: 2.9.3
|
||||
version: 2.9.4
|
||||
description: |
|
||||
OmniRoute is a local-first AI API proxy router. It provides an OpenAI-compatible
|
||||
endpoint that routes requests to multiple AI providers with load balancing,
|
||||
|
||||
4
package-lock.json
generated
4
package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "omniroute",
|
||||
"version": "2.9.3",
|
||||
"version": "2.9.4",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "omniroute",
|
||||
"version": "2.9.3",
|
||||
"version": "2.9.4",
|
||||
"hasInstallScript": true,
|
||||
"license": "MIT",
|
||||
"workspaces": [
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "omniroute",
|
||||
"version": "2.9.3",
|
||||
"version": "2.9.4",
|
||||
"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": {
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
import { getProviderConnectionById, updateProviderConnection, resolveProxyForConnection } from "@/lib/localDb";
|
||||
import {
|
||||
getProviderConnectionById,
|
||||
updateProviderConnection,
|
||||
resolveProxyForConnection,
|
||||
} from "@/lib/localDb";
|
||||
import { getMachineId } from "@/shared/utils/machine";
|
||||
import { getUsageForProvider } from "@omniroute/open-sse/services/usage.ts";
|
||||
import { getExecutor } from "@omniroute/open-sse/executors/index.ts";
|
||||
@@ -109,7 +113,10 @@ async function refreshAndUpdateCredentials(connection: any) {
|
||||
/**
|
||||
* GET /api/usage/[connectionId] - Get usage data for a specific connection
|
||||
*/
|
||||
export async function GET(request: Request, { params }: { params: Promise<{ connectionId: string }> }) {
|
||||
export async function GET(
|
||||
request: Request,
|
||||
{ params }: { params: Promise<{ connectionId: string }> }
|
||||
) {
|
||||
try {
|
||||
const { connectionId } = await params;
|
||||
|
||||
@@ -155,7 +162,34 @@ export async function GET(request: Request, { params }: { params: Promise<{ conn
|
||||
|
||||
// Populate quota cache for quota-aware account selection
|
||||
if (isRecord(usage?.quotas)) {
|
||||
setQuotaCache(connectionId, connection.provider, usage.quotas);
|
||||
setQuotaCache(
|
||||
connectionId,
|
||||
connection.provider as string,
|
||||
usage.quotas as Record<string, unknown>
|
||||
);
|
||||
}
|
||||
|
||||
// (#491) If the live usage check returned an auth error, sync the expired status
|
||||
// back to the DB so the Providers page reflects the same degraded state as
|
||||
// Limits & Quotas (which performs the live check).
|
||||
const errorMessage = typeof usage?.message === "string" ? usage.message.toLowerCase() : "";
|
||||
const isAuthError =
|
||||
errorMessage.includes("token expired") ||
|
||||
errorMessage.includes("access denied") ||
|
||||
errorMessage.includes("re-authenticate") ||
|
||||
errorMessage.includes("unauthorized");
|
||||
|
||||
if (isAuthError && connection.testStatus !== "expired") {
|
||||
try {
|
||||
await updateProviderConnection(connection.id as string, {
|
||||
testStatus: "expired",
|
||||
lastErrorType: "token_expired",
|
||||
lastErrorAt: new Date().toISOString(),
|
||||
});
|
||||
} catch (dbErr) {
|
||||
// Non-critical: log but don't block the response
|
||||
console.error("[Usage API] Failed to sync expired status to DB:", dbErr);
|
||||
}
|
||||
}
|
||||
|
||||
return Response.json(usage);
|
||||
|
||||
Reference in New Issue
Block a user