mirror of
https://github.com/infiniflow/ragflow.git
synced 2025-12-08 12:32:30 +08:00
### What problem does this PR solve? Feat: Modify the style of the agent operator form #10703 ### Type of change - [x] New Feature (non-breaking change which adds functionality)
This commit is contained in:
@ -74,7 +74,7 @@ export function Collapse({
|
|||||||
<div>{rightContent}</div>
|
<div>{rightContent}</div>
|
||||||
</section>
|
</section>
|
||||||
</CollapsibleTrigger>
|
</CollapsibleTrigger>
|
||||||
<CollapsibleContent className="pt-2">{children}</CollapsibleContent>
|
<CollapsibleContent className="pt-5">{children}</CollapsibleContent>
|
||||||
</Collapsible>
|
</Collapsible>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -70,7 +70,7 @@ export function LargeModelFormField({
|
|||||||
<DropdownMenu>
|
<DropdownMenu>
|
||||||
<DropdownMenuTrigger>
|
<DropdownMenuTrigger>
|
||||||
<Button variant={'ghost'}>
|
<Button variant={'ghost'}>
|
||||||
<Funnel />
|
<Funnel className="text-text-disabled" />
|
||||||
</Button>
|
</Button>
|
||||||
</DropdownMenuTrigger>
|
</DropdownMenuTrigger>
|
||||||
<DropdownMenuContent>
|
<DropdownMenuContent>
|
||||||
|
|||||||
@ -140,7 +140,7 @@ export const SelectWithSearch = forwardRef<
|
|||||||
ref={ref}
|
ref={ref}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
className={cn(
|
className={cn(
|
||||||
'bg-background hover:bg-background border-input w-full justify-between px-3 font-normal outline-offset-0 outline-none focus-visible:outline-[3px] [&_svg]:pointer-events-auto',
|
'!bg-bg-input hover:bg-background border-input w-full justify-between px-3 font-normal outline-offset-0 outline-none focus-visible:outline-[3px] [&_svg]:pointer-events-auto',
|
||||||
triggerClassName,
|
triggerClassName,
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
|
|||||||
@ -31,7 +31,7 @@ const Input = React.forwardRef<HTMLInputElement, InputProps>(
|
|||||||
<input
|
<input
|
||||||
type={type}
|
type={type}
|
||||||
className={cn(
|
className={cn(
|
||||||
'flex h-8 w-full rounded-md border border-input bg-bg-base px-2 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-text-disabled focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50',
|
'flex h-8 w-full rounded-md border border-input bg-bg-input px-2 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-text-disabled focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 text-text-primary',
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
ref={ref}
|
ref={ref}
|
||||||
|
|||||||
@ -26,7 +26,7 @@ const SelectTrigger = React.forwardRef<
|
|||||||
<SelectPrimitive.Trigger
|
<SelectPrimitive.Trigger
|
||||||
ref={ref}
|
ref={ref}
|
||||||
className={cn(
|
className={cn(
|
||||||
'flex h-8 w-full items-center bg-bg-card justify-between rounded-md border border-input px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1',
|
'flex h-8 w-full items-center bg-bg-input justify-between rounded-md border border-input px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1',
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
@ -291,7 +291,7 @@ export const RAGFlowSelect = forwardRef<
|
|||||||
onReset={handleReset}
|
onReset={handleReset}
|
||||||
allowClear={allowClear}
|
allowClear={allowClear}
|
||||||
ref={ref}
|
ref={ref}
|
||||||
className={cn('bg-bg-base', triggerClassName)}
|
className={triggerClassName}
|
||||||
>
|
>
|
||||||
<SelectValue placeholder={placeholder}>{label}</SelectValue>
|
<SelectValue placeholder={placeholder}>{label}</SelectValue>
|
||||||
</SelectTrigger>
|
</SelectTrigger>
|
||||||
|
|||||||
@ -18,7 +18,7 @@ const Separator = React.forwardRef<
|
|||||||
decorative={decorative}
|
decorative={decorative}
|
||||||
orientation={orientation}
|
orientation={orientation}
|
||||||
className={cn(
|
className={cn(
|
||||||
'shrink-0 bg-border',
|
'shrink-0 bg-border-button',
|
||||||
orientation === 'horizontal' ? 'h-[1px] w-full' : 'h-full w-[1px]',
|
orientation === 'horizontal' ? 'h-[1px] w-full' : 'h-full w-[1px]',
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
|
|||||||
@ -31,7 +31,7 @@ const SheetOverlay = React.forwardRef<
|
|||||||
SheetOverlay.displayName = SheetPrimitive.Overlay.displayName;
|
SheetOverlay.displayName = SheetPrimitive.Overlay.displayName;
|
||||||
|
|
||||||
const sheetVariants = cva(
|
const sheetVariants = cva(
|
||||||
'fixed z-50 gap-4 bg-text-title-invert rounded-lg p-6 shadow-lg transition ease-in-out data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:duration-300 data-[state=open]:duration-500',
|
'fixed z-50 gap-4 bg-bg-base rounded-lg p-6 shadow-lg transition ease-in-out data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:duration-300 data-[state=open]:duration-500',
|
||||||
{
|
{
|
||||||
variants: {
|
variants: {
|
||||||
side: {
|
side: {
|
||||||
@ -73,7 +73,7 @@ const SheetContent = React.forwardRef<
|
|||||||
{children}
|
{children}
|
||||||
{closeIcon ? (
|
{closeIcon ? (
|
||||||
<SheetPrimitive.Close className="absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-secondary ">
|
<SheetPrimitive.Close className="absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-secondary ">
|
||||||
<X className="h-4 w-4 " />
|
<X className="h-4 w-4" />
|
||||||
<span className="sr-only">Close</span>
|
<span className="sr-only">Close</span>
|
||||||
</SheetPrimitive.Close>
|
</SheetPrimitive.Close>
|
||||||
) : null}
|
) : null}
|
||||||
|
|||||||
@ -1,4 +1,3 @@
|
|||||||
import { Input } from '@/components/ui/input';
|
|
||||||
import {
|
import {
|
||||||
Sheet,
|
Sheet,
|
||||||
SheetContent,
|
SheetContent,
|
||||||
@ -10,17 +9,17 @@ import { IModalProps } from '@/interfaces/common';
|
|||||||
import { RAGFlowNodeType } from '@/interfaces/database/flow';
|
import { RAGFlowNodeType } from '@/interfaces/database/flow';
|
||||||
import { cn } from '@/lib/utils';
|
import { cn } from '@/lib/utils';
|
||||||
import { lowerFirst } from 'lodash';
|
import { lowerFirst } from 'lodash';
|
||||||
import { Play, X } from 'lucide-react';
|
import { CirclePlay, X } from 'lucide-react';
|
||||||
import { useMemo } from 'react';
|
import { Operator } from '../constant';
|
||||||
import { BeginId, Operator } from '../constant';
|
|
||||||
import { AgentFormContext } from '../context';
|
import { AgentFormContext } from '../context';
|
||||||
import { RunTooltip } from '../flow-tooltip';
|
import { RunTooltip } from '../flow-tooltip';
|
||||||
import { useHandleNodeNameChange } from '../hooks/use-change-node-name';
|
import { useIsMcp } from '../hooks/use-is-mcp';
|
||||||
import OperatorIcon from '../operator-icon';
|
import OperatorIcon from '../operator-icon';
|
||||||
import useGraphStore from '../store';
|
import useGraphStore from '../store';
|
||||||
import { needsSingleStepDebugging } from '../utils';
|
import { needsSingleStepDebugging } from '../utils';
|
||||||
import { FormConfigMap } from './form-config-map';
|
import { FormConfigMap } from './form-config-map';
|
||||||
import SingleDebugSheet from './single-debug-sheet';
|
import SingleDebugSheet from './single-debug-sheet';
|
||||||
|
import { TitleInput } from './title-input';
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
node?: RAGFlowNodeType;
|
node?: RAGFlowNodeType;
|
||||||
@ -48,17 +47,7 @@ const FormSheet = ({
|
|||||||
|
|
||||||
const OperatorForm = currentFormMap?.component ?? EmptyContent;
|
const OperatorForm = currentFormMap?.component ?? EmptyContent;
|
||||||
|
|
||||||
const { name, handleNameBlur, handleNameChange } = useHandleNodeNameChange({
|
const isMcp = useIsMcp(operatorName);
|
||||||
id: node?.id,
|
|
||||||
data: node?.data,
|
|
||||||
});
|
|
||||||
|
|
||||||
const isMcp = useMemo(() => {
|
|
||||||
return (
|
|
||||||
operatorName === Operator.Tool &&
|
|
||||||
Object.values(Operator).every((x) => x !== clickedToolId)
|
|
||||||
);
|
|
||||||
}, [clickedToolId, operatorName]);
|
|
||||||
|
|
||||||
const { t } = useTranslate('flow');
|
const { t } = useTranslate('flow');
|
||||||
|
|
||||||
@ -75,36 +64,19 @@ const FormSheet = ({
|
|||||||
<section className="flex-col border-b py-2 px-5">
|
<section className="flex-col border-b py-2 px-5">
|
||||||
<div className="flex items-center gap-2 pb-3">
|
<div className="flex items-center gap-2 pb-3">
|
||||||
<OperatorIcon name={operatorName}></OperatorIcon>
|
<OperatorIcon name={operatorName}></OperatorIcon>
|
||||||
|
<TitleInput node={node}></TitleInput>
|
||||||
{isMcp ? (
|
|
||||||
<div className="flex-1">MCP Config</div>
|
|
||||||
) : (
|
|
||||||
<div className="flex items-center gap-1 flex-1">
|
|
||||||
<label htmlFor="">{t('title')}</label>
|
|
||||||
{node?.id === BeginId ? (
|
|
||||||
<span>{t(BeginId)}</span>
|
|
||||||
) : (
|
|
||||||
<Input
|
|
||||||
value={name}
|
|
||||||
onBlur={handleNameBlur}
|
|
||||||
onChange={handleNameChange}
|
|
||||||
></Input>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{needsSingleStepDebugging(operatorName) && (
|
{needsSingleStepDebugging(operatorName) && (
|
||||||
<RunTooltip>
|
<RunTooltip>
|
||||||
<Play
|
<CirclePlay
|
||||||
className="size-5 cursor-pointer"
|
className="size-3.5 cursor-pointer"
|
||||||
onClick={showSingleDebugDrawer}
|
onClick={showSingleDebugDrawer}
|
||||||
/>
|
/>
|
||||||
</RunTooltip>
|
</RunTooltip>
|
||||||
)}
|
)}
|
||||||
<X onClick={hideModal} />
|
<X onClick={hideModal} className="size-3.5 cursor-pointer" />
|
||||||
</div>
|
</div>
|
||||||
{isMcp || (
|
{isMcp || (
|
||||||
<span>
|
<span className="text-text-secondary">
|
||||||
{t(
|
{t(
|
||||||
`${lowerFirst(operatorName === Operator.Tool ? clickedToolId : operatorName)}Description`,
|
`${lowerFirst(operatorName === Operator.Tool ? clickedToolId : operatorName)}Description`,
|
||||||
)}
|
)}
|
||||||
|
|||||||
61
web/src/pages/agent/form-sheet/title-input.tsx
Normal file
61
web/src/pages/agent/form-sheet/title-input.tsx
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
import { Input } from '@/components/ui/input';
|
||||||
|
import { RAGFlowNodeType } from '@/interfaces/database/agent';
|
||||||
|
import { PenLine } from 'lucide-react';
|
||||||
|
import { useCallback, useState } from 'react';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
import { BeginId, Operator } from '../constant';
|
||||||
|
import { useHandleNodeNameChange } from '../hooks/use-change-node-name';
|
||||||
|
import { useIsMcp } from '../hooks/use-is-mcp';
|
||||||
|
|
||||||
|
type TitleInputProps = {
|
||||||
|
node?: RAGFlowNodeType;
|
||||||
|
};
|
||||||
|
|
||||||
|
export function TitleInput({ node }: TitleInputProps) {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const { name, handleNameBlur, handleNameChange } = useHandleNodeNameChange({
|
||||||
|
id: node?.id,
|
||||||
|
data: node?.data,
|
||||||
|
});
|
||||||
|
|
||||||
|
const operatorName: Operator = node?.data.label as Operator;
|
||||||
|
|
||||||
|
const isMcp = useIsMcp(operatorName);
|
||||||
|
|
||||||
|
const [isEditingMode, setIsEditingMode] = useState(false);
|
||||||
|
|
||||||
|
const switchIsEditingMode = useCallback(() => {
|
||||||
|
setIsEditingMode((prev) => !prev);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const handleBlur = useCallback(() => {
|
||||||
|
handleNameBlur();
|
||||||
|
setIsEditingMode(false);
|
||||||
|
}, [handleNameBlur]);
|
||||||
|
|
||||||
|
if (isMcp) {
|
||||||
|
return <div className="flex-1 text-base">MCP Config</div>;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="flex items-center gap-1 flex-1">
|
||||||
|
{node?.id === BeginId ? (
|
||||||
|
<span>{t(BeginId)}</span>
|
||||||
|
) : isEditingMode ? (
|
||||||
|
<Input
|
||||||
|
value={name}
|
||||||
|
onBlur={handleBlur}
|
||||||
|
onChange={handleNameChange}
|
||||||
|
></Input>
|
||||||
|
) : (
|
||||||
|
<div className="flex items-center gap-2.5 text-base">
|
||||||
|
{name}
|
||||||
|
<PenLine
|
||||||
|
onClick={switchIsEditingMode}
|
||||||
|
className="size-3.5 text-text-secondary cursor-pointer"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@ -28,18 +28,31 @@ import { useDeleteAgentNodeMCP } from './tool-popover/use-update-mcp';
|
|||||||
import { useDeleteAgentNodeTools } from './tool-popover/use-update-tools';
|
import { useDeleteAgentNodeTools } from './tool-popover/use-update-tools';
|
||||||
import { useGetAgentMCPIds, useGetAgentToolNames } from './use-get-tools';
|
import { useGetAgentMCPIds, useGetAgentToolNames } from './use-get-tools';
|
||||||
|
|
||||||
|
type ToolCardProps = React.HTMLAttributes<HTMLLIElement> &
|
||||||
|
PropsWithChildren & {
|
||||||
|
isNodeTool?: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
export function ToolCard({
|
export function ToolCard({
|
||||||
children,
|
children,
|
||||||
className,
|
className,
|
||||||
|
isNodeTool = true,
|
||||||
...props
|
...props
|
||||||
}: PropsWithChildren & React.HTMLAttributes<HTMLLIElement>) {
|
}: ToolCardProps) {
|
||||||
const element = useMemo(() => {
|
const element = useMemo(() => {
|
||||||
return (
|
return (
|
||||||
<LabelCard {...props} className={cn('flex justify-between', className)}>
|
<LabelCard
|
||||||
|
{...props}
|
||||||
|
className={cn(
|
||||||
|
'flex justify-between ',
|
||||||
|
{ 'p-2.5 text-text-primary text-sm': !isNodeTool },
|
||||||
|
className,
|
||||||
|
)}
|
||||||
|
>
|
||||||
{children}
|
{children}
|
||||||
</LabelCard>
|
</LabelCard>
|
||||||
);
|
);
|
||||||
}, [children, className, props]);
|
}, [children, className, isNodeTool, props]);
|
||||||
|
|
||||||
if (children === Operator.Code) {
|
if (children === Operator.Code) {
|
||||||
return (
|
return (
|
||||||
@ -67,13 +80,13 @@ function ActionButton<T>({ deleteRecord, record, edit }: ActionButtonProps<T>) {
|
|||||||
}, [deleteRecord, record]);
|
}, [deleteRecord, record]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex items-center gap-2 text-text-secondary">
|
<div className="flex items-center gap-4 text-text-secondary">
|
||||||
<PencilLine
|
<PencilLine
|
||||||
className="size-4 cursor-pointer"
|
className="size-3.5 cursor-pointer"
|
||||||
data-tool={record}
|
data-tool={record}
|
||||||
onClick={edit}
|
onClick={edit}
|
||||||
/>
|
/>
|
||||||
<X className="size-4 cursor-pointer" onClick={handleDelete} />
|
<X className="size-3.5 cursor-pointer" onClick={handleDelete} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -102,10 +115,10 @@ export function AgentTools() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<section className="space-y-2.5">
|
<section className="space-y-2.5">
|
||||||
<span className="text-text-secondary">{t('flow.tools')}</span>
|
<span className="text-text-secondary text-sm">{t('flow.tools')}</span>
|
||||||
<ul className="space-y-2">
|
<ul className="space-y-2.5">
|
||||||
{toolNames.map((x) => (
|
{toolNames.map((x) => (
|
||||||
<ToolCard key={x}>
|
<ToolCard key={x} isNodeTool={false}>
|
||||||
<div className="flex gap-2 items-center">
|
<div className="flex gap-2 items-center">
|
||||||
<OperatorIcon name={x as Operator}></OperatorIcon>
|
<OperatorIcon name={x as Operator}></OperatorIcon>
|
||||||
{x}
|
{x}
|
||||||
@ -118,7 +131,7 @@ export function AgentTools() {
|
|||||||
</ToolCard>
|
</ToolCard>
|
||||||
))}
|
))}
|
||||||
{mcpIds.map((id) => (
|
{mcpIds.map((id) => (
|
||||||
<ToolCard key={id}>
|
<ToolCard key={id} isNodeTool={false}>
|
||||||
{findMcpById(id)?.name}
|
{findMcpById(id)?.name}
|
||||||
<ActionButton
|
<ActionButton
|
||||||
record={id}
|
record={id}
|
||||||
@ -156,13 +169,13 @@ export function Agents({ node }: INextOperatorForm) {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<section className="space-y-2.5">
|
<section className="space-y-2.5">
|
||||||
<span className="text-text-secondary">{t('flow.agent')}</span>
|
<span className="text-text-secondary text-sm">{t('flow.agent')}</span>
|
||||||
<ul className="space-y-2">
|
<ul className="space-y-2.5">
|
||||||
{subBottomAgentNodeIds.map((id) => {
|
{subBottomAgentNodeIds.map((id) => {
|
||||||
const currentNode = getNode(id);
|
const currentNode = getNode(id);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ToolCard key={id}>
|
<ToolCard key={id} isNodeTool={false}>
|
||||||
{currentNode?.data.name}
|
{currentNode?.data.name}
|
||||||
<ActionButton
|
<ActionButton
|
||||||
record={id}
|
record={id}
|
||||||
|
|||||||
@ -1,5 +1,4 @@
|
|||||||
import { Collapse } from '@/components/collapse';
|
import { Collapse } from '@/components/collapse';
|
||||||
import { FormContainer } from '@/components/form-container';
|
|
||||||
import {
|
import {
|
||||||
LargeModelFilterFormSchema,
|
LargeModelFilterFormSchema,
|
||||||
LargeModelFormField,
|
LargeModelFormField,
|
||||||
@ -15,6 +14,7 @@ import {
|
|||||||
FormLabel,
|
FormLabel,
|
||||||
} from '@/components/ui/form';
|
} from '@/components/ui/form';
|
||||||
import { Input, NumberInput } from '@/components/ui/input';
|
import { Input, NumberInput } from '@/components/ui/input';
|
||||||
|
import { Separator } from '@/components/ui/separator';
|
||||||
import { Switch } from '@/components/ui/switch';
|
import { Switch } from '@/components/ui/switch';
|
||||||
import { LlmModelType } from '@/constants/knowledge';
|
import { LlmModelType } from '@/constants/knowledge';
|
||||||
import { useFindLlmByUuid } from '@/hooks/use-llm-request';
|
import { useFindLlmByUuid } from '@/hooks/use-llm-request';
|
||||||
@ -124,66 +124,53 @@ function AgentForm({ node }: INextOperatorForm) {
|
|||||||
return (
|
return (
|
||||||
<Form {...form}>
|
<Form {...form}>
|
||||||
<FormWrapper>
|
<FormWrapper>
|
||||||
<FormContainer>
|
{isSubAgent && <DescriptionField></DescriptionField>}
|
||||||
{isSubAgent && <DescriptionField></DescriptionField>}
|
<LargeModelFormField showSpeech2TextModel></LargeModelFormField>
|
||||||
<LargeModelFormField showSpeech2TextModel></LargeModelFormField>
|
{findLlmByUuid(llmId)?.model_type === LlmModelType.Image2text && (
|
||||||
{findLlmByUuid(llmId)?.model_type === LlmModelType.Image2text && (
|
<QueryVariable
|
||||||
<QueryVariable
|
name="visual_files_var"
|
||||||
name="visual_files_var"
|
label="Visual Input File"
|
||||||
label="Visual Input File"
|
type={VariableType.File}
|
||||||
type={VariableType.File}
|
></QueryVariable>
|
||||||
></QueryVariable>
|
)}
|
||||||
|
<FormField
|
||||||
|
control={form.control}
|
||||||
|
name={`sys_prompt`}
|
||||||
|
render={({ field }) => (
|
||||||
|
<FormItem className="flex-1">
|
||||||
|
<FormLabel>{t('flow.systemPrompt')}</FormLabel>
|
||||||
|
<FormControl>
|
||||||
|
<PromptEditor
|
||||||
|
{...field}
|
||||||
|
placeholder={t('flow.messagePlaceholder')}
|
||||||
|
showToolbar={true}
|
||||||
|
extraOptions={extraOptions}
|
||||||
|
></PromptEditor>
|
||||||
|
</FormControl>
|
||||||
|
</FormItem>
|
||||||
)}
|
)}
|
||||||
</FormContainer>
|
/>
|
||||||
|
{isSubAgent || (
|
||||||
<FormContainer>
|
|
||||||
<FormField
|
<FormField
|
||||||
control={form.control}
|
control={form.control}
|
||||||
name={`sys_prompt`}
|
name={`prompts`}
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem className="flex-1">
|
<FormItem className="flex-1">
|
||||||
<FormLabel>{t('flow.systemPrompt')}</FormLabel>
|
<FormLabel>{t('flow.userPrompt')}</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<PromptEditor
|
<section>
|
||||||
{...field}
|
<PromptEditor {...field} showToolbar={true}></PromptEditor>
|
||||||
placeholder={t('flow.messagePlaceholder')}
|
</section>
|
||||||
showToolbar={true}
|
|
||||||
extraOptions={extraOptions}
|
|
||||||
></PromptEditor>
|
|
||||||
</FormControl>
|
</FormControl>
|
||||||
</FormItem>
|
</FormItem>
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
</FormContainer>
|
|
||||||
{isSubAgent || (
|
|
||||||
<FormContainer>
|
|
||||||
{/* <DynamicPrompt></DynamicPrompt> */}
|
|
||||||
<FormField
|
|
||||||
control={form.control}
|
|
||||||
name={`prompts`}
|
|
||||||
render={({ field }) => (
|
|
||||||
<FormItem className="flex-1">
|
|
||||||
<FormLabel>{t('flow.userPrompt')}</FormLabel>
|
|
||||||
<FormControl>
|
|
||||||
<section>
|
|
||||||
<PromptEditor
|
|
||||||
{...field}
|
|
||||||
showToolbar={true}
|
|
||||||
></PromptEditor>
|
|
||||||
</section>
|
|
||||||
</FormControl>
|
|
||||||
</FormItem>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
</FormContainer>
|
|
||||||
)}
|
)}
|
||||||
|
<Separator></Separator>
|
||||||
<FormContainer>
|
<AgentTools></AgentTools>
|
||||||
<AgentTools></AgentTools>
|
<Agents node={node}></Agents>
|
||||||
<Agents node={node}></Agents>
|
|
||||||
</FormContainer>
|
|
||||||
<Collapse title={<div>{t('flow.advancedSettings')}</div>}>
|
<Collapse title={<div>{t('flow.advancedSettings')}</div>}>
|
||||||
<FormContainer>
|
<section className="space-y-5">
|
||||||
<MessageHistoryWindowSizeFormField></MessageHistoryWindowSizeFormField>
|
<MessageHistoryWindowSizeFormField></MessageHistoryWindowSizeFormField>
|
||||||
<FormField
|
<FormField
|
||||||
control={form.control}
|
control={form.control}
|
||||||
@ -270,7 +257,7 @@ function AgentForm({ node }: INextOperatorForm) {
|
|||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</FormContainer>
|
</section>
|
||||||
</Collapse>
|
</Collapse>
|
||||||
<Output list={outputList}></Output>
|
<Output list={outputList}></Output>
|
||||||
</FormWrapper>
|
</FormWrapper>
|
||||||
|
|||||||
@ -147,53 +147,48 @@ export function QueryTable({ data = [], deleteRecord, showModal }: IProps) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="w-full">
|
<div className="rounded-md border w-full bg-bg-card">
|
||||||
<div className="rounded-md border">
|
<Table rootClassName="rounded-md">
|
||||||
<Table rootClassName="rounded-md">
|
<TableHeader className="bg-bg-card">
|
||||||
<TableHeader>
|
{table.getHeaderGroups().map((headerGroup) => (
|
||||||
{table.getHeaderGroups().map((headerGroup) => (
|
<TableRow key={headerGroup.id}>
|
||||||
<TableRow key={headerGroup.id}>
|
{headerGroup.headers.map((header) => {
|
||||||
{headerGroup.headers.map((header) => {
|
return (
|
||||||
return (
|
<TableHead key={header.id}>
|
||||||
<TableHead key={header.id}>
|
{header.isPlaceholder
|
||||||
{header.isPlaceholder
|
? null
|
||||||
? null
|
: flexRender(
|
||||||
: flexRender(
|
header.column.columnDef.header,
|
||||||
header.column.columnDef.header,
|
header.getContext(),
|
||||||
header.getContext(),
|
)}
|
||||||
)}
|
</TableHead>
|
||||||
</TableHead>
|
);
|
||||||
);
|
})}
|
||||||
})}
|
</TableRow>
|
||||||
|
))}
|
||||||
|
</TableHeader>
|
||||||
|
<TableBody>
|
||||||
|
{table.getRowModel().rows?.length ? (
|
||||||
|
table.getRowModel().rows.map((row) => (
|
||||||
|
<TableRow
|
||||||
|
key={row.id}
|
||||||
|
data-state={row.getIsSelected() && 'selected'}
|
||||||
|
>
|
||||||
|
{row.getVisibleCells().map((cell) => (
|
||||||
|
<TableCell
|
||||||
|
key={cell.id}
|
||||||
|
className={cn(cell.column.columnDef.meta?.cellClassName)}
|
||||||
|
>
|
||||||
|
{flexRender(cell.column.columnDef.cell, cell.getContext())}
|
||||||
|
</TableCell>
|
||||||
|
))}
|
||||||
</TableRow>
|
</TableRow>
|
||||||
))}
|
))
|
||||||
</TableHeader>
|
) : (
|
||||||
<TableBody>
|
<TableEmpty columnsLength={columns.length}></TableEmpty>
|
||||||
{table.getRowModel().rows?.length ? (
|
)}
|
||||||
table.getRowModel().rows.map((row) => (
|
</TableBody>
|
||||||
<TableRow
|
</Table>
|
||||||
key={row.id}
|
|
||||||
data-state={row.getIsSelected() && 'selected'}
|
|
||||||
>
|
|
||||||
{row.getVisibleCells().map((cell) => (
|
|
||||||
<TableCell
|
|
||||||
key={cell.id}
|
|
||||||
className={cn(cell.column.columnDef.meta?.cellClassName)}
|
|
||||||
>
|
|
||||||
{flexRender(
|
|
||||||
cell.column.columnDef.cell,
|
|
||||||
cell.getContext(),
|
|
||||||
)}
|
|
||||||
</TableCell>
|
|
||||||
))}
|
|
||||||
</TableRow>
|
|
||||||
))
|
|
||||||
) : (
|
|
||||||
<TableEmpty columnsLength={columns.length}></TableEmpty>
|
|
||||||
)}
|
|
||||||
</TableBody>
|
|
||||||
</Table>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,4 @@
|
|||||||
.typeahead-popover {
|
.typeahead-popover {
|
||||||
background: #fff;
|
|
||||||
box-shadow: 0px 5px 10px rgba(0, 0, 0, 0.3);
|
box-shadow: 0px 5px 10px rgba(0, 0, 0, 0.3);
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
position: fixed;
|
position: fixed;
|
||||||
@ -10,16 +9,6 @@
|
|||||||
list-style: none;
|
list-style: none;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
max-height: 200px;
|
max-height: 200px;
|
||||||
overflow-y: scroll;
|
|
||||||
}
|
|
||||||
|
|
||||||
.typeahead-popover ul::-webkit-scrollbar {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.typeahead-popover ul {
|
|
||||||
-ms-overflow-style: none;
|
|
||||||
scrollbar-width: none;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.typeahead-popover ul li {
|
.typeahead-popover ul li {
|
||||||
@ -28,7 +17,6 @@
|
|||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
outline: none;
|
outline: none;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
border-radius: 8px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.typeahead-popover ul li.selected {
|
.typeahead-popover ul li.selected {
|
||||||
@ -37,7 +25,6 @@
|
|||||||
|
|
||||||
.typeahead-popover li {
|
.typeahead-popover li {
|
||||||
margin: 0 8px 0 8px;
|
margin: 0 8px 0 8px;
|
||||||
color: #050505;
|
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
line-height: 16px;
|
line-height: 16px;
|
||||||
font-size: 15px;
|
font-size: 15px;
|
||||||
@ -45,7 +32,6 @@
|
|||||||
align-content: center;
|
align-content: center;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
background-color: #fff;
|
|
||||||
border: 0;
|
border: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -89,7 +89,7 @@ function PromptContent({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<section
|
<section
|
||||||
className={cn('border rounded-sm ', { 'border-blue-400': !isBlur })}
|
className={cn('border rounded-sm ', { 'border-accent-primary': !isBlur })}
|
||||||
>
|
>
|
||||||
{showToolbar && (
|
{showToolbar && (
|
||||||
<div className="border-b px-2 py-2 justify-end flex">
|
<div className="border-b px-2 py-2 justify-end flex">
|
||||||
@ -107,7 +107,7 @@ function PromptContent({
|
|||||||
)}
|
)}
|
||||||
<ContentEditable
|
<ContentEditable
|
||||||
className={cn(
|
className={cn(
|
||||||
'relative px-2 py-1 focus-visible:outline-none max-h-[50vh] overflow-auto',
|
'relative px-2 py-1 focus-visible:outline-none max-h-[50vh] overflow-auto text-sm',
|
||||||
{
|
{
|
||||||
'min-h-40': multiLine,
|
'min-h-40': multiLine,
|
||||||
},
|
},
|
||||||
@ -163,7 +163,7 @@ export function PromptEditor({
|
|||||||
placeholder={
|
placeholder={
|
||||||
<div
|
<div
|
||||||
className={cn(
|
className={cn(
|
||||||
'absolute top-1 left-2 text-text-secondary pointer-events-none',
|
'absolute top-1 left-2 text-text-disabled pointer-events-none',
|
||||||
{
|
{
|
||||||
'truncate w-[90%]': !multiLine,
|
'truncate w-[90%]': !multiLine,
|
||||||
'translate-y-10': multiLine,
|
'translate-y-10': multiLine,
|
||||||
|
|||||||
@ -49,7 +49,7 @@ export class VariableNode extends DecoratorNode<ReactNode> {
|
|||||||
|
|
||||||
decorate(): ReactNode {
|
decorate(): ReactNode {
|
||||||
let content: ReactNode = (
|
let content: ReactNode = (
|
||||||
<div className="text-blue-600">{this.__label}</div>
|
<div className="text-accent-primary">{this.__label}</div>
|
||||||
);
|
);
|
||||||
if (this.__parentLabel) {
|
if (this.__parentLabel) {
|
||||||
content = (
|
content = (
|
||||||
@ -62,7 +62,7 @@ export class VariableNode extends DecoratorNode<ReactNode> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<div className="bg-gray-200 dark:bg-gray-400 text-sm inline-flex items-center rounded-md px-2 py-1">
|
<div className="bg-accent-primary-5 text-sm inline-flex items-center rounded-md px-2 py-1">
|
||||||
{content}
|
{content}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -91,13 +91,13 @@ function VariablePickerMenuItem({
|
|||||||
id={'typeahead-item-' + index}
|
id={'typeahead-item-' + index}
|
||||||
>
|
>
|
||||||
<div>
|
<div>
|
||||||
<span className="text text-slate-500">{option.title}</span>
|
<span className="text text-text-secondary">{option.title}</span>
|
||||||
<ul className="pl-2 py-1">
|
<ul className="pl-2 py-1">
|
||||||
{option.options.map((x) => (
|
{option.options.map((x) => (
|
||||||
<li
|
<li
|
||||||
key={x.value}
|
key={x.value}
|
||||||
onClick={() => selectOptionAndCleanUp(x)}
|
onClick={() => selectOptionAndCleanUp(x)}
|
||||||
className="hover:bg-slate-300 p-1"
|
className="hover:bg-bg-card p-1 text-text-primary rounded-sm"
|
||||||
>
|
>
|
||||||
{x.label}
|
{x.label}
|
||||||
</li>
|
</li>
|
||||||
@ -335,8 +335,8 @@ export default function VariablePickerMenuPlugin({
|
|||||||
const nextOptions = buildNextOptions();
|
const nextOptions = buildNextOptions();
|
||||||
return anchorElementRef.current && nextOptions.length
|
return anchorElementRef.current && nextOptions.length
|
||||||
? ReactDOM.createPortal(
|
? ReactDOM.createPortal(
|
||||||
<div className="typeahead-popover w-[200px] p-2">
|
<div className="typeahead-popover w-[200px] p-2 bg-bg-base">
|
||||||
<ul className="overflow-y-auto !scrollbar-thin overflow-x-hidden">
|
<ul className="scroll-auto overflow-x-hidden">
|
||||||
{nextOptions.map((option, i: number) => (
|
{nextOptions.map((option, i: number) => (
|
||||||
<VariablePickerMenuItem
|
<VariablePickerMenuItem
|
||||||
index={i}
|
index={i}
|
||||||
|
|||||||
11
web/src/pages/agent/hooks/use-is-mcp.ts
Normal file
11
web/src/pages/agent/hooks/use-is-mcp.ts
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
import { Operator } from '../constant';
|
||||||
|
import useGraphStore from '../store';
|
||||||
|
|
||||||
|
export function useIsMcp(operatorName: Operator) {
|
||||||
|
const clickedToolId = useGraphStore((state) => state.clickedToolId);
|
||||||
|
|
||||||
|
return (
|
||||||
|
operatorName === Operator.Tool &&
|
||||||
|
Object.values(Operator).every((x) => x !== clickedToolId)
|
||||||
|
);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user