Files
ragflow/web/src/utils/canvas-util.tsx
buua436 daf8a58c4b Fix: add codeexec attachments output (#14787)
### What problem does this PR solve?

add codeexec attachments output

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2026-05-11 19:16:33 +08:00

153 lines
3.6 KiB
TypeScript

import {
AgentStructuredOutputField,
JsonSchemaDataType,
Operator,
} from '@/constants/agent';
import { BaseNode } from '@/interfaces/database/agent';
import OperatorIcon from '@/pages/agent/operator-icon';
import { Edge } from '@xyflow/react';
import { get, isEmpty } from 'lodash';
import { ReactNode } from 'react';
export function filterAllUpstreamNodeIds(edges: Edge[], nodeIds: string[]) {
return nodeIds.reduce<string[]>((pre, nodeId) => {
const currentEdges = edges.filter((x) => x.target === nodeId);
const upstreamNodeIds: string[] = currentEdges.map((x) => x.source);
const ids = upstreamNodeIds.concat(
filterAllUpstreamNodeIds(edges, upstreamNodeIds),
);
ids.forEach((x) => {
if (pre.every((y) => y !== x)) {
pre.push(x);
}
});
return pre;
}, []);
}
export function filterChildNodeIds(nodes: BaseNode[], nodeId?: string) {
return nodes.filter((x) => x.parentId === nodeId).map((x) => x.id);
}
export function isAgentStructured(id?: string, label?: string) {
return (
label === AgentStructuredOutputField && id?.startsWith(`${Operator.Agent}:`)
);
}
export function buildVariableValue(value: string, nodeId?: string) {
return `${nodeId}@${value}`;
}
export function buildSecondaryOutputOptions(
outputs: Record<string, any> = {},
nodeId?: string,
parentLabel?: string | ReactNode,
icon?: ReactNode,
) {
return Object.keys(outputs).map((x) => ({
label: x,
value: buildVariableValue(x, nodeId),
parentLabel,
icon,
type: isAgentStructured(nodeId, x)
? JsonSchemaDataType.Object
: outputs[x]?.type,
}));
}
function getNodeOutputs(x: BaseNode) {
const outputs = x.data.form?.outputs ?? {};
if (x.data.label !== Operator.Code) {
return outputs;
}
return {
...outputs,
content: outputs.content ?? {
type: JsonSchemaDataType.String,
value: '',
},
attachments: outputs.attachments ?? {
type: 'Array<String>',
value: [],
},
};
}
export function buildOutputOptions(x: BaseNode) {
return {
label: x.data.name,
value: x.id,
title: x.data.name,
options: buildSecondaryOutputOptions(
getNodeOutputs(x),
x.id,
x.data.name,
<OperatorIcon name={x.data.label as Operator} />,
),
};
}
export function buildNodeOutputOptions({
nodes, // all nodes
nodeIds, // Need to obtain the output node IDs
}: {
nodes: BaseNode[];
nodeIds: string[];
}) {
const nodeWithOutputList = nodes.filter(
(x) => nodeIds.some((y) => y === x.id) && !isEmpty(getNodeOutputs(x)),
);
return nodeWithOutputList.map((x) => buildOutputOptions(x));
}
export function buildUpstreamNodeOutputOptions({
nodes,
edges,
nodeId,
}: {
nodes: BaseNode[];
edges: Edge[];
nodeId?: string;
}) {
if (!nodeId) {
return [];
}
const upstreamIds = filterAllUpstreamNodeIds(edges, [nodeId]);
return buildNodeOutputOptions({ nodes, nodeIds: upstreamIds });
}
export function buildChildOutputOptions({
nodes,
nodeId,
}: {
nodes: BaseNode[];
nodeId?: string;
}) {
const nodeWithOutputList = nodes.filter(
(x) => x.parentId === nodeId && !isEmpty(getNodeOutputs(x)),
);
return nodeWithOutputList.map((x) => buildOutputOptions(x));
}
export function getStructuredDatatype(value: Record<string, any> | unknown) {
const dataType = get(value, 'type');
const arrayItemsType = get(value, 'items.type', JsonSchemaDataType.String);
const compositeDataType =
dataType === JsonSchemaDataType.Array
? `${dataType}<${arrayItemsType}>`
: dataType;
return { dataType, compositeDataType };
}