Skip to main content

ย้อนกลับการเปลี่ยนแปลงไฟล์ด้วย Checkpointing

ติดตามการเปลี่ยนแปลงไฟล์ระหว่าง agent sessions และกู้คืนไฟล์ไปยังสถานะก่อนหน้าใดก็ได้

File checkpointing ติดตามการแก้ไขไฟล์ที่ทำผ่าน tools Write, Edit, และ NotebookEdit ระหว่าง agent session ช่วยให้คุณย้อนกลับไฟล์ไปยังสถานะก่อนหน้าใดก็ได้ ต้องการทดลองใช้งาน? ข้ามไปที่ interactive example

ด้วย checkpointing คุณสามารถ:

  • ยกเลิกการเปลี่ยนแปลงที่ไม่ต้องการ โดย restore ไฟล์ไปยังสถานะที่ดีที่รู้จัก
  • สำรวจทางเลือก โดย restore ไปยัง checkpoint และลองวิธีการอื่น
  • กู้คืนจากข้อผิดพลาด เมื่อ agent ทำการแก้ไขที่ไม่ถูกต้อง
warning

เฉพาะการเปลี่ยนแปลงที่ทำผ่าน tools Write, Edit, และ NotebookEdit เท่านั้นที่ถูกติดตาม การเปลี่ยนแปลงที่ทำผ่าน Bash commands (เช่น echo > file.txt หรือ sed -i) ไม่ถูก capture โดยระบบ checkpoint

วิธีการทำงานของ Checkpointing

เมื่อคุณเปิดใช้งาน file checkpointing SDK จะสร้าง backup ของไฟล์ก่อนแก้ไขผ่าน tools Write, Edit, หรือ NotebookEdit User messages ใน response stream มี checkpoint UUID ที่คุณสามารถใช้เป็นจุด restore

Checkpoint ทำงานกับ built-in tools เหล่านี้ที่ agent ใช้แก้ไขไฟล์:

Toolคำอธิบาย
Writeสร้างไฟล์ใหม่หรือ overwrite ไฟล์ที่มีอยู่ด้วยเนื้อหาใหม่
Editทำการแก้ไขเฉพาะจุดในส่วนต่างๆ ของไฟล์ที่มีอยู่
NotebookEditแก้ไข cells ใน Jupyter notebooks (ไฟล์ .ipynb)
note

การย้อนกลับไฟล์จะ restore ไฟล์บน disk ไปยังสถานะก่อนหน้า ไม่ได้ย้อนกลับการสนทนาเอง ประวัติการสนทนาและ context ยังคงอยู่หลังจากเรียก rewindFiles() (TypeScript) หรือ rewind_files() (Python)

ระบบ checkpoint ติดตาม:

  • ไฟล์ที่สร้างระหว่าง session
  • ไฟล์ที่แก้ไขระหว่าง session
  • เนื้อหาดั้งเดิมของไฟล์ที่ถูกแก้ไข

เมื่อคุณย้อนกลับไปยัง checkpoint ไฟล์ที่สร้างจะถูกลบและไฟล์ที่แก้ไขจะ restore ไปยังเนื้อหา ณ จุดนั้น

การ Implement Checkpointing

เพื่อใช้ file checkpointing ให้เปิดใช้งานใน options, capture checkpoint UUIDs จาก response stream แล้วเรียก rewindFiles() (TypeScript) หรือ rewind_files() (Python) เมื่อต้องการ restore

import asyncio
from claude_agent_sdk import (
ClaudeSDKClient,
ClaudeAgentOptions,
UserMessage,
ResultMessage,
)


async def main():
# ขั้นตอนที่ 1: เปิดใช้งาน checkpointing
options = ClaudeAgentOptions(
enable_file_checkpointing=True,
permission_mode="acceptEdits",
extra_args={
"replay-user-messages": None
}, # จำเป็นเพื่อรับ checkpoint UUIDs ใน response stream
)

checkpoint_id = None
session_id = None

# รัน query และ capture checkpoint UUID และ session ID
async with ClaudeSDKClient(options) as client:
await client.query("Refactor the authentication module")

# ขั้นตอนที่ 2: Capture checkpoint UUID จาก user message แรก
async for message in client.receive_response():
if isinstance(message, UserMessage) and message.uuid and not checkpoint_id:
checkpoint_id = message.uuid
if isinstance(message, ResultMessage) and not session_id:
session_id = message.session_id

# ขั้นตอนที่ 3: Rewind โดย resume session ด้วย prompt ว่าง
if checkpoint_id and session_id:
async with ClaudeSDKClient(
ClaudeAgentOptions(enable_file_checkpointing=True, resume=session_id)
) as client:
await client.query("") # Prompt ว่างเพื่อเปิด connection
async for message in client.receive_response():
await client.rewind_files(checkpoint_id)
break
print(f"Rewound to checkpoint: {checkpoint_id}")


asyncio.run(main())
import { query } from "@anthropic-ai/claude-agent-sdk";

async function main() {
// ขั้นตอนที่ 1: เปิดใช้งาน checkpointing
const opts = {
enableFileCheckpointing: true,
permissionMode: "acceptEdits" as const,
extraArgs: { "replay-user-messages": null } // จำเป็นเพื่อรับ checkpoint UUIDs ใน response stream
};

const response = query({
prompt: "Refactor the authentication module",
options: opts
});

let checkpointId: string | undefined;
let sessionId: string | undefined;

// ขั้นตอนที่ 2: Capture checkpoint UUID จาก user message แรก
for await (const message of response) {
if (message.type === "user" && message.uuid && !checkpointId) {
checkpointId = message.uuid;
}
if ("session_id" in message && !sessionId) {
sessionId = message.session_id;
}
}

// ขั้นตอนที่ 3: Rewind โดย resume session ด้วย prompt ว่าง
if (checkpointId && sessionId) {
const rewindQuery = query({
prompt: "", // Prompt ว่างเพื่อเปิด connection
options: { ...opts, resume: sessionId }
});

for await (const msg of rewindQuery) {
await rewindQuery.rewindFiles(checkpointId);
break;
}
console.log(`Rewound to checkpoint: ${checkpointId}`);
}
}

