feat(checkpoint): 添加 Checkpoint 可视化管理功能
Core 层增强:
- 添加 safety.ts: 7点安全检查机制
- 添加 session-tracker.ts: 会话级检查点跟踪
- 添加 lock.ts: 并发控制文件锁
- 添加 lfs.ts: Git LFS 大文件支持
- 添加 path-validator.ts: 路径验证
- 添加 commit-message.ts: 智能提交消息生成
- 增强 manager.ts: 支持三种恢复模式、unrevert 撤销回滚
Server 层:
- 添加 checkpoints.ts: 16个 REST API 端点
- GET/POST /checkpoints: 列表/创建检查点
- GET/DELETE /checkpoints/🆔 获取/删除检查点
- GET /checkpoints/:id/diff: 获取差异
- POST /checkpoints/:id/restore: 恢复到检查点
- POST /checkpoints/unrevert: 撤销回滚
- GET /checkpoints/:id/safety-check: 安全检查
UI 层:
- 添加 CheckpointPanel.tsx: 检查点列表面板
- 添加 CheckpointDiffViewer.tsx: 差异查看器
- 添加 RestoreDialog.tsx: 恢复确认对话框
- 添加 16 个 API 客户端函数
- 添加完整的 TypeScript 类型定义
Web/Desktop 集成:
- 添加 History 按钮到工具栏
- 集成 CheckpointPanel 组件
This commit is contained in:
@@ -28,6 +28,16 @@ import type {
|
||||
AgentDetail,
|
||||
AgentInput,
|
||||
AgentDefaults,
|
||||
CheckpointListItem,
|
||||
CheckpointDetail,
|
||||
CheckpointStats,
|
||||
DiffInfo,
|
||||
FileDiffDetail,
|
||||
RestoreOptions,
|
||||
RestoreResult,
|
||||
SafetyCheckResult,
|
||||
UnrevertStatus,
|
||||
UnrevertResult,
|
||||
} from './types.js';
|
||||
|
||||
// Re-export types
|
||||
@@ -71,6 +81,21 @@ export type {
|
||||
AgentDetail,
|
||||
AgentInput,
|
||||
AgentDefaults,
|
||||
// Checkpoint types
|
||||
CheckpointTrigger,
|
||||
FileChangeType,
|
||||
CheckpointListItem,
|
||||
CheckpointDetail,
|
||||
FileChange,
|
||||
DiffInfo,
|
||||
FileDiffDetail,
|
||||
RestoreMode,
|
||||
RestoreOptions,
|
||||
RestoreResult,
|
||||
SafetyCheckResult,
|
||||
CheckpointStats,
|
||||
UnrevertStatus,
|
||||
UnrevertResult,
|
||||
} from './types.js';
|
||||
|
||||
// API Configuration
|
||||
@@ -588,3 +613,194 @@ export async function updateAgentDefaults(defaults: AgentDefaults): Promise<{
|
||||
}> {
|
||||
return request('PUT', '/agents/defaults', defaults);
|
||||
}
|
||||
|
||||
// ============ Checkpoints API ============
|
||||
|
||||
/**
|
||||
* 获取所有检查点列表
|
||||
*/
|
||||
export async function listCheckpoints(): Promise<{
|
||||
success: boolean;
|
||||
data: CheckpointListItem[];
|
||||
error?: string;
|
||||
}> {
|
||||
return request('GET', '/checkpoints');
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取检查点统计信息
|
||||
*/
|
||||
export async function getCheckpointStats(): Promise<{
|
||||
success: boolean;
|
||||
data: CheckpointStats;
|
||||
error?: string;
|
||||
}> {
|
||||
return request('GET', '/checkpoints/stats');
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取最新检查点
|
||||
*/
|
||||
export async function getLatestCheckpoint(): Promise<{
|
||||
success: boolean;
|
||||
data: CheckpointDetail | null;
|
||||
error?: string;
|
||||
}> {
|
||||
return request('GET', '/checkpoints/latest');
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取单个检查点详情
|
||||
*/
|
||||
export async function getCheckpoint(id: string): Promise<{
|
||||
success: boolean;
|
||||
data?: CheckpointDetail;
|
||||
error?: string;
|
||||
}> {
|
||||
return request('GET', `/checkpoints/${encodeURIComponent(id)}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建手动检查点
|
||||
*/
|
||||
export async function createCheckpoint(options?: {
|
||||
name?: string;
|
||||
description?: string;
|
||||
}): Promise<{
|
||||
success: boolean;
|
||||
data?: CheckpointDetail;
|
||||
error?: string;
|
||||
}> {
|
||||
return request('POST', '/checkpoints', options || {});
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除检查点
|
||||
*/
|
||||
export async function deleteCheckpoint(id: string): Promise<{
|
||||
success: boolean;
|
||||
data?: { deleted: boolean };
|
||||
error?: string;
|
||||
}> {
|
||||
return request('DELETE', `/checkpoints/${encodeURIComponent(id)}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取检查点与当前工作区的差异
|
||||
*/
|
||||
export async function getCheckpointDiff(id: string): Promise<{
|
||||
success: boolean;
|
||||
data?: DiffInfo;
|
||||
error?: string;
|
||||
}> {
|
||||
return request('GET', `/checkpoints/${encodeURIComponent(id)}/diff`);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取单个文件的详细差异
|
||||
*/
|
||||
export async function getFileDiff(checkpointId: string, filePath: string): Promise<{
|
||||
success: boolean;
|
||||
data?: FileDiffDetail;
|
||||
error?: string;
|
||||
}> {
|
||||
const params = new URLSearchParams({ path: filePath });
|
||||
return request('GET', `/checkpoints/${encodeURIComponent(checkpointId)}/file-diff?${params}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* 回滚到检查点
|
||||
*/
|
||||
export async function restoreCheckpoint(
|
||||
id: string,
|
||||
options?: RestoreOptions
|
||||
): Promise<{
|
||||
success: boolean;
|
||||
data?: RestoreResult;
|
||||
error?: string;
|
||||
}> {
|
||||
return request('POST', `/checkpoints/${encodeURIComponent(id)}/restore`, options || {});
|
||||
}
|
||||
|
||||
/**
|
||||
* 预览回滚(dry run)
|
||||
*/
|
||||
export async function previewRestore(
|
||||
id: string,
|
||||
options?: { mode?: RestoreOptions['mode']; files?: string[] }
|
||||
): Promise<{
|
||||
success: boolean;
|
||||
data?: RestoreResult;
|
||||
error?: string;
|
||||
}> {
|
||||
const params = new URLSearchParams();
|
||||
if (options?.mode) params.set('mode', options.mode);
|
||||
if (options?.files) params.set('files', options.files.join(','));
|
||||
return request('GET', `/checkpoints/${encodeURIComponent(id)}/restore/preview?${params}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* 撤销最近一次回滚
|
||||
*/
|
||||
export async function unrevert(): Promise<{
|
||||
success: boolean;
|
||||
data?: UnrevertResult;
|
||||
error?: string;
|
||||
}> {
|
||||
return request('POST', '/checkpoints/unrevert');
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查是否可撤销回滚
|
||||
*/
|
||||
export async function getUnrevertStatus(): Promise<{
|
||||
success: boolean;
|
||||
data?: UnrevertStatus;
|
||||
error?: string;
|
||||
}> {
|
||||
return request('GET', '/checkpoints/unrevert/status');
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行安全检查
|
||||
*/
|
||||
export async function checkSafety(id: string): Promise<{
|
||||
success: boolean;
|
||||
data?: SafetyCheckResult;
|
||||
error?: string;
|
||||
}> {
|
||||
return request('GET', `/checkpoints/${encodeURIComponent(id)}/safety-check`);
|
||||
}
|
||||
|
||||
/**
|
||||
* 清理过期检查点
|
||||
*/
|
||||
export async function cleanupCheckpoints(): Promise<{
|
||||
success: boolean;
|
||||
data?: { deleted: number };
|
||||
error?: string;
|
||||
}> {
|
||||
return request('POST', '/checkpoints/cleanup');
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取会话的所有检查点
|
||||
*/
|
||||
export async function getSessionCheckpoints(sessionId: string): Promise<{
|
||||
success: boolean;
|
||||
data: CheckpointListItem[];
|
||||
error?: string;
|
||||
}> {
|
||||
return request('GET', `/checkpoints/sessions/${encodeURIComponent(sessionId)}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取消息关联的检查点
|
||||
*/
|
||||
export async function getMessageCheckpoints(messageId: string): Promise<{
|
||||
success: boolean;
|
||||
data: CheckpointListItem[];
|
||||
error?: string;
|
||||
}> {
|
||||
return request('GET', `/checkpoints/messages/${encodeURIComponent(messageId)}`);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user