Skip to content

Conversation

@ahmedriad1
Copy link
Member

@ahmedriad1 ahmedriad1 commented Dec 23, 2025

  • Updated allowedEmails validation to use z.email() for better email format checking.
  • Simplified exampleQuestions and exampleSearchQueries handling in useHostingForm.
  • Added unsaved changes warning on page unload in HostingLayout.
  • Improved rendering logic in HostingPreview for better display of example questions.
  • Adjusted tab structure in HostingTabs and GeneralTab for improved navigation and user experience.
  • Enhanced SortableList component with button repositioning for better accessibility.

Summary by CodeRabbit

Release Notes

  • New Features

    • Added unsaved changes warning when navigating away from the hosting configuration page.
    • Added Custom Domain button in the General tab for easier access to domain settings.
  • Improvements

    • Updated preview label and improved tab navigation flow.
    • Enhanced validation for email addresses and example questions/searches.
    • Improved handling of empty lists in form fields with auto-population.

✏️ Tip: You can customize this high-level summary in your review settings.

- Updated allowedEmails validation to use z.email() for better email format checking.
- Simplified exampleQuestions and exampleSearchQueries handling in useHostingForm.
- Added unsaved changes warning on page unload in HostingLayout.
- Improved rendering logic in HostingPreview for better display of example questions.
- Adjusted tab structure in HostingTabs and GeneralTab for improved navigation and user experience.
- Enhanced SortableList component with button repositioning for better accessibility.
@coderabbitai
Copy link

coderabbitai bot commented Dec 23, 2025

Walkthrough

This PR updates the hosting configuration UI components to add unsaved changes warnings via beforeunload handlers, reorder tab navigation, introduce a Custom domain button that programmatically switches tabs, modify form validation schema (relaxing empty string constraints), and enhance the sortable list with auto-append behavior.

Changes

Cohort / File(s) Summary
Hosting Layout & Preview
hosting-layout.tsx, hosting-preview.tsx
Added useEffect-based beforeunload handler for unsaved changes warning with UNSAVED_CHANGES_MESSAGE constant; simplified renderPreviewPane from switch statement to conditional. Updated preview header text from "Live Preview" to "Preview"; removed logo fallback placeholder div; restructured example questions layout with wrapper div and Boolean filter.
Hosting Tabs & General Tab
hosting-tabs.tsx, general-tab.tsx
Reordered Open Graph tab position in tab list; extended GeneralTab with new setTab prop enabling programmatic tab switching. Added Custom domain button in slug field that invokes setTab("other") to navigate to "other" tab.
Form & Utilities
use-hosting-form.ts, sortable-list.tsx
Changed email validation from z.string().email() to z.email(); removed per-item min(1) length constraints from exampleQuestions and exampleSearchQueries arrays, keeping only max(4); adjusted default initialization to wrap empty arrays as [""] in form state. Enhanced sortable-list with useEffect that auto-appends empty item under certain conditions; repositioned Add button below DnD context.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately reflects the main changes: hosting form validation improvements, layout adjustments, and navigation enhancements across multiple components.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/hosting-settings-improvments

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.

@vercel
Copy link

vercel bot commented Dec 23, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Review Updated (UTC)
app-agentset-ai Ready Ready Preview, Comment Dec 23, 2025 2:15pm

Copy link

@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: 3

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 355c928 and 719be20.

📒 Files selected for processing (6)
  • apps/web/src/app/app.agentset.ai/(dashboard)/[slug]/[namespaceSlug]/hosting/components/hosting-layout.tsx
  • apps/web/src/app/app.agentset.ai/(dashboard)/[slug]/[namespaceSlug]/hosting/components/hosting-preview.tsx
  • apps/web/src/app/app.agentset.ai/(dashboard)/[slug]/[namespaceSlug]/hosting/components/hosting-tabs.tsx
  • apps/web/src/app/app.agentset.ai/(dashboard)/[slug]/[namespaceSlug]/hosting/components/tabs/general-tab.tsx
  • apps/web/src/app/app.agentset.ai/(dashboard)/[slug]/[namespaceSlug]/hosting/use-hosting-form.ts
  • apps/web/src/components/sortable-list.tsx
🧰 Additional context used
📓 Path-based instructions (4)
apps/web/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/nextjs.mdc)

