Add "Search with Gemini" button and results to feature library modal

What does this MR do and why?

Adds the explicit "Search with Gemini" (Tier 3) frontend to the "More Features" feature library modal (feature_library_modal.vue):

  • Shows a "Search with Gemini" button, gated on an injected availability signal (geminiSearchAvailable + a resolved resourceId), once a search query settles.
  • On click, calls the dedicated ai_search endpoint and shows a "Searching with Gemini …" loading state.
  • Renders returned features in a "Suggested by Gemini" section reusing the existing feature-library-item grid, deduped against Tier 1/2 results.
  • Adds a Gemini-specific empty state ("Gemini couldn't find a matching feature …") and a Hide control; hiding falls back to the original empty state.
  • Wires real availability via sidebars_helper delegating to FeatureMatchService#ai_search_available? (single source of truth); adds the search_with_gemini_in_feature_library_modal internal event.
  • Treats 404 (feature disabled) and 429 (rate limited) as expected, no Sentry noise.

Tier 1/2 results still render instantly; Gemini is explicit-trigger so AI latency never blocks core search.

References

Refs https://gitlab.com/gitlab-org/gitlab/-/work_items/603100 Part of epic https://gitlab.com/groups/gitlab-org/-/epics/22330

This is a stacked MR. It targets 603091-feature-library-ai-search-endpoint (the AI search endpoint, !245775 (merged)) rather than master, and will auto-retarget to master once that MR merges. Review this MR's diff on top of the endpoint branch.

Screenshots or screen recordings

Screenshot in dark mode:

Screenshot 2026-07-16 at 10.36.58 AM.png

How to set up and validate locally

  1. Restart GDK with SaaS simulation enabled (Gemini availability is SaaS-gated):

    GITLAB_SIMULATE_SAAS=1 gdk restart

    Then enable both feature flags for your user:

    Feature.enable(:feature_library_modal, User.find_by_username('<your-username>'))
    Feature.enable(:feature_discovery_gemini_search, User.find_by_username('<your-username>'))
  2. Make your namespace a trial (Gemini availability requires resource.root_ancestor.trial_active?):

    Group.find_by(id: <Group ID>).gitlab_subscription.update(trial: true, trial_starts_on: 20.days.ago, trial_ends_on: 10.days.from_now)
  3. The AI Gateway isn't wired up locally, so temporarily stub the Tier 3 response. Apply the patch below to ee/app/services/ee/onboarding/feature_library/feature_match_service.rb, then restart Rails. Do not commit this stub. To exercise the Gemini empty state, change the stubbed return to [].

    Local AI search stub patch
    diff --git a/ee/app/services/ee/onboarding/feature_library/feature_match_service.rb b/ee/app/services/ee/onboarding/feature_library/feature_match_service.rb
    --- a/ee/app/services/ee/onboarding/feature_library/feature_match_service.rb
    +++ b/ee/app/services/ee/onboarding/feature_library/feature_match_service.rb
    @@ -34,6 +34,13 @@ def ai_gateway_ids(normalized_query)
               ).execute
    
               return [] if catalogue.empty?
    
    +          # TEMP LOCAL STUB -- do NOT commit. Mimics the AI Gateway locally by
    +          # returning a few real catalogue ids. The sleep lets the
    +          # "Searching with Gemini …" loading state show. To test the Gemini
    +          # empty state, replace the return below with `return []`.
    +          sleep 1.5
    +          return catalogue.first(4).pluck(:id) # rubocop:disable CodeReuse/ActiveRecord, Database/AvoidUsingPluckWithoutLimit -- catalogue is a plain Array
    +
               completion(catalogue, normalized_query).execute # rubocop:disable Lint/UnreachableCode -- temp stub
             end
  4. Open the "More Features" modal from the super sidebar; type a query (2+ chars).

  5. Once results settle, click "Search with Gemini"; observe the loading state, then the "Suggested by Gemini" tiles.

MR acceptance checklist

Evaluate this MR against the MR acceptance checklist. It helps you analyze changes to reduce risks in quality, performance, reliability, security, and maintainability.

Edited by Kiesha Herman

Merge request reports

Loading
Loading