mirror of
https://github.com/langgenius/dify.git
synced 2026-05-04 01:18:05 +08:00
184 lines
6.1 KiB
TypeScript
184 lines
6.1 KiB
TypeScript
import type { LLMGenerationItem } from '@/types/workflow'
|
|
import {
|
|
RiArrowRightSLine,
|
|
} from '@remixicon/react'
|
|
import { useState } from 'react'
|
|
import { useTranslation } from 'react-i18next'
|
|
import AppIcon from '@/app/components/base/app-icon'
|
|
import { TerminalSquare } from '@/app/components/base/icons/src/vender/line/development'
|
|
import { Thinking } from '@/app/components/base/icons/src/vender/workflow'
|
|
import { Markdown } from '@/app/components/base/markdown'
|
|
import BlockIcon from '@/app/components/workflow/block-icon'
|
|
import CodeEditor from '@/app/components/workflow/nodes/_base/components/editor/code-editor'
|
|
import { CodeLanguage } from '@/app/components/workflow/nodes/code/types'
|
|
import { BlockEnum } from '@/app/components/workflow/types'
|
|
import { cn } from '@/utils/classnames'
|
|
|
|
type ToolCallItemComponentProps = {
|
|
className?: string
|
|
payload: LLMGenerationItem
|
|
}
|
|
|
|
const isBashTool = (toolName?: string) => !!toolName?.toLowerCase().includes('bash')
|
|
|
|
const ToolCallItemComponent = ({
|
|
className,
|
|
payload,
|
|
}: ToolCallItemComponentProps) => {
|
|
const { t } = useTranslation()
|
|
const [expand, setExpand] = useState(false)
|
|
|
|
if (payload.type === 'text') {
|
|
return (
|
|
<Markdown
|
|
className={cn(
|
|
'px-2',
|
|
payload.isError && '!text-[#F04438]',
|
|
)}
|
|
content={payload.text ?? ''}
|
|
/>
|
|
)
|
|
}
|
|
|
|
return (
|
|
<div
|
|
className={cn('rounded-[10px] border-[0.5px] border-components-panel-border bg-background-default-subtle px-2 pb-1 pt-2 shadow-xs', className)}
|
|
>
|
|
<div
|
|
className="mb-1 flex cursor-pointer items-center hover:bg-background-gradient-bg-fill-chat-bubble-bg-2"
|
|
onClick={() => {
|
|
setExpand(!expand)
|
|
}}
|
|
>
|
|
{
|
|
payload.type === 'thought' && (
|
|
<Thinking className="mr-1 h-4 w-4 shrink-0" />
|
|
)
|
|
}
|
|
{
|
|
payload.type === 'tool' && (
|
|
isBashTool(payload.toolName)
|
|
? (
|
|
<div className="mr-1 flex h-4 w-4 shrink-0 items-center justify-center rounded-[5px] border-[0.5px] border-white/2 bg-components-icon-bg-midnight-solid text-white shadow-xs">
|
|
<TerminalSquare className="h-3 w-3" />
|
|
</div>
|
|
)
|
|
: (
|
|
<BlockIcon
|
|
type={BlockEnum.Tool}
|
|
toolIcon={payload.toolIcon}
|
|
className="mr-1 h-4 w-4 shrink-0"
|
|
/>
|
|
)
|
|
)
|
|
}
|
|
{
|
|
payload.type === 'model' && (
|
|
<AppIcon
|
|
iconType={typeof payload.modelIcon === 'string' ? 'image' : undefined}
|
|
imageUrl={typeof payload.modelIcon === 'string' ? payload.modelIcon : undefined}
|
|
background={typeof payload.modelIcon === 'object' ? payload.modelIcon.background : undefined}
|
|
className="mr-1 h-4 w-4 shrink-0"
|
|
/>
|
|
)
|
|
}
|
|
{
|
|
payload.type === 'thought' && (
|
|
<div className="mr-1 grow truncate text-text-secondary system-xs-medium" title={payload.thoughtOutput}>
|
|
{
|
|
payload.thoughtCompleted && !expand && (payload.thoughtOutput || '') as string
|
|
}
|
|
{
|
|
payload.thoughtCompleted && expand && 'THOUGHT'
|
|
}
|
|
{
|
|
!payload.thoughtCompleted && 'THINKING...'
|
|
}
|
|
</div>
|
|
)
|
|
}
|
|
{
|
|
payload.type === 'tool' && (
|
|
<div className="mr-1 grow truncate text-text-secondary system-xs-medium" title={payload.toolName}>{payload.toolName}</div>
|
|
)
|
|
}
|
|
{
|
|
payload.type === 'model' && (
|
|
<div className="mr-1 grow truncate text-text-secondary system-xs-medium" title={payload.modelName}>{payload.modelName}</div>
|
|
)
|
|
}
|
|
{
|
|
!!payload.toolDuration && (
|
|
<div className="mr-1 shrink-0 text-text-tertiary system-xs-regular">
|
|
{payload.toolDuration?.toFixed(1)}
|
|
s
|
|
</div>
|
|
)
|
|
}
|
|
{
|
|
!!payload.modelDuration && (
|
|
<div className="mr-1 shrink-0 text-text-tertiary system-xs-regular">
|
|
{payload.modelDuration?.toFixed(1)}
|
|
s
|
|
</div>
|
|
)
|
|
}
|
|
<RiArrowRightSLine
|
|
className={cn(
|
|
'h-4 w-4 shrink-0 text-text-quaternary transition-transform duration-200',
|
|
expand && 'rotate-90',
|
|
)}
|
|
/>
|
|
</div>
|
|
{
|
|
expand && (
|
|
<div className="relative px-2 pl-9">
|
|
<div className="absolute bottom-1 left-2 top-1 w-[1px] bg-divider-regular"></div>
|
|
{
|
|
payload.type === 'thought' && typeof payload.thoughtOutput === 'string' && (
|
|
<div className="text-text-tertiary body-sm-medium">{payload.thoughtOutput}</div>
|
|
)
|
|
}
|
|
{
|
|
payload.type === 'model' && (
|
|
<CodeEditor
|
|
readOnly
|
|
title={<div>{t('common.data', { ns: 'workflow' })}</div>}
|
|
language={CodeLanguage.json}
|
|
value={payload.modelOutput}
|
|
isJSONStringifyBeauty
|
|
/>
|
|
)
|
|
}
|
|
{
|
|
payload.type === 'tool' && (
|
|
<CodeEditor
|
|
readOnly
|
|
title={<div>{t('common.input', { ns: 'workflow' })}</div>}
|
|
language={CodeLanguage.json}
|
|
value={payload.toolArguments}
|
|
isJSONStringifyBeauty
|
|
/>
|
|
)
|
|
}
|
|
{
|
|
payload.type === 'tool' && (
|
|
<CodeEditor
|
|
readOnly
|
|
className="mt-1"
|
|
title={<div>{t('common.output', { ns: 'workflow' })}</div>}
|
|
language={CodeLanguage.json}
|
|
value={payload.toolOutput}
|
|
isJSONStringifyBeauty
|
|
/>
|
|
)
|
|
}
|
|
</div>
|
|
)
|
|
}
|
|
</div>
|
|
)
|
|
}
|
|
|
|
export default ToolCallItemComponent
|