当前位置: 首页 > 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)); } /** * 验证工作树名称 */
http://www.jsqmd.com/news/1076639/

相关文章:

  • 5分钟快速上手wechat-need-web:让微信网页版在浏览器中重获新生
  • 物联网安全架构设计:从芯片到云的分层防御与实战指南
  • CVE-2025-54123漏洞复现:Hoverfly管理API命令注入实战解析
  • Appium自动化测试环境搭建保姆级指南:从零到一运行第一个脚本
  • 15-代码规范与代码审查
  • 16-SEO 与 GEO:让内容被搜索引擎和 AI 发现
  • GetQzonehistory:你的QQ空间数据备份终极指南
  • 2026夏季新款工作衬衫,吸汗透气加防晒,清凉一夏
  • 三步解锁Dism++:从系统小白到维护专家的蜕变之旅
  • 如何为Windows 11 LTSC系统安装Microsoft Store:终极完整指南
  • 分布式GUI自动化测试框架:架构设计与工程实践指南
  • 3步快速部署:Windows风扇控制完全指南
  • 自动售货机常见故障自查指南,遇到问题不慌张~YH
  • 【CXD720】-为何要将将寄存器放入IOB中?
  • 基于eQTL数据库研究基因和疾病因果关系流程
  • 2026生成式引擎优化(GEO)行业科普市场乱象、企业落地逻辑与合规长效运营指南
  • 【计算机毕业设计案例】基于 Python 的畅联智购购物车交易系统设计与实现 基于 Python 的畅联智购电商数据管理系统设计与实现(程序+文档+讲解+定制)
  • 从零到一:基于YOLOv8的AI自瞄助手如何彻底改变你的FPS游戏体验
  • Roblox帧率解锁器:打破60FPS限制,释放游戏流畅体验
  • 如何利用智能图像去重技术高效管理海量图片资源
  • FriendlyWrt VS Debian / Ubuntu 无桌面服务器版(一)
  • TurtleBot3 LDS激光雷达硬件接入与稳定通信实战指南
  • SQL注入攻防实战:从原理剖析到自动化工具利用
  • 【毕业设计】基于 SpringBoot 的图书商品信息运维管理系统设计与实现 校园线上图书购买商城系统设计与实现(源码+文档+远程调试,全bao定制等)
  • 大脑的「偏好」:节能、新奇怪异、即时反馈、认可、规律、预测成功、确定
  • MuleSoft AI编排:企业级LLM集成的治理与可审计实践
  • Visual Paradigm实战指南:序列图绘制与消息流优化
  • 万兴科技携万兴剧厂亮相上海电视节,AI剧本创作全链路能力成关注焦点
  • 5步精通DLSS版本管理:DLSS Swapper让游戏性能优化变得如此简单
  • 什么是PSRAM?PSRAM芯片选型指南