Skip to content

Commit 37e4eba

Browse files
Merge branch 'main' into fix/1979-classpath-skill-repository-jar-fs
2 parents 582bc93 + 1f3fb28 commit 37e4eba

85 files changed

Lines changed: 3507 additions & 1117 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,8 @@ Built for enterprise deployment requirements:
8282
```
8383

8484
```java
85+
import io.agentscope.extensions.model.dashscope.DashScopeChatModel;
86+
8587
ReActAgent agent = ReActAgent.builder()
8688
.name("Assistant")
8789
.sysPrompt("You are a helpful AI assistant.")

README_zh.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,8 @@ AgentScope 设计上能够与现有企业基础设施集成,无需大规模改
8282
```
8383

8484
```java
85+
import io.agentscope.extensions.model.dashscope.DashScopeChatModel;
86+
8587
ReActAgent agent = ReActAgent.builder()
8688
.name("Assistant")
8789
.sysPrompt("You are a helpful AI assistant.")

SKILL.md

Lines changed: 51 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -21,15 +21,15 @@ When the user asks you to write AgentScope Java code, follow these instructions
2121
3. **NEVER use `ThreadLocal`** - Use Reactor Context with `Mono.deferContextual()`.
2222
4. **NEVER hardcode API keys** - Always use `System.getenv()`.
2323
5. **NEVER ignore errors silently** - Always log errors and provide fallback values.
24-
6. **NEVER use wrong import paths** - All models are in `io.agentscope.core.model.*`, NOT `io.agentscope.model.*`.
24+
6. **NEVER use wrong import paths** - Shared model interfaces are in `io.agentscope.core.model.*`; provider models are in `io.agentscope.extensions.model.<provider>.*`.
2525

