Feat: feature and log dark mode (#13208)

pull/13221/head
KVOJJJin 1 year ago committed by GitHub
parent 1de84fdda0
commit 2710242982
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -151,7 +151,6 @@ const SettingBuiltInTool: FC<Props> = ({
isEditMode={false} isEditMode={false}
showOnVariableMap={{}} showOnVariableMap={{}}
validating={false} validating={false}
inputClassName='!bg-gray-50'
readonly={readonly} readonly={readonly}
/> />
) )
@ -224,7 +223,7 @@ const SettingBuiltInTool: FC<Props> = ({
</div> </div>
{!readonly && !isInfoActive && ( {!readonly && !isInfoActive && (
<div className='mt-2 shrink-0 flex justify-end py-4 px-6 space-x-2 rounded-b-[10px] bg-components-panel-bg border-t border-divider-regular'> <div className='mt-2 shrink-0 flex justify-end py-4 px-6 space-x-2 rounded-b-[10px] bg-components-panel-bg border-t border-divider-regular'>
<Button className='flex items-center h-8 !px-3 !text-[13px] font-medium !text-gray-700' onClick={onHide}>{t('common.operation.cancel')}</Button> <Button className='flex items-center h-8 !px-3 !text-[13px] font-medium ' onClick={onHide}>{t('common.operation.cancel')}</Button>
<Button className='flex items-center h-8 !px-3 !text-[13px] font-medium' variant='primary' disabled={!isValid} onClick={() => onSave?.(addDefaultValue(tempSetting, formSchemas))}>{t('common.operation.save')}</Button> <Button className='flex items-center h-8 !px-3 !text-[13px] font-medium' variant='primary' disabled={!isValid} onClick={() => onSave?.(addDefaultValue(tempSetting, formSchemas))}>{t('common.operation.save')}</Button>
</div> </div>
)} )}

@ -48,7 +48,7 @@ import PromptLogModal from '@/app/components/base/prompt-log-modal'
import { useStore as useAppStore } from '@/app/components/app/store' import { useStore as useAppStore } from '@/app/components/app/store'
import { useFeatures, useFeaturesStore } from '@/app/components/base/features/hooks' import { useFeatures, useFeaturesStore } from '@/app/components/base/features/hooks'
interface IDebug { type IDebug = {
isAPIKeySet: boolean isAPIKeySet: boolean
onSetting: () => void onSetting: () => void
inputs: Inputs inputs: Inputs

@ -81,26 +81,26 @@ const AgentLogDetail: FC<AgentLogDetailProps> = ({
return ( return (
<div className='grow relative flex flex-col'> <div className='grow relative flex flex-col'>
{/* tab */} {/* tab */}
<div className='shrink-0 flex items-center px-4 border-b-[0.5px] border-[rgba(0,0,0,0.05)]'> <div className='shrink-0 flex items-center px-4 border-b-[0.5px] border-divider-regular'>
<div <div
className={cn( className={cn(
'mr-6 py-3 border-b-2 border-transparent text-[13px] font-semibold leading-[18px] text-gray-400 cursor-pointer', 'mr-6 py-3 border-b-2 border-transparent text-[13px] font-semibold leading-[18px] text-text-tertiary cursor-pointer',
currentTab === 'DETAIL' && '!border-[rgb(21,94,239)] text-gray-700', currentTab === 'DETAIL' && '!border-[rgb(21,94,239)] text-text-secondary',
)} )}
onClick={() => switchTab('DETAIL')} onClick={() => switchTab('DETAIL')}
>{t('runLog.detail')}</div> >{t('runLog.detail')}</div>
<div <div
className={cn( className={cn(
'mr-6 py-3 border-b-2 border-transparent text-[13px] font-semibold leading-[18px] text-gray-400 cursor-pointer', 'mr-6 py-3 border-b-2 border-transparent text-[13px] font-semibold leading-[18px] text-text-tertiary cursor-pointer',
currentTab === 'TRACING' && '!border-[rgb(21,94,239)] text-gray-700', currentTab === 'TRACING' && '!border-[rgb(21,94,239)] text-text-secondary',
)} )}
onClick={() => switchTab('TRACING')} onClick={() => switchTab('TRACING')}
>{t('runLog.tracing')}</div> >{t('runLog.tracing')}</div>
</div> </div>
{/* panel detail */} {/* panel detail */}
<div className={cn('grow bg-white h-0 overflow-y-auto rounded-b-2xl', currentTab !== 'DETAIL' && '!bg-gray-50')}> <div className={cn('grow bg-components-panel-bg h-0 overflow-y-auto rounded-b-2xl', currentTab !== 'DETAIL' && '!bg-background-section')}>
{loading && ( {loading && (
<div className='flex h-full items-center justify-center bg-white'> <div className='flex h-full items-center justify-center bg-components-panel-bg'>
<Loading /> <Loading />
</div> </div>
)} )}

@ -35,7 +35,7 @@ const AgentLogModal: FC<AgentLogModalProps> = ({
return ( return (
<div <div
className={cn('relative flex flex-col py-3 bg-white border-[0.5px] border-gray-200 rounded-xl shadow-xl z-10')} className={cn('relative flex flex-col py-3 bg-components-panel-bg border-[0.5px] border-components-panel-border rounded-xl shadow-xl z-10')}
style={{ style={{
width: 480, width: 480,
position: 'fixed', position: 'fixed',
@ -45,9 +45,9 @@ const AgentLogModal: FC<AgentLogModalProps> = ({
}} }}
ref={ref} ref={ref}
> >
<h1 className='shrink-0 px-4 py-1 text-md font-semibold text-gray-900'>{t('appLog.runDetail.workflowTitle')}</h1> <h1 className='shrink-0 px-4 py-1 text-md font-semibold text-text-primary'>{t('appLog.runDetail.workflowTitle')}</h1>
<span className='absolute right-3 top-4 p-1 cursor-pointer z-20' onClick={onCancel}> <span className='absolute right-3 top-4 p-1 cursor-pointer z-20' onClick={onCancel}>
<RiCloseLine className='w-4 h-4 text-gray-500' /> <RiCloseLine className='w-4 h-4 text-text-tertiary' />
</span> </span>
<AgentLogDetail <AgentLogDetail
conversationID={currentLogItem.conversationId} conversationID={currentLogItem.conversationId}

@ -2,8 +2,9 @@
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import type { FC } from 'react' import type { FC } from 'react'
import ToolCall from './tool-call' import ToolCall from './tool-call'
import cn from '@/utils/classnames' import Divider from '@/app/components/base/divider'
import type { AgentIteration } from '@/models/log' import type { AgentIteration } from '@/models/log'
import cn from '@/utils/classnames'
type Props = { type Props = {
isFinal: boolean isFinal: boolean
@ -18,12 +19,12 @@ const Iteration: FC<Props> = ({ iterationInfo, isFinal, index }) => {
<div className={cn('px-4 py-2')}> <div className={cn('px-4 py-2')}>
<div className='flex items-center'> <div className='flex items-center'>
{isFinal && ( {isFinal && (
<div className='shrink-0 mr-3 text-gray-500 text-xs leading-[18px] font-semibold'>{t('appLog.agentLogDetail.finalProcessing')}</div> <div className='shrink-0 mr-3 text-text-tertiary text-xs leading-[18px] font-semibold'>{t('appLog.agentLogDetail.finalProcessing')}</div>
)} )}
{!isFinal && ( {!isFinal && (
<div className='shrink-0 mr-3 text-gray-500 text-xs leading-[18px] font-semibold'>{`${t('appLog.agentLogDetail.iteration').toUpperCase()} ${index}`}</div> <div className='shrink-0 mr-3 text-text-tertiary text-xs leading-[18px] font-semibold'>{`${t('appLog.agentLogDetail.iteration').toUpperCase()} ${index}`}</div>
)} )}
<div className='grow h-[1px] bg-gradient-to-r from-[#f3f4f6] to-gray-50'></div> <Divider bgStyle='gradient' className='grow h-[1px] mx-0'/>
</div> </div>
<ToolCall <ToolCall
isLLM isLLM

@ -36,7 +36,7 @@ const ResultPanel: FC<ResultPanelProps> = ({
const { formatTime } = useTimestamp() const { formatTime } = useTimestamp()
return ( return (
<div className='bg-white py-2'> <div className='bg-components-panel-bg py-2'>
<div className='px-4 py-2'> <div className='px-4 py-2'>
<StatusPanel <StatusPanel
status='succeeded' status='succeeded'
@ -62,57 +62,57 @@ const ResultPanel: FC<ResultPanelProps> = ({
/> />
</div> </div>
<div className='px-4 py-2'> <div className='px-4 py-2'>
<div className='h-[0.5px] bg-black opacity-5' /> <div className='h-[0.5px] bg-divider-regular opacity-5' />
</div> </div>
<div className='px-4 py-2'> <div className='px-4 py-2'>
<div className='relative'> <div className='relative'>
<div className='h-6 leading-6 text-gray-500 text-xs font-medium'>{t('runLog.meta.title')}</div> <div className='h-6 leading-6 text-text-tertiary text-xs font-medium'>{t('runLog.meta.title')}</div>
<div className='py-1'> <div className='py-1'>
<div className='flex'> <div className='flex'>
<div className='shrink-0 w-[104px] px-2 py-[5px] text-gray-500 text-xs leading-[18px] truncate'>{t('runLog.meta.status')}</div> <div className='shrink-0 w-[104px] px-2 py-[5px] text-text-tertiary text-xs leading-[18px] truncate'>{t('runLog.meta.status')}</div>
<div className='grow px-2 py-[5px] text-gray-900 text-xs leading-[18px]'> <div className='grow px-2 py-[5px] text-text-primary text-xs leading-[18px]'>
<span>SUCCESS</span> <span>SUCCESS</span>
</div> </div>
</div> </div>
<div className='flex'> <div className='flex'>
<div className='shrink-0 w-[104px] px-2 py-[5px] text-gray-500 text-xs leading-[18px] truncate'>{t('runLog.meta.executor')}</div> <div className='shrink-0 w-[104px] px-2 py-[5px] text-text-tertiary text-xs leading-[18px] truncate'>{t('runLog.meta.executor')}</div>
<div className='grow px-2 py-[5px] text-gray-900 text-xs leading-[18px]'> <div className='grow px-2 py-[5px] text-text-primary text-xs leading-[18px]'>
<span>{created_by || 'N/A'}</span> <span>{created_by || 'N/A'}</span>
</div> </div>
</div> </div>
<div className='flex'> <div className='flex'>
<div className='shrink-0 w-[104px] px-2 py-[5px] text-gray-500 text-xs leading-[18px] truncate'>{t('runLog.meta.startTime')}</div> <div className='shrink-0 w-[104px] px-2 py-[5px] text-text-tertiary text-xs leading-[18px] truncate'>{t('runLog.meta.startTime')}</div>
<div className='grow px-2 py-[5px] text-gray-900 text-xs leading-[18px]'> <div className='grow px-2 py-[5px] text-text-primary text-xs leading-[18px]'>
<span>{formatTime(Date.parse(created_at) / 1000, t('appLog.dateTimeFormat') as string)}</span> <span>{formatTime(Date.parse(created_at) / 1000, t('appLog.dateTimeFormat') as string)}</span>
</div> </div>
</div> </div>
<div className='flex'> <div className='flex'>
<div className='shrink-0 w-[104px] px-2 py-[5px] text-gray-500 text-xs leading-[18px] truncate'>{t('runLog.meta.time')}</div> <div className='shrink-0 w-[104px] px-2 py-[5px] text-text-tertiary text-xs leading-[18px] truncate'>{t('runLog.meta.time')}</div>
<div className='grow px-2 py-[5px] text-gray-900 text-xs leading-[18px]'> <div className='grow px-2 py-[5px] text-text-primary text-xs leading-[18px]'>
<span>{`${elapsed_time?.toFixed(3)}s`}</span> <span>{`${elapsed_time?.toFixed(3)}s`}</span>
</div> </div>
</div> </div>
<div className='flex'> <div className='flex'>
<div className='shrink-0 w-[104px] px-2 py-[5px] text-gray-500 text-xs leading-[18px] truncate'>{t('runLog.meta.tokens')}</div> <div className='shrink-0 w-[104px] px-2 py-[5px] text-text-tertiary text-xs leading-[18px] truncate'>{t('runLog.meta.tokens')}</div>
<div className='grow px-2 py-[5px] text-gray-900 text-xs leading-[18px]'> <div className='grow px-2 py-[5px] text-text-primary text-xs leading-[18px]'>
<span>{`${total_tokens || 0} Tokens`}</span> <span>{`${total_tokens || 0} Tokens`}</span>
</div> </div>
</div> </div>
<div className='flex'> <div className='flex'>
<div className='shrink-0 w-[104px] px-2 py-[5px] text-gray-500 text-xs leading-[18px] truncate'>{t('appLog.agentLogDetail.agentMode')}</div> <div className='shrink-0 w-[104px] px-2 py-[5px] text-text-tertiary text-xs leading-[18px] truncate'>{t('appLog.agentLogDetail.agentMode')}</div>
<div className='grow px-2 py-[5px] text-gray-900 text-xs leading-[18px]'> <div className='grow px-2 py-[5px] text-text-primary text-xs leading-[18px]'>
<span>{agentMode === 'function_call' ? t('appDebug.agent.agentModeType.functionCall') : t('appDebug.agent.agentModeType.ReACT')}</span> <span>{agentMode === 'function_call' ? t('appDebug.agent.agentModeType.functionCall') : t('appDebug.agent.agentModeType.ReACT')}</span>
</div> </div>
</div> </div>
<div className='flex'> <div className='flex'>
<div className='shrink-0 w-[104px] px-2 py-[5px] text-gray-500 text-xs leading-[18px] truncate'>{t('appLog.agentLogDetail.toolUsed')}</div> <div className='shrink-0 w-[104px] px-2 py-[5px] text-text-tertiary text-xs leading-[18px] truncate'>{t('appLog.agentLogDetail.toolUsed')}</div>
<div className='grow px-2 py-[5px] text-gray-900 text-xs leading-[18px]'> <div className='grow px-2 py-[5px] text-text-primary text-xs leading-[18px]'>
<span>{tools?.length ? tools?.join(', ') : 'Null'}</span> <span>{tools?.length ? tools?.join(', ') : 'Null'}</span>
</div> </div>
</div> </div>
<div className='flex'> <div className='flex'>
<div className='shrink-0 w-[104px] px-2 py-[5px] text-gray-500 text-xs leading-[18px] truncate'>{t('appLog.agentLogDetail.iterations')}</div> <div className='shrink-0 w-[104px] px-2 py-[5px] text-text-tertiary text-xs leading-[18px] truncate'>{t('appLog.agentLogDetail.iterations')}</div>
<div className='grow px-2 py-[5px] text-gray-900 text-xs leading-[18px]'> <div className='grow px-2 py-[5px] text-text-primary text-xs leading-[18px]'>
<span>{iterations}</span> <span>{iterations}</span>
</div> </div>
</div> </div>

@ -33,7 +33,7 @@ const ToolCallItem: FC<Props> = ({ toolCall, isLLM = false, isFinal, tokens, obs
if (time < 1) if (time < 1)
return `${(time * 1000).toFixed(3)} ms` return `${(time * 1000).toFixed(3)} ms`
if (time > 60) if (time > 60)
return `${parseInt(Math.round(time / 60).toString())} m ${(time % 60).toFixed(3)} s` return `${Number.parseInt(Math.round(time / 60).toString())} m ${(time % 60).toFixed(3)} s`
return `${time.toFixed(3)} s` return `${time.toFixed(3)} s`
} }
@ -41,14 +41,14 @@ const ToolCallItem: FC<Props> = ({ toolCall, isLLM = false, isFinal, tokens, obs
if (tokens < 1000) if (tokens < 1000)
return tokens return tokens
if (tokens >= 1000 && tokens < 1000000) if (tokens >= 1000 && tokens < 1000000)
return `${parseFloat((tokens / 1000).toFixed(3))}K` return `${Number.parseFloat((tokens / 1000).toFixed(3))}K`
if (tokens >= 1000000) if (tokens >= 1000000)
return `${parseFloat((tokens / 1000000).toFixed(3))}M` return `${Number.parseFloat((tokens / 1000000).toFixed(3))}M`
} }
return ( return (
<div className={cn('py-1')}> <div className={cn('py-1')}>
<div className={cn('group transition-all bg-white border border-gray-100 rounded-2xl shadow-xs hover:shadow-md')}> <div className={cn('group transition-all bg-background-default border border-components-panel-border rounded-2xl shadow-xs hover:shadow-md')}>
<div <div
className={cn( className={cn(
'flex items-center py-3 pl-[6px] pr-3 cursor-pointer', 'flex items-center py-3 pl-[6px] pr-3 cursor-pointer',
@ -58,15 +58,15 @@ const ToolCallItem: FC<Props> = ({ toolCall, isLLM = false, isFinal, tokens, obs
> >
<ChevronRight <ChevronRight
className={cn( className={cn(
'shrink-0 w-3 h-3 mr-1 text-gray-400 transition-all group-hover:text-gray-500', 'shrink-0 w-3 h-3 mr-1 text-text-quaternary transition-all group-hover:text-text-tertiary',
!collapseState && 'rotate-90', !collapseState && 'rotate-90',
)} )}
/> />
<BlockIcon className={cn('shrink-0 mr-2')} type={isLLM ? BlockEnum.LLM : BlockEnum.Tool} toolIcon={toolCall.tool_icon} /> <BlockIcon className={cn('shrink-0 mr-2')} type={isLLM ? BlockEnum.LLM : BlockEnum.Tool} toolIcon={toolCall.tool_icon} />
<div className={cn( <div className={cn(
'grow text-gray-700 text-[13px] leading-[16px] font-semibold truncate', 'grow text-text-secondary text-[13px] leading-[16px] font-semibold truncate',
)} title={toolName}>{toolName}</div> )} title={toolName}>{toolName}</div>
<div className='shrink-0 text-gray-500 text-xs leading-[18px]'> <div className='shrink-0 text-text-tertiary text-xs leading-[18px]'>
{toolCall.time_cost && ( {toolCall.time_cost && (
<span>{getTime(toolCall.time_cost || 0)}</span> <span>{getTime(toolCall.time_cost || 0)}</span>
)} )}

@ -9,7 +9,7 @@ type TracingPanelProps = {
const TracingPanel: FC<TracingPanelProps> = ({ list }) => { const TracingPanel: FC<TracingPanelProps> = ({ list }) => {
return ( return (
<div className='bg-gray-50'> <div className='bg-background-section'>
{list.map((iteration, index) => ( {list.map((iteration, index) => (
<Iteration <Iteration
key={index} key={index}

@ -76,7 +76,7 @@ export const CopyFeedbackNew = ({ content, className }: Pick<Props, 'className'
} }
> >
<div <div
className={`w-8 h-8 cursor-pointer hover:bg-gray-100 rounded-lg ${ className={`w-8 h-8 cursor-pointer hover:bg-components-button-ghost-bg-hover rounded-lg ${
className ?? '' className ?? ''
}`} }`}
> >

@ -6,12 +6,14 @@ import { ReactSortable } from 'react-sortablejs'
import { RiAddLine, RiAsterisk, RiCloseLine, RiDeleteBinLine, RiDraggable } from '@remixicon/react' import { RiAddLine, RiAsterisk, RiCloseLine, RiDeleteBinLine, RiDraggable } from '@remixicon/react'
import Modal from '@/app/components/base/modal' import Modal from '@/app/components/base/modal'
import Button from '@/app/components/base/button' import Button from '@/app/components/base/button'
import Divider from '@/app/components/base/divider'
import ConfirmAddVar from '@/app/components/app/configuration/config-prompt/confirm-add-var' import ConfirmAddVar from '@/app/components/app/configuration/config-prompt/confirm-add-var'
import type { OpeningStatement } from '@/app/components/base/features/types' import type { OpeningStatement } from '@/app/components/base/features/types'
import { getInputKeys } from '@/app/components/base/block-input' import { getInputKeys } from '@/app/components/base/block-input'
import type { PromptVariable } from '@/models/debug' import type { PromptVariable } from '@/models/debug'
import type { InputVar } from '@/app/components/workflow/types' import type { InputVar } from '@/app/components/workflow/types'
import { getNewVar } from '@/utils/var' import { getNewVar } from '@/utils/var'
import cn from '@/utils/classnames'
type OpeningSettingModalProps = { type OpeningSettingModalProps = {
data: OpeningStatement data: OpeningStatement
@ -86,16 +88,19 @@ const OpeningSettingModal = ({
handleSave(true) handleSave(true)
}, [handleSave, hideConfirmAddVar, notIncludeKeys, onAutoAddPromptVariable]) }, [handleSave, hideConfirmAddVar, notIncludeKeys, onAutoAddPromptVariable])
const [focusID, setFocusID] = useState<number | null>(null)
const [deletingID, setDeletingID] = useState<number | null>(null)
const renderQuestions = () => { const renderQuestions = () => {
return ( return (
<div> <div>
<div className='flex items-center py-2'> <div className='flex items-center py-2'>
<div className='shrink-0 flex space-x-0.5 leading-[18px] text-xs font-medium text-gray-500'> <div className='shrink-0 flex space-x-0.5 leading-[18px] text-xs font-medium text-text-tertiary'>
<div className='uppercase'>{t('appDebug.openingStatement.openingQuestion')}</div> <div className='uppercase'>{t('appDebug.openingStatement.openingQuestion')}</div>
<div>·</div> <div>·</div>
<div>{tempSuggestedQuestions.length}/{MAX_QUESTION_NUM}</div> <div>{tempSuggestedQuestions.length}/{MAX_QUESTION_NUM}</div>
</div> </div>
<div className='ml-3 grow w-0 h-px bg-[#243, 244, 246]'></div> <Divider bgStyle='gradient' className='ml-3 grow w-0 h-px'/>
</div> </div>
<ReactSortable <ReactSortable
className="space-y-1" className="space-y-1"
@ -112,8 +117,15 @@ const OpeningSettingModal = ({
> >
{tempSuggestedQuestions.map((question, index) => { {tempSuggestedQuestions.map((question, index) => {
return ( return (
<div className='group relative rounded-lg border border-gray-200 flex items-center pl-2.5 hover:border-gray-300 hover:bg-white' key={index}> <div
<RiDraggable className='handle w-4 h-4 cursor-grab' /> className={cn(
'group relative rounded-lg border border-components-panel-border-subtle bg-components-panel-on-panel-item-bg flex items-center pl-2.5 hover:bg-components-panel-on-panel-item-bg-hover',
focusID === index && 'border-components-input-border-active hover:border-components-input-border-active bg-components-input-bg-active hover:bg-components-input-bg-active',
deletingID === index && 'border-components-input-border-destructive hover:border-components-input-border-destructive bg-state-destructive-hover hover:bg-state-destructive-hover',
)}
key={index}
>
<RiDraggable className='handle w-4 h-4 text-text-quaternary cursor-grab' />
<input <input
type="input" type="input"
value={question || ''} value={question || ''}
@ -126,14 +138,18 @@ const OpeningSettingModal = ({
return item return item
})) }))
}} }}
className={'w-full overflow-x-auto pl-1.5 pr-8 text-sm leading-9 text-gray-900 border-0 grow h-9 bg-transparent focus:outline-none cursor-pointer rounded-lg'} className={'w-full overflow-x-auto pl-1.5 pr-8 text-sm leading-9 text-text-secondary border-0 grow h-9 bg-transparent focus:outline-none cursor-pointer rounded-lg'}
onFocus={() => setFocusID(index)}
onBlur={() => setFocusID(null)}
/> />
<div <div
className='block absolute top-1/2 translate-y-[-50%] right-1.5 p-1 rounded-md cursor-pointer hover:bg-[#FEE4E2] hover:text-[#D92D20]' className='block absolute top-1/2 translate-y-[-50%] right-1.5 p-1 rounded-md cursor-pointer text-text-tertiary hover:bg-state-destructive-hover hover:text-text-destructive'
onClick={() => { onClick={() => {
setTempSuggestedQuestions(tempSuggestedQuestions.filter((_, i) => index !== i)) setTempSuggestedQuestions(tempSuggestedQuestions.filter((_, i) => index !== i))
}} }}
onMouseEnter={() => setDeletingID(index)}
onMouseLeave={() => setDeletingID(null)}
> >
<RiDeleteBinLine className='w-3.5 h-3.5' /> <RiDeleteBinLine className='w-3.5 h-3.5' />
</div> </div>
@ -143,9 +159,9 @@ const OpeningSettingModal = ({
{tempSuggestedQuestions.length < MAX_QUESTION_NUM && ( {tempSuggestedQuestions.length < MAX_QUESTION_NUM && (
<div <div
onClick={() => { setTempSuggestedQuestions([...tempSuggestedQuestions, '']) }} onClick={() => { setTempSuggestedQuestions([...tempSuggestedQuestions, '']) }}
className='mt-1 flex items-center h-9 px-3 gap-2 rounded-lg cursor-pointer text-gray-400 bg-gray-100 hover:bg-gray-200'> className='mt-1 flex items-center h-9 px-3 gap-2 rounded-lg cursor-pointer text-components-button-tertiary-text bg-components-button-tertiary-bg hover:bg-components-button-tertiary-bg-hover'>
<RiAddLine className='w-4 h-4' /> <RiAddLine className='w-4 h-4' />
<div className='text-gray-500 text-[13px]'>{t('appDebug.variableConfig.addOption')}</div> <div className='system-sm-medium text-[13px]'>{t('appDebug.variableConfig.addOption')}</div>
</div> </div>
)} )}
</div> </div>

@ -30,14 +30,14 @@ const FormGeneration: FC<FormGenerationProps> = ({
key={index} key={index}
className='py-2' className='py-2'
> >
<div className='flex items-center h-9 text-sm font-medium text-gray-900'> <div className='flex items-center h-9 text-sm font-medium text-text-primary'>
{locale === 'zh-Hans' ? form.label['zh-Hans'] : form.label['en-US']} {locale === 'zh-Hans' ? form.label['zh-Hans'] : form.label['en-US']}
</div> </div>
{ {
form.type === 'text-input' && ( form.type === 'text-input' && (
<input <input
value={value?.[form.variable] || ''} value={value?.[form.variable] || ''}
className='block px-3 w-full h-9 bg-gray-100 rounded-lg text-sm text-gray-900 outline-none appearance-none' className='block px-3 w-full h-9 bg-components-input-bg-normal rounded-lg text-sm text-text-primary outline-none appearance-none'
placeholder={form.placeholder} placeholder={form.placeholder}
onChange={e => handleFormChange(form.variable, e.target.value)} onChange={e => handleFormChange(form.variable, e.target.value)}
/> />

@ -27,13 +27,13 @@ const ModerationContent: FC<ModerationContentProps> = ({
return ( return (
<div className='py-2'> <div className='py-2'>
<div className='rounded-lg bg-gray-50 border border-gray-200'> <div className='rounded-lg bg-components-panel-bg border border-components-panel-border'>
<div className='flex items-center justify-between px-3 h-10 rounded-lg'> <div className='flex items-center justify-between px-3 h-10 rounded-lg'>
<div className='shrink-0 text-sm font-medium text-gray-900'>{title}</div> <div className='shrink-0 text-sm font-medium text-text-primary'>{title}</div>
<div className='grow flex items-center justify-end'> <div className='grow flex items-center justify-end'>
{ {
info && ( info && (
<div className='mr-2 text-xs text-gray-500 truncate' title={info}>{info}</div> <div className='mr-2 text-xs text-text-tertiary truncate' title={info}>{info}</div>
) )
} }
<Switch <Switch
@ -45,20 +45,20 @@ const ModerationContent: FC<ModerationContentProps> = ({
</div> </div>
{ {
config.enabled && showPreset && ( config.enabled && showPreset && (
<div className='px-3 pt-1 pb-3 bg-white rounded-lg'> <div className='px-3 pt-1 pb-3 bg-components-panel-bg rounded-lg'>
<div className='flex items-center justify-between h-8 text-[13px] font-medium text-gray-700'> <div className='flex items-center justify-between h-8 text-[13px] font-medium text-text-secondary'>
{t('appDebug.feature.moderation.modal.content.preset')} {t('appDebug.feature.moderation.modal.content.preset')}
<span className='text-xs font-normal text-gray-500'>{t('appDebug.feature.moderation.modal.content.supportMarkdown')}</span> <span className='text-xs font-normal text-text-tertiary'>{t('appDebug.feature.moderation.modal.content.supportMarkdown')}</span>
</div> </div>
<div className='relative px-3 py-2 h-20 rounded-lg bg-gray-100'> <div className='relative px-3 py-2 h-20 rounded-lg bg-components-input-bg-normal'>
<textarea <textarea
value={config.preset_response || ''} value={config.preset_response || ''}
className='block w-full h-full bg-transparent text-sm outline-none appearance-none resize-none' className='block w-full h-full bg-transparent text-sm text-text-secondary outline-none appearance-none resize-none'
placeholder={t('appDebug.feature.moderation.modal.content.placeholder') || ''} placeholder={t('appDebug.feature.moderation.modal.content.placeholder') || ''}
onChange={e => handleConfigChange('preset_response', e.target.value)} onChange={e => handleConfigChange('preset_response', e.target.value)}
/> />
<div className='absolute bottom-2 right-2 flex items-center px-1 h-5 rounded-md bg-gray-50 text-xs font-medium text-gray-300'> <div className='absolute bottom-2 right-2 flex items-center px-1 h-5 rounded-md bg-background-section text-xs font-medium text-text-quaternary'>
<span>{(config.preset_response || '').length}</span>/<span className='text-gray-500'>100</span> <span>{(config.preset_response || '').length}</span>/<span className='text-text-tertiary'>100</span>
</div> </div>
</div> </div>
</div> </div>

@ -9,6 +9,7 @@ import FormGeneration from './form-generation'
import ApiBasedExtensionSelector from '@/app/components/header/account-setting/api-based-extension-page/selector' import ApiBasedExtensionSelector from '@/app/components/header/account-setting/api-based-extension-page/selector'
import Modal from '@/app/components/base/modal' import Modal from '@/app/components/base/modal'
import Button from '@/app/components/base/button' import Button from '@/app/components/base/button'
import Divider from '@/app/components/base/divider'
import { BookOpen01 } from '@/app/components/base/icons/src/vender/line/education' import { BookOpen01 } from '@/app/components/base/icons/src/vender/line/education'
import type { ModerationConfig, ModerationContentConfig } from '@/models/debug' import type { ModerationConfig, ModerationContentConfig } from '@/models/debug'
import { useToastContext } from '@/app/components/base/toast' import { useToastContext } from '@/app/components/base/toast'
@ -22,6 +23,7 @@ import { LanguagesSupported } from '@/i18n/language'
import { InfoCircle } from '@/app/components/base/icons/src/vender/line/general' import { InfoCircle } from '@/app/components/base/icons/src/vender/line/general'
import { useModalContext } from '@/context/modal-context' import { useModalContext } from '@/context/modal-context'
import { CustomConfigurationStatusEnum } from '@/app/components/header/account-setting/model-provider-page/declarations' import { CustomConfigurationStatusEnum } from '@/app/components/header/account-setting/model-provider-page/declarations'
import cn from '@/utils/classnames'
const systemTypes = ['openai_moderation', 'keywords', 'api'] const systemTypes = ['openai_moderation', 'keywords', 'api']
@ -245,7 +247,7 @@ const ModerationSettingModal: FC<ModerationSettingModalProps> = ({
<div className='p-1 cursor-pointer' onClick={onCancel}><RiCloseLine className='w-4 h-4 text-text-tertiary'/></div> <div className='p-1 cursor-pointer' onClick={onCancel}><RiCloseLine className='w-4 h-4 text-text-tertiary'/></div>
</div> </div>
<div className='py-2'> <div className='py-2'>
<div className='leading-9 text-sm font-medium text-gray-900'> <div className='leading-9 text-sm font-medium text-text-primary'>
{t('appDebug.feature.moderation.modal.provider.title')} {t('appDebug.feature.moderation.modal.provider.title')}
</div> </div>
<div className='grid gap-2.5 grid-cols-3'> <div className='grid gap-2.5 grid-cols-3'>
@ -253,16 +255,18 @@ const ModerationSettingModal: FC<ModerationSettingModalProps> = ({
providers.map(provider => ( providers.map(provider => (
<div <div
key={provider.key} key={provider.key}
className={` className={cn(
flex items-center px-3 py-2 rounded-lg text-sm text-gray-900 cursor-pointer 'flex items-center px-2 h-8 rounded-md system-sm-regular bg-components-option-card-option-bg border border-components-option-card-option-border text-text-secondary cursor-default',
${localeData.type === provider.key ? 'bg-white border-[1.5px] border-primary-400 shadow-sm' : 'border border-gray-100 bg-gray-25'} localeData.type !== provider.key && 'hover:bg-components-option-card-option-bg-hover hover:border-components-option-card-option-border-hover hover:shadow-xs cursor-pointer',
${localeData.type === 'openai_moderation' && provider.key === 'openai_moderation' && !isOpenAIProviderConfigured && 'opacity-50'} localeData.type === provider.key && 'bg-components-option-card-option-selected-bg border-[1.5px] border-components-option-card-option-selected-border system-sm-medium shadow-xs',
`} localeData.type === 'openai_moderation' && provider.key === 'openai_moderation' && !isOpenAIProviderConfigured && 'text-text-disabled',
)}
onClick={() => handleDataTypeChange(provider.key)} onClick={() => handleDataTypeChange(provider.key)}
> >
<div className={` <div className={cn(
mr-2 w-4 h-4 rounded-full border 'mr-2 w-4 h-4 border border-components-radio-border bg-components-radio-bg shadow-xs rounded-full',
${localeData.type === provider.key ? 'border-[5px] border-primary-600' : 'border border-gray-300'}`} /> localeData.type === provider.key && 'border-[5px] border-components-radio-border-checked',
)}></div>
{provider.name} {provider.name}
</div> </div>
)) ))
@ -289,17 +293,17 @@ const ModerationSettingModal: FC<ModerationSettingModalProps> = ({
{ {
localeData.type === 'keywords' && ( localeData.type === 'keywords' && (
<div className='py-2'> <div className='py-2'>
<div className='mb-1 text-sm font-medium text-gray-900'>{t('appDebug.feature.moderation.modal.provider.keywords')}</div> <div className='mb-1 text-sm font-medium text-text-primary'>{t('appDebug.feature.moderation.modal.provider.keywords')}</div>
<div className='mb-2 text-xs text-gray-500'>{t('appDebug.feature.moderation.modal.keywords.tip')}</div> <div className='mb-2 text-xs text-text-tertiary'>{t('appDebug.feature.moderation.modal.keywords.tip')}</div>
<div className='relative px-3 py-2 h-[88px] bg-gray-100 rounded-lg'> <div className='relative px-3 py-2 h-[88px] bg-components-input-bg-normal rounded-lg'>
<textarea <textarea
value={localeData.config?.keywords || ''} value={localeData.config?.keywords || ''}
onChange={handleDataKeywordsChange} onChange={handleDataKeywordsChange}
className='block w-full h-full bg-transparent text-sm outline-none appearance-none resize-none' className='block w-full h-full bg-transparent text-sm text-text-secondary outline-none appearance-none resize-none'
placeholder={t('appDebug.feature.moderation.modal.keywords.placeholder') || ''} placeholder={t('appDebug.feature.moderation.modal.keywords.placeholder') || ''}
/> />
<div className='absolute bottom-2 right-2 flex items-center px-1 h-5 rounded-md bg-gray-50 text-xs font-medium text-gray-300'> <div className='absolute bottom-2 right-2 flex items-center px-1 h-5 rounded-md bg-background-section text-xs font-medium text-text-quaternary'>
<span>{(localeData.config?.keywords || '').split('\n').filter(Boolean).length}</span>/<span className='text-gray-500'>100 {t('appDebug.feature.moderation.modal.keywords.line')}</span> <span>{(localeData.config?.keywords || '').split('\n').filter(Boolean).length}</span>/<span className='text-text-tertiary'>100 {t('appDebug.feature.moderation.modal.keywords.line')}</span>
</div> </div>
</div> </div>
</div> </div>
@ -309,13 +313,13 @@ const ModerationSettingModal: FC<ModerationSettingModalProps> = ({
localeData.type === 'api' && ( localeData.type === 'api' && (
<div className='py-2'> <div className='py-2'>
<div className='flex items-center justify-between h-9'> <div className='flex items-center justify-between h-9'>
<div className='text-sm font-medium text-gray-900'>{t('common.apiBasedExtension.selector.title')}</div> <div className='text-sm font-medium text-text-primary'>{t('common.apiBasedExtension.selector.title')}</div>
<a <a
href={t('common.apiBasedExtension.linkUrl') || '/'} href={t('common.apiBasedExtension.linkUrl') || '/'}
target='_blank' rel='noopener noreferrer' target='_blank' rel='noopener noreferrer'
className='group flex items-center text-xs text-gray-500 hover:text-primary-600' className='group flex items-center text-xs text-text-tertiary hover:text-primary-600'
> >
<BookOpen01 className='mr-1 w-3 h-3 text-gray-500 group-hover:text-primary-600' /> <BookOpen01 className='mr-1 w-3 h-3 text-text-tertiary group-hover:text-primary-600' />
{t('common.apiBasedExtension.link')} {t('common.apiBasedExtension.link')}
</a> </a>
</div> </div>
@ -337,7 +341,7 @@ const ModerationSettingModal: FC<ModerationSettingModalProps> = ({
/> />
) )
} }
<div className='my-3 h-[1px] bg-gradient-to-r from-[#F3F4F6]'></div> <Divider bgStyle='gradient' className='my-3 h-px' />
<ModerationContent <ModerationContent
title={t('appDebug.feature.moderation.modal.content.input') || ''} title={t('appDebug.feature.moderation.modal.content.input') || ''}
config={localeData.config?.inputs_config || { enabled: false, preset_response: '' }} config={localeData.config?.inputs_config || { enabled: false, preset_response: '' }}
@ -352,7 +356,7 @@ const ModerationSettingModal: FC<ModerationSettingModalProps> = ({
info={(localeData.type === 'api' && t('appDebug.feature.moderation.modal.content.fromApi')) || ''} info={(localeData.type === 'api' && t('appDebug.feature.moderation.modal.content.fromApi')) || ''}
showPreset={!(localeData.type === 'api')} showPreset={!(localeData.type === 'api')}
/> />
<div className='mt-1 mb-8 text-xs font-medium text-gray-500'>{t('appDebug.feature.moderation.modal.content.condition')}</div> <div className='mt-1 mb-8 text-xs font-medium text-text-tertiary'>{t('appDebug.feature.moderation.modal.content.condition')}</div>
<div className='flex items-center justify-end'> <div className='flex items-center justify-end'>
<Button <Button
onClick={onCancel} onClick={onCancel}

@ -93,13 +93,13 @@ const VoiceParamConfig = ({
> >
<div className='relative h-8'> <div className='relative h-8'>
<Listbox.Button <Listbox.Button
className={'w-full h-full rounded-lg border-0 bg-gray-100 py-1.5 pl-3 pr-10 sm:text-sm sm:leading-6 focus-visible:outline-none focus-visible:bg-gray-200 group-hover:bg-gray-200 cursor-pointer'}> className={'w-full h-full rounded-lg border-0 bg-components-input-bg-normal py-1.5 pl-3 pr-10 sm:text-sm sm:leading-6 focus-visible:outline-none focus-visible:bg-state-base-hover group-hover:bg-state-base-hover cursor-pointer'}>
<span className={classNames('block truncate text-left', !languageItem?.name && 'text-gray-400')}> <span className={classNames('block truncate text-left text-text-secondary', !languageItem?.name && 'text-text-tertiary')}>
{languageItem?.name ? t(`common.voice.language.${languageItem?.value.replace('-', '')}`) : localLanguagePlaceholder} {languageItem?.name ? t(`common.voice.language.${languageItem?.value.replace('-', '')}`) : localLanguagePlaceholder}
</span> </span>
<span className="pointer-events-none absolute inset-y-0 right-0 flex items-center pr-2"> <span className="pointer-events-none absolute inset-y-0 right-0 flex items-center pr-2">
<ChevronDownIcon <ChevronDownIcon
className="h-5 w-5 text-gray-400" className="h-4 w-4 text-text-tertiary"
aria-hidden="true" aria-hidden="true"
/> />
</span> </span>
@ -112,12 +112,12 @@ const VoiceParamConfig = ({
> >
<Listbox.Options <Listbox.Options
className="absolute z-10 mt-1 px-1 max-h-60 w-full overflow-auto rounded-md bg-white py-1 text-base shadow-lg border-gray-200 border-[0.5px] focus:outline-none sm:text-sm"> className="absolute z-10 mt-1 px-1 max-h-60 w-full overflow-auto rounded-md bg-components-panel-bg py-1 text-base shadow-lg border-components-panel-border border-[0.5px] focus:outline-none sm:text-sm">
{languages.map((item: Item) => ( {languages.map((item: Item) => (
<Listbox.Option <Listbox.Option
key={item.value} key={item.value}
className={({ active }) => className={({ active }) =>
`relative cursor-pointer select-none py-2 pl-3 pr-9 rounded-lg hover:bg-gray-100 text-gray-700 ${active ? 'bg-gray-100' : '' `relative cursor-pointer select-none py-2 pl-3 pr-9 rounded-lg hover:bg-state-base-hover text-text-secondary ${active ? 'bg-state-base-active' : ''
}` }`
} }
value={item} value={item}
@ -130,10 +130,10 @@ const VoiceParamConfig = ({
{(selected || item.value === text2speech?.language) && ( {(selected || item.value === text2speech?.language) && (
<span <span
className={classNames( className={classNames(
'absolute inset-y-0 right-0 flex items-center pr-4 text-gray-700', 'absolute inset-y-0 right-0 flex items-center pr-4 text-text-secondary',
)} )}
> >
<CheckIcon className="h-5 w-5" aria-hidden="true"/> <CheckIcon className="h-4 w-4" aria-hidden="true"/>
</span> </span>
)} )}
</> </>
@ -161,12 +161,12 @@ const VoiceParamConfig = ({
> >
<div className={'grow relative h-8'}> <div className={'grow relative h-8'}>
<Listbox.Button <Listbox.Button
className={'w-full h-full rounded-lg border-0 bg-gray-100 py-1.5 pl-3 pr-10 sm:text-sm sm:leading-6 focus-visible:outline-none focus-visible:bg-gray-200 group-hover:bg-gray-200 cursor-pointer'}> className={'w-full h-full rounded-lg border-0 bg-components-input-bg-normal py-1.5 pl-3 pr-10 sm:text-sm sm:leading-6 focus-visible:outline-none focus-visible:bg-state-base-hover group-hover:bg-state-base-hover cursor-pointer'}>
<span <span
className={classNames('block truncate text-left', !voiceItem?.name && 'text-gray-400')}>{voiceItem?.name ?? localVoicePlaceholder}</span> className={classNames('block truncate text-left text-text-secondary', !voiceItem?.name && 'text-text-tertiary')}>{voiceItem?.name ?? localVoicePlaceholder}</span>
<span className="pointer-events-none absolute inset-y-0 right-0 flex items-center pr-2"> <span className="pointer-events-none absolute inset-y-0 right-0 flex items-center pr-2">
<ChevronDownIcon <ChevronDownIcon
className="h-5 w-5 text-gray-400" className="h-4 w-4 text-text-tertiary"
aria-hidden="true" aria-hidden="true"
/> />
</span> </span>
@ -179,12 +179,12 @@ const VoiceParamConfig = ({
> >
<Listbox.Options <Listbox.Options
className="absolute z-10 mt-1 px-1 max-h-60 w-full overflow-auto rounded-md bg-white py-1 text-base shadow-lg border-gray-200 border-[0.5px] focus:outline-none sm:text-sm"> className="absolute z-10 mt-1 px-1 max-h-60 w-full overflow-auto rounded-md bg-components-panel-bg py-1 text-base shadow-lg border-components-panel-border border-[0.5px] focus:outline-none sm:text-sm">
{voiceItems?.map((item: Item) => ( {voiceItems?.map((item: Item) => (
<Listbox.Option <Listbox.Option
key={item.value} key={item.value}
className={({ active }) => className={({ active }) =>
`relative cursor-pointer select-none py-2 pl-3 pr-9 rounded-lg hover:bg-gray-100 text-gray-700 ${active ? 'bg-gray-100' : '' `relative cursor-pointer select-none py-2 pl-3 pr-9 rounded-lg hover:bg-state-base-hover text-text-secondary ${active ? 'bg-state-base-active' : ''
}` }`
} }
value={item} value={item}
@ -196,10 +196,10 @@ const VoiceParamConfig = ({
{(selected || item.value === text2speech?.voice) && ( {(selected || item.value === text2speech?.voice) && (
<span <span
className={classNames( className={classNames(
'absolute inset-y-0 right-0 flex items-center pr-4 text-gray-700', 'absolute inset-y-0 right-0 flex items-center pr-4 text-text-secondary',
)} )}
> >
<CheckIcon className="h-5 w-5" aria-hidden="true"/> <CheckIcon className="h-4 w-4" aria-hidden="true"/>
</span> </span>
)} )}
</> </>

@ -12,7 +12,7 @@ const Card: FC<CardProps> = ({
{ {
log.length === 1 && ( log.length === 1 && (
<div className='px-4 py-2'> <div className='px-4 py-2'>
<div className='whitespace-pre-line text-gray-700'> <div className='whitespace-pre-line text-text-secondary'>
{log[0].text} {log[0].text}
</div> </div>
</div> </div>
@ -23,12 +23,12 @@ const Card: FC<CardProps> = ({
<div> <div>
{ {
log.map((item, index) => ( log.map((item, index) => (
<div key={index} className='group/card mb-2 px-4 pt-2 pb-4 rounded-xl hover:bg-gray-50 last-of-type:mb-0'> <div key={index} className='group/card mb-2 px-4 pt-2 pb-4 rounded-xl hover:bg-state-base-hover last-of-type:mb-0'>
<div className='flex justify-between items-center h-8'> <div className='flex justify-between items-center h-8'>
<div className='font-semibold text-[#2D31A6]'>{item.role.toUpperCase()}</div> <div className='font-semibold text-[#2D31A6]'>{item.role.toUpperCase()}</div>
<CopyFeedbackNew className='hidden w-6 h-6 group-hover/card:block' content={item.text} /> <CopyFeedbackNew className='hidden w-6 h-6 group-hover/card:block' content={item.text} />
</div> </div>
<div className='whitespace-pre-line text-gray-700'>{item.text}</div> <div className='whitespace-pre-line text-text-secondary'>{item.text}</div>
</div> </div>
)) ))
} }

@ -33,7 +33,7 @@ const PromptLogModal: FC<PromptLogModalProps> = ({
return ( return (
<div <div
className='relative flex flex-col bg-white border-[0.5px] border-gray-200 rounded-xl shadow-xl z-10' className='relative flex flex-col bg-components-panel-bg border-[0.5px] border-components-panel-border rounded-xl shadow-xl z-10'
style={{ style={{
width: 480, width: 480,
position: 'fixed', position: 'fixed',
@ -43,14 +43,14 @@ const PromptLogModal: FC<PromptLogModalProps> = ({
}} }}
ref={ref} ref={ref}
> >
<div className='shrink-0 flex justify-between items-center pl-6 pr-5 h-14 border-b border-b-gray-100'> <div className='shrink-0 flex justify-between items-center pl-6 pr-5 h-14 border-b border-divider-regular'>
<div className='text-base font-semibold text-gray-900'>PROMPT LOG</div> <div className='text-base font-semibold text-text-primary'>PROMPT LOG</div>
<div className='flex items-center'> <div className='flex items-center'>
{ {
currentLogItem.log?.length === 1 && ( currentLogItem.log?.length === 1 && (
<> <>
<CopyFeedbackNew className='w-6 h-6' content={currentLogItem.log[0].text} /> <CopyFeedbackNew className='w-6 h-6' content={currentLogItem.log[0].text} />
<div className='mx-2.5 w-[1px] h-[14px] bg-gray-200' /> <div className='mx-2.5 w-[1px] h-[14px] bg-divider-regular' />
</> </>
) )
} }
@ -58,7 +58,7 @@ const PromptLogModal: FC<PromptLogModalProps> = ({
onClick={onCancel} onClick={onCancel}
className='flex justify-center items-center w-6 h-6 cursor-pointer' className='flex justify-center items-center w-6 h-6 cursor-pointer'
> >
<RiCloseLine className='w-4 h-4 text-gray-500' /> <RiCloseLine className='w-4 h-4 text-text-tertiary' />
</div> </div>
</div> </div>
</div> </div>

@ -77,7 +77,7 @@ const ApiBasedExtensionModal: FC<ApiBasedExtensionModalProps> = ({
onClose={() => { }} onClose={() => { }}
className='!p-8 !pb-6 !max-w-none !w-[640px]' className='!p-8 !pb-6 !max-w-none !w-[640px]'
> >
<div className='mb-2 text-xl font-semibold text-gray-900'> <div className='mb-2 text-xl font-semibold text-text-primary'>
{ {
data.name data.name
? t('common.apiBasedExtension.modal.editTitle') ? t('common.apiBasedExtension.modal.editTitle')
@ -85,44 +85,44 @@ const ApiBasedExtensionModal: FC<ApiBasedExtensionModalProps> = ({
} }
</div> </div>
<div className='py-2'> <div className='py-2'>
<div className='leading-9 text-sm font-medium text-gray-900'> <div className='leading-9 text-sm font-medium text-text-primary'>
{t('common.apiBasedExtension.modal.name.title')} {t('common.apiBasedExtension.modal.name.title')}
</div> </div>
<input <input
value={localeData.name || ''} value={localeData.name || ''}
onChange={e => handleDataChange('name', e.target.value)} onChange={e => handleDataChange('name', e.target.value)}
className='block px-3 w-full h-9 bg-gray-100 rounded-lg text-sm text-gray-900 outline-none appearance-none' className='block px-3 w-full h-9 bg-components-input-bg-normal rounded-lg text-sm text-text-primary outline-none appearance-none'
placeholder={t('common.apiBasedExtension.modal.name.placeholder') || ''} placeholder={t('common.apiBasedExtension.modal.name.placeholder') || ''}
/> />
</div> </div>
<div className='py-2'> <div className='py-2'>
<div className='flex justify-between items-center h-9 text-sm font-medium text-gray-900'> <div className='flex justify-between items-center h-9 text-sm font-medium text-text-primary'>
{t('common.apiBasedExtension.modal.apiEndpoint.title')} {t('common.apiBasedExtension.modal.apiEndpoint.title')}
<a <a
href={t('common.apiBasedExtension.linkUrl') || '/'} href={t('common.apiBasedExtension.linkUrl') || '/'}
target='_blank' rel='noopener noreferrer' target='_blank' rel='noopener noreferrer'
className='group flex items-center text-xs text-gray-500 font-normal hover:text-primary-600' className='group flex items-center text-xs text-text-tertiary font-normal hover:text-text-accent'
> >
<BookOpen01 className='mr-1 w-3 h-3 text-gray-500 group-hover:text-primary-600' /> <BookOpen01 className='mr-1 w-3 h-3 text-text-tertiary group-hover:text-text-accent' />
{t('common.apiBasedExtension.link')} {t('common.apiBasedExtension.link')}
</a> </a>
</div> </div>
<input <input
value={localeData.api_endpoint || ''} value={localeData.api_endpoint || ''}
onChange={e => handleDataChange('api_endpoint', e.target.value)} onChange={e => handleDataChange('api_endpoint', e.target.value)}
className='block px-3 w-full h-9 bg-gray-100 rounded-lg text-sm text-gray-900 outline-none appearance-none' className='block px-3 w-full h-9 bg-components-input-bg-normal rounded-lg text-sm text-text-primary outline-none appearance-none'
placeholder={t('common.apiBasedExtension.modal.apiEndpoint.placeholder') || ''} placeholder={t('common.apiBasedExtension.modal.apiEndpoint.placeholder') || ''}
/> />
</div> </div>
<div className='py-2'> <div className='py-2'>
<div className='leading-9 text-sm font-medium text-gray-900'> <div className='leading-9 text-sm font-medium text-text-primary'>
{t('common.apiBasedExtension.modal.apiKey.title')} {t('common.apiBasedExtension.modal.apiKey.title')}
</div> </div>
<div className='flex items-center'> <div className='flex items-center'>
<input <input
value={localeData.api_key || ''} value={localeData.api_key || ''}
onChange={e => handleDataChange('api_key', e.target.value)} onChange={e => handleDataChange('api_key', e.target.value)}
className='block grow mr-2 px-3 h-9 bg-gray-100 rounded-lg text-sm text-gray-900 outline-none appearance-none' className='block grow mr-2 px-3 h-9 bg-components-input-bg-normal rounded-lg text-sm text-text-primary outline-none appearance-none'
placeholder={t('common.apiBasedExtension.modal.apiKey.placeholder') || ''} placeholder={t('common.apiBasedExtension.modal.apiKey.placeholder') || ''}
/> />
</div> </div>

@ -54,33 +54,33 @@ const ApiBasedExtensionSelector: FC<ApiBasedExtensionSelectorProps> = ({
{ {
currentItem currentItem
? ( ? (
<div className='flex items-center justify-between pl-3 pr-2.5 h-9 bg-gray-100 rounded-lg cursor-pointer'> <div className='flex items-center justify-between pl-3 pr-2.5 h-9 bg-components-input-bg-normal rounded-lg cursor-pointer'>
<div className='text-sm text-gray-900'>{currentItem.name}</div> <div className='text-sm text-text-primary'>{currentItem.name}</div>
<div className='flex items-center'> <div className='flex items-center'>
<div className='mr-1.5 w-[270px] text-xs text-gray-400 truncate text-right'> <div className='mr-1.5 w-[270px] text-xs text-text-quaternary truncate text-right'>
{currentItem.api_endpoint} {currentItem.api_endpoint}
</div> </div>
<RiArrowDownSLine className={`w-4 h-4 text-gray-700 ${!open && 'opacity-60'}`} /> <RiArrowDownSLine className={`w-4 h-4 text-text-secondary ${!open && 'opacity-60'}`} />
</div> </div>
</div> </div>
) )
: ( : (
<div className='flex items-center justify-between pl-3 pr-2.5 h-9 bg-gray-100 rounded-lg text-sm text-gray-400 cursor-pointer'> <div className='flex items-center justify-between pl-3 pr-2.5 h-9 bg-components-input-bg-normal rounded-lg text-sm text-text-quaternary cursor-pointer'>
{t('common.apiBasedExtension.selector.placeholder')} {t('common.apiBasedExtension.selector.placeholder')}
<RiArrowDownSLine className={`w-4 h-4 text-gray-700 ${!open && 'opacity-60'}`} /> <RiArrowDownSLine className={`w-4 h-4 text-text-secondary ${!open && 'opacity-60'}`} />
</div> </div>
) )
} }
</PortalToFollowElemTrigger> </PortalToFollowElemTrigger>
<PortalToFollowElemContent className='w-[calc(100%-32px)] max-w-[576px] z-[102]'> <PortalToFollowElemContent className='w-[calc(100%-32px)] max-w-[576px] z-[102]'>
<div className='w-full rounded-lg border-[0.5px] border-gray-200 bg-white shadow-lg z-10'> <div className='w-full rounded-lg border-[0.5px] border-components-panel-border bg-components-panel-bg shadow-lg z-10'>
<div className='p-1'> <div className='p-1'>
<div className='flex items-center justify-between px-3 pt-2 pb-1'> <div className='flex items-center justify-between px-3 pt-2 pb-1'>
<div className='text-xs font-medium text-gray-500'> <div className='text-xs font-medium text-text-tertiary'>
{t('common.apiBasedExtension.selector.title')} {t('common.apiBasedExtension.selector.title')}
</div> </div>
<div <div
className='flex items-center text-xs text-primary-600 cursor-pointer' className='flex items-center text-xs text-text-accent cursor-pointer'
onClick={() => { onClick={() => {
setOpen(false) setOpen(false)
setShowAccountSettingModal({ payload: 'api-based-extension' }) setShowAccountSettingModal({ payload: 'api-based-extension' })
@ -95,20 +95,20 @@ const ApiBasedExtensionSelector: FC<ApiBasedExtensionSelectorProps> = ({
data?.map(item => ( data?.map(item => (
<div <div
key={item.id} key={item.id}
className='px-3 py-1.5 w-full cursor-pointer hover:bg-gray-50 rounded-md text-left' className='px-3 py-1.5 w-full cursor-pointer hover:stroke-state-base-hover rounded-md text-left'
onClick={() => handleSelect(item.id!)} onClick={() => handleSelect(item.id!)}
> >
<div className='text-sm text-gray-900'>{item.name}</div> <div className='text-sm text-text-primary'>{item.name}</div>
<div className='text-xs text-gray-500'>{item.api_endpoint}</div> <div className='text-xs text-text-tertiary'>{item.api_endpoint}</div>
</div> </div>
)) ))
} }
</div> </div>
</div> </div>
<div className='h-[1px] bg-gray-100' /> <div className='h-[1px] bg-divider-regular' />
<div className='p-1'> <div className='p-1'>
<div <div
className='flex items-center px-3 h-8 text-sm text-primary-600 cursor-pointer' className='flex items-center px-3 h-8 text-sm text-text-accent cursor-pointer'
onClick={() => { onClick={() => {
setOpen(false) setOpen(false)
setShowApiBasedExtensionModal({ payload: {}, onSaveCallback: () => mutate() }) setShowApiBasedExtensionModal({ payload: {}, onSaveCallback: () => mutate() })

@ -44,6 +44,7 @@ const MultipleToolSelector = ({
// add tool // add tool
const [open, setOpen] = React.useState(false) const [open, setOpen] = React.useState(false)
const [panelShowState, setPanelShowState] = React.useState(true)
const handleAdd = (val: ToolValue) => { const handleAdd = (val: ToolValue) => {
const newValue = [...value, val] const newValue = [...value, val]
// deduplication // deduplication
@ -109,7 +110,10 @@ const MultipleToolSelector = ({
</> </>
)} )}
{!disabled && ( {!disabled && (
<ActionButton className='mx-1' onClick={() => setOpen(!open)}> <ActionButton className='mx-1' onClick={() => {
setOpen(!open)
setPanelShowState(true)
}}>
<RiAddLine className='w-4 h-4' /> <RiAddLine className='w-4 h-4' />
</ActionButton> </ActionButton>
)} )}
@ -126,6 +130,9 @@ const MultipleToolSelector = ({
trigger={ trigger={
<div className=''></div> <div className=''></div>
} }
panelShowState={panelShowState}
onPanelShowStateChange={setPanelShowState}
/> />
{value.length === 0 && ( {value.length === 0 && (
<div className='p-3 flex justify-center rounded-[10px] bg-background-section text-text-tertiary system-xs-regular'>{t('plugin.detailPanel.toolSelector.empty')}</div> <div className='p-3 flex justify-center rounded-[10px] bg-background-section text-text-tertiary system-xs-regular'>{t('plugin.detailPanel.toolSelector.empty')}</div>

@ -53,6 +53,7 @@ type Props = {
onSelect: (tool: { onSelect: (tool: {
provider_name: string provider_name: string
tool_name: string tool_name: string
tool_label: string
parameters?: Record<string, any> parameters?: Record<string, any>
extra?: Record<string, any> extra?: Record<string, any>
}) => void }) => void
@ -62,6 +63,8 @@ type Props = {
trigger?: React.ReactNode trigger?: React.ReactNode
controlledState?: boolean controlledState?: boolean
onControlledStateChange?: (state: boolean) => void onControlledStateChange?: (state: boolean) => void
panelShowState?: boolean
onPanelShowStateChange?: (state: boolean) => void
} }
const ToolSelector: FC<Props> = ({ const ToolSelector: FC<Props> = ({
value, value,
@ -76,6 +79,8 @@ const ToolSelector: FC<Props> = ({
trigger, trigger,
controlledState, controlledState,
onControlledStateChange, onControlledStateChange,
panelShowState,
onPanelShowStateChange,
}) => { }) => {
const { t } = useTranslation() const { t } = useTranslation()
const [isShow, onShowChange] = useState(false) const [isShow, onShowChange] = useState(false)
@ -244,17 +249,18 @@ const ToolSelector: FC<Props> = ({
<div className='flex flex-col gap-1'> <div className='flex flex-col gap-1'>
<div className='h-6 flex items-center system-sm-semibold text-text-secondary'>{t('plugin.detailPanel.toolSelector.toolLabel')}</div> <div className='h-6 flex items-center system-sm-semibold text-text-secondary'>{t('plugin.detailPanel.toolSelector.toolLabel')}</div>
<ToolPicker <ToolPicker
panelClassName='w-[328px]'
placement='bottom' placement='bottom'
offset={offset} offset={offset}
trigger={ trigger={
<ToolTrigger <ToolTrigger
open={isShowChooseTool} open={panelShowState || isShowChooseTool}
value={value} value={value}
provider={currentProvider} provider={currentProvider}
/> />
} }
isShow={isShowChooseTool} isShow={panelShowState || isShowChooseTool}
onShowChange={setIsShowChooseTool} onShowChange={trigger ? onPanelShowStateChange as any : setIsShowChooseTool}
disabled={false} disabled={false}
supportAddCustomTool supportAddCustomTool
onSelect={handleSelectTool} onSelect={handleSelectTool}

@ -24,8 +24,10 @@ import {
import type { CustomCollectionBackend } from '@/app/components/tools/types' import type { CustomCollectionBackend } from '@/app/components/tools/types'
import Toast from '@/app/components/base/toast' import Toast from '@/app/components/base/toast'
import { useAllBuiltInTools, useAllCustomTools, useAllWorkflowTools, useInvalidateAllCustomTools } from '@/service/use-tools' import { useAllBuiltInTools, useAllCustomTools, useAllWorkflowTools, useInvalidateAllCustomTools } from '@/service/use-tools'
import cn from '@/utils/classnames'
type Props = { type Props = {
panelClassName?: string
disabled: boolean disabled: boolean
trigger: React.ReactNode trigger: React.ReactNode
placement?: Placement placement?: Placement
@ -49,6 +51,7 @@ const ToolPicker: FC<Props> = ({
supportAddCustomTool, supportAddCustomTool,
scope = 'all', scope = 'all',
selectedTools, selectedTools,
panelClassName,
}) => { }) => {
const { t } = useTranslation() const { t } = useTranslation()
const [searchText, setSearchText] = useState('') const [searchText, setSearchText] = useState('')
@ -139,7 +142,7 @@ const ToolPicker: FC<Props> = ({
</PortalToFollowElemTrigger> </PortalToFollowElemTrigger>
<PortalToFollowElemContent className='z-[1000]'> <PortalToFollowElemContent className='z-[1000]'>
<div className="relative w-[356px] min-h-20 rounded-xl backdrop-blur-sm bg-components-panel-bg-blur border-[0.5px] border-components-panel-border shadow-lg"> <div className={cn('relative w-[356px] min-h-20 rounded-xl backdrop-blur-sm bg-components-panel-bg-blur border-[0.5px] border-components-panel-border shadow-lg', panelClassName)}>
<div className='p-2 pb-1'> <div className='p-2 pb-1'>
<SearchBox <SearchBox
search={searchText} search={searchText}

@ -0,0 +1,9 @@
<svg width="237" height="50" viewBox="0 0 237 50" fill="none" xmlns="http://www.w3.org/2000/svg">
<path opacity="0.5" d="M0 8C0 3.58172 3.58172 0 8 0H237L215.033 50H8C3.58172 50 0 46.4183 0 42V8Z" fill="url(#paint0_linear_3552_29170)"/>
<defs>
<linearGradient id="paint0_linear_3552_29170" x1="-4.89158e-08" y1="4.62963" x2="168.013" y2="23.1752" gradientUnits="userSpaceOnUse">
<stop stop-color="white" stop-opacity="0.03"/>
<stop offset="1" stop-color="white" stop-opacity="0.05"/>
</linearGradient>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 517 B

@ -1,5 +1,7 @@
'use client' 'use client'
import type { FC } from 'react' import type { FC } from 'react'
import { useAppContext } from '@/context/app-context'
import { Theme } from '@/types/app'
import cn from '@/utils/classnames' import cn from '@/utils/classnames'
type Props = { type Props = {
@ -11,19 +13,36 @@ const StatusContainer: FC<Props> = ({
status, status,
children, children,
}) => { }) => {
const { theme } = useAppContext()
return ( return (
<div <div
className={cn( className={cn(
'relative px-3 py-2.5 rounded-lg border system-xs-regular break-all', 'relative px-3 py-2.5 rounded-lg border system-xs-regular break-all',
status === 'succeeded' && 'border-[rgba(23,178,106,0.8)] bg-workflow-display-success-bg bg-[url(~@/app/components/workflow/run/assets/bg-line-success.svg)] shadow-[inset_2px_2px_0_0_rgba(255,255,255,0.5),inset_0_1px_3px_0_rgba(0,0,0,0.12),inset_0_2px_24px_0_rgba(23,178,106,0.2),0_1px_2px_0_rgba(9,9,11,0.05),0_0_0_1px_rgba(0,0,0,0.05)] text-text-success', status === 'succeeded' && 'border-[rgba(23,178,106,0.8)] bg-workflow-display-success-bg bg-[url(~@/app/components/workflow/run/assets/bg-line-success.svg)] text-text-success',
status === 'partial-succeeded' && 'border-[rgba(23,178,106,0.8)] bg-workflow-display-success-bg bg-[url(~@/app/components/workflow/run/assets/bg-line-success.svg)] shadow-[inset_2px_2px_0_0_rgba(255,255,255,0.5),inset_0_1px_3px_0_rgba(0,0,0,0.12),inset_0_2px_24px_0_rgba(23,178,106,0.2),0_1px_2px_0_rgba(9,9,11,0.05),0_0_0_1px_rgba(0,0,0,0.05)] text-text-success', status === 'succeeded' && theme === Theme.light && 'shadow-[inset_2px_2px_0_0_rgba(255,255,255,0.5),inset_0_1px_3px_0_rgba(0,0,0,0.12),inset_0_2px_24px_0_rgba(23,178,106,0.2),0_1px_2px_0_rgba(9,9,11,0.05),0_0_0_1px_rgba(0,0,0,0.05)]',
status === 'failed' && 'border-[rgba(240,68,56,0.8)] bg-workflow-display-error-bg bg-[url(~@/app/components/workflow/run/assets/bg-line-error.svg)] shadow-[inset_2px_2px_0_0_rgba(255,255,255,0.5),inset_0_1px_3px_0_rgba(0,0,0,0.12),inset_0_2px_24px_0_rgba(240,68,56,0.2),0_1px_2px_0_rgba(9,9,11,0.05),0_0_0_1px_rgba(0,0,0,0.05)] text-text-warning', status === 'succeeded' && theme === Theme.dark && 'shadow-[inset_2px_2px_0_0_rgba(255,255,255,0.12),inset_0_1px_3px_0_rgba(0,0,0,0.4),inset_0_2px_24px_0_rgba(23,178,106,0.25),0_1px_2px_0_rgba(0,0,0,0.1),0_0_0_1px_rgba(24, 24, 27, 0.95)]',
status === 'stopped' && 'border-[rgba(247,144,9,0.8)] bg-workflow-display-warning-bg bg-[url(~@/app/components/workflow/run/assets/bg-line-warning.svg)] shadow-[inset_2px_2px_0_0_rgba(255,255,255,0.5),inset_0_1px_3px_0_rgba(0,0,0,0.12),inset_0_2px_24px_0_rgba(247,144,9,0.2),0_1px_2px_0_rgba(9,9,11,0.05),0_0_0_1px_rgba(0,0,0,0.05)] text-text-destructive', status === 'partial-succeeded' && 'border-[rgba(23,178,106,0.8)] bg-workflow-display-success-bg bg-[url(~@/app/components/workflow/run/assets/bg-line-success.svg)] text-text-success',
status === 'exception' && 'border-[rgba(247,144,9,0.8)] bg-workflow-display-warning-bg bg-[url(~@/app/components/workflow/run/assets/bg-line-warning.svg)] shadow-[inset_2px_2px_0_0_rgba(255,255,255,0.5),inset_0_1px_3px_0_rgba(0,0,0,0.12),inset_0_2px_24px_0_rgba(247,144,9,0.2),0_1px_2px_0_rgba(9,9,11,0.05),0_0_0_1px_rgba(0,0,0,0.05)] text-text-destructive', status === 'partial-succeeded' && theme === Theme.light && 'shadow-[inset_2px_2px_0_0_rgba(255,255,255,0.5),inset_0_1px_3px_0_rgba(0,0,0,0.12),inset_0_2px_24px_0_rgba(23,178,106,0.2),0_1px_2px_0_rgba(9,9,11,0.05),0_0_0_1px_rgba(0,0,0,0.05)]',
status === 'running' && 'border-[rgba(11,165,236,0.8)] bg-workflow-display-normal-bg bg-[url(~@/app/components/workflow/run/assets/bg-line-running.svg)] shadow-[inset_2px_2px_0_0_rgba(255,255,255,0.5),inset_0_1px_3px_0_rgba(0,0,0,0.12),inset_0_2px_24px_0_rgba(11,165,236,0.2),0_1px_2px_0_rgba(9,9,11,0.05),0_0_0_1px_rgba(0,0,0,0.05)] text-util-colors-blue-light-blue-light-600', status === 'partial-succeeded' && theme === Theme.dark && 'shadow-[inset_2px_2px_0_0_rgba(255,255,255,0.12),inset_0_1px_3px_0_rgba(0,0,0,0.4),inset_0_2px_24px_0_rgba(23,178,106,0.25),0_1px_2px_0_rgba(0,0,0,0.1),0_0_0_1px_rgba(24, 24, 27, 0.95)]',
status === 'failed' && 'border-[rgba(240,68,56,0.8)] bg-workflow-display-error-bg bg-[url(~@/app/components/workflow/run/assets/bg-line-error.svg)] text-text-warning',
status === 'failed' && theme === Theme.light && 'shadow-[inset_2px_2px_0_0_rgba(255,255,255,0.5),inset_0_1px_3px_0_rgba(0,0,0,0.12),inset_0_2px_24px_0_rgba(240,68,56,0.2),0_1px_2px_0_rgba(9,9,11,0.05),0_0_0_1px_rgba(0,0,0,0.05)]',
status === 'failed' && theme === Theme.dark && 'shadow-[inset_2px_2px_0_0_rgba(255,255,255,0.12),inset_0_1px_3px_0_rgba(0,0,0,0.4),inset_0_2px_24px_0_rgba(240,68,56,0.25),0_1px_2px_0_rgba(0,0,0,0.1),0_0_0_1px_rgba(24, 24, 27, 0.95)]',
status === 'stopped' && 'border-[rgba(247,144,9,0.8)] bg-workflow-display-warning-bg bg-[url(~@/app/components/workflow/run/assets/bg-line-warning.svg)] text-text-destructive',
status === 'stopped' && theme === Theme.light && 'shadow-[inset_2px_2px_0_0_rgba(255,255,255,0.5),inset_0_1px_3px_0_rgba(0,0,0,0.12),inset_0_2px_24px_0_rgba(247,144,9,0.2),0_1px_2px_0_rgba(9,9,11,0.05),0_0_0_1px_rgba(0,0,0,0.05)]',
status === 'stopped' && theme === Theme.dark && 'shadow-[inset_2px_2px_0_0_rgba(255,255,255,0.12),inset_0_1px_3px_0_rgba(0,0,0,0.4),inset_0_2px_24px_0_rgba(247,144,9,0.25),0_1px_2px_0_rgba(0,0,0,0.1),0_0_0_1px_rgba(24, 24, 27, 0.95)]',
status === 'exception' && 'border-[rgba(247,144,9,0.8)] bg-workflow-display-warning-bg bg-[url(~@/app/components/workflow/run/assets/bg-line-warning.svg)] text-text-destructive',
status === 'exception' && theme === Theme.light && 'shadow-[inset_2px_2px_0_0_rgba(255,255,255,0.5),inset_0_1px_3px_0_rgba(0,0,0,0.12),inset_0_2px_24px_0_rgba(247,144,9,0.2),0_1px_2px_0_rgba(9,9,11,0.05),0_0_0_1px_rgba(0,0,0,0.05)]',
status === 'exception' && theme === Theme.dark && 'shadow-[inset_2px_2px_0_0_rgba(255,255,255,0.12),inset_0_1px_3px_0_rgba(0,0,0,0.4),inset_0_2px_24px_0_rgba(247,144,9,0.25),0_1px_2px_0_rgba(0,0,0,0.1),0_0_0_1px_rgba(24, 24, 27, 0.95)]',
status === 'running' && 'border-[rgba(11,165,236,0.8)] bg-workflow-display-normal-bg bg-[url(~@/app/components/workflow/run/assets/bg-line-running.svg)] text-util-colors-blue-light-blue-light-600',
status === 'running' && theme === Theme.light && 'shadow-[inset_2px_2px_0_0_rgba(255,255,255,0.5),inset_0_1px_3px_0_rgba(0,0,0,0.12),inset_0_2px_24px_0_rgba(11,165,236,0.2),0_1px_2px_0_rgba(9,9,11,0.05),0_0_0_1px_rgba(0,0,0,0.05)]',
status === 'running' && theme === Theme.dark && 'shadow-[inset_2px_2px_0_0_rgba(255,255,255,0.12),inset_0_1px_3px_0_rgba(0,0,0,0.4),inset_0_2px_24px_0_rgba(11,165,236,0.25),0_1px_2px_0_rgba(0,0,0,0.1),0_0_0_1px_rgba(24, 24, 27, 0.95)]',
)} )}
> >
<div className='absolute top-0 left-0 w-[65%] h-[50px] bg-[url(~@/app/components/workflow/run/assets/highlight.svg)]'></div> <div className={cn(
'absolute top-0 left-0 w-[65%] h-[50px] bg-no-repeat',
theme === Theme.light && 'bg-[url(~@/app/components/workflow/run/assets/highlight.svg)]',
theme === Theme.dark && 'bg-[url(~@/app/components/workflow/run/assets/highlight-dark.svg)]',
)}></div>
{children} {children}
</div> </div>
) )

@ -5,7 +5,7 @@ import cn from '@/utils/classnames'
import Indicator from '@/app/components/header/indicator' import Indicator from '@/app/components/header/indicator'
import StatusContainer from '@/app/components/workflow/run/status-container' import StatusContainer from '@/app/components/workflow/run/status-container'
interface ResultProps { type ResultProps = {
status: string status: string
time?: number time?: number
tokens?: number tokens?: number

@ -66,6 +66,7 @@ const AppContext = createContext<AppContextValue>({
name: '', name: '',
email: '', email: '',
avatar: '', avatar: '',
avatar_url: '',
is_password_set: false, is_password_set: false,
}, },
currentWorkspace: initialWorkspaceInfo, currentWorkspace: initialWorkspaceInfo,

Loading…
Cancel
Save