@mesadev/agentblame 0.1.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/dist/blame.d.ts +14 -0
- package/dist/blame.js +252 -0
- package/dist/blame.js.map +1 -0
- package/dist/capture.d.ts +16 -0
- package/dist/capture.js +284 -0
- package/dist/capture.js.map +1 -0
- package/dist/cleanup.d.ts +10 -0
- package/dist/cleanup.js +136 -0
- package/dist/cleanup.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.js +240 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/db.d.ts +53 -0
- package/dist/lib/db.js +290 -0
- package/dist/lib/db.js.map +1 -0
- package/dist/lib/diff.d.ts +13 -0
- package/dist/lib/diff.js +32 -0
- package/dist/lib/diff.js.map +1 -0
- package/dist/lib/git/gitBlame.d.ts +25 -0
- package/dist/lib/git/gitBlame.js +87 -0
- package/dist/lib/git/gitBlame.js.map +1 -0
- package/dist/lib/git/gitCli.d.ts +17 -0
- package/dist/lib/git/gitCli.js +57 -0
- package/dist/lib/git/gitCli.js.map +1 -0
- package/dist/lib/git/gitConfig.d.ts +20 -0
- package/dist/lib/git/gitConfig.js +91 -0
- package/dist/lib/git/gitConfig.js.map +1 -0
- package/dist/lib/git/gitDiff.d.ts +42 -0
- package/dist/lib/git/gitDiff.js +346 -0
- package/dist/lib/git/gitDiff.js.map +1 -0
- package/dist/lib/git/gitNotes.d.ts +31 -0
- package/dist/lib/git/gitNotes.js +93 -0
- package/dist/lib/git/gitNotes.js.map +1 -0
- package/dist/lib/git/index.d.ts +5 -0
- package/dist/lib/git/index.js +22 -0
- package/dist/lib/git/index.js.map +1 -0
- package/dist/lib/hooks.d.ts +65 -0
- package/dist/lib/hooks.js +423 -0
- package/dist/lib/hooks.js.map +1 -0
- package/dist/lib/index.d.ts +10 -0
- package/dist/lib/index.js +33 -0
- package/dist/lib/index.js.map +1 -0
- package/dist/lib/types.d.ts +190 -0
- package/dist/lib/types.js +8 -0
- package/dist/lib/types.js.map +1 -0
- package/dist/lib/util.d.ts +24 -0
- package/dist/lib/util.js +82 -0
- package/dist/lib/util.js.map +1 -0
- package/dist/process.d.ts +14 -0
- package/dist/process.js +224 -0
- package/dist/process.js.map +1 -0
- package/dist/sync.d.ts +15 -0
- package/dist/sync.js +413 -0
- package/dist/sync.js.map +1 -0
- package/dist/transfer-notes.d.ts +16 -0
- package/dist/transfer-notes.js +426 -0
- package/dist/transfer-notes.js.map +1 -0
- package/package.json +37 -0
package/dist/blame.d.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agent Blame Command
|
|
3
|
+
*
|
|
4
|
+
* Shows AI attribution for each line in a file, similar to git blame
|
|
5
|
+
*/
|
|
6
|
+
interface BlameOptions {
|
|
7
|
+
json?: boolean;
|
|
8
|
+
summary?: boolean;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Run agentblame on a file
|
|
12
|
+
*/
|
|
13
|
+
export declare function blame(filePath: string, options?: BlameOptions): Promise<void>;
|
|
14
|
+
export {};
|
package/dist/blame.js
ADDED
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Agent Blame Command
|
|
4
|
+
*
|
|
5
|
+
* Shows AI attribution for each line in a file, similar to git blame
|
|
6
|
+
*/
|
|
7
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
8
|
+
if (k2 === undefined) k2 = k;
|
|
9
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
10
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
11
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
12
|
+
}
|
|
13
|
+
Object.defineProperty(o, k2, desc);
|
|
14
|
+
}) : (function(o, m, k, k2) {
|
|
15
|
+
if (k2 === undefined) k2 = k;
|
|
16
|
+
o[k2] = m[k];
|
|
17
|
+
}));
|
|
18
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
19
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
20
|
+
}) : function(o, v) {
|
|
21
|
+
o["default"] = v;
|
|
22
|
+
});
|
|
23
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
24
|
+
var ownKeys = function(o) {
|
|
25
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
26
|
+
var ar = [];
|
|
27
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
28
|
+
return ar;
|
|
29
|
+
};
|
|
30
|
+
return ownKeys(o);
|
|
31
|
+
};
|
|
32
|
+
return function (mod) {
|
|
33
|
+
if (mod && mod.__esModule) return mod;
|
|
34
|
+
var result = {};
|
|
35
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
36
|
+
__setModuleDefault(result, mod);
|
|
37
|
+
return result;
|
|
38
|
+
};
|
|
39
|
+
})();
|
|
40
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
41
|
+
exports.blame = blame;
|
|
42
|
+
const path = __importStar(require("node:path"));
|
|
43
|
+
const fs = __importStar(require("node:fs"));
|
|
44
|
+
const lib_1 = require("./lib");
|
|
45
|
+
// Terminal colors
|
|
46
|
+
const c = {
|
|
47
|
+
reset: "\x1b[0m",
|
|
48
|
+
bold: "\x1b[1m",
|
|
49
|
+
dim: "\x1b[2m",
|
|
50
|
+
cyan: "\x1b[36m",
|
|
51
|
+
yellow: "\x1b[33m",
|
|
52
|
+
green: "\x1b[32m",
|
|
53
|
+
magenta: "\x1b[35m",
|
|
54
|
+
blue: "\x1b[34m",
|
|
55
|
+
gray: "\x1b[90m",
|
|
56
|
+
};
|
|
57
|
+
/**
|
|
58
|
+
* Run agentblame on a file
|
|
59
|
+
*/
|
|
60
|
+
async function blame(filePath, options = {}) {
|
|
61
|
+
// Resolve file path
|
|
62
|
+
const absolutePath = path.resolve(filePath);
|
|
63
|
+
// Check file exists
|
|
64
|
+
if (!fs.existsSync(absolutePath)) {
|
|
65
|
+
console.error(`Error: File not found: ${absolutePath}`);
|
|
66
|
+
process.exit(1);
|
|
67
|
+
}
|
|
68
|
+
// Check it's a file, not directory
|
|
69
|
+
const stat = fs.statSync(absolutePath);
|
|
70
|
+
if (!stat.isFile()) {
|
|
71
|
+
console.error(`Error: Not a file: ${absolutePath}`);
|
|
72
|
+
process.exit(1);
|
|
73
|
+
}
|
|
74
|
+
const repoRoot = await (0, lib_1.getRepoRoot)(path.dirname(absolutePath));
|
|
75
|
+
if (!repoRoot) {
|
|
76
|
+
console.error("Error: Not in a git repository");
|
|
77
|
+
process.exit(1);
|
|
78
|
+
}
|
|
79
|
+
// Get relative path and validate it's within repo
|
|
80
|
+
const relativePath = path.relative(repoRoot, absolutePath);
|
|
81
|
+
if (relativePath.startsWith("..")) {
|
|
82
|
+
console.error("Error: File is outside the repository");
|
|
83
|
+
process.exit(1);
|
|
84
|
+
}
|
|
85
|
+
// Fetch latest notes from remote (silent, ignores errors)
|
|
86
|
+
await (0, lib_1.fetchNotesQuiet)(repoRoot);
|
|
87
|
+
// Get blame data
|
|
88
|
+
let blameResult;
|
|
89
|
+
try {
|
|
90
|
+
blameResult = await (0, lib_1.getBlame)(repoRoot, relativePath);
|
|
91
|
+
}
|
|
92
|
+
catch (err) {
|
|
93
|
+
console.error(`Error: ${err}`);
|
|
94
|
+
process.exit(1);
|
|
95
|
+
}
|
|
96
|
+
// Fetch notes for all unique commits
|
|
97
|
+
const uniqueShas = [...new Set(blameResult.lines.map((l) => l.sha))];
|
|
98
|
+
const notesMap = new Map();
|
|
99
|
+
for (const sha of uniqueShas) {
|
|
100
|
+
const note = await (0, lib_1.readNote)(repoRoot, sha);
|
|
101
|
+
if (note?.attributions) {
|
|
102
|
+
notesMap.set(sha, note.attributions);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
// Build line attribution
|
|
106
|
+
const lineAttributions = blameResult.lines.map((line) => {
|
|
107
|
+
const commitNotes = notesMap.get(line.sha) || [];
|
|
108
|
+
// Find attribution that covers this line (must match path AND line number range)
|
|
109
|
+
const attr = commitNotes.find((a) => {
|
|
110
|
+
const pathMatches = a.path === relativePath ||
|
|
111
|
+
a.path.endsWith(relativePath) ||
|
|
112
|
+
relativePath.endsWith(a.path);
|
|
113
|
+
if (!pathMatches)
|
|
114
|
+
return false;
|
|
115
|
+
// Check if original line number (at commit time) is within the attribution range
|
|
116
|
+
return line.origLine >= a.start_line && line.origLine <= a.end_line;
|
|
117
|
+
});
|
|
118
|
+
return { line, attribution: attr || null };
|
|
119
|
+
});
|
|
120
|
+
// Output
|
|
121
|
+
if (options.json) {
|
|
122
|
+
outputJson(lineAttributions, relativePath);
|
|
123
|
+
}
|
|
124
|
+
else if (options.summary) {
|
|
125
|
+
outputSummary(lineAttributions, relativePath);
|
|
126
|
+
}
|
|
127
|
+
else {
|
|
128
|
+
outputFormatted(lineAttributions, relativePath);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Output formatted blame with attribution markers
|
|
133
|
+
*/
|
|
134
|
+
function outputFormatted(lines, filePath) {
|
|
135
|
+
console.log("");
|
|
136
|
+
console.log(` ${c.bold}${c.cyan}${filePath}${c.reset}`);
|
|
137
|
+
console.log(` ${c.dim}${"─".repeat(70)}${c.reset}`);
|
|
138
|
+
// Calculate column widths
|
|
139
|
+
const maxLineNum = lines.length.toString().length;
|
|
140
|
+
for (const { line, attribution } of lines) {
|
|
141
|
+
const sha = `${c.yellow}${line.sha.slice(0, 7)}${c.reset}`;
|
|
142
|
+
const author = `${c.blue}${line.author.slice(0, 12).padEnd(12)}${c.reset}`;
|
|
143
|
+
const date = `${c.dim}${formatDate(line.authorTime)}${c.reset}`;
|
|
144
|
+
const lineNum = `${c.dim}${line.lineNumber.toString().padStart(maxLineNum)}${c.reset}`;
|
|
145
|
+
// Attribution info - use fixed width column (must fit longest: "✨ Cursor - claude-4.5-opus-high-thinking")
|
|
146
|
+
const ATTR_WIDTH = 44;
|
|
147
|
+
let attrInfo = "";
|
|
148
|
+
let visibleLen = 0;
|
|
149
|
+
if (attribution) {
|
|
150
|
+
const provider = attribution.provider === "cursor" ? "Cursor" : "Claude";
|
|
151
|
+
const model = attribution.model && attribution.model !== "claude" ? attribution.model : "";
|
|
152
|
+
const label = model ? `${provider} - ${model}` : provider;
|
|
153
|
+
visibleLen = label.length + 3; // +2 for emoji (renders 2-wide) + 1 space
|
|
154
|
+
attrInfo = `${c.magenta}✨ ${label}${c.reset}`;
|
|
155
|
+
}
|
|
156
|
+
const attrPadded = attribution
|
|
157
|
+
? attrInfo + " ".repeat(Math.max(0, ATTR_WIDTH - visibleLen))
|
|
158
|
+
: " ".repeat(ATTR_WIDTH);
|
|
159
|
+
console.log(` ${sha} ${author} ${date} ${attrPadded} ${c.dim}│${c.reset} ${lineNum} ${c.dim}│${c.reset} ${line.content}`);
|
|
160
|
+
}
|
|
161
|
+
// Print summary
|
|
162
|
+
const aiGenerated = lines.filter((l) => l.attribution?.category === "ai_generated").length;
|
|
163
|
+
const human = lines.length - aiGenerated;
|
|
164
|
+
const aiPct = lines.length > 0 ? Math.round((aiGenerated / lines.length) * 100) : 0;
|
|
165
|
+
const humanPct = 100 - aiPct;
|
|
166
|
+
// Summary bar
|
|
167
|
+
const barWidth = 40;
|
|
168
|
+
const aiBarWidth = Math.round((aiPct / 100) * barWidth);
|
|
169
|
+
const humanBarWidth = barWidth - aiBarWidth;
|
|
170
|
+
const aiBar = `${c.magenta}${"█".repeat(aiBarWidth)}${c.reset}`;
|
|
171
|
+
const humanBar = `${c.dim}${"░".repeat(humanBarWidth)}${c.reset}`;
|
|
172
|
+
console.log(` ${c.dim}${"─".repeat(70)}${c.reset}`);
|
|
173
|
+
console.log(` ${aiBar}${humanBar}`);
|
|
174
|
+
console.log(` ${c.magenta}✨ AI: ${aiGenerated} (${aiPct}%)${c.reset} ${c.dim}│${c.reset} ${c.green}👤 Human: ${human} (${humanPct}%)${c.reset}`);
|
|
175
|
+
console.log("");
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Output summary only
|
|
179
|
+
*/
|
|
180
|
+
function outputSummary(lines, filePath) {
|
|
181
|
+
const aiGenerated = lines.filter((l) => l.attribution?.category === "ai_generated").length;
|
|
182
|
+
const human = lines.length - aiGenerated;
|
|
183
|
+
console.log(`\n${filePath}:`);
|
|
184
|
+
console.log(` Total lines: ${lines.length}`);
|
|
185
|
+
console.log(` AI-generated: ${aiGenerated} (${pct(aiGenerated, lines.length)})`);
|
|
186
|
+
console.log(` Human: ${human} (${pct(human, lines.length)})`);
|
|
187
|
+
console.log("");
|
|
188
|
+
// Provider breakdown
|
|
189
|
+
const providers = new Map();
|
|
190
|
+
const matchTypes = new Map();
|
|
191
|
+
for (const { attribution } of lines) {
|
|
192
|
+
if (attribution) {
|
|
193
|
+
const provider = attribution.provider;
|
|
194
|
+
providers.set(provider, (providers.get(provider) || 0) + 1);
|
|
195
|
+
const matchType = attribution.match_type;
|
|
196
|
+
matchTypes.set(matchType, (matchTypes.get(matchType) || 0) + 1);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
if (providers.size > 0) {
|
|
200
|
+
console.log(" By provider:");
|
|
201
|
+
for (const [provider, count] of providers) {
|
|
202
|
+
console.log(` ${provider}: ${count} lines`);
|
|
203
|
+
}
|
|
204
|
+
console.log("");
|
|
205
|
+
}
|
|
206
|
+
if (matchTypes.size > 0) {
|
|
207
|
+
console.log(" By match type:");
|
|
208
|
+
for (const [matchType, count] of matchTypes) {
|
|
209
|
+
console.log(` ${matchType}: ${count} lines`);
|
|
210
|
+
}
|
|
211
|
+
console.log("");
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Output as JSON
|
|
216
|
+
*/
|
|
217
|
+
function outputJson(lines, filePath) {
|
|
218
|
+
const output = {
|
|
219
|
+
file: filePath,
|
|
220
|
+
lines: lines.map(({ line, attribution }) => ({
|
|
221
|
+
lineNumber: line.lineNumber,
|
|
222
|
+
sha: line.sha,
|
|
223
|
+
author: line.author,
|
|
224
|
+
date: line.authorTime.toISOString(),
|
|
225
|
+
content: line.content,
|
|
226
|
+
attribution: attribution
|
|
227
|
+
? {
|
|
228
|
+
category: attribution.category,
|
|
229
|
+
provider: attribution.provider,
|
|
230
|
+
model: attribution.model,
|
|
231
|
+
match_type: attribution.match_type,
|
|
232
|
+
content_hash: attribution.content_hash,
|
|
233
|
+
}
|
|
234
|
+
: null,
|
|
235
|
+
})),
|
|
236
|
+
summary: {
|
|
237
|
+
total: lines.length,
|
|
238
|
+
aiGenerated: lines.filter((l) => l.attribution?.category === "ai_generated").length,
|
|
239
|
+
human: lines.filter((l) => !l.attribution).length,
|
|
240
|
+
},
|
|
241
|
+
};
|
|
242
|
+
console.log(JSON.stringify(output, null, 2));
|
|
243
|
+
}
|
|
244
|
+
function formatDate(date) {
|
|
245
|
+
return date.toISOString().slice(0, 10);
|
|
246
|
+
}
|
|
247
|
+
function pct(n, total) {
|
|
248
|
+
if (total === 0)
|
|
249
|
+
return "0%";
|
|
250
|
+
return `${Math.round((n / total) * 100)}%`;
|
|
251
|
+
}
|
|
252
|
+
//# sourceMappingURL=blame.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"blame.js","sourceRoot":"","sources":["../src/blame.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
/**
|
|
3
|
+
* Agent Blame Hook Capture
|
|
4
|
+
*
|
|
5
|
+
* Captures AI-generated code from Cursor and Claude Code hooks.
|
|
6
|
+
* Performs line-level hashing for precise attribution matching.
|
|
7
|
+
*
|
|
8
|
+
* Usage:
|
|
9
|
+
* echo '{"payload": ...}' | bun run capture.ts --provider cursor --event afterFileEdit
|
|
10
|
+
* echo '{"payload": ...}' | bun run capture.ts --provider claude
|
|
11
|
+
*
|
|
12
|
+
* Note: We only track afterFileEdit (Composer/Agent mode).
|
|
13
|
+
* Tab completions (afterTabFileEdit) are NOT tracked because they fire
|
|
14
|
+
* as fragments that cannot be reliably matched to commits.
|
|
15
|
+
*/
|
|
16
|
+
export {};
|
package/dist/capture.js
ADDED
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
"use strict";
|
|
3
|
+
/**
|
|
4
|
+
* Agent Blame Hook Capture
|
|
5
|
+
*
|
|
6
|
+
* Captures AI-generated code from Cursor and Claude Code hooks.
|
|
7
|
+
* Performs line-level hashing for precise attribution matching.
|
|
8
|
+
*
|
|
9
|
+
* Usage:
|
|
10
|
+
* echo '{"payload": ...}' | bun run capture.ts --provider cursor --event afterFileEdit
|
|
11
|
+
* echo '{"payload": ...}' | bun run capture.ts --provider claude
|
|
12
|
+
*
|
|
13
|
+
* Note: We only track afterFileEdit (Composer/Agent mode).
|
|
14
|
+
* Tab completions (afterTabFileEdit) are NOT tracked because they fire
|
|
15
|
+
* as fragments that cannot be reliably matched to commits.
|
|
16
|
+
*/
|
|
17
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
18
|
+
if (k2 === undefined) k2 = k;
|
|
19
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
20
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
21
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
22
|
+
}
|
|
23
|
+
Object.defineProperty(o, k2, desc);
|
|
24
|
+
}) : (function(o, m, k, k2) {
|
|
25
|
+
if (k2 === undefined) k2 = k;
|
|
26
|
+
o[k2] = m[k];
|
|
27
|
+
}));
|
|
28
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
29
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
30
|
+
}) : function(o, v) {
|
|
31
|
+
o["default"] = v;
|
|
32
|
+
});
|
|
33
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
34
|
+
var ownKeys = function(o) {
|
|
35
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
36
|
+
var ar = [];
|
|
37
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
38
|
+
return ar;
|
|
39
|
+
};
|
|
40
|
+
return ownKeys(o);
|
|
41
|
+
};
|
|
42
|
+
return function (mod) {
|
|
43
|
+
if (mod && mod.__esModule) return mod;
|
|
44
|
+
var result = {};
|
|
45
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
46
|
+
__setModuleDefault(result, mod);
|
|
47
|
+
return result;
|
|
48
|
+
};
|
|
49
|
+
})();
|
|
50
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
51
|
+
const fs = __importStar(require("node:fs"));
|
|
52
|
+
const path = __importStar(require("node:path"));
|
|
53
|
+
const crypto = __importStar(require("node:crypto"));
|
|
54
|
+
const diff_1 = require("diff");
|
|
55
|
+
// =============================================================================
|
|
56
|
+
// Utilities
|
|
57
|
+
// =============================================================================
|
|
58
|
+
function getAgentBlameLogsDir() {
|
|
59
|
+
const home = process.env.HOME || process.env.USERPROFILE || "";
|
|
60
|
+
return path.join(home, ".agentblame", "logs");
|
|
61
|
+
}
|
|
62
|
+
function computeHash(content) {
|
|
63
|
+
return `sha256:${crypto.createHash("sha256").update(content).digest("hex")}`;
|
|
64
|
+
}
|
|
65
|
+
function computeNormalizedHash(content) {
|
|
66
|
+
const normalized = content.replace(/\s+/g, "");
|
|
67
|
+
return `sha256:${crypto.createHash("sha256").update(normalized).digest("hex")}`;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Extract only the added lines from a diff between old and new text.
|
|
71
|
+
*/
|
|
72
|
+
function extractAddedContent(oldText, newText) {
|
|
73
|
+
const parts = (0, diff_1.diffLines)(oldText ?? "", newText ?? "");
|
|
74
|
+
const addedParts = [];
|
|
75
|
+
for (const part of parts) {
|
|
76
|
+
if (part.added) {
|
|
77
|
+
addedParts.push(part.value ?? "");
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
return addedParts.join("");
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Determine the edit type based on old and new content
|
|
84
|
+
*/
|
|
85
|
+
function determineEditType(oldContent, newContent) {
|
|
86
|
+
if (!oldContent || oldContent.trim() === "") {
|
|
87
|
+
return "addition";
|
|
88
|
+
}
|
|
89
|
+
if (newContent.includes(oldContent)) {
|
|
90
|
+
return "modification"; // New content contains old content (added to it)
|
|
91
|
+
}
|
|
92
|
+
return "replacement"; // Old content was replaced
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Hash each line individually for precise matching
|
|
96
|
+
*/
|
|
97
|
+
function hashLines(content) {
|
|
98
|
+
const lines = content.split("\n");
|
|
99
|
+
const result = [];
|
|
100
|
+
for (const line of lines) {
|
|
101
|
+
// Skip empty lines for hashing purposes but keep them for content
|
|
102
|
+
if (!line.trim())
|
|
103
|
+
continue;
|
|
104
|
+
result.push({
|
|
105
|
+
content: line,
|
|
106
|
+
hash: computeHash(line),
|
|
107
|
+
hash_normalized: computeNormalizedHash(line),
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
return result;
|
|
111
|
+
}
|
|
112
|
+
// =============================================================================
|
|
113
|
+
// Payload Processing
|
|
114
|
+
// =============================================================================
|
|
115
|
+
function parseArgs() {
|
|
116
|
+
const args = process.argv.slice(2);
|
|
117
|
+
let provider = "cursor";
|
|
118
|
+
let event;
|
|
119
|
+
for (let i = 0; i < args.length; i++) {
|
|
120
|
+
if (args[i] === "--provider" && args[i + 1]) {
|
|
121
|
+
provider = args[i + 1];
|
|
122
|
+
i++;
|
|
123
|
+
}
|
|
124
|
+
else if (args[i] === "--event" && args[i + 1]) {
|
|
125
|
+
event = args[i + 1];
|
|
126
|
+
i++;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
return { provider, event };
|
|
130
|
+
}
|
|
131
|
+
function appendToLog(logFile, entry) {
|
|
132
|
+
const logsDir = getAgentBlameLogsDir();
|
|
133
|
+
fs.mkdirSync(logsDir, { recursive: true });
|
|
134
|
+
const logPath = path.join(logsDir, logFile);
|
|
135
|
+
const line = `${JSON.stringify(entry)}\n`;
|
|
136
|
+
fs.appendFileSync(logPath, line, "utf8");
|
|
137
|
+
}
|
|
138
|
+
function processCursorPayload(payload, event) {
|
|
139
|
+
const edits = [];
|
|
140
|
+
const timestamp = new Date().toISOString();
|
|
141
|
+
// Only process afterFileEdit (Composer/Agent mode)
|
|
142
|
+
// Skip afterTabFileEdit - tab completions fire as fragments that can't be matched
|
|
143
|
+
if (event === "afterTabFileEdit") {
|
|
144
|
+
return edits;
|
|
145
|
+
}
|
|
146
|
+
if (!payload.edits || payload.edits.length === 0) {
|
|
147
|
+
return edits;
|
|
148
|
+
}
|
|
149
|
+
for (const edit of payload.edits) {
|
|
150
|
+
const oldString = edit.old_string || "";
|
|
151
|
+
const newString = edit.new_string || "";
|
|
152
|
+
if (!newString)
|
|
153
|
+
continue;
|
|
154
|
+
// Extract only the added content
|
|
155
|
+
const addedContent = extractAddedContent(oldString, newString);
|
|
156
|
+
if (!addedContent.trim())
|
|
157
|
+
continue;
|
|
158
|
+
// Hash each line individually
|
|
159
|
+
const lines = hashLines(addedContent);
|
|
160
|
+
if (lines.length === 0)
|
|
161
|
+
continue;
|
|
162
|
+
edits.push({
|
|
163
|
+
timestamp,
|
|
164
|
+
provider: "cursor",
|
|
165
|
+
file_path: payload.file_path,
|
|
166
|
+
model: payload.model || null,
|
|
167
|
+
// Line-level data
|
|
168
|
+
lines,
|
|
169
|
+
// Aggregate data
|
|
170
|
+
content: addedContent,
|
|
171
|
+
content_hash: computeHash(addedContent),
|
|
172
|
+
content_hash_normalized: computeNormalizedHash(addedContent),
|
|
173
|
+
// Edit context
|
|
174
|
+
edit_type: determineEditType(oldString, newString),
|
|
175
|
+
old_content: oldString || undefined,
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
return edits;
|
|
179
|
+
}
|
|
180
|
+
function processClaudePayload(payload) {
|
|
181
|
+
const edits = [];
|
|
182
|
+
const timestamp = new Date().toISOString();
|
|
183
|
+
// Claude Code has tool_input with the actual content, or it may be at top level
|
|
184
|
+
const toolInput = payload.tool_input;
|
|
185
|
+
const filePath = toolInput?.file_path || payload.file_path;
|
|
186
|
+
if (!filePath)
|
|
187
|
+
return edits;
|
|
188
|
+
// Get content from tool_input or top-level payload
|
|
189
|
+
const content = toolInput?.content || payload.content;
|
|
190
|
+
const oldString = toolInput?.old_string || payload.old_string || "";
|
|
191
|
+
const newString = toolInput?.new_string || payload.new_string || "";
|
|
192
|
+
// Handle Write tool (new file, content only)
|
|
193
|
+
if (content && !oldString && !newString) {
|
|
194
|
+
if (!content.trim())
|
|
195
|
+
return edits;
|
|
196
|
+
const lines = hashLines(content);
|
|
197
|
+
if (lines.length === 0)
|
|
198
|
+
return edits;
|
|
199
|
+
edits.push({
|
|
200
|
+
timestamp,
|
|
201
|
+
provider: "claude_code",
|
|
202
|
+
file_path: filePath,
|
|
203
|
+
model: "claude",
|
|
204
|
+
// Line-level data
|
|
205
|
+
lines,
|
|
206
|
+
// Aggregate data
|
|
207
|
+
content: content,
|
|
208
|
+
content_hash: computeHash(content),
|
|
209
|
+
content_hash_normalized: computeNormalizedHash(content),
|
|
210
|
+
// Edit context
|
|
211
|
+
edit_type: "addition",
|
|
212
|
+
});
|
|
213
|
+
return edits;
|
|
214
|
+
}
|
|
215
|
+
// Handle Edit tool (old_string -> new_string)
|
|
216
|
+
if (!newString)
|
|
217
|
+
return edits;
|
|
218
|
+
const addedContent = extractAddedContent(oldString, newString);
|
|
219
|
+
if (!addedContent.trim())
|
|
220
|
+
return edits;
|
|
221
|
+
const lines = hashLines(addedContent);
|
|
222
|
+
if (lines.length === 0)
|
|
223
|
+
return edits;
|
|
224
|
+
edits.push({
|
|
225
|
+
timestamp,
|
|
226
|
+
provider: "claude_code",
|
|
227
|
+
file_path: filePath,
|
|
228
|
+
model: "claude",
|
|
229
|
+
// Line-level data
|
|
230
|
+
lines,
|
|
231
|
+
// Aggregate data
|
|
232
|
+
content: addedContent,
|
|
233
|
+
content_hash: computeHash(addedContent),
|
|
234
|
+
content_hash_normalized: computeNormalizedHash(addedContent),
|
|
235
|
+
// Edit context
|
|
236
|
+
edit_type: determineEditType(oldString, newString),
|
|
237
|
+
old_content: oldString || undefined,
|
|
238
|
+
});
|
|
239
|
+
return edits;
|
|
240
|
+
}
|
|
241
|
+
// =============================================================================
|
|
242
|
+
// Main
|
|
243
|
+
// =============================================================================
|
|
244
|
+
async function readStdin() {
|
|
245
|
+
const chunks = [];
|
|
246
|
+
for await (const chunk of process.stdin) {
|
|
247
|
+
chunks.push(chunk);
|
|
248
|
+
}
|
|
249
|
+
return Buffer.concat(chunks).toString("utf8");
|
|
250
|
+
}
|
|
251
|
+
async function main() {
|
|
252
|
+
try {
|
|
253
|
+
const { provider, event } = parseArgs();
|
|
254
|
+
const input = await readStdin();
|
|
255
|
+
if (!input.trim()) {
|
|
256
|
+
process.exit(0);
|
|
257
|
+
}
|
|
258
|
+
const data = JSON.parse(input);
|
|
259
|
+
// The hook receives the payload directly or wrapped
|
|
260
|
+
const payload = data.payload || data;
|
|
261
|
+
let edits = [];
|
|
262
|
+
if (provider === "cursor") {
|
|
263
|
+
const eventName = event || data.hook_event_name || "afterFileEdit";
|
|
264
|
+
edits = processCursorPayload(payload, eventName);
|
|
265
|
+
for (const edit of edits) {
|
|
266
|
+
appendToLog("cursor-generated.log", edit);
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
else if (provider === "claude") {
|
|
270
|
+
edits = processClaudePayload(payload);
|
|
271
|
+
for (const edit of edits) {
|
|
272
|
+
appendToLog("claude-generated.log", edit);
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
process.exit(0);
|
|
276
|
+
}
|
|
277
|
+
catch (err) {
|
|
278
|
+
// Silent failure - don't interrupt the editor
|
|
279
|
+
console.error("Agent Blame capture error:", err);
|
|
280
|
+
process.exit(0);
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
main();
|
|
284
|
+
//# sourceMappingURL=capture.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"capture.js","sourceRoot":"","sources":["../src/capture.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
/**
|
|
3
|
+
* Agent Blame Cleanup Script
|
|
4
|
+
*
|
|
5
|
+
* Removes all Agent Blame data and hook configurations:
|
|
6
|
+
* - ~/.agentblame directory (logs, hooks)
|
|
7
|
+
* - Agent Blame entries from ~/.cursor/hooks.json
|
|
8
|
+
* - Agent Blame entries from ~/.claude/settings.json
|
|
9
|
+
*/
|
|
10
|
+
export {};
|