@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.
- package/bin/vibetime.mjs +582 -275
- 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
|
|
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
|
|
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 {
|
|
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
|
|
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.
|
|
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.
|
|
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 =
|
|
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
|
-
|
|
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 =
|
|
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 =
|
|
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.
|
|
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] :
|
|
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
|
|
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 =
|
|
1815
|
-
const cacheFile =
|
|
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) =>
|
|
2410
|
+
return override.split(",").map((entry) => entry.trim()).filter(Boolean).map((entry) => path5.resolve(entry));
|
|
2148
2411
|
}
|
|
2149
|
-
return [
|
|
2412
|
+
return [path5.join(home, ".gemini", "antigravity-cli", "brain")];
|
|
2150
2413
|
}
|
|
2151
2414
|
async function agyBackfillFiles(sourceRoot, home, env) {
|
|
2152
|
-
const roots = sourceRoot ? [
|
|
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
|
|
2419
|
+
const info = await stat3(filePath);
|
|
2157
2420
|
return { path: filePath, modifiedAt: info.mtime.toISOString() };
|
|
2158
2421
|
}));
|
|
2159
2422
|
}
|
|
2160
|
-
|
|
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
|
|
2495
|
+
return path5.join(path5.dirname(agyDataDirs(home, env)[0]), "hooks.json");
|
|
2233
2496
|
},
|
|
2234
2497
|
async isInstalled(home, env) {
|
|
2235
|
-
const base =
|
|
2236
|
-
const settingsPath =
|
|
2237
|
-
const hooksPath =
|
|
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 =
|
|
2242
|
-
const settingsPath =
|
|
2243
|
-
const hooksPath =
|
|
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
|
|
2528
|
+
import { readdir as readdir2, readFile as readFile3, stat as stat4 } from "node:fs/promises";
|
|
2266
2529
|
import os2 from "node:os";
|
|
2267
|
-
import
|
|
2530
|
+
import path7 from "node:path";
|
|
2268
2531
|
|
|
2269
2532
|
// src/lib/adapter-helpers.ts
|
|
2270
|
-
import
|
|
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 =
|
|
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 ?
|
|
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 =
|
|
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 &&
|
|
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 ?
|
|
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 =
|
|
3001
|
+
let current = path7.resolve(cwd);
|
|
2739
3002
|
while (!seen.has(current)) {
|
|
2740
3003
|
seen.add(current);
|
|
2741
3004
|
try {
|
|
2742
|
-
await
|
|
3005
|
+
await stat4(path7.join(current, ".git"));
|
|
2743
3006
|
return current;
|
|
2744
3007
|
} catch {
|
|
2745
3008
|
}
|
|
2746
|
-
const parent =
|
|
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 =
|
|
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 =
|
|
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
|
|
3035
|
+
return path7.resolve(value).split(path7.sep).join("-").replace(/_/g, "-");
|
|
2773
3036
|
}
|
|
2774
3037
|
function rawClaudeProjectPath(value) {
|
|
2775
|
-
return
|
|
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 =
|
|
2792
|
-
const home = options ?
|
|
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
|
|
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 =
|
|
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
|
|
3129
|
+
return path7.resolve(override);
|
|
2867
3130
|
}
|
|
2868
|
-
return
|
|
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
|
|
3143
|
+
return path7.join(claudeConfigDir(home, env), "settings.json");
|
|
2881
3144
|
},
|
|
2882
3145
|
async isInstalled(home, env) {
|
|
2883
3146
|
return isHooksJsonInstalled(
|
|
2884
|
-
|
|
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:
|
|
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
|
-
|
|
2899
|
-
|
|
2900
|
-
|
|
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
|
|
3171
|
+
import { readdir as readdir3, readFile as readFile4, stat as stat5 } from "node:fs/promises";
|
|
2909
3172
|
import os3 from "node:os";
|
|
2910
|
-
import
|
|
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) =>
|
|
3179
|
+
return override.split(",").map((item) => item.trim()).filter(Boolean).map((item) => path8.resolve(item));
|
|
2917
3180
|
}
|
|
2918
3181
|
return [
|
|
2919
|
-
|
|
2920
|
-
|
|
2921
|
-
|
|
2922
|
-
|
|
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
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 = `${
|
|
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 =
|
|
3308
|
+
const resolved = path8.resolve(folder);
|
|
3046
3309
|
return {
|
|
3047
|
-
project:
|
|
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 ? [
|
|
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
|
|
3373
|
+
const transcriptInfo = await stat5(transcriptPath);
|
|
3111
3374
|
let modifiedAt = transcriptInfo.mtime;
|
|
3112
3375
|
try {
|
|
3113
|
-
const metaInfo = await
|
|
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] ||
|
|
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
|
|
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 ?
|
|
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 =
|
|
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 ?
|
|
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 =
|
|
3836
|
+
const sessionsDir = path9.join(home, ".codebuddy", "sessions");
|
|
3574
3837
|
if (pid) {
|
|
3575
|
-
const cwd = await readCwdFromSession(
|
|
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
|
-
|
|
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 =
|
|
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
|
|
3927
|
+
return path9.resolve(override);
|
|
3665
3928
|
}
|
|
3666
|
-
return
|
|
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
|
|
3941
|
+
return path9.join(codebuddyConfigDir(home, env), "settings.json");
|
|
3679
3942
|
},
|
|
3680
3943
|
async isInstalled(home, env) {
|
|
3681
3944
|
return isHooksJsonInstalled(
|
|
3682
|
-
|
|
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:
|
|
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
|
-
|
|
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 ||
|
|
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 =
|
|
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 =
|
|
3981
|
+
const filePath = path9.join(traceDir, entry);
|
|
3719
3982
|
try {
|
|
3720
|
-
const
|
|
3721
|
-
files.push({ path: filePath, modifiedAt:
|
|
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
|
|
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
|
|
4047
|
+
import path10 from "node:path";
|
|
3785
4048
|
var SESSION_CONTEXT_VERSION = 1;
|
|
3786
4049
|
function sessionContextDir(home) {
|
|
3787
|
-
return
|
|
4050
|
+
return path10.join(home, ".vibetime", "session-context");
|
|
3788
4051
|
}
|
|
3789
4052
|
function sessionContextPath(home, sessionId) {
|
|
3790
|
-
return
|
|
4053
|
+
return path10.join(sessionContextDir(home), `${encodeURIComponent(sessionId)}.json`);
|
|
3791
4054
|
}
|
|
3792
4055
|
function resolveHome2(options) {
|
|
3793
|
-
return options ?
|
|
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 || !
|
|
4082
|
+
if (!sessionId || !cwd || !path10.isAbsolute(cwd)) {
|
|
3820
4083
|
return;
|
|
3821
4084
|
}
|
|
3822
|
-
const project =
|
|
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 ?
|
|
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 ?
|
|
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 || !
|
|
4604
|
+
if (!cwd || !path11.isAbsolute(filePath)) {
|
|
4342
4605
|
return filePath;
|
|
4343
4606
|
}
|
|
4344
|
-
const relative =
|
|
4345
|
-
return relative && !relative.startsWith("..") && !
|
|
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
|
|
4627
|
+
return path11.resolve(override);
|
|
4365
4628
|
}
|
|
4366
|
-
return
|
|
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
|
|
4641
|
+
return path11.join(codexHome(home, env), "hooks.json");
|
|
4379
4642
|
},
|
|
4380
4643
|
async isInstalled(home, env) {
|
|
4381
4644
|
return isHooksJsonInstalled(
|
|
4382
|
-
|
|
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:
|
|
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
|
-
|
|
4397
|
-
|
|
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
|
|
4668
|
+
import { readdir as readdir5, readFile as readFile7, stat as stat6 } from "node:fs/promises";
|
|
4406
4669
|
import os5 from "node:os";
|
|
4407
|
-
import
|
|
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 ?
|
|
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 ||
|
|
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 =
|
|
4688
|
-
const info = await
|
|
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
|
|
4968
|
+
return path12.resolve(override);
|
|
4706
4969
|
}
|
|
4707
|
-
return
|
|
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
|
|
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(
|
|
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:
|
|
4995
|
+
path: path12.join(copilotHome(home, env), ".vibetime"),
|
|
4733
4996
|
content: copilotPluginContent()
|
|
4734
4997
|
}];
|
|
4735
4998
|
},
|
|
4736
4999
|
sourcePaths(home, env) {
|
|
4737
|
-
return [
|
|
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
|
|
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 ?
|
|
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 ?
|
|
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
|
|
5393
|
+
return path13.resolve(override);
|
|
5131
5394
|
}
|
|
5132
5395
|
const xdgConfig = env?.XDG_CONFIG_HOME;
|
|
5133
5396
|
if (xdgConfig && xdgConfig.trim()) {
|
|
5134
|
-
return
|
|
5397
|
+
return path13.join(path13.resolve(xdgConfig), "opencode");
|
|
5135
5398
|
}
|
|
5136
|
-
return
|
|
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() ?
|
|
5141
|
-
return [primary,
|
|
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:
|
|
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
|
|
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
|
|
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
|
|
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(
|
|
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:
|
|
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
|
|
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 ?
|
|
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
|
|
5962
|
+
return path14.resolve(override);
|
|
5700
5963
|
}
|
|
5701
|
-
return
|
|
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
|
|
5969
|
+
return path14.resolve(override);
|
|
5707
5970
|
}
|
|
5708
|
-
return
|
|
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
|
|
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(
|
|
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:
|
|
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
|
|
6008
|
+
import { readdir as readdir6, readFile as readFile9, stat as stat7 } from "node:fs/promises";
|
|
5746
6009
|
import os7 from "node:os";
|
|
5747
|
-
import
|
|
6010
|
+
import path15 from "node:path";
|
|
5748
6011
|
function parseQoderCnPaths(filePath) {
|
|
5749
|
-
const parts = filePath.split(
|
|
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(
|
|
6021
|
+
configDir2 = parts.slice(0, projectsIdx).join(path15.sep);
|
|
5759
6022
|
} else {
|
|
5760
6023
|
const filename = parts.at(-1) || "";
|
|
5761
|
-
sessionId =
|
|
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(
|
|
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 =
|
|
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 =
|
|
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(
|
|
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 ?
|
|
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(`${
|
|
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 &&
|
|
6562
|
+
if (cwd && path15.isAbsolute(cwd)) {
|
|
6300
6563
|
cwds.push(cwd);
|
|
6301
6564
|
}
|
|
6302
6565
|
}
|
|
6303
6566
|
if (isSubagent) {
|
|
6304
|
-
if (inherited?.cwd &&
|
|
6567
|
+
if (inherited?.cwd && path15.isAbsolute(inherited.cwd)) {
|
|
6305
6568
|
cwds = [inherited.cwd];
|
|
6306
6569
|
} else {
|
|
6307
|
-
const parentSessionPath =
|
|
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 &&
|
|
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 ?
|
|
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 =
|
|
6598
|
+
let current = path15.resolve(cwd);
|
|
6336
6599
|
while (!seen.has(current)) {
|
|
6337
6600
|
seen.add(current);
|
|
6338
6601
|
try {
|
|
6339
|
-
await
|
|
6602
|
+
await stat7(path15.join(current, ".git"));
|
|
6340
6603
|
return current;
|
|
6341
6604
|
} catch {
|
|
6342
6605
|
}
|
|
6343
|
-
const parent =
|
|
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 =
|
|
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 =
|
|
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
|
|
6632
|
+
return path15.resolve(value).split(path15.sep).join("-").replace(/_/g, "-");
|
|
6370
6633
|
}
|
|
6371
6634
|
async function qoderCnProjectFromFilePath(filePath, options) {
|
|
6372
|
-
const projectDir =
|
|
6373
|
-
const home = options ?
|
|
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
|
|
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 =
|
|
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
|
|
6709
|
+
return path15.resolve(override);
|
|
6447
6710
|
}
|
|
6448
|
-
return
|
|
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
|
|
6723
|
+
return path15.join(qoderCnConfigDir(home, env), "settings.json");
|
|
6461
6724
|
},
|
|
6462
6725
|
async isInstalled(home, env) {
|
|
6463
6726
|
return isHooksJsonInstalled(
|
|
6464
|
-
|
|
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:
|
|
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
|
-
|
|
6479
|
-
|
|
6480
|
-
|
|
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
|
|
6751
|
+
import { readdir as readdir7, readFile as readFile10, stat as stat8 } from "node:fs/promises";
|
|
6489
6752
|
import os8 from "node:os";
|
|
6490
|
-
import
|
|
6753
|
+
import path16 from "node:path";
|
|
6491
6754
|
function parseQoderPaths(filePath) {
|
|
6492
|
-
const parts = filePath.split(
|
|
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(
|
|
6764
|
+
configDir2 = parts.slice(0, projectsIdx).join(path16.sep);
|
|
6502
6765
|
} else {
|
|
6503
6766
|
const filename = parts.at(-1) || "";
|
|
6504
|
-
sessionId =
|
|
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(
|
|
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 =
|
|
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 =
|
|
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(
|
|
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 ?
|
|
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(`${
|
|
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 &&
|
|
7271
|
+
if (cwd && path16.isAbsolute(cwd)) {
|
|
7009
7272
|
cwds.push(cwd);
|
|
7010
7273
|
}
|
|
7011
7274
|
}
|
|
7012
7275
|
if (isSubagent) {
|
|
7013
|
-
if (inherited?.cwd &&
|
|
7276
|
+
if (inherited?.cwd && path16.isAbsolute(inherited.cwd)) {
|
|
7014
7277
|
cwds = [inherited.cwd];
|
|
7015
7278
|
} else {
|
|
7016
|
-
const parentSessionPath =
|
|
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 &&
|
|
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 ?
|
|
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 =
|
|
7307
|
+
let current = path16.resolve(cwd);
|
|
7045
7308
|
while (!seen.has(current)) {
|
|
7046
7309
|
seen.add(current);
|
|
7047
7310
|
try {
|
|
7048
|
-
await
|
|
7311
|
+
await stat8(path16.join(current, ".git"));
|
|
7049
7312
|
return current;
|
|
7050
7313
|
} catch {
|
|
7051
7314
|
}
|
|
7052
|
-
const parent =
|
|
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 =
|
|
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 =
|
|
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
|
|
7341
|
+
return path16.resolve(value).split(path16.sep).join("-").replace(/_/g, "-");
|
|
7079
7342
|
}
|
|
7080
7343
|
function rawQoderProjectPath(value) {
|
|
7081
|
-
return
|
|
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 =
|
|
7098
|
-
const home = options ?
|
|
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
|
|
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 =
|
|
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
|
|
7435
|
+
return path16.resolve(override);
|
|
7173
7436
|
}
|
|
7174
|
-
return
|
|
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
|
|
7449
|
+
return path16.join(qoderConfigDir(home, env), "settings.json");
|
|
7187
7450
|
},
|
|
7188
7451
|
async isInstalled(home, env) {
|
|
7189
7452
|
return isHooksJsonInstalled(
|
|
7190
|
-
|
|
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:
|
|
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
|
-
|
|
7205
|
-
|
|
7206
|
-
|
|
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
|
|
7242
|
-
import
|
|
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
|
|
7510
|
+
return path17.resolve(override, override.endsWith("projects") ? "" : "projects");
|
|
7248
7511
|
}
|
|
7249
|
-
return
|
|
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
|
|
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") ||
|
|
7358
|
-
const fallbackProject =
|
|
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 =
|
|
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 =
|
|
7537
|
-
const info = await
|
|
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
|
|
7575
|
-
import
|
|
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
|
|
7845
|
+
return path18.resolve(override, override.endsWith("cli") ? "" : "cli");
|
|
7583
7846
|
}
|
|
7584
|
-
return
|
|
7847
|
+
return path18.join(home, ".zcode", "cli");
|
|
7585
7848
|
}
|
|
7586
7849
|
function zcodeDbPath(home, env) {
|
|
7587
|
-
return
|
|
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
|
|
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 ?
|
|
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 =
|
|
8040
|
+
let candidate = path18.resolve(filePath);
|
|
7778
8041
|
let configPath2 = "";
|
|
7779
8042
|
for (let i = 0; i < 12; i++) {
|
|
7780
|
-
const probe =
|
|
8043
|
+
const probe = path18.join(candidate, ".zcode", "v2", "config.json");
|
|
7781
8044
|
try {
|
|
7782
|
-
await
|
|
8045
|
+
await stat10(probe);
|
|
7783
8046
|
configPath2 = probe;
|
|
7784
8047
|
break;
|
|
7785
8048
|
} catch {
|
|
7786
|
-
const parent =
|
|
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 :
|
|
8265
|
+
const filePath = candidate.endsWith(".sqlite") ? candidate : path18.join(candidate, "db", "db.sqlite");
|
|
8003
8266
|
try {
|
|
8004
|
-
const info = await
|
|
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
|
|
8739
|
+
import path19 from "node:path";
|
|
8477
8740
|
function configDir(home = homedir()) {
|
|
8478
|
-
return
|
|
8741
|
+
return path19.join(home, ".vibetime");
|
|
8479
8742
|
}
|
|
8480
8743
|
function configPath(home = homedir()) {
|
|
8481
|
-
return
|
|
8744
|
+
return path19.join(configDir(home), "config.json");
|
|
8482
8745
|
}
|
|
8483
8746
|
function machineIdPath(home = homedir()) {
|
|
8484
|
-
return
|
|
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
|
|
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
|
|
8796
|
+
import path20 from "node:path";
|
|
8534
8797
|
var MAX_BYTES = 1 * 1024 * 1024;
|
|
8535
8798
|
function logDir(home = homedir2()) {
|
|
8536
|
-
return
|
|
8799
|
+
return path20.join(home, ".vibetime", "logs");
|
|
8537
8800
|
}
|
|
8538
8801
|
function logPath(home = homedir2(), name = "cli.log") {
|
|
8539
|
-
return
|
|
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
|
|
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,
|
|
8715
|
-
return new URL(
|
|
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 =
|
|
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)
|
|
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)
|
|
8970
|
-
|
|
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
|
|
9074
|
-
|
|
9075
|
-
|
|
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
|
|
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
|
|
9889
|
+
return path21.join(home, ".vibetime", "backfill-state.json");
|
|
9601
9890
|
}
|
|
9602
9891
|
function syncLocalTriggerStatePath(home) {
|
|
9603
|
-
return
|
|
9892
|
+
return path21.join(home, ".vibetime", "sync-local-trigger.json");
|
|
9604
9893
|
}
|
|
9605
9894
|
function syncLocalTriggerLockPath(home) {
|
|
9606
|
-
return
|
|
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(
|
|
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(
|
|
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(
|
|
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 [
|
|
10108
|
+
return [path21.resolve(path21.dirname(cliPath), "../bin/vibetime.mjs")];
|
|
9802
10109
|
}
|
|
9803
10110
|
function resolveHome3(options, ctx) {
|
|
9804
|
-
return
|
|
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;
|