Skip to content

Add features, refactor user and thread management, update UI and database scripts#488

Merged
AndlerRL merged 57 commits intomainfrom
develop
May 16, 2025
Merged

Add features, refactor user and thread management, update UI and database scripts#488
AndlerRL merged 57 commits intomainfrom
develop

Conversation

@AndlerRL
Copy link
Member

@AndlerRL AndlerRL commented May 16, 2025

Summary by Sourcery

Implement account and thread deletion, image generation, and UI enhancements across the application.

New Features:

  • Add account and thread deletion workflows with confirmation dialogs and Hasura mutations, including cron job to purge data after 30 days.
  • Introduce image generation support with prompt utilities, UI dialog, and components to display and download AI-generated images.
  • Extract common thread-opening logic into a helper and update thread and browse lists to use it.
  • Integrate Twitter pixel for analytics via conditional script injection.
  • Simplify profile routing with default redirects and refactor sidebar navigation for main profile pages.
  • Enhance subscription flow by checking for pending deletion requests on sign-in and refactoring payment context to use session data.

Bug Fixes:

  • Fix deleteThread response handling to return accurate success flags.
  • Correct model enums and update graphQL migrations for Gemini flash variants.
  • Ensure Metadata base URL uses BASE_URL env variable instead of VERCEL_URL.

Enhancements:

  • Refactor PreferenceSection, UserMenu, ThemeToggle, ChatMessage, and sidebar components for improved layout, theming, and code reuse.
  • Filter and cast preference constants based on dev mode and update control types with identifiers.
  • Migrate Hasura service calls: rename getUserRoleByEmail, streamline getThreads arguments, and add success handling on delete mutations.
  • Update subscription and payment components to derive user info from NextAuth session instead of manual props.
  • Clean up duplicate code, remove obsolete preferences and hooks, and consolidate UI class adjustments.

Summary by CodeRabbit

  • New Features

    • Added support for AI-generated images in chat messages, including image rendering, download, and a dialog for generating images with style and detail options.
    • Introduced account deletion request and management, with a 30-day grace period and UI for users to cancel deletion.
    • Added cron job and API endpoint for automated deletion of accounts requested for deletion.
    • Enhanced preferences with a "Danger Zone" for account and thread deletion, including confirmation dialogs.
    • Improved role-based admin mode controls for thread panels and navigation.
    • Added new AI model options, including Gemini 2.0 Flash.
  • Enhancements

    • Improved user menu and sidebar navigation with preferences and subscriptions links, icons, and better state management.
    • Refined subscription and payment flows to use authenticated session data.
    • Updated redirect rules for unified and deeper path matching.
    • Added Twitter Ads tracking script support and new ad configuration options.
  • Bug Fixes

    • Fixed state management and user identification in subscription and payment components.
    • Improved thread fetching and visibility logic for admin and user modes.
  • Refactor

    • Simplified and centralized thread activation logic.
    • Streamlined profile sidebar and user data fetching.
    • Updated preference constants and types for better maintainability.
  • Chores

    • Updated package dependencies for stability and compatibility.
    • Managed large seed and migration files for database consistency.

Bran18 and others added 30 commits March 26, 2025 18:06
* update

* fix: update

* update

* update

* update

* update

* fix: opening threads

* fix: rm threads dropdwon  & added back link to bot page thread view page

* fix: rm threads dropdwon  & added back link to bot page thread view page

* fix: update

* fix: added back to profile page

* fix: added sticky and color
…ock & clipboard hook (#425)

* fix: codeblock ctas

* fix: ts build
…426)

* fix: css handleCLick condition

* fix: get latest search params, continuous thread

* fix(impr): all messages sorting

* perf(impr): sign in & up redirection tweak

