Skip to content

Latest commit

 

History

History
192 lines (153 loc) · 5.9 KB

File metadata and controls

192 lines (153 loc) · 5.9 KB

该系列文章基于 github.com/shareAI-lab/learn-claude-code 写就,该仓库以大道至简的风格剖析了Claude Code的核心原理,值得大家学习。由于该仓库是基于Python语言,为方便.NET开发者学习,我已经将代码基于.NET 10的dotnet file 重写,源码已上传至github,源码地址见文末。

v6: 任务系统 - 文件系统上的持久化任务看板

本文是 Learn Claude Code (C# 版) 系列的第七篇,对应代码文件 v6_task_system_agent.cs

问题:压缩会清除记忆

v5 的上下文压缩解决了窗口溢出问题,但带来了副作用:

当对话被压缩时,所有的任务状态都丢失了。

想象你在管理一个 10 个任务的项目:

压缩前:
  Task 1: done ✓
  Task 2: in-progress 🔄
  Task 3: blocked by Task 2 ⏳
  ... (全在上下文中)

压缩后:
  [Summary]: "用户在处理一个多任务项目"
  ...具体任务? 不知道了

你需要一种方式让状态存活于上下文压缩之外

解决方案:文件系统上的任务看板

任务以 JSON 文件持久化在 .tasks/ 目录中,每个任务一个文件:

.tasks/
  ├── task_001.json     ← { "id": "001", "title": "...", "status": "done" }
  ├── task_002.json     ← { "id": "002", "title": "...", "status": "in-progress" }
  └── task_003.json     ← { "id": "003", "blockedBy": ["002"], ... }
Agent Context                    File System (.tasks/)
+------------------+            +------------------+
| Messages[]       |            | task_001.json    |
| (can be cleared) |  ←--读取--→ | task_002.json    |
|                  |            | task_003.json    |
+------------------+            +------------------+
     ↑ volatile                      ↑ persistent

TaskManager 核心类

class TaskManager
{
    string taskDir;
    int nextId;

    public TaskManager()
    {
        taskDir = ".tasks";
        Directory.CreateDirectory(taskDir);
        // ... 从已有文件推断 nextId ...
    }

创建任务

    public string Create(string title, string description, List<string>? blockedBy)
    {
        var id = $"{nextId++:D3}";
        var task = new Dictionary<string, object>
        {
            ["id"] = id,
            ["title"] = title,
            ["description"] = description,
            ["status"] = "pending",
            ["blockedBy"] = blockedBy ?? [],
            ["blocks"] = new List<string>()
        };

        // 双向依赖连接
        if (blockedBy != null)
            foreach (var depId in blockedBy)
            {
                var dep = Load(depId);
                ((List<string>)dep["blocks"]).Add(id);
                Save(depId, dep);
            }

        Save(id, task);
        return id;
    }

依赖图

    // 完成任务时, 自动从下游任务的 blockedBy 中移除自己
    public void ClearDependency(string finishedId)
    {
        var finished = Load(finishedId);
        foreach (var downId in (List<string>)finished["blocks"])
        {
            var down = Load(downId);
            ((List<string>)down["blockedBy"]).Remove(finishedId);
            Save(downId, down);
        }
    }

当更新任务状态为 done 时,自动调用 ClearDependency

    public void Update(string id, string? status, string? title)
    {
        var task = Load(id);
        if (title != null) task["title"] = title;
        if (status != null)
        {
            task["status"] = status;
            if (status == "done") ClearDependency(id);
        }
        Save(id, task);
    }

工具定义

除了原有的 4 个基础工具外,新增 4 个任务工具:

工具 参数 说明
task_create title, description, blocked_by 创建任务,自动建立双向依赖
task_update task_id, status, title 更新任务状态,完成时自动清除依赖
task_list - 列出所有任务概览
task_get task_id 获取单个任务详情

Agent Loop 整合

在工具执行的 switch 中增加任务相关分支:

var result = toolName switch
{
    "bash" => RunBash(input),
    "read_file" => File.ReadAllText(input["path"]),
    "write_file" => WriteFile(input),
    "edit_file" => EditFile(input),
    "task_create" => taskManager.Create(
        input["title"], input["description"],
        input.TryGetProperty("blocked_by", out var bb)
            ? bb.EnumerateArray().Select(x => x.GetString()!).ToList()
            : null),
    "task_update" => taskManager.Update(...),
    "task_list" => taskManager.ListAll(),
    "task_get" => taskManager.Get(input["task_id"]),
    _ => $"Unknown tool: {toolName}"
};

相对 v5 的变更

组件 之前 (v5) 之后 (v6)
Tools 5 (基础 + compact) 8 (+ 4 task 工具)
上下文管理 三层压缩 三层压缩 (继承)
持久化状态 无 (仅 transcript) .tasks/ JSON 文件
依赖管理 双向 blockedBy/blocks
状态恢复 无法恢复 压缩后仍可读取

设计原理

文件系统是最简单的持久化方案:无需数据库,无需序列化框架,JSON + 文件目录就是一个功能完整的任务看板。

关键设计选择:

  • 每个任务一个文件:避免并发写入冲突,方便单任务读写
  • 双向依赖链接blockedBy 记录上游,blocks 记录下游,完成时反向清理
  • 状态转换触发器done 状态自动级联 ClearDependency

任务系统的价值在于让状态外部化——它不再关心上下文窗口发生了什么。

运行

dotnet run v6_task_system_agent.cs

可以尝试的提示:

  1. Create a plan with 5 tasks for building a REST API, with proper dependencies
  2. Show me all tasks(观察 .tasks/ 目录中的 JSON 文件)
  3. Mark task 001 as done(观察依赖自动清理)