apps/web/**/*.{ts,tsx}: Use the App Router directory structure in Next.js projects
Mark client components explicitly with 'use client' directive
Place static content and interfaces at file end
When using useRouter, import from @bprogress/next/app to show global progress bar
Use Zod for form validation in forms
Use react-hook-form for form handling as defined in apps/web/src/components/ui/form.tsx

Files:

  • apps/web/src/app/app.agentset.ai/(dashboard)/[slug]/[namespaceSlug]/hosting/components/tabs/general-tab.tsx
  • apps/web/src/app/app.agentset.ai/(dashboard)/[slug]/[namespaceSlug]/hosting/components/hosting-layout.tsx
  • apps/web/src/components/sortable-list.tsx
  • apps/web/src/app/app.agentset.ai/(dashboard)/[slug]/[namespaceSlug]/hosting/use-hosting-form.ts
  • apps/web/src/app/app.agentset.ai/(dashboard)/[slug]/[namespaceSlug]/hosting/components/hosting-preview.tsx
  • apps/web/src/app/app.agentset.ai/(dashboard)/[slug]/[namespaceSlug]/hosting/components/hosting-tabs.tsx
apps/web/**/*.tsx

📄 CodeRabbit inference engine (.cursor/rules/nextjs.mdc)

apps/web/**/*.tsx: Wrap client components in Suspense with fallback
Minimize use of 'useEffect' and 'setState' hooks
Show loading states during form submission

Files:

  • apps/web/src/app/app.agentset.ai/(dashboard)/[slug]/[namespaceSlug]/hosting/components/tabs/general-tab.tsx
  • apps/web/src/app/app.agentset.ai/(dashboard)/[slug]/[namespaceSlug]/hosting/components/hosting-layout.tsx
  • apps/web/src/components/sortable-list.tsx
  • apps/web/src/app/app.agentset.ai/(dashboard)/[slug]/[namespaceSlug]/hosting/components/hosting-preview.tsx
  • apps/web/src/app/app.agentset.ai/(dashboard)/[slug]/[namespaceSlug]/hosting/components/hosting-tabs.tsx
{apps/web/**/*.ts,apps/web/**/*.tsx,packages/ui/**/*.ts,packages/ui/**/*.tsx}

📄 CodeRabbit inference engine (.cursor/rules/shadcn.mdc)

{apps/web/**/*.ts,apps/web/**/*.tsx,packages/ui/**/*.ts,packages/ui/**/*.tsx}: Import Shadcn UI components from the @agentset/ui alias (e.g., import { Button, Card } from "@agentset/ui")
Use Shadcn UI components from the packages/ui/src/components/ui directory for UI elements
Style components using the 'new-york' style variant with 'neutral' base color and CSS variables for theming as configured in components.json
The Button component supports an isLoading prop to display a loading spinner

Files:

  • apps/web/src/app/app.agentset.ai/(dashboard)/[slug]/[namespaceSlug]/hosting/components/tabs/general-tab.tsx
  • apps/web/src/app/app.agentset.ai/(dashboard)/[slug]/[namespaceSlug]/hosting/components/hosting-layout.tsx
  • apps/web/src/components/sortable-list.tsx
  • apps/web/src/app/app.agentset.ai/(dashboard)/[slug]/[namespaceSlug]/hosting/use-hosting-form.ts
  • apps/web/src/app/app.agentset.ai/(dashboard)/[slug]/[namespaceSlug]/hosting/components/hosting-preview.tsx
  • apps/web/src/app/app.agentset.ai/(dashboard)/[slug]/[namespaceSlug]/hosting/components/hosting-tabs.tsx
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (.cursor/rules/project-structure.mdc)

Import from packages using configured aliases (e.g., @agentset/ui, @agentset/db/client) instead of relative paths to packages

Files:

  • apps/web/src/app/app.agentset.ai/(dashboard)/[slug]/[namespaceSlug]/hosting/components/tabs/general-tab.tsx
  • apps/web/src/app/app.agentset.ai/(dashboard)/[slug]/[namespaceSlug]/hosting/components/hosting-layout.tsx
  • apps/web/src/components/sortable-list.tsx
  • apps/web/src/app/app.agentset.ai/(dashboard)/[slug]/[namespaceSlug]/hosting/use-hosting-form.ts
  • apps/web/src/app/app.agentset.ai/(dashboard)/[slug]/[namespaceSlug]/hosting/components/hosting-preview.tsx
  • apps/web/src/app/app.agentset.ai/(dashboard)/[slug]/[namespaceSlug]/hosting/components/hosting-tabs.tsx
