Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@
**/venv/
**/__pycache__/**
private.*
.venv
.venv
**/temp/
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,7 @@ Choose higher settings (like the t3.xlarge profile above) for raw speed, or lowe

## 💬 Need Help?

**🔗 [Join our Discord](https://discord.gg/qPaAuTCv)** for:
**🔗 [Join our Discord](https://getmax.im/bifrost-discord)** for:

- ❓ Quick setup assistance and troubleshooting
- 💡 Best practices and configuration tips
Expand Down
2 changes: 1 addition & 1 deletion docs/benchmarks.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ _\*Bifrost's overhead is measured at 59 µs on t3.medium and 11 µs on t3.xlarge

**Note**: On the t3.xlarge, we tested with significantly larger response payloads (~10 KB average vs ~1 KB on t3.medium). Even so, response parsing time dropped dramatically thanks to better CPU throughput and Bifrost's optimized memory reuse.

**Disclaimer**: These metrics are measured without the UI enabled. When using the UI, there is no drop in performance - only memory usage increases due to the additional UI build being served.
**Disclaimer**: These metrics are measured without the UI logging enabled. When logging is enabled, there is no drop in performance - only memory usage increases due to the additional log storage being used.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick (assertive)

Minor punctuation nitpick

The spaced hyphen reads as a minus; an em-dash improves readability:

-... performance - only memory usage increases ...
+... performance—only memory usage increases ...

Totally optional.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
**Disclaimer**: These metrics are measured without the UI logging enabled. When logging is enabled, there is no drop in performance - only memory usage increases due to the additional log storage being used.
**Disclaimer**: These metrics are measured without the UI logging enabled. When logging is enabled, there is no drop in performanceonly memory usage increases due to the additional log storage being used.
🧰 Tools
🪛 LanguageTool

[typographical] ~46-~46: To join two clauses or set off examples, consider using an em dash.
Context: ...logging is enabled, there is no drop in performance - only memory usage increases due to the a...

(QB_NEW_EN_DASH_RULE_EM)


[grammar] ~46-~46: Use correct spacing
Context: ...due to the additional log storage being used. --- ## 🎯 Key Performance Highlights - **Perf...

(QB_NEW_EN_OTHER_ERROR_IDS_5)

🤖 Prompt for AI Agents
In docs/benchmarks.md at line 46, replace the spaced hyphen with an em-dash to
improve readability in the sentence about logging impact on performance and
memory usage. This involves changing the " - " to an em-dash character without
spaces around it.


---

Expand Down
4 changes: 2 additions & 2 deletions docs/contributing/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ cd ../transports-integrations/

### **💬 Need Help Contributing?**

**🔗 [Join our Discord](https://discord.gg/qPaAuTCv)** for:
**🔗 [Join our Discord](https://getmax.im/bifrost-discord)** for:

- ❓ Quick questions about contributing
- 💡 Discuss your contribution ideas
Expand Down Expand Up @@ -524,7 +524,7 @@ We value every contribution and recognize contributors:

- **💬 [GitHub Discussions](https://github.com/maximhq/bifrost/discussions)** - Questions, ideas, and general discussion
- **🐛 [GitHub Issues](https://github.com/maximhq/bifrost/issues)** - Bug reports and feature requests
- **🔗 [Discord Community](https://discord.gg/qPaAuTCv)** - Real-time chat and collaboration
- **🔗 [Discord Community](https://getmax.im/bifrost-discord)** - Real-time chat and collaboration

---

Expand Down
2 changes: 1 addition & 1 deletion docs/quickstart/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ After completing the quick start:

## 💡 Need Help?

- **[💬 Join Discord](https://discord.gg/qPaAuTCv)** - Real-time setup help and community support
- **[💬 Join Discord](https://getmax.im/bifrost-discord)** - Real-time setup help and community support
- **[🔍 Troubleshooting](../troubleshooting.md)** - Common issues and solutions
- **[❓ FAQ](../faq.md)** - Frequently asked questions
- **[📖 Full Documentation](../README.md)** - Complete documentation hub
Expand Down
2 changes: 1 addition & 1 deletion docs/quickstart/go-package.md
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@ response, err := client.ChatCompletionRequest(context.Background(), schemas.Chat

## 💬 Need Help?

**🔗 [Join our Discord](https://discord.gg/qPaAuTCv)** for real-time setup assistance and Go-specific support!
**🔗 [Join our Discord](https://getmax.im/bifrost-discord)** for real-time setup assistance and Go-specific support!

---

Expand Down
2 changes: 1 addition & 1 deletion docs/quickstart/http-transport.md
Original file line number Diff line number Diff line change
Expand Up @@ -325,7 +325,7 @@ response, err := http.Post(

## 💬 Need Help?

**🔗 [Join our Discord](https://discord.gg/qPaAuTCv)** for real-time setup assistance and HTTP integration support!
**🔗 [Join our Discord](https://getmax.im/bifrost-discord)** for real-time setup assistance and HTTP integration support!
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick (assertive)

Trim double space after exclamation

There’s a double space before the section divider:

-...support!  ---
+...support! ---

Purely cosmetic.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
**🔗 [Join our Discord](https://getmax.im/bifrost-discord)** for real-time setup assistance and HTTP integration support!
**🔗 [Join our Discord](https://getmax.im/bifrost-discord)** for real-time setup assistance and HTTP integration support! ---
🧰 Tools
🪛 LanguageTool

[grammar] ~328-~328: Use correct spacing
Context: ...e setup assistance and HTTP integration support! --- ## 📚 Learn More | What You Want ...

(QB_NEW_EN_OTHER_ERROR_IDS_5)

🤖 Prompt for AI Agents
In docs/quickstart/http-transport.md at line 328, there is a double space after
the exclamation mark before the section divider. Remove the extra space so that
only a single space remains after the exclamation mark to fix the spacing issue.


---

Expand Down
1 change: 0 additions & 1 deletion ui/app/config/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,6 @@ export default function ConfigPage() {

return (
<div className="bg-background">
<Header title="Configuration" />
{isLoadingProviders || isLoadingMcpClients ? (
<FullPageLoader />
) : (
Expand Down
1 change: 0 additions & 1 deletion ui/app/docs/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,6 @@ const docSections = [
export default function DocsPage() {
return (
<div className="bg-background">
<Header title="Documentation" />
<div className="mx-auto max-w-7xl">
<div className="space-y-8">
{/* Header */}
Expand Down
53 changes: 53 additions & 0 deletions ui/app/globals.css
Original file line number Diff line number Diff line change
Expand Up @@ -121,3 +121,56 @@
@apply bg-background text-foreground;
}
}

@utility custom-scrollbar {
overflow: auto !important;
scrollbar-width: thin; /* Firefox */
scrollbar-color: rgba(228, 228, 231, 1) transparent; /* Firefox */
Comment on lines +126 to +128
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick (assertive)

overflow: auto !important can clobber component-level overflow settings

For example, a modal with overflow-y-scroll will now become bi-directional. Unless every caller truly wants both axes, drop !important or split into two utilities (x-scrollbar, y-scrollbar) and apply them explicitly.

🤖 Prompt for AI Agents
In ui/app/globals.css around lines 126 to 128, the use of 'overflow: auto
!important' forces both horizontal and vertical scrolling, which can override
component-specific overflow settings like 'overflow-y-scroll' on modals. To fix
this, remove the '!important' flag from the overflow property or refactor by
splitting the overflow styles into separate utilities for horizontal and
vertical scrolling (e.g., 'x-scrollbar' and 'y-scrollbar') so they can be
applied explicitly and avoid unintended bi-directional scrolling.


&::-webkit-scrollbar {
--custom-scrollbar-width: 8px;
--custom-scrollbar-height: 8px;
width: var(--custom-scrollbar-width, 8px);
height: var(--custom-scrollbar-height, 8px);
touch-action: none;
}

&::-webkit-scrollbar-track {
background-color: transparent;
}

&::-webkit-scrollbar-thumb {
--tw-bg-opacity: 1 !important;
background-color: rgba(228, 228, 231, var(--tw-bg-opacity)) !important;
border-radius: 8px;
opacity: 0;
visibility: hidden;
}

&:hover::-webkit-scrollbar-thumb {
opacity: 1;
visibility: visible;
}

&::-webkit-scrollbar-thumb:hover {
--tw-bg-opacity: 1 !important;
background-color: rgba(82, 82, 91, var(--tw-bg-opacity)) !important;
}

/* For older WebKit browsers */
&::-webkit-scrollbar-thumb:horizontal {
background-color: rgba(228, 228, 231, var(--tw-bg-opacity)) !important;
}

&::-webkit-scrollbar-thumb:vertical {
background-color: rgba(228, 228, 231, var(--tw-bg-opacity)) !important;
}

&:hover::-webkit-scrollbar-thumb:horizontal {
background-color: rgba(82, 82, 91, var(--tw-bg-opacity)) !important;
}

&:hover::-webkit-scrollbar-thumb:vertical {
background-color: rgba(82, 82, 91, var(--tw-bg-opacity)) !important;
}
}
11 changes: 7 additions & 4 deletions ui/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { SidebarProvider } from "@/components/ui/sidebar";
import { ThemeProvider } from "@/components/theme-provider";
import { Toaster } from "sonner";
import ProgressProvider from "@/components/progress-bar";
import { WebSocketProvider } from "@/hooks/useWebSocket";

const geistSans = Geist({
variable: "--font-geist-sans",
Expand All @@ -30,10 +31,12 @@ export default function RootLayout({ children }: { children: React.ReactNode })
<ProgressProvider>
<ThemeProvider attribute="class" defaultTheme="system" enableSystem>
<Toaster />
<SidebarProvider>
<Sidebar />
<main className="relative mx-auto flex min-h-screen w-5xl flex-col pt-24 pb-12">{children}</main>
</SidebarProvider>
<WebSocketProvider>
<SidebarProvider>
<Sidebar />
<main className="custom-scrollbar relative mx-auto flex min-h-screen w-5xl flex-col py-12">{children}</main>
</SidebarProvider>
</WebSocketProvider>
</ThemeProvider>
</ProgressProvider>
</body>
Expand Down
23 changes: 14 additions & 9 deletions ui/app/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,12 @@ export default function LogsPage() {
[pagination.offset, pagination.sort_by, pagination.order, pagination.limit, filters, showEmptyState],
);

const { ws, isConnected: isSocketConnected } = useWebSocket({ onMessage: handleNewLog });
const { isConnected: isSocketConnected, setMessageHandler } = useWebSocket();

// Set up the message handler when the component mounts
useEffect(() => {
setMessageHandler(handleNewLog);
}, [handleNewLog, setMessageHandler]);

const fetchLogs = useCallback(async () => {
setFetchingLogs(true);
Expand All @@ -109,17 +114,18 @@ export default function LogsPage() {
setLogs(response.logs || []);
setTotalItems(response.stats.total_requests);
setStats(response.stats);
}

// Only set showEmptyState on initial load and only based on total logs
if (initialLoading) {
// Check if there are any logs globally, not just in the current filter
setShowEmptyState(response.stats.total_requests === 0);
}
// Only set showEmptyState on initial load and only based on total logs
if (initialLoading) {
// Check if there are any logs globally, not just in the current filter
setShowEmptyState(response ? response.stats.total_requests === 0 : true);
}
} catch {
setError("Failed to fetch logs. Please try again.");
setError("Cannot fetch logs. Please check if logs are enabled in your Bifrost config.");
setLogs([]);
setTotalItems(0);
setShowEmptyState(true);
} finally {
setFetchingLogs(false);
}
Expand Down Expand Up @@ -225,11 +231,10 @@ export default function LogsPage() {

return (
<div className="bg-background">
<Header title="Request Logs" />
{initialLoading ? (
<FullPageLoader />
) : showEmptyState ? (
<EmptyState isSocketConnected={isSocketConnected} />
<EmptyState isSocketConnected={isSocketConnected} error={error} />
) : (
<div className="space-y-6">
<div>
Expand Down
31 changes: 23 additions & 8 deletions ui/app/plugins/page.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
"use client";

import Header from "@/components/header";
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
import { Button } from "@/components/ui/button";
Expand All @@ -21,6 +23,8 @@ import {
} from "lucide-react";
import Link from "next/link";
import GradientHeader from "@/components/ui/gradient-header";
import Image from "next/image";
import { useTheme } from "next-themes";

const featuredPlugins = [
{
Expand Down Expand Up @@ -54,7 +58,7 @@ const featuredPlugins = [
"Latency simulation",
],
icon: Code,
color: "bg-green-500",
color: "bg-blue-500",
url: "https://github.com/maximhq/bifrost/tree/main/plugins/mocker",
quickStart: {
http: "HTTP support coming soon",
Expand All @@ -66,7 +70,7 @@ const featuredPlugins = [
displayName: "Circuit Breaker",
description: "Resilience patterns for handling provider failures and preventing cascade errors",
category: "Reliability",
status: "available",
status: "enterprise",
httpSupport: false,
capabilities: ["Automatic failure detection", "Fallback mechanisms", "Rate limiting", "Health monitoring", "Recovery strategies"],
icon: Shield,
Expand Down Expand Up @@ -101,9 +105,9 @@ const upcomingPlugins = [
];

export default function PluginsPage() {
const { resolvedTheme } = useTheme();
return (
<div className="bg-background min-h-screen">
<Header title="Plugins" />
<div className="mx-auto max-w-7xl">
<div className="space-y-12">
{/* Hero Section */}
Expand Down Expand Up @@ -161,11 +165,22 @@ export default function PluginsPage() {
<Card key={plugin.name} className="group hover:border-primary/50 border-2 transition-all duration-300 hover:shadow-xl">
<CardHeader>
<div className="flex items-start justify-between">
<div className={`rounded-xl p-3 ${plugin.color} bg-opacity-10`}>
<Icon className={`h-8 w-8 ${plugin.color.replace("bg-", "text-")}`} />
</div>
<Badge variant={plugin.status === "production" ? "default" : "secondary"} className="text-xs">
{plugin.status === "production" ? "Production" : "Available"}
{plugin.name == "maxim" ? (
<Image
src={`/maxim-logo${resolvedTheme === "dark" ? "-dark" : ""}.png`}
alt="Maxim"
width={32}
height={32}
className="h-14 w-auto"
/>
) : (
<div className={`rounded-xl p-3 ${plugin.color} bg-opacity-10`}>
<Icon className={`h-8 w-8 ${plugin.color.replace("bg-", "text-")}`} />
</div>
)}

<Badge variant={plugin.status === "production" ? "default" : "secondary"} className="text-xs capitalize">
{plugin.status}
</Badge>
</div>

Expand Down
47 changes: 8 additions & 39 deletions ui/components/config/core-settings-list.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,16 @@ export default function CoreSettingsList() {
const [config, setConfig] = useState<CoreConfig>({
drop_excess_requests: false,
initial_pool_size: 300,
log_queue_size: 1000,
enable_logging: true,
});
const [droppedRequests, setDroppedRequests] = useState<number>(0);
const [isLoading, setIsLoading] = useState(true);
const [localValues, setLocalValues] = useState<{
initial_pool_size: string;
prometheus_labels: string;
log_queue_size: string;
}>({
initial_pool_size: "300",
prometheus_labels: "",
log_queue_size: "1000",
});

useEffect(() => {
Expand All @@ -46,7 +44,6 @@ export default function CoreSettingsList() {
// Use refs to store timeout IDs
const poolSizeTimeoutRef = useRef<NodeJS.Timeout | undefined>(undefined);
const prometheusLabelsTimeoutRef = useRef<NodeJS.Timeout | undefined>(undefined);
const logQueueSizeTimeoutRef = useRef<NodeJS.Timeout | undefined>(undefined);

useEffect(() => {
const fetchConfig = async () => {
Expand All @@ -58,7 +55,6 @@ export default function CoreSettingsList() {
setLocalValues({
initial_pool_size: coreConfig.initial_pool_size?.toString() || "300",
prometheus_labels: coreConfig.prometheus_labels || "",
log_queue_size: coreConfig.log_queue_size?.toString() || "1000",
});
}
setIsLoading(false);
Expand Down Expand Up @@ -122,26 +118,6 @@ export default function CoreSettingsList() {
[updateConfig],
);

const handleLogQueueSizeChange = useCallback(
(value: string) => {
setLocalValues((prev) => ({ ...prev, log_queue_size: value }));

// Clear existing timeout
if (logQueueSizeTimeoutRef.current) {
clearTimeout(logQueueSizeTimeoutRef.current);
}

// Set new timeout
logQueueSizeTimeoutRef.current = setTimeout(() => {
const numValue = Number.parseInt(value);
if (!isNaN(numValue) && numValue > 0) {
updateConfig("log_queue_size", numValue);
}
}, 1000);
},
[updateConfig],
);

// Cleanup timeouts on unmount
useEffect(() => {
return () => {
Expand All @@ -151,9 +127,6 @@ export default function CoreSettingsList() {
if (prometheusLabelsTimeoutRef.current) {
clearTimeout(prometheusLabelsTimeoutRef.current);
}
if (logQueueSizeTimeoutRef.current) {
clearTimeout(logQueueSizeTimeoutRef.current);
}
};
}, []);

Expand Down Expand Up @@ -216,21 +189,17 @@ export default function CoreSettingsList() {

<div className="flex items-center justify-between space-x-2 rounded-lg border p-4">
<div className="space-y-0.5">
<label htmlFor="log-queue-size" className="text-sm font-medium">
Log Queue Size
<label htmlFor="enable-logging" className="text-sm font-medium">
Enable Logs
</label>
<p className="text-muted-foreground text-sm">
Additional logs will be dropped if the queue is full. Bifrost has dropped{" "}
<span className="font-bold">{droppedRequests} logs</span> so far.
Enable logging of requests and responses to a SQLite database. This can add 40-60mb of overhead to the system memory.
</p>
</div>
<Input
id="log-queue-size"
type="number"
className="w-24"
value={localValues.log_queue_size}
onChange={(e) => handleLogQueueSizeChange(e.target.value)}
min="1"
<Switch
id="enable-logging"
checked={config.enable_logging}
onCheckedChange={(checked) => handleConfigChange("enable_logging", checked)}
/>
</div>

Expand Down
Loading