Documentation Index
Fetch the complete documentation index at: https://docs.qoder.com/llms.txt
Use this file to discover all available pages before exploring further.
enableFileCheckpointing 是 query() 的 options 参数之一,用来让 CLI 在工具修改文件前后做快照;启用后,调用方可以用 q.rewindFiles(userMessageId, ...) 把文件回滚到某条用户消息开始处理时的状态。这两件事必须配合使用:没启用 checkpoint,rewind 不可用。
启用文件 checkpoint
import { query } from '@qoder-ai/qoder-agent-sdk';
const q = query({
prompt: 'Refactor src/foo.ts into a cleaner implementation',
options: {
cwd: '/path/to/project',
enableFileCheckpointing: true,
allowedTools: ['Read', 'Edit', 'Write'],
permissionMode: 'acceptEdits',
},
});
进阶:通过 settings 同时调整其他 CLI 配置时
query() 的 options 还支持一个 settings 字段,可以传一个 Settings 对象,也可以传一个 settings 文件的绝对路径字符串。它和 enableFileCheckpointing 的关系如下:
- 传
settings 对象时,SDK 会把 general.fileCheckpointing.enabled = true 自动合并进去,无需手动写。
- 传
settings 文件路径字符串时,SDK 不会改写文件内容,需要你自己在该文件中配置:
{
"general": {
"fileCheckpointing": {
"enabled": true
}
}
}
只设置 enableFileCheckpointing: true、不传 settings,对于纯粹只用 rewind 的场景已经够用。
使用显式 user message id
Rewind 以用户消息 ID 为锚点。需要精确回滚时,建议用结构化输入并自己生成 uuid,这样 UI 才能稳定反查「回到那条消息之前」。
import { randomUUID } from 'node:crypto';
import { query } from '@qoder-ai/qoder-agent-sdk';
const userMessageId = randomUUID();
async function* input() {
yield {
type: 'user' as const,
uuid: userMessageId,
parent_tool_use_id: null,
message: {
role: 'user' as const,
content: [
{
type: 'text' as const,
text: 'Rewrite notes.txt as a two-line summary.',
},
],
},
};
// If your application needs to call rewind later within the same session,
// keep yielding subsequent user inputs here instead of closing the stream.
}
const q = query({
prompt: input(),
options: {
cwd: '/path/to/project',
enableFileCheckpointing: true,
allowedTools: ['Read', 'Write'],
permissionMode: 'acceptEdits',
},
});
Dry run 预览
先 dry run 可以看到是否能回滚、会影响哪些文件,以及整体的插入/删除统计。Dry run 不会修改文件。
返回的 RewindFilesResult 包含以下字段:
| 字段 | 类型 | 说明 |
|---|
canRewind | boolean | 是否可以执行回滚。dry run 失败时不抛错,由该字段标记 |
error | string? | canRewind=false 时的诊断文案,可直接展示给用户 |
filesChanged | string[]? | 受影响文件的绝对路径列表,可用于在 UI 中列出每一个将要被回滚的文件 |
insertions | number? | 回滚动作总共会“撤销新增”的行数(汇总值) |
deletions | number? | 回滚动作总共会“撤销删除”的行数(汇总值) |
当前 SDK 只在 RewindFilesResult 中返回受影响的文件列表与汇总的行级统计,不会返回每个文件的具体 diff。如果你需要展示每文件的差异,可以在 dry run 后基于 filesChanged 自己读取磁盘内容并与 checkpoint 内容比对,或在执行 rewind 后用 git/工作区对比工具呈现。
const preview = await q.rewindFiles(userMessageId, { dryRun: true });
if (!preview.canRewind) {
// Show the diagnostic message in the UI.
console.error(preview.error);
return;
}
// Overall stats across all affected files.
console.log({
files: preview.filesChanged?.length ?? 0,
insertions: preview.insertions ?? 0,
deletions: preview.deletions ?? 0,
});
// Per-file listing — useful for a confirmation dialog.
for (const file of preview.filesChanged ?? []) {
console.log(`will be reverted: ${file}`);
}
执行回滚
const result = await q.rewindFiles(userMessageId);
console.log(result.filesChanged);
失败语义
| 调用形式 | 不可回滚时的表现 |
|---|
rewindFiles(id, { dryRun: true }) | resolve 一个 { canRewind: false, error },便于在 UI 上展示诊断 |
rewindFiles(id)(执行模式) | Promise reject,调用方建议用 try/catch 展示失败原因 |
try {
await q.rewindFiles(userMessageId);
} catch (error) {
console.error(error instanceof Error ? error.message : String(error));
}
Options 速查
| 字段 | 类型 | 说明 |
|---|
enableFileCheckpointing | boolean | 启用文件 checkpoint,供 rewindFiles() 使用 |
settings | string | Settings | 传给 CLI 的 settings;传对象时 SDK 会合并 general.fileCheckpointing.enabled |
返回值参考
type RewindFilesResult = {
canRewind: boolean;
error?: string;
filesChanged?: string[];
insertions?: number;
deletions?: number;
};
最佳实践
- 保存 user message id:需要回滚能力的应用应在发送消息时保存
uuid,不要依赖 UI 文本反查。
- Rewind 前先 dry run:先展示影响范围,再让用户确认执行回滚。
- 回滚后刷新 UI:rewind 只改文件,不改会话历史,UI 需要根据
filesChanged 自行重新加载相关视图。
- 失败时给用户看到
error:canRewind=false 时的 error 文案通常能直接展示给最终用户做诊断。