feat: support enable agent mode show tip in prompt editor

This commit is contained in:
Joel
2026-02-10 17:01:07 +08:00
parent 32fcbcdc62
commit c980f1b2ac
13 changed files with 186 additions and 46 deletions

View File

@ -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>

View File

@ -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)

View File

@ -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?.()}
/>
)}
/>
)
}

View File

@ -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>
)}

View File

@ -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)}
/>
)}

View File

@ -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,