mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-08-03 22:02:08 +03:00
* chore(release): v3.7.4 — version bump, openapi and changelog sync * fix: preserve previous_response_id and conversation_id fields on empty input array (#1729) * fix: bypass UI validation block for optional API keys and fix string fallback typing (#1721) * fix(proxy): disable HTTP keep-alive and pipelining in Undici proxy dispatcher to prevent socket hang up * feat(proxy): implement bulk proxy import via pipe-delimited parser with update-or-create logic * docs: update changelog for v3.7.4 fixes and proxy features * test: update responses store expectations for empty input arrays * feat(pwa): add fullscreen installable PWA with manifest, service worker, and cross-platform app icons. (#1728) Integrated into release/v3.7.4 * Fix image provider validation and Stability image requests (#1726) Integrated into release/v3.7.4 * docs: add PR 1726 and PR 1728 to v3.7.4 changelog * fix(security): replace insecure Math.random with crypto.getRandomValues for fallback UUID generation * fix(migrations): intercept 007 migration to use IF NOT EXISTS logic on fresh installs Fixes #1733 * test: fix typescript compilation errors in unit tests * fix(db): reconcile legacy reasoning cache migration * chore(release): bump to v3.7.4 — changelog, docs, version sync * fix(cc-compatible): preserve Claude Code system skeleton (#1740) Integrated into release/v3.7.4 * docs(changelog): update for PR #1740 merge * docs(changelog): include workflow updates * fix(db): reconcile legacy reasoning cache migration (#1734) Integrated into release/v3.7.4 * Add endpoint tunnel visibility settings (#1743) Integrated into release/v3.7.4 * Normalize max reasoning effort for Codex routing (#1744) Integrated into release/v3.7.4 * Fix Claude Code gateway config helper (#1745) Integrated into release/v3.7.4 * Refresh CLI fingerprint provider profiles (#1746) Integrated into release/v3.7.4 * Integrated into release/v3.7.4 (PR #1742) * docs(changelog): update for PRs 1742-1746 --------- Co-authored-by: diegosouzapw <diegosouzapw@users.noreply.github.com> Co-authored-by: Yash Ghule <y.ghule77@gmail.com> Co-authored-by: backryun <bakryun0718@proton.me> Co-authored-by: dhaern <manker_lol@hotmail.com> Co-authored-by: Randi <55005611+rdself@users.noreply.github.com> Co-authored-by: Duncan L <leungd@gmail.com>
100 lines
3.6 KiB
TypeScript
100 lines
3.6 KiB
TypeScript
import { Inter } from "next/font/google";
|
|
import "./globals.css";
|
|
import { ThemeProvider } from "@/shared/components/ThemeProvider";
|
|
import { NextIntlClientProvider } from "next-intl";
|
|
import { getMessages, getLocale } from "next-intl/server";
|
|
import { RTL_LOCALES } from "@/i18n/config";
|
|
import { getSettings } from "@/lib/db/settings";
|
|
import type { Viewport } from "next";
|
|
import { PwaRegister } from "@/shared/components/PwaRegister";
|
|
|
|
const inter = Inter({
|
|
subsets: ["latin"],
|
|
variable: "--font-inter",
|
|
});
|
|
|
|
export const viewport: Viewport = {
|
|
themeColor: "#0b0f1a",
|
|
viewportFit: "cover",
|
|
};
|
|
|
|
export async function generateMetadata() {
|
|
const settings = await getSettings();
|
|
const instanceName = settings?.instanceName || "OmniRoute";
|
|
const customFaviconUrl = settings?.customFaviconUrl || settings?.customFaviconBase64;
|
|
|
|
return {
|
|
title: `${instanceName} — AI Gateway for Multi-Provider LLMs`,
|
|
description:
|
|
"OmniRoute is an AI gateway for multi-provider LLMs. One endpoint for all your AI providers.",
|
|
manifest: "/manifest.webmanifest",
|
|
applicationName: instanceName,
|
|
appleWebApp: {
|
|
capable: true,
|
|
title: instanceName,
|
|
statusBarStyle: "black-translucent",
|
|
},
|
|
other: {
|
|
"mobile-web-app-capable": "yes",
|
|
},
|
|
icons: {
|
|
icon: customFaviconUrl
|
|
? "/api/settings/favicon"
|
|
: [
|
|
{ url: "/favicon.ico", sizes: "any" },
|
|
{ url: "/favicon.svg", type: "image/svg+xml" },
|
|
{ url: "/icon-512.png", type: "image/png", sizes: "512x512" },
|
|
],
|
|
apple: [{ url: "/apple-touch-icon.png", sizes: "180x180", type: "image/png" }],
|
|
},
|
|
};
|
|
}
|
|
|
|
export default async function RootLayout({ children }) {
|
|
const locale = await getLocale();
|
|
const messages = await getMessages();
|
|
const isRtl = RTL_LOCALES.includes(locale as (typeof RTL_LOCALES)[number]);
|
|
|
|
return (
|
|
<html lang={locale} dir={isRtl ? "rtl" : "ltr"} suppressHydrationWarning>
|
|
<head>
|
|
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossOrigin="anonymous" />
|
|
{/* eslint-disable-next-line @next/next/no-page-custom-font */}
|
|
<link
|
|
href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@20..48,100..700,0..1,-50..200&display=swap"
|
|
rel="stylesheet"
|
|
/>
|
|
<script
|
|
dangerouslySetInnerHTML={{
|
|
__html: `
|
|
try {
|
|
const stored = localStorage.getItem('theme');
|
|
const parsed = stored ? JSON.parse(stored) : null;
|
|
const theme = parsed?.state?.theme || 'system';
|
|
if (theme === 'dark' || (theme === 'system' && window.matchMedia('(prefers-color-scheme: dark)').matches)) {
|
|
document.documentElement.classList.add('dark');
|
|
} else {
|
|
document.documentElement.classList.remove('dark');
|
|
}
|
|
} catch (e) {}
|
|
`,
|
|
}}
|
|
/>
|
|
</head>
|
|
<body className={`${inter.variable} font-sans antialiased`} suppressHydrationWarning>
|
|
<a
|
|
href="#main-content"
|
|
className="sr-only focus:not-sr-only focus:absolute focus:top-2 focus:left-2 focus:z-50 focus:px-4 focus:py-2 focus:bg-[#6366f1] focus:text-white focus:rounded-lg focus:text-sm focus:font-semibold focus:shadow-lg"
|
|
>
|
|
Skip to content
|
|
</a>
|
|
<NextIntlClientProvider locale={locale} messages={messages}>
|
|
<PwaRegister />
|
|
<ThemeProvider>{children}</ThemeProvider>
|
|
</NextIntlClientProvider>
|
|
</body>
|
|
</html>
|
|
);
|
|
}
|