From 1d51d8ff275c61847955b8e9bdddf88cd6f012ce Mon Sep 17 00:00:00 2001 From: diegosouzapw Date: Sun, 29 Mar 2026 14:16:37 -0300 Subject: [PATCH] =?UTF-8?q?chore(release):=20v3.2.9=20=E2=80=94=20combo=20?= =?UTF-8?q?diagnostics,=20quality=20gates,=20Gemini=20tool=20fix?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 13 +++++++++++++ docs/openapi.yaml | 2 +- open-sse/handlers/chatCore.ts | 8 ++------ package-lock.json | 4 ++-- package.json | 2 +- tests/unit/combo-circuit-breaker.test.mjs | 4 +++- 6 files changed, 22 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3b80529020..54ffeb3cb1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,19 @@ --- +## [3.2.9] - 2026-03-29 + +### ✨ Enhancements & Refactoring + +- **Combo Diagnostics** — Introduced a live test bypass flag (`forceLiveComboTest`) allowing administrators to execute real upstream health checks that bypass all local circuit-breaker and cooldown state mechanisms, enabling precise diagnostics during rolling outages (PR #759) +- **Quality Gates** — Added automated response quality validation for combos and officially integrated `claude-4.6` model support into the core routing schemas (PR #762) + +### 🐛 Bug Fixes + +- **Tool Definition Validation** — Repaired Gemini API integration by normalizing enum types inside tool definitions, preventing upstream HTTP 400 parameter errors (PR #760) + +--- + ## [3.2.8] - 2026-03-29 ### ✨ Enhancements & Refactoring diff --git a/docs/openapi.yaml b/docs/openapi.yaml index 1a05ff089d..10ebe45d8c 100644 --- a/docs/openapi.yaml +++ b/docs/openapi.yaml @@ -1,7 +1,7 @@ openapi: 3.1.0 info: title: OmniRoute API - version: 3.2.8 + version: 3.2.9 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, diff --git a/open-sse/handlers/chatCore.ts b/open-sse/handlers/chatCore.ts index 0716069b63..d40376eb94 100644 --- a/open-sse/handlers/chatCore.ts +++ b/open-sse/handlers/chatCore.ts @@ -43,7 +43,7 @@ import { } from "@/lib/localDb"; import { getExecutor } from "../executors/index.ts"; import { getCacheControlSettings } from "@/lib/cacheControlSettings"; -import { shouldPreserveCacheControl, recordCacheHit } from "../utils/cacheControlPolicy.ts"; +import { shouldPreserveCacheControl } from "../utils/cacheControlPolicy.ts"; import { getCacheMetrics } from "@/lib/db/settings.ts"; import { @@ -1554,11 +1554,6 @@ export async function handleChatCore({ claudeCacheUsageMeta: cacheUsageLogMeta, }); - // Persist cache metrics to database - updateCacheMetrics(currentMetrics).catch((err) => { - log?.debug?.("CACHE", `Failed to persist cache metrics: ${err?.message || "unknown"}`); - }); - return { success: true, response: new Response(JSON.stringify(translatedResponse), { @@ -1595,6 +1590,7 @@ export async function handleChatCore({ responseBody: streamResponseBody, providerPayload, clientPayload, + ttft, }) => { const cacheUsageLogMeta = buildCacheUsageLogMeta(streamUsage); diff --git a/package-lock.json b/package-lock.json index 44e5079d62..fc170a47e5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "omniroute", - "version": "3.2.8", + "version": "3.2.9", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "omniroute", - "version": "3.2.8", + "version": "3.2.9", "hasInstallScript": true, "license": "MIT", "workspaces": [ diff --git a/package.json b/package.json index 9d5ccd2888..3f30a2403e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "omniroute", - "version": "3.2.8", + "version": "3.2.9", "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": { diff --git a/tests/unit/combo-circuit-breaker.test.mjs b/tests/unit/combo-circuit-breaker.test.mjs index 90d6d9e3de..d646066377 100644 --- a/tests/unit/combo-circuit-breaker.test.mjs +++ b/tests/unit/combo-circuit-breaker.test.mjs @@ -26,7 +26,7 @@ function mockLog() { function mockHandler(statusSequence) { let callIndex = 0; return async (body, modelStr) => { - const status = statusSequence[callIndex] ?? 200; + const status = statusSequence[callIndex] ?? statusSequence[statusSequence.length - 1] ?? 200; callIndex++; if (status === 200) { return new Response(JSON.stringify({ ok: true }), { status: 200 }); @@ -55,6 +55,7 @@ test("handleComboChat: circuit breaker opens after repeated 502 errors", async ( name: "test-combo", models: [{ model: "groq/llama-3.3-70b", weight: 0 }], strategy: "priority", + config: { maxRetries: 0 }, }; const log = mockLog(); @@ -74,6 +75,7 @@ test("handleComboChat: circuit breaker opens after repeated 502 errors", async ( // Breaker should now be OPEN const status = breaker.getStatus(); + console.log("=== BREAKER STATUS AFTER 3 CALLS ===", status); assert.equal(status.state, STATE.OPEN, "Breaker should be OPEN after 3 failures"); assert.equal(status.failureCount, 3, "Failure count should be 3"); });