mirror of
https://github.com/langgenius/dify.git
synced 2026-05-06 02:18:08 +08:00
feat: support enable agent mode show tip in prompt editor
This commit is contained in:
@ -86,6 +86,7 @@ type Props = {
|
||||
onBlur?: () => void
|
||||
onFocus?: () => void
|
||||
disableToolBlocks?: boolean
|
||||
footer?: ReactNode
|
||||
}
|
||||
|
||||
const Editor: FC<Props> = ({
|
||||
@ -131,6 +132,7 @@ const Editor: FC<Props> = ({
|
||||
onBlur,
|
||||
onFocus,
|
||||
disableToolBlocks,
|
||||
footer,
|
||||
}) => {
|
||||
const { t } = useTranslation()
|
||||
const { eventEmitter } = useEventEmitterContextContext()
|
||||
@ -351,6 +353,11 @@ const Editor: FC<Props> = ({
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
{!!footer && (
|
||||
<div className="px-1 pt-2">
|
||||
{footer}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -0,0 +1,56 @@
|
||||
import type { FC } from 'react'
|
||||
import * as React from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import Button from '@/app/components/base/button'
|
||||
|
||||
type Props = {
|
||||
visible: boolean
|
||||
onEnable: () => void
|
||||
}
|
||||
|
||||
const ComputerUseTip: FC<Props> = ({
|
||||
visible,
|
||||
onEnable,
|
||||
}) => {
|
||||
const { t } = useTranslation()
|
||||
const [dismissed, setDismissed] = React.useState(false)
|
||||
|
||||
React.useEffect(() => {
|
||||
if (!visible)
|
||||
// eslint-disable-next-line react-hooks-extra/no-direct-set-state-in-use-effect
|
||||
setDismissed(false)
|
||||
}, [visible])
|
||||
|
||||
if (!visible || dismissed)
|
||||
return null
|
||||
|
||||
return (
|
||||
<div className="relative top-1 rounded-xl border border-state-warning-hover-alt bg-state-warning-hover pb-2 pl-2.5 pr-2 pt-2.5">
|
||||
<div className="flex items-start gap-1.5">
|
||||
<span className="i-ri-alert-fill mt-0.5 size-4 shrink-0 text-text-warning-secondary" />
|
||||
<div className="flex min-w-0 flex-1 flex-col gap-2">
|
||||
<div className="text-text-primary system-sm-regular">
|
||||
{t('nodes.llm.computerUse.enableForPromptTools', { ns: 'workflow' })}
|
||||
</div>
|
||||
<div className="flex items-center justify-end gap-1">
|
||||
<Button
|
||||
size="small"
|
||||
onClick={() => setDismissed(true)}
|
||||
>
|
||||
{t('nodes.llm.computerUse.dismiss', { ns: 'workflow' })}
|
||||
</Button>
|
||||
<Button
|
||||
size="small"
|
||||
variant="primary"
|
||||
onClick={onEnable}
|
||||
>
|
||||
{t('nodes.llm.computerUse.enable', { ns: 'workflow' })}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default React.memo(ComputerUseTip)
|
||||
@ -7,9 +7,11 @@ import { useTranslation } from 'react-i18next'
|
||||
import Tooltip from '@/app/components/base/tooltip'
|
||||
import Editor from '@/app/components/workflow/nodes/_base/components/prompt/editor'
|
||||
import TypeSelector from '@/app/components/workflow/nodes/_base/components/selector'
|
||||
import { extractToolConfigIds } from '@/app/components/workflow/utils'
|
||||
import { PromptRole } from '@/models/debug'
|
||||
import { useWorkflowStore } from '../../../store'
|
||||
import { EditionType } from '../../../types'
|
||||
import ComputerUseTip from './computer-use-tip'
|
||||
|
||||
const i18nPrefix = 'nodes.llm'
|
||||
|
||||
@ -44,6 +46,8 @@ type Props = {
|
||||
isSupportSandbox?: boolean
|
||||
onPromptEditorBlur?: () => void
|
||||
disableToolBlocks?: boolean
|
||||
showComputerUseTip?: boolean
|
||||
onEnableComputerUse?: () => void
|
||||
}
|
||||
|
||||
const roleOptions = [
|
||||
@ -90,6 +94,8 @@ const ConfigPromptItem: FC<Props> = ({
|
||||
isSupportSandbox,
|
||||
onPromptEditorBlur,
|
||||
disableToolBlocks,
|
||||
showComputerUseTip,
|
||||
onEnableComputerUse,
|
||||
}) => {
|
||||
const { t } = useTranslation()
|
||||
const workflowStore = useWorkflowStore()
|
||||
@ -101,6 +107,11 @@ const ConfigPromptItem: FC<Props> = ({
|
||||
onPromptChange(prompt)
|
||||
setTimeout(() => setControlPromptEditorRerenderKey(Date.now()))
|
||||
}, [onPromptChange, setControlPromptEditorRerenderKey])
|
||||
const editorValue = payload.edition_type === EditionType.jinja2
|
||||
? (payload.jinja2_text || '')
|
||||
: payload.text
|
||||
const shouldShowComputerUseTip = !!showComputerUseTip
|
||||
&& extractToolConfigIds(editorValue || '').size > 0
|
||||
|
||||
return (
|
||||
<Editor
|
||||
@ -135,7 +146,7 @@ const ConfigPromptItem: FC<Props> = ({
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
value={payload.edition_type === EditionType.jinja2 ? (payload.jinja2_text || '') : payload.text}
|
||||
value={editorValue}
|
||||
onChange={onPromptChange}
|
||||
promptMetadata={payload.metadata}
|
||||
onPromptMetadataChange={onMetadataChange}
|
||||
@ -162,6 +173,12 @@ const ConfigPromptItem: FC<Props> = ({
|
||||
isSupportSandbox={isSupportSandbox}
|
||||
disableToolBlocks={disableToolBlocks}
|
||||
onBlur={onPromptEditorBlur}
|
||||
footer={(
|
||||
<ComputerUseTip
|
||||
visible={shouldShowComputerUseTip}
|
||||
onEnable={() => onEnableComputerUse?.()}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
@ -22,6 +22,7 @@ import { cn } from '@/utils/classnames'
|
||||
import { useWorkflowStore } from '../../../store'
|
||||
import { BlockEnum, EditionType, isPromptMessageContext, PromptRole, VarType } from '../../../types'
|
||||
import useAvailableVarList from '../../_base/hooks/use-available-var-list'
|
||||
import ComputerUseTip from './computer-use-tip'
|
||||
import ConfigContextItem from './config-context-item'
|
||||
import ConfigPromptItem from './config-prompt-item'
|
||||
|
||||
@ -67,6 +68,8 @@ type Props = {
|
||||
modelConfig: ModelConfig
|
||||
onPromptEditorBlur?: () => void
|
||||
disableToolBlocks?: boolean
|
||||
showComputerUseTip?: boolean
|
||||
onEnableComputerUse?: () => void
|
||||
}
|
||||
|
||||
const ConfigPrompt: FC<Props> = ({
|
||||
@ -84,6 +87,8 @@ const ConfigPrompt: FC<Props> = ({
|
||||
modelConfig,
|
||||
onPromptEditorBlur,
|
||||
disableToolBlocks,
|
||||
showComputerUseTip,
|
||||
onEnableComputerUse,
|
||||
}) => {
|
||||
const { t } = useTranslation()
|
||||
const workflowStore = useWorkflowStore()
|
||||
@ -284,6 +289,11 @@ const ConfigPrompt: FC<Props> = ({
|
||||
}
|
||||
return false
|
||||
})()
|
||||
const completionEditorValue = ((payload as PromptItem).edition_type === EditionType.basic || !(payload as PromptItem).edition_type)
|
||||
? (payload as PromptItem).text
|
||||
: ((payload as PromptItem).jinja2_text || '')
|
||||
const shouldShowCompletionComputerUseTip = !!showComputerUseTip
|
||||
&& extractToolConfigIds(completionEditorValue || '').size > 0
|
||||
|
||||
return (
|
||||
<div>
|
||||
@ -364,6 +374,8 @@ const ConfigPrompt: FC<Props> = ({
|
||||
isSupportSandbox={isSupportSandbox}
|
||||
onPromptEditorBlur={onPromptEditorBlur}
|
||||
disableToolBlocks={disableToolBlocks}
|
||||
showComputerUseTip={showComputerUseTip}
|
||||
onEnableComputerUse={onEnableComputerUse}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
@ -421,7 +433,7 @@ const ConfigPrompt: FC<Props> = ({
|
||||
instanceId={`${nodeId}-chat-workflow-llm-prompt-editor`}
|
||||
nodeId={nodeId}
|
||||
title={<span className="capitalize">{t(`${i18nPrefix}.prompt`, { ns: 'workflow' })}</span>}
|
||||
value={((payload as PromptItem).edition_type === EditionType.basic || !(payload as PromptItem).edition_type) ? (payload as PromptItem).text : ((payload as PromptItem).jinja2_text || '')}
|
||||
value={completionEditorValue}
|
||||
onChange={handleCompletionPromptChange}
|
||||
promptMetadata={(payload as PromptItem).metadata}
|
||||
onPromptMetadataChange={handleCompletionMetadataChange}
|
||||
@ -443,6 +455,12 @@ const ConfigPrompt: FC<Props> = ({
|
||||
isSupportSandbox={isSupportSandbox}
|
||||
onBlur={onPromptEditorBlur}
|
||||
disableToolBlocks={disableToolBlocks}
|
||||
footer={(
|
||||
<ComputerUseTip
|
||||
visible={shouldShowCompletionComputerUseTip}
|
||||
onEnable={() => onEnableComputerUse?.()}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@ -102,6 +102,7 @@ const Panel: FC<NodePanelProps<LLMNodeType>> = ({
|
||||
isComputerUseBlocked,
|
||||
isToolsBlocked,
|
||||
disableToolBlocks,
|
||||
shouldEnableComputerUseForPromptTools,
|
||||
structuredOutputDisabledTip,
|
||||
computerUseDisabledTip,
|
||||
toolsDisabledTip,
|
||||
@ -185,6 +186,8 @@ const Panel: FC<NodePanelProps<LLMNodeType>> = ({
|
||||
modelConfig={model}
|
||||
onPromptEditorBlur={handlePromptEditorBlur}
|
||||
disableToolBlocks={disableToolBlocks}
|
||||
showComputerUseTip={shouldEnableComputerUseForPromptTools}
|
||||
onEnableComputerUse={() => handleComputerUseChange(true)}
|
||||
/>
|
||||
)}
|
||||
|
||||
|
||||
@ -49,7 +49,12 @@ export const useStructuredOutputMutualExclusion = ({
|
||||
const isStructuredOutputBlocked = readOnly || (hasToolConflict && !isStructuredOutputEnabled)
|
||||
const isComputerUseBlocked = readOnly || (isStructuredOutputEnabled && !inputs.computer_use)
|
||||
const isToolsBlocked = readOnly || isStructuredOutputEnabled
|
||||
const disableToolBlocks = isStructuredOutputEnabled
|
||||
const shouldEnableComputerUseForPromptTools = isSupportSandbox
|
||||
&& !readOnly
|
||||
&& !inputs.computer_use
|
||||
&& hasToolDependencies
|
||||
&& !isComputerUseBlocked
|
||||
const disableToolBlocks = isStructuredOutputEnabled || shouldEnableComputerUseForPromptTools
|
||||
|
||||
const structuredOutputDisabledTip = useMemo(() => {
|
||||
if (readOnly || !isStructuredOutputBlocked)
|
||||
@ -76,6 +81,7 @@ export const useStructuredOutputMutualExclusion = ({
|
||||
isComputerUseBlocked,
|
||||
isToolsBlocked,
|
||||
disableToolBlocks,
|
||||
shouldEnableComputerUseForPromptTools,
|
||||
structuredOutputDisabledTip,
|
||||
computerUseDisabledTip,
|
||||
toolsDisabledTip,
|
||||
|
||||
Reference in New Issue
Block a user