当前位置: 首页 > news >正文

【从0到1构建一个ClaudeAgent】协作-Worktree+任务隔离 _

任务板管 "做什么" 但不管 "在哪做"。解法: 给每个任务一个独立的 git worktree 目录, 用任务 ID 把两边关联起来。"各干各的目录, 互不干扰",任务管目标,,worktree 管目录,按 ID 绑定。

Java实现代码

java

public class WorktreeTaskIsolationSystem { // --- 新增配置 --- private static final Path REPO_ROOT = detectRepoRoot(WORKDIR); // Git仓库根目录 private static final Path TASKS_DIR = REPO_ROOT.resolve(".tasks"); private static final Path WORKTREES_DIR = REPO_ROOT.resolve(".worktrees"); private static final Path EVENTS_LOG_PATH = WORKTREES_DIR.resolve("events.jsonl"); // --- 新增:Git 仓库检测 --- private static Path detectRepoRoot(Path cwd) { try { ProcessBuilder pb = new ProcessBuilder("git", "rev-parse", "--show-toplevel"); pb.directory(cwd.toFile()); Process process = pb.start(); boolean finished = process.waitFor(10, TimeUnit.SECONDS); if (!finished) { return cwd; } String output = new String(process.getInputStream().readAllBytes()).trim(); Path root = Paths.get(output); return Files.exists(root) ? root : cwd; // 自动检测:自动发现Git仓库根目录 // 向后兼容:如果不是Git仓库,使用当前目录 } catch (Exception e) { return cwd; } } // --- 新增:事件总线(EventBus)--- static class EventBus { private final Path eventLogPath; public EventBus(Path eventLogPath) { this.eventLogPath = eventLogPath; try { Files.createDirectories(eventLogPath.getParent()); if (!Files.exists(eventLogPath)) { Files.writeString(eventLogPath, ""); } } catch (IOException e) { throw new RuntimeException("Failed to create event bus", e); } } /** * 发出事件 */ public void emit(String event, Map<String, Object> task, Map<String, Object> worktree, String error) { Map<String, Object> payload = new LinkedHashMap<>(); payload.put("event", event); payload.put("ts", System.currentTimeMillis() / 1000.0); payload.put("task", task != null ? task : Map.of()); payload.put("worktree", worktree != null ? worktree : Map.of()); if (error != null) { payload.put("error", error); } // 结构化事件:事件类型、时间戳、关联数据 // 错误跟踪:支持记录操作失败信息 try { String jsonLine = gson.toJson(payload) + "\n"; Files.writeString(eventLogPath, jsonLine, StandardOpenOption.CREATE, StandardOpenOption.APPEND); // JSONL格式:每行一个事件,便于流式处理 // 追加写入:支持长时间运行的事件记录 } catch (IOException e) { System.err.println("Failed to emit event: " + e.getMessage()); } } /** * 列出最近事件 */ public String listRecent(int limit) { int n = Math.max(1, Math.min(limit, 200)); try { List<String> lines = Files.readAllLines(eventLogPath); List<Map<String, Object>> events = new ArrayList<>(); int start = Math.max(0, lines.size() - n); for (int i = start; i < lines.size(); i++) { try { Type type = new TypeToken<Map<String, Object>>(){}.getType(); Map<String, Object> event = gson.fromJson(lines.get(i), type); events.add(event); } catch (Exception e) { Map<String, Object> errorEvent = new HashMap<>(); errorEvent.put("event", "parse_error"); errorEvent.put("raw", lines.get(i)); events.add(errorEvent); // 容错处理:即使解析失败也记录原始数据 } } return gson.toJson(events); } catch (IOException e) { return "[]"; } } } // 初始化事件总线 private static final EventBus EVENTS = new EventBus(EVENTS_LOG_PATH); // --- 新增:任务管理器(支持工作树绑定)--- static class TaskManager { private final Path tasksDir; private int nextId = 1; public TaskManager(Path tasksDir) { this.tasksDir = tasksDir; try { Files.createDirectories(tasksDir); this.nextId = getMaxId() + 1; } catch (IOException e) { throw new RuntimeException("Failed to initialize task manager", e); } } /** * 绑定任务到工作树 */ public String bindWorktree(int taskId, String worktree, String owner) throws IOException { Map<String, Object> task = loadTask(taskId); task.put("worktree", worktree); // 任务-工作树关联:建立任务和工作树的双向链接 if (owner != null && !owner.isEmpty()) { task.put("owner", owner); } if ("pending".equals(task.get("status"))) { task.put("status", "in_progress"); // 状态自动转换:绑定工作树时自动开始任务 } task.put("updated_at", System.currentTimeMillis() / 1000.0); saveTask(task); return gson.toJson(task); } /** * 解绑工作树 */ public String unbindWorktree(int taskId) throws IOException { Map<String, Object> task = loadTask(taskId); task.put("worktree", ""); task.put("updated_at", System.currentTimeMillis() / 1000.0); saveTask(task); return gson.toJson(task); // 解绑机制:支持任务和工作树的解耦 } /** * 列出所有任务 */ public String listAllTasks() throws IOException { // ... 列出任务逻辑,包含工作树绑定信息 sb.append(String.format("%s #%d: %s%s%s\n", marker, id, subject, ownerStr, worktreeStr)); // 可视化展示:显示任务状态、所有者、工作树绑定 } } // 初始化任务管理器 private static final TaskManager TASKS = new TaskManager(TASKS_DIR); // --- 新增:工作树管理器(WorktreeManager)--- static class WorktreeManager { private final Path repoRoot; private final TaskManager taskManager; private final EventBus eventBus; private final Path worktreesDir; private final Path indexPath; private final boolean gitAvailable; public WorktreeManager(Path repoRoot, TaskManager taskManager, EventBus eventBus) { this.repoRoot = repoRoot; this.taskManager = taskManager; this.eventBus = eventBus; this.worktreesDir = repoRoot.resolve(".worktrees"); this.indexPath = worktreesDir.resolve("index.json"); // 集成架构:工作树管理器与任务管理器、事件总线集成 try { Files.createDirectories(worktreesDir); if (!Files.exists(indexPath)) { Map<String, Object> index = new HashMap<>(); index.put("worktrees", new ArrayList<Map<String, Object>>()); Files.writeString(indexPath, gson.toJson(index)); } } catch (IOException e) { throw new RuntimeException("Failed to initialize worktree manager", e); } this.gitAvailable = isGitRepo(); } /** * 检查是否是Git仓库 */ private boolean isGitRepo() { try { ProcessBuilder pb = new ProcessBuilder("git", "rev-parse", "--is-inside-work-tree"); pb.directory(repoRoot.toFile()); Process process = pb.start(); return process.exitValue() == 0; } catch (Exception e) { return false; } } /** * 执行Git命令 */ private String runGit(List<String> args) throws Exception { if (!gitAvailable) { throw new RuntimeException("Not in a git repository. worktree tools require git."); } ProcessBuilder pb = new ProcessBuilder("git"); pb.command().addAll(args); pb.directory(repoRoot.toFile()); Process process = pb.start(); boolean finished = process.waitFor(120, TimeUnit.SECONDS); if (!finished) { process.destroy(); throw new RuntimeException("git command timeout"); } int exitCode = process.exitValue(); if (exitCode != 0) { String error = new String(process.getErrorStream().readAllBytes()).trim(); String output = new String(process.getInputStream().readAllBytes()).trim(); String message = error.isEmpty() ? output : error; if (message.isEmpty()) { message = "git " + String.join(" ", args) + " failed"; } throw new RuntimeException(message); } String output = new String(process.getInputStream().readAllBytes()).trim(); String error = new String(process.getErrorStream().readAllBytes()).trim(); String result = output + (error.isEmpty() ? "" : "\n" + error); return result.isEmpty() ? "(no output)" : result; } /** * 加载索引文件 */ @SuppressWarnings("unchecked") private Map<String, Object> loadIndex() throws IOException { String content = Files.readString(indexPath); Type type = new TypeToken<Map<String, Object>>(){}.getType(); return gson.fromJson(content, type); } /** * 保存索引文件 */ private void saveIndex(Map<String, Object> index) throws IOException { Files.writeString(indexPath, gson.toJson(index)); } /** * 验证工作树名称 */ private void validateName(String name) { if (name == null || name.isEmpty() || name.length() > 40) { throw new IllegalArgumentException("Worktree name must be 1-40 characters"); } if (!name.matches("[A-Za-z0-9._-]+")) { throw new IllegalArgumentException( "Invalid worktree name. Use letters, numbers, ., _, - only" ); } // 名称规范:确保工作树名称安全且规范 } /** * 创建工作树 */ public String createWorktree(String name, Integer taskId, String baseRef) throws Exception { validateName(name); Map<String, Object> existing = findWorktree(name); if (existing != null) { throw new IllegalArgumentException("Worktree '" + name + "' already exists"); } if (taskId != null && !taskManager.taskExists(taskId)) { throw new IllegalArgumentException("Task " + taskId + " not found"); } // 发出创建前事件 Map<String, Object> taskInfo = taskId != null ? Map.of("id", taskId) : Map.of(); Map<String, Object> worktreeInfo = Map.of("name", name, "base_ref", baseRef); eventBus.emit("worktree.create.before", taskInfo, worktreeInfo, null); try { Path worktreePath = worktreesDir.resolve(name); String branch = "wt/" + name; // 自动生成分支名 // Git工作树创建 runGit(Arrays.asList("worktree", "add", "-b", branch, worktreePath.toString(), baseRef)); // Git工作树:独立的代码工作目录 // 自动分支:为每个工作树创建独立分支 // 创建索引条目 Map<String, Object> entry = new LinkedHashMap<>(); entry.put("name", name); entry.put("path", worktreePath.toString()); entry.put("branch", branch); entry.put("task_id", taskId); entry.put("status", "active"); entry.put("created_at", System.currentTimeMillis() / 1000.0); // 保存到索引 Map<String, Object> index = loadIndex(); @SuppressWarnings("unchecked") List<Map<String, Object>> worktrees = (List<Map<String, Object>>) index.get("worktrees"); worktrees.add(entry); saveIndex(index); // 绑定任务 if (taskId != null) { taskManager.bindWorktree(taskId, name, ""); } // 发出创建后事件 Map<String, Object> worktreeAfter = new LinkedHashMap<>(); worktreeAfter.put("name", name); worktreeAfter.put("path", worktreePath.toString()); worktreeAfter.put("branch", branch); worktreeAfter.put("status", "active"); eventBus.emit("worktree.create.after", taskInfo, worktreeAfter, null); return gson.toJson(entry); } catch (Exception e) { eventBus.emit("worktree.create.failed", taskInfo, Map.of("name", name, "base_ref", baseRef), e.getMessage()); throw e; } } /** * 获取工作树状态 */ public String getWorktreeStatus(String name) throws IOException { Map<String, Object> worktree = findWorktree(name); if (worktree == null) { return "Error: Unknown worktree '" + name + "'"; } Path worktreePath = Paths.get((String) worktree.get("path")); if (!Files.exists(worktreePath)) { return "Error: Worktree path missing: " + worktreePath; } try { ProcessBuilder pb = new ProcessBuilder("git", "status", "--short", "--branch"); pb.directory(worktreePath.toFile()); Process process = pb.start(); boolean finished = process.waitFor(60, TimeUnit.SECONDS); if (!finished) { process.destroy(); return "Error: Git status timeout"; } String output = new String(process.getInputStream().readAllBytes()).trim(); String error = new String(process.getErrorStream().readAllBytes()).trim(); String result = output + (error.isEmpty() ? "" : "\n" + error); return result.isEmpty() ? "Clean worktree" : result; // Git状态检查:提供详细的工作树状态信息 } catch (Exception e) { return "Error: " + e.getMessage(); } } /** * 在工作树中运行命令 */ public String runInWorktree(String name, String command) throws Exception { // 安全检查 String[] dangerous = {"rm -rf /", "sudo", "shutdown", "reboot", "> /dev/"}; for (String d : dangerous) { if (command.contains(d)) { return "Error: Dangerous command blocked"; } } Map<String, Object> worktree = findWorktree(name); if (worktree == null) { return "Error: Unknown worktree '" + name + "'"; } Path worktreePath = Paths.get((String) worktree.get("path")); if (!Files.exists(worktreePath)) { return "Error: Worktree path missing: " + worktreePath; } try { ProcessBuilder pb = new ProcessBuilder("bash", "-c", command); pb.directory(worktreePath.toFile()); // 目录隔离:命令在工作树的独立目录中执行 Process process = pb.start(); boolean finished = process.waitFor(300, TimeUnit.SECONDS); if (!finished) { process.destroy(); return "Error: Timeout (300s)"; } String output = new String(process.getInputStream().readAllBytes()).trim(); String error = new String(process.getErrorStream().readAllBytes()).trim(); String result = output + (error.isEmpty() ? "" : "\n" + error); return result.isEmpty() ? "(no output)" : result.substring(0, Math.min(result.length(), 50000)); } catch (Exception e) { return "Error: " + e.getMessage(); } } /** * 删除工作树 */ public String removeWorktree(String name, boolean force, boolean completeTask) throws Exception { Map<String, Object> worktree = findWorktree(name); if (worktree == null) { return "Error: Unknown worktree '" + name + "'"; } // 发出删除前事件 Integer taskId = (Integer) worktree.get("task_id"); Map<String, Object> taskInfo = taskId != null ? Map.of("id", taskId) : Map.of(); Map<String, Object> worktreeInfo = Map.of( "name", name, "path", worktree.get("path") ); eventBus.emit("worktree.remove.before", taskInfo, worktreeInfo, null); try { List<String> args = new ArrayList<>(); args.addAll(Arrays.asList("worktree", "remove")); if (force) { args.add("--force"); } args.add((String) worktree.get("path")); runGit(args); // Git工作树删除:清理Git工作树 // 完成任务 if (completeTask && taskId != null) { Map<String, Object> task = gson.fromJson(taskManager.getTask(taskId), new TypeToken<Map<String, Object>>(){}.getType()); taskManager.updateTask(taskId, "completed", null); taskManager.unbindWorktree(taskId); // 任务-工作树生命周期协同:删除工作树时自动完成任务 Map<String, Object> taskEvent = new HashMap<>(); taskEvent.put("id", taskId); taskEvent.put("subject", task.get("subject")); taskEvent.put("status", "completed"); eventBus.emit("task.completed", taskEvent, Map.of("name", name), null); } // 更新索引 Map<String, Object> index = loadIndex(); @SuppressWarnings("unchecked") List<Map<String, Object>> worktrees = (List<Map<String, Object>>) index.get("worktrees"); for (Map<String, Object> wt : worktrees) { if (name.equals(wt.get("name"))) { wt.put("status", "removed"); wt.put("removed_at", System.currentTimeMillis() / 1000.0); break; } } saveIndex(index); // 索引更新:标记工作树为已删除状态 // 发出删除后事件 Map<String, Object> worktreeAfter = new HashMap<>(); worktreeAfter.put("name", name); worktreeAfter.put("path", worktree.get("path")); worktreeAfter.put("status", "removed"); eventBus.emit("worktree.remove.after", taskInfo, worktreeAfter, null); return "Removed worktree '" + name + "'"; } catch (Exception e) { eventBus.emit("worktree.remove.failed", taskInfo, worktreeInfo, e.getMessage()); throw e; } } /** * 保留工作树(标记为保留状态) */ public String keepWorktree(String name) throws IOException { Map<String, Object> worktree = findWorktree(name); if (worktree == null) { return "Error: Unknown worktree '" + name + "'"; } Map<String, Object> index = loadIndex(); @SuppressWarnings("unchecked") List<Map<String, Object>> worktrees = (List<Map<String, Object>>) index.get("worktrees"); Map<String, Object> keptWorktree = null; for (Map<String, Object> wt : worktrees) { if (name.equals(wt.get("name"))) { wt.put("status", "kept"); wt.put("kept_at", System.currentTimeMillis() / 1000.0); keptWorktree = wt; break; } } saveIndex(index); // 保留状态:标记工作树为需要保留,不自动清理 // 发出保留事件 Integer taskId = (Integer) worktree.get("task_id"); Map<String, Object> taskInfo = taskId != null ? Map.of("id", taskId) : Map.of(); Map<String, Object> worktreeInfo = new HashMap<>(); worktreeInfo.put("name", name); worktreeInfo.put("path", worktree.get("path")); worktreeInfo.put("status", "kept"); eventBus.emit("worktree.keep", taskInfo, worktreeInfo, null); return keptWorktree != null ? gson.toJson(keptWorktree) : "Error: Unknown worktree '" + name + "'"; } } // 初始化工作树管理器 private static final WorktreeManager WORKTREES = new WorktreeManager(REPO_ROOT, TASKS, EVENTS); // --- 新增:工具处理器 --- static { // 新增任务工具 TOOL_HANDLERS.put("task_create", args -> { String subject = (String) args.get("subject"); String description = (String) args.get("description"); return TASKS.createTask(subject, description); }); TOOL_HANDLERS.put("task_list", args -> TASKS.listAllTasks()); TOOL_HANDLERS.put("task_get", args -> { int taskId = ((Number) args.get("task_id")).intValue(); return TASKS.getTask(taskId); }); TOOL_HANDLERS.put("task_update", args -> { int taskId = ((Number) args.get("task_id")).intValue(); String status = (String) args.get("status"); String owner = (String) args.get("owner"); return TASKS.updateTask(taskId, status, owner); }); TOOL_HANDLERS.put("task_bind_worktree", args -> { int taskId = ((Number) args.get("task_id")).intValue(); String worktree = (String) args.get("worktree"); String owner = (String) args.get("owner"); return TASKS.bindWorktree(taskId, worktree, owner); }); // 新增工作树工具 TOOL_HANDLERS.put("worktree_create", args -> { String name = (String) args.get("name"); Integer taskId = args.get("task_id") != null ? ((Number) args.get("task_id")).intValue() : null; String baseRef = (String) args.get("base_ref"); if (baseRef == null) baseRef = "HEAD"; return WORKTREES.createWorktree(name, taskId, baseRef); }); TOOL_HANDLERS.put("worktree_list", args -> WORKTREES.listWorktrees()); TOOL_HANDLERS.put("worktree_status", args -> { String name = (String) args.get("name"); return WORKTREES.getWorktreeStatus(name); }); TOOL_HANDLERS.put("worktree_run", args -> { String name = (String) args.get("name"); String command = (String) args.get("command"); return WORKTREES.runInWorktree(name, command); }); TOOL_HANDLERS.put("worktree_keep", args -> { String name = (String) args.get("name"); return WORKTREES.keepWorktree(name); }); TOOL_HANDLERS.put("worktree_remove", args -> { String name = (String) args.get("name"); boolean force = args.get("force") != null && (Boolean) args.get("force"); boolean completeTask = args.get("complete_task") != null && (Boolean) args.get("complete_task"); return WORKTREES.removeWorktree(name, force, completeTask); }); TOOL_HANDLERS.put("worktree_events", args -> { int limit = args.get("limit") != null ? ((Number) args.get("limit")).intValue() : 20; return EVENTS.listRecent(limit); }); } // --- 新增:工具定义 --- private static List<Map<String, Object>> getToolSpecs() { List<Map<String, Object>> tools = new ArrayList<>(); // 任务工具定义... // 工作树工具定义... return tools; } }

这段代码引入了工作树任务隔离系统,实现了:

