File size: 3,772 Bytes
12673bf
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
bc7e9cd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
import { DynamicStructuredTool } from "@langchain/core/tools";
import { z } from "zod";

interface Task {
  id: number;
  description: string;
  status: "pending" | "in_progress" | "completed";
  createdAt: Date;
  completedAt?: Date;
}

class TaskTracker {
  private tasks: Task[] = [];
  private nextId = 1;

  addTask(description: string): Task {
    const task: Task = {
      id: this.nextId++,
      description,
      status: "pending",
      createdAt: new Date(),
    };
    this.tasks.push(task);
    return task;
  }

  updateTaskStatus(id: number, status: Task["status"]): Task | null {
    const task = this.tasks.find((t) => t.id === id);
    if (task) {
      task.status = status;
      if (status === "completed") {
        task.completedAt = new Date();
      }
      return task;
    }
    return null;
  }

  getTasks(): Task[] {
    return [...this.tasks];
  }

  getActiveTasks(): Task[] {
    return this.tasks.filter((t) => t.status !== "completed");
  }

  clear(): void {
    this.tasks = [];
    this.nextId = 1;
  }

  formatTaskList(): string {
    if (this.tasks.length === 0) {
      return "No tasks in the list.";
    }

    const statusEmoji = {
      pending: "⏳",
      in_progress: "πŸ”„",
      completed: "βœ…",
    };

    return this.tasks
      .map(
        (t) =>
          `${statusEmoji[t.status]} [${t.id}] ${t.description} (${t.status})`,
      )
      .join("\n");
  }
}

const taskTracker = new TaskTracker();

export const planTasksTool = new DynamicStructuredTool({
  name: "plan_tasks",
  description:
    "Plan and break down a complex task into smaller steps. Use this BEFORE starting any multi-step work to organize your approach.",
  schema: z.object({
    tasks: z
      .array(z.string())
      .min(1)
      .describe(
        "List of task descriptions in order of execution. Keep each task focused and achievable with a single tool call.",
      ),
  }),
  func: async (input: { tasks: string[] }) => {
    taskTracker.clear();
    const createdTasks = input.tasks.map((desc) => taskTracker.addTask(desc));

    return `Task plan created with ${createdTasks.length} tasks:\n${taskTracker.formatTaskList()}\n\nStart with task 1 and mark it as in_progress when you begin.`;
  },
});

export const updateTaskTool = new DynamicStructuredTool({
  name: "update_task",
  description:
    "Update the status of a task. Mark as 'in_progress' when starting, 'completed' when done.",
  schema: z.object({
    taskId: z.number().min(1).describe("The task ID to update"),
    status: z
      .enum(["pending", "in_progress", "completed"])
      .describe("The new status for the task"),
  }),
  func: async (input: { taskId: number; status: Task["status"] }) => {
    const task = taskTracker.updateTaskStatus(input.taskId, input.status);

    if (!task) {
      return `Error: Task ${input.taskId} not found.`;
    }

    const activeTasks = taskTracker.getActiveTasks();
    const nextTask = activeTasks.find((t) => t.status === "pending");

    let response = `Task ${task.id} marked as ${task.status}: "${task.description}"`;

    if (input.status === "completed" && nextTask) {
      response += `\n\nNext task: [${nextTask.id}] ${nextTask.description}`;
    } else if (input.status === "completed" && activeTasks.length === 0) {
      response += "\n\nAll tasks completed! πŸŽ‰";
    }

    response += `\n\nCurrent task list:\n${taskTracker.formatTaskList()}`;
    return response;
  },
});

export const viewTasksTool = new DynamicStructuredTool({
  name: "view_tasks",
  description: "View the current task list and their statuses.",
  schema: z.object({}),
  func: async () => {
    return taskTracker.formatTaskList();
  },
});

export const taskTrackerTools = [planTasksTool, updateTaskTool, viewTasksTool];