main();

รูปแบบทั่วไป

Checkpoint ก่อนการดำเนินการที่มีความเสี่ยง

รูปแบบนี้เก็บเฉพาะ checkpoint UUID ล่าสุด อัปเดตก่อนแต่ละ agent turn หากมีสิ่งผิดปกติเกิดขึ้นระหว่างการประมวลผล คุณสามารถ rewind ไปยังสถานะล่าสุดที่ปลอดภัยได้ทันที

import asyncio
from claude_agent_sdk import ClaudeSDKClient, ClaudeAgentOptions, UserMessage


async def main():
options = ClaudeAgentOptions(
enable_file_checkpointing=True,
permission_mode="acceptEdits",
extra_args={"replay-user-messages": None},
)

safe_checkpoint = None

async with ClaudeSDKClient(options) as client:
await client.query("Refactor the authentication module")

async for message in client.receive_response():
# อัปเดต checkpoint ก่อนแต่ละ agent turn เริ่มต้น
if isinstance(message, UserMessage) and message.uuid:
safe_checkpoint = message.uuid

# ตัดสินใจว่าจะ revert เมื่อไหร่ตาม logic ของคุณเอง
if your_revert_condition and safe_checkpoint:
await client.rewind_files(safe_checkpoint)
break


asyncio.run(main())

Multiple restore points

หาก Claude ทำการเปลี่ยนแปลงใน multiple turns คุณอาจต้องการย้อนกลับไปยังจุดเฉพาะแทนที่จะกลับไปทั้งหมด

import asyncio
from dataclasses import dataclass
from datetime import datetime
from claude_agent_sdk import (
ClaudeSDKClient,
ClaudeAgentOptions,
UserMessage,
ResultMessage,
)


@dataclass
class Checkpoint:
id: str
description: str
timestamp: datetime


async def main():
options = ClaudeAgentOptions(
enable_file_checkpointing=True,
permission_mode="acceptEdits",
extra_args={"replay-user-messages": None},
)

checkpoints = []
session_id = None

async with ClaudeSDKClient(options) as client:
await client.query("Refactor the authentication module")

async for message in client.receive_response():
if isinstance(message, UserMessage) and message.uuid:
checkpoints.append(
Checkpoint(
id=message.uuid,
description=f"After turn {len(checkpoints) + 1}",
timestamp=datetime.now(),
)
)
if isinstance(message, ResultMessage) and not session_id:
session_id = message.session_id

# ต่อมา: rewind ไปยัง checkpoint ใดก็ได้โดย resume session
if checkpoints and session_id:
target = checkpoints[0] # เลือก checkpoint ใดก็ได้
async with ClaudeSDKClient(
ClaudeAgentOptions(enable_file_checkpointing=True, resume=session_id)
) as client:
await client.query("")
async for message in client.receive_response():
await client.rewind_files(target.id)
break
print(f"Rewound to: {target.description}")


asyncio.run(main())

ข้อจำกัด

ข้อจำกัดคำอธิบาย
เฉพาะ tools Write/Edit/NotebookEditการเปลี่ยนแปลงที่ทำผ่าน Bash commands ไม่ถูกติดตาม
Session เดียวกันCheckpoints ผูกกับ session ที่สร้างพวกมัน
เฉพาะเนื้อหาไฟล์การสร้าง, ย้าย, หรือลบ directories ไม่ถูกยกเลิกโดยการ rewind
ไฟล์ localไฟล์ remote หรือ network ไม่ถูกติดตาม

การแก้ปัญหา

Checkpointing options ไม่ถูกรู้จัก

หาก enableFileCheckpointing หรือ rewindFiles() ไม่พร้อมใช้งาน คุณอาจใช้ SDK เวอร์ชันเก่า

แก้ไข: อัปเดตเป็น SDK เวอร์ชันล่าสุด:

  • Python: pip install --upgrade claude-agent-sdk
  • TypeScript: npm install @anthropic-ai/claude-agent-sdk@latest

User messages ไม่มี UUIDs

หาก message.uuid เป็น undefined หรือหายไป คุณไม่ได้รับ checkpoint UUIDs

สาเหตุ: Option replay-user-messages ไม่ได้ถูกตั้งค่า

แก้ไข: เพิ่ม extra_args={"replay-user-messages": None} (Python) หรือ extraArgs: { 'replay-user-messages': null } (TypeScript) ใน options ของคุณ

ข้อผิดพลาด "No file checkpoint found for message"

ข้อผิดพลาดนี้เกิดขึ้นเมื่อข้อมูล checkpoint ไม่มีอยู่สำหรับ user message UUID ที่ระบุ

แก้ไข: ตรวจสอบว่า enable_file_checkpointing=True (Python) หรือ enableFileCheckpointing: true (TypeScript) ถูกตั้งค่าใน session ดั้งเดิม

ขั้นตอนถัดไป

  • Sessions: เรียนรู้วิธี resume sessions ซึ่งจำเป็นสำหรับการ rewind หลังจาก stream เสร็จสิ้น
  • Permissions: configure tools ที่ Claude สามารถใช้ได้และวิธีอนุมัติการแก้ไขไฟล์
  • TypeScript SDK reference: API reference ครบถ้วนรวมถึง method rewindFiles()
  • Python SDK reference: API reference ครบถ้วนรวมถึง method rewind_files()