mirror of
https://github.com/langgenius/dify.git
synced 2026-05-05 18:08:07 +08:00
chore: add warning ui for agentic stragey
This commit is contained in:
@ -0,0 +1,86 @@
|
||||
import { PortalToFollowElem, PortalToFollowElemContent, PortalToFollowElemTrigger } from '@/app/components/base/portal-to-follow-elem'
|
||||
import { useState } from 'react'
|
||||
import AllTools from '../../../block-selector/all-tools'
|
||||
import type { Strategy } from './agent-strategy'
|
||||
import classNames from '@/utils/classnames'
|
||||
import { RiArrowDownSLine, RiErrorWarningFill } from '@remixicon/react'
|
||||
import { useAllBuiltInTools } from '@/service/use-tools'
|
||||
import Tooltip from '@/app/components/base/tooltip'
|
||||
import Link from 'next/link'
|
||||
import { InstallPluginButton } from './install-plugin-button'
|
||||
|
||||
const ExternalNotInstallWarn = () => {
|
||||
// TODO: add i18n label
|
||||
return <Tooltip
|
||||
popupContent={<div className='space-y-1 text-xs'>
|
||||
<h3 className='text-text-primary font-semibold'>This plugin is not installed</h3>
|
||||
<p className='text-text-secondary tracking-tight'>This plugin is installed from GitHub. Please go to Plugins to reinstall</p>
|
||||
<p>
|
||||
<Link href={'/plugins'} className='text-text-accent tracking-tight'>Link to Plugins</Link>
|
||||
</p>
|
||||
</div>}
|
||||
needsDelay
|
||||
>
|
||||
<div>
|
||||
<RiErrorWarningFill className='text-text-destructive size-4' />
|
||||
</div>
|
||||
</Tooltip>
|
||||
}
|
||||
|
||||
export type AgentStrategySelectorProps = {
|
||||
value?: Strategy,
|
||||
onChange: (value?: Strategy) => void,
|
||||
}
|
||||
|
||||
export const AgentStrategySelector = (props: AgentStrategySelectorProps) => {
|
||||
const { value, onChange } = props
|
||||
const [open, setOpen] = useState(false)
|
||||
const list = useAllBuiltInTools()
|
||||
// TODO: should be replaced by real data
|
||||
const isExternalInstalled = true
|
||||
return <PortalToFollowElem open={open} onOpenChange={setOpen}>
|
||||
<PortalToFollowElemTrigger className='w-full'>
|
||||
<div className='py-2 pl-3 pr-2 flex items-center rounded-lg bg-components-input-bg-normal w-full hover:bg-state-base-hover-alt' onClick={() => setOpen(true)}>
|
||||
{list.data && <img
|
||||
src={list.data.find(
|
||||
coll => coll,
|
||||
)?.icon as string}
|
||||
width={24}
|
||||
height={24}
|
||||
className='rounded-md border-[0.5px] border-components-panel-border-subtle bg-background-default-dodge'
|
||||
alt='icon'
|
||||
/>}
|
||||
<p
|
||||
className={classNames(value ? 'text-components-input-text-filled' : 'text-components-input-text-placeholder', 'text-xs px-1')}
|
||||
>
|
||||
{value?.agent_strategy_name || 'Select agentic strategy'}
|
||||
</p>
|
||||
<div className='ml-auto flex items-center gap-1'>
|
||||
<InstallPluginButton onClick={e => e.preventDefault()} />
|
||||
{isExternalInstalled ? <ExternalNotInstallWarn /> : <RiArrowDownSLine className='size-4 text-text-tertiary' />}
|
||||
</div>
|
||||
</div>
|
||||
</PortalToFollowElemTrigger>
|
||||
<PortalToFollowElemContent>
|
||||
{list.data && <AllTools
|
||||
className='border-components-panel-border bg-components-panel-bg-blur'
|
||||
searchText=''
|
||||
tags={[]}
|
||||
buildInTools={list.data}
|
||||
customTools={[]}
|
||||
workflowTools={[]}
|
||||
onSelect={(_e, tool) => {
|
||||
if (!tool) {
|
||||
// TODO: should not be called, try it
|
||||
return
|
||||
}
|
||||
onChange({
|
||||
agent_strategy_name: tool.title,
|
||||
agent_strategy_provider_name: tool.provider_name,
|
||||
agent_parameters: {},
|
||||
})
|
||||
}}
|
||||
/>}
|
||||
</PortalToFollowElemContent>
|
||||
</PortalToFollowElem>
|
||||
}
|
||||
@ -0,0 +1,39 @@
|
||||
import type { CredentialFormSchema } from '@/app/components/header/account-setting/model-provider-page/declarations'
|
||||
import type { ToolVarInputs } from '../../tool/types'
|
||||
import ListEmpty from '@/app/components/base/list-empty'
|
||||
import { AgentStrategySelector } from './agent-strategy-selector'
|
||||
import Link from 'next/link'
|
||||
|
||||
export type Strategy = {
|
||||
agent_strategy_provider_name: string
|
||||
agent_strategy_name: string
|
||||
agent_strategy_label?: string
|
||||
agent_parameters?: ToolVarInputs
|
||||
}
|
||||
|
||||
export type AgentStrategyProps = {
|
||||
strategy?: Strategy
|
||||
onStrategyChange: (strategy?: Strategy) => void
|
||||
formSchema: CredentialFormSchema[]
|
||||
formValue: ToolVarInputs
|
||||
onFormValueChange: (value: ToolVarInputs) => void
|
||||
}
|
||||
|
||||
export const AgentStrategy = (props: AgentStrategyProps) => {
|
||||
const { strategy, onStrategyChange, formSchema, formValue, onFormValueChange } = props
|
||||
return <div className='space-y-2'>
|
||||
<AgentStrategySelector value={strategy} onChange={onStrategyChange} />
|
||||
{
|
||||
strategy
|
||||
? <div></div>
|
||||
// TODO: list empty need a icon
|
||||
: <ListEmpty
|
||||
title='Please configure agentic strategy.'
|
||||
description={<div className='text-text-tertiary text-xs'>
|
||||
After configuring the agentic strategy, this node will automatically load the remaining configurations. The strategy will affect the mechanism of multi-step tool reasoning. <br />
|
||||
<Link href={'/'} className='text-text-accent-secondary'>Learn more</Link>
|
||||
</div>}
|
||||
/>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
25
web/app/components/workflow/nodes/_base/components/group.tsx
Normal file
25
web/app/components/workflow/nodes/_base/components/group.tsx
Normal file
@ -0,0 +1,25 @@
|
||||
import classNames from '@/utils/classnames'
|
||||
import type { ComponentProps, FC, PropsWithChildren, ReactNode } from 'react'
|
||||
|
||||
export type GroupLabelProps = ComponentProps<'div'>
|
||||
|
||||
export const GroupLabel: FC<GroupLabelProps> = (props) => {
|
||||
const { children, className, ...rest } = props
|
||||
return <div {...rest} className={classNames('mb-1 system-2xs-medium-uppercase text-text-tertiary', className)}>
|
||||
{children}
|
||||
</div>
|
||||
}
|
||||
|
||||
export type Group = PropsWithChildren<{
|
||||
label: ReactNode
|
||||
}>
|
||||
|
||||
export const Group: FC<Group> = (props) => {
|
||||
const { children, label } = props
|
||||
return <div className={classNames('py-1')}>
|
||||
{label}
|
||||
<div className='space-y-0.5'>
|
||||
{children}
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
@ -1,10 +1,10 @@
|
||||
'use client'
|
||||
import type { FC } from 'react'
|
||||
import type { FC, ReactNode } from 'react'
|
||||
import React from 'react'
|
||||
|
||||
interface Props {
|
||||
type Props = {
|
||||
title: string
|
||||
content: string | JSX.Element
|
||||
content: ReactNode
|
||||
}
|
||||
|
||||
const InfoPanel: FC<Props> = ({
|
||||
|
||||
@ -0,0 +1,15 @@
|
||||
import Button from '@/app/components/base/button'
|
||||
import { RiInstallLine, RiLoader2Line } from '@remixicon/react'
|
||||
import type { ComponentProps } from 'react'
|
||||
import classNames from '@/utils/classnames'
|
||||
|
||||
type InstallPluginButtonProps = Omit<ComponentProps<typeof Button>, 'children'>
|
||||
|
||||
export const InstallPluginButton = (props: InstallPluginButtonProps) => {
|
||||
const { loading, className, ...rest } = props
|
||||
// TODO: add i18n label
|
||||
return <Button variant={'secondary'} disabled={loading} className={classNames('flex items-center', className)} {...rest}>
|
||||
{loading ? 'Installing' : 'Install'}
|
||||
{!loading ? <RiInstallLine className='size-4 ml-1' /> : <RiLoader2Line className='size-4 ml-1 animate-spin' />}
|
||||
</Button>
|
||||
}
|
||||
@ -0,0 +1,19 @@
|
||||
import Indicator from '@/app/components/header/indicator'
|
||||
import type { ComponentProps, PropsWithChildren } from 'react'
|
||||
|
||||
export type SettingItemProps = PropsWithChildren<{
|
||||
label: string
|
||||
indicator?: ComponentProps<typeof Indicator>['color']
|
||||
}>
|
||||
|
||||
export const SettingItem = ({ label, children, indicator }: SettingItemProps) => {
|
||||
return <div className='flex items-center h-6 justify-between bg-gray-100 rounded-md px-1 space-x-1 text-xs font-normal relative'>
|
||||
<div className='max-w-[100px] shrink-0 truncate text-xs font-medium text-text-tertiary uppercase'>
|
||||
{label}
|
||||
</div>
|
||||
<div className='grow w-0 shrink-0 truncate text-right text-xs font-normal text-text-secondary'>
|
||||
{children}
|
||||
</div>
|
||||
{indicator && <Indicator color={indicator} className='absolute -right-0.5 -top-0.5' />}
|
||||
</div>
|
||||
}
|
||||
@ -293,6 +293,11 @@ const formatItem = (
|
||||
break
|
||||
}
|
||||
|
||||
case BlockEnum.Agent: {
|
||||
res.vars = []
|
||||
break
|
||||
}
|
||||
|
||||
case 'env': {
|
||||
res.vars = data.envList.map((env: EnvironmentVariable) => {
|
||||
return {
|
||||
|
||||
Reference in New Issue
Block a user