Skip to content

Commit 9975da6

Browse files
committed
Merge branch 'refs/heads/main' into feat/replace_genai_sdk
# Conflicts: # agentscope-core/src/main/java/io/agentscope/core/agent/AgentBase.java # agentscope-core/src/test/java/io/agentscope/core/tool/mcp/McpClientBuilderTest.java
2 parents 8e109b1 + dd358b7 commit 9975da6

32 files changed

Lines changed: 1571 additions & 202 deletions

File tree

agentscope-core/src/main/java/io/agentscope/core/ReActAgent.java

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -648,7 +648,10 @@ protected Mono<Msg> summarizing() {
648648
postEvent -> {
649649
Msg finalMsg =
650650
postEvent
651-
.getSummaryMessage();
651+
.getSummaryMessage()
652+
.withGenerateReason(
653+
GenerateReason
654+
.MAX_ITERATIONS);
652655
memory.addMessage(finalMsg);
653656
return finalMsg;
654657
}));
@@ -747,12 +750,9 @@ private boolean isFinished(Msg msg) {
747750
List<ToolUseBlock> toolCalls = msg.getContentBlocks(ToolUseBlock.class);
748751

749752
// No tool calls - finished
750-
if (toolCalls.isEmpty()) {
751-
return true;
752-
}
753-
754-
// Has tool calls but none are in toolkit - finished
755-
return toolCalls.stream().noneMatch(tc -> toolkit.getTool(tc.getName()) != null);
753+
// If there are tool calls (even non-existent ones), continue to acting phase
754+
// where ToolExecutor will return "Tool not found" error for the model to see
755+
return toolCalls.isEmpty();
756756
}
757757

758758
/**

agentscope-core/src/main/java/io/agentscope/core/agent/AgentBase.java

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,8 @@ public abstract class AgentBase implements StateModule, Agent {
9999
// Interrupt state management (available to all agents)
100100
private final AtomicBoolean interruptFlag = new AtomicBoolean(false);
101101
private final AtomicReference<Msg> userInterruptMessage = new AtomicReference<>(null);
102+
// Hook non-null
103+
private static final Comparator<Hook> HOOK_COMPARATOR = Comparator.comparingInt(Hook::priority);
102104

103105
/**
104106
* Constructor for AgentBase.
@@ -134,6 +136,7 @@ public AgentBase(String name, String description, boolean checkRunning, List<Hoo
134136
this.checkRunning = checkRunning;
135137
this.hooks = new CopyOnWriteArrayList<>(hooks != null ? hooks : List.of());
136138
this.hooks.addAll(systemHooks);
139+
sortHooks();
137140
}
138141

139142
@Override
@@ -475,9 +478,14 @@ public List<Hook> getHooks() {
475478
protected void addHook(Hook hook) {
476479
if (hook != null) {
477480
hooks.add(hook);
481+
sortHooks();
478482
}
479483
}
480484

485+
private void sortHooks() {
486+
this.hooks.sort(HOOK_COMPARATOR);
487+
}
488+
481489
/**
482490
* Remove a hook from this agent dynamically.
483491
*
@@ -499,7 +507,7 @@ protected void removeHook(Hook hook) {
499507
* @return Sorted list of hooks
500508
*/
501509
protected List<Hook> getSortedHooks() {
502-
return hooks.stream().sorted(Comparator.comparingInt(Hook::priority)).toList();
510+
return hooks;
503511
}
504512

