Conversation
|
Caution Review failedFailed to post review comments. Summary by CodeRabbit
Summary by CodeRabbit
WalkthroughThis update introduces a fully featured React/Next.js-based UI for the Bifrost HTTP transport, including configuration, logs, documentation, and plugin management pages. The UI is embedded and served via Go's Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant Browser
participant GoServer
participant EmbeddedUI
participant APIHandlers
User->>Browser: Navigates to Bifrost UI URL
Browser->>GoServer: HTTP GET / (or /config, /docs, etc.)
GoServer->>EmbeddedUI: Serve embedded static file (via embed.FS)
EmbeddedUI-->>Browser: index.html + JS/CSS assets
Browser->>GoServer: API requests (e.g., /api/logs, /api/providers)
GoServer->>APIHandlers: Route to API handler
APIHandlers-->>GoServer: JSON response
GoServer-->>Browser: API JSON
Browser->>GoServer: WebSocket /ws/logs (for live logs)
GoServer-->>Browser: Streaming log entries
Possibly related PRs
Suggested reviewers
Poem
""" Warning There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure. 🔧 ast-grep (0.38.1)transports/bifrost-http/ui/_next/static/chunks/443-5702d24d72c89eac.jstransports/bifrost-http/ui/_next/static/chunks/867-ee04be25d0141432.js✨ Finishing Touches
🧪 Generate unit tests
🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Actionable comments posted: 64
🔭 Outside diff range comments (1)
ui/components/logs/columns.tsx (1)
345-351: Improve type safety by using proper types instead ofany.The use of
anytype reduces type safety. Consider using the proper types from @tanstack/react-table.- {typeof column.cell === "function" - ? // eslint-disable-next-line @typescript-eslint/no-explicit-any - column.cell({ row: { original: log }, column } as any) - : column.cell} + {flexRender( + column.cell, + { row: { original: log }, column, getValue: () => null, renderValue: () => null, table } + )}The
flexRenderutility from @tanstack/react-table handles the rendering correctly with proper types.
♻️ Duplicate comments (1)
ui/components/logs/data-table.tsx (1)
346-351: Improve type safety by avoidinganytype.Similar to the columns definition file, proper types should be used instead of
any.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro
⛔ Files ignored due to path filters (7)
ui/app/favicon.icois excluded by!**/*.icoui/package-lock.jsonis excluded by!**/package-lock.jsonui/public/file.svgis excluded by!**/*.svgui/public/globe.svgis excluded by!**/*.svgui/public/next.svgis excluded by!**/*.svgui/public/vercel.svgis excluded by!**/*.svgui/public/window.svgis excluded by!**/*.svg
📒 Files selected for processing (74)
transports/bifrost-http/handlers/config.go(1 hunks)transports/bifrost-http/main.go(2 hunks)ui/.gitignore(1 hunks)ui/README.md(1 hunks)ui/app/config/page.tsx(1 hunks)ui/app/docs/page.tsx(1 hunks)ui/app/globals.css(1 hunks)ui/app/layout.tsx(1 hunks)ui/app/logs/page.tsx(1 hunks)ui/app/page.tsx(1 hunks)ui/app/plugins/page.tsx(1 hunks)ui/components.json(1 hunks)ui/components/config/core-settings-form.tsx(1 hunks)ui/components/config/mcp-client-form.tsx(1 hunks)ui/components/config/mcp-clients-lists.tsx(1 hunks)ui/components/config/meta-config-renderer.tsx(1 hunks)ui/components/config/provider-form.tsx(1 hunks)ui/components/config/providers-list.tsx(1 hunks)ui/components/header.tsx(1 hunks)ui/components/logs/analytics/latency-chart.tsx(1 hunks)ui/components/logs/analytics/provider-distribution-chart.tsx(1 hunks)ui/components/logs/analytics/request-volume-chart.tsx(1 hunks)ui/components/logs/analytics/status-distribution-chart.tsx(1 hunks)ui/components/logs/analytics/token-usage-chart.tsx(1 hunks)ui/components/logs/columns.tsx(1 hunks)ui/components/logs/data-table.tsx(1 hunks)ui/components/logs/log-detail-sheet.tsx(1 hunks)ui/components/progress-bar.tsx(1 hunks)ui/components/sidebar.tsx(1 hunks)ui/components/theme-provider.tsx(1 hunks)ui/components/theme-toggle.tsx(1 hunks)ui/components/ui/accordion.tsx(1 hunks)ui/components/ui/alert-dialog.tsx(1 hunks)ui/components/ui/alert.tsx(1 hunks)ui/components/ui/aspect-ratio.tsx(1 hunks)ui/components/ui/avatar.tsx(1 hunks)ui/components/ui/badge.tsx(1 hunks)ui/components/ui/button.tsx(1 hunks)ui/components/ui/card.tsx(1 hunks)ui/components/ui/collapsible.tsx(1 hunks)ui/components/ui/command.tsx(1 hunks)ui/components/ui/dialog.tsx(1 hunks)ui/components/ui/dropdown-menu.tsx(1 hunks)ui/components/ui/hover-card.tsx(1 hunks)ui/components/ui/input.tsx(1 hunks)ui/components/ui/label.tsx(1 hunks)ui/components/ui/progress.tsx(1 hunks)ui/components/ui/scroll-area.tsx(1 hunks)ui/components/ui/select.tsx(1 hunks)ui/components/ui/separator.tsx(1 hunks)ui/components/ui/sheet.tsx(1 hunks)ui/components/ui/sidebar.tsx(1 hunks)ui/components/ui/skeleton.tsx(1 hunks)ui/components/ui/switch.tsx(1 hunks)ui/components/ui/table.tsx(1 hunks)ui/components/ui/tabs.tsx(1 hunks)ui/components/ui/tag-input.tsx(1 hunks)ui/components/ui/textarea.tsx(1 hunks)ui/components/ui/tooltip.tsx(1 hunks)ui/eslint.config.mjs(1 hunks)ui/hooks/use-mobile.ts(1 hunks)ui/hooks/use-toast.ts(1 hunks)ui/hooks/useWebSocket.ts(1 hunks)ui/lib/api.ts(1 hunks)ui/lib/data/analytics-data.ts(1 hunks)ui/lib/data/dummy-logs.ts(1 hunks)ui/lib/types/config.ts(1 hunks)ui/lib/types/logs.ts(1 hunks)ui/lib/types/mcp.ts(1 hunks)ui/lib/utils.ts(1 hunks)ui/next.config.ts(1 hunks)ui/package.json(1 hunks)ui/postcss.config.mjs(1 hunks)ui/tsconfig.json(1 hunks)
🧰 Additional context used
🧠 Learnings (7)
📓 Common learnings
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#102
File: README.md:62-66
Timestamp: 2025-06-19T17:03:03.639Z
Learning: Pratham-Mishra04 prefers using the implicit 'latest' tag for the maximhq/bifrost Docker image rather than pinning to specific versions.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#54
File: core/schemas/provider.go:148-148
Timestamp: 2025-06-04T03:57:50.981Z
Learning: Breaking changes in the Bifrost codebase are managed by first merging and tagging core schema changes, then updating dependent code references in subsequent steps after the core version is released.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#84
File: transports/bifrost-http/main.go:2-2
Timestamp: 2025-06-15T16:05:13.489Z
Learning: For the Bifrost project, HTTP transport integration routers for new providers (like Mistral and Ollama) are implemented in separate PRs from the core provider support, following a focused PR strategy.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#85
File: core/providers/anthropic.go:150-156
Timestamp: 2025-06-15T16:07:53.140Z
Learning: In the Bifrost codebase, constructor functions are allowed to mutate input ProviderConfig objects in-place (e.g., setting default BaseURL values and trimming trailing slashes). This pattern is acceptable and doesn't need to be flagged as a code review issue.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#94
File: core/bifrost.go:823-845
Timestamp: 2025-06-18T15:15:51.323Z
Learning: In the Bifrost project, the team prioritizes maintaining consistent error handling patterns over exposing detailed error context. All errors should be wrapped in the standard `BifrostError` structure rather than creating specific error types or exposing richer error details like exit codes or stderr output.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#83
File: core/providers/mistral.go:168-170
Timestamp: 2025-06-15T14:24:49.882Z
Learning: In the Bifrost codebase, performance is prioritized over defensive copying for HTTP service operations. Specifically, shallow slice assignments in provider response handling are acceptable due to object pool reset patterns and JSON unmarshaling behavior that minimize practical data corruption risks.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#103
File: .github/workflows/transport-dependency-update.yml:53-75
Timestamp: 2025-06-20T16:21:18.912Z
Learning: In the bifrost repository's transport dependency update workflow, when updating the core dependency to a new version using `go get`, the go.mod and go.sum files will always change in normal operation, making the safety check for changes more of a defensive programming practice rather than handling a common scenario.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#55
File: core/providers/anthropic.go:358-388
Timestamp: 2025-06-04T05:37:59.699Z
Learning: User Pratham-Mishra04 prefers not to extract small code duplications (around 2 lines) into helper functions, considering the overhead not worth it for such minor repetition.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#138
File: docs/usage/go-package/mcp.md:408-412
Timestamp: 2025-07-01T12:40:08.576Z
Learning: Pratham-Mishra04 is okay with keeping bullet list formatting that uses colons after dashes in markdown documentation, even if it triggers linter warnings, preferring functionality over strict formatting rules.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#138
File: transports/README.md:26-28
Timestamp: 2025-07-01T12:45:06.906Z
Learning: Pratham-Mishra04 prefers keeping documentation examples simple and concise, trusting users to handle production-specific considerations like version pinning themselves rather than cluttering examples with additional notes.
ui/package.json (1)
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#54
File: core/schemas/provider.go:148-148
Timestamp: 2025-06-04T03:57:50.981Z
Learning: Breaking changes in the Bifrost codebase are managed by first merging and tagging core schema changes, then updating dependent code references in subsequent steps after the core version is released.
transports/bifrost-http/main.go (5)
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#67
File: transports/bifrost-http/integrations/anthropic/router.go:26-34
Timestamp: 2025-06-10T11:19:29.604Z
Learning: The Generic router in transports/bifrost-http/integrations/utils.go already handles nil pointers from RequestConverter functions. When a RequestConverter returns a nil *schemas.BifrostRequest, the Generic router automatically returns an HTTP 400 error, making additional nil checks in individual router implementations redundant.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#103
File: .github/workflows/transport-dependency-update.yml:53-75
Timestamp: 2025-06-20T16:21:18.912Z
Learning: In the bifrost repository's transport dependency update workflow, when updating the core dependency to a new version using `go get`, the go.mod and go.sum files will always change in normal operation, making the safety check for changes more of a defensive programming practice rather than handling a common scenario.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#67
File: transports/bifrost-http/integrations/anthropic/router.go:26-34
Timestamp: 2025-06-10T11:19:29.604Z
Learning: The Generic router in transports/bifrost-http/integrations/utils.go already handles nil pointers from RequestConverter functions. When a RequestConverter returns a nil *schemas.BifrostRequest, the Generic router automatically returns an HTTP 400 error with "Invalid request" message, making additional nil checks in individual router implementations redundant.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#65
File: transports/bifrost-http/integrations/anthropic/router.go:19-33
Timestamp: 2025-06-09T16:46:32.018Z
Learning: In the GenericRouter (transports/bifrost-http/integrations), ResponseFunc is not called if the BifrostResponse parameter is nil, providing built-in protection against nil response marshaling.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#83
File: core/providers/mistral.go:168-170
Timestamp: 2025-06-15T14:24:49.882Z
Learning: In the Bifrost codebase, performance is prioritized over defensive copying for HTTP service operations. Specifically, shallow slice assignments in provider response handling are acceptable due to object pool reset patterns and JSON unmarshaling behavior that minimize practical data corruption risks.
ui/app/config/page.tsx (1)
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#85
File: core/providers/anthropic.go:150-156
Timestamp: 2025-06-15T16:07:53.140Z
Learning: In the Bifrost codebase, constructor functions are allowed to mutate input ProviderConfig objects in-place (e.g., setting default BaseURL values and trimming trailing slashes). This pattern is acceptable and doesn't need to be flagged as a code review issue.
ui/components/config/provider-form.tsx (1)
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#85
File: core/providers/anthropic.go:150-156
Timestamp: 2025-06-15T16:07:53.140Z
Learning: In the Bifrost codebase, constructor functions are allowed to mutate input ProviderConfig objects in-place (e.g., setting default BaseURL values and trimming trailing slashes). This pattern is acceptable and doesn't need to be flagged as a code review issue.
ui/lib/types/mcp.ts (1)
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#100
File: core/mcp.go:489-490
Timestamp: 2025-06-19T12:38:07.544Z
Learning: In the Bifrost MCP manager (core/mcp.go), the connectToMCPClient method is called during initialization/connection setup, not frequently during runtime. Logging operations like m.logger.Info inside critical sections in this context have negligible performance impact and don't require optimization for lock contention.
ui/lib/types/logs.ts (2)
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#64
File: transports/bifrost-http/integrations/genai/types.go:383-395
Timestamp: 2025-06-09T16:26:05.777Z
Learning: In the Bifrost schema (core/schemas/bifrost.go), only UserMessage and ToolMessage structs have ImageContent fields. AssistantMessage does not have an ImageContent field and cannot contain images. The schema design intentionally limits image content to user and tool messages only.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#80
File: plugins/maxim/main.go:249-264
Timestamp: 2025-06-14T06:17:54.426Z
Learning: In the BifrostError struct, the Error field is a struct (not a pointer), so accessing bifrostErr.Error.Message, bifrostErr.Error.Code, and bifrostErr.Error.Type is safe without nil checks on the Error field itself. The Code and Type fields are of type *string.
🧬 Code Graph Analysis (47)
ui/components/logs/analytics/token-usage-chart.tsx (2)
ui/lib/data/analytics-data.ts (1)
TokenUsageData(31-36)ui/components/ui/tooltip.tsx (1)
Tooltip(61-61)
ui/app/layout.tsx (2)
ui/components/theme-provider.tsx (1)
ThemeProvider(6-11)ui/components/ui/sidebar.tsx (2)
SidebarProvider(721-721)Sidebar(702-702)
ui/components/theme-toggle.tsx (2)
ui/components/ui/dropdown-menu.tsx (4)
DropdownMenu(242-242)DropdownMenuTrigger(244-244)DropdownMenuContent(245-245)DropdownMenuItem(248-248)ui/components/ui/button.tsx (1)
Button(62-62)
ui/components/logs/analytics/status-distribution-chart.tsx (2)
ui/lib/data/analytics-data.ts (1)
StatusData(18-22)ui/components/ui/tooltip.tsx (1)
Tooltip(61-61)
ui/components/ui/textarea.tsx (1)
ui/lib/utils.ts (1)
cn(4-6)
ui/components/ui/input.tsx (1)
ui/lib/utils.ts (1)
cn(4-6)
ui/components/logs/analytics/provider-distribution-chart.tsx (1)
ui/lib/data/analytics-data.ts (1)
ProviderData(11-16)
ui/components/logs/analytics/request-volume-chart.tsx (1)
ui/lib/data/analytics-data.ts (1)
RequestVolumeData(4-9)
ui/components/ui/switch.tsx (1)
ui/lib/utils.ts (1)
cn(4-6)
ui/components/config/mcp-clients-lists.tsx (7)
ui/lib/types/mcp.ts (1)
MCPClient(20-25)ui/hooks/use-toast.ts (1)
useToast(9-21)ui/lib/api.ts (1)
apiService(228-228)ui/components/ui/badge.tsx (1)
Badge(46-46)ui/components/ui/card.tsx (5)
Card(85-85)CardHeader(86-86)CardTitle(88-88)CardDescription(90-90)CardContent(91-91)ui/components/ui/button.tsx (1)
Button(62-62)ui/components/ui/table.tsx (6)
Table(108-108)TableHeader(109-109)TableRow(113-113)TableHead(112-112)TableBody(110-110)TableCell(114-114)
ui/components/ui/label.tsx (1)
ui/lib/utils.ts (1)
cn(4-6)
ui/components/logs/analytics/latency-chart.tsx (1)
ui/lib/data/analytics-data.ts (1)
LatencyData(24-29)
ui/components/ui/avatar.tsx (1)
ui/lib/utils.ts (1)
cn(4-6)
ui/components/config/core-settings-form.tsx (8)
ui/lib/types/config.ts (1)
CoreConfig(127-131)ui/lib/api.ts (1)
apiService(228-228)ui/components/ui/alert.tsx (2)
Alert(66-66)AlertDescription(66-66)ui/components/ui/card.tsx (5)
Card(85-85)CardHeader(86-86)CardTitle(88-88)CardDescription(90-90)CardContent(91-91)ui/components/ui/switch.tsx (1)
Switch(29-29)ui/components/ui/tooltip.tsx (4)
TooltipProvider(61-61)Tooltip(61-61)TooltipTrigger(61-61)TooltipContent(61-61)ui/components/ui/input.tsx (1)
Input(21-21)ui/components/ui/badge.tsx (1)
Badge(46-46)
ui/components/ui/hover-card.tsx (1)
ui/lib/utils.ts (1)
cn(4-6)
ui/components/config/mcp-client-form.tsx (11)
ui/lib/types/mcp.ts (5)
MCPClient(20-25)MCPStdioConfig(5-9)CreateMCPClientRequest(27-34)MCPConnectionType(1-1)UpdateMCPClientRequest(36-39)ui/hooks/use-toast.ts (1)
useToast(9-21)ui/lib/api.ts (1)
apiService(228-228)ui/components/ui/dialog.tsx (5)
Dialog(133-133)DialogContent(135-135)DialogHeader(138-138)DialogTitle(141-141)DialogFooter(137-137)ui/components/ui/alert.tsx (2)
Alert(66-66)AlertDescription(66-66)ui/components/ui/label.tsx (1)
Label(24-24)ui/components/ui/input.tsx (1)
Input(21-21)ui/components/ui/select.tsx (5)
Select(175-175)SelectTrigger(183-183)SelectValue(184-184)SelectContent(176-176)SelectItem(178-178)ui/components/ui/tooltip.tsx (4)
TooltipProvider(61-61)Tooltip(61-61)TooltipTrigger(61-61)TooltipContent(61-61)ui/components/ui/textarea.tsx (1)
Textarea(18-18)ui/components/ui/button.tsx (1)
Button(62-62)
ui/components/ui/skeleton.tsx (1)
ui/lib/utils.ts (1)
cn(4-6)
ui/components/ui/separator.tsx (1)
ui/lib/utils.ts (1)
cn(4-6)
ui/components/sidebar.tsx (2)
ui/components/ui/sidebar.tsx (11)
Sidebar(702-702)SidebarHeader(709-709)SidebarSeparator(723-723)SidebarContent(703-703)SidebarGroup(705-705)SidebarGroupLabel(708-708)SidebarGroupContent(707-707)SidebarMenu(712-712)SidebarMenuItem(716-716)SidebarMenuButton(715-715)SidebarFooter(704-704)ui/components/ui/badge.tsx (1)
Badge(46-46)
ui/components/ui/button.tsx (1)
ui/lib/utils.ts (1)
cn(4-6)
ui/components/header.tsx (2)
ui/components/theme-toggle.tsx (1)
ThemeToggle(15-40)ui/components/ui/separator.tsx (1)
Separator(28-28)
ui/components/ui/accordion.tsx (1)
ui/lib/utils.ts (1)
cn(4-6)
ui/components/ui/progress.tsx (1)
ui/lib/utils.ts (1)
cn(4-6)
ui/components/ui/tabs.tsx (1)
ui/lib/utils.ts (1)
cn(4-6)
ui/components/ui/scroll-area.tsx (1)
ui/lib/utils.ts (1)
cn(4-6)
ui/hooks/useWebSocket.ts (1)
ui/lib/types/logs.ts (1)
LogEntry(129-145)
ui/components/ui/badge.tsx (1)
ui/lib/utils.ts (1)
cn(4-6)
ui/app/docs/page.tsx (1)
ui/components/header.tsx (1)
Header(4-14)
ui/components/ui/alert.tsx (1)
ui/lib/utils.ts (1)
cn(4-6)
ui/components/config/meta-config-renderer.tsx (6)
ui/lib/types/config.ts (1)
MetaConfig(38-57)ui/components/ui/textarea.tsx (1)
Textarea(18-18)ui/components/ui/input.tsx (1)
Input(21-21)ui/components/ui/separator.tsx (1)
Separator(28-28)ui/components/ui/card.tsx (3)
CardHeader(86-86)CardTitle(88-88)CardContent(91-91)ui/components/ui/tooltip.tsx (4)
TooltipProvider(61-61)Tooltip(61-61)TooltipTrigger(61-61)TooltipContent(61-61)
ui/components/config/provider-form.tsx (4)
ui/lib/types/config.ts (10)
ProviderResponse(80-85)NetworkConfig(22-29)ConcurrencyAndBufferSize(32-35)MetaConfig(38-57)ProxyConfig(63-68)UpdateProviderRequest(104-110)AddProviderRequest(94-101)ModelProvider(4-12)Key(15-19)ProxyType(60-60)ui/lib/api.ts (1)
apiService(228-228)ui/lib/utils.ts (2)
PROVIDER_COLORS(19-28)PROVIDER_LABELS(8-17)ui/components/ui/tag-input.tsx (1)
TagInput(19-83)
ui/app/page.tsx (6)
ui/components/header.tsx (1)
Header(4-14)ui/components/ui/button.tsx (1)
Button(62-62)ui/components/ui/card.tsx (5)
Card(85-85)CardContent(91-91)CardHeader(86-86)CardTitle(88-88)CardDescription(90-90)ui/components/ui/separator.tsx (1)
Separator(28-28)ui/components/ui/tabs.tsx (4)
Tabs(66-66)TabsList(66-66)TabsTrigger(66-66)TabsContent(66-66)ui/components/ui/accordion.tsx (4)
Accordion(66-66)AccordionItem(66-66)AccordionTrigger(66-66)AccordionContent(66-66)
ui/components/logs/data-table.tsx (7)
ui/lib/types/logs.ts (3)
LogEntry(129-145)LogFilters(147-158)Pagination(160-165)ui/components/ui/label.tsx (1)
Label(24-24)ui/components/ui/input.tsx (1)
Input(21-21)ui/components/ui/select.tsx (5)
Select(175-175)SelectTrigger(183-183)SelectValue(184-184)SelectContent(176-176)SelectItem(178-178)ui/components/ui/button.tsx (1)
Button(62-62)ui/components/ui/badge.tsx (1)
Badge(46-46)ui/components/ui/table.tsx (6)
Table(108-108)TableHeader(109-109)TableRow(113-113)TableHead(112-112)TableBody(110-110)TableCell(114-114)
ui/components/ui/tag-input.tsx (3)
ui/lib/utils.ts (1)
cn(4-6)ui/components/ui/badge.tsx (1)
Badge(46-46)ui/components/ui/input.tsx (1)
Input(21-21)
ui/app/plugins/page.tsx (4)
ui/components/header.tsx (1)
Header(4-14)ui/components/ui/badge.tsx (1)
Badge(46-46)ui/components/ui/card.tsx (5)
Card(85-85)CardHeader(86-86)CardTitle(88-88)CardDescription(90-90)CardContent(91-91)ui/components/ui/button.tsx (1)
Button(62-62)
ui/components/ui/table.tsx (1)
ui/lib/utils.ts (1)
cn(4-6)
ui/components/logs/columns.tsx (3)
ui/lib/types/logs.ts (1)
LogEntry(129-145)ui/components/ui/button.tsx (1)
Button(62-62)ui/components/ui/badge.tsx (1)
Badge(46-46)
ui/components/ui/alert-dialog.tsx (2)
ui/lib/utils.ts (1)
cn(4-6)ui/components/ui/button.tsx (1)
buttonVariants(62-62)
ui/components/ui/card.tsx (1)
ui/lib/utils.ts (1)
cn(4-6)
ui/components/ui/tooltip.tsx (1)
ui/lib/utils.ts (1)
cn(4-6)
ui/components/ui/dialog.tsx (1)
ui/lib/utils.ts (1)
cn(4-6)
ui/lib/api.ts (3)
ui/lib/types/config.ts (6)
ErrorResponse(113-124)ListProvidersResponse(88-91)AddProviderRequest(94-101)ProviderResponse(80-85)UpdateProviderRequest(104-110)CoreConfig(127-131)ui/lib/types/logs.ts (3)
LogFilters(147-158)Pagination(160-165)LogEntry(129-145)ui/lib/types/mcp.ts (3)
MCPClient(20-25)CreateMCPClientRequest(27-34)UpdateMCPClientRequest(36-39)
ui/components/ui/select.tsx (1)
ui/lib/utils.ts (1)
cn(4-6)
ui/components/ui/sheet.tsx (1)
ui/lib/utils.ts (1)
cn(4-6)
ui/lib/data/analytics-data.ts (1)
ui/lib/types/logs.ts (1)
LogEntry(129-145)
ui/components/ui/dropdown-menu.tsx (1)
ui/lib/utils.ts (1)
cn(4-6)
ui/components/ui/sidebar.tsx (8)
ui/hooks/use-mobile.ts (1)
useIsMobile(5-19)ui/components/ui/tooltip.tsx (4)
TooltipProvider(61-61)TooltipContent(61-61)Tooltip(61-61)TooltipTrigger(61-61)ui/lib/utils.ts (1)
cn(4-6)ui/components/ui/sheet.tsx (5)
Sheet(131-131)SheetContent(134-134)SheetHeader(135-135)SheetTitle(137-137)SheetDescription(138-138)ui/components/ui/button.tsx (1)
Button(62-62)ui/components/ui/input.tsx (1)
Input(21-21)ui/components/ui/separator.tsx (1)
Separator(28-28)ui/components/ui/skeleton.tsx (1)
Skeleton(13-13)
🪛 Biome (1.9.4)
ui/eslint.config.mjs
[error] 1-1: A Node.js builtin module should be imported with the node: protocol.
Using the node: protocol is more explicit and signals that the imported module belongs to Node.js.
Unsafe fix: Add the node: protocol.
(lint/style/useNodejsImportProtocol)
[error] 2-2: A Node.js builtin module should be imported with the node: protocol.
Using the node: protocol is more explicit and signals that the imported module belongs to Node.js.
Unsafe fix: Add the node: protocol.
(lint/style/useNodejsImportProtocol)
ui/components/config/mcp-clients-lists.tsx
[error] 85-87: Template literals are preferred over string concatenation.
Unsafe fix: Use a template literal.
(lint/style/useTemplate)
ui/components/config/core-settings-form.tsx
[error] 93-95: A form label must be associated with an input.
Consider adding a for or htmlFor attribute to the label element or moving the input element to inside the label element.
(lint/a11y/noLabelWithoutControl)
[error] 160-160: Use Number.parseInt instead of the equivalent global.
ES2015 moved some globals into the Number namespace for consistency.
Safe fix: Use Number.parseInt instead.
(lint/style/useNumberNamespace)
ui/components/config/mcp-client-form.tsx
[error] 117-117: Forbidden non-null assertion.
(lint/style/noNonNullAssertion)
[error] 172-172: Forbidden non-null assertion.
(lint/style/noNonNullAssertion)
ui/components/sidebar.tsx
[error] 208-208: JSX elements without children should be marked as self-closing. In JSX, it is valid for any element to be self-closing.
Unsafe fix: Use a SelfClosingElement instead
(lint/style/useSelfClosingElements)
ui/components/config/meta-config-renderer.tsx
[error] 181-183: A form label must be associated with an input.
Consider adding a for or htmlFor attribute to the label element or moving the input element to inside the label element.
(lint/a11y/noLabelWithoutControl)
ui/components/config/provider-form.tsx
[error] 474-476: A form label must be associated with an input.
Consider adding a for or htmlFor attribute to the label element or moving the input element to inside the label element.
(lint/a11y/noLabelWithoutControl)
[error] 509-511: A form label must be associated with an input.
Consider adding a for or htmlFor attribute to the label element or moving the input element to inside the label element.
(lint/a11y/noLabelWithoutControl)
[error] 574-577: A form label must be associated with an input.
Consider adding a for or htmlFor attribute to the label element or moving the input element to inside the label element.
(lint/a11y/noLabelWithoutControl)
[error] 596-598: A form label must be associated with an input.
Consider adding a for or htmlFor attribute to the label element or moving the input element to inside the label element.
(lint/a11y/noLabelWithoutControl)
[error] 613-615: A form label must be associated with an input.
Consider adding a for or htmlFor attribute to the label element or moving the input element to inside the label element.
(lint/a11y/noLabelWithoutControl)
[error] 646-648: A form label must be associated with an input.
Consider adding a for or htmlFor attribute to the label element or moving the input element to inside the label element.
(lint/a11y/noLabelWithoutControl)
[error] 664-666: A form label must be associated with an input.
Consider adding a for or htmlFor attribute to the label element or moving the input element to inside the label element.
(lint/a11y/noLabelWithoutControl)
[error] 696-698: A form label must be associated with an input.
Consider adding a for or htmlFor attribute to the label element or moving the input element to inside the label element.
(lint/a11y/noLabelWithoutControl)
[error] 723-725: A form label must be associated with an input.
Consider adding a for or htmlFor attribute to the label element or moving the input element to inside the label element.
(lint/a11y/noLabelWithoutControl)
[error] 736-738: A form label must be associated with an input.
Consider adding a for or htmlFor attribute to the label element or moving the input element to inside the label element.
(lint/a11y/noLabelWithoutControl)
[error] 748-750: A form label must be associated with an input.
Consider adding a for or htmlFor attribute to the label element or moving the input element to inside the label element.
(lint/a11y/noLabelWithoutControl)
[error] 333-333: Use Number.parseFloat instead of the equivalent global.
ES2015 moved some globals into the Number namespace for consistency.
Safe fix: Use Number.parseFloat instead.
(lint/style/useNumberNamespace)
[error] 607-607: Use Number.parseInt instead of the equivalent global.
ES2015 moved some globals into the Number namespace for consistency.
Safe fix: Use Number.parseInt instead.
(lint/style/useNumberNamespace)
[error] 623-623: Use Number.parseInt instead of the equivalent global.
ES2015 moved some globals into the Number namespace for consistency.
Safe fix: Use Number.parseInt instead.
(lint/style/useNumberNamespace)
[error] 655-655: Use Number.parseInt instead of the equivalent global.
ES2015 moved some globals into the Number namespace for consistency.
Safe fix: Use Number.parseInt instead.
(lint/style/useNumberNamespace)
[error] 673-673: Use Number.parseInt instead of the equivalent global.
ES2015 moved some globals into the Number namespace for consistency.
Safe fix: Use Number.parseInt instead.
(lint/style/useNumberNamespace)
ui/components/logs/data-table.tsx
[error] 113-113: Use Number.parseInt instead of the equivalent global.
ES2015 moved some globals into the Number namespace for consistency.
Safe fix: Use Number.parseInt instead.
(lint/style/useNumberNamespace)
[error] 423-423: Use Number.parseInt instead of the equivalent global.
ES2015 moved some globals into the Number namespace for consistency.
Safe fix: Use Number.parseInt instead.
(lint/style/useNumberNamespace)
ui/lib/api.ts
[error] 35-35: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
🪛 markdownlint-cli2 (0.17.2)
ui/README.md
1-1: First line in a file should be a top-level heading
(MD041, first-line-heading, first-line-h1)
🔇 Additional comments (66)
ui/.gitignore (1)
1-42: Looks good – covers the usual Next.js artefacts
No issues spotted.ui/components/ui/aspect-ratio.tsx (1)
1-11: Clean and well-structured component wrapper.The implementation follows best practices for wrapping Radix UI primitives:
- Proper use of "use client" directive for client-side components
- Correct TypeScript typing with ComponentProps
- Props forwarding using spread operator
- Consistent data-slot attribute for styling
ui/components/theme-provider.tsx (1)
1-11: Proper theme provider wrapper implementation.The component correctly wraps NextThemesProvider with appropriate client-side directive and props forwarding. This pattern allows for future customization while maintaining clean integration with next-themes.
ui/hooks/use-mobile.ts (1)
5-19: Consider adding SSR-safe initialization to prevent hydration mismatches.The hook logic is correct, but initializing
isMobileasundefinedmay cause hydration mismatches between server and client rendering. Consider using a more SSR-safe pattern:export function useIsMobile() { - const [isMobile, setIsMobile] = React.useState<boolean | undefined>(undefined) + const [isMobile, setIsMobile] = React.useState<boolean | undefined>(undefined) + const [isClient, setIsClient] = React.useState(false) React.useEffect(() => { + setIsClient(true) const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`) const onChange = () => { setIsMobile(window.innerWidth < MOBILE_BREAKPOINT) } mql.addEventListener("change", onChange) setIsMobile(window.innerWidth < MOBILE_BREAKPOINT) return () => mql.removeEventListener("change", onChange) }, []) - return !!isMobile + return isClient ? !!isMobile : false }This ensures consistent behavior during SSR and prevents hydration warnings.
Likely an incorrect or invalid review comment.
ui/components/ui/skeleton.tsx (1)
1-13: Well-implemented skeleton loading component.The implementation correctly:
- Uses the
cnutility for proper class merging with Tailwind CSS- Applies appropriate skeleton styles (
bg-accent animate-pulse rounded-md)- Forwards all div props using the spread operator
- Includes the data-slot attribute for consistent styling
- Follows the established component patterns in this codebase
ui/components.json (1)
1-21: Proper shadcn/ui configuration setup.The configuration correctly establishes:
- "new-york" style preset for consistent component styling
- React Server Components and TypeScript support
- Tailwind CSS integration with zinc base color and CSS variables
- Well-organized path aliases matching the directory structure
- Lucide icon library integration
This configuration provides a solid foundation for the UI component system.
ui/components/logs/analytics/token-usage-chart.tsx (1)
44-55: Good use of CSS custom properties for tooltip styling.The tooltip styling using CSS custom properties (
hsl(var(--card)),hsl(var(--border))) ensures theme consistency. The number formatting withtoLocaleString()is also a nice touch for better readability.transports/bifrost-http/handlers/config.go (1)
35-35: Good naming improvement for clarity.The method rename from
handleReloadConfigtohandleUpdateConfigbetter describes the actual behavior of reading configuration and applying updatable settings. The route registration and comments are properly updated to match.Also applies to: 38-41
ui/components/theme-toggle.tsx (1)
15-40: Excellent implementation with good accessibility practices.The component demonstrates several best practices:
- Proper use of the
useThemehook for state management- Smooth CSS transitions for icon animations using dark mode classes
- Accessible design with
sr-onlytext for screen readers- Clean dropdown menu with clear options for light, dark, and system themes
- Consistent use of the design system components
The icon animation approach is particularly elegant with the rotation and scale transforms.
ui/components/ui/textarea.tsx (1)
5-16: Comprehensive textarea component with excellent state coverage.The component demonstrates thorough attention to detail with:
- Proper TypeScript interface extending native textarea props
- Comprehensive CSS classes covering all interactive states (focus, invalid, disabled, dark mode)
- Good use of the
cnutility for flexible class composition- Accessibility considerations with
data-slotattribute- Consistent styling patterns with other UI components
The extensive className string covers all necessary states and follows modern design system patterns.
ui/app/globals.css (1)
1-122: Excellent modern CSS architecture with OKLCH color space.The global stylesheet demonstrates excellent modern CSS practices:
- Uses OKLCH color space for better color consistency across displays
- Comprehensive theme system with proper CSS custom properties
- Well-structured dark mode support
- Clean separation of concerns with Tailwind's @theme directive
- Consistent base layer styles
The architecture supports maintainable theming and provides a solid foundation for the UI components.
ui/tsconfig.json (1)
1-27: Well-configured TypeScript setup for Next.js.The TypeScript configuration follows Next.js best practices with:
- Appropriate ES2017 target with modern library support
- Strict type checking enabled for better code quality
- Proper module resolution for bundler-based workflows
- Clean path aliasing setup for
@/imports- Incremental compilation for better performance
- Next.js plugin integration
This provides a solid foundation for the UI application with proper type safety and development experience.
ui/components/logs/analytics/status-distribution-chart.tsx (2)
23-23: All analytics chart heights are consistent.The
h-80class is used uniformly across all components inui/components/logs/analytics/. No changes needed.
47-52: Replace hardcoded HSL colors with CSS custom properties.The tooltip styling uses hardcoded HSL values instead of CSS custom properties, which could cause inconsistency with the theme system.
- contentStyle={{ - backgroundColor: "hsl(var(--card))", - border: "1px solid hsl(var(--border))", - borderRadius: "6px", - fontSize: "12px", - }} + contentStyle={{ + backgroundColor: "hsl(var(--card))", + border: "1px solid hsl(var(--border))", + borderRadius: "var(--radius)", + fontSize: "12px", + }}Likely an incorrect or invalid review comment.
ui/components/ui/progress.tsx (1)
8-12: LGTM - Well-structured component with proper TypeScript usage.The component correctly extends Radix UI's Progress primitive props and uses proper TypeScript typing.
ui/components/ui/label.tsx (1)
8-21: LGTM - Excellent implementation with comprehensive accessibility support.The component demonstrates best practices with:
- Proper TypeScript typing extending Radix UI props
- Comprehensive CSS classes for styling including disabled states
- Accessibility features with data attributes and peer selectors
- Proper use of the
cnutility for class mergingui/components/logs/analytics/latency-chart.tsx (1)
51-54: LGTM - Well-implemented tooltip formatter.The tooltip formatter correctly formats latency values with "ms" suffix and capitalizes metric names for better UX.
ui/lib/utils.ts (1)
1-29: LGTM! Well-structured utility module.The
cnfunction follows the standard pattern for combining class names with Tailwind CSS, and the provider constants provide good centralization for display names and colors. The consistent mapping betweenPROVIDER_LABELSandPROVIDER_COLORSensures UI consistency across the application.ui/components/ui/switch.tsx (1)
1-30: LGTM! Well-implemented Switch component.The component properly wraps Radix UI's Switch primitive with correct ref forwarding, TypeScript typing, and comprehensive styling. The implementation follows React best practices and maintains consistency with the UI design system.
ui/components/ui/separator.tsx (1)
1-29: LGTM! Clean Separator component implementation.The component correctly wraps Radix UI's Separator primitive with appropriate default props and conditional styling based on orientation. The implementation is consistent with the UI design system.
ui/package.json (1)
39-56: Dependency versions confirmed compatibleReact 19, Next.js 15.3.4, and Tailwind CSS 4 are confirmed to be compatible with each other and stable for production use. Please ensure that any additional third-party packages in your
ui/package.jsonalso list React 19 in their peer dependencies to avoid runtime conflicts.• ui/package.json (lines 39–56): review peer dependencies of all other libraries for React 19 support.
ui/components/config/mcp-clients-lists.tsx (1)
27-212: LGTM! Comprehensive MCP client management component.The component provides a complete interface for managing MCP clients with proper error handling, state management, and user feedback. The CRUD operations are well-implemented with appropriate API calls and toast notifications. The conditional rendering based on client state provides good UX.
ui/app/layout.tsx (3)
10-18: Font setup is well-configured.The Google Fonts integration using Next.js font optimization is properly implemented with appropriate CSS variables and Latin subsets.
20-24: Metadata is comprehensive and well-written.The title and description effectively communicate the application's purpose as an AI gateway dashboard with key features highlighted.
32-32: suppressHydrationWarning is appropriately used.This attribute is necessary when using theme providers to prevent hydration mismatches between server and client rendering.
ui/components/ui/collapsible.tsx (1)
1-34: Clean implementation of Radix UI collapsible wrapper.The components properly wrap the Radix UI primitives while maintaining their API. The consistent use of
data-slotattributes and prop forwarding follows the established pattern across the UI component library.ui/components/logs/analytics/provider-distribution-chart.tsx (3)
19-38: Custom tooltip implementation is well-designed.The tooltip provides clear information with provider name, request count, and formatted percentage. The conditional rendering and styling are appropriate.
40-74: Label positioning logic is mathematically sound.The custom label component correctly calculates positioning using polar coordinates and implements a sensible 5% threshold to prevent label clutter on small slices.
88-88: Type casting for PieLabel props is acceptable.The type assertion
CustomLabel as PieLabel<PieLabelProps>is necessary due to recharts' type definitions and is handled safely.ui/lib/data/dummy-logs.ts (4)
15-24: Provider-model mappings are realistic and comprehensive.The mapping accurately reflects the models available from each major AI provider, providing realistic test data for the UI components.
26-33: Status distribution is well-balanced for testing.The weighted distribution (4 success, 1 error, 1 cancelled) provides a realistic success rate while ensuring error cases are represented for UI testing.
50-117: Comprehensive fullResponse structure supports all UI features.The detailed response structure includes all necessary fields for testing charts, filters, and detail views. The conditional tool_calls addition (30% probability) adds realistic variability.
136-137: Sorting by timestamp ensures consistent display order.Sorting logs by newest first provides a logical default order for the UI display.
ui/components/ui/avatar.tsx (3)
8-22: Avatar component with appropriate default styling.The base avatar component uses sensible defaults with size-8 and rounded-full styling. The className merging allows for customization while maintaining the core design.
24-35: AvatarImage ensures proper image fitting.The aspect-square and size-full classes ensure the image fills the container properly while maintaining aspect ratio.
37-51: AvatarFallback provides appropriate fallback styling.The muted background and centered content provide a clean fallback appearance when no image is available.
ui/components/ui/button.tsx (1)
1-63: Well-implemented button component with modern React patterns.The button component follows excellent practices:
- Proper ref forwarding for accessibility
- Flexible composition with
asChildprop using Radix UI Slot- Comprehensive styling system with variants and sizes
- Good TypeScript typing and utility function usage
The implementation is solid and follows established UI component patterns.
ui/components/sidebar.tsx (1)
82-219: Well-structured sidebar component with proper navigation logic.The sidebar implementation demonstrates good practices:
- Proper active route detection logic
- Accessibility-friendly navigation with semantic HTML
- Secure external link handling with
target="_blank"andrelattributes- Clean separation of navigation data and rendering logic
The component provides a solid foundation for the application's navigation system.
ui/components/ui/tag-input.tsx (1)
1-86: Excellent tag input component implementation.The component demonstrates solid React patterns:
- Proper ref forwarding for form integration
- Intuitive keyboard interactions (Enter/comma to add, Backspace to remove)
- Duplicate prevention and input validation
- Clean state management with proper TypeScript typing
- Good accessibility with focusable remove buttons
The implementation is well-structured and follows established UI component patterns.
transports/bifrost-http/main.go (2)
115-139: Well-implemented CORS middleware for localhost development.The CORS implementation properly addresses development needs:
- Correctly targets localhost origins (both
localhostand127.0.0.1)- Sets appropriate CORS headers for credentials, methods, and headers
- Handles preflight OPTIONS requests correctly
- Maintains security by only allowing localhost origins
This enables the new UI components to interact with the backend during development without CORS issues.
282-291: Consistent CORS application across all routes.The server handler correctly applies CORS middleware to both metrics and API routes, ensuring consistent behavior across all endpoints. The middleware wrapping approach maintains the existing telemetry functionality while adding CORS support.
ui/hooks/useWebSocket.ts (1)
1-77: Robust WebSocket hook implementation with proper lifecycle management.The hook demonstrates excellent practices:
- Proper ref management for WebSocket instance and timeouts
- Automatic reconnection with reasonable 5-second delay
- Comprehensive cleanup to prevent memory leaks
- Environment variable configuration for port flexibility
- Good error handling for JSON parsing failures
- Correct dependency array to avoid stale closure issues
The implementation provides a solid foundation for real-time log updates in the UI.
ui/app/page.tsx (1)
278-287: LGTM! Docker example follows established patterns.The Docker example correctly uses the implicit 'latest' tag as per your preferences.
ui/components/ui/hover-card.tsx (1)
29-29: Add data-slot attribute to Portal for consistency.Other components have
data-slotattributes for identification, but the Portal is missing one.Apply this diff:
- <HoverCardPrimitive.Portal data-slot="hover-card-portal"> + <HoverCardPrimitive.Portal data-slot="hover-card-portal">Likely an incorrect or invalid review comment.
ui/components/ui/alert.tsx (1)
1-67: LGTM! Well-structured alert component.The alert component is well-implemented with:
- Proper use of cva for variant management
- Semantic HTML with
role="alert"- Consistent data-slot attributes
- Clean component composition
ui/components/ui/badge.tsx (1)
1-46: LGTM! Well-structured badge component with comprehensive styling.The Badge component is excellently implemented with:
- Proper TypeScript typing and variant management using cva
- Flexible composition via the asChild prop and Radix UI Slot
- Comprehensive styling including focus states, hover effects, and accessibility features
- Four well-defined variants for different use cases
- Proper export of both component and styling variants
The implementation follows React best practices and integrates well with the overall UI component library.
ui/components/config/core-settings-form.tsx (1)
32-172: LGTM! Well-structured configuration form with proper state management.The CoreSettingsForm component is well-implemented with:
- Proper React hooks usage for state management
- Asynchronous API calls with error handling
- User-friendly loading states and toast notifications
- Clear UI organization with cards and tooltips
- Comprehensive form validation and user guidance
The component integrates well with the broader configuration system and follows React best practices.
ui/app/config/page.tsx (1)
34-285: LGTM! Comprehensive configuration page with excellent state management.The ConfigPage component is excellently implemented with:
- Proper React hooks for state management and side effects
- Comprehensive error handling with user-friendly toast notifications
- Well-organized tabbed interface for different configuration sections
- Proper separation of concerns with dedicated components for each tab
- Efficient loading states and data fetching patterns
- Clean integration with the API service and UI component library
The component follows React best practices and provides a robust user experience for configuration management.
ui/components/ui/tabs.tsx (1)
8-66: LGTM! Well-structured tabs component with comprehensive styling.The Tabs component is excellently implemented with:
- Proper wrapping of Radix UI primitives while maintaining all functionality
- Comprehensive styling including focus states, hover effects, and accessibility features
- Clean component architecture with proper TypeScript typing
- Consistent use of data attributes for styling hooks
- Proper class name merging with the cn utility
- Export of all necessary components for flexible usage
The implementation follows React best practices and integrates seamlessly with the Radix UI ecosystem.
ui/components/ui/accordion.tsx (1)
9-66: LGTM! Well-structured accordion component with smooth animations.The Accordion component is excellently implemented with:
- Proper wrapping of Radix UI primitives while preserving accessibility
- Smooth animations for open/close states with proper CSS transitions
- Clean integration of ChevronDownIcon with rotation animation
- Comprehensive styling including focus states and hover effects
- Proper TypeScript typing and component architecture
- Consistent use of data attributes for styling hooks
The implementation follows React best practices and provides a polished user experience with the animated chevron icon.
ui/components/logs/data-table.tsx (1)
279-286: Potential timezone issue with date handling.Splitting the ISO string and creating a new Date from just the date part can cause timezone shifts. The date input interprets values as local time, which might differ from the server's timezone.
Consider preserving the time component or explicitly handling timezones:
onChange={(e) => updateFilters({ start_time: e.target.value - ? new Date(e.target.value).toISOString() + ? new Date(e.target.value + 'T00:00:00').toISOString() : undefined, }) }This ensures consistent time handling. You might also want to document the expected timezone behavior or use a date library that handles timezones properly.
Also applies to: 293-300
ui/app/docs/page.tsx (1)
86-86: Benchmarks Link Correctly Points to a Single File
The benchmarks documentation lives as a standalone file (docs/benchmarks.md)—there is nodocs/benchmarks/directory—so the URL is intentionally pointing at the.mdfile. No changes required.ui/components/ui/alert-dialog.tsx (1)
1-157: LGTM! Well-structured AlertDialog component wrapper.The implementation properly wraps Radix UI primitives with consistent styling, TypeScript types, and data attributes for targeting. Good use of the
cnutility for class composition.ui/lib/types/mcp.ts (1)
1-39: Well-structured type definitionsThe MCP type definitions are clean, well-organized, and follow TypeScript best practices.
ui/components/ui/card.tsx (1)
1-92: Well-implemented card componentsThe card components are well-structured, consistently implemented, and follow React best practices.
ui/lib/api.ts (1)
144-147: Fix token usage field mapping to match LogEntry interface.The current implementation references non-existent direct properties on the log object. According to the LogEntry interface in
ui/lib/types/logs.ts, token usage is nested undertoken_usage.- promptTokens: acc.promptTokens + log.promptTokens, - completionTokens: acc.completionTokens + log.completionTokens, - totalTokens: acc.totalTokens + log.totalTokens, + promptTokens: acc.promptTokens + (log.token_usage?.prompt_tokens || 0), + completionTokens: acc.completionTokens + (log.token_usage?.completion_tokens || 0), + totalTokens: acc.totalTokens + (log.token_usage?.total_tokens || 0),Likely an incorrect or invalid review comment.
ui/components/ui/dialog.tsx (1)
9-143: Well-structured dialog component suite.The dialog components are well-implemented with consistent patterns, proper prop forwarding, and good accessibility features. The optional close button in
DialogContentis a nice touch for flexibility.ui/components/ui/sheet.tsx (1)
9-139: Excellent sheet component implementation.The sheet components are well-designed with proper directional support, consistent styling patterns, and good integration with Radix UI primitives. The side-specific animation classes are properly implemented.
ui/components/ui/select.tsx (1)
9-185: Comprehensive and well-implemented select component suite.The select components provide excellent functionality with size variants, scroll handling, proper indicators, and consistent styling. The implementation follows established patterns from other UI components in this PR.
ui/lib/types/config.ts (1)
1-162: Well-structured type definitionsThe TypeScript interfaces and types are comprehensive and well-organized, properly matching the Go backend structures. Good use of optional properties, type unions, and clear documentation.
ui/lib/types/logs.ts (1)
1-165: Comprehensive and well-structured log typesExcellent type definitions for the logging interface. The types are comprehensive, properly documented, and match the backend BifrostResponse schema. Good use of optional properties and type unions throughout.
ui/app/plugins/page.tsx (1)
72-283: Well-structured plugin overview pageThe implementation demonstrates good practices:
- Clean component structure with clear sections
- Responsive grid layouts
- Proper use of UI primitives from the design system
- Good accessibility with semantic HTML and descriptive text
- Consistent styling patterns
ui/components/config/providers-list.tsx (2)
56-67: Solid error handling patternGood implementation of async deletion with proper error handling, loading states, and user feedback via toast notifications. The tuple destructuring pattern for API responses is clean and consistent.
89-220: Well-implemented provider management tableExcellent implementation with:
- Comprehensive data display with status indicators, API keys count, and configuration details
- Proper loading and empty states
- User-friendly delete confirmation with AlertDialog
- Visual feedback during deletion with loading spinner
- Good use of design system components and consistent styling
ui/components/ui/sidebar.tsx (2)
56-152: Excellent sidebar architecture with comprehensive featuresThe SidebarProvider implementation showcases excellent patterns:
- Proper context-based state management with TypeScript
- Keyboard shortcut support (Cmd/Ctrl+B)
- Cookie persistence for user preferences
- Responsive design with mobile detection
- Controlled/uncontrolled component support
154-700: Comprehensive sidebar component suite with excellent flexibilityThe implementation provides:
- Multiple rendering modes for different use cases
- Rich component API with proper composition patterns
- Excellent accessibility with ARIA attributes and keyboard navigation
- Responsive behavior with mobile sheet rendering
- Well-structured variant system using CVA
- Thoughtful UX details like tooltips in collapsed state
This is a high-quality, production-ready sidebar implementation.
| const config = { | ||
| plugins: ["@tailwindcss/postcss"], | ||
| }; | ||
|
|
||
| export default config; |
There was a problem hiding this comment.
Plugin name likely wrong – Tailwind will not load
PostCSS expects the Tailwind plugin to be "tailwindcss" (and usually "autoprefixer" as well).
"@tailwindcss/postcss" is not a published package, so the current setup will break the build.
-const config = {
- plugins: ["@tailwindcss/postcss"],
-};
+const config = {
+ plugins: {
+ tailwindcss: {},
+ autoprefixer: {},
+ },
+};📝 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.
| const config = { | |
| plugins: ["@tailwindcss/postcss"], | |
| }; | |
| export default config; | |
| const config = { | |
| plugins: { | |
| tailwindcss: {}, | |
| autoprefixer: {}, | |
| }, | |
| }; | |
| export default config; |
🤖 Prompt for AI Agents
In ui/postcss.config.mjs lines 1 to 5, the PostCSS plugin name is incorrect as
"@tailwindcss/postcss" is not a valid package. Replace the plugin name with
"tailwindcss" and also add "autoprefixer" to the plugins array to ensure
Tailwind CSS loads correctly and the build does not break.
There was a problem hiding this comment.
nope its not breaking the build
| const docSections = [ | ||
| { | ||
| title: "Quick Start", | ||
| description: "Get Bifrost running in under 30 seconds", | ||
| icon: Play, | ||
| url: "https://github.com/maximhq/bifrost/tree/main/docs/quickstart", | ||
| badge: "Popular", | ||
| items: ["HTTP Transport Setup", "Go Package Usage", "Docker Installation"], | ||
| }, | ||
| { | ||
| title: "Architecture", | ||
| description: "Deep dive into Bifrost's design and performance", | ||
| icon: GitBranch, | ||
| url: "https://github.com/maximhq/bifrost/tree/main/docs/architecture", | ||
| items: [ | ||
| "System Overview", | ||
| "Request Flow", | ||
| "Concurrency Model", | ||
| "Plugin Architecture", | ||
| ], | ||
| }, | ||
| { | ||
| title: "Usage Guides", | ||
| description: "Complete API reference and configuration guides", | ||
| icon: BookOpen, | ||
| url: "https://github.com/maximhq/bifrost/tree/main/docs/usage", | ||
| badge: "Comprehensive", | ||
| items: [ | ||
| "Provider Configuration", | ||
| "Key Management", | ||
| "Error Handling", | ||
| "MCP Integration", | ||
| ], | ||
| }, | ||
| { | ||
| title: "Contributing", | ||
| description: "Help improve Bifrost for everyone", | ||
| icon: Users, | ||
| url: "https://github.com/maximhq/bifrost/tree/main/docs/contributing", | ||
| items: [ | ||
| "Development Setup", | ||
| "Adding Providers", | ||
| "Plugin Development", | ||
| "Code Conventions", | ||
| ], | ||
| }, | ||
| { | ||
| title: "Examples", | ||
| description: "Practical, executable examples for common use cases", | ||
| icon: Code, | ||
| url: "https://github.com/maximhq/bifrost/tree/main/docs/examples", | ||
| items: [ | ||
| "End-to-end Examples", | ||
| "Tool Calling", | ||
| "MCP Scenarios", | ||
| "Production Patterns", | ||
| ], | ||
| }, | ||
| { | ||
| title: "Benchmarks", | ||
| description: "Performance metrics and optimization guides", | ||
| icon: Zap, | ||
| url: "https://github.com/maximhq/bifrost/blob/main/docs/benchmarks.md", | ||
| items: [ | ||
| "Performance Benchmarks", | ||
| "Latency Analysis", | ||
| "Throughput Tests", | ||
| "Optimization Tips", | ||
| ], | ||
| }, | ||
| ]; |
There was a problem hiding this comment.
🧹 Nitpick (assertive)
Add TypeScript interface for documentation sections.
The docSections array would benefit from explicit type definitions for better type safety and IntelliSense support.
Add this type definition before the array:
interface DocSection {
title: string;
description: string;
icon: React.ComponentType<{ className?: string }>;
url: string;
badge?: string;
items: string[];
}
const docSections: DocSection[] = [
// ... existing sections
];🤖 Prompt for AI Agents
In ui/app/docs/page.tsx around lines 24 to 94, the docSections array lacks
explicit TypeScript typing, which reduces type safety and IntelliSense support.
Define a TypeScript interface named DocSection with properties title,
description, icon (typed as React.ComponentType with optional className), url,
optional badge, and items as a string array. Then, annotate the docSections
array with this DocSection[] type to enforce consistent structure and improve
developer experience.
| <Link | ||
| href="https://github.com/maximhq/bifrost/tree/main/docs" | ||
| target="_blank" | ||
| > | ||
| <ExternalLink className="mr-2 h-4 w-4" /> | ||
| View Full Documentation | ||
| </Link> |
There was a problem hiding this comment.
Add rel="noopener noreferrer" to external links for security.
External links with target="_blank" should include rel="noopener noreferrer" to prevent potential security vulnerabilities.
Apply this pattern to all external links:
- href="https://github.com/maximhq/bifrost/tree/main/docs"
- target="_blank"
+ href="https://github.com/maximhq/bifrost/tree/main/docs"
+ target="_blank"
+ rel="noopener noreferrer"Also applies to: 124-130, 174-180, 207-212, 234-239
🤖 Prompt for AI Agents
In ui/app/docs/page.tsx at lines 115-121 and also at 124-130, 174-180, 207-212,
and 234-239, all external links using target="_blank" lack the rel="noopener
noreferrer" attribute. To fix this, add rel="noopener noreferrer" to each Link
component with target="_blank" to enhance security by preventing the new page
from accessing the window.opener property.
| const matchesFilters = (log: LogEntry, filters: LogFilters): boolean => { | ||
| if ( | ||
| filters.providers?.length && | ||
| !filters.providers.includes(log.provider) | ||
| ) { | ||
| return false; | ||
| } | ||
| if (filters.models?.length && !filters.models.includes(log.model)) { | ||
| return false; | ||
| } | ||
| if (filters.status?.length && !filters.status.includes(log.status)) { | ||
| return false; | ||
| } | ||
| if ( | ||
| filters.start_time && | ||
| new Date(log.timestamp) < new Date(filters.start_time) | ||
| ) { | ||
| return false; | ||
| } | ||
| if ( | ||
| filters.end_time && | ||
| new Date(log.timestamp) > new Date(filters.end_time) | ||
| ) { | ||
| return false; | ||
| } | ||
| if ( | ||
| filters.min_latency && | ||
| (!log.latency || log.latency < filters.min_latency) | ||
| ) { | ||
| return false; | ||
| } | ||
| if ( | ||
| filters.max_latency && | ||
| (!log.latency || log.latency > filters.max_latency) | ||
| ) { | ||
| return false; | ||
| } | ||
| if ( | ||
| filters.min_tokens && | ||
| (!log.token_usage || log.token_usage.total_tokens < filters.min_tokens) | ||
| ) { | ||
| return false; | ||
| } | ||
| if ( | ||
| filters.max_tokens && | ||
| (!log.token_usage || log.token_usage.total_tokens > filters.max_tokens) | ||
| ) { | ||
| return false; | ||
| } | ||
| if (filters.content_search) { | ||
| const search = filters.content_search.toLowerCase(); | ||
| const content = [ | ||
| ...(log.input_history || []).map((msg: BifrostMessage) => | ||
| getMessageText(msg.content) | ||
| ), | ||
| log.input_text || "", | ||
| log.output_message ? getMessageText(log.output_message.content) : "", | ||
| ] | ||
| .join(" ") | ||
| .toLowerCase(); | ||
|
|
||
| if (!content.includes(search)) { | ||
| return false; | ||
| } | ||
| } | ||
| return true; | ||
| }; |
There was a problem hiding this comment.
🧹 Nitpick (assertive)
Consider breaking down the matchesFilters function.
The matchesFilters function is quite long and handles multiple filtering criteria. Consider extracting individual filter checks into separate functions for better readability and testability.
Example refactor:
const matchesProviderFilter = (log: LogEntry, providers?: string[]) =>
!providers?.length || providers.includes(log.provider);
const matchesTimeFilter = (log: LogEntry, startTime?: string, endTime?: string) => {
const timestamp = new Date(log.timestamp);
if (startTime && timestamp < new Date(startTime)) return false;
if (endTime && timestamp > new Date(endTime)) return false;
return true;
};
// Then use these in matchesFilters:
const matchesFilters = (log: LogEntry, filters: LogFilters): boolean => {
return matchesProviderFilter(log, filters.providers) &&
matchesTimeFilter(log, filters.start_time, filters.end_time) &&
// ... other checks
};🤖 Prompt for AI Agents
In ui/app/logs/page.tsx between lines 117 and 183, the matchesFilters function
is lengthy and checks multiple filter criteria inline, reducing readability and
testability. Refactor by extracting each filter check into its own helper
function, such as matchesProviderFilter, matchesTimeFilter,
matchesLatencyFilter, matchesTokenFilter, and matchesContentSearchFilter. Then
update matchesFilters to combine these helper functions with logical AND,
improving modularity and clarity.
| ), | ||
| }; | ||
|
|
||
| const columns = createColumns((log: LogEntry) => setSelectedLog(log)); |
There was a problem hiding this comment.
🧹 Nitpick (assertive)
Memoize createColumns to prevent unnecessary re-renders.
The createColumns function is called on every render, which could impact performance.
- const columns = createColumns((log: LogEntry) => setSelectedLog(log));
+ const columns = useMemo(
+ () => createColumns((log: LogEntry) => setSelectedLog(log)),
+ []
+ );📝 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.
| const columns = createColumns((log: LogEntry) => setSelectedLog(log)); | |
| const columns = useMemo( | |
| () => createColumns((log: LogEntry) => setSelectedLog(log)), | |
| [] | |
| ); |
🤖 Prompt for AI Agents
In ui/app/logs/page.tsx at line 208, the createColumns function is called
directly inside the render, causing it to run on every render and potentially
degrade performance. To fix this, memoize the result of createColumns using
React's useMemo hook, passing setSelectedLog as a dependency, so that columns
are only recalculated when setSelectedLog changes.
| const stats = { | ||
| totalRequests: totalItems, | ||
| successRate: | ||
| logs.length > 0 | ||
| ? Math.round( | ||
| (logs.filter((log) => log.status === "success").length / | ||
| logs.length) * | ||
| 100 | ||
| ) | ||
| : 0, | ||
| avgLatency: | ||
| logs.length > 0 | ||
| ? Math.round( | ||
| logs.reduce((sum, log) => sum + (log.latency || 0), 0) / logs.length | ||
| ) | ||
| : 0, | ||
| totalTokens: logs.reduce( | ||
| (sum, log) => sum + (log.token_usage?.total_tokens || 0), | ||
| 0 | ||
| ), | ||
| }; |
There was a problem hiding this comment.
🧹 Nitpick (assertive)
Memoize stats calculation to improve performance.
The stats object is recalculated on every render. Consider using useMemo to optimize this calculation.
- // Calculate basic stats for display
- const stats = {
+ // Calculate basic stats for display
+ const stats = useMemo(() => ({
totalRequests: totalItems,
successRate:
logs.length > 0
? Math.round(
(logs.filter((log) => log.status === "success").length /
logs.length) *
100
)
: 0,
avgLatency:
logs.length > 0
? Math.round(
logs.reduce((sum, log) => sum + (log.latency || 0), 0) / logs.length
)
: 0,
totalTokens: logs.reduce(
(sum, log) => sum + (log.token_usage?.total_tokens || 0),
0
),
- };
+ }), [logs, totalItems]);Don't forget to import useMemo:
-import { useState, useEffect, useCallback } from "react";
+import { useState, useEffect, useCallback, useMemo } from "react";📝 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.
| const stats = { | |
| totalRequests: totalItems, | |
| successRate: | |
| logs.length > 0 | |
| ? Math.round( | |
| (logs.filter((log) => log.status === "success").length / | |
| logs.length) * | |
| 100 | |
| ) | |
| : 0, | |
| avgLatency: | |
| logs.length > 0 | |
| ? Math.round( | |
| logs.reduce((sum, log) => sum + (log.latency || 0), 0) / logs.length | |
| ) | |
| : 0, | |
| totalTokens: logs.reduce( | |
| (sum, log) => sum + (log.token_usage?.total_tokens || 0), | |
| 0 | |
| ), | |
| }; | |
| // at the top of ui/app/logs/page.tsx | |
| -import { useState, useEffect, useCallback } from "react"; | |
| +import { useState, useEffect, useCallback, useMemo } from "react"; | |
| // ... | |
| // Calculate basic stats for display | |
| - const stats = { | |
| + const stats = useMemo(() => ({ | |
| totalRequests: totalItems, | |
| successRate: | |
| logs.length > 0 | |
| ? Math.round( | |
| (logs.filter((log) => log.status === "success").length / | |
| logs.length) * | |
| 100 | |
| ) | |
| : 0, | |
| avgLatency: | |
| logs.length > 0 | |
| ? Math.round( | |
| logs.reduce((sum, log) => sum + (log.latency || 0), 0) / logs.length | |
| ) | |
| : 0, | |
| totalTokens: logs.reduce( | |
| (sum, log) => sum + (log.token_usage?.total_tokens || 0), | |
| 0 | |
| ), | |
| - }; | |
| + }), [logs, totalItems]); |
🤖 Prompt for AI Agents
In ui/app/logs/page.tsx around lines 186 to 206, the stats object is
recalculated on every render, which can hurt performance. To fix this, wrap the
stats calculation inside a useMemo hook, passing logs and totalItems as
dependencies to memoize the result. Also, ensure you import useMemo from React
at the top of the file.
| if (field.isJson) { | ||
| try { | ||
| const parsed = JSON.parse(e.target.value); | ||
| onMetaConfigChange(field.name, parsed); | ||
| } catch { | ||
| // Ignore parsing errors, keep it as string | ||
| } | ||
| } |
There was a problem hiding this comment.
🛠️ Refactor suggestion
Provide user feedback for JSON parsing errors.
Currently, JSON parsing errors are silently ignored, which could confuse users when their input doesn't save as expected.
Consider adding error feedback:
onBlur={(e) => {
if (field.isJson) {
try {
const parsed = JSON.parse(e.target.value);
onMetaConfigChange(field.name, parsed);
} catch (error) {
// You could add a validation state or show a toast
console.error(`Invalid JSON for ${field.label}:`, error);
// Optionally, you could pass an error handler prop:
// onJsonError?.(field.name, error);
}
}
}}🤖 Prompt for AI Agents
In ui/components/config/meta-config-renderer.tsx around lines 126 to 133, JSON
parsing errors are currently ignored silently, which can confuse users. Modify
the catch block to provide user feedback by logging the error to the console and
optionally triggering an error handler or validation state. This will inform
users when their JSON input is invalid and improve the user experience.
| // eslint-disable-next-line @typescript-eslint/no-explicit-any | ||
| onMetaConfigChange: (key: keyof MetaConfig, value: any) => void; |
There was a problem hiding this comment.
🛠️ Refactor suggestion
Replace any type with a more specific type.
Using any defeats TypeScript's type safety benefits.
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- onMetaConfigChange: (key: keyof MetaConfig, value: any) => void;
+ onMetaConfigChange: (key: keyof MetaConfig, value: MetaConfig[keyof MetaConfig]) => void;📝 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.
| // eslint-disable-next-line @typescript-eslint/no-explicit-any | |
| onMetaConfigChange: (key: keyof MetaConfig, value: any) => void; | |
| onMetaConfigChange: (key: keyof MetaConfig, value: MetaConfig[keyof MetaConfig]) => void; |
🤖 Prompt for AI Agents
In ui/components/config/meta-config-renderer.tsx at lines 93 to 94, replace the
use of the `any` type for the `value` parameter in the `onMetaConfigChange`
function with a more specific type that corresponds to the possible types of
values in the MetaConfig object. This will improve type safety by ensuring the
value matches the expected type for the given key.
| <div key={field.name}> | ||
| <label className="text-sm font-medium block mb-2"> | ||
| {field.label} | ||
| </label> | ||
| {renderField(field)} | ||
| </div> |
There was a problem hiding this comment.
Fix accessibility issue: Associate label with form input.
The label element is not properly associated with its input/textarea, which impacts accessibility.
- <label className="text-sm font-medium block mb-2">
+ <label
+ htmlFor={`meta-${field.name}`}
+ className="text-sm font-medium block mb-2"
+ >
{field.label}
</label>Then update the renderField function to add the corresponding id:
<Textarea
+ id={`meta-${field.name}`}
placeholder={field.placeholder} <Input
+ id={`meta-${field.name}`}
placeholder={field.placeholder}📝 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.
| <div key={field.name}> | |
| <label className="text-sm font-medium block mb-2"> | |
| {field.label} | |
| </label> | |
| {renderField(field)} | |
| </div> | |
| <div key={field.name}> | |
| - <label className="text-sm font-medium block mb-2"> | |
| + <label | |
| + htmlFor={`meta-${field.name}`} | |
| + className="text-sm font-medium block mb-2" | |
| + > | |
| {field.label} | |
| </label> | |
| {renderField(field)} | |
| </div> |
🧰 Tools
🪛 Biome (1.9.4)
[error] 181-183: A form label must be associated with an input.
Consider adding a for or htmlFor attribute to the label element or moving the input element to inside the label element.
(lint/a11y/noLabelWithoutControl)
🤖 Prompt for AI Agents
In ui/components/config/meta-config-renderer.tsx around lines 180 to 185, the
label element is not properly associated with its input or textarea, causing an
accessibility issue. Fix this by adding a unique id attribute to the input
element rendered by the renderField function and then set the label's htmlFor
attribute to this id. Update the renderField function to accept and apply this
id to the input or textarea element it returns.
| const estimatedCost = tokenUsage | ||
| ? { | ||
| inputCost: (tokenUsage.prompt_tokens / 1000) * 0.01, // $0.01 per 1K tokens | ||
| outputCost: (tokenUsage.completion_tokens / 1000) * 0.03, // $0.03 per 1K tokens | ||
| total: | ||
| (tokenUsage.prompt_tokens / 1000) * 0.01 + | ||
| (tokenUsage.completion_tokens / 1000) * 0.03, | ||
| } | ||
| : { inputCost: 0, outputCost: 0, total: 0 }; |
There was a problem hiding this comment.
🛠️ Refactor suggestion
Extract hardcoded pricing rates to configuration.
The token pricing rates are hardcoded, making them difficult to update when provider pricing changes.
Consider extracting these to a configuration object:
// At the top of the file or in a separate config file
const TOKEN_PRICING = {
input: {
costPer1K: 0.01, // $0.01 per 1K tokens
},
output: {
costPer1K: 0.03, // $0.03 per 1K tokens
},
};
// Then use in the calculation:
const estimatedCost = tokenUsage
? {
inputCost: (tokenUsage.prompt_tokens / 1000) * TOKEN_PRICING.input.costPer1K,
outputCost: (tokenUsage.completion_tokens / 1000) * TOKEN_PRICING.output.costPer1K,
total:
(tokenUsage.prompt_tokens / 1000) * TOKEN_PRICING.input.costPer1K +
(tokenUsage.completion_tokens / 1000) * TOKEN_PRICING.output.costPer1K,
}
: { inputCost: 0, outputCost: 0, total: 0 };🤖 Prompt for AI Agents
In ui/components/logs/log-detail-sheet.tsx around lines 92 to 100, the token
pricing rates are hardcoded in the estimatedCost calculation. To fix this,
define a configuration object (e.g., TOKEN_PRICING) at the top of the file or in
a separate config file containing the input and output cost rates per 1K tokens.
Then update the estimatedCost calculation to use these configuration values
instead of hardcoded numbers, improving maintainability and ease of updates.
| function DropdownMenuSubContent({ | ||
| className, | ||
| ...props | ||
| }: React.ComponentProps<typeof DropdownMenuPrimitive.SubContent>) { | ||
| return ( | ||
| <DropdownMenuPrimitive.SubContent | ||
| data-slot="dropdown-menu-sub-content" | ||
| className={cn( | ||
| "bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 min-w-[8rem] origin-(--radix-dropdown-menu-content-transform-origin) overflow-hidden rounded-md border p-1 shadow-lg", | ||
| className | ||
| )} | ||
| {...props} | ||
| /> | ||
| ) | ||
| } |
There was a problem hiding this comment.
Fix Tailwind CSS custom property syntax
Use square brackets for CSS custom properties in Tailwind.
className={cn(
- "bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 min-w-[8rem] origin-(--radix-dropdown-menu-content-transform-origin) overflow-hidden rounded-md border p-1 shadow-lg",
+ "bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 min-w-[8rem] origin-[var(--radix-dropdown-menu-content-transform-origin)] overflow-hidden rounded-md border p-1 shadow-lg",
className
)}📝 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.
| function DropdownMenuSubContent({ | |
| className, | |
| ...props | |
| }: React.ComponentProps<typeof DropdownMenuPrimitive.SubContent>) { | |
| return ( | |
| <DropdownMenuPrimitive.SubContent | |
| data-slot="dropdown-menu-sub-content" | |
| className={cn( | |
| "bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 min-w-[8rem] origin-(--radix-dropdown-menu-content-transform-origin) overflow-hidden rounded-md border p-1 shadow-lg", | |
| className | |
| )} | |
| {...props} | |
| /> | |
| ) | |
| } | |
| function DropdownMenuSubContent({ | |
| className, | |
| ...props | |
| }: React.ComponentProps<typeof DropdownMenuPrimitive.SubContent>) { | |
| return ( | |
| <DropdownMenuPrimitive.SubContent | |
| data-slot="dropdown-menu-sub-content" | |
| className={cn( | |
| "bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 min-w-[8rem] origin-[var(--radix-dropdown-menu-content-transform-origin)] overflow-hidden rounded-md border p-1 shadow-lg", | |
| className | |
| )} | |
| {...props} | |
| /> | |
| ) | |
| } |
🤖 Prompt for AI Agents
In ui/components/ui/dropdown-menu.tsx around lines 225 to 239, the Tailwind CSS
custom property syntax for origin is incorrect; it uses parentheses instead of
square brackets. Replace origin-(--radix-dropdown-menu-content-transform-origin)
with origin-[--radix-dropdown-menu-content-transform-origin] to fix the syntax
and ensure Tailwind processes the custom property correctly.
| function DropdownMenuContent({ | ||
| className, | ||
| sideOffset = 4, | ||
| ...props | ||
| }: React.ComponentProps<typeof DropdownMenuPrimitive.Content>) { | ||
| return ( | ||
| <DropdownMenuPrimitive.Portal> | ||
| <DropdownMenuPrimitive.Content | ||
| data-slot="dropdown-menu-content" | ||
| sideOffset={sideOffset} | ||
| className={cn( | ||
| "bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 max-h-(--radix-dropdown-menu-content-available-height) min-w-[8rem] origin-(--radix-dropdown-menu-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-md border p-1 shadow-md", | ||
| className | ||
| )} | ||
| {...props} | ||
| /> | ||
| </DropdownMenuPrimitive.Portal> | ||
| ) | ||
| } |
There was a problem hiding this comment.
Fix Tailwind CSS custom property syntax
The className contains incorrect syntax for CSS custom properties. Tailwind requires square brackets for arbitrary values.
className={cn(
- "bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 max-h-(--radix-dropdown-menu-content-available-height) min-w-[8rem] origin-(--radix-dropdown-menu-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-md border p-1 shadow-md",
+ "bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 max-h-[var(--radix-dropdown-menu-content-available-height)] min-w-[8rem] origin-[var(--radix-dropdown-menu-content-transform-origin)] overflow-x-hidden overflow-y-auto rounded-md border p-1 shadow-md",
className
)}📝 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.
| function DropdownMenuContent({ | |
| className, | |
| sideOffset = 4, | |
| ...props | |
| }: React.ComponentProps<typeof DropdownMenuPrimitive.Content>) { | |
| return ( | |
| <DropdownMenuPrimitive.Portal> | |
| <DropdownMenuPrimitive.Content | |
| data-slot="dropdown-menu-content" | |
| sideOffset={sideOffset} | |
| className={cn( | |
| "bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 max-h-(--radix-dropdown-menu-content-available-height) min-w-[8rem] origin-(--radix-dropdown-menu-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-md border p-1 shadow-md", | |
| className | |
| )} | |
| {...props} | |
| /> | |
| </DropdownMenuPrimitive.Portal> | |
| ) | |
| } | |
| function DropdownMenuContent({ | |
| className, | |
| sideOffset = 4, | |
| ...props | |
| }: React.ComponentProps<typeof DropdownMenuPrimitive.Content>) { | |
| return ( | |
| <DropdownMenuPrimitive.Portal> | |
| <DropdownMenuPrimitive.Content | |
| data-slot="dropdown-menu-content" | |
| sideOffset={sideOffset} | |
| className={cn( | |
| "bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 max-h-[var(--radix-dropdown-menu-content-available-height)] min-w-[8rem] origin-[var(--radix-dropdown-menu-content-transform-origin)] overflow-x-hidden overflow-y-auto rounded-md border p-1 shadow-md", | |
| className | |
| )} | |
| {...props} | |
| /> | |
| </DropdownMenuPrimitive.Portal> | |
| ) | |
| } |
🤖 Prompt for AI Agents
In ui/components/ui/dropdown-menu.tsx around lines 34 to 52, the Tailwind CSS
custom properties in the className string use parentheses instead of square
brackets for arbitrary values, which is incorrect. Replace the parentheses
around the custom properties with square brackets to follow Tailwind's syntax
for arbitrary values, for example, change
max-h-(--radix-dropdown-menu-content-available-height) to
max-h-[--radix-dropdown-menu-content-available-height] and
origin-(--radix-dropdown-menu-content-transform-origin) to
origin-[--radix-dropdown-menu-content-transform-origin].
| <Link | ||
| href="https://github.com/maximhq/bifrost/tree/main/docs/contributing/plugin.md" | ||
| target="_blank" | ||
| > | ||
| <Code className="mr-2 h-4 w-4" /> | ||
| Plugin Guide | ||
| </Link> | ||
| </Button> |
There was a problem hiding this comment.
Add security attributes to documentation links
These external links also need the security attributes for consistency and safety.
Apply these diffs:
<Button asChild className="w-full">
<Link
href="https://github.com/maximhq/bifrost/tree/main/docs/contributing/plugin.md"
target="_blank"
+ rel="noopener noreferrer"
>
<Code className="mr-2 h-4 w-4" />
Plugin Guide
</Link>
</Button> <Button asChild variant="outline" className="w-full">
<Link
href="https://github.com/maximhq/bifrost/tree/main/docs/architecture/plugins.md"
target="_blank"
+ rel="noopener noreferrer"
>
<Puzzle className="mr-2 h-4 w-4" />
Architecture Docs
</Link>
</Button>Also applies to: 267-274
🤖 Prompt for AI Agents
In ui/app/plugins/page.tsx around lines 240 to 247 and also lines 267 to 274,
the external documentation links are missing security attributes. Add
rel="noopener noreferrer" to all external <Link> components with target="_blank"
to improve security and prevent potential exploitation via the opened tabs.
| <Link | ||
| href="https://github.com/maximhq/bifrost/tree/main/docs/contributing/plugin.md" | ||
| target="_blank" | ||
| > | ||
| <Plus className="mr-2 h-4 w-4" /> | ||
| Create Plugin | ||
| </Link> | ||
| </Button> |
There was a problem hiding this comment.
Add security attributes to external links
External links with target="_blank" should include rel="noopener noreferrer" to prevent potential security vulnerabilities through window.opener access.
Apply these diffs to add the security attributes:
<Button variant="outline" asChild>
<Link
href="https://github.com/maximhq/bifrost/tree/main/docs/contributing/plugin.md"
target="_blank"
+ rel="noopener noreferrer"
>
<Plus className="mr-2 h-4 w-4" />
Create Plugin
</Link>
</Button> <Button asChild variant="outline" className="flex-1">
<Link
href={plugin.url}
target="_blank"
+ rel="noopener noreferrer"
className="flex items-center justify-center gap-2"
>
<Code className="h-4 w-4" />
View Source
</Link>
</Button>
<Button asChild size="sm" variant="ghost">
- <Link href={plugin.url} target="_blank">
+ <Link href={plugin.url} target="_blank" rel="noopener noreferrer">
<ExternalLink className="h-4 w-4" />
</Link>
</Button>Also applies to: 201-214
🤖 Prompt for AI Agents
In ui/app/plugins/page.tsx around lines 138 to 145 and also lines 201 to 214,
external links using target="_blank" are missing the rel="noopener noreferrer"
attributes. To fix this, add rel="noopener noreferrer" to all Link components
that open in a new tab to prevent security risks related to window.opener
access.
| // This sets the cookie to keep the sidebar state. | ||
| document.cookie = `${SIDEBAR_COOKIE_NAME}=${openState}; path=/; max-age=${SIDEBAR_COOKIE_MAX_AGE}` | ||
| }, |
There was a problem hiding this comment.
Potential SSR issue with document.cookie
Direct access to document.cookie could cause issues during server-side rendering. Consider wrapping in a check or using an effect.
Apply this fix to ensure SSR compatibility:
// This sets the cookie to keep the sidebar state.
- document.cookie = `${SIDEBAR_COOKIE_NAME}=${openState}; path=/; max-age=${SIDEBAR_COOKIE_MAX_AGE}`
+ if (typeof document !== 'undefined') {
+ document.cookie = `${SIDEBAR_COOKIE_NAME}=${openState}; path=/; max-age=${SIDEBAR_COOKIE_MAX_AGE}`
+ }📝 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.
| // This sets the cookie to keep the sidebar state. | |
| document.cookie = `${SIDEBAR_COOKIE_NAME}=${openState}; path=/; max-age=${SIDEBAR_COOKIE_MAX_AGE}` | |
| }, | |
| // This sets the cookie to keep the sidebar state. | |
| if (typeof document !== 'undefined') { | |
| document.cookie = `${SIDEBAR_COOKIE_NAME}=${openState}; path=/; max-age=${SIDEBAR_COOKIE_MAX_AGE}` | |
| } | |
| }, |
🤖 Prompt for AI Agents
In ui/components/ui/sidebar.tsx around lines 85 to 87, direct access to
document.cookie can cause errors during server-side rendering because document
is not defined on the server. To fix this, wrap the code that sets
document.cookie inside a check to ensure it only runs in the browser, such as
verifying if typeof window !== 'undefined' before accessing document.cookie, or
move the cookie-setting logic inside a useEffect hook that only runs on the
client side.
8d78f26 to
f3ac4cc
Compare
a8f4d06 to
c522aad
Compare
f3ac4cc to
70f6ae3
Compare
There was a problem hiding this comment.
Actionable comments posted: 43
♻️ Duplicate comments (47)
ui/postcss.config.mjs (1)
1-3: Plugin name still wrong – Tailwind will not load
Same issue flagged earlier:@tailwindcss/postcssis not a package. Usetailwindcss(plusautoprefixer) or the build fails.-const config = { - plugins: ["@tailwindcss/postcss"], -}; +const config = { + plugins: { + tailwindcss: {}, + autoprefixer: {}, + }, +};ui/next.config.ts (1)
3-5: Empty config adds noise – delete until needed
No custom options; removing the file avoids dead code and maintenance overhead.ui/components/progress-bar.tsx (1)
1-6: Missing type-only React import (repeat of earlier feedback).
React.ReactNodeis referenced butReactisn’t imported; this still breaks in TS strict projects."use client"; -import { ProgressProvider } from "@bprogress/next/app"; +import type React from "react"; +import { ProgressProvider } from "@bprogress/next/app";ui/components/header.tsx (1)
6-6: Fix invalid Tailwind CSS syntax for CSS custom property.The class
left-(--sidebar-width)is not valid Tailwind CSS syntax. This issue was previously identified and needs to be addressed.Use one of these approaches:
Option 1: Inline style
- <div className="bg-background fixed top-0 right-0 left-(--sidebar-width) z-10"> + <div + className="bg-background fixed top-0 right-0 z-10" + style={{ left: 'var(--sidebar-width)' }} + >Option 2: Custom CSS class
- <div className="bg-background fixed top-0 right-0 left-(--sidebar-width) z-10"> + <div className="bg-background fixed top-0 right-0 z-10 header-with-sidebar">Then define in your CSS:
.header-with-sidebar { left: var(--sidebar-width); }ui/components/logs/analytics/token-usage-chart.tsx (2)
21-21: Fixed height may impact responsiveness.The fixed height class
h-80may not be responsive across different screen sizes. Consider using a more flexible approach.
61-71: Hardcoded colors should use theme-aware variables.The hardcoded hex colors
#6B7280and#8B5CF6won't adapt to theme changes. Consider using CSS custom properties from your design system.ui/README.md (1)
1-1: Missing top-level heading for better markdown structure.The markdown linter suggests adding a top-level heading at the beginning of the file for better structure.
ui/components/logs/analytics/latency-chart.tsx (2)
44-50: Consider using consistent tooltip styling across chart components.Similar to the StatusDistributionChart, this uses hardcoded HSL values. Consider creating a shared tooltip style configuration.
57-74: Replace hardcoded colors with CSS custom properties for theme consistency.The bar colors are hardcoded hex values instead of using CSS custom properties, which could cause theme inconsistencies.
ui/components/logs/analytics/request-volume-chart.tsx (1)
53-76: Consider using theme-aware colors for consistency.The chart implementation is excellent, but mixing hardcoded hex colors with theme-aware CSS custom properties could lead to inconsistent theming, especially in dark mode.
ui/hooks/use-toast.ts (2)
11-11: Improve message formatting for better UX.The message concatenation still uses colon formatting which may not provide optimal user experience.
13-17: Consider adding neutral toast variant for better semantic accuracy.The implementation still defaults to success for all non-destructive variants, which may not be semantically correct for informational messages.
ui/components/logs/analytics/status-distribution-chart.tsx (1)
35-37: Optimize data mapping for better performance.The
data.map()call inside the render function is still not memoized and may cause unnecessary re-renders for large datasets.ui/components/config/core-settings-form.tsx (1)
60-63: Fix accessibility issue: Associate label with form control.The label "Drop Excess Requests" is not properly associated with the Switch component, creating accessibility issues for screen readers.
ui/components/ui/progress.tsx (1)
18-18: Add value validation to prevent rendering issues.The transform calculation doesn't handle edge cases where
valuemight be negative or exceed 100, which could cause visual inconsistencies.- style={{ transform: `translateX(-${100 - (value || 0)}%)` }} + style={{ + transform: `translateX(-${100 - Math.max(0, Math.min(100, value || 0))}%)` + }}ui/components/ui/input.tsx (1)
7-21: Consider addingforwardReffor better form library integration.The Input component is well-implemented with comprehensive styling and accessibility features. However, adding
forwardRefwould improve compatibility with form libraries like react-hook-form that need direct DOM access.-export function Input({ className, type, ...props }: InputProps) { +const Input = React.forwardRef<HTMLInputElement, InputProps>( + ({ className, type, ...props }, ref) => { return ( <input + ref={ref} type={type} data-slot="input" className={cn( "file:text-foreground placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground dark:bg-input/30 border-input flex h-9 w-full min-w-0 rounded-md border bg-transparent px-3 py-1 text-base shadow-xs transition-[color,box-shadow] outline-none file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm", "focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]", "aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive", className, )} {...props} /> ); -} +}); +Input.displayName = "Input"; +export { Input };ui/components/sidebar.tsx (1)
170-170: Fix JSX self-closing element.The animated dot div should be self-closing as it has no children.
Apply this diff to fix the JSX formatting:
- <div className="h-2 w-2 animate-pulse rounded-full bg-green-500"></div> + <div className="h-2 w-2 animate-pulse rounded-full bg-green-500" />ui/app/plugins/page.tsx (1)
106-106: Add security attributes to external linksThe external links with
target="_blank"are still missing therel="noopener noreferrer"security attributes that were flagged in previous reviews.Also applies to: 150-150, 156-156, 182-182, 203-203
ui/components/ui/scroll-area.tsx (1)
17-17: ScrollBar orientation is not configurableThe ScrollBar is still rendered with default orientation without allowing configuration, which was flagged in the previous review.
ui/components/ui/hover-card.tsx (1)
29-29: Fix CSS variable syntax in className.The CSS variable syntax is invalid. Apply the previously suggested fix:
-"bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 w-64 origin-(--radix-hover-card-content-transform-origin) rounded-md border p-4 shadow-md outline-hidden", +"bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 w-64 origin-[var(--radix-hover-card-content-transform-origin)] rounded-md border p-4 shadow-md outline-hidden",ui/app/docs/page.tsx (2)
73-76: Add security attributes to external links.External links with
target="_blank"are missingrel="noopener noreferrer"attributes, which creates security vulnerabilities.Apply this pattern to all external links:
- href="https://github.com/maximhq/bifrost/tree/main/docs" - target="_blank" + href="https://github.com/maximhq/bifrost/tree/main/docs" + target="_blank" + rel="noopener noreferrer"Also applies to: 79-82, 117-120, 143-146, 164-167
8-53: Add TypeScript interface for better type safety.The
docSectionsarray lacks explicit type definitions, reducing type safety and IntelliSense support.Add this interface definition:
+interface DocSection { + title: string; + description: string; + icon: React.ComponentType<{ className?: string }>; + url: string; + badge?: string; + items: string[]; +} + -const docSections = [ +const docSections: DocSection[] = [ui/components/config/mcp-clients-lists.tsx (1)
82-84: Fix string concatenation with template literal.Use template literals instead of string concatenation for better readability and performance.
- client.config.stdio_config?.command + " " + client.config.stdio_config?.args.join(" ") || "STDIO"; + `${client.config.stdio_config?.command} ${client.config.stdio_config?.args.join(" ")}` || "STDIO";ui/components/config/meta-config-renderer.tsx (3)
83-84: Replaceanytype with a more specific type.Using
anydefeats TypeScript's type safety benefits.- // eslint-disable-next-line @typescript-eslint/no-explicit-any - onMetaConfigChange: (key: keyof MetaConfig, value: any) => void; + onMetaConfigChange: (key: keyof MetaConfig, value: MetaConfig[keyof MetaConfig]) => void;
106-112: Provide user feedback for JSON parsing errors.Currently, JSON parsing errors are silently ignored, which could confuse users when their input doesn't save as expected.
Consider adding error feedback:
onBlur={(e) => { if (field.isJson) { try { const parsed = JSON.parse(e.target.value); onMetaConfigChange(field.name, parsed); } catch (error) { // You could add a validation state or show a toast console.error(`Invalid JSON for ${field.label}:`, error); // Optionally, you could pass an error handler prop: // onJsonError?.(field.name, error); } } }}
156-157: Fix accessibility issue: Associate label with form input.The label element is not properly associated with its input/textarea, which impacts accessibility.
- <label className="block text-sm font-medium">{field.label}</label> + <label + htmlFor={`meta-${field.name}`} + className="block text-sm font-medium" + > + {field.label} + </label>Then update the
renderFieldfunction to add the correspondingid:<Textarea + id={`meta-${field.name}`} placeholder={field.placeholder}<Input + id={`meta-${field.name}`} placeholder={field.placeholder}ui/components/ui/tooltip.tsx (2)
31-31: Fix the CSS custom property syntax.The transform-origin class appears to have incorrect syntax for referencing a CSS variable.
- "bg-primary text-primary-foreground animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 w-fit origin-(--radix-tooltip-content-transform-origin) rounded-md px-3 py-1.5 text-xs text-balance", + "bg-primary text-primary-foreground animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 w-fit origin-[var(--radix-tooltip-content-transform-origin)] rounded-md px-3 py-1.5 text-xs text-balance",
12-18: Consider removing the nested TooltipProvider to improve performance.The current implementation creates a new
TooltipProviderfor eachTooltipinstance, which is inefficient and can lead to performance issues when multiple tooltips are used.Remove the nested provider:
-function Tooltip({ - ...props -}: React.ComponentProps<typeof TooltipPrimitive.Root>) { - return ( - <TooltipProvider> - <TooltipPrimitive.Root data-slot="tooltip" {...props} /> - </TooltipProvider> - ) -} +const Tooltip = TooltipPrimitive.RootThen ensure a single
TooltipProvideris added at the app root level (e.g., inui/app/layout.tsx).ui/components/ui/table.tsx (1)
42-42: Address the hardcoded whitespace handling issueThe previous review comment about hardcoded
whitespace-nowrapinTableHeadandTableCellcomponents is still applicable. This can cause horizontal scrolling issues with long content or on smaller screens.Consider making whitespace handling configurable through props:
-function TableHead({ className, ...props }: React.ComponentProps<"th">) { +function TableHead({ className, nowrap = true, ...props }: React.ComponentProps<"th"> & { nowrap?: boolean }) { return ( <th data-slot="table-head" className={cn( - "text-foreground h-10 px-2 text-left align-middle font-medium whitespace-nowrap [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]", + "text-foreground h-10 px-2 text-left align-middle font-medium [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]", + nowrap && "whitespace-nowrap", className )} {...props} /> ) }Apply similar changes to
TableCell.Also applies to: 54-54
ui/components/config/mcp-client-form.tsx (3)
80-88: Replace non-null assertion with safer type handling.The non-null assertion on
prev.stdio_config!could cause runtime errors if stdio_config is undefined.Apply this diff for safer handling:
const handleStdioConfigChange = (field: keyof MCPStdioConfig, value: string | string[]) => { setForm((prev) => ({ ...prev, stdio_config: { - ...prev.stdio_config!, + ...(prev.stdio_config || emptyStdioConfig), [field]: value, }, })); };
103-158: Consider extracting validation logic for better maintainability.The validation logic could be extracted into a separate function for better testability and reusability.
167-176: Use optional chaining instead of non-null assertion.Replace the non-null assertion with safer optional chaining to prevent runtime errors.
Apply this diff:
stdio_config: form.connection_type === "stdio" ? { - ...form.stdio_config!, + ...(form.stdio_config || emptyStdioConfig), args: parseArrayFromText(argsText), envs: parseArrayFromText(envsText), } : undefined,ui/components/config/provider-form.tsx (4)
411-535: Fix accessibility issues with form labels
298-298: Use Number namespace methods for consistencyAlso applies to: 508-508, 522-522, 559-559, 573-573
574-627: Apply consistent label accessibility fixes to remaining form fields
84-675: Consider breaking down this large componentui/lib/api.ts (3)
31-31: Apply optional chaining for cleaner error handling.
132-139: Clarify the distinction between reloadConfig and updateCoreConfig.Also applies to: 150-157
169-176: Fix return value for reconnectMCPClient method.ui/components/ui/command.tsx (1)
55-55: Fix invalid Tailwind CSS classAlso applies to: 100-100
ui/components/ui/sidebar.tsx (1)
85-87: Potential SSR issue with document.cookieui/components/ui/dropdown-menu.tsx (6)
56-56: Replace non-standardoutline-hiddenwithoutline-none
74-74: Replace non-standardoutline-hiddenwithoutline-none
99-99: Replace non-standardoutline-hiddenwithoutline-none
168-168: Replace non-standardoutline-hiddenwithoutline-none
28-28: Fix Tailwind CSS custom property syntax
184-184: Fix Tailwind CSS custom property syntax
📜 Review details
Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro
⛔ Files ignored due to path filters (1)
ui/package-lock.jsonis excluded by!**/package-lock.json
📒 Files selected for processing (85)
transports/bifrost-http/handlers/config.go(1 hunks)transports/bifrost-http/main.go(2 hunks)transports/bifrost-http/plugins/logging/main.go(3 hunks)transports/bifrost-http/plugins/logging/utils.go(0 hunks)ui/.gitignore(1 hunks)ui/.prettierrc(1 hunks)ui/README.md(1 hunks)ui/app/config/page.tsx(1 hunks)ui/app/docs/page.tsx(1 hunks)ui/app/globals.css(1 hunks)ui/app/layout.tsx(1 hunks)ui/app/page.tsx(1 hunks)ui/app/plugins/page.tsx(1 hunks)ui/components.json(1 hunks)ui/components/config/core-settings-form.tsx(1 hunks)ui/components/config/mcp-client-form.tsx(1 hunks)ui/components/config/mcp-clients-lists.tsx(1 hunks)ui/components/config/meta-config-renderer.tsx(1 hunks)ui/components/config/provider-form.tsx(1 hunks)ui/components/config/providers-list.tsx(1 hunks)ui/components/header.tsx(1 hunks)ui/components/logs/analytics/latency-chart.tsx(1 hunks)ui/components/logs/analytics/provider-distribution-chart.tsx(1 hunks)ui/components/logs/analytics/request-volume-chart.tsx(1 hunks)ui/components/logs/analytics/status-distribution-chart.tsx(1 hunks)ui/components/logs/analytics/token-usage-chart.tsx(1 hunks)ui/components/logs/columns.tsx(1 hunks)ui/components/logs/filters.tsx(1 hunks)ui/components/logs/log-detail-sheet.tsx(1 hunks)ui/components/logs/logs-table.tsx(1 hunks)ui/components/logs/ui/code-editor.css(1 hunks)ui/components/logs/ui/code-editor.tsx(1 hunks)ui/components/logs/ui/log-entry-details-view.tsx(1 hunks)ui/components/logs/ui/log-message-view.tsx(1 hunks)ui/components/progress-bar.tsx(1 hunks)ui/components/sidebar.tsx(1 hunks)ui/components/theme-provider.tsx(1 hunks)ui/components/theme-toggle.tsx(1 hunks)ui/components/ui/accordion.tsx(1 hunks)ui/components/ui/alert-dialog.tsx(1 hunks)ui/components/ui/alert.tsx(1 hunks)ui/components/ui/aspect-ratio.tsx(1 hunks)ui/components/ui/avatar.tsx(1 hunks)ui/components/ui/badge.tsx(1 hunks)ui/components/ui/button.tsx(1 hunks)ui/components/ui/card.tsx(1 hunks)ui/components/ui/collapsible.tsx(1 hunks)ui/components/ui/command.tsx(1 hunks)ui/components/ui/dialog.tsx(1 hunks)ui/components/ui/dropdown-menu.tsx(1 hunks)ui/components/ui/form-field.tsx(1 hunks)ui/components/ui/hover-card.tsx(1 hunks)ui/components/ui/input.tsx(1 hunks)ui/components/ui/label.tsx(1 hunks)ui/components/ui/popover.tsx(1 hunks)ui/components/ui/progress.tsx(1 hunks)ui/components/ui/scroll-area.tsx(1 hunks)ui/components/ui/select.tsx(1 hunks)ui/components/ui/separator.tsx(1 hunks)ui/components/ui/sheet.tsx(1 hunks)ui/components/ui/sidebar.tsx(1 hunks)ui/components/ui/skeleton.tsx(1 hunks)ui/components/ui/switch.tsx(1 hunks)ui/components/ui/table.tsx(1 hunks)ui/components/ui/tabs.tsx(1 hunks)ui/components/ui/tag-input.tsx(1 hunks)ui/components/ui/textarea.tsx(1 hunks)ui/components/ui/tooltip.tsx(1 hunks)ui/eslint.config.mjs(1 hunks)ui/hooks/use-mobile.ts(1 hunks)ui/hooks/use-toast.ts(1 hunks)ui/hooks/useWebSocket.ts(1 hunks)ui/lib/api.ts(1 hunks)ui/lib/constants/config.ts(1 hunks)ui/lib/constants/icons.tsx(1 hunks)ui/lib/constants/logs.ts(1 hunks)ui/lib/types/config.ts(1 hunks)ui/lib/types/logs.ts(1 hunks)ui/lib/types/mcp.ts(1 hunks)ui/lib/utils.ts(1 hunks)ui/lib/utils/validation.ts(1 hunks)ui/next.config.ts(1 hunks)ui/package.json(1 hunks)ui/postcss.config.mjs(1 hunks)ui/tsconfig.json(1 hunks)
💤 Files with no reviewable changes (1)
- transports/bifrost-http/plugins/logging/utils.go
🧰 Additional context used
🧠 Learnings (11)
📓 Common learnings
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#84
File: transports/bifrost-http/main.go:2-2
Timestamp: 2025-06-15T16:05:13.489Z
Learning: For the Bifrost project, HTTP transport integration routers for new providers (like Mistral and Ollama) are implemented in separate PRs from the core provider support, following a focused PR strategy.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#103
File: .github/workflows/transport-dependency-update.yml:30-36
Timestamp: 2025-06-19T16:57:25.177Z
Learning: In the bifrost repository, Pratham-Mishra04 prefers to keep GitHub Actions workflows lean and trusts their controlled tagging process for core releases, avoiding unnecessary validation steps that they consider overkill.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#63
File: transports/bifrost-http/integrations/openai/types.go:89-119
Timestamp: 2025-06-10T11:00:02.875Z
Learning: In the Bifrost OpenAI integration (transports/bifrost-http/integrations/openai/types.go), the convertOpenAIContent function currently only handles the last image URL when multiple images are present in a content array. The user Pratham-Mishra04 has acknowledged this limitation and indicated it's part of a larger architectural issue that will be addressed comprehensively later, rather than with piecemeal fixes.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#54
File: core/schemas/provider.go:148-148
Timestamp: 2025-06-04T03:57:50.981Z
Learning: Breaking changes in the Bifrost codebase are managed by first merging and tagging core schema changes, then updating dependent code references in subsequent steps after the core version is released.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#55
File: core/providers/anthropic.go:358-388
Timestamp: 2025-06-04T05:37:59.699Z
Learning: User Pratham-Mishra04 prefers not to extract small code duplications (around 2 lines) into helper functions, considering the overhead not worth it for such minor repetition.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#102
File: README.md:62-66
Timestamp: 2025-06-19T17:03:03.639Z
Learning: Pratham-Mishra04 prefers using the implicit 'latest' tag for the maximhq/bifrost Docker image rather than pinning to specific versions.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#138
File: docs/usage/go-package/mcp.md:408-412
Timestamp: 2025-07-01T12:40:08.576Z
Learning: Pratham-Mishra04 is okay with keeping bullet list formatting that uses colons after dashes in markdown documentation, even if it triggers linter warnings, preferring functionality over strict formatting rules.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#138
File: transports/README.md:26-28
Timestamp: 2025-07-01T12:45:06.906Z
Learning: Pratham-Mishra04 prefers keeping documentation examples simple and concise, trusting users to handle production-specific considerations like version pinning themselves rather than cluttering examples with additional notes.
ui/lib/constants/icons.tsx (1)
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#81
File: tests/core-providers/go.mod:38-38
Timestamp: 2025-06-16T03:54:48.005Z
Learning: The `core-providers-test` module in `tests/core-providers/` is an internal testing module that will never be consumed as a dependency by external projects, so the replace directive pointing to `../../core` is acceptable for local development and testing purposes.
ui/app/config/page.tsx (1)
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#85
File: core/providers/anthropic.go:150-156
Timestamp: 2025-06-15T16:07:53.140Z
Learning: In the Bifrost codebase, constructor functions are allowed to mutate input ProviderConfig objects in-place (e.g., setting default BaseURL values and trimming trailing slashes). This pattern is acceptable and doesn't need to be flagged as a code review issue.
ui/README.md (1)
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#94
File: core/bifrost.go:823-845
Timestamp: 2025-06-18T15:15:51.323Z
Learning: In the Bifrost project, the team prioritizes maintaining consistent error handling patterns over exposing detailed error context. All errors should be wrapped in the standard `BifrostError` structure rather than creating specific error types or exposing richer error details like exit codes or stderr output.
transports/bifrost-http/main.go (6)
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#67
File: transports/bifrost-http/integrations/anthropic/router.go:26-34
Timestamp: 2025-06-10T11:19:29.604Z
Learning: The Generic router in transports/bifrost-http/integrations/utils.go already handles nil pointers from RequestConverter functions. When a RequestConverter returns a nil *schemas.BifrostRequest, the Generic router automatically returns an HTTP 400 error, making additional nil checks in individual router implementations redundant.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#67
File: transports/bifrost-http/integrations/anthropic/router.go:26-34
Timestamp: 2025-06-10T11:19:29.604Z
Learning: The Generic router in transports/bifrost-http/integrations/utils.go already handles nil pointers from RequestConverter functions. When a RequestConverter returns a nil *schemas.BifrostRequest, the Generic router automatically returns an HTTP 400 error with "Invalid request" message, making additional nil checks in individual router implementations redundant.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#103
File: .github/workflows/transport-dependency-update.yml:53-75
Timestamp: 2025-06-20T16:21:18.912Z
Learning: In the bifrost repository's transport dependency update workflow, when updating the core dependency to a new version using `go get`, the go.mod and go.sum files will always change in normal operation, making the safety check for changes more of a defensive programming practice rather than handling a common scenario.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#65
File: transports/bifrost-http/integrations/anthropic/router.go:19-33
Timestamp: 2025-06-09T16:46:32.018Z
Learning: In the GenericRouter (transports/bifrost-http/integrations), ResponseFunc is not called if the BifrostResponse parameter is nil, providing built-in protection against nil response marshaling.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#83
File: core/providers/mistral.go:168-170
Timestamp: 2025-06-15T14:24:49.882Z
Learning: In the Bifrost codebase, performance is prioritized over defensive copying for HTTP service operations. Specifically, shallow slice assignments in provider response handling are acceptable due to object pool reset patterns and JSON unmarshaling behavior that minimize practical data corruption risks.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#84
File: transports/bifrost-http/main.go:2-2
Timestamp: 2025-06-15T16:05:13.489Z
Learning: For the Bifrost project, HTTP transport integration routers for new providers (like Mistral and Ollama) are implemented in separate PRs from the core provider support, following a focused PR strategy.
ui/components/logs/columns.tsx (1)
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#85
File: core/providers/anthropic.go:150-156
Timestamp: 2025-06-15T16:07:53.140Z
Learning: In the Bifrost codebase, constructor functions are allowed to mutate input ProviderConfig objects in-place (e.g., setting default BaseURL values and trimming trailing slashes). This pattern is acceptable and doesn't need to be flagged as a code review issue.
transports/bifrost-http/plugins/logging/main.go (6)
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#79
File: core/bifrost.go:94-103
Timestamp: 2025-06-14T04:06:58.240Z
Learning: In core/bifrost.go, the count parameter in RunPostHooks method is intentionally kept separate from p.executedPreHooks to support circuit breaker plugins that may need to trigger PostHooks for only a subset of executed plugins when detecting failure conditions mid-execution.
Learnt from: connyay
PR: maximhq/bifrost#92
File: core/providers/utils.go:60-64
Timestamp: 2025-06-17T14:04:21.104Z
Learning: The bifrost codebase uses string alias types (like `type ContextKey string`) for context keys consistently across multiple packages including plugins/maxim/main.go and transports/bifrost-http/tracking/plugin.go. This pattern should be maintained for consistency rather than switching to the canonical struct{} approach.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#55
File: core/providers/bedrock.go:443-468
Timestamp: 2025-06-04T09:32:15.826Z
Learning: In core/providers/bedrock.go, for tool call result messages (ModelChatMessageRoleTool), the Content field represents the actual tool call output. A tool result message should only be created when msg.Content is non-nil, as there's no semantic meaning to a tool result without output content.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#55
File: core/providers/bedrock.go:750-791
Timestamp: 2025-06-04T06:09:18.600Z
Learning: In the Bedrock provider, tool result messages maintain their original tool role in the input messages. The remapping from tool role to user role only occurs during message preparation for the Bedrock API request in `prepareChatCompletionMessages`, not in the original input. The `extractToolsFromHistory` function operates on unprocessed input messages where tool results retain their tool role.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#54
File: core/schemas/bifrost.go:46-49
Timestamp: 2025-06-04T09:22:18.123Z
Learning: In core/schemas/bifrost.go, the RequestInput struct uses ChatCompletionInput *[]BifrostMessage (pointer-to-slice) rather than []BifrostMessage to properly represent union type semantics. For text completion requests, ChatCompletionInput should be nil to indicate "no chat payload at all", while for chat completion requests it should be non-nil (even if empty slice). This distinguishes between different request types rather than just empty vs non-empty chat messages.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#65
File: transports/bifrost-http/integrations/utils.go:169-173
Timestamp: 2025-06-09T17:33:52.234Z
Learning: The ChatCompletionRequest method in the Bifrost client follows a contract where the result parameter will never be nil if the error parameter is nil. This means when error checking passes (err == nil), the result is guaranteed to be valid and can be safely used without additional nil checks.
ui/components/config/mcp-client-form.tsx (1)
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#131
File: transports/bifrost-http/lib/config.go:35-68
Timestamp: 2025-06-26T07:37:24.385Z
Learning: In the Bifrost project's MCP configuration handling, empty environment variables should be treated as missing/invalid rather than as valid empty values. The current implementation using `os.Getenv(envKey); envValue != ""` to check for non-empty values is the desired behavior.
ui/lib/types/mcp.ts (1)
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#100
File: core/mcp.go:489-490
Timestamp: 2025-06-19T12:38:07.544Z
Learning: In the Bifrost MCP manager (core/mcp.go), the connectToMCPClient method is called during initialization/connection setup, not frequently during runtime. Logging operations like m.logger.Info inside critical sections in this context have negligible performance impact and don't require optimization for lock contention.
ui/components/config/provider-form.tsx (1)
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#85
File: core/providers/anthropic.go:150-156
Timestamp: 2025-06-15T16:07:53.140Z
Learning: In the Bifrost codebase, constructor functions are allowed to mutate input ProviderConfig objects in-place (e.g., setting default BaseURL values and trimming trailing slashes). This pattern is acceptable and doesn't need to be flagged as a code review issue.
ui/lib/types/logs.ts (2)
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#64
File: transports/bifrost-http/integrations/genai/types.go:383-395
Timestamp: 2025-06-09T16:26:05.777Z
Learning: In the Bifrost schema (core/schemas/bifrost.go), only UserMessage and ToolMessage structs have ImageContent fields. AssistantMessage does not have an ImageContent field and cannot contain images. The schema design intentionally limits image content to user and tool messages only.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#80
File: plugins/maxim/main.go:249-264
Timestamp: 2025-06-14T06:17:54.426Z
Learning: In the BifrostError struct, the Error field is a struct (not a pointer), so accessing bifrostErr.Error.Message, bifrostErr.Error.Code, and bifrostErr.Error.Type is safe without nil checks on the Error field itself. The Code and Type fields are of type *string.
🧬 Code Graph Analysis (40)
ui/components/header.tsx (1)
ui/components/theme-toggle.tsx (1)
ThemeToggle(10-29)
ui/components/ui/textarea.tsx (1)
ui/lib/utils.ts (1)
cn(4-6)
ui/components/theme-toggle.tsx (2)
ui/components/ui/dropdown-menu.tsx (4)
DropdownMenu(193-193)DropdownMenuTrigger(195-195)DropdownMenuContent(196-196)DropdownMenuItem(199-199)ui/components/ui/button.tsx (1)
Button(71-71)
ui/app/layout.tsx (2)
ui/components/theme-provider.tsx (1)
ThemeProvider(6-8)ui/components/ui/sidebar.tsx (2)
SidebarProvider(721-721)Sidebar(702-702)
ui/components/ui/skeleton.tsx (1)
ui/lib/utils.ts (1)
cn(4-6)
ui/components/ui/avatar.tsx (1)
ui/lib/utils.ts (1)
cn(4-6)
ui/components/ui/switch.tsx (1)
ui/lib/utils.ts (1)
cn(4-6)
ui/components/ui/progress.tsx (1)
ui/lib/utils.ts (1)
cn(4-6)
ui/components/ui/button.tsx (1)
ui/lib/utils.ts (1)
cn(4-6)
ui/components/ui/alert.tsx (1)
ui/lib/utils.ts (1)
cn(4-6)
ui/components/ui/tooltip.tsx (1)
ui/lib/utils.ts (1)
cn(4-6)
ui/components/ui/separator.tsx (1)
ui/lib/utils.ts (1)
cn(4-6)
ui/components/ui/input.tsx (1)
ui/lib/utils.ts (1)
cn(4-6)
ui/components/ui/scroll-area.tsx (1)
ui/lib/utils.ts (1)
cn(4-6)
ui/components/ui/popover.tsx (1)
ui/lib/utils.ts (1)
cn(4-6)
ui/components/ui/hover-card.tsx (1)
ui/lib/utils.ts (1)
cn(4-6)
ui/components/ui/accordion.tsx (1)
ui/lib/utils.ts (1)
cn(4-6)
ui/components/ui/tag-input.tsx (3)
ui/lib/utils.ts (1)
cn(4-6)ui/components/ui/badge.tsx (1)
Badge(37-37)ui/components/ui/input.tsx (1)
Input(7-21)
ui/components/logs/filters.tsx (7)
ui/lib/types/logs.ts (1)
LogFilters(147-159)ui/lib/constants/logs.ts (3)
STATUSES(3-3)PROVIDERS(1-1)REQUEST_TYPES(5-5)ui/components/ui/input.tsx (1)
Input(7-21)ui/components/ui/popover.tsx (3)
Popover(48-48)PopoverTrigger(48-48)PopoverContent(48-48)ui/components/ui/button.tsx (1)
Button(71-71)ui/components/ui/command.tsx (6)
Command(114-114)CommandInput(114-114)CommandList(114-114)CommandEmpty(114-114)CommandGroup(114-114)CommandItem(114-114)ui/lib/utils.ts (1)
cn(4-6)
ui/hooks/useWebSocket.ts (2)
transports/bifrost-http/plugins/logging/main.go (1)
LogEntry(46-62)ui/lib/types/logs.ts (1)
LogEntry(129-145)
ui/components/logs/columns.tsx (5)
transports/bifrost-http/plugins/logging/main.go (1)
LogEntry(46-62)ui/lib/types/logs.ts (1)
LogEntry(129-145)ui/components/ui/button.tsx (1)
Button(71-71)ui/lib/constants/logs.ts (6)
Provider(47-47)PROVIDER_COLORS(18-27)Status(48-48)STATUS_COLORS(29-33)REQUEST_TYPE_COLORS(41-45)REQUEST_TYPE_LABELS(35-39)ui/components/ui/badge.tsx (1)
Badge(37-37)
transports/bifrost-http/plugins/logging/main.go (2)
plugins/mocker/main.go (2)
Latency(124-128)Usage(137-141)ui/lib/types/logs.ts (1)
BifrostMessage(17-25)
ui/components/logs/ui/log-entry-details-view.tsx (1)
ui/lib/utils.ts (1)
cn(4-6)
ui/components/ui/form-field.tsx (5)
ui/lib/utils/validation.ts (2)
ValidationConfig(8-11)validateField(19-27)ui/lib/utils.ts (1)
cn(4-6)ui/components/ui/label.tsx (1)
Label(24-24)ui/components/ui/tooltip.tsx (4)
TooltipProvider(43-43)Tooltip(43-43)TooltipTrigger(43-43)TooltipContent(43-43)ui/components/ui/input.tsx (1)
Input(7-21)
ui/components/ui/alert-dialog.tsx (2)
ui/lib/utils.ts (1)
cn(4-6)ui/components/ui/button.tsx (1)
buttonVariants(71-71)
ui/components/ui/label.tsx (1)
ui/lib/utils.ts (1)
cn(4-6)
ui/components/logs/ui/code-editor.tsx (1)
ui/lib/utils.ts (1)
cn(4-6)
ui/components/ui/table.tsx (1)
ui/lib/utils.ts (1)
cn(4-6)
ui/components/ui/badge.tsx (1)
ui/lib/utils.ts (1)
cn(4-6)
ui/components/ui/select.tsx (1)
ui/lib/utils.ts (1)
cn(4-6)
ui/components/ui/command.tsx (2)
ui/lib/utils.ts (1)
cn(4-6)ui/components/ui/dialog.tsx (5)
Dialog(91-91)DialogHeader(96-96)DialogTitle(99-99)DialogDescription(94-94)DialogContent(93-93)
ui/components/ui/tabs.tsx (1)
ui/lib/utils.ts (1)
cn(4-6)
ui/components/ui/dialog.tsx (1)
ui/lib/utils.ts (1)
cn(4-6)
ui/components/config/mcp-clients-lists.tsx (9)
ui/lib/types/mcp.ts (1)
MCPClient(20-25)ui/hooks/use-toast.ts (1)
useToast(9-21)ui/lib/api.ts (1)
apiService(209-209)ui/components/ui/card.tsx (3)
CardHeader(50-50)CardTitle(50-50)CardDescription(50-50)ui/components/ui/button.tsx (1)
Button(71-71)ui/components/ui/table.tsx (6)
Table(64-64)TableHeader(64-64)TableRow(64-64)TableHead(64-64)TableBody(64-64)TableCell(64-64)ui/components/ui/badge.tsx (1)
Badge(37-37)ui/lib/constants/config.ts (1)
MCP_STATUS_COLORS(14-18)ui/components/ui/alert-dialog.tsx (9)
AlertDialog(83-83)AlertDialogTrigger(86-86)AlertDialogContent(87-87)AlertDialogHeader(88-88)AlertDialogTitle(90-90)AlertDialogDescription(91-91)AlertDialogFooter(89-89)AlertDialogCancel(93-93)AlertDialogAction(92-92)
ui/components/ui/card.tsx (1)
ui/lib/utils.ts (1)
cn(4-6)
ui/components/ui/sheet.tsx (1)
ui/lib/utils.ts (1)
cn(4-6)
ui/components/config/meta-config-renderer.tsx (5)
ui/lib/types/config.ts (1)
MetaConfig(30-49)ui/components/ui/textarea.tsx (1)
Textarea(18-18)ui/components/ui/input.tsx (1)
Input(7-21)ui/components/ui/card.tsx (3)
CardHeader(50-50)CardTitle(50-50)CardContent(50-50)ui/components/ui/tooltip.tsx (4)
TooltipProvider(43-43)Tooltip(43-43)TooltipTrigger(43-43)TooltipContent(43-43)
ui/components/ui/sidebar.tsx (8)
ui/hooks/use-mobile.ts (1)
useIsMobile(5-19)ui/components/ui/tooltip.tsx (4)
TooltipProvider(43-43)TooltipContent(43-43)Tooltip(43-43)TooltipTrigger(43-43)ui/lib/utils.ts (1)
cn(4-6)ui/components/ui/sheet.tsx (5)
Sheet(90-90)SheetContent(90-90)SheetHeader(90-90)SheetTitle(90-90)SheetDescription(90-90)ui/components/ui/button.tsx (1)
Button(71-71)ui/components/ui/input.tsx (1)
Input(7-21)ui/components/ui/separator.tsx (1)
Separator(43-43)ui/components/ui/skeleton.tsx (1)
Skeleton(7-7)
ui/components/ui/dropdown-menu.tsx (1)
ui/lib/utils.ts (1)
cn(4-6)
ui/lib/types/logs.ts (2)
transports/bifrost-http/plugins/logging/main.go (2)
LogEntry(46-62)LogStats(100-109)ui/components/logs/filters.tsx (1)
LogFilters(22-118)
🪛 markdownlint-cli2 (0.17.2)
ui/README.md
1-1: First line in a file should be a top-level heading
(MD041, first-line-heading, first-line-h1)
🪛 Biome (1.9.4)
ui/components/config/core-settings-form.tsx
[error] 60-60: A form label must be associated with an input.
Consider adding a for or htmlFor attribute to the label element or moving the input element to inside the label element.
(lint/a11y/noLabelWithoutControl)
ui/components/sidebar.tsx
[error] 170-170: JSX elements without children should be marked as self-closing. In JSX, it is valid for any element to be self-closing.
Unsafe fix: Use a SelfClosingElement instead
(lint/style/useSelfClosingElements)
ui/components/logs/filters.tsx
[error] 22-22: Shouldn't redeclare 'LogFilters'. Consider to delete it or rename it.
'LogFilters' is defined here:
(lint/suspicious/noRedeclare)
ui/components/logs/logs-table.tsx
[error] 78-78: Use Number.parseInt instead of the equivalent global.
ES2015 moved some globals into the Number namespace for consistency.
Safe fix: Use Number.parseInt instead.
(lint/style/useNumberNamespace)
ui/components/config/mcp-client-form.tsx
[error] 84-84: Forbidden non-null assertion.
(lint/style/noNonNullAssertion)
[error] 170-170: Forbidden non-null assertion.
(lint/style/noNonNullAssertion)
ui/components/logs/ui/code-editor.tsx
[error] 111-111: Forbidden non-null assertion.
Unsafe fix: Replace with optional chain operator ?. This operator includes runtime checks, so it is safer than the compile-only non-null assertion operator
(lint/style/noNonNullAssertion)
[error] 134-134: Forbidden non-null assertion.
Unsafe fix: Replace with optional chain operator ?. This operator includes runtime checks, so it is safer than the compile-only non-null assertion operator
(lint/style/noNonNullAssertion)
[error] 208-209: Forbidden non-null assertion.
Unsafe fix: Replace with optional chain operator ?. This operator includes runtime checks, so it is safer than the compile-only non-null assertion operator
(lint/style/noNonNullAssertion)
[error] 267-267: Forbidden non-null assertion.
Unsafe fix: Replace with optional chain operator ?. This operator includes runtime checks, so it is safer than the compile-only non-null assertion operator
(lint/style/noNonNullAssertion)
[error] 360-360: Forbidden non-null assertion.
Unsafe fix: Replace with optional chain operator ?. This operator includes runtime checks, so it is safer than the compile-only non-null assertion operator
(lint/style/noNonNullAssertion)
[error] 378-378: Forbidden non-null assertion.
Unsafe fix: Replace with optional chain operator ?. This operator includes runtime checks, so it is safer than the compile-only non-null assertion operator
(lint/style/noNonNullAssertion)
[error] 392-392: Forbidden non-null assertion.
Unsafe fix: Replace with optional chain operator ?. This operator includes runtime checks, so it is safer than the compile-only non-null assertion operator
(lint/style/noNonNullAssertion)
[error] 393-393: Forbidden non-null assertion.
Unsafe fix: Replace with optional chain operator ?. This operator includes runtime checks, so it is safer than the compile-only non-null assertion operator
(lint/style/noNonNullAssertion)
[error] 407-407: Forbidden non-null assertion.
Unsafe fix: Replace with optional chain operator ?. This operator includes runtime checks, so it is safer than the compile-only non-null assertion operator
(lint/style/noNonNullAssertion)
[error] 459-459: Unnecessary use of boolean literals in conditional expression.
Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with
(lint/complexity/noUselessTernary)
[error] 465-465: Unnecessary use of boolean literals in conditional expression.
Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with
(lint/complexity/noUselessTernary)
ui/components/logs/log-detail-sheet.tsx
[error] 173-173: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
[error] 173-173: Missing key property for this element in iterable.
The order of the items may change, and having a key can help React identify which item was moved.
Check the React documentation.
(lint/correctness/useJsxKeyInIterable)
ui/components/config/provider-form.tsx
[error] 339-355: Enforce to have the onClick mouse event with the onKeyUp, the onKeyDown, or the onKeyPress keyboard event.
Actions triggered using mouse events should have corresponding keyboard events to account for keyboard-only navigation.
(lint/a11y/useKeyWithClickEvents)
[error] 412-412: A form label must be associated with an input.
Consider adding a for or htmlFor attribute to the label element or moving the input element to inside the label element.
(lint/a11y/noLabelWithoutControl)
[error] 439-439: A form label must be associated with an input.
Consider adding a for or htmlFor attribute to the label element or moving the input element to inside the label element.
(lint/a11y/noLabelWithoutControl)
[error] 485-485: A form label must be associated with an input.
Consider adding a for or htmlFor attribute to the label element or moving the input element to inside the label element.
(lint/a11y/noLabelWithoutControl)
[error] 500-500: A form label must be associated with an input.
Consider adding a for or htmlFor attribute to the label element or moving the input element to inside the label element.
(lint/a11y/noLabelWithoutControl)
[error] 514-514: A form label must be associated with an input.
Consider adding a for or htmlFor attribute to the label element or moving the input element to inside the label element.
(lint/a11y/noLabelWithoutControl)
[error] 552-552: A form label must be associated with an input.
Consider adding a for or htmlFor attribute to the label element or moving the input element to inside the label element.
(lint/a11y/noLabelWithoutControl)
[error] 566-566: A form label must be associated with an input.
Consider adding a for or htmlFor attribute to the label element or moving the input element to inside the label element.
(lint/a11y/noLabelWithoutControl)
[error] 593-593: A form label must be associated with an input.
Consider adding a for or htmlFor attribute to the label element or moving the input element to inside the label element.
(lint/a11y/noLabelWithoutControl)
[error] 610-610: A form label must be associated with an input.
Consider adding a for or htmlFor attribute to the label element or moving the input element to inside the label element.
(lint/a11y/noLabelWithoutControl)
[error] 619-619: A form label must be associated with an input.
Consider adding a for or htmlFor attribute to the label element or moving the input element to inside the label element.
(lint/a11y/noLabelWithoutControl)
[error] 627-627: A form label must be associated with an input.
Consider adding a for or htmlFor attribute to the label element or moving the input element to inside the label element.
(lint/a11y/noLabelWithoutControl)
[error] 298-298: Use Number.parseFloat instead of the equivalent global.
ES2015 moved some globals into the Number namespace for consistency.
Safe fix: Use Number.parseFloat instead.
(lint/style/useNumberNamespace)
[error] 508-508: Use Number.parseInt instead of the equivalent global.
ES2015 moved some globals into the Number namespace for consistency.
Safe fix: Use Number.parseInt instead.
(lint/style/useNumberNamespace)
[error] 522-522: Use Number.parseInt instead of the equivalent global.
ES2015 moved some globals into the Number namespace for consistency.
Safe fix: Use Number.parseInt instead.
(lint/style/useNumberNamespace)
[error] 559-559: Use Number.parseInt instead of the equivalent global.
ES2015 moved some globals into the Number namespace for consistency.
Safe fix: Use Number.parseInt instead.
(lint/style/useNumberNamespace)
[error] 573-573: Use Number.parseInt instead of the equivalent global.
ES2015 moved some globals into the Number namespace for consistency.
Safe fix: Use Number.parseInt instead.
(lint/style/useNumberNamespace)
ui/components/config/mcp-clients-lists.tsx
[error] 82-82: Template literals are preferred over string concatenation.
Unsafe fix: Use a template literal.
(lint/style/useTemplate)
ui/lib/api.ts
[error] 31-31: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
ui/components/config/meta-config-renderer.tsx
[error] 156-156: A form label must be associated with an input.
Consider adding a for or htmlFor attribute to the label element or moving the input element to inside the label element.
(lint/a11y/noLabelWithoutControl)
ui/lib/utils/validation.ts
[error] 92-92: Using this in a static context can be confusing.
this refers to the class.
Unsafe fix: Use the class name instead.
(lint/complexity/noThisInStatic)
[error] 96-96: Using this in a static context can be confusing.
this refers to the class.
Unsafe fix: Use the class name instead.
(lint/complexity/noThisInStatic)
🔇 Additional comments (52)
ui/.gitignore (1)
1-42: Looks good – comprehensive ignore list.
Covers common Node/Next artefacts and keeps the repo clean.ui/hooks/use-mobile.ts (1)
9-11: Fix inconsistency between media query and onChange handler.The media query uses
max-width: ${MOBILE_BREAKPOINT - 1}px(767px) while the onChange handler useswindow.innerWidth < MOBILE_BREAKPOINT(768px). This creates a 1px gap where the states might not match.Use consistent logic:
- const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`); - const onChange = () => { - setIsMobile(window.innerWidth < MOBILE_BREAKPOINT); - }; + const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`); + const onChange = () => { + setIsMobile(mql.matches); + };Likely an incorrect or invalid review comment.
ui/components/ui/skeleton.tsx (1)
3-5: LGTM! Clean skeleton component implementation.The component follows good practices with proper class merging, extensible styling, and appropriate default animations for loading states.
transports/bifrost-http/handlers/config.go (2)
35-35: Good semantic improvement with method rename.The rename from
handleReloadConfigtohandleUpdateConfigbetter reflects the handler's actual functionality of updating configuration settings.
38-41: LGTM! Consistent naming across comments and method.The comments and method name are now properly aligned with the updated naming convention.
ui/components/ui/textarea.tsx (1)
5-16: Excellent textarea component implementation.The component includes comprehensive styling with:
- Proper accessibility features (focus-visible, aria-invalid)
- Responsive design and dark mode support
- Consistent styling with the design system
- Good extensibility through className prop
ui/components/logs/analytics/token-usage-chart.tsx (1)
19-79: Well-implemented token usage visualization component.The component follows React best practices with proper TypeScript interfaces, responsive design using ResponsiveContainer, and good accessibility features. The stacked area chart effectively visualizes token usage over time.
ui/README.md (1)
1-37: Comprehensive and well-structured documentation.The README provides clear getting started instructions, covers multiple package managers, and includes helpful resources for learning and deployment. The content is well-organized and follows standard Next.js documentation patterns.
ui/components/theme-toggle.tsx (1)
10-29: Excellent theme toggle implementation with proper accessibility.The component demonstrates good practices:
- Proper accessibility with screen reader text
- Smooth icon transitions using CSS transforms
- Consistent UI patterns using established components
- Clean integration with next-themes
The implementation is well-structured and follows React best practices.
ui/tsconfig.json (1)
1-27: Well-configured TypeScript setup for Next.js project.The configuration includes:
- Appropriate compiler options for modern React development
- Strict type checking for better code quality
- Next.js integration with proper plugin setup
- Clean path aliasing with
@/*mapping- Proper inclusion/exclusion patterns
The setup follows Next.js best practices and supports the comprehensive UI implementation.
ui/components/ui/label.tsx (1)
1-25: Well-implemented UI component following best practices.The Label component implementation is excellent:
- Properly extends Radix UI primitive with type safety
- Uses the cn utility for consistent class merging
- Includes comprehensive accessibility styling (disabled states, peer selectors)
- Follows consistent patterns with other UI components in the library
ui/components/ui/collapsible.tsx (1)
1-18: LGTM! Clean wrapper implementation.The collapsible component wrapper follows the established pattern for Radix UI primitives with proper prop forwarding and data-slot attributes for styling hooks.
ui/components/ui/switch.tsx (1)
8-29: Excellent implementation of the Switch component.The component properly forwards refs, merges classNames using the utility function, and provides comprehensive styling for all states (checked, unchecked, disabled, focus). The TypeScript typing is accurate and the display name is correctly assigned.
ui/components/config/core-settings-form.tsx (1)
22-45: Well-implemented async operations with proper error handling.The component correctly handles loading states, API calls, and provides appropriate user feedback through toast notifications. The state management is clean and follows React best practices.
ui/components/ui/alert.tsx (1)
1-42: Well-implemented alert component system.The alert components are properly structured with good accessibility features (role="alert"), comprehensive styling variants, and proper TypeScript typing. The use of
class-variance-authorityfor variant management and data-slot attributes for component identification follows modern React UI library patterns.ui/app/globals.css (1)
1-123: Excellent CSS architecture with modern practices.The global stylesheet demonstrates excellent use of modern CSS features:
- OKLCH color space for better accessibility and color consistency
- Comprehensive dark mode support with proper variable overrides
- Clean theme architecture with CSS custom properties
- Proper base layer styling for consistent defaults
transports/bifrost-http/main.go (2)
115-139: Well-implemented CORS middleware for localhost development.The CORS middleware is properly implemented with:
- Secure origin validation (only localhost/127.0.0.1 allowed)
- Proper preflight OPTIONS handling
- Appropriate CORS headers for web development
- Support for both HTTP and HTTPS schemes
282-291: Correct application of CORS middleware to all routes.The handler properly applies CORS middleware to all routes, including the metrics endpoint, which is appropriate for monitoring dashboards that need to access metrics from web interfaces.
ui/components/logs/ui/log-message-view.tsx (1)
25-61: LGTM! Well-structured component with proper conditional rendering.The component correctly handles different content types and renders tool calls appropriately. The use of CodeEditor for JSON formatting and the conditional rendering logic is well implemented.
ui/components/ui/separator.tsx (1)
8-26: LGTM! Well-implemented Separator component.The Separator component properly wraps the Radix UI primitive with appropriate styling and prop forwarding. The use of data attributes and orientation handling is correct.
ui/components/sidebar.tsx (1)
67-181: LGTM! Well-structured sidebar component with proper navigation logic.The sidebar component is well-implemented with good separation of concerns, proper active state management, and accessibility considerations. The navigation items configuration and external links handling are appropriate.
ui/components/ui/tag-input.tsx (1)
16-67: LGTM! Excellent implementation of TagInput component.The component demonstrates good React practices with:
- Proper use of
React.forwardReffor ref forwarding- Correct event handling for keyboard interactions (Enter, comma, Backspace)
- Proper state management with controlled input
- Good accessibility with focus management
- Appropriate prop type extensions excluding conflicting props
The logic for adding tags on Enter/comma and removing the last tag on Backspace is intuitive and well-implemented.
ui/components/config/providers-list.tsx (1)
33-193: LGTM! Well-implemented provider management component.The component demonstrates excellent practices:
- Proper async error handling with user-friendly toast notifications
- Good loading state management with visual feedback
- Appropriate empty state handling
- Clean separation of concerns with modal state management
- Correct conditional rendering based on provider types (vertex/ollama vs others)
- Proper cleanup of state after operations
The delete confirmation dialog and the integration with the provider form modal are well-implemented.
ui/components/ui/avatar.tsx (1)
8-32: Clean implementation following established patternsThe avatar component properly implements the Radix UI wrapper pattern with consistent styling and prop forwarding. The component structure is well-organized and follows the established UI component conventions.
ui/components/ui/button.tsx (1)
8-71: Comprehensive button component with excellent variant systemThe button implementation is well-structured with:
- Comprehensive variant definitions using class-variance-authority
- Proper loading state handling with spinner
- Flexible composition via BaseButton pattern
- Excellent TypeScript typing with VariantProps
- Consistent styling patterns with other UI components
ui/eslint.config.mjs (1)
1-79: ESLint configuration looks well-structured.The flat config format is properly implemented with appropriate plugins, parser configuration, and rule settings for a Next.js TypeScript project. The configuration correctly handles Prettier integration and includes sensible rule overrides for the UI codebase.
Note: The past review comment about
node:protocol is not applicable to this file since it doesn't import core Node.js modules.ui/components/logs/filters.tsx (1)
63-118: Component UI implementation looks solid.The filter UI using Popover and Command components is well-implemented with proper state management, search functionality, and visual feedback for selected filters.
ui/components/ui/form-field.tsx (1)
41-70: Validation integration and UI feedback look good.The validation logic, tooltip display, and error styling provide good user feedback. The conditional rendering of validation messages is well-implemented.
ui/hooks/useWebSocket.ts (1)
19-81: WebSocket implementation looks robust.The hook properly manages connection state, handles reconnection logic, and includes appropriate cleanup. The error handling and logging provide good debugging capabilities.
Note: The hardcoded
localhostURL is appropriate for development but may need configuration for production deployment.ui/components/ui/badge.tsx (1)
1-37: Well-structured badge component implementation.The component follows excellent patterns with proper TypeScript typing, variant management using
cva, and consistent styling approach. The use ofasChildprop for composition and proper prop forwarding demonstrates good component design.ui/components/ui/tabs.tsx (1)
1-39: Excellent tabs component implementation.The component properly wraps Radix UI primitives with consistent styling, TypeScript typing, and data-slot attributes for identification. The styling approach is coherent and follows established patterns.
ui/components/config/mcp-clients-lists.tsx (1)
26-179: Well-structured component with proper error handling.The component demonstrates excellent patterns with proper state management, API error handling, and user feedback through toast notifications. The table layout and action buttons provide a good user experience.
ui/components/ui/dialog.tsx (1)
1-101: Excellent dialog component with accessibility features.The component properly wraps Radix UI primitives with excellent accessibility considerations, including screen reader support and proper focus management. The composition pattern with portal and overlay is well-implemented, and the TypeScript typing with additional props enhances usability.
transports/bifrost-http/plugins/logging/main.go (3)
49-49: Good structural improvement.Moving the
Objectfield aboveProviderimproves the logical grouping of request metadata fields in the struct.
324-334: Excellent improvement to ID assignment logic.The enhanced logic properly assigns
result.IDwhen available and falls back to generating a new UUID when empty. This ensures every log entry has a valid ID.
350-356: Good enhancement to input history fallback logic.The improved fallback logic ensures input history is captured even when not present in
result.ExtraFields.ChatHistoryby attempting to retrieve it from the request context. This makes the logging more robust.ui/package.json (2)
1-72: Well-structured package configuration.The package.json is comprehensive and includes appropriate dependencies for a modern React/Next.js application with UI components, development tooling, and linting setup. The version choices align well with the component architecture being implemented.
33-33: No known security vulnerabilities in axios@1.10.0GitHub’s Security Advisory database shows that all listed axios advisories affect versions below 1.10.0 (patched by 0.30.0, 1.8.2, 1.7.4, etc.), so our dependency at
"axios": "^1.10.0"is not vulnerable. No further action needed.ui/components/ui/card.tsx (1)
1-51: Well-structured card component implementationThe card component module follows React best practices with:
- Proper TypeScript typing using
React.ComponentProps<"div">- Consistent use of data-slot attributes for identification
- Flexible styling through className merging with the
cnutility- Proper prop forwarding with rest/spread operators
The component hierarchy provides good semantic structure for building card-based UIs.
ui/components/ui/accordion.tsx (1)
1-47: Solid accordion implementation using Radix UIThe accordion component properly wraps Radix UI primitives with custom styling. The implementation follows best practices with proper TypeScript typing and consistent data-slot attributes.
ui/components/ui/select.tsx (1)
1-147: Comprehensive select component implementationThe select component implementation is well-structured with:
- Proper use of Radix UI primitives with custom styling
- Good TypeScript typing throughout
- Flexible size prop for SelectTrigger
- Proper portal usage for content rendering
- Consistent data-slot attributes for identification
The component provides a complete select implementation with all necessary subcomponents.
ui/lib/constants/logs.ts (1)
1-48: Well-structured constants moduleThe constants module follows TypeScript best practices with:
- Proper use of
as constfor type safety- Consistent color mappings using Tailwind CSS classes
- Logical organization of related constants
- Proper union type derivation from constants
- Clear naming conventions
This provides a solid foundation for type-safe usage across the UI components.
ui/lib/types/mcp.ts (1)
1-39: Well-structured type definitions.The MCP type definitions are clean, properly typed, and follow TypeScript best practices with appropriate use of optional properties and literal types.
ui/components/ui/alert-dialog.tsx (1)
1-94: Clean and well-structured Alert Dialog component.The component properly wraps Radix UI primitives with consistent styling and follows React best practices.
ui/lib/types/config.ts (1)
1-139: Well-structured type definitionsThe TypeScript interfaces and types are properly defined, matching the backend Go structures. Good use of optional properties, type unions, and index signatures for extensibility.
ui/components/ui/sheet.tsx (1)
1-91: Clean sheet component implementationExcellent implementation using Radix UI primitives with proper accessibility features, animations, and flexible positioning options. The component follows React best practices.
ui/lib/utils/validation.ts (5)
45-47: Good defensive programming practiceFiltering out undefined rules prevents potential runtime errors.
3-17: Well-structured validation interfaces.The interface definitions provide a clear and comprehensive foundation for the validation system. The separation of concerns between validation rules, configuration, and results is well thought out.
19-27: Validation logic is sound.The
validateFieldfunction correctly finds the first invalid rule and handles tooltip visibility based on touch state and configuration. The implementation is clean and efficient.
34-40: Simple and effective form validation.The
validateFormfunction provides a straightforward way to aggregate validation results. The implementation correctly filters invalid rules and collects error messages.
113-125: Add null safety to array validators.The array validation methods should handle null/undefined arrays more defensively to prevent runtime errors.
Consider adding explicit null checks:
static arrayMinLength<T>(array: T[], min: number, message = `Must have at least ${min} items`): ValidationRule { return { - isValid: array?.length >= min, + isValid: (array?.length ?? 0) >= min, message, }; } static arrayMaxLength<T>(array: T[], max: number, message = `Must have at most ${max} items`): ValidationRule { return { - isValid: array?.length <= max, + isValid: (array?.length ?? 0) <= max, message, }; }Likely an incorrect or invalid review comment.
ui/lib/types/logs.ts (1)
1-179: Well-structured and comprehensive type definitionsThe type definitions are thorough and align well with the backend schemas. Good use of optional properties and proper typing throughout.
| "printWidth": 140, | ||
| "singleQuote": false, | ||
| "bracketSpacing": true, | ||
| "jsxBracketSameLine": false, |
There was a problem hiding this comment.
jsxBracketSameLine is deprecated – switch to bracketSameLine.
Prettier 3 removed the jsxBracketSameLine option; keeping it causes “Unknown option” errors and breaks CI format checks.
- "jsxBracketSameLine": false,
+ "bracketSameLine": false,📝 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.
| "jsxBracketSameLine": false, | |
| "bracketSameLine": false, |
🤖 Prompt for AI Agents
In ui/.prettierrc at line 5, replace the deprecated option "jsxBracketSameLine"
with the new "bracketSameLine" option to avoid unknown option errors and fix CI
format checks. Update the key name while keeping the boolean value consistent.
| import { clsx, type ClassValue } from "clsx"; | ||
| import { twMerge } from "tailwind-merge"; | ||
|
|
||
| export function cn(...inputs: ClassValue[]) { | ||
| return twMerge(clsx(inputs)); | ||
| } |
There was a problem hiding this comment.
Incorrect clsx import – will be undefined at runtime
clsx exports a default function, not a named export. Fix import and spread args for clarity.
-import { clsx, type ClassValue } from "clsx";
+import clsx, { type ClassValue } from "clsx";
@@
-export function cn(...inputs: ClassValue[]) {
- return twMerge(clsx(inputs));
+export function cn(...inputs: ClassValue[]): string {
+ return twMerge(clsx(...inputs));
}📝 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.
| import { clsx, type ClassValue } from "clsx"; | |
| import { twMerge } from "tailwind-merge"; | |
| export function cn(...inputs: ClassValue[]) { | |
| return twMerge(clsx(inputs)); | |
| } | |
| import clsx, { type ClassValue } from "clsx"; | |
| import { twMerge } from "tailwind-merge"; | |
| export function cn(...inputs: ClassValue[]): string { | |
| return twMerge(clsx(...inputs)); | |
| } |
🤖 Prompt for AI Agents
In ui/lib/utils.ts lines 1 to 6, the import of `clsx` is incorrect because
`clsx` is a default export, not a named export, causing it to be undefined at
runtime. Change the import to use the default import syntax for `clsx`. Also,
update the function call to spread the input arguments when passing them to
`clsx` for clarity and correctness.
| export function ThemeProvider({ children, ...props }: React.ComponentProps<typeof NextThemesProvider>) { | ||
| return <NextThemesProvider {...props}>{children}</NextThemesProvider>; | ||
| } |
There was a problem hiding this comment.
🧹 Nitpick (assertive)
Consider exposing sane defaults instead of a raw passthrough.
Right now the wrapper simply forwards everything to NextThemesProvider.
If every consumer has to remember to pass attribute="class" or enableSystem, the wrapper adds little value.
Exposing sensible defaults (e.g. attribute="class", enableSystem, defaultTheme="system") and letting callers override on demand will reduce duplication and mis-configuration risk.
-export function ThemeProvider({ children, ...props }: React.ComponentProps<typeof NextThemesProvider>) {
- return <NextThemesProvider {...props}>{children}</NextThemesProvider>;
-}
+export function ThemeProvider({
+ children,
+ ...props
+}: React.ComponentProps<typeof NextThemesProvider>) {
+ return (
+ <NextThemesProvider
+ attribute="class"
+ defaultTheme="system"
+ enableSystem
+ {...props}
+ >
+ {children}
+ </NextThemesProvider>
+ );
+}📝 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.
| export function ThemeProvider({ children, ...props }: React.ComponentProps<typeof NextThemesProvider>) { | |
| return <NextThemesProvider {...props}>{children}</NextThemesProvider>; | |
| } | |
| export function ThemeProvider({ | |
| children, | |
| ...props | |
| }: React.ComponentProps<typeof NextThemesProvider>) { | |
| return ( | |
| <NextThemesProvider | |
| attribute="class" | |
| defaultTheme="system" | |
| enableSystem | |
| {...props} | |
| > | |
| {children} | |
| </NextThemesProvider> | |
| ); | |
| } |
🤖 Prompt for AI Agents
In ui/components/theme-provider.tsx around lines 6 to 8, the ThemeProvider
component currently just forwards all props to NextThemesProvider without
setting any defaults. To improve usability and reduce errors, update the
ThemeProvider to provide sensible default props such as attribute="class",
enableSystem=true, and defaultTheme="system", while still allowing callers to
override these defaults by passing their own props. This way, the wrapper adds
value by reducing duplication and configuration mistakes.
| function AspectRatio({ ...props }: React.ComponentProps<typeof AspectRatioPrimitive.Root>) { | ||
| return <AspectRatioPrimitive.Root data-slot="aspect-ratio" {...props} />; | ||
| } |
There was a problem hiding this comment.
🛠️ Refactor suggestion
Forward the ref to stay Radix-compliant.
Radix primitives rely on refs for focus management & measurements.
Wrapping without forwardRef blocks ref propagation.
-import * as AspectRatioPrimitive from "@radix-ui/react-aspect-ratio";
+import * as React from "react";
+import * as AspectRatioPrimitive from "@radix-ui/react-aspect-ratio";
+
+const AspectRatio = React.forwardRef<
+ React.ElementRef<typeof AspectRatioPrimitive.Root>,
+ React.ComponentPropsWithoutRef<typeof AspectRatioPrimitive.Root>
+>((props, ref) => (
+ <AspectRatioPrimitive.Root ref={ref} data-slot="aspect-ratio" {...props} />
+));
+
+AspectRatio.displayName = AspectRatioPrimitive.Root.displayName;
+
+export { AspectRatio };
-
-function AspectRatio({ ...props }: React.ComponentProps<typeof AspectRatioPrimitive.Root>) {
- return <AspectRatioPrimitive.Root data-slot="aspect-ratio" {...props} />;
-}
-
-export { AspectRatio };📝 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.
| function AspectRatio({ ...props }: React.ComponentProps<typeof AspectRatioPrimitive.Root>) { | |
| return <AspectRatioPrimitive.Root data-slot="aspect-ratio" {...props} />; | |
| } | |
| import * as React from "react"; | |
| import * as AspectRatioPrimitive from "@radix-ui/react-aspect-ratio"; | |
| const AspectRatio = React.forwardRef< | |
| React.ElementRef<typeof AspectRatioPrimitive.Root>, | |
| React.ComponentPropsWithoutRef<typeof AspectRatioPrimitive.Root> | |
| >((props, ref) => ( | |
| <AspectRatioPrimitive.Root ref={ref} data-slot="aspect-ratio" {...props} /> | |
| )); | |
| AspectRatio.displayName = AspectRatioPrimitive.Root.displayName; | |
| export { AspectRatio }; |
🤖 Prompt for AI Agents
In ui/components/ui/aspect-ratio.tsx around lines 5 to 7, the AspectRatio
component does not forward the ref to AspectRatioPrimitive.Root, which breaks
Radix compliance. Wrap the component with React.forwardRef and forward the ref
parameter to AspectRatioPrimitive.Root along with the props to ensure proper ref
propagation for focus management and measurements.
| <ProgressProvider height="4px" color="#33a9fd" options={{ showSpinner: false }} shallowRouting> | ||
| {children} | ||
| </ProgressProvider> |
There was a problem hiding this comment.
🧹 Nitpick (assertive)
Prefer PropsWithChildren for clearer intent.
Using an inline type each time is noisy. React.PropsWithChildren<{}> (or a proper interface) communicates that the component simply forwards children.
-const AppProgressProvider = ({ children }: { children: React.ReactNode }) => {
+const AppProgressProvider: React.FC<React.PropsWithChildren> = ({ children }) => {Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In ui/components/progress-bar.tsx around lines 7 to 9, the component currently
uses an inline type for props which is verbose and less clear. Refactor the
component's props type to use React.PropsWithChildren or define a proper
interface extending PropsWithChildren to clearly indicate that the component
forwards children. Replace the inline type with this clearer type annotation for
better readability and intent.
| if (contentHeight && editorRef.current.getDomNode()) | ||
| editorRef.current.layout({ | ||
| height: contentHeight + 15, | ||
| width: editorRef.current.getDomNode()!.clientWidth, | ||
| }); | ||
| } | ||
| }, [props.readonly, props.code, props.height, props.minHeight, props.maxHeight, props.shouldAdjustInitialHeight]); |
There was a problem hiding this comment.
Replace non-null assertions with optional chaining for DOM operations.
Multiple instances of getDomNode()! could cause runtime errors. Use optional chaining for safer DOM access.
Example fix for one instance:
-if (contentHeight && editorRef.current.getDomNode())
+const domNode = editorRef.current.getDomNode();
+if (contentHeight && domNode) {
editorRef.current.layout({
height: contentHeight + 15,
- width: editorRef.current.getDomNode()!.clientWidth,
+ width: domNode.clientWidth,
});
+}Apply similar pattern to all instances where getDomNode()! is used.
Also applies to: 358-362, 376-378, 405-409
🧰 Tools
🪛 Biome (1.9.4)
[error] 111-111: Forbidden non-null assertion.
Unsafe fix: Replace with optional chain operator ?. This operator includes runtime checks, so it is safer than the compile-only non-null assertion operator
(lint/style/noNonNullAssertion)
🤖 Prompt for AI Agents
In ui/components/logs/ui/code-editor.tsx around lines 108 to 114, replace all
non-null assertions on getDomNode() (i.e., getDomNode()!) with optional chaining
(getDomNode()?.) to safely access the DOM node and prevent runtime errors. Apply
this change consistently to all similar usages in lines 358-362, 376-378, and
405-409 as well.
|
|
||
| if (props.onFocus) { | ||
| editor.onDidFocusEditorWidget(() => { | ||
| props.onFocus!(); |
There was a problem hiding this comment.
🛠️ Refactor suggestion
Use optional chaining instead of non-null assertions in event handlers.
Replace non-null assertions with optional chaining for safer code execution.
Examples:
-props.onFocus!();
+props.onFocus?.();
-.customCompletions!.filter((item) => item.type !== "object")
+.customCompletions?.filter((item) => item.type !== "object") || []
-objectItem.methods!.map((method) => {
+objectItem.methods?.map((method) => {
-const markers = props.customLanguage!.validate(monaco, model);
-monaco.editor.setModelMarkers(model, props.customLanguage!.id, markers);
+const markers = props.customLanguage?.validate(monaco, model);
+if (markers && props.customLanguage?.id) {
+ monaco.editor.setModelMarkers(model, props.customLanguage.id, markers);
+}Also applies to: 209-209, 267-267, 392-393
🧰 Tools
🪛 Biome (1.9.4)
[error] 134-134: Forbidden non-null assertion.
Unsafe fix: Replace with optional chain operator ?. This operator includes runtime checks, so it is safer than the compile-only non-null assertion operator
(lint/style/noNonNullAssertion)
🤖 Prompt for AI Agents
In ui/components/logs/ui/code-editor.tsx at lines 134, 209, 267, and 392-393,
replace the non-null assertion operator (!) used when calling event handler
props like onFocus with optional chaining (?.) to safely call these handlers
only if they are defined, preventing potential runtime errors.
| // Register custom completions including objects and methods | ||
| if (props.customCompletions !== undefined) { | ||
| // Adding new | ||
| const newDisposables: monaco.IDisposable[] = []; | ||
| // First, register signature help providers for custom methods | ||
| const objectItems = props.customCompletions.filter((item) => item.type === "object" && item.methods); | ||
|
|
||
| // Register signature help for all methods with signatures | ||
| objectItems.forEach((objectItem) => { | ||
| // For each object with methods that have signatures, register a signature help provider | ||
| newDisposables.push( | ||
| monaco.languages.registerSignatureHelpProvider(lang || "javascript", { | ||
| signatureHelpTriggerCharacters: ["(", ","], | ||
| signatureHelpRetriggerCharacters: [","], | ||
| provideSignatureHelp: (model, position, token, context): monaco.languages.SignatureHelpResult | null => { | ||
| // Get the content before the cursor to determine if we're in a method call | ||
| const textUntilPosition = model.getValueInRange({ | ||
| startLineNumber: position.lineNumber, | ||
| startColumn: 1, | ||
| endLineNumber: position.lineNumber, | ||
| endColumn: position.column, | ||
| }); | ||
|
|
||
| // Check for method calls like "objectName.methodName(" | ||
| const methodCallMatch = textUntilPosition.match(new RegExp(`${objectItem.label}\\.(\\w+)\\(`)); | ||
| if (!methodCallMatch) return null; | ||
|
|
||
| const methodName = methodCallMatch[1]; | ||
| const method = objectItem.methods?.find((m) => m.label === methodName); | ||
|
|
||
| if (!method || !method.signature) return null; | ||
|
|
||
| // Count commas to determine which parameter we're on | ||
| const commaCount = textUntilPosition | ||
| .substring(textUntilPosition.lastIndexOf("(")) | ||
| .split("") | ||
| .filter((char) => char === ",").length; | ||
|
|
||
| // Create signature information | ||
| return { | ||
| dispose: () => {}, | ||
| value: { | ||
| signatures: [ | ||
| { | ||
| label: `${methodName}(${method.signature.parameters.join(", ")})${method.signature.returnType ? `: ${method.signature.returnType}` : ""}`, | ||
| documentation: method.description || "", | ||
| parameters: method.signature.parameters.map((param) => ({ | ||
| label: param, | ||
| documentation: "", // Could add per-parameter documentation if available | ||
| })), | ||
| }, | ||
| ], | ||
| activeSignature: 0, | ||
| activeParameter: Math.min(commaCount, method.signature.parameters.length - 1), | ||
| }, | ||
| }; | ||
| }, | ||
| }), | ||
| ); | ||
| }); | ||
|
|
||
| // Register completion provider for non-object items | ||
| newDisposables.push( | ||
| monaco.languages.registerCompletionItemProvider(lang || "javascript", { | ||
| provideCompletionItems: (model, position) => { | ||
| const wordUntilPosition = model.getWordUntilPosition(position); | ||
| return { | ||
| suggestions: props | ||
| .customCompletions!.filter((item) => item.type !== "object") | ||
| .map((item) => { | ||
| // Format the signature for display in detail | ||
| let detail = item.label; | ||
|
|
||
| // Add signature details to methods if available | ||
| if (item.signature) { | ||
| const params = item.signature.parameters.join(", "); | ||
| const returnType = item.signature.returnType ? `: ${item.signature.returnType}` : ""; | ||
| detail = `${item.label}(${params})${returnType}`; | ||
| } | ||
|
|
||
| return { | ||
| label: item.label, | ||
| kind: | ||
| item.type === "variable" ? monaco.languages.CompletionItemKind.Variable : monaco.languages.CompletionItemKind.Method, | ||
| insertText: item.insertText, | ||
| documentation: { value: item.documentation ?? "", isTrusted: true }, | ||
| detail: item.description || "", | ||
| // For methods with signatures, add these to show parameter hints | ||
| ...(item.type === "method" && item.signature | ||
| ? { | ||
| insertTextRules: monaco.languages.CompletionItemInsertTextRule.KeepWhitespace, | ||
| command: { id: "editor.action.triggerParameterHints", title: "Trigger Parameter Hints" }, | ||
| } | ||
| : {}), | ||
| range: { | ||
| startLineNumber: position.lineNumber, | ||
| startColumn: wordUntilPosition.startColumn, | ||
| endLineNumber: position.lineNumber, | ||
| endColumn: position.column, | ||
| }, | ||
| } satisfies monaco.languages.CompletionItem; | ||
| }), | ||
| }; | ||
| }, | ||
| }), | ||
| ); | ||
|
|
||
| // Register objects and their methods for dot completion | ||
| objectItems.forEach((objectItem) => { | ||
| // Register object's methods completion when typing after object name and dot | ||
| monaco.languages.registerCompletionItemProvider(lang || "javascript", { | ||
| triggerCharacters: ["."], | ||
| provideCompletionItems: (model, position) => { | ||
| const textUntilPosition = model.getValueInRange({ | ||
| startLineNumber: position.lineNumber, | ||
| startColumn: 1, | ||
| endLineNumber: position.lineNumber, | ||
| endColumn: position.column, | ||
| }); | ||
|
|
||
| // Check if we're typing after the object name and a dot | ||
| const objectAccessPattern = new RegExp(`${objectItem.label}\\.\\w*$`); | ||
| if (objectAccessPattern.test(textUntilPosition)) { | ||
| const wordUntilPosition = model.getWordUntilPosition(position); | ||
|
|
||
| return { | ||
| suggestions: objectItem.methods!.map((method) => { | ||
| // Format method signature for display | ||
| let detail = method.label; | ||
|
|
||
| // Add signature details if available | ||
| if (method.signature) { | ||
| const params = method.signature.parameters.join(", "); | ||
| const returnType = method.signature.returnType ? `: ${method.signature.returnType}` : ""; | ||
| detail = `${method.label}(${params})${returnType}`; | ||
| } | ||
|
|
||
| // Create completion item for method | ||
| return { | ||
| label: { | ||
| label: method.label, | ||
| description: method.signature | ||
| ? `(${method.signature.parameters.join(", ")})${method.signature.returnType ? `: ${method.signature.returnType}` : ""}` | ||
| : undefined, | ||
| }, | ||
| kind: monaco.languages.CompletionItemKind.Method, | ||
| insertText: method.insertText, | ||
| documentation: { value: method.description || "" }, | ||
| detail: detail, | ||
| // Important: These properties help trigger parameter hints | ||
| ...(method.signature | ||
| ? { | ||
| insertTextRules: monaco.languages.CompletionItemInsertTextRule.KeepWhitespace, | ||
| command: { id: "editor.action.triggerParameterHints", title: "Trigger Parameter Hints" }, | ||
| } | ||
| : {}), | ||
| range: { | ||
| startLineNumber: position.lineNumber, | ||
| startColumn: wordUntilPosition.startColumn, | ||
| endLineNumber: position.lineNumber, | ||
| endColumn: position.column, | ||
| }, | ||
| }; | ||
| }), | ||
| }; | ||
| } | ||
|
|
||
| return { suggestions: [] }; | ||
| }, | ||
| }); | ||
| newDisposables.push( | ||
| // Register the object itself for completion | ||
| monaco.languages.registerCompletionItemProvider(lang || "javascript", { | ||
| provideCompletionItems: (model, position) => { | ||
| const wordUntilPosition = model.getWordUntilPosition(position); | ||
|
|
||
| // Only suggest the object name if we're typing something that matches the start | ||
| if (objectItem.label.startsWith(wordUntilPosition.word)) { | ||
| return { | ||
| suggestions: [ | ||
| { | ||
| label: objectItem.label, | ||
| kind: monaco.languages.CompletionItemKind.Class, | ||
| insertText: objectItem.label, | ||
| documentation: { value: objectItem.description || `Object containing various methods` }, | ||
| detail: objectItem.description || `Object with methods`, | ||
| range: { | ||
| startLineNumber: position.lineNumber, | ||
| startColumn: wordUntilPosition.startColumn, | ||
| endLineNumber: position.lineNumber, | ||
| endColumn: position.column, | ||
| }, | ||
| }, | ||
| ], | ||
| }; | ||
| } | ||
|
|
||
| return { suggestions: [] }; | ||
| }, | ||
| }), | ||
| ); | ||
| }); | ||
| setDisposables(newDisposables); |
There was a problem hiding this comment.
🧹 Nitpick (assertive)
Consider extracting custom completion logic for better maintainability.
The custom completion registration logic is complex and could be extracted into separate functions or a custom hook for better testability and reusability.
Would you like me to help refactor the completion logic into a more modular structure, such as a useMonacoCompletions hook?
🧰 Tools
🪛 Biome (1.9.4)
[error] 208-209: Forbidden non-null assertion.
Unsafe fix: Replace with optional chain operator ?. This operator includes runtime checks, so it is safer than the compile-only non-null assertion operator
(lint/style/noNonNullAssertion)
[error] 267-267: Forbidden non-null assertion.
Unsafe fix: Replace with optional chain operator ?. This operator includes runtime checks, so it is safer than the compile-only non-null assertion operator
(lint/style/noNonNullAssertion)
🤖 Prompt for AI Agents
In ui/components/logs/ui/code-editor.tsx around lines 141 to 343, the custom
completion registration logic is complex and tightly coupled within the
component. To improve maintainability and testability, extract this logic into
separate functions or a custom React hook, such as `useMonacoCompletions`. This
hook should handle registering signature help providers and completion item
providers based on the custom completions passed as props, and return the
disposables for cleanup. Refactor the component to use this hook, simplifying
the component code and isolating the completion logic.
| <div | ||
| key={p} | ||
| className={cn( | ||
| "flex w-full items-center gap-2 rounded-lg border px-4 py-3 text-sm", | ||
| PROVIDER_COLORS[p as keyof typeof PROVIDER_COLORS], | ||
| selectedProvider === p | ||
| ? "border-primary/20 opacity-100 hover:opacity-100" | ||
| : availableProviders.includes(p) | ||
| ? "cursor-pointer border-transparent opacity-60 hover:opacity-80 hover:shadow-md" | ||
| : "cursor-not-allowed border-transparent opacity-30", | ||
| )} | ||
| onClick={() => { | ||
| if (availableProviders.includes(p)) { | ||
| updateField("selectedProvider", p); | ||
| } | ||
| }} | ||
| > | ||
| {ProviderIcons[p as keyof typeof ProviderIcons]} | ||
| <div className="text-sm">{PROVIDER_LABELS[p as keyof typeof PROVIDER_LABELS]}</div> | ||
| </div> | ||
| ))} | ||
| </div> |
There was a problem hiding this comment.
Add keyboard support for provider selection
The provider selection div has onClick but lacks keyboard accessibility. Screen reader users and keyboard-only users cannot select providers.
Add keyboard event handlers and proper ARIA attributes:
<div
key={p}
className={cn(
"flex w-full items-center gap-2 rounded-lg border px-4 py-3 text-sm",
PROVIDER_COLORS[p as keyof typeof PROVIDER_COLORS],
selectedProvider === p
? "border-primary/20 opacity-100 hover:opacity-100"
: availableProviders.includes(p)
? "cursor-pointer border-transparent opacity-60 hover:opacity-80 hover:shadow-md"
: "cursor-not-allowed border-transparent opacity-30",
)}
+ role="button"
+ tabIndex={availableProviders.includes(p) ? 0 : -1}
+ aria-pressed={selectedProvider === p}
+ aria-disabled={!availableProviders.includes(p)}
onClick={() => {
if (availableProviders.includes(p)) {
updateField("selectedProvider", p);
}
}}
+ onKeyDown={(e) => {
+ if (availableProviders.includes(p) && (e.key === "Enter" || e.key === " ")) {
+ e.preventDefault();
+ updateField("selectedProvider", p);
+ }
+ }}
>📝 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.
| <div | |
| key={p} | |
| className={cn( | |
| "flex w-full items-center gap-2 rounded-lg border px-4 py-3 text-sm", | |
| PROVIDER_COLORS[p as keyof typeof PROVIDER_COLORS], | |
| selectedProvider === p | |
| ? "border-primary/20 opacity-100 hover:opacity-100" | |
| : availableProviders.includes(p) | |
| ? "cursor-pointer border-transparent opacity-60 hover:opacity-80 hover:shadow-md" | |
| : "cursor-not-allowed border-transparent opacity-30", | |
| )} | |
| onClick={() => { | |
| if (availableProviders.includes(p)) { | |
| updateField("selectedProvider", p); | |
| } | |
| }} | |
| > | |
| {ProviderIcons[p as keyof typeof ProviderIcons]} | |
| <div className="text-sm">{PROVIDER_LABELS[p as keyof typeof PROVIDER_LABELS]}</div> | |
| </div> | |
| ))} | |
| </div> | |
| <div | |
| key={p} | |
| className={cn( | |
| "flex w-full items-center gap-2 rounded-lg border px-4 py-3 text-sm", | |
| PROVIDER_COLORS[p as keyof typeof PROVIDER_COLORS], | |
| selectedProvider === p | |
| ? "border-primary/20 opacity-100 hover:opacity-100" | |
| : availableProviders.includes(p) | |
| ? "cursor-pointer border-transparent opacity-60 hover:opacity-80 hover:shadow-md" | |
| : "cursor-not-allowed border-transparent opacity-30", | |
| )} | |
| role="button" | |
| tabIndex={availableProviders.includes(p) ? 0 : -1} | |
| aria-pressed={selectedProvider === p} | |
| aria-disabled={!availableProviders.includes(p)} | |
| onClick={() => { | |
| if (availableProviders.includes(p)) { | |
| updateField("selectedProvider", p); | |
| } | |
| }} | |
| onKeyDown={(e) => { | |
| if (availableProviders.includes(p) && (e.key === "Enter" || e.key === " ")) { | |
| e.preventDefault(); | |
| updateField("selectedProvider", p); | |
| } | |
| }} | |
| > | |
| {ProviderIcons[p as keyof typeof ProviderIcons]} | |
| <div className="text-sm">{PROVIDER_LABELS[p as keyof typeof PROVIDER_LABELS]}</div> | |
| </div> |
🧰 Tools
🪛 Biome (1.9.4)
[error] 339-355: Enforce to have the onClick mouse event with the onKeyUp, the onKeyDown, or the onKeyPress keyboard event.
Actions triggered using mouse events should have corresponding keyboard events to account for keyboard-only navigation.
(lint/a11y/useKeyWithClickEvents)
🤖 Prompt for AI Agents
In ui/components/config/provider-form.tsx around lines 339 to 360, the provider
selection divs have onClick handlers but lack keyboard accessibility, preventing
keyboard-only and screen reader users from selecting providers. Add onKeyDown
handlers to handle Enter and Space keys to trigger selection, set tabIndex=0 to
make the divs focusable, and include appropriate ARIA roles and attributes such
as role="button" and aria-pressed to indicate selection state for screen
readers.
| static email(value: string, message = "Must be a valid email"): ValidationRule { | ||
| return this.pattern(value, /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i, message); | ||
| } | ||
|
|
||
| static url(value: string, message = "Must be a valid URL"): ValidationRule { | ||
| return this.pattern(value, /^https?:\/\/.+/, message); | ||
| } |
There was a problem hiding this comment.
🧹 Nitpick (assertive)
Use explicit class name instead of this in static methods
Using this in static methods can be confusing as it refers to the class itself. Use the explicit class name for clarity.
Apply this refactor:
static email(value: string, message = "Must be a valid email"): ValidationRule {
- return this.pattern(value, /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i, message);
+ return Validator.pattern(value, /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i, message);
}
static url(value: string, message = "Must be a valid URL"): ValidationRule {
- return this.pattern(value, /^https?:\/\/.+/, message);
+ return Validator.pattern(value, /^https?:\/\/.+/, message);
}📝 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.
| static email(value: string, message = "Must be a valid email"): ValidationRule { | |
| return this.pattern(value, /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i, message); | |
| } | |
| static url(value: string, message = "Must be a valid URL"): ValidationRule { | |
| return this.pattern(value, /^https?:\/\/.+/, message); | |
| } | |
| static email(value: string, message = "Must be a valid email"): ValidationRule { | |
| return Validator.pattern(value, /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i, message); | |
| } | |
| static url(value: string, message = "Must be a valid URL"): ValidationRule { | |
| return Validator.pattern(value, /^https?:\/\/.+/, message); | |
| } |
🧰 Tools
🪛 Biome (1.9.4)
[error] 92-92: Using this in a static context can be confusing.
this refers to the class.
Unsafe fix: Use the class name instead.
(lint/complexity/noThisInStatic)
[error] 96-96: Using this in a static context can be confusing.
this refers to the class.
Unsafe fix: Use the class name instead.
(lint/complexity/noThisInStatic)
🤖 Prompt for AI Agents
In ui/lib/utils/validation.ts around lines 91 to 97, replace the use of 'this'
in the static methods 'email' and 'url' with the explicit class name
'Validation' to improve clarity. Change calls from 'this.pattern' to
'Validation.pattern' within these static methods.
Fix static method implementation.
The static analysis tool correctly identifies that using this in static methods is confusing and should reference the class name instead.
Apply this fix to use the class name:
- static email(value: string, message = "Must be a valid email"): ValidationRule {
- return this.pattern(value, /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i, message);
- }
+ static email(value: string, message = "Must be a valid email"): ValidationRule {
+ return Validator.pattern(value, /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i, message);
+ }
- static url(value: string, message = "Must be a valid URL"): ValidationRule {
- return this.pattern(value, /^https?:\/\/.+/, message);
- }
+ static url(value: string, message = "Must be a valid URL"): ValidationRule {
+ return Validator.pattern(value, /^https?:\/\/.+/, message);
+ }📝 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.
| static email(value: string, message = "Must be a valid email"): ValidationRule { | |
| return this.pattern(value, /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i, message); | |
| } | |
| static url(value: string, message = "Must be a valid URL"): ValidationRule { | |
| return this.pattern(value, /^https?:\/\/.+/, message); | |
| } | |
| static email(value: string, message = "Must be a valid email"): ValidationRule { | |
| return Validator.pattern(value, /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i, message); | |
| } | |
| static url(value: string, message = "Must be a valid URL"): ValidationRule { | |
| return Validator.pattern(value, /^https?:\/\/.+/, message); | |
| } |
🧰 Tools
🪛 Biome (1.9.4)
[error] 92-92: Using this in a static context can be confusing.
this refers to the class.
Unsafe fix: Use the class name instead.
(lint/complexity/noThisInStatic)
[error] 96-96: Using this in a static context can be confusing.
this refers to the class.
Unsafe fix: Use the class name instead.
(lint/complexity/noThisInStatic)
🤖 Prompt for AI Agents
In ui/lib/utils/validation.ts around lines 91 to 97, the static methods email
and url use 'this' to call another static method, which can be confusing.
Replace 'this' with the actual class name to reference the static method
correctly. For example, if the class is named ValidationUtils, change
'this.pattern' to 'ValidationUtils.pattern' in both methods.
| static required(value: any, message = "This field is required"): ValidationRule { | ||
| return { | ||
| isValid: value !== undefined && value !== null && value !== "" && value !== 0, | ||
| message, | ||
| }; | ||
| } |
There was a problem hiding this comment.
Fix the required validator to accept 0 as a valid value
The current implementation treats 0 as invalid, which is incorrect for numeric fields where 0 is a legitimate value (e.g., temperature, quantity, index).
Apply this fix:
static required(value: any, message = "This field is required"): ValidationRule {
return {
- isValid: value !== undefined && value !== null && value !== "" && value !== 0,
+ isValid: value !== undefined && value !== null && value !== "",
message,
};
}📝 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.
| static required(value: any, message = "This field is required"): ValidationRule { | |
| return { | |
| isValid: value !== undefined && value !== null && value !== "" && value !== 0, | |
| message, | |
| }; | |
| } | |
| static required(value: any, message = "This field is required"): ValidationRule { | |
| return { | |
| isValid: value !== undefined && value !== null && value !== "", | |
| message, | |
| }; | |
| } |
🤖 Prompt for AI Agents
In ui/lib/utils/validation.ts around lines 63 to 68, the required validator
incorrectly treats 0 as invalid. Modify the isValid condition to accept 0 as a
valid value by removing the check that excludes 0, ensuring that only undefined,
null, or empty string values are considered invalid.
🛠️ Refactor suggestion
Review the required validator logic.
The required validator treats 0 as an invalid value (value !== 0), which may not be expected behavior for numeric fields where zero is a valid value.
Consider this adjustment to handle numeric zero appropriately:
- static required(value: any, message = "This field is required"): ValidationRule {
- return {
- isValid: value !== undefined && value !== null && value !== "" && value !== 0,
- message,
- };
- }
+ static required(value: any, message = "This field is required"): ValidationRule {
+ return {
+ isValid: value !== undefined && value !== null && value !== "",
+ message,
+ };
+ }Or provide a separate validator for numeric fields where zero is valid.
📝 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.
| static required(value: any, message = "This field is required"): ValidationRule { | |
| return { | |
| isValid: value !== undefined && value !== null && value !== "" && value !== 0, | |
| message, | |
| }; | |
| } | |
| static required(value: any, message = "This field is required"): ValidationRule { | |
| return { | |
| isValid: value !== undefined && value !== null && value !== "", | |
| message, | |
| }; | |
| } |
🤖 Prompt for AI Agents
In ui/lib/utils/validation.ts around lines 63 to 68, the required validator
incorrectly treats the numeric value 0 as invalid. To fix this, modify the
isValid condition to allow 0 as a valid value by removing the check that
excludes 0. Alternatively, create a separate validator specifically for numeric
fields where zero should be considered valid.
| // Random width between 50 to 90%. | ||
| const width = React.useMemo(() => { | ||
| return `${Math.floor(Math.random() * 40) + 50}%` | ||
| }, []) |
There was a problem hiding this comment.
Potential SSR hydration mismatch with random width
Using Math.random() will generate different values on server and client, causing hydration mismatches in SSR environments.
Consider using a deterministic approach or generating the width only on the client:
const width = React.useMemo(() => {
- return `${Math.floor(Math.random() * 40) + 50}%`
+ // Use a deterministic default or generate only on client
+ return "70%"
}, [])Alternatively, use an effect to set the width after mount:
-const width = React.useMemo(() => {
- return `${Math.floor(Math.random() * 40) + 50}%`
-}, [])
+const [width, setWidth] = React.useState("70%")
+
+React.useEffect(() => {
+ setWidth(`${Math.floor(Math.random() * 40) + 50}%`)
+}, [])🤖 Prompt for AI Agents
In ui/components/ui/sidebar.tsx around lines 609 to 612, the useMemo hook
generates a random width using Math.random(), which causes server-client
hydration mismatches in SSR. To fix this, remove the random width generation
from the initial render and instead set the width inside a useEffect hook that
runs only on the client after mount, ensuring the width is deterministic during
SSR and only randomized on the client side.
| // Combine multiple validation rules | ||
| static all(rules: ValidationRule[]): ValidationRule { | ||
| const invalidRule = rules.find((rule) => !rule.isValid); | ||
| return invalidRule || { isValid: true, message: "" }; | ||
| } |
There was a problem hiding this comment.
🧹 Nitpick (assertive)
Enhance the all validator with better error handling.
The current implementation only returns the first invalid rule, which might not provide comprehensive feedback when multiple validations fail.
Consider returning all validation errors or providing an option to combine messages:
- static all(rules: ValidationRule[]): ValidationRule {
- const invalidRule = rules.find((rule) => !rule.isValid);
- return invalidRule || { isValid: true, message: "" };
- }
+ static all(rules: ValidationRule[]): ValidationRule {
+ const invalidRules = rules.filter((rule) => !rule.isValid);
+ return {
+ isValid: invalidRules.length === 0,
+ message: invalidRules.map(rule => rule.message).join("; "),
+ };
+ }📝 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.
| // Combine multiple validation rules | |
| static all(rules: ValidationRule[]): ValidationRule { | |
| const invalidRule = rules.find((rule) => !rule.isValid); | |
| return invalidRule || { isValid: true, message: "" }; | |
| } | |
| // Combine multiple validation rules | |
| static all(rules: ValidationRule[]): ValidationRule { | |
| const invalidRules = rules.filter((rule) => !rule.isValid); | |
| return { | |
| isValid: invalidRules.length === 0, | |
| message: invalidRules.map(rule => rule.message).join("; "), | |
| }; | |
| } |
🤖 Prompt for AI Agents
In ui/lib/utils/validation.ts around lines 134 to 138, the all validator
currently returns only the first invalid rule, limiting feedback on multiple
validation failures. Modify the method to collect all invalid rules from the
input array and return a combined result that includes all error messages,
either as a list or a concatenated string. This will provide comprehensive
validation feedback instead of stopping at the first failure.
70f6ae3 to
1f4a34b
Compare
There was a problem hiding this comment.
Actionable comments posted: 17
♻️ Duplicate comments (91)
ui/next.config.ts (1)
1-7: Empty config is still unnecessary noiseThe file remains empty with just a placeholder comment. Consider removing it until actual configuration is needed.
ui/postcss.config.mjs (1)
1-5: Plugin name is still incorrect – build will failThe plugin name
"@tailwindcss/postcss"is not a valid package. Use"tailwindcss"and add"autoprefixer"for proper Tailwind CSS processing.ui/lib/utils.ts (1)
1-6: clsx import is still incorrect – runtime error will occurThe import of
clsxas a named export is incorrect. It should be a default import, and arguments should be spread when calling the function.ui/.prettierrc (1)
5-5: Deprecated option still present – CI will failThe
jsxBracketSameLineoption was deprecated in Prettier 3. Replace withbracketSameLineto avoid format check failures.ui/components/theme-provider.tsx (1)
6-8: Consider exposing sane defaults instead of a raw passthrough.The existing comment correctly identifies that this wrapper adds little value without sensible defaults. The component should provide defaults like
attribute="class",enableSystem, anddefaultTheme="system"to reduce configuration burden on consumers.ui/components/ui/aspect-ratio.tsx (1)
5-7: Forward therefto stay Radix-compliant.The existing comment correctly identifies that Radix primitives require proper ref forwarding for focus management and measurements. The component should use
React.forwardRefto ensure proper ref propagation.ui/components/progress-bar.tsx (1)
5-5: Missing React import for type annotation.The existing comment correctly identifies that
React.ReactNoderequires a React import when using the new JSX runtime. This should be addressed to avoid potential runtime issues.ui/lib/constants/icons.tsx (1)
3-12: Export the key union to eliminate stringly-typed consumers.The existing comment correctly identifies that exporting a union type of the
ProviderIconskeys would provide better type safety and autocomplete for consumers, preventing stringly-typed usage.ui/components.json (1)
6-10: Empty Tailwind config path might break CLI commands.The existing comment correctly identifies that setting
"config": ""could cause shadcn/ui and Tailwind helpers to fail when looking for the config file. This should point to the actual Tailwind config file location.ui/hooks/use-mobile.ts (2)
6-6: Fix potential layout shift from undefined initial state.The hook initializes
isMobileasundefinedbut returns!!isMobilewhich convertsundefinedtofalse. This can cause layout shift when the actual mobile state is determined.
18-18: Simplify return statement.Since
isMobileis now a boolean, the double negation is unnecessary.ui/components/header.tsx (1)
6-6: Fix invalid Tailwind CSS syntax for CSS custom property.The class
left-(--sidebar-width)is not valid Tailwind CSS syntax. Tailwind doesn't support CSS custom properties directly in class names.ui/components/logs/ui/code-editor.css (1)
1-16: Consider a more maintainable approach to Monaco editor styling.The transparent background styling achieves the desired integration effect, but the multiple
!importantdeclarations could make future maintenance challenging. Consider using CSS custom properties or a more specific selector strategy.ui/components/logs/analytics/token-usage-chart.tsx (2)
21-21: Fixed height may not be responsive across screen sizes.
61-62: Hardcoded colors should use theme-aware values.Also applies to: 70-71
ui/README.md (1)
1-1: Add top-level heading for better markdown structure.ui/components/logs/analytics/latency-chart.tsx (2)
57-74: Replace hardcoded colors with CSS custom properties for theme consistency.The bar colors are hardcoded hex values instead of using CSS custom properties, which could cause theme inconsistencies.
44-50: Consider using consistent tooltip styling across chart components.Similar to the StatusDistributionChart, this uses hardcoded HSL values. Consider creating a shared tooltip style configuration.
ui/lib/constants/config.ts (1)
14-18: Consider using CSS custom properties for theme consistency.The MCP_STATUS_COLORS uses hardcoded Tailwind classes which may not adapt well to different themes. Consider using CSS custom properties instead.
ui/components/logs/analytics/request-volume-chart.tsx (1)
53-76: Consider using theme-aware colors for consistency.The chart implementation is excellent, but mixing hardcoded hex colors with theme-aware CSS custom properties could lead to inconsistent theming, especially in dark mode.
ui/app/layout.tsx (1)
35-35: Consider using max-width instead of fixed width for better responsiveness.The
w-5xlclass sets a fixed width which may cause layout issues on smaller screens. Consider usingmax-w-5xlinstead to allow the content to be responsive.ui/hooks/use-toast.ts (2)
10-11: Message formatting could be improved for better UX.The current colon-based concatenation may not provide optimal readability for longer messages.
13-17: Consider semantic accuracy for toast variants.Using
successas the default for all non-destructive variants may not be semantically correct for neutral informational messages.ui/components/logs/analytics/status-distribution-chart.tsx (1)
35-37: Performance optimization opportunity still applies.The data mapping inside the render function could benefit from memoization to prevent unnecessary re-renders with large datasets.
ui/components/config/core-settings-form.tsx (2)
59-64: Fix accessibility issue: Associate label with form control.The label "Drop Excess Requests" is not properly associated with the Switch component, which creates accessibility issues for screen readers.
67-113: Remove commented code or implement the feature.The large commented section for Pool Size configuration should either be removed if not needed or implemented if it's intended functionality.
ui/components/ui/progress.tsx (1)
18-18: Add value validation to prevent rendering issues.The transform calculation doesn't handle edge cases where
valuemight be negative or exceed 100, which could cause visual inconsistencies.ui/components/ui/input.tsx (1)
7-21: Consider addingforwardReffor better form library integration.The Input component is well-implemented with comprehensive styling and accessibility features. However, adding
forwardRefwould improve compatibility with form libraries like react-hook-form that need direct DOM access.ui/app/plugins/page.tsx (3)
106-110: Add security attributes to external linksThe external link is still missing the
rel="noopener noreferrer"attribute for security.Apply this diff:
<Button variant="outline" asChild> <Link href="https://github.com/maximhq/bifrost/tree/main/docs/contributing/plugin.md" target="_blank" + rel="noopener noreferrer" > <Plus className="mr-2 h-4 w-4" /> Create Plugin </Link> </Button>
150-153: Add security attributes to plugin source linksThese external links are still missing the
rel="noopener noreferrer"attributes for security.Apply these diffs:
<Button asChild variant="outline" className="flex-1"> <Link href={plugin.url} target="_blank" + rel="noopener noreferrer" className="flex items-center justify-center gap-2" > <Code className="h-4 w-4" /> View Source </Link> </Button> <Button asChild size="sm" variant="ghost"> - <Link href={plugin.url} target="_blank"> + <Link href={plugin.url} target="_blank" rel="noopener noreferrer"> <ExternalLink className="h-4 w-4" /> </Link> </Button>Also applies to: 156-158
182-186: Add security attributes to documentation linksThese external documentation links are still missing the
rel="noopener noreferrer"attributes for security.Apply these diffs:
<Button asChild className="w-full"> <Link href="https://github.com/maximhq/bifrost/tree/main/docs/contributing/plugin.md" target="_blank" + rel="noopener noreferrer" > <Code className="mr-2 h-4 w-4" /> Plugin Guide </Link> </Button><Button asChild variant="outline" className="w-full"> <Link href="https://github.com/maximhq/bifrost/tree/main/docs/architecture/plugins.md" target="_blank" + rel="noopener noreferrer" > <Puzzle className="mr-2 h-4 w-4" /> Architecture Docs </Link> </Button>Also applies to: 203-207
ui/components/logs/ui/log-message-view.tsx (2)
8-15: Memoize the JSON validation for performanceThe
isJsonfunction still callsJSON.parseon every render, which can be expensive for large strings.Consider memoizing the JSON validation result using
useMemo:+import { useMemo } from 'react'; export default function LogMessageView({ message }: LogMessageViewProps) { + const contentIsJson = useMemo(() => + typeof message.content === "string" && isJson(message.content), + [message.content] + ); + return ( <div className="w-full rounded-sm border"> <div className="border-b px-6 py-2 text-sm font-medium capitalize">{message.role}</div> - {typeof message.content === "string" && !isJson(message.content) ? ( + {typeof message.content === "string" && !contentIsJson ? (
17-23: Improve type safety in the cleanJson functionThe
cleanJsonfunction still usesanytype, which reduces type safety.-const cleanJson = (text: any) => { +const cleanJson = (text: string | object) => { try { - return JSON.parse(text); + return typeof text === 'string' ? JSON.parse(text) : text; } catch { return text; } };ui/components/ui/separator.tsx (1)
32-41: Simplify the conditional className logicThe conditional className logic in DottedSeparator can still be simplified since the
cnutility handles undefined values gracefully.function DottedSeparator(props: Props) { const { className } = props; return ( <div - className={cn("border-border h-[1px] w-full border-t border-dashed bg-transparent", { - [`${className}`]: className !== undefined, - })} + className={cn("border-border h-[1px] w-full border-t border-dashed bg-transparent", className)} /> ); }ui/components/sidebar.tsx (1)
170-170: Fix JSX self-closing elementThe animated dot div should still be self-closing as it has no children.
Apply this diff to fix the JSX formatting:
- <div className="h-2 w-2 animate-pulse rounded-full bg-green-500"></div> + <div className="h-2 w-2 animate-pulse rounded-full bg-green-500" />ui/components/ui/scroll-area.tsx (1)
17-17: ScrollBar orientation is not configurable.The ScrollBar is rendered with default vertical orientation. Consider making it configurable if horizontal scrolling support is needed.
ui/app/config/page.tsx (1)
48-60: Fix inconsistent error handling patternThe
loadMcpClientsfunction sets the state before checking for errors, which differs from the pattern used inloadProviders. This could lead to setting an empty array even when there's an error.Apply this diff to make the error handling consistent:
const loadMcpClients = async () => { const [data, error] = await apiService.getMCPClients(); - setMcpClients(data || []); if (error) { toast({ title: "Error", description: error, variant: "destructive", }); return; } + setMcpClients(data || []); };ui/components/logs/filters.tsx (1)
25-52: Refactor duplicate filterKeyMap for better maintainability.The
filterKeyMapobject is duplicated in bothhandleFilterSelectandisSelectedfunctions. Extract this to a constant at the module level to eliminate duplication.+const FILTER_KEY_MAP: Record<string, keyof LogFilters> = { + Status: "status", + Providers: "providers", + Type: "objects", +}; + export function LogFilters({ filters, onFiltersChange }: LogFiltersProps) { const [open, setOpen] = useState(false); const handleFilterSelect = (category: keyof typeof FILTER_OPTIONS, value: string) => { - const filterKeyMap: Record<keyof typeof FILTER_OPTIONS, keyof LogFilters> = { - Status: "status", - Providers: "providers", - Type: "objects", - }; - - const filterKey = filterKeyMap[category]; + const filterKey = FILTER_KEY_MAP[category]; const currentValues = (filters[filterKey] as string[]) || []; const newValues = currentValues.includes(value) ? currentValues.filter((v) => v !== value) : [...currentValues, value]; @@ -40,13 +35,7 @@ export function LogFilters({ filters, onFiltersChange }: LogFiltersProps) { }; const isSelected = (category: string, value: string) => { - const filterKeyMap: Record<string, keyof LogFilters> = { - Status: "status", - Providers: "providers", - Type: "objects", - }; - - const filterKey = filterKeyMap[category]; + const filterKey = FILTER_KEY_MAP[category]; const currentValues = filters[filterKey]; return Array.isArray(currentValues) && currentValues.includes(value); };ui/components/logs/analytics/provider-distribution-chart.tsx (1)
76-78: Add validation for empty or invalid data.The component doesn't handle edge cases like empty data arrays, which could cause rendering issues.
export function ProviderDistributionChart({ data, }: ProviderDistributionChartProps) { + if (!data || data.length === 0) { + return ( + <div className="w-full h-80 flex items-center justify-center text-muted-foreground"> + No provider data available + </div> + ); + } + return (ui/app/docs/page.tsx (2)
8-53: Add TypeScript interface for documentation sections.The
docSectionsarray would benefit from explicit type definitions for better type safety and IntelliSense support.Add this type definition before the array:
interface DocSection { title: string; description: string; icon: React.ComponentType<{ className?: string }>; url: string; badge?: string; items: string[]; } const docSections: DocSection[] = [ // ... existing sections ];
73-73: Addrel="noopener noreferrer"to external links for security.External links with
target="_blank"should includerel="noopener noreferrer"to prevent potential security vulnerabilities.Apply this pattern to all external links:
- href="https://github.com/maximhq/bifrost/tree/main/docs" - target="_blank" + href="https://github.com/maximhq/bifrost/tree/main/docs" + target="_blank" + rel="noopener noreferrer"Also applies to: 79-79, 117-117, 143-143, 164-164
ui/components/ui/popover.tsx (1)
33-33: Fix CSS custom property syntax in className.The origin property appears to have incorrect syntax for a CSS custom property.
- "bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 w-72 origin-(--radix-popover-content-transform-origin) rounded-md border p-4 shadow-md outline-hidden", + "bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 w-72 origin-[--radix-popover-content-transform-origin] rounded-md border p-4 shadow-md outline-hidden",ui/components/config/mcp-clients-lists.tsx (1)
82-82: Fix string concatenation with template literal.The string concatenation should use a template literal for better readability and performance.
-return client.config.stdio_config?.command + " " + client.config.stdio_config?.args.join(" ") || "STDIO"; +return `${client.config.stdio_config?.command} ${client.config.stdio_config?.args.join(" ")}` || "STDIO";ui/components/config/meta-config-renderer.tsx (3)
84-84: Replaceanytype with a more specific type.Using
anydefeats TypeScript's type safety benefits.- // eslint-disable-next-line @typescript-eslint/no-explicit-any - onMetaConfigChange: (key: keyof MetaConfig, value: any) => void; + onMetaConfigChange: (key: keyof MetaConfig, value: MetaConfig[keyof MetaConfig]) => void;
156-156: Fix accessibility issue: Associate label with form input.The label element is not properly associated with its input/textarea, which impacts accessibility.
- <label className="block text-sm font-medium">{field.label}</label> + <label + htmlFor={`meta-${field.name}`} + className="block text-sm font-medium" + > + {field.label} + </label>Then update the
renderFieldfunction to add the correspondingid:<Textarea + id={`meta-${field.name}`} placeholder={field.placeholder}<Input + id={`meta-${field.name}`} placeholder={field.placeholder}
110-112: Provide user feedback for JSON parsing errors.Currently, JSON parsing errors are silently ignored, which could confuse users when their input doesn't save as expected.
Consider adding error feedback:
onBlur={(e) => { if (field.isJson) { try { const parsed = JSON.parse(e.target.value); onMetaConfigChange(field.name, parsed); } catch (error) { // You could add a validation state or show a toast console.error(`Invalid JSON for ${field.label}:`, error); // Optionally, you could pass an error handler prop: // onJsonError?.(field.name, error); } } }}ui/components/logs/logs-table.tsx (2)
78-78: Use Number.parseInt for consistency with ES2015 standards.
156-170: Remove commented-out code to improve maintainability.ui/components/ui/tooltip.tsx (2)
31-31: Fix the CSS custom property syntax.
12-18: Consider removing the nested TooltipProvider to improve performance.ui/components/logs/ui/log-entry-details-view.tsx (2)
22-26: Fix inconsistent class name application pattern.
35-40: Fix orientation logic and class name consistency.ui/components/ui/accordion.tsx (1)
39-39: Define custom accordion animations.The custom animation classes
animate-accordion-upandanimate-accordion-downneed to be defined in your Tailwind configuration or CSS files to ensure proper functionality.ui/components/ui/table.tsx (2)
42-42: Consider making whitespace handling configurable.The hardcoded
whitespace-nowrapclass could cause horizontal scrolling issues with long content. Consider making this configurable through props to allow text wrapping when needed.
54-54: Consider making whitespace handling configurable.The hardcoded
whitespace-nowrapclass could cause horizontal scrolling issues with long content. Consider making this configurable through props to allow text wrapping when needed.ui/lib/constants/logs.ts (1)
18-45: Consider adding dark mode color variants.The color mappings only include light mode classes. Consider adding dark mode variants (e.g.,
dark:bg-cyan-900 dark:text-cyan-200) to ensure proper theme consistency across light and dark modes.ui/components/config/mcp-client-form.tsx (4)
84-84: Replace non-null assertion with safer type handling.The non-null assertion on
prev.stdio_config!could cause runtime errors.Apply this diff for safer handling:
stdio_config: { - ...prev.stdio_config!, + ...(prev.stdio_config || emptyStdioConfig), [field]: value, },
162-162: Remove unused error variable initialization.The error variable is initialized but never used for validation before submission, as validation is handled by the validator.
const handleSubmit = async () => { setIsLoading(true); - let error: string | null = null;
170-170: Use optional chaining instead of non-null assertion.Replace the non-null assertion with safer optional chaining.
Apply this diff:
stdio_config: form.connection_type === "stdio" ? { - ...form.stdio_config!, + ...(form.stdio_config || emptyStdioConfig), args: parseArrayFromText(argsText), envs: parseArrayFromText(envsText), } : undefined,
130-158: Consider extracting validation logic for better maintainability.The validation logic could be extracted into a separate function for better testability and reusability.
Example refactor:
const validateForm = (form: CreateMCPClientRequest): string | null => { if (!form.name.trim()) { return "Name is required."; } if (form.connection_type === "http" || form.connection_type === "sse") { if (!form.connection_string?.trim()) { return "Connection string is required for HTTP/SSE connections."; } } if (form.connection_type === "stdio") { if (!form.stdio_config?.command?.trim()) { return "Command is required for STDIO connections."; } } return null; };ui/components/logs/log-detail-sheet.tsx (2)
36-42: Extract hardcoded pricing rates to configuration.The token pricing rates are hardcoded, making them difficult to update when provider pricing changes.
Consider extracting these to a configuration object:
// At the top of the file or in a separate config file const TOKEN_PRICING = { input: { costPer1K: 0.01, // $0.01 per 1K tokens }, output: { costPer1K: 0.03, // $0.03 per 1K tokens }, }; // Then use in the calculation: const estimatedCost = tokenUsage ? { inputCost: (tokenUsage.prompt_tokens / 1000) * TOKEN_PRICING.input.costPer1K, outputCost: (tokenUsage.completion_tokens / 1000) * TOKEN_PRICING.output.costPer1K, total: (tokenUsage.prompt_tokens / 1000) * TOKEN_PRICING.input.costPer1K + (tokenUsage.completion_tokens / 1000) * TOKEN_PRICING.output.costPer1K, } : { inputCost: 0, outputCost: 0, total: 0 };
173-173: Add key prop and use optional chaining for safer rendering.The map iteration is missing a required key prop, and the conditional rendering could be simplified with optional chaining.
Apply this diff:
<div className="mt-4 w-full text-center text-sm font-medium">Conversation History</div> -{log.input_history && log.input_history.map((message) => <LogMessageView message={message} />)} +{log.input_history?.map((message, index) => <LogMessageView key={index} message={message} />)}ui/components/ui/select.tsx (1)
33-35: Consider extracting complex className stringsThe SelectTrigger has a very long className string that could benefit from being broken down for better readability and maintainability.
Consider using a more structured approach:
className={cn( - "border-input data-[placeholder]:text-muted-foreground [&_svg:not([class*='text-'])]:text-muted-foreground focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:bg-input/30 dark:hover:bg-input/50 flex w-fit items-center justify-between gap-2 rounded-md border bg-transparent px-3 py-2 text-sm whitespace-nowrap shadow-xs transition-[color,box-shadow] outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50 data-[size=default]:h-9 data-[size=sm]:h-8 *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center *:data-[slot=select-value]:gap-2 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4", + [ + // Base styles + "flex w-fit items-center justify-between gap-2 rounded-md border bg-transparent px-3 py-2 text-sm whitespace-nowrap shadow-xs transition-[color,box-shadow] outline-none", + // State styles + "border-input data-[placeholder]:text-muted-foreground focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]", + // Size variants + "data-[size=default]:h-9 data-[size=sm]:h-8", + // Invalid states + "aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive", + // Dark mode + "dark:bg-input/30 dark:hover:bg-input/50", + // Disabled states + "disabled:cursor-not-allowed disabled:opacity-50", + // SVG and value styles + "[&_svg:not([class*='text-'])]:text-muted-foreground [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4", + "*:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center *:data-[slot=select-value]:gap-2" + ], className, )}ui/components/logs/ui/code-editor.tsx (5)
358-363: Apply consistent safe DOM access pattern throughout.Multiple instances of
getDomNode()!need to be replaced with safe access patterns.Apply the same safe DOM access pattern as suggested earlier:
-if (contentHeight && editor.getDomNode()) { +const domNode = editor.getDomNode(); +if (contentHeight && domNode) { editor.layout({ height: contentHeight + 15, - width: editor.getDomNode()!.clientWidth, + width: domNode.clientWidth, }); }Also applies to: 376-381, 405-411
461-461: Simplify boolean ternary expressions.Also applies to: 467-467
143-345: Consider extracting custom completion logic for better maintainability.
134-137: Use optional chaining for event handler calls.Replace the non-null assertion with optional chaining for safer execution.
if (props.onFocus) { editor.onDidFocusEditorWidget(() => { - props.onFocus!(); + props.onFocus?.(); }); }
108-114: Replace non-null assertion with safe DOM access.The code checks for
getDomNode()existence but then uses a non-null assertion on the next line, which could cause runtime errors.-if (contentHeight && editorRef.current.getDomNode()) +const domNode = editorRef.current.getDomNode(); +if (contentHeight && domNode) { editorRef.current.layout({ height: contentHeight + 15, - width: editorRef.current.getDomNode()!.clientWidth, + width: domNode.clientWidth, }); +}ui/components/config/provider-form.tsx (6)
339-360: Add keyboard support for provider selection.
298-298: Use Number namespace methods for consistency.Also applies to: 508-508, 522-522, 559-559, 573-573
401-409: Fix accessibility issues with form labels.Also applies to: 426-435, 438-458
485-496: Apply consistent label accessibility fixes to remaining form fields.Also applies to: 500-511, 514-526
552-563: Apply consistent label accessibility fixes to remaining form fields.Also applies to: 566-577, 593-604, 610-615, 619-624, 627-633
1-676: Consider breaking down this large component.ui/lib/api.ts (3)
31-31: Apply optional chaining for cleaner error handling.
132-139: Clarify the distinction between reloadConfig and updateCoreConfig.Also applies to: 150-157
169-176: Fix return value for reconnectMCPClient method.ui/components/ui/command.tsx (1)
55-55: Fix invalid Tailwind CSS class.The class
outline-hiddenis not a valid Tailwind CSS utility. This should beoutline-none.ui/lib/utils/validation.ts (3)
63-68: Fix the required validator to accept 0 as a valid value.The current implementation treats
0as invalid, which is incorrect for numeric fields where 0 is a legitimate value.
91-97: Use explicit class name instead ofthisin static methods.Using
thisin static methods can be confusing. Use the explicit class nameValidatorinstead.
134-138: Enhance theallvalidator with better error handling.The current implementation only returns the first invalid rule, which might not provide comprehensive feedback when multiple validations fail.
ui/components/ui/sidebar.tsx (2)
85-87: Potential SSR issue with document.cookie.Direct access to
document.cookiecould cause issues during server-side rendering. Consider wrapping in a check or using an effect.
609-612: Potential SSR hydration mismatch with random width.Using
Math.random()will generate different values on server and client, causing hydration mismatches in SSR environments.ui/components/ui/dropdown-menu.tsx (6)
28-28: Fix Tailwind CSS custom property syntax.The className contains incorrect syntax for CSS custom properties. Tailwind requires square brackets for arbitrary values.
56-56: Replace non-standardoutline-hiddenwithoutline-none.The class
outline-hiddenis not a standard Tailwind CSS utility. Useoutline-noneinstead.
74-74: Replace non-standardoutline-hiddenwithoutline-none.The class
outline-hiddenis not a standard Tailwind CSS utility. Useoutline-noneinstead.
99-99: Replace non-standardoutline-hiddenwithoutline-none.The class
outline-hiddenis not a standard Tailwind CSS utility. Useoutline-noneinstead.
168-168: Replaceoutline-hiddenwithoutline-none.Use the standard Tailwind class for removing outlines.
184-184: Fix Tailwind CSS custom property syntax.Use square brackets for CSS custom properties in Tailwind.
ui/components/ui/hover-card.tsx (1)
28-31: Fix CSS variable syntax.The CSS class contains invalid syntax for a CSS variable reference. The
origin-(--radix-hover-card-content-transform-origin)should use proper Tailwind CSS arbitrary value syntax.Apply this diff to fix the CSS variable syntax:
- "bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 w-64 origin-(--radix-hover-card-content-transform-origin) rounded-md border p-4 shadow-md outline-hidden", + "bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 w-64 origin-[var(--radix-hover-card-content-transform-origin)] rounded-md border p-4 shadow-md outline-hidden",ui/components/ui/form-field.tsx (1)
25-35: Fix controlled vs uncontrolled input pattern.The component maintains internal state for
valuewhile accepting an externalvalueprop, which can lead to synchronization issues. External prop changes won't be reflected in the component state.For a fully controlled pattern:
export function FormField({ label, validation, onChange, className, tooltipSide = "right", - value: initialValue = "", + value = "", ...props }: FormFieldProps) { const [touched, setTouched] = useState(false); - const [value, setValue] = useState(initialValue); const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => { const newValue = e.target.value; - setValue(newValue); onChange?.(newValue); };Or add proper synchronization with useEffect if internal state is needed.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro
⛔ Files ignored due to path filters (1)
ui/package-lock.jsonis excluded by!**/package-lock.json
📒 Files selected for processing (86)
transports/bifrost-http/handlers/config.go(1 hunks)transports/bifrost-http/main.go(2 hunks)transports/bifrost-http/plugins/logging/main.go(3 hunks)transports/bifrost-http/plugins/logging/utils.go(0 hunks)ui/.gitignore(1 hunks)ui/.prettierrc(1 hunks)ui/README.md(1 hunks)ui/app/config/page.tsx(1 hunks)ui/app/docs/page.tsx(1 hunks)ui/app/globals.css(1 hunks)ui/app/layout.tsx(1 hunks)ui/app/page.tsx(1 hunks)ui/app/plugins/page.tsx(1 hunks)ui/components.json(1 hunks)ui/components/config/core-settings-form.tsx(1 hunks)ui/components/config/mcp-client-form.tsx(1 hunks)ui/components/config/mcp-clients-lists.tsx(1 hunks)ui/components/config/meta-config-renderer.tsx(1 hunks)ui/components/config/provider-form.tsx(1 hunks)ui/components/config/providers-list.tsx(1 hunks)ui/components/header.tsx(1 hunks)ui/components/logs/analytics/latency-chart.tsx(1 hunks)ui/components/logs/analytics/provider-distribution-chart.tsx(1 hunks)ui/components/logs/analytics/request-volume-chart.tsx(1 hunks)ui/components/logs/analytics/status-distribution-chart.tsx(1 hunks)ui/components/logs/analytics/token-usage-chart.tsx(1 hunks)ui/components/logs/columns.tsx(1 hunks)ui/components/logs/empty-state.tsx(1 hunks)ui/components/logs/filters.tsx(1 hunks)ui/components/logs/log-detail-sheet.tsx(1 hunks)ui/components/logs/logs-table.tsx(1 hunks)ui/components/logs/ui/code-editor.css(1 hunks)ui/components/logs/ui/code-editor.tsx(1 hunks)ui/components/logs/ui/log-entry-details-view.tsx(1 hunks)ui/components/logs/ui/log-message-view.tsx(1 hunks)ui/components/progress-bar.tsx(1 hunks)ui/components/sidebar.tsx(1 hunks)ui/components/theme-provider.tsx(1 hunks)ui/components/theme-toggle.tsx(1 hunks)ui/components/ui/accordion.tsx(1 hunks)ui/components/ui/alert-dialog.tsx(1 hunks)ui/components/ui/alert.tsx(1 hunks)ui/components/ui/aspect-ratio.tsx(1 hunks)ui/components/ui/avatar.tsx(1 hunks)ui/components/ui/badge.tsx(1 hunks)ui/components/ui/button.tsx(1 hunks)ui/components/ui/card.tsx(1 hunks)ui/components/ui/collapsible.tsx(1 hunks)ui/components/ui/command.tsx(1 hunks)ui/components/ui/dialog.tsx(1 hunks)ui/components/ui/dropdown-menu.tsx(1 hunks)ui/components/ui/form-field.tsx(1 hunks)ui/components/ui/hover-card.tsx(1 hunks)ui/components/ui/input.tsx(1 hunks)ui/components/ui/label.tsx(1 hunks)ui/components/ui/popover.tsx(1 hunks)ui/components/ui/progress.tsx(1 hunks)ui/components/ui/scroll-area.tsx(1 hunks)ui/components/ui/select.tsx(1 hunks)ui/components/ui/separator.tsx(1 hunks)ui/components/ui/sheet.tsx(1 hunks)ui/components/ui/sidebar.tsx(1 hunks)ui/components/ui/skeleton.tsx(1 hunks)ui/components/ui/switch.tsx(1 hunks)ui/components/ui/table.tsx(1 hunks)ui/components/ui/tabs.tsx(1 hunks)ui/components/ui/tag-input.tsx(1 hunks)ui/components/ui/textarea.tsx(1 hunks)ui/components/ui/tooltip.tsx(1 hunks)ui/eslint.config.mjs(1 hunks)ui/hooks/use-mobile.ts(1 hunks)ui/hooks/use-toast.ts(1 hunks)ui/hooks/useWebSocket.ts(1 hunks)ui/lib/api.ts(1 hunks)ui/lib/constants/config.ts(1 hunks)ui/lib/constants/icons.tsx(1 hunks)ui/lib/constants/logs.ts(1 hunks)ui/lib/types/config.ts(1 hunks)ui/lib/types/logs.ts(1 hunks)ui/lib/types/mcp.ts(1 hunks)ui/lib/utils.ts(1 hunks)ui/lib/utils/validation.ts(1 hunks)ui/next.config.ts(1 hunks)ui/package.json(1 hunks)ui/postcss.config.mjs(1 hunks)ui/tsconfig.json(1 hunks)
💤 Files with no reviewable changes (1)
- transports/bifrost-http/plugins/logging/utils.go
🧰 Additional context used
🧠 Learnings (13)
📓 Common learnings
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#84
File: transports/bifrost-http/main.go:2-2
Timestamp: 2025-06-15T16:05:13.489Z
Learning: For the Bifrost project, HTTP transport integration routers for new providers (like Mistral and Ollama) are implemented in separate PRs from the core provider support, following a focused PR strategy.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#103
File: .github/workflows/transport-dependency-update.yml:30-36
Timestamp: 2025-06-19T16:57:25.177Z
Learning: In the bifrost repository, Pratham-Mishra04 prefers to keep GitHub Actions workflows lean and trusts their controlled tagging process for core releases, avoiding unnecessary validation steps that they consider overkill.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#63
File: transports/bifrost-http/integrations/openai/types.go:89-119
Timestamp: 2025-06-10T11:00:02.875Z
Learning: In the Bifrost OpenAI integration (transports/bifrost-http/integrations/openai/types.go), the convertOpenAIContent function currently only handles the last image URL when multiple images are present in a content array. The user Pratham-Mishra04 has acknowledged this limitation and indicated it's part of a larger architectural issue that will be addressed comprehensively later, rather than with piecemeal fixes.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#54
File: core/schemas/provider.go:148-148
Timestamp: 2025-06-04T03:57:50.981Z
Learning: Breaking changes in the Bifrost codebase are managed by first merging and tagging core schema changes, then updating dependent code references in subsequent steps after the core version is released.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#85
File: core/providers/anthropic.go:150-156
Timestamp: 2025-06-15T16:07:53.140Z
Learning: In the Bifrost codebase, constructor functions are allowed to mutate input ProviderConfig objects in-place (e.g., setting default BaseURL values and trimming trailing slashes). This pattern is acceptable and doesn't need to be flagged as a code review issue.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#103
File: .github/workflows/transport-dependency-update.yml:53-75
Timestamp: 2025-06-20T16:21:18.912Z
Learning: In the bifrost repository's transport dependency update workflow, when updating the core dependency to a new version using `go get`, the go.mod and go.sum files will always change in normal operation, making the safety check for changes more of a defensive programming practice rather than handling a common scenario.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#63
File: transports/bifrost-http/integrations/openai/router.go:0-0
Timestamp: 2025-06-09T14:03:34.227Z
Learning: In the Bifrost HTTP transport layer (transports/bifrost-http/integrations/), request validation like checking for empty messages should be handled by the provider rather than at the transport layer. The transport layer should forward requests to Bifrost core/providers for validation.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#83
File: core/providers/mistral.go:168-170
Timestamp: 2025-06-15T14:24:49.882Z
Learning: In the Bifrost codebase, performance is prioritized over defensive copying for HTTP service operations. Specifically, shallow slice assignments in provider response handling are acceptable due to object pool reset patterns and JSON unmarshaling behavior that minimize practical data corruption risks.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#55
File: core/providers/anthropic.go:358-388
Timestamp: 2025-06-04T05:37:59.699Z
Learning: User Pratham-Mishra04 prefers not to extract small code duplications (around 2 lines) into helper functions, considering the overhead not worth it for such minor repetition.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#102
File: README.md:62-66
Timestamp: 2025-06-19T17:03:03.639Z
Learning: Pratham-Mishra04 prefers using the implicit 'latest' tag for the maximhq/bifrost Docker image rather than pinning to specific versions.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#138
File: docs/usage/go-package/mcp.md:408-412
Timestamp: 2025-07-01T12:40:08.576Z
Learning: Pratham-Mishra04 is okay with keeping bullet list formatting that uses colons after dashes in markdown documentation, even if it triggers linter warnings, preferring functionality over strict formatting rules.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#138
File: transports/README.md:26-28
Timestamp: 2025-07-01T12:45:06.906Z
Learning: Pratham-Mishra04 prefers keeping documentation examples simple and concise, trusting users to handle production-specific considerations like version pinning themselves rather than cluttering examples with additional notes.
ui/components/theme-provider.tsx (1)
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#85
File: core/providers/anthropic.go:150-156
Timestamp: 2025-06-15T16:07:53.140Z
Learning: In the Bifrost codebase, constructor functions are allowed to mutate input ProviderConfig objects in-place (e.g., setting default BaseURL values and trimming trailing slashes). This pattern is acceptable and doesn't need to be flagged as a code review issue.
ui/README.md (1)
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#94
File: core/bifrost.go:823-845
Timestamp: 2025-06-18T15:15:51.323Z
Learning: In the Bifrost project, the team prioritizes maintaining consistent error handling patterns over exposing detailed error context. All errors should be wrapped in the standard `BifrostError` structure rather than creating specific error types or exposing richer error details like exit codes or stderr output.
ui/lib/constants/icons.tsx (1)
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#81
File: tests/core-providers/go.mod:38-38
Timestamp: 2025-06-16T03:54:48.005Z
Learning: The `core-providers-test` module in `tests/core-providers/` is an internal testing module that will never be consumed as a dependency by external projects, so the replace directive pointing to `../../core` is acceptable for local development and testing purposes.
ui/components/config/core-settings-form.tsx (1)
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#85
File: core/providers/anthropic.go:150-156
Timestamp: 2025-06-15T16:07:53.140Z
Learning: In the Bifrost codebase, constructor functions are allowed to mutate input ProviderConfig objects in-place (e.g., setting default BaseURL values and trimming trailing slashes). This pattern is acceptable and doesn't need to be flagged as a code review issue.
transports/bifrost-http/main.go (6)
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#67
File: transports/bifrost-http/integrations/anthropic/router.go:26-34
Timestamp: 2025-06-10T11:19:29.604Z
Learning: The Generic router in transports/bifrost-http/integrations/utils.go already handles nil pointers from RequestConverter functions. When a RequestConverter returns a nil *schemas.BifrostRequest, the Generic router automatically returns an HTTP 400 error, making additional nil checks in individual router implementations redundant.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#103
File: .github/workflows/transport-dependency-update.yml:53-75
Timestamp: 2025-06-20T16:21:18.912Z
Learning: In the bifrost repository's transport dependency update workflow, when updating the core dependency to a new version using `go get`, the go.mod and go.sum files will always change in normal operation, making the safety check for changes more of a defensive programming practice rather than handling a common scenario.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#67
File: transports/bifrost-http/integrations/anthropic/router.go:26-34
Timestamp: 2025-06-10T11:19:29.604Z
Learning: The Generic router in transports/bifrost-http/integrations/utils.go already handles nil pointers from RequestConverter functions. When a RequestConverter returns a nil *schemas.BifrostRequest, the Generic router automatically returns an HTTP 400 error with "Invalid request" message, making additional nil checks in individual router implementations redundant.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#65
File: transports/bifrost-http/integrations/anthropic/router.go:19-33
Timestamp: 2025-06-09T16:46:32.018Z
Learning: In the GenericRouter (transports/bifrost-http/integrations), ResponseFunc is not called if the BifrostResponse parameter is nil, providing built-in protection against nil response marshaling.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#83
File: core/providers/mistral.go:168-170
Timestamp: 2025-06-15T14:24:49.882Z
Learning: In the Bifrost codebase, performance is prioritized over defensive copying for HTTP service operations. Specifically, shallow slice assignments in provider response handling are acceptable due to object pool reset patterns and JSON unmarshaling behavior that minimize practical data corruption risks.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#84
File: transports/bifrost-http/main.go:2-2
Timestamp: 2025-06-15T16:05:13.489Z
Learning: For the Bifrost project, HTTP transport integration routers for new providers (like Mistral and Ollama) are implemented in separate PRs from the core provider support, following a focused PR strategy.
ui/app/config/page.tsx (1)
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#85
File: core/providers/anthropic.go:150-156
Timestamp: 2025-06-15T16:07:53.140Z
Learning: In the Bifrost codebase, constructor functions are allowed to mutate input ProviderConfig objects in-place (e.g., setting default BaseURL values and trimming trailing slashes). This pattern is acceptable and doesn't need to be flagged as a code review issue.
ui/components/logs/columns.tsx (1)
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#85
File: core/providers/anthropic.go:150-156
Timestamp: 2025-06-15T16:07:53.140Z
Learning: In the Bifrost codebase, constructor functions are allowed to mutate input ProviderConfig objects in-place (e.g., setting default BaseURL values and trimming trailing slashes). This pattern is acceptable and doesn't need to be flagged as a code review issue.
transports/bifrost-http/plugins/logging/main.go (6)
Learnt from: connyay
PR: maximhq/bifrost#92
File: core/providers/utils.go:60-64
Timestamp: 2025-06-17T14:04:21.104Z
Learning: The bifrost codebase uses string alias types (like `type ContextKey string`) for context keys consistently across multiple packages including plugins/maxim/main.go and transports/bifrost-http/tracking/plugin.go. This pattern should be maintained for consistency rather than switching to the canonical struct{} approach.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#79
File: core/bifrost.go:94-103
Timestamp: 2025-06-14T04:06:58.240Z
Learning: In core/bifrost.go, the count parameter in RunPostHooks method is intentionally kept separate from p.executedPreHooks to support circuit breaker plugins that may need to trigger PostHooks for only a subset of executed plugins when detecting failure conditions mid-execution.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#55
File: core/providers/bedrock.go:443-468
Timestamp: 2025-06-04T09:32:15.826Z
Learning: In core/providers/bedrock.go, for tool call result messages (ModelChatMessageRoleTool), the Content field represents the actual tool call output. A tool result message should only be created when msg.Content is non-nil, as there's no semantic meaning to a tool result without output content.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#55
File: core/providers/bedrock.go:750-791
Timestamp: 2025-06-04T06:09:18.600Z
Learning: In the Bedrock provider, tool result messages maintain their original tool role in the input messages. The remapping from tool role to user role only occurs during message preparation for the Bedrock API request in `prepareChatCompletionMessages`, not in the original input. The `extractToolsFromHistory` function operates on unprocessed input messages where tool results retain their tool role.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#54
File: core/schemas/bifrost.go:46-49
Timestamp: 2025-06-04T09:22:18.123Z
Learning: In core/schemas/bifrost.go, the RequestInput struct uses ChatCompletionInput *[]BifrostMessage (pointer-to-slice) rather than []BifrostMessage to properly represent union type semantics. For text completion requests, ChatCompletionInput should be nil to indicate "no chat payload at all", while for chat completion requests it should be non-nil (even if empty slice). This distinguishes between different request types rather than just empty vs non-empty chat messages.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#65
File: transports/bifrost-http/integrations/utils.go:169-173
Timestamp: 2025-06-09T17:33:52.234Z
Learning: The ChatCompletionRequest method in the Bifrost client follows a contract where the result parameter will never be nil if the error parameter is nil. This means when error checking passes (err == nil), the result is guaranteed to be valid and can be safely used without additional nil checks.
ui/components/config/mcp-client-form.tsx (1)
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#131
File: transports/bifrost-http/lib/config.go:35-68
Timestamp: 2025-06-26T07:37:24.385Z
Learning: In the Bifrost project's MCP configuration handling, empty environment variables should be treated as missing/invalid rather than as valid empty values. The current implementation using `os.Getenv(envKey); envValue != ""` to check for non-empty values is the desired behavior.
ui/components/config/provider-form.tsx (1)
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#85
File: core/providers/anthropic.go:150-156
Timestamp: 2025-06-15T16:07:53.140Z
Learning: In the Bifrost codebase, constructor functions are allowed to mutate input ProviderConfig objects in-place (e.g., setting default BaseURL values and trimming trailing slashes). This pattern is acceptable and doesn't need to be flagged as a code review issue.
ui/lib/types/mcp.ts (1)
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#100
File: core/mcp.go:489-490
Timestamp: 2025-06-19T12:38:07.544Z
Learning: In the Bifrost MCP manager (core/mcp.go), the connectToMCPClient method is called during initialization/connection setup, not frequently during runtime. Logging operations like m.logger.Info inside critical sections in this context have negligible performance impact and don't require optimization for lock contention.
ui/lib/types/logs.ts (2)
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#64
File: transports/bifrost-http/integrations/genai/types.go:383-395
Timestamp: 2025-06-09T16:26:05.777Z
Learning: In the Bifrost schema (core/schemas/bifrost.go), only UserMessage and ToolMessage structs have ImageContent fields. AssistantMessage does not have an ImageContent field and cannot contain images. The schema design intentionally limits image content to user and tool messages only.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#80
File: plugins/maxim/main.go:249-264
Timestamp: 2025-06-14T06:17:54.426Z
Learning: In the BifrostError struct, the Error field is a struct (not a pointer), so accessing bifrostErr.Error.Message, bifrostErr.Error.Code, and bifrostErr.Error.Type is safe without nil checks on the Error field itself. The Code and Type fields are of type *string.
🧬 Code Graph Analysis (38)
ui/components/ui/label.tsx (1)
ui/lib/utils.ts (1)
cn(4-6)
ui/components/header.tsx (2)
ui/components/theme-toggle.tsx (1)
ThemeToggle(10-29)ui/components/ui/separator.tsx (1)
Separator(43-43)
ui/components/ui/textarea.tsx (1)
ui/lib/utils.ts (1)
cn(4-6)
ui/components/theme-toggle.tsx (2)
ui/components/ui/dropdown-menu.tsx (4)
DropdownMenu(193-193)DropdownMenuTrigger(195-195)DropdownMenuContent(196-196)DropdownMenuItem(199-199)ui/components/ui/button.tsx (1)
Button(71-71)
ui/components/ui/skeleton.tsx (1)
ui/lib/utils.ts (1)
cn(4-6)
ui/app/layout.tsx (2)
ui/components/theme-provider.tsx (1)
ThemeProvider(6-8)ui/components/ui/sidebar.tsx (2)
SidebarProvider(721-721)Sidebar(702-702)
ui/components/ui/scroll-area.tsx (1)
ui/lib/utils.ts (1)
cn(4-6)
ui/components/ui/input.tsx (1)
ui/lib/utils.ts (1)
cn(4-6)
ui/hooks/useWebSocket.ts (2)
transports/bifrost-http/plugins/logging/main.go (1)
LogEntry(46-62)ui/lib/types/logs.ts (1)
LogEntry(129-145)
ui/app/plugins/page.tsx (4)
ui/components/header.tsx (1)
Header(4-14)ui/components/ui/badge.tsx (1)
Badge(37-37)ui/components/ui/card.tsx (5)
Card(50-50)CardHeader(50-50)CardTitle(50-50)CardDescription(50-50)CardContent(50-50)ui/components/ui/button.tsx (1)
Button(71-71)
ui/components/ui/switch.tsx (1)
ui/lib/utils.ts (1)
cn(4-6)
ui/components/ui/separator.tsx (1)
ui/lib/utils.ts (1)
cn(4-6)
ui/components/ui/alert.tsx (1)
ui/lib/utils.ts (1)
cn(4-6)
ui/components/logs/filters.tsx (7)
ui/lib/types/logs.ts (1)
LogFilters(147-159)ui/lib/constants/logs.ts (3)
STATUSES(3-3)PROVIDERS(1-1)REQUEST_TYPES(5-5)ui/components/ui/input.tsx (1)
Input(7-21)ui/components/ui/popover.tsx (3)
Popover(48-48)PopoverTrigger(48-48)PopoverContent(48-48)ui/components/ui/button.tsx (1)
Button(71-71)ui/components/ui/command.tsx (6)
Command(114-114)CommandInput(114-114)CommandList(114-114)CommandEmpty(114-114)CommandGroup(114-114)CommandItem(114-114)ui/lib/utils.ts (1)
cn(4-6)
ui/components/ui/avatar.tsx (1)
ui/lib/utils.ts (1)
cn(4-6)
ui/components/ui/button.tsx (1)
ui/lib/utils.ts (1)
cn(4-6)
ui/components/logs/columns.tsx (5)
transports/bifrost-http/plugins/logging/main.go (1)
LogEntry(46-62)ui/lib/types/logs.ts (1)
LogEntry(129-145)ui/components/ui/button.tsx (1)
Button(71-71)ui/lib/constants/logs.ts (6)
Provider(47-47)PROVIDER_COLORS(18-27)Status(48-48)STATUS_COLORS(29-33)REQUEST_TYPE_COLORS(41-45)REQUEST_TYPE_LABELS(35-39)ui/components/ui/badge.tsx (1)
Badge(37-37)
ui/components/logs/ui/log-message-view.tsx (2)
ui/lib/types/logs.ts (1)
BifrostMessage(17-25)ui/components/logs/ui/code-editor.tsx (1)
CodeEditor(79-492)
ui/components/ui/tabs.tsx (1)
ui/lib/utils.ts (1)
cn(4-6)
ui/components/ui/tag-input.tsx (3)
ui/lib/utils.ts (1)
cn(4-6)ui/components/ui/badge.tsx (1)
Badge(37-37)ui/components/ui/input.tsx (1)
Input(7-21)
ui/components/ui/popover.tsx (1)
ui/lib/utils.ts (1)
cn(4-6)
ui/components/ui/tooltip.tsx (1)
ui/lib/utils.ts (1)
cn(4-6)
ui/components/ui/hover-card.tsx (1)
ui/lib/utils.ts (1)
cn(4-6)
ui/components/ui/dialog.tsx (1)
ui/lib/utils.ts (1)
cn(4-6)
ui/components/ui/progress.tsx (1)
ui/lib/utils.ts (1)
cn(4-6)
transports/bifrost-http/plugins/logging/main.go (2)
plugins/mocker/main.go (2)
Latency(124-128)Usage(137-141)ui/lib/types/logs.ts (1)
BifrostMessage(17-25)
ui/components/ui/badge.tsx (1)
ui/lib/utils.ts (1)
cn(4-6)
ui/components/ui/accordion.tsx (1)
ui/lib/utils.ts (1)
cn(4-6)
ui/components/logs/ui/log-entry-details-view.tsx (1)
ui/lib/utils.ts (1)
cn(4-6)
ui/components/ui/table.tsx (1)
ui/lib/utils.ts (1)
cn(4-6)
ui/components/ui/alert-dialog.tsx (2)
ui/lib/utils.ts (1)
cn(4-6)ui/components/ui/button.tsx (1)
buttonVariants(71-71)
ui/components/ui/card.tsx (1)
ui/lib/utils.ts (1)
cn(4-6)
ui/components/logs/ui/code-editor.tsx (1)
ui/lib/utils.ts (1)
cn(4-6)
ui/components/config/provider-form.tsx (16)
ui/lib/types/config.ts (10)
ProviderResponse(72-74)NetworkConfig(14-21)ConcurrencyAndBufferSize(24-27)MetaConfig(30-49)ProxyConfig(55-60)UpdateProviderRequest(93-99)AddProviderRequest(83-90)ModelProvider(4-4)Key(7-11)ProxyType(52-52)ui/lib/constants/config.ts (2)
DEFAULT_NETWORK_CONFIG(1-7)DEFAULT_PERFORMANCE_CONFIG(9-12)ui/lib/constants/logs.ts (3)
PROVIDERS(1-1)PROVIDER_COLORS(18-27)PROVIDER_LABELS(7-16)ui/lib/api.ts (1)
apiService(209-209)ui/lib/utils/validation.ts (1)
Validator(42-139)ui/components/ui/dialog.tsx (5)
Dialog(91-91)DialogContent(93-93)DialogHeader(96-96)DialogTitle(99-99)DialogDescription(94-94)ui/components/ui/separator.tsx (1)
Separator(43-43)ui/lib/utils.ts (1)
cn(4-6)ui/lib/constants/icons.tsx (1)
ProviderIcons(3-12)ui/components/ui/card.tsx (3)
CardHeader(50-50)CardTitle(50-50)CardContent(50-50)ui/components/ui/tooltip.tsx (4)
TooltipProvider(43-43)Tooltip(43-43)TooltipTrigger(43-43)TooltipContent(43-43)ui/components/ui/button.tsx (1)
Button(71-71)ui/components/ui/input.tsx (1)
Input(7-21)ui/components/ui/tag-input.tsx (1)
TagInput(16-65)ui/components/ui/alert.tsx (2)
Alert(41-41)AlertDescription(41-41)ui/components/ui/select.tsx (5)
Select(137-137)SelectTrigger(145-145)SelectValue(146-146)SelectContent(138-138)SelectItem(140-140)
ui/components/ui/select.tsx (1)
ui/lib/utils.ts (1)
cn(4-6)
ui/components/ui/sheet.tsx (1)
ui/lib/utils.ts (1)
cn(4-6)
ui/components/ui/sidebar.tsx (8)
ui/hooks/use-mobile.ts (1)
useIsMobile(5-19)ui/components/ui/tooltip.tsx (4)
TooltipProvider(43-43)TooltipContent(43-43)Tooltip(43-43)TooltipTrigger(43-43)ui/lib/utils.ts (1)
cn(4-6)ui/components/ui/sheet.tsx (5)
Sheet(90-90)SheetContent(90-90)SheetHeader(90-90)SheetTitle(90-90)SheetDescription(90-90)ui/components/ui/button.tsx (1)
Button(71-71)ui/components/ui/input.tsx (1)
Input(7-21)ui/components/ui/separator.tsx (1)
Separator(43-43)ui/components/ui/skeleton.tsx (1)
Skeleton(7-7)
ui/components/ui/dropdown-menu.tsx (1)
ui/lib/utils.ts (1)
cn(4-6)
🪛 markdownlint-cli2 (0.17.2)
ui/README.md
1-1: First line in a file should be a top-level heading
(MD041, first-line-heading, first-line-h1)
🪛 Biome (1.9.4)
ui/components/config/core-settings-form.tsx
[error] 60-60: A form label must be associated with an input.
Consider adding a for or htmlFor attribute to the label element or moving the input element to inside the label element.
(lint/a11y/noLabelWithoutControl)
ui/components/sidebar.tsx
[error] 170-170: JSX elements without children should be marked as self-closing. In JSX, it is valid for any element to be self-closing.
Unsafe fix: Use a SelfClosingElement instead
(lint/style/useSelfClosingElements)
ui/components/logs/filters.tsx
[error] 22-22: Shouldn't redeclare 'LogFilters'. Consider to delete it or rename it.
'LogFilters' is defined here:
(lint/suspicious/noRedeclare)
ui/components/config/meta-config-renderer.tsx
[error] 156-156: A form label must be associated with an input.
Consider adding a for or htmlFor attribute to the label element or moving the input element to inside the label element.
(lint/a11y/noLabelWithoutControl)
ui/components/config/mcp-clients-lists.tsx
[error] 82-82: Template literals are preferred over string concatenation.
Unsafe fix: Use a template literal.
(lint/style/useTemplate)
ui/components/config/mcp-client-form.tsx
[error] 84-84: Forbidden non-null assertion.
(lint/style/noNonNullAssertion)
[error] 170-170: Forbidden non-null assertion.
(lint/style/noNonNullAssertion)
ui/components/logs/logs-table.tsx
[error] 78-78: Use Number.parseInt instead of the equivalent global.
ES2015 moved some globals into the Number namespace for consistency.
Safe fix: Use Number.parseInt instead.
(lint/style/useNumberNamespace)
ui/components/logs/empty-state.tsx
[error] 205-205: Missing key property for this element in iterable.
The order of the items may change, and having a key can help React identify which item was moved.
Check the React documentation.
(lint/correctness/useJsxKeyInIterable)
[error] 210-210: Missing key property for this element in iterable.
The order of the items may change, and having a key can help React identify which item was moved.
Check the React documentation.
(lint/correctness/useJsxKeyInIterable)
ui/components/logs/log-detail-sheet.tsx
[error] 173-173: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
[error] 173-173: Missing key property for this element in iterable.
The order of the items may change, and having a key can help React identify which item was moved.
Check the React documentation.
(lint/correctness/useJsxKeyInIterable)
ui/components/logs/ui/code-editor.tsx
[error] 111-111: Forbidden non-null assertion.
Unsafe fix: Replace with optional chain operator ?. This operator includes runtime checks, so it is safer than the compile-only non-null assertion operator
(lint/style/noNonNullAssertion)
[error] 136-136: Forbidden non-null assertion.
Unsafe fix: Replace with optional chain operator ?. This operator includes runtime checks, so it is safer than the compile-only non-null assertion operator
(lint/style/noNonNullAssertion)
[error] 210-211: Forbidden non-null assertion.
Unsafe fix: Replace with optional chain operator ?. This operator includes runtime checks, so it is safer than the compile-only non-null assertion operator
(lint/style/noNonNullAssertion)
[error] 269-269: Forbidden non-null assertion.
Unsafe fix: Replace with optional chain operator ?. This operator includes runtime checks, so it is safer than the compile-only non-null assertion operator
(lint/style/noNonNullAssertion)
[error] 362-362: Forbidden non-null assertion.
Unsafe fix: Replace with optional chain operator ?. This operator includes runtime checks, so it is safer than the compile-only non-null assertion operator
(lint/style/noNonNullAssertion)
[error] 380-380: Forbidden non-null assertion.
Unsafe fix: Replace with optional chain operator ?. This operator includes runtime checks, so it is safer than the compile-only non-null assertion operator
(lint/style/noNonNullAssertion)
[error] 394-394: Forbidden non-null assertion.
Unsafe fix: Replace with optional chain operator ?. This operator includes runtime checks, so it is safer than the compile-only non-null assertion operator
(lint/style/noNonNullAssertion)
[error] 395-395: Forbidden non-null assertion.
Unsafe fix: Replace with optional chain operator ?. This operator includes runtime checks, so it is safer than the compile-only non-null assertion operator
(lint/style/noNonNullAssertion)
[error] 409-409: Forbidden non-null assertion.
Unsafe fix: Replace with optional chain operator ?. This operator includes runtime checks, so it is safer than the compile-only non-null assertion operator
(lint/style/noNonNullAssertion)
[error] 461-461: Unnecessary use of boolean literals in conditional expression.
Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with
(lint/complexity/noUselessTernary)
[error] 467-467: Unnecessary use of boolean literals in conditional expression.
Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with
(lint/complexity/noUselessTernary)
ui/components/config/provider-form.tsx
[error] 339-355: Enforce to have the onClick mouse event with the onKeyUp, the onKeyDown, or the onKeyPress keyboard event.
Actions triggered using mouse events should have corresponding keyboard events to account for keyboard-only navigation.
(lint/a11y/useKeyWithClickEvents)
[error] 412-412: A form label must be associated with an input.
Consider adding a for or htmlFor attribute to the label element or moving the input element to inside the label element.
(lint/a11y/noLabelWithoutControl)
[error] 439-439: A form label must be associated with an input.
Consider adding a for or htmlFor attribute to the label element or moving the input element to inside the label element.
(lint/a11y/noLabelWithoutControl)
[error] 485-485: A form label must be associated with an input.
Consider adding a for or htmlFor attribute to the label element or moving the input element to inside the label element.
(lint/a11y/noLabelWithoutControl)
[error] 500-500: A form label must be associated with an input.
Consider adding a for or htmlFor attribute to the label element or moving the input element to inside the label element.
(lint/a11y/noLabelWithoutControl)
[error] 514-514: A form label must be associated with an input.
Consider adding a for or htmlFor attribute to the label element or moving the input element to inside the label element.
(lint/a11y/noLabelWithoutControl)
[error] 552-552: A form label must be associated with an input.
Consider adding a for or htmlFor attribute to the label element or moving the input element to inside the label element.
(lint/a11y/noLabelWithoutControl)
[error] 566-566: A form label must be associated with an input.
Consider adding a for or htmlFor attribute to the label element or moving the input element to inside the label element.
(lint/a11y/noLabelWithoutControl)
[error] 593-593: A form label must be associated with an input.
Consider adding a for or htmlFor attribute to the label element or moving the input element to inside the label element.
(lint/a11y/noLabelWithoutControl)
[error] 610-610: A form label must be associated with an input.
Consider adding a for or htmlFor attribute to the label element or moving the input element to inside the label element.
(lint/a11y/noLabelWithoutControl)
[error] 619-619: A form label must be associated with an input.
Consider adding a for or htmlFor attribute to the label element or moving the input element to inside the label element.
(lint/a11y/noLabelWithoutControl)
[error] 627-627: A form label must be associated with an input.
Consider adding a for or htmlFor attribute to the label element or moving the input element to inside the label element.
(lint/a11y/noLabelWithoutControl)
[error] 298-298: Use Number.parseFloat instead of the equivalent global.
ES2015 moved some globals into the Number namespace for consistency.
Safe fix: Use Number.parseFloat instead.
(lint/style/useNumberNamespace)
[error] 508-508: Use Number.parseInt instead of the equivalent global.
ES2015 moved some globals into the Number namespace for consistency.
Safe fix: Use Number.parseInt instead.
(lint/style/useNumberNamespace)
[error] 522-522: Use Number.parseInt instead of the equivalent global.
ES2015 moved some globals into the Number namespace for consistency.
Safe fix: Use Number.parseInt instead.
(lint/style/useNumberNamespace)
[error] 559-559: Use Number.parseInt instead of the equivalent global.
ES2015 moved some globals into the Number namespace for consistency.
Safe fix: Use Number.parseInt instead.
(lint/style/useNumberNamespace)
[error] 573-573: Use Number.parseInt instead of the equivalent global.
ES2015 moved some globals into the Number namespace for consistency.
Safe fix: Use Number.parseInt instead.
(lint/style/useNumberNamespace)
ui/lib/utils/validation.ts
[error] 92-92: Using this in a static context can be confusing.
this refers to the class.
Unsafe fix: Use the class name instead.
(lint/complexity/noThisInStatic)
[error] 96-96: Using this in a static context can be confusing.
this refers to the class.
Unsafe fix: Use the class name instead.
(lint/complexity/noThisInStatic)
ui/lib/api.ts
[error] 31-31: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
🔇 Additional comments (46)
ui/.gitignore (1)
1-41: Comprehensive gitignore setupThe gitignore file is well-structured and covers all the necessary patterns for a Next.js project, including dependencies, build outputs, environment files, and system files.
ui/components/ui/skeleton.tsx (1)
1-7: Well-implemented skeleton component.The component follows React best practices with proper TypeScript typing, clean props spreading, and appropriate use of the
cnutility function for class merging.ui/components/ui/textarea.tsx (1)
1-18: Excellent textarea component implementation.The component demonstrates good React practices with comprehensive styling, proper accessibility features (aria-invalid handling), and clean TypeScript typing. The extensive CSS classes cover various states including focus, invalid, disabled, and dark mode support.
transports/bifrost-http/handlers/config.go (1)
35-41: LGTM! Method naming improvement enhances clarity.The rename from
handleReloadConfigtohandleUpdateConfigbetter describes the method's functionality since it actively updates configuration settings rather than just reloading. The route registration and comments are consistently updated.ui/components/theme-toggle.tsx (1)
10-29: Excellent implementation with proper accessibility and smooth animations.The theme toggle component is well-crafted with:
- Proper accessibility support via
sr-onlytext- Smooth CSS transitions for icon animations
- Clean integration with next-themes
- Consistent use of UI primitives
ui/tsconfig.json (1)
1-27: Well-configured TypeScript setup for Next.js project.The configuration properly enables:
- Strict type checking for code quality
- Modern JavaScript features (ES2017+)
- Next.js plugin integration
- Path aliasing for clean imports
- Incremental compilation for faster builds
ui/components/ui/label.tsx (1)
1-25: Well-structured accessible label component.The implementation correctly wraps Radix UI's Label primitive with consistent styling and proper TypeScript typing. The component handles disabled states appropriately using peer and group data attributes, and the
data-slotattribute aids in component identification.ui/lib/constants/config.ts (1)
1-12: Well-structured configuration constants.The default network and performance configuration objects provide sensible defaults with clear naming conventions. The timeout values and retry settings are appropriate for production use.
ui/app/layout.tsx (2)
20-24: Comprehensive metadata configuration.The metadata provides clear, descriptive information about the Bifrost UI application with appropriate SEO-friendly content.
26-42: Well-structured provider composition.The layout properly nests providers in the correct order: ProgressProvider → ThemeProvider → SidebarProvider, ensuring proper context propagation throughout the application.
ui/hooks/use-toast.ts (1)
9-21: The hook implementation provides a clean interface.The useToast hook successfully abstracts the sonner library and provides a consistent API for toast notifications across the application.
ui/components/ui/collapsible.tsx (1)
1-17: Clean wrapper implementation following established patterns.The component wrappers properly forward props to Radix primitives while adding consistent data-slot attributes for styling hooks. This aligns well with the overall UI component architecture.
ui/components/logs/analytics/status-distribution-chart.tsx (1)
10-43: Well-structured chart component with proper responsive design.The component implements a clean interface with proper tooltip styling, responsive container, and consistent theme integration using CSS variables.
ui/components/ui/switch.tsx (1)
8-29: Excellent implementation following React best practices.The Switch component properly uses forwardRef, comprehensive Tailwind styling for all states, and correct displayName assignment. The styling covers focus, disabled, and transition states appropriately.
ui/components/ui/alert.tsx (2)
6-19: Smart variant management with sophisticated grid layout.The cva configuration handles variants cleanly while the CSS grid implementation with conditional columns (
has-[>svg]:grid-cols-[calc(var(--spacing)*4)_1fr]) is a clever approach for handling optional icons.
21-39: Excellent component composition with proper accessibility.The Alert components provide flexible composition with proper semantic roles and consistent data-slot attributes. The use of
role="alert"ensures accessibility compliance.ui/components/config/core-settings-form.tsx (2)
22-33: LGTM: Well-structured async configuration loading.The useEffect implementation properly handles async configuration fetching with error handling and loading state management. The pattern of checking for both error and successful data is solid.
35-45: LGTM: Robust configuration update handling.The handleConfigChange function correctly implements optimistic UI updates with proper error handling and user feedback via toast notifications.
ui/components/ui/progress.tsx (1)
8-22: LGTM: Clean component implementation.The component properly extends Radix UI primitives with good TypeScript typing and uses the utility function for class name merging. The data-slot attributes are helpful for styling and testing.
ui/app/globals.css (3)
1-4: LGTM: Proper CSS setup with modern features.The Tailwind imports and custom dark mode variant are correctly configured. The custom dark mode variant using
(&:is(.dark *))provides flexible dark mode scoping.
47-114: Excellent use of modern OKLCH color space.The comprehensive theme variables using OKLCH color space provide better color consistency and perceptual uniformity compared to traditional RGB/HSL. The extensive variable definitions support both light and dark modes effectively.
116-123: LGTM: Clean base layer styling.The base layer applies sensible defaults with proper use of CSS custom properties for consistent theming across the application.
ui/components/ui/input.tsx (1)
12-17: Excellent comprehensive styling approach.The extensive Tailwind classes cover all necessary input states including focus, disabled, file inputs, dark mode, and ARIA invalid states. The use of the
cnutility function allows for proper class composition.transports/bifrost-http/main.go (2)
115-139: LGTM: Appropriate CORS implementation for development.The CORS middleware correctly handles localhost origins with proper preflight support and standard CORS headers. The string prefix matching for localhost/127.0.0.1 is simple but effective for development scenarios.
282-291: Confirm CORS on/metricsendpointThe handler now applies CORS to
/metrics, which could allow cross-origin scraping of sensitive metrics. Ensure this change is intentional and that, in production, you’re not exposing metrics to untrusted origins.• File: transports/bifrost-http/main.go
Lines: 282–291If you don’t want public CORS on
/metrics, consider:
- Restricting allowed origins via your CORS middleware configuration
- Disabling CORS for
/metricsand only enabling it on API routesui/components/ui/tag-input.tsx (1)
16-67: Well-implemented tag input componentThe
TagInputcomponent is well-structured and follows React best practices:
- Proper use of
forwardReffor ref forwarding- Good keyboard interaction handling (Enter, comma, Backspace)
- Prevents duplicate tags
- Clean TypeScript types with proper prop omission
- Intuitive user experience with visual tag badges and remove buttons
The implementation handles edge cases well and provides a solid foundation for tag input functionality.
ui/components/ui/avatar.tsx (1)
8-32: Clean avatar component implementation.The avatar components follow consistent patterns with proper prop forwarding, class name merging, and accessibility attributes. The implementation aligns well with the broader UI component system.
ui/components/ui/button.tsx (1)
8-71: Comprehensive button component with excellent variant system.The button implementation provides a robust foundation with proper variant handling, loading states, and accessibility features. The use of
class-variance-authorityfor styling variants and the separation of concerns betweenButtonandBaseButtoncomponents shows good architectural thinking.ui/components/logs/columns.tsx (1)
28-33: Good use of imported color constants.The code now correctly uses the imported
PROVIDER_COLORSandSTATUS_COLORSconstants, maintaining consistency across the application.Also applies to: 44-50
ui/components/ui/badge.tsx (1)
1-37: Well-implemented badge component with comprehensive styling.The badge component is excellently structured with proper TypeScript types, clean variant management using CVA, and comprehensive accessibility features. The CSS classes include proper focus states, ARIA attributes, and responsive design patterns. The use of Radix Slot for polymorphic behavior is a good architectural choice.
ui/components/ui/tabs.tsx (1)
1-39: Solid tabs implementation with comprehensive styling.The tabs component properly wraps Radix UI primitives with well-thought-out styling. The complex CSS classes in
TabsTriggerprovide comprehensive state management for active/inactive, focus, and disabled states. The dark mode support and accessibility features are well-handled.ui/components/config/mcp-clients-lists.tsx (1)
26-178: Well-structured MCP client management component.The component implements comprehensive CRUD operations with proper error handling, state management, and user feedback via toast notifications. The API integration patterns are consistent and the UI provides clear actions for different client states.
ui/components/ui/dialog.tsx (1)
1-101: Comprehensive dialog component with excellent accessibility.The dialog component is well-architected with proper composition of Radix primitives. The accessibility features are excellent, including screen reader support, focus management, and keyboard navigation. The optional close button with
showCloseButtonprop provides good flexibility, and the animation classes create smooth transitions.ui/components/config/meta-config-renderer.tsx (1)
19-78: Well-structured provider meta configuration mapping.The
providerMetaFieldsconfiguration object provides a clean, maintainable way to define provider-specific form fields. The typing withMetaFieldinterface ensures consistency across different provider configurations.transports/bifrost-http/plugins/logging/main.go (3)
49-49: Good structural organization.Moving the
Objectfield aboveProviderimproves the logical grouping of fields in theLogEntrystruct.
324-334: Excellent improvement to ID assignment logic.The enhanced ID assignment ensures that log entries always have a valid ID by using
result.IDwhen available and falling back to a generated UUID when it's empty. This prevents potential issues with empty IDs in log entries.
350-356: Robust fallback logic for InputHistory extraction.The enhanced logic properly handles cases where
result.ExtraFields.ChatHistoryis nil by falling back to context values or an empty slice. This improves the reliability of log entry creation and ensuresInputHistoryis always populated appropriately.ui/package.json (1)
42-45: Dependency Versions Are StableReact 19.0.0 (released December 2024) and Next.js 15.3.4 (released May 2025) are both marked as stable and suitable for production use. No changes required here.
ui/components/ui/card.tsx (1)
1-51: Well-structured card component implementation.The card component suite is well-designed with proper prop forwarding, class name merging, and semantic data attributes. The conditional grid layout in
CardHeaderfor handlingCardActionpositioning is particularly well thought out.ui/components/config/providers-list.tsx (1)
1-194: Comprehensive provider management component.The implementation is well-structured with proper state management, error handling, and loading states. The conditional API key display for different provider types (lines 146-154) and the comprehensive table layout provide a good user experience.
ui/lib/types/mcp.ts (1)
1-39: LGTM! Well-structured type definitions.The MCP type definitions are clear, well-organized, and follow TypeScript best practices. The interfaces properly separate concerns between configuration, client state, and request payloads.
ui/components/ui/alert-dialog.tsx (1)
1-94: LGTM! Clean and consistent UI component implementation.The AlertDialog components properly wrap Radix UI primitives with appropriate styling and maintain consistency with the rest of the UI library. Good use of data-slot attributes for styling hooks and proper props forwarding.
ui/lib/types/config.ts (1)
1-139: Well-structured type definitions!The type definitions are clean, well-organized, and properly mirror the Go backend structures. Good use of TypeScript features like union types, optional properties, and index signatures.
ui/components/ui/sheet.tsx (1)
1-91: Clean implementation of the Sheet component!Well-structured component built on Radix UI primitives with proper TypeScript types, accessibility features (ARIA labels), and clean separation of concerns. The animation classes and side-specific styling are properly implemented.
ui/components/ui/command.tsx (1)
40-40: Verify the**selector syntax in the className.The className contains
**:data-[slot=command-input-wrapper]:h-12which uses a**selector. This is an unusual syntax for Tailwind CSS and might be a typo. Did you mean*:data-[slot=command-input-wrapper]:h-12(direct children) instead?ui/lib/utils/validation.ts (1)
16-16: Fix typo in property name.The property
showTooltipappears to be a typo and should beshowTooltip.Apply this fix:
- showTooltip: boolean; + showTooltip: boolean;Also update line 26:
- showTooltip: config.showAlways || (touched && !!invalidRule), + showTooltip: config.showAlways || (touched && !!invalidRule),Likely an incorrect or invalid review comment.
| const compat = new FlatCompat({ | ||
| baseDirectory: __dirname, | ||
| recommendedConfig: js.configs.recommended, | ||
| }); |
There was a problem hiding this comment.
Fix __dirname usage in ES module context.
__dirname is not available in ES modules. You need to derive it from import.meta.url.
Add these imports and derive __dirname:
+import { dirname } from "node:path";
+import { fileURLToPath } from "node:url";
+
+const __dirname = dirname(fileURLToPath(import.meta.url));
const compat = new FlatCompat({
baseDirectory: __dirname,
recommendedConfig: js.configs.recommended,
});📝 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.
| const compat = new FlatCompat({ | |
| baseDirectory: __dirname, | |
| recommendedConfig: js.configs.recommended, | |
| }); | |
| import { dirname } from "node:path"; | |
| import { fileURLToPath } from "node:url"; | |
| const __dirname = dirname(fileURLToPath(import.meta.url)); | |
| const compat = new FlatCompat({ | |
| baseDirectory: __dirname, | |
| recommendedConfig: js.configs.recommended, | |
| }); |
🤖 Prompt for AI Agents
In ui/eslint.config.mjs around lines 9 to 12, __dirname is used but it is not
available in ES modules. To fix this, import 'fileURLToPath' from 'url' and
'dirname' from 'path', then derive __dirname by converting import.meta.url to a
file path and getting its directory name. Replace the direct use of __dirname
with this derived value.
| declare const process: { | ||
| env: { | ||
| NEXT_PUBLIC_BIFROST_PORT?: string; | ||
| }; | ||
| }; |
There was a problem hiding this comment.
🧹 Nitpick (assertive)
Remove unnecessary process declaration.
In a Next.js environment, process is already available globally and this declaration is redundant.
Remove the process declaration:
-declare const process: {
- env: {
- NEXT_PUBLIC_BIFROST_PORT?: string;
- };
-};📝 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.
| declare const process: { | |
| env: { | |
| NEXT_PUBLIC_BIFROST_PORT?: string; | |
| }; | |
| }; |
🤖 Prompt for AI Agents
In ui/hooks/useWebSocket.ts around lines 8 to 12, remove the entire declaration
of the process constant since process is globally available in Next.js and this
declaration is redundant.
| const port = process.env.NEXT_PUBLIC_BIFROST_PORT || "8080"; | ||
| const connect = () => { | ||
| if (wsRef.current?.readyState === WebSocket.OPEN) { | ||
| return; | ||
| } | ||
|
|
||
| const ws = new WebSocket(`ws://localhost:${port}/ws/logs`); |
There was a problem hiding this comment.
🛠️ Refactor suggestion
WebSocket URL should be configurable for production deployments.
The WebSocket URL is hardcoded to localhost, which won't work when the UI is deployed separately from the backend server.
Make the WebSocket host configurable:
const port = process.env.NEXT_PUBLIC_BIFROST_PORT || "8080";
+const host = process.env.NEXT_PUBLIC_BIFROST_HOST || "localhost";
const connect = () => {
if (wsRef.current?.readyState === WebSocket.OPEN) {
return;
}
- const ws = new WebSocket(`ws://localhost:${port}/ws/logs`);
+ const ws = new WebSocket(`ws://${host}:${port}/ws/logs`);Consider also supporting secure WebSocket (wss://) for production:
+const protocol = process.env.NEXT_PUBLIC_BIFROST_WS_PROTOCOL || "ws";
-const ws = new WebSocket(`ws://${host}:${port}/ws/logs`);
+const ws = new WebSocket(`${protocol}://${host}:${port}/ws/logs`);📝 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.
| const port = process.env.NEXT_PUBLIC_BIFROST_PORT || "8080"; | |
| const connect = () => { | |
| if (wsRef.current?.readyState === WebSocket.OPEN) { | |
| return; | |
| } | |
| const ws = new WebSocket(`ws://localhost:${port}/ws/logs`); | |
| const port = process.env.NEXT_PUBLIC_BIFROST_PORT || "8080"; | |
| const host = process.env.NEXT_PUBLIC_BIFROST_HOST || "localhost"; | |
| const protocol = process.env.NEXT_PUBLIC_BIFROST_WS_PROTOCOL || "ws"; | |
| const connect = () => { | |
| if (wsRef.current?.readyState === WebSocket.OPEN) { | |
| return; | |
| } | |
| const ws = new WebSocket(`${protocol}://${host}:${port}/ws/logs`); |
🤖 Prompt for AI Agents
In ui/hooks/useWebSocket.ts around lines 20 to 26, the WebSocket URL is
hardcoded to use localhost, which is not suitable for production deployments
where the backend may be on a different host. Modify the code to read the
WebSocket host from an environment variable or configuration, falling back to
localhost if not set. Additionally, detect or configure the protocol to use
ws:// for development and wss:// for production to support secure WebSocket
connections.
| } | ||
|
|
||
| const sidebarMenuButtonVariants = cva( | ||
| "peer/menu-button flex w-full items-center gap-2 overflow-hidden rounded-md p-2 text-left text-sm outline-hidden ring-sidebar-ring transition-[width,height,padding] hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 active:bg-sidebar-accent active:text-sidebar-accent-foreground disabled:pointer-events-none disabled:opacity-50 group-has-data-[sidebar=menu-action]/menu-item:pr-8 aria-disabled:pointer-events-none aria-disabled:opacity-50 data-[active=true]:bg-sidebar-accent data-[active=true]:font-medium data-[active=true]:text-sidebar-accent-foreground data-[state=open]:hover:bg-sidebar-accent data-[state=open]:hover:text-sidebar-accent-foreground group-data-[collapsible=icon]:size-8! group-data-[collapsible=icon]:p-2! [&>span:last-child]:truncate [&>svg]:size-4 [&>svg]:shrink-0", |
There was a problem hiding this comment.
Fix invalid Tailwind CSS class.
The class outline-hidden is not a valid Tailwind CSS utility. This should be outline-none.
Apply this fix:
- "peer/menu-button flex w-full items-center gap-2 overflow-hidden rounded-md p-2 text-left text-sm outline-hidden ring-sidebar-ring transition-[width,height,padding] hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 active:bg-sidebar-accent active:text-sidebar-accent-foreground disabled:pointer-events-none disabled:opacity-50 group-has-data-[sidebar=menu-action]/menu-item:pr-8 aria-disabled:pointer-events-none aria-disabled:opacity-50 data-[active=true]:bg-sidebar-accent data-[active=true]:font-medium data-[active=true]:text-sidebar-accent-foreground data-[state=open]:hover:bg-sidebar-accent data-[state=open]:hover:text-sidebar-accent-foreground group-data-[collapsible=icon]:size-8! group-data-[collapsible=icon]:p-2! [&>span:last-child]:truncate [&>svg]:size-4 [&>svg]:shrink-0",
+ "peer/menu-button flex w-full items-center gap-2 overflow-hidden rounded-md p-2 text-left text-sm outline-none ring-sidebar-ring transition-[width,height,padding] hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 active:bg-sidebar-accent active:text-sidebar-accent-foreground disabled:pointer-events-none disabled:opacity-50 group-has-data-[sidebar=menu-action]/menu-item:pr-8 aria-disabled:pointer-events-none aria-disabled:opacity-50 data-[active=true]:bg-sidebar-accent data-[active=true]:font-medium data-[active=true]:text-sidebar-accent-foreground data-[state=open]:hover:bg-sidebar-accent data-[state=open]:hover:text-sidebar-accent-foreground group-data-[collapsible=icon]:size-8! group-data-[collapsible=icon]:p-2! [&>span:last-child]:truncate [&>svg]:size-4 [&>svg]:shrink-0",📝 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.
| "peer/menu-button flex w-full items-center gap-2 overflow-hidden rounded-md p-2 text-left text-sm outline-hidden ring-sidebar-ring transition-[width,height,padding] hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 active:bg-sidebar-accent active:text-sidebar-accent-foreground disabled:pointer-events-none disabled:opacity-50 group-has-data-[sidebar=menu-action]/menu-item:pr-8 aria-disabled:pointer-events-none aria-disabled:opacity-50 data-[active=true]:bg-sidebar-accent data-[active=true]:font-medium data-[active=true]:text-sidebar-accent-foreground data-[state=open]:hover:bg-sidebar-accent data-[state=open]:hover:text-sidebar-accent-foreground group-data-[collapsible=icon]:size-8! group-data-[collapsible=icon]:p-2! [&>span:last-child]:truncate [&>svg]:size-4 [&>svg]:shrink-0", | |
| "peer/menu-button flex w-full items-center gap-2 overflow-hidden rounded-md p-2 text-left text-sm outline-none ring-sidebar-ring transition-[width,height,padding] hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 active:bg-sidebar-accent active:text-sidebar-accent-foreground disabled:pointer-events-none disabled:opacity-50 group-has-data-[sidebar=menu-action]/menu-item:pr-8 aria-disabled:pointer-events-none aria-disabled:opacity-50 data-[active=true]:bg-sidebar-accent data-[active=true]:font-medium data-[active=true]:text-sidebar-accent-foreground data-[state=open]:hover:bg-sidebar-accent data-[state=open]:hover:text-sidebar-accent-foreground group-data-[collapsible=icon]:size-8! group-data-[collapsible=icon]:p-2! [&>span:last-child]:truncate [&>svg]:size-4 [&>svg]:shrink-0", |
🤖 Prompt for AI Agents
In ui/components/ui/sidebar.tsx at line 477, replace the invalid Tailwind CSS
class 'outline-hidden' with the correct class 'outline-none' to ensure proper
styling and avoid errors.
| data-slot="sidebar-group-action" | ||
| data-sidebar="group-action" | ||
| className={cn( | ||
| "text-sidebar-foreground ring-sidebar-ring hover:bg-sidebar-accent hover:text-sidebar-accent-foreground absolute top-3.5 right-3 flex aspect-square w-5 items-center justify-center rounded-md p-0 outline-hidden transition-transform focus-visible:ring-2 [&>svg]:size-4 [&>svg]:shrink-0", |
There was a problem hiding this comment.
Fix invalid Tailwind CSS class.
The class outline-hidden is not a valid Tailwind CSS utility. This should be outline-none.
Apply this fix:
- "text-sidebar-foreground ring-sidebar-ring hover:bg-sidebar-accent hover:text-sidebar-accent-foreground absolute top-3.5 right-3 flex aspect-square w-5 items-center justify-center rounded-md p-0 outline-hidden transition-transform focus-visible:ring-2 [&>svg]:size-4 [&>svg]:shrink-0",
+ "text-sidebar-foreground ring-sidebar-ring hover:bg-sidebar-accent hover:text-sidebar-accent-foreground absolute top-3.5 right-3 flex aspect-square w-5 items-center justify-center rounded-md p-0 outline-none transition-transform focus-visible:ring-2 [&>svg]:size-4 [&>svg]:shrink-0",📝 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.
| "text-sidebar-foreground ring-sidebar-ring hover:bg-sidebar-accent hover:text-sidebar-accent-foreground absolute top-3.5 right-3 flex aspect-square w-5 items-center justify-center rounded-md p-0 outline-hidden transition-transform focus-visible:ring-2 [&>svg]:size-4 [&>svg]:shrink-0", | |
| "text-sidebar-foreground ring-sidebar-ring hover:bg-sidebar-accent hover:text-sidebar-accent-foreground absolute top-3.5 right-3 flex aspect-square w-5 items-center justify-center rounded-md p-0 outline-none transition-transform focus-visible:ring-2 [&>svg]:size-4 [&>svg]:shrink-0", |
🤖 Prompt for AI Agents
In ui/components/ui/sidebar.tsx at line 429, replace the invalid Tailwind CSS
class "outline-hidden" with the correct class "outline-none" to ensure proper
styling and avoid build errors.
| data-slot="sidebar-group-label" | ||
| data-sidebar="group-label" | ||
| className={cn( | ||
| "text-sidebar-foreground/70 ring-sidebar-ring flex h-8 shrink-0 items-center rounded-md px-2 text-xs font-medium outline-hidden transition-[margin,opacity] duration-200 ease-linear focus-visible:ring-2 [&>svg]:size-4 [&>svg]:shrink-0", |
There was a problem hiding this comment.
Fix invalid Tailwind CSS class.
The class outline-hidden is not a valid Tailwind CSS utility. This should be outline-none.
Apply this fix:
- "text-sidebar-foreground/70 ring-sidebar-ring flex h-8 shrink-0 items-center rounded-md px-2 text-xs font-medium outline-hidden transition-[margin,opacity] duration-200 ease-linear focus-visible:ring-2 [&>svg]:size-4 [&>svg]:shrink-0",
+ "text-sidebar-foreground/70 ring-sidebar-ring flex h-8 shrink-0 items-center rounded-md px-2 text-xs font-medium outline-none transition-[margin,opacity] duration-200 ease-linear focus-visible:ring-2 [&>svg]:size-4 [&>svg]:shrink-0",📝 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.
| "text-sidebar-foreground/70 ring-sidebar-ring flex h-8 shrink-0 items-center rounded-md px-2 text-xs font-medium outline-hidden transition-[margin,opacity] duration-200 ease-linear focus-visible:ring-2 [&>svg]:size-4 [&>svg]:shrink-0", | |
| "text-sidebar-foreground/70 ring-sidebar-ring flex h-8 shrink-0 items-center rounded-md px-2 text-xs font-medium outline-none transition-[margin,opacity] duration-200 ease-linear focus-visible:ring-2 [&>svg]:size-4 [&>svg]:shrink-0", |
🤖 Prompt for AI Agents
In ui/components/ui/sidebar.tsx at line 408, replace the invalid Tailwind CSS
class "outline-hidden" with the correct class "outline-none" to fix the styling
issue.
| data-size={size} | ||
| data-active={isActive} | ||
| className={cn( | ||
| "text-sidebar-foreground ring-sidebar-ring hover:bg-sidebar-accent hover:text-sidebar-accent-foreground active:bg-sidebar-accent active:text-sidebar-accent-foreground [&>svg]:text-sidebar-accent-foreground flex h-7 min-w-0 -translate-x-px items-center gap-2 overflow-hidden rounded-md px-2 outline-hidden focus-visible:ring-2 disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50 [&>span:last-child]:truncate [&>svg]:size-4 [&>svg]:shrink-0", |
There was a problem hiding this comment.
Fix invalid Tailwind CSS class.
The class outline-hidden is not a valid Tailwind CSS utility. This should be outline-none.
Apply this fix:
- "text-sidebar-foreground ring-sidebar-ring hover:bg-sidebar-accent hover:text-sidebar-accent-foreground active:bg-sidebar-accent active:text-sidebar-accent-foreground [&>svg]:text-sidebar-accent-foreground flex h-7 min-w-0 -translate-x-px items-center gap-2 overflow-hidden rounded-md px-2 outline-hidden focus-visible:ring-2 disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50 [&>span:last-child]:truncate [&>svg]:size-4 [&>svg]:shrink-0",
+ "text-sidebar-foreground ring-sidebar-ring hover:bg-sidebar-accent hover:text-sidebar-accent-foreground active:bg-sidebar-accent active:text-sidebar-accent-foreground [&>svg]:text-sidebar-accent-foreground flex h-7 min-w-0 -translate-x-px items-center gap-2 overflow-hidden rounded-md px-2 outline-none focus-visible:ring-2 disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50 [&>span:last-child]:truncate [&>svg]:size-4 [&>svg]:shrink-0",📝 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.
| "text-sidebar-foreground ring-sidebar-ring hover:bg-sidebar-accent hover:text-sidebar-accent-foreground active:bg-sidebar-accent active:text-sidebar-accent-foreground [&>svg]:text-sidebar-accent-foreground flex h-7 min-w-0 -translate-x-px items-center gap-2 overflow-hidden rounded-md px-2 outline-hidden focus-visible:ring-2 disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50 [&>span:last-child]:truncate [&>svg]:size-4 [&>svg]:shrink-0", | |
| "text-sidebar-foreground ring-sidebar-ring hover:bg-sidebar-accent hover:text-sidebar-accent-foreground active:bg-sidebar-accent active:text-sidebar-accent-foreground [&>svg]:text-sidebar-accent-foreground flex h-7 min-w-0 -translate-x-px items-center gap-2 overflow-hidden rounded-md px-2 outline-none focus-visible:ring-2 disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50 [&>span:last-child]:truncate [&>svg]:size-4 [&>svg]:shrink-0", |
🤖 Prompt for AI Agents
In ui/components/ui/sidebar.tsx at line 689, replace the invalid Tailwind CSS
class "outline-hidden" with the correct class "outline-none" to ensure proper
styling and avoid build errors.
| export interface FunctionCall { | ||
| name?: string; | ||
| arguments: string; // stringified JSON | ||
| } |
There was a problem hiding this comment.
🧹 Nitpick (assertive)
Consider adding type safety utilities for JSON arguments.
The arguments field is typed as a string containing stringified JSON, which requires manual parsing and can be error-prone. Consider adding utility types or helper functions to safely parse and validate these JSON strings.
Example utility approach:
// Helper type for parsed arguments
export type ParsedFunctionCall<T = unknown> = Omit<FunctionCall, 'arguments'> & {
arguments: T;
rawArguments: string;
};
// Utility function
export function parseFunctionCall<T = unknown>(call: FunctionCall): ParsedFunctionCall<T> {
try {
return {
...call,
arguments: JSON.parse(call.arguments) as T,
rawArguments: call.arguments
};
} catch (error) {
throw new Error(`Failed to parse function arguments: ${error.message}`);
}
}🤖 Prompt for AI Agents
In ui/lib/types/logs.ts around lines 48 to 51, the FunctionCall interface
defines the arguments field as a string containing stringified JSON, which is
error-prone and requires manual parsing. To improve type safety, create a
utility type ParsedFunctionCall that replaces the string arguments with a
generic typed arguments field and includes the raw string as rawArguments. Also,
implement a parseFunctionCall function that takes a FunctionCall, safely parses
the JSON string in arguments, and returns a ParsedFunctionCall with typed
arguments, throwing a descriptive error if parsing fails.
c522aad to
3c07f75
Compare
1f4a34b to
df1c9b7
Compare
There was a problem hiding this comment.
Bug: Stdio Config Handling Fails on Undefined Values
The getConnectionDisplay function's handling of stdio connections is buggy. If client.config.stdio_config is undefined, attempting to call .join() on stdio_config?.args results in a runtime error. Furthermore, if client.config.stdio_config.command is undefined, the output string will incorrectly include "undefined " and prevent the || "STDIO" fallback from being applied.
ui/components/config/mcp-clients-lists.tsx#L81-L82
bifrost/ui/components/config/mcp-clients-lists.tsx
Lines 81 to 82 in df1c9b7
BugBot free trial expires on July 22, 2025
You have used $0.00 of your $50.00 spend limit so far. Manage your spend limit in the Cursor dashboard.
Was this report helpful? Give feedback by reacting with 👍 or 👎
There was a problem hiding this comment.
Actionable comments posted: 13
🔭 Outside diff range comments (1)
ui/README.md (1)
1-37: Consider adding Bifrost-specific context to the README.While the standard Next.js template information is helpful, the README would be more valuable with specific information about the Bifrost UI's purpose, how it integrates with the backend, and any Bifrost-specific development considerations.
Consider adding sections like:
- Brief description of the Bifrost UI's role in the system
- How it connects to the Bifrost backend
- Any specific build or deployment considerations for the embedded UI
- Links to related documentation
♻️ Duplicate comments (90)
ui/.prettierrc (1)
5-5: Fix deprecated Prettier option to prevent build failures.The
jsxBracketSameLineoption was deprecated in Prettier 3 and will cause "Unknown option" errors in CI/CD pipelines.ui/postcss.config.mjs (1)
1-5: Fix incorrect plugin name to prevent build failures.The
@tailwindcss/postcssplugin doesn't exist and will cause the build to fail. The correct plugin name istailwindcss.ui/lib/utils.ts (1)
1-6: Fix incorrect clsx import to prevent runtime errors.The
clsximport is incorrect - it's a default export, not a named export. This will causeclsxto be undefined at runtime, breaking the utility function.ui/components/theme-provider.tsx (1)
6-8: Consider exposing sane defaults instead of a raw passthrough.The wrapper currently just forwards everything to
NextThemesProviderwithout adding value. Setting sensible defaults likeattribute="class",enableSystem, anddefaultTheme="system"would reduce duplication and configuration mistakes.ui/components/ui/aspect-ratio.tsx (1)
5-7: Forward therefto stay Radix-compliant.Radix primitives rely on refs for focus management and measurements. The current implementation doesn't forward refs, which breaks Radix compliance. Wrap the component with
React.forwardRefto ensure proper ref propagation.ui/components/progress-bar.tsx (1)
5-5: Missing React import for type annotation.
React.ReactNodeis used but React is not imported. Add a type-only import at the top of the file:import type React from "react";to ensure the React namespace is defined for type annotations.ui/lib/constants/icons.tsx (1)
3-12: Export the key union to avoid stringly-typed consumers.Down-stream code is forced to repeat the provider key strings, losing autocomplete & type-safety. Re-export
type ProviderName = keyof typeof ProviderIconsso callers can rely on a single source of truth.ui/components.json (1)
6-8: Provide explicit Tailwind config path to prevent CLI lookup failures.
"config": ""makesshadcn/ui& Tailwind helpers hunt fortailwind.config.{js,ts}in the CWD, which breaks when commands run from repo root or CI. Point to the actual file, e.g."config": "ui/tailwind.config.ts".ui/hooks/use-mobile.ts (2)
6-6: Initialundefinedcauses layout shift on hydration.During SSR
isMobileisundefined, which coerces tofalselater. This flips the rendered tree once the effect runs, triggering a layout shift. Initialise with a boolean or lazy-init usingwindowguard.
18-18: Redundant double negation.
isMobileis already boolean after the first render;!!is unnecessary.ui/components/header.tsx (1)
6-6: Invalid Tailwind syntax — replace with inline style or custom class.
left-(--sidebar-width)is not recognised by Tailwind; it will be stripped at build time, positioning the header incorrectly.- <div className="bg-background fixed top-0 right-0 left-(--sidebar-width) z-10"> + <div + className="bg-background fixed top-0 right-0 z-10" + style={{ left: "var(--sidebar-width)" }} + >ui/components/logs/ui/code-editor.css (1)
1-16: Consider a more maintainable approach to Monaco editor styling.The transparent background styling achieves the desired integration effect, but the multiple
!importantdeclarations could make future maintenance challenging.ui/README.md (1)
1-1: Add a top-level heading for better markdown structure.The file should start with a top-level heading to improve markdown structure and readability.
ui/lib/constants/config.ts (1)
14-18: Consider using CSS custom properties for theme consistency.The MCP_STATUS_COLORS uses hardcoded Tailwind classes which may not adapt well to different themes, particularly dark mode.
The previous review comment about using CSS custom properties or dark mode variants is still applicable here.
ui/app/layout.tsx (1)
35-35: Consider using max-width instead of fixed width for better responsiveness.The
w-5xlclass sets a fixed width which may cause layout issues on smaller screens.The previous review comment about using
max-w-5xlinstead ofw-5xland adding horizontal padding is still applicable.ui/hooks/use-toast.ts (2)
10-11: Improve message formatting for better UX.The current message concatenation logic could be enhanced to handle edge cases and provide better formatting.
The previous review comment about using newlines instead of colons for better message formatting is still applicable.
13-17: Consider adding neutral toast variant for better semantic accuracy.The current implementation defaults to success toast for "default" variant, which might not be semantically correct for informational messages.
The previous review comment about explicitly handling neutral variants is still applicable.
ui/components/ui/progress.tsx (1)
18-18: Value validation still needed for transform calculation.The transform calculation continues to use the
valueprop without validation, which can cause rendering issues if the value is outside the 0-100 range.ui/components/logs/ui/log-message-view.tsx (2)
8-15: Performance optimization for JSON validation still needed.The
isJsonfunction continues to parse JSON on every render, which can be expensive for large strings.
17-23: Type safety improvement for cleanJson function still needed.The
cleanJsonfunction still usesanytype parameter, reducing type safety.ui/app/plugins/page.tsx (4)
106-110: Add security attributes to external linksExternal links with
target="_blank"should includerel="noopener noreferrer"to prevent potential security vulnerabilities through window.opener access.
150-160: Add security attributes to external linksExternal links with
target="_blank"should includerel="noopener noreferrer"to prevent potential security vulnerabilities through window.opener access.
182-186: Add security attributes to documentation linksThese external links also need the security attributes for consistency and safety.
203-207: Add security attributes to documentation linksThese external links also need the security attributes for consistency and safety.
ui/components/ui/separator.tsx (1)
32-41: Simplify the conditional className logic.The conditional className logic in DottedSeparator can be simplified since the
cnutility already handles undefined values gracefully.ui/components/ui/scroll-area.tsx (1)
8-21: ScrollBar orientation is not configurable.The ScrollBar is rendered with default vertical orientation. Consider making it configurable if horizontal scrolling support is needed.
ui/components/ui/input.tsx (1)
7-25: LGTM! The forwardRef implementation is correctly in place.The Input component is well-implemented with React.forwardRef, comprehensive styling, and proper TypeScript typing. The past review comment about adding forwardRef for form library integration has been addressed.
ui/components/sidebar.tsx (1)
171-171: Fix JSX self-closing element.The animated dot div should be self-closing as it has no children.
Apply this diff to fix the JSX formatting:
- <div className="h-2 w-2 animate-pulse rounded-full bg-green-500"></div> + <div className="h-2 w-2 animate-pulse rounded-full bg-green-500" />ui/components/logs/filters.tsx (1)
25-52: Refactor duplicate filterKeyMap for better maintainability.The
filterKeyMapobject is duplicated in bothhandleFilterSelectandisSelectedfunctions. Extract this to a constant at the module level to eliminate duplication.+const FILTER_KEY_MAP: Record<keyof typeof FILTER_OPTIONS, keyof LogFilters> = { + Status: "status", + Providers: "providers", + Type: "objects", +}; + export function LogFilters({ filters, onFiltersChange }: LogFiltersProps) { const [open, setOpen] = useState(false); const handleFilterSelect = (category: keyof typeof FILTER_OPTIONS, value: string) => { - const filterKeyMap: Record<keyof typeof FILTER_OPTIONS, keyof LogFilters> = { - Status: "status", - Providers: "providers", - Type: "objects", - }; - - const filterKey = filterKeyMap[category]; + const filterKey = FILTER_KEY_MAP[category]; const currentValues = (filters[filterKey] as string[]) || []; const newValues = currentValues.includes(value) ? currentValues.filter((v) => v !== value) : [...currentValues, value]; @@ -40,13 +35,7 @@ export function LogFilters({ filters, onFiltersChange }: LogFiltersProps) { }; const isSelected = (category: string, value: string) => { - const filterKeyMap: Record<string, keyof LogFilters> = { - Status: "status", - Providers: "providers", - Type: "objects", - }; - - const filterKey = filterKeyMap[category]; + const filterKey = FILTER_KEY_MAP[category]; const currentValues = filters[filterKey]; return Array.isArray(currentValues) && currentValues.includes(value); };ui/components/ui/hover-card.tsx (1)
28-31: Fix CSS variable syntax.The CSS class contains invalid syntax for a CSS variable reference.
ui/components/logs/columns.tsx (1)
95-96: Simplify type assertions for better readability.The type assertions here are quite verbose and could be made more readable by extracting the object type.
+ const objectType = row.original.object as keyof typeof REQUEST_TYPE_COLORS; return ( - <Badge variant="outline" className={`${REQUEST_TYPE_COLORS[row.original.object as keyof typeof REQUEST_TYPE_COLORS]} text-xs`}> - {REQUEST_TYPE_LABELS[row.original.object as keyof typeof REQUEST_TYPE_LABELS]} + <Badge variant="outline" className={`${REQUEST_TYPE_COLORS[objectType] || ""} text-xs`}> + {REQUEST_TYPE_LABELS[objectType] || row.original.object} </Badge> );ui/components/ui/form-field.tsx (1)
25-35: Consider controlled vs uncontrolled input pattern.The component maintains internal state for
valuebut also accepts an externalvalueprop. This can lead to synchronization issues.ui/hooks/useWebSocket.ts (2)
8-12: Remove unnecessary process declaration.In a Next.js environment,
processis already available globally and this declaration is redundant.
20-26: WebSocket URL should be configurable for production deployments.The WebSocket URL is hardcoded to
localhost, which won't work when the UI is deployed separately from the backend server.ui/app/docs/page.tsx (2)
8-53: Add TypeScript interface for documentation sections.The
docSectionsarray would benefit from explicit type definitions for better type safety and IntelliSense support.Add this type definition before the array:
interface DocSection { title: string; description: string; icon: React.ComponentType<{ className?: string }>; url: string; badge?: string; items: string[]; } const docSections: DocSection[] = [ // ... existing sections ];
73-73: Addrel="noopener noreferrer"to external links for security.External links with
target="_blank"should includerel="noopener noreferrer"to prevent potential security vulnerabilities.Apply this pattern to all external links:
- href="https://github.com/maximhq/bifrost/tree/main/docs" - target="_blank" + href="https://github.com/maximhq/bifrost/tree/main/docs" + target="_blank" + rel="noopener noreferrer"Also applies to: 79-79, 119-119, 145-145, 166-166
ui/components/ui/popover.tsx (1)
33-33: Fix CSS custom property syntax in className.The origin property appears to have incorrect syntax for a CSS custom property.
- "bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 w-72 origin-(--radix-popover-content-transform-origin) rounded-md border p-4 shadow-md outline-hidden", + "bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 w-72 origin-[var(--radix-popover-content-transform-origin)] rounded-md border p-4 shadow-md outline-hidden",ui/eslint.config.mjs (1)
9-12: Fix__dirnameusage in ES module context.
__dirnameis not available in ES modules. You need to derive it fromimport.meta.url.Add these imports and derive
__dirname:+import { dirname } from "node:path"; +import { fileURLToPath } from "node:url"; + +const __dirname = dirname(fileURLToPath(import.meta.url)); const compat = new FlatCompat({ baseDirectory: __dirname, recommendedConfig: js.configs.recommended, });Also applies to: 29-29
ui/components/config/mcp-clients-lists.tsx (1)
82-82: Fix string concatenation with template literal.The string concatenation should use a template literal for better readability and performance.
- return client.config.stdio_config?.command + " " + client.config.stdio_config?.args.join(" ") || "STDIO"; + return `${client.config.stdio_config?.command} ${client.config.stdio_config?.args.join(" ")}` || "STDIO";ui/components/config/meta-config-renderer.tsx (3)
84-84: Replaceanytype with a more specific type.Using
anydefeats TypeScript's type safety benefits.- // eslint-disable-next-line @typescript-eslint/no-explicit-any - onMetaConfigChange: (key: keyof MetaConfig, value: any) => void; + onMetaConfigChange: (key: keyof MetaConfig, value: MetaConfig[keyof MetaConfig]) => void;
156-156: Fix accessibility issue: Associate label with form input.The label element is not properly associated with its input/textarea, which impacts accessibility.
- <label className="block text-sm font-medium">{field.label}</label> + <label + htmlFor={`meta-${field.name}`} + className="block text-sm font-medium" + > + {field.label} + </label>Then update the
renderFieldfunction to add the correspondingidto both Input and Textarea components.
106-113: Provide user feedback for JSON parsing errors.Currently, JSON parsing errors are silently ignored, which could confuse users when their input doesn't save as expected.
Consider adding error feedback:
onBlur={(e) => { if (field.isJson) { try { const parsed = JSON.parse(e.target.value); onMetaConfigChange(field.name, parsed); } catch (error) { // You could add a validation state or show a toast console.error(`Invalid JSON for ${field.label}:`, error); // Optionally, you could pass an error handler prop: // onJsonError?.(field.name, error); } } }}ui/components/logs/logs-table.tsx (2)
78-78: Use Number.parseInt for consistency with ES2015 standards.
156-170: Remove commented-out code to improve maintainability.The commented-out code blocks should be removed if they're not needed. If these features are planned for the future, consider tracking them in issues instead.
ui/components/ui/tooltip.tsx (2)
31-31: Fix the CSS custom property syntax.The transform-origin class has incorrect syntax for referencing a CSS variable.
-"bg-primary text-primary-foreground animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 w-fit origin-(--radix-tooltip-content-transform-origin) rounded-md px-3 py-1.5 text-xs text-balance", +"bg-primary text-primary-foreground animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 w-fit origin-[var(--radix-tooltip-content-transform-origin)] rounded-md px-3 py-1.5 text-xs text-balance",
12-18: Consider removing the nested TooltipProvider to improve performance.The current implementation creates a new
TooltipProviderfor eachTooltipinstance, which is inefficient. The standard pattern is to have a singleTooltipProviderat the application root level.ui/components/logs/ui/log-entry-details-view.tsx (2)
22-26: Fix inconsistent class name application pattern.The conditional class name application mixes different patterns - some use template literals while others use object notation. This should be consistent.
-className={cn("items-top flex flex-col gap-2", { - [`${props.className}`]: props.className !== undefined, - "items-start": props.align === "left" || props.align === undefined, - "items-end": props.align === "right", -})} +className={cn("items-top flex flex-col gap-2", { + "items-start": props.align === "left" || props.align === undefined, + "items-end": props.align === "right", +}, props.className)}
35-40: Fix orientation logic and class name consistency.The orientation logic appears backwards - "horizontal" applies
flex-col(vertical layout) and "vertical" appliesflex-row(horizontal layout). Also, maintain consistent class name application pattern.-className={cn("text-md flex text-xs font-medium whitespace-nowrap transition-transform delay-75", { - "w-full flex-col items-center gap-2": orientation === "horizontal", - "flex-row items-start gap-2": orientation === "vertical", - [`${props.valueClassName}`]: props.valueClassName !== undefined, - "text-end": props.align === "right", -})} +className={cn("text-md flex text-xs font-medium whitespace-nowrap transition-transform delay-75", { + "w-full flex-row items-center gap-2": orientation === "horizontal", + "flex-col items-start gap-2": orientation === "vertical", + "text-end": props.align === "right", +}, props.valueClassName)}transports/bifrost-http/main.go (1)
119-143: CORS middleware implementation looks solidThe middleware properly handles localhost origins for development, sets comprehensive CORS headers, and correctly handles preflight OPTIONS requests. The implementation supports both HTTP and HTTPS schemes and any port, which is appropriate for local development scenarios.
ui/components/ui/accordion.tsx (1)
39-39: Verify custom accordion animations are definedThe component references custom animation classes
animate-accordion-upandanimate-accordion-downthat may not be defined in your Tailwind configuration.#!/bin/bash # Description: Check for accordion animations in Tailwind config and CSS files # Expected: Find animation definitions or Tailwind plugin configuration # Search for Tailwind config files fd 'tailwind.config.*' -t f --exec cat {} \; | rg -A5 -B5 "accordion|animate" # Search for CSS animation definitions rg -A5 -B5 "@keyframes.*accordion" --type css # Search for animation plugin usage rg -A3 -B3 "tailwindcss-animate|accordion.*animation" --glob "*.js" --glob "*.ts" --glob "*.json"ui/components/logs/empty-state.tsx (2)
127-130: Add error handling for clipboard operationsThe clipboard API can fail due to permissions or browser compatibility issues.
Apply this diff to add error handling:
- const copyToClipboard = () => { - navigator.clipboard.writeText(code); - toast.success("Copied to clipboard"); - }; + const copyToClipboard = async () => { + try { + await navigator.clipboard.writeText(code); + toast.success("Copied to clipboard"); + } catch (error) { + toast.error("Failed to copy to clipboard"); + } + };
204-217: Add missing key props for React iterablesThe mapped elements are missing required key properties, which can cause React rendering issues.
Apply this diff to add proper keys:
- {CARDS.map((card) => ( - <Card className="p-6"> + {CARDS.map((card, index) => ( + <Card key={index} className="p-6"> <h3 className="text-lg font-semibold">{card.title}</h3> <p className="text-muted-foreground">{card.description}</p> <ul className="text-muted-foreground space-y-3"> - {card.features.map((feature) => ( - <li className="flex items-start gap-2"> + {card.features.map((feature, featureIndex) => ( + <li key={featureIndex} className="flex items-start gap-2"> <ArrowRight className="mt-0.5 h-5 w-5 shrink-0" /> <span>{feature}</span> </li>ui/components/ui/table.tsx (1)
42-42: Consider making whitespace handling configurableBoth
TableHeadandTableCellcomponents hardcodewhitespace-nowrap, which prevents text wrapping and could cause horizontal scrolling issues with long content.Consider making whitespace handling optional through props:
-function TableHead({ className, ...props }: React.ComponentProps<"th">) { +function TableHead({ className, nowrap = true, ...props }: React.ComponentProps<"th"> & { nowrap?: boolean }) { return ( <th data-slot="table-head" className={cn( - "text-foreground h-10 px-2 text-left align-middle font-medium whitespace-nowrap [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]", + "text-foreground h-10 px-2 text-left align-middle font-medium [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]", + nowrap && "whitespace-nowrap", className, )} {...props} /> ); }Apply similar changes to
TableCell.Also applies to: 54-54
ui/lib/constants/logs.ts (1)
18-27: Add dark mode variants for better theme consistency.The color mappings only use light background colors without dark mode support, which affects theme consistency across light and dark modes.
ui/components/config/mcp-client-form.tsx (3)
80-88: Replace non-null assertion with safer type handling.The non-null assertion on
prev.stdio_config!could cause runtime errors ifstdio_configis undefined.
167-174: Replace non-null assertion with safer type handling.The non-null assertion on
form.stdio_config!could cause runtime errors ifstdio_configis undefined.
160-162: Remove unused error variable initialization.The error variable is declared but never used since validation is handled by the validator.
ui/components/logs/log-detail-sheet.tsx (2)
35-42: Extract hardcoded pricing rates to configuration.The token pricing rates are hardcoded, making them difficult to update when provider pricing changes.
172-173: Add key prop and use optional chaining for safer rendering.The map iteration is missing a required key prop, and the conditional rendering could be improved with optional chaining.
Apply this diff:
<div className="mt-4 w-full text-center text-sm font-medium">Conversation History</div> -{log.input_history && log.input_history.map((message) => <LogMessageView message={message} />)} +{log.input_history?.map((message, index) => <LogMessageView key={index} message={message} />)}ui/components/ui/select.tsx (1)
33-35: Consider extracting complex className stringsThe SelectTrigger has a very long className string that could benefit from being broken down for better readability and maintainability.
ui/components/logs/ui/code-editor.tsx (6)
108-114: Replace non-null assertions with optional chaining for DOM operations.Multiple instances of
getDomNode()!could cause runtime errors. Use optional chaining for safer DOM access.
134-136: Use optional chaining instead of non-null assertions in event handlers.Replace non-null assertions with optional chaining for safer code execution.
143-345: Consider extracting custom completion logic for better maintainability.The custom completion registration logic is complex and could be extracted into separate functions or a custom hook for better testability and reusability.
208-212: Replace non-null assertions with defensive coding in completion providers.Use optional chaining and provide default values to prevent runtime errors.
391-396: Use optional chaining in custom language validation.Replace non-null assertions with optional chaining for safer execution.
461-461: Simplify boolean ternary expressions.Remove unnecessary ternary operators for cleaner code.
Also applies to: 467-467
ui/components/config/provider-form.tsx (4)
339-360: Add keyboard support for provider selectionThe provider selection div has onClick but lacks keyboard accessibility. Screen reader users and keyboard-only users cannot select providers.
298-298: Use Number namespace methods for consistencyReplace global
parseIntandparseFloatwith their Number namespace equivalents for ES2015 consistency.Also applies to: 508-508, 522-522, 559-559, 573-573
412-412: Fix accessibility issues with form labelsMultiple form labels are not properly associated with their inputs, which creates accessibility issues for screen readers.
Also applies to: 439-439, 485-485, 500-500, 514-514, 552-552, 566-566, 593-593, 610-610, 619-619, 627-627
1-675: Consider breaking down this large componentAt 675 lines, this component is quite large and handles multiple responsibilities. Consider extracting sub-components for better maintainability.
ui/lib/api.ts (2)
31-31: Apply optional chaining for cleaner error handling.
160-167: Fix return value for reconnectMCPClient method.ui/components/ui/command.tsx (2)
55-55: Fix invalid Tailwind CSS class
100-100: Fix invalid Tailwind CSS class.ui/lib/utils/validation.ts (2)
63-68: Fix the required validator to accept 0 as a valid value
91-97: Fix static method implementation.ui/components/ui/sidebar.tsx (7)
85-87: Potential SSR issue with document.cookie
408-408: Fix invalid Tailwind CSS class.
429-429: Fix invalid Tailwind CSS class.
477-477: Fix invalid Tailwind CSS class.
564-564: Fix invalid Tailwind CSS class.
609-612: Potential SSR hydration mismatch with random width
689-689: Fix invalid Tailwind CSS class.ui/components/ui/dropdown-menu.tsx (6)
28-28: Fix Tailwind CSS custom property syntax
56-56: Replace non-standardoutline-hiddenwithoutline-none
74-74: Replace non-standardoutline-hiddenwithoutline-none
99-99: Replace non-standardoutline-hiddenwithoutline-none
168-168: Replaceoutline-hiddenwithoutline-none
184-184: Fix Tailwind CSS custom property syntaxui/lib/types/logs.ts (1)
48-51: Consider typed parsing helper forarguments
Same concern was raised earlier: keepingargumentsas a raw JSON string
pushes parsing & validation to every call-site.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro
⛔ Files ignored due to path filters (1)
ui/package-lock.jsonis excluded by!**/package-lock.json
📒 Files selected for processing (82)
docs/contributing/README.md(3 hunks)transports/bifrost-http/main.go(4 hunks)transports/bifrost-http/plugins/logging/main.go(3 hunks)transports/bifrost-http/plugins/logging/utils.go(0 hunks)ui/.gitignore(1 hunks)ui/.prettierrc(1 hunks)ui/README.md(1 hunks)ui/app/config/page.tsx(1 hunks)ui/app/docs/page.tsx(1 hunks)ui/app/globals.css(1 hunks)ui/app/layout.tsx(1 hunks)ui/app/page.tsx(1 hunks)ui/app/plugins/page.tsx(1 hunks)ui/components.json(1 hunks)ui/components/config/core-settings-list.tsx(1 hunks)ui/components/config/mcp-client-form.tsx(1 hunks)ui/components/config/mcp-clients-lists.tsx(1 hunks)ui/components/config/meta-config-renderer.tsx(1 hunks)ui/components/config/provider-form.tsx(1 hunks)ui/components/config/providers-list.tsx(1 hunks)ui/components/full-page-loader.tsx(1 hunks)ui/components/header.tsx(1 hunks)ui/components/logs/columns.tsx(1 hunks)ui/components/logs/empty-state.tsx(1 hunks)ui/components/logs/filters.tsx(1 hunks)ui/components/logs/log-detail-sheet.tsx(1 hunks)ui/components/logs/logs-table.tsx(1 hunks)ui/components/logs/ui/code-editor.css(1 hunks)ui/components/logs/ui/code-editor.tsx(1 hunks)ui/components/logs/ui/log-entry-details-view.tsx(1 hunks)ui/components/logs/ui/log-message-view.tsx(1 hunks)ui/components/progress-bar.tsx(1 hunks)ui/components/sidebar.tsx(1 hunks)ui/components/theme-provider.tsx(1 hunks)ui/components/theme-toggle.tsx(1 hunks)ui/components/ui/accordion.tsx(1 hunks)ui/components/ui/alert-dialog.tsx(1 hunks)ui/components/ui/alert.tsx(1 hunks)ui/components/ui/aspect-ratio.tsx(1 hunks)ui/components/ui/avatar.tsx(1 hunks)ui/components/ui/badge.tsx(1 hunks)ui/components/ui/button.tsx(1 hunks)ui/components/ui/card.tsx(1 hunks)ui/components/ui/collapsible.tsx(1 hunks)ui/components/ui/command.tsx(1 hunks)ui/components/ui/dialog.tsx(1 hunks)ui/components/ui/dropdown-menu.tsx(1 hunks)ui/components/ui/form-field.tsx(1 hunks)ui/components/ui/hover-card.tsx(1 hunks)ui/components/ui/input.tsx(1 hunks)ui/components/ui/label.tsx(1 hunks)ui/components/ui/popover.tsx(1 hunks)ui/components/ui/progress.tsx(1 hunks)ui/components/ui/scroll-area.tsx(1 hunks)ui/components/ui/select.tsx(1 hunks)ui/components/ui/separator.tsx(1 hunks)ui/components/ui/sheet.tsx(1 hunks)ui/components/ui/sidebar.tsx(1 hunks)ui/components/ui/skeleton.tsx(1 hunks)ui/components/ui/switch.tsx(1 hunks)ui/components/ui/table.tsx(1 hunks)ui/components/ui/tabs.tsx(1 hunks)ui/components/ui/tag-input.tsx(1 hunks)ui/components/ui/textarea.tsx(1 hunks)ui/components/ui/tooltip.tsx(1 hunks)ui/eslint.config.mjs(1 hunks)ui/hooks/use-mobile.ts(1 hunks)ui/hooks/use-toast.ts(1 hunks)ui/hooks/useWebSocket.ts(1 hunks)ui/lib/api.ts(1 hunks)ui/lib/constants/config.ts(1 hunks)ui/lib/constants/icons.tsx(1 hunks)ui/lib/constants/logs.ts(1 hunks)ui/lib/types/config.ts(1 hunks)ui/lib/types/logs.ts(1 hunks)ui/lib/types/mcp.ts(1 hunks)ui/lib/utils.ts(1 hunks)ui/lib/utils/validation.ts(1 hunks)ui/next.config.ts(1 hunks)ui/package.json(1 hunks)ui/postcss.config.mjs(1 hunks)ui/tsconfig.json(1 hunks)
💤 Files with no reviewable changes (1)
- transports/bifrost-http/plugins/logging/utils.go
🧰 Additional context used
🧠 Learnings (15)
📓 Common learnings
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#84
File: transports/bifrost-http/main.go:2-2
Timestamp: 2025-06-15T16:05:13.489Z
Learning: For the Bifrost project, HTTP transport integration routers for new providers (like Mistral and Ollama) are implemented in separate PRs from the core provider support, following a focused PR strategy.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#103
File: .github/workflows/transport-dependency-update.yml:30-36
Timestamp: 2025-06-19T16:57:25.177Z
Learning: In the bifrost repository, Pratham-Mishra04 prefers to keep GitHub Actions workflows lean and trusts their controlled tagging process for core releases, avoiding unnecessary validation steps that they consider overkill.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#63
File: transports/bifrost-http/integrations/openai/types.go:89-119
Timestamp: 2025-06-10T11:00:02.875Z
Learning: In the Bifrost OpenAI integration (transports/bifrost-http/integrations/openai/types.go), the convertOpenAIContent function currently only handles the last image URL when multiple images are present in a content array. The user Pratham-Mishra04 has acknowledged this limitation and indicated it's part of a larger architectural issue that will be addressed comprehensively later, rather than with piecemeal fixes.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#54
File: core/schemas/provider.go:148-148
Timestamp: 2025-06-04T03:57:50.981Z
Learning: Breaking changes in the Bifrost codebase are managed by first merging and tagging core schema changes, then updating dependent code references in subsequent steps after the core version is released.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#94
File: core/bifrost.go:823-845
Timestamp: 2025-06-18T15:15:51.323Z
Learning: In the Bifrost project, the team prioritizes maintaining consistent error handling patterns over exposing detailed error context. All errors should be wrapped in the standard `BifrostError` structure rather than creating specific error types or exposing richer error details like exit codes or stderr output.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#103
File: .github/workflows/transport-dependency-update.yml:53-75
Timestamp: 2025-06-20T16:21:18.912Z
Learning: In the bifrost repository's transport dependency update workflow, when updating the core dependency to a new version using `go get`, the go.mod and go.sum files will always change in normal operation, making the safety check for changes more of a defensive programming practice rather than handling a common scenario.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#55
File: core/providers/anthropic.go:358-388
Timestamp: 2025-06-04T05:37:59.699Z
Learning: User Pratham-Mishra04 prefers not to extract small code duplications (around 2 lines) into helper functions, considering the overhead not worth it for such minor repetition.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#102
File: README.md:62-66
Timestamp: 2025-06-19T17:03:03.639Z
Learning: Pratham-Mishra04 prefers using the implicit 'latest' tag for the maximhq/bifrost Docker image rather than pinning to specific versions.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#138
File: docs/usage/go-package/mcp.md:408-412
Timestamp: 2025-07-01T12:40:08.576Z
Learning: Pratham-Mishra04 is okay with keeping bullet list formatting that uses colons after dashes in markdown documentation, even if it triggers linter warnings, preferring functionality over strict formatting rules.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#138
File: transports/README.md:26-28
Timestamp: 2025-07-01T12:45:06.906Z
Learning: Pratham-Mishra04 prefers keeping documentation examples simple and concise, trusting users to handle production-specific considerations like version pinning themselves rather than cluttering examples with additional notes.
ui/README.md (1)
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#94
File: core/bifrost.go:823-845
Timestamp: 2025-06-18T15:15:51.323Z
Learning: In the Bifrost project, the team prioritizes maintaining consistent error handling patterns over exposing detailed error context. All errors should be wrapped in the standard `BifrostError` structure rather than creating specific error types or exposing richer error details like exit codes or stderr output.
ui/components/theme-provider.tsx (1)
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#85
File: core/providers/anthropic.go:150-156
Timestamp: 2025-06-15T16:07:53.140Z
Learning: In the Bifrost codebase, constructor functions are allowed to mutate input ProviderConfig objects in-place (e.g., setting default BaseURL values and trimming trailing slashes). This pattern is acceptable and doesn't need to be flagged as a code review issue.
ui/lib/constants/icons.tsx (1)
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#81
File: tests/core-providers/go.mod:38-38
Timestamp: 2025-06-16T03:54:48.005Z
Learning: The `core-providers-test` module in `tests/core-providers/` is an internal testing module that will never be consumed as a dependency by external projects, so the replace directive pointing to `../../core` is acceptable for local development and testing purposes.
ui/components/logs/columns.tsx (1)
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#85
File: core/providers/anthropic.go:150-156
Timestamp: 2025-06-15T16:07:53.140Z
Learning: In the Bifrost codebase, constructor functions are allowed to mutate input ProviderConfig objects in-place (e.g., setting default BaseURL values and trimming trailing slashes). This pattern is acceptable and doesn't need to be flagged as a code review issue.
ui/app/config/page.tsx (1)
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#85
File: core/providers/anthropic.go:150-156
Timestamp: 2025-06-15T16:07:53.140Z
Learning: In the Bifrost codebase, constructor functions are allowed to mutate input ProviderConfig objects in-place (e.g., setting default BaseURL values and trimming trailing slashes). This pattern is acceptable and doesn't need to be flagged as a code review issue.
ui/hooks/useWebSocket.ts (1)
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#85
File: core/providers/anthropic.go:150-156
Timestamp: 2025-06-15T16:07:53.140Z
Learning: In the Bifrost codebase, constructor functions are allowed to mutate input ProviderConfig objects in-place (e.g., setting default BaseURL values and trimming trailing slashes). This pattern is acceptable and doesn't need to be flagged as a code review issue.
docs/contributing/README.md (2)
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#54
File: core/schemas/provider.go:148-148
Timestamp: 2025-06-04T03:57:50.981Z
Learning: Breaking changes in the Bifrost codebase are managed by first merging and tagging core schema changes, then updating dependent code references in subsequent steps after the core version is released.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#94
File: core/bifrost.go:823-845
Timestamp: 2025-06-18T15:15:51.323Z
Learning: In the Bifrost project, the team prioritizes maintaining consistent error handling patterns over exposing detailed error context. All errors should be wrapped in the standard `BifrostError` structure rather than creating specific error types or exposing richer error details like exit codes or stderr output.
transports/bifrost-http/plugins/logging/main.go (6)
Learnt from: connyay
PR: maximhq/bifrost#92
File: core/providers/utils.go:60-64
Timestamp: 2025-06-17T14:04:21.104Z
Learning: The bifrost codebase uses string alias types (like `type ContextKey string`) for context keys consistently across multiple packages including plugins/maxim/main.go and transports/bifrost-http/tracking/plugin.go. This pattern should be maintained for consistency rather than switching to the canonical struct{} approach.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#79
File: core/bifrost.go:94-103
Timestamp: 2025-06-14T04:06:58.240Z
Learning: In core/bifrost.go, the count parameter in RunPostHooks method is intentionally kept separate from p.executedPreHooks to support circuit breaker plugins that may need to trigger PostHooks for only a subset of executed plugins when detecting failure conditions mid-execution.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#55
File: core/providers/bedrock.go:443-468
Timestamp: 2025-06-04T09:32:15.826Z
Learning: In core/providers/bedrock.go, for tool call result messages (ModelChatMessageRoleTool), the Content field represents the actual tool call output. A tool result message should only be created when msg.Content is non-nil, as there's no semantic meaning to a tool result without output content.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#55
File: core/providers/bedrock.go:750-791
Timestamp: 2025-06-04T06:09:18.600Z
Learning: In the Bedrock provider, tool result messages maintain their original tool role in the input messages. The remapping from tool role to user role only occurs during message preparation for the Bedrock API request in `prepareChatCompletionMessages`, not in the original input. The `extractToolsFromHistory` function operates on unprocessed input messages where tool results retain their tool role.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#54
File: core/schemas/bifrost.go:46-49
Timestamp: 2025-06-04T09:22:18.123Z
Learning: In core/schemas/bifrost.go, the RequestInput struct uses ChatCompletionInput *[]BifrostMessage (pointer-to-slice) rather than []BifrostMessage to properly represent union type semantics. For text completion requests, ChatCompletionInput should be nil to indicate "no chat payload at all", while for chat completion requests it should be non-nil (even if empty slice). This distinguishes between different request types rather than just empty vs non-empty chat messages.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#65
File: transports/bifrost-http/integrations/utils.go:169-173
Timestamp: 2025-06-09T17:33:52.234Z
Learning: The ChatCompletionRequest method in the Bifrost client follows a contract where the result parameter will never be nil if the error parameter is nil. This means when error checking passes (err == nil), the result is guaranteed to be valid and can be safely used without additional nil checks.
ui/components/config/mcp-client-form.tsx (1)
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#131
File: transports/bifrost-http/lib/config.go:35-68
Timestamp: 2025-06-26T07:37:24.385Z
Learning: In the Bifrost project's MCP configuration handling, empty environment variables should be treated as missing/invalid rather than as valid empty values. The current implementation using `os.Getenv(envKey); envValue != ""` to check for non-empty values is the desired behavior.
transports/bifrost-http/main.go (4)
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#103
File: .github/workflows/transport-dependency-update.yml:53-75
Timestamp: 2025-06-20T16:21:18.912Z
Learning: In the bifrost repository's transport dependency update workflow, when updating the core dependency to a new version using `go get`, the go.mod and go.sum files will always change in normal operation, making the safety check for changes more of a defensive programming practice rather than handling a common scenario.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#67
File: transports/bifrost-http/integrations/anthropic/router.go:26-34
Timestamp: 2025-06-10T11:19:29.604Z
Learning: The Generic router in transports/bifrost-http/integrations/utils.go already handles nil pointers from RequestConverter functions. When a RequestConverter returns a nil *schemas.BifrostRequest, the Generic router automatically returns an HTTP 400 error, making additional nil checks in individual router implementations redundant.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#63
File: transports/bifrost-http/integrations/openai/router.go:0-0
Timestamp: 2025-06-09T14:03:34.227Z
Learning: In the Bifrost HTTP transport layer (transports/bifrost-http/integrations/), request validation like checking for empty messages should be handled by the provider rather than at the transport layer. The transport layer should forward requests to Bifrost core/providers for validation.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#131
File: transports/bifrost-http/lib/config.go:35-68
Timestamp: 2025-06-26T07:37:24.385Z
Learning: In the Bifrost project's MCP configuration handling, empty environment variables should be treated as missing/invalid rather than as valid empty values. The current implementation using `os.Getenv(envKey); envValue != ""` to check for non-empty values is the desired behavior.
ui/lib/types/mcp.ts (1)
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#100
File: core/mcp.go:489-490
Timestamp: 2025-06-19T12:38:07.544Z
Learning: In the Bifrost MCP manager (core/mcp.go), the connectToMCPClient method is called during initialization/connection setup, not frequently during runtime. Logging operations like m.logger.Info inside critical sections in this context have negligible performance impact and don't require optimization for lock contention.
ui/components/logs/ui/code-editor.tsx (1)
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#85
File: core/providers/anthropic.go:150-156
Timestamp: 2025-06-15T16:07:53.140Z
Learning: In the Bifrost codebase, constructor functions are allowed to mutate input ProviderConfig objects in-place (e.g., setting default BaseURL values and trimming trailing slashes). This pattern is acceptable and doesn't need to be flagged as a code review issue.
ui/components/config/provider-form.tsx (1)
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#85
File: core/providers/anthropic.go:150-156
Timestamp: 2025-06-15T16:07:53.140Z
Learning: In the Bifrost codebase, constructor functions are allowed to mutate input ProviderConfig objects in-place (e.g., setting default BaseURL values and trimming trailing slashes). This pattern is acceptable and doesn't need to be flagged as a code review issue.
ui/lib/types/logs.ts (2)
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#64
File: transports/bifrost-http/integrations/genai/types.go:383-395
Timestamp: 2025-06-09T16:26:05.777Z
Learning: In the Bifrost schema (core/schemas/bifrost.go), only UserMessage and ToolMessage structs have ImageContent fields. AssistantMessage does not have an ImageContent field and cannot contain images. The schema design intentionally limits image content to user and tool messages only.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#80
File: plugins/maxim/main.go:249-264
Timestamp: 2025-06-14T06:17:54.426Z
Learning: In the BifrostError struct, the Error field is a struct (not a pointer), so accessing bifrostErr.Error.Message, bifrostErr.Error.Code, and bifrostErr.Error.Type is safe without nil checks on the Error field itself. The Code and Type fields are of type *string.
🧬 Code Graph Analysis (41)
ui/components/ui/textarea.tsx (1)
ui/lib/utils.ts (1)
cn(4-6)
ui/app/layout.tsx (2)
ui/components/theme-provider.tsx (1)
ThemeProvider(6-8)ui/components/ui/sidebar.tsx (2)
SidebarProvider(721-721)Sidebar(702-702)
ui/components/ui/skeleton.tsx (1)
ui/lib/utils.ts (1)
cn(4-6)
ui/components/ui/label.tsx (1)
ui/lib/utils.ts (1)
cn(4-6)
ui/components/ui/progress.tsx (1)
ui/lib/utils.ts (1)
cn(4-6)
ui/components/ui/switch.tsx (1)
ui/lib/utils.ts (1)
cn(4-6)
ui/components/theme-toggle.tsx (2)
ui/components/ui/dropdown-menu.tsx (4)
DropdownMenu(193-193)DropdownMenuTrigger(195-195)DropdownMenuContent(196-196)DropdownMenuItem(199-199)ui/components/ui/button.tsx (1)
Button(71-71)
ui/components/ui/input.tsx (1)
ui/lib/utils.ts (1)
cn(4-6)
ui/components/ui/alert.tsx (1)
ui/lib/utils.ts (1)
cn(4-6)
ui/components/ui/avatar.tsx (1)
ui/lib/utils.ts (1)
cn(4-6)
ui/components/ui/form-field.tsx (5)
ui/lib/utils/validation.ts (2)
ValidationConfig(8-11)validateField(19-27)ui/lib/utils.ts (1)
cn(4-6)ui/components/ui/label.tsx (1)
Label(24-24)ui/components/ui/tooltip.tsx (4)
TooltipProvider(43-43)Tooltip(43-43)TooltipTrigger(43-43)TooltipContent(43-43)ui/components/ui/input.tsx (1)
Input(7-22)
ui/components/ui/separator.tsx (1)
ui/lib/utils.ts (1)
cn(4-6)
ui/components/ui/scroll-area.tsx (1)
ui/lib/utils.ts (1)
cn(4-6)
ui/components/ui/popover.tsx (1)
ui/lib/utils.ts (1)
cn(4-6)
ui/components/config/mcp-clients-lists.tsx (9)
ui/lib/types/mcp.ts (1)
MCPClient(20-25)ui/hooks/use-toast.ts (1)
useToast(9-21)ui/lib/api.ts (1)
apiService(200-200)ui/components/ui/card.tsx (3)
CardHeader(50-50)CardTitle(50-50)CardDescription(50-50)ui/components/ui/button.tsx (1)
Button(71-71)ui/components/ui/table.tsx (6)
Table(64-64)TableHeader(64-64)TableRow(64-64)TableHead(64-64)TableBody(64-64)TableCell(64-64)ui/components/ui/badge.tsx (1)
Badge(37-37)ui/lib/constants/config.ts (1)
MCP_STATUS_COLORS(14-18)ui/components/ui/alert-dialog.tsx (9)
AlertDialog(83-83)AlertDialogTrigger(86-86)AlertDialogContent(87-87)AlertDialogHeader(88-88)AlertDialogTitle(90-90)AlertDialogDescription(91-91)AlertDialogFooter(89-89)AlertDialogCancel(93-93)AlertDialogAction(92-92)
ui/components/ui/dialog.tsx (1)
ui/lib/utils.ts (1)
cn(4-6)
ui/components/ui/badge.tsx (1)
ui/lib/utils.ts (1)
cn(4-6)
ui/components/ui/tooltip.tsx (1)
ui/lib/utils.ts (1)
cn(4-6)
ui/components/ui/tag-input.tsx (3)
ui/lib/utils.ts (1)
cn(4-6)ui/components/ui/badge.tsx (1)
Badge(37-37)ui/components/ui/input.tsx (1)
Input(7-22)
ui/components/logs/filters.tsx (7)
ui/lib/types/logs.ts (1)
LogFilters(147-159)ui/lib/constants/logs.ts (3)
STATUSES(3-3)PROVIDERS(1-1)REQUEST_TYPES(5-5)ui/components/ui/input.tsx (1)
Input(7-22)ui/components/ui/popover.tsx (3)
Popover(48-48)PopoverTrigger(48-48)PopoverContent(48-48)ui/components/ui/button.tsx (1)
Button(71-71)ui/components/ui/command.tsx (6)
Command(114-114)CommandInput(114-114)CommandList(114-114)CommandEmpty(114-114)CommandGroup(114-114)CommandItem(114-114)ui/lib/utils.ts (1)
cn(4-6)
ui/app/docs/page.tsx (4)
ui/components/header.tsx (1)
Header(4-14)ui/components/ui/button.tsx (1)
Button(71-71)ui/components/ui/card.tsx (5)
Card(50-50)CardHeader(50-50)CardTitle(50-50)CardDescription(50-50)CardContent(50-50)ui/components/ui/badge.tsx (1)
Badge(37-37)
ui/components/ui/button.tsx (1)
ui/lib/utils.ts (1)
cn(4-6)
ui/components/ui/tabs.tsx (1)
ui/lib/utils.ts (1)
cn(4-6)
ui/components/ui/hover-card.tsx (1)
ui/lib/utils.ts (1)
cn(4-6)
ui/hooks/useWebSocket.ts (2)
transports/bifrost-http/plugins/logging/main.go (1)
LogEntry(46-62)ui/lib/types/logs.ts (1)
LogEntry(129-145)
ui/components/config/core-settings-list.tsx (8)
ui/lib/types/config.ts (1)
CoreConfig(116-120)ui/lib/api.ts (1)
apiService(200-200)ui/components/ui/card.tsx (3)
CardHeader(50-50)CardTitle(50-50)CardDescription(50-50)ui/components/ui/switch.tsx (1)
Switch(29-29)ui/components/ui/separator.tsx (1)
Separator(43-43)ui/components/ui/alert.tsx (2)
Alert(41-41)AlertDescription(41-41)ui/components/ui/input.tsx (1)
Input(7-22)ui/components/ui/textarea.tsx (1)
Textarea(18-18)
ui/components/ui/table.tsx (1)
ui/lib/utils.ts (1)
cn(4-6)
ui/components/ui/card.tsx (1)
ui/lib/utils.ts (1)
cn(4-6)
ui/components/logs/logs-table.tsx (4)
ui/lib/types/logs.ts (3)
LogEntry(129-145)LogFilters(147-159)Pagination(161-166)ui/components/logs/filters.tsx (1)
LogFilters(22-118)ui/components/ui/table.tsx (6)
Table(64-64)TableHeader(64-64)TableRow(64-64)TableHead(64-64)TableBody(64-64)TableCell(64-64)ui/components/ui/button.tsx (1)
Button(71-71)
ui/components/ui/accordion.tsx (1)
ui/lib/utils.ts (1)
cn(4-6)
ui/components/ui/alert-dialog.tsx (2)
ui/lib/utils.ts (1)
cn(4-6)ui/components/ui/button.tsx (1)
buttonVariants(71-71)
ui/components/logs/log-detail-sheet.tsx (8)
ui/lib/types/logs.ts (1)
LogEntry(129-145)ui/components/ui/sheet.tsx (2)
Sheet(90-90)SheetContent(90-90)ui/components/ui/badge.tsx (1)
Badge(37-37)ui/lib/constants/logs.ts (4)
STATUS_COLORS(29-33)PROVIDER_LABELS(7-16)REQUEST_TYPE_COLORS(41-45)REQUEST_TYPE_LABELS(35-39)ui/components/logs/ui/log-entry-details-view.tsx (1)
LogEntryDetailsView(15-47)ui/components/ui/separator.tsx (1)
DottedSeparator(43-43)ui/components/logs/ui/code-editor.tsx (1)
CodeEditor(79-492)ui/components/logs/ui/log-message-view.tsx (1)
LogMessageView(25-61)
transports/bifrost-http/plugins/logging/main.go (2)
plugins/mocker/main.go (2)
Latency(124-128)Usage(137-141)ui/lib/types/logs.ts (1)
BifrostMessage(17-25)
ui/components/config/mcp-client-form.tsx (12)
ui/lib/types/mcp.ts (5)
MCPClient(20-25)MCPStdioConfig(5-9)CreateMCPClientRequest(27-34)MCPConnectionType(1-1)UpdateMCPClientRequest(36-39)ui/hooks/use-toast.ts (1)
useToast(9-21)ui/lib/utils/validation.ts (1)
Validator(42-139)ui/lib/api.ts (1)
apiService(200-200)ui/components/ui/dialog.tsx (5)
Dialog(91-91)DialogContent(93-93)DialogHeader(96-96)DialogTitle(99-99)DialogFooter(95-95)ui/components/ui/alert.tsx (2)
Alert(41-41)AlertDescription(41-41)ui/components/ui/label.tsx (1)
Label(24-24)ui/components/ui/input.tsx (1)
Input(7-22)ui/components/ui/select.tsx (5)
Select(137-137)SelectTrigger(145-145)SelectValue(146-146)SelectContent(138-138)SelectItem(140-140)ui/components/ui/tooltip.tsx (4)
TooltipProvider(43-43)Tooltip(43-43)TooltipTrigger(43-43)TooltipContent(43-43)ui/components/ui/textarea.tsx (1)
Textarea(18-18)ui/components/ui/button.tsx (1)
Button(71-71)
ui/components/ui/select.tsx (1)
ui/lib/utils.ts (1)
cn(4-6)
ui/components/logs/ui/code-editor.tsx (1)
ui/lib/utils.ts (1)
cn(4-6)
ui/components/logs/ui/log-entry-details-view.tsx (1)
ui/lib/utils.ts (1)
cn(4-6)
ui/components/ui/sheet.tsx (1)
ui/lib/utils.ts (1)
cn(4-6)
ui/components/ui/dropdown-menu.tsx (1)
ui/lib/utils.ts (1)
cn(4-6)
ui/components/ui/sidebar.tsx (8)
ui/hooks/use-mobile.ts (1)
useIsMobile(5-19)ui/components/ui/tooltip.tsx (4)
TooltipProvider(43-43)TooltipContent(43-43)Tooltip(43-43)TooltipTrigger(43-43)ui/lib/utils.ts (1)
cn(4-6)ui/components/ui/sheet.tsx (5)
Sheet(90-90)SheetContent(90-90)SheetHeader(90-90)SheetTitle(90-90)SheetDescription(90-90)ui/components/ui/button.tsx (1)
Button(71-71)ui/components/ui/input.tsx (1)
Input(7-22)ui/components/ui/separator.tsx (1)
Separator(43-43)ui/components/ui/skeleton.tsx (1)
Skeleton(7-7)
ui/lib/types/logs.ts (2)
transports/bifrost-http/plugins/logging/main.go (2)
LogEntry(46-62)LogStats(100-109)ui/components/logs/filters.tsx (1)
LogFilters(22-118)
🪛 markdownlint-cli2 (0.17.2)
ui/README.md
1-1: First line in a file should be a top-level heading
(MD041, first-line-heading, first-line-h1)
docs/contributing/README.md
134-134: Emphasis used instead of a heading
(MD036, no-emphasis-as-heading)
168-168: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
🪛 Biome (1.9.4)
ui/components/sidebar.tsx
[error] 171-171: JSX elements without children should be marked as self-closing. In JSX, it is valid for any element to be self-closing.
Unsafe fix: Use a SelfClosingElement instead
(lint/style/useSelfClosingElements)
ui/components/config/mcp-clients-lists.tsx
[error] 82-82: Template literals are preferred over string concatenation.
Unsafe fix: Use a template literal.
(lint/style/useTemplate)
ui/components/logs/filters.tsx
[error] 22-22: Shouldn't redeclare 'LogFilters'. Consider to delete it or rename it.
'LogFilters' is defined here:
(lint/suspicious/noRedeclare)
ui/components/config/meta-config-renderer.tsx
[error] 156-156: A form label must be associated with an input.
Consider adding a for or htmlFor attribute to the label element or moving the input element to inside the label element.
(lint/a11y/noLabelWithoutControl)
ui/components/logs/empty-state.tsx
[error] 205-205: Missing key property for this element in iterable.
The order of the items may change, and having a key can help React identify which item was moved.
Check the React documentation.
(lint/correctness/useJsxKeyInIterable)
[error] 210-210: Missing key property for this element in iterable.
The order of the items may change, and having a key can help React identify which item was moved.
Check the React documentation.
(lint/correctness/useJsxKeyInIterable)
ui/components/config/core-settings-list.tsx
[error] 136-136: A form label must be associated with an input.
Consider adding a for or htmlFor attribute to the label element or moving the input element to inside the label element.
(lint/a11y/noLabelWithoutControl)
[error] 157-157: A form label must be associated with an input.
Consider adding a for or htmlFor attribute to the label element or moving the input element to inside the label element.
(lint/a11y/noLabelWithoutControl)
[error] 171-171: A form label must be associated with an input.
Consider adding a for or htmlFor attribute to the label element or moving the input element to inside the label element.
(lint/a11y/noLabelWithoutControl)
[error] 80-80: Use Number.parseInt instead of the equivalent global.
ES2015 moved some globals into the Number namespace for consistency.
Safe fix: Use Number.parseInt instead.
(lint/style/useNumberNamespace)
ui/components/logs/logs-table.tsx
[error] 78-78: Use Number.parseInt instead of the equivalent global.
ES2015 moved some globals into the Number namespace for consistency.
Safe fix: Use Number.parseInt instead.
(lint/style/useNumberNamespace)
ui/components/logs/log-detail-sheet.tsx
[error] 173-173: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
[error] 173-173: Missing key property for this element in iterable.
The order of the items may change, and having a key can help React identify which item was moved.
Check the React documentation.
(lint/correctness/useJsxKeyInIterable)
ui/components/config/mcp-client-form.tsx
[error] 84-84: Forbidden non-null assertion.
(lint/style/noNonNullAssertion)
[error] 170-170: Forbidden non-null assertion.
(lint/style/noNonNullAssertion)
ui/components/logs/ui/code-editor.tsx
[error] 111-111: Forbidden non-null assertion.
Unsafe fix: Replace with optional chain operator ?. This operator includes runtime checks, so it is safer than the compile-only non-null assertion operator
(lint/style/noNonNullAssertion)
[error] 136-136: Forbidden non-null assertion.
Unsafe fix: Replace with optional chain operator ?. This operator includes runtime checks, so it is safer than the compile-only non-null assertion operator
(lint/style/noNonNullAssertion)
[error] 210-211: Forbidden non-null assertion.
Unsafe fix: Replace with optional chain operator ?. This operator includes runtime checks, so it is safer than the compile-only non-null assertion operator
(lint/style/noNonNullAssertion)
[error] 269-269: Forbidden non-null assertion.
Unsafe fix: Replace with optional chain operator ?. This operator includes runtime checks, so it is safer than the compile-only non-null assertion operator
(lint/style/noNonNullAssertion)
[error] 362-362: Forbidden non-null assertion.
Unsafe fix: Replace with optional chain operator ?. This operator includes runtime checks, so it is safer than the compile-only non-null assertion operator
(lint/style/noNonNullAssertion)
[error] 380-380: Forbidden non-null assertion.
Unsafe fix: Replace with optional chain operator ?. This operator includes runtime checks, so it is safer than the compile-only non-null assertion operator
(lint/style/noNonNullAssertion)
[error] 394-394: Forbidden non-null assertion.
Unsafe fix: Replace with optional chain operator ?. This operator includes runtime checks, so it is safer than the compile-only non-null assertion operator
(lint/style/noNonNullAssertion)
[error] 395-395: Forbidden non-null assertion.
Unsafe fix: Replace with optional chain operator ?. This operator includes runtime checks, so it is safer than the compile-only non-null assertion operator
(lint/style/noNonNullAssertion)
[error] 409-409: Forbidden non-null assertion.
Unsafe fix: Replace with optional chain operator ?. This operator includes runtime checks, so it is safer than the compile-only non-null assertion operator
(lint/style/noNonNullAssertion)
[error] 461-461: Unnecessary use of boolean literals in conditional expression.
Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with
(lint/complexity/noUselessTernary)
[error] 467-467: Unnecessary use of boolean literals in conditional expression.
Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with
(lint/complexity/noUselessTernary)
ui/components/config/provider-form.tsx
[error] 339-355: Enforce to have the onClick mouse event with the onKeyUp, the onKeyDown, or the onKeyPress keyboard event.
Actions triggered using mouse events should have corresponding keyboard events to account for keyboard-only navigation.
(lint/a11y/useKeyWithClickEvents)
[error] 412-412: A form label must be associated with an input.
Consider adding a for or htmlFor attribute to the label element or moving the input element to inside the label element.
(lint/a11y/noLabelWithoutControl)
[error] 439-439: A form label must be associated with an input.
Consider adding a for or htmlFor attribute to the label element or moving the input element to inside the label element.
(lint/a11y/noLabelWithoutControl)
[error] 485-485: A form label must be associated with an input.
Consider adding a for or htmlFor attribute to the label element or moving the input element to inside the label element.
(lint/a11y/noLabelWithoutControl)
[error] 500-500: A form label must be associated with an input.
Consider adding a for or htmlFor attribute to the label element or moving the input element to inside the label element.
(lint/a11y/noLabelWithoutControl)
[error] 514-514: A form label must be associated with an input.
Consider adding a for or htmlFor attribute to the label element or moving the input element to inside the label element.
(lint/a11y/noLabelWithoutControl)
[error] 552-552: A form label must be associated with an input.
Consider adding a for or htmlFor attribute to the label element or moving the input element to inside the label element.
(lint/a11y/noLabelWithoutControl)
[error] 566-566: A form label must be associated with an input.
Consider adding a for or htmlFor attribute to the label element or moving the input element to inside the label element.
(lint/a11y/noLabelWithoutControl)
[error] 593-593: A form label must be associated with an input.
Consider adding a for or htmlFor attribute to the label element or moving the input element to inside the label element.
(lint/a11y/noLabelWithoutControl)
[error] 610-610: A form label must be associated with an input.
Consider adding a for or htmlFor attribute to the label element or moving the input element to inside the label element.
(lint/a11y/noLabelWithoutControl)
[error] 619-619: A form label must be associated with an input.
Consider adding a for or htmlFor attribute to the label element or moving the input element to inside the label element.
(lint/a11y/noLabelWithoutControl)
[error] 627-627: A form label must be associated with an input.
Consider adding a for or htmlFor attribute to the label element or moving the input element to inside the label element.
(lint/a11y/noLabelWithoutControl)
[error] 298-298: Use Number.parseFloat instead of the equivalent global.
ES2015 moved some globals into the Number namespace for consistency.
Safe fix: Use Number.parseFloat instead.
(lint/style/useNumberNamespace)
[error] 508-508: Use Number.parseInt instead of the equivalent global.
ES2015 moved some globals into the Number namespace for consistency.
Safe fix: Use Number.parseInt instead.
(lint/style/useNumberNamespace)
[error] 522-522: Use Number.parseInt instead of the equivalent global.
ES2015 moved some globals into the Number namespace for consistency.
Safe fix: Use Number.parseInt instead.
(lint/style/useNumberNamespace)
[error] 559-559: Use Number.parseInt instead of the equivalent global.
ES2015 moved some globals into the Number namespace for consistency.
Safe fix: Use Number.parseInt instead.
(lint/style/useNumberNamespace)
[error] 573-573: Use Number.parseInt instead of the equivalent global.
ES2015 moved some globals into the Number namespace for consistency.
Safe fix: Use Number.parseInt instead.
(lint/style/useNumberNamespace)
ui/lib/api.ts
[error] 31-31: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
ui/lib/utils/validation.ts
[error] 92-92: Using this in a static context can be confusing.
this refers to the class.
Unsafe fix: Use the class name instead.
(lint/complexity/noThisInStatic)
[error] 96-96: Using this in a static context can be confusing.
this refers to the class.
Unsafe fix: Use the class name instead.
(lint/complexity/noThisInStatic)
🪛 LanguageTool
docs/contributing/README.md
[typographical] ~58-~58: If specifying a range, consider using an en dash instead of a hyphen.
Context: ...UI Development** | Variable | 1-2 hours | [UI Guide →](#-ui-devel...
(HYPHEN_TO_EN)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: Graphite / mergeability_check
- GitHub Check: Graphite / mergeability_check
🔇 Additional comments (48)
ui/.gitignore (1)
1-42: Well-structured gitignore configuration.The gitignore file comprehensively covers standard Node.js and Next.js development patterns, including dependencies, build outputs, environment files, and system-specific files.
docs/contributing/README.md (1)
132-298: Comprehensive UI development contribution guide.The new UI development section provides excellent guidance for contributors, covering tech stack, project structure, testing guidelines, and detailed checklists. This will significantly help new contributors get started with the UI codebase.
ui/next.config.ts (1)
3-9: Configuration is appropriate for static export.The Next.js configuration correctly sets up static export with
output: "export"and disables image optimization withimages: { unoptimized: true }, which is suitable for embedding in the Go backend.ui/components/full-page-loader.tsx (1)
3-11: Clean and reusable loading component.The implementation is straightforward and uses appropriate styling with Tailwind classes. The component serves its purpose well as a reusable loading indicator.
ui/components/theme-toggle.tsx (1)
10-29: Excellent implementation of theme toggle functionality.The component demonstrates several good practices:
- Proper accessibility with screen reader text
- Smooth visual transitions between theme states
- Clean integration with the existing UI component system
- Appropriate use of client-side rendering
The icon animation approach with absolute positioning and CSS transforms is particularly well-executed.
ui/tsconfig.json (1)
1-27: Well-configured TypeScript setup for Next.js.The configuration includes all the necessary settings for a modern Next.js project:
- Appropriate compiler target and library settings
- Strict type checking enabled
- Proper module resolution and path aliasing
- Next.js plugin integration
ui/lib/constants/config.ts (1)
1-12: Configuration constants look well-structured.The DEFAULT_NETWORK_CONFIG and DEFAULT_PERFORMANCE_CONFIG provide sensible defaults for timeout, retries, and performance settings.
ui/app/layout.tsx (1)
26-42: Layout structure and provider setup look good.The component properly nests providers (ProgressProvider, ThemeProvider, SidebarProvider) and sets up fonts correctly. The metadata and HTML structure are appropriate.
ui/components/ui/collapsible.tsx (1)
1-17: Clean implementation following established patterns.The collapsible wrapper components properly forward props to Radix UI primitives and include consistent data-slot attributes for identification. The implementation aligns well with the UI component library pattern.
ui/components/ui/switch.tsx (1)
8-29: Well-implemented switch component with proper accessibility and styling.The component correctly implements the forwardRef pattern, uses proper TypeScript typing, and includes comprehensive styling for all interaction states including focus, disabled, and checked/unchecked states. The semantic structure and accessibility features are well-implemented.
ui/components/ui/alert.tsx (2)
6-19: Well-structured alert variants with comprehensive styling.The
alertVariantsdefinition properly handles grid layout for icons, spacing, and responsive design. The use of CSS Grid with conditional column sizing (has-[>svg]:grid-cols-[calc(var(--spacing)*4)_1fr]) elegantly handles the presence of icons.
21-41: Excellent component composition with proper semantic HTML.The three alert components work together cohesively:
Alertuses semanticrole="alert"for accessibilityAlertTitleandAlertDescriptionuse proper grid positioning- Data-slot attributes enable targeted styling
- Consistent prop spreading and className merging
ui/app/globals.css (3)
1-5: Clean imports and modern CSS setup.The imports are properly structured with Tailwind CSS and the animation plugin. The custom dark variant using
@custom-variantprovides better scoping than traditional approaches.
47-80: Comprehensive color system using modern OKLCH color space.The color definitions use OKLCH which provides better perceptual uniformity compared to traditional color spaces. The comprehensive coverage includes all necessary UI elements, charts, and sidebar components.
82-114: Well-implemented dark mode with consistent theming.The dark mode overrides maintain visual hierarchy while providing appropriate contrast. The alpha channel usage for borders and inputs (
oklch(1 0 0 / 10%)) creates subtle differentiation.ui/components/logs/ui/log-message-view.tsx (1)
25-61: Well-structured component with proper conditional rendering.The component properly handles different content types and provides good visual separation between message content and tool calls. The use of CodeEditor for JSON formatting enhances readability.
ui/app/config/page.tsx (1)
141-143: Inconsistent data passing pattern for MCPClientsList.The parent component loads MCP clients and stores them in state, but doesn't pass this data to
MCPClientsList. This is inconsistent withProvidersListwhich receives both data and a refresh callback.Either:
MCPClientsListshould receivemcpClientsdata andonRefreshcallback likeProvidersList- Or the parent component shouldn't load MCP clients if
MCPClientsListhandles its own data fetchingPlease clarify the intended pattern for consistency.
<TabsContent value="mcp" className="space-y-4"> - <MCPClientsList /> + <MCPClientsList mcpClients={mcpClients} onRefresh={loadMcpClients} /> </TabsContent>ui/components/ui/avatar.tsx (1)
8-32: LGTM! Clean implementation following good component composition patterns.The Avatar components properly wrap Radix UI primitives with consistent styling and appropriate prop forwarding. The use of data-slot attributes and the cn utility for class merging follows established patterns.
ui/components/sidebar.tsx (1)
67-177: Excellent sidebar implementation with comprehensive navigation structure.The AppSidebar component provides a well-structured navigation system with proper active state handling, external link support, and server status indicator. The use of semantic HTML and accessibility features is commendable.
ui/components/ui/button.tsx (1)
8-71: Excellent button implementation with comprehensive variant system.The Button component demonstrates excellent use of class-variance-authority for variant management, clean loading state handling, and proper component composition patterns. The extensive styling variants and accessibility features make this a robust, reusable component.
ui/components/logs/filters.tsx (1)
63-118: Well-implemented log filtering UI with comprehensive functionality.The LogFilters component provides an excellent user experience with search input, popover-based filtering, and visual feedback for selected filters. The integration with the Command component for searchable options is particularly well done.
ui/components/ui/dialog.tsx (1)
1-102: Well-implemented dialog component with excellent accessibility features.This dialog component wrapper follows best practices with proper TypeScript typing, accessibility features (screen reader text, focus management), and consistent styling. The component composition and prop forwarding are implemented correctly.
ui/components/config/providers-list.tsx (1)
1-181: Excellent provider management component with solid UX patterns.This component demonstrates good React practices with proper state management, comprehensive error handling, confirmation dialogs for destructive actions, and loading states. The API integration and user feedback mechanisms are well implemented.
transports/bifrost-http/plugins/logging/main.go (2)
308-318: Improved ID assignment logic with better fallback handling.The simplified logic for setting
logEntry.IDis cleaner and more robust. Usingresult.IDwhen available and generating a UUID as fallback ensures consistent ID assignment.
334-340: Enhanced InputHistory extraction with proper fallback logic.The improved fallback logic for extracting
InputHistoryensures consistent data availability by checking the context whenresult.ExtraFields.ChatHistoryis nil, with a sensible default to an empty slice.ui/components/logs/logs-table.tsx (1)
35-84: Well-implemented table state management and pagination logic.The sorting state synchronization, pagination calculations, and navigation functions are correctly implemented. The component properly manages the interaction between internal sorting state and external pagination callbacks.
ui/package.json (2)
1-72: Well-structured package.json with comprehensive tooling.The project setup includes all necessary dependencies for a modern React/Next.js UI with good development tooling including ESLint, Prettier, TypeScript, and Tailwind CSS.
11-49: Dependency Security Verified — No Vulnerabilities DetectedRan
npm audit --audit-level=moderateinui/; no security issues were found. All dependencies inui/package.json(lines 11–49) are secure and compatible.ui/components/ui/card.tsx (1)
1-50: Excellent card component implementation with sophisticated styling.The card component system is well-designed with:
- Consistent use of data-slot attributes for easy targeting
- Flexible prop forwarding and className merging
- Sophisticated grid layout in CardHeader with container queries
- Proper component composition pattern
transports/bifrost-http/main.go (3)
78-79: LGTM: Clean embedded UI integrationThe embed directive and variable declaration follow Go best practices for embedding static assets.
145-197: Excellent UI handler with proper security measuresThe implementation includes several important security and functionality features:
- Path sanitization to prevent directory traversal attacks
- SPA routing support by serving index.html for extensionless paths
- Appropriate MIME type detection and cache headers
- Graceful fallback handling for missing files
The cache strategy is well thought out with immutable caching for static assets and no-cache for HTML files.
321-330: Proper CORS integration across all endpointsThe server handler correctly applies CORS middleware to both metrics and API routes while preserving existing middleware chain order. Good decision to include metrics endpoint in CORS for monitoring dashboard access.
ui/components/ui/accordion.tsx (1)
9-47: Well-structured accordion component implementationThe component properly wraps Radix UI primitives with appropriate styling, accessibility features, and data attributes. The use of compound components provides good API ergonomics.
ui/components/logs/empty-state.tsx (1)
22-106: Comprehensive integration examples with good structureThe examples cover multiple providers and languages with well-organized code snippets. The constant structure makes it easy to extend with additional providers or languages.
ui/components/config/core-settings-list.tsx (1)
69-104: Excellent debouncing implementationThe debounced handlers properly manage timeouts and provide immediate UI feedback while preventing excessive API calls. The cleanup logic in useEffect ensures no memory leaks.
ui/components/ui/table.tsx (1)
7-63: Well-designed table component architectureThe components provide a clean API with proper HTML semantics, consistent styling, and useful features like overflow handling and hover states. The data-slot attributes aid in testing and debugging.
ui/lib/types/mcp.ts (1)
1-40: Well-structured TypeScript definitions.The MCP type definitions are clean and well-organized, with appropriate use of union types, optional properties, and clear interface separation for different use cases.
ui/components/ui/alert-dialog.tsx (1)
1-95: Excellent AlertDialog component implementation.The component properly wraps Radix UI primitives with consistent styling, good accessibility features, and follows established patterns. The use of
cnutility for class merging and proper prop forwarding makes this a solid UI primitive.ui/lib/types/config.ts (1)
1-139: Well-structured configuration types!The type definitions are comprehensive, properly typed, and align well with the backend structures. Good use of union types, optional fields, and index signatures for extensibility.
ui/components/ui/sheet.tsx (1)
1-91: Clean Sheet component implementation!The Sheet components are well-structured with proper accessibility features, animation support for all sides, and good use of Radix UI primitives. The close button includes screen reader text and the components follow consistent patterns.
ui/components/ui/badge.tsx (3)
1-5: Clean dependency imports and setup.The imports are well-organized with proper TypeScript typing and the necessary dependencies for a polymorphic badge component.
26-35: Well-implemented polymorphic component with proper TypeScript typing.The Badge component implementation is solid with:
- Proper TypeScript intersection types for component props
- Polymorphic rendering support via asChild prop
- Correct prop forwarding and className composition
- Data slot attribute for component identification
37-37: Proper exports for component and variant utilities.Exporting both the component and badgeVariants enables external usage of the styling configuration, which is good for consistency across the design system.
ui/components/ui/tabs.tsx (5)
1-6: Appropriate client-side setup for interactive tab components.The "use client" directive is correctly placed for components that require client-side interactivity, and the imports are properly organized.
8-10: Clean and simple tabs root implementation.The Tabs component provides a clean wrapper with sensible default layout styling (flex column with gap).
12-20: Well-styled tabs list with proper container styling.The TabsList component provides appropriate visual grouping with muted background and rounded corners, following good design system practices.
35-37: Simple and appropriate tabs content implementation.The TabsContent component provides a clean wrapper with flex-1 for proper content area expansion and removes default outline styling.
39-39: Complete component exports for tabs functionality.All four tab components are properly exported, providing a complete tabbed interface solution.
| function Skeleton({ className, ...props }: React.ComponentProps<"div">) { | ||
| return <div data-slot="skeleton" className={cn("bg-accent animate-pulse rounded-md", className)} {...props} />; | ||
| } |
There was a problem hiding this comment.
🧹 Nitpick (assertive)
Expose ref to match shadcn/ui conventions.
Most primitives in this codebase use React.forwardRef so parents can attach refs for measurement or focus. Align Skeleton with the same pattern:
-function Skeleton({ className, ...props }: React.ComponentProps<"div">) {
- return <div data-slot="skeleton" className={cn("bg-accent animate-pulse rounded-md", className)} {...props} />;
-}
+const Skeleton = React.forwardRef<HTMLDivElement, React.ComponentProps<"div">>(
+ ({ className, ...props }, ref) => (
+ <div
+ ref={ref}
+ data-slot="skeleton"
+ className={cn("bg-accent animate-pulse rounded-md", className)}
+ {...props}
+ />
+ ),
+);
+Skeleton.displayName = "Skeleton";🤖 Prompt for AI Agents
In ui/components/ui/skeleton.tsx around lines 3 to 5, the Skeleton component
does not currently expose a ref, which is inconsistent with the codebase
convention of using React.forwardRef for primitives. Refactor the Skeleton
function to use React.forwardRef, accepting a ref parameter and forwarding it to
the root div element. This will allow parent components to attach refs for
measurement or focus, aligning with shadcn/ui conventions.
| function Textarea({ className, ...props }: React.ComponentProps<"textarea">) { | ||
| return ( | ||
| <textarea | ||
| data-slot="textarea" | ||
| className={cn( | ||
| "border-input placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:bg-input/30 flex field-sizing-content min-h-16 w-full rounded-md border bg-transparent px-3 py-2 text-base shadow-xs transition-[color,box-shadow] outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50 md:text-sm", | ||
| className, | ||
| )} | ||
| {...props} | ||
| /> | ||
| ); | ||
| } |
There was a problem hiding this comment.
🛠️ Refactor suggestion
Add forwardRef for better form library integration.
UI primitive components like Textarea should typically use forwardRef to enable proper integration with form libraries and direct DOM access when needed.
-function Textarea({ className, ...props }: React.ComponentProps<"textarea">) {
+const Textarea = React.forwardRef<HTMLTextAreaElement, React.ComponentProps<"textarea">>(
+ ({ className, ...props }, ref) => {
return (
<textarea
+ ref={ref}
data-slot="textarea"
className={cn(
"border-input placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:bg-input/30 flex field-sizing-content min-h-16 w-full rounded-md border bg-transparent px-3 py-2 text-base shadow-xs transition-[color,box-shadow] outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
className,
)}
{...props}
/>
);
+ }
+);
+
+Textarea.displayName = "Textarea";📝 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.
| function Textarea({ className, ...props }: React.ComponentProps<"textarea">) { | |
| return ( | |
| <textarea | |
| data-slot="textarea" | |
| className={cn( | |
| "border-input placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:bg-input/30 flex field-sizing-content min-h-16 w-full rounded-md border bg-transparent px-3 py-2 text-base shadow-xs transition-[color,box-shadow] outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50 md:text-sm", | |
| className, | |
| )} | |
| {...props} | |
| /> | |
| ); | |
| } | |
| const Textarea = React.forwardRef< | |
| HTMLTextAreaElement, | |
| React.ComponentProps<"textarea"> | |
| >(({ className, ...props }, ref) => { | |
| return ( | |
| <textarea | |
| ref={ref} | |
| data-slot="textarea" | |
| className={cn( | |
| "border-input placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:bg-input/30 flex field-sizing-content min-h-16 w-full rounded-md border bg-transparent px-3 py-2 text-base shadow-xs transition-[color,box-shadow] outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50 md:text-sm", | |
| className, | |
| )} | |
| {...props} | |
| /> | |
| ); | |
| }); | |
| Textarea.displayName = "Textarea"; |
🤖 Prompt for AI Agents
In ui/components/ui/textarea.tsx around lines 5 to 16, the Textarea component
lacks forwardRef usage, which is important for form library integration and
direct DOM access. Refactor the Textarea function to use React.forwardRef,
accepting a ref parameter and passing it to the underlying <textarea> element
via the ref attribute, while keeping the existing props and className handling
intact.
| className={cn( | ||
| "flex items-center gap-2 text-sm leading-none font-medium select-none group-data-[disabled=true]:pointer-events-none group-data-[disabled=true]:opacity-50 peer-disabled:cursor-not-allowed peer-disabled:opacity-50", | ||
| className | ||
| )} |
There was a problem hiding this comment.
🧹 Nitpick (assertive)
Consider breaking down the long className string for better readability.
The className string on line 16 is quite long and could be improved for maintainability.
className={cn(
- "flex items-center gap-2 text-sm leading-none font-medium select-none group-data-[disabled=true]:pointer-events-none group-data-[disabled=true]:opacity-50 peer-disabled:cursor-not-allowed peer-disabled:opacity-50",
+ "flex items-center gap-2 text-sm leading-none font-medium select-none",
+ "group-data-[disabled=true]:pointer-events-none group-data-[disabled=true]:opacity-50",
+ "peer-disabled:cursor-not-allowed peer-disabled:opacity-50",
className
)}📝 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.
| className={cn( | |
| "flex items-center gap-2 text-sm leading-none font-medium select-none group-data-[disabled=true]:pointer-events-none group-data-[disabled=true]:opacity-50 peer-disabled:cursor-not-allowed peer-disabled:opacity-50", | |
| className | |
| )} | |
| className={cn( | |
| "flex items-center gap-2 text-sm leading-none font-medium select-none", | |
| "group-data-[disabled=true]:pointer-events-none group-data-[disabled=true]:opacity-50", | |
| "peer-disabled:cursor-not-allowed peer-disabled:opacity-50", | |
| className | |
| )} |
🤖 Prompt for AI Agents
In ui/components/ui/label.tsx around lines 15 to 18, the className string is
very long and hard to read. Break down the long className string into multiple
lines or separate variables to improve readability and maintainability, ensuring
each class or related group of classes is on its own line or clearly grouped.
| <button | ||
| type="button" | ||
| className="ring-offset-background focus:ring-ring cursor-pointer rounded-full outline-none focus:ring-2 focus:ring-offset-2" | ||
| onClick={() => removeTag(tag)} | ||
| > | ||
| <X className="h-3 w-3" /> | ||
| </button> | ||
| </Badge> |
There was a problem hiding this comment.
🧹 Nitpick (assertive)
Add accessibility attributes to remove buttons.
The remove buttons only contain X icons without descriptive text or aria-label attributes. Screen readers will announce these as just "button" without explaining their purpose.
Add aria-label attributes to improve accessibility:
<button
type="button"
+ aria-label={`Remove ${tag} tag`}
className="ring-offset-background focus:ring-ring cursor-pointer rounded-full outline-none focus:ring-2 focus:ring-offset-2"
onClick={() => removeTag(tag)}
>
<X className="h-3 w-3" />
</button>📝 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.
| <button | |
| type="button" | |
| className="ring-offset-background focus:ring-ring cursor-pointer rounded-full outline-none focus:ring-2 focus:ring-offset-2" | |
| onClick={() => removeTag(tag)} | |
| > | |
| <X className="h-3 w-3" /> | |
| </button> | |
| </Badge> | |
| <button | |
| type="button" | |
| aria-label={`Remove ${tag} tag`} | |
| className="ring-offset-background focus:ring-ring cursor-pointer rounded-full outline-none focus:ring-2 focus:ring-offset-2" | |
| onClick={() => removeTag(tag)} | |
| > | |
| <X className="h-3 w-3" /> | |
| </button> | |
| </Badge> |
🤖 Prompt for AI Agents
In ui/components/ui/tag-input.tsx around lines 45 to 52, the remove buttons lack
aria-label attributes, causing screen readers to announce them without context.
Add an aria-label attribute to each remove button that clearly describes its
action, such as "Remove tag" followed by the tag name, to improve accessibility
for screen reader users.
| } | ||
| setIsConnected(false); | ||
| }; | ||
| }, [onMessage]); // Add onMessage to dependencies to avoid stale closure |
There was a problem hiding this comment.
🧹 Nitpick (assertive)
Optimize useEffect dependencies to prevent unnecessary reconnections.
Including onMessage in the dependency array can cause the WebSocket to reconnect unnecessarily if the callback is not memoized properly.
- }, [onMessage]); // Add onMessage to dependencies to avoid stale closure
+ }, []); // Remove onMessage dependency to prevent unnecessary reconnectionsConsider using useRef to store the latest onMessage callback if you need to avoid stale closures:
+ const onMessageRef = useRef(onMessage);
+ onMessageRef.current = onMessage;
// In the onmessage handler:
- onMessage(data.payload);
+ onMessageRef.current(data.payload);Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In ui/hooks/useWebSocket.ts at line 78, the useEffect dependency array includes
onMessage, which can cause unnecessary WebSocket reconnections if onMessage is
not memoized. To fix this, remove onMessage from the dependency array and
instead use a useRef hook to store the latest onMessage callback. Update the ref
inside a separate useEffect when onMessage changes, and use the ref inside the
WebSocket event handler to always call the latest callback without triggering
reconnections.
|
|
||
| // Set new timeout | ||
| poolSizeTimeoutRef.current = setTimeout(() => { | ||
| const numValue = parseInt(value); |
There was a problem hiding this comment.
🧹 Nitpick (assertive)
Use Number.parseInt instead of global parseInt
Modern JavaScript recommends using the Number namespace for consistency.
Apply this fix:
- const numValue = parseInt(value);
+ const numValue = Number.parseInt(value);📝 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.
| const numValue = parseInt(value); | |
| const numValue = Number.parseInt(value); |
🧰 Tools
🪛 Biome (1.9.4)
[error] 80-80: Use Number.parseInt instead of the equivalent global.
ES2015 moved some globals into the Number namespace for consistency.
Safe fix: Use Number.parseInt instead.
(lint/style/useNumberNamespace)
🤖 Prompt for AI Agents
In ui/components/config/core-settings-list.tsx at line 80, replace the global
parseInt function with Number.parseInt to follow modern JavaScript best
practices and maintain consistency. Change the code from parseInt(value) to
Number.parseInt(value).
| export interface ModelParameters { | ||
| tool_choice?: unknown; // Can be string or object | ||
| tools?: Tool[]; | ||
| temperature?: number; | ||
| top_p?: number; | ||
| top_k?: number; | ||
| max_tokens?: number; | ||
| stop_sequences?: string[]; | ||
| presence_penalty?: number; | ||
| frequency_penalty?: number; | ||
| parallel_tool_calls?: boolean; | ||
| extra_params?: Record<string, unknown>; | ||
| } |
There was a problem hiding this comment.
🧹 Nitpick (assertive)
Refine overly-broad unknown fields in ModelParameters
Using unknown forces consumers to cast. If the actual shape is limited to a
few known patterns, encode them explicitly to gain autocompletion and static
safety, e.g.:
export type ToolChoice =
| "none"
| "auto"
| "required"
| { type: "function"; function_name: string };
tool_choice?: ToolChoice;
extra_params?: Record<string, string | number | boolean>;🤖 Prompt for AI Agents
In ui/lib/types/logs.ts between lines 60 and 72, the ModelParameters interface
uses overly broad unknown types for tool_choice and extra_params, which forces
consumers to cast and reduces type safety. Refine tool_choice by defining a
union type with specific string literals and an object shape for function type,
and update extra_params to be a Record with string keys and values limited to
string, number, or boolean. Replace the unknown types accordingly to improve
autocompletion and static type checking.
| export interface Function { | ||
| name: string; | ||
| description: string; | ||
| parameters: FunctionParameters; | ||
| } | ||
|
|
||
| export interface Tool { | ||
| id?: string; | ||
| type: string; | ||
| function: Function; | ||
| } |
There was a problem hiding this comment.
🛠️ Refactor suggestion
Rename Function interface to avoid shadowing the global Function type
Function is already a global interface in the TypeScript lib.
Redefining it here silently overrides the ambient declaration and can break
type-checking or tooling that relies on the built-in Function.
Rename the interface (e.g. ToolFunction) and update the references.
-// Tool-related types
-export interface Function {
+// Tool-related types
+export interface ToolFunction {
name: string;
description: string;
parameters: FunctionParameters;
}
export interface Tool {
id?: string;
type: string;
- function: Function;
+ function: ToolFunction;
}
export interface FunctionCall {
name?: string;
arguments: string; // stringified JSON
}📝 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.
| export interface Function { | |
| name: string; | |
| description: string; | |
| parameters: FunctionParameters; | |
| } | |
| export interface Tool { | |
| id?: string; | |
| type: string; | |
| function: Function; | |
| } | |
| // Tool-related types | |
| export interface ToolFunction { | |
| name: string; | |
| description: string; | |
| parameters: FunctionParameters; | |
| } | |
| export interface Tool { | |
| id?: string; | |
| type: string; | |
| function: ToolFunction; | |
| } | |
| export interface FunctionCall { | |
| name?: string; | |
| arguments: string; // stringified JSON | |
| } |
🤖 Prompt for AI Agents
In ui/lib/types/logs.ts around lines 36 to 46, the interface named Function
shadows the global TypeScript Function type, which can cause type-checking and
tooling issues. Rename this interface to a unique name like ToolFunction and
update all references to this interface accordingly, including the property in
the Tool interface that currently uses Function.
| const badgeVariants = cva( | ||
| "inline-flex items-center justify-center rounded-md border px-2 py-0.5 text-xs font-medium w-fit whitespace-nowrap shrink-0 [&>svg]:size-3 gap-1 [&>svg]:pointer-events-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive transition-[color,box-shadow] overflow-hidden", | ||
| { | ||
| variants: { | ||
| variant: { | ||
| default: "border-transparent bg-primary text-primary-foreground [a&]:hover:bg-primary/90", | ||
| secondary: "border-transparent bg-secondary text-secondary-foreground [a&]:hover:bg-secondary/90", | ||
| destructive: | ||
| "border-transparent bg-destructive text-white [a&]:hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60", | ||
| outline: "text-foreground [a&]:hover:bg-accent [a&]:hover:text-accent-foreground", | ||
| success: "border-transparent bg-green-700 text-white [a&]:hover:bg-green-700/90", | ||
| }, | ||
| }, | ||
| defaultVariants: { | ||
| variant: "default", | ||
| }, | ||
| }, | ||
| ); |
There was a problem hiding this comment.
🧹 Nitpick (assertive)
Consider refactoring the complex base class string for better maintainability.
The badgeVariants definition includes comprehensive styling with good coverage of interactive states and accessibility features. However, the base class string on line 8 is quite long and complex, which could impact readability.
Consider breaking down the base classes for better maintainability:
const badgeVariants = cva(
- "inline-flex items-center justify-center rounded-md border px-2 py-0.5 text-xs font-medium w-fit whitespace-nowrap shrink-0 [&>svg]:size-3 gap-1 [&>svg]:pointer-events-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive transition-[color,box-shadow] overflow-hidden",
+ [
+ "inline-flex items-center justify-center rounded-md border px-2 py-0.5 text-xs font-medium w-fit whitespace-nowrap shrink-0 gap-1 overflow-hidden",
+ "[&>svg]:size-3 [&>svg]:pointer-events-none",
+ "focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]",
+ "aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
+ "transition-[color,box-shadow]"
+ ].join(" "),📝 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.
| const badgeVariants = cva( | |
| "inline-flex items-center justify-center rounded-md border px-2 py-0.5 text-xs font-medium w-fit whitespace-nowrap shrink-0 [&>svg]:size-3 gap-1 [&>svg]:pointer-events-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive transition-[color,box-shadow] overflow-hidden", | |
| { | |
| variants: { | |
| variant: { | |
| default: "border-transparent bg-primary text-primary-foreground [a&]:hover:bg-primary/90", | |
| secondary: "border-transparent bg-secondary text-secondary-foreground [a&]:hover:bg-secondary/90", | |
| destructive: | |
| "border-transparent bg-destructive text-white [a&]:hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60", | |
| outline: "text-foreground [a&]:hover:bg-accent [a&]:hover:text-accent-foreground", | |
| success: "border-transparent bg-green-700 text-white [a&]:hover:bg-green-700/90", | |
| }, | |
| }, | |
| defaultVariants: { | |
| variant: "default", | |
| }, | |
| }, | |
| ); | |
| const badgeVariants = cva( | |
| [ | |
| "inline-flex items-center justify-center rounded-md border px-2 py-0.5 text-xs font-medium w-fit whitespace-nowrap shrink-0 gap-1 overflow-hidden", | |
| "[&>svg]:size-3 [&>svg]:pointer-events-none", | |
| "focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]", | |
| "aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive", | |
| "transition-[color,box-shadow]" | |
| ].join(" "), | |
| { | |
| variants: { | |
| variant: { | |
| default: "border-transparent bg-primary text-primary-foreground [a&]:hover:bg-primary/90", | |
| secondary: "border-transparent bg-secondary text-secondary-foreground [a&]:hover:bg-secondary/90", | |
| destructive: | |
| "border-transparent bg-destructive text-white [a&]:hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60", | |
| outline: "text-foreground [a&]:hover:bg-accent [a&]:hover:text-accent-foreground", | |
| success: "border-transparent bg-green-700 text-white [a&]:hover:bg-green-700/90", | |
| }, | |
| }, | |
| defaultVariants: { | |
| variant: "default", | |
| }, | |
| }, | |
| ); |
🤖 Prompt for AI Agents
In ui/components/ui/badge.tsx around lines 7 to 24, the base class string in the
badgeVariants definition is very long and complex, reducing readability and
maintainability. Refactor by splitting the base class string into smaller,
logically grouped constants or arrays representing different style categories
(e.g., layout, typography, interaction states). Then combine these smaller
groups when passing to the cva function to keep the code cleaner and easier to
manage.
| function TabsTrigger({ className, ...props }: React.ComponentProps<typeof TabsPrimitive.Trigger>) { | ||
| return ( | ||
| <TabsPrimitive.Trigger | ||
| data-slot="tabs-trigger" | ||
| className={cn( | ||
| "data-[state=active]:bg-background dark:data-[state=active]:text-foreground focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:outline-ring dark:data-[state=active]:border-input dark:data-[state=active]:bg-input/30 text-foreground dark:text-muted-foreground inline-flex h-[calc(100%-1px)] flex-1 cursor-pointer items-center justify-center gap-1.5 rounded-md border border-transparent px-2 py-1 text-sm font-medium whitespace-nowrap transition-[color,box-shadow] focus-visible:ring-[3px] focus-visible:outline-1 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:shadow-sm [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4", | ||
| className, | ||
| )} | ||
| {...props} | ||
| /> | ||
| ); | ||
| } |
There was a problem hiding this comment.
🧹 Nitpick (assertive)
Consider breaking down the complex TabsTrigger className for better maintainability.
The TabsTrigger component includes comprehensive styling for various states, but the className string is very long and complex, making it difficult to read and maintain.
Consider breaking down the complex className for better readability:
<TabsPrimitive.Trigger
data-slot="tabs-trigger"
className={cn(
- "data-[state=active]:bg-background dark:data-[state=active]:text-foreground focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:outline-ring dark:data-[state=active]:border-input dark:data-[state=active]:bg-input/30 text-foreground dark:text-muted-foreground inline-flex h-[calc(100%-1px)] flex-1 cursor-pointer items-center justify-center gap-1.5 rounded-md border border-transparent px-2 py-1 text-sm font-medium whitespace-nowrap transition-[color,box-shadow] focus-visible:ring-[3px] focus-visible:outline-1 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:shadow-sm [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
+ [
+ "inline-flex h-[calc(100%-1px)] flex-1 cursor-pointer items-center justify-center gap-1.5 rounded-md border border-transparent px-2 py-1 text-sm font-medium whitespace-nowrap",
+ "text-foreground dark:text-muted-foreground",
+ "data-[state=active]:bg-background data-[state=active]:shadow-sm",
+ "dark:data-[state=active]:text-foreground dark:data-[state=active]:border-input dark:data-[state=active]:bg-input/30",
+ "focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:outline-ring focus-visible:ring-[3px] focus-visible:outline-1",
+ "disabled:pointer-events-none disabled:opacity-50",
+ "transition-[color,box-shadow]",
+ "[&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4"
+ ].join(" "),
className,
)}
{...props}
/>📝 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.
| function TabsTrigger({ className, ...props }: React.ComponentProps<typeof TabsPrimitive.Trigger>) { | |
| return ( | |
| <TabsPrimitive.Trigger | |
| data-slot="tabs-trigger" | |
| className={cn( | |
| "data-[state=active]:bg-background dark:data-[state=active]:text-foreground focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:outline-ring dark:data-[state=active]:border-input dark:data-[state=active]:bg-input/30 text-foreground dark:text-muted-foreground inline-flex h-[calc(100%-1px)] flex-1 cursor-pointer items-center justify-center gap-1.5 rounded-md border border-transparent px-2 py-1 text-sm font-medium whitespace-nowrap transition-[color,box-shadow] focus-visible:ring-[3px] focus-visible:outline-1 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:shadow-sm [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4", | |
| className, | |
| )} | |
| {...props} | |
| /> | |
| ); | |
| } | |
| function TabsTrigger({ className, ...props }: React.ComponentProps<typeof TabsPrimitive.Trigger>) { | |
| return ( | |
| <TabsPrimitive.Trigger | |
| data-slot="tabs-trigger" | |
| className={cn( | |
| [ | |
| "inline-flex h-[calc(100%-1px)] flex-1 cursor-pointer items-center justify-center gap-1.5 rounded-md border border-transparent px-2 py-1 text-sm font-medium whitespace-nowrap", | |
| "text-foreground dark:text-muted-foreground", | |
| "data-[state=active]:bg-background data-[state=active]:shadow-sm", | |
| "dark:data-[state=active]:text-foreground dark:data-[state=active]:border-input dark:data-[state=active]:bg-input/30", | |
| "focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:outline-ring focus-visible:ring-[3px] focus-visible:outline-1", | |
| "disabled:pointer-events-none disabled:opacity-50", | |
| "transition-[color,box-shadow]", | |
| "[&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4" | |
| ].join(" "), | |
| className, | |
| )} | |
| {...props} | |
| /> | |
| ); | |
| } |
🤖 Prompt for AI Agents
In ui/components/ui/tabs.tsx around lines 22 to 33, the TabsTrigger component's
className string is very long and complex, reducing readability and
maintainability. Refactor by splitting the className into multiple smaller,
descriptive variables or constants representing different style groups (e.g.,
active state styles, focus styles, base styles) and then combine them using the
cn function. This will make the styles easier to manage and update.
df1c9b7 to
e7fbff2
Compare
1851754 to
9ffc628
Compare
2abd063 to
0aed797
Compare
0aed797 to
da9db1e
Compare
Merge activity
|

No description provided.