Skip to content

feat(models): introduce ModelsSupported unified component - #346

Merged
steebchen merged 1 commit into
mainfrom
feat/unified-models-ui
Jun 11, 2025
Merged

steebchen merged 1 commit into
mainfrom
feat/unified-models-ui

Conversation

@smakosh

@smakosh smakosh commented Jun 11, 2025

Copy link
Copy Markdown
Member

Summary by CodeRabbit

  • New Features

    • Introduced a new component that displays supported AI providers and their models, including provider icons, model details, and links to documentation.
    • The component adapts its layout for dashboard or standalone pages and summarizes total providers and models.
  • Refactor

    • Replaced previous model/provider display logic in relevant pages with the new, consolidated component for a streamlined and consistent user experience.

@smakosh
smakosh requested a review from steebchen June 11, 2025 17:24
@smakosh smakosh self-assigned this Jun 11, 2025
@coderabbitai

coderabbitai Bot commented Jun 11, 2025

Copy link
Copy Markdown
Contributor

Walkthrough

A new ModelsSupported React component was introduced to encapsulate the display logic for supported AI providers and their models. The previous model listing and grouping logic in the dashboard and models routes was replaced by usage of this new component, streamlining and centralizing the UI and data handling for supported models.

Changes

File(s) Change Summary
apps/ui/src/components/models-supported.tsx Added new ModelsSupported component to display supported AI providers and their models, with icons and stats.
apps/ui/src/routes/dashboard/_layout/models.tsx Replaced previous card-based model listing with the new ModelsSupported component and removed old imports.
apps/ui/src/routes/models.tsx Removed all manual provider/model listing logic and replaced with ModelsSupported component usage.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant DashboardRoute
    participant ModelsRoute
    participant ModelsSupported

    User->>DashboardRoute: Navigates to dashboard models
    DashboardRoute->>ModelsSupported: Render with isDashboard=true
    ModelsSupported->>ModelsSupported: Fetch and group providers/models
    ModelsSupported->>User: Display providers and models

    User->>ModelsRoute: Navigates to models page
    ModelsRoute->>ModelsSupported: Render with isDashboard=false
    ModelsSupported->>ModelsSupported: Fetch and group providers/models
    ModelsSupported->>User: Display providers and models
Loading

Suggested reviewers

  • steebchen
✨ Finishing Touches
  • 📝 Generate Docstrings

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need 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)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@smakosh smakosh changed the title feat(models): introduce ModelsSupported component for displaying AI p… feat(models): introduce ModelsSupported unified component Jun 11, 2025
@steebchen
steebchen added this pull request to the merge queue Jun 11, 2025

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🧹 Nitpick comments (1)
apps/ui/src/components/models-supported.tsx (1)

161-163: Consider using a more unique key for model cards.

While the current key should work in most cases, using just ${model.providerId}-${model.model} could theoretically have collisions if a provider has duplicate model names. Consider adding an index or using a more unique identifier.