  1. 目录级隔离:每个任务在自己的工作树中执行
  2. 控制平面与执行平面分离
    • 控制平面:任务管理(.tasks/)
    • 执行平面:工作树管理(.worktrees/)
  3. 事件总线:记录完整生命周期事件
  4. Git 工作树集成:利用 git worktree 实现隔离

关键洞察:通过目录隔离并行任务,通过任务ID进行协调。

Git工作树隔离架构

核心思想:从文件系统隔离升级为Git仓库级别的代码隔离,通过Git工作树实现完全隔离的并行开发环境,为每个任务提供独立的代码工作空间,避免冲突,支持真正的并行开发。

java

// 核心路径配置 private static final Path REPO_ROOT = detectRepoRoot(WORKDIR); // Git仓库根目录 private static final Path WORKTREES_DIR = REPO_ROOT.resolve(".worktrees"); // 工作树目录 // Git仓库感知:自动检测Git仓库根目录 // 工作树管理:专门的工作树存储目录 // 版本控制集成:与Git深度集成

java

// Git仓库检测 private static Path detectRepoRoot(Path cwd) { try { ProcessBuilder pb = new ProcessBuilder("git", "rev-parse", "--show-toplevel"); pb.directory(cwd.toFile()); Process process = pb.start(); String output = new String(process.getInputStream().readAllBytes()).trim(); Path root = Paths.get(output); return Files.exists(root) ? root : cwd; // 自动发现:自动定位Git仓库根目录 // 兼容处理:非Git仓库时回退到当前目录 } catch (Exception e) { return cwd; } }
  • Git原生集成:深度集成Git版本控制系统
  • 仓库感知:自动识别和适应Git仓库结构
  • 向后兼容:非Git环境也能工作
  • 专业级隔离:为专业软件开发设计

工作树管理系统

java

// 工作树管理器核心 static class WorktreeManager { private final Path repoRoot; private final TaskManager taskManager; private final EventBus eventBus; private final Path worktreesDir; private final Path indexPath; private final boolean gitAvailable; // 三组件集成:仓库、任务、事件总线 // 索引管理:工作树元数据索引 // 可用性检查:检测Git环境 }
  • 集成架构:与任务管理和事件系统深度集成
  • 元数据管理:工作树元数据集中管理
  • 环境感知:自动检测和适应Git环境
  • 专业级管理:企业级的工作树生命周期管理

Git工作树创建机制

java

// 创建工作树 public String createWorktree(String name, Integer taskId, String baseRef) throws Exception { validateName(name); Path worktreePath = worktreesDir.resolve(name); String branch = "wt/" + name; // 自动生成分支名 // Git工作树创建 runGit(Arrays.asList("worktree", "add", "-b", branch, worktreePath.toString(), baseRef)); // Git工作树:独立的工作目录 // 自动分支:为每个工作树创建独立分支 // 创建索引条目 Map<String, Object> entry = new LinkedHashMap<>(); entry.put("name", name); entry.put("path", worktreePath.toString()); entry.put("branch", branch); entry.put("task_id", taskId); entry.put("status", "active"); entry.put("created_at", System.currentTimeMillis() / 1000.0); // 完整元数据:名称、路径、分支、关联任务 // 状态管理:明确的工作树生命周期状态 // 保存到索引 Map<String, Object> index = loadIndex(); @SuppressWarnings("unchecked") List<Map<String, Object>> worktrees = (List<Map<String, Object>>) index.get("worktrees"); worktrees.add(entry); saveIndex(index); // 索引管理:集中式工作树元数据管理 // 持久化:工作树信息持久化存储 }
  • Git原生:使用Git工作树实现真正的代码隔离
  • 自动分支:为每个工作树自动创建分支
  • 元数据完整:完整的工作树元数据记录
  • 持久化索引:工作树信息持久化存储
  • 状态管理:明确的工作树生命周期状态

任务-工作树双向绑定

java

// 任务管理器中的工作树绑定 public String bindWorktree(int taskId, String worktree, String owner) throws IOException { Map<String, Object> task = loadTask(taskId); task.put("worktree", worktree); // 双向绑定:任务记录工作树,工作树记录任务 // 关联管理:建立任务和工作树的一对一关系 if (owner != null && !owner.isEmpty()) { task.put("owner", owner); } if ("pending".equals(task.get("status"))) { task.put("status", "in_progress"); // 状态自动转换:绑定工作树时自动开始任务 // 工作流优化:简化任务启动流程 } task.put("updated_at", System.currentTimeMillis() / 1000.0); saveTask(task); return gson.toJson(task); }

java

// 工作树管理器中的任务绑定 if (taskId != null) { taskManager.bindWorktree(taskId, name, ""); // 协同绑定:创建工作树时自动绑定任务 // 双向同步:确保任务和工作树状态一致 }
  • 双向关联:任务和工作树相互引用
  • 状态协同:任务和工作树状态自动同步
  • 工作流简化:自动的状态转换和绑定
  • 数据一致性:确保关联数据的一致性

工作树操作隔离

java

// 在工作树中运行命令 public String runInWorktree(String name, String command) throws Exception { Map<String, Object> worktree = findWorktree(name); Path worktreePath = Paths.get((String) worktree.get("path")); try { ProcessBuilder pb = new ProcessBuilder("bash", "-c", command); pb.directory(worktreePath.toFile()); // 目录隔离:命令在工作树的独立目录中执行 // 环境隔离:每个工作树有自己的Git环境 Process process = pb.start(); boolean finished = process.waitFor(300, TimeUnit.SECONDS); String output = new String(process.getInputStream().readAllBytes()).trim(); String error = new String(process.getErrorStream().readAllBytes()).trim(); String result = output + (error.isEmpty() ? "" : "\n" + error); return result.isEmpty() ? "(no output)" : result.substring(0, Math.min(result.length(), 50000)); } catch (Exception e) { return "Error: " + e.getMessage(); } }
  • 完全隔离:每个工作树是独立的文件系统目录
  • Git环境隔离:每个工作树有自己的Git配置和历史
  • 安全执行:命令在隔离环境中执行
  • 结果返回:返回完整的命令执行结果

Git状态检查

java

// 获取工作树状态 public String getWorktreeStatus(String name) throws IOException { Path worktreePath = Paths.get((String) worktree.get("path")); try { ProcessBuilder pb = new ProcessBuilder("git", "status", "--short", "--branch"); pb.directory(worktreePath.toFile()); // Git状态:获取详细的工作树Git状态 // 信息丰富:包括分支信息、变更状态等 Process process = pb.start(); boolean finished = process.waitFor(60, TimeUnit.SECONDS); String output = new String(process.getInputStream().readAllBytes()).trim(); String error = new String(process.getErrorStream().readAllBytes()).trim(); String result = output + (error.isEmpty() ? "" : "\n" + error); return result.isEmpty() ? "Clean worktree" : result; } catch (Exception e) { return "Error: " + e.getMessage(); } }
  • Git专业:提供专业的Git状态信息
  • 实时状态:实时检查工作树的Git状态
  • 变更追踪:跟踪代码变更情况
  • 问题诊断:便于诊断Git相关问题

工作树生命周期管理

java

// 删除工作树 public String removeWorktree(String name, boolean force, boolean completeTask) throws Exception { // Git工作树删除 List<String> args = new ArrayList<>(); args.addAll(Arrays.asList("worktree", "remove")); if (force) { args.add("--force"); } args.add((String) worktree.get("path")); runGit(args); // Git清理:使用Git命令清理工作树 // 选项支持:支持强制删除等选项 // 完成任务 if (completeTask && taskId != null) { taskManager.updateTask(taskId, "completed", null); taskManager.unbindWorktree(taskId); // 生命周期协同:删除工作树时自动完成任务 // 状态清理:清理任务和工作树的关联 Map<String, Object> taskEvent = new HashMap<>(); taskEvent.put("id", taskId); taskEvent.put("subject", task.get("subject")); taskEvent.put("status", "completed"); eventBus.emit("task.completed", taskEvent, Map.of("name", name), null); } // 更新索引 for (Map<String, Object> wt : worktrees) { if (name.equals(wt.get("name"))) { wt.put("status", "removed"); wt.put("removed_at", System.currentTimeMillis() / 1000.0); break; } } saveIndex(index); // 状态更新:标记工作树为已删除状态 // 历史保留:保留工作树的删除记录 }
  • 完整生命周期:创建、使用、保留、删除的完整生命周期
  • Git原生:使用Git命令管理工作树
  • 任务协同:工作树删除时自动处理关联任务
  • 状态管理:明确的工作树状态管理
  • 历史追踪:保留工作树的历史记录

工作树保留机制

java

// 保留工作树 public String keepWorktree(String name) throws IOException { for (Map<String, Object> wt : worktrees) { if (name.equals(wt.get("name"))) { wt.put("status", "kept"); wt.put("kept_at", System.currentTimeMillis() / 1000.0); keptWorktree = wt; break; } } saveIndex(index); // 保留状态:标记工作树为需要保留 // 不自动清理:保留的工作树不会被自动清理 // 时间戳记录:记录保留时间 }
  • 选择性保留:可以保留有价值的工作树
  • 长期存储:保留的工作树可以长期存在
  • 状态明确:明确的保留状态标记
  • 时间追踪:记录保留时间

事件总线集成

java

// 事件总线 static class EventBus { public void emit(String event, Map<String, Object> task, Map<String, Object> worktree, String error) { Map<String, Object> payload = new LinkedHashMap<>(); payload.put("event", event); payload.put("ts", System.currentTimeMillis() / 1000.0); payload.put("task", task != null ? task : Map.of()); payload.put("worktree", worktree != null ? worktree : Map.of()); if (error != null) { payload.put("error", error); } // 结构化事件:标准的事件格式 // 时间戳:精确的事件时间 // 关联数据:关联的任务和工作树信息 // 错误信息:支持错误事件记录 String jsonLine = gson.toJson(payload) + "\n"; Files.writeString(eventLogPath, jsonLine, StandardOpenOption.CREATE, StandardOpenOption.APPEND); // JSONL格式:便于流式处理和分析 // 追加写入:支持长时间运行的事件记录 } }
  • 全面审计:所有工作树操作都有完整的事件记录
  • 结构化日志:标准化的JSON事件格式
  • 时间序列:精确的时间戳序列
  • 错误追踪:完整的错误事件追踪
  • 可分析性:便于后续的数据分析

架构演进与价值

从 AutonomousAgentsSystem 到 WorktreeTaskIsolationSystem 的升级

维度AutonomousAgentsSystemWorktreeTaskIsolationSystem
代码隔离文件系统级Git仓库级
并行开发有限并行完全并行
版本控制外部集成原生集成
冲突避免手动管理自动隔离
专业程度通用系统专业开发系统

总结

完结撒花。。。

总体来说,这个开源网站系统性地拆解了一个高级AI编程智能体的构建过程,展现了一条清晰的能力演进路径:从具备基础感知和执行能力的单一智能体(工具与执行),发展到能够进行内部规划、分解任务、调用外部知识的协调者(规划与协调),再升级为可以管理资源、并行处理、支撑长时对话的高效执行者(内存管理与并发),最终演化为一个角色分明、通信

http://www.jsqmd.com/news/1146163/

相关文章:

