@mesadev/agentblame 0.2.11 → 3.0.1
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/dist/agentblame.js +3500 -0
- package/dist/blame.d.ts +4 -1
- package/dist/blame.js +293 -78
- package/dist/blame.js.map +1 -1
- package/dist/capture.d.ts +4 -7
- package/dist/capture.js +464 -486
- package/dist/capture.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +248 -85
- package/dist/index.js.map +1 -1
- package/dist/lib/analytics.d.ts +179 -0
- package/dist/lib/analytics.js +833 -0
- package/dist/lib/analytics.js.map +1 -0
- package/dist/lib/attribution.d.ts +54 -0
- package/dist/lib/attribution.js +266 -0
- package/dist/lib/attribution.js.map +1 -0
- package/dist/lib/checkpoint.d.ts +97 -0
- package/dist/lib/checkpoint.js +441 -0
- package/dist/lib/checkpoint.js.map +1 -0
- package/dist/lib/config.d.ts +46 -0
- package/dist/lib/config.js +123 -0
- package/dist/lib/config.js.map +1 -0
- package/dist/lib/database.d.ts +115 -85
- package/dist/lib/database.js +305 -325
- package/dist/lib/database.js.map +1 -1
- package/dist/lib/delta.d.ts +78 -0
- package/dist/lib/delta.js +309 -0
- package/dist/lib/delta.js.map +1 -0
- package/dist/lib/git/gitBlame.js +9 -4
- package/dist/lib/git/gitBlame.js.map +1 -1
- package/dist/lib/git/gitConfig.d.ts +5 -3
- package/dist/lib/git/gitConfig.js +41 -6
- package/dist/lib/git/gitConfig.js.map +1 -1
- package/dist/lib/git/gitDiff.d.ts +13 -1
- package/dist/lib/git/gitDiff.js +39 -7
- package/dist/lib/git/gitDiff.js.map +1 -1
- package/dist/lib/git/gitNotes.d.ts +30 -4
- package/dist/lib/git/gitNotes.js +140 -24
- package/dist/lib/git/gitNotes.js.map +1 -1
- package/dist/lib/hooks.d.ts +1 -0
- package/dist/lib/hooks.js +148 -27
- package/dist/lib/hooks.js.map +1 -1
- package/dist/lib/index.d.ts +7 -0
- package/dist/lib/index.js +13 -0
- package/dist/lib/index.js.map +1 -1
- package/dist/lib/storage.d.ts +163 -0
- package/dist/lib/storage.js +823 -0
- package/dist/lib/storage.js.map +1 -0
- package/dist/lib/trace.d.ts +118 -0
- package/dist/lib/trace.js +499 -0
- package/dist/lib/trace.js.map +1 -0
- package/dist/lib/types.d.ts +322 -114
- package/dist/lib/types.js +2 -1
- package/dist/lib/types.js.map +1 -1
- package/dist/lib/util.d.ts +8 -8
- package/dist/lib/util.js +18 -22
- package/dist/lib/util.js.map +1 -1
- package/dist/lib/watcher.d.ts +104 -0
- package/dist/lib/watcher.js +398 -0
- package/dist/lib/watcher.js.map +1 -0
- package/dist/post-merge.js +460 -421
- package/dist/post-merge.js.map +1 -1
- package/dist/process.d.ts +6 -5
- package/dist/process.js +233 -152
- package/dist/process.js.map +1 -1
- package/dist/sync.js +172 -131
- package/dist/sync.js.map +1 -1
- package/package.json +3 -2
|
@@ -0,0 +1,441 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Checkpoint Module v3
|
|
4
|
+
*
|
|
5
|
+
* Bulletproof capture of file states before AI edits.
|
|
6
|
+
* This replaces the file watcher approach with a deterministic checkpoint system.
|
|
7
|
+
*
|
|
8
|
+
* Strategy:
|
|
9
|
+
* - Cursor: beforeSubmitPrompt captures modified files, afterFileEdit uses checkpoint
|
|
10
|
+
* - Claude: PreToolUse captures target file, PostToolUse uses checkpoint
|
|
11
|
+
* - OpenCode: tool.execute.before captures target file, tool.execute.after uses checkpoint
|
|
12
|
+
*
|
|
13
|
+
* Storage: .git/agentblame/checkpoints/{conversation_id}.json
|
|
14
|
+
*/
|
|
15
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
16
|
+
if (k2 === undefined) k2 = k;
|
|
17
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
18
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
19
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
20
|
+
}
|
|
21
|
+
Object.defineProperty(o, k2, desc);
|
|
22
|
+
}) : (function(o, m, k, k2) {
|
|
23
|
+
if (k2 === undefined) k2 = k;
|
|
24
|
+
o[k2] = m[k];
|
|
25
|
+
}));
|
|
26
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
27
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
28
|
+
}) : function(o, v) {
|
|
29
|
+
o["default"] = v;
|
|
30
|
+
});
|
|
31
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
32
|
+
var ownKeys = function(o) {
|
|
33
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
34
|
+
var ar = [];
|
|
35
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
36
|
+
return ar;
|
|
37
|
+
};
|
|
38
|
+
return ownKeys(o);
|
|
39
|
+
};
|
|
40
|
+
return function (mod) {
|
|
41
|
+
if (mod && mod.__esModule) return mod;
|
|
42
|
+
var result = {};
|
|
43
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
44
|
+
__setModuleDefault(result, mod);
|
|
45
|
+
return result;
|
|
46
|
+
};
|
|
47
|
+
})();
|
|
48
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
49
|
+
exports.hashContent = hashContent;
|
|
50
|
+
exports.hasFileChanged = hasFileChanged;
|
|
51
|
+
exports.getCheckpointContent = getCheckpointContent;
|
|
52
|
+
exports.getCheckpointsDir = getCheckpointsDir;
|
|
53
|
+
exports.getCheckpointPath = getCheckpointPath;
|
|
54
|
+
exports.ensureCheckpointsDir = ensureCheckpointsDir;
|
|
55
|
+
exports.saveCheckpoint = saveCheckpoint;
|
|
56
|
+
exports.loadCheckpoint = loadCheckpoint;
|
|
57
|
+
exports.updateCheckpointFile = updateCheckpointFile;
|
|
58
|
+
exports.updateCheckpointWithContent = updateCheckpointWithContent;
|
|
59
|
+
exports.getCheckpointBlob = getCheckpointBlob;
|
|
60
|
+
exports.deleteCheckpoint = deleteCheckpoint;
|
|
61
|
+
exports.cleanupOldCheckpoints = cleanupOldCheckpoints;
|
|
62
|
+
exports.getGitModifiedFiles = getGitModifiedFiles;
|
|
63
|
+
exports.captureBeforePromptCheckpoint = captureBeforePromptCheckpoint;
|
|
64
|
+
exports.captureFileCheckpoint = captureFileCheckpoint;
|
|
65
|
+
exports.getBeforeBlob = getBeforeBlob;
|
|
66
|
+
const fs = __importStar(require("node:fs"));
|
|
67
|
+
const path = __importStar(require("node:path"));
|
|
68
|
+
const node_child_process_1 = require("node:child_process");
|
|
69
|
+
const node_crypto_1 = require("node:crypto");
|
|
70
|
+
const storage_1 = require("./storage");
|
|
71
|
+
// =============================================================================
|
|
72
|
+
// Hash Helpers
|
|
73
|
+
// =============================================================================
|
|
74
|
+
/**
|
|
75
|
+
* Compute a fast content hash for comparison
|
|
76
|
+
* Uses SHA256 truncated to 16 chars for efficiency
|
|
77
|
+
*/
|
|
78
|
+
function hashContent(content) {
|
|
79
|
+
return (0, node_crypto_1.createHash)("sha256").update(content).digest("hex").slice(0, 16);
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Check if a file has changed since the checkpoint
|
|
83
|
+
* Returns true if the file content differs from the checkpoint
|
|
84
|
+
*/
|
|
85
|
+
async function hasFileChanged(repoRoot, conversationId, filePath) {
|
|
86
|
+
const checkpoint = loadCheckpoint(repoRoot, conversationId);
|
|
87
|
+
if (!checkpoint) {
|
|
88
|
+
return false; // No checkpoint, can't detect change
|
|
89
|
+
}
|
|
90
|
+
const fileCheckpoint = checkpoint.files[filePath];
|
|
91
|
+
if (!fileCheckpoint) {
|
|
92
|
+
return false; // File not in checkpoint
|
|
93
|
+
}
|
|
94
|
+
// Read current file content
|
|
95
|
+
const absolutePath = filePath.startsWith("/")
|
|
96
|
+
? filePath
|
|
97
|
+
: path.join(repoRoot, filePath);
|
|
98
|
+
try {
|
|
99
|
+
const currentContent = fs.readFileSync(absolutePath, "utf8");
|
|
100
|
+
const currentHash = hashContent(currentContent);
|
|
101
|
+
return currentHash !== fileCheckpoint.contentHash;
|
|
102
|
+
}
|
|
103
|
+
catch {
|
|
104
|
+
return false; // Can't read file
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Get checkpoint content for a file (loads from git blob)
|
|
109
|
+
*/
|
|
110
|
+
async function getCheckpointContent(repoRoot, conversationId, filePath) {
|
|
111
|
+
const checkpoint = loadCheckpoint(repoRoot, conversationId);
|
|
112
|
+
if (!checkpoint) {
|
|
113
|
+
return null;
|
|
114
|
+
}
|
|
115
|
+
const fileCheckpoint = checkpoint.files[filePath];
|
|
116
|
+
if (!fileCheckpoint) {
|
|
117
|
+
return null;
|
|
118
|
+
}
|
|
119
|
+
try {
|
|
120
|
+
return await (0, storage_1.loadSnapshot)(repoRoot, fileCheckpoint.blobSha);
|
|
121
|
+
}
|
|
122
|
+
catch {
|
|
123
|
+
return null;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
// =============================================================================
|
|
127
|
+
// Path Helpers
|
|
128
|
+
// =============================================================================
|
|
129
|
+
/**
|
|
130
|
+
* Get the checkpoints directory path
|
|
131
|
+
*/
|
|
132
|
+
function getCheckpointsDir(repoRoot) {
|
|
133
|
+
return path.join((0, storage_1.getAgentBlameGitDir)(repoRoot), "checkpoints");
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Get the checkpoint file path for a conversation
|
|
137
|
+
*/
|
|
138
|
+
function getCheckpointPath(repoRoot, conversationId) {
|
|
139
|
+
// Sanitize conversation ID for filesystem
|
|
140
|
+
const safeId = conversationId.replace(/[^a-zA-Z0-9-_]/g, "_");
|
|
141
|
+
return path.join(getCheckpointsDir(repoRoot), `${safeId}.json`);
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Ensure checkpoints directory exists
|
|
145
|
+
*/
|
|
146
|
+
function ensureCheckpointsDir(repoRoot) {
|
|
147
|
+
const dir = getCheckpointsDir(repoRoot);
|
|
148
|
+
if (!fs.existsSync(dir)) {
|
|
149
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
// =============================================================================
|
|
153
|
+
// Checkpoint CRUD
|
|
154
|
+
// =============================================================================
|
|
155
|
+
/**
|
|
156
|
+
* Save a checkpoint for a conversation
|
|
157
|
+
*/
|
|
158
|
+
function saveCheckpoint(repoRoot, checkpoint) {
|
|
159
|
+
ensureCheckpointsDir(repoRoot);
|
|
160
|
+
const checkpointPath = getCheckpointPath(repoRoot, checkpoint.conversationId);
|
|
161
|
+
fs.writeFileSync(checkpointPath, JSON.stringify(checkpoint, null, 2), "utf8");
|
|
162
|
+
if (process.env.AGENTBLAME_DEBUG) {
|
|
163
|
+
console.error(`[agentblame] Saved checkpoint: ${checkpoint.conversationId} with ${Object.keys(checkpoint.files).length} files`);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Load a checkpoint for a conversation
|
|
168
|
+
*/
|
|
169
|
+
function loadCheckpoint(repoRoot, conversationId) {
|
|
170
|
+
const checkpointPath = getCheckpointPath(repoRoot, conversationId);
|
|
171
|
+
if (!fs.existsSync(checkpointPath)) {
|
|
172
|
+
return null;
|
|
173
|
+
}
|
|
174
|
+
try {
|
|
175
|
+
const content = fs.readFileSync(checkpointPath, "utf8");
|
|
176
|
+
return JSON.parse(content);
|
|
177
|
+
}
|
|
178
|
+
catch {
|
|
179
|
+
return null;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Update a checkpoint with a new file state
|
|
184
|
+
*/
|
|
185
|
+
function updateCheckpointFile(repoRoot, conversationId, filePath, blobSha, contentHash) {
|
|
186
|
+
let checkpoint = loadCheckpoint(repoRoot, conversationId);
|
|
187
|
+
if (!checkpoint) {
|
|
188
|
+
checkpoint = {
|
|
189
|
+
conversationId,
|
|
190
|
+
timestamp: new Date().toISOString(),
|
|
191
|
+
files: {},
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
checkpoint.files[filePath] = {
|
|
195
|
+
blobSha,
|
|
196
|
+
contentHash,
|
|
197
|
+
timestamp: new Date().toISOString(),
|
|
198
|
+
};
|
|
199
|
+
saveCheckpoint(repoRoot, checkpoint);
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* Update checkpoint with content (computes hash and stores blob)
|
|
203
|
+
*/
|
|
204
|
+
async function updateCheckpointWithContent(repoRoot, conversationId, filePath, content) {
|
|
205
|
+
const blobSha = await (0, storage_1.storeSnapshot)(repoRoot, content);
|
|
206
|
+
const contentHash = hashContent(content);
|
|
207
|
+
updateCheckpointFile(repoRoot, conversationId, filePath, blobSha, contentHash);
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* Get the "before" blob for a file from checkpoint
|
|
211
|
+
* Returns null if no checkpoint exists for this file
|
|
212
|
+
*/
|
|
213
|
+
function getCheckpointBlob(repoRoot, conversationId, filePath) {
|
|
214
|
+
const checkpoint = loadCheckpoint(repoRoot, conversationId);
|
|
215
|
+
if (!checkpoint) {
|
|
216
|
+
return null;
|
|
217
|
+
}
|
|
218
|
+
return checkpoint.files[filePath]?.blobSha || null;
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* Delete a checkpoint (cleanup after commit or session end)
|
|
222
|
+
*/
|
|
223
|
+
function deleteCheckpoint(repoRoot, conversationId) {
|
|
224
|
+
const checkpointPath = getCheckpointPath(repoRoot, conversationId);
|
|
225
|
+
if (fs.existsSync(checkpointPath)) {
|
|
226
|
+
fs.unlinkSync(checkpointPath);
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
/**
|
|
230
|
+
* Clean up old checkpoints (older than specified hours)
|
|
231
|
+
*/
|
|
232
|
+
function cleanupOldCheckpoints(repoRoot, maxAgeHours = 24) {
|
|
233
|
+
const dir = getCheckpointsDir(repoRoot);
|
|
234
|
+
if (!fs.existsSync(dir)) {
|
|
235
|
+
return 0;
|
|
236
|
+
}
|
|
237
|
+
const now = Date.now();
|
|
238
|
+
const maxAgeMs = maxAgeHours * 60 * 60 * 1000;
|
|
239
|
+
let cleaned = 0;
|
|
240
|
+
try {
|
|
241
|
+
const files = fs.readdirSync(dir);
|
|
242
|
+
for (const file of files) {
|
|
243
|
+
if (!file.endsWith(".json"))
|
|
244
|
+
continue;
|
|
245
|
+
const filePath = path.join(dir, file);
|
|
246
|
+
const stat = fs.statSync(filePath);
|
|
247
|
+
if (now - stat.mtimeMs > maxAgeMs) {
|
|
248
|
+
fs.unlinkSync(filePath);
|
|
249
|
+
cleaned++;
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
catch {
|
|
254
|
+
// Silent failure
|
|
255
|
+
}
|
|
256
|
+
return cleaned;
|
|
257
|
+
}
|
|
258
|
+
// =============================================================================
|
|
259
|
+
// Git Status Helpers
|
|
260
|
+
// =============================================================================
|
|
261
|
+
/**
|
|
262
|
+
* Get list of modified files from git status (staged + unstaged)
|
|
263
|
+
* These are files that may have human edits since last commit
|
|
264
|
+
*/
|
|
265
|
+
async function getGitModifiedFiles(repoRoot) {
|
|
266
|
+
return new Promise((resolve) => {
|
|
267
|
+
const proc = (0, node_child_process_1.spawn)("git", ["status", "--porcelain", "-z"], {
|
|
268
|
+
cwd: repoRoot,
|
|
269
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
270
|
+
});
|
|
271
|
+
let stdout = "";
|
|
272
|
+
proc.stdout.on("data", (data) => {
|
|
273
|
+
stdout += data.toString();
|
|
274
|
+
});
|
|
275
|
+
proc.on("close", (code) => {
|
|
276
|
+
if (code !== 0) {
|
|
277
|
+
resolve([]);
|
|
278
|
+
return;
|
|
279
|
+
}
|
|
280
|
+
// Parse git status output (NUL-separated)
|
|
281
|
+
const files = [];
|
|
282
|
+
const entries = stdout.split("\0").filter(Boolean);
|
|
283
|
+
for (const entry of entries) {
|
|
284
|
+
// Format: XY filename (where XY is status codes)
|
|
285
|
+
if (entry.length < 4)
|
|
286
|
+
continue;
|
|
287
|
+
const status = entry.substring(0, 2);
|
|
288
|
+
const filePath = entry.substring(3);
|
|
289
|
+
// Include modified, added, and renamed files (not deleted)
|
|
290
|
+
if (status.includes("M") || status.includes("A") || status.includes("R") || status === "??") {
|
|
291
|
+
// For renamed files, use the new name (after ->)
|
|
292
|
+
const actualPath = filePath.includes(" -> ")
|
|
293
|
+
? filePath.split(" -> ")[1]
|
|
294
|
+
: filePath;
|
|
295
|
+
files.push(actualPath);
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
resolve(files);
|
|
299
|
+
});
|
|
300
|
+
proc.on("error", () => {
|
|
301
|
+
resolve([]);
|
|
302
|
+
});
|
|
303
|
+
});
|
|
304
|
+
}
|
|
305
|
+
/**
|
|
306
|
+
* Read file content from disk
|
|
307
|
+
*/
|
|
308
|
+
function readFileContent(filePath) {
|
|
309
|
+
try {
|
|
310
|
+
return fs.readFileSync(filePath, "utf8");
|
|
311
|
+
}
|
|
312
|
+
catch {
|
|
313
|
+
return null;
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
// =============================================================================
|
|
317
|
+
// Checkpoint Capture Functions
|
|
318
|
+
// =============================================================================
|
|
319
|
+
/**
|
|
320
|
+
* Capture checkpoint for Cursor's beforeSubmitPrompt
|
|
321
|
+
* Captures all modified files (from git status) since they may have human edits
|
|
322
|
+
*/
|
|
323
|
+
async function captureBeforePromptCheckpoint(repoRoot, conversationId) {
|
|
324
|
+
const checkpoint = {
|
|
325
|
+
conversationId,
|
|
326
|
+
timestamp: new Date().toISOString(),
|
|
327
|
+
files: {},
|
|
328
|
+
};
|
|
329
|
+
// Get all modified files from git status
|
|
330
|
+
const modifiedFiles = await getGitModifiedFiles(repoRoot);
|
|
331
|
+
if (process.env.AGENTBLAME_DEBUG) {
|
|
332
|
+
console.error(`[agentblame] beforeSubmitPrompt: ${modifiedFiles.length} modified files`);
|
|
333
|
+
}
|
|
334
|
+
// Capture each modified file's current state
|
|
335
|
+
for (const relativePath of modifiedFiles) {
|
|
336
|
+
const absolutePath = path.join(repoRoot, relativePath);
|
|
337
|
+
const content = readFileContent(absolutePath);
|
|
338
|
+
if (content === null)
|
|
339
|
+
continue;
|
|
340
|
+
try {
|
|
341
|
+
const blobSha = await (0, storage_1.storeSnapshot)(repoRoot, content);
|
|
342
|
+
const contentHash = hashContent(content);
|
|
343
|
+
checkpoint.files[relativePath] = {
|
|
344
|
+
blobSha,
|
|
345
|
+
contentHash,
|
|
346
|
+
timestamp: new Date().toISOString(),
|
|
347
|
+
};
|
|
348
|
+
}
|
|
349
|
+
catch {
|
|
350
|
+
// Skip files that fail to store
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
saveCheckpoint(repoRoot, checkpoint);
|
|
354
|
+
return checkpoint;
|
|
355
|
+
}
|
|
356
|
+
/**
|
|
357
|
+
* Capture checkpoint for a single file (Claude PreToolUse / OpenCode tool.execute.before)
|
|
358
|
+
* More efficient than capturing all modified files since we know the target
|
|
359
|
+
*/
|
|
360
|
+
async function captureFileCheckpoint(repoRoot, conversationId, filePath) {
|
|
361
|
+
// Make path relative if absolute
|
|
362
|
+
const relativePath = filePath.startsWith(repoRoot)
|
|
363
|
+
? filePath.slice(repoRoot.length + 1)
|
|
364
|
+
: filePath;
|
|
365
|
+
const absolutePath = filePath.startsWith("/")
|
|
366
|
+
? filePath
|
|
367
|
+
: path.join(repoRoot, filePath);
|
|
368
|
+
const content = readFileContent(absolutePath);
|
|
369
|
+
if (content === null) {
|
|
370
|
+
// File doesn't exist yet (new file)
|
|
371
|
+
return null;
|
|
372
|
+
}
|
|
373
|
+
try {
|
|
374
|
+
const blobSha = await (0, storage_1.storeSnapshot)(repoRoot, content);
|
|
375
|
+
const contentHash = hashContent(content);
|
|
376
|
+
updateCheckpointFile(repoRoot, conversationId, relativePath, blobSha, contentHash);
|
|
377
|
+
if (process.env.AGENTBLAME_DEBUG) {
|
|
378
|
+
console.error(`[agentblame] PreToolUse checkpoint: ${relativePath} -> ${blobSha.slice(0, 8)}`);
|
|
379
|
+
}
|
|
380
|
+
return blobSha;
|
|
381
|
+
}
|
|
382
|
+
catch (err) {
|
|
383
|
+
if (process.env.AGENTBLAME_DEBUG) {
|
|
384
|
+
console.error(`[agentblame] Failed to capture file checkpoint:`, err);
|
|
385
|
+
}
|
|
386
|
+
return null;
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
/**
|
|
390
|
+
* Get the "before" blob for a file, using checkpoint if available, else git HEAD
|
|
391
|
+
*/
|
|
392
|
+
async function getBeforeBlob(repoRoot, conversationId, filePath) {
|
|
393
|
+
// Make path relative
|
|
394
|
+
const relativePath = filePath.startsWith(repoRoot)
|
|
395
|
+
? filePath.slice(repoRoot.length + 1)
|
|
396
|
+
: filePath;
|
|
397
|
+
// First, check checkpoint
|
|
398
|
+
const checkpointBlob = getCheckpointBlob(repoRoot, conversationId, relativePath);
|
|
399
|
+
if (checkpointBlob) {
|
|
400
|
+
if (process.env.AGENTBLAME_DEBUG) {
|
|
401
|
+
console.error(`[agentblame] Using checkpoint blob for ${relativePath}: ${checkpointBlob.slice(0, 8)}`);
|
|
402
|
+
}
|
|
403
|
+
return checkpointBlob;
|
|
404
|
+
}
|
|
405
|
+
// Fall back to git HEAD
|
|
406
|
+
return getFileBlobAtHead(repoRoot, relativePath);
|
|
407
|
+
}
|
|
408
|
+
/**
|
|
409
|
+
* Get the blob SHA for a file at HEAD
|
|
410
|
+
*/
|
|
411
|
+
async function getFileBlobAtHead(repoRoot, filePath) {
|
|
412
|
+
return new Promise((resolve) => {
|
|
413
|
+
const proc = (0, node_child_process_1.spawn)("git", ["ls-tree", "HEAD", filePath], {
|
|
414
|
+
cwd: repoRoot,
|
|
415
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
416
|
+
});
|
|
417
|
+
let stdout = "";
|
|
418
|
+
proc.stdout.on("data", (data) => {
|
|
419
|
+
stdout += data.toString();
|
|
420
|
+
});
|
|
421
|
+
proc.on("close", (code) => {
|
|
422
|
+
if (code === 0 && stdout.trim()) {
|
|
423
|
+
// Output format: mode type blob\tpath
|
|
424
|
+
const parts = stdout.trim().split(/\s+/);
|
|
425
|
+
if (parts.length >= 3) {
|
|
426
|
+
resolve(parts[2]); // The blob SHA
|
|
427
|
+
}
|
|
428
|
+
else {
|
|
429
|
+
resolve(null);
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
else {
|
|
433
|
+
resolve(null);
|
|
434
|
+
}
|
|
435
|
+
});
|
|
436
|
+
proc.on("error", () => {
|
|
437
|
+
resolve(null);
|
|
438
|
+
});
|
|
439
|
+
});
|
|
440
|
+
}
|
|
441
|
+
//# sourceMappingURL=checkpoint.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"checkpoint.js","sourceRoot":"","sources":["../../src/lib/checkpoint.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agent Blame Configuration
|
|
3
|
+
*
|
|
4
|
+
* Manages user preferences stored in git config.
|
|
5
|
+
* Settings are stored per-repo in .git/config under [agentblame] section.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Configuration keys and their defaults
|
|
9
|
+
*/
|
|
10
|
+
export interface AgentBlameConfig {
|
|
11
|
+
/** Whether to store actual prompt content (default: true) */
|
|
12
|
+
storePromptContent: boolean;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Get a configuration value
|
|
16
|
+
*/
|
|
17
|
+
export declare function getConfig<K extends keyof AgentBlameConfig>(repoRoot: string, key: K): Promise<AgentBlameConfig[K]>;
|
|
18
|
+
/**
|
|
19
|
+
* Set a configuration value
|
|
20
|
+
*/
|
|
21
|
+
export declare function setConfig<K extends keyof AgentBlameConfig>(repoRoot: string, key: K, value: AgentBlameConfig[K]): Promise<void>;
|
|
22
|
+
/**
|
|
23
|
+
* Unset a configuration value (revert to default)
|
|
24
|
+
*/
|
|
25
|
+
export declare function unsetConfig<K extends keyof AgentBlameConfig>(repoRoot: string, key: K): Promise<void>;
|
|
26
|
+
/**
|
|
27
|
+
* Get all configuration values
|
|
28
|
+
*/
|
|
29
|
+
export declare function getAllConfig(repoRoot: string): Promise<AgentBlameConfig>;
|
|
30
|
+
/**
|
|
31
|
+
* List all configuration with their current values and defaults
|
|
32
|
+
*/
|
|
33
|
+
export declare function listConfig(repoRoot: string): Promise<Array<{
|
|
34
|
+
key: string;
|
|
35
|
+
value: string;
|
|
36
|
+
default: string;
|
|
37
|
+
isDefault: boolean;
|
|
38
|
+
}>>;
|
|
39
|
+
/**
|
|
40
|
+
* Valid config keys for user input validation
|
|
41
|
+
*/
|
|
42
|
+
export declare const VALID_CONFIG_KEYS: (keyof AgentBlameConfig)[];
|
|
43
|
+
/**
|
|
44
|
+
* Parse a string value to the appropriate type for a config key
|
|
45
|
+
*/
|
|
46
|
+
export declare function parseConfigValue<K extends keyof AgentBlameConfig>(key: K, value: string): AgentBlameConfig[K] | null;
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Agent Blame Configuration
|
|
4
|
+
*
|
|
5
|
+
* Manages user preferences stored in git config.
|
|
6
|
+
* Settings are stored per-repo in .git/config under [agentblame] section.
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.VALID_CONFIG_KEYS = void 0;
|
|
10
|
+
exports.getConfig = getConfig;
|
|
11
|
+
exports.setConfig = setConfig;
|
|
12
|
+
exports.unsetConfig = unsetConfig;
|
|
13
|
+
exports.getAllConfig = getAllConfig;
|
|
14
|
+
exports.listConfig = listConfig;
|
|
15
|
+
exports.parseConfigValue = parseConfigValue;
|
|
16
|
+
const gitCli_1 = require("./git/gitCli");
|
|
17
|
+
const CONFIG_DEFAULTS = {
|
|
18
|
+
storePromptContent: false, // Default: don't store prompt text (privacy-first)
|
|
19
|
+
};
|
|
20
|
+
const CONFIG_PREFIX = "agentblame";
|
|
21
|
+
/**
|
|
22
|
+
* Get a configuration value
|
|
23
|
+
*/
|
|
24
|
+
async function getConfig(repoRoot, key) {
|
|
25
|
+
try {
|
|
26
|
+
const result = await (0, gitCli_1.runGit)(repoRoot, [
|
|
27
|
+
"config",
|
|
28
|
+
"--local",
|
|
29
|
+
"--get",
|
|
30
|
+
`${CONFIG_PREFIX}.${key}`,
|
|
31
|
+
]);
|
|
32
|
+
// git config --get returns exit code 1 if key not found
|
|
33
|
+
if (result.exitCode !== 0) {
|
|
34
|
+
return CONFIG_DEFAULTS[key];
|
|
35
|
+
}
|
|
36
|
+
const value = result.stdout.trim();
|
|
37
|
+
// Parse based on type
|
|
38
|
+
if (typeof CONFIG_DEFAULTS[key] === "boolean") {
|
|
39
|
+
return (value === "true");
|
|
40
|
+
}
|
|
41
|
+
return value;
|
|
42
|
+
}
|
|
43
|
+
catch {
|
|
44
|
+
// Return default if not set
|
|
45
|
+
return CONFIG_DEFAULTS[key];
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Set a configuration value
|
|
50
|
+
*/
|
|
51
|
+
async function setConfig(repoRoot, key, value) {
|
|
52
|
+
await (0, gitCli_1.runGit)(repoRoot, [
|
|
53
|
+
"config",
|
|
54
|
+
"--local",
|
|
55
|
+
`${CONFIG_PREFIX}.${key}`,
|
|
56
|
+
String(value),
|
|
57
|
+
]);
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Unset a configuration value (revert to default)
|
|
61
|
+
*/
|
|
62
|
+
async function unsetConfig(repoRoot, key) {
|
|
63
|
+
try {
|
|
64
|
+
await (0, gitCli_1.runGit)(repoRoot, [
|
|
65
|
+
"config",
|
|
66
|
+
"--local",
|
|
67
|
+
"--unset",
|
|
68
|
+
`${CONFIG_PREFIX}.${key}`,
|
|
69
|
+
]);
|
|
70
|
+
}
|
|
71
|
+
catch {
|
|
72
|
+
// Ignore if not set
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Get all configuration values
|
|
77
|
+
*/
|
|
78
|
+
async function getAllConfig(repoRoot) {
|
|
79
|
+
const config = { ...CONFIG_DEFAULTS };
|
|
80
|
+
for (const key of Object.keys(CONFIG_DEFAULTS)) {
|
|
81
|
+
config[key] = await getConfig(repoRoot, key);
|
|
82
|
+
}
|
|
83
|
+
return config;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* List all configuration with their current values and defaults
|
|
87
|
+
*/
|
|
88
|
+
async function listConfig(repoRoot) {
|
|
89
|
+
const result = [];
|
|
90
|
+
for (const key of Object.keys(CONFIG_DEFAULTS)) {
|
|
91
|
+
const currentValue = await getConfig(repoRoot, key);
|
|
92
|
+
const defaultValue = CONFIG_DEFAULTS[key];
|
|
93
|
+
const isDefault = currentValue === defaultValue;
|
|
94
|
+
result.push({
|
|
95
|
+
key,
|
|
96
|
+
value: String(currentValue),
|
|
97
|
+
default: String(defaultValue),
|
|
98
|
+
isDefault,
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
return result;
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Valid config keys for user input validation
|
|
105
|
+
*/
|
|
106
|
+
exports.VALID_CONFIG_KEYS = Object.keys(CONFIG_DEFAULTS);
|
|
107
|
+
/**
|
|
108
|
+
* Parse a string value to the appropriate type for a config key
|
|
109
|
+
*/
|
|
110
|
+
function parseConfigValue(key, value) {
|
|
111
|
+
const defaultValue = CONFIG_DEFAULTS[key];
|
|
112
|
+
if (typeof defaultValue === "boolean") {
|
|
113
|
+
if (value === "true" || value === "1" || value === "yes") {
|
|
114
|
+
return true;
|
|
115
|
+
}
|
|
116
|
+
if (value === "false" || value === "0" || value === "no") {
|
|
117
|
+
return false;
|
|
118
|
+
}
|
|
119
|
+
return null; // Invalid boolean value
|
|
120
|
+
}
|
|
121
|
+
return value;
|
|
122
|
+
}
|
|
123
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"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"}
|