codiedev 0.9.6-beta.0 → 0.9.7-beta.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/hook.js +6 -0
- package/dist/utils.d.ts +4 -0
- package/dist/utils.js +91 -0
- package/package.json +1 -1
package/dist/hook.js
CHANGED
|
@@ -252,6 +252,10 @@ async function main() {
|
|
|
252
252
|
? { messageCount: 0, toolCallCount: 0 }
|
|
253
253
|
: (0, utils_1.parseClaudeCodeStats)(transcriptContent);
|
|
254
254
|
const transcriptBase64 = Buffer.from(transcriptContent, "utf8").toString("base64");
|
|
255
|
+
// Session→merge join keys: the branch + HEAD sha the work happened on. Matched
|
|
256
|
+
// server-side against a merged MR/PR's source_branch / commits for AI attribution.
|
|
257
|
+
const branch = (0, utils_1.getGitBranch)(workspaceRoot);
|
|
258
|
+
const headSha = (0, utils_1.getGitHeadSha)(workspaceRoot);
|
|
255
259
|
const payload = (0, utils_1.buildCapturePayload)({
|
|
256
260
|
sessionId: session_id,
|
|
257
261
|
transcriptBase64,
|
|
@@ -262,6 +266,8 @@ async function main() {
|
|
|
262
266
|
toolCallCount: stats.toolCallCount,
|
|
263
267
|
capturedAt: Date.now(),
|
|
264
268
|
source: mode,
|
|
269
|
+
branch,
|
|
270
|
+
headSha,
|
|
265
271
|
});
|
|
266
272
|
// Fire the upload from a fully detached child and exit immediately. Awaiting
|
|
267
273
|
// it inline let Claude Code's SessionEnd shutdown window elapse and kill the
|
package/dist/utils.d.ts
CHANGED
|
@@ -27,6 +27,8 @@ export declare function matchRepo(remoteUrl: string, repos: Array<{
|
|
|
27
27
|
url: string;
|
|
28
28
|
fullName: string;
|
|
29
29
|
} | null;
|
|
30
|
+
export declare function getGitBranch(cwd: string): string | null;
|
|
31
|
+
export declare function getGitHeadSha(cwd: string): string | null;
|
|
30
32
|
export interface CapturePayloadInput {
|
|
31
33
|
sessionId?: string;
|
|
32
34
|
transcriptBase64: string;
|
|
@@ -37,6 +39,8 @@ export interface CapturePayloadInput {
|
|
|
37
39
|
toolCallCount: number;
|
|
38
40
|
capturedAt: number;
|
|
39
41
|
source: string;
|
|
42
|
+
branch?: string | null;
|
|
43
|
+
headSha?: string | null;
|
|
40
44
|
}
|
|
41
45
|
export declare function buildCapturePayload(input: CapturePayloadInput): Record<string, unknown>;
|
|
42
46
|
export declare function hashToken(token: string): string;
|
package/dist/utils.js
CHANGED
|
@@ -40,6 +40,8 @@ exports.readGitRemoteFromConfig = readGitRemoteFromConfig;
|
|
|
40
40
|
exports.getGitRemoteUrl = getGitRemoteUrl;
|
|
41
41
|
exports.normalizeRepoUrl = normalizeRepoUrl;
|
|
42
42
|
exports.matchRepo = matchRepo;
|
|
43
|
+
exports.getGitBranch = getGitBranch;
|
|
44
|
+
exports.getGitHeadSha = getGitHeadSha;
|
|
43
45
|
exports.buildCapturePayload = buildCapturePayload;
|
|
44
46
|
exports.hashToken = hashToken;
|
|
45
47
|
exports.claudeCodeInstalled = claudeCodeInstalled;
|
|
@@ -247,12 +249,101 @@ function matchRepo(remoteUrl, repos) {
|
|
|
247
249
|
}
|
|
248
250
|
return null;
|
|
249
251
|
}
|
|
252
|
+
// Current branch via direct .git/HEAD read (no git binary required, same
|
|
253
|
+
// robustness as getGitRemoteUrl). Returns null on detached HEAD or when
|
|
254
|
+
// unresolvable. This is the session→merge join key: a captured session's
|
|
255
|
+
// branch is matched against a merged MR/PR's source_branch.
|
|
256
|
+
function getGitBranch(cwd) {
|
|
257
|
+
const gitDir = resolveGitDir(cwd);
|
|
258
|
+
if (gitDir) {
|
|
259
|
+
try {
|
|
260
|
+
const head = fs.readFileSync(path.join(gitDir, "HEAD"), "utf8").trim();
|
|
261
|
+
const m = head.match(/^ref:\s*refs\/heads\/(.+)$/);
|
|
262
|
+
if (m)
|
|
263
|
+
return m[1].trim();
|
|
264
|
+
// raw sha => detached HEAD, no branch
|
|
265
|
+
}
|
|
266
|
+
catch {
|
|
267
|
+
// fall through to git
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
try {
|
|
271
|
+
const b = (0, child_process_1.execSync)("git rev-parse --abbrev-ref HEAD", {
|
|
272
|
+
cwd,
|
|
273
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
274
|
+
})
|
|
275
|
+
.toString()
|
|
276
|
+
.trim();
|
|
277
|
+
return b && b !== "HEAD" ? b : null;
|
|
278
|
+
}
|
|
279
|
+
catch {
|
|
280
|
+
return null;
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
// Current commit SHA (HEAD), direct-read first then git fallback. Exact join
|
|
284
|
+
// key — survives branch renames that branch-matching would miss.
|
|
285
|
+
function getGitHeadSha(cwd) {
|
|
286
|
+
const gitDir = resolveGitDir(cwd);
|
|
287
|
+
if (gitDir) {
|
|
288
|
+
try {
|
|
289
|
+
const head = fs.readFileSync(path.join(gitDir, "HEAD"), "utf8").trim();
|
|
290
|
+
if (/^[0-9a-f]{40}$/i.test(head))
|
|
291
|
+
return head.toLowerCase();
|
|
292
|
+
const m = head.match(/^ref:\s*(.+)$/);
|
|
293
|
+
if (m) {
|
|
294
|
+
const ref = m[1].trim();
|
|
295
|
+
for (const cfg of gitConfigCandidates(gitDir)) {
|
|
296
|
+
const baseDir = path.dirname(cfg);
|
|
297
|
+
try {
|
|
298
|
+
const sha = fs.readFileSync(path.join(baseDir, ref), "utf8").trim();
|
|
299
|
+
if (/^[0-9a-f]{40}$/i.test(sha))
|
|
300
|
+
return sha.toLowerCase();
|
|
301
|
+
}
|
|
302
|
+
catch {
|
|
303
|
+
/* try packed-refs */
|
|
304
|
+
}
|
|
305
|
+
try {
|
|
306
|
+
const packed = fs.readFileSync(path.join(baseDir, "packed-refs"), "utf8");
|
|
307
|
+
const line = packed
|
|
308
|
+
.split("\n")
|
|
309
|
+
.find((l) => l.endsWith(" " + ref));
|
|
310
|
+
if (line) {
|
|
311
|
+
const sha = line.split(" ")[0].trim();
|
|
312
|
+
if (/^[0-9a-f]{40}$/i.test(sha))
|
|
313
|
+
return sha.toLowerCase();
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
catch {
|
|
317
|
+
/* ignore */
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
catch {
|
|
323
|
+
// fall through to git
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
try {
|
|
327
|
+
const sha = (0, child_process_1.execSync)("git rev-parse HEAD", {
|
|
328
|
+
cwd,
|
|
329
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
330
|
+
})
|
|
331
|
+
.toString()
|
|
332
|
+
.trim();
|
|
333
|
+
return /^[0-9a-f]{40}$/i.test(sha) ? sha.toLowerCase() : null;
|
|
334
|
+
}
|
|
335
|
+
catch {
|
|
336
|
+
return null;
|
|
337
|
+
}
|
|
338
|
+
}
|
|
250
339
|
function buildCapturePayload(input) {
|
|
251
340
|
return {
|
|
252
341
|
sessionId: input.sessionId,
|
|
253
342
|
repoUrl: input.remoteUrl ?? "",
|
|
254
343
|
repoId: input.matchedRepoId,
|
|
255
344
|
companyId: input.companyId,
|
|
345
|
+
branch: input.branch ?? "",
|
|
346
|
+
headSha: input.headSha ?? "",
|
|
256
347
|
transcript: input.transcriptBase64,
|
|
257
348
|
messageCount: input.messageCount,
|
|
258
349
|
toolCallCount: input.toolCallCount,
|
package/package.json
CHANGED