505513
/**
@@ -693,7 +701,7 @@ private Flux<Event> createEventStream(StreamOptions options, Supplier<Mono<Msg>>
693701
new StreamingHook(sink, options);
694702

695703
// Add temporary hook
696-
hooks.add(streamingHook);
704+
addHook(streamingHook);
697705

698706
// Use Mono.defer to ensure trace context propagation
699707
// while maintaining streaming hook functionality

agentscope-core/src/main/java/io/agentscope/core/formatter/openai/OpenAIConversationMerger.java

Lines changed: 8 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -83,38 +83,16 @@ public OpenAIMessage mergeToUserMessage(
8383
StringBuilder textBuffer = new StringBuilder();
8484
textBuffer.append(conversationHistoryPrompt);
8585
textBuffer.append(HISTORY_START_TAG).append("\n");
86-
87-
// Process all messages EXCEPT the last one as history
88-
int lastIndex = msgs.size() - 1;
89-
90-
// Append history messages
91-
if (lastIndex > 0) {
92-
for (int i = 0; i < lastIndex; i++) {
93-
processMessage(
94-
msgs.get(i),
95-
roleFormatter,
96-
toolResultConverter,
97-
textBuffer,
98-
allParts,
99-
true);
100-
}
101-
}
102-
textBuffer.append(HISTORY_END_TAG).append("\n");
103-
104-
// Process the last message (current turn)
105-
if (lastIndex >= 0) {
106-
// Include prefix only if there is history (multi-turn context)
107-
// or if it's explicitly needed. For single-turn user queries,
108-
// omitting the prefix makes it look like a standard chat request.
109-
boolean includePrefix = lastIndex > 0;
86+
// Include prefix only if there is history (multi-turn context)
87+
// For single-turn user queries,
88+
// omitting the prefix makes it look like a standard chat request.
89+
boolean includePrefix = msgs.size() > 1;
90+
// Process all messages as history (similar to DashScopeConversationMerger)
91+
for (Msg msg : msgs) {
11092
processMessage(
111-
msgs.get(lastIndex),
112-
roleFormatter,
113-
toolResultConverter,
114-
textBuffer,
115-
allParts,
116-
includePrefix);
93+
msg, roleFormatter, toolResultConverter, textBuffer, allParts, includePrefix);
11794
}
95+
textBuffer.append(HISTORY_END_TAG).append("\n");
11896

11997
// Flush remaining text
12098
if (textBuffer.length() > 0) {

agentscope-core/src/main/java/io/agentscope/core/skill/repository/ClasspathSkillRepository.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,9 @@ protected ClasspathSkillRepository(String resourcePath, String source, ClassLoad
139139
if ("jar".equals(uri.getScheme())) {
140140
this.isJar = true;
141141
this.fileSystem = FileSystems.newFileSystem(uri, Collections.emptyMap());
142-
String actualResourcePath = uri.getSchemeSpecificPart().split("!")[1];
142+
String schemeSpecificUriPath = uri.getSchemeSpecificPart();
143+
String actualResourcePath =
144+
schemeSpecificUriPath.substring(schemeSpecificUriPath.lastIndexOf("!") + 1);
143145
logger.info("Actual resource path: {}", actualResourcePath);
144146
this.skillBasePath = fileSystem.getPath(actualResourcePath);
145147
} else {

agentscope-core/src/test/java/io/agentscope/core/agent/ReActAgentTest.java

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
import io.agentscope.core.hook.ReasoningChunkEvent;
3333
import io.agentscope.core.memory.InMemoryMemory;
3434
import io.agentscope.core.message.ContentBlock;
35+
import io.agentscope.core.message.GenerateReason;
3536
import io.agentscope.core.message.Msg;
3637
import io.agentscope.core.message.MsgRole;
3738
import io.agentscope.core.message.TextBlock;
@@ -482,9 +483,13 @@ void testMaxIterations() {
482483

483484
// Get response with timeout
484485
// Verify it completes within reasonable time (not infinite loop)
485-
agent.call(userMsg)
486-
.timeout(Duration.ofMillis(TestConstants.DEFAULT_TEST_TIMEOUT_MS))
487-
.block(Duration.ofMillis(TestConstants.DEFAULT_TEST_TIMEOUT_MS));
486+
Msg response =
487+
agent.call(userMsg)
488+
.timeout(Duration.ofMillis(TestConstants.DEFAULT_TEST_TIMEOUT_MS))
489+
.block(Duration.ofMillis(TestConstants.DEFAULT_TEST_TIMEOUT_MS));
490+
491+
// Verify max iterations generate reason was respected
492+
assertEquals(GenerateReason.MAX_ITERATIONS, response.getGenerateReason());
488493

489494
// Verify max iterations was respected
490495
assertTrue(

0 commit comments

Comments
 (0)