mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-08-05 06:42:12 +03:00
chore: resolve merge conflicts in Dockerfile
This commit is contained in:
@@ -126,6 +126,7 @@ export async function PUT(request: Request, { params }: { params: Promise<{ id:
|
||||
healthCheckInterval,
|
||||
group,
|
||||
maxConcurrent,
|
||||
projectId,
|
||||
providerSpecificData: incomingPsd,
|
||||
} = body;
|
||||
|
||||
@@ -152,6 +153,7 @@ export async function PUT(request: Request, { params }: { params: Promise<{ id:
|
||||
if (healthCheckInterval !== undefined) updateData.healthCheckInterval = healthCheckInterval;
|
||||
if (group !== undefined) updateData.group = group;
|
||||
if (maxConcurrent !== undefined) updateData.maxConcurrent = maxConcurrent;
|
||||
if (projectId !== undefined) updateData.projectId = projectId;
|
||||
|
||||
// Merge providerSpecificData (partial update — preserve existing keys not sent by caller)
|
||||
if (incomingPsd !== undefined && incomingPsd !== null && typeof incomingPsd === "object") {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { NextResponse } from "next/server";
|
||||
import { getApiKeys } from "@/lib/db/apiKeys";
|
||||
import { getDbInstance } from "@/lib/db/core";
|
||||
|
||||
function getRangeStartIso(range: string): string | null {
|
||||
@@ -76,6 +77,16 @@ function uniqueValues(values: Array<string | null | undefined>): string[] {
|
||||
return result;
|
||||
}
|
||||
|
||||
function makeApiKeyUsageGroup(apiKeyId: string, fallbackName: string): string {
|
||||
return apiKeyId ? `id:${apiKeyId}` : `name:${fallbackName}`;
|
||||
}
|
||||
|
||||
function addApiKeyAlias(target: Set<string>, value: unknown): void {
|
||||
if (typeof value !== "string") return;
|
||||
const trimmed = value.trim();
|
||||
if (trimmed) target.add(trimmed);
|
||||
}
|
||||
|
||||
function stripCodexEffortSuffix(model: string): string {
|
||||
return model.replace(/-(?:xhigh|high|medium|low|none)$/i, "");
|
||||
}
|
||||
@@ -244,6 +255,13 @@ export async function GET(request: Request) {
|
||||
const presetsParam = searchParams.get("presets");
|
||||
|
||||
const db = getDbInstance();
|
||||
const apiKeys = await getApiKeys();
|
||||
const currentApiKeyNames = new Map<string, string>();
|
||||
for (const apiKey of apiKeys) {
|
||||
if (typeof apiKey.id === "string" && typeof apiKey.name === "string") {
|
||||
currentApiKeyNames.set(apiKey.id, apiKey.name);
|
||||
}
|
||||
}
|
||||
|
||||
const conditions = [];
|
||||
const params: Record<string, string> = {};
|
||||
@@ -296,7 +314,7 @@ export async function GET(request: Request) {
|
||||
COALESCE(SUM(tokens_input + tokens_output), 0) as totalTokens,
|
||||
COUNT(DISTINCT model) as uniqueModels,
|
||||
COUNT(DISTINCT connection_id) as uniqueAccounts,
|
||||
COUNT(DISTINCT api_key_id) as uniqueApiKeys,
|
||||
COUNT(DISTINCT COALESCE(NULLIF(api_key_id, ''), NULLIF(api_key_name, ''))) as uniqueApiKeys,
|
||||
COALESCE(SUM(CASE WHEN success = 1 THEN 1 ELSE 0 END), 0) as successfulRequests,
|
||||
COALESCE(AVG(latency_ms), 0) as avgLatencyMs,
|
||||
COALESCE(MIN(timestamp), '') as firstRequest,
|
||||
@@ -489,8 +507,8 @@ export async function GET(request: Request) {
|
||||
.prepare(
|
||||
`
|
||||
SELECT
|
||||
api_key_id as apiKeyId,
|
||||
COALESCE(NULLIF(api_key_name, ''), NULLIF(api_key_id, ''), 'Unknown API key') as apiKeyName,
|
||||
NULLIF(api_key_id, '') as apiKeyId,
|
||||
COALESCE(NULLIF(api_key_id, ''), NULLIF(api_key_name, ''), 'unknown') as apiKeyGroupKey,
|
||||
LOWER(provider) as provider,
|
||||
LOWER(model) as model,
|
||||
COUNT(*) as requests,
|
||||
@@ -502,11 +520,42 @@ export async function GET(request: Request) {
|
||||
COALESCE(SUM(tokens_input + tokens_output), 0) as totalTokens
|
||||
FROM usage_history
|
||||
${apiKeyWhereClause}
|
||||
GROUP BY api_key_id, api_key_name, LOWER(provider), LOWER(model)
|
||||
GROUP BY COALESCE(NULLIF(api_key_id, ''), NULLIF(api_key_name, ''), 'unknown'), NULLIF(api_key_id, ''), LOWER(provider), LOWER(model)
|
||||
`
|
||||
)
|
||||
.all(params) as Array<Record<string, unknown>>;
|
||||
|
||||
const apiKeyMetadataRows = db
|
||||
.prepare(
|
||||
`
|
||||
SELECT
|
||||
NULLIF(api_key_id, '') as apiKeyId,
|
||||
NULLIF(api_key_name, '') as apiKeyName,
|
||||
COALESCE(NULLIF(api_key_id, ''), NULLIF(api_key_name, ''), 'unknown') as apiKeyGroupKey,
|
||||
MAX(timestamp) as lastUsed
|
||||
FROM usage_history
|
||||
${apiKeyWhereClause}
|
||||
GROUP BY NULLIF(api_key_id, ''), NULLIF(api_key_name, '')
|
||||
ORDER BY lastUsed DESC
|
||||
`
|
||||
)
|
||||
.all(params) as Array<Record<string, unknown>>;
|
||||
|
||||
const apiKeyMetadata = new Map<string, { latestName: string; aliases: Set<string> }>();
|
||||
for (const row of apiKeyMetadataRows) {
|
||||
const apiKeyId = toStringValue(row.apiKeyId);
|
||||
const apiKeyGroupKey = toStringValue(row.apiKeyGroupKey, "unknown");
|
||||
const groupKey = makeApiKeyUsageGroup(apiKeyId, apiKeyGroupKey);
|
||||
const existing = apiKeyMetadata.get(groupKey) || {
|
||||
latestName: "",
|
||||
aliases: new Set<string>(),
|
||||
};
|
||||
const apiKeyName = toStringValue(row.apiKeyName);
|
||||
if (!existing.latestName && apiKeyName) existing.latestName = apiKeyName;
|
||||
addApiKeyAlias(existing.aliases, apiKeyName);
|
||||
apiKeyMetadata.set(groupKey, existing);
|
||||
}
|
||||
|
||||
const weeklyRows = db
|
||||
.prepare(
|
||||
`
|
||||
@@ -742,6 +791,7 @@ export async function GET(request: Request) {
|
||||
apiKey: string;
|
||||
apiKeyId: string | null;
|
||||
apiKeyName: string;
|
||||
historicalApiKeyNames: string[];
|
||||
requests: number;
|
||||
promptTokens: number;
|
||||
completionTokens: number;
|
||||
@@ -751,12 +801,20 @@ export async function GET(request: Request) {
|
||||
>();
|
||||
for (const row of apiKeyRows) {
|
||||
const apiKeyId = toStringValue(row.apiKeyId);
|
||||
const apiKeyName = toStringValue(row.apiKeyName, apiKeyId || "Unknown API key");
|
||||
const key = `${apiKeyId || "unknown"}::${apiKeyName}`;
|
||||
const apiKeyGroupKey = toStringValue(row.apiKeyGroupKey, "unknown");
|
||||
const key = makeApiKeyUsageGroup(apiKeyId, apiKeyGroupKey);
|
||||
const metadata = apiKeyMetadata.get(key);
|
||||
const apiKeyName =
|
||||
(apiKeyId ? currentApiKeyNames.get(apiKeyId) : undefined) ||
|
||||
metadata?.latestName ||
|
||||
apiKeyId ||
|
||||
apiKeyGroupKey ||
|
||||
"Unknown API key";
|
||||
const existing = apiKeyMap.get(key) || {
|
||||
apiKey: apiKeyId && apiKeyName !== apiKeyId ? `${apiKeyName} (${apiKeyId})` : apiKeyName,
|
||||
apiKeyId: apiKeyId || null,
|
||||
apiKeyName,
|
||||
historicalApiKeyNames: Array.from(metadata?.aliases || []),
|
||||
requests: 0,
|
||||
promptTokens: 0,
|
||||
completionTokens: 0,
|
||||
|
||||
@@ -16,6 +16,7 @@ import { getAllModerationModels } from "@omniroute/open-sse/config/moderationReg
|
||||
import { getAllVideoModels } from "@omniroute/open-sse/config/videoRegistry.ts";
|
||||
import { getAllMusicModels } from "@omniroute/open-sse/config/musicRegistry.ts";
|
||||
import { REGISTRY } from "@omniroute/open-sse/config/providerRegistry.ts";
|
||||
import { CODEX_NATIVE_UNPREFIXED_MODELS } from "@omniroute/open-sse/services/model.ts";
|
||||
import { getAllSyncedAvailableModels } from "@/lib/db/models";
|
||||
import { getCompatibleFallbackModels } from "@/lib/providers/managedAvailableModels";
|
||||
import { hasEligibleConnectionForModel } from "@/domain/connectionModelRules";
|
||||
@@ -25,6 +26,8 @@ import {
|
||||
getCatalogDiagnosticsHeaders,
|
||||
} from "@/lib/modelMetadataRegistry";
|
||||
import { isAuthRequired, isDashboardSessionAuthenticated } from "@/shared/utils/apiAuth";
|
||||
import { parseModel } from "@omniroute/open-sse/services/model.ts";
|
||||
import { getTokenLimit } from "@omniroute/open-sse/services/contextManager.ts";
|
||||
|
||||
const FALLBACK_ALIAS_TO_PROVIDER = {
|
||||
ag: "antigravity",
|
||||
@@ -313,6 +316,30 @@ export async function getUnifiedModelsResponse(
|
||||
// Add combos first (they appear at the top) — only active ones
|
||||
for (const combo of combos) {
|
||||
if (combo.isActive === false || combo.isHidden === true) continue;
|
||||
|
||||
// Calculate combo context length from its model targets.
|
||||
// OpenCode and other clients read context_length from the catalog; without it
|
||||
// they fall back to a conservative ~4000 token limit, causing truncation.
|
||||
const comboContextLength = Array.isArray(combo.models)
|
||||
? combo.models
|
||||
.filter((step) => step && step.kind === "model" && step.model)
|
||||
.map((step) => {
|
||||
const parsed = parseModel(step.model);
|
||||
const provider = parsed.provider || (step as any).providerId || "unknown";
|
||||
const model = parsed.model || step.model;
|
||||
return getTokenLimit(provider, model);
|
||||
})
|
||||
.filter((limit): limit is number => typeof limit === "number" && limit > 0)
|
||||
.reduce((min, limit) => Math.min(min, limit), Infinity)
|
||||
: undefined;
|
||||
|
||||
const effectiveContextLength =
|
||||
typeof combo.context_length === "number" && combo.context_length > 0
|
||||
? combo.context_length
|
||||
: comboContextLength !== undefined && comboContextLength !== Infinity
|
||||
? comboContextLength
|
||||
: undefined;
|
||||
|
||||
models.push({
|
||||
id: combo.name,
|
||||
object: "model",
|
||||
@@ -321,7 +348,7 @@ export async function getUnifiedModelsResponse(
|
||||
permission: [],
|
||||
root: combo.name,
|
||||
parent: null,
|
||||
...(combo.context_length ? { context_length: combo.context_length } : {}),
|
||||
...(effectiveContextLength !== undefined ? { context_length: effectiveContextLength } : {}),
|
||||
});
|
||||
}
|
||||
|
||||
@@ -377,6 +404,33 @@ export async function getUnifiedModelsResponse(
|
||||
}
|
||||
}
|
||||
|
||||
for (const modelId of CODEX_NATIVE_UNPREFIXED_MODELS) {
|
||||
if (!providerSupportsModel("codex", modelId)) continue;
|
||||
if (getModelIsHidden("codex", modelId)) continue;
|
||||
|
||||
const alias = providerIdToAlias.codex || "cx";
|
||||
const aliasId = `${alias}/${modelId}`;
|
||||
const providerIdModel = `codex/${modelId}`;
|
||||
const entries = [
|
||||
{ id: aliasId, parent: null },
|
||||
{ id: providerIdModel, parent: aliasId },
|
||||
{ id: modelId, parent: providerIdModel },
|
||||
];
|
||||
|
||||
for (const entry of entries) {
|
||||
if (models.some((existingModel) => existingModel.id === entry.id)) continue;
|
||||
models.push({
|
||||
id: entry.id,
|
||||
object: "model",
|
||||
created: timestamp,
|
||||
owned_by: "codex",
|
||||
permission: [],
|
||||
root: modelId,
|
||||
parent: entry.parent,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
const syncedModelsByProvider = await getAllSyncedAvailableModels();
|
||||
for (const [providerId, syncedModels] of Object.entries(syncedModelsByProvider)) {
|
||||
|
||||
Reference in New Issue
Block a user