refactor: remove debug prints and add logging for todo updates
This commit is contained in:
@@ -85,11 +85,6 @@ public class S03TodoWrite implements CommandLineRunner {
|
|||||||
.call()
|
.call()
|
||||||
.content();
|
.content();
|
||||||
|
|
||||||
// 每次回复后打印当前 todo 状态
|
|
||||||
System.out.println("\n--- Todo Status ---");
|
|
||||||
System.out.println(todoManager.render());
|
|
||||||
System.out.println("-------------------");
|
|
||||||
|
|
||||||
return response;
|
return response;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
package io.mybatis.learn.s03;
|
package io.mybatis.learn.s03;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.ai.tool.annotation.Tool;
|
import org.springframework.ai.tool.annotation.Tool;
|
||||||
import org.springframework.ai.tool.annotation.ToolParam;
|
import org.springframework.ai.tool.annotation.ToolParam;
|
||||||
|
|
||||||
@@ -23,6 +25,8 @@ import java.util.List;
|
|||||||
*/
|
*/
|
||||||
public class TodoManager {
|
public class TodoManager {
|
||||||
|
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(TodoManager.class);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Todo 项数据结构。
|
* Todo 项数据结构。
|
||||||
* TIP: 对应 Python 中 todo item 字典 {@code {"id": ..., "text": ..., "status": ...}}。
|
* TIP: 对应 Python 中 todo item 字典 {@code {"id": ..., "text": ..., "status": ...}}。
|
||||||
@@ -73,7 +77,11 @@ public class TodoManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.items = validated;
|
this.items = validated;
|
||||||
return render();
|
String rendered = render();
|
||||||
|
if (log.isDebugEnabled()) {
|
||||||
|
System.out.printf("📋 调用工具 [Todo] 更新 %d 项任务%n%s%n", items.size(), rendered);
|
||||||
|
}
|
||||||
|
return rendered;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -24,7 +24,13 @@ import java.util.stream.Collectors;
|
|||||||
* <p>
|
* <p>
|
||||||
* TIP: 对应 Python {@code agents/s08_background_tasks.py} 中的 {@code BackgroundManager} 类。
|
* TIP: 对应 Python {@code agents/s08_background_tasks.py} 中的 {@code BackgroundManager} 类。
|
||||||
* Python 使用 {@code threading.Thread(daemon=True)},
|
* Python 使用 {@code threading.Thread(daemon=True)},
|
||||||
* Java 使用 {@link ExecutorService} + 虚拟线程(Java 21)。
|
* Java 同样使用 daemon 平台线程(而非虚拟线程)。
|
||||||
|
* <p>
|
||||||
|
* ⚠️ 为何不用虚拟线程:{@code execute()} 内通过 {@code BufferedReader.lines()} 读取进程输出,
|
||||||
|
* 底层调用 {@code FileInputStream.read0()}(native 方法),会将虚拟线程
|
||||||
|
* <b>钉住(pin)在载体线程(carrier thread)</b> 上。
|
||||||
|
* 载体线程池大小 = {@code availableProcessors()},若池耗尽则后续任务只能串行等待。
|
||||||
|
* daemon 平台线程没有此约束,可真正并行执行多个阻塞 I/O 任务,符合 Python 版行为。
|
||||||
* <pre>
|
* <pre>
|
||||||
* Main thread Background thread
|
* Main thread Background thread
|
||||||
* +-----------------+ +-----------------+
|
* +-----------------+ +-----------------+
|
||||||
@@ -42,7 +48,14 @@ public class BackgroundManager {
|
|||||||
|
|
||||||
private final Map<String, TaskInfo> tasks = new ConcurrentHashMap<>();
|
private final Map<String, TaskInfo> tasks = new ConcurrentHashMap<>();
|
||||||
private final List<Notification> notificationQueue = new CopyOnWriteArrayList<>();
|
private final List<Notification> notificationQueue = new CopyOnWriteArrayList<>();
|
||||||
private final ExecutorService executor = Executors.newVirtualThreadPerTaskExecutor();
|
// TIP: 使用 daemon 平台线程而非虚拟线程。
|
||||||
|
// 读取进程输出时底层会调用 native read0(),虚拟线程遇到 native 方法会被 pin 在载体线程上,
|
||||||
|
// 导致多个后台任务串行排队。平台线程无此限制,对应 Python 的 threading.Thread(daemon=True)。
|
||||||
|
private final ExecutorService executor = Executors.newCachedThreadPool(r -> {
|
||||||
|
Thread t = new Thread(r, "bg-worker");
|
||||||
|
t.setDaemon(true);
|
||||||
|
return t;
|
||||||
|
});
|
||||||
private final String workDir;
|
private final String workDir;
|
||||||
|
|
||||||
record TaskInfo(String status, String result, String command) {
|
record TaskInfo(String status, String result, String command) {
|
||||||
@@ -56,7 +69,9 @@ public class BackgroundManager {
|
|||||||
log.info("BackgroundManager 初始化,workDir={}", workDir);
|
log.info("BackgroundManager 初始化,workDir={}", workDir);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Tool(description = "Run a command in a background thread. Returns task_id immediately without waiting.")
|
@Tool(description = "Run a command in a background thread. Returns task_id immediately without waiting. "
|
||||||
|
+ "When starting multiple independent background tasks, call this tool for ALL of them "
|
||||||
|
+ "in a single response (parallel function calls) so they start at the same time.")
|
||||||
public String backgroundRun(
|
public String backgroundRun(
|
||||||
@ToolParam(description = "The shell command to run in background") String command) {
|
@ToolParam(description = "The shell command to run in background") String command) {
|
||||||
String taskId = UUID.randomUUID().toString().substring(0, 8);
|
String taskId = UUID.randomUUID().toString().substring(0, 8);
|
||||||
|
|||||||
@@ -50,8 +50,15 @@ public class S08BackgroundTasks implements CommandLineRunner {
|
|||||||
System.out.println("[Background tasks completed: " + notifs.size() + "]");
|
System.out.println("[Background tasks completed: " + notifs.size() + "]");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TIP: 明确要求 LLM 并行调用 backgroundRun,避免逐个调用导致任务串行提交。
|
||||||
|
// 同时注入当前 OS 信息,让 LLM 选择平台适配的命令(如 Windows 用 timeout /t N /nobreak 替代 sleep N)。
|
||||||
|
String os = System.getProperty("os.name");
|
||||||
String system = "You are a coding agent at " + workDir
|
String system = "You are a coding agent at " + workDir
|
||||||
+ ". Use backgroundRun for long-running commands." + bgContext;
|
+ ". Current OS: " + os + "."
|
||||||
|
+ " Use backgroundRun for long-running commands."
|
||||||
|
+ " When starting multiple independent background tasks, issue ALL backgroundRun"
|
||||||
|
+ " calls in a single parallel batch so they begin simultaneously."
|
||||||
|
+ bgContext;
|
||||||
|
|
||||||
ChatClient chatClient = ChatClient.builder(chatModel)
|
ChatClient chatClient = ChatClient.builder(chatModel)
|
||||||
.defaultSystem(system)
|
.defaultSystem(system)
|
||||||
|
|||||||
Reference in New Issue
Block a user