feat(web): 完成子流程节点和代码节点的运行
This commit is contained in:
@@ -86,6 +86,11 @@
|
|||||||
<groupId>org.noear</groupId>
|
<groupId>org.noear</groupId>
|
||||||
<artifactId>solon-ai-dialect-openai</artifactId>
|
<artifactId>solon-ai-dialect-openai</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.yomahub</groupId>
|
||||||
|
<artifactId>liteflow-script-graaljs</artifactId>
|
||||||
|
<version>${liteflow.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.hibernate.orm</groupId>
|
<groupId>org.hibernate.orm</groupId>
|
||||||
|
|||||||
@@ -27,6 +27,8 @@ import org.springframework.scheduling.annotation.EnableScheduling;
|
|||||||
public class WebApplication implements ApplicationRunner {
|
public class WebApplication implements ApplicationRunner {
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
|
System.setProperty("polyglot.engine.WarnInterpreterOnly", "false");
|
||||||
|
|
||||||
SpringApplication.run(WebApplication.class, args);
|
SpringApplication.run(WebApplication.class, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package com.lanyuanxiaoyao.service.ai.web.engine;
|
package com.lanyuanxiaoyao.service.ai.web.engine;
|
||||||
|
|
||||||
|
import cn.hutool.core.util.IdUtil;
|
||||||
import cn.hutool.core.util.ObjectUtil;
|
import cn.hutool.core.util.ObjectUtil;
|
||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
import com.lanyuanxiaoyao.service.ai.web.engine.entity.FlowContext;
|
import com.lanyuanxiaoyao.service.ai.web.engine.entity.FlowContext;
|
||||||
@@ -44,8 +45,10 @@ public final class FlowGraphRunner {
|
|||||||
flowStore.init(flowGraph);
|
flowStore.init(flowGraph);
|
||||||
|
|
||||||
for (FlowNode node : flowGraph.nodes()) {
|
for (FlowNode node : flowGraph.nodes()) {
|
||||||
|
if (ObjectUtil.isNull(node.parentId())) {
|
||||||
executionQueue.offer(node);
|
executionQueue.offer(node);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
while (!executionQueue.isEmpty()) {
|
while (!executionQueue.isEmpty()) {
|
||||||
var node = executionQueue.poll();
|
var node = executionQueue.poll();
|
||||||
if (ObjectUtil.isNull(node)) {
|
if (ObjectUtil.isNull(node)) {
|
||||||
@@ -77,8 +80,17 @@ public final class FlowGraphRunner {
|
|||||||
var runner = runnerClazz.getDeclaredConstructor().newInstance();
|
var runner = runnerClazz.getDeclaredConstructor().newInstance();
|
||||||
runner.setNodeId(node.id());
|
runner.setNodeId(node.id());
|
||||||
runner.setContext(context);
|
runner.setContext(context);
|
||||||
|
|
||||||
|
// 处理子流程节点的逻辑
|
||||||
|
if (runner instanceof FlowNodeSubflowRunner subflowRunner) {
|
||||||
|
var subflowNodes = flowGraph.nodes().select(n -> StrUtil.equals(n.parentId(), node.id()));
|
||||||
|
var subGraph = new FlowGraph(IdUtil.fastUUID(), subflowNodes, flowGraph.edges());
|
||||||
|
subflowRunner.setSubGraph(subGraph);
|
||||||
|
}
|
||||||
|
|
||||||
runner.run();
|
runner.run();
|
||||||
|
|
||||||
|
// 处理选择节点的逻辑
|
||||||
if (runner instanceof FlowNodeOptionalRunner) {
|
if (runner instanceof FlowNodeOptionalRunner) {
|
||||||
var targetPoint = ((FlowNodeOptionalRunner) runner).getTargetPoint();
|
var targetPoint = ((FlowNodeOptionalRunner) runner).getTargetPoint();
|
||||||
for (FlowEdge edge : nodeOutputMap.get(node.id())) {
|
for (FlowEdge edge : nodeOutputMap.get(node.id())) {
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
package com.lanyuanxiaoyao.service.ai.web.engine;
|
||||||
|
|
||||||
|
import com.lanyuanxiaoyao.service.ai.web.engine.entity.FlowGraph;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 包含子流程的流程
|
||||||
|
*
|
||||||
|
* @author lanyuanxiaoyao
|
||||||
|
* @version 20250717
|
||||||
|
*/
|
||||||
|
public abstract class FlowNodeSubflowRunner extends FlowNodeRunner {
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
private FlowGraph subGraph;
|
||||||
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
package com.lanyuanxiaoyao.service.ai.web.engine.entity;
|
package com.lanyuanxiaoyao.service.ai.web.engine.entity;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -12,7 +13,9 @@ public record FlowEdge(
|
|||||||
String id,
|
String id,
|
||||||
String source,
|
String source,
|
||||||
String target,
|
String target,
|
||||||
|
@JsonProperty("sourceHandle")
|
||||||
String sourcePoint,
|
String sourcePoint,
|
||||||
|
@JsonProperty("targetHandle")
|
||||||
String targetPoint
|
String targetPoint
|
||||||
) {
|
) {
|
||||||
public enum Status {
|
public enum Status {
|
||||||
|
|||||||
@@ -10,7 +10,8 @@ import java.time.LocalDateTime;
|
|||||||
*/
|
*/
|
||||||
public record FlowNode(
|
public record FlowNode(
|
||||||
String id,
|
String id,
|
||||||
String type
|
String type,
|
||||||
|
String parentId
|
||||||
) {
|
) {
|
||||||
public enum Status {
|
public enum Status {
|
||||||
INITIAL, RUNNING, FINISHED, SKIPPED
|
INITIAL, RUNNING, FINISHED, SKIPPED
|
||||||
|
|||||||
@@ -0,0 +1,33 @@
|
|||||||
|
package com.lanyuanxiaoyao.service.ai.web.engine.node;
|
||||||
|
|
||||||
|
import cn.hutool.core.util.ObjectUtil;
|
||||||
|
import cn.hutool.core.util.StrUtil;
|
||||||
|
import com.lanyuanxiaoyao.service.ai.web.engine.FlowHelper;
|
||||||
|
import com.lanyuanxiaoyao.service.ai.web.engine.FlowNodeRunner;
|
||||||
|
import com.lanyuanxiaoyao.service.ai.web.engine.node.code.CodeExecutor;
|
||||||
|
import com.lanyuanxiaoyao.service.ai.web.engine.node.code.JavaScriptCodeExecutor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author lanyuanxiaoyao
|
||||||
|
* @version 20250717
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
public class CodeNode extends FlowNodeRunner {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
var inputVariablesMap = FlowHelper.generateInputVariablesMap(getNodeId(), getContext());
|
||||||
|
var type = this.<String>getData("type");
|
||||||
|
var script = this.<String>getData("content");
|
||||||
|
CodeExecutor executor = null;
|
||||||
|
switch (type) {
|
||||||
|
case "javascript":
|
||||||
|
executor = new JavaScriptCodeExecutor();
|
||||||
|
}
|
||||||
|
if (ObjectUtil.isNull(executor)) {
|
||||||
|
throw new RuntimeException(StrUtil.format("Unsupported type: {}", type));
|
||||||
|
}
|
||||||
|
var result = executor.execute(script, inputVariablesMap);
|
||||||
|
result.forEachKeyValue(this::setData);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
package com.lanyuanxiaoyao.service.ai.web.engine.node;
|
||||||
|
|
||||||
|
import com.lanyuanxiaoyao.service.ai.web.engine.FlowNodeSubflowRunner;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 循环节点
|
||||||
|
*
|
||||||
|
* @author lanyuanxiaoyao
|
||||||
|
* @version 20250717
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
public class LoopNode extends FlowNodeSubflowRunner {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
log.info("{}", getSubGraph());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,65 @@
|
|||||||
|
package com.lanyuanxiaoyao.service.ai.web.engine.node;
|
||||||
|
|
||||||
|
import cn.hutool.core.bean.BeanUtil;
|
||||||
|
import cn.hutool.core.util.ObjectUtil;
|
||||||
|
import cn.hutool.core.util.StrUtil;
|
||||||
|
import com.lanyuanxiaoyao.service.ai.web.engine.FlowHelper;
|
||||||
|
import com.lanyuanxiaoyao.service.ai.web.engine.FlowNodeOptionalRunner;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author lanyuanxiaoyao
|
||||||
|
* @version 20250717
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
@Slf4j
|
||||||
|
public class SwitchNode extends FlowNodeOptionalRunner {
|
||||||
|
@Override
|
||||||
|
public String runOptional() {
|
||||||
|
var conditions = this.<List<Map<String, Object>>>getData("conditions");
|
||||||
|
for (Map<String, Object> item : conditions) {
|
||||||
|
var condition = (Map<String, Object>) item.getOrDefault("condition", Map.of());
|
||||||
|
var id = (String) condition.getOrDefault("id", "");
|
||||||
|
var conjunction = (String) condition.getOrDefault("conjunction", "and");
|
||||||
|
var conditionChildren = ((List<Map<String, Object>>) condition.getOrDefault("children", List.<Map<String, Object>>of()));
|
||||||
|
if (
|
||||||
|
StrUtil.equals(conjunction, "and")
|
||||||
|
&& conditionChildren.stream().allMatch(this::check)
|
||||||
|
) {
|
||||||
|
return id;
|
||||||
|
} else if (
|
||||||
|
StrUtil.equals(conjunction, "or")
|
||||||
|
&& conditionChildren.stream().anyMatch(this::check)
|
||||||
|
) {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
private Boolean check(Map<String, Object> condition) {
|
||||||
|
var leftVariable = (String) BeanUtil.getProperty(condition, "left.field");
|
||||||
|
var left = FlowHelper.generateVariable(leftVariable, getContext());
|
||||||
|
var operator = (String) condition.get("op");
|
||||||
|
var right = condition.get("right");
|
||||||
|
if (right instanceof Map<?, ?>) {
|
||||||
|
var rightVariable = (String) BeanUtil.getProperty(condition, "right.field");
|
||||||
|
if (StrUtil.isNotBlank(rightVariable)) {
|
||||||
|
right = FlowHelper.generateVariable(rightVariable, getContext());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return switch (operator) {
|
||||||
|
case "equal" -> ObjectUtil.equals(left, right);
|
||||||
|
case "not_equal" -> ObjectUtil.notEqual(left, right);
|
||||||
|
case "is_empty" -> ObjectUtil.isEmpty(left);
|
||||||
|
case "is_not_empty" -> ObjectUtil.isNotEmpty(left);
|
||||||
|
case "like" -> StrUtil.contains((String) left, (String) right);
|
||||||
|
case "not_like" -> !StrUtil.contains((String) left, (String) right);
|
||||||
|
case "starts_with" -> StrUtil.startWith((String) left, (String) right);
|
||||||
|
case "ends_with" -> StrUtil.endWith((String) left, (String) right);
|
||||||
|
default -> false;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package com.lanyuanxiaoyao.service.ai.web.engine.node.code;
|
||||||
|
|
||||||
|
import org.eclipse.collections.api.map.ImmutableMap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author lanyuanxiaoyao
|
||||||
|
* @version 20250717
|
||||||
|
*/
|
||||||
|
public interface CodeExecutor {
|
||||||
|
ImmutableMap<String, Object> execute(String script, ImmutableMap<String, Object> inputVariablesMap);
|
||||||
|
}
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
package com.lanyuanxiaoyao.service.ai.web.engine.node.code;
|
||||||
|
|
||||||
|
import cn.hutool.core.util.StrUtil;
|
||||||
|
import org.eclipse.collections.api.factory.Maps;
|
||||||
|
import org.eclipse.collections.api.map.ImmutableMap;
|
||||||
|
import org.graalvm.polyglot.Context;
|
||||||
|
import org.graalvm.polyglot.Engine;
|
||||||
|
import org.graalvm.polyglot.Source;
|
||||||
|
import org.graalvm.polyglot.TypeLiteral;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author lanyuanxiaoyao
|
||||||
|
* @version 20250717
|
||||||
|
*/
|
||||||
|
public class JavaScriptCodeExecutor implements CodeExecutor{
|
||||||
|
@Override
|
||||||
|
public ImmutableMap<String, Object> execute(String script, ImmutableMap<String, Object> inputVariablesMap) {
|
||||||
|
if (StrUtil.isBlank(script)) {
|
||||||
|
return Maps.immutable.empty();
|
||||||
|
}
|
||||||
|
try (var engin = Engine.create()) {
|
||||||
|
try (
|
||||||
|
var context = Context.newBuilder()
|
||||||
|
.allowAllAccess(true)
|
||||||
|
.engine(engin)
|
||||||
|
.build()
|
||||||
|
) {
|
||||||
|
var bindings = context.getBindings("js");
|
||||||
|
inputVariablesMap.forEachKeyValue(bindings::putMember);
|
||||||
|
var result = context.eval(
|
||||||
|
Source.create(
|
||||||
|
"js",
|
||||||
|
"""
|
||||||
|
function process() {
|
||||||
|
%s
|
||||||
|
}
|
||||||
|
process();
|
||||||
|
""".formatted(script)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
return Maps.immutable.ofAll(result.as(new TypeLiteral<>() {}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -10,12 +10,16 @@ import com.lanyuanxiaoyao.service.ai.web.engine.entity.FlowContext;
|
|||||||
import com.lanyuanxiaoyao.service.ai.web.engine.entity.FlowEdge;
|
import com.lanyuanxiaoyao.service.ai.web.engine.entity.FlowEdge;
|
||||||
import com.lanyuanxiaoyao.service.ai.web.engine.entity.FlowGraph;
|
import com.lanyuanxiaoyao.service.ai.web.engine.entity.FlowGraph;
|
||||||
import com.lanyuanxiaoyao.service.ai.web.engine.entity.FlowNode;
|
import com.lanyuanxiaoyao.service.ai.web.engine.entity.FlowNode;
|
||||||
|
import com.lanyuanxiaoyao.service.ai.web.engine.node.CodeNode;
|
||||||
import com.lanyuanxiaoyao.service.ai.web.engine.node.LlmNode;
|
import com.lanyuanxiaoyao.service.ai.web.engine.node.LlmNode;
|
||||||
|
import com.lanyuanxiaoyao.service.ai.web.engine.node.LoopNode;
|
||||||
import com.lanyuanxiaoyao.service.ai.web.engine.node.OutputNode;
|
import com.lanyuanxiaoyao.service.ai.web.engine.node.OutputNode;
|
||||||
|
import com.lanyuanxiaoyao.service.ai.web.engine.node.SwitchNode;
|
||||||
import com.lanyuanxiaoyao.service.ai.web.engine.store.InMemoryFlowStore;
|
import com.lanyuanxiaoyao.service.ai.web.engine.store.InMemoryFlowStore;
|
||||||
import com.lanyuanxiaoyao.service.ai.web.entity.FlowTask;
|
import com.lanyuanxiaoyao.service.ai.web.entity.FlowTask;
|
||||||
import com.lanyuanxiaoyao.service.ai.web.repository.FlowTaskRepository;
|
import com.lanyuanxiaoyao.service.ai.web.repository.FlowTaskRepository;
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import java.util.Map;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.eclipse.collections.api.factory.Maps;
|
import org.eclipse.collections.api.factory.Maps;
|
||||||
@@ -38,14 +42,18 @@ public class FlowTaskService extends SimpleServiceSupport<FlowTask> {
|
|||||||
var flowTask = detailOrThrow(id);
|
var flowTask = detailOrThrow(id);
|
||||||
var graphVo = mapper.readValue(flowTask.getTemplateFlowGraph(), FlowGraphVo.class);
|
var graphVo = mapper.readValue(flowTask.getTemplateFlowGraph(), FlowGraphVo.class);
|
||||||
var flowGraph = new FlowGraph(IdUtil.fastUUID(), graphVo.getNodes(), graphVo.getEdges());
|
var flowGraph = new FlowGraph(IdUtil.fastUUID(), graphVo.getNodes(), graphVo.getEdges());
|
||||||
|
log.info("Graph: {}", flowGraph);
|
||||||
|
|
||||||
var store = new InMemoryFlowStore();
|
var store = new InMemoryFlowStore();
|
||||||
var executor = new FlowExecutor(
|
var executor = new FlowExecutor(
|
||||||
store,
|
store,
|
||||||
Maps.immutable.of(
|
Maps.immutable.ofAll(Map.of(
|
||||||
"output-node", OutputNode.class,
|
"loop-node", LoopNode.class,
|
||||||
"llm-node", LlmNode.class
|
"switch-node", SwitchNode.class,
|
||||||
)
|
"code-node", CodeNode.class,
|
||||||
|
"llm-node", LlmNode.class,
|
||||||
|
"output-node", OutputNode.class
|
||||||
|
))
|
||||||
);
|
);
|
||||||
FlowContext context = new FlowContext();
|
FlowContext context = new FlowContext();
|
||||||
context.setInput(mapper.readValue(flowTask.getInput(), new TypeReference<>() {}));
|
context.setInput(mapper.readValue(flowTask.getInput(), new TypeReference<>() {}));
|
||||||
|
|||||||
@@ -35,15 +35,15 @@ public class TestFlow {
|
|||||||
var graph = new FlowGraph(
|
var graph = new FlowGraph(
|
||||||
"graph-1",
|
"graph-1",
|
||||||
Sets.immutable.of(
|
Sets.immutable.of(
|
||||||
new FlowNode("node-1", "plain-node"),
|
new FlowNode("node-1", "plain-node", null),
|
||||||
new FlowNode("node-2", "plain-node"),
|
new FlowNode("node-2", "plain-node", null),
|
||||||
new FlowNode("node-4", "plain-node"),
|
new FlowNode("node-4", "plain-node", null),
|
||||||
new FlowNode("node-6", "plain-node"),
|
new FlowNode("node-6", "plain-node", null),
|
||||||
new FlowNode("node-7", "plain-node"),
|
new FlowNode("node-7", "plain-node", null),
|
||||||
new FlowNode("node-5", "plain-node"),
|
new FlowNode("node-5", "plain-node", null),
|
||||||
new FlowNode("node-8", "option-node"),
|
new FlowNode("node-8", "option-node", null),
|
||||||
new FlowNode("node-9", "plain-node"),
|
new FlowNode("node-9", "plain-node", null),
|
||||||
new FlowNode("node-3", "plain-node")
|
new FlowNode("node-3", "plain-node", null)
|
||||||
),
|
),
|
||||||
Sets.immutable.of(
|
Sets.immutable.of(
|
||||||
new FlowEdge("edge-1", "node-1", "node-2", null, null),
|
new FlowEdge("edge-1", "node-1", "node-2", null, null),
|
||||||
|
|||||||
@@ -0,0 +1,57 @@
|
|||||||
|
package com.lanyuanxiaoyao.service.ai.web;
|
||||||
|
|
||||||
|
import cn.hutool.core.util.StrUtil;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.eclipse.collections.api.factory.Maps;
|
||||||
|
import org.eclipse.collections.api.map.ImmutableMap;
|
||||||
|
import org.graalvm.polyglot.Context;
|
||||||
|
import org.graalvm.polyglot.Engine;
|
||||||
|
import org.graalvm.polyglot.Source;
|
||||||
|
import org.graalvm.polyglot.TypeLiteral;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author lanyuanxiaoyao
|
||||||
|
* @version 20250717
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
public class TestJsExecutor {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
var result = executeJavascript(
|
||||||
|
// language=JavaScript
|
||||||
|
"return 'hello'",
|
||||||
|
Maps.immutable.of(
|
||||||
|
"code", 1
|
||||||
|
)
|
||||||
|
);
|
||||||
|
log.info("Result: {}", result);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ImmutableMap<String, Object> executeJavascript(String script, ImmutableMap<String, Object> inputVariablesMap) {
|
||||||
|
if (StrUtil.isBlank(script)) {
|
||||||
|
return Maps.immutable.empty();
|
||||||
|
}
|
||||||
|
try (var engin = Engine.create()) {
|
||||||
|
try (
|
||||||
|
var context = Context.newBuilder()
|
||||||
|
.allowAllAccess(true)
|
||||||
|
.engine(engin)
|
||||||
|
.build()
|
||||||
|
) {
|
||||||
|
var bindings = context.getBindings("js");
|
||||||
|
inputVariablesMap.forEachKeyValue(bindings::putMember);
|
||||||
|
var result = context.eval(
|
||||||
|
Source.create(
|
||||||
|
"js",
|
||||||
|
"""
|
||||||
|
function process() {
|
||||||
|
%s
|
||||||
|
}
|
||||||
|
process();
|
||||||
|
""".formatted(script)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
return Maps.immutable.ofAll(result.as(new TypeLiteral<>() {}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,11 +1,11 @@
|
|||||||
import {type Edge, getIncomers, type Node} from '@xyflow/react'
|
import {type Edge, getIncomers, type Node} from '@xyflow/react'
|
||||||
import type {Option} from 'amis/lib/Schema'
|
import type {Option} from 'amis/lib/Schema'
|
||||||
import {find, has, isEqual, max, min, unique} from 'licia'
|
import {contain, find, has, isEqual, max, min, unique} from 'licia'
|
||||||
import {type DependencyList, type MouseEvent as ReactMouseEvent, useCallback, useRef} from 'react'
|
import {type DependencyList, type MouseEvent as ReactMouseEvent, useCallback, useRef} from 'react'
|
||||||
import Queue from 'yocto-queue'
|
import Queue from 'yocto-queue'
|
||||||
import {originTypeMap} from '../../pages/ai/task/InputSchema.tsx'
|
import {originTypeMap} from '../../pages/ai/task/InputSchema.tsx'
|
||||||
import {useFlowStore} from './store/FlowStore.ts'
|
import {useFlowStore} from './store/FlowStore.ts'
|
||||||
import {type OutputVariable} from './types.ts'
|
import {type OutputVariable, type OutputVariableType} from './types.ts'
|
||||||
|
|
||||||
export const getAllIncomerNodeById: (id: string, nodes: Node[], edges: Edge[]) => string[] = (id, nodes, edges) => {
|
export const getAllIncomerNodeById: (id: string, nodes: Node[], edges: Edge[]) => string[] = (id, nodes, edges) => {
|
||||||
let queue = new Queue<Node>()
|
let queue = new Queue<Node>()
|
||||||
@@ -82,9 +82,12 @@ export const getAllIncomerNodeOutputVariables: (id: string, inputSchema: Record<
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
export const generateAllIncomerOutputVariablesFormOptions: (id: string, inputSchema: Record<string, Record<string, any>>, nodes: Node[], edges: Edge[], data: any) => Option[] = (id, inputSchema, nodes, edges, data) => {
|
export const generateAllIncomerOutputVariablesFormOptions: (id: string, inputSchema: Record<string, Record<string, any>>, nodes: Node[], edges: Edge[], data: any, targetTypes?: OutputVariableType[]) => Option[] = (id, inputSchema, nodes, edges, data, targetTypes) => {
|
||||||
let optionMap: Record<string, Option[]> = {}
|
let optionMap: Record<string, Option[]> = {}
|
||||||
for (const item of getAllIncomerNodeOutputVariables(id, inputSchema, nodes, edges, data)) {
|
for (const item of getAllIncomerNodeOutputVariables(id, inputSchema, nodes, edges, data)) {
|
||||||
|
if (targetTypes && !contain(targetTypes, item.type)) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
if (!optionMap[item.group]) {
|
if (!optionMap[item.group]) {
|
||||||
optionMap[item.group] = []
|
optionMap[item.group] = []
|
||||||
}
|
}
|
||||||
@@ -142,7 +145,7 @@ export const generateAllIncomerOutputVariablesConditions: (id: string, inputSche
|
|||||||
options: [
|
options: [
|
||||||
{label: '真', value: true},
|
{label: '真', value: true},
|
||||||
{label: '假', value: false},
|
{label: '假', value: false},
|
||||||
]
|
],
|
||||||
},
|
},
|
||||||
defaultOp: booleanDefaultOperator,
|
defaultOp: booleanDefaultOperator,
|
||||||
operators: booleanOperators,
|
operators: booleanOperators,
|
||||||
|
|||||||
Reference in New Issue
Block a user