diff --git a/experimental/agentic/pom.xml b/experimental/agentic/pom.xml
new file mode 100644
index 00000000..dec8a5e5
--- /dev/null
+++ b/experimental/agentic/pom.xml
@@ -0,0 +1,46 @@
+
+ 4.0.0
+
+ io.serverlessworkflow
+ serverlessworkflow-experimental
+ 8.0.0-SNAPSHOT
+
+ serverlessworkflow-experimental-agentic
+ ServelessWorkflow:: Experimental:: Agentic
+
+
+ io.serverlessworkflow
+ serverlessworkflow-experimental-lambda
+
+
+ dev.langchain4j
+ langchain4j-agentic
+
+
+ org.junit.jupiter
+ junit-jupiter-api
+ test
+
+
+ org.junit.jupiter
+ junit-jupiter-engine
+ test
+
+
+ org.junit.jupiter
+ junit-jupiter-params
+ test
+
+
+ org.assertj
+ assertj-core
+ test
+
+
+ ch.qos.logback
+ logback-classic
+ test
+
+
+
\ No newline at end of file
diff --git a/experimental/agentic/src/main/java/io/serverlessworkflow/impl/expressions/agentic/AgenticExpressionFactory.java b/experimental/agentic/src/main/java/io/serverlessworkflow/impl/expressions/agentic/AgenticExpressionFactory.java
new file mode 100644
index 00000000..a4b79a18
--- /dev/null
+++ b/experimental/agentic/src/main/java/io/serverlessworkflow/impl/expressions/agentic/AgenticExpressionFactory.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2020-Present The Serverless Workflow Specification Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.serverlessworkflow.impl.expressions.agentic;
+
+import io.serverlessworkflow.impl.WorkflowModelFactory;
+import io.serverlessworkflow.impl.expressions.func.JavaExpressionFactory;
+
+public class AgenticExpressionFactory extends JavaExpressionFactory {
+
+ private final WorkflowModelFactory modelFactory = new AgenticModelFactory();
+
+ @Override
+ public WorkflowModelFactory modelFactory() {
+ return modelFactory;
+ }
+
+ public int priority() {
+ return DEFAULT_PRIORITY - 1;
+ }
+}
diff --git a/experimental/agentic/src/main/java/io/serverlessworkflow/impl/expressions/agentic/AgenticModel.java b/experimental/agentic/src/main/java/io/serverlessworkflow/impl/expressions/agentic/AgenticModel.java
new file mode 100644
index 00000000..9ab57838
--- /dev/null
+++ b/experimental/agentic/src/main/java/io/serverlessworkflow/impl/expressions/agentic/AgenticModel.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2020-Present The Serverless Workflow Specification Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.serverlessworkflow.impl.expressions.agentic;
+
+import dev.langchain4j.agentic.cognisphere.Cognisphere;
+import dev.langchain4j.agentic.cognisphere.ResultWithCognisphere;
+import io.serverlessworkflow.impl.WorkflowModel;
+import io.serverlessworkflow.impl.expressions.func.JavaModel;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Optional;
+
+class AgenticModel extends JavaModel {
+
+ private final Cognisphere cognisphere;
+
+ AgenticModel(Object object, Cognisphere cognisphere) {
+ super(object);
+ this.cognisphere = cognisphere;
+ }
+
+ @Override
+ public Collection asCollection() {
+ return object instanceof Collection value
+ ? new AgenticModelCollection(value, cognisphere)
+ : Collections.emptyList();
+ }
+
+ @Override
+ public Optional as(Class clazz) {
+ if (Cognisphere.class.isAssignableFrom(clazz)) {
+ return Optional.of(clazz.cast(cognisphere));
+ } else if (ResultWithCognisphere.class.isAssignableFrom(clazz)) {
+ return Optional.of(clazz.cast(new ResultWithCognisphere<>(cognisphere, object)));
+ } else {
+ return super.as(clazz);
+ }
+ }
+}
diff --git a/experimental/agentic/src/main/java/io/serverlessworkflow/impl/expressions/agentic/AgenticModelCollection.java b/experimental/agentic/src/main/java/io/serverlessworkflow/impl/expressions/agentic/AgenticModelCollection.java
new file mode 100644
index 00000000..e9440fb5
--- /dev/null
+++ b/experimental/agentic/src/main/java/io/serverlessworkflow/impl/expressions/agentic/AgenticModelCollection.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2020-Present The Serverless Workflow Specification Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.serverlessworkflow.impl.expressions.agentic;
+
+import dev.langchain4j.agentic.cognisphere.Cognisphere;
+import dev.langchain4j.agentic.cognisphere.ResultWithCognisphere;
+import io.serverlessworkflow.impl.WorkflowModel;
+import io.serverlessworkflow.impl.expressions.func.JavaModelCollection;
+import java.util.Collection;
+import java.util.Optional;
+
+class AgenticModelCollection extends JavaModelCollection {
+
+ private final Cognisphere cognisphere;
+
+ AgenticModelCollection(Collection> object, Cognisphere cognisphere) {
+ super(object);
+ this.cognisphere = cognisphere;
+ }
+
+ AgenticModelCollection(Cognisphere cognisphere) {
+ this.cognisphere = cognisphere;
+ }
+
+ @Override
+ protected WorkflowModel nextItem(Object obj) {
+ return new AgenticModel(obj, cognisphere);
+ }
+
+ @Override
+ public Optional as(Class clazz) {
+ if (Cognisphere.class.isAssignableFrom(clazz)) {
+ return Optional.of(clazz.cast(cognisphere));
+ } else if (ResultWithCognisphere.class.isAssignableFrom(clazz)) {
+ return Optional.of(clazz.cast(new ResultWithCognisphere<>(cognisphere, object)));
+ } else {
+ return super.as(clazz);
+ }
+ }
+}
diff --git a/experimental/agentic/src/main/java/io/serverlessworkflow/impl/expressions/agentic/AgenticModelFactory.java b/experimental/agentic/src/main/java/io/serverlessworkflow/impl/expressions/agentic/AgenticModelFactory.java
new file mode 100644
index 00000000..dc7c53ac
--- /dev/null
+++ b/experimental/agentic/src/main/java/io/serverlessworkflow/impl/expressions/agentic/AgenticModelFactory.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2020-Present The Serverless Workflow Specification Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.serverlessworkflow.impl.expressions.agentic;
+
+import dev.langchain4j.agentic.cognisphere.Cognisphere;
+import dev.langchain4j.agentic.cognisphere.CognisphereRegistry;
+import io.cloudevents.CloudEvent;
+import io.cloudevents.CloudEventData;
+import io.serverlessworkflow.impl.WorkflowModel;
+import io.serverlessworkflow.impl.WorkflowModelCollection;
+import io.serverlessworkflow.impl.WorkflowModelFactory;
+import java.time.OffsetDateTime;
+import java.util.Map;
+
+class AgenticModelFactory implements WorkflowModelFactory {
+ private final Cognisphere cognisphere = CognisphereRegistry.createEphemeralCognisphere();
+
+ private final AgenticModel TrueModel = new AgenticModel(Boolean.TRUE, cognisphere);
+ private final AgenticModel FalseModel = new AgenticModel(Boolean.FALSE, cognisphere);
+ private final AgenticModel NullModel = new AgenticModel(null, cognisphere);
+
+ @Override
+ public WorkflowModel combine(Map workflowVariables) {
+ return new AgenticModel(workflowVariables, cognisphere);
+ }
+
+ @Override
+ public WorkflowModelCollection createCollection() {
+ return new AgenticModelCollection(cognisphere);
+ }
+
+ @Override
+ public WorkflowModel from(boolean value) {
+ return value ? TrueModel : FalseModel;
+ }
+
+ @Override
+ public WorkflowModel from(Number value) {
+ return new AgenticModel(value, cognisphere);
+ }
+
+ @Override
+ public WorkflowModel from(String value) {
+ return new AgenticModel(value, cognisphere);
+ }
+
+ @Override
+ public WorkflowModel from(CloudEvent ce) {
+ return new AgenticModel(ce, cognisphere);
+ }
+
+ @Override
+ public WorkflowModel from(CloudEventData ce) {
+ return new AgenticModel(ce, cognisphere);
+ }
+
+ @Override
+ public WorkflowModel from(OffsetDateTime value) {
+ return new AgenticModel(value, cognisphere);
+ }
+
+ @Override
+ public WorkflowModel from(Map map) {
+ cognisphere.writeStates(map);
+ return new AgenticModel(map, cognisphere);
+ }
+
+ @Override
+ public WorkflowModel fromNull() {
+ return NullModel;
+ }
+
+ @Override
+ public WorkflowModel fromOther(Object value) {
+ return new AgenticModel(value, cognisphere);
+ }
+}
diff --git a/experimental/agentic/src/main/resources/META-INF/services/io.serverlessworkflow.impl.expressions.ExpressionFactory b/experimental/agentic/src/main/resources/META-INF/services/io.serverlessworkflow.impl.expressions.ExpressionFactory
new file mode 100644
index 00000000..e0038ed9
--- /dev/null
+++ b/experimental/agentic/src/main/resources/META-INF/services/io.serverlessworkflow.impl.expressions.ExpressionFactory
@@ -0,0 +1 @@
+io.serverlessworkflow.impl.expressions.agentic.AgenticExpressionFactory
\ No newline at end of file
diff --git a/experimental/lambda/src/main/java/io/serverlessworkflow/impl/executors/func/JavaForExecutorBuilder.java b/experimental/lambda/src/main/java/io/serverlessworkflow/impl/executors/func/JavaForExecutorBuilder.java
index f58ce510..9723fba7 100644
--- a/experimental/lambda/src/main/java/io/serverlessworkflow/impl/executors/func/JavaForExecutorBuilder.java
+++ b/experimental/lambda/src/main/java/io/serverlessworkflow/impl/executors/func/JavaForExecutorBuilder.java
@@ -43,7 +43,8 @@ protected JavaForExecutorBuilder(
protected Optional buildWhileFilter() {
if (task instanceof ForTaskFunction taskFunctions) {
- LoopPredicateIndex whilePred = taskFunctions.getWhilePredicate();
+ final LoopPredicateIndex whilePred = taskFunctions.getWhilePredicate();
+ Optional> modelClass = taskFunctions.getModelClass();
String varName = task.getFor().getEach();
String indexName = task.getFor().getAt();
if (whilePred != null) {
@@ -54,7 +55,7 @@ protected Optional buildWhileFilter() {
.modelFactory()
.from(
whilePred.test(
- n.asJavaObject(),
+ JavaFuncUtils.convert(n, modelClass),
item,
(Integer) safeObject(t.variables().get(indexName))));
});
diff --git a/experimental/lambda/src/main/java/io/serverlessworkflow/impl/executors/func/JavaFuncUtils.java b/experimental/lambda/src/main/java/io/serverlessworkflow/impl/executors/func/JavaFuncUtils.java
index 33b90fb9..ed42bf50 100644
--- a/experimental/lambda/src/main/java/io/serverlessworkflow/impl/executors/func/JavaFuncUtils.java
+++ b/experimental/lambda/src/main/java/io/serverlessworkflow/impl/executors/func/JavaFuncUtils.java
@@ -16,6 +16,7 @@
package io.serverlessworkflow.impl.executors.func;
import io.serverlessworkflow.impl.WorkflowModel;
+import java.util.Optional;
public class JavaFuncUtils {
@@ -23,5 +24,29 @@ static Object safeObject(Object obj) {
return obj instanceof WorkflowModel model ? model.asJavaObject() : obj;
}
+ static T convertT(WorkflowModel model, Optional> inputClass) {
+ return inputClass
+ .map(
+ c ->
+ model
+ .as(c)
+ .orElseThrow(
+ () ->
+ new IllegalArgumentException(
+ "Model " + model + " cannot be converted to type " + c)))
+ .orElseGet(() -> (T) model.asJavaObject());
+ }
+
+ static Object convert(WorkflowModel model, Optional> inputClass) {
+ return inputClass.isPresent()
+ ? model
+ .as(inputClass.orElseThrow())
+ .orElseThrow(
+ () ->
+ new IllegalArgumentException(
+ "Model " + model + " cannot be converted to type " + inputClass))
+ : model.asJavaObject();
+ }
+
private JavaFuncUtils() {}
}
diff --git a/experimental/lambda/src/main/java/io/serverlessworkflow/impl/executors/func/JavaFunctionCallExecutor.java b/experimental/lambda/src/main/java/io/serverlessworkflow/impl/executors/func/JavaFunctionCallExecutor.java
index 8a9f219a..9b040772 100644
--- a/experimental/lambda/src/main/java/io/serverlessworkflow/impl/executors/func/JavaFunctionCallExecutor.java
+++ b/experimental/lambda/src/main/java/io/serverlessworkflow/impl/executors/func/JavaFunctionCallExecutor.java
@@ -25,19 +25,27 @@
import io.serverlessworkflow.impl.WorkflowModelFactory;
import io.serverlessworkflow.impl.executors.CallableTask;
import io.serverlessworkflow.impl.resources.ResourceLoader;
+import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.function.Function;
-public class JavaFunctionCallExecutor implements CallableTask {
+public class JavaFunctionCallExecutor
+ implements CallableTask> {
- private Function function;
+ private Function function;
+ private Optional> inputClass;
+
+ static String fromInt(Integer integer) {
+ return Integer.toString(integer);
+ }
public void init(
- CallJava.CallJavaFunction task,
+ CallJava.CallJavaFunction task,
Workflow workflow,
WorkflowApplication application,
ResourceLoader loader) {
function = task.function();
+ inputClass = task.inputClass();
}
@Override
@@ -45,7 +53,7 @@ public CompletableFuture apply(
WorkflowContext workflowContext, TaskContext taskContext, WorkflowModel input) {
WorkflowModelFactory modelFactory = workflowContext.definition().application().modelFactory();
return CompletableFuture.completedFuture(
- modelFactory.fromAny(function.apply(input.asJavaObject())));
+ modelFactory.fromAny(function.apply(JavaFuncUtils.convertT(input, inputClass))));
}
@Override
diff --git a/experimental/lambda/src/main/java/io/serverlessworkflow/impl/expressions/func/JavaModel.java b/experimental/lambda/src/main/java/io/serverlessworkflow/impl/expressions/func/JavaModel.java
index bb236ed7..8c2992f2 100644
--- a/experimental/lambda/src/main/java/io/serverlessworkflow/impl/expressions/func/JavaModel.java
+++ b/experimental/lambda/src/main/java/io/serverlessworkflow/impl/expressions/func/JavaModel.java
@@ -26,15 +26,11 @@
import java.util.function.BiConsumer;
import java.util.stream.Collectors;
-class JavaModel implements WorkflowModel {
+public class JavaModel implements WorkflowModel {
- private Object object;
+ protected final Object object;
- static final JavaModel TrueModel = new JavaModel(Boolean.TRUE);
- static final JavaModel FalseModel = new JavaModel(Boolean.FALSE);
- static final JavaModel NullModel = new JavaModel(null);
-
- JavaModel(Object object) {
+ protected JavaModel(Object object) {
this.object = asJavaObject(object);
}
diff --git a/experimental/lambda/src/main/java/io/serverlessworkflow/impl/expressions/func/JavaModelCollection.java b/experimental/lambda/src/main/java/io/serverlessworkflow/impl/expressions/func/JavaModelCollection.java
index 0b9c914f..12e0ab66 100644
--- a/experimental/lambda/src/main/java/io/serverlessworkflow/impl/expressions/func/JavaModelCollection.java
+++ b/experimental/lambda/src/main/java/io/serverlessworkflow/impl/expressions/func/JavaModelCollection.java
@@ -22,15 +22,15 @@
import java.util.Iterator;
import java.util.Optional;
-class JavaModelCollection implements Collection, WorkflowModelCollection {
+public class JavaModelCollection implements Collection, WorkflowModelCollection {
- private final Collection object;
+ protected final Collection object;
- JavaModelCollection() {
+ protected JavaModelCollection() {
this.object = new ArrayList<>();
}
- JavaModelCollection(Collection> object) {
+ protected JavaModelCollection(Collection> object) {
this.object = (Collection) JavaModel.asJavaObject(object);
}
@@ -65,10 +65,14 @@ public boolean hasNext() {
@Override
public WorkflowModel next() {
Object obj = wrapped.next();
- return obj instanceof WorkflowModel value ? value : new JavaModel(obj);
+ return obj instanceof WorkflowModel value ? value : nextItem(obj);
}
}
+ protected WorkflowModel nextItem(Object obj) {
+ return new JavaModel(obj);
+ }
+
@Override
public Iterator iterator() {
return new ModelIterator(object.iterator());
diff --git a/experimental/lambda/src/main/java/io/serverlessworkflow/impl/expressions/func/JavaModelFactory.java b/experimental/lambda/src/main/java/io/serverlessworkflow/impl/expressions/func/JavaModelFactory.java
index 59975e50..2ccc0dcd 100644
--- a/experimental/lambda/src/main/java/io/serverlessworkflow/impl/expressions/func/JavaModelFactory.java
+++ b/experimental/lambda/src/main/java/io/serverlessworkflow/impl/expressions/func/JavaModelFactory.java
@@ -24,6 +24,9 @@
import java.util.Map;
class JavaModelFactory implements WorkflowModelFactory {
+ private final JavaModel TrueModel = new JavaModel(Boolean.TRUE);
+ private final JavaModel FalseModel = new JavaModel(Boolean.FALSE);
+ private final JavaModel NullModel = new JavaModel(null);
@Override
public WorkflowModel combine(Map workflowVariables) {
@@ -37,7 +40,7 @@ public WorkflowModelCollection createCollection() {
@Override
public WorkflowModel from(boolean value) {
- return value ? JavaModel.TrueModel : JavaModel.FalseModel;
+ return value ? TrueModel : FalseModel;
}
@Override
@@ -72,7 +75,7 @@ public WorkflowModel from(Map map) {
@Override
public WorkflowModel fromNull() {
- return JavaModel.NullModel;
+ return NullModel;
}
@Override
diff --git a/experimental/pom.xml b/experimental/pom.xml
index c4b61781..a8dbc874 100644
--- a/experimental/pom.xml
+++ b/experimental/pom.xml
@@ -38,8 +38,9 @@
- types
- lambda
+ types
+ lambda
+ agentic
lambda-fluent
\ No newline at end of file
diff --git a/experimental/types/src/main/java/io/serverlessworkflow/api/types/func/CallJava.java b/experimental/types/src/main/java/io/serverlessworkflow/api/types/func/CallJava.java
index 4158ee57..6423fdae 100644
--- a/experimental/types/src/main/java/io/serverlessworkflow/api/types/func/CallJava.java
+++ b/experimental/types/src/main/java/io/serverlessworkflow/api/types/func/CallJava.java
@@ -18,6 +18,7 @@
import io.serverlessworkflow.api.types.TaskBase;
import io.serverlessworkflow.impl.expressions.LoopFunction;
import io.serverlessworkflow.impl.expressions.LoopFunctionIndex;
+import java.util.Optional;
import java.util.function.Consumer;
import java.util.function.Function;
@@ -29,8 +30,13 @@ public static CallJava consumer(Consumer consumer) {
return new CallJavaConsumer<>(consumer);
}
- public static CallJava function(Function function) {
- return new CallJavaFunction<>(function);
+ public static CallJavaFunction function(Function function) {
+ return new CallJavaFunction<>(function, Optional.empty());
+ }
+
+ public static CallJavaFunction function(
+ Function function, Class inputClass) {
+ return new CallJavaFunction<>(function, Optional.ofNullable(inputClass));
}
public static CallJava loopFunction(
@@ -60,14 +66,20 @@ public static class CallJavaFunction extends CallJava {
private static final long serialVersionUID = 1L;
private Function function;
+ private Optional> inputClass;
- public CallJavaFunction(Function function) {
+ public CallJavaFunction(Function function, Optional> inputClass) {
this.function = function;
+ this.inputClass = inputClass;
}
public Function function() {
return function;
}
+
+ public Optional> inputClass() {
+ return inputClass;
+ }
}
public static class CallJavaLoopFunction extends CallJava {
diff --git a/experimental/types/src/main/java/io/serverlessworkflow/api/types/func/ForTaskFunction.java b/experimental/types/src/main/java/io/serverlessworkflow/api/types/func/ForTaskFunction.java
index 779dccd4..8c9ad956 100644
--- a/experimental/types/src/main/java/io/serverlessworkflow/api/types/func/ForTaskFunction.java
+++ b/experimental/types/src/main/java/io/serverlessworkflow/api/types/func/ForTaskFunction.java
@@ -19,17 +19,28 @@
import io.serverlessworkflow.impl.expressions.LoopPredicate;
import io.serverlessworkflow.impl.expressions.LoopPredicateIndex;
import java.util.Collection;
+import java.util.Optional;
import java.util.function.Function;
public class ForTaskFunction extends ForTask {
private static final long serialVersionUID = 1L;
private LoopPredicateIndex, ?> whilePredicate;
+ private Optional> modelClass;
+ private Optional> itemClass;
private Function, Collection>> collection;
public ForTaskFunction withWhile(LoopPredicate whilePredicate) {
- this.whilePredicate = toPredicateIndex(whilePredicate);
- return this;
+ return withWhile(toPredicateIndex(whilePredicate));
+ }
+
+ public ForTaskFunction withWhile(LoopPredicate whilePredicate, Class modelClass) {
+ return withWhile(toPredicateIndex(whilePredicate), modelClass);
+ }
+
+ public ForTaskFunction withWhile(
+ LoopPredicate whilePredicate, Class modelClass, Class itemClass) {
+ return withWhile(toPredicateIndex(whilePredicate), modelClass, itemClass);
}
private LoopPredicateIndex toPredicateIndex(LoopPredicate whilePredicate) {
@@ -37,7 +48,26 @@ private LoopPredicateIndex toPredicateIndex(LoopPredicate whi
}
public ForTaskFunction withWhile(LoopPredicateIndex whilePredicate) {
+ return withWhile(whilePredicate, Optional.empty(), Optional.empty());
+ }
+
+ public ForTaskFunction withWhile(
+ LoopPredicateIndex whilePredicate, Class modelClass) {
+ return withWhile(whilePredicate, Optional.of(modelClass), Optional.empty());
+ }
+
+ public ForTaskFunction withWhile(
+ LoopPredicateIndex whilePredicate, Class modelClass, Class itemClass) {
+ return withWhile(whilePredicate, Optional.of(modelClass), Optional.of(itemClass));
+ }
+
+ private ForTaskFunction withWhile(
+ LoopPredicateIndex whilePredicate,
+ Optional> modelClass,
+ Optional> itemClass) {
this.whilePredicate = whilePredicate;
+ this.modelClass = modelClass;
+ this.itemClass = itemClass;
return this;
}
@@ -50,6 +80,14 @@ public ForTaskFunction withCollection(Function> collection)
return whilePredicate;
}
+ public Optional> getModelClass() {
+ return modelClass;
+ }
+
+ public Optional> getItemClass() {
+ return itemClass;
+ }
+
public Function, Collection>> getCollection() {
return collection;
}
diff --git a/fluent/agentic/pom.xml b/fluent/agentic/pom.xml
index 02d1847d..849bf747 100644
--- a/fluent/agentic/pom.xml
+++ b/fluent/agentic/pom.xml
@@ -16,8 +16,6 @@
17
17
UTF-8
-
- 1.2.0-beta8-SNAPSHOT
@@ -32,7 +30,6 @@
dev.langchain4j
langchain4j-agentic
- ${version.dev.langchain4j}
org.slf4j
@@ -62,7 +59,7 @@
io.serverlessworkflow
- serverlessworkflow-experimental-lambda
+ serverlessworkflow-experimental-agentic
${project.version}
test
diff --git a/fluent/agentic/src/main/java/io/serverlessworkflow/fluent/agentic/AgentTaskItemListBuilder.java b/fluent/agentic/src/main/java/io/serverlessworkflow/fluent/agentic/AgentTaskItemListBuilder.java
index 5aed3127..60329e43 100644
--- a/fluent/agentic/src/main/java/io/serverlessworkflow/fluent/agentic/AgentTaskItemListBuilder.java
+++ b/fluent/agentic/src/main/java/io/serverlessworkflow/fluent/agentic/AgentTaskItemListBuilder.java
@@ -15,6 +15,7 @@
*/
package io.serverlessworkflow.fluent.agentic;
+import dev.langchain4j.agentic.cognisphere.Cognisphere;
import dev.langchain4j.agentic.internal.AgentExecutor;
import io.serverlessworkflow.api.types.Task;
import io.serverlessworkflow.api.types.TaskItem;
@@ -54,7 +55,9 @@ protected AgentTaskItemListBuilder newItemListBuilder() {
public AgentTaskItemListBuilder agent(String name, Object agent) {
AgentAdapters.toExecutors(agent)
.forEach(
- exec -> this.delegate.callFn(name, fn -> fn.function(AgentAdapters.toFunction(exec))));
+ exec ->
+ this.delegate.callFn(
+ name, fn -> fn.function(AgentAdapters.toFunction(exec), Cognisphere.class)));
return self();
}
@@ -82,7 +85,8 @@ public AgentTaskItemListBuilder parallel(String name, Object... agents) {
List execs = AgentAdapters.toExecutors(agents);
for (int i = 0; i < execs.size(); i++) {
AgentExecutor ex = execs.get(i);
- fork.branch("branch-" + i + "-" + name, AgentAdapters.toFunction(ex));
+ fork.branch(
+ "branch-" + i + "-" + name, AgentAdapters.toFunction(ex), Cognisphere.class);
}
});
return self();
diff --git a/fluent/agentic/src/test/java/io/serverlessworkflow/fluent/agentic/Agents.java b/fluent/agentic/src/test/java/io/serverlessworkflow/fluent/agentic/Agents.java
index 8ba9d8c7..7215ddd6 100644
--- a/fluent/agentic/src/test/java/io/serverlessworkflow/fluent/agentic/Agents.java
+++ b/fluent/agentic/src/test/java/io/serverlessworkflow/fluent/agentic/Agents.java
@@ -153,7 +153,12 @@ interface MeetingInvitationDraft extends AgentInstance {
Agenda: {{agenda}}
""")
@Agent("Drafts a professional meeting invitation email.")
- String invoke(@V("subject") String subject, @V("date") String date, @V("time") String time, @V("location") String location, @V("agenda") String agenda);
+ String invoke(
+ @V("subject") String subject,
+ @V("date") String date,
+ @V("time") String time,
+ @V("location") String location,
+ @V("agenda") String agenda);
}
interface MeetingInvitationStyle extends AgentInstance {
@@ -166,5 +171,4 @@ interface MeetingInvitationStyle extends AgentInstance {
@Agent("Edits a meeting invitation email to better fit a given style.")
String invoke(@V("invitation") String invitation, @V("style") String style);
}
-
- }
+}
diff --git a/fluent/agentic/src/test/java/io/serverlessworkflow/fluent/agentic/WorkflowTests.java b/fluent/agentic/src/test/java/io/serverlessworkflow/fluent/agentic/WorkflowTests.java
index 0071d0bd..8bbbe62d 100644
--- a/fluent/agentic/src/test/java/io/serverlessworkflow/fluent/agentic/WorkflowTests.java
+++ b/fluent/agentic/src/test/java/io/serverlessworkflow/fluent/agentic/WorkflowTests.java
@@ -35,6 +35,7 @@
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Function;
import java.util.stream.Collectors;
+import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
class WorkflowTests {
@@ -225,16 +226,18 @@ public void testSeqAndThenParallel() throws ExecutionException, InterruptedExcep
}
@Test
+ @Disabled("HumanLoop not implemented yet")
public void humanInTheLoop() throws ExecutionException, InterruptedException {
final MeetingInvitationDraft meetingInvitationDraft = mock(MeetingInvitationDraft.class);
- when(meetingInvitationDraft.invoke(eq("Meeting with John Doe"),
- eq("2023-10-01"), eq("08:00AM"),
+ when(meetingInvitationDraft.invoke(
+ eq("Meeting with John Doe"),
+ eq("2023-10-01"),
+ eq("08:00AM"),
eq("London"),
eq("Discuss project updates")))
.thenReturn("Drafted meeting invitation for John Doe");
when(meetingInvitationDraft.outputName()).thenReturn("draft");
-
final MeetingInvitationStyle meetingInvitationStyle = mock(MeetingInvitationStyle.class);
when(meetingInvitationStyle.invoke(eq("Drafted meeting invitation for John Doe"), eq("formal")))
.thenReturn("Styled meeting invitation for John Doe");
@@ -242,11 +245,16 @@ public void humanInTheLoop() throws ExecutionException, InterruptedException {
AtomicReference request = new AtomicReference<>();
- HumanInTheLoop humanInTheLoop = AgentServices.humanInTheLoopBuilder()
- .description("What level of formality would you like? (please reply with “formal”, “casual”, or “friendly”)")
+ HumanInTheLoop humanInTheLoop =
+ AgentServices.humanInTheLoopBuilder()
+ .description(
+ "What level of formality would you like? (please reply with “formal”, “casual”, or “friendly”)")
.inputName("style")
.outputName("style")
- .requestWriter(q -> request.set("What level of formality would you like? (please reply with “formal”, “casual”, or “friendly”)"))
+ .requestWriter(
+ q ->
+ request.set(
+ "What level of formality would you like? (please reply with “formal”, “casual”, or “friendly”)"))
.responseReader(() -> "formal")
.build();
@@ -254,8 +262,9 @@ public void humanInTheLoop() throws ExecutionException, InterruptedException {
AgentWorkflowBuilder.workflow("meetingInvitationFlow")
.tasks(
d ->
- d.sequence("draft", meetingInvitationDraft, humanInTheLoop, meetingInvitationStyle)
- ).build();
+ d.sequence(
+ "draft", meetingInvitationDraft, humanInTheLoop, meetingInvitationStyle))
+ .build();
Map initialValues = new HashMap<>();
initialValues.put("title", "Meeting with John Doe");
initialValues.put("date", "2023-10-01");
@@ -265,11 +274,14 @@ public void humanInTheLoop() throws ExecutionException, InterruptedException {
try (WorkflowApplication app = WorkflowApplication.builder().build()) {
String result =
- app.workflowDefinition(workflow).instance(initialValues).start().get().asText().orElseThrow();
-
- assertEquals("Styled meeting invitation for John Doe", result);
+ app.workflowDefinition(workflow)
+ .instance(initialValues)
+ .start()
+ .get()
+ .asText()
+ .orElseThrow();
+
+ assertEquals("Styled meeting invitation for John Doe", result);
}
-
-
}
}
diff --git a/fluent/func/src/main/java/io/serverlessworkflow/fluent/func/FuncCallTaskBuilder.java b/fluent/func/src/main/java/io/serverlessworkflow/fluent/func/FuncCallTaskBuilder.java
index 6e1da87f..30d874f0 100644
--- a/fluent/func/src/main/java/io/serverlessworkflow/fluent/func/FuncCallTaskBuilder.java
+++ b/fluent/func/src/main/java/io/serverlessworkflow/fluent/func/FuncCallTaskBuilder.java
@@ -39,7 +39,11 @@ protected FuncCallTaskBuilder self() {
}
public FuncCallTaskBuilder function(Function function) {
- this.callTaskJava = new CallTaskJava(CallJava.function(function));
+ return function(function, null);
+ }
+
+ public FuncCallTaskBuilder function(Function function, Class argClass) {
+ this.callTaskJava = new CallTaskJava(CallJava.function(function, argClass));
super.setTask(this.callTaskJava.getCallJava());
return this;
}
diff --git a/fluent/func/src/main/java/io/serverlessworkflow/fluent/func/FuncForkTaskBuilder.java b/fluent/func/src/main/java/io/serverlessworkflow/fluent/func/FuncForkTaskBuilder.java
index a4326276..372da744 100644
--- a/fluent/func/src/main/java/io/serverlessworkflow/fluent/func/FuncForkTaskBuilder.java
+++ b/fluent/func/src/main/java/io/serverlessworkflow/fluent/func/FuncForkTaskBuilder.java
@@ -51,8 +51,15 @@ protected FuncForkTaskBuilder self() {
}
public FuncForkTaskBuilder branch(String name, Function function) {
+ return branch(name, function, null);
+ }
+
+ public FuncForkTaskBuilder branch(
+ String name, Function function, Class argParam) {
this.items.add(
- new TaskItem(name, new Task().withCallTask(new CallTaskJava(CallJava.function(function)))));
+ new TaskItem(
+ name,
+ new Task().withCallTask(new CallTaskJava(CallJava.function(function, argParam)))));
return this;
}
diff --git a/impl/core/src/main/java/io/serverlessworkflow/impl/ServicePriority.java b/impl/core/src/main/java/io/serverlessworkflow/impl/ServicePriority.java
new file mode 100644
index 00000000..74b5bdf1
--- /dev/null
+++ b/impl/core/src/main/java/io/serverlessworkflow/impl/ServicePriority.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2020-Present The Serverless Workflow Specification Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.serverlessworkflow.impl;
+
+public interface ServicePriority extends Comparable {
+
+ static final int DEFAULT_PRIORITY = 1000;
+
+ default int priority() {
+ return DEFAULT_PRIORITY;
+ }
+
+ @Override
+ default int compareTo(ServicePriority other) {
+ return this.priority() - other.priority();
+ }
+}
diff --git a/impl/core/src/main/java/io/serverlessworkflow/impl/WorkflowModelFactory.java b/impl/core/src/main/java/io/serverlessworkflow/impl/WorkflowModelFactory.java
index 4c55723a..25564bc0 100644
--- a/impl/core/src/main/java/io/serverlessworkflow/impl/WorkflowModelFactory.java
+++ b/impl/core/src/main/java/io/serverlessworkflow/impl/WorkflowModelFactory.java
@@ -42,6 +42,11 @@ public interface WorkflowModelFactory {
WorkflowModel fromNull();
+ default WorkflowModel fromOther(Object obj) {
+ throw new IllegalArgumentException(
+ "Unsupported conversion for object " + obj + " of type" + obj.getClass());
+ }
+
default WorkflowModel fromAny(Object obj) {
if (obj == null) {
return fromNull();
@@ -62,8 +67,7 @@ default WorkflowModel fromAny(Object obj) {
} else if (obj instanceof WorkflowModel model) {
return model;
} else {
- throw new IllegalArgumentException(
- "Unsopported conversion for object " + obj + " of type" + obj.getClass());
+ return fromOther(obj);
}
}
}
diff --git a/impl/core/src/main/java/io/serverlessworkflow/impl/executors/TaskExecutorFactory.java b/impl/core/src/main/java/io/serverlessworkflow/impl/executors/TaskExecutorFactory.java
index b1be3429..be1f1bee 100644
--- a/impl/core/src/main/java/io/serverlessworkflow/impl/executors/TaskExecutorFactory.java
+++ b/impl/core/src/main/java/io/serverlessworkflow/impl/executors/TaskExecutorFactory.java
@@ -18,11 +18,12 @@
import io.serverlessworkflow.api.types.Task;
import io.serverlessworkflow.api.types.TaskBase;
import io.serverlessworkflow.api.types.Workflow;
+import io.serverlessworkflow.impl.ServicePriority;
import io.serverlessworkflow.impl.WorkflowApplication;
import io.serverlessworkflow.impl.WorkflowPosition;
import io.serverlessworkflow.impl.resources.ResourceLoader;
-public interface TaskExecutorFactory {
+public interface TaskExecutorFactory extends ServicePriority {
TaskExecutorBuilder extends TaskBase> getTaskExecutor(
WorkflowPosition position,
Task task,
diff --git a/impl/core/src/main/java/io/serverlessworkflow/impl/expressions/ExpressionFactory.java b/impl/core/src/main/java/io/serverlessworkflow/impl/expressions/ExpressionFactory.java
index cb14555e..28039cc7 100644
--- a/impl/core/src/main/java/io/serverlessworkflow/impl/expressions/ExpressionFactory.java
+++ b/impl/core/src/main/java/io/serverlessworkflow/impl/expressions/ExpressionFactory.java
@@ -16,11 +16,12 @@
package io.serverlessworkflow.impl.expressions;
import io.serverlessworkflow.api.types.TaskBase;
+import io.serverlessworkflow.impl.ServicePriority;
import io.serverlessworkflow.impl.WorkflowFilter;
import io.serverlessworkflow.impl.WorkflowModelFactory;
import java.util.Optional;
-public interface ExpressionFactory {
+public interface ExpressionFactory extends ServicePriority {
/**
* @throws ExpressionValidationException
* @param expression
diff --git a/impl/core/src/main/java/io/serverlessworkflow/impl/schema/SchemaValidatorFactory.java b/impl/core/src/main/java/io/serverlessworkflow/impl/schema/SchemaValidatorFactory.java
index 56b4b079..ff57ef5d 100644
--- a/impl/core/src/main/java/io/serverlessworkflow/impl/schema/SchemaValidatorFactory.java
+++ b/impl/core/src/main/java/io/serverlessworkflow/impl/schema/SchemaValidatorFactory.java
@@ -16,9 +16,10 @@
package io.serverlessworkflow.impl.schema;
import io.serverlessworkflow.api.types.SchemaInline;
+import io.serverlessworkflow.impl.ServicePriority;
import io.serverlessworkflow.impl.resources.StaticResource;
-public interface SchemaValidatorFactory {
+public interface SchemaValidatorFactory extends ServicePriority {
SchemaValidator getValidator(SchemaInline inline);
SchemaValidator getValidator(StaticResource resource);
diff --git a/pom.xml b/pom.xml
index 428e82bb..471a0028 100644
--- a/pom.xml
+++ b/pom.xml
@@ -86,7 +86,7 @@
2.0.17
9.0.1.Final
6.0.0
-
+ 1.3.0-beta9-SNAPSHOT
true
${version.org.assertj}
test
+
+ dev.langchain4j
+ langchain4j-agentic
+ ${version.dev.langchain4j}
+