Skip to content

fix: ui fixes for providers#478

Merged
Pratham-Mishra04 merged 1 commit into
mainfrom
09-16-fix_ui_fixes_for_providers
Sep 17, 2025
Merged

fix: ui fixes for providers#478
Pratham-Mishra04 merged 1 commit into
mainfrom
09-16-fix_ui_fixes_for_providers

Conversation

@TejasGhatte
Copy link
Copy Markdown
Collaborator

@TejasGhatte TejasGhatte commented Sep 16, 2025

Summary

Enhanced the custom provider configuration UI with granular request type controls and improved form handling for provider settings.

Solves #445

Changes

  • Added AllowedRequestsFields component to configure which request types a custom provider can handle
  • Implemented the component in both the "Add Custom Provider" dialog and existing provider configuration forms
  • Enhanced the network form fragment with extra headers configuration and retry backoff settings
  • Improved dialog titles to reflect whether adding or editing a key
  • Added conditional restart alerts that only show when forms are dirty
  • Made API keys section conditional based on provider requirements

Type of change

  • Bug fix
  • Feature
  • Refactor
  • Documentation
  • Chore/CI

Affected areas

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

How to test

  1. Navigate to the Providers section in the UI
  2. Test adding a new custom provider and verify the allowed request types can be configured
  3. Edit an existing provider and check that the network settings include extra headers and retry backoff options
  4. Verify that restart alerts only appear when changes are made
  5. Test adding/editing provider keys and confirm the dialog titles are correct
# UI
cd ui
pnpm i
pnpm dev

Screenshots/Recordings

N/A

Breaking changes

  • Yes
  • No

Related issues

N/A

Security considerations

No significant security implications. The changes are UI enhancements for configuration options that already exist in the backend.

Checklist

  • I read docs/contributing/README.md and followed the guidelines
  • I added/updated tests where appropriate
  • I updated documentation where needed
  • I verified builds succeed (Go and UI)
  • I verified the CI pipeline passes locally if applicable

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Sep 16, 2025

Caution

Review failed

The pull request is closed.

📝 Walkthrough

Summary by CodeRabbit

  • New Features

    • Configure allowed request types for providers via toggles.
    • Network settings: add Extra Headers (JSON) and retry backoff (initial/max) fields.
    • Dynamic dialog titles/messages when adding vs. editing keys; success toast on key deletion.
    • Conditional display of API keys section based on provider.
  • Refactor

    • Consolidated allowed-request controls into a reusable component.
    • Restart alerts now show only when there are unsaved changes; improved dialog behavior/scrolling.
  • Documentation

    • Observability docs revamped with clearer capabilities, governance/security, and alerts.
  • Chores

    • Version bumps across core, framework, transports, and multiple plugins.

Walkthrough

Adds per-provider allowed-request toggles and an AllowedRequestsFields component; threads allowed_requests into provider create/update payloads; makes restart-required alerts conditional on form dirtiness; enhances network config with extra_headers and retry backoff fields plus validation; updates schemas and types; removes Maxim plugin UI; adjusts dialogs and minor UX; bumps multiple version strings.

Changes

