- 'use client'
 - 
 - import type { FC } from 'react'
 - import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
 - import { useRouter } from 'next/navigation'
 - import Modal from '@/app/components/base/modal'
 - import Input from '@/app/components/base/input'
 - import { useDebounce, useKeyPress } from 'ahooks'
 - import { getKeyboardKeyCodeBySystem, isEventTargetInputArea, isMac } from '@/app/components/workflow/utils/common'
 - import { selectWorkflowNode } from '@/app/components/workflow/utils/node-navigation'
 - import { RiSearchLine } from '@remixicon/react'
 - import { type SearchResult, createActions, matchAction, searchAnything } from './actions'
 - import { GotoAnythingProvider, useGotoAnythingContext } from './context'
 - import { slashCommandRegistry } from './actions/commands/registry'
 - import { useQuery } from '@tanstack/react-query'
 - import { useGetLanguage } from '@/context/i18n'
 - import { useTranslation } from 'react-i18next'
 - import InstallFromMarketplace from '../plugins/install-plugin/install-from-marketplace'
 - import type { Plugin } from '../plugins/types'
 - import { Command } from 'cmdk'
 - import CommandSelector from './command-selector'
 - import { SlashCommandProvider } from './actions/commands'
 - 
 - type Props = {
 -   onHide?: () => void
 - }
 - const GotoAnything: FC<Props> = ({
 -   onHide,
 - }) => {
 -   const router = useRouter()
 -   const defaultLocale = useGetLanguage()
 -   const { isWorkflowPage, isRagPipelinePage } = useGotoAnythingContext()
 -   const { t } = useTranslation()
 -   const [show, setShow] = useState<boolean>(false)
 -   const [searchQuery, setSearchQuery] = useState<string>('')
 -   const [cmdVal, setCmdVal] = useState<string>('_')
 -   const inputRef = useRef<HTMLInputElement>(null)
 - 
 -   // Filter actions based on context
 -   const Actions = useMemo(() => {
 -     // Create actions based on current page context
 -     return createActions(isWorkflowPage, isRagPipelinePage)
 -   }, [isWorkflowPage, isRagPipelinePage])
 - 
 -   const [activePlugin, setActivePlugin] = useState<Plugin>()
 - 
 -   // Handle keyboard shortcuts
 -   const handleToggleModal = useCallback((e: KeyboardEvent) => {
 -     // Allow closing when modal is open, even if focus is in the search input
 -     if (!show && isEventTargetInputArea(e.target as HTMLElement))
 -       return
 -     e.preventDefault()
 -     setShow((prev) => {
 -       if (!prev) {
 -         // Opening modal - reset search state
 -         setSearchQuery('')
 -       }
 -       return !prev
 -     })
 -   }, [show])
 - 
 -   useKeyPress(`${getKeyboardKeyCodeBySystem('ctrl')}.k`, handleToggleModal, {
 -     exactMatch: true,
 -     useCapture: true,
 -   })
 - 
 -   useKeyPress(['esc'], (e) => {
 -     if (show) {
 -       e.preventDefault()
 -       setShow(false)
 -       setSearchQuery('')
 -     }
 -   })
 - 
 -   const searchQueryDebouncedValue = useDebounce(searchQuery.trim(), {
 -     wait: 300,
 -   })
 - 
 -   const isCommandsMode = searchQuery.trim() === '@' || searchQuery.trim() === '/'
 -     || (searchQuery.trim().startsWith('@') && !matchAction(searchQuery.trim(), Actions))
 -     || (searchQuery.trim().startsWith('/') && !matchAction(searchQuery.trim(), Actions))
 - 
 -   const searchMode = useMemo(() => {
 -     if (isCommandsMode) {
 -       // Distinguish between @ (scopes) and / (commands) mode
 -       if (searchQuery.trim().startsWith('@'))
 -         return 'scopes'
 -       else if (searchQuery.trim().startsWith('/'))
 -         return 'commands'
 -       return 'commands' // default fallback
 -     }
 - 
 -     const query = searchQueryDebouncedValue.toLowerCase()
 -     const action = matchAction(query, Actions)
 - 
 -     if (!action)
 -       return 'general'
 - 
 -     return action.key === '/' ? '@command' : action.key
 -   }, [searchQueryDebouncedValue, Actions, isCommandsMode, searchQuery])
 - 
 -   const { data: searchResults = [], isLoading, isError, error } = useQuery(
 -     {
 -       queryKey: [
 -         'goto-anything',
 -         'search-result',
 -         searchQueryDebouncedValue,
 -         searchMode,
 -         isWorkflowPage,
 -         isRagPipelinePage,
 -         defaultLocale,
 -         Object.keys(Actions).sort().join(','),
 -       ],
 -       queryFn: async () => {
 -         const query = searchQueryDebouncedValue.toLowerCase()
 -         const action = matchAction(query, Actions)
 -         return await searchAnything(defaultLocale, query, action, Actions)
 -       },
 -       enabled: !!searchQueryDebouncedValue && !isCommandsMode,
 -       staleTime: 30000,
 -       gcTime: 300000,
 -     },
 -   )
 - 
 -   // Prevent automatic selection of the first option when cmdVal is not set
 -   const clearSelection = () => {
 -     setCmdVal('_')
 -   }
 - 
 -   const handleCommandSelect = useCallback((commandKey: string) => {
 -     // Check if it's a slash command
 -     if (commandKey.startsWith('/')) {
 -       const commandName = commandKey.substring(1)
 -       const handler = slashCommandRegistry.findCommand(commandName)
 - 
 -       // If it's a direct mode command, execute immediately
 -       if (handler?.mode === 'direct' && handler.execute) {
 -         handler.execute()
 -         setShow(false)
 -         setSearchQuery('')
 -         return
 -       }
 -     }
 - 
 -     // Otherwise, proceed with the normal flow (submenu mode)
 -     setSearchQuery(`${commandKey} `)
 -     clearSelection()
 -     setTimeout(() => {
 -       inputRef.current?.focus()
 -     }, 0)
 -   }, [])
 - 
 -   // Handle navigation to selected result
 -   const handleNavigate = useCallback((result: SearchResult) => {
 -     setShow(false)
 -     setSearchQuery('')
 - 
 -     switch (result.type) {
 -       case 'command': {
 -         // Execute slash commands
 -         const action = Actions.slash
 -         action?.action?.(result)
 -         break
 -       }
 -       case 'plugin':
 -         setActivePlugin(result.data)
 -         break
 -       case 'workflow-node':
 -         // Handle workflow node selection and navigation
 -         if (result.metadata?.nodeId)
 -           selectWorkflowNode(result.metadata.nodeId, true)
 - 
 -         break
 -       default:
 -         if (result.path)
 -           router.push(result.path)
 -     }
 -   }, [router])
 - 
 -   // Group results by type
 -   const groupedResults = useMemo(() => searchResults.reduce((acc, result) => {
 -     if (!acc[result.type])
 -       acc[result.type] = []
 - 
 -     acc[result.type].push(result)
 -     return acc
 -   }, {} as { [key: string]: SearchResult[] }),
 -   [searchResults])
 - 
 -   const emptyResult = useMemo(() => {
 -     if (searchResults.length || !searchQuery.trim() || isLoading || isCommandsMode)
 -       return null
 - 
 -     const isCommandSearch = searchMode !== 'general'
 -     const commandType = isCommandSearch ? searchMode.replace('@', '') : ''
 - 
 -     if (isError) {
 -       return (
 -         <div className="flex items-center justify-center py-8 text-center text-text-tertiary">
 -           <div>
 -             <div className='text-sm font-medium text-red-500'>{t('app.gotoAnything.searchTemporarilyUnavailable')}</div>
 -             <div className='mt-1 text-xs text-text-quaternary'>
 -               {t('app.gotoAnything.servicesUnavailableMessage')}
 -             </div>
 -           </div>
 -         </div>
 -       )
 -     }
 - 
 -     return (
 -       <div className="flex items-center justify-center py-8 text-center text-text-tertiary">
 -         <div>
 -           <div className='text-sm font-medium'>
 -             {isCommandSearch
 -               ? (() => {
 -                 const keyMap: Record<string, string> = {
 -                   app: 'app.gotoAnything.emptyState.noAppsFound',
 -                   plugin: 'app.gotoAnything.emptyState.noPluginsFound',
 -                   knowledge: 'app.gotoAnything.emptyState.noKnowledgeBasesFound',
 -                   node: 'app.gotoAnything.emptyState.noWorkflowNodesFound',
 -                 }
 -                 return t(keyMap[commandType] || 'app.gotoAnything.noResults')
 -               })()
 -               : t('app.gotoAnything.noResults')
 -             }
 -           </div>
 -           <div className='mt-1 text-xs text-text-quaternary'>
 -             {isCommandSearch
 -               ? t('app.gotoAnything.emptyState.tryDifferentTerm')
 -               : t('app.gotoAnything.emptyState.trySpecificSearch', { shortcuts: Object.values(Actions).map(action => action.shortcut).join(', ') })
 -             }
 -           </div>
 -         </div>
 -       </div>
 -     )
 -   }, [searchResults, searchQuery, Actions, searchMode, isLoading, isError, isCommandsMode])
 - 
 -   const defaultUI = useMemo(() => {
 -     if (searchQuery.trim())
 -       return null
 - 
 -     return (<div className="flex items-center justify-center py-8 text-center text-text-tertiary">
 -       <div>
 -         <div className='text-sm font-medium'>{t('app.gotoAnything.searchTitle')}</div>
 -         <div className='mt-3 space-y-1 text-xs text-text-quaternary'>
 -           <div>{t('app.gotoAnything.searchHint')}</div>
 -           <div>{t('app.gotoAnything.commandHint')}</div>
 -           <div>{t('app.gotoAnything.slashHint')}</div>
 -         </div>
 -       </div>
 -     </div>)
 -   }, [searchQuery, Actions])
 - 
 -   useEffect(() => {
 -     if (show) {
 -       requestAnimationFrame(() => {
 -         inputRef.current?.focus()
 -       })
 -     }
 -   }, [show])
 - 
 -   return (
 -     <>
 -       <SlashCommandProvider />
 -       <Modal
 -         isShow={show}
 -         onClose={() => {
 -           setShow(false)
 -           setSearchQuery('')
 -           clearSelection()
 -           onHide?.()
 -         }}
 -         closable={false}
 -         className='!w-[480px] !p-0'
 -         highPriority={true}
 -       >
 -         <div className='flex flex-col rounded-2xl border border-components-panel-border bg-components-panel-bg shadow-xl'>
 -           <Command
 -             className='outline-none'
 -             value={cmdVal}
 -             onValueChange={setCmdVal}
 -             disablePointerSelection
 -             loop
 -           >
 -             <div className='flex items-center gap-3 border-b border-divider-subtle bg-components-panel-bg-blur px-4 py-3'>
 -               <RiSearchLine className='h-4 w-4 text-text-quaternary' />
 -               <div className='flex flex-1 items-center gap-2'>
 -                 <Input
 -                   ref={inputRef}
 -                   value={searchQuery}
 -                   placeholder={t('app.gotoAnything.searchPlaceholder')}
 -                   onChange={(e) => {
 -                     setSearchQuery(e.target.value)
 -                     if (!e.target.value.startsWith('@') && !e.target.value.startsWith('/'))
 -                       clearSelection()
 -                   }}
 -                   onKeyDown={(e) => {
 -                     if (e.key === 'Enter') {
 -                       const query = searchQuery.trim()
 -                       // Check if it's a complete slash command
 -                       if (query.startsWith('/')) {
 -                         const commandName = query.substring(1).split(' ')[0]
 -                         const handler = slashCommandRegistry.findCommand(commandName)
 - 
 -                         // If it's a direct mode command, execute immediately
 -                         if (handler?.mode === 'direct' && handler.execute) {
 -                           e.preventDefault()
 -                           handler.execute()
 -                           setShow(false)
 -                           setSearchQuery('')
 -                         }
 -                       }
 -                     }
 -                   }}
 -                   className='flex-1 !border-0 !bg-transparent !shadow-none'
 -                   wrapperClassName='flex-1 !border-0 !bg-transparent'
 -                   autoFocus
 -                 />
 -                 {searchMode !== 'general' && (
 -                   <div className='flex items-center gap-1 rounded bg-gray-100 px-2 py-[2px] text-xs font-medium text-gray-700 dark:bg-gray-800 dark:text-gray-300'>
 -                     <span>{(() => {
 -                       if (searchMode === 'scopes')
 -                         return 'SCOPES'
 -                       else if (searchMode === 'commands')
 -                         return 'COMMANDS'
 -                       else
 -                         return searchMode.replace('@', '').toUpperCase()
 -                     })()}</span>
 -                   </div>
 -                 )}
 -               </div>
 -               <div className='text-xs text-text-quaternary'>
 -                 <span className='system-kbd rounded bg-gray-200 px-1 py-[2px] font-mono text-gray-700 dark:bg-gray-800 dark:text-gray-100'>
 -                   {isMac() ? '⌘' : 'Ctrl'}
 -                 </span>
 -                 <span className='system-kbd ml-1 rounded bg-gray-200 px-1 py-[2px] font-mono text-gray-700 dark:bg-gray-800 dark:text-gray-100'>
 -                   K
 -                 </span>
 -               </div>
 -             </div>
 - 
 -             <Command.List className='h-[240px] overflow-y-auto'>
 -               {isLoading && (
 -                 <div className="flex items-center justify-center py-8 text-center text-text-tertiary">
 -                   <div className="flex items-center gap-2">
 -                     <div className="h-4 w-4 animate-spin rounded-full border-2 border-gray-300 border-t-gray-600"></div>
 -                     <span className="text-sm">{t('app.gotoAnything.searching')}</span>
 -                   </div>
 -                 </div>
 -               )}
 -               {isError && (
 -                 <div className="flex items-center justify-center py-8 text-center text-text-tertiary">
 -                   <div>
 -                     <div className="text-sm font-medium text-red-500">{t('app.gotoAnything.searchFailed')}</div>
 -                     <div className="mt-1 text-xs text-text-quaternary">
 -                       {error.message}
 -                     </div>
 -                   </div>
 -                 </div>
 -               )}
 -               {!isLoading && !isError && (
 -                 <>
 -                   {isCommandsMode ? (
 -                     <CommandSelector
 -                       actions={Actions}
 -                       onCommandSelect={handleCommandSelect}
 -                       searchFilter={searchQuery.trim().substring(1)}
 -                       commandValue={cmdVal}
 -                       onCommandValueChange={setCmdVal}
 -                       originalQuery={searchQuery.trim()}
 -                     />
 -                   ) : (
 -                     Object.entries(groupedResults).map(([type, results], groupIndex) => (
 -                       <Command.Group key={groupIndex} heading={(() => {
 -                         const typeMap: Record<string, string> = {
 -                           'app': 'app.gotoAnything.groups.apps',
 -                           'plugin': 'app.gotoAnything.groups.plugins',
 -                           'knowledge': 'app.gotoAnything.groups.knowledgeBases',
 -                           'workflow-node': 'app.gotoAnything.groups.workflowNodes',
 -                           'command': 'app.gotoAnything.groups.commands',
 -                         }
 -                         return t(typeMap[type] || `${type}s`)
 -                       })()} className='p-2 capitalize text-text-secondary'>
 -                         {results.map(result => (
 -                           <Command.Item
 -                             key={`${result.type}-${result.id}`}
 -                             value={result.title}
 -                             className='flex cursor-pointer items-center gap-3 rounded-md p-3 will-change-[background-color] aria-[selected=true]:bg-state-base-hover data-[selected=true]:bg-state-base-hover'
 -                             onSelect={() => handleNavigate(result)}
 -                           >
 -                             {result.icon}
 -                             <div className='min-w-0 flex-1'>
 -                               <div className='truncate font-medium text-text-secondary'>
 -                                 {result.title}
 -                               </div>
 -                               {result.description && (
 -                                 <div className='mt-0.5 truncate text-xs text-text-quaternary'>
 -                                   {result.description}
 -                                 </div>
 -                               )}
 -                             </div>
 -                             <div className='text-xs capitalize text-text-quaternary'>
 -                               {result.type}
 -                             </div>
 -                           </Command.Item>
 -                         ))}
 -                       </Command.Group>
 -                     ))
 -                   )}
 -                   {!isCommandsMode && emptyResult}
 -                   {!isCommandsMode && defaultUI}
 -                 </>
 -               )}
 -             </Command.List>
 - 
 -             {/* Always show footer to prevent height jumping */}
 -             <div className='border-t border-divider-subtle bg-components-panel-bg-blur px-4 py-2 text-xs text-text-tertiary'>
 -               <div className='flex min-h-[16px] items-center justify-between'>
 -                 {(!!searchResults.length || isError) ? (
 -                   <>
 -                     <span>
 -                       {isError ? (
 -                         <span className='text-red-500'>{t('app.gotoAnything.someServicesUnavailable')}</span>
 -                       ) : (
 -                         <>
 -                           {t('app.gotoAnything.resultCount', { count: searchResults.length })}
 -                           {searchMode !== 'general' && (
 -                             <span className='ml-2 opacity-60'>
 -                               {t('app.gotoAnything.inScope', { scope: searchMode.replace('@', '') })}
 -                             </span>
 -                           )}
 -                         </>
 -                       )}
 -                     </span>
 -                     <span className='opacity-60'>
 -                       {searchMode !== 'general'
 -                         ? t('app.gotoAnything.clearToSearchAll')
 -                         : t('app.gotoAnything.useAtForSpecific')
 -                       }
 -                     </span>
 -                   </>
 -                 ) : (
 -                   <>
 -                     <span className='opacity-60'>
 -                       {(() => {
 -                         if (isCommandsMode)
 -                           return t('app.gotoAnything.selectToNavigate')
 - 
 -                         if (searchQuery.trim())
 -                           return t('app.gotoAnything.searching')
 - 
 -                         return t('app.gotoAnything.startTyping')
 -                       })()}
 -                     </span>
 -                     <span className='opacity-60'>
 -                       {searchQuery.trim() || isCommandsMode
 -                         ? t('app.gotoAnything.tips')
 -                         : t('app.gotoAnything.pressEscToClose')}
 -                     </span>
 -                   </>
 -                 )}
 -               </div>
 -             </div>
 -           </Command>
 -         </div>
 - 
 -       </Modal>
 -       {
 -         activePlugin && (
 -           <InstallFromMarketplace
 -             manifest={activePlugin}
 -             uniqueIdentifier={activePlugin.latest_package_identifier}
 -             onClose={() => setActivePlugin(undefined)}
 -             onSuccess={() => setActivePlugin(undefined)}
 -           />
 -         )
 -       }
 -     </>
 -   )
 - }
 - 
 - /**
 -  * GotoAnything component with context provider
 -  */
 - const GotoAnythingWithContext: FC<Props> = (props) => {
 -   return (
 -     <GotoAnythingProvider>
 -       <GotoAnything {...props} />
 -     </GotoAnythingProvider>
 -   )
 - }
 - 
 - export default GotoAnythingWithContext
 
 
  |