Spaces:
Running
Running
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];
|