Cohort / File(s) Summary of Changes
Custom Provider Dialog
ui/app/providers/dialogs/addNewCustomProviderDialog.tsx
Adds allowed_requests schema/defaults to form and includes custom_provider_config.allowed_requests in mutation payload; swaps Dialog open handling to onOpenChange for close callback; adds max-scroll styling; shows inline Alert when form is dirty; integrates AllowedRequestsFields; updates imports.
Add/Edit Key Dialog
ui/app/providers/dialogs/addNewKeyDialog.tsx
Infers edit vs add mode to set dialog title and success toast message; no other control-flow changes.
Allowed Requests component
ui/app/providers/fragments/allowedRequestsFields.tsx
New AllowedRequestsFields client component exporting toggles bound to react-hook-form with optional namePrefix; renders eight request-type switches.
API Structure form
ui/app/providers/fragments/apiStructureFormFragment.tsx
Replaces inline allowed-requests UI with AllowedRequestsFields; replaces unconditional banner with Alert/AlertDescription + AlertTriangle and shows it only when showRestartAlert && form.formState.isDirty; updates imports.
Fragments barrel export
ui/app/providers/fragments/index.ts
Re-exports AllowedRequestsFields.
Network form enhancements
ui/app/providers/fragments/networkFormFragment.tsx
Adds Textarea for network_config.extra_headers with parse-on-blur behavior (stores string or parsed object/undefined); includes extra_headers in submit payload; introduces retry_backoff_initial and retry_backoff_max with UI, default/reset logic and validation; restart banner shown only when showRestartAlert && form.formState.isDirty.
Proxy form alert gating
ui/app/providers/fragments/proxyFormFragment.tsx
Restart alert now renders only when showRestartAlert && form.formState.isDirty.
Provider config view
ui/app/providers/views/modelProviderConfig.tsx
Uses keysRequired(provider.name) to conditionally show API keys section; passes showRestartAlert to ApiStructure, Network, and Proxy fragments; fragment signatures updated to accept showRestartAlert.
Schemas / Types
ui/lib/types/schemas.ts
networkFormConfigSchema adds extra_headers?: Record<string,string> and retry_backoff_initial/retry_backoff_max (coerced non‑negative numbers) with a refine enforcing retry_backoff_initial <= retry_backoff_max; coreConfigSchema adds max_request_body_size_mb (min 1, default 100).
Core config types
ui/lib/types/config.ts
Removed enable_maxim: boolean from exported CoreConfig interface.
Plugins form (UI)
ui/app/config/views/pluginsForm.tsx
Removes Maxim plugin support and related UI/state/side-effects; narrows plugin UI to semantic cache only; cleans up imports and debounced logic.
Default config page
ui/app/config/page.tsx
defaultConfig explicitly typed as CoreConfig; removes plugins field from default object.
Provider keys table
ui/app/providers/views/modelProviderKeysTableView.tsx
Shows a success toast on successful key deletion before closing delete dialog.
Docs
docs/features/observability.mdx
Rewrote observability doc to a narrative capability-focused layout; added Governance, Alerts & SLAs, reorganized sections, added generation-name to reserved keys.
Version bumps
core/version, framework/version, plugins/*/version, transports/version
Multiple version string updates across core, framework, plugins, and transports.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor User
  participant Dialog as AddNewCustomProviderDialog
  participant Form as react-hook-form
  participant Fields as AllowedRequestsFields
  participant API as Mutation
  participant Backend

  User->>Dialog: Open dialog
  Dialog->>Form: Initialize (allowed_requests defaults = true)
  User->>Fields: Toggle request types
  Fields-->>Form: Update values
  User->>Form: Submit
  Form->>API: Send payload (includes custom_provider_config.allowed_requests)
  API->>Backend: POST
  Backend-->>API: Response
  API-->>Dialog: Close / notify
Loading
sequenceDiagram
  autonumber
  actor User
  participant Network as NetworkFormFragment
  participant Textarea as ExtraHeadersTextarea
  participant Schema as ZodSchema

  User->>Textarea: Type JSON text
  User->>Textarea: Blur
  Textarea->>Network: Try JSON.parse
  alt Valid JSON object
    Network-->>Network: Set extra_headers = parsed object
  else Invalid or empty
    Network-->>Network: Keep string or set undefined
  end
  User->>Network: Submit
  Network->>Schema: Validate (retry_backoff_initial <= retry_backoff_max)
  Schema-->>Network: Result (ok / error)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

I twitch my nose at toggles bright,
Eight little switches in the night.
Headers whisper JSON strings,
Backoffs count their patient swings.
Save the keys — the restart waits — hooray, hop to delight! 🐇✨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 11.11% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
Title Check ❓ Inconclusive The title "fix: ui fixes for providers" is related to the PR's area (provider UI) but is overly generic and misleading because the changes include feature additions and refactors (e.g., AllowedRequestsFields, extra headers, retry backoff, schema/type updates) rather than only bug fixes; therefore the title does not clearly summarize the primary changes. Please update the title to be more specific and use an appropriate conventional prefix (feat/refactor) so it reflects the main changes; for example: "feat(ui/providers): add allowed request-type toggles and network extra-headers/retry backoff" or "refactor(ui/providers): consolidate provider forms and add allowed-requests controls".
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed The PR description largely follows the repository template and includes a clear Summary, Changes, Type of change, Affected areas, How to test, Breaking changes, Security considerations, and a filled Checklist, so it is mostly complete and actionable for reviewers. However the Summary states "Solves #445" while the Related issues section lists "N/A", and Screenshots/Recordings is "N/A" despite UI changes where visual proof would be helpful.

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6a67135 and dbf1853.

📒 Files selected for processing (24)
  • core/version (1 hunks)
  • docs/features/observability.mdx (1 hunks)
  • framework/version (1 hunks)
  • plugins/governance/version (1 hunks)
  • plugins/jsonparser/version (1 hunks)
  • plugins/logging/version (1 hunks)
  • plugins/maxim/version (1 hunks)
  • plugins/mocker/version (1 hunks)
  • plugins/semanticcache/version (1 hunks)
  • plugins/telemetry/version (1 hunks)
  • transports/version (1 hunks)
  • ui/app/config/page.tsx (1 hunks)
  • ui/app/config/views/pluginsForm.tsx (3 hunks)
  • ui/app/providers/dialogs/addNewCustomProviderDialog.tsx (5 hunks)
  • ui/app/providers/dialogs/addNewKeyDialog.tsx (3 hunks)
  • ui/app/providers/fragments/allowedRequestsFields.tsx (1 hunks)
  • ui/app/providers/fragments/apiStructureFormFragment.tsx (4 hunks)
  • ui/app/providers/fragments/index.ts (1 hunks)
  • ui/app/providers/fragments/networkFormFragment.tsx (4 hunks)
  • ui/app/providers/fragments/proxyFormFragment.tsx (1 hunks)
  • ui/app/providers/views/modelProviderConfig.tsx (4 hunks)
  • ui/app/providers/views/modelProviderKeysTableView.tsx (1 hunks)
  • ui/lib/types/config.ts (0 hunks)
  • ui/lib/types/schemas.ts (3 hunks)

Tip

👮 Agentic pre-merge checks are now available in preview!

Pro plan users can now enable pre-merge checks in their settings to enforce checklists before merging PRs.

  • Built-in checks – Quickly apply ready-made checks to enforce title conventions, require pull request descriptions that follow templates, validate linked issues for compliance, and more.
  • Custom agentic checks – Define your own rules using CodeRabbit’s advanced agentic capabilities to enforce organization-specific policies and workflows. For example, you can instruct CodeRabbit’s agent to verify that API documentation is updated whenever API schema files are modified in a PR. Note: Upto 5 custom checks are currently allowed during the preview period. Pricing for this feature will be announced in a few weeks.

Please see the documentation for more information.

Example:

reviews:
  pre_merge_checks:
    custom_checks:
      - name: "Undocumented Breaking Changes"
        mode: "warning"
        instructions: |
          Pass/fail criteria: All breaking changes to public APIs, CLI flags, environment variables, configuration keys, database schemas, or HTTP/GraphQL endpoints must be documented in the "Breaking Change" section of the PR description and in CHANGELOG.md. Exclude purely internal or private changes (e.g., code not exported from package entry points or explicitly marked as internal).

Please share your feedback with us on this Discord post.


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

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Collaborator Author

TejasGhatte commented Sep 16, 2025

@TejasGhatte TejasGhatte marked this pull request as ready for review September 16, 2025 11:10
Copy link
Copy Markdown
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

Caution

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

⚠️ Outside diff range comments (1)
ui/app/providers/fragments/networkFormFragment.tsx (1)

209-227: “Remove configuration” bypasses validation, doesn’t remove config, and blocks custom providers.

  • Calls onSubmit(getValues()) (bypasses resolver).
  • Spreads existing provider.network_config, so fields persist.
  • Fails for custom providers due to base URL check.

Apply this diff to truly remove the config and keep UX consistent:

-          <Button
-            type="button"
-            variant="outline"
-            onClick={() => {
-              form.reset({
-                network_config: undefined,
-              });
-              onSubmit(form.getValues());
-            }}
-            disabled={
-              isUpdatingProvider ||
-              !provider.network_config ||
-              !provider.network_config.base_url ||
-              provider.network_config.base_url.trim() === ""
-            }
-          >
+          <Button
+            type="button"
+            variant="outline"
+            onClick={() => {
+              updateProvider({ ...provider, network_config: undefined })
+                .unwrap()
+                .then(() => {
+                  form.reset({ network_config: undefined });
+                  toast.success("Network configuration removed.");
+                })
+                .catch((err) =>
+                  toast.error("Failed to update provider configuration", { description: getErrorMessage(err) }),
+                );
+            }}
+            disabled={isUpdatingProvider || !provider.network_config}
+          >
             Remove configuration
           </Button>

Also applies to: 218-223

🧹 Nitpick comments (16)
ui/app/providers/dialogs/addNewKeyDialog.tsx (1)

20-21: onOpenChange handler should consume the boolean argument

Passing onCancel (no-arg) to onOpenChange?: (open: boolean) => void can be a type mismatch in stricter TS configs. Forward the boolean and close only on false.

Apply this diff:

-  <Dialog open={show} onOpenChange={onCancel}>
+  <Dialog open={show} onOpenChange={(open) => !open && onCancel()}>
ui/lib/types/schemas.ts (2)

97-99: Fix validation message for max_retries

Message says “greater than 0” but min(0) allows 0. Align the copy.

-  .min(0, "Max retries must be greater than 0")
+  .min(0, "Max retries must be at least 0")

100-106: Backoff constraints: copy does not match numeric mins

The messages (100ms/1000ms) don’t match the actual mins (500/5000). Align messages to avoid confusing users.

 retry_backoff_initial: z.coerce
   .number("Retry backoff initial must be a number")
-  .min(500, "Initial backoff must be at least 100ms"),
+  .min(500, "Initial backoff must be at least 500ms"),
 retry_backoff_max: z.coerce
   .number("Retry backoff max must be a number")
-  .min(5000, "Max backoff must be at least 1000ms"),
+  .min(5000, "Max backoff must be at least 5000ms"),

Also applies to: 103-106

ui/app/providers/fragments/allowedRequestsFields.tsx (1)

12-21: Preserve literal types for request keys

Adding as const tightens types and helps avoid typos at call sites.

-const REQUEST_TYPES = [
+const REQUEST_TYPES = [
   { key: "text_completion", label: "Text Completion" },
   { key: "chat_completion", label: "Chat Completion" },
   { key: "chat_completion_stream", label: "Chat Completion Stream" },
   { key: "embedding", label: "Embedding" },
   { key: "speech", label: "Speech" },
   { key: "speech_stream", label: "Speech Stream" },
   { key: "transcription", label: "Transcription" },
   { key: "transcription_stream", label: "Transcription Stream" },
-];
+] as const;
ui/app/providers/views/modelProviderConfig.tsx (1)

47-49: Memo dependency may miss tab changes for custom providers

availableTabs(provider) depends on provider.custom_provider_config presence, but the memo key only tracks provider.name. Include the relevant bit to prevent stale tabs.

-  const tabs = useMemo(() => {
-    return availableTabs(provider);
-  }, [provider.name]);
+  const tabs = useMemo(() => availableTabs(provider), [provider.name, !!provider.custom_provider_config]);
ui/app/providers/dialogs/addNewCustomProviderDialog.tsx (3)

16-31: Avoid schema duplication; reuse central schemas

allowedRequestsSchema is already defined in @/lib/types/schemas. Duplicating it risks drift. Also, validate baseFormat against knownProviderSchema instead of a free string.

-import { z } from "zod";
+import { z } from "zod";
+import { allowedRequestsSchema, knownProviderSchema } from "@/lib/types/schemas";
@@
-const allowedRequestsSchema = z.object({
-  text_completion: z.boolean(),
-  chat_completion: z.boolean(),
-  chat_completion_stream: z.boolean(),
-  embedding: z.boolean(),
-  speech: z.boolean(),
-  speech_stream: z.boolean(),
-  transcription: z.boolean(),
-  transcription_stream: z.boolean(),
-});
+// Reuse centralized schemas to prevent drift.
@@
-const formSchema = z.object({
-  name: z.string().min(1),
-  baseFormat: z.string().min(1),
-  allowed_requests: allowedRequestsSchema,
-});
+const formSchema = z.object({
+  name: z.string().min(1),
+  baseFormat: knownProviderSchema, // restrict to known provider values
+  allowed_requests: allowedRequestsSchema,
+});

83-85: onOpenChange should use the boolean argument

Same as the keys dialog: consume the open flag and close on false to satisfy the prop type.

-  <Dialog open={show} onOpenChange={onClose}>
+  <Dialog open={show} onOpenChange={(open) => !open && onClose()}>

16-31: Optional: consolidate imports via fragments index

Minor import hygiene: prefer importing AllowedRequestsFields from the fragments barrel to keep import style consistent.

-import { AllowedRequestsFields } from "../fragments/allowedRequestsFields";
+import { AllowedRequestsFields } from "../fragments";

Also applies to: 48-57, 61-68

ui/app/providers/fragments/networkFormFragment.tsx (5)

42-67: Coerce extra_headers on submit; clear dirty state on success.

Guarantee an object shape for headers before sending and reset form after a successful save.

Apply this diff:

-const onSubmit = (data: NetworkOnlyFormSchema) => {
+const onSubmit = (data: NetworkOnlyFormSchema) => {
   if (isCustomProvider && !(data.network_config?.base_url || "").trim()) {
     toast.error("Base URL is required for custom providers.");
     return;
   }
-  // Create updated provider configuration
+  // Coerce/validate extra_headers to an object
+  const rawHeaders = data.network_config?.extra_headers as unknown;
+  let extraHeaders: Record<string, string> | undefined;
+  if (typeof rawHeaders === "string") {
+    try {
+      const parsed = JSON.parse(rawHeaders);
+      if (!parsed || typeof parsed !== "object" || Array.isArray(parsed) || !Object.values(parsed).every((v) => typeof v === "string")) {
+        throw new Error("Invalid headers");
+      }
+      extraHeaders = parsed as Record<string, string>;
+    } catch {
+      toast.error("Extra headers must be valid JSON with string values.");
+      form.setError("network_config.extra_headers", { type: "custom", message: "Invalid headers JSON." });
+      return;
+    }
+  } else if (rawHeaders && typeof rawHeaders === "object") {
+    extraHeaders = rawHeaders as Record<string, string>;
+  }
+
+  // Create updated provider configuration
   const updatedProvider: ModelProvider = {
     ...provider,
     network_config: {
       ...provider.network_config,
       base_url: data.network_config?.base_url || undefined,
-      extra_headers: data.network_config?.extra_headers || undefined,
+      extra_headers: extraHeaders,
       default_request_timeout_in_seconds: data.network_config?.default_request_timeout_in_seconds ?? 30,
       max_retries: data.network_config?.max_retries ?? 0,
       retry_backoff_initial: data.network_config?.retry_backoff_initial ?? 500,
       retry_backoff_max: data.network_config?.retry_backoff_max ?? 10000,
     },
   };
-  updateProvider(updatedProvider)
-    .unwrap()
+  updateProvider(updatedProvider)
+    .unwrap()
+    .then(() => {
+      form.reset({ network_config: updatedProvider.network_config });
+      toast.success("Network configuration saved.");
+    })
     .catch((err) => {
       toast.error("Failed to update provider configuration", {
         description: getErrorMessage(err),
       });
     });
 };

114-121: Number inputs: avoid NaN/controlled-state glitches.

Typing clears to empty → Number("") ⇒ 0, or NaN may render “NaN”. Normalize empty to undefined and control the value.

Apply this diff:

-                      <Input placeholder="30" {...field} onChange={(e) => field.onChange(Number(e.target.value))} />
+                      <Input
+                        placeholder="30"
+                        {...field}
+                        value={field.value ?? ""}
+                        onChange={(e) => {
+                          const v = e.target.value.trim();
+                          field.onChange(v === "" ? undefined : Number(v));
+                        }}
+                      />
-                      <Input placeholder="0" {...field} onChange={(e) => field.onChange(Number(e.target.value))} />
+                      <Input
+                        placeholder="0"
+                        {...field}
+                        value={field.value ?? ""}
+                        onChange={(e) => {
+                          const v = e.target.value.trim();
+                          field.onChange(v === "" ? undefined : Number(v));
+                        }}
+                      />

Also applies to: 124-136


181-189: Backoff inputs: same empty/NaN issue; align placeholder with default.

Normalize input like above; also placeholder shows 5000 while default fallback is 10000.

Apply this diff:

-                      <Input placeholder="500" {...field} onChange={(e) => field.onChange(Number(e.target.value))} />
+                      <Input
+                        placeholder="500"
+                        {...field}
+                        value={field.value ?? ""}
+                        onChange={(e) => {
+                          const v = e.target.value.trim();
+                          field.onChange(v === "" ? undefined : Number(v));
+                        }}
+                      />
-                      <Input placeholder="5000" {...field} onChange={(e) => field.onChange(Number(e.target.value))} />
+                      <Input
+                        placeholder="10000"
+                        {...field}
+                        value={field.value ?? ""}
+                        onChange={(e) => {
+                          const v = e.target.value.trim();
+                          field.onChange(v === "" ? undefined : Number(v));
+                        }}
+                      />

Also applies to: 193-201


169-169: Non-standard class name.

wrap-anywhere isn’t a standard Tailwind class. Prefer break-words or break-all (or confirm a custom utility exists).


29-36: Schema-level coercion can simplify handlers.

Consider using z.coerce.number() with .min(0) etc. in networkOnlyFormSchema to drop manual Number(...) parsing and edge cases.

If you want, I can open a follow-up PR to update ui/lib/types/schemas.ts.

ui/app/providers/fragments/apiStructureFormFragment.tsx (3)

56-58: Reset preserves defaults poorly; merge with current values.

Resetting to provider.custom_provider_config alone can unset fields that rely on defaults. Merge with current values to keep defaults when provider omits keys.

Apply this diff:

-  useEffect(() => {
-    form.reset(provider.custom_provider_config);
-  }, [form, provider.name, provider.custom_provider_config]);
+  useEffect(() => {
+    form.reset({
+      base_provider_type:
+        provider.custom_provider_config?.base_provider_type ?? form.getValues().base_provider_type,
+      allowed_requests: {
+        ...form.getValues().allowed_requests,
+        ...provider.custom_provider_config?.allowed_requests,
+      },
+    });
+  }, [form, provider.name, provider.custom_provider_config]);

69-73: Clear dirty state after successful save.

Reset to current values so Save/alert states reflect reality.

Apply this diff:

-      .then(() => {
-        toast.success("Provider configuration updated successfully");
-      })
+      .then(() => {
+        form.reset(form.getValues());
+        toast.success("Provider configuration updated successfully");
+      })

13-13: Remove unused imports.

use from React and fi locale aren’t used.

-import { use, useEffect } from "react";
+import { useEffect } from "react";
-import { fi } from "zod/v4/locales";

Also applies to: 17-17

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0bcba23 and f5b100b.

📒 Files selected for processing (9)
  • ui/app/providers/dialogs/addNewCustomProviderDialog.tsx (5 hunks)
  • ui/app/providers/dialogs/addNewKeyDialog.tsx (3 hunks)
  • ui/app/providers/fragments/allowedRequestsFields.tsx (1 hunks)
  • ui/app/providers/fragments/apiStructureFormFragment.tsx (4 hunks)
  • ui/app/providers/fragments/index.ts (1 hunks)
  • ui/app/providers/fragments/networkFormFragment.tsx (4 hunks)
  • ui/app/providers/fragments/proxyFormFragment.tsx (1 hunks)
  • ui/app/providers/views/modelProviderConfig.tsx (4 hunks)
  • ui/lib/types/schemas.ts (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (5)
ui/app/providers/fragments/allowedRequestsFields.tsx (3)
ui/app/providers/fragments/index.ts (1)
  • AllowedRequestsFields (1-1)
ui/components/ui/form.tsx (3)
  • FormItem (161-161)
  • FormLabel (162-162)
  • FormControl (163-163)
ui/components/ui/switch.tsx (1)
  • Switch (36-36)
ui/app/providers/dialogs/addNewCustomProviderDialog.tsx (2)
ui/lib/types/schemas.ts (1)
  • allowedRequestsSchema (193-202)
ui/app/providers/fragments/allowedRequestsFields.tsx (1)
  • AllowedRequestsFields (23-76)
ui/app/providers/fragments/apiStructureFormFragment.tsx (1)
ui/app/providers/fragments/allowedRequestsFields.tsx (1)
  • AllowedRequestsFields (23-76)
ui/app/providers/views/modelProviderConfig.tsx (5)
ui/app/providers/views/utils.ts (1)
  • keysRequired (1-1)
ui/app/providers/fragments/apiStructureFormFragment.tsx (1)
  • ApiStructureFormFragment (31-147)
ui/app/providers/fragments/networkFormFragment.tsx (1)
  • NetworkFormFragment (24-251)
ui/app/providers/fragments/proxyFormFragment.tsx (1)
  • ProxyFormFragment (26-196)
ui/app/providers/views/modelProviderKeysTableView.tsx (1)
  • ModelProviderKeysTableView (31-174)
ui/app/providers/fragments/networkFormFragment.tsx (2)
ui/components/ui/textarea.tsx (1)
  • Textarea (18-18)
ui/components/ui/input.tsx (1)
  • Input (7-21)
⏰ Context from checks skipped due to timeout of 900000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (19)
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
🔇 Additional comments (14)
ui/app/providers/fragments/proxyFormFragment.tsx (1)

84-92: Restart alert gated by dirty-state — LGTM

Showing the alert only when showRestartAlert and the form is dirty is correct and consistent with other fragments.

ui/app/providers/dialogs/addNewKeyDialog.tsx (1)

15-18: Dynamic title/toast for add vs. edit — LGTM

isEditing, dialogTitle, and successMessage correctly improve UX with minimal surface change.

ui/app/providers/fragments/allowedRequestsFields.tsx (1)

23-75: Reusable allowed-requests fieldset — LGTM

Clean extraction, good RHF integration, and clear UI layout.

ui/app/providers/fragments/index.ts (1)

1-1: Re-export added — LGTM

Centralizing the export of AllowedRequestsFields improves import ergonomics.

ui/app/providers/views/modelProviderConfig.tsx (2)

78-85: Propagating restart-alert flag — LGTM

Passing showRestartAlert={true} to all fragments keeps behavior consistent across tabs.


94-99: Conditional API keys section — LGTM

Using keysRequired(provider.name) to gate the keys table is a good UX improvement.

ui/app/providers/dialogs/addNewCustomProviderDialog.tsx (3)

91-99: Restart alert on dirty state — LGTM

Good consistency with other forms; clear copy.


48-57: Sensible defaults for allowed requests — LGTM

Starting with all request types enabled reduces setup friction.


143-145: Component reuse — LGTM

Using AllowedRequestsFields keeps forms DRY and consistent.

ui/app/providers/fragments/networkFormFragment.tsx (2)

79-87: Conditional restart alert: good guard.

Rendering the alert only when both showRestartAlert and form.formState.isDirty are true is correct and avoids noise.


53-58: Backoff defaults changed; confirm product intent + schema guard.

You changed fallbacks to 500/10000 ms. Verify these align with backend/provider defaults and docs, and ensure cross‑field validation (initial <= max) is enforced at schema level.

Would you confirm that networkOnlyFormSchema enforces retry_backoff_initial <= retry_backoff_max and that the docs reflect 500/10000 ms?

ui/app/providers/fragments/apiStructureFormFragment.tsx (3)

7-7: Extraction to AllowedRequestsFields: good consolidation.

Removes duplication and centralizes allowed-requests UI.


83-91: Conditional restart alert: consistent and correct.

Good alignment with other fragments; gated by showRestartAlert && form.formState.isDirty.


121-123: Component usage is clean.

<AllowedRequestsFields control={form.control} /> reads well and keeps the fragment lean.

Comment thread ui/app/providers/fragments/networkFormFragment.tsx
@TejasGhatte TejasGhatte changed the base branch from 09-13-enhancement_configuration_updates_in_maxim_plugin to graphite-base/478 September 16, 2025 12:49
@TejasGhatte TejasGhatte force-pushed the 09-16-fix_ui_fixes_for_providers branch from f5b100b to 2748b9c Compare September 16, 2025 13:19
@TejasGhatte TejasGhatte changed the base branch from graphite-base/478 to 09-13-enhancement_configuration_updates_in_maxim_plugin September 16, 2025 13:19
@TejasGhatte TejasGhatte changed the base branch from 09-13-enhancement_configuration_updates_in_maxim_plugin to graphite-base/478 September 16, 2025 13:24
@TejasGhatte TejasGhatte force-pushed the 09-16-fix_ui_fixes_for_providers branch from 2748b9c to ef8079d Compare September 16, 2025 13:33
@TejasGhatte TejasGhatte changed the base branch from graphite-base/478 to 09-13-enhancement_configuration_updates_in_maxim_plugin September 16, 2025 13:34
@TejasGhatte TejasGhatte changed the base branch from 09-13-enhancement_configuration_updates_in_maxim_plugin to graphite-base/478 September 16, 2025 13:48
Copy link
Copy Markdown
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

Caution

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

⚠️ Outside diff range comments (1)
ui/lib/types/schemas.ts (1)

121-129: URL is required even for “environment”/“none” proxy types.

proxyConfigSchema marks url as required, contradicting the conditional refinements and the UI flow for “Environment”/“None”.

Apply:

 export const proxyConfigSchema = z
   .object({
     type: proxyTypeSchema,
-    url: z.url("Must be a valid URL"),
+    url: z.url("Must be a valid URL").optional(),
     username: z.string().optional(),
     password: z.string().optional(),
   })
   .refine((data) => !(data.type === "http" || data.type === "socks5") || (data.url && data.url.trim().length > 0), {
     message: "Proxy URL is required when using HTTP or SOCKS5 proxy",
     path: ["url"],
   })

Also applies to: 129-147

🧹 Nitpick comments (4)
ui/app/providers/fragments/proxyFormFragment.tsx (2)

33-41: Expose “None” in the proxy type UI and avoid empty-string values.

Currently the Select shows a blank state when the value is "none", which is confusing and makes the control’s value diverge from form state. Default to "none" and add an explicit option.

Apply:

@@
-      proxy_config: {
-        type: provider.proxy_config?.type,
+      proxy_config: {
+        type: provider.proxy_config?.type ?? "none",
@@
-                  <Select onValueChange={field.onChange} value={field.value === "none" ? "" : field.value}>
+                  <Select onValueChange={field.onChange} value={field.value ?? "none"}>
@@
-                    <SelectContent>
+                    <SelectContent>
+                      <SelectItem value="none">None</SelectItem>
                       <SelectItem value="http">HTTP</SelectItem>
                       <SelectItem value="socks5">SOCKS5</SelectItem>
                       <SelectItem value="environment">Environment</SelectItem>
                     </SelectContent>

Also applies to: 103-114


64-68: Avoid sending stale URL/credentials when type is “environment” or “none”.

If a user switches from HTTP/SOCKS5 to Environment, hidden fields can retain values and be sent unintentionally.

Apply:

-      proxy_config: {
-        type: data.proxy_config?.type ?? "none",
-        url: data.proxy_config?.url || undefined,
-        username: data.proxy_config?.username || undefined,
-        password: data.proxy_config?.password || undefined,
-      },
+      // Only include URL/creds when the proxy type actually needs them
+      ...(() => {
+        const type = data.proxy_config?.type ?? "none";
+        const needsAuth = type === "http" || type === "socks5";
+        return {
+          proxy_config: {
+            type,
+            url: needsAuth ? data.proxy_config?.url || undefined : undefined,
+            username: needsAuth ? data.proxy_config?.username || undefined : undefined,
+            password: needsAuth ? data.proxy_config?.password || undefined : undefined,
+          },
+        };
+      })(),
ui/lib/types/schemas.ts (1)

74-74: Align validation message with constraint for max_retries.

Message says “greater than 0” but constraint is min(0).

Apply:

-  max_retries: z.number().min(0, "Max retries must be greater than 0").max(10, "Max retries must be less than 10"),
+  max_retries: z.number().min(0, "Max retries must be greater than or equal to 0").max(10, "Max retries must be less than 10"),
ui/app/config/page.tsx (1)

301-305: Fix label association and description for Max Request Body Size.

The label’s htmlFor points to the wrong id, and the description is copy/pasted.

Apply:

-                <label htmlFor="initial-pool-size" className="text-sm font-medium">
-                  Max Request Body Size
+                <label htmlFor="max-request-body-size-mb" className="text-sm font-medium">
+                  Max Request Body Size (MB)
                 </label>
-                <p className="text-muted-foreground text-sm">The initial connection pool size.</p>
+                <p className="text-muted-foreground text-sm">
+                  Maximum allowed request body size in megabytes for HTTP and WebSocket requests.
+                </p>
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f5b100b and ef8079d.

📒 Files selected for processing (10)
  • ui/app/config/page.tsx (1 hunks)
  • ui/app/providers/dialogs/addNewCustomProviderDialog.tsx (5 hunks)
  • ui/app/providers/dialogs/addNewKeyDialog.tsx (3 hunks)
  • ui/app/providers/fragments/allowedRequestsFields.tsx (1 hunks)
  • ui/app/providers/fragments/apiStructureFormFragment.tsx (4 hunks)
  • ui/app/providers/fragments/index.ts (1 hunks)
  • ui/app/providers/fragments/networkFormFragment.tsx (4 hunks)
  • ui/app/providers/fragments/proxyFormFragment.tsx (1 hunks)
  • ui/app/providers/views/modelProviderConfig.tsx (4 hunks)
  • ui/lib/types/schemas.ts (3 hunks)
🚧 Files skipped from review as they are similar to previous changes (7)
  • ui/app/providers/fragments/index.ts
  • ui/app/providers/views/modelProviderConfig.tsx
  • ui/app/providers/fragments/allowedRequestsFields.tsx
  • ui/app/providers/dialogs/addNewCustomProviderDialog.tsx
  • ui/app/providers/fragments/apiStructureFormFragment.tsx
  • ui/app/providers/fragments/networkFormFragment.tsx
  • ui/app/providers/dialogs/addNewKeyDialog.tsx
🧰 Additional context used
🧬 Code graph analysis (1)
ui/app/config/page.tsx (1)
ui/lib/types/config.ts (1)
  • CoreConfig (210-221)
⏰ Context from checks skipped due to timeout of 900000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (9)
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
🔇 Additional comments (2)
ui/app/providers/fragments/proxyFormFragment.tsx (1)

84-92: Good: restart alert gated by form dirtiness.

Rendering the alert only when both showRestartAlert and form.formState.isDirty are true is correct and matches the stated UX.

ui/app/config/page.tsx (1)

18-29: LGTM: defaultConfig typed and updated with enable_maxim.

Consistent with CoreConfig and the schema changes.

Comment thread ui/lib/types/schemas.ts
@TejasGhatte TejasGhatte force-pushed the 09-16-fix_ui_fixes_for_providers branch from ef8079d to 1d82802 Compare September 16, 2025 14:05
@TejasGhatte TejasGhatte changed the base branch from graphite-base/478 to 09-13-enhancement_configuration_updates_in_maxim_plugin September 16, 2025 14:05
@TejasGhatte TejasGhatte force-pushed the 09-16-fix_ui_fixes_for_providers branch 2 times, most recently from 5805660 to 07dde20 Compare September 16, 2025 14:15
@TejasGhatte TejasGhatte force-pushed the 09-13-enhancement_configuration_updates_in_maxim_plugin branch from d6b2896 to d659da9 Compare September 16, 2025 15:14
@TejasGhatte TejasGhatte force-pushed the 09-16-fix_ui_fixes_for_providers branch 2 times, most recently from 5666888 to 1a69a17 Compare September 16, 2025 15:15
@Pratham-Mishra04 Pratham-Mishra04 force-pushed the 09-16-fix_ui_fixes_for_providers branch from 1a69a17 to a7859e0 Compare September 16, 2025 15:42
@Pratham-Mishra04 Pratham-Mishra04 force-pushed the 09-13-enhancement_configuration_updates_in_maxim_plugin branch from d659da9 to 729b729 Compare September 16, 2025 15:42
Copy link
Copy Markdown
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

Caution

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

⚠️ Outside diff range comments (1)
ui/app/providers/fragments/networkFormFragment.tsx (1)

220-224: “Remove configuration” doesn’t actually remove network_config and bypasses resolver.

This path resets the form and then reuses onSubmit, which rebuilds network_config (with defaults) instead of deleting it. Call the mutation directly with network_config: undefined.

Apply:

-            onClick={() => {
-              form.reset({
-                network_config: undefined,
-              });
-              onSubmit(form.getValues());
-            }}
+            onClick={async () => {
+              form.reset({ network_config: undefined });
+              try {
+                await updateProvider({ ...provider, network_config: undefined }).unwrap();
+                toast.success("Removed network configuration");
+              } catch (err) {
+                toast.error("Failed to remove provider configuration", { description: getErrorMessage(err) });
+              }
+            }}

Optionally relax the disabled condition to allow removal whenever provider.network_config exists, not only when base_url is set.

♻️ Duplicate comments (1)
ui/app/providers/fragments/networkFormFragment.tsx (1)

144-182: Extra headers: consider stricter onBlur validation (duplicate of earlier thread).

Current onBlur accepts any JSON object (arrays included) and doesn’t surface field-level errors. If schema requires Record<string, string>, either enforce here or guarantee it in zod.

If you prefer schema-level enforcement, ensure networkOnlyFormSchema uses something like:

  • z.record(z.string()) for values, and
  • a preprocess to parse string → object safely.
🧹 Nitpick comments (9)
ui/app/providers/fragments/apiStructureFormFragment.tsx (5)

83-91: Restart alert gating looks good; add a11y tweaks.

Add role and hide the icon from AT; set a warning variant if supported.

-{showRestartAlert && form.formState.isDirty && (
-  <Alert>
-    <AlertTriangle className="h-4 w-4" />
+{showRestartAlert && form.formState.isDirty && (
+  <Alert role="alert" variant="warning">
+    <AlertTriangle className="h-4 w-4" aria-hidden="true" />
     <AlertDescription>
       The settings below require a Bifrost service restart to take effect. Current connections will continue with existing settings
       until restart.
     </AlertDescription>
   </Alert>
 )}

56-58: Reset currently risks unsetting new boolean flags.

Resetting with a partial custom_provider_config can turn newly added request-type flags into undefined (rendering as false). Merge with defaults on reset.

-useEffect(() => {
-  form.reset(provider.custom_provider_config);
-}, [form, provider.name, provider.custom_provider_config]);
+useEffect(() => {
+  form.reset({
+    base_provider_type: provider.custom_provider_config?.base_provider_type ?? "openai",
+    allowed_requests: {
+      text_completion: provider.custom_provider_config?.allowed_requests?.text_completion ?? true,
+      chat_completion: provider.custom_provider_config?.allowed_requests?.chat_completion ?? true,
+      chat_completion_stream: provider.custom_provider_config?.allowed_requests?.chat_completion_stream ?? true,
+      embedding: provider.custom_provider_config?.allowed_requests?.embedding ?? true,
+      speech: provider.custom_provider_config?.allowed_requests?.speech ?? true,
+      speech_stream: provider.custom_provider_config?.allowed_requests?.speech_stream ?? true,
+      transcription: provider.custom_provider_config?.allowed_requests?.transcription ?? true,
+      transcription_stream: provider.custom_provider_config?.allowed_requests?.transcription_stream ?? true,
+    },
+  });
+}, [form, provider.name, provider.custom_provider_config]);

52-55: Exhaustive-deps: include dispatch.

Small cleanup to satisfy the linter and future-proof.

-useEffect(() => {
+useEffect(() => {
   dispatch(setProviderFormDirtyState(form.formState.isDirty));
-}, [form.formState.isDirty]);
+}, [dispatch, form.formState.isDirty]);

129-140: Tooltip on disabled Button won’t trigger.

Radix Tooltip won’t fire on disabled elements. Wrap the Button in a focusable span.

-<Tooltip>
-  <TooltipTrigger asChild>
-    <Button type="submit" disabled={!form.formState.isDirty || !form.formState.isValid} isLoading={isUpdatingProvider}>
-      Save API Structure Configuration
-    </Button>
-  </TooltipTrigger>
+<Tooltip>
+  <TooltipTrigger asChild>
+    <span tabIndex={0}>
+      <Button type="submit" disabled={!form.formState.isDirty || !form.formState.isValid} isLoading={isUpdatingProvider}>
+        Save API Structure Configuration
+      </Button>
+    </span>
+  </TooltipTrigger>
   {!form.formState.isValid && (
     <TooltipContent>
       <p>{form.formState.errors.root?.message || "Please fix validation errors"}</p>
     </TooltipContent>
   )}
 </Tooltip>

65-65: Avoid double cast.

Prefer a single cast (or better: type the Zod schema to KnownProvider).

- base_provider_type: data.base_provider_type as unknown as KnownProvider,
+ base_provider_type: data.base_provider_type as KnownProvider,
ui/app/providers/dialogs/addNewKeyDialog.tsx (2)

16-17: Optional: route user‑visible strings through i18n.

If the app uses localization, wrap these strings with your translation helper for consistency.

Also applies to: 28-28, 38-38


15-17: Fix isEditing guard to handle negative/out-of-range indices and missing provider.keys.

modelProviderKeysTableView.tsx passes keyIndex as 0..len or len for add (no -1 sentinel found). Make AddNewKeyDialog robust by validating keyIndex and provider.keys. Apply:

-const isEditing = keyIndex < provider.keys.length;
-const dialogTitle = isEditing ? "Edit key" : "Add new key";
-const successMessage = isEditing ? "Key updated successfully" : "Key added successfully";
+const keysLen = provider.keys?.length ?? 0;
+const isEditing = Number.isInteger(keyIndex) && keyIndex >= 0 && keyIndex < keysLen;
+const dialogTitle = isEditing ? "Edit Key" : "Add New Key";
+const successMessage = isEditing ? "Key updated successfully" : "Key added successfully";
ui/app/providers/fragments/networkFormFragment.tsx (2)

72-79: Use nullish coalescing and align defaults with onSubmit.

  • || will clobber valid 0 for default_request_timeout_in_seconds; use ??.
  • Keep retry_backoff_max consistent with onSubmit (choose 5000 or 10000, but be consistent with schema).

Apply:

       network_config: {
         base_url: provider.network_config?.base_url || "",
         extra_headers: provider.network_config?.extra_headers,
-        default_request_timeout_in_seconds: provider.network_config?.default_request_timeout_in_seconds || 30,
-        max_retries: provider.network_config?.max_retries || 0,
-        retry_backoff_initial: provider.network_config?.retry_backoff_initial || 500,
-        retry_backoff_max: provider.network_config?.retry_backoff_max || 5000,
+        default_request_timeout_in_seconds: provider.network_config?.default_request_timeout_in_seconds ?? 30,
+        max_retries: provider.network_config?.max_retries ?? 0,
+        retry_backoff_initial: provider.network_config?.retry_backoff_initial ?? 500,
+        retry_backoff_max: provider.network_config?.retry_backoff_max ?? 5000,
       },

183-210: Numeric inputs: use type=number and valueAsNumber with NaN guard.

Prevents accidental “empty → 0” coercion and improves mobile UX.

Apply:

-                      <Input placeholder="500" {...field} onChange={(e) => field.onChange(Number(e.target.value))} />
+                      <Input
+                        type="number"
+                        inputMode="numeric"
+                        min={0}
+                        step={100}
+                        placeholder="500"
+                        {...field}
+                        onChange={(e) => {
+                          const n = e.currentTarget.valueAsNumber;
+                          field.onChange(Number.isNaN(n) ? undefined : n);
+                        }}
+                      />
-                      <Input placeholder="5000" {...field} onChange={(e) => field.onChange(Number(e.target.value))} />
+                      <Input
+                        type="number"
+                        inputMode="numeric"
+                        min={0}
+                        step={100}
+                        placeholder="5000"
+                        {...field}
+                        onChange={(e) => {
+                          const n = e.currentTarget.valueAsNumber;
+                          field.onChange(Number.isNaN(n) ? undefined : n);
+                        }}
+                      />

For consistency, consider applying the same pattern to the Timeout and Max Retries fields above (lines 124 and 137).

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a7859e0 and 2771a81.

📒 Files selected for processing (21)
  • core/version (1 hunks)
  • framework/version (1 hunks)
  • plugins/governance/version (1 hunks)
  • plugins/jsonparser/version (1 hunks)
  • plugins/logging/version (1 hunks)
  • plugins/maxim/version (1 hunks)
  • plugins/mocker/version (1 hunks)
  • plugins/semanticcache/version (1 hunks)
  • plugins/telemetry/version (1 hunks)
  • transports/version (1 hunks)
  • ui/app/config/page.tsx (1 hunks)
  • ui/app/providers/dialogs/addNewCustomProviderDialog.tsx (5 hunks)
  • ui/app/providers/dialogs/addNewKeyDialog.tsx (3 hunks)
  • ui/app/providers/fragments/allowedRequestsFields.tsx (1 hunks)
  • ui/app/providers/fragments/apiStructureFormFragment.tsx (4 hunks)
  • ui/app/providers/fragments/index.ts (1 hunks)
  • ui/app/providers/fragments/networkFormFragment.tsx (4 hunks)
  • ui/app/providers/fragments/proxyFormFragment.tsx (1 hunks)
  • ui/app/providers/views/modelProviderConfig.tsx (4 hunks)
  • ui/app/providers/views/modelProviderKeysTableView.tsx (1 hunks)
  • ui/lib/types/schemas.ts (3 hunks)
✅ Files skipped from review due to trivial changes (7)
  • plugins/logging/version
  • plugins/semanticcache/version
  • transports/version
  • plugins/telemetry/version
  • plugins/governance/version
  • plugins/mocker/version
  • core/version
🚧 Files skipped from review as they are similar to previous changes (11)
  • framework/version
  • ui/app/providers/fragments/proxyFormFragment.tsx
  • plugins/maxim/version
  • ui/app/providers/views/modelProviderKeysTableView.tsx
  • ui/app/providers/fragments/allowedRequestsFields.tsx
  • ui/lib/types/schemas.ts
  • plugins/jsonparser/version
  • ui/app/providers/views/modelProviderConfig.tsx
  • ui/app/providers/fragments/index.ts
  • ui/app/providers/dialogs/addNewCustomProviderDialog.tsx
  • ui/app/config/page.tsx
🧰 Additional context used
🧬 Code graph analysis (2)
ui/app/providers/fragments/networkFormFragment.tsx (2)
ui/components/ui/textarea.tsx (1)
  • Textarea (18-18)
ui/components/ui/input.tsx (1)
  • Input (7-21)
ui/app/providers/fragments/apiStructureFormFragment.tsx (2)
ui/components/ui/alert.tsx (2)
  • Alert (41-41)
  • AlertDescription (41-41)
ui/app/providers/fragments/allowedRequestsFields.tsx (1)
  • AllowedRequestsFields (23-76)
⏰ Context from checks skipped due to timeout of 900000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (8)
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
🔇 Additional comments (9)
ui/app/providers/fragments/apiStructureFormFragment.tsx (3)

7-7: Nice dedup via AllowedRequestsFields.

Good move extracting the toggles into a shared fragment to remove duplication.


60-68: Confirm update semantics; avoid dropping unrelated config fields.

If updateProvider replaces custom_provider_config server‑side, this will discard fields owned by other tabs. Prefer shallow merge to preserve unknown keys.

-      custom_provider_config: {
-        base_provider_type: data.base_provider_type as unknown as KnownProvider,
-        allowed_requests: data.allowed_requests,
-      },
+      custom_provider_config: {
+        ...(provider.custom_provider_config ?? {}),
+        base_provider_type: data.base_provider_type as KnownProvider,
+        allowed_requests: {
+          ...(provider.custom_provider_config?.allowed_requests ?? {}),
+          ...data.allowed_requests,
+        },
+      },

Would you confirm whether the API performs a merge vs. replace? If replace, the above change is safer.


122-122: LGTM on integration of AllowedRequestsFields.

Good reuse and clear separation of concerns.

ui/app/providers/dialogs/addNewKeyDialog.tsx (3)

20-21: Confirm Dialog onOpenChange signature.

If Dialog expects (open: boolean) => void, passing onCancel: () => void is a type mismatch. Prefer:

-<Dialog open={show} onOpenChange={onCancel}>
+<Dialog open={show} onOpenChange={(open) => { if (!open) onCancel(); }}>

28-28: LGTM: dynamic title wired correctly.


38-38: LGTM: contextual success toast.

ui/app/providers/fragments/networkFormFragment.tsx (3)

7-7: Import looks good.

Textarea import is correct and scoped to the single usage below.


86-94: Nice: restart alert gated by isDirty.

Better UX; avoids spurious banners.


53-58: Fix defaults drift & allow true removal of network_config

File: ui/app/providers/fragments/networkFormFragment.tsx (lines 53-58)

  • If data.network_config is undefined this still constructs a network_config object (due to ...provider.network_config) so the remove flow doesn't actually remove it.
  • retry_backoff_max default here (10000) disagrees with reset (5000); keep a single source of truth for defaults.

Apply:

-    const updatedProvider: ModelProvider = {
-      ...provider,
-      network_config: {
-        ...provider.network_config,
-        base_url: data.network_config?.base_url || undefined,
-        extra_headers: data.network_config?.extra_headers || undefined,
-        default_request_timeout_in_seconds: data.network_config?.default_request_timeout_in_seconds ?? 30,
-        max_retries: data.network_config?.max_retries ?? 0,
-        retry_backoff_initial: data.network_config?.retry_backoff_initial ?? 500,
-        retry_backoff_max: data.network_config?.retry_backoff_max ?? 10000,
-      },
-    };
+    const nextNetworkConfig =
+      data.network_config === undefined
+        ? undefined
+        : {
+            ...provider.network_config,
+            base_url: (data.network_config.base_url || "").trim() || undefined,
+            extra_headers: data.network_config.extra_headers || undefined,
+            default_request_timeout_in_seconds: data.network_config.default_request_timeout_in_seconds ?? 30,
+            max_retries: data.network_config.max_retries ?? 0,
+            retry_backoff_initial: data.network_config.retry_backoff_initial ?? 500,
+            retry_backoff_max: data.network_config.retry_backoff_max ?? 5000,
+          };
+    const updatedProvider: ModelProvider = { ...provider, network_config: nextNetworkConfig };

Confirm the intended default for retry_backoff_max in the schema and make both places match.

@TejasGhatte TejasGhatte changed the base branch from 09-13-enhancement_configuration_updates_in_maxim_plugin to graphite-base/478 September 16, 2025 17:24
@Pratham-Mishra04 Pratham-Mishra04 force-pushed the 09-16-fix_ui_fixes_for_providers branch from 2771a81 to c5897d2 Compare September 16, 2025 19:59
@Pratham-Mishra04 Pratham-Mishra04 changed the base branch from graphite-base/478 to 09-13-enhancement_configuration_updates_in_maxim_plugin September 16, 2025 19:59
@Pratham-Mishra04 Pratham-Mishra04 force-pushed the 09-13-enhancement_configuration_updates_in_maxim_plugin branch from 2156d53 to 91e2d09 Compare September 16, 2025 20:47
@Pratham-Mishra04 Pratham-Mishra04 force-pushed the 09-16-fix_ui_fixes_for_providers branch from c5897d2 to 2dc4ebe Compare September 16, 2025 20:47
Copy link
Copy Markdown
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

🧹 Nitpick comments (7)
ui/app/providers/views/modelProviderConfig.tsx (7)

9-9: keysRequired import: verify provider IDs stay in sync with backend enums.

If backend identifiers change (e.g., "sgl" vs "sglx"), this UI gate could drift. Consider centralizing from a shared type or server‑driven capability flag.


47-53: useMemo dependency may be stale vs. what availableTabs(provider) actually uses.

availableTabs inspects provider.custom_provider_config, but the memo only depends on provider.name. Depend on provider (or include the specific fields) to avoid stale tabs.

-  const tabs = useMemo(() => {
-    return availableTabs(provider);
-  }, [provider.name]);
+  const tabs = useMemo(() => availableTabs(provider), [provider]);

66-66: Avoid mixing controlled value with defaultValue on Tabs.

You’re fully controlling with value; drop defaultValue to reduce confusion.

-  <Tabs defaultValue={tabs[0]?.id} value={selectedTab} onValueChange={setSelectedTab} className="space-y-6">
+  <Tabs value={selectedTab} onValueChange={setSelectedTab} className="space-y-6">

Optionally initialize state with the first tab to avoid an initial undefined:

- const [selectedTab, setSelectedTab] = useState<string | undefined>(undefined);
+ const [selectedTab, setSelectedTab] = useState<string | undefined>(() => availableTabs(provider)[0]?.id);

68-70: + 3 in gridTemplateColumns likely leaves empty columns.

Use tabs.length (or auto-fit) to match triggers and avoid layout gaps.

- style={{ gridTemplateColumns: `repeat(${tabs.length + 3}, 1fr)` }}
+ style={{ gridTemplateColumns: `repeat(${tabs.length}, 1fr)` }}

Or:

- style={{ gridTemplateColumns: `repeat(${tabs.length + 3}, 1fr)` }}
+ style={{ gridTemplateColumns: `repeat(auto-fit, minmax(0, 1fr))` }}

78-85: Passing showRestartAlert explicitly is good; minor DRY nit.

Consider a local const to avoid repetition and ease future toggling.

+ const showRestartAlert = true;
...
- <ApiStructureFormFragment provider={provider} showRestartAlert={true} />
+ <ApiStructureFormFragment provider={provider} showRestartAlert={showRestartAlert} />
...
- <NetworkFormFragment provider={provider} showRestartAlert={true} />
+ <NetworkFormFragment provider={provider} showRestartAlert={showRestartAlert} />
...
- <ProxyFormFragment provider={provider} showRestartAlert={true} />
+ <ProxyFormFragment provider={provider} showRestartAlert={showRestartAlert} />

4-6: Import consistency nit.

Either re-export NetworkFormFragment from the fragments index or import all fragments directly to keep import style uniform.


94-99: API keys section conditional render: looks good; consider UX hint.

Optional: add a brief caption explaining why keys are hidden for this provider to reduce user confusion.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2771a81 and 2dc4ebe.

📒 Files selected for processing (21)
  • core/version (1 hunks)
  • framework/version (1 hunks)
  • plugins/governance/version (1 hunks)
  • plugins/jsonparser/version (1 hunks)
  • plugins/logging/version (1 hunks)
  • plugins/maxim/version (1 hunks)
  • plugins/mocker/version (1 hunks)
  • plugins/semanticcache/version (1 hunks)
  • plugins/telemetry/version (1 hunks)
  • transports/version (1 hunks)
  • ui/app/config/page.tsx (1 hunks)
  • ui/app/providers/dialogs/addNewCustomProviderDialog.tsx (5 hunks)
  • ui/app/providers/dialogs/addNewKeyDialog.tsx (3 hunks)
  • ui/app/providers/fragments/allowedRequestsFields.tsx (1 hunks)
  • ui/app/providers/fragments/apiStructureFormFragment.tsx (4 hunks)
  • ui/app/providers/fragments/index.ts (1 hunks)
  • ui/app/providers/fragments/networkFormFragment.tsx (4 hunks)
  • ui/app/providers/fragments/proxyFormFragment.tsx (1 hunks)
  • ui/app/providers/views/modelProviderConfig.tsx (4 hunks)
  • ui/app/providers/views/modelProviderKeysTableView.tsx (1 hunks)
  • ui/lib/types/schemas.ts (3 hunks)
✅ Files skipped from review due to trivial changes (3)
  • transports/version
  • framework/version
  • plugins/governance/version
🚧 Files skipped from review as they are similar to previous changes (16)
  • plugins/semanticcache/version
  • plugins/logging/version
  • plugins/mocker/version
  • ui/app/providers/dialogs/addNewKeyDialog.tsx
  • core/version
  • ui/app/providers/fragments/proxyFormFragment.tsx
  • ui/app/config/page.tsx
  • ui/app/providers/views/modelProviderKeysTableView.tsx
  • plugins/telemetry/version
  • ui/app/providers/dialogs/addNewCustomProviderDialog.tsx
  • ui/app/providers/fragments/networkFormFragment.tsx
  • ui/app/providers/fragments/index.ts
  • ui/app/providers/fragments/allowedRequestsFields.tsx
  • ui/lib/types/schemas.ts
  • plugins/jsonparser/version
  • ui/app/providers/fragments/apiStructureFormFragment.tsx
🧰 Additional context used
🧬 Code graph analysis (1)
ui/app/providers/views/modelProviderConfig.tsx (4)
ui/app/providers/views/utils.ts (1)
  • keysRequired (1-1)
ui/app/providers/fragments/apiStructureFormFragment.tsx (1)
  • ApiStructureFormFragment (31-147)
ui/app/providers/fragments/networkFormFragment.tsx (1)
  • NetworkFormFragment (24-258)
ui/app/providers/fragments/proxyFormFragment.tsx (1)
  • ProxyFormFragment (26-196)
⏰ Context from checks skipped due to timeout of 900000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (12)
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
🔇 Additional comments (2)
ui/app/providers/views/modelProviderConfig.tsx (1)

55-55: Gating API keys UI is correct.

This keeps keys hidden for providers that don’t need them; aligns with PR goals.

plugins/maxim/version (1)

1-1: Version bump to 1.3.0 — verify release hygiene

Sanity check: plugins/maxim/version = 1.3.0; other version files found: core/version 1.1.34, framework/version 1.0.17, plugins/governance 1.2.10, plugins/jsonparser 1.2.9, plugins/logging 1.2.10, plugins/mocker 1.2.8, plugins/semanticcache 1.2.11, plugins/telemetry 1.2.9, transports/version 1.2.14. Confirm CHANGELOG/release notes updated and bump any dependent plugin/core/framework versions if this is intended as a coordinated stack release.

Copy link
Copy Markdown
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

🧹 Nitpick comments (7)
ui/app/providers/dialogs/addNewCustomProviderDialog.tsx (6)

16-25: Don’t duplicate allowedRequestsSchema; import the shared schema to avoid drift.

This inline schema mirrors ui/lib/types/schemas.ts. Centralize to the shared source.

-const allowedRequestsSchema = z.object({
-  text_completion: z.boolean(),
-  chat_completion: z.boolean(),
-  chat_completion_stream: z.boolean(),
-  embedding: z.boolean(),
-  speech: z.boolean(),
-  speech_stream: z.boolean(),
-  transcription: z.boolean(),
-  transcription_stream: z.boolean(),
-});

Add this import near the other imports:

+import { allowedRequestsSchema } from "@/lib/types/schemas";

27-31: Constrain baseFormat and require at least one allowed request.

  • Use a z.enum for base formats to prevent invalid values.
  • Add a refinement ensuring at least one request type is enabled.
-const formSchema = z.object({
-  name: z.string().min(1),
-  baseFormat: z.string().min(1),
-  allowed_requests: allowedRequestsSchema,
-});
+const formSchema = z
+  .object({
+    name: z.string().min(1),
+    baseFormat: z.enum(["openai", "anthropic", "gemini", "cohere", "bedrock"]),
+    allowed_requests: allowedRequestsSchema,
+  })
+  .refine(
+    (v) => Object.values(v.allowed_requests).some(Boolean),
+    { message: "Select at least one request type.", path: ["allowed_requests"] }
+  );

124-128: Use controlled value instead of defaultValue for Select.

defaultValue won’t update on form.reset(); use value for a controlled field.

-<Select onValueChange={field.onChange} defaultValue={field.value}>
+<Select onValueChange={field.onChange} value={field.value || undefined}>

61-67: Avoid unsafe cast to ModelProviderName.

data.name is free-form; casting to ModelProviderName bypasses type safety and can mis-shape the mutation payload if the union excludes custom names. Prefer widening the mutation type to accept a string for custom providers or validate the name against an allowed pattern.

Would you like me to propose typings for useCreateProviderMutation that separate known vs. custom providers?


48-57: DRY up default allowed_requests.

These defaults duplicate the schema fields. Consider a shared constant (e.g., ALL_REQUESTS_ENABLED) imported where needed to prevent drift.

Example:

// ui/lib/types/constants.ts
export const ALL_REQUESTS_ENABLED = {
  text_completion: true,
  chat_completion: true,
  chat_completion_stream: true,
  embedding: true,
  speech: true,
  speech_stream: true,
  transcription: true,
  transcription_stream: true,
} as const;

Then:

-allowed_requests: { ...inline... },
+allowed_requests: ALL_REQUESTS_ENABLED,

91-99: Confirm restart notice behavior and wording.

Showing the “restart required” alert as soon as the form is dirty may confuse users on initial creation. If restarts are only required after saving, consider gating on a showRestartAlert prop or displaying the notice post‑save.

Do we require a restart immediately upon creating a provider, or only after persisting changes?

ui/app/providers/fragments/apiStructureFormFragment.tsx (1)

17-17: Remove unused import.

The fi import from zod/v4/locales appears to be unused in this file and should be removed to keep imports clean.

Apply this diff to remove the unused import:

-import { fi } from "zod/v4/locales";
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2771a81 and 2dc4ebe.

📒 Files selected for processing (21)
  • core/version (1 hunks)
  • framework/version (1 hunks)
  • plugins/governance/version (1 hunks)
  • plugins/jsonparser/version (1 hunks)
  • plugins/logging/version (1 hunks)
  • plugins/maxim/version (1 hunks)
  • plugins/mocker/version (1 hunks)
  • plugins/semanticcache/version (1 hunks)
  • plugins/telemetry/version (1 hunks)
  • transports/version (1 hunks)
  • ui/app/config/page.tsx (1 hunks)
  • ui/app/providers/dialogs/addNewCustomProviderDialog.tsx (5 hunks)
  • ui/app/providers/dialogs/addNewKeyDialog.tsx (3 hunks)
  • ui/app/providers/fragments/allowedRequestsFields.tsx (1 hunks)
  • ui/app/providers/fragments/apiStructureFormFragment.tsx (4 hunks)
  • ui/app/providers/fragments/index.ts (1 hunks)
  • ui/app/providers/fragments/networkFormFragment.tsx (4 hunks)
  • ui/app/providers/fragments/proxyFormFragment.tsx (1 hunks)
  • ui/app/providers/views/modelProviderConfig.tsx (4 hunks)
  • ui/app/providers/views/modelProviderKeysTableView.tsx (1 hunks)
  • ui/lib/types/schemas.ts (3 hunks)
✅ Files skipped from review due to trivial changes (2)
  • plugins/mocker/version
  • plugins/jsonparser/version
🚧 Files skipped from review as they are similar to previous changes (17)
  • plugins/telemetry/version
  • ui/app/config/page.tsx
  • framework/version
  • ui/app/providers/views/modelProviderKeysTableView.tsx
  • core/version
  • ui/app/providers/dialogs/addNewKeyDialog.tsx
  • plugins/maxim/version
  • ui/app/providers/fragments/proxyFormFragment.tsx
  • plugins/semanticcache/version
  • ui/lib/types/schemas.ts
  • plugins/logging/version
  • plugins/governance/version
  • transports/version
  • ui/app/providers/views/modelProviderConfig.tsx
  • ui/app/providers/fragments/index.ts
  • ui/app/providers/fragments/allowedRequestsFields.tsx
  • ui/app/providers/fragments/networkFormFragment.tsx
🧰 Additional context used
🧬 Code graph analysis (2)
ui/app/providers/fragments/apiStructureFormFragment.tsx (1)
ui/app/providers/fragments/allowedRequestsFields.tsx (1)
  • AllowedRequestsFields (23-76)
ui/app/providers/dialogs/addNewCustomProviderDialog.tsx (2)
ui/lib/types/schemas.ts (1)
  • allowedRequestsSchema (193-202)
ui/app/providers/fragments/allowedRequestsFields.tsx (1)
  • AllowedRequestsFields (23-76)
⏰ Context from checks skipped due to timeout of 900000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (20)
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
🔇 Additional comments (8)
ui/app/providers/dialogs/addNewCustomProviderDialog.tsx (4)

84-84: DialogContent sizing/scrolling looks good.

Max height + custom scrollbar is consistent with long forms.


143-145: AllowedRequestsFields integration is clean.

Good reuse of the fragment with the default namePrefix. No issues.


6-6: Alert components import is appropriate.

Matches usage below; no issues.


13-15: New imports LGTM.

Icon and fragment paths are correct and used.

ui/app/providers/fragments/apiStructureFormFragment.tsx (4)

7-7: Good refactoring for code reusability.

The extraction of allowed requests fields into a dedicated component eliminates code duplication and improves maintainability across the provider configuration forms.


18-19: Good addition of proper Alert component.

The imports for Alert components are correctly added and align with the UI component structure.


83-91: Excellent improvement to conditional alert display.

The restart alert now correctly displays only when both showRestartAlert is true AND the form has been modified (form.formState.isDirty). This prevents unnecessary alerts from appearing when users haven't made any changes, improving the user experience.


122-122: Clean component usage.

The replacement of the duplicated allowed requests fields with the reusable AllowedRequestsFields component significantly reduces code duplication and maintains consistent functionality.

Comment thread ui/app/providers/dialogs/addNewCustomProviderDialog.tsx Outdated
@Pratham-Mishra04 Pratham-Mishra04 force-pushed the 09-16-fix_ui_fixes_for_providers branch 2 times, most recently from f2a70ce to ffff75a Compare September 17, 2025 05:02
@Pratham-Mishra04 Pratham-Mishra04 force-pushed the 09-16-fix_ui_fixes_for_providers branch from ffff75a to d37ab4a Compare September 17, 2025 05:24
Copy link
Copy Markdown
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 (1)
ui/app/providers/dialogs/addNewCustomProviderDialog.tsx (1)

83-85: onOpenChange handler fix matches Dialog’s signature

Good catch; wraps onClose on false as previously requested.

🧹 Nitpick comments (3)
ui/app/providers/dialogs/addNewCustomProviderDialog.tsx (2)

16-25: Deduplicate allowedRequestsSchema by importing the shared schema

This local schema duplicates ui/lib/types/schemas.ts and risks drift.

Apply this diff to remove the local definition:

-const allowedRequestsSchema = z.object({
-  text_completion: z.boolean(),
-  chat_completion: z.boolean(),
-  chat_completion_stream: z.boolean(),
-  embedding: z.boolean(),
-  speech: z.boolean(),
-  speech_stream: z.boolean(),
-  transcription: z.boolean(),
-  transcription_stream: z.boolean(),
-});

Then add this import (outside the changed hunk):

import { allowedRequestsSchema } from "@/lib/types/schemas";

48-57: Avoid inline defaults: extract a single source of truth for allowed_requests

Define a DEFAULT_ALLOWED_REQUESTS constant (or use schema defaults) and reuse across forms/dialogs to prevent divergence.

Example (place near imports):

const DEFAULT_ALLOWED_REQUESTS: z.infer<typeof allowedRequestsSchema> = {
  text_completion: true,
  chat_completion: true,
  chat_completion_stream: true,
  embedding: true,
  speech: true,
  speech_stream: true,
  transcription: true,
  transcription_stream: true,
};

Then:

allowed_requests: DEFAULT_ALLOWED_REQUESTS,
docs/features/observability.mdx (1)

230-230: Punctuation nit

Add a period for consistency with the surrounding bullets.

-* **Alerts & SLAs**: Threshold-based notifications to keep quality and latency in guardrails
+* **Alerts & SLAs**: Threshold-based notifications to keep quality and latency in guardrails.
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2dc4ebe and d37ab4a.

📒 Files selected for processing (22)
  • core/version (1 hunks)
  • docs/features/observability.mdx (1 hunks)
  • framework/version (1 hunks)
  • plugins/governance/version (1 hunks)
  • plugins/jsonparser/version (1 hunks)
  • plugins/logging/version (1 hunks)
  • plugins/maxim/version (1 hunks)
  • plugins/mocker/version (1 hunks)
  • plugins/semanticcache/version (1 hunks)
  • plugins/telemetry/version (1 hunks)
  • transports/version (1 hunks)
  • ui/app/config/page.tsx (1 hunks)
  • ui/app/providers/dialogs/addNewCustomProviderDialog.tsx (5 hunks)
  • ui/app/providers/dialogs/addNewKeyDialog.tsx (3 hunks)
  • ui/app/providers/fragments/allowedRequestsFields.tsx (1 hunks)
  • ui/app/providers/fragments/apiStructureFormFragment.tsx (4 hunks)
  • ui/app/providers/fragments/index.ts (1 hunks)
  • ui/app/providers/fragments/networkFormFragment.tsx (4 hunks)
  • ui/app/providers/fragments/proxyFormFragment.tsx (1 hunks)
  • ui/app/providers/views/modelProviderConfig.tsx (4 hunks)
  • ui/app/providers/views/modelProviderKeysTableView.tsx (1 hunks)
  • ui/lib/types/schemas.ts (3 hunks)
✅ Files skipped from review due to trivial changes (3)
  • plugins/logging/version
  • plugins/mocker/version
  • framework/version
🚧 Files skipped from review as they are similar to previous changes (16)
  • plugins/governance/version
  • plugins/maxim/version
  • ui/app/config/page.tsx
  • plugins/telemetry/version
  • ui/app/providers/fragments/proxyFormFragment.tsx
  • plugins/jsonparser/version
  • ui/app/providers/fragments/index.ts
  • core/version
  • ui/app/providers/views/modelProviderConfig.tsx
  • plugins/semanticcache/version
  • ui/app/providers/fragments/apiStructureFormFragment.tsx
  • ui/lib/types/schemas.ts
  • ui/app/providers/fragments/allowedRequestsFields.tsx
  • transports/version
  • ui/app/providers/dialogs/addNewKeyDialog.tsx
  • ui/app/providers/fragments/networkFormFragment.tsx
🧰 Additional context used
🧬 Code graph analysis (1)
ui/app/providers/dialogs/addNewCustomProviderDialog.tsx (2)
ui/lib/types/schemas.ts (1)
  • allowedRequestsSchema (193-202)
ui/app/providers/fragments/allowedRequestsFields.tsx (1)
  • AllowedRequestsFields (23-76)
⏰ Context from checks skipped due to timeout of 900000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (18)
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
🔇 Additional comments (5)
ui/app/providers/views/modelProviderKeysTableView.tsx (1)

71-73: Success toast on delete looks good

Nice UX touch; placement after unwrap() is correct and dialog closes reliably.

ui/app/providers/dialogs/addNewCustomProviderDialog.tsx (3)

66-67: Payload wiring LGTM

Forwarding allowed_requests under custom_provider_config is correct.


91-97: Confirm restart requirement text for this dialog

Does creating a custom provider always require a Bifrost restart, or only for specific backends? If conditional, consider gating the alert behind a prop (like other fragments) or clarifying the message.


141-143: Reusable AllowedRequestsFields integration is clean

Good reuse; default namePrefix aligns with form shape.

docs/features/observability.mdx (1)

208-210: Clarify scope of supported request types

Only “Text Completion” and “Chat Completion” are listed. If embeddings/speech/transcription aren’t observed by the Maxim plugin, add a note to avoid confusion with the provider UI toggles. If they are supported, list them here.

@TejasGhatte TejasGhatte force-pushed the 09-13-enhancement_configuration_updates_in_maxim_plugin branch from 37bc39a to c81c8bb Compare September 17, 2025 06:30
@TejasGhatte TejasGhatte force-pushed the 09-16-fix_ui_fixes_for_providers branch from d37ab4a to 6a67135 Compare September 17, 2025 06:31
Copy link
Copy Markdown
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

Caution

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

⚠️ Outside diff range comments (2)
ui/app/config/views/pluginsForm.tsx (1)

271-281: Numeric parsing bug: “0” becomes default due to || fallback.

threshold cannot be set to 0 because parseFloat(...) || 0.8 treats 0 as falsy; similar patterns exist in other fields. Use Number.isNaN checks.

- onChange={(e) => debouncedUpdateCacheConfig({ threshold: parseFloat(e.target.value) || 0.8 })}
+ onChange={(e) => {
+   const v = parseFloat(e.target.value);
+   debouncedUpdateCacheConfig({ threshold: Number.isNaN(v) ? 0.8 : v });
+ }}

[ suggest_optional_refactor ]
Apply the same pattern to these handlers for consistency/correctness:

- onChange={(e) => debouncedUpdateCacheConfig({ ttl_seconds: parseInt(e.target.value) || 300 })}
+ onChange={(e) => {
+   const v = parseInt(e.target.value, 10);
+   debouncedUpdateCacheConfig({ ttl_seconds: Number.isNaN(v) ? 300 : v });
+ }}

- onChange={(e) => debouncedUpdateCacheConfig({ dimension: parseInt(e.target.value) || 0 })}
+ onChange={(e) => {
+   const v = parseInt(e.target.value, 10);
+   debouncedUpdateCacheConfig({ dimension: Number.isNaN(v) ? 0 : v });
+ }}

- onChange={(e) => debouncedUpdateCacheConfig({ conversation_history_threshold: parseInt(e.target.value) || 3 })}
+ onChange={(e) => {
+   const v = parseInt(e.target.value, 10);
+   debouncedUpdateCacheConfig({ conversation_history_threshold: Number.isNaN(v) ? 3 : v });
+ }}

Also applies to: 261-269, 283-291, 305-312

ui/app/providers/fragments/networkFormFragment.tsx (1)

42-47: “Remove configuration” can’t work for custom providers (hard base URL check).

When clicking Remove, the form sets network_config to undefined and calls onSubmit, but the base‑URL requirement blocks submission. Allow clearing config for custom providers by only enforcing base URL when network_config exists.

- if (isCustomProvider && !(data.network_config?.base_url || "").trim()) {
+ if (isCustomProvider && data.network_config !== undefined && !(data.network_config?.base_url || "").trim()) {
   toast.error("Base URL is required for custom providers.");
   return;
 }
🧹 Nitpick comments (5)
ui/app/config/views/pluginsForm.tsx (2)

200-209: Fix switch state: reflect actual plugin enablement even when vector store is disabled.

Using checked={isSemanticCacheEnabled && isVectorStoreEnabled} renders the toggle “off” when the plugin is enabled but the vector store is disabled, which misrepresents current state. Keep it checked based on plugin state; only disable interaction.

-checked={isSemanticCacheEnabled && isVectorStoreEnabled}
+checked={isSemanticCacheEnabled}
 disabled={!isVectorStoreEnabled || providersLoading || providers.length === 0}

124-160: Avoid success-toast spam on debounced updates.

Saving on every keystroke shows a success toast each time. Gate toasts with an ID or switch to a silent save and a single “saved” toast on blur/settle.

- .then(() => {
-   toast.success("Cache configuration updated successfully");
- })
+ .then(() => {
+   toast.success("Cache configuration updated", { id: "cache-config" });
+ })
docs/features/observability.mdx (1)

202-219: Consistent bullet punctuation.

Some bullets end with periods, others don’t. Make punctuation consistent for a tighter doc.

ui/app/providers/fragments/networkFormFragment.tsx (2)

57-58: Align retry backoff defaults (5000 vs 10000).

onSubmit uses retry_backoff_max ?? 10000 but the form resets to 5000 and the placeholder shows 5000. Use one default.

- retry_backoff_max: data.network_config?.retry_backoff_max ?? 10000,
+ retry_backoff_max: data.network_config?.retry_backoff_max ?? 5000,

Also applies to: 69-81


184-210: Avoid coercing empty input to 0 for numeric fields.

Number(e.target.value) turns empty string into 0, producing invalid states and surprising users. Parse and pass undefined for empty to let Zod/RHF validate properly.

- <Input placeholder="500" {...field} onChange={(e) => field.onChange(Number(e.target.value))} />
+ <Input placeholder="500" {...field} onChange={(e) => {
+   const s = e.target.value;
+   field.onChange(s === "" ? undefined : Number(s));
+ }} />

- <Input placeholder="5000" {...field} onChange={(e) => field.onChange(Number(e.target.value))} />
+ <Input placeholder="5000" {...field} onChange={(e) => {
+   const s = e.target.value;
+   field.onChange(s === "" ? undefined : Number(s));
+ }} />
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d37ab4a and 6a67135.

📒 Files selected for processing (24)
  • core/version (1 hunks)
  • docs/features/observability.mdx (1 hunks)
  • framework/version (1 hunks)
  • plugins/governance/version (1 hunks)
  • plugins/jsonparser/version (1 hunks)
  • plugins/logging/version (1 hunks)
  • plugins/maxim/version (1 hunks)
  • plugins/mocker/version (1 hunks)
  • plugins/semanticcache/version (1 hunks)
  • plugins/telemetry/version (1 hunks)
  • transports/version (1 hunks)
  • ui/app/config/page.tsx (1 hunks)
  • ui/app/config/views/pluginsForm.tsx (3 hunks)
  • ui/app/providers/dialogs/addNewCustomProviderDialog.tsx (5 hunks)
  • ui/app/providers/dialogs/addNewKeyDialog.tsx (3 hunks)
  • ui/app/providers/fragments/allowedRequestsFields.tsx (1 hunks)
  • ui/app/providers/fragments/apiStructureFormFragment.tsx (4 hunks)
  • ui/app/providers/fragments/index.ts (1 hunks)
  • ui/app/providers/fragments/networkFormFragment.tsx (4 hunks)
  • ui/app/providers/fragments/proxyFormFragment.tsx (1 hunks)
  • ui/app/providers/views/modelProviderConfig.tsx (4 hunks)
  • ui/app/providers/views/modelProviderKeysTableView.tsx (1 hunks)
  • ui/lib/types/config.ts (0 hunks)
  • ui/lib/types/schemas.ts (3 hunks)
💤 Files with no reviewable changes (1)
  • ui/lib/types/config.ts
✅ Files skipped from review due to trivial changes (1)
  • plugins/maxim/version
🚧 Files skipped from review as they are similar to previous changes (19)
  • plugins/semanticcache/version
  • plugins/jsonparser/version
  • ui/app/providers/fragments/proxyFormFragment.tsx
  • plugins/telemetry/version
  • core/version
  • transports/version
  • plugins/governance/version
  • framework/version
  • ui/app/providers/fragments/index.ts
  • plugins/mocker/version
  • ui/app/providers/views/modelProviderConfig.tsx
  • ui/app/providers/fragments/apiStructureFormFragment.tsx
  • ui/app/config/page.tsx
  • plugins/logging/version
  • ui/app/providers/views/modelProviderKeysTableView.tsx
  • ui/app/providers/dialogs/addNewKeyDialog.tsx
  • ui/lib/types/schemas.ts
  • ui/app/providers/dialogs/addNewCustomProviderDialog.tsx
  • ui/app/providers/fragments/allowedRequestsFields.tsx
🧰 Additional context used
🧬 Code graph analysis (2)
ui/app/config/views/pluginsForm.tsx (1)
ui/lib/types/config.ts (1)
  • ModelProviderName (12-12)
ui/app/providers/fragments/networkFormFragment.tsx (3)
ui/components/ui/form.tsx (5)
  • Form (160-160)
  • FormItem (161-161)
  • FormLabel (162-162)
  • FormControl (163-163)
  • FormMessage (165-165)
ui/components/ui/textarea.tsx (1)
  • Textarea (18-18)
ui/components/ui/input.tsx (1)
  • Input (7-21)
⏰ Context from checks skipped due to timeout of 900000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (14)
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
🔇 Additional comments (2)
docs/features/observability.mdx (1)

197-199: LGTM: clearer request types.

Switching to a simple list improves readability.

ui/app/providers/fragments/networkFormFragment.tsx (1)

86-94: LGTM: restart alert gated by form dirtiness.

Good UX—avoids noisy alerts unless there are changes.

Copy link
Copy Markdown
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

Caution

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

⚠️ Outside diff range comments (3)
ui/lib/types/schemas.ts (1)

121-146: proxyConfigSchema.url is required even when type is none/environment.

As written, url is always required (z.url()), but later refines imply it’s only required for http/socks5. This blocks valid configs for none/environment.

 export const proxyConfigSchema = z
   .object({
     type: proxyTypeSchema,
-    url: z.url("Must be a valid URL"),
+    url: z.string().optional(),
     username: z.string().optional(),
     password: z.string().optional(),
   })
   .refine((data) => !(data.type === "http" || data.type === "socks5") || (data.url && data.url.trim().length > 0), {
     message: "Proxy URL is required when using HTTP or SOCKS5 proxy",
     path: ["url"],
   })
   .refine(
     (data) => {
-      if ((data.type === "http" || data.type === "socks5") && data.url?.trim()) {
+      if ((data.type === "http" || data.type === "socks5") && data.url?.trim()) {
         try {
           new URL(data.url);
           return true;
         } catch {
           return false;
         }
       }
       return true;
     },
     { message: "Must be a valid URL (e.g., http://proxy.example.com:8080)", path: ["url"] },
   );
ui/app/config/views/pluginsForm.tsx (2)

261-268: Numeric parsing: || default masks valid 0 and intermediate input. Clamp explicitly.

Using || 300 treats 0 as falsy. Parse with radix 10 and clamp to min.

Apply this diff:

-                  onChange={(e) => debouncedUpdateCacheConfig({ ttl_seconds: parseInt(e.target.value) || 300 })}
+                  onChange={(e) => {
+                    const v = parseInt(e.target.value, 10);
+                    debouncedUpdateCacheConfig({ ttl_seconds: Number.isNaN(v) ? 300 : Math.max(1, v) });
+                  }}

271-280: Numeric parsing: || 0.8 ignores user-entered 0 and doesn’t clamp to [0,1].

Parse, validate NaN, then clamp 0–1.

Apply this diff:

-                  onChange={(e) => debouncedUpdateCacheConfig({ threshold: parseFloat(e.target.value) || 0.8 })}
+                  onChange={(e) => {
+                    const v = parseFloat(e.target.value);
+                    const next = Number.isNaN(v) ? 0.8 : Math.min(1, Math.max(0, v));
+                    debouncedUpdateCacheConfig({ threshold: next });
+                  }}
♻️ Duplicate comments (1)
ui/lib/types/schemas.ts (1)

100-106: Backoff mins in form schema still don’t match base schema (regression).

networkFormConfigSchema uses 0/0, while networkConfigSchema enforces 100/1000. Align the form schema to avoid accepting values the persisted schema rejects. This mirrors an earlier comment; looks like it slipped back in.

Apply:

-  retry_backoff_initial: z.coerce
-    .number("Retry backoff initial must be a number")
-    .min(0, "Retry backoff initial must be greater than 0"),
-  retry_backoff_max: z.coerce
-    .number("Retry backoff max must be a number")
-    .min(0, "Retry backoff max must be greater than 0"),
+  retry_backoff_initial: z.coerce
+    .number("Retry backoff initial must be a number")
+    .min(100, "Initial backoff must be at least 100ms"),
+  retry_backoff_max: z.coerce
+    .number("Retry backoff max must be a number")
+    .min(1000, "Max backoff must be at least 1000ms"),

Also applies to: 107-110

🧹 Nitpick comments (16)
ui/lib/types/schemas.ts (5)

74-74: Fix constraint/message mismatch for max_retries (allowing 0).

Validators allow 0 but the message says “greater than 0”. Either make it min(1) or update the message to “at least 0”. Recommending message change to preserve 0 as valid.

- max_retries: z.number().min(0, "Max retries must be greater than 0").max(10, "Max retries must be less than 10"),
+ max_retries: z.number().min(0, "Max retries must be at least 0").max(10, "Max retries must be less than or equal to 10"),
...
-  .min(0, "Max retries must be greater than 0")
-  .max(10, "Max retries must be less than 10"),
+  .min(0, "Max retries must be at least 0")
+  .max(10, "Max retries must be less than or equal to 10"),

Also applies to: 96-99


71-73: Clarify “≤” vs “<” in timeout max messages.

.max(300) is inclusive, but the message says “less than 300”. Update copy.

- .max(300, "Timeout must be less than 300 seconds"),
+ .max(300, "Timeout must be at most 300 seconds"),
...
- .max(300, "Timeout must be less than 300 seconds"),
+ .max(300, "Timeout must be at most 300 seconds"),

Also applies to: 93-95


45-46: Weight upper bound message contradicts .max(1) (inclusive).

Change copy to “≤ 1” to match the constraint.

- .max(1, "Weight must be less than 1"),
+ .max(1, "Weight must be less than or equal to 1"),

233-239: Form schema uses persisted networkConfigSchema instead of lenient networkFormConfigSchema.

In forms we typically need coercion and relaxed URL rules. Using the persisted schema risks RHF failing on string inputs.

-  network_config: networkConfigSchema.optional(),
+  network_config: networkFormConfigSchema.optional(),

68-69: Optional: treat empty base_url as undefined via preprocess.

Avoid the union with z.string().length(0) by preprocessing ""undefined, which simplifies consumers.

- base_url: z.union([z.string().url("Must be a valid URL"), z.string().length(0)]).optional(),
+ base_url: z.preprocess(
+   (v) => (typeof v === "string" && v.trim() === "" ? undefined : v),
+   z.string().url("Must be a valid URL").optional(),
+ ),
ui/app/providers/dialogs/addNewCustomProviderDialog.tsx (3)

16-25: Deduplicate allowedRequestsSchema – import from shared schemas.

Defining it locally risks drift from ui/lib/types/schemas.ts. Import the shared schema.

-import { z } from "zod";
+import { z } from "zod";
+import { allowedRequestsSchema } from "@/lib/types/schemas";
...
-const allowedRequestsSchema = z.object({
-  text_completion: z.boolean(),
-  chat_completion: z.boolean(),
-  chat_completion_stream: z.boolean(),
-  embedding: z.boolean(),
-  speech: z.boolean(),
-  speech_stream: z.boolean(),
-  transcription: z.boolean(),
-  transcription_stream: z.boolean(),
-});

121-134: Make Select controlled (RHF + shadcn pattern).

Use value={field.value} instead of defaultValue to keep it controlled by RHF.

- <Select onValueChange={field.onChange} defaultValue={field.value}>
+ <Select onValueChange={field.onChange} value={field.value}>

148-149: UX: disable submit while creating.

Prevent double submits and show busy state.

- <Button type="submit">Add</Button>
+ <Button type="submit" disabled={isAddingProvider} aria-busy={isAddingProvider}>
+   {isAddingProvider ? "Adding…" : "Add"}
+ </Button>
ui/app/providers/fragments/allowedRequestsFields.tsx (2)

23-26: Type the control generically for better DX.

Expose a generic so consumers can pass their form type and get field name safety.

-interface AllowedRequestsFieldsProps {
-  control: Control<any>;
+interface AllowedRequestsFieldsProps<TFieldValues = any> {
+  control: Control<TFieldValues>;
   namePrefix?: string;
 }
 
-export function AllowedRequestsFields({ control, namePrefix = "allowed_requests" }: AllowedRequestsFieldsProps) {
+export function AllowedRequestsFields<TFieldValues = any>({
+  control,
+  namePrefix = "allowed_requests",
+}: AllowedRequestsFieldsProps<TFieldValues>) {

47-47: Check Switch API: is size="md" supported?

If not, drop it to avoid passing unknown props.

Also applies to: 66-66

ui/app/config/views/pluginsForm.tsx (6)

41-45: Avoid any cast when extracting error message.

Prefer passing unknown (or the concrete error type) to getErrorMessage to keep type-safety.

Apply this diff:

-      toast.error(`Failed to load providers: ${getErrorMessage(providersError as any)}`);
+      toast.error(`Failed to load providers: ${getErrorMessage(providersError)}`);

66-72: Handle stale/missing provider in existing configs.

If an existing plugin config refers to a provider that no longer exists, the Select will render with an invalid value. Normalize to the first available provider when mismatch is detected.

Apply this diff:

-useEffect(() => {
-  if (providers.length > 0 && !semanticCachePlugin?.config) {
-    setCacheConfig((prev) => ({
-      ...prev,
-      provider: providers[0].name as ModelProviderName,
-    }));
-  }
-}, [providers, semanticCachePlugin?.config]);
+useEffect(() => {
+  if (providers.length === 0) return;
+  const hasValidProvider = providers.some((p) => p.name === cacheConfig.provider);
+  if (!semanticCachePlugin?.config || !hasValidProvider) {
+    setCacheConfig((prev) => ({
+      ...prev,
+      provider: providers[0].name as ModelProviderName,
+    }));
+  }
+}, [providers, semanticCachePlugin?.config, cacheConfig.provider]);

212-220: Hide config panel when no providers are configured.

Currently, config UI can render with an empty providers list. Gate the panel on providers length and show a small note instead.

Apply this diff:

-        {isSemanticCacheEnabled &&
-          isVectorStoreEnabled &&
-          (providersLoading ? (
+        {isSemanticCacheEnabled &&
+          isVectorStoreEnabled &&
+          (providersLoading ? (
             <div className="flex items-center justify-center">
               <Loader2 className="h-4 w-4 animate-spin" />
             </div>
-          ) : (
-            <div className="mt-4 space-y-4">
+          ) : providers.length > 0 ? (
+            <div className="mt-4 space-y-4">
+            </div>
+          ) : (
+            <div className="mt-4 text-sm text-destructive">
+              Configure at least one provider to edit cache settings.
             </div>
           ))}

283-291: Numeric parsing: avoid || 0; clamp to non-negative and keep radix.

Prevents accidental fallback when user types “0” or during intermediate edits.

Apply this diff:

-                  onChange={(e) => debouncedUpdateCacheConfig({ dimension: parseInt(e.target.value) || 0 })}
+                  onChange={(e) => {
+                    const v = parseInt(e.target.value, 10);
+                    debouncedUpdateCacheConfig({ dimension: Number.isNaN(v) ? 0 : Math.max(0, v) });
+                  }}

303-312: Numeric parsing: same || default issue and no bounds enforcement.

Clamp to 1–50 and preserve defaults only on NaN.

Apply this diff:

-                  onChange={(e) => debouncedUpdateCacheConfig({ conversation_history_threshold: parseInt(e.target.value) || 3 })}
+                  onChange={(e) => {
+                    const v = parseInt(e.target.value, 10);
+                    const next = Number.isNaN(v) ? 3 : Math.min(50, Math.max(1, v));
+                    debouncedUpdateCacheConfig({ conversation_history_threshold: next });
+                  }}

147-151: Reduce toast noise on debounced saves.

Frequent edits fire repeated success toasts. Consider collapsing to a single “Saving…” → “Saved” toast or suppressing success toasts for debounced background saves.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d37ab4a and 6a67135.

📒 Files selected for processing (24)
  • core/version (1 hunks)
  • docs/features/observability.mdx (1 hunks)
  • framework/version (1 hunks)
  • plugins/governance/version (1 hunks)
  • plugins/jsonparser/version (1 hunks)
  • plugins/logging/version (1 hunks)
  • plugins/maxim/version (1 hunks)
  • plugins/mocker/version (1 hunks)
  • plugins/semanticcache/version (1 hunks)
  • plugins/telemetry/version (1 hunks)
  • transports/version (1 hunks)
  • ui/app/config/page.tsx (1 hunks)
  • ui/app/config/views/pluginsForm.tsx (3 hunks)
  • ui/app/providers/dialogs/addNewCustomProviderDialog.tsx (5 hunks)
  • ui/app/providers/dialogs/addNewKeyDialog.tsx (3 hunks)
  • ui/app/providers/fragments/allowedRequestsFields.tsx (1 hunks)
  • ui/app/providers/fragments/apiStructureFormFragment.tsx (4 hunks)
  • ui/app/providers/fragments/index.ts (1 hunks)
  • ui/app/providers/fragments/networkFormFragment.tsx (4 hunks)
  • ui/app/providers/fragments/proxyFormFragment.tsx (1 hunks)
  • ui/app/providers/views/modelProviderConfig.tsx (4 hunks)
  • ui/app/providers/views/modelProviderKeysTableView.tsx (1 hunks)
  • ui/lib/types/config.ts (0 hunks)
  • ui/lib/types/schemas.ts (3 hunks)
💤 Files with no reviewable changes (1)
  • ui/lib/types/config.ts
🚧 Files skipped from review as they are similar to previous changes (19)
  • ui/app/providers/fragments/index.ts
  • ui/app/providers/fragments/proxyFormFragment.tsx
  • plugins/semanticcache/version
  • plugins/logging/version
  • plugins/telemetry/version
  • plugins/jsonparser/version
  • core/version
  • framework/version
  • ui/app/providers/fragments/apiStructureFormFragment.tsx
  • plugins/maxim/version
  • ui/app/providers/dialogs/addNewKeyDialog.tsx
  • plugins/governance/version
  • ui/app/config/page.tsx
  • transports/version
  • plugins/mocker/version
  • ui/app/providers/views/modelProviderKeysTableView.tsx
  • ui/app/providers/views/modelProviderConfig.tsx
  • docs/features/observability.mdx
  • ui/app/providers/fragments/networkFormFragment.tsx
🧰 Additional context used
🧬 Code graph analysis (3)
ui/app/config/views/pluginsForm.tsx (1)
ui/lib/types/config.ts (1)
  • ModelProviderName (12-12)
ui/app/providers/fragments/allowedRequestsFields.tsx (3)
ui/app/providers/fragments/index.ts (1)
  • AllowedRequestsFields (1-1)
ui/components/ui/form.tsx (3)
  • FormItem (161-161)
  • FormLabel (162-162)
  • FormControl (163-163)
ui/components/ui/switch.tsx (1)
  • Switch (36-36)
ui/app/providers/dialogs/addNewCustomProviderDialog.tsx (3)
ui/lib/types/schemas.ts (1)
  • allowedRequestsSchema (193-202)
ui/components/ui/alert.tsx (2)
  • Alert (41-41)
  • AlertDescription (41-41)
ui/app/providers/fragments/allowedRequestsFields.tsx (1)
  • AllowedRequestsFields (23-76)
⏰ Context from checks skipped due to timeout of 900000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (22)
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
🔇 Additional comments (7)
ui/app/providers/dialogs/addNewCustomProviderDialog.tsx (3)

83-84: Dialog onOpenChange wiring is correct.

Handler now matches (open: boolean) => void and only closes on false. Good fix.


61-69: Verify: backend acceptance of keys: [] for custom providers.

Type schema for add requests generally requires ≥1 key. If the API permits keyless creation, fine; else this will 400. Consider omitting keys or gating via a separate “add keys” flow.

Would you like me to scan usages of useCreateProviderMutation and the API handler to confirm accepted payloads?


91-96: Nice touch: conditional restart notice tied to form dirtiness.

Matches PR intent and keeps noise down.

ui/app/providers/fragments/allowedRequestsFields.tsx (1)

12-21: Good: keys/labels align with schema.

The 8 toggles match allowedRequestsSchema. Nice, balanced 2‑column layout.

ui/app/config/views/pluginsForm.tsx (3)

11-12: Imports LGTM; types correctly scoped to config/plugins.

No issues. Using ModelProviderName for provider values is appropriate here.


124-125: Debounce ref separation is good.

Clear, single-responsibility ref for cache updates; cleanup handled below.


200-209: Confirm Switch checked state reflects intended UX.

checked={isSemanticCacheEnabled && isVectorStoreEnabled} will show “off” when the plugin is enabled but vector store is disabled. If that’s intentional, ignore; otherwise bind to isSemanticCacheEnabled and rely solely on disabled to block interaction.

@TejasGhatte TejasGhatte changed the base branch from 09-13-enhancement_configuration_updates_in_maxim_plugin to graphite-base/478 September 17, 2025 07:24
Copy link
Copy Markdown
Contributor

akshaydeo commented Sep 17, 2025

Merge activity

  • Sep 17, 8:34 AM UTC: A user started a stack merge that includes this pull request via Graphite.
  • Sep 17, 8:37 AM UTC: Graphite couldn't merge this PR because it had merge conflicts.
  • Sep 17, 8:40 AM UTC: A user started a stack merge that includes this pull request via Graphite.
  • Sep 17, 8:40 AM UTC: @Pratham-Mishra04 merged this pull request with Graphite.

@akshaydeo akshaydeo changed the base branch from graphite-base/478 to main September 17, 2025 08:35
@Pratham-Mishra04 Pratham-Mishra04 force-pushed the 09-16-fix_ui_fixes_for_providers branch from 6a67135 to dbf1853 Compare September 17, 2025 08:38
@Pratham-Mishra04 Pratham-Mishra04 self-requested a review September 17, 2025 08:38
@Pratham-Mishra04 Pratham-Mishra04 merged commit 330d206 into main Sep 17, 2025
3 of 4 checks passed
@Pratham-Mishra04 Pratham-Mishra04 deleted the 09-16-fix_ui_fixes_for_providers branch September 17, 2025 08:40
@akshaydeo akshaydeo mentioned this pull request Oct 6, 2025
18 tasks
akshaydeo added a commit that referenced this pull request Oct 6, 2025
## Summary

Improved error handling for request timeouts across all provider implementations, ensuring consistent error messages and better user experience when API requests time out.

## Changes

- Added specific error handling for timeout scenarios (context.Canceled, context.DeadlineExceeded, fasthttp.ErrTimeout) across all providers
- Created a dedicated error message for timeouts that guides users to adjust the timeout setting
- Fixed validation in HTTP handlers for embeddings, speech, and text completion requests
- Improved CORS wildcard pattern matching to support domain patterns like `*.example.com`
- Fixed issues in the logging plugin to properly handle text completion responses
- Enhanced UI form handling for network configuration with proper default values

## Type of change

- [x] Bug fix
- [x] Feature
- [x] Refactor
- [ ] Documentation
- [ ] Chore/CI

## Affected areas

- [x] Core (Go)
- [x] Transports (HTTP)
- [x] Providers/Integrations
- [x] Plugins
- [x] UI (Next.js)
- [ ] Docs

## How to test

Test timeout handling by configuring a very short timeout and making requests:

```sh
# Core/Transports
go test ./core/providers/... -run TestProviderTimeouts

# Test CORS with wildcard domains
curl -H "Origin: https://test.example.com" -v http://localhost:8000/v1/chat/completions

# Test UI network config form
cd ui
pnpm i
pnpm dev
# Navigate to Providers > [Any Provider] > Network Config
```

## Breaking changes

- [ ] Yes
- [x] No

## Related issues

Closes #456 - Inconsistent timeout error handling
Closes #478 - CORS wildcard pattern support

## Security considerations

The CORS wildcard pattern implementation has been carefully designed to prevent regex-based attacks.

## Checklist

- [x] I read `docs/contributing/README.md` and followed the guidelines
- [x] I added/updated tests where appropriate
- [x] I updated documentation where needed
- [x] I verified builds succeed (Go and UI)
- [x] I verified the CI pipeline passes locally if applicable
akshaydeo added a commit that referenced this pull request Nov 17, 2025
## Summary

Improved error handling for request timeouts across all provider implementations, ensuring consistent error messages and better user experience when API requests time out.

## Changes

- Added specific error handling for timeout scenarios (context.Canceled, context.DeadlineExceeded, fasthttp.ErrTimeout) across all providers
- Created a dedicated error message for timeouts that guides users to adjust the timeout setting
- Fixed validation in HTTP handlers for embeddings, speech, and text completion requests
- Improved CORS wildcard pattern matching to support domain patterns like `*.example.com`
- Fixed issues in the logging plugin to properly handle text completion responses
- Enhanced UI form handling for network configuration with proper default values

## Type of change

- [x] Bug fix
- [x] Feature
- [x] Refactor
- [ ] Documentation
- [ ] Chore/CI

## Affected areas

- [x] Core (Go)
- [x] Transports (HTTP)
- [x] Providers/Integrations
- [x] Plugins
- [x] UI (Next.js)
- [ ] Docs

## How to test

Test timeout handling by configuring a very short timeout and making requests:

```sh
# Core/Transports
go test ./core/providers/... -run TestProviderTimeouts

# Test CORS with wildcard domains
curl -H "Origin: https://test.example.com" -v http://localhost:8000/v1/chat/completions

# Test UI network config form
cd ui
pnpm i
pnpm dev
# Navigate to Providers > [Any Provider] > Network Config
```

## Breaking changes

- [ ] Yes
- [x] No

## Related issues

Closes #456 - Inconsistent timeout error handling
Closes #478 - CORS wildcard pattern support

## Security considerations

The CORS wildcard pattern implementation has been carefully designed to prevent regex-based attacks.

## Checklist

- [x] I read `docs/contributing/README.md` and followed the guidelines
- [x] I added/updated tests where appropriate
- [x] I updated documentation where needed
- [x] I verified builds succeed (Go and UI)
- [x] I verified the CI pipeline passes locally if applicable
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