From 6c5613ffcefacaeb55080ea1d72baaf922cb23fe Mon Sep 17 00:00:00 2001 From: Brendan Kellam Date: Wed, 1 Apr 2026 14:05:44 -0700 Subject: [PATCH 1/2] chore(web): remove unused code and dead exports Remove unused functions, components, hooks, and schemas identified via ts-unused-exports analysis across the web package. Co-Authored-By: Claude Opus 4.6 (1M context) --- packages/web/src/actions.ts | 13 +- .../[domain]/browse/hooks/useBrowsePath.ts | 32 ----- .../components/codeHostIconButton.tsx | 35 ----- .../repos/components/addRepositoryDialog.tsx | 126 ------------------ packages/web/src/data/connection.ts | 26 ---- .../src/hooks/useFindLanguageDescription.ts | 23 ---- .../src/lib/extensions/lineOffsetExtension.ts | 20 --- packages/web/src/lib/schemas.ts | 9 -- packages/web/src/lib/serviceError.ts | 35 ----- packages/web/src/lib/utils.ts | 35 ----- packages/web/src/openapi/publicApiSchemas.ts | 4 - 11 files changed, 1 insertion(+), 357 deletions(-) delete mode 100644 packages/web/src/app/[domain]/browse/hooks/useBrowsePath.ts delete mode 100644 packages/web/src/app/[domain]/components/codeHostIconButton.tsx delete mode 100644 packages/web/src/app/[domain]/repos/components/addRepositoryDialog.tsx delete mode 100644 packages/web/src/data/connection.ts delete mode 100644 packages/web/src/hooks/useFindLanguageDescription.ts delete mode 100644 packages/web/src/lib/extensions/lineOffsetExtension.ts diff --git a/packages/web/src/actions.ts b/packages/web/src/actions.ts index f3581cbed..ba1105c81 100644 --- a/packages/web/src/actions.ts +++ b/packages/web/src/actions.ts @@ -26,7 +26,7 @@ import InviteUserEmail from "./emails/inviteUserEmail"; import JoinRequestApprovedEmail from "./emails/joinRequestApprovedEmail"; import JoinRequestSubmittedEmail from "./emails/joinRequestSubmittedEmail"; import { AGENTIC_SEARCH_TUTORIAL_DISMISSED_COOKIE_NAME, MOBILE_UNSUPPORTED_SPLASH_SCREEN_DISMISSED_COOKIE_NAME, SINGLE_TENANT_ORG_DOMAIN, SOURCEBOT_GUEST_USER_ID, SOURCEBOT_SUPPORT_EMAIL } from "./lib/constants"; -import { ApiKeyPayload, RepositoryQuery, TenancyMode } from "./lib/types"; +import { ApiKeyPayload, RepositoryQuery } from "./lib/types"; import { withAuthV2, withOptionalAuthV2 } from "./withAuthV2"; import { getBrowsePath } from "./app/[domain]/browse/hooks/utils"; @@ -171,17 +171,6 @@ export const withOrgMembership = async (userId: string, domain: string, fn: ( }); } -export const withTenancyModeEnforcement = async(mode: TenancyMode, fn: () => Promise) => { - if (env.SOURCEBOT_TENANCY_MODE !== mode) { - return { - statusCode: StatusCodes.FORBIDDEN, - errorCode: ErrorCode.ACTION_DISALLOWED_IN_TENANCY_MODE, - message: "This action is not allowed in the current tenancy mode.", - } satisfies ServiceError; - } - return fn(); -} - ////// Actions /////// export const completeOnboarding = async (domain: string): Promise<{ success: boolean } | ServiceError> => sew(() => withAuth((userId) => diff --git a/packages/web/src/app/[domain]/browse/hooks/useBrowsePath.ts b/packages/web/src/app/[domain]/browse/hooks/useBrowsePath.ts deleted file mode 100644 index 2165025d2..000000000 --- a/packages/web/src/app/[domain]/browse/hooks/useBrowsePath.ts +++ /dev/null @@ -1,32 +0,0 @@ -'use client'; - -import { useMemo } from "react"; -import { getBrowsePath, GetBrowsePathProps } from "./utils"; -import { useDomain } from "@/hooks/useDomain"; - -export const useBrowsePath = ({ - repoName, - revisionName, - path, - pathType, - highlightRange, - setBrowseState, -}: Omit) => { - const domain = useDomain(); - - const browsePath = useMemo(() => { - return getBrowsePath({ - repoName, - revisionName, - path, - pathType, - highlightRange, - setBrowseState, - domain, - }); - }, [repoName, revisionName, path, pathType, highlightRange, setBrowseState, domain]); - - return { - path: browsePath, - } -} \ No newline at end of file diff --git a/packages/web/src/app/[domain]/components/codeHostIconButton.tsx b/packages/web/src/app/[domain]/components/codeHostIconButton.tsx deleted file mode 100644 index 796adf4e9..000000000 --- a/packages/web/src/app/[domain]/components/codeHostIconButton.tsx +++ /dev/null @@ -1,35 +0,0 @@ -'use client'; - -import { Button } from "@/components/ui/button"; -import useCaptureEvent from "@/hooks/useCaptureEvent"; -import { cn } from "@/lib/utils"; -import Image from "next/image"; - -interface CodeHostIconButton { - name: string; - logo: { src: string, className?: string }; - onClick: () => void; -} - -export const CodeHostIconButton = ({ - name, - logo, - onClick, -}: CodeHostIconButton) => { - const captureEvent = useCaptureEvent(); - return ( - - ) -} \ No newline at end of file diff --git a/packages/web/src/app/[domain]/repos/components/addRepositoryDialog.tsx b/packages/web/src/app/[domain]/repos/components/addRepositoryDialog.tsx deleted file mode 100644 index 45a8b6c60..000000000 --- a/packages/web/src/app/[domain]/repos/components/addRepositoryDialog.tsx +++ /dev/null @@ -1,126 +0,0 @@ -'use client'; - -import { Button } from "@/components/ui/button"; -import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle } from "@/components/ui/dialog"; -import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from "@/components/ui/form"; -import { Input } from "@/components/ui/input"; -import { zodResolver } from "@hookform/resolvers/zod"; -import { useForm } from "react-hook-form"; -import { z } from "zod"; -import { experimental_addGithubRepositoryByUrl } from "@/actions"; -import { isServiceError } from "@/lib/utils"; -import { useToast } from "@/components/hooks/use-toast"; -import { useRouter } from "next/navigation"; - -interface AddRepositoryDialogProps { - isOpen: boolean; - onOpenChange: (open: boolean) => void; -} - -// Validation schema for repository URLs -const formSchema = z.object({ - repositoryUrl: z.string() - .min(1, "Repository URL is required") - .refine((url) => { - // Allow various GitHub URL formats: - // - https://github.com/owner/repo - // - github.com/owner/repo - // - owner/repo - const patterns = [ - /^https?:\/\/github\.com\/[a-zA-Z0-9_.-]+\/[a-zA-Z0-9_.-]+\/?$/, - /^github\.com\/[a-zA-Z0-9_.-]+\/[a-zA-Z0-9_.-]+\/?$/, - /^[a-zA-Z0-9_.-]+\/[a-zA-Z0-9_.-]+$/ - ]; - return patterns.some(pattern => pattern.test(url.trim())); - }, "Please enter a valid GitHub repository URL (e.g., owner/repo or https://github.com/owner/repo)"), -}); - -export const AddRepositoryDialog = ({ isOpen, onOpenChange }: AddRepositoryDialogProps) => { - const { toast } = useToast(); - const router = useRouter(); - - const form = useForm>({ - resolver: zodResolver(formSchema), - defaultValues: { - repositoryUrl: "", - }, - }); - - const { isSubmitting } = form.formState; - - const onSubmit = async (data: z.infer) => { - - const result = await experimental_addGithubRepositoryByUrl(data.repositoryUrl.trim()); - if (isServiceError(result)) { - toast({ - title: "Error adding repository", - description: result.message, - variant: "destructive", - }); - } else { - toast({ - title: "Repository added successfully!", - description: "It will be indexed shortly.", - }); - form.reset(); - onOpenChange(false); - router.refresh(); - } - }; - - const handleCancel = () => { - form.reset(); - onOpenChange(false); - }; - - return ( - - - - Add a public repository from GitHub - - Paste the repo URL - the code will be indexed and available in search. - - - -
- - ( - - Repository URL - - - - - - )} - /> - - - - - - - -
-
- ); -}; diff --git a/packages/web/src/data/connection.ts b/packages/web/src/data/connection.ts deleted file mode 100644 index 7664dcd98..000000000 --- a/packages/web/src/data/connection.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { prisma } from '@/prisma'; -import 'server-only'; - -export const getConnection = async (connectionId: number, orgId: number) => { - const connection = await prisma.connection.findUnique({ - where: { - id: connectionId, - orgId: orgId, - }, - }); - - return connection; -} - -export const getConnectionByDomain = async (connectionId: number, domain: string) => { - const connection = await prisma.connection.findUnique({ - where: { - id: connectionId, - org: { - domain: domain, - } - }, - }); - - return connection; -} diff --git a/packages/web/src/hooks/useFindLanguageDescription.ts b/packages/web/src/hooks/useFindLanguageDescription.ts deleted file mode 100644 index 344f93871..000000000 --- a/packages/web/src/hooks/useFindLanguageDescription.ts +++ /dev/null @@ -1,23 +0,0 @@ -'use client'; - -import { LanguageDescription } from "@codemirror/language"; -import { useMemo } from "react"; -import { languages as builtinLanguages } from '@codemirror/language-data' - -interface UseFindLanguageDescriptionProps { - languageName: string; - fuzzyMatch?: boolean; -} - -export const useFindLanguageDescription = ({ languageName, fuzzyMatch = true }: UseFindLanguageDescriptionProps) => { - const languageDescription = useMemo(() => { - const description = LanguageDescription.matchLanguageName( - builtinLanguages, - languageName, - fuzzyMatch - ); - return description; - }, [languageName, fuzzyMatch]); - - return languageDescription; -} \ No newline at end of file diff --git a/packages/web/src/lib/extensions/lineOffsetExtension.ts b/packages/web/src/lib/extensions/lineOffsetExtension.ts deleted file mode 100644 index 60f890e00..000000000 --- a/packages/web/src/lib/extensions/lineOffsetExtension.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { Compartment } from "@codemirror/state"; -import { lineNumbers } from "@codemirror/view"; - -const gutter = new Compartment(); - -/** - * Offsets the line numbers by the given amount - * @see: https://discuss.codemirror.net/t/codemirror-6-offset-line-numbers/2675/8 - */ -export const lineOffsetExtension = (lineOffset: number) => { - const lines = lineNumbers({ - formatNumber: (n) => { - return (n + lineOffset).toString(); - } - }); - - return [ - gutter.of(lines) - ] -} \ No newline at end of file diff --git a/packages/web/src/lib/schemas.ts b/packages/web/src/lib/schemas.ts index 3abfe73b0..4fdae9cad 100644 --- a/packages/web/src/lib/schemas.ts +++ b/packages/web/src/lib/schemas.ts @@ -1,15 +1,6 @@ import { z } from "zod"; import { CodeHostType } from "@sourcebot/db"; -export const secretCreateRequestSchema = z.object({ - key: z.string(), - value: z.string(), -}); - -export const secreteDeleteRequestSchema = z.object({ - key: z.string(), -}); - export const repositoryQuerySchema = z.object({ codeHostType: z.nativeEnum(CodeHostType), repoId: z.number(), diff --git a/packages/web/src/lib/serviceError.ts b/packages/web/src/lib/serviceError.ts index a34a15805..f874cdb7b 100644 --- a/packages/web/src/lib/serviceError.ts +++ b/packages/web/src/lib/serviceError.ts @@ -53,25 +53,6 @@ export const queryParamsSchemaValidationError = (error: ZodError): ServiceError }; } -export const invalidZoektResponse = async (zoektResponse: Response): Promise => { - const zoektMessage = await (async () => { - try { - const zoektResponseBody = await zoektResponse.json(); - if (zoektResponseBody.Error) { - return zoektResponseBody.Error; - } - } catch (_e) { - return "Unknown error"; - } - })(); - - return { - statusCode: StatusCodes.INTERNAL_SERVER_ERROR, - errorCode: ErrorCode.INVALID_REQUEST_BODY, - message: `Zoekt request failed with status code ${zoektResponse.status} and message: "${zoektMessage}"`, - }; -} - export const fileNotFound = (fileName: string, repository: string): ServiceError => { return { statusCode: StatusCodes.NOT_FOUND, @@ -120,22 +101,6 @@ export const orgNotFound = (): ServiceError => { } } -export const orgDomainExists = (): ServiceError => { - return { - statusCode: StatusCodes.CONFLICT, - errorCode: ErrorCode.ORG_DOMAIN_ALREADY_EXISTS, - message: "Organization domain already exists, please try a different one.", - } -} - -export const secretAlreadyExists = (): ServiceError => { - return { - statusCode: StatusCodes.CONFLICT, - errorCode: ErrorCode.SECRET_ALREADY_EXISTS, - message: "Secret already exists", - } -} - export const invalidGitRef = (ref: string): ServiceError => { return { statusCode: StatusCodes.BAD_REQUEST, diff --git a/packages/web/src/lib/utils.ts b/packages/web/src/lib/utils.ts index 43a1ad3ae..2f6dedfe6 100644 --- a/packages/web/src/lib/utils.ts +++ b/packages/web/src/lib/utils.ts @@ -14,9 +14,6 @@ import microsoftLogo from "@/public/microsoft_entra.svg"; import authentikLogo from "@/public/authentik.svg"; import jumpcloudLogo from "@/public/jumpcloud.svg"; import { ServiceError } from "./serviceError"; -import { StatusCodes } from "http-status-codes"; -import { ErrorCode } from "./errorCodes"; -import { NextRequest } from "next/server"; import { ConnectionType, Org } from "@sourcebot/db"; import { OrgMetadata, orgMetadataSchema } from "@/types"; import { SINGLE_TENANT_ORG_DOMAIN } from "./constants"; @@ -441,21 +438,6 @@ export const getCodeHostBrowseFileAtBranchUrl = ({ } } -export const isAuthSupportedForCodeHost = (codeHostType: CodeHostType): boolean => { - switch (codeHostType) { - case "github": - case "gitlab": - case "gitea": - case "bitbucketCloud": - case "bitbucketServer": - case "azuredevops": - return true; - case "genericGitHost": - case "gerrit": - return false; - } -} - export const isServiceError = (data: unknown): data is ServiceError => { return typeof data === 'object' && data !== null && @@ -464,11 +446,6 @@ export const isServiceError = (data: unknown): data is ServiceError => { 'message' in data; } -// @see: https://stackoverflow.com/a/65959350/23221295 -export const isDefined = (arg: T | null | undefined): arg is T extends null | undefined ? never : T => { - return arg !== null && arg !== undefined; -} - export const getFormattedDate = (date: Date) => { const now = new Date(); const diffMinutes = (now.getTime() - date.getTime()) / (1000 * 60); @@ -574,18 +551,6 @@ export const unwrapServiceError = async (promise: Promise): return data; } -export const requiredQueryParamGuard = (request: NextRequest, param: string): ServiceError | string => { - const value = request.nextUrl.searchParams.get(param); - if (!value) { - return { - statusCode: StatusCodes.BAD_REQUEST, - errorCode: ErrorCode.MISSING_REQUIRED_QUERY_PARAMETER, - message: `Missing required query param: ${param}`, - }; - } - return value; -} - export const getRepoImageSrc = (imageUrl: string | undefined, repoId: number): string | undefined => { if (!imageUrl) return undefined; diff --git a/packages/web/src/openapi/publicApiSchemas.ts b/packages/web/src/openapi/publicApiSchemas.ts index 99726090b..f0d8b06f6 100644 --- a/packages/web/src/openapi/publicApiSchemas.ts +++ b/packages/web/src/openapi/publicApiSchemas.ts @@ -10,8 +10,6 @@ import { fileSourceResponseSchema, getDiffRequestSchema, getDiffResponseSchema, - getFilesRequestSchema, - getFilesResponseSchema, getTreeRequestSchema, listCommitsQueryParamsSchema, } from '../features/git/schemas.js'; @@ -36,8 +34,6 @@ export const publicServiceErrorSchema = serviceErrorSchema.openapi('PublicApiSer export const publicSearchRequestSchema = searchRequestSchema.openapi('PublicSearchRequest'); export const publicSearchResponseSchema = searchResponseSchema.openapi('PublicSearchResponse'); export const publicGetTreeRequestSchema = getTreeRequestSchema.openapi('PublicGetTreeRequest'); -export const publicGetFilesRequestSchema = getFilesRequestSchema.openapi('PublicGetFilesRequest'); -export const publicGetFilesResponseSchema = getFilesResponseSchema.openapi('PublicGetFilesResponse'); export const publicFileSourceRequestSchema = fileSourceRequestSchema.openapi('PublicFileSourceRequest'); export const publicFileSourceResponseSchema = fileSourceResponseSchema.openapi('PublicFileSourceResponse'); export const publicVersionResponseSchema = getVersionResponseSchema.openapi('PublicVersionResponse'); From a84204ff15e1a9d15014d20c843d958f73b085c0 Mon Sep 17 00:00:00 2001 From: Brendan Kellam Date: Wed, 1 Apr 2026 14:06:21 -0700 Subject: [PATCH 2/2] chore(web): remove unused configEditor and OnboardingSteps enum Co-Authored-By: Claude Opus 4.6 (1M context) --- .../app/[domain]/components/configEditor.tsx | 285 ------------------ packages/web/src/lib/constants.ts | 9 - 2 files changed, 294 deletions(-) delete mode 100644 packages/web/src/app/[domain]/components/configEditor.tsx diff --git a/packages/web/src/app/[domain]/components/configEditor.tsx b/packages/web/src/app/[domain]/components/configEditor.tsx deleted file mode 100644 index 63ba1acde..000000000 --- a/packages/web/src/app/[domain]/components/configEditor.tsx +++ /dev/null @@ -1,285 +0,0 @@ -'use client'; - -import { ScrollArea } from "@/components/ui/scroll-area"; -import { useKeymapExtension } from "@/hooks/useKeymapExtension"; -import { json, jsonLanguage, jsonParseLinter } from "@codemirror/lang-json"; -import { linter } from "@codemirror/lint"; -import { EditorView, hoverTooltip } from "@codemirror/view"; -import CodeMirror, { Extension, ReactCodeMirrorRef } from "@uiw/react-codemirror"; -import { useRef, forwardRef, useImperativeHandle, Ref, ReactNode, useState, useEffect } from "react"; -import { Button } from "@/components/ui/button"; -import { Separator } from "@/components/ui/separator"; -import { Schema } from "ajv"; -import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@/components/ui/tooltip"; -import useCaptureEvent from "@/hooks/useCaptureEvent"; -import { useCodeMirrorTheme } from "@/hooks/useCodeMirrorTheme"; -import { CodeHostType } from "@sourcebot/db"; - -export type QuickActionFn = (previous: T) => T; -export type QuickAction = { - name: string; - fn: QuickActionFn; - description?: string | ReactNode; - selectionText?: string; -}; - -interface ConfigEditorProps { - value: string; - type: CodeHostType; - // eslint-disable-next-line @typescript-eslint/no-explicit-any - onChange: (...event: any[]) => void; - actions: QuickAction[], - schema: Schema; -} - -const customAutocompleteStyle = EditorView.baseTheme({ - ".cm-tooltip.cm-completionInfo": { - padding: "8px", - fontSize: "12px", - fontFamily: "monospace", - }, - ".cm-tooltip-hover.cm-tooltip": { - padding: "8px", - fontSize: "12px", - fontFamily: "monospace", - } -}); - -export function onQuickAction( - action: QuickActionFn, - config: string, - view: EditorView, - options?: { - focusEditor?: boolean; - moveCursor?: boolean; - selectionText?: string; - } -) { - const { - focusEditor = false, - moveCursor = true, - selectionText = `""`, - } = options ?? {}; - - let previousConfig: T; - try { - previousConfig = JSON.parse(config) as T; - } catch { - return; - } - - const nextConfig = action(previousConfig); - const next = JSON.stringify(nextConfig, null, 2); - - if (focusEditor) { - view.focus(); - } - - view.dispatch({ - changes: { - from: 0, - to: config.length, - insert: next, - } - }); - - if (moveCursor && selectionText) { - const cursorPos = next.lastIndexOf(selectionText); - if (cursorPos >= 0) { - view.dispatch({ - selection: { - anchor: cursorPos, - head: cursorPos + selectionText.length - } - }); - } - } -} - -export const isConfigValidJson = (config: string) => { - try { - JSON.parse(config); - return true; - } catch (_e) { - return false; - } -} - -const DEFAULT_ACTIONS_VISIBLE = 4; - -const ConfigEditor = (props: ConfigEditorProps, forwardedRef: Ref) => { - const { value, type, onChange, actions, schema } = props; - const captureEvent = useCaptureEvent(); - const editorRef = useRef(null); - const [isViewMoreActionsEnabled, setIsViewMoreActionsEnabled] = useState(false); - const [height, setHeight] = useState(224); - useImperativeHandle( - forwardedRef, - () => editorRef.current as ReactCodeMirrorRef - ); - - const keymapExtension = useKeymapExtension(editorRef.current?.view); - const theme = useCodeMirrorTheme(); - - // ⚠️ DISGUSTING HACK AHEAD ⚠️ - // Background: When navigating to the /connections/:id?tab=settings page, we were hitting a 500 error with the following - // message server side: - // - // > Internal error: Error: Element type is invalid: expected a string (for built-in components) or a class/function - // > (for composite components) but got: undefined. You likely forgot to export your component from the file it's - // > defined in, or you might have mixed up default and named imports. - // - // Why was this happening? We have no idea, but we isolated it to the extensions exported by the `codemirror-json-schema` - // package. The solution that worked was to dynamically import the package inside of the useEffect and load the extensions - // async. - // - // So, yeah. - Brendan - const [jsonSchemaExtensions, setJsonSchemaExtensions] = useState([]); - useEffect(() => { - const loadExtensions = async () => { - const { - handleRefresh, - jsonCompletion, - jsonSchemaHover, - jsonSchemaLinter, - stateExtensions - } = await import('codemirror-json-schema'); - return [ - linter(jsonParseLinter(), { - delay: 300, - }), - linter(jsonSchemaLinter(), { - needsRefresh: handleRefresh, - }), - jsonLanguage.data.of({ - autocomplete: jsonCompletion(), - }), - hoverTooltip(jsonSchemaHover()), - // eslint-disable-next-line @typescript-eslint/no-explicit-any - stateExtensions(schema as any), - ] - } - - loadExtensions().then((extensions) => { - console.debug('Loaded json schema extensions'); - setJsonSchemaExtensions(extensions); - }); - }, [schema]); - - return ( -
-
- - {actions - .slice(0, isViewMoreActionsEnabled ? actions.length : DEFAULT_ACTIONS_VISIBLE) - .map(({ name, fn, description, selectionText }, index, truncatedActions) => ( -
- - - - - - - {index !== truncatedActions.length - 1 && ( - - )} - {index === truncatedActions.length - 1 && truncatedActions.length < actions.length && ( - <> - - - - )} -
- ))} - -
-
- - - - - -
{ - e.preventDefault(); - const startY = e.clientY; - const startHeight = height; - - function onMouseMove(e: MouseEvent) { - const delta = e.clientY - startY; - setHeight(Math.max(112, startHeight + delta)); - } - - function onMouseUp() { - document.removeEventListener('mousemove', onMouseMove); - document.removeEventListener('mouseup', onMouseUp); - } - - document.addEventListener('mousemove', onMouseMove); - document.addEventListener('mouseup', onMouseUp); - }} - /> -
- ) -}; - -// @see: https://stackoverflow.com/a/78692562 -export default forwardRef(ConfigEditor) as ( - props: ConfigEditorProps & { ref?: Ref }, -) => ReturnType; diff --git a/packages/web/src/lib/constants.ts b/packages/web/src/lib/constants.ts index d6dbaf5e9..168dd1a7a 100644 --- a/packages/web/src/lib/constants.ts +++ b/packages/web/src/lib/constants.ts @@ -1,12 +1,3 @@ - -// @note: Order is important here. -export enum OnboardingSteps { - CreateOrg = 'create-org', - ConnectCodeHost = 'connect-code-host', - InviteTeam = 'invite-team', - Complete = 'complete', -} - export const MOBILE_UNSUPPORTED_SPLASH_SCREEN_DISMISSED_COOKIE_NAME = 'sb.mobile-unsupported-splash-screen-dismissed'; export const AGENTIC_SEARCH_TUTORIAL_DISMISSED_COOKIE_NAME = 'sb.agentic-search-tutorial-dismissed'; export const OPTIONAL_PROVIDERS_LINK_SKIPPED_COOKIE_NAME = 'sb.optional-providers-link-skipped';