@yhong91/vibetime 0.1.17 → 0.1.18

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.
Files changed (2) hide show
  1. package/bin/vibetime.mjs +582 -275
  2. package/package.json +1 -1
package/bin/vibetime.mjs CHANGED
@@ -158,11 +158,11 @@ var init_fs = __esm({
158
158
  });
159
159
 
160
160
  // src/cli.ts
161
- import { spawn, spawnSync } from "node:child_process";
161
+ import { spawn as spawn2, spawnSync } from "node:child_process";
162
162
  import { randomUUID as randomUUID2 } from "node:crypto";
163
- import { mkdir as mkdir5, rename as rename2, rm, stat as stat11, writeFile as writeFile4 } from "node:fs/promises";
163
+ import { mkdir as mkdir5, open, rename as rename2, rm, stat as stat12, writeFile as writeFile4 } from "node:fs/promises";
164
164
  import os9 from "node:os";
165
- import path20 from "node:path";
165
+ import path21 from "node:path";
166
166
  import { fileURLToPath } from "node:url";
167
167
 
168
168
  // ../shared/src/index.ts
@@ -296,6 +296,12 @@ function validateMetricBag(value, errors, prefix) {
296
296
  }
297
297
  for (const key of Object.keys(value)) {
298
298
  const metric = value[key];
299
+ if (key === "reasoningEffort") {
300
+ if (metric !== void 0 && typeof metric !== "string") {
301
+ errors.push(`${prefix}.${key} must be a string`);
302
+ }
303
+ continue;
304
+ }
299
305
  if (metric !== void 0 && (typeof metric !== "number" || !Number.isFinite(metric))) {
300
306
  errors.push(`${prefix}.${key} must be a finite number`);
301
307
  }
@@ -978,10 +984,10 @@ var cac = (name = "") => new CAC(name);
978
984
 
979
985
  // src/adapters/agy.ts
980
986
  import { exec } from "node:child_process";
981
- import { readFile as readFile2, stat as stat2, mkdir as mkdir2, writeFile as writeFile2 } from "node:fs/promises";
987
+ import { mkdir as mkdir2, readFile as readFile2, stat as stat3, writeFile as writeFile2 } from "node:fs/promises";
982
988
  import * as https from "node:https";
983
989
  import * as os from "node:os";
984
- import path4 from "node:path";
990
+ import path5 from "node:path";
985
991
  import { promisify } from "node:util";
986
992
 
987
993
  // src/lib/activity.ts
@@ -1196,7 +1202,7 @@ function countTextLines(text) {
1196
1202
  }
1197
1203
 
1198
1204
  // src/lib/constants.ts
1199
- var PACKAGE_VERSION = true ? "0.1.17" : "0.1.1";
1205
+ var PACKAGE_VERSION = true ? "0.1.18" : "0.1.1";
1200
1206
  var DEFAULT_API_URL = "http://121.196.224.82:3001";
1201
1207
  var DEFAULT_BACKFILL_BATCH_SIZE = 50;
1202
1208
  var DEFAULT_BACKFILL_BATCH_BYTES = 800 * 1024;
@@ -1433,6 +1439,254 @@ var SessionParserState = class {
1433
1439
  }
1434
1440
  };
1435
1441
 
1442
+ // src/adapters/agy-legacy-db.ts
1443
+ import { spawn } from "node:child_process";
1444
+ import { stat as stat2 } from "node:fs/promises";
1445
+ import path4 from "node:path";
1446
+ function readVarint(buffer, offset) {
1447
+ let value = 0n;
1448
+ let shift = 0n;
1449
+ let cursor = offset;
1450
+ while (cursor < buffer.length && shift <= 63n) {
1451
+ const byte = buffer[cursor++];
1452
+ value |= BigInt(byte & 127) << shift;
1453
+ if ((byte & 128) === 0) {
1454
+ return { value, offset: cursor };
1455
+ }
1456
+ shift += 7n;
1457
+ }
1458
+ throw new TypeError("invalid protobuf varint");
1459
+ }
1460
+ function decodeFields(buffer) {
1461
+ const fields = [];
1462
+ let offset = 0;
1463
+ while (offset < buffer.length) {
1464
+ const key = readVarint(buffer, offset);
1465
+ offset = key.offset;
1466
+ const keyNumber = Number(key.value);
1467
+ if (!Number.isSafeInteger(keyNumber)) {
1468
+ throw new TypeError("protobuf key exceeds safe integer range");
1469
+ }
1470
+ const field = keyNumber >>> 3;
1471
+ const wire = keyNumber & 7;
1472
+ if (field === 0) {
1473
+ throw new Error("invalid protobuf field");
1474
+ }
1475
+ switch (wire) {
1476
+ case 0: {
1477
+ const decoded = readVarint(buffer, offset);
1478
+ offset = decoded.offset;
1479
+ fields.push({ field, wire, value: decoded.value });
1480
+ break;
1481
+ }
1482
+ case 1: {
1483
+ if (offset + 8 > buffer.length) {
1484
+ throw new TypeError("truncated protobuf fixed64");
1485
+ }
1486
+ fields.push({ field, wire, value: buffer.subarray(offset, offset + 8) });
1487
+ offset += 8;
1488
+ break;
1489
+ }
1490
+ case 2: {
1491
+ const decoded = readVarint(buffer, offset);
1492
+ offset = decoded.offset;
1493
+ const length = Number(decoded.value);
1494
+ if (!Number.isSafeInteger(length)) {
1495
+ throw new TypeError("protobuf byte length exceeds safe integer range");
1496
+ }
1497
+ const end = offset + length;
1498
+ if (end > buffer.length) {
1499
+ throw new TypeError("truncated protobuf bytes");
1500
+ }
1501
+ fields.push({ field, wire, value: buffer.subarray(offset, end) });
1502
+ offset = end;
1503
+ break;
1504
+ }
1505
+ case 5: {
1506
+ if (offset + 4 > buffer.length) {
1507
+ throw new TypeError("truncated protobuf fixed32");
1508
+ }
1509
+ fields.push({ field, wire, value: buffer.subarray(offset, offset + 4) });
1510
+ offset += 4;
1511
+ break;
1512
+ }
1513
+ default: {
1514
+ throw new TypeError(`unsupported protobuf wire type ${wire}`);
1515
+ }
1516
+ }
1517
+ }
1518
+ return fields;
1519
+ }
1520
+ function bytesField(fields, field) {
1521
+ const value = fields.find((item) => item.field === field && item.wire === 2)?.value;
1522
+ return value instanceof Uint8Array ? value : void 0;
1523
+ }
1524
+ function numberField2(fields, field) {
1525
+ const value = fields.find((item) => item.field === field && item.wire === 0)?.value;
1526
+ if (typeof value !== "bigint") {
1527
+ return void 0;
1528
+ }
1529
+ const number = Number(value);
1530
+ return Number.isSafeInteger(number) ? number : void 0;
1531
+ }
1532
+ function stringField2(fields, field) {
1533
+ const value = bytesField(fields, field);
1534
+ if (!value) {
1535
+ return void 0;
1536
+ }
1537
+ return new TextDecoder().decode(value);
1538
+ }
1539
+ function decodePackedVarints(buffer) {
1540
+ if (!buffer) {
1541
+ return [];
1542
+ }
1543
+ const values = [];
1544
+ let offset = 0;
1545
+ while (offset < buffer.length) {
1546
+ const decoded = readVarint(buffer, offset);
1547
+ const value = Number(decoded.value);
1548
+ if (!Number.isSafeInteger(value)) {
1549
+ throw new TypeError("packed protobuf varint exceeds safe integer range");
1550
+ }
1551
+ values.push(value);
1552
+ offset = decoded.offset;
1553
+ }
1554
+ return values;
1555
+ }
1556
+ function decodeTimestamp(buffer) {
1557
+ if (!buffer) {
1558
+ return void 0;
1559
+ }
1560
+ const fields = decodeFields(buffer);
1561
+ const seconds = numberField2(fields, 1);
1562
+ if (seconds === void 0) {
1563
+ return void 0;
1564
+ }
1565
+ const nanos = numberField2(fields, 2) ?? 0;
1566
+ const date = new Date(seconds * 1e3 + Math.floor(nanos / 1e6));
1567
+ return Number.isNaN(date.getTime()) ? void 0 : date.toISOString();
1568
+ }
1569
+ function decodeLegacyAgyGeneratorMetadata(data) {
1570
+ try {
1571
+ const fields = decodeFields(data);
1572
+ const stepIndices = decodePackedVarints(bytesField(fields, 2));
1573
+ const chatModelBytes = bytesField(fields, 1);
1574
+ if (stepIndices.length === 0 || !chatModelBytes) {
1575
+ return null;
1576
+ }
1577
+ const chatModelFields = decodeFields(chatModelBytes);
1578
+ const usageBytes = bytesField(chatModelFields, 4);
1579
+ if (!usageBytes) {
1580
+ return null;
1581
+ }
1582
+ const usageFields = decodeFields(usageBytes);
1583
+ const inputTokens = numberField2(usageFields, 2);
1584
+ const outputTokens = numberField2(usageFields, 3);
1585
+ if (inputTokens === void 0 || outputTokens === void 0) {
1586
+ return null;
1587
+ }
1588
+ const cacheReadTokens = numberField2(usageFields, 5);
1589
+ const thinkingOutputTokens = numberField2(usageFields, 9);
1590
+ const createdAt = decodeTimestamp(bytesField(
1591
+ decodeFields(bytesField(chatModelFields, 9) ?? new Uint8Array()),
1592
+ 4
1593
+ ));
1594
+ const modelDisplayName = stringField2(chatModelFields, 21);
1595
+ const responseModel = stringField2(chatModelFields, 19);
1596
+ return {
1597
+ stepIndices,
1598
+ chatModel: {
1599
+ usage: {
1600
+ inputTokens: String(inputTokens),
1601
+ outputTokens: String(outputTokens),
1602
+ ...cacheReadTokens === void 0 ? {} : { cacheReadTokens: String(cacheReadTokens) },
1603
+ ...thinkingOutputTokens === void 0 ? {} : { thinkingOutputTokens: String(thinkingOutputTokens) }
1604
+ },
1605
+ ...modelDisplayName ? { modelDisplayName } : {},
1606
+ ...responseModel ? { responseModel } : {},
1607
+ ...createdAt ? { chatStartMetadata: { createdAt } } : {}
1608
+ }
1609
+ };
1610
+ } catch {
1611
+ return null;
1612
+ }
1613
+ }
1614
+ async function readRowsWithNodeSqlite(dbPath) {
1615
+ try {
1616
+ const sqlite = await import("node:sqlite");
1617
+ const db = new sqlite.DatabaseSync(dbPath, { readOnly: true });
1618
+ try {
1619
+ return db.prepare("SELECT data FROM gen_metadata ORDER BY idx").all().map(
1620
+ (row) => ({ data: row.data })
1621
+ );
1622
+ } finally {
1623
+ db.close();
1624
+ }
1625
+ } catch {
1626
+ return null;
1627
+ }
1628
+ }
1629
+ async function readRowsWithSqliteCli(dbPath) {
1630
+ return new Promise((resolve) => {
1631
+ const child = spawn("sqlite3", [
1632
+ "-readonly",
1633
+ dbPath,
1634
+ "SELECT hex(data) FROM gen_metadata ORDER BY idx;"
1635
+ ], {
1636
+ stdio: ["ignore", "pipe", "ignore"]
1637
+ });
1638
+ const rows = [];
1639
+ let pending = "";
1640
+ let failed = false;
1641
+ child.stdout.setEncoding("utf8");
1642
+ child.stdout.on("data", (chunk) => {
1643
+ pending += chunk;
1644
+ let newline = pending.indexOf("\n");
1645
+ while (newline >= 0) {
1646
+ const line = pending.slice(0, newline).trim();
1647
+ pending = pending.slice(newline + 1);
1648
+ if (line) {
1649
+ try {
1650
+ rows.push({ data: Buffer.from(line, "hex") });
1651
+ } catch {
1652
+ failed = true;
1653
+ child.kill();
1654
+ return;
1655
+ }
1656
+ }
1657
+ newline = pending.indexOf("\n");
1658
+ }
1659
+ });
1660
+ child.on("error", () => resolve(null));
1661
+ child.on("close", (code) => {
1662
+ if (!failed && code === 0) {
1663
+ const line = pending.trim();
1664
+ if (line) {
1665
+ rows.push({ data: Buffer.from(line, "hex") });
1666
+ }
1667
+ resolve(rows);
1668
+ } else {
1669
+ resolve(null);
1670
+ }
1671
+ });
1672
+ });
1673
+ }
1674
+ async function readLegacyAgyGeneratorMetadata(transcriptPath, sessionId) {
1675
+ const antigravityCliDir = path4.resolve(path4.dirname(transcriptPath), "../../../..");
1676
+ const dbPath = path4.join(antigravityCliDir, "conversations", `${sessionId}.db`);
1677
+ try {
1678
+ await stat2(dbPath);
1679
+ } catch {
1680
+ return null;
1681
+ }
1682
+ const rows = await readRowsWithNodeSqlite(dbPath) ?? await readRowsWithSqliteCli(dbPath);
1683
+ if (!rows || rows.length === 0) {
1684
+ return null;
1685
+ }
1686
+ const metadata = rows.map((row) => decodeLegacyAgyGeneratorMetadata(row.data)).filter((item) => item !== null);
1687
+ return metadata.length > 0 ? metadata : null;
1688
+ }
1689
+
1436
1690
  // src/adapters/agy.ts
1437
1691
  var execAsync = promisify(exec);
1438
1692
  var cachedRpcConnections = null;
@@ -1652,7 +1906,7 @@ function detectModel(content, currentModel) {
1652
1906
  return currentModel;
1653
1907
  }
1654
1908
  function resolveModelName(text) {
1655
- const cleaned = text.replace(/\s*\([^)]*\)\s*/g, " ").trim();
1909
+ const cleaned = text.replaceAll(/\s*\([^)]*\)\s*/g, " ").trim();
1656
1910
  if (cleaned.includes("Claude Opus 4.7") || cleaned.includes("claude-opus-4.7")) {
1657
1911
  return "claude-opus-4.7";
1658
1912
  }
@@ -1721,11 +1975,11 @@ function usageMetadataFromGenerator(item) {
1721
1975
  };