2626
**✅ ALWAYS DO:**
2727
1. **Use `Mono` and `Flux`** for all asynchronous operations.
2828
2. **Chain operations** with `.map()`, `.flatMap()`, `.then()`.
2929
3. **Use Builder pattern** for creating agents, models, and messages.
3030
4. **Include error handling** with `.onErrorResume()` or `.onErrorReturn()`.
3131
5. **Add logging** with SLF4J for important operations.
32-
6. **Use correct imports**: `import io.agentscope.core.model.DashScopeChatModel;`
32+
6. **Use correct imports**: `import io.agentscope.extensions.model.dashscope.DashScopeChatModel;`
3333
7. **Use correct APIs** (many methods don't exist or have changed):
3434
- `toolkit.registerTool()` NOT `registerObject()`
3535
- `toolkit.getToolNames()` NOT `getTools()`
@@ -56,7 +56,7 @@ When the user asks you to write AgentScope Java code, follow these instructions
5656
2. Check: Are all operations non-blocking? → If no, **FIX IT**.
5757
3. Check: Does it have error handling? → If no, **ADD IT**.
5858
4. Check: Are API keys from environment? → If no, **CHANGE IT**.
59-
5. Check: Are imports correct? → If using `io.agentscope.model.*`, **FIX TO** `io.agentscope.core.model.*`.
59+
5. Check: Are imports correct? → If using provider models from `io.agentscope.core.model.*`, **FIX TO** `io.agentscope.extensions.model.<provider>.*`.
6060

6161
**Default code structure for agent logic:**
6262
```java
@@ -118,6 +118,11 @@ public static void main(String[] args) {
118118
<artifactId>agentscope-core</artifactId>
119119
<version>${agentscope.version}</version>
120120
</dependency>
121+
<dependency>
122+
<groupId>io.agentscope</groupId>
123+
<artifactId>agentscope-extensions-model-dashscope</artifactId>
124+
<version>${agentscope.version}</version>
125+
</dependency>
121126
</dependencies>
122127
```
123128

@@ -165,23 +170,23 @@ public static void main(String[] args) {
165170
</dependency>
166171
```
167172

168-
### Available Model Classes (all in agentscope-core)
173+
### Available Model Classes (provider-specific extension modules)
169174

170175
```java
171176
// DashScope (Alibaba Cloud)
172-
import io.agentscope.core.model.DashScopeChatModel;
177+
import io.agentscope.extensions.model.dashscope.DashScopeChatModel;
173178

174179
// OpenAI
175180
import io.agentscope.extensions.model.openai.OpenAIChatModel;
176181

177182
// Gemini (Google)
178-
import io.agentscope.core.model.GeminiChatModel;
183+
import io.agentscope.extensions.model.gemini.GeminiChatModel;
179184

180185
// Anthropic (Claude)
181-
import io.agentscope.core.model.AnthropicChatModel;
186+
import io.agentscope.extensions.model.anthropic.AnthropicChatModel;
182187

183188
// Ollama (Local models)
184-
import io.agentscope.core.model.OllamaChatModel;
189+
import io.agentscope.extensions.model.ollama.OllamaChatModel;
185190
```
186191

187192
### Optional Extensions
@@ -320,7 +325,7 @@ Extend `AgentBase` and implement `doCall(List<Msg> msgs)`:
320325
public class MyAgent extends AgentBase {
321326
private final Model model;
322327
private final Memory memory;
323-
328+
324329
public MyAgent(String name, Model model) {
325330
super(name, "A custom agent", true, List.of());
326331
this.model = model;
@@ -333,7 +338,7 @@ public class MyAgent extends AgentBase {
333338
if (msgs != null) {
334339
msgs.forEach(memory::addMessage);
335340
}
336-
341+
337342
// 2. Call model or logic
338343
return model.generate(memory.getMessages(), null, null)
339344
.map(response -> Msg.builder()
@@ -362,7 +367,7 @@ Use `@Tool` annotation for function-based tools. Tools can return:
362367
public class WeatherTools {
363368
@Tool(description = "Get current weather for a city. Returns temperature and conditions.")
364369
public String getWeather(
365-
@ToolParam(name = "city", description = "City name, e.g., 'San Francisco'")
370+
@ToolParam(name = "city", description = "City name, e.g., 'San Francisco'")
366371
String city) {
367372
// Implementation
368373
return "Sunny, 25°C";
@@ -374,10 +379,10 @@ public class WeatherTools {
374379
```java
375380
public class AsyncTools {
376381
private final WebClient webClient;
377-
382+
378383
@Tool(description = "Fetch data from trusted API endpoint")
379384
public Mono<String> fetchData(
380-
@ToolParam(name = "url", description = "API endpoint URL (must start with https://api.myservice.com)")
385+
@ToolParam(name = "url", description = "API endpoint URL (must start with https://api.myservice.com)")
381386
String url) {
382387
// SECURITY: Validate URL to prevent SSRF
383388
if (!url.startsWith("https://api.myservice.com")) {
@@ -444,7 +449,7 @@ Hook loggingHook = new Hook() {
444449
return Mono.just(event);
445450
}
446451
}
447-
452+
448453
@Override
449454
public int priority() {
450455
return 500; // Low priority (logging)
@@ -475,7 +480,7 @@ Hook loggingHook = new Hook() {
475480
}
476481
return Mono.just(event);
477482
}
478-
483+
479484
@Override
480485
public int priority() {
481486
return 500;
@@ -597,7 +602,7 @@ void testAgentCall() {
597602
.role(MsgRole.USER)
598603
.content(TextBlock.builder().text("Hello").build())
599604
.build();
600-
605+
601606
StepVerifier.create(agent.call(input))
602607
.assertNext(response -> {
603608
assertEquals(MsgRole.ASSISTANT, response.getRole());
@@ -616,12 +621,12 @@ void testWithMockModel() {
616621
.thenReturn(Mono.just(ChatResponse.builder()
617622
.text("Mocked response")
618623
.build()));
619-
624+
620625
ReActAgent agent = ReActAgent.builder()
621626
.name("TestAgent")
622627
.model(mockModel)
623628
.build();
624-
629+
625630
// Test agent behavior
626631
}
627632
```
@@ -722,7 +727,7 @@ Duration delay = Duration.ofMillis((long) Math.pow(2, attempt) * baseDelayMs);
722727
```java
723728
// ❌ WRONG
724729
Thread.sleep(1000);
725-
730+
726731
// ✅ CORRECT
727732
return Mono.delay(Duration.ofSeconds(1));
728733
```
@@ -740,7 +745,7 @@ Duration delay = Duration.ofMillis((long) Math.pow(2, attempt) * baseDelayMs);
740745
```java
741746
// ❌ WRONG
742747
.onErrorResume(e -> Mono.empty())
743-
748+
744749
// ✅ CORRECT
745750
.onErrorResume(e -> {
746751
log.error("Operation failed", e);
@@ -752,7 +757,7 @@ Duration delay = Duration.ofMillis((long) Math.pow(2, attempt) * baseDelayMs);
752757
```java
753758
// ❌ WRONG
754759
ThreadLocal<String> context = new ThreadLocal<>();
755-
760+
756761
// ✅ CORRECT
757762
return Mono.deferContextual(ctx -> {
758763
String value = ctx.get("key");
@@ -775,7 +780,7 @@ Duration delay = Duration.ofMillis((long) Math.pow(2, attempt) * baseDelayMs);
775780
```java
776781
// ❌ WRONG
777782
String apiKey = "sk-1234567890";
778-
783+
779784
// ✅ CORRECT
780785
String apiKey = System.getenv("OPENAI_API_KEY");
781786
```
@@ -788,7 +793,7 @@ Duration delay = Duration.ofMillis((long) Math.pow(2, attempt) * baseDelayMs);
788793
case PostActingEvent e -> handleActing(e);
789794
default -> Mono.just(event);
790795
};
791-
796+
792797
// ✅ CORRECT - Java 17 compatible
793798
if (event instanceof PreReasoningEvent e) {
794799
return handleReasoning(e);
@@ -878,7 +883,7 @@ import io.agentscope.core.model.Model;
878883
import io.agentscope.core.tool.Tool;
879884
import io.agentscope.core.tool.ToolParam;
880885
import io.agentscope.core.tool.Toolkit;
881-
import io.agentscope.core.model.DashScopeChatModel;
886+
import io.agentscope.extensions.model.dashscope.DashScopeChatModel;
882887
import org.slf4j.Logger;
883888
import org.slf4j.LoggerFactory;
884889
import reactor.core.publisher.Mono;
@@ -890,22 +895,22 @@ import java.time.format.DateTimeFormatter;
890895
* Complete example demonstrating AgentScope best practices.
891896
*/
892897
public class CompleteExample {
893-
898+
894899
private static final Logger log = LoggerFactory.getLogger(CompleteExample.class);
895-
900+
896901
public static void main(String[] args) {
897902
// 1. Create model (no .temperature() method, use defaultOptions)
898903
Model model = DashScopeChatModel.builder()
899904
.apiKey(System.getenv("DASHSCOPE_API_KEY"))
900905
.modelName("qwen-plus")
901906
.stream(true)
902907
.build();
903-
908+
904909
// 2. Create toolkit with tools
905910
Toolkit toolkit = new Toolkit();
906911
toolkit.registerTool(new WeatherTools());
907912
toolkit.registerTool(new TimeTools());
908-
913+
909914
// 3. Create hook for streaming output
910915
Hook streamingHook = new Hook() {
911916
@Override
@@ -918,13 +923,13 @@ public class CompleteExample {
918923
}
919924
return Mono.just(event);
920925
}
921-
926+
922927
@Override
923928
public int priority() {
924929
return 500; // Low priority
925930
}
926931
};
927-
932+
928933
// 4. Build agent
929934
ReActAgent agent = ReActAgent.builder()
930935
.name("Assistant")
@@ -935,65 +940,65 @@ public class CompleteExample {
935940
.hook(streamingHook)
936941
.maxIters(10)
937942
.build();
938-
943+
939944
// 5. Use agent
940945
Msg userMsg = Msg.builder()
941946
.role(MsgRole.USER)
942947
.content(TextBlock.builder()
943948
.text("What's the weather in San Francisco and what time is it?")
944949
.build())
945950
.build();
946-
951+
947952
try {
948953
System.out.println("User: " + userMsg.getTextContent());
949954
System.out.print("Assistant: ");
950-
955+
951956
// ⚠️ IMPORTANT: .block() is ONLY allowed in main() methods for demo purposes
952957
// NEVER use .block() in agent logic, service methods, or library code
953958
Msg response = agent.call(userMsg).block();
954-
959+
955960
System.out.println("\n\n--- Response Details ---");
956961
System.out.println("Role: " + response.getRole());
957962
System.out.println("Content: " + response.getTextContent());
958-
963+
959964
} catch (Exception e) {
960965
log.error("Error during agent execution", e);
961966
System.err.println("Error: " + e.getMessage());
962967
}
963968
}
964-
969+
965970
/**
966971
* Example tool class for weather information.
967972
*/
968973
public static class WeatherTools {
969-
974+
970975
@Tool(description = "Get current weather for a city. Returns temperature and conditions.")
971976
public String getWeather(
972-
@ToolParam(name = "city", description = "City name, e.g., 'San Francisco'")
977+
@ToolParam(name = "city", description = "City name, e.g., 'San Francisco'")
973978
String city) {
974-
979+
975980
log.info("Getting weather for city: {}", city);
976-
981+
977982
// Simulate API call
978983
return String.format("Weather in %s: Sunny, 22°C, Light breeze", city);
979984
}
980985
}
981-
986+
982987
/**
983988
* Example tool class for time information.
984989
*/
985990
public static class TimeTools {
986-
987-
private static final DateTimeFormatter FORMATTER =
991+
992+
private static final DateTimeFormatter FORMATTER =
988993
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
989-
994+
990995
@Tool(description = "Get current date and time")
991996
public String getCurrentTime() {
992997
LocalDateTime now = LocalDateTime.now();
993998
String formatted = now.format(FORMATTER);
994-
999+
9951000
log.info("Returning current time: {}", formatted);
996-
1001+
9971002
return "Current time: " + formatted;
9981003
}
9991004
}

0 commit comments

Comments
 (0)