  • Label Studio终极指南:免费开源的多模态数据标注工具
  • APK Installer:Windows跨平台Android应用安装解决方案
  • 直付通二级商户的“信任杠杆”:用好一级方的背书效应
  • 惠普暗影精灵笔记本终极性能控制指南:OmenSuperHub完整教程
  • 现代操作系统与大学教材的鸿沟:从理论抽象到工程实践的跨越
  • 变分推断与KL散度:从ELBO推导到VAE损失函数的3步拆解
  • 如何用神奇工具轻松下载全网小说:novel-downloader终极指南
  • 你的SEO排名再高也挡不住AI搜索的降维打击
  • 搜不到你的品牌?2026年AI搜索排名优化(GEO)的完整技术指南
  • 和平精英吃丹修仙灵宠洗练进化路线 云手机刷魔君养灵宠性价比
  • MDAnalysis 2.9.0:分子动力学分析的并行计算革新与生态演进
  • 2026微博图片去水印方法,合法合规教程,手机电脑工具推荐
  • 普推黑体(PUTUI)最终版来了,揭开免费字体的注意!
  • SPDK网络存储实现:NVMe-oF和iSCSI target的完整部署指南
  • 从告警到多防火墙联动封禁:智能体与XDR的自动化响应实践
  • 爬坑 10 年!京东店铺全量商品接口实战开发:从分页优化、SKU 关联到数据完整性闭环
  • 《低空无人系统智能中枢平台 · 公司级技术与产品总纲(V1.0)》
  • 鸿蒙新特性:Swiper 轮播组件——构建知识卡片浏览器
  • 记一次网络io学习流水账
  • AutoCVE是一款基于多Agent协同的全流程自动化CVE挖掘与源码审计系统
  • RPG Maker Decrypter终极指南:轻松解密RPG游戏加密资源的完整教程
  • Dism++ Windows系统优化终极指南:3个步骤让电脑重获新生
  • Windows 10/11终极指南:轻松解决PL2303芯片驱动兼容性问题
  • OpenWrt Turbo ACC网络加速深度解析:解锁路由器性能的终极方案
  • 为什么临床前实验优先选用ICR小鼠动物模型?_MedChemExpress (MCE)
  • 144、SIoU 引入角度惩罚的 YOLOv11 代码实现:四阶段距离度量的完整计算
  • SQLyog 与 Navicat 下载安装全攻略:从零开始快速上手两大 MySQL 图形化工具
  • 5分钟搞定微信QQ防撤回:不再错过任何重要消息
  • codex: command not found 2026年全平台修复指南
  • 通达信缠论量化插件:5分钟快速掌握专业级技术分析的完整指南