diff --git a/src/main/java/com/openjiuwen/harness/task_loop/TaskLoopEventHandler.java b/src/main/java/com/openjiuwen/harness/task_loop/TaskLoopEventHandler.java index 7de75d691..b2528cf1e 100644 --- a/src/main/java/com/openjiuwen/harness/task_loop/TaskLoopEventHandler.java +++ b/src/main/java/com/openjiuwen/harness/task_loop/TaskLoopEventHandler.java @@ -4,6 +4,7 @@ package com.openjiuwen.harness.task_loop; +import com.openjiuwen.core.common.constants.Constant; import com.openjiuwen.core.controller.modules.EventHandler; import com.openjiuwen.core.controller.modules.EventHandlerInput; import com.openjiuwen.core.controller.schema.DataFrame; @@ -194,7 +195,10 @@ public Map handleTaskInteraction(EventHandlerInput inputs) { String message = ""; Event event = inputs == null ? null : inputs.getEvent(); if (event instanceof TaskInteractionEvent interactionEvent && !interactionEvent.getInteraction().isEmpty()) { - message = frameText(interactionEvent.getInteraction().get(0)); + DataFrame frame = interactionEvent.getInteraction().get(0); + if (!isStructuredInterrupt(frame)) { + message = frameText(frame); + } } if (!message.isBlank() && interactionQueues != null) { interactionQueues.pushSteer(message); @@ -325,6 +329,15 @@ private static String extractQuery(Event event) { return ""; } + private static boolean isStructuredInterrupt(DataFrame frame) { + if (!(frame instanceof DataFrame.JsonDataFrame jsonDataFrame) || jsonDataFrame.data() == null) { + return false; + } + Map data = jsonDataFrame.data(); + return Constant.INTERACTION.equals(String.valueOf(data.get("type"))) + || "interrupt".equals(String.valueOf(data.get("result_type"))); + } + private static String frameText(DataFrame frame) { if (frame instanceof DataFrame.TextDataFrame textDataFrame && textDataFrame.text() != null) { return textDataFrame.text(); diff --git a/src/test/java/com/openjiuwen/harness/task_loop/TaskLoopEventHandlerTest.java b/src/test/java/com/openjiuwen/harness/task_loop/TaskLoopEventHandlerTest.java index 7bb52fc2c..23be9a967 100644 --- a/src/test/java/com/openjiuwen/harness/task_loop/TaskLoopEventHandlerTest.java +++ b/src/test/java/com/openjiuwen/harness/task_loop/TaskLoopEventHandlerTest.java @@ -6,6 +6,7 @@ import static org.assertj.core.api.Assertions.assertThat; +import com.openjiuwen.core.common.constants.Constant; import com.openjiuwen.core.controller.ControllerConfig; import com.openjiuwen.core.controller.modules.EventHandlerInput; import com.openjiuwen.core.controller.modules.TaskManager; @@ -17,6 +18,7 @@ import com.openjiuwen.core.controller.schema.TaskInteractionEvent; import com.openjiuwen.core.controller.schema.TaskStatus; import com.openjiuwen.core.session.AgentSessionApi; +import com.openjiuwen.core.session.interaction.InteractionOutput; import com.openjiuwen.core.singleagent.schema.AgentCard; import com.openjiuwen.harness.DeepAgent; @@ -93,6 +95,49 @@ void handleTaskInteraction() { assertThat(queues.drainSteering()).containsExactly("change plan"); } + @Test + void structuredInteractionShouldNotEnterSteering() { + TaskLoopEventHandler handler = new TaskLoopEventHandler(makeAgent()); + LoopQueues queues = new LoopQueues(); + handler.setInteractionQueues(queues); + InteractionOutput payload = new InteractionOutput("ask-user-call", Map.of("question", "Continue?")); + TaskInteractionEvent event = new TaskInteractionEvent( + List.of(new DataFrame.JsonDataFrame(Map.of( + "type", Constant.INTERACTION, + "payload", payload + ))), + null + ); + + Map result = handler.handleTaskInteraction( + new EventHandlerInput(event, new FakeSession("s1")) + ); + + assertThat(result).containsEntry("msg", ""); + assertThat(queues.drainSteering()).isEmpty(); + } + + @Test + void interruptResultShouldNotEnterSteering() { + TaskLoopEventHandler handler = new TaskLoopEventHandler(makeAgent()); + LoopQueues queues = new LoopQueues(); + handler.setInteractionQueues(queues); + TaskInteractionEvent event = new TaskInteractionEvent( + List.of(new DataFrame.JsonDataFrame(Map.of( + "result_type", "interrupt", + "message", "approval required" + ))), + null + ); + + Map result = handler.handleTaskInteraction( + new EventHandlerInput(event, new FakeSession("s1")) + ); + + assertThat(result).containsEntry("msg", ""); + assertThat(queues.drainSteering()).isEmpty(); + } + @Test void handleTaskCompletionSignals() { TaskLoopEventHandler handler = new TaskLoopEventHandler(makeAgent());