agent-insights 0.0.18 → 0.0.20

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/cli.js CHANGED
@@ -817,6 +817,7 @@ function asString(v) {
817
817
  }
818
818
 
819
819
  // src/adapters/codex.ts
820
+ import { readdirSync } from "fs";
820
821
  import { mkdir as mkdir3, readFile as readFile3, writeFile as writeFile3 } from "fs/promises";
821
822
  import { homedir as homedir3 } from "os";
822
823
  import { dirname as dirname3, join as join3 } from "path";
@@ -841,7 +842,7 @@ var codexAdapter = {
841
842
  const data = payload.data ?? {};
842
843
  const sessionId = asString2(data["session_id"]) ?? asString2(data["sessionId"]);
843
844
  const toolName = asString2(data["tool_name"]) ?? asString2(data["toolName"]) ?? asString2(data["tool"]?.["name"]);
844
- const transcriptPath = asString2(data["transcript_path"]) ?? asString2(data["transcriptPath"]);
845
+ const transcriptPath = asString2(data["transcript_path"]) ?? asString2(data["transcriptPath"]) ?? (type === "session.end" && sessionId ? findCodexTranscript(sessionId, defaultSessionsRoot()) : void 0);
845
846
  return {
846
847
  type,
847
848
  ...sessionId !== void 0 ? { sessionId } : {},
@@ -966,6 +967,49 @@ async function readJson2(path) {
966
967
  function asString2(v) {
967
968
  return typeof v === "string" && v.length > 0 ? v : void 0;
968
969
  }
970
+ function defaultSessionsRoot() {
971
+ return join3(homedir3(), ".codex", "sessions");
972
+ }
973
+ function findCodexTranscript(sessionId, root) {
974
+ const suffix = `-${sessionId}.jsonl`;
975
+ const MAX_DAYS = 7;
976
+ let scanned = 0;
977
+ let years;
978
+ try {
979
+ years = readdirSync(root).filter((s) => /^\d{4}$/.test(s)).sort().reverse();
980
+ } catch {
981
+ return void 0;
982
+ }
983
+ for (const y of years) {
984
+ let months;
985
+ try {
986
+ months = readdirSync(join3(root, y)).filter((s) => /^\d{2}$/.test(s)).sort().reverse();
987
+ } catch {
988
+ continue;
989
+ }
990
+ for (const m of months) {
991
+ let days;
992
+ try {
993
+ days = readdirSync(join3(root, y, m)).filter((s) => /^\d{2}$/.test(s)).sort().reverse();
994
+ } catch {
995
+ continue;
996
+ }
997
+ for (const d of days) {
998
+ if (++scanned > MAX_DAYS) return void 0;
999
+ const dir = join3(root, y, m, d);
1000
+ let files;
1001
+ try {
1002
+ files = readdirSync(dir);
1003
+ } catch {
1004
+ continue;
1005
+ }
1006
+ const match = files.find((f) => f.endsWith(suffix));
1007
+ if (match) return join3(dir, match);
1008
+ }
1009
+ }
1010
+ }
1011
+ return void 0;
1012
+ }
969
1013
 
970
1014
  // src/adapters/cursor.ts
971
1015
  import { mkdir as mkdir4, readFile as readFile4, writeFile as writeFile4 } from "fs/promises";
@@ -1211,11 +1255,18 @@ var adapterList = Object.values(adapters);
1211
1255
 
1212
1256
  // src/commands/disable.ts
1213
1257
  init_paths();
1258
+ var CONFIG_KEY_BY_ID = {
1259
+ "claude-code": "claudeCode",
1260
+ cursor: "cursor",
1261
+ codex: "codex",
1262
+ pi: "pi"
1263
+ };
1214
1264
  async function runDisable(opts) {
1215
1265
  const repoRoot = process.cwd();
1266
+ const knownIds = new Set(adapterList.map((a) => a.id));
1216
1267
  const targets = opts.agent ? [opts.agent] : adapterList.map((a) => a.id);
1217
1268
  for (const id of targets) {
1218
- if (id !== "claude-code" && id !== "cursor") {
1269
+ if (!knownIds.has(id)) {
1219
1270
  log.warn(`Unknown agent id "${id}"`);
1220
1271
  continue;
1221
1272
  }
@@ -1227,11 +1278,9 @@ async function runDisable(opts) {
1227
1278
  }
1228
1279
  const cfg = await loadConfig();
1229
1280
  if (cfg) {
1230
- if (!opts.agent || opts.agent === "claude-code") {
1231
- cfg.agents.claudeCode.enabled = false;
1232
- }
1233
- if (!opts.agent || opts.agent === "cursor") {
1234
- cfg.agents.cursor.enabled = false;
1281
+ for (const id of targets) {
1282
+ const key = CONFIG_KEY_BY_ID[id];
1283
+ if (key) cfg.agents[key].enabled = false;
1235
1284
  }
1236
1285
  if (!opts.agent) cfg.enabled = false;
1237
1286
  await saveConfig(cfg);
@@ -1347,7 +1396,10 @@ var AnalyzerTranscriptStore = class {
1347
1396
  "x-session-id": input.sessionId,
1348
1397
  "x-agent": input.agent,
1349
1398
  "x-user-hash": input.userHash,
1350
- ...input.userEmail ? { "x-user-email": input.userEmail } : {}
1399
+ ...input.userEmail ? { "x-user-email": input.userEmail } : {},
1400
+ ...input.gitInfo?.repoName ? { "x-git-repo-name": input.gitInfo.repoName } : {},
1401
+ ...input.gitInfo?.branch ? { "x-git-branch": input.gitInfo.branch } : {},
1402
+ ...input.gitInfo?.commitSha ? { "x-git-commit-sha": input.gitInfo.commitSha } : {}
1351
1403
  });
1352
1404
  const res = await fetch(url, { method: "POST", headers, body });
1353
1405
  if (!res.ok) {
@@ -1482,6 +1534,40 @@ async function runDoctor(opts) {
1482
1534
 
1483
1535
  // src/commands/hook.ts
1484
1536
  init_store();
1537
+
1538
+ // src/util/git-info.ts
1539
+ import { execSync as execSync2 } from "child_process";
1540
+ import { basename } from "path";
1541
+ function readGitInfo(cwd) {
1542
+ let raw;
1543
+ try {
1544
+ raw = execSync2("git rev-parse HEAD --show-toplevel", {
1545
+ cwd,
1546
+ stdio: ["ignore", "pipe", "ignore"],
1547
+ timeout: 1500
1548
+ }).toString("utf8");
1549
+ } catch {
1550
+ return void 0;
1551
+ }
1552
+ const [commitSha, top] = raw.split("\n").map((s) => s.trim());
1553
+ if (!top) return void 0;
1554
+ let branch;
1555
+ try {
1556
+ const out = execSync2("git rev-parse --abbrev-ref HEAD", {
1557
+ cwd,
1558
+ stdio: ["ignore", "pipe", "ignore"],
1559
+ timeout: 1500
1560
+ }).toString("utf8").trim();
1561
+ if (out && out !== "HEAD") branch = out;
1562
+ } catch {
1563
+ }
1564
+ const info = { repoName: basename(top) };
1565
+ if (branch) info.branch = branch;
1566
+ if (commitSha) info.commitSha = commitSha;
1567
+ return info;
1568
+ }
1569
+
1570
+ // src/commands/hook.ts
1485
1571
  async function runHook(eventName, opts) {
1486
1572
  const cfg = await loadConfig();
1487
1573
  if (!cfg || !cfg.enabled) {
@@ -1511,12 +1597,15 @@ async function runHook(eventName, opts) {
1511
1597
  try {
1512
1598
  const store = createTranscriptStore(cfg.transcriptStore);
1513
1599
  const userEmail = await loadEmail();
1600
+ const cwd = (typeof data?.["cwd"] === "string" ? data["cwd"] : void 0) ?? process.cwd();
1601
+ const gitInfo = readGitInfo(cwd);
1514
1602
  const result = await store.upload({
1515
1603
  transcriptPath: mapped.transcriptPath,
1516
1604
  userHash: event.userHash ?? userHash(),
1517
1605
  sessionId: mapped.sessionId ?? "unknown",
1518
1606
  agent: adapter.id,
1519
- ...userEmail ? { userEmail } : {}
1607
+ ...userEmail ? { userEmail } : {},
1608
+ ...gitInfo ? { gitInfo } : {}
1520
1609
  });
1521
1610
  debug("transcript uploaded", {
1522
1611
  size: result.size,
@@ -1953,7 +2042,7 @@ function yn(v) {
1953
2042
  var program = new Command();
1954
2043
  program.name("agent-insights").description(
1955
2044
  "Internal CLI for AI coding agent observability (Claude Code, Cursor)."
1956
- ).version("0.0.18");
2045
+ ).version("0.0.20");
1957
2046
  program.command("login").description("Authenticate with Vercel (Sign in with Vercel).").action(async () => {
1958
2047
  await runLogin();
1959
2048
  });