Skip to content

Conversation

@TejasGhatte
Copy link
Collaborator

@TejasGhatte TejasGhatte commented Sep 1, 2025

Provider Capabilities and Validation for Custom Providers

Added a new system to define and validate provider capabilities, ensuring custom providers only enable operations supported by their base provider type.

Changes

  • Added ProviderCapabilities struct to define what operations each provider supports
  • Implemented GetProviderCapabilities function to return capabilities for each provider type
  • Created ValidateAllowedRequests function to automatically disable unsupported operations
  • Updated UI to dynamically adjust allowed operations based on the selected base provider
  • Added validation in HTTP handlers and config validation to ensure custom providers only enable supported operations
  • Enhanced documentation with Go SDK example for custom providers
  • Updated UI to disable checkboxes for unsupported operations

Type of change

  • Feature
  • Refactor
  • Documentation

Affected areas

  • Core (Go)
  • Transports (HTTP)
  • Providers/Integrations
  • UI (Next.js)
  • Docs

How to test

  1. Create a custom provider with different base provider types and observe how the allowed operations change
  2. Try to enable unsupported operations and verify they are automatically disabled
  3. Test with the Go SDK example from the documentation
# Core/Transports
go test ./...

# UI
cd ui
pnpm i
pnpm test
pnpm build

Breaking changes

  • No

Security considerations

This change improves system integrity by preventing custom providers from attempting operations not supported by their base provider.

Checklist

  • I added/updated tests where appropriate
  • I updated documentation where needed
  • I verified builds succeed (Go and UI)

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Sep 1, 2025

📝 Walkthrough

Summary by CodeRabbit

  • New Features

    • Per‑provider capability defaults for Allowed Requests, with UI switches auto‑disabled for unsupported features.
    • Custom provider form syncs Allowed Requests when base provider changes and sets sensible defaults.
    • Automatically selects the first available provider when none is selected.
  • Bug Fixes

    • Custom provider validation now coerces unsupported operations and applies on updates.
    • Duplicate-name check runs only when creating new providers.
  • Documentation

    • Added “Using Go SDK” example for custom providers.
  • Style

    • Minor dialog background styling update in delete confirmation.

Walkthrough

Adds provider capability APIs and validation in core schemas; integrates AllowedRequests sanitization into backend create/update flows; updates UI to derive and gate AllowedRequests from base provider capabilities and provider-specific defaults; adds a Go SDK custom-provider example and minor UI/ordering tweaks.

Changes

Cohort / File(s) Summary
Core capabilities & validation
core/schemas/provider.go
Adds GetProviderCapabilities, GetDefaultAllowedRequestsForProvider, and ValidateAllowedRequests; extends CustomProviderConfig with AllowedRequests; updates IsOperationAllowed to use provider defaults when explicit config is absent; unknown providers yield empty capabilities.
Backend validation & handlers
transports/bifrost-http/lib/config.go, transports/bifrost-http/handlers/providers.go
ValidateCustomProvider now validates or derives AllowedRequests from base provider capabilities; ValidateCustomProviderUpdate delegates to it; AddProvider handler removed some prechecks and invokes ValidateCustomProvider before persisting, returning 400 on validation errors.
UI provider defaults (constants)
ui/lib/constants/config.ts
Adds PROVIDER_DEFAULT_ALLOWED_REQUESTS mapping and getProviderDefaultAllowedRequests(providerName) helper with per-provider capability sets (openai, anthropic, cohere, bedrock, gemini) and fallback to DEFAULT_ALLOWED_REQUESTS.
UI provider form behavior
ui/app/providers/configure/provider-form.tsx
Adds baseProviderType to form state; uses getProviderDefaultAllowedRequests for defaults; syncs allowedRequests when base provider changes; disables switches for unsupported ops; duplicate-name validation limited to creation.
UI provider page selection
ui/app/providers/configure/page.tsx
Adds auto-selection of the first available provider when none is selected (dispatches setSelectedProvider).
UI provider list styling
ui/app/providers/views/providers-list.tsx
Adds className="bg-secondary" to the Delete Provider dialog content.
Logs / known providers ordering
ui/lib/constants/logs.ts
Reorders and substitutes entries in KNOWN_PROVIDERS (changes sequence and literal provider list).
Documentation (Go SDK example)
docs/features/custom-providers.mdx
Adds a “Using Go SDK” tab with a Go example: MyAccount, public OpenAICustom provider identifier, and methods GetConfiguredProviders, GetKeysForProvider, and GetConfigForProvider demonstrating per-provider keys/config and an AllowedRequests-restricted openai-custom config.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor User
  participant UI as Provider Form (UI)
  participant API as HTTP Handler
  participant Cfg as ValidateCustomProvider
  participant Sch as schemas (Get/Validate AllowedRequests)
  participant Store as Provider Store

  User->>UI: Submit Create/Update Custom Provider
  UI->>API: POST /providers {config, allowedRequests, baseProviderType}
  API->>Cfg: ValidateCustomProvider(newConfig, req.Provider)
  alt allowedRequests provided
    Cfg->>Sch: ValidateAllowedRequests(allowedRequests, baseProviderType)
    Sch-->>Cfg: sanitized allowedRequests
  else none provided
    Cfg->>Sch: GetDefaultAllowedRequestsForProvider(baseProviderType)
    Sch-->>Cfg: default allowedRequests
  end
  Cfg-->>API: ok / error
  alt validation error
    API-->>UI: 400 Bad Request (validation error)
  else ok
    API->>Store: Add/Update Provider (sanitized allowedRequests)
    Store-->>API: ack
    API-->>UI: 200 OK
  end
