diff --git a/fluent/agentic-langchain4j/src/main/java/io/serverlessworkflow/fluent/agentic/langchain4j/AbstractAgentService.java b/fluent/agentic-langchain4j/src/main/java/io/serverlessworkflow/fluent/agentic/langchain4j/AbstractAgentService.java index c7ed7d83..8abc54b1 100644 --- a/fluent/agentic-langchain4j/src/main/java/io/serverlessworkflow/fluent/agentic/langchain4j/AbstractAgentService.java +++ b/fluent/agentic-langchain4j/src/main/java/io/serverlessworkflow/fluent/agentic/langchain4j/AbstractAgentService.java @@ -82,6 +82,7 @@ public S output(Function output) { @SuppressWarnings("unchecked") public S errorHandler(Function errorHandler) { + // TODO: implement return (S) this; } @@ -89,4 +90,16 @@ public S errorHandler(Function errorHandler) public Workflow getDefinition() { return this.workflowBuilder.build(); } + + @SuppressWarnings("unchecked") + public S name(String name) { + this.workflowBuilder.document(d -> d.name(name)); + return (S) this; + } + + @SuppressWarnings("unchecked") + public S description(String description) { + this.workflowBuilder.document(d -> d.summary(description)); + return (S) this; + } } diff --git a/fluent/agentic-langchain4j/src/main/java/io/serverlessworkflow/fluent/agentic/langchain4j/ParallelAgentServiceImpl.java b/fluent/agentic-langchain4j/src/main/java/io/serverlessworkflow/fluent/agentic/langchain4j/ParallelAgentServiceImpl.java index eaaaf67a..00f6e1c2 100644 --- a/fluent/agentic-langchain4j/src/main/java/io/serverlessworkflow/fluent/agentic/langchain4j/ParallelAgentServiceImpl.java +++ b/fluent/agentic-langchain4j/src/main/java/io/serverlessworkflow/fluent/agentic/langchain4j/ParallelAgentServiceImpl.java @@ -19,6 +19,7 @@ import dev.langchain4j.agentic.workflow.ParallelAgentService; import io.serverlessworkflow.impl.ExecutorServiceHolder; import java.util.List; +import java.util.concurrent.Executor; import java.util.concurrent.ExecutorService; public class ParallelAgentServiceImpl extends AbstractAgentService> @@ -32,12 +33,6 @@ public static ParallelAgentService builder(Class agentServiceClass) { return new ParallelAgentServiceImpl<>(agentServiceClass); } - @Override - public ParallelAgentService executorService(ExecutorService executorService) { - this.workflowExecBuilder.withExecutorFactory(new ExecutorServiceHolder(executorService)); - return this; - } - @Override public ParallelAgentService subAgents(Object... agents) { this.workflowBuilder.tasks(t -> t.parallel(agents)); @@ -48,4 +43,16 @@ public ParallelAgentService subAgents(Object... agents) { public ParallelAgentService subAgents(List agentExecutors) { return this.subAgents(agentExecutors.toArray()); } + + @Override + public ParallelAgentService executor(Executor executor) { + if (!(executor instanceof ExecutorService)) { + throw new IllegalArgumentException( + "ExecutorService is required for the ParallelAgentService"); + } + // TODO: create an adapter or change or internal holder to accept a plain `Executor`. + this.workflowExecBuilder.withExecutorFactory( + new ExecutorServiceHolder((ExecutorService) executor)); + return this; + } } diff --git a/fluent/agentic-langchain4j/src/main/java/io/serverlessworkflow/fluent/agentic/langchain4j/WorkflowInvocationHandler.java b/fluent/agentic-langchain4j/src/main/java/io/serverlessworkflow/fluent/agentic/langchain4j/WorkflowInvocationHandler.java index 5ffbfb3a..8eaffcee 100644 --- a/fluent/agentic-langchain4j/src/main/java/io/serverlessworkflow/fluent/agentic/langchain4j/WorkflowInvocationHandler.java +++ b/fluent/agentic-langchain4j/src/main/java/io/serverlessworkflow/fluent/agentic/langchain4j/WorkflowInvocationHandler.java @@ -84,13 +84,15 @@ public Object invoke(Object proxy, Method method, Object[] args) throws Throwabl // outputName if (method.getDeclaringClass() == AgentSpecification.class) { return switch (method.getName()) { + case "name" -> this.workflow.getDocument().getName(); + case "description" -> this.workflow.getDocument().getSummary(); case "outputName" -> outputName(); default -> throw new UnsupportedOperationException( "Unknown method on AgentInstance class : " + method.getName()); }; } - // withCognisphere + // withAgenticScope if (method.getDeclaringClass() == AgenticScopeOwner.class) { // Ingest the workflow input as a AgenticScope object // Later, retrieve it and start the workflow with it as input. @@ -99,11 +101,11 @@ public Object invoke(Object proxy, Method method, Object[] args) throws Throwabl case "registry" -> registry; default -> throw new UnsupportedOperationException( - "Unknown method on CognisphereOwner class : " + method.getName()); + "Unknown method on AgenticScopeOwner class : " + method.getName()); }; } // getAgenticScope - // evictCognisphere + // evictAgenticScope if (method.getDeclaringClass() == AgenticScopeAccess.class) { return switch (method.getName()) { case "getAgenticScope" -> registry().get(args[0]); @@ -132,7 +134,7 @@ private Object executeWorkflow(AgenticScope agenticScope, Method method, Object[ .orElseThrow( () -> new IllegalArgumentException( - "Workflow hasn't returned a Cognisphere object.")); + "Workflow hasn't returned a AgenticScope object.")); Object result = output.readState(outputName()); return method.getReturnType().equals(ResultWithAgenticScope.class) 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 09cc12cc..cfbaf545 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 @@ -42,6 +42,7 @@ public void testAgent() throws ExecutionException, InterruptedException { when(storySeedAgent.invoke(eq("A Great Story"))).thenReturn("storySeedAgent"); when(storySeedAgent.outputName()).thenReturn("premise"); + when(storySeedAgent.name()).thenReturn("storySeedAgent"); Workflow workflow = AgentWorkflowBuilder.workflow("storyFlow") @@ -72,12 +73,15 @@ public void testAgents() throws ExecutionException, InterruptedException { when(storySeedAgent.invoke(eq("A Great Story"))).thenReturn("storySeedAgent"); when(storySeedAgent.outputName()).thenReturn("premise"); + when(storySeedAgent.name()).thenReturn("storySeedAgent"); when(plotAgent.invoke(eq("storySeedAgent"))).thenReturn("plotAgent"); when(plotAgent.outputName()).thenReturn("plot"); + when(plotAgent.name()).thenReturn("plotAgent"); when(sceneAgent.invoke(eq("plotAgent"))).thenReturn("sceneAgent"); when(sceneAgent.outputName()).thenReturn("story"); + when(sceneAgent.name()).thenReturn("sceneAgent"); Workflow workflow = AgentWorkflowBuilder.workflow("storyFlow") @@ -112,12 +116,15 @@ public void testSequence() throws ExecutionException, InterruptedException { when(storySeedAgent.invoke(eq("A Great Story"))).thenReturn("storySeedAgent"); when(storySeedAgent.outputName()).thenReturn("premise"); + when(storySeedAgent.name()).thenReturn("storySeedAgent"); when(plotAgent.invoke(eq("storySeedAgent"))).thenReturn("plotAgent"); when(plotAgent.outputName()).thenReturn("plot"); + when(plotAgent.name()).thenReturn("plotAgent"); when(sceneAgent.invoke(eq("plotAgent"))).thenReturn("sceneAgent"); when(sceneAgent.outputName()).thenReturn("story"); + when(sceneAgent.name()).thenReturn("sceneAgent"); Workflow workflow = AgentWorkflowBuilder.workflow("storyFlow") @@ -149,12 +156,15 @@ public void testParallel() throws ExecutionException, InterruptedException { when(setting.invoke(eq("sci-fi"))).thenReturn("Fake conflict response"); when(setting.outputName()).thenReturn("setting"); + when(setting.name()).thenReturn("setting"); when(hero.invoke(eq("sci-fi"))).thenReturn("Fake hero response"); when(hero.outputName()).thenReturn("hero"); + when(hero.name()).thenReturn("hero"); when(conflict.invoke(eq("sci-fi"))).thenReturn("Fake setting response"); when(conflict.outputName()).thenReturn("conflict"); + when(conflict.name()).thenReturn("conflict"); Workflow workflow = AgentWorkflowBuilder.workflow("parallelFlow") @@ -193,12 +203,15 @@ public void testSeqAndThenParallel() throws ExecutionException, InterruptedExcep when(factAgent.invoke(eq("alien"))).thenReturn("Some Fact about aliens"); when(factAgent.outputName()).thenReturn("fact"); + when(factAgent.name()).thenReturn("fact"); when(cultureAgent.invoke(eq("Some Fact about aliens"))).thenReturn(cultureTraits); when(cultureAgent.outputName()).thenReturn("culture"); + when(cultureAgent.name()).thenReturn("culture"); when(technologyAgent.invoke(eq("Some Fact about aliens"))).thenReturn(technologyTraits); when(technologyAgent.outputName()).thenReturn("technology"); + when(technologyAgent.name()).thenReturn("technology"); Workflow workflow = AgentWorkflowBuilder.workflow("alienCultureFlow") .tasks( @@ -237,11 +250,13 @@ public void humanInTheLoop() throws ExecutionException, InterruptedException { eq("Discuss project updates"))) .thenReturn("Drafted meeting invitation for John Doe"); when(meetingInvitationDraft.outputName()).thenReturn("draft"); + when(meetingInvitationDraft.name()).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"); when(meetingInvitationStyle.outputName()).thenReturn("styled"); + when(meetingInvitationStyle.name()).thenReturn("styled"); AtomicReference request = new AtomicReference<>(); diff --git a/pom.xml b/pom.xml index b8daf0ee..88091a84 100644 --- a/pom.xml +++ b/pom.xml @@ -77,7 +77,8 @@ 1.5.18 - 2.19.2 + 2.20.0 + 2.20 1.5.8 5.1.0 4.0.1 @@ -90,7 +91,7 @@ 9.0.1.Final 6.0.0 - 1.3.0-beta9 + 1.4.0-beta10 1.4.0 @@ -136,7 +137,7 @@ com.fasterxml.jackson.core jackson-annotations - ${version.com.fasterxml.jackson} + ${version.com.fasterxml.jackson.annotations} io.cloudevents