🧠 Learnings (6)
📚 Learning: 2025-12-21T13:02:44.489Z
Learnt from: max-programming
Repo: agentset-ai/agentset PR: 73
File: apps/web/src/app/app.agentset.ai/(dashboard)/[slug]/[namespaceSlug]/hosting/components/hosting-layout.tsx:19-19
Timestamp: 2025-12-21T13:02:44.489Z
Learning: Tailwind CSS v4 supports the spacing(n) shorthand inside arbitrary values (e.g., h-[calc(...(--spacing(16))...)) to compile to calc(var(--spacing) * n). When reviewing TSX files that use Tailwind and arbitrary values, verify any usage of --spacing within calc expressions is valid per Tailwind v4 docs and that the resulting CSS is correctly applied. If you introduce or rely on such spacing syntax, ensure the syntax is supported in the specific Tailwind build configuration and that there are no typos or unsupported nested expressions.

Applied to files:

  • apps/web/src/app/app.agentset.ai/(dashboard)/[slug]/[namespaceSlug]/hosting/components/tabs/general-tab.tsx
  • apps/web/src/app/app.agentset.ai/(dashboard)/[slug]/[namespaceSlug]/hosting/components/hosting-layout.tsx
  • apps/web/src/components/sortable-list.tsx
  • apps/web/src/app/app.agentset.ai/(dashboard)/[slug]/[namespaceSlug]/hosting/components/hosting-preview.tsx
  • apps/web/src/app/app.agentset.ai/(dashboard)/[slug]/[namespaceSlug]/hosting/components/hosting-tabs.tsx
📚 Learning: 2025-11-26T20:30:45.439Z
Learnt from: CR
Repo: agentset-ai/agentset PR: 0
File: .cursor/rules/nextjs.mdc:0-0
Timestamp: 2025-11-26T20:30:45.439Z
Learning: Applies to apps/web/**/*.tsx : Minimize use of 'useEffect' and 'setState' hooks

Applied to files:

  • apps/web/src/app/app.agentset.ai/(dashboard)/[slug]/[namespaceSlug]/hosting/components/hosting-layout.tsx
  • apps/web/src/components/sortable-list.tsx
📚 Learning: 2025-11-26T20:30:45.439Z
Learnt from: CR
Repo: agentset-ai/agentset PR: 0
File: .cursor/rules/nextjs.mdc:0-0
Timestamp: 2025-11-26T20:30:45.439Z
Learning: Applies to apps/web/**/*.tsx : Wrap client components in Suspense with fallback

Applied to files:

  • apps/web/src/app/app.agentset.ai/(dashboard)/[slug]/[namespaceSlug]/hosting/components/hosting-layout.tsx
📚 Learning: 2025-11-26T20:30:45.439Z
Learnt from: CR
Repo: agentset-ai/agentset PR: 0
File: .cursor/rules/nextjs.mdc:0-0
Timestamp: 2025-11-26T20:30:45.439Z
Learning: Applies to apps/web/**/*.{ts,tsx} : Use react-hook-form for form handling as defined in `apps/web/src/components/ui/form.tsx`

Applied to files:

  • apps/web/src/app/app.agentset.ai/(dashboard)/[slug]/[namespaceSlug]/hosting/components/hosting-layout.tsx
  • apps/web/src/components/sortable-list.tsx
📚 Learning: 2025-11-26T20:30:45.439Z
Learnt from: CR
Repo: agentset-ai/agentset PR: 0
File: .cursor/rules/nextjs.mdc:0-0
Timestamp: 2025-11-26T20:30:45.439Z
Learning: Applies to apps/web/**/*.tsx : Show loading states during form submission

Applied to files:

  • apps/web/src/app/app.agentset.ai/(dashboard)/[slug]/[namespaceSlug]/hosting/components/hosting-layout.tsx
📚 Learning: 2025-11-26T20:30:45.439Z
Learnt from: CR
Repo: agentset-ai/agentset PR: 0
File: .cursor/rules/nextjs.mdc:0-0
Timestamp: 2025-11-26T20:30:45.439Z
Learning: Applies to apps/web/**/*.{ts,tsx} : Use Zod for form validation in forms

Applied to files:

  • apps/web/src/app/app.agentset.ai/(dashboard)/[slug]/[namespaceSlug]/hosting/use-hosting-form.ts
🧬 Code graph analysis (3)
apps/web/src/app/app.agentset.ai/(dashboard)/[slug]/[namespaceSlug]/hosting/components/tabs/general-tab.tsx (3)
apps/web/src/app/app.agentset.ai/(dashboard)/[slug]/[namespaceSlug]/hosting/use-hosting-form.ts (2)
  • HostingFormValues (40-40)
  • HostingData (42-42)
apps/web/src/app/app.agentset.ai/(dashboard)/[slug]/[namespaceSlug]/hosting/components/hosting-tabs.tsx (1)
  • TabValue (15-20)
packages/ui/src/components/ui/form.tsx (1)
  • FormLabel (164-164)
apps/web/src/app/app.agentset.ai/(dashboard)/[slug]/[namespaceSlug]/hosting/components/hosting-layout.tsx (4)
apps/web/src/app/app.agentset.ai/(dashboard)/[slug]/[namespaceSlug]/hosting/use-hosting-form.ts (2)
  • HostingData (42-42)
  • useHostingForm (44-152)
apps/web/src/app/app.agentset.ai/(dashboard)/[slug]/[namespaceSlug]/hosting/components/hosting-tabs.tsx (1)
  • TabValue (15-20)
apps/web/src/lib/constants.ts (2)
  • APP_DOMAIN (13-18)
  • HOSTING_PREFIX (34-34)
apps/web/src/app/app.agentset.ai/(dashboard)/[slug]/[namespaceSlug]/hosting/components/hosting-preview.tsx (1)
  • HostingPreview (23-80)
apps/web/src/app/app.agentset.ai/(dashboard)/[slug]/[namespaceSlug]/hosting/components/hosting-tabs.tsx (1)
apps/web/src/app/app.agentset.ai/(dashboard)/[slug]/[namespaceSlug]/hosting/components/tabs/general-tab.tsx (1)
  • GeneralTab (27-129)
🔇 Additional comments (13)
apps/web/src/components/sortable-list.tsx (2)

7-7: LGTM!

The useEffect import is properly added to support the new hook introduced later in the component.


157-168: LGTM!

The Add button has been repositioned below the sortable list with proper spacing. This improves the visual hierarchy and accessibility by separating the action button from the drag-and-drop area.

apps/web/src/app/app.agentset.ai/(dashboard)/[slug]/[namespaceSlug]/hosting/components/hosting-tabs.tsx (2)

47-47: LGTM! Tab reordering aligns with PR objectives.

The Open Graph tab has been repositioned to appear after the Security tab, improving the navigation structure as mentioned in the PR description.


53-53: LGTM! Programmatic tab switching enabled.

The setTab={setActiveTab} prop correctly enables GeneralTab to trigger tab changes (e.g., switching to the Advanced tab via the Custom domain button). The type signature matches: setActiveTab is React.Dispatch<React.SetStateAction<TabValue>>, which is compatible with (tab: TabValue) => void.

apps/web/src/app/app.agentset.ai/(dashboard)/[slug]/[namespaceSlug]/hosting/components/hosting-layout.tsx (2)

22-37: Unsaved changes warning implemented correctly, but note browser limitations.

The beforeunload handler correctly prevents accidental data loss when isDirty is true. The implementation properly:

  • Sets event.returnValue for Chrome compatibility
  • Returns the message string
  • Cleans up the event listener on unmount

However, note that modern browsers (Chrome 51+, Firefox 44+) ignore custom messages and show generic "Leave site?" dialogs. The UNSAVED_CHANGES_MESSAGE constant won't be displayed to users but serves as documentation.

Regarding the coding guideline to minimize useEffect usage: this is a justified exception since integrating with browser APIs like beforeunload requires an effect. There's no alternative pattern for this use case.


42-43: LGTM! Simplified conditional logic.

The switch-to-conditional refactor reduces complexity while maintaining the same functionality. The binary choice (Open Graph tab vs. default preview) is more clearly expressed with an if statement.

apps/web/src/app/app.agentset.ai/(dashboard)/[slug]/[namespaceSlug]/hosting/components/hosting-preview.tsx (3)

33-33: LGTM! Header text simplified.

The change from "Live Preview" to "Preview" is cleaner and aligns with the PR's UI refinements.


46-46: LGTM! Logo fallback simplified.

Removing the placeholder div when no logo is present simplifies the UI. The logo now only renders when explicitly provided.


57-66: LGTM! Critical filter for empty strings added.

The .filter(Boolean) is essential given the validation schema changes in use-hosting-form.ts (lines 29, 101-102) that now allow empty strings in the exampleQuestions array. Without this filter, empty suggestion buttons would render in the preview.

The restructured wrapper with mx-4 mb-4 classes improves spacing consistency.

apps/web/src/app/app.agentset.ai/(dashboard)/[slug]/[namespaceSlug]/hosting/components/tabs/general-tab.tsx (3)

19-19: LGTM! Type import added for tab switching.

The TabValue import supports the new setTab prop, enabling type-safe programmatic tab navigation.


24-24: LGTM! Interface extended to support tab switching.

The setTab callback prop enables the Custom domain button to programmatically switch to the Advanced tab, improving UX by guiding users to the custom domain configuration.

Also applies to: 27-27


63-72: LGTM! Custom domain navigation button implemented correctly.

The button implementation is solid:

  • type="button" correctly prevents form submission
  • setTab("other") switches to the Advanced tab where custom domain settings reside
  • Positioned contextually next to the Slug field for discoverability
  • Link-like styling (underline, text-primary) indicates navigation action
apps/web/src/app/app.agentset.ai/(dashboard)/[slug]/[namespaceSlug]/hosting/use-hosting-form.ts (1)

26-26: Update Zod email validation syntax to v4 standard.

The change from z.array(z.string().email()) to z.array(z.email()) is correct for Zod v4. Both syntaxes are functionally equivalent—z.email() is the idiomatic v4 approach and provides identical validation behavior and error messages. No compatibility concerns.

Comment on lines +29 to +30
exampleQuestions: z.array(z.string()).max(4),
exampleSearchQueries: z.array(z.string()).max(4),
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

# Find the form file and examine the validation schema
find . -type f -name "use-hosting-form.ts" | head -5

Repository: agentset-ai/agentset

Length of output: 161


🏁 Script executed:

# Search for backend hosting handlers and API routes
rg "hosting.*update|exampleQuestions|exampleSearchQueries" --type ts --type tsx -g '!node_modules' | head -50

Repository: agentset-ai/agentset

Length of output: 91


🏁 Script executed:

# Find hosting-preview.tsx to verify the UI filtering
find . -type f -name "hosting-preview.tsx" | head -5

Repository: agentset-ai/agentset

Length of output: 172


🏁 Script executed:

# Read the form validation file to see the schema
cat -n ./apps/web/src/app/app.agentset.ai/\(dashboard\)/\[slug\]/\[namespaceSlug\]/hosting/use-hosting-form.ts

Repository: agentset-ai/agentset

Length of output: 6359


🏁 Script executed:

# Read hosting-preview.tsx to verify the filtering logic
cat -n ./apps/web/src/app/app.agentset.ai/\(dashboard\)/\[slug\]/\[namespaceSlug\]/hosting/components/hosting-preview.tsx | head -80

Repository: agentset-ai/agentset

Length of output: 3065


🏁 Script executed:

# Search for backend handling - look in server, api, and packages directories
rg "exampleQuestions|exampleSearchQueries" --type ts -g '!node_modules' -C 3

Repository: agentset-ai/agentset

Length of output: 14687


🏁 Script executed:

# Read the backend update service to see if filtering happens
cat -n ./apps/web/src/services/hosting/update.ts

Repository: agentset-ai/agentset

Length of output: 4587


🏁 Script executed:

# Search for the TRPC hosting update handler in server directories
find . -type f -name "*.ts" -path "*/server/*" -o -path "*/api/*" | xargs rg -l "hosting.*update" 2>/dev/null | head -10

Repository: agentset-ai/agentset

Length of output: 671


🏁 Script executed:

# Look for the TRPC procedure definition for hosting.update
rg "hosting.*update|\.update\(" --type ts -g '!node_modules' -B 2 -A 10 | grep -A 10 "trpc.*hosting" | head -50

Repository: agentset-ai/agentset

Length of output: 1636


Backend persists empty strings without filtering—add validation to sanitize arrays.

The backend service (apps/web/src/services/hosting/update.ts lines 83-84) passes exampleQuestions and exampleSearchQueries directly to the database without filtering empty or whitespace-only strings. Combined with the form's removal of .min(1) validation and the UI-only filtering in the preview component, empty strings like ["", "valid question", ""] will be persisted to the database.

Implement backend filtering to remove empty/whitespace-only strings before the Prisma update, or add stricter validation to reject submissions with empty array elements.

Comment on lines +101 to +106
exampleQuestions:
data.exampleQuestions.length === 0 ? [""] : data.exampleQuestions,
exampleSearchQueries:
data.exampleSearchQueries.length === 0
? [""]
: data.exampleSearchQueries,
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

# First, read the file to understand the full context
wc -l apps/web/src/app/app.agentset.ai/\(dashboard\)/\[slug\]/\[namespaceSlug\]/hosting/use-hosting-form.ts

Repository: agentset-ai/agentset

Length of output: 163


🏁 Script executed:

# Since we need to handle special characters in the path, let's find the file first
fd "use-hosting-form.ts" apps/web/

Repository: agentset-ai/agentset

Length of output: 159


🏁 Script executed:

cat -n "apps/web/src/app/app.agentset.ai/(dashboard)/[slug]/[namespaceSlug]/hosting/use-hosting-form.ts"

Repository: agentset-ai/agentset

Length of output: 6359


🏁 Script executed:

# Search for the TRPC hosting.update mutation
find apps/web -type f -name "*.ts" -o -name "*.tsx" | xargs grep -l "hosting.update" | head -5

Repository: agentset-ai/agentset

Length of output: 371


🏁 Script executed:

# Also search in packages for backend logic
find packages -type f -name "*.ts" | xargs grep -l "exampleQuestions" | head -10

Repository: agentset-ai/agentset

Length of output: 46


🏁 Script executed:

cat -n "apps/web/src/server/api/routers/hosting.ts"

Repository: agentset-ai/agentset

Length of output: 2673


🏁 Script executed:

fd "hosting.ts" packages/ | grep -i schema

Repository: agentset-ai/agentset

Length of output: 46


🏁 Script executed:

# Find the schema file
find apps/web -path "*schemas/api/hosting*" -type f

Repository: agentset-ai/agentset

Length of output: 99


🏁 Script executed:

cat -n "apps/web/src/schemas/api/hosting.ts"

Repository: agentset-ai/agentset

Length of output: 5326


🏁 Script executed:

find apps/web/src/services -name "*hosting*" -type f

Repository: agentset-ai/agentset

Length of output: 46


🏁 Script executed:

find apps/web/src/services -type f -name "*.ts" | xargs grep -l "exampleQuestions" 2>/dev/null

Repository: agentset-ai/agentset

Length of output: 103


🏁 Script executed:

# Also search for updateHosting function
rg "export.*updateHosting" apps/web/src --type ts

Repository: agentset-ai/agentset

Length of output: 331


🏁 Script executed:

cat -n "apps/web/src/services/hosting/update.ts"

Repository: agentset-ai/agentset

Length of output: 4587


🏁 Script executed:

# Verify if there's any filtering elsewhere in the codebase
rg "filter.*empty" apps/web/src/services/hosting/ --type ts

Repository: agentset-ai/agentset

Length of output: 46


🏁 Script executed:

# Check if there's any normalization in the API layer
rg "exampleQuestions" apps/web/src/app/api/ --type ts -A 3

Repository: agentset-ai/agentset

Length of output: 46


Filter empty strings before submission to prevent backend round-trip inconsistency.

The logic initializes empty arrays as [""] to display an empty input field in the UI, but submits them as-is without filtering. When the backend stores [""] and returns it on next fetch, the data becomes inconsistent—the ternary check at lines 101-106 only transforms when length === 0, so [""] (length 1) won't be transformed back to [].

Filter empty strings in onSubmit before submitting:

exampleQuestions: newData.exampleQuestions.filter(q => q.trim() !== ""),
exampleSearchQueries: newData.exampleSearchQueries.filter(q => q.trim() !== ""),
🤖 Prompt for AI Agents
In
apps/web/src/app/app.agentset.ai/(dashboard)/[slug]/[namespaceSlug]/hosting/use-hosting-form.ts
around lines 101 to 106, the form initializes empty inputs as [""] for UI but
currently submits these unchanged, causing backend-store/round-trip
inconsistency because the length check only handles true empty arrays; update
the onSubmit handler to filter out empty/whitespace-only strings before sending
(e.g., replace submitted exampleQuestions and exampleSearchQueries with filtered
arrays using .filter(q => q.trim() !== "") so [""] becomes [] while preserving
real entries).

Comment on lines +61 to +65
useEffect(() => {
if (virtualIds.length === 1 && fields.length === 0) {
append("" as any);
}
}, [virtualIds, fields, append]);
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

# First, let's read the file to understand the full context
cat -n apps/web/src/components/sortable-list.tsx | head -100

Repository: agentset-ai/agentset

Length of output: 3415


🏁 Script executed:

# Let's see more of the file to understand the complete render and usage
cat -n apps/web/src/components/sortable-list.tsx | tail -80

Repository: agentset-ai/agentset

Length of output: 2242


🏁 Script executed:

# Let's check the context around how form values are passed and initialized
# Look for uses of this SortableList component
rg "SortableList" apps/web --type tsx -B 2 -A 2

Repository: agentset-ai/agentset

Length of output: 91


🏁 Script executed:

# Search for SortableList usage without specifying file type
rg "SortableList" apps/web -B 2 -A 2

Repository: agentset-ai/agentset

Length of output: 2887


🏁 Script executed:

# Let's examine how the form is initialized and passed to SortableList
cat -n apps/web/src/app/app.agentset.ai/'(dashboard)'/[slug]/[namespaceSlug]/hosting/components/tabs/general-tab.tsx | grep -A 30 "exampleQuestions"

Repository: agentset-ai/agentset

Length of output: 288


🏁 Script executed:

# Let's look at the full form initialization in general-tab.tsx to understand
# when exampleQuestions might be empty or out of sync
head -100 apps/web/src/app/app.agentset.ai/'(dashboard)'/[slug]/[namespaceSlug]/hosting/components/tabs/general-tab.tsx

Repository: agentset-ai/agentset

Length of output: 3106


🏁 Script executed:

# Find the use-hosting-form file to understand form initialization
fd "use-hosting-form" apps/web

Repository: agentset-ai/agentset

Length of output: 159


🏁 Script executed:

# Let's examine the form initialization to see how exampleQuestions is set
cat -n apps/web/src/app/app.agentset.ai/'(dashboard)'/[slug]/[namespaceSlug]/hosting/use-hosting-form.ts | head -150

Repository: agentset-ai/agentset

Length of output: 6338


Avoid useEffect for managing minimum item count; enforce this through explicit component logic instead.

This useEffect violates the explicit coding guideline to minimize useEffect hooks in apps/web/**/*.tsx files. The condition virtualIds.length === 1 && fields.length === 0 detects a synchronization issue when items are deleted, but this constraint should be enforced through component logic rather than a side effect.

The form initialization already ensures at least one empty item exists when the data is empty (see use-hosting-form.ts). To maintain this requirement:

  • Prevent removal of the last item directly in handleRemove by checking fields.length === 1
  • Add a minItems prop and validate it explicitly
  • Remove the useEffect entirely
🤖 Prompt for AI Agents
In apps/web/src/components/sortable-list.tsx around lines 61 to 65, remove the
useEffect that appends an item when virtualIds.length === 1 && fields.length ===
0 and instead enforce a minimum item count via component logic: delete the
useEffect block entirely, add a minItems prop (default 1) and validate it at
component entry, and update the handleRemove function to prevent removing the
last allowed item by checking if fields.length <= minItems before calling
remove; ensure any initialization relies on the existing form initialization
(use-hosting-form) so no append side-effect is needed.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants