chore(release): v3.6.9 — changelog, docs, version sync

This commit is contained in:
diegosouzapw
2026-04-18 09:07:57 -03:00
parent 7bc4ac1833
commit c8679b0c79
8 changed files with 41 additions and 15 deletions
+19
View File
@@ -4,6 +4,25 @@
---
## [3.6.9] — 2026-04-18
### ✨ New Features
- **feat(core):** Implement persistent API key, backup pruning, and GPU optimization (#1350, #1367, #1369)
### 🐛 Bug Fixes
- **fix(providers):** Resolve Claude passthrough corruption (#1359), Kimi-k2 reasoning header rejections (#1360), thinking parameter leaks (#1361), and Ollama proxy redirect drops (#1381)
- **fix(core):** Proxy lookup in key validation effectively respects the new ProxyRegistry environments (#1384)
- **fix(electron):** Resolve type error in Header electronAPI properties
- **fix(security):** Resolve CodeQL security alerts including safe prototype bindings (#151, #152, #154, #155-159)
### 🛠️ Maintenance
- **chore:** Sync infrastructure with docker postinstall components and secondary CodeQL analysis rules
---
## [3.6.8] — 2026-04-17
### ✨ New Features
+1 -1
View File
@@ -1,7 +1,7 @@
openapi: 3.1.0
info:
title: OmniRoute API
version: 3.6.8
version: 3.6.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,
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "omniroute-desktop",
"version": "3.6.8",
"version": "3.6.9",
"description": "OmniRoute Desktop Application",
"main": "main.js",
"author": {
+2 -2
View File
@@ -8,7 +8,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
**Key value:** One endpoint (`http://localhost:20128/v1`), unlimited models, zero downtime, minimal cost.
**Current version:** 3.6.8
**Current version:** 3.6.9
## Tech Stack
@@ -279,7 +279,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
└── .env.example # Environment variable template
```
## Key Features (v3.6.8)
## Key Features (v3.6.9)
### Core Proxy
- **60+ AI providers** with automatic format translation
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@omniroute/open-sse",
"version": "3.6.8",
"version": "3.6.9",
"description": "Express SSE sidecar for OmniRoute — handles streaming, protocol translation, and provider orchestration",
"type": "module",
"main": "index.js",
+1 -1
View File
@@ -20962,7 +20962,7 @@
},
"open-sse": {
"name": "@omniroute/open-sse",
"version": "3.6.8"
"version": "3.6.9"
}
}
}
+10 -4
View File
@@ -7,7 +7,7 @@ import {
isAnthropicCompatibleProvider,
} from "@/shared/constants/providers";
import { validateProviderApiKey } from "@/lib/providers/validation";
import { getProxyForLevel } from "@/lib/localDb";
import { getProxyForLevel, resolveProxyForProvider } from "@/lib/localDb";
import { validateProviderApiKeySchema } from "@/shared/validation/schemas";
import { isValidationFailure, validateBody } from "@/shared/validation/helpers";
import { runWithProxyContext } from "@omniroute/open-sse/utils/proxyFetch.ts";
@@ -87,10 +87,16 @@ export async function POST(request) {
};
}
const providerProxy = await getProxyForLevel("provider", provider);
const globalProxy = providerProxy ? null : await getProxyForLevel("global");
const registryProxy = await resolveProxyForProvider(provider);
let proxyToUse = registryProxy;
const result = await runWithProxyContext(providerProxy || globalProxy || null, () =>
if (!proxyToUse) {
const providerProxy = await getProxyForLevel("provider", provider);
const globalProxy = providerProxy ? null : await getProxyForLevel("global");
proxyToUse = providerProxy || globalProxy || null;
}
const result = await runWithProxyContext(proxyToUse || null, () =>
validateProviderApiKey({
provider,
apiKey,
@@ -581,12 +581,12 @@ test("chatCore auto cache policy becomes false for nondeterministic combos", asy
responseFormat: "claude",
});
assert.equal(call.body.system[0].text.includes("You are Claude Code"), true);
assert.equal(call.body.system[0].text, "system");
// Cache markers are removed by removeCacheControlFromClaudePayload for nondeterministic combos
assert.equal(
call.body.system.some((block) => block.cache_control?.ttl === "5m"),
call.body.system.some((block) => !!block.cache_control),
false
);
assert.equal(call.body.system.at(-1).cache_control?.ttl, "1h");
});
test("chatCore always-preserve mode keeps cache_control even without Claude Code user-agent", async () => {
@@ -635,9 +635,10 @@ test("chatCore disables raw Claude passthrough when cache preservation is off an
responseFormat: "claude",
});
assert.equal(call.body.system[0].text.includes("You are Claude Code"), true);
assert.equal(call.body.system.at(-1).cache_control?.ttl, "1h");
assert.equal(call.body.system[0].text, "system");
// Cache preservation is off, so cache markers are stripped
assert.equal(call.body.messages[0].content[0].cache_control, undefined);
// Tools disable flag is applied
assert.equal("_disableToolPrefix" in call.body, false);
});