Loading
sequenceDiagram
  autonumber
  actor User
  participant UI as Provider Form
  participant Const as getProviderDefaultAllowedRequests

  User->>UI: Select baseProviderType
  UI->>Const: getProviderDefaultAllowedRequests(baseProviderType)
  Const-->>UI: capability defaults
  UI->>UI: Update allowedRequests switches (disable unsupported)
  UI-->>User: Render gated controls and hint text
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Poem

I nibble toggles, sniff the base,
Capabilities tidy up the place.
Backend trims what rabbits can't do,
Frontend greys the options through.
Hops aligned — release carrots for the crew. 🐇✨

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch 09-01-fix_base_provider_level_request_level_restriction

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 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.
    • 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.
  • 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 the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore or @coderabbit 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

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • 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.

Copy link
Collaborator Author

This stack of pull requests is managed by Graphite. Learn more about stacking.

@TejasGhatte TejasGhatte changed the title fix: base provider level request level restriction fix: base provider level request level restriction and updated custom provider docs Sep 1, 2025
@TejasGhatte TejasGhatte changed the title fix: base provider level request level restriction and updated custom provider docs fix: base provider level request level restriction and updated custom provider docs for g SDK Sep 1, 2025
@TejasGhatte TejasGhatte changed the title fix: base provider level request level restriction and updated custom provider docs for g SDK fix: base provider level request level restriction and updated custom provider docs for go SDK Sep 1, 2025
@TejasGhatte TejasGhatte force-pushed the 09-01-fix_base_provider_level_request_level_restriction branch from 6d784ea to 90b6637 Compare September 1, 2025 07:26
@TejasGhatte TejasGhatte marked this pull request as ready for review September 1, 2025 07:26
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 11

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
transports/bifrost-http/lib/config.go (2)

976-979: Update path misses AllowedRequests sanitization.

ValidateCustomProviderUpdate doesn't sanitize AllowedRequests, so updates can re-enable unsupported ops. Sanitize here too to keep behavior consistent with creation.

Add inside ValidateCustomProviderUpdate after the base type immutability check:

// Normalize/sanitize AllowedRequests on update as well
if newCPC.AllowedRequests == nil {
  caps := schemas.GetProviderCapabilities(newCPC.BaseProviderType)
  newCPC.AllowedRequests = &schemas.AllowedRequests{
    TextCompletion:       caps.TextCompletion,
    ChatCompletion:       caps.ChatCompletion,
    ChatCompletionStream: caps.ChatCompletionStream,
    Embedding:            caps.Embedding,
    Speech:               caps.Speech,
    SpeechStream:         caps.SpeechStream,
    Transcription:        caps.Transcription,
    TranscriptionStream:  caps.TranscriptionStream,
  }
} else {
  schemas.ValidateAllowedRequests(newCPC.AllowedRequests, newCPC.BaseProviderType)
}

Optionally log when the incoming flags are narrowed to aid debugging.


966-1047: Consider last-mile safety: sanitize before persisting.

Even with the fixes above, adding a final guard before s.Providers[provider] = config avoids future regressions.

Insert just before assigning s.Providers[provider]:

