Feat: Modify the style of the agent operator form #10703 (#10821)

### 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:
balibabu
2025-10-27 19:37:52 +08:00
committed by GitHub
parent 0089e2b30c
commit 0a78920bff
17 changed files with 204 additions and 179 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View 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>
);
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View 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)
);
}