فهرستهای Todo
ردیابی todo راهی ساختاریافته برای مدیریت کارها و نمایش پیشرفت به کاربران فراهم میکند. Claude Agent SDK یک قابلیت todoیِ داخلی دارد که به سازماندهیِ ورکفلوهای پیچیده و باخبر نگهداشتنِ کاربران از روند پیشرفتِ کار کمک میکند.
چرخهی عمر todo
Section titled “چرخهی عمر todo”todoها از یک چرخهی عمرِ قابلپیشبینی پیروی میکنند:
- هنگام شناسایی کارها بهعنوان
pendingایجاد میشوند - هنگام شروع کار به
in_progressفعال میشوند - وقتی کار با موفقیت تمام شد تکمیل میشوند
- وقتی همهی کارهای یک گروه تکمیل شدند حذف میشوند
چه زمانی todoها به کار میروند
Section titled “چه زمانی todoها به کار میروند”این SDK بهطور خودکار برای این موارد todo میسازد:
- کارهای پیچیدهی چندمرحلهای که به ۳ اقدام مجزا یا بیشتر نیاز دارند
- فهرستهای کاریِ ارائهشده توسط کاربر وقتی چند مورد ذکر شده باشد
- عملیاتِ غیرپیشپاافتاده که از ردیابیِ پیشرفت بهره میبرند
- درخواستهای صریح وقتی کاربران سازماندهیِ todo را میخواهند
مثالها
Section titled “مثالها”پایش تغییرات todo
Section titled “پایش تغییرات todo”import { query } from "@anthropic-ai/claude-agent-sdk";
for await (const message of query({ prompt: "Optimize my React app performance and track progress with todos", // Re-enable TodoWrite, which this example monitors. Without it, the SDK uses // Task tools instead and these tool_use blocks never appear. options: { maxTurns: 15, env: { ...process.env, CLAUDE_CODE_ENABLE_TASKS: "0" } }})) { // Todo updates are reflected in the message stream if (message.type === "assistant") { for (const block of message.message.content) { if (block.type === "tool_use" && block.name === "TodoWrite") { const todos = block.input.todos;
console.log("Todo Status Update:"); todos.forEach((todo, index) => { const status = todo.status === "completed" ? "✅" : todo.status === "in_progress" ? "🔧" : "❌"; console.log(`${index + 1}. ${status} ${todo.content}`); }); } } }}from claude_agent_sdk import query, ClaudeAgentOptions, AssistantMessage, ToolUseBlock
async for message in query( prompt="Optimize my React app performance and track progress with todos", # Re-enable TodoWrite, which this example monitors. Without it, the SDK uses # Task tools instead and these tool_use blocks never appear. options=ClaudeAgentOptions(max_turns=15, env={"CLAUDE_CODE_ENABLE_TASKS": "0"}),): # Todo updates are reflected in the message stream if isinstance(message, AssistantMessage): for block in message.content: if isinstance(block, ToolUseBlock) and block.name == "TodoWrite": todos = block.input["todos"]
print("Todo Status Update:") for i, todo in enumerate(todos): status = ( "✅" if todo["status"] == "completed" else "🔧" if todo["status"] == "in_progress" else "❌" ) print(f"{i + 1}. {status} {todo['content']}")نمایش پیشرفت در لحظه
Section titled “نمایش پیشرفت در لحظه”import { query } from "@anthropic-ai/claude-agent-sdk";
class TodoTracker { private todos: any[] = [];
displayProgress() { if (this.todos.length === 0) return;
const completed = this.todos.filter((t) => t.status === "completed").length; const inProgress = this.todos.filter((t) => t.status === "in_progress").length; const total = this.todos.length;
console.log(`\nProgress: ${completed}/${total} completed`); console.log(`Currently working on: ${inProgress} task(s)\n`);
this.todos.forEach((todo, index) => { const icon = todo.status === "completed" ? "✅" : todo.status === "in_progress" ? "🔧" : "❌"; const text = todo.status === "in_progress" ? todo.activeForm : todo.content; console.log(`${index + 1}. ${icon} ${text}`); }); }
async trackQuery(prompt: string) { for await (const message of query({ prompt, // Re-enable TodoWrite, which this tracker watches for. options: { maxTurns: 20, env: { ...process.env, CLAUDE_CODE_ENABLE_TASKS: "0" } } })) { if (message.type === "assistant") { for (const block of message.message.content) { if (block.type === "tool_use" && block.name === "TodoWrite") { this.todos = block.input.todos; this.displayProgress(); } } } } }}
// Usageconst tracker = new TodoTracker();await tracker.trackQuery("Build a complete authentication system with todos");from claude_agent_sdk import query, ClaudeAgentOptions, AssistantMessage, ToolUseBlockfrom typing import List, Dict
class TodoTracker: def __init__(self): self.todos: List[Dict] = []
def display_progress(self): if not self.todos: return
completed = len([t for t in self.todos if t["status"] == "completed"]) in_progress = len([t for t in self.todos if t["status"] == "in_progress"]) total = len(self.todos)
print(f"\nProgress: {completed}/{total} completed") print(f"Currently working on: {in_progress} task(s)\n")
for i, todo in enumerate(self.todos): icon = ( "✅" if todo["status"] == "completed" else "🔧" if todo["status"] == "in_progress" else "❌" ) text = ( todo["activeForm"] if todo["status"] == "in_progress" else todo["content"] ) print(f"{i + 1}. {icon} {text}")
async def track_query(self, prompt: str): async for message in query( prompt=prompt, # Re-enable TodoWrite, which this tracker watches for. options=ClaudeAgentOptions(max_turns=20, env={"CLAUDE_CODE_ENABLE_TASKS": "0"}), ): if isinstance(message, AssistantMessage): for block in message.content: if isinstance(block, ToolUseBlock) and block.name == "TodoWrite": self.todos = block.input["todos"] self.display_progress()
# Usagetracker = TodoTracker()await tracker.track_query("Build a complete authentication system with todos")مهاجرت به ابزارهای Task
Section titled “مهاجرت به ابزارهای Task”ابزارهای Task فراخوانیِ واحدِ TodoWrite را به TaskCreate برای هر مورد جدید و TaskUpdate برای هر تغییرِ وضعیت تقسیم میکنند، و TaskList و TaskGet هم در دسترسِ مدل هستند تا فهرستِ فعلی را بازخوانی کند. کدِ پایشِ تو همچنان بلاکهای tool_use را در استریمِ دستیار بررسی میکند، اما بهجای جایگزینکردنِ کل فهرست در هر فراخوانی، یک نگاشت (map) را که کلیدش شناسهی تسک است نگه میدارد. {/* min-version: 2.1.142 */}ابزارهای Task از TypeScript Agent SDK نسخهی 0.3.142 و Claude Code v2.1.142 به بعد پیشفرض هستند، پس هیچ تغییری در options.env لازم نیست.
با TodoWrite | با ابزارهای Task |
|---|---|
یک فراخوانیِ ابزار کلِ آرایهی todos را بازنویسی میکند | TaskCreate یک مورد اضافه میکند، TaskUpdate یک مورد را بر اساس taskId وصله میکند |
تطبیق با block.name === "TodoWrite" | تطبیق با block.name === "TaskCreate" یا "TaskUpdate" |
شکل مورد: { content, status, activeForm } | ورودیِ TaskCreate: { subject, description, activeForm?, metadata? }. ورودیِ TaskUpdate: { taskId, status?, subject?, description?, activeForm?, addBlocks?, addBlockedBy?, owner?, metadata? }. مقدار status یکی از "pending"، "in_progress" یا "completed" است؛ برای حذف، status: "deleted" بگذار |
block.input.todos را مستقیماً رندر کن | موردها را در طول فراخوانیها انباشته کن، یا یک snapshot از نتیجهی ابزار TaskList بخوان |
شناسهی تسکِ تخصیصیافته در ورودیِ TaskCreate نیست. این شناسه در tool_resultِ متناظر بهصورت { task: { id, subject } } برمیگردد، پس آن را از بلاکِ نتیجه بردار تا کلیدِ نگاشتت شود. مثالِ زیر کمترین تغییرِ لازم در حلقهی پایش تغییرات todo را نشان میدهد. برای رندرِ یک فهرستِ کامل، در استریم منتظرِ نتیجهی ابزار TaskList بمان، یا نتایجِ TaskCreate و ورودیهای TaskUpdate را در یک نگاشت انباشته کن:
import { query } from "@anthropic-ai/claude-agent-sdk";
for await (const message of query({ prompt: "Optimize my React app performance",})) { if (message.type !== "assistant") continue; for (const block of message.message.content) { if (block.type !== "tool_use") continue; if (block.name === "TaskCreate") { const input = block.input as { subject: string }; console.log(`+ ${input.subject}`); } else if (block.name === "TaskUpdate") { const input = block.input as { taskId: string; status?: string }; if (input.status) console.log(` ${input.taskId} -> ${input.status}`); } }}from claude_agent_sdk import query, AssistantMessage, ToolUseBlock
async for message in query( prompt="Optimize my React app performance",): if not isinstance(message, AssistantMessage): continue for block in message.content: if not isinstance(block, ToolUseBlock): continue if block.name == "TaskCreate": print(f"+ {block.input['subject']}") elif block.name == "TaskUpdate" and block.input.get("status"): print(f" {block.input['taskId']} -> {block.input['status']}")