if config.CustomProviderConfig != nil && config.CustomProviderConfig.AllowedRequests != nil {
  schemas.ValidateAllowedRequests(config.CustomProviderConfig.AllowedRequests, config.CustomProviderConfig.BaseProviderType)
}
📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between fbe9c42 and 90b6637.

📒 Files selected for processing (8)
  • core/schemas/provider.go (1 hunks)
  • docs/features/custom-providers.mdx (1 hunks)
  • framework/go.mod (1 hunks)
  • transports/bifrost-http/handlers/providers.go (1 hunks)
  • transports/bifrost-http/lib/config.go (1 hunks)
  • transports/go.mod (1 hunks)
  • ui/app/providers/configure/provider-form.tsx (15 hunks)
  • ui/lib/constants/config.ts (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (5)
transports/bifrost-http/lib/config.go (2)
core/schemas/provider.go (2)
  • AllowedRequests (87-96)
  • ValidateAllowedRequests (202-235)
ui/lib/types/config.ts (1)
  • AllowedRequests (88-97)
transports/bifrost-http/handlers/providers.go (2)
core/schemas/provider.go (3)
  • CustomProviderConfig (237-241)
  • AllowedRequests (87-96)
  • ValidateAllowedRequests (202-235)
ui/lib/types/config.ts (2)
  • CustomProviderConfig (82-85)
  • AllowedRequests (88-97)
ui/lib/constants/config.ts (2)
core/schemas/provider.go (1)
  • AllowedRequests (87-96)
ui/lib/types/config.ts (1)
  • AllowedRequests (88-97)
core/schemas/provider.go (2)
core/schemas/bifrost.go (5)
  • ModelProvider (38-38)
  • OpenAI (41-41)
  • Anthropic (43-43)
  • Cohere (45-45)
  • Bedrock (44-44)
ui/lib/types/config.ts (2)
  • ModelProvider (12-12)
  • AllowedRequests (88-97)
ui/app/providers/configure/provider-form.tsx (2)
ui/lib/constants/config.ts (1)
  • getProviderDefaultAllowedRequests (86-101)
ui/lib/utils/validation.ts (1)
  • Validator (40-151)
🔇 Additional comments (5)
ui/app/providers/configure/provider-form.tsx (3)

426-434: Good fix for duplicate name validation

The logic correctly prevents duplicate name validation when updating existing providers, which resolves a common UX issue where users couldn't save their own provider during updates.


864-867: Clear and helpful UI text for disabled features

The explanatory text effectively communicates to users why certain features are disabled based on the underlying provider's capabilities. This improves the user experience by setting clear expectations.


877-943: Consistent capability gating implementation

The switch controls are properly disabled based on the provider's capabilities using getProviderDefaultAllowedRequests. This ensures users cannot enable unsupported operations, preventing runtime errors.

transports/bifrost-http/lib/config.go (1)

590-591: Verify EnvKeyInfo.ConfigPath vs getRestoredMCPConfig mapping
Ensure the paths used in getRestoredMCPConfig (e.g. mcp.client_configs[%d].connection_string) align with how EnvKeyInfo.ConfigPath is stored (mcp.client_configs.<name>.connection_string); otherwise restoration may skip entries and leak values.

core/schemas/provider.go (1)

126-136: LGTM on the capabilities type.

Clear, minimal surface; pairs cleanly with validation and UI.

@TejasGhatte TejasGhatte force-pushed the 09-01-fix_base_provider_level_request_level_restriction branch from 90b6637 to 6507562 Compare September 1, 2025 08:28
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 10

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (5)
docs/features/custom-providers.mdx (1)

24-29: Doc behavior inconsistent with backend: nil allowed_requests defaults to provider capabilities, not “all allowed”

Update this section to reflect current CustomProviderConfig.IsOperationAllowed semantics.

-**Important**: The `allowed_requests` field follows a specific behavior:
-- **Omitted entirely**: All operations are allowed (default behavior)
-- **Partially specified**: Only explicitly set fields are allowed, others default to `false`
-- **Fully specified**: Only the operations you explicitly enable are allowed
-- **Present but empty object (`{}`)**: All fields are set to false
+**Important**: The `allowed_requests` field follows this behavior:
+- **Omitted entirely**: Defaults to the capabilities of the selected base provider (unsupported operations remain disabled)
+- **Partially specified**: Only explicitly set fields are allowed; omitted fields default to `false` and are further limited by base provider capabilities
+- **Fully specified**: Only the operations you explicitly enable are allowed, limited by base provider capabilities
+- **Present but empty object (`{}`)**: All fields are set to `false`
ui/app/providers/configure/provider-form.tsx (3)

187-189: Keys/base URL requirements should depend on effectiveProviderType (bug blocks custom Ollama/SGL).

Currently keyed to selectedProvider, so custom providers based on ollama/sgl incorrectly require keys and don’t require base_url. Use effectiveProviderType.

- const baseURLRequired = selectedProvider === "ollama" || selectedProvider === "sgl";
- const keysRequired = selectedProvider === "custom" || !["ollama", "sgl"].includes(selectedProvider); // Custom providers and most others need keys
+ const baseURLRequired = effectiveProviderType === "ollama" || effectiveProviderType === "sgl";
+ const keysRequired = !["ollama", "sgl"].includes(effectiveProviderType);

870-946: Avoid repeated calls to getProviderDefaultAllowedRequests in disabled checks.

Memoize baseCaps once and reference it. Reduces rework on each render.

Add near other useMemo declarations:

const baseCaps = useMemo(
  () => getProviderDefaultAllowedRequests(baseProviderType || "openai"),
  [baseProviderType]
);

Then update switches:

- disabled={!getProviderDefaultAllowedRequests(baseProviderType || "openai").text_completion}
+ disabled={!baseCaps.text_completion}
...
- disabled={!getProviderDefaultAllowedRequests(baseProviderType || "openai").chat_completion}
+ disabled={!baseCaps.chat_completion}
...
- disabled={!getProviderDefaultAllowedRequests(baseProviderType || "openai").chat_completion_stream}
+ disabled={!baseCaps.chat_completion_stream}
...
- disabled={!getProviderDefaultAllowedRequests(baseProviderType || "openai").embedding}
+ disabled={!baseCaps.embedding}
...
- disabled={!getProviderDefaultAllowedRequests(baseProviderType || "openai").speech}
+ disabled={!baseCaps.speech}
...
- disabled={!getProviderDefaultAllowedRequests(baseProviderType || "openai").speech_stream}
+ disabled={!baseCaps.speech_stream}
...
- disabled={!getProviderDefaultAllowedRequests(baseProviderType || "openai").transcription}
+ disabled={!baseCaps.transcription}
...
- disabled={!getProviderDefaultAllowedRequests(baseProviderType || "openai").transcription_stream}
+ disabled={!baseCaps.transcription_stream}

1094-1136: Vertex key UI is hidden for custom Vertex providers (wrong condition).

Gate on effectiveProviderType, not selectedProvider, else custom providers based on Vertex can’t configure required fields.

- {selectedProvider === "vertex" && (
+ {effectiveProviderType === "vertex" && (
transports/bifrost-http/lib/config.go (1)

410-474: Also validate/sanitize custom providers when loading from config.json (parity with DB path).

This branch processes providers from the file but doesn’t call ValidateCustomProvider before assigning cfg, so unsupported ops could slip through until first update.

-               processedProviders[provider] = cfg
+               if err := ValidateCustomProvider(cfg, provider); err != nil {
+                 logger.Warn("invalid custom provider config for %s: %v", provider, err)
+                 continue
+               }
+               processedProviders[provider] = cfg
♻️ Duplicate comments (2)
ui/lib/constants/config.ts (1)

33-83: Reduce duplication: generate provider defaults from a compact capability set

This manually repeated boolean matrix is brittle and easy to drift from core. Generate it from a single capability set.

-// Define the default allowed requests for each provider type
-// This is based on the actual capabilities of each provider
-export const PROVIDER_DEFAULT_ALLOWED_REQUESTS: Record<string, AllowedRequests> = {
-  // OpenAI
-  openai: {
-    text_completion: false,
-    chat_completion: true,
-    chat_completion_stream: true,
-    embedding: true,
-    speech: true,
-    speech_stream: true,
-    transcription: true,
-    transcription_stream: true,
-  },
-  // Anthropic
-  anthropic: {
-    text_completion: true,
-    chat_completion: true,
-    chat_completion_stream: true,
-    embedding: false,
-    speech: false,
-    speech_stream: false,
-    transcription: false,
-    transcription_stream: false,
-  },
-  // Cohere
-  cohere: {
-    text_completion: false,
-    chat_completion: true,
-    chat_completion_stream: true,
-    embedding: true,
-    speech: false,
-    speech_stream: false,
-    transcription: false,
-    transcription_stream: false,
-  },
-  // AWS Bedrock
-  bedrock: {
-    text_completion: true,
-    chat_completion: true,
-    chat_completion_stream: true,
-    embedding: true,
-    speech: false,
-    speech_stream: false,
-    transcription: false,
-    transcription_stream: false,
-  },
-};
+type ProviderCapability =
+  | "text_completion"
+  | "chat_completion"
+  | "chat_completion_stream"
+  | "embedding"
+  | "speech"
+  | "speech_stream"
+  | "transcription"
+  | "transcription_stream";
+
+const PROVIDER_CAPABILITIES: Record<string, ReadonlySet<ProviderCapability>> = {
+  openai: new Set([
+    "chat_completion",
+    "chat_completion_stream",
+    "embedding",
+    "speech",
+    "speech_stream",
+    "transcription",
+    "transcription_stream",
+  ]),
+  anthropic: new Set(["text_completion", "chat_completion", "chat_completion_stream"]),
+  cohere: new Set(["chat_completion", "chat_completion_stream", "embedding"]),
+  bedrock: new Set(["text_completion", "chat_completion", "chat_completion_stream", "embedding"]),
+} as const;
+
+const ALL_CAPS: ProviderCapability[] = [
+  "text_completion",
+  "chat_completion",
+  "chat_completion_stream",
+  "embedding",
+  "speech",
+  "speech_stream",
+  "transcription",
+  "transcription_stream",
+];
+
+export const PROVIDER_DEFAULT_ALLOWED_REQUESTS: Record<string, AllowedRequests> = Object.fromEntries(
+  Object.entries(PROVIDER_CAPABILITIES).map(([k, caps]) => [
+    k,
+    Object.fromEntries(
+      ALL_CAPS.map((c) => [c, caps.has(c)])
+    ) as AllowedRequests,
+  ])
+);
ui/app/providers/configure/provider-form.tsx (1)

193-204: Debounce/cancel the allowedRequests reset to avoid flicker and stale updates.

-useEffect(() => {
-  if (baseProviderType && isCustomProvider && !isEditingExisting) {
-    const newAllowedRequests = getProviderDefaultAllowedRequests(baseProviderType);
-    setFormData((prev) => ({
-      ...prev,
-      allowedRequests: newAllowedRequests,
-      isDirty: true,
-    }));
-  }
-}, [baseProviderType, isCustomProvider, isEditingExisting]);
+useEffect(() => {
+  if (!baseProviderType || !isCustomProvider || isEditingExisting) return;
+  const id = setTimeout(() => {
+    const newAllowedRequests = getProviderDefaultAllowedRequests(baseProviderType);
+    setFormData((prev) => ({
+      ...prev,
+      allowedRequests: newAllowedRequests,
+      isDirty: true,
+    }));
+  }, 200);
+  return () => clearTimeout(id);
+}, [baseProviderType, isCustomProvider, isEditingExisting]);
📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 90b6637 and 6507562.

📒 Files selected for processing (6)
  • core/schemas/provider.go (2 hunks)
  • docs/features/custom-providers.mdx (1 hunks)
  • transports/bifrost-http/handlers/providers.go (1 hunks)
  • transports/bifrost-http/lib/config.go (2 hunks)
  • ui/app/providers/configure/provider-form.tsx (15 hunks)
  • ui/lib/constants/config.ts (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (5)
ui/lib/constants/config.ts (2)
core/schemas/provider.go (1)
  • AllowedRequests (87-96)
ui/lib/types/config.ts (1)
  • AllowedRequests (88-97)
transports/bifrost-http/lib/config.go (2)
core/schemas/provider.go (3)
  • AllowedRequests (87-96)
  • ValidateAllowedRequests (197-230)
  • GetDefaultAllowedRequestsForProvider (190-193)
ui/lib/types/config.ts (1)
  • AllowedRequests (88-97)
core/schemas/provider.go (2)
core/schemas/bifrost.go (5)
  • ModelProvider (38-38)
  • OpenAI (41-41)
  • Anthropic (43-43)
  • Cohere (45-45)
  • Bedrock (44-44)
ui/lib/types/config.ts (2)
  • ModelProvider (12-12)
  • AllowedRequests (88-97)
transports/bifrost-http/handlers/providers.go (3)
core/schemas/provider.go (1)
  • CustomProviderConfig (232-236)
transports/bifrost-http/lib/config.go (1)
  • ValidateCustomProvider (1824-1855)
transports/bifrost-http/handlers/utils.go (1)
  • SendError (27-36)
ui/app/providers/configure/provider-form.tsx (2)
ui/lib/constants/config.ts (1)
  • getProviderDefaultAllowedRequests (86-101)
ui/lib/utils/validation.ts (1)
  • Validator (40-151)
🔇 Additional comments (5)
docs/features/custom-providers.mdx (1)

112-174: Verify SDK interface signatures

Please confirm the account interface expects GetKeysForProvider(ctx context.Context, …) and not a pointer. If it does require a pointer, adjust imports and examples consistently.

ui/app/providers/configure/provider-form.tsx (3)

20-20: Import looks correct.


427-435: Scoped duplicate-name validation only on create — good.


864-867: Helpful UX copy.

transports/bifrost-http/lib/config.go (1)

1845-1852: Good: normalize/sanitize AllowedRequests on create.

Defaults to base capabilities when nil; otherwise sanitizes in place. Aligns backend with UI gating.

@TejasGhatte TejasGhatte force-pushed the 09-01-fix_base_provider_level_request_level_restriction branch from 6507562 to fb5f099 Compare September 4, 2025 12:35
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

♻️ Duplicate comments (2)
core/schemas/provider.go (2)

126-177: Centralize capability definitions to reduce duplication and drift.

Prefer a package-level map[ModelProvider]AllowedRequests + lookup over a switch; easier to keep UI defaults and backend in sync. Also add/keep a small table-driven test to assert UI defaults == core capabilities.

Example sketch:

+var providerCapabilities = map[ModelProvider]AllowedRequests{
+  OpenAI:    {ChatCompletion: true, ChatCompletionStream: true, Embedding: true, Speech: true, SpeechStream: true, Transcription: true, TranscriptionStream: true},
+  Anthropic: {TextCompletion: true, ChatCompletion: true, ChatCompletionStream: true},
+  Cohere:    {ChatCompletion: true, ChatCompletionStream: true, Embedding: true},
+  Bedrock:   {TextCompletion: true, ChatCompletion: true, ChatCompletionStream: true, Embedding: true},
+}
 func GetProviderCapabilities(provider ModelProvider) AllowedRequests {
-  switch provider {
-  ...
-  default:
-    return AllowedRequests{}
-  }
+  if caps, ok := providerCapabilities[provider]; ok {
+    return caps
+  }
+  return AllowedRequests{}
 }

186-221: Document in-place mutation and offer a pure sanitizer to avoid surprises.

This function mutates its input; call-sites must pass pointers they own. Either document this explicitly or provide a pure alternative returning a sanitized copy.

Apply:

-// ValidateAllowedRequests checks if the allowed requests are valid for the given base provider
-// and silently sets any unsupported operations to false instead of returning an error
+// ValidateAllowedRequests mutates allowedRequests in place to disable unsupported operations
+// for the given base provider. Unsupported true flags are silently set to false.
 func ValidateAllowedRequests(allowedRequests *AllowedRequests, baseProvider ModelProvider) {
   ...
 }
+
+// SanitizeAllowedRequests returns a new AllowedRequests with unsupported ops disabled.
+func SanitizeAllowedRequests(in *AllowedRequests, baseProvider ModelProvider) *AllowedRequests {
+	if in == nil {
+		return nil
+	}
+	out := *in
+	ValidateAllowedRequests(&out, baseProvider)
+	return &out
+}
🧹 Nitpick comments (3)
ui/app/providers/configure/page.tsx (1)

14-23: Gate auto-select to avoid premature dispatch and accidental “create-new” override.

Add an isSuccess guard (from RTK Query) and trim the deps to reduce re-runs. This avoids dispatching before data is ready and prevents auto-select from hijacking a create-new flow when selectedProvider is intentionally unset.

  • Confirm: is there a separate “create new provider” path that relies on selectedProvider being empty? If yes, consider gating this effect behind a route flag or explicit “edit” mode.

Apply:

-	useEffect(() => {
-		if (!selectedProvider && providersData?.providers && providersData.providers.length > 0) {
+	useEffect(() => {
+		if (!selectedProvider && providersData?.providers?.length) {
 			const providerToSelect = providersData.providers[0];
 			// Update Redux state to select this provider
 			dispatch(setSelectedProvider(providerToSelect));
 		}
-	}, [selectedProvider, providersData?.providers, dispatch]);
+	}, [selectedProvider, providersData?.providers?.length, dispatch]);

And also destructure isSuccess (keep usage inline if you prefer):

// near Line 12
const { data: providersData, refetch, isSuccess } = useGetProvidersQuery();

Optionally tighten the condition further:

- if (!selectedProvider && providersData?.providers?.length) {
+ if (!selectedProvider && isSuccess && providersData?.providers?.length) {

Nit: if provider ordering isn’t deterministic, consider sorting before picking index 0 to avoid UI surprises.

core/schemas/provider.go (1)

231-238: Clarify nil semantics for CustomProviderConfig.AllowedRequests.

Make the “not allow-all” behavior explicit to avoid confusion with AllowedRequests’ general nil semantics.

-	if cpc.AllowedRequests == nil {
-		// Use provider capabilities as default when no explicit restrictions are set
+	if cpc.AllowedRequests == nil {
+		// Note: When AllowedRequests is nil on CustomProviderConfig, we default to the
+		// base provider's capabilities (NOT "allow all"). This keeps unsupported ops disabled
+		// even without explicit restrictions.
 		defaultAllowedRequests := GetDefaultAllowedRequestsForProvider(cpc.BaseProviderType)
 		return defaultAllowedRequests.IsOperationAllowed(operation)
 	}
transports/bifrost-http/lib/config.go (1)

1854-1872: Good normalization of AllowedRequests; minor dedupe.

Logic aligns with PR goals. You can simplify the nil branch by reusing the helper.

-		caps := schemas.GetProviderCapabilities(cpc.BaseProviderType)
-		cpc.AllowedRequests = &schemas.AllowedRequests{
-			TextCompletion:       caps.TextCompletion,
-			ChatCompletion:       caps.ChatCompletion,
-			ChatCompletionStream: caps.ChatCompletionStream,
-			Embedding:            caps.Embedding,
-			Speech:               caps.Speech,
-			SpeechStream:         caps.SpeechStream,
-			Transcription:        caps.Transcription,
-			TranscriptionStream:  caps.TranscriptionStream,
-		}
+		cpc.AllowedRequests = schemas.GetDefaultAllowedRequestsForProvider(cpc.BaseProviderType)
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 6507562 and fb5f099.

📒 Files selected for processing (8)
  • core/schemas/provider.go (2 hunks)
  • docs/features/custom-providers.mdx (1 hunks)
  • transports/bifrost-http/handlers/providers.go (1 hunks)
  • transports/bifrost-http/lib/config.go (2 hunks)
  • ui/app/providers/configure/page.tsx (2 hunks)
  • ui/app/providers/configure/provider-form.tsx (15 hunks)
  • ui/app/providers/views/providers-list.tsx (1 hunks)
  • ui/lib/constants/config.ts (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • ui/app/providers/views/providers-list.tsx
🚧 Files skipped from review as they are similar to previous changes (4)
  • ui/lib/constants/config.ts
  • transports/bifrost-http/handlers/providers.go
  • docs/features/custom-providers.mdx
  • ui/app/providers/configure/provider-form.tsx
🧰 Additional context used
🧬 Code graph analysis (2)
transports/bifrost-http/lib/config.go (1)
core/schemas/provider.go (3)
  • AllowedRequests (87-96)
  • ValidateAllowedRequests (188-221)
  • GetProviderCapabilities (127-177)
core/schemas/provider.go (2)
core/schemas/bifrost.go (5)
  • ModelProvider (38-38)
  • OpenAI (41-41)
  • Anthropic (43-43)
  • Cohere (45-45)
  • Bedrock (44-44)
ui/lib/types/config.ts (2)
  • ModelProvider (12-12)
  • AllowedRequests (88-97)
🔇 Additional comments (3)
ui/app/providers/configure/page.tsx (1)

3-5: LGTM — imports and hook usage look correct.

core/schemas/provider.go (1)

179-185: LGTM — clear helper returning provider defaults.

transports/bifrost-http/lib/config.go (1)

1905-1907: LGTM — update path reuses creation validation (consistent sanitization).

@TejasGhatte TejasGhatte force-pushed the 09-01-fix_base_provider_level_request_level_restriction branch from fb5f099 to e5ac17c Compare September 4, 2025 12:57
@TejasGhatte TejasGhatte force-pushed the 09-01-fix_base_provider_level_request_level_restriction branch from e5ac17c to af1820c Compare September 4, 2025 12:58
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

♻️ Duplicate comments (1)
ui/lib/constants/config.ts (1)

97-101: Narrow lookup key; reuse shared fallback (repeat of prior suggestion).

Use keyof typeof PROVIDER_DEFAULT_ALLOWED_REQUESTS for the normalized key to gain type safety.

-export const getProviderDefaultAllowedRequests = (providerName: string): AllowedRequests => {
-  const normalizedName = providerName.toLowerCase().trim();
-  return PROVIDER_DEFAULT_ALLOWED_REQUESTS[normalizedName] ?? (DEFAULT_ALLOWED_REQUESTS as AllowedRequests);
-};
+export const getProviderDefaultAllowedRequests = (providerName: string): AllowedRequests => {
+  const key = providerName.toLowerCase().trim() as keyof typeof PROVIDER_DEFAULT_ALLOWED_REQUESTS;
+  return PROVIDER_DEFAULT_ALLOWED_REQUESTS[key] ?? (DEFAULT_ALLOWED_REQUESTS as AllowedRequests);
+};
🧹 Nitpick comments (1)
ui/lib/constants/config.ts (1)

35-95: Type-safe provider map; cover all known providers to prevent drift.

  • Type the map against Provider to eliminate key typos and make intent explicit.
  • Using Partial<Record<Provider,...>> keeps it flexible while still tied to the union.
  • Consider adding entries for azure, cerebras, groq, mistral, ollama, parasail, sgl, vertex to avoid the all-true fallback UX for those bases.

Apply:

+// Tie defaults to the Provider union to avoid key drift/typos
+import type { Provider } from "@/lib/constants/logs";
@@
-export const PROVIDER_DEFAULT_ALLOWED_REQUESTS: Record<string, AllowedRequests> = {
+export const PROVIDER_DEFAULT_ALLOWED_REQUESTS = {
   // OpenAI
   openai: {
@@
   // Gemini
   gemini: {
@@
-};
+} as const satisfies Partial<Record<Provider, AllowedRequests>>;

If desired, add stubs (with correct booleans from core) for the remaining providers:

// azure: { /* fill from core GetProviderCapabilities */ },
// cerebras: { /* ... */ },
// groq: { /* ... */ },
// mistral: { /* ... */ },
// ollama: { /* ... */ },
// parasail: { /* ... */ },
// sgl: { /* ... */ },
// vertex: { /* ... */ },

To keep UI in lockstep with core, extend the existing guardrail to include all providers present in KNOWN_PROVIDERS, failing on any mismatch. I can wire this up if you want.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between fb5f099 and af1820c.

📒 Files selected for processing (9)
  • core/schemas/provider.go (2 hunks)
  • docs/features/custom-providers.mdx (1 hunks)
  • transports/bifrost-http/handlers/providers.go (1 hunks)
  • transports/bifrost-http/lib/config.go (2 hunks)
  • ui/app/providers/configure/page.tsx (2 hunks)
  • ui/app/providers/configure/provider-form.tsx (15 hunks)
  • ui/app/providers/views/providers-list.tsx (1 hunks)
  • ui/lib/constants/config.ts (1 hunks)
  • ui/lib/constants/logs.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (7)
  • transports/bifrost-http/handlers/providers.go
  • ui/app/providers/views/providers-list.tsx
  • transports/bifrost-http/lib/config.go
  • ui/app/providers/configure/page.tsx
  • docs/features/custom-providers.mdx
  • core/schemas/provider.go
  • ui/app/providers/configure/provider-form.tsx
🧰 Additional context used
🧬 Code graph analysis (1)
ui/lib/constants/config.ts (2)
core/schemas/provider.go (1)
  • AllowedRequests (87-96)
ui/lib/types/config.ts (1)
  • AllowedRequests (88-97)
🔇 Additional comments (1)
ui/lib/constants/config.ts (1)

32-32: Good: strong shape guarantee for defaults.

satisfies Required<AllowedRequests> is the right guard to keep the constant in sync with the interface.

}

// GetProviderCapabilities returns the capabilities for a given provider
func GetProviderCapabilities(provider ModelProvider) AllowedRequests {
Copy link
Collaborator

Choose a reason for hiding this comment

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

@TejasGhatte pls change its name to get GetBaseProviderCapabilities cause it only contains the base providers, not all

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.

3 participants