1722
1976
  }
1723
1977
  async function readAgyModelSetting(filePath) {
1724
- const settingsPath = path4.resolve(path4.dirname(filePath), "../../../..", "settings.json");
1978
+ const settingsPath = path5.resolve(path5.dirname(filePath), "../../../..", "settings.json");
1725
1979
  try {
1726
1980
  const [text, info] = await Promise.all([
1727
1981
  readFile2(settingsPath, "utf8"),
1728
- stat2(settingsPath)
1982
+ stat3(settingsPath)
1729
1983
  ]);
1730
1984
  const configured = JSON.parse(text)?.model;
1731
1985
  const rawModel = typeof configured === "string" ? configured : null;
@@ -1748,16 +2002,16 @@ function extractProjectContext(rawLines) {
1748
2002
  if (args.DirectoryPath) {
1749
2003
  candidate = normalizePath(args.DirectoryPath);
1750
2004
  } else if (args.AbsolutePath) {
1751
- candidate = path4.dirname(normalizePath(args.AbsolutePath));
2005
+ candidate = path5.dirname(normalizePath(args.AbsolutePath));
1752
2006
  } else if (args.SearchPath) {
1753
2007
  candidate = normalizePath(args.SearchPath);
1754
2008
  } else if (args.TargetFile) {
1755
- candidate = path4.dirname(normalizePath(args.TargetFile));
2009
+ candidate = path5.dirname(normalizePath(args.TargetFile));
1756
2010
  } else if (args.Cwd) {
1757
2011
  candidate = normalizePath(args.Cwd);
1758
2012
  }
1759
2013
  if (candidate) {
1760
- const norm = candidate.replace(/\\/g, "/").toLowerCase();
2014
+ const norm = candidate.replaceAll("\\", "/").toLowerCase();
1761
2015
  const isTemp = norm.startsWith("/var/") || norm.startsWith("/private/var/") || norm.startsWith("/tmp/") || norm.startsWith("/private/tmp/") || norm.includes("/tmp.");
1762
2016
  if (isTemp) {
1763
2017
  if (!fallbackCwd) {
@@ -1780,7 +2034,7 @@ function extractProjectContext(rawLines) {
1780
2034
  }
1781
2035
  if (cwd) {
1782
2036
  const match = cwd.match(/[/\\]projects[/\\]([^/\\]+)/i);
1783
- project = match && match[1] ? match[1] : path4.basename(cwd);
2037
+ project = match && match[1] ? match[1] : path5.basename(cwd);
1784
2038
  }
1785
2039
  return { cwd, project };
1786
2040
  }
@@ -1792,7 +2046,7 @@ function normalizePath(p) {
1792
2046
  if (cleaned.startsWith("'") && cleaned.endsWith("'")) {
1793
2047
  cleaned = cleaned.slice(1, -1);
1794
2048
  }
1795
- return path4.normalize(cleaned);
2049
+ return path5.normalize(cleaned);
1796
2050
  }
1797
2051
  async function parseAgySessionFile(filePath, options) {
1798
2052
  const text = await readFile2(filePath, "utf8");
@@ -1811,8 +2065,8 @@ async function parseAgySessionFile(filePath, options) {
1811
2065
  const sessionId = getSessionId(filePath);
1812
2066
  const modelSetting = await readAgyModelSetting(filePath);
1813
2067
  let generatorMetadata = options?.mockTrajectoryMetadata || await getTrajectoryGeneratorMetadata(sessionId).catch(() => null);
1814
- const cacheDir = path4.join(path4.dirname(path4.dirname(filePath)), "cache");
1815
- const cacheFile = path4.join(cacheDir, "trajectory_metadata.json");
2068
+ const cacheDir = path5.join(path5.dirname(path5.dirname(filePath)), "cache");
2069
+ const cacheFile = path5.join(cacheDir, "trajectory_metadata.json");
1816
2070
  if (generatorMetadata) {
1817
2071
  try {
1818
2072
  await mkdir2(cacheDir, { recursive: true });
@@ -1828,6 +2082,16 @@ async function parseAgySessionFile(filePath, options) {
1828
2082
  } catch {
1829
2083
  }
1830
2084
  }
2085
+ if (!generatorMetadata) {
2086
+ generatorMetadata = await readLegacyAgyGeneratorMetadata(filePath, sessionId);
2087
+ if (generatorMetadata) {
2088
+ try {
2089
+ await mkdir2(cacheDir, { recursive: true });
2090
+ await writeFile2(cacheFile, JSON.stringify(generatorMetadata, null, 2), "utf8");
2091
+ } catch {
2092
+ }
2093
+ }
2094
+ }
1831
2095
  const usageMap = /* @__PURE__ */ new Map();
1832
2096
  const usageEntries = [];
1833
2097
  const matchedUsageEntries = /* @__PURE__ */ new Set();
@@ -1932,7 +2196,6 @@ async function parseAgySessionFile(filePath, options) {
1932
2196
  })
1933
2197
  }), lineNumber, raw.type);
1934
2198
  } else if (raw.type === "PLANNER_RESPONSE") {
1935
- const content = stringField(raw, "content") || "";
1936
2199
  const usageMetadata = usageMap.get(raw.step_index);
1937
2200
  if (usageMetadata) {
1938
2201
  matchedUsageEntries.add(usageMetadata);
@@ -2144,27 +2407,27 @@ async function parseAgySessionFile(filePath, options) {
2144
2407
  function agyDataDirs(home, env) {
2145
2408
  const override = env?.ANTIGRAVITY_DATA_DIR || env?.AGY_DATA_DIR;
2146
2409
  if (override && override.trim()) {
2147
- return override.split(",").map((entry) => entry.trim()).filter(Boolean).map((entry) => path4.resolve(entry));
2410
+ return override.split(",").map((entry) => entry.trim()).filter(Boolean).map((entry) => path5.resolve(entry));
2148
2411
  }
2149
- return [path4.join(home, ".gemini", "antigravity-cli", "brain")];
2412
+ return [path5.join(home, ".gemini", "antigravity-cli", "brain")];
2150
2413
  }
2151
2414
  async function agyBackfillFiles(sourceRoot, home, env) {
2152
- const roots = sourceRoot ? [path4.resolve(sourceRoot)] : agyDataDirs(home, env);
2415
+ const roots = sourceRoot ? [path5.resolve(sourceRoot)] : agyDataDirs(home, env);
2153
2416
  const fileLists = await Promise.all(roots.map((root) => listFilesByExtensions(root, [".jsonl"])));
2154
2417
  const files = fileLists.flat().filter((f) => f.endsWith("transcript.jsonl")).sort();
2155
2418
  return Promise.all(files.map(async (filePath) => {
2156
- const info = await stat2(filePath);
2419
+ const info = await stat3(filePath);
2157
2420
  return { path: filePath, modifiedAt: info.mtime.toISOString() };
2158
2421
  }));
2159
2422
  }
2160
- var agyHandler = (msg) => {
2423
+ function agyHandler(msg) {
2161
2424
  return {
2162
2425
  type: "command",
2163
2426
  command: "vibetime hook --agent agy",
2164
2427
  timeout: 10,
2165
2428
  statusMessage: msg
2166
2429
  };
2167
- };
2430
+ }
2168
2431
  function hookConfig() {
2169
2432
  const anyTool = [{ matcher: "", hooks: [agyHandler("Reporting tool activity")] }];
2170
2433
  const lifecycle = (msg) => [{ matcher: "", hooks: [agyHandler(msg)] }];
@@ -2229,18 +2492,18 @@ function createAgyAdapter() {
2229
2492
  return agyDataDirs(home, env)[0];
2230
2493
  },
2231
2494
  installedPath(home, env) {
2232
- return path4.join(path4.dirname(agyDataDirs(home, env)[0]), "hooks.json");
2495
+ return path5.join(path5.dirname(agyDataDirs(home, env)[0]), "hooks.json");
2233
2496
  },
2234
2497
  async isInstalled(home, env) {
2235
- const base = path4.dirname(agyDataDirs(home, env)[0]);
2236
- const settingsPath = path4.join(base, "settings.json");
2237
- const hooksPath = path4.join(base, "hooks.json");
2498
+ const base = path5.dirname(agyDataDirs(home, env)[0]);
2499
+ const settingsPath = path5.join(base, "settings.json");
2500
+ const hooksPath = path5.join(base, "hooks.json");
2238
2501
  return await checkEnableJsonHooks(settingsPath) && await isAgyHooksInstalled(hooksPath, "vibetime hook --agent agy");
2239
2502
  },
2240
2503
  installEntries(home, env) {
2241
- const base = path4.dirname(agyDataDirs(home, env)[0]);
2242
- const settingsPath = path4.join(base, "settings.json");
2243
- const hooksPath = path4.join(base, "hooks.json");
2504
+ const base = path5.dirname(agyDataDirs(home, env)[0]);
2505
+ const settingsPath = path5.join(base, "settings.json");
2506
+ const hooksPath = path5.join(base, "hooks.json");
2244
2507
  return [
2245
2508
  {
2246
2509
  kind: "hooks-json",
@@ -2262,12 +2525,12 @@ function createAgyAdapter() {
2262
2525
  }
2263
2526
 
2264
2527
  // src/adapters/claude-code.ts
2265
- import { readdir as readdir2, readFile as readFile3, stat as stat3 } from "node:fs/promises";
2528
+ import { readdir as readdir2, readFile as readFile3, stat as stat4 } from "node:fs/promises";
2266
2529
  import os2 from "node:os";
2267
- import path6 from "node:path";
2530
+ import path7 from "node:path";
2268
2531
 
2269
2532
  // src/lib/adapter-helpers.ts
2270
- import path5 from "node:path";
2533
+ import path6 from "node:path";
2271
2534
  var TURN_IDLE_MS = 6e4;
2272
2535
  function isTurnIdle(lastEventAt) {
2273
2536
  if (!lastEventAt) {
@@ -2280,7 +2543,7 @@ function isTurnIdle(lastEventAt) {
2280
2543
  return Date.now() - lastMs > TURN_IDLE_MS;
2281
2544
  }
2282
2545
  function sessionIdFromFilePath(filePath, prefix) {
2283
- const match = path5.basename(filePath).match(/([0-9a-f]{8}-[0-9a-f-]{27,})/);
2546
+ const match = path6.basename(filePath).match(/([0-9a-f]{8}-[0-9a-f-]{27,})/);
2284
2547
  return match?.[1] || `${prefix}_${createStableHash(filePath).slice(0, 24)}`;
2285
2548
  }
2286
2549
  function hookHandler(agentId, statusMessage) {
@@ -2344,7 +2607,7 @@ async function parseClaudeCodeSessionFile(filePath, options) {
2344
2607
  sessionId = stringField(raw, "sessionId") || sessionId;
2345
2608
  state.sessionId = sessionId;
2346
2609
  cwd = stringField(raw, "cwd") || cwd;
2347
- project = projectContext.project || (cwd ? path6.basename(cwd) : project || await claudeProjectFromFilePath(filePath, options));
2610
+ project = projectContext.project || (cwd ? path7.basename(cwd) : project || await claudeProjectFromFilePath(filePath, options));
2348
2611
  if (!ts) {
2349
2612
  continue;
2350
2613
  }
@@ -2716,17 +2979,17 @@ function claudeTextStats(value) {
2716
2979
  };
2717
2980
  }
2718
2981
  async function claudeProjectContextFromLines(filePath, lines, options) {
2719
- const projectDir = path6.basename(path6.dirname(filePath));
2982
+ const projectDir = path7.basename(path7.dirname(filePath));
2720
2983
  const cwds = [];
2721
2984
  for (const line of lines) {
2722
2985
  const raw = parseJsonLine(line);
2723
2986
  const cwd = raw ? stringField(raw, "cwd") : void 0;
2724
- if (cwd && path6.isAbsolute(cwd)) {
2987
+ if (cwd && path7.isAbsolute(cwd)) {
2725
2988
  cwds.push(cwd);
2726
2989
  }
2727
2990
  }
2728
2991
  const root = await gitRootFromCwds(cwds) || claudeProjectRootFromCwds(projectDir, cwds);
2729
- const project = cwds.length > 0 ? path6.basename(cwds[0]) : root ? path6.basename(root) : await claudeProjectFromFilePath(filePath, options);
2992
+ const project = cwds.length > 0 ? path7.basename(cwds[0]) : root ? path7.basename(root) : await claudeProjectFromFilePath(filePath, options);
2730
2993
  return {
2731
2994
  project,
2732
2995
  workspaceId: createWorkspaceId({ projectName: project, repoRoot: root })
@@ -2735,15 +2998,15 @@ async function claudeProjectContextFromLines(filePath, lines, options) {
2735
2998
  async function gitRootFromCwds(cwds) {
2736
2999
  const seen = /* @__PURE__ */ new Set();
2737
3000
  for (const cwd of cwds) {
2738
- let current = path6.resolve(cwd);
3001
+ let current = path7.resolve(cwd);
2739
3002
  while (!seen.has(current)) {
2740
3003
  seen.add(current);
2741
3004
  try {
2742
- await stat3(path6.join(current, ".git"));
3005
+ await stat4(path7.join(current, ".git"));
2743
3006
  return current;
2744
3007
  } catch {
2745
3008
  }
2746
- const parent = path6.dirname(current);
3009
+ const parent = path7.dirname(current);
2747
3010
  if (parent === current) {
2748
3011
  break;
2749
3012
  }
@@ -2754,12 +3017,12 @@ async function gitRootFromCwds(cwds) {
2754
3017
  }
2755
3018
  function claudeProjectRootFromCwds(projectDir, cwds) {
2756
3019
  for (const cwd of cwds) {
2757
- let current = path6.resolve(cwd);
3020
+ let current = path7.resolve(cwd);
2758
3021
  while (true) {
2759
3022
  if (encodeClaudeProjectPath(current) === projectDir) {
2760
3023
  return current;
2761
3024
  }
2762
- const parent = path6.dirname(current);
3025
+ const parent = path7.dirname(current);
2763
3026
  if (parent === current) {
2764
3027
  break;
2765
3028
  }
@@ -2769,10 +3032,10 @@ function claudeProjectRootFromCwds(projectDir, cwds) {
2769
3032
  return void 0;
2770
3033
  }
2771
3034
  function encodeClaudeProjectPath(value) {
2772
- return path6.resolve(value).split(path6.sep).join("-").replace(/_/g, "-");
3035
+ return path7.resolve(value).split(path7.sep).join("-").replace(/_/g, "-");
2773
3036
  }
2774
3037
  function rawClaudeProjectPath(value) {
2775
- return path6.resolve(value).split(path6.sep).join("-");
3038
+ return path7.resolve(value).split(path7.sep).join("-");
2776
3039
  }
2777
3040
  function claudeEncodedVariants(value) {
2778
3041
  const raw = rawClaudeProjectPath(value);
@@ -2788,11 +3051,11 @@ function claudeEncodedProjectSuffix(projectDir, home) {
2788
3051
  return void 0;
2789
3052
  }
2790
3053
  async function claudeProjectFromFilePath(filePath, options) {
2791
- const projectDir = path6.basename(path6.dirname(filePath));
2792
- const home = options ? path6.resolve(stringOption(options.home) || os2.homedir()) : os2.homedir();
3054
+ const projectDir = path7.basename(path7.dirname(filePath));
3055
+ const home = options ? path7.resolve(stringOption(options.home) || os2.homedir()) : os2.homedir();
2793
3056
  const resolved = await resolveClaudeProjectPath(projectDir, home);
2794
3057
  if (resolved) {
2795
- return path6.basename(resolved);
3058
+ return path7.basename(resolved);
2796
3059
  }
2797
3060
  const suffix = claudeEncodedProjectSuffix(projectDir, home);
2798
3061
  if (suffix) {
@@ -2818,7 +3081,7 @@ async function resolveClaudeProjectPath(projectDir, home) {
2818
3081
  if (!entry.isDirectory()) {
2819
3082
  continue;
2820
3083
  }
2821
- const candidate = path6.join(current, entry.name);
3084
+ const candidate = path7.join(current, entry.name);
2822
3085
  const candidateVariants = claudeEncodedVariants(candidate);
2823
3086
  if (candidateVariants.includes(projectDir)) {
2824
3087
  return candidate;
@@ -2863,9 +3126,9 @@ function hookConfig2() {
2863
3126
  function claudeConfigDir(home, env) {
2864
3127
  const override = env?.CLAUDE_CONFIG_DIR;
2865
3128
  if (override && override.trim()) {
2866
- return path6.resolve(override);
3129
+ return path7.resolve(override);
2867
3130
  }
2868
- return path6.join(home, ".claude");
3131
+ return path7.join(home, ".claude");
2869
3132
  }
2870
3133
  function createClaudeCodeAdapter() {
2871
3134
  return {
@@ -2877,27 +3140,27 @@ function createClaudeCodeAdapter() {
2877
3140
  return claudeConfigDir(home, env);
2878
3141
  },
2879
3142
  installedPath(home, env) {
2880
- return path6.join(claudeConfigDir(home, env), "settings.json");
3143
+ return path7.join(claudeConfigDir(home, env), "settings.json");
2881
3144
  },
2882
3145
  async isInstalled(home, env) {
2883
3146
  return isHooksJsonInstalled(
2884
- path6.join(claudeConfigDir(home, env), "settings.json"),
3147
+ path7.join(claudeConfigDir(home, env), "settings.json"),
2885
3148
  "vibetime hook --agent claude"
2886
3149
  );
2887
3150
  },
2888
3151
  installEntries(home, env) {
2889
3152
  return [{
2890
3153
  kind: "hooks-json",
2891
- path: path6.join(claudeConfigDir(home, env), "settings.json"),
3154
+ path: path7.join(claudeConfigDir(home, env), "settings.json"),
2892
3155
  content: hookConfig2()
2893
3156
  }];
2894
3157
  },
2895
3158
  sourcePaths(home, env) {
2896
3159
  const base = claudeConfigDir(home, env);
2897
3160
  return [
2898
- path6.join(base, "projects"),
2899
- path6.join(base, ".claude.json"),
2900
- path6.join(home, ".claude.json")
3161
+ path7.join(base, "projects"),
3162
+ path7.join(base, ".claude.json"),
3163
+ path7.join(home, ".claude.json")
2901
3164
  ];
2902
3165
  },
2903
3166
  parseSessionFile: parseClaudeCodeSessionFile
@@ -2905,21 +3168,21 @@ function createClaudeCodeAdapter() {
2905
3168
  }
2906
3169
 
2907
3170
  // src/adapters/claude-cowork.ts
2908
- import { readdir as readdir3, readFile as readFile4, stat as stat4 } from "node:fs/promises";
3171
+ import { readdir as readdir3, readFile as readFile4, stat as stat5 } from "node:fs/promises";
2909
3172
  import os3 from "node:os";
2910
- import path7 from "node:path";
3173
+ import path8 from "node:path";
2911
3174
  init_fs();
2912
3175
  var COWORK_PREFIX = "cowork:";
2913
3176
  function coworkDataDirs(home, env) {
2914
3177
  const override = env?.COWORK_DIR || env?.CLAUDE_COWORK_DIR;
2915
3178
  if (override && override.trim()) {
2916
- return override.split(",").map((item) => item.trim()).filter(Boolean).map((item) => path7.resolve(item));
3179
+ return override.split(",").map((item) => item.trim()).filter(Boolean).map((item) => path8.resolve(item));
2917
3180
  }
2918
3181
  return [
2919
- path7.join(home, "Library", "Application Support", "Claude", "local-agent-mode-sessions"),
2920
- path7.join(home, ".config", "Claude", "local-agent-mode-sessions"),
2921
- path7.join(home, "AppData", "Local", "Packages", "Claude_pzs8sxrjxfjjc", "LocalCache", "Roaming", "Claude", "local-agent-mode-sessions"),
2922
- path7.join(home, "AppData", "Roaming", "Claude", "local-agent-mode-sessions")
3182
+ path8.join(home, "Library", "Application Support", "Claude", "local-agent-mode-sessions"),
3183
+ path8.join(home, ".config", "Claude", "local-agent-mode-sessions"),
3184
+ path8.join(home, "AppData", "Local", "Packages", "Claude_pzs8sxrjxfjjc", "LocalCache", "Roaming", "Claude", "local-agent-mode-sessions"),
3185
+ path8.join(home, "AppData", "Roaming", "Claude", "local-agent-mode-sessions")
2923
3186
  ];
2924
3187
  }
2925
3188
  function isCoworkMetaFileName(name) {
@@ -2935,7 +3198,7 @@ async function readCoworkMeta(filePath) {
2935
3198
  }
2936
3199
  async function isRegularFile(filePath) {
2937
3200
  try {
2938
- return (await stat4(filePath)).isFile();
3201
+ return (await stat5(filePath)).isFile();
2939
3202
  } catch {
2940
3203
  return false;
2941
3204
  }
@@ -2944,7 +3207,7 @@ async function resolveCoworkTranscript(sessionDir, cliSessionId) {
2944
3207
  if (!sessionDir || !cliSessionId) {
2945
3208
  return void 0;
2946
3209
  }
2947
- const projectsDir = path7.join(sessionDir, ".claude", "projects");
3210
+ const projectsDir = path8.join(sessionDir, ".claude", "projects");
2948
3211
  let entries;
2949
3212
  try {
2950
3213
  entries = await readdir3(projectsDir, { withFileTypes: true });
@@ -2956,7 +3219,7 @@ async function resolveCoworkTranscript(sessionDir, cliSessionId) {
2956
3219
  if (!entry.isDirectory() && !entry.isSymbolicLink()) {
2957
3220
  continue;
2958
3221
  }
2959
- const candidate = path7.join(projectsDir, entry.name, target);
3222
+ const candidate = path8.join(projectsDir, entry.name, target);
2960
3223
  if (await isRegularFile(candidate)) {
2961
3224
  return candidate;
2962
3225
  }
@@ -2964,7 +3227,7 @@ async function resolveCoworkTranscript(sessionDir, cliSessionId) {
2964
3227
  return void 0;
2965
3228
  }
2966
3229
  async function coworkSubagentTranscripts(mainTranscript, cliSessionId) {
2967
- const root = path7.join(path7.dirname(mainTranscript), cliSessionId, "subagents");
3230
+ const root = path8.join(path8.dirname(mainTranscript), cliSessionId, "subagents");
2968
3231
  const out = [];
2969
3232
  async function walk(dir) {
2970
3233
  let entries;
@@ -2974,7 +3237,7 @@ async function coworkSubagentTranscripts(mainTranscript, cliSessionId) {
2974
3237
  return;
2975
3238
  }
2976
3239
  await Promise.all(entries.map(async (entry) => {
2977
- const entryPath = path7.join(dir, entry.name);
3240
+ const entryPath = path8.join(dir, entry.name);
2978
3241
  if (entry.isDirectory()) {
2979
3242
  await walk(entryPath);
2980
3243
  return;
@@ -2997,7 +3260,7 @@ async function discoverCoworkTranscripts(root) {
2997
3260
  return;
2998
3261
  }
2999
3262
  await Promise.all(entries.map(async (entry) => {
3000
- const entryPath = path7.join(dir, entry.name);
3263
+ const entryPath = path8.join(dir, entry.name);
3001
3264
  if (entry.isDirectory()) {
3002
3265
  if (entry.name.startsWith("local_") || entry.name === "skills-plugin" || entry.name === "node_modules" || entry.name === ".git") {
3003
3266
  return;
@@ -3027,7 +3290,7 @@ async function discoverCoworkTranscripts(root) {
3027
3290
  return transcripts.sort((a, b) => a.transcriptPath.localeCompare(b.transcriptPath));
3028
3291
  }
3029
3292
  function coworkMetaPathForTranscript(transcriptPath) {
3030
- const marker = `${path7.sep}.claude${path7.sep}projects${path7.sep}`;
3293
+ const marker = `${path8.sep}.claude${path8.sep}projects${path8.sep}`;
3031
3294
  const index = transcriptPath.indexOf(marker);
3032
3295
  if (index < 0) {
3033
3296
  return void 0;
@@ -3042,9 +3305,9 @@ function projectFromMeta(meta) {
3042
3305
  if (!folder) {
3043
3306
  return { project: "cowork" };
3044
3307
  }
3045
- const resolved = path7.resolve(folder);
3308
+ const resolved = path8.resolve(folder);
3046
3309
  return {
3047
- project: path7.basename(resolved).replace(/-/g, "_") || "cowork",
3310
+ project: path8.basename(resolved).replace(/-/g, "_") || "cowork",
3048
3311
  cwd: resolved
3049
3312
  };
3050
3313
  }
@@ -3104,13 +3367,13 @@ async function parseClaudeCoworkSessionFile(filePath, options) {
3104
3367
  });
3105
3368
  }
3106
3369
  async function claudeCoworkBackfillFiles(sourceRoot, home, env) {
3107
- const roots = sourceRoot ? [path7.resolve(sourceRoot)] : coworkDataDirs(home, env);
3370
+ const roots = sourceRoot ? [path8.resolve(sourceRoot)] : coworkDataDirs(home, env);
3108
3371
  const discovered = (await Promise.all(roots.map(discoverCoworkTranscripts))).flat();
3109
3372
  return Promise.all(discovered.map(async ({ transcriptPath, metadataPath }) => {
3110
- const transcriptInfo = await stat4(transcriptPath);
3373
+ const transcriptInfo = await stat5(transcriptPath);
3111
3374
  let modifiedAt = transcriptInfo.mtime;
3112
3375
  try {
3113
- const metaInfo = await stat4(metadataPath);
3376
+ const metaInfo = await stat5(metadataPath);
3114
3377
  if (metaInfo.mtime > modifiedAt) {
3115
3378
  modifiedAt = metaInfo.mtime;
3116
3379
  }
@@ -3126,7 +3389,7 @@ function createClaudeCoworkAdapter() {
3126
3389
  agentName: "claude-cowork",
3127
3390
  kind: "agent",
3128
3391
  detectPath(home, env) {
3129
- return coworkDataDirs(home, env)[0] || path7.join(os3.homedir(), "Library", "Application Support", "Claude", "local-agent-mode-sessions");
3392
+ return coworkDataDirs(home, env)[0] || path8.join(os3.homedir(), "Library", "Application Support", "Claude", "local-agent-mode-sessions");
3130
3393
  },
3131
3394
  installedPath(home, env) {
3132
3395
  return this.detectPath(home, env);
@@ -3151,7 +3414,7 @@ function createClaudeCoworkAdapter() {
3151
3414
 
3152
3415
  // src/adapters/codebuddy.ts
3153
3416
  import { readFile as readFile5, readdir as readdir4 } from "node:fs/promises";
3154
- import path8 from "node:path";
3417
+ import path9 from "node:path";
3155
3418
  var ENDPOINT_MODEL_ID_RE = /^(?:ep|endpoint)-/i;
3156
3419
  async function parseCodebuddyTraceFile(filePath, options) {
3157
3420
  const text = await readFile5(filePath, "utf8");
@@ -3178,7 +3441,7 @@ async function parseCodebuddyTraceFile(filePath, options) {
3178
3441
  if (!cwd && trace.startedAt) {
3179
3442
  cwd = await cwdFromHistoryFile(trace.startedAt, options);
3180
3443
  }
3181
- const project = cwd ? path8.basename(cwd) : void 0;
3444
+ const project = cwd ? path9.basename(cwd) : void 0;
3182
3445
  const workspaceId = createWorkspaceId({ projectName: project, repoRoot: cwd });
3183
3446
  const model = resolveCodebuddyModel(trace, spans);
3184
3447
  const baseEvent = (event) => ({
@@ -3545,11 +3808,11 @@ function modelUsageFromTrace(trace, generationIndex, totalGenerations) {
3545
3808
  return { modelCalls: 1 };
3546
3809
  }
3547
3810
  function sessionIdFromTracePath(filePath) {
3548
- const match = path8.basename(filePath).match(/trace_([0-9a-f]{32})/);
3811
+ const match = path9.basename(filePath).match(/trace_([0-9a-f]{32})/);
3549
3812
  return match?.[1] ? `codebuddy_${match[1]}` : `codebuddy_${createStableHash(filePath).slice(0, 24)}`;
3550
3813
  }
3551
3814
  function resolveHome(options) {
3552
- return options.home ? path8.resolve(String(options.home)) : process.env.HOME || __require("node:os").homedir();
3815
+ return options.home ? path9.resolve(String(options.home)) : process.env.HOME || __require("node:os").homedir();
3553
3816
  }
3554
3817
  async function readCwdFromSession(sessionPath, matchSessionId) {
3555
3818
  try {
@@ -3570,9 +3833,9 @@ async function readCwdFromSession(sessionPath, matchSessionId) {
3570
3833
  }
3571
3834
  async function cwdFromSessionFile(pid, traceSessionId, options) {
3572
3835
  const home = resolveHome(options);
3573
- const sessionsDir = path8.join(home, ".codebuddy", "sessions");
3836
+ const sessionsDir = path9.join(home, ".codebuddy", "sessions");
3574
3837
  if (pid) {
3575
- const cwd = await readCwdFromSession(path8.join(sessionsDir, `${pid}.json`));
3838
+ const cwd = await readCwdFromSession(path9.join(sessionsDir, `${pid}.json`));
3576
3839
  if (cwd) {
3577
3840
  return cwd;
3578
3841
  }
@@ -3585,7 +3848,7 @@ async function cwdFromSessionFile(pid, traceSessionId, options) {
3585
3848
  continue;
3586
3849
  }
3587
3850
  const cwd = await readCwdFromSession(
3588
- path8.join(sessionsDir, f),
3851
+ path9.join(sessionsDir, f),
3589
3852
  traceSessionId
3590
3853
  );
3591
3854
  if (cwd) {
@@ -3599,7 +3862,7 @@ async function cwdFromSessionFile(pid, traceSessionId, options) {
3599
3862
  }
3600
3863
  async function cwdFromHistoryFile(traceStartedAt, options) {
3601
3864
  const home = resolveHome(options);
3602
- const historyPath = path8.join(home, ".codebuddy", "history.jsonl");
3865
+ const historyPath = path9.join(home, ".codebuddy", "history.jsonl");
3603
3866
  const traceMs = Date.parse(traceStartedAt);
3604
3867
  if (Number.isNaN(traceMs)) {
3605
3868
  return void 0;
@@ -3661,9 +3924,9 @@ function hookConfig3() {
3661
3924
  function codebuddyConfigDir(home, env) {
3662
3925
  const override = env?.CODEBUDDY_CONFIG_DIR;
3663
3926
  if (override && override.trim()) {
3664
- return path8.resolve(override);
3927
+ return path9.resolve(override);
3665
3928
  }
3666
- return path8.join(home, ".codebuddy");
3929
+ return path9.join(home, ".codebuddy");
3667
3930
  }
3668
3931
  function createCodebuddyAdapter() {
3669
3932
  return {
@@ -3675,32 +3938,32 @@ function createCodebuddyAdapter() {
3675
3938
  return codebuddyConfigDir(home, env);
3676
3939
  },
3677
3940
  installedPath(home, env) {
3678
- return path8.join(codebuddyConfigDir(home, env), "settings.json");
3941
+ return path9.join(codebuddyConfigDir(home, env), "settings.json");
3679
3942
  },
3680
3943
  async isInstalled(home, env) {
3681
3944
  return isHooksJsonInstalled(
3682
- path8.join(codebuddyConfigDir(home, env), "settings.json"),
3945
+ path9.join(codebuddyConfigDir(home, env), "settings.json"),
3683
3946
  "vibetime hook --agent codebuddy"
3684
3947
  );
3685
3948
  },
3686
3949
  installEntries(home, env) {
3687
3950
  return [{
3688
3951
  kind: "hooks-json",
3689
- path: path8.join(codebuddyConfigDir(home, env), "settings.json"),
3952
+ path: path9.join(codebuddyConfigDir(home, env), "settings.json"),
3690
3953
  content: hookConfig3()
3691
3954
  }];
3692
3955
  },
3693
3956
  sourcePaths(home, env) {
3694
3957
  const base = codebuddyConfigDir(home, env);
3695
3958
  return [
3696
- path8.join(base, "traces")
3959
+ path9.join(base, "traces")
3697
3960
  ];
3698
3961
  },
3699
3962
  parseSessionFile: parseCodebuddyTraceFile
3700
3963
  };
3701
3964
  }
3702
3965
  async function codebuddyBackfillFiles(sourceRoot, home, env) {
3703
- const base = sourceRoot || path8.join(codebuddyConfigDir(home, env), "traces");
3966
+ const base = sourceRoot || path9.join(codebuddyConfigDir(home, env), "traces");
3704
3967
  const files = [];
3705
3968
  try {
3706
3969
  const pidDirs = await readdir4(base, { withFileTypes: true });
@@ -3708,17 +3971,17 @@ async function codebuddyBackfillFiles(sourceRoot, home, env) {
3708
3971
  if (!pidDir.isDirectory()) {
3709
3972
  continue;
3710
3973
  }
3711
- const traceDir = path8.join(base, pidDir.name);
3974
+ const traceDir = path9.join(base, pidDir.name);
3712
3975
  try {
3713
3976
  const entries = await readdir4(traceDir);
3714
3977
  for (const entry of entries) {
3715
3978
  if (!entry.endsWith(".json") || !entry.startsWith("trace_")) {
3716
3979
  continue;
3717
3980
  }
3718
- const filePath = path8.join(traceDir, entry);
3981
+ const filePath = path9.join(traceDir, entry);
3719
3982
  try {
3720
- const stat12 = await import("node:fs/promises").then((fs) => fs.stat(filePath));
3721
- files.push({ path: filePath, modifiedAt: stat12.mtime.toISOString() });
3983
+ const stat13 = await import("node:fs/promises").then((fs) => fs.stat(filePath));
3984
+ files.push({ path: filePath, modifiedAt: stat13.mtime.toISOString() });
3722
3985
  } catch {
3723
3986
  }
3724
3987
  }
@@ -3732,7 +3995,7 @@ async function codebuddyBackfillFiles(sourceRoot, home, env) {
3732
3995
 
3733
3996
  // src/adapters/codex.ts
3734
3997
  import { readFile as readFile6 } from "node:fs/promises";
3735
- import path10 from "node:path";
3998
+ import path11 from "node:path";
3736
3999
 
3737
4000
  // src/lib/diff.ts
3738
4001
  function diffStats(diff) {
@@ -3781,16 +4044,16 @@ function fileActivitiesFromPatchChanges(changes, ts, cwd, displayFilePath3) {
3781
4044
  init_fs();
3782
4045
  import { mkdir as mkdir3, writeFile as writeFile3 } from "node:fs/promises";
3783
4046
  import os4 from "node:os";
3784
- import path9 from "node:path";
4047
+ import path10 from "node:path";
3785
4048
  var SESSION_CONTEXT_VERSION = 1;
3786
4049
  function sessionContextDir(home) {
3787
- return path9.join(home, ".vibetime", "session-context");
4050
+ return path10.join(home, ".vibetime", "session-context");
3788
4051
  }
3789
4052
  function sessionContextPath(home, sessionId) {
3790
- return path9.join(sessionContextDir(home), `${encodeURIComponent(sessionId)}.json`);
4053
+ return path10.join(sessionContextDir(home), `${encodeURIComponent(sessionId)}.json`);
3791
4054
  }
3792
4055
  function resolveHome2(options) {
3793
- return options ? path9.resolve(stringOption(options.home) || os4.homedir()) : os4.homedir();
4056
+ return options ? path10.resolve(stringOption(options.home) || os4.homedir()) : os4.homedir();
3794
4057
  }
3795
4058
  async function readPersistedSessionContext(home, sessionId) {
3796
4059
  const raw = await readJsonIfExists(sessionContextPath(home, sessionId));
@@ -3816,10 +4079,10 @@ async function persistHookSessionContext(home, payload) {
3816
4079
  }
3817
4080
  const sessionId = typeof payload.session_id === "string" ? payload.session_id.trim() : typeof payload.sessionId === "string" ? payload.sessionId.trim() : "";
3818
4081
  const cwd = typeof payload.cwd === "string" ? payload.cwd.trim() : "";
3819
- if (!sessionId || !cwd || !path9.isAbsolute(cwd)) {
4082
+ if (!sessionId || !cwd || !path10.isAbsolute(cwd)) {
3820
4083
  return;
3821
4084
  }
3822
- const project = path9.basename(cwd) || void 0;
4085
+ const project = path10.basename(cwd) || void 0;
3823
4086
  const context = {
3824
4087
  version: SESSION_CONTEXT_VERSION,
3825
4088
  sessionId,
@@ -3870,7 +4133,7 @@ async function parseCodexSessionFile(filePath, options) {
3870
4133
  const inherited = forkedFromId ? await readPersistedSessionContextFromOptions(options, forkedFromId) : void 0;
3871
4134
  sessionId = stringField(payload, "id") || sessionId;
3872
4135
  cwd = inherited?.cwd || stringField(payload, "cwd") || cwd;
3873
- project = inherited?.project || (cwd ? path10.basename(cwd) : project);
4136
+ project = inherited?.project || (cwd ? path11.basename(cwd) : project);
3874
4137
  model = stringField(payload, "model_provider") || model;
3875
4138
  events.push(withBackfillRefs({
3876
4139
  schemaVersion: AGENT_TIME_SCHEMA_VERSION,
@@ -3891,7 +4154,7 @@ async function parseCodexSessionFile(filePath, options) {
3891
4154
  if (topType === "turn_context") {
3892
4155
  currentTurnId = stringField(payload, "turn_id") || currentTurnId;
3893
4156
  cwd = stringField(payload, "cwd") || cwd;
3894
- project = cwd ? path10.basename(cwd) : project;
4157
+ project = cwd ? path11.basename(cwd) : project;
3895
4158
  model = stringField(payload, "model") || model;
3896
4159
  const effort = stringField(payload, "effort") || stringField(objectField(objectField(payload, "collaboration_mode"), "settings"), "reasoning_effort");
3897
4160
  if (effort) {
@@ -4338,11 +4601,11 @@ function functionCallArguments(payload) {
4338
4601
  }
4339
4602
  }
4340
4603
  function displayFilePath2(filePath, cwd) {
4341
- if (!cwd || !path10.isAbsolute(filePath)) {
4604
+ if (!cwd || !path11.isAbsolute(filePath)) {
4342
4605
  return filePath;
4343
4606
  }
4344
- const relative = path10.relative(cwd, filePath);
4345
- return relative && !relative.startsWith("..") && !path10.isAbsolute(relative) ? relative : filePath;
4607
+ const relative = path11.relative(cwd, filePath);
4608
+ return relative && !relative.startsWith("..") && !path11.isAbsolute(relative) ? relative : filePath;
4346
4609
  }
4347
4610
  var codexHandler = (msg) => hookHandler("codex", msg);
4348
4611
  function hookConfig4() {
@@ -4361,9 +4624,9 @@ function hookConfig4() {
4361
4624
  function codexHome(home, env) {
4362
4625
  const override = env?.CODEX_HOME;
4363
4626
  if (override && override.trim()) {
4364
- return path10.resolve(override);
4627
+ return path11.resolve(override);
4365
4628
  }
4366
- return path10.join(home, ".codex");
4629
+ return path11.join(home, ".codex");
4367
4630
  }
4368
4631
  function createCodexAdapter() {
4369
4632
  return {
@@ -4375,26 +4638,26 @@ function createCodexAdapter() {
4375
4638
  return codexHome(home, env);
4376
4639
  },
4377
4640
  installedPath(home, env) {
4378
- return path10.join(codexHome(home, env), "hooks.json");
4641
+ return path11.join(codexHome(home, env), "hooks.json");
4379
4642
  },
4380
4643
  async isInstalled(home, env) {
4381
4644
  return isHooksJsonInstalled(
4382
- path10.join(codexHome(home, env), "hooks.json"),
4645
+ path11.join(codexHome(home, env), "hooks.json"),
4383
4646
  "vibetime hook --agent codex"
4384
4647
  );
4385
4648
  },
4386
4649
  installEntries(home, env) {
4387
4650
  return [{
4388
4651
  kind: "hooks-json",
4389
- path: path10.join(codexHome(home, env), "hooks.json"),
4652
+ path: path11.join(codexHome(home, env), "hooks.json"),
4390
4653
  content: hookConfig4()
4391
4654
  }];
4392
4655
  },
4393
4656
  sourcePaths(home, env) {
4394
4657
  const base = codexHome(home, env);
4395
4658
  return [
4396
- path10.join(base, "sessions"),
4397
- path10.join(base, "history.jsonl")
4659
+ path11.join(base, "sessions"),
4660
+ path11.join(base, "history.jsonl")
4398
4661
  ];
4399
4662
  },
4400
4663
  parseSessionFile: parseCodexSessionFile
@@ -4402,9 +4665,9 @@ function createCodexAdapter() {
4402
4665
  }
4403
4666
 
4404
4667
  // src/adapters/copilot.ts
4405
- import { readdir as readdir5, readFile as readFile7, stat as stat5 } from "node:fs/promises";
4668
+ import { readdir as readdir5, readFile as readFile7, stat as stat6 } from "node:fs/promises";
4406
4669
  import os5 from "node:os";
4407
- import path11 from "node:path";
4670
+ import path12 from "node:path";
4408
4671
  async function parseCopilotSessionFile(filePath, options) {
4409
4672
  const text = await readFile7(filePath, "utf8");
4410
4673
  const lines = text.split("\n").filter(Boolean);
@@ -4440,7 +4703,7 @@ async function parseCopilotSessionFile(filePath, options) {
4440
4703
  }
4441
4704
  const context = objectField(data, "context");
4442
4705
  cwd = stringField(context, "cwd") || stringField(context, "gitRoot") || cwd;
4443
- project = stringField(context, "repository") || (cwd ? path11.basename(cwd) : void 0);
4706
+ project = stringField(context, "repository") || (cwd ? path12.basename(cwd) : void 0);
4444
4707
  sessionStartedAt = ts;
4445
4708
  events.push(baseCopilotEvent({
4446
4709
  ts,
@@ -4672,7 +4935,7 @@ function baseCopilotEvent(event) {
4672
4935
  };
4673
4936
  }
4674
4937
  async function copilotBackfillFiles(sourceRoot, home = os5.homedir(), _env) {
4675
- const sessionDir = sourceRoot || path11.join(home, ".copilot", "session-state");
4938
+ const sessionDir = sourceRoot || path12.join(home, ".copilot", "session-state");
4676
4939
  const results = [];
4677
4940
  let entries;
4678
4941
  try {
@@ -4684,8 +4947,8 @@ async function copilotBackfillFiles(sourceRoot, home = os5.homedir(), _env) {
4684
4947
  if (entry.startsWith("pending-session")) {
4685
4948
  continue;
4686
4949
  }
4687
- const eventsPath = path11.join(sessionDir, entry, "events.jsonl");
4688
- const info = await stat5(eventsPath).catch(() => null);
4950
+ const eventsPath = path12.join(sessionDir, entry, "events.jsonl");
4951
+ const info = await stat6(eventsPath).catch(() => null);
4689
4952
  if (info) {
4690
4953
  results.push({ path: eventsPath, modifiedAt: info.mtime.toISOString() });
4691
4954
  }
@@ -4702,9 +4965,9 @@ function copilotPluginContent() {
4702
4965
  function copilotHome(home, env) {
4703
4966
  const override = env?.COPILOT_HOME;
4704
4967
  if (override && override.trim()) {
4705
- return path11.resolve(override);
4968
+ return path12.resolve(override);
4706
4969
  }
4707
- return path11.join(home, ".copilot");
4970
+ return path12.join(home, ".copilot");
4708
4971
  }
4709
4972
  function createCopilotAdapter() {
4710
4973
  return {
@@ -4716,12 +4979,12 @@ function createCopilotAdapter() {
4716
4979
  return copilotHome(home, env);
4717
4980
  },
4718
4981
  installedPath(home, env) {
4719
- return path11.join(copilotHome(home, env), ".vibetime");
4982
+ return path12.join(copilotHome(home, env), ".vibetime");
4720
4983
  },
4721
4984
  async isInstalled(home, env) {
4722
4985
  try {
4723
4986
  const { pathExists: pathExists2 } = await Promise.resolve().then(() => (init_fs(), fs_exports));
4724
- return await pathExists2(path11.join(copilotHome(home, env), ".vibetime"));
4987
+ return await pathExists2(path12.join(copilotHome(home, env), ".vibetime"));
4725
4988
  } catch {
4726
4989
  return false;
4727
4990
  }
@@ -4729,12 +4992,12 @@ function createCopilotAdapter() {
4729
4992
  installEntries(home, env) {
4730
4993
  return [{
4731
4994
  kind: "file",
4732
- path: path11.join(copilotHome(home, env), ".vibetime"),
4995
+ path: path12.join(copilotHome(home, env), ".vibetime"),
4733
4996
  content: copilotPluginContent()
4734
4997
  }];
4735
4998
  },
4736
4999
  sourcePaths(home, env) {
4737
- return [path11.join(copilotHome(home, env), "session-state")];
5000
+ return [path12.join(copilotHome(home, env), "session-state")];
4738
5001
  },
4739
5002
  parseSessionFile: parseCopilotSessionFile
4740
5003
  };
@@ -4742,7 +5005,7 @@ function createCopilotAdapter() {
4742
5005
 
4743
5006
  // src/adapters/opencode.ts
4744
5007
  import os6 from "node:os";
4745
- import path12 from "node:path";
5008
+ import path13 from "node:path";
4746
5009
  async function parseOpenCodeSessionFile(dbPath, options) {
4747
5010
  const { DatabaseSync } = await import("node:sqlite");
4748
5011
  if (!dbPath.endsWith(".db")) {
@@ -4773,7 +5036,7 @@ async function parseOpenCodeSessionFile(dbPath, options) {
4773
5036
  for (const session of sessions) {
4774
5037
  const sessionId = session.id;
4775
5038
  const cwd = session.directory || session.path || void 0;
4776
- const project = cwd ? path12.basename(cwd) : void 0;
5039
+ const project = cwd ? path13.basename(cwd) : void 0;
4777
5040
  const sessionTs = msToIso(session.time_created);
4778
5041
  events.push(baseOpenCodeEvent({
4779
5042
  ts: sessionTs,
@@ -4881,7 +5144,7 @@ async function parseOpenCodeSessionFile(dbPath, options) {
4881
5144
  const provider = currentProvider;
4882
5145
  const pathObj = objectField(info, "path");
4883
5146
  const assistantCwd = stringField(pathObj, "cwd") || cwd;
4884
- const assistantProject = assistantCwd ? path12.basename(assistantCwd) : project;
5147
+ const assistantProject = assistantCwd ? path13.basename(assistantCwd) : project;
4885
5148
  const completedTs = numberField(objectField(info, "time"), "completed");
4886
5149
  const createdTs = timeCreated;
4887
5150
  const tokens = opencodeUsageFromInfo(info);
@@ -5127,33 +5390,33 @@ function opencodeUsageFromInfo(info) {
5127
5390
  function opencodeConfigDir(home, env) {
5128
5391
  const override = env?.OPENCODE_CONFIG_DIR;
5129
5392
  if (override && override.trim()) {
5130
- return path12.resolve(override);
5393
+ return path13.resolve(override);
5131
5394
  }
5132
5395
  const xdgConfig = env?.XDG_CONFIG_HOME;
5133
5396
  if (xdgConfig && xdgConfig.trim()) {
5134
- return path12.join(path12.resolve(xdgConfig), "opencode");
5397
+ return path13.join(path13.resolve(xdgConfig), "opencode");
5135
5398
  }
5136
- return path12.join(home, ".config", "opencode");
5399
+ return path13.join(home, ".config", "opencode");
5137
5400
  }
5138
5401
  function opencodeDataCandidates(home, env) {
5139
5402
  const xdgData = env?.XDG_DATA_HOME;
5140
- const primary = xdgData && xdgData.trim() ? path12.join(path12.resolve(xdgData), "opencode", "opencode.db") : path12.join(home, ".local", "share", "opencode", "opencode.db");
5141
- return [primary, path12.join(home, ".opencode", "opencode.db")];
5403
+ const primary = xdgData && xdgData.trim() ? path13.join(path13.resolve(xdgData), "opencode", "opencode.db") : path13.join(home, ".local", "share", "opencode", "opencode.db");
5404
+ return [primary, path13.join(home, ".opencode", "opencode.db")];
5142
5405
  }
5143
5406
  async function opencodeBackfillFiles(sourceRoot, home = os6.homedir(), env) {
5144
- const { stat: stat12 } = await import("node:fs/promises");
5407
+ const { stat: stat13 } = await import("node:fs/promises");
5145
5408
  if (sourceRoot) {
5146
5409
  if (!sourceRoot.endsWith(".db")) {
5147
5410
  return [];
5148
5411
  }
5149
- const info = await stat12(sourceRoot).catch(() => null);
5412
+ const info = await stat13(sourceRoot).catch(() => null);
5150
5413
  if (!info) {
5151
5414
  return [];
5152
5415
  }
5153
5416
  return [{ path: sourceRoot, modifiedAt: info.mtime.toISOString() }];
5154
5417
  }
5155
5418
  for (const candidatePath of opencodeDataCandidates(home, env)) {
5156
- const info = await stat12(candidatePath).catch(() => null);
5419
+ const info = await stat13(candidatePath).catch(() => null);
5157
5420
  if (info) {
5158
5421
  return [{ path: candidatePath, modifiedAt: info.mtime.toISOString() }];
5159
5422
  }
@@ -5228,12 +5491,12 @@ function createOpenCodeAdapter() {
5228
5491
  return opencodeConfigDir(home, env);
5229
5492
  },
5230
5493
  installedPath(home, env) {
5231
- return path12.join(opencodeConfigDir(home, env), PLUGIN_PATH);
5494
+ return path13.join(opencodeConfigDir(home, env), PLUGIN_PATH);
5232
5495
  },
5233
5496
  async isInstalled(home, env) {
5234
5497
  try {
5235
5498
  const { pathExists: pathExists2 } = await Promise.resolve().then(() => (init_fs(), fs_exports));
5236
- return await pathExists2(path12.join(opencodeConfigDir(home, env), PLUGIN_PATH)) || await pathExists2(path12.join(".opencode", PLUGIN_PATH));
5499
+ return await pathExists2(path13.join(opencodeConfigDir(home, env), PLUGIN_PATH)) || await pathExists2(path13.join(".opencode", PLUGIN_PATH));
5237
5500
  } catch {
5238
5501
  return false;
5239
5502
  }
@@ -5241,7 +5504,7 @@ function createOpenCodeAdapter() {
5241
5504
  installEntries(home, env) {
5242
5505
  return [{
5243
5506
  kind: "file",
5244
- path: path12.join(opencodeConfigDir(home, env), PLUGIN_PATH),
5507
+ path: path13.join(opencodeConfigDir(home, env), PLUGIN_PATH),
5245
5508
  content: opencodePluginContent()
5246
5509
  }];
5247
5510
  },
@@ -5254,7 +5517,7 @@ function createOpenCodeAdapter() {
5254
5517
 
5255
5518
  // src/adapters/pi.ts
5256
5519
  import { readFile as readFile8 } from "node:fs/promises";
5257
- import path13 from "node:path";
5520
+ import path14 from "node:path";
5258
5521
  async function parsePiSessionFile(filePath, options) {
5259
5522
  const text = await readFile8(filePath, "utf8");
5260
5523
  const lines = text.split("\n").filter(Boolean);
@@ -5287,7 +5550,7 @@ async function parsePiSessionFile(filePath, options) {
5287
5550
  sessionId = stringField(raw, "id") || state.sessionId;
5288
5551
  state.sessionId = sessionId || state.sessionId;
5289
5552
  cwd = stringField(raw, "cwd") || cwd;
5290
- project = cwd ? path13.basename(cwd) : project;
5553
+ project = cwd ? path14.basename(cwd) : project;
5291
5554
  continue;
5292
5555
  }
5293
5556
  if (entryType === "model_change") {
@@ -5696,16 +5959,16 @@ export default function (pi: ExtensionAPI) {
5696
5959
  function piAgentDir(home, env) {
5697
5960
  const override = env?.PI_CODING_AGENT_DIR;
5698
5961
  if (override && override.trim()) {
5699
- return path13.resolve(override);
5962
+ return path14.resolve(override);
5700
5963
  }
5701
- return path13.join(home, ".pi", "agent");
5964
+ return path14.join(home, ".pi", "agent");
5702
5965
  }
5703
5966
  function piSessionDir(home, env) {
5704
5967
  const override = env?.PI_CODING_AGENT_SESSION_DIR;
5705
5968
  if (override && override.trim()) {
5706
- return path13.resolve(override);
5969
+ return path14.resolve(override);
5707
5970
  }
5708
- return path13.join(piAgentDir(home, env), "sessions");
5971
+ return path14.join(piAgentDir(home, env), "sessions");
5709
5972
  }
5710
5973
  function createPiAdapter() {
5711
5974
  return {
@@ -5717,12 +5980,12 @@ function createPiAdapter() {
5717
5980
  return piAgentDir(home, env);
5718
5981
  },
5719
5982
  installedPath(home, env) {
5720
- return path13.join(piAgentDir(home, env), "extensions", "vibetime.ts");
5983
+ return path14.join(piAgentDir(home, env), "extensions", "vibetime.ts");
5721
5984
  },
5722
5985
  async isInstalled(home, env) {
5723
5986
  try {
5724
5987
  const { pathExists: pathExists2 } = await Promise.resolve().then(() => (init_fs(), fs_exports));
5725
- return await pathExists2(path13.join(piAgentDir(home, env), "extensions", "vibetime.ts"));
5988
+ return await pathExists2(path14.join(piAgentDir(home, env), "extensions", "vibetime.ts"));
5726
5989
  } catch {
5727
5990
  return false;
5728
5991
  }
@@ -5730,7 +5993,7 @@ function createPiAdapter() {
5730
5993
  installEntries(home, env) {
5731
5994
  return [{
5732
5995
  kind: "file",
5733
- path: path13.join(piAgentDir(home, env), "extensions", "vibetime.ts"),
5996
+ path: path14.join(piAgentDir(home, env), "extensions", "vibetime.ts"),
5734
5997
  content: piExtensionContent()
5735
5998
  }];
5736
5999
  },
@@ -5742,11 +6005,11 @@ function createPiAdapter() {
5742
6005
  }
5743
6006
 
5744
6007
  // src/adapters/qoder-cn.ts
5745
- import { readdir as readdir6, readFile as readFile9, stat as stat6 } from "node:fs/promises";
6008
+ import { readdir as readdir6, readFile as readFile9, stat as stat7 } from "node:fs/promises";
5746
6009
  import os7 from "node:os";
5747
- import path14 from "node:path";
6010
+ import path15 from "node:path";
5748
6011
  function parseQoderCnPaths(filePath) {
5749
- const parts = filePath.split(path14.sep);
6012
+ const parts = filePath.split(path15.sep);
5750
6013
  const subagentsIdx = parts.lastIndexOf("subagents");
5751
6014
  let sessionId = "";
5752
6015
  let projectName = "";
@@ -5755,19 +6018,19 @@ function parseQoderCnPaths(filePath) {
5755
6018
  sessionId = parts[subagentsIdx - 1];
5756
6019
  projectName = parts[subagentsIdx - 2];
5757
6020
  const projectsIdx = parts.lastIndexOf("projects");
5758
- configDir2 = parts.slice(0, projectsIdx).join(path14.sep);
6021
+ configDir2 = parts.slice(0, projectsIdx).join(path15.sep);
5759
6022
  } else {
5760
6023
  const filename = parts.at(-1) || "";
5761
- sessionId = path14.basename(filename, ".jsonl");
6024
+ sessionId = path15.basename(filename, ".jsonl");
5762
6025
  projectName = parts.at(-2) || "";
5763
6026
  const projectsIdx = parts.lastIndexOf("projects");
5764
- configDir2 = parts.slice(0, projectsIdx).join(path14.sep);
6027
+ configDir2 = parts.slice(0, projectsIdx).join(path15.sep);
5765
6028
  }
5766
6029
  return { configDir: configDir2, projectName, sessionId };
5767
6030
  }
5768
6031
  async function loadQoderCnModelNames(configDir2) {
5769
6032
  try {
5770
- const dynamicTextsPath = path14.join(configDir2, ".auth", "dynamic-texts.json");
6033
+ const dynamicTextsPath = path15.join(configDir2, ".auth", "dynamic-texts.json");
5771
6034
  const content = await readFile9(dynamicTextsPath, "utf8");
5772
6035
  const json = JSON.parse(content);
5773
6036
  const texts = json.texts || {};
@@ -5785,7 +6048,7 @@ async function loadQoderCnModelNames(configDir2) {
5785
6048
  }
5786
6049
  async function loadQoderCnSegmentModelCalls(filePath, isSubagentSession, modelMap) {
5787
6050
  const { configDir: configDir2, projectName, sessionId } = parseQoderCnPaths(filePath);
5788
- const segmentsPath = path14.join(configDir2, "logs", "sessions", projectName, sessionId, "segments");
6051
+ const segmentsPath = path15.join(configDir2, "logs", "sessions", projectName, sessionId, "segments");
5789
6052
  const modelCalls = [];
5790
6053
  try {
5791
6054
  const files = await readdir6(segmentsPath);
@@ -5793,7 +6056,7 @@ async function loadQoderCnSegmentModelCalls(filePath, isSubagentSession, modelMa
5793
6056
  if (!file.endsWith(".jsonl")) {
5794
6057
  continue;
5795
6058
  }
5796
- const content = await readFile9(path14.join(segmentsPath, file), "utf8");
6059
+ const content = await readFile9(path15.join(segmentsPath, file), "utf8");
5797
6060
  let currentTurnIsSubagent = false;
5798
6061
  for (const line of content.split("\n").filter(Boolean)) {
5799
6062
  const raw = parseJsonLine(line);
@@ -5861,7 +6124,7 @@ async function parseQoderCnSessionFile(filePath, options) {
5861
6124
  sessionId = stringField(raw, "sessionId") || sessionId;
5862
6125
  state.sessionId = sessionId;
5863
6126
  cwd = stringField(raw, "cwd") || cwd;
5864
- project = projectContext.project || (cwd ? path14.basename(cwd) : project || await qoderCnProjectFromFilePath(filePath, options));
6127
+ project = projectContext.project || (cwd ? path15.basename(cwd) : project || await qoderCnProjectFromFilePath(filePath, options));
5865
6128
  if (!ts) {
5866
6129
  continue;
5867
6130
  }
@@ -6290,28 +6553,28 @@ function isNoisePrompt(text) {
6290
6553
  }
6291
6554
  async function qoderCnProjectContextFromLines(filePath, lines, options, configDir2) {
6292
6555
  const { projectName: projectDir, sessionId } = parseQoderCnPaths(filePath);
6293
- const isSubagent = filePath.includes(`${path14.sep}subagents${path14.sep}`);
6556
+ const isSubagent = filePath.includes(`${path15.sep}subagents${path15.sep}`);
6294
6557
  const inherited = isSubagent ? await readPersistedSessionContextFromOptions(options, sessionId) : void 0;
6295
6558
  let cwds = [];
6296
6559
  for (const line of lines) {
6297
6560
  const raw = parseJsonLine(line);
6298
6561
  const cwd = raw ? stringField(raw, "cwd") : void 0;
6299
- if (cwd && path14.isAbsolute(cwd)) {
6562
+ if (cwd && path15.isAbsolute(cwd)) {
6300
6563
  cwds.push(cwd);
6301
6564
  }
6302
6565
  }
6303
6566
  if (isSubagent) {
6304
- if (inherited?.cwd && path14.isAbsolute(inherited.cwd)) {
6567
+ if (inherited?.cwd && path15.isAbsolute(inherited.cwd)) {
6305
6568
  cwds = [inherited.cwd];
6306
6569
  } else {
6307
- const parentSessionPath = path14.join(configDir2, "projects", projectDir, `${sessionId}.jsonl`);
6570
+ const parentSessionPath = path15.join(configDir2, "projects", projectDir, `${sessionId}.jsonl`);
6308
6571
  try {
6309
6572
  const parentText = await readFile9(parentSessionPath, "utf8");
6310
6573
  const parentCwds = [];
6311
6574
  for (const line of parentText.split("\n").filter(Boolean)) {
6312
6575
  const raw = parseJsonLine(line);
6313
6576
  const cwd = raw ? stringField(raw, "cwd") : void 0;
6314
- if (cwd && path14.isAbsolute(cwd)) {
6577
+ if (cwd && path15.isAbsolute(cwd)) {
6315
6578
  parentCwds.push(cwd);
6316
6579
  }
6317
6580
  }
@@ -6323,7 +6586,7 @@ async function qoderCnProjectContextFromLines(filePath, lines, options, configDi
6323
6586
  }
6324
6587
  }
6325
6588
  const root = await gitRootFromCwds2(cwds) || qoderCnProjectRootFromCwds(projectDir, cwds);
6326
- const project = inherited?.project || (cwds.length > 0 ? path14.basename(cwds[0]) : root ? path14.basename(root) : await qoderCnProjectFromFilePath(filePath, options));
6589
+ const project = inherited?.project || (cwds.length > 0 ? path15.basename(cwds[0]) : root ? path15.basename(root) : await qoderCnProjectFromFilePath(filePath, options));
6327
6590
  return {
6328
6591
  project,
6329
6592
  workspaceId: createWorkspaceId({ projectName: project, repoRoot: root })
@@ -6332,15 +6595,15 @@ async function qoderCnProjectContextFromLines(filePath, lines, options, configDi
6332
6595
  async function gitRootFromCwds2(cwds) {
6333
6596
  const seen = /* @__PURE__ */ new Set();
6334
6597
  for (const cwd of cwds) {
6335
- let current = path14.resolve(cwd);
6598
+ let current = path15.resolve(cwd);
6336
6599
  while (!seen.has(current)) {
6337
6600
  seen.add(current);
6338
6601
  try {
6339
- await stat6(path14.join(current, ".git"));
6602
+ await stat7(path15.join(current, ".git"));
6340
6603
  return current;
6341
6604
  } catch {
6342
6605
  }
6343
- const parent = path14.dirname(current);
6606
+ const parent = path15.dirname(current);
6344
6607
  if (parent === current) {
6345
6608
  break;
6346
6609
  }
@@ -6351,12 +6614,12 @@ async function gitRootFromCwds2(cwds) {
6351
6614
  }
6352
6615
  function qoderCnProjectRootFromCwds(projectDir, cwds) {
6353
6616
  for (const cwd of cwds) {
6354
- let current = path14.resolve(cwd);
6617
+ let current = path15.resolve(cwd);
6355
6618
  while (true) {
6356
6619
  if (encodeQoderCnProjectPath(current) === projectDir) {
6357
6620
  return current;
6358
6621
  }
6359
- const parent = path14.dirname(current);
6622
+ const parent = path15.dirname(current);
6360
6623
  if (parent === current) {
6361
6624
  break;
6362
6625
  }
@@ -6366,14 +6629,14 @@ function qoderCnProjectRootFromCwds(projectDir, cwds) {
6366
6629
  return void 0;
6367
6630
  }
6368
6631
  function encodeQoderCnProjectPath(value) {
6369
- return path14.resolve(value).split(path14.sep).join("-").replace(/_/g, "-");
6632
+ return path15.resolve(value).split(path15.sep).join("-").replace(/_/g, "-");
6370
6633
  }
6371
6634
  async function qoderCnProjectFromFilePath(filePath, options) {
6372
- const projectDir = path14.basename(path14.dirname(filePath));
6373
- const home = options ? path14.resolve(stringOption(options.home) || os7.homedir()) : os7.homedir();
6635
+ const projectDir = path15.basename(path15.dirname(filePath));
6636
+ const home = options ? path15.resolve(stringOption(options.home) || os7.homedir()) : os7.homedir();
6374
6637
  const resolved = await resolveQoderCnProjectPath(projectDir, home);
6375
6638
  if (resolved) {
6376
- return path14.basename(resolved);
6639
+ return path15.basename(resolved);
6377
6640
  }
6378
6641
  const homePrefix = `${encodeQoderCnProjectPath(home)}-`;
6379
6642
  if (projectDir.startsWith(homePrefix)) {
@@ -6398,7 +6661,7 @@ async function resolveQoderCnProjectPath(projectDir, home) {
6398
6661
  if (!entry.isDirectory()) {
6399
6662
  continue;
6400
6663
  }
6401
- const candidate = path14.join(current, entry.name);
6664
+ const candidate = path15.join(current, entry.name);
6402
6665
  const encoded = encodeQoderCnProjectPath(candidate);
6403
6666
  if (encoded === projectDir) {
6404
6667
  return candidate;
@@ -6443,9 +6706,9 @@ function hookConfig5() {
6443
6706
  function qoderCnConfigDir(home, env) {
6444
6707
  const override = env?.QODER_CN_CONFIG_DIR;
6445
6708
  if (override && override.trim()) {
6446
- return path14.resolve(override);
6709
+ return path15.resolve(override);
6447
6710
  }
6448
- return path14.join(home, ".qoder-cn");
6711
+ return path15.join(home, ".qoder-cn");
6449
6712
  }
6450
6713
  function createQoderCnAdapter() {
6451
6714
  return {
@@ -6457,27 +6720,27 @@ function createQoderCnAdapter() {
6457
6720
  return qoderCnConfigDir(home, env);
6458
6721
  },
6459
6722
  installedPath(home, env) {
6460
- return path14.join(qoderCnConfigDir(home, env), "settings.json");
6723
+ return path15.join(qoderCnConfigDir(home, env), "settings.json");
6461
6724
  },
6462
6725
  async isInstalled(home, env) {
6463
6726
  return isHooksJsonInstalled(
6464
- path14.join(qoderCnConfigDir(home, env), "settings.json"),
6727
+ path15.join(qoderCnConfigDir(home, env), "settings.json"),
6465
6728
  "vibetime hook --agent qoder-cn"
6466
6729
  );
6467
6730
  },
6468
6731
  installEntries(home, env) {
6469
6732
  return [{
6470
6733
  kind: "hooks-json",
6471
- path: path14.join(qoderCnConfigDir(home, env), "settings.json"),
6734
+ path: path15.join(qoderCnConfigDir(home, env), "settings.json"),
6472
6735
  content: hookConfig5()
6473
6736
  }];
6474
6737
  },
6475
6738
  sourcePaths(home, env) {
6476
6739
  const base = qoderCnConfigDir(home, env);
6477
6740
  return [
6478
- path14.join(base, "projects"),
6479
- path14.join(base, ".qoder.json"),
6480
- path14.join(home, ".qoder.json")
6741
+ path15.join(base, "projects"),
6742
+ path15.join(base, ".qoder.json"),
6743
+ path15.join(home, ".qoder.json")
6481
6744
  ];
6482
6745
  },
6483
6746
  parseSessionFile: parseQoderCnSessionFile
@@ -6485,11 +6748,11 @@ function createQoderCnAdapter() {
6485
6748
  }
6486
6749
 
6487
6750
  // src/adapters/qoder.ts
6488
- import { readdir as readdir7, readFile as readFile10, stat as stat7 } from "node:fs/promises";
6751
+ import { readdir as readdir7, readFile as readFile10, stat as stat8 } from "node:fs/promises";
6489
6752
  import os8 from "node:os";
6490
- import path15 from "node:path";
6753
+ import path16 from "node:path";
6491
6754
  function parseQoderPaths(filePath) {
6492
- const parts = filePath.split(path15.sep);
6755
+ const parts = filePath.split(path16.sep);
6493
6756
  const subagentsIdx = parts.lastIndexOf("subagents");
6494
6757
  let sessionId = "";
6495
6758
  let projectName = "";
@@ -6498,19 +6761,19 @@ function parseQoderPaths(filePath) {
6498
6761
  sessionId = parts[subagentsIdx - 1];
6499
6762
  projectName = parts[subagentsIdx - 2];
6500
6763
  const projectsIdx = parts.lastIndexOf("projects");
6501
- configDir2 = parts.slice(0, projectsIdx).join(path15.sep);
6764
+ configDir2 = parts.slice(0, projectsIdx).join(path16.sep);
6502
6765
  } else {
6503
6766
  const filename = parts.at(-1) || "";
6504
- sessionId = path15.basename(filename, ".jsonl");
6767
+ sessionId = path16.basename(filename, ".jsonl");
6505
6768
  projectName = parts.at(-2) || "";
6506
6769
  const projectsIdx = parts.lastIndexOf("projects");
6507
- configDir2 = parts.slice(0, projectsIdx).join(path15.sep);
6770
+ configDir2 = parts.slice(0, projectsIdx).join(path16.sep);
6508
6771
  }
6509
6772
  return { configDir: configDir2, projectName, sessionId };
6510
6773
  }
6511
6774
  async function loadQoderModelNames(configDir2) {
6512
6775
  try {
6513
- const dynamicTextsPath = path15.join(configDir2, ".auth", "dynamic-texts.json");
6776
+ const dynamicTextsPath = path16.join(configDir2, ".auth", "dynamic-texts.json");
6514
6777
  const content = await readFile10(dynamicTextsPath, "utf8");
6515
6778
  const json = JSON.parse(content);
6516
6779
  const texts = json.texts || {};
@@ -6528,7 +6791,7 @@ async function loadQoderModelNames(configDir2) {
6528
6791
  }
6529
6792
  async function loadQoderSegmentModelCalls(filePath, isSubagentSession, modelMap) {
6530
6793
  const { configDir: configDir2, projectName, sessionId } = parseQoderPaths(filePath);
6531
- const segmentsPath = path15.join(configDir2, "logs", "sessions", projectName, sessionId, "segments");
6794
+ const segmentsPath = path16.join(configDir2, "logs", "sessions", projectName, sessionId, "segments");
6532
6795
  const modelCalls = [];
6533
6796
  try {
6534
6797
  const files = await readdir7(segmentsPath);
@@ -6536,7 +6799,7 @@ async function loadQoderSegmentModelCalls(filePath, isSubagentSession, modelMap)
6536
6799
  if (!file.endsWith(".jsonl")) {
6537
6800
  continue;
6538
6801
  }
6539
- const content = await readFile10(path15.join(segmentsPath, file), "utf8");
6802
+ const content = await readFile10(path16.join(segmentsPath, file), "utf8");
6540
6803
  let currentTurnIsSubagent = false;
6541
6804
  for (const line of content.split("\n").filter(Boolean)) {
6542
6805
  const raw = parseJsonLine(line);
@@ -6604,7 +6867,7 @@ async function parseQoderSessionFile(filePath, options) {
6604
6867
  sessionId = stringField(raw, "sessionId") || sessionId;
6605
6868
  state.sessionId = sessionId;
6606
6869
  cwd = stringField(raw, "cwd") || cwd;
6607
- project = projectContext.project || (cwd ? path15.basename(cwd) : project || await qoderProjectFromFilePath(filePath, options));
6870
+ project = projectContext.project || (cwd ? path16.basename(cwd) : project || await qoderProjectFromFilePath(filePath, options));
6608
6871
  if (!ts) {
6609
6872
  continue;
6610
6873
  }
@@ -6999,28 +7262,28 @@ function qoderExtractText(value) {
6999
7262
  }
7000
7263
  async function qoderProjectContextFromLines(filePath, lines, options, configDir2) {
7001
7264
  const { projectName: projectDir, sessionId } = parseQoderPaths(filePath);
7002
- const isSubagent = filePath.includes(`${path15.sep}subagents${path15.sep}`);
7265
+ const isSubagent = filePath.includes(`${path16.sep}subagents${path16.sep}`);
7003
7266
  const inherited = isSubagent ? await readPersistedSessionContextFromOptions(options, sessionId) : void 0;
7004
7267
  let cwds = [];
7005
7268
  for (const line of lines) {
7006
7269
  const raw = parseJsonLine(line);
7007
7270
  const cwd = raw ? stringField(raw, "cwd") : void 0;
7008
- if (cwd && path15.isAbsolute(cwd)) {
7271
+ if (cwd && path16.isAbsolute(cwd)) {
7009
7272
  cwds.push(cwd);
7010
7273
  }
7011
7274
  }
7012
7275
  if (isSubagent) {
7013
- if (inherited?.cwd && path15.isAbsolute(inherited.cwd)) {
7276
+ if (inherited?.cwd && path16.isAbsolute(inherited.cwd)) {
7014
7277
  cwds = [inherited.cwd];
7015
7278
  } else {
7016
- const parentSessionPath = path15.join(configDir2, "projects", projectDir, `${sessionId}.jsonl`);
7279
+ const parentSessionPath = path16.join(configDir2, "projects", projectDir, `${sessionId}.jsonl`);
7017
7280
  try {
7018
7281
  const parentText = await readFile10(parentSessionPath, "utf8");
7019
7282
  const parentCwds = [];
7020
7283
  for (const line of parentText.split("\n").filter(Boolean)) {
7021
7284
  const raw = parseJsonLine(line);
7022
7285
  const cwd = raw ? stringField(raw, "cwd") : void 0;
7023
- if (cwd && path15.isAbsolute(cwd)) {
7286
+ if (cwd && path16.isAbsolute(cwd)) {
7024
7287
  parentCwds.push(cwd);
7025
7288
  }
7026
7289
  }
@@ -7032,7 +7295,7 @@ async function qoderProjectContextFromLines(filePath, lines, options, configDir2
7032
7295
  }
7033
7296
  }
7034
7297
  const root = await gitRootFromCwds3(cwds) || qoderProjectRootFromCwds(projectDir, cwds);
7035
- const project = inherited?.project || (cwds.length > 0 ? path15.basename(cwds[0]) : root ? path15.basename(root) : await qoderProjectFromFilePath(filePath, options));
7298
+ const project = inherited?.project || (cwds.length > 0 ? path16.basename(cwds[0]) : root ? path16.basename(root) : await qoderProjectFromFilePath(filePath, options));
7036
7299
  return {
7037
7300
  project,
7038
7301
  workspaceId: createWorkspaceId({ projectName: project, repoRoot: root })
@@ -7041,15 +7304,15 @@ async function qoderProjectContextFromLines(filePath, lines, options, configDir2
7041
7304
  async function gitRootFromCwds3(cwds) {
7042
7305
  const seen = /* @__PURE__ */ new Set();
7043
7306
  for (const cwd of cwds) {
7044
- let current = path15.resolve(cwd);
7307
+ let current = path16.resolve(cwd);
7045
7308
  while (!seen.has(current)) {
7046
7309
  seen.add(current);
7047
7310
  try {
7048
- await stat7(path15.join(current, ".git"));
7311
+ await stat8(path16.join(current, ".git"));
7049
7312
  return current;
7050
7313
  } catch {
7051
7314
  }
7052
- const parent = path15.dirname(current);
7315
+ const parent = path16.dirname(current);
7053
7316
  if (parent === current) {
7054
7317
  break;
7055
7318
  }
@@ -7060,12 +7323,12 @@ async function gitRootFromCwds3(cwds) {
7060
7323
  }
7061
7324
  function qoderProjectRootFromCwds(projectDir, cwds) {
7062
7325
  for (const cwd of cwds) {
7063
- let current = path15.resolve(cwd);
7326
+ let current = path16.resolve(cwd);
7064
7327
  while (true) {
7065
7328
  if (encodeQoderProjectPath(current) === projectDir) {
7066
7329
  return current;
7067
7330
  }
7068
- const parent = path15.dirname(current);
7331
+ const parent = path16.dirname(current);
7069
7332
  if (parent === current) {
7070
7333
  break;
7071
7334
  }
@@ -7075,10 +7338,10 @@ function qoderProjectRootFromCwds(projectDir, cwds) {
7075
7338
  return void 0;
7076
7339
  }
7077
7340
  function encodeQoderProjectPath(value) {
7078
- return path15.resolve(value).split(path15.sep).join("-").replace(/_/g, "-");
7341
+ return path16.resolve(value).split(path16.sep).join("-").replace(/_/g, "-");
7079
7342
  }
7080
7343
  function rawQoderProjectPath(value) {
7081
- return path15.resolve(value).split(path15.sep).join("-");
7344
+ return path16.resolve(value).split(path16.sep).join("-");
7082
7345
  }
7083
7346
  function qoderEncodedVariants(value) {
7084
7347
  const raw = rawQoderProjectPath(value);
@@ -7094,11 +7357,11 @@ function qoderEncodedProjectSuffix(projectDir, home) {
7094
7357
  return void 0;
7095
7358
  }
7096
7359
  async function qoderProjectFromFilePath(filePath, options) {
7097
- const projectDir = path15.basename(path15.dirname(filePath));
7098
- const home = options ? path15.resolve(stringOption(options.home) || os8.homedir()) : os8.homedir();
7360
+ const projectDir = path16.basename(path16.dirname(filePath));
7361
+ const home = options ? path16.resolve(stringOption(options.home) || os8.homedir()) : os8.homedir();
7099
7362
  const resolved = await resolveQoderProjectPath(projectDir, home);
7100
7363
  if (resolved) {
7101
- return path15.basename(resolved);
7364
+ return path16.basename(resolved);
7102
7365
  }
7103
7366
  const suffix = qoderEncodedProjectSuffix(projectDir, home);
7104
7367
  if (suffix) {
@@ -7124,7 +7387,7 @@ async function resolveQoderProjectPath(projectDir, home) {
7124
7387
  if (!entry.isDirectory()) {
7125
7388
  continue;
7126
7389
  }
7127
- const candidate = path15.join(current, entry.name);
7390
+ const candidate = path16.join(current, entry.name);
7128
7391
  const candidateVariants = qoderEncodedVariants(candidate);
7129
7392
  if (candidateVariants.includes(projectDir)) {
7130
7393
  return candidate;
@@ -7169,9 +7432,9 @@ function hookConfig6() {
7169
7432
  function qoderConfigDir(home, env) {
7170
7433
  const override = env?.QODER_CONFIG_DIR;
7171
7434
  if (override && override.trim()) {
7172
- return path15.resolve(override);
7435
+ return path16.resolve(override);
7173
7436
  }
7174
- return path15.join(home, ".qoder");
7437
+ return path16.join(home, ".qoder");
7175
7438
  }
7176
7439
  function createQoderAdapter() {
7177
7440
  return {
@@ -7183,27 +7446,27 @@ function createQoderAdapter() {
7183
7446
  return qoderConfigDir(home, env);
7184
7447
  },
7185
7448
  installedPath(home, env) {
7186
- return path15.join(qoderConfigDir(home, env), "settings.json");
7449
+ return path16.join(qoderConfigDir(home, env), "settings.json");
7187
7450
  },
7188
7451
  async isInstalled(home, env) {
7189
7452
  return isHooksJsonInstalled(
7190
- path15.join(qoderConfigDir(home, env), "settings.json"),
7453
+ path16.join(qoderConfigDir(home, env), "settings.json"),
7191
7454
  "vibetime hook --agent qoder"
7192
7455
  );
7193
7456
  },
7194
7457
  installEntries(home, env) {
7195
7458
  return [{
7196
7459
  kind: "hooks-json",
7197
- path: path15.join(qoderConfigDir(home, env), "settings.json"),
7460
+ path: path16.join(qoderConfigDir(home, env), "settings.json"),
7198
7461
  content: hookConfig6()
7199
7462
  }];
7200
7463
  },
7201
7464
  sourcePaths(home, env) {
7202
7465
  const base = qoderConfigDir(home, env);
7203
7466
  return [
7204
- path15.join(base, "projects"),
7205
- path15.join(base, ".qoder.json"),
7206
- path15.join(home, ".qoder.json")
7467
+ path16.join(base, "projects"),
7468
+ path16.join(base, ".qoder.json"),
7469
+ path16.join(home, ".qoder.json")
7207
7470
  ];
7208
7471
  },
7209
7472
  parseSessionFile: parseQoderSessionFile
@@ -7238,21 +7501,21 @@ function normalizeId(id) {
7238
7501
  }
7239
7502
 
7240
7503
  // src/adapters/workbuddy.ts
7241
- import { readFile as readFile11, readdir as readdir8, stat as stat8 } from "node:fs/promises";
7242
- import path16 from "node:path";
7504
+ import { readFile as readFile11, readdir as readdir8, stat as stat9 } from "node:fs/promises";
7505
+ import path17 from "node:path";
7243
7506
  init_fs();
7244
7507
  function workbuddyProjectsDir(home, env) {
7245
7508
  const override = env?.WORKBUDDY_PROJECTS_DIR || env?.WORKBUDDY_HOME;
7246
7509
  if (override && override.trim()) {
7247
- return path16.resolve(override, override.endsWith("projects") ? "" : "projects");
7510
+ return path17.resolve(override, override.endsWith("projects") ? "" : "projects");
7248
7511
  }
7249
- return path16.join(home, ".workbuddy", "projects");
7512
+ return path17.join(home, ".workbuddy", "projects");
7250
7513
  }
7251
7514
  function projectFromCwd(cwd, fallback) {
7252
7515
  if (!cwd) {
7253
7516
  return fallback;
7254
7517
  }
7255
- return path16.basename(cwd) || fallback;
7518
+ return path17.basename(cwd) || fallback;
7256
7519
  }
7257
7520
  function sourceHash(filePath) {
7258
7521
  return `sha256:${createStableHash(filePath)}`;
@@ -7354,8 +7617,8 @@ async function parseWorkbuddySessionFile(filePath, options) {
7354
7617
  }
7355
7618
  const events = [];
7356
7619
  const first = lines[0].record;
7357
- const sessionId = stringField(first, "sessionId") || path16.basename(filePath, ".jsonl");
7358
- const fallbackProject = path16.basename(path16.dirname(filePath));
7620
+ const sessionId = stringField(first, "sessionId") || path17.basename(filePath, ".jsonl");
7621
+ const fallbackProject = path17.basename(path17.dirname(filePath));
7359
7622
  const cwd = lines.map((line) => stringField(line.record, "cwd")).find(Boolean);
7360
7623
  const project = projectFromCwd(cwd, fallbackProject);
7361
7624
  const workspaceId = createWorkspaceId({ projectName: project, repoRoot: cwd });
@@ -7529,12 +7792,12 @@ async function workbuddyBackfillFiles(sourceRoot, home, env) {
7529
7792
  if (!project.isDirectory()) {
7530
7793
  continue;
7531
7794
  }
7532
- const projectDir = path16.join(base, project.name);
7795
+ const projectDir = path17.join(base, project.name);
7533
7796
  const entries = await readdir8(projectDir, { withFileTypes: true });
7534
7797
  for (const entry of entries) {
7535
7798
  if (entry.isFile() && entry.name.endsWith(".jsonl")) {
7536
- const filePath = path16.join(projectDir, entry.name);
7537
- const info = await stat8(filePath);
7799
+ const filePath = path17.join(projectDir, entry.name);
7800
+ const info = await stat9(filePath);
7538
7801
  files.push({ path: filePath, modifiedAt: info.mtime.toISOString() });
7539
7802
  }
7540
7803
  }
@@ -7571,26 +7834,26 @@ function createWorkbuddyAdapter() {
7571
7834
 
7572
7835
  // src/adapters/zcode.ts
7573
7836
  import { execFile } from "node:child_process";
7574
- import { readFile as readFile12, stat as stat9 } from "node:fs/promises";
7575
- import path17 from "node:path";
7837
+ import { readFile as readFile12, stat as stat10 } from "node:fs/promises";
7838
+ import path18 from "node:path";
7576
7839
  import { promisify as promisify2 } from "node:util";
7577
7840
  init_fs();
7578
7841
  var execFileAsync = promisify2(execFile);
7579
7842
  function zcodeCliDir(home, env) {
7580
7843
  const override = env?.ZCODE_CLI_DIR || env?.ZCODE_HOME;
7581
7844
  if (override && override.trim()) {
7582
- return path17.resolve(override, override.endsWith("cli") ? "" : "cli");
7845
+ return path18.resolve(override, override.endsWith("cli") ? "" : "cli");
7583
7846
  }
7584
- return path17.join(home, ".zcode", "cli");
7847
+ return path18.join(home, ".zcode", "cli");
7585
7848
  }
7586
7849
  function zcodeDbPath(home, env) {
7587
- return path17.join(zcodeCliDir(home, env), "db", "db.sqlite");
7850
+ return path18.join(zcodeCliDir(home, env), "db", "db.sqlite");
7588
7851
  }
7589
7852
  var providerNameCache = null;
7590
7853
  async function loadProviderNames(configPath2) {
7591
7854
  let fileMtime = 0;
7592
7855
  try {
7593
- const info = await stat9(configPath2);
7856
+ const info = await stat10(configPath2);
7594
7857
  fileMtime = info.mtimeMs;
7595
7858
  } catch {
7596
7859
  return /* @__PURE__ */ new Map();
@@ -7618,7 +7881,7 @@ function sourceHash2(filePath) {
7618
7881
  return `sha256:${createStableHash(filePath)}`;
7619
7882
  }
7620
7883
  function projectFromDirectory(directory) {
7621
- return directory ? path17.basename(directory) || "zcode" : "zcode";
7884
+ return directory ? path18.basename(directory) || "zcode" : "zcode";
7622
7885
  }
7623
7886
  function isoFromMs(value) {
7624
7887
  return timestampFrom(typeof value === "number" ? value : Number(value));
@@ -7774,16 +8037,16 @@ async function parseZCodeDb(filePath, options) {
7774
8037
  if (rows.length === 0) {
7775
8038
  return [];
7776
8039
  }
7777
- let candidate = path17.resolve(filePath);
8040
+ let candidate = path18.resolve(filePath);
7778
8041
  let configPath2 = "";
7779
8042
  for (let i = 0; i < 12; i++) {
7780
- const probe = path17.join(candidate, ".zcode", "v2", "config.json");
8043
+ const probe = path18.join(candidate, ".zcode", "v2", "config.json");
7781
8044
  try {
7782
- await stat9(probe);
8045
+ await stat10(probe);
7783
8046
  configPath2 = probe;
7784
8047
  break;
7785
8048
  } catch {
7786
- const parent = path17.dirname(candidate);
8049
+ const parent = path18.dirname(candidate);
7787
8050
  if (parent === candidate) break;
7788
8051
  candidate = parent;
7789
8052
  }
@@ -7999,9 +8262,9 @@ async function parseZCodeDb(filePath, options) {
7999
8262
  }
8000
8263
  async function zcodeBackfillFiles(sourceRoot, home, env) {
8001
8264
  const candidate = sourceRoot || zcodeDbPath(home, env);
8002
- const filePath = candidate.endsWith(".sqlite") ? candidate : path17.join(candidate, "db", "db.sqlite");
8265
+ const filePath = candidate.endsWith(".sqlite") ? candidate : path18.join(candidate, "db", "db.sqlite");
8003
8266
  try {
8004
- const info = await stat9(filePath);
8267
+ const info = await stat10(filePath);
8005
8268
  return [{ path: filePath, modifiedAt: info.mtime.toISOString() }];
8006
8269
  } catch {
8007
8270
  return [];
@@ -8473,15 +8736,15 @@ function hookCommandFromGroup(group) {
8473
8736
  import { randomUUID } from "node:crypto";
8474
8737
  import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
8475
8738
  import { homedir, hostname } from "node:os";
8476
- import path18 from "node:path";
8739
+ import path19 from "node:path";
8477
8740
  function configDir(home = homedir()) {
8478
- return path18.join(home, ".vibetime");
8741
+ return path19.join(home, ".vibetime");
8479
8742
  }
8480
8743
  function configPath(home = homedir()) {
8481
- return path18.join(configDir(home), "config.json");
8744
+ return path19.join(configDir(home), "config.json");
8482
8745
  }
8483
8746
  function machineIdPath(home = homedir()) {
8484
- return path18.join(configDir(home), "machine-id");
8747
+ return path19.join(configDir(home), "machine-id");
8485
8748
  }
8486
8749
  function readConfig(home = homedir()) {
8487
8750
  const file = configPath(home);
@@ -8528,15 +8791,15 @@ function defaultMachineName() {
8528
8791
  init_fs();
8529
8792
 
8530
8793
  // src/lib/logger.ts
8531
- import { appendFile, mkdir as mkdir4, rename, stat as stat10 } from "node:fs/promises";
8794
+ import { appendFile, mkdir as mkdir4, rename, stat as stat11 } from "node:fs/promises";
8532
8795
  import { homedir as homedir2 } from "node:os";
8533
- import path19 from "node:path";
8796
+ import path20 from "node:path";
8534
8797
  var MAX_BYTES = 1 * 1024 * 1024;
8535
8798
  function logDir(home = homedir2()) {
8536
- return path19.join(home, ".vibetime", "logs");
8799
+ return path20.join(home, ".vibetime", "logs");
8537
8800
  }
8538
8801
  function logPath(home = homedir2(), name = "cli.log") {
8539
- return path19.join(logDir(home), name);
8802
+ return path20.join(logDir(home), name);
8540
8803
  }
8541
8804
  function serializeError(error) {
8542
8805
  if (error instanceof Error) {
@@ -8546,7 +8809,7 @@ function serializeError(error) {
8546
8809
  }
8547
8810
  async function rotateIfNeeded(file) {
8548
8811
  try {
8549
- const info = await stat10(file);
8812
+ const info = await stat11(file);
8550
8813
  if (info.size > MAX_BYTES) {
8551
8814
  await rename(file, `${file}.1`).catch(() => {
8552
8815
  });
@@ -8711,8 +8974,8 @@ function buildHeaders(token, machine) {
8711
8974
  ...machine?.platform ? { "x-machine-platform": machine.platform } : {}
8712
8975
  };
8713
8976
  }
8714
- function joinUrl(base, path21) {
8715
- return new URL(path21, base.endsWith("/") ? base : `${base}/`).toString();
8977
+ function joinUrl(base, path22) {
8978
+ return new URL(path22, base.endsWith("/") ? base : `${base}/`).toString();
8716
8979
  }
8717
8980
  async function postRollupBatch(remote, rollups, options = {}) {
8718
8981
  const response = await remote.fetchImpl(joinUrl(remote.baseUrl, "/v3/agent/ingest"), {
@@ -8777,7 +9040,7 @@ async function deleteMachine(remote, id) {
8777
9040
  }
8778
9041
 
8779
9042
  // src/lib/types.ts
8780
- var BACKFILL_STATE_SCHEMA_VERSION = 5;
9043
+ var BACKFILL_STATE_SCHEMA_VERSION = 6;
8781
9044
 
8782
9045
  // src/cli.ts
8783
9046
  function createRegistry() {
@@ -8802,7 +9065,7 @@ var defaultContext = {
8802
9065
  stdout: process.stdout,
8803
9066
  stderr: process.stderr,
8804
9067
  fetch: globalThis.fetch,
8805
- spawn
9068
+ spawn: spawn2
8806
9069
  };
8807
9070
  async function run(argv, context = {}) {
8808
9071
  const ctx = { ...defaultContext, ...context };
@@ -8953,7 +9216,9 @@ async function fetchLatestVersion() {
8953
9216
  headers: { Accept: "application/json" },
8954
9217
  signal: AbortSignal.timeout(1e4)
8955
9218
  });
8956
- if (!response.ok) return null;
9219
+ if (!response.ok) {
9220
+ return null;
9221
+ }
8957
9222
  const data = await response.json();
8958
9223
  return typeof data.version === "string" ? data.version : null;
8959
9224
  } catch {
@@ -8966,8 +9231,12 @@ function compareVersions(a, b) {
8966
9231
  for (let i = 0; i < Math.max(pa.length, pb.length); i++) {
8967
9232
  const na = pa[i] ?? 0;
8968
9233
  const nb = pb[i] ?? 0;
8969
- if (na > nb) return 1;
8970
- if (na < nb) return -1;
9234
+ if (na > nb) {
9235
+ return 1;
9236
+ }
9237
+ if (na < nb) {
9238
+ return -1;
9239
+ }
8971
9240
  }
8972
9241
  return 0;
8973
9242
  }
@@ -9070,15 +9339,35 @@ async function syncLocalTriggerCommand(options, ctx, _registry) {
9070
9339
  `);
9071
9340
  return 0;
9072
9341
  }
9073
- const child = spawnSyncLocalRunner({ options, ctx, home, lockPath, statePath, triggeredAt: now });
9074
- if (typeof child.pid !== "number") {
9075
- throw new TypeError("Could not start background sync-local runner");
9342
+ const acquired = await acquireSyncLocalLock(lockPath, {
9343
+ pid: process.pid,
9344
+ startedAt: now
9345
+ });
9346
+ if (!acquired) {
9347
+ const current = await readSyncLocalLock(lockPath);
9348
+ if (options.json) {
9349
+ write(ctx.stdout, `${JSON.stringify({
9350
+ status: "already-running",
9351
+ ...current ? { pid: current.pid, startedAt: current.startedAt } : {}
9352
+ }, null, 2)}
9353
+ `);
9354
+ }
9355
+ return 0;
9356
+ }
9357
+ try {
9358
+ const child = spawnSyncLocalRunner({ options, ctx, home, lockPath, statePath, triggeredAt: now });
9359
+ if (typeof child.pid !== "number") {
9360
+ throw new TypeError("Could not start background sync-local runner");
9361
+ }
9362
+ state.lastTriggeredAt = now;
9363
+ state.pid = child.pid;
9364
+ await writeSyncLocalTriggerState(statePath, state);
9365
+ await writeSyncLocalLock(lockPath, { pid: child.pid, startedAt: now });
9366
+ return 0;
9367
+ } catch (error) {
9368
+ await clearSyncLocalLock(lockPath);
9369
+ throw error;
9076
9370
  }
9077
- state.lastTriggeredAt = now;
9078
- state.pid = child.pid;
9079
- await writeSyncLocalTriggerState(statePath, state);
9080
- await writeSyncLocalLock(lockPath, { pid: child.pid, startedAt: now });
9081
- return 0;
9082
9371
  }
9083
9372
  async function syncLocalRunnerCommand(options, ctx, _registry) {
9084
9373
  const home = resolveHome3(options, ctx);
@@ -9284,7 +9573,7 @@ async function listBackfillSourceFiles(source, options, ctx) {
9284
9573
  const fileLists = await Promise.all(roots.map((r) => listJsonlFiles(r)));
9285
9574
  const files = fileLists.flat().sort().slice(0, numberOption(options.limit) || void 0);
9286
9575
  return Promise.all(files.map(async (filePath) => {
9287
- const info = await stat11(filePath);
9576
+ const info = await stat12(filePath);
9288
9577
  return { path: filePath, modifiedAt: info.mtime.toISOString() };
9289
9578
  }));
9290
9579
  }
@@ -9597,13 +9886,13 @@ function selectBackfillFilesForImport(files, watermarkTs) {
9597
9886
  });
9598
9887
  }
9599
9888
  function backfillIncrementalStatePath(home) {
9600
- return path20.join(home, ".vibetime", "backfill-state.json");
9889
+ return path21.join(home, ".vibetime", "backfill-state.json");
9601
9890
  }
9602
9891
  function syncLocalTriggerStatePath(home) {
9603
- return path20.join(home, ".vibetime", "sync-local-trigger.json");
9892
+ return path21.join(home, ".vibetime", "sync-local-trigger.json");
9604
9893
  }
9605
9894
  function syncLocalTriggerLockPath(home) {
9606
- return path20.join(home, ".vibetime", "sync-local-trigger.lock");
9895
+ return path21.join(home, ".vibetime", "sync-local-trigger.lock");
9607
9896
  }
9608
9897
  function backfillRemoteKey(baseUrl) {
9609
9898
  try {
@@ -9665,7 +9954,7 @@ async function readBackfillIncrementalStateFile(home, ctx) {
9665
9954
  }
9666
9955
  async function writeBackfillIncrementalStateFile(home, file) {
9667
9956
  const statePath = backfillIncrementalStatePath(home);
9668
- await mkdir5(path20.dirname(statePath), { recursive: true });
9957
+ await mkdir5(path21.dirname(statePath), { recursive: true });
9669
9958
  await writeFile4(statePath, `${JSON.stringify(file, null, 2)}
9670
9959
  `, "utf8");
9671
9960
  }
@@ -9714,7 +10003,7 @@ async function readSyncLocalTriggerState(statePath) {
9714
10003
  return nextState;
9715
10004
  }
9716
10005
  async function writeSyncLocalTriggerState(statePath, state) {
9717
- await mkdir5(path20.dirname(statePath), { recursive: true });
10006
+ await mkdir5(path21.dirname(statePath), { recursive: true });
9718
10007
  const tmpPath = `${statePath}.${process.pid}.${randomUUID2()}.tmp`;
9719
10008
  await writeFile4(tmpPath, `${JSON.stringify(state, null, 2)}
9720
10009
  `, "utf8");
@@ -9731,10 +10020,28 @@ async function readSyncLocalLock(lockPath) {
9731
10020
  return { pid: lock.pid, startedAt: lock.startedAt };
9732
10021
  }
9733
10022
  async function writeSyncLocalLock(lockPath, lock) {
9734
- await mkdir5(path20.dirname(lockPath), { recursive: true });
10023
+ await mkdir5(path21.dirname(lockPath), { recursive: true });
9735
10024
  await writeFile4(lockPath, `${JSON.stringify(lock, null, 2)}
9736
10025
  `, "utf8");
9737
10026
  }
10027
+ async function acquireSyncLocalLock(lockPath, lock) {
10028
+ await mkdir5(path21.dirname(lockPath), { recursive: true });
10029
+ try {
10030
+ const handle = await open(lockPath, "wx");
10031
+ try {
10032
+ await handle.writeFile(`${JSON.stringify(lock, null, 2)}
10033
+ `, "utf8");
10034
+ } finally {
10035
+ await handle.close();
10036
+ }
10037
+ return true;
10038
+ } catch (error) {
10039
+ if (error.code === "EEXIST") {
10040
+ return false;
10041
+ }
10042
+ throw error;
10043
+ }
10044
+ }
9738
10045
  async function clearSyncLocalLock(lockPath) {
9739
10046
  try {
9740
10047
  await rm(lockPath, { force: true });
@@ -9798,10 +10105,10 @@ function syncLocalRunnerEntryArgs(cliPath) {
9798
10105
  if (cliPath.endsWith(".ts")) {
9799
10106
  return ["--import", "tsx", cliPath];
9800
10107
  }
9801
- return [path20.resolve(path20.dirname(cliPath), "../bin/vibetime.mjs")];
10108
+ return [path21.resolve(path21.dirname(cliPath), "../bin/vibetime.mjs")];
9802
10109
  }
9803
10110
  function resolveHome3(options, ctx) {
9804
- return path20.resolve(stringOption(options.home) || ctx.env.HOME || os9.homedir());
10111
+ return path21.resolve(stringOption(options.home) || ctx.env.HOME || os9.homedir());
9805
10112
  }
9806
10113
  function requestedTargets(options) {
9807
10114
  const value = options.target || options.targets;