* perf(impr): mobile chat css
…ck (#432)

* refactor: use chat and continue generation

* fix: uniq slug and id gen (#433)

* fix: uniq thread + msg slug gen

* style: formatting

* fix: thread user attachments state upt

* perf: impr thread component at all pages + mobile tweaks

* refactor: thread-component card

* chore: restore continue generation v1

* feat(impr): thread component card

* fix: admin panel n actions

* fix: fetch getThreads

* chore: continue conversation v1.2

* chore: continue and update thread content

* chore: add ui control continue generation state

* chore: fix infinity loop

* chore(impr): enable upt msg table permission

* fix: seo thread fetch

* chore: style formating

* fix(impr): continued thread title + thread component reusability

* chore: refactor loadings + extending sonners

---------

Co-authored-by: bran18 <andreyfdez18@gmail.com>

---------

Co-authored-by: Roberto Lucas <andler@bitcash.org>
* feat: add gemini provider

* chore: update icons
* feat(wip): impr continuing thread tags + accordion first msg toggle

* feat(impr): continuing thread tags + accordion at first message + header mobile tweak

* style(impr): mobile thread-component x-axis space

* perf(style): coderabbitai feedbacks

* fix: css typo

* perf: sendMessageFromResponse clicked guard + continued thread tags label tweak

* chore: user thread panel clean up

* fix: user-thread-panel infinite loader

* perf: impr shared accordion animation and ux

* style: defaultAccordionState comments loc

* fix: record type warning, hasura updateMessage

* fix: getThread user data, shared-accordion
* update

* fix: update

* update

* update

* update

* update

* refactor: profile page threads pop up

* fix: update config

* fix: update

* fix: update

* fix: make profile page scroll on hero

* fix: bot make popup and scroll

* fix: make profile page sidebar scroll independently

* fix: make profile page sidebar scroll independently

* fix: check the category along the chatbot when it's not checked

* fix: check the category along the chatbot when it's not checked

---------

Co-authored-by: Roberto Lucas <andler.dev@gmail.com>
Co-authored-by: Roberto Lucas <andler@bitcash.org>
* feat-add-models

* feat-add-models

* feat-add-models

* chore: add model

* fix: typo

* chore: add toggler color
… seeds (#447)

* feat(wip): thread llm context, prev questions

* fix: previousQuestionsString slice

* fix: clickedContentId in followingQuestionsPrompt

* feat: isContinued + model type in message table

* fix: ts typo + sendMessageFromResponse callback call

* fix: ts typo
* fix(wip): bot profile thread list

* style: formatting
* fix: new chat state reset

* fix: genql gen + share link check

* fix: og img

* fix: duplicate role permission in msg table
* chore: restore base version

* chore: add new logic and hooks

* chore: fix providers file

* chore: improve continuation prompt

* chore: add exlucision flag

* chore: add better handler

* chore: updated flow + experimental delay

* chore: extended time

* chore(impr): streamDelayMs experimental feat flag

* style: formatting

---------

Co-authored-by: Roberto Lucas <andler.dev@gmail.com>
* fix: profile sidebar cat opt render

* chore: clean-up
…ess and type support (#456)

* fix: slugify fn

* chore: devMode logs
* fix: slugify first request delay incr + genql ts, seeds & model migration upt

* fix: create thread & msg ts
* update

* fix: update

* update

* update

* update

* update

* fix: use the user avatar or robohash

* fix: added avater to user menu

* fix: user avatar

* fix: reset search input when filter by category or chatbot

* fix: personal chat browse provider + username chk in sign up

* chore: clean duplicated if condition signup

---------

Co-authored-by: Roberto Lucas <andler.dev@gmail.com>
* impr: continuation logic flow

* impr: continuation logic flow

* chore: update createImprovementPrompt

* chore: upt logs

---------

Co-authored-by: Roberto Lucas <andler.dev@gmail.com>
…gic (#462)

* feat: models table

* style: formatting

* fix: continuation accordion content

* fix: sql + metadata typo
AndlerRL and others added 7 commits May 12, 2025 16:58
* chore: enable twitter pixel track

* perf(impr): twitter ads availability + dynamic config
* fix(wip): subscriptions page render

* feat(impr): profile navigation + page ui tweaks

* style: lintin + formatting

* style(css): nav links px on mob

* fix: goToProfile in mob prof sidebar

* fix: build

* fix: thread popup opening at nav

* chore: enable preferences nav on prod
* feat: add image generation support - gemini provider

* chore: add mineType

* chore: add conditional checks
* chore: hasura, set icl seeds chunks

* chore: track backup icl seed loc to lfs

* chore(seeds): uncomment phase 3 topics & add new chatbots + icl metadata rel

* chore: upt phase 3 init config seeds, adding rel

* fix: example seeds integrity

* test: incr hasura max req body

* revert: cloudbuild og config

* chore: restore skipped seed lines
* fix: thread list render states

* chore: linting & format

* fix: thread pop-up on refresh

* fix: user table selection
@AndlerRL AndlerRL requested a review from Copilot May 16, 2025 22:19
@AndlerRL AndlerRL self-assigned this May 16, 2025
@sourcery-ai
Copy link

sourcery-ai bot commented May 16, 2025

Reviewer's Guide

This PR implements end-to-end user deletion flows, refactors profile sidebar and routing, centralizes thread-popup logic, enhances the thread visibility hook, integrates account-deletion checks in sign-in, adds AI image generation support, streamlines subscription components, and updates service methods, configuration, and migrations accordingly.

Sequence Diagram: User Account Deletion Request Process

sequenceDiagram
    actor User
    participant PrefSection as PreferenceSection
    participant AlertDialog as Confirmation Dialog
    participant HasuraSVC as Hasura Service
    participant NextAuth

    User->>PrefSection: Clicks "Delete Account"
    PrefSection->>PrefSection: executeButton("delete_account")
    PrefSection->>AlertDialog: Opens confirmation
    AlertDialog-->>User: Shows "Are you sure?" message
    User->>AlertDialog: Clicks "Delete"
    AlertDialog->>PrefSection: handleDelete()
    PrefSection->>PrefSection: requestUserAccountDelete()
    PrefSection->>HasuraSVC: updateUserDeletionRequest(userId, jwt)
    HasuraSVC->>HasuraSVC: Update user.deletionRequestedAt = now()
    HasuraSVC-->>PrefSection: Success
    PrefSection->>NextAuth: signOut({ callbackUrl: '/' })
    NextAuth-->>User: User signed out, redirected
Loading

Sequence Diagram: Sign-In Process with Account Deletion Check

sequenceDiagram
    actor User
    participant SignInFormComp as SignInForm
    participant NextAuthSVC as NextAuth.signIn
    participant HasuraSVC as Hasura Service
    participant DeletionDialog as DeletionRequest Dialog
    participant Router

    User->>SignInFormComp: Submits email and password
    SignInFormComp->>NextAuthSVC: signIn('credentials', {email, password})
    alt Authentication Fails
        NextAuthSVC-->>SignInFormComp: Error
        SignInFormComp-->>User: Shows error message
    else Authentication Succeeds
        NextAuthSVC-->>SignInFormComp: Success (session created)
        SignInFormComp->>HasuraSVC: getUserByEmail(email)
        HasuraSVC-->>SignInFormComp: User data (including deletionRequestedAt)
        alt User.deletionRequestedAt is set
            SignInFormComp->>DeletionDialog: Opens, shows deletion info and remaining days
            DeletionDialog-->>User: Displays options (Cancel Request / Go Back)
        else User.deletionRequestedAt is null
            SignInFormComp->>Router: router.push('/c')
            Router-->>User: Redirected to dashboard
        end
    end
Loading

Sequence Diagram: AI Image Generation and Display

sequenceDiagram
    actor User
    participant ChatInput
    participant MBChatProvider
    participant AIService as AI Service (e.g., Gemini)
    participant ChatMessageComp as ChatMessage
    participant GeneratedImageComp as GeneratedImage

    User->>ChatInput: Enters prompt for image generation (or uses ImageGeneratorDialog)
    ChatInput->>MBChatProvider: appendWithMbContextPrompts(message, {files: [...]})
    note right of MBChatProvider: If ImageGeneratorDialog used, prompt is already formatted for image gen.
    MBChatProvider->>AIService: createResponseStream(prompt, model with IMAGE modality)
    AIService-->>MBChatProvider: Streamed response (text part, image part with base64 data)
    MBChatProvider->>MBChatProvider: saveMessagesToDB (message with content and image parts)
    MBChatProvider-->>ChatMessageComp: Renders new message
    ChatMessageComp->>ChatMessageComp: Calls ImagesSection()
    ChatMessageComp->>ai_helpers: hasImageGeneration(message)
    ai_helpers-->>ChatMessageComp: true
    ChatMessageComp->>ai_helpers: extractImageContent(message)
    ai_helpers-->>ChatMessageComp: Image data parts
    ChatMessageComp->>GeneratedImageComp: Renders each image
    GeneratedImageComp-->>User: Displays generated image(s)
Loading

ER Diagram: Updates to User Table for Deletion Feature

erDiagram
    User {
        string userId PK
        string email
        string name
        string role
        string slug
        timestamp date_joined
        timestamp last_login
        timestamp deletionRequestedAt "Nullable - NEW"
    }
    note for User "Added 'deletionRequestedAt' to track account deletion requests."
Loading

File-Level Changes

Change Details Files
Account and thread deletion flow added
  • Added AlertDialog in PreferenceSection to confirm deletion actions
  • Implemented requestUserAccountDelete and handleDeleteThreads using useSonner and next-auth signOut
  • Created Hasura service methods updateUserDeletionRequest and deleteUserMessagesAndThreads
  • Built DeletionRequest component and cron route to auto-delete accounts older than 30 days
preference-section.tsx
hasura.service.ts
deletion-request.tsx
delete-requested-accounts/route.ts
Profile sidebar and routing refactored
  • Replaced devMode accordion links with dynamic Sidebar rendering based on isMainProfilePage
  • Updated getUserInfo hook usage and simplified getAsync user fetch
  • Unified sidebar and footer visibility conditions
  • Added redirect logic for /u/[userSlug] routes
profile-page-sidebar.tsx
profile-sidebar.tsx
sidebar.tsx
app/u/[userSlug]/*.tsx
Thread-popup activation logic centralized
  • Extracted getOpeningActiveThreadHelper utility
  • Replaced inline useAsyncFn code in ThreadList and BrowseList
  • Simplified useEffect dependencies for popup activation
lib/threads.ts
thread-list.tsx
browse-list.tsx
ThreadVisibility hook enhanced
  • Replaced threads state with threadsState object including count
  • Refined admin fetch logic and toggleVisibility signature
  • Exposed isAdminMode and initiated admin approval flow
use-thread-visibility.tsx
Sign-in flow augmented with deletion checks
  • Integrated getUserByEmail to fetch deletionRequestedAt
  • Displayed DeletionRequest modal when deletion is pending
  • Added loading spinner and error handling in SignInForm
signin-form.tsx
AI image generation support added
  • Created extractImage helpers and Updated MBChatProvider to populate message.parts
  • Implemented GeneratedImage and ImageGeneratorDialog components
  • Extended ChatMessage to render ImagesSection beneath content
ai-helpers.ts
use-mb-chat.tsx
generated-image.tsx
image-generator-dialog.tsx
chat-message.tsx
Subscription UI and flow streamlined
  • Switched to useSession for user context across subscription components
  • Removed redundant user props in Subscription, Plans, Checkout, PaymentInformation
  • Introduced SubscriptionPageComponent and unified open-wizard logic
subscription.tsx
subscription-page.tsx
plans.tsx
checkout.tsx
payment-information.tsx
Configuration, prompts, and migrations updated
  • Added ads config and Twitter pixel injection in app layout
  • Updated constants with IMAGE_GENERATION_PROMPT_TEMPLATE and createImageGenerationPrompt
  • Introduced new model enums and updated Hasura migrations/seeds
config.env.ts
prompts.ts
app/layout.tsx
migrations
seeds

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@vercel
Copy link

vercel bot commented May 16, 2025

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
masterbots ✅ Ready (Inspect) Visit Preview 💬 Add feedback May 16, 2025 10:21pm

@coderabbitai
Copy link
Contributor

coderabbitai bot commented May 16, 2025

Walkthrough

This update introduces new features, refactors user and thread management, enhances UI components, and restructures database seed and migration scripts. Key changes include improved admin and subscription flows, image generation and rendering in chat, expanded user deletion logic, and streamlined sidebar/profile navigation. Several database seed files are replaced or reorganized, and new cron jobs and redirect rules are added.

Changes

File(s) / Path(s) Change Summary
apps/hasura/metadata/databases/masterbots/tables/public_user.yaml Added deletion_requested_at to selectable columns for user roles.
apps/hasura/migrations/masterbots/1718416395664_create_table_models_enum/up.sql Added 'Gemini__2_0__Flash' enum entry.
apps/hasura/migrations/masterbots/1745471202166_create_table_public_models/up.sql Added 'gemini-2.0-flash-exp' model entry.
apps/hasura/migrations/masterbots/1745923775527_alter_table_public_user_add_column_deletion_requested_at/up.sql, down.sql Migration adds nullable deletion_requested_at column to public.user; down migration is a placeholder.
apps/hasura/seeds/masterbots/1724269974513_init_config_seeds.sql, 1724270512560_init_users_seeds.sql, 1740386119321_init_chatbot_metadata_seeds.sql Updated Git LFS pointer metadata for large seed files.
apps/hasura/seeds/masterbots/1740386118928_init_domain_enum.sql, 1740386128297_init_category_enum.sql, 1740386133107_init_subcategory_enum.sql, 1740386141151_init_tag_enum.sql, 1740386174715_init_example_pt_1.sql, 1740386174815_init_example_pt_2.sql, 1740386174915_init_example_pt_3.sql, 1740386175015_init_example_pt_4.sql, 1740386175115_init_example_pt_5.sql, 1740386175215_init_example_pt_6.sql, 1740386175315_init_example_pt_7.sql, 1740386175415_init_example_pt_8.sql Deleted old enum and example seed files.
apps/hasura/seeds/masterbots/1740386119320_init_domain_enum.sql, 1746466168385_init_category_enum.sql, 1746466170867_init_subcategory_enum.sql, 1746466178152_init_tag_enum_pt_1.sql, 1746466178153_init_tag_enum_pt_2.sql, 1746466541637_init_example_pt_1.sql-1746466541650_init_example_pt_14.sql Added new enum and example seed files using Git LFS.
apps/masterbots.ai/app/actions/ai-main-call.ts Added conditional responseModalities for Gemini 2.0 Flash experimental model.
apps/masterbots.ai/app/actions/subscriptions.ts Removed 'use server' directive.
apps/masterbots.ai/app/api/chat/models/models.ts Renamed and added enum values for Gemini models.
apps/masterbots.ai/app/api/cron/delete-requested-accounts/route.ts Added API route to delete accounts with deletion requests older than 30 days.
apps/masterbots.ai/app/api/cron/unverified-users/route.ts Removed extraneous blank line.
apps/masterbots.ai/app/c/[category]/[domain]/[chatbot]/[threadSlug]/[threadQuestionSlug]/page.tsx, [threadSlug]/page.tsx, [category]/[domain]/[chatbot]/page.tsx, c/page.tsx Added role-based admin mode prop to ThreadPanel; consolidated admin UI logic.
apps/masterbots.ai/app/c/p/page.tsx Removed user prop from Subscription component.
apps/masterbots.ai/app/layout.tsx Injected Twitter Ads script conditionally; changed metadata base URL env var.
apps/masterbots.ai/app/u/[userSlug]/page.tsx, u/[userSlug]/s/page.tsx, u/page.tsx Added default redirect components for user profile routes.
apps/masterbots.ai/app/u/[userSlug]/s/subs/page.tsx Replaced static content with SubscriptionPageComponent.
apps/masterbots.ai/auth.ts Switched user role fetch logic to getUserByEmail.
apps/masterbots.ai/components/auth/deletion-request.tsx Added new DeletionRequest modal component for account deletion status/cancellation.
apps/masterbots.ai/components/auth/signin-form.tsx Enhanced sign-in with loading, user existence, and deletion request handling.
apps/masterbots.ai/components/layout/header/user-menu.tsx Improved dropdown state, added preferences/subscriptions, reorganized menu groups and icons.
apps/masterbots.ai/components/layout/profile/profile-page-sidebar.tsx Refactored profile sidebar, removed dev-mode UI, simplified layout, made user fetch async.
apps/masterbots.ai/components/layout/sidebar/profile-sidebar.tsx Refactored navigation to use Link, unified styling, added new preference/subscription links.
apps/masterbots.ai/components/layout/sidebar/sidebar-category-general.tsx, sidebar.tsx Added/inherited min-height classes; changed wrapper to <nav>.
apps/masterbots.ai/components/routes/browse/browse-list.tsx, thread/thread-list.tsx Refactored thread opening logic to use getOpeningActiveThreadHelper.
apps/masterbots.ai/components/routes/chat/chat-message.tsx Added ImagesSection to render AI-generated images in messages.
apps/masterbots.ai/components/routes/chat/chat-panel.tsx Removed unused icon import; increased z-index.
apps/masterbots.ai/components/routes/preferences/preference-section.tsx Added confirmation dialog for account/thread deletion; improved destructive action handling.
apps/masterbots.ai/components/routes/preferences/preferences.tsx Filtered preferences by dev mode and section; updated imports.
apps/masterbots.ai/components/routes/profile/user-thread-list.tsx Removed padding class; minor formatting.
apps/masterbots.ai/components/routes/subscription/checkout.tsx, payment-information.tsx, plans.tsx, subscription.tsx, succes-content.tsx Refactored to use session data for user/email; updated navigation and prop usage.
apps/masterbots.ai/components/routes/subscription/subscription-page.tsx Added new SubscriptionPageComponent with subscription creation UI.
apps/masterbots.ai/components/routes/thread/thread-component.tsx Removed trailing blank line.
apps/masterbots.ai/components/routes/thread/thread-panel.tsx Added isAdminMode prop to render AdminModeToggle.
apps/masterbots.ai/components/routes/thread/user-thread-panel.tsx Refactored to use passed user props, simplified ownership checks, adjusted admin mode logic.
apps/masterbots.ai/components/shared/generated-image.tsx Added new GeneratedImage component for AI-generated images with download.
apps/masterbots.ai/components/shared/image-generator-dialog.tsx Added new ImageGeneratorDialog for user-driven image prompt generation.
apps/masterbots.ai/components/shared/theme-toggle.tsx Updated to accept props, removed wrapper, improved class merging.
apps/masterbots.ai/components/ui/button.tsx Added hover styles to sideBarProfile button variant.
apps/masterbots.ai/lib/constants/preferences.ts Commented out certain preferences, added buttonId to danger buttons, improved type assertions.
apps/masterbots.ai/lib/constants/prompts.ts Added image generation prompt template and helper function.
apps/masterbots.ai/lib/helpers/ai-helpers.ts Added image extraction/detection helpers for messages.
apps/masterbots.ai/lib/hooks/use-mb-chat.tsx Added support for generated image files in chat message processing.
apps/masterbots.ai/lib/hooks/use-payment.tsx Removed user state/method from payment context.
apps/masterbots.ai/lib/hooks/use-sidebar.tsx Removed extraneous blank line.
apps/masterbots.ai/lib/hooks/use-thread-visibility.tsx Enhanced thread state, refactored unapproved thread loading, improved admin mode logic.
apps/masterbots.ai/lib/models.tsx Reformatted conditionals in getModelIcon.
apps/masterbots.ai/lib/threads.ts Added getOpeningActiveThreadHelper for thread popup activation.
apps/masterbots.ai/package.json, packages/mb-genql/package.json, package.json Updated genql version range; added @types/bun dev dependency.
apps/masterbots.ai/services/hasura/hasura.service.ts, hasura.service.type.ts Refactored thread/user functions, added user deletion helpers, updated types for admin mode and user info.
apps/masterbots.ai/types/types.ts Added buttonId to PreferenceItemType.
apps/masterbots.ai/vercel.json Added cron job for account deletion, expanded and unified redirect rules.
packages/mb-env/src/config.env.ts Added ads section to app config for Google and Twitter Ads.

Sequence Diagram(s)

Account Deletion Cron Job Flow

sequenceDiagram
    participant Cron as Cron Scheduler
    participant API as /api/cron/delete-requested-accounts
    participant Hasura as Hasura Client

    Cron->>API: Trigger GET /api/cron/delete-requested-accounts
    API->>Hasura: Query users with deletionRequestedAt <= 30 days ago
    Hasura-->>API: Return user IDs
    alt No users found
        API-->>Cron: 200 OK (no users to delete)
    else Users found
        API->>Hasura: Delete threads and users for found IDs
        Hasura-->>API: Return affected rows
        API-->>Cron: 200 OK (deleted users and threads count)
    end
Loading

User-Initiated Account Deletion (Preferences)

sequenceDiagram
    participant User
    participant UI as PreferenceSection
    participant Hasura as Hasura Service
    participant Auth as Auth System

    User->>UI: Click "Delete Account"
    UI->>UI: Show confirmation dialog
    User->>UI: Confirm deletion
    UI->>Hasura: updateUserDeletionRequest (set deletionRequestedAt)
    Hasura-->>UI: Success/Failure
    alt Success
        UI->>Auth: Sign out and redirect
    else Failure
        UI->>User: Show error notification
    end
Loading

Sign-In With Deletion Request Handling

sequenceDiagram
    participant User
    participant SignInForm
    participant Hasura
    participant UI as DeletionRequest Modal

    User->>SignInForm: Submit credentials
    SignInForm->>Hasura: getUserByEmail
    Hasura-->>SignInForm: Return user data
    alt User not found
        SignInForm-->>User: Show "Sign up" error
    else Deletion requested
        SignInForm-->>UI: Show DeletionRequest modal
    else Normal user
        SignInForm-->>User: Redirect to dashboard
    end
Loading

Image Generation in Chat

sequenceDiagram
    participant User
    participant ImageGenDialog
    participant Chat as useMBChat
    participant UI as ChatMessage

    User->>ImageGenDialog: Open dialog, input description/style/detail
    ImageGenDialog->>Chat: Append image generation prompt
    Chat->>UI: Render chat message with generated images
    UI->>User: Show images, allow download
Loading

Poem

A bunny hops with code delight,
New features gleam, the UI bright.
Images bloom in chat’s embrace,
Preferences, threads, all find their place.
Deletion’s handled, seeds refreshed,
Cron jobs run while users rest.
With every merge, the garden grows—
Onward, masterbots, as springtime flows!

(_/)
( •_•)
/ >🌱

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

apps/masterbots.ai/app/api/chat/models/models.ts

Oops! Something went wrong! :(

ESLint: 8.57.1

ESLint couldn't find the config "next/core-web-vitals" to extend from. Please check that the name of the config is correct.

The config "next/core-web-vitals" was referenced from the config file in "/apps/masterbots.ai/.eslintrc.json".

If you still have problems, please stop by https://eslint.org/chat/help to chat with the team.

apps/masterbots.ai/app/actions/ai-main-call.ts

Oops! Something went wrong! :(

ESLint: 8.57.1

ESLint couldn't find the config "next/core-web-vitals" to extend from. Please check that the name of the config is correct.

The config "next/core-web-vitals" was referenced from the config file in "/apps/masterbots.ai/.eslintrc.json".

If you still have problems, please stop by https://eslint.org/chat/help to chat with the team.

apps/masterbots.ai/app/api/cron/delete-requested-accounts/route.ts

Oops! Something went wrong! :(

ESLint: 8.57.1

ESLint couldn't find the config "next/core-web-vitals" to extend from. Please check that the name of the config is correct.

The config "next/core-web-vitals" was referenced from the config file in "/apps/masterbots.ai/.eslintrc.json".

If you still have problems, please stop by https://eslint.org/chat/help to chat with the team.

  • 47 others
✨ Finishing Touches
  • 📝 Generate Docstrings

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

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

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

Support

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

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

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

Other keywords and placeholders

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

CodeRabbit Configuration File (.coderabbit.yaml)

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

Documentation and Community

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

@AndlerRL
Copy link
Member Author

AndlerRL commented May 16, 2025

@coderabbitai review

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR cleans up several seed files by removing outdated Git LFS metadata, adds a new column (deletion_requested_at) to the public.user table, updates permissions accordingly, and introduces new model definitions in the migrations.

  • Removed Git LFS pointer metadata from various seed SQL files.
  • Updated seed file hashes and sizes where applicable.
  • Added a new column to public.user with corresponding permission updates and introduced new model variants in migrations.

Reviewed Changes

Copilot reviewed 106 out of 106 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
apps/hasura/seeds/masterbots/*.sql Removed Git LFS metadata lines from seed files.
apps/hasura/migrations/masterbots/1745923775527_alter_table_public_user_add_column_deletion_requested_at/up.sql Added the deletion_requested_at column to the public.user table.
apps/hasura/migrations/masterbots/1745923775527_alter_table_public_user_add_column_deletion_requested_at/down.sql Contains a placeholder for a down migration requiring review.
apps/hasura/migrations/masterbots/1745471202166_create_table_public_models/up.sql Updated model insertions to include a new model definition.
apps/hasura/migrations/masterbots/1718416395664_create_table_models_enum/up.sql Added a new model enum tuple for the gemini-2.0-flash-exp model.
apps/hasura/metadata/databases/masterbots/tables/public_user.yaml Updated select_permissions to include the new deletion_requested_at column.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented May 16, 2025

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai bot changed the title @coderabbitai Add features, refactor user and thread management, update UI and database scripts May 16, 2025
@AndlerRL AndlerRL merged commit d8466d1 into main May 16, 2025
2 checks passed
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 21

🔭 Outside diff range comments (8)
apps/hasura/metadata/databases/masterbots/tables/public_user.yaml (1)

162-199: ⚠️ Potential issue

Missing update permission for deletion_requested_at

The update permissions for both moderator and user roles don't include the new deletion_requested_at column, which means users won't be able to cancel their deletion requests, and moderators won't be able to manage them.

Add the deletion_requested_at column to the update permissions for both roles:

  - role: moderator
    permission:
      columns:
        - bio
        - date_joined
        - email
        - favourite_topic
        - get_free_month
        - is_blocked
        - is_verified
        - last_login
+       - deletion_requested_at
        - pro_user_subscription_id
        - profile_picture
        - role
        - slug
        - user_id
        - username

And similarly for the user role:

  - role: user
    permission:
      columns:
        - bio
        - favourite_topic
        - get_free_month
        - last_login
        - password
+       - deletion_requested_at
        - pro_user_subscription_id
        - profile_picture
        - role
        - slug
        - username
apps/masterbots.ai/components/routes/thread/thread-list.tsx (1)

72-84: ⚠️ Potential issue

Loading flag is ineffective – the flag is reset synchronously

activateThreadPopup sets loadingThread to true, immediately flips it to false in the same tick, so the skeleton never appears.
Either make the function async and await a real asynchronous task, or drop the loading flag entirely.

-const activateThreadPopup = (thread: Thread) => {
-  try {
-    setLoadingThread(true)
-    setActiveThread(thread)
-    setIsOpenPopup(true)
-  } catch (error) {
-    ...
-  } finally {
-    setLoadingThread(false)
-  }
-}
+const activateThreadPopup = (thread: Thread) => {
+  setActiveThread(thread)
+  setIsOpenPopup(true)
+}
apps/masterbots.ai/components/layout/header/user-menu.tsx (1)

78-86: ⚠️ Potential issue

Guard against empty image src to avoid Next.js runtime error

When data?.profilePicture is falsy you fall back to an empty string.
<Image> throws if src is an empty string, so the component will crash while the user data is loading.

- <Image … src={data?.profilePicture ? data.profilePicture : ''} … />
+ {data?.profilePicture ? (
+   <Image … src={data.profilePicture} … />
+ ) : (
+   /* fallback avatar (initials) or a blurred placeholder */
+ )}

Alternatively, move the user?.image condition inside and only render <Image> when data?.profilePicture is truthy.

apps/masterbots.ai/components/layout/sidebar/profile-sidebar.tsx (1)

57-65: ⚠️ Potential issue

Guard against missing user.slug to avoid malformed routes

goToProfile blindly interpolates user.slug into the URL.
If slug is undefined (possible when the auth provider hasn’t populated the field yet, or the type definition doesn’t include it), the app will navigate to /u/undefined/t, breaking the profile page.

-	router.push(`/u/${user.slug}/t`)
+	if (!user.slug) {
+		console.error('User slug is missing – aborting navigation')
+		return
+	}
+	router.push(`/u/${user.slug}/t`)
apps/masterbots.ai/lib/hooks/use-thread-visibility.tsx (1)

115-122: ⚠️ Potential issue

Potential runtime error: getThreads result shape differs from state shape

getThreads previously returned Thread[]; the new state expects { threads, count }.
Passing the array directly to setThreadsState will break rendering or TypeScript compilation.

Ensure the service returns the new shape or adapt the setter:

-const fetchedThreads = await getThreads({ … })
-if (fetchedThreads) {
-  setThreadsState(fetchedThreads)
-}
+const fetchedThreads = await getThreads({ … })
+if (fetchedThreads) {
+  setThreadsState({
+    threads: fetchedThreads.threads ?? fetchedThreads, // fallback for old shape
+    count: fetchedThreads.count ?? fetchedThreads.length,
+  })
+}
apps/masterbots.ai/services/hasura/hasura.service.ts (3)

274-303: 🛠️ Refactor suggestion

⚠️ Potential issue

Private / un-approved threads can slip through & domain filter silently ignored

The new baseThreadsArguments no longer appends isPublic / isApproved constraints when the caller is not filtering by userId.
As a consequence, a public browse page that supplies only chatbotName, categoryId, or domain will now return all threads for that bot/category – including drafts and content awaiting moderation.

In addition, when the caller passes only domain, the where clause is not produced because the outer condition chatbotName || categoryId evaluates to false, so the domain filter is dropped entirely.

 const baseThreadsArguments = {
-    ...(chatbotName || categoryId
+    ...(chatbotName || categoryId || domain               // keep domain-only queries
         ? {
              where: {
                 chatbot: {
@@
                 ...(userId ? { userId: { _eq: userId } } : {}),
+                // apply default visibility rules for anonymous/non-admin users
+                ...(!userId && {
+                    isPublic: { _eq: true },
+                    isApproved: { _eq: true },
+                }),
              },
          }
-        : userId
-            ? { where: { userId: { _eq: userId } } }
-            : {}),
+        : userId                                   // personal dashboard
+            ? { where: { userId: { _eq: userId } } }
+            : {
+                where: {                           // generic browse
+                    isPublic: { _eq: true },
+                    isApproved: { _eq: true },
+                },
+            }),
 }

This preserves the old safety net while still allowing admins (or the owner) to bypass it explicitly.
Please adjust accompanying unit / integration tests accordingly.

Also applies to: 356-366


760-768: ⚠️ Potential issue

isAdminMode exposes unapproved threads without authentication & lacks default

  1. isAdminMode can be set to true from the browser while the client is instantiated without jwt/adminSecret, effectively requesting un-approved data as an anonymous user. Unless Hasura row-level-permissions block it, this is a privilege escalation vector.
  2. The parameter is currently required. Mark it as optional (isAdminMode = false) to avoid undefinedfalsey bugs and improve DX.
-export async function getBrowseThreads({
+export async function getBrowseThreads({
@@
-    isAdminMode,
+    isAdminMode = false,

When isAdminMode is true, enforce proper credentials:

if (isAdminMode && !jwt) {
    throw new Error('Admin mode requires authentication');
}
const client = getHasuraClient({ jwt });

Finally, remember to update the type definition in hasura.service.type.ts.

Also applies to: 820-827


1159-1175: 💡 Verification agent

🧩 Analysis chain

Empty JWT token & broad return shape introduce security / DX issues

  • Using getHasuraClient({ jwt: '' }) sends an empty bearer token header (Authorization: Bearer ).
    – This is equivalent to anonymous access but confuses observability & cache layers.
    – Simply omit the field: getHasuraClient({}).

  • Function name implies a single record, but you return { users: User[] }.
    Either rename to getUsersByEmail or return user[0] (with null-safety).

Suggested minimal patch:

-const client = getHasuraClient({ jwt: '' })
+const client = getHasuraClient({})

 // …
-return { users: user as User[] }
+return { user: user[0] as User | null }

Also consider guarding the request with adminSecret (or appropriate role) because email look-ups can reveal account existence to unauthorised callers.


The repository files aren’t available to inspect right now—let’s load the full getUserByEmail implementation to confirm how it returns values. Please run:


🏁 Script executed:

#!/bin/bash
# Show the full getUserByEmail function (with 20 lines of context after start)
rg -n -A20 "export async function getUserByEmail" apps/masterbots.ai/services/hasura/hasura.service.ts

Length of output: 670


Let’s verify how getHasuraClient is defined—specifically whether its jwt option is optional and how headers are set. Please run:


🏁 Script executed:

#!/bin/bash
# Find its definition and inspect parameter defaults
rg -n -C5 "export function getHasuraClient" -g "*.ts" 
rg -n -C5 "export const getHasuraClient" -g "*.ts"

Length of output: 817


To inspect how getHasuraClient handles its parameters and headers, dump its full definition:


🏁 Script executed:

#!/bin/bash
# Print getHasuraClient implementation
sed -n -e '/export function getHasuraClient/,/^}/p' packages/mb-lib/src/hasura/hasura.lib.ts

Length of output: 1150


Remove JWT override & tighten return shape

The getHasuraClient function no longer accepts a jwt parameter—calling it with an object is ignored (or will error). To use the configured admin secret, invoke it without arguments. Also, getUserByEmail returns a list (users: User[]) but its name implies a single user. Align these by either renaming the function or returning only the first match.

• File: apps/masterbots.ai/services/hasura/hasura.service.ts
• Lines: 1159–1177

Suggested patch:

- const client = getHasuraClient({ jwt: '' })
+ const client = getHasuraClient()

// …

- return { users: user as User[] }
+ return { user: (user[0] as User) || null }

Consider adding service-level authorization checks to prevent unauthorised email enumeration.

♻️ Duplicate comments (1)
apps/hasura/migrations/masterbots/1745923775527_alter_table_public_user_add_column_deletion_requested_at/down.sql (1)

1-4: Incomplete down migration script

The down migration script contains only comments and doesn't implement the actual SQL command to drop the column.

Implement a proper down migration to drop the 'deletion_requested_at' column:

-- Could not auto-generate a down migration.
-- Please write an appropriate down migration for the SQL below:
-- alter table "public"."user" add column "deletion_requested_at" timestamptz
--  null;
+ALTER TABLE "public"."user" DROP COLUMN IF EXISTS "deletion_requested_at";
🧹 Nitpick comments (30)
apps/masterbots.ai/package.json (1)

110-111: Pin @types/bun to a specific version for reproducible builds
The "latest" tag can unexpectedly introduce breaking changes when new type definitions are published. Consider aligning this with the monorepo’s TypeScript version (e.g. ^5.8.2) or another fixed version to ensure consistency across environments.

packages/mb-genql/package.json (1)

25-25: Ensure consistency across GenQL-related packages
You’ve pinned genql to ^2.0.1 but left @genql/cli and @genql/runtime at "latest". This mismatch can lead to runtime or CLI incompatibilities. Consider aligning all three to the same major version range (e.g. ^2.0.1) to guarantee compatibility.

package.json (1)

27-27: Align root GenQL devDependency with workspace packages
The main package.json now pins "genql": "^2.0.1". To maintain version harmony, update @genql/cli and @genql/runtime in this file (and across other workspaces) to the same semver range, avoiding potential discrepancies during CI or local development.

apps/masterbots.ai/components/routes/profile/user-thread-list.tsx (1)

15-15: Extra blank line after early return.
The inserted blank line after if (!user) return null is an unnecessary formatting change that may disrupt consistency with surrounding components. Consider removing it to adhere to the established style.

apps/masterbots.ai/lib/models.tsx (1)

26-30: Consider adding braces to the multi-line if for clarity
While the current single-statement if is valid, wrapping the return in braces improves readability and consistency:

-if (
-	model.startsWith('openai') ||
-	model.startsWith('gpt') ||
-	model.startsWith('o4-mini')
-)
-	return <IconOpenAI />
+if (
+	model.startsWith('openai') ||
+	model.startsWith('gpt') ||
+	model.startsWith('o4-mini')
+) {
+	return <IconOpenAI />
+}
apps/masterbots.ai/components/layout/sidebar/sidebar.tsx (2)

43-43: Unify Tailwind class for min-height inheritance
Other components use min-h-inherit rather than the bracketed min-h-[inherit]. For consistency, consider:

- 'min-h-[inherit] h-full flex flex-col z-40',
+ 'min-h-inherit h-full flex flex-col z-40',

50-52: Enhance accessibility by adding an aria-label to the <nav>
The <nav> wrapper currently has no accessible name. Recommend:

-<nav className="pt-4 pb-20 size-full scrollbar">
+<nav aria-label="Sidebar categories" className="pt-4 pb-20 size-full scrollbar">

This provides screen readers with context about the navigation region.

apps/masterbots.ai/app/u/[userSlug]/s/subs/page.tsx (1)

1-5: Function name doesn't match component responsibility

The function is named PreferencePage but it renders subscription content via the SubscriptionPageComponent. Consider renaming this function to SubscriptionPage to better reflect its purpose and maintain consistency between component names and their responsibilities.

-export default async function PreferencePage() {
+export default async function SubscriptionPage() {
	return <SubscriptionPageComponent />
}
apps/masterbots.ai/components/routes/subscription/payment-information.tsx (1)

28-29: Add error handling for potentially undefined session user.

The component now correctly uses session-based authentication instead of getting user data from the payment hook. However, there's no protection against a potentially undefined session when accessing the user email in the Stripe confirmation token creation.

Consider adding a null check before using the user email:

-const user = session?.user as User
+const user = session?.user as User | undefined
 
 const handlePaymentSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
   e.preventDefault()

   handleSetLoading(true)
   if (!stripe || !elements) {
     handleSetLoading(false)
     handleSetError('Stripe.js  and Element has not loaded')

     return
   }
+  if (!user?.email) {
+    handleSetLoading(false)
+    handleSetError('User email is required')
+    return
+  }

Also applies to: 37-40

apps/masterbots.ai/components/routes/preferences/preferences.tsx (1)

8-14: Consider refactoring the filtering logic for better readability.

While the filtering logic works correctly, the conditional expression is complex and could be clearer. Consider separating it into more readable conditions or using constants for the section titles to reduce the risk of errors if preference titles change.

-const filteredPreferences = preferences.filter(
-  (section) =>
-    ((section.title === 'General' ||
-     section.title === 'Thread Preferences') &&
-     appConfig.features.devMode) ||
-    section.title === 'Danger Zone',
-)
+const DEV_ONLY_SECTIONS = ['General', 'Thread Preferences']
+const ALWAYS_VISIBLE_SECTIONS = ['Danger Zone']
+
+const filteredPreferences = preferences.filter((section) => 
+  (DEV_ONLY_SECTIONS.includes(section.title) && appConfig.features.devMode) || 
+  ALWAYS_VISIBLE_SECTIONS.includes(section.title)
+)
apps/masterbots.ai/components/routes/subscription/plans.tsx (1)

73-73: Add null check for session data

While you've provided empty default values for email and name, the functions that use this data might expect valid user information. Consider adding validation before calling these functions with potentially empty values.

-		const del = await handleDeleteCustomer(email)
+		if (email) {
+			const del = await handleDeleteCustomer(email)
+			if (del) return router.push('/c')
+		} else {
+			return router.push('/c')
+		}
-		if (del) return router.push('/c')

Similarly, for the handleSubscription call:

			const data = {
				planId: paymentPlan?.id,
				trialPeriodDays: paymentPlan?.recurring?.trial_period_days || 0,
				automatic_payment_methods: {
					enabled: true,
				},
-				email,
-				name: name as string,
+				email: email || '',
+				name: name || '',
			}

Also applies to: 121-123

apps/masterbots.ai/components/routes/subscription/subscription-page.tsx (2)

13-16: Remove stale commented-out code or convert to a TODO

Dead code tends to linger and confuses future maintainers. If you really need to keep the alternate redirect flow, capture it in a proper TODO: comment with context; otherwise delete lines 13-15.


10-12: handleOpenSubscriptionSteps toggles but recreates on every render

The handler is re-created on each render which can cause unnecessary re-renders downstream (e.g., if passed to memoised children). It’s cheap to wrap it in useCallback.

-import { useState } from 'react'
+import { useState, useCallback } from 'react'

-const handleOpenSubscriptionSteps = () => {
-  setOpenSubscriptionSteps(!openSubscriptionSteps)
-}
+const handleOpenSubscriptionSteps = useCallback(
+  () => setOpenSubscriptionSteps((prev) => !prev),
+  [],
+)

Also applies to: 33-41

apps/masterbots.ai/components/auth/deletion-request.tsx (1)

58-60: Dialog is permanently open & cannot be dismissed

open={true} with an onOpenChange that only logs prevents any way to close the modal (e.g., Escape key or clicking outside).
If the intent is to force the user to decide, route them away after cancellation or sign-out; otherwise make the dialog controllable:

-<Dialog open={true} onOpenChange={() => console.log('Dialog closed')}>
+<Dialog open onOpenChange={() => { /* optional redirect */ }}>

Consider removing the prop altogether and letting the component caller decide the open state.

apps/masterbots.ai/lib/helpers/ai-helpers.ts (1)

302-312: Replace any with a typed helper & narrow return payload

The helper currently suppresses type-checking (// biome-ignore … noExplicitAny) and exposes the rest of the codebase to silent type errors.

-// biome-ignore lint/suspicious/noExplicitAny: <explanation>
-export function extractImageFiles(files: any[] | undefined) {
+interface RawFile {
+  mimeType?: string;
+  base64: string;
+  uint8Array: Uint8Array;
+}
+
+export function extractImageFiles(files?: RawFile[]): {
+  base64: string;
+  uint8Array: Uint8Array;
+  mimeType: string;
+}[] {
   if (!files || !Array.isArray(files)) return []

Typing the argument/return value prevents accidental misuse (e.g. passing a single object or a string).

apps/masterbots.ai/components/routes/thread/user-thread-panel.tsx (1)

239-246: Consider adding isAdminMode to the dependency array

threadVisibilityState is derived from isAdminMode. When isAdminMode toggles, but threadVisibilityState has not yet updated, this effect may miss the latest change. Adding it ensures state stays in sync:

-}, [threadVisibilityState])
+}, [threadVisibilityState, isAdminMode])

This is a minor resilience improvement; ignore if threadVisibilityState already captures every isAdminMode transition internally.

apps/masterbots.ai/components/layout/profile/profile-page-sidebar.tsx (4)

26-35: Shadowed variable name reduces clarity
const { user, error } = await getUserInfo(...) re-uses the identifier user that will later become the value returned from the useAsync. Although legal, the shadowing (inner and outer user) is easy to mis-read and complicates debugging.

- const { user, error } = await getUserInfo(userSlug as string)
+ const { user: fetchedUser, error } = await getUserInfo(userSlug as string)
...
- return user
+ return fetchedUser

37-42: sameUser referenced before initialisation
handleToggleThreads closes over sameUser, but the constant is declared after the function. At runtime this works (the binding exists) yet the value is still undefined until the next render, making the guard ineffective on first mount. Move the sameUser declaration above the handler or compute it inside the callback.


60-65: Key check for SPACE is incorrect
KeyboardEvent.key for the space bar is ' ' (single space) or historically 'Spacebar', not 'Space'. The guard currently never triggers, so the sidebar can’t be toggled with the space bar.

-if (e.key === 'Enter' || e.key === 'Space') {
+if (e.key === 'Enter' || e.key === ' ' || e.key === 'Spacebar') {

92-101: Use Link instead of raw <a> for client-side navigation
Within a Next.js app router context, <Link> preserves SPA behaviour and pre-fetching. Swapping to <Link href=...> prevents full page reloads and maintains correct routing state.

apps/masterbots.ai/lib/threads.ts (2)

128-137: Empty threadSlug leads to inefficient query
When none of the route branches sets threadSlug, getThread({ threadSlug: '' }) still fires a network request that will always return null. Add an early return to save a round-trip.

if (!threadSlug) return

153-158: Remove stray console.log before production
Leaving debugging logs in bundled code bloats the console and may leak PII (the slug). Please delete or guard with if (process.env.NODE_ENV === 'development').

apps/masterbots.ai/lib/constants/preferences.ts (2)

24-25: Consider removing redundant type assertions

items is already typed as PreferenceItemType[] by virtue of the parent object’s structure, and the final as const cast is enough to keep literal types. Keeping the extra as PreferenceItemType[] casts is harmless but adds noise and can sometimes mask missing required keys because the cast overrides structural checks.

-        ] as PreferenceItemType[],
+        ],

Same applies to the other sections.
If you rely on as const to preserve literal buttonId strings for discriminated unions, consider casting only the outer array:

export const preferences = [
  /* … */
] as const satisfies readonly {
  /* explicit shape here if needed */
}

Also applies to: 41-42, 113-113


100-110: Ensure buttonId strings remain unique & strongly-typed

'delete_account' and 'delete_threads' look fine now, but because they are plain strings there’s no compiler guarantee against accidental reuse or typos in callers (e.g. 'delete_threds').
You could extract them to a const enum or a string-literal union:

export const enum DangerButtonId {
  DeleteAccount = 'delete_account',
  DeleteThreads = 'delete_threads',
}

buttonId: DangerButtonId.DeleteAccount

and reference the same union in the consuming component to get full type-safety.

apps/masterbots.ai/components/layout/header/user-menu.tsx (2)

130-147: Disable unavailable links instead of preventing default

Rendering an anchor and then preventDefault() when devMode is off still lets screen-readers announce it as an active link and breaks expected keyboard behaviour.

Consider:

- <Link href={appConfig.features.devMode ? … : '#'} … onClick={…}>
+ {appConfig.features.devMode ? (
+   <Link href={`/u/${user.slug}/s/pref`} …>
+     Preferences <SettingsIcon …/>
+   </Link>
+ ) : (
+   <span className="flex w-full gap-4 px-0 text-sm opacity-50 cursor-not-allowed">
+     Preferences <SettingsIcon …/>
+   </span>
+ )}

This keeps semantics correct and avoids unnecessary preventDefault logic.


48-65: Abort stale fetch requests to avoid memory leaks

If the component unmounts before getUserInfoFromBrowse resolves, setData will try to set state on an unmounted component. Wrap the fetch in an abortable controller or track a mounted flag:

React.useEffect(() => {
  if (!user?.slug) return
  let cancelled = false
  ;(async () => {
    try {
      const userData = await getUserInfoFromBrowse(user.slug!)
      if (!cancelled) setData(userData as User)
    } catch (e) { /* … */ }
  })()
  return () => { cancelled = true }
}, [user?.slug])
apps/masterbots.ai/components/routes/preferences/preference-section.tsx (2)

90-124: Duplicate deletion logic could be consolidated

requestUserAccountDelete and handleDeleteThreads share nearly identical JWT / error-handling scaffolding. Extract a generic helper to DRY up the component and make future maintenance easier:

async function callDeletion<T>(
  fn: (args: {userId: string; jwt: string}) => Promise<T>,
  successMsg: string
) {  }

Then invoke with the specific mutation.
This keeps the component lean and reduces the risk of inconsistencies (e.g. different Sonner messages, typo in “deletion successfully.”).


158-166: Provide clearer destructive action affordances

While the spinner disables the button, users can still close the dialog with the Cancel button, potentially leaving isRemovePending stuck if the mutation races.
Either:

  1. Disable the whole dialog while pending, or
  2. Keep the dialog open until the promise resolves and show a success / error state inside.

This improves feedback and prevents confusing intermediate UI states.

apps/masterbots.ai/lib/hooks/use-thread-visibility.tsx (2)

64-71: State setter name and shape mismatch hinder readability

setThreads now manages an object ({ threads, count }), but the setter is still named as if it sets an array. Renaming improves clarity and prevents accidental misuse.

-const [threadsState, setThreads] = useState<{ … }>(…)
+const [threadsState, setThreadsState] = useState<{ … }>(…)

(remember to update all calls).


193-198: await on synchronous constant is unnecessary

botNames is a plain Map, not a promise. Using await adds pointless micro-tasks and misleads readers.

-const botSlugs = await botNames
+const botSlugs = botNames
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
Cache: Disabled due to data retention organization setting
Knowledge Base: Disabled due to data retention organization setting

📥 Commits

Reviewing files that changed from the base of the PR and between 2ef3645 and 7fd35ab.

⛔ Files ignored due to path filters (4)
  • bun.lock is excluded by !**/*.lock
  • packages/mb-genql/generated/schema.graphql is excluded by !**/generated/**
  • packages/mb-genql/generated/schema.ts is excluded by !**/generated/**
  • packages/mb-genql/generated/types.ts is excluded by !**/generated/**
📒 Files selected for processing (99)
  • apps/hasura/metadata/databases/masterbots/tables/public_user.yaml (3 hunks)
  • apps/hasura/migrations/masterbots/1718416395664_create_table_models_enum/up.sql (1 hunks)
  • apps/hasura/migrations/masterbots/1745471202166_create_table_public_models/up.sql (1 hunks)
  • apps/hasura/migrations/masterbots/1745923775527_alter_table_public_user_add_column_deletion_requested_at/down.sql (1 hunks)
  • apps/hasura/migrations/masterbots/1745923775527_alter_table_public_user_add_column_deletion_requested_at/up.sql (1 hunks)
  • apps/hasura/seeds/masterbots/1724269974513_init_config_seeds.sql (1 hunks)
  • apps/hasura/seeds/masterbots/1724270512560_init_users_seeds.sql (1 hunks)
  • apps/hasura/seeds/masterbots/1740386118928_init_domain_enum.sql (0 hunks)
  • apps/hasura/seeds/masterbots/1740386119320_init_domain_enum.sql (1 hunks)
  • apps/hasura/seeds/masterbots/1740386119321_init_chatbot_metadata_seeds.sql (1 hunks)
  • apps/hasura/seeds/masterbots/1740386128297_init_category_enum.sql (0 hunks)
  • apps/hasura/seeds/masterbots/1740386133107_init_subcategory_enum.sql (0 hunks)
  • apps/hasura/seeds/masterbots/1740386141151_init_tag_enum.sql (0 hunks)
  • apps/hasura/seeds/masterbots/1740386174715_init_example_pt_1.sql (0 hunks)
  • apps/hasura/seeds/masterbots/1740386174815_init_example_pt_2.sql (0 hunks)
  • apps/hasura/seeds/masterbots/1740386174915_init_example_pt_3.sql (0 hunks)
  • apps/hasura/seeds/masterbots/1740386175015_init_example_pt_4.sql (0 hunks)
  • apps/hasura/seeds/masterbots/1740386175115_init_example_pt_5.sql (0 hunks)
  • apps/hasura/seeds/masterbots/1740386175215_init_example_pt_6.sql (0 hunks)
  • apps/hasura/seeds/masterbots/1740386175315_init_example_pt_7.sql (0 hunks)
  • apps/hasura/seeds/masterbots/1740386175415_init_example_pt_8.sql (0 hunks)
  • apps/hasura/seeds/masterbots/1746466168385_init_category_enum.sql (1 hunks)
  • apps/hasura/seeds/masterbots/1746466170867_init_subcategory_enum.sql (1 hunks)
  • apps/hasura/seeds/masterbots/1746466178152_init_tag_enum_pt_1.sql (1 hunks)
  • apps/hasura/seeds/masterbots/1746466178153_init_tag_enum_pt_2.sql (1 hunks)
  • apps/hasura/seeds/masterbots/1746466541637_init_example_pt_1.sql (1 hunks)
  • apps/hasura/seeds/masterbots/1746466541638_init_example_pt_2.sql (1 hunks)
  • apps/hasura/seeds/masterbots/1746466541639_init_example_pt_3.sql (1 hunks)
  • apps/hasura/seeds/masterbots/1746466541640_init_example_pt_4.sql (1 hunks)
  • apps/hasura/seeds/masterbots/1746466541641_init_example_pt_5.sql (1 hunks)
  • apps/hasura/seeds/masterbots/1746466541642_init_example_pt_6.sql (1 hunks)
  • apps/hasura/seeds/masterbots/1746466541643_init_example_pt_7.sql (1 hunks)
  • apps/hasura/seeds/masterbots/1746466541644_init_example_pt_8.sql (1 hunks)
  • apps/hasura/seeds/masterbots/1746466541645_init_example_pt_9.sql (1 hunks)
  • apps/hasura/seeds/masterbots/1746466541646_init_example_pt_10.sql (1 hunks)
  • apps/hasura/seeds/masterbots/1746466541647_init_example_pt_11.sql (1 hunks)
  • apps/hasura/seeds/masterbots/1746466541648_init_example_pt_12.sql (1 hunks)
  • apps/hasura/seeds/masterbots/1746466541649_init_example_pt_13.sql (1 hunks)
  • apps/hasura/seeds/masterbots/1746466541650_init_example_pt_14.sql (1 hunks)
  • apps/masterbots.ai/app/actions/ai-main-call.ts (1 hunks)
  • apps/masterbots.ai/app/actions/subscriptions.ts (0 hunks)
  • apps/masterbots.ai/app/api/chat/models/models.ts (1 hunks)
  • apps/masterbots.ai/app/api/cron/delete-requested-accounts/route.ts (1 hunks)
  • apps/masterbots.ai/app/api/cron/unverified-users/route.ts (0 hunks)
  • apps/masterbots.ai/app/c/[category]/[domain]/[chatbot]/[threadSlug]/[threadQuestionSlug]/page.tsx (3 hunks)
  • apps/masterbots.ai/app/c/[category]/[domain]/[chatbot]/[threadSlug]/page.tsx (3 hunks)
  • apps/masterbots.ai/app/c/[category]/[domain]/[chatbot]/page.tsx (3 hunks)
  • apps/masterbots.ai/app/c/p/page.tsx (1 hunks)
  • apps/masterbots.ai/app/c/page.tsx (1 hunks)
  • apps/masterbots.ai/app/layout.tsx (2 hunks)
  • apps/masterbots.ai/app/u/[userSlug]/page.tsx (1 hunks)
  • apps/masterbots.ai/app/u/[userSlug]/s/page.tsx (1 hunks)
  • apps/masterbots.ai/app/u/[userSlug]/s/subs/page.tsx (1 hunks)
  • apps/masterbots.ai/app/u/page.tsx (1 hunks)
  • apps/masterbots.ai/auth.ts (2 hunks)
  • apps/masterbots.ai/components/auth/deletion-request.tsx (1 hunks)
  • apps/masterbots.ai/components/auth/signin-form.tsx (2 hunks)
  • apps/masterbots.ai/components/layout/header/user-menu.tsx (4 hunks)
  • apps/masterbots.ai/components/layout/profile/profile-page-sidebar.tsx (3 hunks)
  • apps/masterbots.ai/components/layout/sidebar/profile-sidebar.tsx (5 hunks)
  • apps/masterbots.ai/components/layout/sidebar/sidebar-category-general.tsx (1 hunks)
  • apps/masterbots.ai/components/layout/sidebar/sidebar.tsx (1 hunks)
  • apps/masterbots.ai/components/routes/browse/browse-list.tsx (2 hunks)
  • apps/masterbots.ai/components/routes/chat/chat-message.tsx (5 hunks)
  • apps/masterbots.ai/components/routes/chat/chat-panel.tsx (1 hunks)
  • apps/masterbots.ai/components/routes/preferences/preference-section.tsx (1 hunks)
  • apps/masterbots.ai/components/routes/preferences/preferences.tsx (1 hunks)
  • apps/masterbots.ai/components/routes/profile/user-thread-list.tsx (1 hunks)
  • apps/masterbots.ai/components/routes/subscription/checkout.tsx (3 hunks)
  • apps/masterbots.ai/components/routes/subscription/payment-information.tsx (1 hunks)
  • apps/masterbots.ai/components/routes/subscription/plans.tsx (4 hunks)
  • apps/masterbots.ai/components/routes/subscription/subscription-page.tsx (1 hunks)
  • apps/masterbots.ai/components/routes/subscription/subscription.tsx (2 hunks)
  • apps/masterbots.ai/components/routes/subscription/succes-content.tsx (2 hunks)
  • apps/masterbots.ai/components/routes/thread/thread-component.tsx (0 hunks)
  • apps/masterbots.ai/components/routes/thread/thread-list.tsx (3 hunks)
  • apps/masterbots.ai/components/routes/thread/thread-panel.tsx (2 hunks)
  • apps/masterbots.ai/components/routes/thread/user-thread-panel.tsx (10 hunks)
  • apps/masterbots.ai/components/shared/generated-image.tsx (1 hunks)
  • apps/masterbots.ai/components/shared/image-generator-dialog.tsx (1 hunks)
  • apps/masterbots.ai/components/shared/theme-toggle.tsx (1 hunks)
  • apps/masterbots.ai/components/ui/button.tsx (1 hunks)
  • apps/masterbots.ai/lib/constants/preferences.ts (5 hunks)
  • apps/masterbots.ai/lib/constants/prompts.ts (1 hunks)
  • apps/masterbots.ai/lib/helpers/ai-helpers.ts (1 hunks)
  • apps/masterbots.ai/lib/hooks/use-mb-chat.tsx (2 hunks)
  • apps/masterbots.ai/lib/hooks/use-payment.tsx (0 hunks)
  • apps/masterbots.ai/lib/hooks/use-sidebar.tsx (0 hunks)
  • apps/masterbots.ai/lib/hooks/use-thread-visibility.tsx (7 hunks)
  • apps/masterbots.ai/lib/models.tsx (1 hunks)
  • apps/masterbots.ai/lib/threads.ts (2 hunks)
  • apps/masterbots.ai/package.json (1 hunks)
  • apps/masterbots.ai/services/hasura/hasura.service.ts (9 hunks)
  • apps/masterbots.ai/services/hasura/hasura.service.type.ts (1 hunks)
  • apps/masterbots.ai/types/types.ts (1 hunks)
  • apps/masterbots.ai/vercel.json (1 hunks)
  • package.json (1 hunks)
  • packages/mb-env/src/config.env.ts (1 hunks)
  • packages/mb-genql/package.json (1 hunks)
💤 Files with no reviewable changes (17)
  • apps/masterbots.ai/components/routes/thread/thread-component.tsx
  • apps/masterbots.ai/lib/hooks/use-sidebar.tsx
  • apps/masterbots.ai/app/api/cron/unverified-users/route.ts
  • apps/hasura/seeds/masterbots/1740386175415_init_example_pt_8.sql
  • apps/hasura/seeds/masterbots/1740386174715_init_example_pt_1.sql
  • apps/hasura/seeds/masterbots/1740386175215_init_example_pt_6.sql
  • apps/hasura/seeds/masterbots/1740386175115_init_example_pt_5.sql
  • apps/masterbots.ai/app/actions/subscriptions.ts
  • apps/hasura/seeds/masterbots/1740386174915_init_example_pt_3.sql
  • apps/hasura/seeds/masterbots/1740386174815_init_example_pt_2.sql
  • apps/hasura/seeds/masterbots/1740386141151_init_tag_enum.sql
  • apps/hasura/seeds/masterbots/1740386118928_init_domain_enum.sql
  • apps/hasura/seeds/masterbots/1740386128297_init_category_enum.sql
  • apps/hasura/seeds/masterbots/1740386175015_init_example_pt_4.sql
  • apps/hasura/seeds/masterbots/1740386133107_init_subcategory_enum.sql
  • apps/masterbots.ai/lib/hooks/use-payment.tsx
  • apps/hasura/seeds/masterbots/1740386175315_init_example_pt_7.sql
🧰 Additional context used
🧬 Code Graph Analysis (23)
apps/masterbots.ai/app/c/p/page.tsx (1)
apps/masterbots.ai/components/routes/subscription/subscription.tsx (1)
  • Subscription (44-81)
apps/masterbots.ai/components/shared/theme-toggle.tsx (1)
apps/masterbots.ai/lib/utils.ts (1)
  • cn (9-11)
apps/masterbots.ai/components/layout/sidebar/sidebar.tsx (2)
apps/masterbots.ai/components/layout/sidebar/sidebar-header.tsx (1)
  • SidebarHeader (6-12)
apps/masterbots.ai/components/layout/sidebar/sidebar-category-general.tsx (1)
  • SidebarCategoryGeneral (6-28)
apps/masterbots.ai/components/routes/preferences/preferences.tsx (2)
apps/masterbots.ai/lib/constants/preferences.ts (1)
  • preferences (4-113)
packages/mb-env/src/config.env.ts (1)
  • appConfig (2-51)
apps/masterbots.ai/components/layout/sidebar/sidebar-category-general.tsx (1)
apps/masterbots.ai/lib/memoized-markdown-components.tsx (1)
  • ul (132-136)
apps/masterbots.ai/app/u/[userSlug]/s/subs/page.tsx (2)
apps/masterbots.ai/app/u/[userSlug]/s/pref/page.tsx (1)
  • PreferencePage (3-9)
apps/masterbots.ai/components/routes/subscription/subscription-page.tsx (1)
  • SubscriptionPageComponent (7-44)
apps/masterbots.ai/app/layout.tsx (1)
packages/mb-env/src/config.env.ts (1)
  • appConfig (2-51)
apps/masterbots.ai/lib/hooks/use-mb-chat.tsx (1)
packages/mb-env/src/config.env.ts (1)
  • appConfig (2-51)
apps/masterbots.ai/components/routes/subscription/payment-information.tsx (3)
apps/masterbots.ai/components/ui/wizard/index.tsx (1)
  • WizardStepProps (13-20)
apps/masterbots.ai/auth.ts (1)
  • session (171-186)
apps/masterbots.ai/lib/hooks/use-payment.tsx (1)
  • usePayment (53-59)
apps/masterbots.ai/components/routes/subscription/subscription-page.tsx (3)
apps/masterbots.ai/lib/memoized-markdown-components.tsx (2)
  • h1 (71-86)
  • p (62-68)
apps/masterbots.ai/components/ui/button.tsx (1)
  • Button (71-71)
apps/masterbots.ai/components/routes/subscription/subscription.tsx (1)
  • Subscription (44-81)
apps/masterbots.ai/app/u/[userSlug]/page.tsx (2)
apps/masterbots.ai/app/u/[userSlug]/s/page.tsx (1)
  • ProfilePageDefaultRedirect (4-8)
apps/masterbots.ai/types/types.ts (1)
  • PageProps (276-286)
apps/masterbots.ai/auth.ts (1)
apps/masterbots.ai/services/hasura/hasura.service.ts (1)
  • getUserByEmail (1159-1182)
apps/masterbots.ai/app/u/[userSlug]/s/page.tsx (1)
apps/masterbots.ai/types/types.ts (1)
  • PageProps (276-286)
apps/masterbots.ai/app/c/page.tsx (2)
apps/masterbots.ai/components/routes/thread/thread-panel.tsx (1)
  • ThreadPanel (24-44)
apps/masterbots.ai/lib/utils.ts (1)
  • isAdminOrModeratorRole (229-231)
apps/masterbots.ai/components/shared/image-generator-dialog.tsx (7)
apps/masterbots.ai/lib/hooks/use-mb-chat.tsx (1)
  • useMBChat (72-78)
apps/masterbots.ai/lib/constants/prompts.ts (1)
  • createImageGenerationPrompt (232-240)
apps/masterbots.ai/components/ui/dialog.tsx (5)
  • Dialog (115-115)
  • DialogTrigger (124-124)
  • DialogContent (117-117)
  • DialogHeader (120-120)
  • DialogTitle (123-123)
apps/masterbots.ai/components/ui/button.tsx (1)
  • Button (71-71)
apps/masterbots.ai/components/ui/label.tsx (1)
  • Label (38-38)
apps/masterbots.ai/components/ui/input.tsx (1)
  • Input (25-25)
apps/masterbots.ai/components/ui/select.tsx (5)
  • Select (111-111)
  • SelectTrigger (117-117)
  • SelectValue (118-118)
  • SelectContent (112-112)
  • SelectItem (114-114)
apps/masterbots.ai/components/routes/subscription/plans.tsx (1)
apps/masterbots.ai/auth.ts (1)
  • session (171-186)
apps/masterbots.ai/app/c/[category]/[domain]/[chatbot]/[threadSlug]/page.tsx (3)
apps/masterbots.ai/auth.ts (1)
  • session (171-186)
apps/masterbots.ai/lib/utils.ts (2)
  • RoleTypes (227-227)
  • isAdminOrModeratorRole (229-231)
apps/masterbots.ai/components/routes/thread/thread-panel.tsx (1)
  • ThreadPanel (24-44)
apps/masterbots.ai/components/routes/subscription/checkout.tsx (1)
apps/masterbots.ai/auth.ts (1)
  • session (171-186)
apps/masterbots.ai/components/routes/subscription/succes-content.tsx (3)
apps/masterbots.ai/components/ui/wizard/index.tsx (1)
  • WizardStepProps (13-20)
apps/masterbots.ai/lib/hooks/use-payment.tsx (1)
  • usePayment (53-59)
apps/masterbots.ai/auth.ts (1)
  • session (171-186)
apps/masterbots.ai/components/routes/browse/browse-list.tsx (1)
apps/masterbots.ai/lib/threads.ts (1)
  • getOpeningActiveThreadHelper (53-162)
apps/masterbots.ai/lib/helpers/ai-helpers.ts (1)
packages/mb-genql/generated/schema.ts (1)
  • Message (906-934)
apps/masterbots.ai/lib/threads.ts (4)
packages/mb-genql/generated/schema.ts (1)
  • Thread (2206-2236)
apps/masterbots.ai/lib/hooks/useSonner.tsx (1)
  • useSonner (42-130)
apps/masterbots.ai/lib/utils.ts (1)
  • getRouteType (310-341)
apps/masterbots.ai/services/hasura/hasura.service.ts (1)
  • getThread (381-486)
apps/masterbots.ai/lib/constants/preferences.ts (1)
apps/masterbots.ai/types/types.ts (1)
  • PreferenceItemType (399-409)
🔇 Additional comments (76)
apps/masterbots.ai/app/layout.tsx (2)

12-12: Twitter Ads tracking script implementation looks good.

The implementation correctly uses the Next.js Script component to load the Twitter Ads pixel dynamically when enabled. The script is conditionally rendered based on the config flag and properly injects the campaign ID from the configuration.

Also applies to: 18-27


65-65: Metadata base URL change improves configuration consistency.

Changing from VERCEL_URL to BASE_URL aligns with standard environment variable naming conventions and likely provides better flexibility for different deployment environments.

packages/mb-env/src/config.env.ts (2)

41-50: The new ads configuration section is well-structured.

The implementation follows the existing pattern in the configuration file, with environment variables and appropriate defaults. This structure provides a clean way to manage ad-related settings.


47-47: Consider if a default campaign ID is appropriate.

The Twitter Ads campaign ID has a hardcoded default of 'pngjn', unlike most other configuration values that default to empty strings. Verify if this is intentional or if it should follow the pattern of other configuration values.

apps/masterbots.ai/components/routes/chat/chat-panel.tsx (1)

128-128: Improved z-index value for proper UI layering

The change from z-[2] to z-20 ensures the chat panel appears at the appropriate level in the UI stack, preventing potential overlap issues with other components.

apps/hasura/migrations/masterbots/1745923775527_alter_table_public_user_add_column_deletion_requested_at/up.sql (1)

1-2:

Details

✅ Verification successful

LGTM: Good addition for user deletion flow

The nullable deletion_requested_at timestamp column is well-designed for tracking when users request account deletion, which will support the account deletion workflow.

Run this script to verify this column is being properly used in relevant queries:


🏁 Script executed:

#!/bin/bash
# Check how the deletion_requested_at column is used in queries
rg -A 5 "deletion_requested_at" --glob "*.{ts,tsx,js,jsx,graphql,gql}"

Length of output: 533


deletion_requested_at usage verified

The deletion_requested_at column is properly referenced in the user deletion flow. In particular:

  • apps/masterbots.ai/services/hasura/hasura.service.ts: updateUserDeletionRequest sets or clears this timestamp as expected.

LGTM—good to merge.

apps/hasura/seeds/masterbots/1724270512560_init_users_seeds.sql (1)

2-3:

Details

❓ Verification inconclusive

Verify updated LFS pointer integrity

The Git LFS pointer has been updated with a new SHA-256 hash and file size. Ensure the updated seed file content is properly synced and contains the expected data.

Run this script to check LFS status and verify the file is properly tracked:


🏁 Script executed:

#!/bin/bash
# Check the status of LFS-tracked files
git lfs status

# List all LFS files in the repository
git lfs ls-files | grep users_seeds

Length of output: 224


🏁 Script executed:

#!/bin/bash
# Locate the seed file in the repository
FILE=$(fd 1724270512560_init_users_seeds.sql)

if [[ -z "$FILE" ]]; then
  echo "Seed file not found."
  exit 1
fi

echo "Located file: $FILE"
echo "---- First 5 lines (LFS pointer header) ----"
head -n 5 "$FILE"
echo "---- Last 5 lines (size hash) ----"
tail -n 5 "$FILE"

Length of output: 939


Verify updated LFS pointer integrity

I’ve confirmed that the pointer header in
apps/hasura/seeds/masterbots/1724270512560_init_users_seeds.sql
matches the new SHA-256 and size. Please perform the following to ensure the true seed data is in place:

  • Confirm .gitattributes includes an LFS filter for .sql files (or this specific path).
  • Run git lfs pull (or git lfs fetch && git lfs checkout) to retrieve the real file.
  • Inspect the fetched content, for example:
    git show HEAD:apps/hasura/seeds/masterbots/1724270512560_init_users_seeds.sql | head -n 20
    and verify it contains the expected SQL seed statements rather than a pointer.
apps/masterbots.ai/types/types.ts (1)

400-400:

Details

✅ Verification successful

Good addition for specific button identification

Adding the optional buttonId property to PreferenceItemType enables identifying specific dangerous operations like account deletion in the preferences UI.

Let's check where this new property is being used:


🏁 Script executed:

#!/bin/bash
# Find where buttonId is being referenced in the codebase
rg -A 3 "buttonId" --glob "*.{ts,tsx}"

# Look specifically for implementation in preference-related files
rg -A 5 "buttonId.*delete" --glob "*.{ts,tsx}"

Length of output: 2167


buttonId property correctly integrated

I’ve verified that the new optional buttonId on PreferenceItemType is being used in:

  • apps/masterbots.ai/components/routes/preferences/preference-section.tsx for calling executeButton(item.buttonId ?? '')
  • apps/masterbots.ai/lib/constants/preferences.ts where each dangerous-action preference (e.g. delete_account, delete_threads) is assigned its buttonId

No further changes needed.

apps/masterbots.ai/app/c/p/page.tsx (1)

32-32: Improved component encapsulation by removing prop drilling

The removal of props from the Subscription component is a good refactoring decision. The component now retrieves user data directly from the session using useSession() hook, which reduces prop drilling and centralizes user session management.

apps/hasura/seeds/masterbots/1746466541650_init_example_pt_14.sql (1)

1-3: Appropriate use of Git LFS for large seed file

Using Git LFS for managing this large seed file (~7.36 MB) is a good practice. This keeps the repository size manageable while still tracking the seed data in version control.

apps/hasura/seeds/masterbots/1740386119320_init_domain_enum.sql (1)

1-3: Consistent approach to enum seed file management

The addition of this domain enum seed file using Git LFS maintains consistency with the project's approach to managing seed data. The systematic naming convention with timestamps helps track the evolution of seed data over time.

apps/hasura/seeds/masterbots/1746466541637_init_example_pt_1.sql (1)

1-3: Well-structured approach to large seed data management

The addition of this large seed file (~26.2 MB) using Git LFS and breaking the overall dataset into multiple parts (pt_1 through pt_14) demonstrates good data management practices. This approach makes the seed data more manageable while keeping it under version control.

apps/masterbots.ai/components/routes/profile/user-thread-list.tsx (1)

17-17: Verify removal of vertical padding (pb-10).
The pb-10 class was dropped from the outer <div>, which may affect the vertical spacing on the profile thread list. Please confirm that the layout and responsive design remain as intended, or provide alternative spacing adjustments if needed.

apps/hasura/seeds/masterbots/1746466541648_init_example_pt_12.sql (1)

1-4: LFS pointer file, no SQL content to review.
This file is a Git LFS pointer for large seed data; it contains no SQL statements in the diff.

apps/hasura/seeds/masterbots/1746466541645_init_example_pt_9.sql (1)

1-4: LFS pointer file, no SQL content to review.
This file is a Git LFS pointer for large seed data; it contains no SQL statements in the diff.

apps/hasura/seeds/masterbots/1746466541639_init_example_pt_3.sql (1)

1-4: LFS pointer file, no SQL content to review.
This file is a Git LFS pointer for large seed data; it contains no SQL statements in the diff.

apps/hasura/seeds/masterbots/1746466541644_init_example_pt_8.sql (1)

1-4: LFS pointer file, no SQL content to review.
This file is a Git LFS pointer for large seed data; it contains no SQL statements in the diff.

apps/hasura/seeds/masterbots/1746466170867_init_subcategory_enum.sql (1)

1-3: Verify Git LFS pointer metadata
This seed file is tracked as a Git LFS pointer (oid and size). Please confirm that the actual SQL content is correctly stored in LFS, available in CI/local clones, and matches the intended subcategory enum initialization.

apps/hasura/seeds/masterbots/1746466541641_init_example_pt_5.sql (1)

1-3: Verify Git LFS pointer metadata
This example seed is a Git LFS pointer. Ensure the underlying SQL is present in LFS, resolves properly in build environments, and contains the expected example data for part 5.

apps/hasura/seeds/masterbots/1746466168385_init_category_enum.sql (1)

1-3: Verify Git LFS pointer metadata
The new category enum seed is stored via Git LFS. Confirm that the actual SQL file is correctly tracked, accessible in CI, and accurately represents the category enumeration changes.

apps/hasura/seeds/masterbots/1746466541643_init_example_pt_7.sql (1)

1-3: Verify Git LFS pointer metadata
This example seed (part 7) is an LFS pointer file. Please validate that the SQL content is properly checked into LFS, available during migrations, and contains the correct data.

apps/hasura/seeds/masterbots/1746466541642_init_example_pt_6.sql (1)

1-3: Verify Git LFS pointer metadata
The seed file for example pt 6 is tracked via Git LFS. Ensure the actual SQL payload is present, resolves in CI/builds, and aligns with the intended seed data.

apps/hasura/seeds/masterbots/1746466541649_init_example_pt_13.sql (1)

1-3: LFS pointer file only – no SQL content to review.
This file is a Git LFS pointer to a large seed script. Ensure the actual SQL is properly stored in LFS and included in your seed execution process.

apps/hasura/seeds/masterbots/1746466541647_init_example_pt_11.sql (1)

1-3: LFS pointer file only – no SQL content to review.
This is a Git LFS pointer. Confirm that the corresponding SQL file is present in LFS and that your deployment pipeline applies it in the correct sequence.

apps/hasura/seeds/masterbots/1746466541638_init_example_pt_2.sql (1)

1-3: LFS pointer file only – no SQL content to review.
Ensure that the referenced SQL file is committed to LFS and referenced correctly by your seeding mechanism.

apps/hasura/seeds/masterbots/1746466541646_init_example_pt_10.sql (1)

1-3: LFS pointer file only – no SQL content to review.
Verify that this seed file is tracked in LFS and loaded properly alongside the other init_example_pt files.

apps/hasura/seeds/masterbots/1724269974513_init_config_seeds.sql (1)

1-3: LFS pointer update – verify alignment with schema migrations.
This pointer reflects a major update to init_config_seeds.sql. Please confirm that the new seed populates recently added schema elements (e.g., deletion_requested_at, new enum values) introduced in your migrations.

apps/masterbots.ai/components/ui/button.tsx (1)

23-24: Well-aligned hover styles for sideBarProfile variant
The addition of hover:bg-muted and hover:text-muted-foreground brings interactive feedback in line with other variants. LGTM!

apps/hasura/seeds/masterbots/1746466178152_init_tag_enum_pt_1.sql (1)

1-3: Skip seed file pointer metadata review
This file contains only Git LFS pointer metadata. The actual SQL content should be reviewed separately if needed.

apps/hasura/seeds/masterbots/1746466541640_init_example_pt_4.sql (1)

1-3: Skip seed file pointer metadata review
As with other LFS-tracked seed files, this pointer is formatted correctly. Ensure the SQL it references is valid.

apps/masterbots.ai/app/actions/ai-main-call.ts (1)

462-467: Good implementation of Gemini 2.0 Flash image response capabilities.

The conditional configuration for the 'gemini-2.0-flash-exp' model looks correct, specifically setting the response modalities to include both text and images. This aligns well with the broader changes mentioned in the PR summary regarding image generation and rendering.

apps/masterbots.ai/app/u/page.tsx (1)

1-6: LGTM: Proper implementation of profile default redirect.

This simple redirect implementation serves as a sensible fallback for the '/u' route, directing users to the homepage when no specific user profile is requested. It aligns with the broader routing improvements in the PR.

apps/hasura/seeds/masterbots/1746466178153_init_tag_enum_pt_2.sql (1)

1-3: LGTM: Proper use of Git LFS for large data file.

Using Git LFS for managing large SQL seed files is appropriate. This approach prevents bloating the main repository with large binary files while still allowing version control of the data.

apps/hasura/migrations/masterbots/1718416395664_create_table_models_enum/up.sql (1)

19-20: LGTM: New Gemini model properly added to database enum.

The addition of the 'Gemini__2_0__Flash' entry with value 'gemini-2.0-flash-exp' is consistent with the model handling added in the ai-main-call.ts file. The ON CONFLICT clause properly handles potential duplicate entries.

apps/masterbots.ai/app/c/[category]/[domain]/[chatbot]/page.tsx (3)

7-7: LGTM: Added proper import for role-based utilities.

The addition of the RoleTypes type and isAdminOrModeratorRole utility function import is appropriate for the new role-based admin mode functionality.


43-43: LGTM: Added role extraction from session.

Properly casting the session.user.role as RoleTypes to ensure type safety when using the role value.


53-57: LGTM: ThreadPanel now receives isAdminMode prop based on user role.

The isAdminOrModeratorRole utility is correctly used to determine if the current user has admin privileges, and this boolean value is properly passed to the ThreadPanel component via the isAdminMode prop.

apps/hasura/seeds/masterbots/1740386119321_init_chatbot_metadata_seeds.sql (1)

2-3: Updated seed file metadata with new version

The Git LFS pointer has been updated to reference a new version of the chatbot metadata seeds file, with an increased size (from 17,251 bytes to 32,262 bytes). This indicates significant additions to the seed data.

apps/masterbots.ai/app/c/[category]/[domain]/[chatbot]/[threadSlug]/[threadQuestionSlug]/page.tsx (3)

6-6: Added role-based access control imports

The import of RoleTypes type and isAdminOrModeratorRole utility function will help identify admin/moderator users for conditional UI rendering.


43-43: Role extraction and typecasting from user session

Good approach to extract and properly type-cast the user role from the session object.


53-57: Added admin mode toggle to ThreadPanel

The ThreadPanel component now receives an isAdminMode prop based on the user's role, which will enable admin-specific UI elements and functionality.

apps/hasura/metadata/databases/masterbots/tables/public_user.yaml (3)

104-104: Added deletion_requested_at to anonymous role permissions

The new column has been properly added to the select permissions for the anonymous role.


122-122: Added deletion_requested_at to moderator role permissions

The new column has been properly added to the select permissions for the moderator role.


143-143: Added deletion_requested_at to user role permissions

The new column has been properly added to the select permissions for the user role.

apps/masterbots.ai/app/u/[userSlug]/s/subs/page.tsx (1)

4-4: Cleaner component implementation

Good simplification by delegating all subscription-related UI and logic to the SubscriptionPageComponent. This makes the page component cleaner and follows proper component composition patterns.

apps/masterbots.ai/components/layout/sidebar/sidebar-category-general.tsx (2)

11-13: Consistent height styling added to "no matches" view

The addition of min-h-inherit class improves layout consistency when no categories are found.


16-16: Consistent height styling for category list

The addition of min-h-inherit class to the <ul> element ensures consistent height behavior whether categories are found or not, maintaining visual stability during filtering.

apps/masterbots.ai/services/hasura/hasura.service.type.ts (1)

72-72: Admin mode filter moved to proper interface

Good refactoring of the isAdminMode flag from GetThreadsParams to GetBrowseThreadsParams. This change centralizes admin mode filtering logic to the browse threads query, which is a more appropriate location based on the changes in the implementation.

apps/masterbots.ai/auth.ts (2)

24-24: Enhanced user data retrieval with deletion tracking support

The import has been updated from getUserRoleByEmail to getUserByEmail, supporting the expanded user data model that includes account deletion request tracking.


106-106: Updated function call for enhanced user data retrieval

Updated the function call to use getUserByEmail which now fetches additional user data fields including deletionRequestedAt timestamp and email fields alongside the previously retrieved role and slug. This supports the account deletion request tracking feature.

apps/masterbots.ai/app/u/[userSlug]/s/page.tsx (1)

1-8: Clean and straightforward redirect implementation.

This new page component effectively handles redirecting users from /u/[userSlug]/s to /u/[userSlug]/t, consistent with the application's routing patterns. The implementation correctly awaits the Promise-based params and uses Next.js's redirect function.

apps/hasura/migrations/masterbots/1745471202166_create_table_public_models/up.sql (1)

29-30: Successfully added new model entries to the database.

The migration correctly adds two new models to the public.models table:

  1. llama-3-sonar-large-32k-online (disabled, paid)
  2. gemini-2.0-flash-exp (enabled, paid)

Both follow the established pattern for model entries and properly use the ON CONFLICT clause to handle potential duplicates.

apps/masterbots.ai/components/routes/preferences/preferences.tsx (2)

1-4: LGTM: Client directive and imports properly configured.

The addition of the 'use client' directive is necessary since this component uses client-side features. The imports for preferences and appConfig are correctly defined.


17-23: Correctly implemented the filtered preferences rendering.

The component now properly renders only the preferences sections that pass the filtering conditions, which aligns with the conditional display requirements based on the devMode feature flag.

apps/masterbots.ai/lib/hooks/use-mb-chat.tsx (2)

272-294: Image file handling added to enhance chat responses with generated images.

The implementation properly maps generated image files to message parts with appropriate metadata (base64, Uint8Array, mimeType, fileName) and includes a dev-mode notification. This is a well-structured addition that enables AI-generated image support.


438-441: Prepare for backend integration of image files.

The commented code and TODO indicate upcoming backend integration for generated image files. Make sure to track this task to ensure it's completed when the backend is ready.

Are there any tracking tickets/issues for this backend integration work? Consider adding the ticket number to the TODO comment to improve traceability.

apps/masterbots.ai/app/api/chat/models/models.ts (1)

13-14: AI model nomenclature updated for consistency and new model added.

The change standardizes the Gemini model naming convention using hyphens instead of underscores and adds the new Gemini Flash Pro model, properly aligning with the backend database migrations.

apps/masterbots.ai/app/c/[category]/[domain]/[chatbot]/[threadSlug]/page.tsx (3)

6-6: Import utility for role-based access control.

Good addition of the role type and utility function for admin/moderator role checking.


43-43: Extract and type-cast user role from session.

Correctly extracts the user role from the session and casts it to the proper RoleTypes type.


53-57: Add admin mode conditional rendering based on user role.

Properly passes the isAdminMode prop to the ThreadPanel component based on the user's role, enabling role-specific UI elements.

apps/masterbots.ai/app/u/[userSlug]/page.tsx (1)

1-8: Implement default redirect for user profile routes.

This component properly extracts the userSlug parameter and redirects to the threads view, simplifying URL structure and providing consistent navigation for user profiles.

apps/masterbots.ai/components/routes/thread/thread-panel.tsx (3)

2-2: Nice work adding the AdminModeToggle import.

The addition of this import enables the conditional rendering of admin functionality.


27-27: Good addition of the isAdminMode prop.

The boolean prop allows for conditional rendering of admin functionality while maintaining clear interface documentation.

Also applies to: 31-31


35-40: Consider improving the sticky behavior.

The implementation of the admin toggle in a sticky container looks good, but there's a TODO comment noting a limitation with the sticky behavior when scrolling beyond 100vh.

You might want to address this sticky positioning limitation in a future update. Consider using a fixed position with appropriate z-index, or investigate if CSS position: sticky with a different container structure would solve the issue.

apps/masterbots.ai/components/routes/subscription/succes-content.tsx (1)

26-26: Good implementation of session-based user data.

Using the useSession hook to access user data is appropriate and aligns with authentication best practices.

Also applies to: 31-31

apps/masterbots.ai/app/c/page.tsx (1)

32-36: Good centralization of admin mode logic.

The refactoring to pass isAdminMode as a prop to the ThreadPanel component simplifies the page-level JSX and centralizes the admin UI control logic. This is a clean approach.

apps/masterbots.ai/components/routes/subscription/checkout.tsx (1)

35-35: Good implementation of session-based user identification.

Using the useSession hook to access authenticated user data is appropriate and aligns with authentication best practices.

Also applies to: 46-46

apps/masterbots.ai/lib/constants/prompts.ts (1)

228-240: Good implementation of the image generation prompt template

The template and helper function provide a clear structure for generating image prompts with placeholders for description, style, and details. This aligns well with the image generation features being added in this PR.

Consider adding parameter validation to handle edge cases like null or undefined inputs, though this may not be critical for this straightforward use case.

apps/masterbots.ai/components/shared/theme-toggle.tsx (1)

8-38: Great improvement to the ThemeToggle component

The refactoring enhances the component's reusability by:

  1. Accepting standard button props (className, onClick)
  2. Properly handling theme transitions
  3. Correctly merging classNames using the cn utility
  4. Using a more appropriate text size (sm instead of xs)

The handling of the onClick event inside the startTransition callback is particularly well done, ensuring the theme toggle happens first before any external click handlers.

apps/masterbots.ai/components/routes/subscription/plans.tsx (1)

32-33: Good migration to using authenticated session data

This change correctly transitions from using usePayment hook's user data to the authenticated session data by importing and using useSession from next-auth/react.

Also applies to: 52-56

apps/masterbots.ai/components/routes/chat/chat-message.tsx (2)

109-127: Well-implemented image rendering for chat messages

The ImagesSection component correctly:

  1. Checks if the message contains image generation data
  2. Extracts image content using the helper functions
  3. Renders each image with proper properties
  4. Includes download capability through the GeneratedImage component

This implementation neatly integrates with the existing message rendering flow.


147-147: Good placement of the ImagesSection component

The ImagesSection is appropriately placed after the markdown content but before the actions and references sections, providing a logical content flow in the UI.

apps/masterbots.ai/components/routes/subscription/subscription.tsx (1)

61-68: Avoid calling customer-deletion endpoint with an empty email

handleCloseWizard will happily invoke handleDeleteCustomer('') when the session has not hydrated yet.
Add a safeguard:

-const del = await handleDeleteCustomer(email)
+if (!email) return router.push('/c')   // nothing to delete
+const del = await handleDeleteCustomer(email)
apps/masterbots.ai/components/routes/browse/browse-list.tsx (1)

33-35: getOpeningActiveThreadHelper import looks good

Centralising the logic is a solid refactor and removes a sizeable chunk of duplicate code from this component.

apps/masterbots.ai/app/api/cron/delete-requested-accounts/route.ts (1)

14-23:

Details

❓ Verification inconclusive

GraphQL field casing may not exist (user vs users)
Hasura’s generated root field for querying a table called user is normally user only if singularization has been customised. By default it is users. Double-check the schema; if it is still users, this query will return undefined, propagating to an empty userIds array and silently skipping deletions.


🏁 Script executed:

#!/bin/bash
set -e
echo "Searching for GraphQL schema files (.graphql, .gql)..."
fd --type f --exclude node_modules -e graphql -e gql

Length of output: 262


🏁 Script executed:

#!/bin/bash
set -e
echo "== Query type snippet =="
rg -n -A 30 "type Query" packages/mb-genql/generated/schema.graphql
echo ""
echo "== 'users(' occurrences =="
rg -n "users(" packages/mb-genql/generated/schema.graphql
echo ""
echo "== 'user(' occurrences =="
rg -n "user(" packages/mb-genql/generated/schema.graphql

Length of output: 137


🏁 Script executed:

#!/bin/bash
set -e
echo "== Query root definition and fields =="
rg -n -A 200 "type query_root" packages/mb-genql/generated/schema.graphql || echo "No query_root found"
echo ""
echo "== Roots named 'users(' =="
rg -n "users(" -C 3 packages/mb-genql/generated/schema.graphql || echo "No 'users(' occurrences"
echo ""
echo "== Roots named 'user(' =="
rg -n "user(" -C 3 packages/mb-genql/generated/schema.graphql || echo "No 'user(' occurrences"

Length of output: 5444


#!/bin/bash
set -e
echo "=== Fetch doc for 'user' table ==="
rg -n -A 5 'fetch data from the table: "user"' packages/mb-genql/generated/schema.graphql || echo "No doc for 'user' table found"
echo ""
echo "=== Root fields for 'user' ==="
rg -n -F 'user(' -C 2 packages/mb-genql/generated/schema.graphql || echo "No literal 'user(' occurrences"
echo ""
echo "=== Root fields for 'users' ==="
rg -n -F 'users(' -C 2 packages/mb-genql/generated/schema.graphql || echo "No literal 'users(' occurrences"

#!/bin/bash
set -e
echo "== Locate 'table: \"user\"' occurrences =="
rg -n 'table: "user"' -C 2 packages/mb-genql/generated/schema.graphql || echo "No 'table: \"user\"' found"
echo
echo "== Literal root field 'user(' =="
rg -n -F 'user(' -C 2 packages/mb-genql/generated/schema.graphql || echo "No literal 'user(' occurrences"
echo
echo "== Literal root field 'users(' =="
rg -n -F 'users(' -C 2 packages/mb-genql/generated/schema.graphql || echo "No literal 'users(' occurrences"

Double-check Hasura root query field for user table
I wasn’t able to find either a user( or users( root in the generated schema (packages/mb-genql/generated/schema.graphql). By default, a table named user in Hasura exposes a users field unless you’ve customized singularization. If your root is users, the current user query will return undefined, producing an empty userIds array and silently skipping deletions.

• Verify in packages/mb-genql/generated/schema.graphql whether the root is users or user.
• If it’s the default users, update the query in
apps/masterbots.ai/app/api/cron/delete-requested-accounts/route.ts (lines 14–23) to:

 const userQuery = await client.query({
-     user: {
+     users: {
      userId: true,
      __args: {
        where: { deletionRequestedAt: { _lte: thirtyDaysAgo } },
      },
    },
 })

Please verify your Hasura schema and adjust this field name to avoid silent failures.

apps/masterbots.ai/components/layout/sidebar/profile-sidebar.tsx (1)

39-45: Re-evaluate the sidebar-reset logic in handleNavigation

Every navigation click (including Theme toggle) resets activeCategory and activeChatbot.
This may be surprising when the user simply changes the theme or visits another page inside the same category. Consider decoupling the “close drawer” concern from the “reset filters” concern, or make the reset conditional (e.g. only when navigating to /c).

[ suggest_optional_refactor ]

target="_blank"
rel="noopener noreferrer"
href={`/u/s/subs/${paymentIntent.id}`}
href={`/u/${session?.user.slug}/s/subs/${paymentIntent.id}`}
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Consider adding a fallback for the session user slug.

The dynamic URL construction using session?.user.slug lacks a fallback if the session is not available or the slug is missing.

-href={`/u/${session?.user.slug}/s/subs/${paymentIntent.id}`}
+href={`/u/${session?.user.slug || 'profile'}/s/subs/${paymentIntent.id}`}
🤖 Prompt for AI Agents
In apps/masterbots.ai/components/routes/subscription/succes-content.tsx at line
54, the URL uses session?.user.slug without a fallback, which can cause issues
if session or slug is undefined. Add a fallback value for the slug, such as an
empty string or a default placeholder, to ensure the URL is always valid even
when session data is missing.

Comment on lines +83 to +87
window.history.pushState(
{},
'',
`/u/${session?.user.slug}/s/subs/${paymentIntent.id}`,
)
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Add fallback for missing session slug when constructing the URL.

The history pushState call uses session?.user.slug without handling the case where session may be null or slug may be missing.

window.history.pushState(
  {},
  '',
- `/u/${session?.user.slug}/s/subs/${paymentIntent.id}`,
+ `/u/${session?.user.slug || 'profile'}/s/subs/${paymentIntent.id}`,
)

This ensures that navigation won't break if the session hasn't fully loaded or if the slug is missing for any reason.

📝 Committable suggestion

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

Suggested change
window.history.pushState(
{},
'',
`/u/${session?.user.slug}/s/subs/${paymentIntent.id}`,
)
window.history.pushState(
{},
'',
`/u/${session?.user.slug || 'profile'}/s/subs/${paymentIntent.id}`,
)
🤖 Prompt for AI Agents
In apps/masterbots.ai/components/routes/subscription/checkout.tsx around lines
83 to 87, the code uses session?.user.slug directly in the URL without handling
cases where session or slug might be null or undefined. To fix this, add a
fallback value (like an empty string or a placeholder) for the slug when
constructing the URL in window.history.pushState to prevent navigation errors if
session or slug is missing.

Comment on lines +46 to 50
const { data: session } = useSession()
const { email } = (session?.user as Session['user']) || {
email: '',
}
const {
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Guard against undefined session & avoid unsafe type-casts

(session?.user as Session['user']) assumes session.user is always shape-compatible with Session['user'].
If session is still loading, email becomes an empty string which then propagates to the subsequent API calls, causing useless requests and potential 400/404 noise on the server.

Consider early-returning until the session is ready, and drop the brittle type-cast:

-const { email } = (session?.user as Session['user']) || { email: '' }
+if (!session?.user?.email) return null            // or render a loader
+const { email } = session.user
📝 Committable suggestion

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

Suggested change
const { data: session } = useSession()
const { email } = (session?.user as Session['user']) || {
email: '',
}
const {
const { data: session } = useSession()
- const { email } = (session?.user as Session['user']) || {
- email: '',
- }
+ if (!session?.user?.email) return null // or render a loader
+ const { email } = session.user
const {
🤖 Prompt for AI Agents
In apps/masterbots.ai/components/routes/subscription/subscription.tsx around
lines 46 to 50, the code uses an unsafe type-cast on session.user and assigns an
empty string to email if session is undefined, which can cause invalid API
calls. To fix this, remove the type-cast and add an early return or conditional
rendering to wait until the session is fully loaded before accessing
session.user and email, preventing unnecessary requests with invalid data.

Comment on lines 57 to 59
const { value: openDialog } = useAsync(
async () => await checkIfCustomerHasActiveSub(user.email),
async () => await checkIfCustomerHasActiveSub(email),
)
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

useAsync never re-runs when the email arrives – add dependency & null-check

useAsync without a deps array only fires once (on mount).
On first render email === ''; once the real email arrives the check is never repeated, so users with a cold page load are shown the wrong dialog state.

-const { value: openDialog } = useAsync(
-  async () => await checkIfCustomerHasActiveSub(email),
-)
+const { value: openDialog } = useAsync(
+  async () => {
+    if (!email) return false          // skip until we know who the user is
+    return checkIfCustomerHasActiveSub(email)
+  },
+  [email],                            // <- rerun when session resolves
+)
📝 Committable suggestion

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

Suggested change
const { value: openDialog } = useAsync(
async () => await checkIfCustomerHasActiveSub(user.email),
async () => await checkIfCustomerHasActiveSub(email),
)
const { value: openDialog } = useAsync(
async () => {
if (!email) return false // skip until we know who the user is
return checkIfCustomerHasActiveSub(email)
},
[email], // <- rerun when session resolves
)
🤖 Prompt for AI Agents
In apps/masterbots.ai/components/routes/subscription/subscription.tsx around
lines 57 to 59, the useAsync hook is called without a dependency array, causing
it to run only once on mount and not re-run when the email value changes. To fix
this, add the email variable to the dependency array of useAsync so it
re-executes whenever email updates. Also, add a null or empty string check to
avoid running the async function when email is not yet available.

Comment on lines +86 to +94
const [, getOpeningActiveThread] = useAsyncFn(
() =>
getOpeningActiveThreadHelper(
activeThread,
customSonner,
activateThreadPopup,
),
[activeThread, window.location.pathname],
)
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Avoid window.location inside dependency array – use usePathname

Referencing window directly breaks during pre-render / storybook and hinders testing. Next-auth provides usePathname() which is reactive and SSR-safe.

-import { useEffect, useState } from 'react'
+import { useEffect, useState } from 'react'
+import { usePathname } from 'next/navigation'

+const pathname = usePathname()

 const [, getOpeningActiveThread] = useAsyncFn(
   () =>
     getOpeningActiveThreadHelper(
       activeThread,
       customSonner,
       activateThreadPopup,
     ),
-  [activeThread, window.location.pathname],
+  [activeThread, pathname],
 )
📝 Committable suggestion

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

Suggested change
const [, getOpeningActiveThread] = useAsyncFn(
() =>
getOpeningActiveThreadHelper(
activeThread,
customSonner,
activateThreadPopup,
),
[activeThread, window.location.pathname],
)
// at the top of the file
import { useEffect, useState } from 'react'
import { usePathname } from 'next/navigation'
export function ThreadList(/* … */) {
// usePathname is SSR-safe and reactive
const pathname = usePathname()
const [, getOpeningActiveThread] = useAsyncFn(
() =>
getOpeningActiveThreadHelper(
activeThread,
customSonner,
activateThreadPopup,
),
[activeThread, pathname],
)
// …
}
🤖 Prompt for AI Agents
In apps/masterbots.ai/components/routes/thread/thread-list.tsx around lines 86
to 94, replace the direct use of window.location.pathname in the dependency
array with the Next.js hook usePathname() to ensure the code is reactive,
SSR-safe, and compatible with pre-rendering and testing environments. Import
usePathname from 'next/navigation' and use it to get the current path, then
include that value in the dependency array instead of window.location.pathname.

Comment on lines +13 to +23
{ "source": "/user/:path*", "destination": "/u/:path*", "permanent": true },
{
"source": "/profile/:path*",
"destination": "/u/:path*",
"permanent": true
},
{
"source": "/author/:path*",
"destination": "/u/:path*",
"permanent": true
},
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Specific redirects are shadow-ed by the broader /user/:path* rule

Vercel evaluates redirects top-to-bottom.
Because the catch-all rule /user/:path* → /u/:path* comes before the more specific preferences/subscriptions rules, requests like /user/john/preferences will match the first rule and be redirected to /u/john/preferences, never reaching /u/john/s/pref.

Move the three catch-all rules to the bottom or place the specific rules above them.

-    { "source": "/user/:path*", "destination": "/u/:path*", "permanent": true },
+    // … specific /user/:userSlug/preferences & /subscriptions rules first …
+    { "source": "/user/:path*", "destination": "/u/:path*", "permanent": true },

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In apps/masterbots.ai/vercel.json around lines 13 to 23, the broad redirect rule
for "/user/:path*" is placed before more specific rules like "/profile/:path*"
and "/author/:path*", causing the specific redirects to be shadowed. To fix
this, reorder the redirect rules by moving the broad "/user/:path*" catch-all
rule to the bottom of the list or placing the more specific rules above it,
ensuring specific paths are matched before the general catch-all.

Comment on lines 25 to 36
interface ThreadVisibilityContextProps {
isPublic: boolean
toggleVisibility: (newIsPublic: boolean, threadId: string) => Promise<void>
threads: Thread[]
threadsState: {
threads: Thread[]
count: number
}
isAdminMode: boolean
isContinuousThread: boolean
isSameUser: (thread: Thread) => boolean
toggleVisibility: (newIsPublic: boolean, threadId: string) => Promise<void>
adminApproveThread: (threadId: string) => void
initiateDeleteThread: (threadId: string) => Promise<DeleteThreadResponse>
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

adminApproveThread type is incorrect – returning a Promise but declared void

The async implementation (lines 216-233) returns Promise<void>, which is not assignable to the declared (threadId: string) => void.
Consumers expecting void will silently ignore rejections.

-	adminApproveThread: (threadId: string) => void
+	adminApproveThread: (threadId: string) => Promise<void>
📝 Committable suggestion

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

Suggested change
interface ThreadVisibilityContextProps {
isPublic: boolean
toggleVisibility: (newIsPublic: boolean, threadId: string) => Promise<void>
threads: Thread[]
threadsState: {
threads: Thread[]
count: number
}
isAdminMode: boolean
isContinuousThread: boolean
isSameUser: (thread: Thread) => boolean
toggleVisibility: (newIsPublic: boolean, threadId: string) => Promise<void>
adminApproveThread: (threadId: string) => void
initiateDeleteThread: (threadId: string) => Promise<DeleteThreadResponse>
interface ThreadVisibilityContextProps {
isPublic: boolean
threadsState: {
threads: Thread[]
count: number
}
isAdminMode: boolean
isContinuousThread: boolean
isSameUser: (thread: Thread) => boolean
toggleVisibility: (newIsPublic: boolean, threadId: string) => Promise<void>
adminApproveThread: (threadId: string) => Promise<void>
initiateDeleteThread: (threadId: string) => Promise<DeleteThreadResponse>
}
🤖 Prompt for AI Agents
In apps/masterbots.ai/lib/hooks/use-thread-visibility.tsx around lines 25 to 36,
the adminApproveThread function is declared to return void but its
implementation returns Promise<void>. Update the type declaration of
adminApproveThread to return Promise<void> to match the async implementation and
ensure consumers handle the promise correctly.

Comment on lines +1794 to +1840
// a function to delete all users messages and threads
export async function deleteUserMessagesAndThreads({
userId,
jwt,
}: {
userId: string
jwt: string
}): Promise<{ success: boolean; error?: string }> {
try {
if (!jwt) {
throw new Error(
'Authentication required to delete user messages and threads',
)
}

const client = getHasuraClient({ jwt })

// First, delete all messages associated with the user's threads
// Then, delete all the user's threads
const whereArgDeleteObject = {
thread: {
userId: { _eq: userId },
isPublic: { _eq: true },
isApproved: { _eq: true },
},
}
await client.mutation({
deleteMessage: {
__args: {
where: whereArgDeleteObject,
},
affectedRows: true,
},
deleteThread: {
__args: {
where: whereArgDeleteObject,
},
affectedRows: true,
},
})

return { success: true }
} catch (error) {
console.error('Error deleting user messages and threads:', error)
return { success: false, error: (error as Error).message }
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

⚠️ Potential issue

Thread deletion helper uses invalid where shape & misses private content

  1. deleteThread expects columns of thread, but you pass a nested thread object ({ thread: { … } }) – this will raise a GraphQL validation error.
  2. The current predicate deletes only public & approved content, leaving drafts/private threads and their messages behind, which defeats account-deletion requirements.
  3. Two separate deletions are issued in a single mutation; use Postgres ON DELETE CASCADE or wrap them in a transaction to avoid orphaned rows on partial failure.

Proposed fix (simplified):

-const whereArgDeleteObject = {
-  thread: {
-    userId: { _eq: userId },
-    isPublic: { _eq: true },
-    isApproved: { _eq: true },
-  },
-}
+const threadWhere = { userId: { _eq: userId } }   // delete **all** threads
+const messageWhere = { thread: threadWhere }      // messages linked to those threads
@@
 deleteMessage: { __args: { where: messageWhere }, affectedRows: true },
 deleteThread:  { __args: { where: threadWhere },  affectedRows: true },

Add a follow-up verification to ensure the number of deleted rows matches expectations.

if (result.deleteThread.affectedRows === 0) {
    return { success:false, error:'No threads deleted – check userId.' }
}
🤖 Prompt for AI Agents
In apps/masterbots.ai/services/hasura/hasura.service.ts around lines 1794 to
1840, the deleteUserMessagesAndThreads function incorrectly uses a nested
`thread` object in the `where` clause for deleting threads, which causes GraphQL
validation errors. Fix this by passing the correct shape with direct thread
columns for `deleteThread`. Also, remove the filters limiting deletion to only
public and approved threads to ensure all user threads and messages, including
private and drafts, are deleted. To prevent orphaned rows, either rely on
Postgres ON DELETE CASCADE or wrap deletions in a transaction. Finally, add a
verification step after deletion to check if any threads were deleted and return
an error if none were affected.

Comment on lines 1198 to 1215
const client = getHasuraClient({ jwt })
await client.mutation({
const result = await client.mutation({
deleteThread: {
__args: {
where: { threadId: { _eq: threadId }, userId: { _eq: userId } },
},
returning: {
threadId: true,
where: {
threadId: { _eq: threadId },
userId: { _eq: userId },
},
},
affectedRows: true,
},
})

return { success: true }
if ((result.deleteThread?.affectedRows ?? 0) > 0) {
return { success: true }
}
return { success: false }
} catch (error) {
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Deletion check trusts caller-supplied userId – verify against JWT

The where clause now matches both threadId and userId, which is good, but userId is supplied as a parameter and not validated against jwt claims.
A malicious client could therefore delete another user’s thread by passing that user’s id.

Add a quick guard:

const claimsUserId = parseJwt(jwt).['x-hasura-user-id']
if (claimsUserId !== userId) {
    throw new Error('UserId mismatch – forbidden')
}

(or simply drop userId from the API and read it exclusively from JWT claims).

Minor: on failure you return only { success:false }; include error for observability consistency.

🤖 Prompt for AI Agents
In apps/masterbots.ai/services/hasura/hasura.service.ts around lines 1198 to
1215, the deletion logic uses a caller-supplied userId without verifying it
against the JWT claims, which risks unauthorized deletions. Fix this by
extracting the userId from the JWT using a parseJwt function and comparing it to
the supplied userId; if they differ, throw an error to prevent unauthorized
access. Alternatively, remove the userId parameter entirely and rely solely on
the JWT userId. Also, enhance the failure response to include the error details
alongside success:false for better observability.

Comment on lines +1759 to +1792
// update user deletion_requested_at with the current date
export async function updateUserDeletionRequest({
userId,
jwt,
reset = false,
}: {
userId: string
jwt: string
reset?: boolean
}): Promise<{ success: boolean; error?: string }> {
try {
if (!jwt) {
throw new Error('Authentication required to update user deletion request')
}

const client = getHasuraClient({ jwt })
await client.mutation({
updateUserByPk: {
__args: {
pkColumns: { userId },
_set: {
deletionRequestedAt: reset ? null : new Date().toISOString(),
},
},
userId: true,
},
})

return { success: true }
} catch (error) {
console.error('Error updating user deletion request:', error)
return { success: false, error: (error as Error).message }
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Prefer database timestamp for deletionRequestedAt

new Date().toISOString() is generated on the frontend server, which may differ from the DB clock or be susceptible to manual tampering in tests.
Hasura (Postgres) already exposes now(). You can set it with x-hasura-update:

- _set: { deletionRequestedAt: reset ? null : new Date().toISOString() }
+ _set: { deletionRequestedAt: reset ? null : 'now()' }

This guarantees a consistent, timezone-aware value.

Also, when reset === true the mutation still requires authentication. Consider letting admins reset without JWT by accepting adminSecret.

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In apps/masterbots.ai/services/hasura/hasura.service.ts around lines 1759 to
1792, replace the client-side timestamp new Date().toISOString() for
deletionRequestedAt with the database server timestamp by using Hasura's
x-hasura-update or equivalent to set deletionRequestedAt to now() in the
mutation. Additionally, modify the function to allow resetting
deletionRequestedAt without a JWT by accepting an adminSecret parameter and
using it for authentication when reset is true, enabling admins to perform the
reset securely without a user JWT.

@AndlerRL
Copy link
Member Author

@AndlerRL
Copy link
Member Author

sheriffjimoh added a commit that referenced this pull request Sep 9, 2025
# Add features, refactor user and thread management, update UI and database scripts
* fix: change toggler wording + util hook (#424)

* impr: makes threads open on profile page and profile tweaks (#421)

* update

* fix: update

* update

* update

* update

* update

* fix: opening threads

* fix: rm threads dropdwon  & added back link to bot page thread view page

* fix: rm threads dropdwon  & added back link to bot page thread view page

* fix: update

* fix: added back to profile page

* fix: added sticky and color

* fix: codeblock ctas refactor markdown rendering, sidebar nav, code block & clipboard hook (#425)

* fix: codeblock ctas

* fix: ts build

* fix: continue thread + allMessages sequence + mobile chat css tweak (#426)

* fix: css handleCLick condition

* fix: get latest search params, continuous thread

* fix(impr): all messages sorting

* perf(impr): sign in & up redirection tweak

* perf(impr): mobile chat css

* chore: next + react security ver upt (#427)

* refactor: use chat and continue thread + continue conversation fallback (#432)

* refactor: use chat and continue generation

* fix: uniq slug and id gen (#433)

* fix: uniq thread + msg slug gen

* style: formatting

* fix: thread user attachments state upt

* perf: impr thread component at all pages + mobile tweaks

* refactor: thread-component card

* chore: restore continue generation v1

* feat(impr): thread component card

* fix: admin panel n actions

* fix: fetch getThreads

* chore: continue conversation v1.2

* chore: continue and update thread content

* chore: add ui control continue generation state

* chore: fix infinity loop

* chore(impr): enable upt msg table permission

* fix: seo thread fetch

* chore: style formating

* fix(impr): continued thread title + thread component reusability

* chore: refactor loadings + extending sonners

---------

Co-authored-by: bran18 <andreyfdez18@gmail.com>

---------

Co-authored-by: Roberto Lucas <andler@bitcash.org>

* feat: add gemini provider (#437)

* feat: add gemini provider

* chore: update icons

* feat: impr continuing thread tags + accordion first msg toggle (#435)

* feat(wip): impr continuing thread tags + accordion first msg toggle

* feat(impr): continuing thread tags + accordion at first message + header mobile tweak

* style(impr): mobile thread-component x-axis space

* perf(style): coderabbitai feedbacks

* fix: css typo

* perf: sendMessageFromResponse clicked guard + continued thread tags label tweak

* chore: user thread panel clean up

* fix: user-thread-panel infinite loader

* perf: impr shared accordion animation and ux

* style: defaultAccordionState comments loc

* fix: record type warning, hasura updateMessage

* fix: getThread user data, shared-accordion

* fix: coderabbitai observations

* fix: impr file management per llm, multimodel feat flag, chat tool labels, parent thread guard

* fix: tunningUserContent parentThread condition

* fix: feature flag typo

* feat: profile page thread popup feature flag and tweaks  (#434)

* update

* fix: update

* update

* update

* update

* update

* refactor: profile page threads pop up

* fix: update config

* fix: update

* fix: update

* fix: make profile page scroll on hero

* fix: bot make popup and scroll

* fix: make profile page sidebar scroll independently

* fix: make profile page sidebar scroll independently

* fix: check the category along the chatbot when it's not checked

* fix: check the category along the chatbot when it's not checked

---------

Co-authored-by: Roberto Lucas <andler.dev@gmail.com>
Co-authored-by: Roberto Lucas <andler@bitcash.org>

* feat: add new llm models (#444)

* feat-add-models

* feat-add-models

* feat-add-models

* chore: add model

* fix: typo

* chore: add toggler color

* perf(impr): thread llm context, last question & response + new models seeds (#447)

* feat(wip): thread llm context, prev questions

* fix: previousQuestionsString slice

* fix: clickedContentId in followingQuestionsPrompt

* feat: isContinued + model type in message table

* fix: ts typo + sendMessageFromResponse callback call

* fix: ts typo

* fix: bot profile page view (#449)

* fix(wip): bot profile thread list

* style: formatting

* fix: new chats and share + og img (#451)

* fix: new chat state reset

* fix: genql gen + share link check

* fix: og img

* fix: duplicate role permission in msg table

* feat: initial continuation logic flow (#450)

* chore: restore base version

* chore: add new logic and hooks

* chore: fix providers file

* chore: improve continuation prompt

* chore: add exlucision flag

* chore: add better handler

* chore: updated flow + experimental delay

* chore: extended time

* chore(impr): streamDelayMs experimental feat flag

* style: formatting

---------

Co-authored-by: Roberto Lucas <andler.dev@gmail.com>

* fix: profile sidebar cat opt render (#453)

* fix: profile sidebar cat opt render

* chore: clean-up

* [masterbots.ai] refactor: slug generation logic with improved uniqueness and type support (#456)

* fix: slugify fn

* chore: devMode logs

* fix: uniq slug gen fn nanoid flag typo

* feat: sentry logs in webapp (#457)

* fix(impr): llm enum data, thread creation, ts, and log behavior (#458)

* fix: slugify first request delay incr + genql ts, seeds & model migration upt

* fix: create thread & msg ts

* fix(impr): profile page bugs & tweaks v1 4/15/25 (#455)

* update

* fix: update

* update

* update

* update

* update

* fix: use the user avatar or robohash

* fix: added avater to user menu

* fix: user avatar

* fix: reset search input when filter by category or chatbot

* fix: personal chat browse provider + username chk in sign up

* chore: clean duplicated if condition signup

---------

Co-authored-by: Roberto Lucas <andler.dev@gmail.com>

* refactor: continuation flow (#460)

* impr: continuation logic flow

* impr: continuation logic flow

* chore: update createImprovementPrompt

* chore: upt logs

---------

Co-authored-by: Roberto Lucas <andler.dev@gmail.com>

* feat: models table, enum type, and refactor chat msg deduplication logic (#462)

* feat: models table

* style: formatting

* fix: continuation accordion content

* fix: sql + metadata typo

* fix: db migrations and messages uniqby condition (#463)

* fix: db migrations + messages uniqby condition

* fix: typo

* perf(impr): verify duplicate message return condition

* chore: upt default available models

* perf(impr): reassign continued prompt

* chore: incr fn stream max duration

* fix: mob prof sidebar + sign-up pw verif + username chk (#464)

* fix: mob prof sidebar + sign-up pw verif + username chk

* chore: upt genql gen

* perf(impr): profile navigation

* feat: model selector (#466)

* wip: model selector query

* wip: model selector query

* chore: improve funtions

* chore: add coderabbit suggestion

* chore: add hasura permissions, models table

* style: formatting

* chore: fix get model client type

* chore: add model

---------

Co-authored-by: Roberto Romero Lucas <contact@andler.dev>

* chore: impr models (#472)

* chore: fix model name and condition (#473)

* refactor: user fetching code (#471)

* refactor: profile sidebar ui, upt styling, and disable prefetch (#470)

* chore: remove prefetch on sidebar & profile navigation

* perf: impr profile sidebar

* fix: infinite scroll load more fetch

* perf(impr): google sign-in

* perf(impr): session loaders tweak

* perf: impr categoriesId obtention

* fix: tailwind typo

* chore(impr): pro user guard in model selector

* chore: category label upt to topic

* chore: rm dev mode guard (#476)

* feat: add reasoning compatibility (#480)

* feat: add resoning stable

* chore: add reasoning stable v

* chore: activate reasoning

* chore: activate reasoning

* feat: pro users whitelist (#481)

* feat(wip): whitelist pro users

* chore: add whitelist pro users + page size fetch

* perf(impr): following question impr prompt

* fix: pro whitelist users clean up

* feat: user account setting  (#468)

* update

* fix: update

* update

* update

* update

* update

* feat: imple account setting

* feat: added dialog to delete button

* feat: update user deletion func

* fix: move back exmaples files

* fix: update

* fix: user account scheduling api

* fix: user account deletion request function

* refactor: account deletion request api

* fix: user account request and thread deletion

* fix: added permission and account deletion page

* fix: update on permission

* fix: enable new col permission

* fix: profile side bar

* fix: update

* fix: function rerendering

* fix: update route

* chore(impr): preferences actions and ui tweaks

---------

Co-authored-by: Roberto Lucas <andler.dev@gmail.com>

* chore: enable twitter pixel track (#479)

* chore: enable twitter pixel track

* perf(impr): twitter ads availability + dynamic config

* feat: impr profile navigation page (#478)

* fix(wip): subscriptions page render

* feat(impr): profile navigation + page ui tweaks

* style: lintin + formatting

* style(css): nav links px on mob

* fix: goToProfile in mob prof sidebar

* fix: build

* fix: thread popup opening at nav

* chore: enable preferences nav on prod

* feat: image generation  (#486)

* feat: add image generation support - gemini provider

* chore: add mineType

* chore: add conditional checks

* chore: upt model enums & list

* chore: hasura, set icl seeds chunks (#484)

* chore: hasura, set icl seeds chunks

* chore: track backup icl seed loc to lfs

* chore(seeds): uncomment phase 3 topics & add new chatbots + icl metadata rel

* chore: upt phase 3 init config seeds, adding rel

* fix: example seeds integrity

* test: incr hasura max req body

* revert: cloudbuild og config

* chore: restore skipped seed lines

* fix: thread rendering (#487)

* fix: thread list render states

* chore: linting & format

* fix: thread pop-up on refresh

* fix: user table selection

---------

Co-authored-by: Brandon Fernández <31634868+Bran18@users.noreply.github.com>
Co-authored-by: Jimoh sherifdeen <63134009+sheriffjimoh@users.noreply.github.com>
sheriffjimoh added a commit that referenced this pull request Sep 10, 2025
# Add features, refactor user and thread management, update UI and database scripts
* fix: change toggler wording + util hook (#424)

* impr: makes threads open on profile page and profile tweaks (#421)

* update

* fix: update

* update

* update

* update

* update

* fix: opening threads

* fix: rm threads dropdwon  & added back link to bot page thread view page

* fix: rm threads dropdwon  & added back link to bot page thread view page

* fix: update

* fix: added back to profile page

* fix: added sticky and color

* fix: codeblock ctas refactor markdown rendering, sidebar nav, code block & clipboard hook (#425)

* fix: codeblock ctas

* fix: ts build

* fix: continue thread + allMessages sequence + mobile chat css tweak (#426)

* fix: css handleCLick condition

* fix: get latest search params, continuous thread

* fix(impr): all messages sorting

* perf(impr): sign in & up redirection tweak

* perf(impr): mobile chat css

* chore: next + react security ver upt (#427)

* refactor: use chat and continue thread + continue conversation fallback (#432)

* refactor: use chat and continue generation

* fix: uniq slug and id gen (#433)

* fix: uniq thread + msg slug gen

* style: formatting

* fix: thread user attachments state upt

* perf: impr thread component at all pages + mobile tweaks

* refactor: thread-component card

* chore: restore continue generation v1

* feat(impr): thread component card

* fix: admin panel n actions

* fix: fetch getThreads

* chore: continue conversation v1.2

* chore: continue and update thread content

* chore: add ui control continue generation state

* chore: fix infinity loop

* chore(impr): enable upt msg table permission

* fix: seo thread fetch

* chore: style formating

* fix(impr): continued thread title + thread component reusability

* chore: refactor loadings + extending sonners

---------

Co-authored-by: bran18 <andreyfdez18@gmail.com>

---------

Co-authored-by: Roberto Lucas <andler@bitcash.org>

* feat: add gemini provider (#437)

* feat: add gemini provider

* chore: update icons

* feat: impr continuing thread tags + accordion first msg toggle (#435)

* feat(wip): impr continuing thread tags + accordion first msg toggle

* feat(impr): continuing thread tags + accordion at first message + header mobile tweak

* style(impr): mobile thread-component x-axis space

* perf(style): coderabbitai feedbacks

* fix: css typo

* perf: sendMessageFromResponse clicked guard + continued thread tags label tweak

* chore: user thread panel clean up

* fix: user-thread-panel infinite loader

* perf: impr shared accordion animation and ux

* style: defaultAccordionState comments loc

* fix: record type warning, hasura updateMessage

* fix: getThread user data, shared-accordion

* fix: coderabbitai observations

* fix: impr file management per llm, multimodel feat flag, chat tool labels, parent thread guard

* fix: tunningUserContent parentThread condition

* fix: feature flag typo

* feat: profile page thread popup feature flag and tweaks  (#434)

* update

* fix: update

* update

* update

* update

* update

* refactor: profile page threads pop up

* fix: update config

* fix: update

* fix: update

* fix: make profile page scroll on hero

* fix: bot make popup and scroll

* fix: make profile page sidebar scroll independently

* fix: make profile page sidebar scroll independently

* fix: check the category along the chatbot when it's not checked

* fix: check the category along the chatbot when it's not checked

---------

Co-authored-by: Roberto Lucas <andler.dev@gmail.com>
Co-authored-by: Roberto Lucas <andler@bitcash.org>

* feat: add new llm models (#444)

* feat-add-models

* feat-add-models

* feat-add-models

* chore: add model

* fix: typo

* chore: add toggler color

* perf(impr): thread llm context, last question & response + new models seeds (#447)

* feat(wip): thread llm context, prev questions

* fix: previousQuestionsString slice

* fix: clickedContentId in followingQuestionsPrompt

* feat: isContinued + model type in message table

* fix: ts typo + sendMessageFromResponse callback call

* fix: ts typo

* fix: bot profile page view (#449)

* fix(wip): bot profile thread list

* style: formatting

* fix: new chats and share + og img (#451)

* fix: new chat state reset

* fix: genql gen + share link check

* fix: og img

* fix: duplicate role permission in msg table

* feat: initial continuation logic flow (#450)

* chore: restore base version

* chore: add new logic and hooks

* chore: fix providers file

* chore: improve continuation prompt

* chore: add exlucision flag

* chore: add better handler

* chore: updated flow + experimental delay

* chore: extended time

* chore(impr): streamDelayMs experimental feat flag

* style: formatting

---------

Co-authored-by: Roberto Lucas <andler.dev@gmail.com>

* fix: profile sidebar cat opt render (#453)

* fix: profile sidebar cat opt render

* chore: clean-up

* [masterbots.ai] refactor: slug generation logic with improved uniqueness and type support (#456)

* fix: slugify fn

* chore: devMode logs

* fix: uniq slug gen fn nanoid flag typo

* feat: sentry logs in webapp (#457)

* fix(impr): llm enum data, thread creation, ts, and log behavior (#458)

* fix: slugify first request delay incr + genql ts, seeds & model migration upt

* fix: create thread & msg ts

* fix(impr): profile page bugs & tweaks v1 4/15/25 (#455)

* update

* fix: update

* update

* update

* update

* update

* fix: use the user avatar or robohash

* fix: added avater to user menu

* fix: user avatar

* fix: reset search input when filter by category or chatbot

* fix: personal chat browse provider + username chk in sign up

* chore: clean duplicated if condition signup

---------

Co-authored-by: Roberto Lucas <andler.dev@gmail.com>

* refactor: continuation flow (#460)

* impr: continuation logic flow

* impr: continuation logic flow

* chore: update createImprovementPrompt

* chore: upt logs

---------

Co-authored-by: Roberto Lucas <andler.dev@gmail.com>

* feat: models table, enum type, and refactor chat msg deduplication logic (#462)

* feat: models table

* style: formatting

* fix: continuation accordion content

* fix: sql + metadata typo

* fix: db migrations and messages uniqby condition (#463)

* fix: db migrations + messages uniqby condition

* fix: typo

* perf(impr): verify duplicate message return condition

* chore: upt default available models

* perf(impr): reassign continued prompt

* chore: incr fn stream max duration

* fix: mob prof sidebar + sign-up pw verif + username chk (#464)

* fix: mob prof sidebar + sign-up pw verif + username chk

* chore: upt genql gen

* perf(impr): profile navigation

* feat: model selector (#466)

* wip: model selector query

* wip: model selector query

* chore: improve funtions

* chore: add coderabbit suggestion

* chore: add hasura permissions, models table

* style: formatting

* chore: fix get model client type

* chore: add model

---------

Co-authored-by: Roberto Romero Lucas <contact@andler.dev>

* chore: impr models (#472)

* chore: fix model name and condition (#473)

* refactor: user fetching code (#471)

* refactor: profile sidebar ui, upt styling, and disable prefetch (#470)

* chore: remove prefetch on sidebar & profile navigation

* perf: impr profile sidebar

* fix: infinite scroll load more fetch

* perf(impr): google sign-in

* perf(impr): session loaders tweak

* perf: impr categoriesId obtention

* fix: tailwind typo

* chore(impr): pro user guard in model selector

* chore: category label upt to topic

* chore: rm dev mode guard (#476)

* feat: add reasoning compatibility (#480)

* feat: add resoning stable

* chore: add reasoning stable v

* chore: activate reasoning

* chore: activate reasoning

* feat: pro users whitelist (#481)

* feat(wip): whitelist pro users

* chore: add whitelist pro users + page size fetch

* perf(impr): following question impr prompt

* fix: pro whitelist users clean up

* feat: user account setting  (#468)

* update

* fix: update

* update

* update

* update

* update

* feat: imple account setting

* feat: added dialog to delete button

* feat: update user deletion func

* fix: move back exmaples files

* fix: update

* fix: user account scheduling api

* fix: user account deletion request function

* refactor: account deletion request api

* fix: user account request and thread deletion

* fix: added permission and account deletion page

* fix: update on permission

* fix: enable new col permission

* fix: profile side bar

* fix: update

* fix: function rerendering

* fix: update route

* chore(impr): preferences actions and ui tweaks

---------

Co-authored-by: Roberto Lucas <andler.dev@gmail.com>

* chore: enable twitter pixel track (#479)

* chore: enable twitter pixel track

* perf(impr): twitter ads availability + dynamic config

* feat: impr profile navigation page (#478)

* fix(wip): subscriptions page render

* feat(impr): profile navigation + page ui tweaks

* style: lintin + formatting

* style(css): nav links px on mob

* fix: goToProfile in mob prof sidebar

* fix: build

* fix: thread popup opening at nav

* chore: enable preferences nav on prod

* feat: image generation  (#486)

* feat: add image generation support - gemini provider

* chore: add mineType

* chore: add conditional checks

* chore: upt model enums & list

* chore: hasura, set icl seeds chunks (#484)

* chore: hasura, set icl seeds chunks

* chore: track backup icl seed loc to lfs

* chore(seeds): uncomment phase 3 topics & add new chatbots + icl metadata rel

* chore: upt phase 3 init config seeds, adding rel

* fix: example seeds integrity

* test: incr hasura max req body

* revert: cloudbuild og config

* chore: restore skipped seed lines

* fix: thread rendering (#487)

* fix: thread list render states

* chore: linting & format

* fix: thread pop-up on refresh

* fix: user table selection

---------

Co-authored-by: Brandon Fernández <31634868+Bran18@users.noreply.github.com>
Co-authored-by: Jimoh sherifdeen <63134009+sheriffjimoh@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants