| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289 | import { useMemo } from 'react'import { useTranslation } from 'react-i18next'import { $insertNodes } from 'lexical'import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext'import type {  ContextBlockType,  ExternalToolBlockType,  HistoryBlockType,  QueryBlockType,  VariableBlockType,  WorkflowVariableBlockType,} from '../../types'import { INSERT_CONTEXT_BLOCK_COMMAND } from '../context-block'import { INSERT_HISTORY_BLOCK_COMMAND } from '../history-block'import { INSERT_QUERY_BLOCK_COMMAND } from '../query-block'import { INSERT_VARIABLE_VALUE_BLOCK_COMMAND } from '../variable-block'import { $createCustomTextNode } from '../custom-text/node'import { PromptMenuItem } from './prompt-option'import { VariableMenuItem } from './variable-option'import { PickerBlockMenuOption } from './menu'import { File05 } from '@/app/components/base/icons/src/vender/solid/files'import {  MessageClockCircle,  Tool03,} from '@/app/components/base/icons/src/vender/solid/general'import { BracketsX } from '@/app/components/base/icons/src/vender/line/development'import { UserEdit02 } from '@/app/components/base/icons/src/vender/solid/users'import { ArrowUpRight } from '@/app/components/base/icons/src/vender/line/arrows'import AppIcon from '@/app/components/base/app-icon'export const usePromptOptions = (  contextBlock?: ContextBlockType,  queryBlock?: QueryBlockType,  historyBlock?: HistoryBlockType,) => {  const { t } = useTranslation()  const [editor] = useLexicalComposerContext()  const promptOptions: PickerBlockMenuOption[] = []  if (contextBlock?.show) {    promptOptions.push(new PickerBlockMenuOption({      key: t('common.promptEditor.context.item.title'),      group: 'prompt context',      render: ({ isSelected, onSelect, onSetHighlight }) => {        return <PromptMenuItem          title={t('common.promptEditor.context.item.title')}          icon={<File05 className='w-4 h-4 text-[#6938EF]' />}          disabled={!contextBlock.selectable}          isSelected={isSelected}          onClick={onSelect}          onMouseEnter={onSetHighlight}        />      },      onSelect: () => {        if (!contextBlock?.selectable)          return        editor.dispatchCommand(INSERT_CONTEXT_BLOCK_COMMAND, undefined)      },    }))  }  if (queryBlock?.show) {    promptOptions.push(      new PickerBlockMenuOption({        key: t('common.promptEditor.query.item.title'),        group: 'prompt query',        render: ({ isSelected, onSelect, onSetHighlight }) => {          return (            <PromptMenuItem              title={t('common.promptEditor.query.item.title')}              icon={<UserEdit02 className='w-4 h-4 text-[#FD853A]' />}              disabled={!queryBlock.selectable}              isSelected={isSelected}              onClick={onSelect}              onMouseEnter={onSetHighlight}            />          )        },        onSelect: () => {          if (!queryBlock?.selectable)            return          editor.dispatchCommand(INSERT_QUERY_BLOCK_COMMAND, undefined)        },      }),    )  }  if (historyBlock?.show) {    promptOptions.push(      new PickerBlockMenuOption({        key: t('common.promptEditor.history.item.title'),        group: 'prompt history',        render: ({ isSelected, onSelect, onSetHighlight }) => {          return (            <PromptMenuItem              title={t('common.promptEditor.history.item.title')}              icon={<MessageClockCircle className='w-4 h-4 text-[#DD2590]' />}              disabled={!historyBlock.selectable              }              isSelected={isSelected}              onClick={onSelect}              onMouseEnter={onSetHighlight}            />          )        },        onSelect: () => {          if (!historyBlock?.selectable)            return          editor.dispatchCommand(INSERT_HISTORY_BLOCK_COMMAND, undefined)        },      }),    )  }  return promptOptions}export const useVariableOptions = (  variableBlock?: VariableBlockType,  queryString?: string,): PickerBlockMenuOption[] => {  const { t } = useTranslation()  const [editor] = useLexicalComposerContext()  const options = useMemo(() => {    if (!variableBlock?.variables)      return []    const baseOptions = (variableBlock.variables).map((item) => {      return new PickerBlockMenuOption({        key: item.value,        group: 'prompt variable',        render: ({ queryString, isSelected, onSelect, onSetHighlight }) => {          return (            <VariableMenuItem              title={item.value}              icon={<BracketsX className='w-[14px] h-[14px] text-[#2970FF]' />}              queryString={queryString}              isSelected={isSelected}              onClick={onSelect}              onMouseEnter={onSetHighlight}            />          )        },        onSelect: () => {          editor.dispatchCommand(INSERT_VARIABLE_VALUE_BLOCK_COMMAND, `{{${item.value}}}`)        },      })    })    if (!queryString)      return baseOptions    const regex = new RegExp(queryString, 'i')    return baseOptions.filter(option => regex.test(option.key))  }, [editor, queryString, variableBlock])  const addOption = useMemo(() => {    return new PickerBlockMenuOption({      key: t('common.promptEditor.variable.modal.add'),      group: 'prompt variable',      render: ({ queryString, isSelected, onSelect, onSetHighlight }) => {        return (          <VariableMenuItem            title={t('common.promptEditor.variable.modal.add')}            icon={<BracketsX className='mr-2 w-[14px] h-[14px] text-[#2970FF]' />}            queryString={queryString}            isSelected={isSelected}            onClick={onSelect}            onMouseEnter={onSetHighlight}          />        )      },      onSelect: () => {        editor.update(() => {          const prefixNode = $createCustomTextNode('{{')          const suffixNode = $createCustomTextNode('}}')          $insertNodes([prefixNode, suffixNode])          prefixNode.select()        })      },    })  }, [editor, t])  return useMemo(() => {    return variableBlock?.show ? [...options, addOption] : []  }, [options, addOption, variableBlock?.show])}export const useExternalToolOptions = (  externalToolBlockType?: ExternalToolBlockType,  queryString?: string,) => {  const { t } = useTranslation()  const [editor] = useLexicalComposerContext()  const options = useMemo(() => {    if (!externalToolBlockType?.externalTools)      return []    const baseToolOptions = (externalToolBlockType.externalTools).map((item) => {      return new PickerBlockMenuOption({        key: item.name,        group: 'external tool',        render: ({ queryString, isSelected, onSelect, onSetHighlight }) => {          return (            <VariableMenuItem              title={item.name}              icon={                <AppIcon                  className='!w-[14px] !h-[14px]'                  icon={item.icon}                  background={item.icon_background}                />              }              extraElement={<div className='text-xs text-gray-400'>{item.variableName}</div>}              queryString={queryString}              isSelected={isSelected}              onClick={onSelect}              onMouseEnter={onSetHighlight}            />          )        },        onSelect: () => {          editor.dispatchCommand(INSERT_VARIABLE_VALUE_BLOCK_COMMAND, `{{${item.variableName}}}`)        },      })    })    if (!queryString)      return baseToolOptions    const regex = new RegExp(queryString, 'i')    return baseToolOptions.filter(option => regex.test(option.key))  }, [editor, queryString, externalToolBlockType])  const addOption = useMemo(() => {    return new PickerBlockMenuOption({      key: t('common.promptEditor.variable.modal.addTool'),      group: 'external tool',      render: ({ queryString, isSelected, onSelect, onSetHighlight }) => {        return (          <VariableMenuItem            title={t('common.promptEditor.variable.modal.addTool')}            icon={<Tool03 className='mr-2 w-[14px] h-[14px] text-[#444CE7]' />}            extraElement={< ArrowUpRight className='w-3 h-3 text-gray-400' />}            queryString={queryString}            isSelected={isSelected}            onClick={onSelect}            onMouseEnter={onSetHighlight}          />        )      },      onSelect: () => {        externalToolBlockType?.onAddExternalTool?.()      },    })  }, [externalToolBlockType, t])  return useMemo(() => {    return externalToolBlockType?.show ? [...options, addOption] : []  }, [options, addOption, externalToolBlockType?.show])}export const useOptions = (  contextBlock?: ContextBlockType,  queryBlock?: QueryBlockType,  historyBlock?: HistoryBlockType,  variableBlock?: VariableBlockType,  externalToolBlockType?: ExternalToolBlockType,  workflowVariableBlockType?: WorkflowVariableBlockType,  queryString?: string,) => {  const promptOptions = usePromptOptions(contextBlock, queryBlock, historyBlock)  const variableOptions = useVariableOptions(variableBlock, queryString)  const externalToolOptions = useExternalToolOptions(externalToolBlockType, queryString)  const workflowVariableOptions = useMemo(() => {    if (!workflowVariableBlockType?.show)      return []    return workflowVariableBlockType.variables || []  }, [workflowVariableBlockType])  return useMemo(() => {    return {      workflowVariableOptions,      allFlattenOptions: [...promptOptions, ...variableOptions, ...externalToolOptions],    }  }, [promptOptions, variableOptions, externalToolOptions, workflowVariableOptions])}
 |