chore(release): v3.6.9 — changelog, docs, version sync
This commit is contained in:
@@ -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
@@ -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,6 +1,6 @@
|
||||
{
|
||||
"name": "omniroute-desktop",
|
||||
"version": "3.6.8",
|
||||
"version": "3.6.9",
|
||||
"description": "OmniRoute Desktop Application",
|
||||
"main": "main.js",
|
||||
"author": {
|
||||
|
||||
@@ -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,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",
|
||||
|
||||
Generated
+1
-1
@@ -20962,7 +20962,7 @@
|
||||
},
|
||||
"open-sse": {
|
||||
"name": "@omniroute/open-sse",
|
||||
"version": "3.6.8"
|
||||
"version": "3.6.9"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user