@defai.digital/ax-cli 2.7.0 → 2.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.ax-cli/checkpoints/2025-11-20/checkpoint-2dd84869-e62d-46c8-9885-7e45f37f36e2.json +69 -0
- package/.ax-cli/checkpoints/2025-11-20/checkpoint-484dc350-353f-4808-9ed1-ebb3cefdab37.json +24 -0
- package/.ax-cli/checkpoints/2025-11-20/checkpoint-74a18b87-6172-4215-962b-44bb9f46a662.json +69 -0
- package/.ax-cli/checkpoints/2025-11-20/checkpoint-870a5fb9-6e82-4ff2-8ec8-af4c251cc514.json +44 -0
- package/.ax-cli/checkpoints/2025-11-20/checkpoint-93946601-0e83-456c-ba47-def9713124dd.json +24 -0
- package/.ax-cli/checkpoints/metadata.json +62 -0
- package/README.md +2 -2
- package/dist/agent/context-manager.d.ts +2 -2
- package/dist/agent/context-manager.js +28 -15
- package/dist/agent/context-manager.js.map +1 -1
- package/dist/agent/dependency-resolver.d.ts +83 -0
- package/dist/agent/dependency-resolver.js +302 -0
- package/dist/agent/dependency-resolver.js.map +1 -0
- package/dist/agent/llm-agent.d.ts +63 -0
- package/dist/agent/llm-agent.js +250 -0
- package/dist/agent/llm-agent.js.map +1 -1
- package/dist/agent/specialized/analysis-agent.d.ts +11 -0
- package/dist/agent/specialized/analysis-agent.js +33 -0
- package/dist/agent/specialized/analysis-agent.js.map +1 -0
- package/dist/agent/specialized/debug-agent.d.ts +11 -0
- package/dist/agent/specialized/debug-agent.js +33 -0
- package/dist/agent/specialized/debug-agent.js.map +1 -0
- package/dist/agent/specialized/documentation-agent.d.ts +11 -0
- package/dist/agent/specialized/documentation-agent.js +33 -0
- package/dist/agent/specialized/documentation-agent.js.map +1 -0
- package/dist/agent/specialized/index.d.ts +11 -0
- package/dist/agent/specialized/index.js +12 -0
- package/dist/agent/specialized/index.js.map +1 -0
- package/dist/agent/specialized/performance-agent.d.ts +11 -0
- package/dist/agent/specialized/performance-agent.js +33 -0
- package/dist/agent/specialized/performance-agent.js.map +1 -0
- package/dist/agent/specialized/refactoring-agent.d.ts +11 -0
- package/dist/agent/specialized/refactoring-agent.js +33 -0
- package/dist/agent/specialized/refactoring-agent.js.map +1 -0
- package/dist/agent/specialized/testing-agent.d.ts +11 -0
- package/dist/agent/specialized/testing-agent.js +33 -0
- package/dist/agent/specialized/testing-agent.js.map +1 -0
- package/dist/agent/subagent-orchestrator.d.ts +124 -0
- package/dist/agent/subagent-orchestrator.js +345 -0
- package/dist/agent/subagent-orchestrator.js.map +1 -0
- package/dist/agent/subagent-types.d.ts +262 -0
- package/dist/agent/subagent-types.js +152 -0
- package/dist/agent/subagent-types.js.map +1 -0
- package/dist/agent/subagent.d.ts +88 -0
- package/dist/agent/subagent.js +402 -0
- package/dist/agent/subagent.js.map +1 -0
- package/dist/checkpoint/index.d.ts +9 -0
- package/dist/checkpoint/index.js +11 -0
- package/dist/checkpoint/index.js.map +1 -0
- package/dist/checkpoint/manager.d.ts +99 -0
- package/dist/checkpoint/manager.js +281 -0
- package/dist/checkpoint/manager.js.map +1 -0
- package/dist/checkpoint/storage.d.ts +31 -0
- package/dist/checkpoint/storage.js +265 -0
- package/dist/checkpoint/storage.js.map +1 -0
- package/dist/checkpoint/types.d.ts +111 -0
- package/dist/checkpoint/types.js +17 -0
- package/dist/checkpoint/types.js.map +1 -0
- package/dist/commands/rewind.d.ts +19 -0
- package/dist/commands/rewind.js +221 -0
- package/dist/commands/rewind.js.map +1 -0
- package/dist/hooks/use-input-handler.js +24 -0
- package/dist/hooks/use-input-handler.js.map +1 -1
- package/dist/llm/client.js +2 -1
- package/dist/llm/client.js.map +1 -1
- package/dist/mcp/client.d.ts +1 -0
- package/dist/mcp/client.js +27 -12
- package/dist/mcp/client.js.map +1 -1
- package/dist/mcp/transports.d.ts +0 -1
- package/dist/mcp/transports.js +10 -7
- package/dist/mcp/transports.js.map +1 -1
- package/dist/schemas/api-schemas.js +4 -0
- package/dist/schemas/api-schemas.js.map +1 -1
- package/dist/tools/bash.js +26 -1
- package/dist/tools/bash.js.map +1 -1
- package/dist/tools/search.js +21 -9
- package/dist/tools/search.js.map +1 -1
- package/dist/tools/text-editor.d.ts +16 -0
- package/dist/tools/text-editor.js +33 -0
- package/dist/tools/text-editor.js.map +1 -1
- package/dist/ui/components/chat-interface.js +3 -2
- package/dist/ui/components/chat-interface.js.map +1 -1
- package/dist/ui/components/subagent-monitor.d.ts +29 -0
- package/dist/ui/components/subagent-monitor.js +150 -0
- package/dist/ui/components/subagent-monitor.js.map +1 -0
- package/dist/utils/history-manager.d.ts +1 -0
- package/dist/utils/history-manager.js +40 -5
- package/dist/utils/history-manager.js.map +1 -1
- package/dist/utils/json-utils.d.ts +7 -0
- package/dist/utils/json-utils.js +70 -2
- package/dist/utils/json-utils.js.map +1 -1
- package/dist/utils/settings-manager.js +12 -10
- package/dist/utils/settings-manager.js.map +1 -1
- package/dist/utils/text-utils.js +3 -3
- package/dist/utils/text-utils.js.map +1 -1
- package/dist/utils/token-counter.d.ts +5 -0
- package/dist/utils/token-counter.js +18 -3
- package/dist/utils/token-counter.js.map +1 -1
- package/package.json +2 -1
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Checkpoint Manager
|
|
3
|
+
*
|
|
4
|
+
* High-level API for checkpoint operations:
|
|
5
|
+
* - Creating checkpoints
|
|
6
|
+
* - Listing checkpoints
|
|
7
|
+
* - Restoring checkpoints
|
|
8
|
+
* - Pruning old checkpoints
|
|
9
|
+
* - Automatic checkpoint scheduling
|
|
10
|
+
*/
|
|
11
|
+
import crypto from 'crypto';
|
|
12
|
+
import * as fs from 'fs/promises';
|
|
13
|
+
import { CheckpointStorage, calculateHash } from './storage.js';
|
|
14
|
+
import { DEFAULT_CHECKPOINT_CONFIG } from './types.js';
|
|
15
|
+
export class CheckpointManager {
|
|
16
|
+
storage;
|
|
17
|
+
config;
|
|
18
|
+
constructor(config, baseDir) {
|
|
19
|
+
this.config = { ...DEFAULT_CHECKPOINT_CONFIG, ...config };
|
|
20
|
+
// Use config.storageDir if provided, otherwise use baseDir parameter
|
|
21
|
+
const storageDir = this.config.storageDir || baseDir;
|
|
22
|
+
this.storage = new CheckpointStorage(storageDir);
|
|
23
|
+
}
|
|
24
|
+
async initialize() {
|
|
25
|
+
await this.storage.initialize();
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Create a new checkpoint
|
|
29
|
+
*/
|
|
30
|
+
async createCheckpoint(options) {
|
|
31
|
+
if (!this.config.enabled) {
|
|
32
|
+
throw new Error('Checkpoint system is disabled');
|
|
33
|
+
}
|
|
34
|
+
const checkpointId = crypto.randomUUID();
|
|
35
|
+
const timestamp = new Date();
|
|
36
|
+
// Create file snapshots
|
|
37
|
+
const fileSnapshots = [];
|
|
38
|
+
for (const file of options.files) {
|
|
39
|
+
const hash = calculateHash(file.content);
|
|
40
|
+
fileSnapshots.push({
|
|
41
|
+
path: file.path,
|
|
42
|
+
content: file.content,
|
|
43
|
+
hash,
|
|
44
|
+
size: Buffer.byteLength(file.content, 'utf-8'),
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
// Limit conversation depth
|
|
48
|
+
const conversationState = options.conversationState.slice(-this.config.conversationDepth);
|
|
49
|
+
// Generate default description if not provided
|
|
50
|
+
const defaultDescription = options.files.length > 0
|
|
51
|
+
? `Before modifying ${options.files.length === 1 ? options.files[0].path : `${options.files.length} files`}`
|
|
52
|
+
: 'Auto-generated checkpoint';
|
|
53
|
+
const checkpoint = {
|
|
54
|
+
id: checkpointId,
|
|
55
|
+
timestamp,
|
|
56
|
+
description: options.description || defaultDescription,
|
|
57
|
+
files: fileSnapshots,
|
|
58
|
+
conversationState,
|
|
59
|
+
metadata: {
|
|
60
|
+
model: options.metadata?.model || 'unknown',
|
|
61
|
+
triggeredBy: options.metadata?.triggeredBy || 'manual',
|
|
62
|
+
...options.metadata,
|
|
63
|
+
},
|
|
64
|
+
};
|
|
65
|
+
await this.storage.save(checkpoint);
|
|
66
|
+
// Run maintenance
|
|
67
|
+
await this.runMaintenance();
|
|
68
|
+
return checkpoint;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Restore a checkpoint
|
|
72
|
+
*/
|
|
73
|
+
async restoreCheckpoint(checkpointId) {
|
|
74
|
+
const checkpoint = await this.storage.load(checkpointId);
|
|
75
|
+
if (!checkpoint) {
|
|
76
|
+
return {
|
|
77
|
+
success: false,
|
|
78
|
+
filesRestored: [],
|
|
79
|
+
filesFailed: [],
|
|
80
|
+
error: `Checkpoint ${checkpointId} not found`,
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
const filesRestored = [];
|
|
84
|
+
const filesFailed = [];
|
|
85
|
+
// Restore files
|
|
86
|
+
for (const snapshot of checkpoint.files) {
|
|
87
|
+
try {
|
|
88
|
+
await fs.writeFile(snapshot.path, snapshot.content, 'utf-8');
|
|
89
|
+
filesRestored.push(snapshot.path);
|
|
90
|
+
}
|
|
91
|
+
catch (error) {
|
|
92
|
+
filesFailed.push(snapshot.path);
|
|
93
|
+
console.error(`Failed to restore ${snapshot.path}: ${error.message}`);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
return {
|
|
97
|
+
success: filesFailed.length === 0,
|
|
98
|
+
filesRestored,
|
|
99
|
+
filesFailed,
|
|
100
|
+
conversationIndex: checkpoint.conversationState.length,
|
|
101
|
+
error: filesFailed.length > 0
|
|
102
|
+
? `Failed to restore ${filesFailed.length} file(s)`
|
|
103
|
+
: undefined,
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Apply a checkpoint (restore files and return conversation state)
|
|
108
|
+
* Alias for restoreCheckpoint for backward compatibility
|
|
109
|
+
*/
|
|
110
|
+
async applyCheckpoint(checkpointId) {
|
|
111
|
+
return await this.restoreCheckpoint(checkpointId);
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* List checkpoints with optional filtering
|
|
115
|
+
*/
|
|
116
|
+
async listCheckpoints(filter) {
|
|
117
|
+
let checkpoints = await this.storage.listInfo();
|
|
118
|
+
// Apply filters
|
|
119
|
+
// Support both beforeDate/until (before this date, i.e., <=)
|
|
120
|
+
const beforeDate = filter?.beforeDate || filter?.until;
|
|
121
|
+
if (beforeDate) {
|
|
122
|
+
checkpoints = checkpoints.filter(c => c.timestamp <= beforeDate);
|
|
123
|
+
}
|
|
124
|
+
// Support both afterDate/since (after this date, i.e., >=)
|
|
125
|
+
const afterDate = filter?.afterDate || filter?.since;
|
|
126
|
+
if (afterDate) {
|
|
127
|
+
checkpoints = checkpoints.filter(c => c.timestamp >= afterDate);
|
|
128
|
+
}
|
|
129
|
+
if (filter?.filesChanged) {
|
|
130
|
+
checkpoints = checkpoints.filter(c => filter.filesChanged.some(searchPath => c.filesChanged.some(filePath => filePath.includes(searchPath))));
|
|
131
|
+
}
|
|
132
|
+
// Apply limit
|
|
133
|
+
if (filter?.limit) {
|
|
134
|
+
checkpoints = checkpoints.slice(0, filter.limit);
|
|
135
|
+
}
|
|
136
|
+
return checkpoints;
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Get checkpoint by ID
|
|
140
|
+
*/
|
|
141
|
+
async getCheckpoint(checkpointId) {
|
|
142
|
+
return await this.storage.load(checkpointId);
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Get checkpoint info
|
|
146
|
+
*/
|
|
147
|
+
async getCheckpointInfo(checkpointId) {
|
|
148
|
+
return await this.storage.getCheckpointInfo(checkpointId);
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Delete a checkpoint
|
|
152
|
+
*/
|
|
153
|
+
async deleteCheckpoint(checkpointId) {
|
|
154
|
+
await this.storage.delete(checkpointId);
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Get checkpoint statistics
|
|
158
|
+
*/
|
|
159
|
+
async getStats() {
|
|
160
|
+
return await this.storage.getStats();
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Prune old checkpoints based on config
|
|
164
|
+
*/
|
|
165
|
+
async pruneOldCheckpoints() {
|
|
166
|
+
const pruneDate = new Date();
|
|
167
|
+
pruneDate.setDate(pruneDate.getDate() - this.config.pruneAfterDays);
|
|
168
|
+
return await this.storage.pruneOlderThan(pruneDate);
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Compress old checkpoints based on config
|
|
172
|
+
*/
|
|
173
|
+
async compressOldCheckpoints() {
|
|
174
|
+
const compressDate = new Date();
|
|
175
|
+
compressDate.setDate(compressDate.getDate() - this.config.compressAfterDays);
|
|
176
|
+
const checkpoints = await this.storage.listInfo();
|
|
177
|
+
let compressed = 0;
|
|
178
|
+
for (const checkpoint of checkpoints) {
|
|
179
|
+
if (checkpoint.timestamp < compressDate && !checkpoint.compressed) {
|
|
180
|
+
await this.storage.compress(checkpoint.id);
|
|
181
|
+
compressed++;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
return compressed;
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Run maintenance (pruning, compression, limit enforcement)
|
|
188
|
+
*/
|
|
189
|
+
async runMaintenance() {
|
|
190
|
+
// Compress old checkpoints
|
|
191
|
+
await this.compressOldCheckpoints();
|
|
192
|
+
// Prune very old checkpoints
|
|
193
|
+
await this.pruneOldCheckpoints();
|
|
194
|
+
// Enforce max checkpoints limit
|
|
195
|
+
await this.enforceCheckpointLimit();
|
|
196
|
+
// Enforce storage limit
|
|
197
|
+
await this.enforceStorageLimit();
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* Enforce maximum number of checkpoints
|
|
201
|
+
*/
|
|
202
|
+
async enforceCheckpointLimit() {
|
|
203
|
+
const checkpoints = await this.storage.listInfo();
|
|
204
|
+
if (checkpoints.length > this.config.maxCheckpoints) {
|
|
205
|
+
const toDelete = checkpoints
|
|
206
|
+
.slice(this.config.maxCheckpoints)
|
|
207
|
+
.map(c => c.id);
|
|
208
|
+
for (const id of toDelete) {
|
|
209
|
+
await this.storage.delete(id);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Enforce storage size limit (in MB)
|
|
215
|
+
*/
|
|
216
|
+
async enforceStorageLimit() {
|
|
217
|
+
const stats = await this.storage.getStats();
|
|
218
|
+
const limitBytes = this.config.storageLimit * 1024 * 1024;
|
|
219
|
+
if (stats.totalSize > limitBytes) {
|
|
220
|
+
const checkpoints = await this.storage.listInfo();
|
|
221
|
+
let currentSize = stats.totalSize;
|
|
222
|
+
// Delete oldest checkpoints until under limit
|
|
223
|
+
for (let i = checkpoints.length - 1; i >= 0 && currentSize > limitBytes; i--) {
|
|
224
|
+
const checkpoint = checkpoints[i];
|
|
225
|
+
await this.storage.delete(checkpoint.id);
|
|
226
|
+
currentSize -= checkpoint.size;
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
/**
|
|
231
|
+
* Get conversation state from a checkpoint
|
|
232
|
+
*/
|
|
233
|
+
async getConversationState(checkpointId) {
|
|
234
|
+
const checkpoint = await this.storage.load(checkpointId);
|
|
235
|
+
return checkpoint?.conversationState || null;
|
|
236
|
+
}
|
|
237
|
+
/**
|
|
238
|
+
* Check if checkpoint should be created before an operation
|
|
239
|
+
*/
|
|
240
|
+
shouldCreateCheckpoint(operation) {
|
|
241
|
+
return (this.config.enabled &&
|
|
242
|
+
this.config.createBeforeOperations.includes(operation));
|
|
243
|
+
}
|
|
244
|
+
/**
|
|
245
|
+
* Update configuration
|
|
246
|
+
*/
|
|
247
|
+
updateConfig(config) {
|
|
248
|
+
this.config = { ...this.config, ...config };
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* Get current configuration
|
|
252
|
+
*/
|
|
253
|
+
getConfig() {
|
|
254
|
+
return { ...this.config };
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
// Singleton instance
|
|
258
|
+
let checkpointManagerInstance = null;
|
|
259
|
+
/**
|
|
260
|
+
* Get the singleton checkpoint manager instance
|
|
261
|
+
*/
|
|
262
|
+
export function getCheckpointManager(config, baseDir) {
|
|
263
|
+
if (!checkpointManagerInstance) {
|
|
264
|
+
checkpointManagerInstance = new CheckpointManager(config, baseDir);
|
|
265
|
+
}
|
|
266
|
+
return checkpointManagerInstance;
|
|
267
|
+
}
|
|
268
|
+
/**
|
|
269
|
+
* Initialize a new checkpoint manager instance (creates new singleton)
|
|
270
|
+
*/
|
|
271
|
+
export function initCheckpointManager(config, baseDir) {
|
|
272
|
+
checkpointManagerInstance = new CheckpointManager(config, baseDir);
|
|
273
|
+
return checkpointManagerInstance;
|
|
274
|
+
}
|
|
275
|
+
/**
|
|
276
|
+
* Reset the singleton instance (for testing)
|
|
277
|
+
*/
|
|
278
|
+
export function resetCheckpointManager() {
|
|
279
|
+
checkpointManagerInstance = null;
|
|
280
|
+
}
|
|
281
|
+
//# sourceMappingURL=manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manager.js","sourceRoot":"","sources":["../../src/checkpoint/manager.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Checkpoint Storage Layer
|
|
3
|
+
*/
|
|
4
|
+
import type { Checkpoint, CheckpointInfo, CheckpointStats, FileSnapshot } from './types.js';
|
|
5
|
+
export declare class CheckpointStorage {
|
|
6
|
+
private storageDir;
|
|
7
|
+
private indexPath;
|
|
8
|
+
private index;
|
|
9
|
+
constructor(baseDir?: string);
|
|
10
|
+
initialize(): Promise<void>;
|
|
11
|
+
save(checkpoint: Checkpoint): Promise<void>;
|
|
12
|
+
load(checkpointId: string): Promise<Checkpoint | null>;
|
|
13
|
+
delete(checkpointId: string): Promise<void>;
|
|
14
|
+
compress(checkpointId: string): Promise<void>;
|
|
15
|
+
getStats(): Promise<CheckpointStats>;
|
|
16
|
+
listInfo(): Promise<CheckpointInfo[]>;
|
|
17
|
+
list(): Promise<string[]>;
|
|
18
|
+
getCheckpointInfo(checkpointId: string): Promise<CheckpointInfo | null>;
|
|
19
|
+
getTotalSize(): Promise<number>;
|
|
20
|
+
private loadIndex;
|
|
21
|
+
private saveIndex;
|
|
22
|
+
private addToIndex;
|
|
23
|
+
private removeFromIndex;
|
|
24
|
+
private updateCompressionStatus;
|
|
25
|
+
private updateStats;
|
|
26
|
+
private getDateDir;
|
|
27
|
+
private findCheckpointFile;
|
|
28
|
+
pruneOlderThan(date: Date): Promise<number>;
|
|
29
|
+
}
|
|
30
|
+
export declare function calculateHash(content: string): string;
|
|
31
|
+
export declare function verifyFileSnapshot(snapshot: FileSnapshot): boolean;
|
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Checkpoint Storage Layer
|
|
3
|
+
*/
|
|
4
|
+
import * as fs from 'fs/promises';
|
|
5
|
+
import * as path from 'path';
|
|
6
|
+
import * as crypto from 'crypto';
|
|
7
|
+
import * as zlib from 'zlib';
|
|
8
|
+
import { promisify } from 'util';
|
|
9
|
+
const gzip = promisify(zlib.gzip);
|
|
10
|
+
const gunzip = promisify(zlib.gunzip);
|
|
11
|
+
export class CheckpointStorage {
|
|
12
|
+
storageDir;
|
|
13
|
+
indexPath;
|
|
14
|
+
index = null;
|
|
15
|
+
constructor(baseDir = '.ax-cli') {
|
|
16
|
+
// If baseDir is absolute, use it directly. Otherwise, resolve relative to cwd
|
|
17
|
+
const resolvedBase = path.isAbsolute(baseDir) ? baseDir : path.join(process.cwd(), baseDir);
|
|
18
|
+
this.storageDir = path.join(resolvedBase, 'checkpoints');
|
|
19
|
+
this.indexPath = path.join(this.storageDir, 'metadata.json');
|
|
20
|
+
}
|
|
21
|
+
async initialize() {
|
|
22
|
+
try {
|
|
23
|
+
await fs.mkdir(this.storageDir, { recursive: true });
|
|
24
|
+
const indexExisted = await this.loadIndex();
|
|
25
|
+
// If index was created in-memory (file didn't exist), persist it
|
|
26
|
+
if (!indexExisted) {
|
|
27
|
+
await this.saveIndex();
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
catch (error) {
|
|
31
|
+
throw new Error(`Failed to initialize checkpoint storage: ${error instanceof Error ? error.message : String(error)}`);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
async save(checkpoint) {
|
|
35
|
+
try {
|
|
36
|
+
const dateDir = this.getDateDir(checkpoint.timestamp);
|
|
37
|
+
await fs.mkdir(dateDir, { recursive: true });
|
|
38
|
+
const filepath = path.join(dateDir, `checkpoint-${checkpoint.id}.json`);
|
|
39
|
+
const content = JSON.stringify(checkpoint, null, 2);
|
|
40
|
+
// Atomic write
|
|
41
|
+
const tempPath = `${filepath}.tmp`;
|
|
42
|
+
await fs.writeFile(tempPath, content, 'utf-8');
|
|
43
|
+
await fs.rename(tempPath, filepath);
|
|
44
|
+
// Update index
|
|
45
|
+
await this.addToIndex(checkpoint, filepath);
|
|
46
|
+
}
|
|
47
|
+
catch (error) {
|
|
48
|
+
throw new Error(`Failed to save checkpoint: ${error instanceof Error ? error.message : String(error)}`);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
async load(checkpointId) {
|
|
52
|
+
try {
|
|
53
|
+
const info = await this.getCheckpointInfo(checkpointId);
|
|
54
|
+
if (!info)
|
|
55
|
+
return null;
|
|
56
|
+
const filepath = await this.findCheckpointFile(checkpointId);
|
|
57
|
+
if (!filepath)
|
|
58
|
+
return null;
|
|
59
|
+
let content;
|
|
60
|
+
if (info.compressed) {
|
|
61
|
+
const compressed = await fs.readFile(filepath);
|
|
62
|
+
const decompressed = await gunzip(compressed);
|
|
63
|
+
content = decompressed.toString('utf-8');
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
content = await fs.readFile(filepath, 'utf-8');
|
|
67
|
+
}
|
|
68
|
+
const checkpoint = JSON.parse(content);
|
|
69
|
+
checkpoint.timestamp = new Date(checkpoint.timestamp);
|
|
70
|
+
// Convert conversation state timestamps
|
|
71
|
+
if (checkpoint.conversationState) {
|
|
72
|
+
checkpoint.conversationState = checkpoint.conversationState.map((entry) => ({
|
|
73
|
+
...entry,
|
|
74
|
+
timestamp: new Date(entry.timestamp),
|
|
75
|
+
}));
|
|
76
|
+
}
|
|
77
|
+
return checkpoint;
|
|
78
|
+
}
|
|
79
|
+
catch (error) {
|
|
80
|
+
throw new Error(`Failed to load checkpoint: ${error instanceof Error ? error.message : String(error)}`);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
async delete(checkpointId) {
|
|
84
|
+
const filepath = await this.findCheckpointFile(checkpointId);
|
|
85
|
+
if (filepath) {
|
|
86
|
+
await fs.unlink(filepath);
|
|
87
|
+
}
|
|
88
|
+
await this.removeFromIndex(checkpointId);
|
|
89
|
+
}
|
|
90
|
+
async compress(checkpointId) {
|
|
91
|
+
const filepath = await this.findCheckpointFile(checkpointId);
|
|
92
|
+
if (!filepath || filepath.endsWith('.gz'))
|
|
93
|
+
return;
|
|
94
|
+
const content = await fs.readFile(filepath, 'utf-8');
|
|
95
|
+
const compressed = await gzip(content);
|
|
96
|
+
const compressedPath = `${filepath}.gz`;
|
|
97
|
+
await fs.writeFile(compressedPath, compressed);
|
|
98
|
+
await fs.unlink(filepath);
|
|
99
|
+
await this.updateCompressionStatus(checkpointId, true);
|
|
100
|
+
}
|
|
101
|
+
async getStats() {
|
|
102
|
+
await this.loadIndex();
|
|
103
|
+
return this.index?.stats || {
|
|
104
|
+
totalCount: 0,
|
|
105
|
+
totalSize: 0,
|
|
106
|
+
compressedCount: 0,
|
|
107
|
+
oldestDate: null,
|
|
108
|
+
newestDate: null,
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
async listInfo() {
|
|
112
|
+
await this.loadIndex();
|
|
113
|
+
return this.index?.checkpoints || [];
|
|
114
|
+
}
|
|
115
|
+
async list() {
|
|
116
|
+
await this.loadIndex();
|
|
117
|
+
return this.index?.checkpoints.map(c => c.id) || [];
|
|
118
|
+
}
|
|
119
|
+
async getCheckpointInfo(checkpointId) {
|
|
120
|
+
await this.loadIndex();
|
|
121
|
+
return this.index?.checkpoints.find(c => c.id === checkpointId) || null;
|
|
122
|
+
}
|
|
123
|
+
async getTotalSize() {
|
|
124
|
+
const stats = await this.getStats();
|
|
125
|
+
return stats.totalSize;
|
|
126
|
+
}
|
|
127
|
+
async loadIndex() {
|
|
128
|
+
try {
|
|
129
|
+
const content = await fs.readFile(this.indexPath, 'utf-8');
|
|
130
|
+
const data = JSON.parse(content);
|
|
131
|
+
this.index = {
|
|
132
|
+
checkpoints: data.checkpoints.map((c) => ({
|
|
133
|
+
...c,
|
|
134
|
+
timestamp: new Date(c.timestamp),
|
|
135
|
+
})),
|
|
136
|
+
stats: {
|
|
137
|
+
...data.stats,
|
|
138
|
+
oldestDate: data.stats.oldestDate ? new Date(data.stats.oldestDate) : null,
|
|
139
|
+
newestDate: data.stats.newestDate ? new Date(data.stats.newestDate) : null,
|
|
140
|
+
},
|
|
141
|
+
lastUpdated: new Date(data.lastUpdated),
|
|
142
|
+
};
|
|
143
|
+
return true; // File existed
|
|
144
|
+
}
|
|
145
|
+
catch {
|
|
146
|
+
this.index = {
|
|
147
|
+
checkpoints: [],
|
|
148
|
+
stats: {
|
|
149
|
+
totalCount: 0,
|
|
150
|
+
totalSize: 0,
|
|
151
|
+
compressedCount: 0,
|
|
152
|
+
oldestDate: null,
|
|
153
|
+
newestDate: null,
|
|
154
|
+
},
|
|
155
|
+
lastUpdated: new Date(),
|
|
156
|
+
};
|
|
157
|
+
return false; // File didn't exist, created new index
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
async saveIndex() {
|
|
161
|
+
if (!this.index)
|
|
162
|
+
return;
|
|
163
|
+
const content = JSON.stringify(this.index, null, 2);
|
|
164
|
+
const tempPath = `${this.indexPath}.tmp`;
|
|
165
|
+
await fs.writeFile(tempPath, content, 'utf-8');
|
|
166
|
+
await fs.rename(tempPath, this.indexPath);
|
|
167
|
+
}
|
|
168
|
+
async addToIndex(checkpoint, filepath) {
|
|
169
|
+
await this.loadIndex();
|
|
170
|
+
if (!this.index)
|
|
171
|
+
return;
|
|
172
|
+
const stat = await fs.stat(filepath);
|
|
173
|
+
const info = {
|
|
174
|
+
id: checkpoint.id,
|
|
175
|
+
timestamp: checkpoint.timestamp,
|
|
176
|
+
description: checkpoint.description,
|
|
177
|
+
filesChanged: checkpoint.files.map(f => f.path),
|
|
178
|
+
size: stat.size,
|
|
179
|
+
compressed: false,
|
|
180
|
+
};
|
|
181
|
+
this.index.checkpoints.push(info);
|
|
182
|
+
this.index.checkpoints.sort((a, b) => b.timestamp.getTime() - a.timestamp.getTime());
|
|
183
|
+
this.updateStats();
|
|
184
|
+
await this.saveIndex();
|
|
185
|
+
}
|
|
186
|
+
async removeFromIndex(checkpointId) {
|
|
187
|
+
await this.loadIndex();
|
|
188
|
+
if (!this.index)
|
|
189
|
+
return;
|
|
190
|
+
this.index.checkpoints = this.index.checkpoints.filter(c => c.id !== checkpointId);
|
|
191
|
+
this.updateStats();
|
|
192
|
+
await this.saveIndex();
|
|
193
|
+
}
|
|
194
|
+
async updateCompressionStatus(checkpointId, compressed) {
|
|
195
|
+
await this.loadIndex();
|
|
196
|
+
if (!this.index)
|
|
197
|
+
return;
|
|
198
|
+
const info = this.index.checkpoints.find(c => c.id === checkpointId);
|
|
199
|
+
if (info) {
|
|
200
|
+
info.compressed = compressed;
|
|
201
|
+
this.updateStats();
|
|
202
|
+
await this.saveIndex();
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
updateStats() {
|
|
206
|
+
if (!this.index)
|
|
207
|
+
return;
|
|
208
|
+
const checkpoints = this.index.checkpoints;
|
|
209
|
+
this.index.stats = {
|
|
210
|
+
totalCount: checkpoints.length,
|
|
211
|
+
totalSize: checkpoints.reduce((sum, c) => sum + c.size, 0),
|
|
212
|
+
compressedCount: checkpoints.filter(c => c.compressed).length,
|
|
213
|
+
oldestDate: checkpoints.length > 0 ? checkpoints[checkpoints.length - 1].timestamp : null,
|
|
214
|
+
newestDate: checkpoints.length > 0 ? checkpoints[0].timestamp : null,
|
|
215
|
+
};
|
|
216
|
+
this.index.lastUpdated = new Date();
|
|
217
|
+
}
|
|
218
|
+
getDateDir(date) {
|
|
219
|
+
// Use UTC to match toISOString() format used in tests
|
|
220
|
+
const year = date.getUTCFullYear();
|
|
221
|
+
const month = String(date.getUTCMonth() + 1).padStart(2, '0');
|
|
222
|
+
const day = String(date.getUTCDate()).padStart(2, '0');
|
|
223
|
+
return path.join(this.storageDir, `${year}-${month}-${day}`);
|
|
224
|
+
}
|
|
225
|
+
async findCheckpointFile(checkpointId) {
|
|
226
|
+
const info = await this.getCheckpointInfo(checkpointId);
|
|
227
|
+
if (!info)
|
|
228
|
+
return null;
|
|
229
|
+
const dateDir = this.getDateDir(info.timestamp);
|
|
230
|
+
const baseName = `checkpoint-${checkpointId}.json`;
|
|
231
|
+
const uncompressed = path.join(dateDir, baseName);
|
|
232
|
+
const compressed = path.join(dateDir, `${baseName}.gz`);
|
|
233
|
+
try {
|
|
234
|
+
await fs.access(compressed);
|
|
235
|
+
return compressed;
|
|
236
|
+
}
|
|
237
|
+
catch {
|
|
238
|
+
try {
|
|
239
|
+
await fs.access(uncompressed);
|
|
240
|
+
return uncompressed;
|
|
241
|
+
}
|
|
242
|
+
catch {
|
|
243
|
+
return null;
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
async pruneOlderThan(date) {
|
|
248
|
+
await this.loadIndex();
|
|
249
|
+
if (!this.index)
|
|
250
|
+
return 0;
|
|
251
|
+
const toDelete = this.index.checkpoints.filter(c => c.timestamp < date);
|
|
252
|
+
for (const checkpoint of toDelete) {
|
|
253
|
+
await this.delete(checkpoint.id);
|
|
254
|
+
}
|
|
255
|
+
return toDelete.length;
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
export function calculateHash(content) {
|
|
259
|
+
return crypto.createHash('sha256').update(content).digest('hex');
|
|
260
|
+
}
|
|
261
|
+
export function verifyFileSnapshot(snapshot) {
|
|
262
|
+
const actualHash = calculateHash(snapshot.content);
|
|
263
|
+
return actualHash === snapshot.hash;
|
|
264
|
+
}
|
|
265
|
+
//# sourceMappingURL=storage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage.js","sourceRoot":"","sources":["../../src/checkpoint/storage.ts"],"names":[],"mappings":"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"}
|