refactor: remove debug prints and add logging for todo updates

learn
abel533 1 month ago
parent 1ecef9dc3a
commit 5878af1262
  1. 5
      src/main/java/io/mybatis/learn/s03/S03TodoWrite.java
  2. 10
      src/main/java/io/mybatis/learn/s03/TodoManager.java
  3. 21
      src/main/java/io/mybatis/learn/s08/BackgroundManager.java
  4. 9
      src/main/java/io/mybatis/learn/s08/S08BackgroundTasks.java

@ -85,11 +85,6 @@ public class S03TodoWrite implements CommandLineRunner {
.call()
.content();
// 每次回复后打印当前 todo 状态
System.out.println("\n--- Todo Status ---");
System.out.println(todoManager.render());
System.out.println("-------------------");
return response;
});
}

@ -1,5 +1,7 @@
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.ToolParam;
@ -23,6 +25,8 @@ import java.util.List;
*/
public class TodoManager {
private static final Logger log = LoggerFactory.getLogger(TodoManager.class);
/**
* Todo 项数据结构
* TIP: 对应 Python todo item 字典 {@code {"id": ..., "text": ..., "status": ...}}
@ -73,7 +77,11 @@ public class TodoManager {
}
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>
* TIP: 对应 Python {@code agents/s08_background_tasks.py} 中的 {@code BackgroundManager}
* 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>
* Main thread Background thread
* +-----------------+ +-----------------+
@ -42,7 +48,14 @@ public class BackgroundManager {
private final Map<String, TaskInfo> tasks = new ConcurrentHashMap<>();
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;
record TaskInfo(String status, String result, String command) {
@ -56,7 +69,9 @@ public class BackgroundManager {
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(
@ToolParam(description = "The shell command to run in background") String command) {
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() + "]");
}
// 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
+ ". 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)
.defaultSystem(system)

Loading…
Cancel
Save