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()