-								{models.map((model) => (
+								{models.map((model, index) => (
 									<Card
-										key={`${model.providerId}-${model.model}`}
+										key={`${model.providerId}-${model.model}-${index}`}
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a5613c3 and 74e9009.

📒 Files selected for processing (3)
  • apps/ui/src/components/models-supported.tsx (1 hunks)
  • apps/ui/src/routes/dashboard/_layout/models.tsx (2 hunks)
  • apps/ui/src/routes/models.tsx (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (3)
apps/ui/src/routes/dashboard/_layout/models.tsx (1)
apps/ui/src/components/models-supported.tsx (1)
  • ModelsSupported (105-209)
apps/ui/src/routes/models.tsx (1)
apps/ui/src/components/models-supported.tsx (1)
  • ModelsSupported (105-209)
apps/ui/src/components/models-supported.tsx (4)
apps/ui/src/components/provider-keys/provider-keys-list.tsx (1)
  • providerLogoComponents (44-53)
packages/models/src/providers.ts (1)
  • ProviderId (109-109)
apps/ui/src/lib/utils.ts (2)
  • cn (4-6)
  • formatContextSize (13-24)
apps/ui/src/lib/env.ts (1)
  • DOCS_URL (4-5)
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: e2e / run
🔇 Additional comments (2)
apps/ui/src/routes/dashboard/_layout/models.tsx (1)

3-3: Clean refactor to use the new ModelsSupported component.

The simplification of this route to use the centralized ModelsSupported component is a good improvement that reduces code duplication.

Also applies to: 16-16

apps/ui/src/routes/models.tsx (1)

5-5: Clean refactor to use the new ModelsSupported component.

Good consolidation of the provider/model display logic into a reusable component.

Also applies to: 12-12

Comment on lines +75 to +93
const groupedProviders = modelDefinitions.reduce<
Record<string, ProviderModel[]>
>((acc, def) => {
def.providers.forEach((map) => {
const provider = providerDefinitions.find((p) => p.id === map.providerId)!;
if (!acc[provider.name]) {
acc[provider.name] = [];
}
acc[provider.name].push({
model: def.model,
providerId: map.providerId,
providerName: provider.name,
inputPrice: map.inputPrice,
outputPrice: map.outputPrice,
contextSize: map.contextSize,
});
});
return acc;
}, {});

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Add error handling for missing provider definitions.

The non-null assertion on line 79 could cause a runtime error if a provider ID exists in model definitions but not in provider definitions.

-		const provider = providerDefinitions.find((p) => p.id === map.providerId)!;
+		const provider = providerDefinitions.find((p) => p.id === map.providerId);
+		if (!provider) {
+			console.warn(`Provider definition not found for ID: ${map.providerId}`);
+			return;
+		}
📝 Committable suggestion

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

Suggested change
const groupedProviders = modelDefinitions.reduce<
Record<string, ProviderModel[]>
>((acc, def) => {
def.providers.forEach((map) => {
const provider = providerDefinitions.find((p) => p.id === map.providerId)!;
if (!acc[provider.name]) {
acc[provider.name] = [];
}
acc[provider.name].push({
model: def.model,
providerId: map.providerId,
providerName: provider.name,
inputPrice: map.inputPrice,
outputPrice: map.outputPrice,
contextSize: map.contextSize,
});
});
return acc;
}, {});
const groupedProviders = modelDefinitions.reduce<
Record<string, ProviderModel[]>
>((acc, def) => {
def.providers.forEach((map) => {
- const provider = providerDefinitions.find((p) => p.id === map.providerId)!;
+ const provider = providerDefinitions.find((p) => p.id === map.providerId);
+ if (!provider) {
+ console.warn(`Provider definition not found for ID: ${map.providerId}`);
+ return;
+ }
if (!acc[provider.name]) {
acc[provider.name] = [];
}
acc[provider.name].push({
model: def.model,
providerId: map.providerId,
providerName: provider.name,
inputPrice: map.inputPrice,
outputPrice: map.outputPrice,
contextSize: map.contextSize,
});
});
return acc;
}, {});
🤖 Prompt for AI Agents
In apps/ui/src/components/models-supported.tsx around lines 75 to 93, the code
uses a non-null assertion when finding a provider by ID, which can cause a
runtime error if the provider is not found. Modify the code to check if the
provider exists before accessing its properties. If the provider is missing,
handle the case gracefully, such as by skipping that entry or logging a warning,
to prevent runtime exceptions.

Comment on lines +198 to +205
<a
href={`${DOCS_URL}/v1/models`}
target="_blank"
className="inline-flex items-center gap-2 text-sm text-muted-foreground"
>
<span>Data sourced from @llmgateway/models</span>
<ExternalLink className="w-4 h-4" />
</a>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Add security attributes to external link.

Links with target="_blank" should include rel="noopener noreferrer" to prevent security vulnerabilities.

 				<a
 					href={`${DOCS_URL}/v1/models`}
 					target="_blank"
+					rel="noopener noreferrer"
 					className="inline-flex items-center gap-2 text-sm text-muted-foreground"
 				>
📝 Committable suggestion

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

Suggested change
<a
href={`${DOCS_URL}/v1/models`}
target="_blank"
className="inline-flex items-center gap-2 text-sm text-muted-foreground"
>
<span>Data sourced from @llmgateway/models</span>
<ExternalLink className="w-4 h-4" />
</a>
<a
href={`${DOCS_URL}/v1/models`}
target="_blank"
rel="noopener noreferrer"
className="inline-flex items-center gap-2 text-sm text-muted-foreground"
>
<span>Data sourced from @llmgateway/models</span>
<ExternalLink className="w-4 h-4" />
</a>
🤖 Prompt for AI Agents
In apps/ui/src/components/models-supported.tsx around lines 198 to 205, the
anchor tag with target="_blank" is missing the security attributes rel="noopener
noreferrer". Add rel="noopener noreferrer" to the anchor tag to prevent security
vulnerabilities related to opening links in a new tab.

Comment on lines +26 to +36
const providerLogoComponents: Partial<
Record<ProviderId, React.FC<React.SVGProps<SVGSVGElement>> | null>
> = {
openai: OpenAiLogo,
anthropic: anthropicLogo,
"google-vertex": GoogleVertexLogo,
"inference.net": InferenceLogo,
"kluster.ai": KlusterLogo,
"together.ai": TogetherAiLogo,
"google-ai-studio": GoogleStudioAiLogo,
};

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Verify if the "llmgateway" provider logo should be included.

The provider logo mapping is missing the "llmgateway" provider that appears in the similar mapping in provider-keys-list.tsx. Please verify if this omission is intentional.


🏁 Script executed:

#!/bin/bash
# Check if llmgateway provider exists in the models/providers data
ast-grep --pattern 'id: "llmgateway"'

Length of output: 39


🏁 Script executed:

#!/bin/bash
# Search for occurrences of "llmgateway" in the repository
rg -n '"llmgateway"' .
rg -n llmgateway .

Length of output: 20692


🏁 Script executed:

#!/bin/bash
# Show logo imports in models-supported.tsx
sed -n '1,100p' apps/ui/src/components/models-supported.tsx | rg -n 'import .*Logo'

Length of output: 619


🏁 Script executed:

#!/bin/bash
# Display the provider logo mapping and getProviderIcon logic
rg -n "providerLogoComponents" -A 15 -B 5 apps/ui/src/components/models-supported.tsx
rg -n "function getProviderIcon" -A 15 -B 5 apps/ui/src/components/models-supported.tsx

Length of output: 1447


Add “llmgateway” to the provider logo mapping

The UI currently falls back to the generic logo for the “llmgateway” provider. To match the mapping in provider-keys-list.tsx and ensure the correct icon is displayed, please:

• In apps/ui/src/components/models-supported.tsx, add the import for the LLMGateway logo alongside the other SVG imports (around lines 8–14):

 import TogetherAiLogo from "@/assets/models/together-ai.svg?react";
+import LLMGatewayLogo from "@/assets/models/llmgateway.svg?react";

• Include the “llmgateway” entry in providerLogoComponents (around lines 26–36):

  const providerLogoComponents: Partial<Record<ProviderId, React.FC<React.SVGProps<SVGSVGElement>> | null>> = {
     openai: OpenAiLogo,
     anthropic: anthropicLogo,
     "google-vertex": GoogleVertexLogo,
     "inference.net": InferenceLogo,
     "kluster.ai": KlusterLogo,
     "together.ai": TogetherAiLogo,
     "google-ai-studio": GoogleStudioAiLogo,
+    llmgateway: LLMGatewayLogo,
  };

This ensures getProviderIcon("llmgateway") renders the correct gateway logo instead of the generic one.

📝 Committable suggestion

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

Suggested change
const providerLogoComponents: Partial<
Record<ProviderId, React.FC<React.SVGProps<SVGSVGElement>> | null>
> = {
openai: OpenAiLogo,
anthropic: anthropicLogo,
"google-vertex": GoogleVertexLogo,
"inference.net": InferenceLogo,
"kluster.ai": KlusterLogo,
"together.ai": TogetherAiLogo,
"google-ai-studio": GoogleStudioAiLogo,
};
// (somewhere alongside the other SVG imports)
import TogetherAiLogo from "@/assets/models/together-ai.svg?react";
import LLMGatewayLogo from "@/assets/models/llmgateway.svg?react";
// …
const providerLogoComponents: Partial<
Record<ProviderId, React.FC<React.SVGProps<SVGSVGElement>> | null>
> = {
openai: OpenAiLogo,
anthropic: anthropicLogo,
"google-vertex": GoogleVertexLogo,
"inference.net": InferenceLogo,
"kluster.ai": KlusterLogo,
"together.ai": TogetherAiLogo,
"google-ai-studio": GoogleStudioAiLogo,
llmgateway: LLMGatewayLogo,
};
🤖 Prompt for AI Agents
In apps/ui/src/components/models-supported.tsx around lines 8 to 14, add an
import statement for the LLMGateway logo SVG component alongside the existing
logo imports. Then, between lines 26 and 36, add an entry for "llmgateway" in
the providerLogoComponents mapping, assigning it the imported LLMGateway logo
component. This will ensure the "llmgateway" provider uses its specific logo
instead of falling back to the generic icon.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants