feat: cherry-pick PR #183 — multi-provider support, PWA, dynamic models, UI improvements

Cherry-picked from decolua/9router PR #183.
Note: open-sse changes included but need further review due to extensive modifications.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Quan
2026-02-25 11:40:50 +07:00
committed by decolua
co-authored by Cursor
parent 147fc168f9
commit 07717bad60
30 changed files with 773 additions and 159 deletions
+13 -5
View File
@@ -268,11 +268,11 @@ export async function markAccountUnavailable(connectionId, status, errorText, pr
export async function clearAccountError(connectionId, currentConnection) {
// Only update if currently has error status
const hasError = currentConnection.testStatus === "unavailable" ||
currentConnection.lastError ||
currentConnection.rateLimitedUntil;
currentConnection.lastError ||
currentConnection.rateLimitedUntil;
if (!hasError) return; // Skip if already clean
await updateProviderConnection(connectionId, {
testStatus: "active",
lastError: null,
@@ -280,17 +280,25 @@ export async function clearAccountError(connectionId, currentConnection) {
rateLimitedUntil: null,
backoffLevel: 0
});
log.info("AUTH", `Account ${connectionId.slice(0,8)} error cleared`);
log.info("AUTH", `Account ${connectionId.slice(0, 8)} error cleared`);
}
/**
* Extract API key from request headers
*/
export function extractApiKey(request) {
// Check Authorization header first
const authHeader = request.headers.get("Authorization");
if (authHeader?.startsWith("Bearer ")) {
return authHeader.slice(7);
}
// Check Anthropic x-api-key header
const xApiKey = request.headers.get("x-api-key");
if (xApiKey) {
return xApiKey;
}
return null;
}