@yhong91/vibetime 0.1.58 → 0.1.59
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 +550 -36
- package/package.json +1 -1
package/bin/vibetime.mjs
CHANGED
|
@@ -884,7 +884,7 @@ var init_esm = __esm({
|
|
|
884
884
|
|
|
885
885
|
// src/cli.ts
|
|
886
886
|
import { spawn as spawn2, spawnSync } from "node:child_process";
|
|
887
|
-
import { mkdir as
|
|
887
|
+
import { mkdir as mkdir6, open, rm, stat as stat16, writeFile as writeFile5 } from "node:fs/promises";
|
|
888
888
|
import os13 from "node:os";
|
|
889
889
|
import path26 from "node:path";
|
|
890
890
|
import { fileURLToPath } from "node:url";
|
|
@@ -2047,7 +2047,7 @@ function claudeStyleFileMetrics(tool, input) {
|
|
|
2047
2047
|
}
|
|
2048
2048
|
|
|
2049
2049
|
// src/lib/constants.ts
|
|
2050
|
-
var PACKAGE_VERSION = true ? "0.1.
|
|
2050
|
+
var PACKAGE_VERSION = true ? "0.1.59" : "0.1.1";
|
|
2051
2051
|
var GENERATED_MARKER = "Generated by vibetime.";
|
|
2052
2052
|
var DEFAULT_API_URL = "http://121.196.224.82:3001";
|
|
2053
2053
|
var DEFAULT_BACKFILL_BATCH_SIZE = 50;
|
|
@@ -6292,7 +6292,7 @@ function createCopilotAdapter() {
|
|
|
6292
6292
|
}
|
|
6293
6293
|
|
|
6294
6294
|
// src/adapters/cursor.ts
|
|
6295
|
-
import { copyFile, readdir as readdir6, readFile as readFile8, stat as stat8 } from "node:fs/promises";
|
|
6295
|
+
import { copyFile, mkdir as mkdir4, readdir as readdir6, readFile as readFile8, stat as stat8, writeFile as writeFile4 } from "node:fs/promises";
|
|
6296
6296
|
import os6 from "node:os";
|
|
6297
6297
|
import path13 from "node:path";
|
|
6298
6298
|
|
|
@@ -6400,6 +6400,222 @@ function collectCursorHookCommands(content) {
|
|
|
6400
6400
|
|
|
6401
6401
|
// src/adapters/cursor.ts
|
|
6402
6402
|
init_fs();
|
|
6403
|
+
|
|
6404
|
+
// src/adapters/cursor-cloud-usage.ts
|
|
6405
|
+
var CURSOR_CLOUD_USAGE_GENERATION_ID = "cursor-cloud";
|
|
6406
|
+
var CURSOR_CLOUD_USAGE_FILENAME = "cursor-cloud-usage.json";
|
|
6407
|
+
var CURSOR_CLOUD_AGENT_PROJECT = "Cloud Agent";
|
|
6408
|
+
var CURSOR_DASHBOARD_USAGE_URL = "https://cursor.com/api/dashboard/get-filtered-usage-events";
|
|
6409
|
+
var CURSOR_CLOUD_USAGE_CACHE_VERSION = 1;
|
|
6410
|
+
var DEFAULT_WINDOW_DAYS = 90;
|
|
6411
|
+
var PAGE_SIZE = 1e3;
|
|
6412
|
+
function cursorCloudUsageDisabled(env = process.env) {
|
|
6413
|
+
const value = env.VIBETIME_CURSOR_CLOUD_USAGE;
|
|
6414
|
+
return value === "0" || value === "false";
|
|
6415
|
+
}
|
|
6416
|
+
function cursorSessionCookie(accessToken) {
|
|
6417
|
+
const token = accessToken.trim();
|
|
6418
|
+
if (!token) {
|
|
6419
|
+
return void 0;
|
|
6420
|
+
}
|
|
6421
|
+
const payload = jwtPayload(token);
|
|
6422
|
+
const userId = String(payload?.sub || "").split("|").at(-1)?.trim();
|
|
6423
|
+
if (!userId) {
|
|
6424
|
+
return void 0;
|
|
6425
|
+
}
|
|
6426
|
+
return `WorkosCursorSessionToken=${userId}%3A%3A${token}`;
|
|
6427
|
+
}
|
|
6428
|
+
function cursorCloudEventFromDashboard(event) {
|
|
6429
|
+
if (!isPlainObject(event)) {
|
|
6430
|
+
return void 0;
|
|
6431
|
+
}
|
|
6432
|
+
const conversationId = stringField(event, "conversationId")?.trim();
|
|
6433
|
+
if (!conversationId) {
|
|
6434
|
+
return void 0;
|
|
6435
|
+
}
|
|
6436
|
+
const tokenUsage = objectField(event, "tokenUsage");
|
|
6437
|
+
const tokensInput = numberField(tokenUsage, "inputTokens") || 0;
|
|
6438
|
+
const tokensOutput = numberField(tokenUsage, "outputTokens") || 0;
|
|
6439
|
+
const tokensCacheReadInput = numberField(tokenUsage, "cacheReadTokens") || 0;
|
|
6440
|
+
const tokensCacheCreationInput = numberField(tokenUsage, "cacheWriteTokens") || 0;
|
|
6441
|
+
if (tokensInput <= 0 && tokensOutput <= 0 && tokensCacheReadInput <= 0 && tokensCacheCreationInput <= 0) {
|
|
6442
|
+
return void 0;
|
|
6443
|
+
}
|
|
6444
|
+
return {
|
|
6445
|
+
conversationId,
|
|
6446
|
+
model: stringField(event, "model") || void 0,
|
|
6447
|
+
ts: timestampFrom(event.timestamp) || (/* @__PURE__ */ new Date(0)).toISOString(),
|
|
6448
|
+
tokensInput,
|
|
6449
|
+
tokensOutput,
|
|
6450
|
+
tokensCacheReadInput,
|
|
6451
|
+
tokensCacheCreationInput
|
|
6452
|
+
};
|
|
6453
|
+
}
|
|
6454
|
+
function groupCursorUsageEvents(events) {
|
|
6455
|
+
const byConversation = /* @__PURE__ */ new Map();
|
|
6456
|
+
for (const event of events) {
|
|
6457
|
+
const parsed = cursorCloudEventFromDashboard(event);
|
|
6458
|
+
if (!parsed) {
|
|
6459
|
+
continue;
|
|
6460
|
+
}
|
|
6461
|
+
const current = byConversation.get(parsed.conversationId);
|
|
6462
|
+
if (current) {
|
|
6463
|
+
current.push(parsed);
|
|
6464
|
+
} else {
|
|
6465
|
+
byConversation.set(parsed.conversationId, [parsed]);
|
|
6466
|
+
}
|
|
6467
|
+
}
|
|
6468
|
+
return byConversation;
|
|
6469
|
+
}
|
|
6470
|
+
function sumCursorCloudEvents(conversationId, events) {
|
|
6471
|
+
if (events.length === 0) {
|
|
6472
|
+
return void 0;
|
|
6473
|
+
}
|
|
6474
|
+
const first = events[0];
|
|
6475
|
+
const firstStart = first.startedAt || first.ts;
|
|
6476
|
+
const summed = {
|
|
6477
|
+
conversationId,
|
|
6478
|
+
model: first.model,
|
|
6479
|
+
ts: first.ts,
|
|
6480
|
+
startedAt: firstStart,
|
|
6481
|
+
tokensInput: 0,
|
|
6482
|
+
tokensOutput: 0,
|
|
6483
|
+
tokensCacheReadInput: 0,
|
|
6484
|
+
tokensCacheCreationInput: 0
|
|
6485
|
+
};
|
|
6486
|
+
for (const event of events) {
|
|
6487
|
+
summed.tokensInput += event.tokensInput;
|
|
6488
|
+
summed.tokensOutput += event.tokensOutput;
|
|
6489
|
+
summed.tokensCacheReadInput += event.tokensCacheReadInput;
|
|
6490
|
+
summed.tokensCacheCreationInput += event.tokensCacheCreationInput;
|
|
6491
|
+
const eventStart = event.startedAt || event.ts;
|
|
6492
|
+
if (Date.parse(eventStart) < Date.parse(summed.startedAt)) {
|
|
6493
|
+
summed.startedAt = eventStart;
|
|
6494
|
+
}
|
|
6495
|
+
if (Date.parse(event.ts) >= Date.parse(summed.ts)) {
|
|
6496
|
+
summed.ts = event.ts;
|
|
6497
|
+
if (event.model) {
|
|
6498
|
+
summed.model = event.model;
|
|
6499
|
+
}
|
|
6500
|
+
}
|
|
6501
|
+
}
|
|
6502
|
+
return summed;
|
|
6503
|
+
}
|
|
6504
|
+
function hookUncachedInputTokens(turn) {
|
|
6505
|
+
return Math.max(0, (turn.tokensInput || 0) - (turn.tokensCacheReadInput || 0));
|
|
6506
|
+
}
|
|
6507
|
+
function cloudEventMatchesHookTurn(event, turn) {
|
|
6508
|
+
return event.tokensInput === hookUncachedInputTokens(turn) && event.tokensOutput === (turn.tokensOutput || 0) && event.tokensCacheReadInput === (turn.tokensCacheReadInput || 0);
|
|
6509
|
+
}
|
|
6510
|
+
function unmatchedCloudEvents(events, turns) {
|
|
6511
|
+
const used = /* @__PURE__ */ new Set();
|
|
6512
|
+
for (const turn of turns) {
|
|
6513
|
+
const index = events.findIndex((event, i) => !used.has(i) && cloudEventMatchesHookTurn(event, turn));
|
|
6514
|
+
if (index >= 0) {
|
|
6515
|
+
used.add(index);
|
|
6516
|
+
}
|
|
6517
|
+
}
|
|
6518
|
+
return events.filter((_, i) => !used.has(i));
|
|
6519
|
+
}
|
|
6520
|
+
async function fetchCursorDashboardUsage(args) {
|
|
6521
|
+
const cookie = cursorSessionCookie(args.accessToken);
|
|
6522
|
+
if (!cookie) {
|
|
6523
|
+
return /* @__PURE__ */ new Map();
|
|
6524
|
+
}
|
|
6525
|
+
const fetchImpl = args.fetchImpl || fetch;
|
|
6526
|
+
const now = args.now || /* @__PURE__ */ new Date();
|
|
6527
|
+
const windowDays = args.windowDays ?? DEFAULT_WINDOW_DAYS;
|
|
6528
|
+
const pageSize = args.pageSize ?? PAGE_SIZE;
|
|
6529
|
+
const start = new Date(now.getTime() - windowDays * 24 * 60 * 60 * 1e3);
|
|
6530
|
+
const events = [];
|
|
6531
|
+
let page = 1;
|
|
6532
|
+
let total = Number.POSITIVE_INFINITY;
|
|
6533
|
+
while ((page - 1) * pageSize < total) {
|
|
6534
|
+
const body = JSON.stringify({
|
|
6535
|
+
page,
|
|
6536
|
+
pageSize,
|
|
6537
|
+
startDate: String(start.getTime()),
|
|
6538
|
+
endDate: String(now.getTime())
|
|
6539
|
+
});
|
|
6540
|
+
const response = await fetchImpl(CURSOR_DASHBOARD_USAGE_URL, {
|
|
6541
|
+
method: "POST",
|
|
6542
|
+
headers: {
|
|
6543
|
+
"Content-Type": "application/json",
|
|
6544
|
+
Accept: "application/json",
|
|
6545
|
+
Cookie: cookie,
|
|
6546
|
+
Origin: "https://cursor.com",
|
|
6547
|
+
Referer: "https://cursor.com/settings",
|
|
6548
|
+
"User-Agent": "vibetime-cli"
|
|
6549
|
+
},
|
|
6550
|
+
body,
|
|
6551
|
+
signal: AbortSignal.timeout(2e4)
|
|
6552
|
+
});
|
|
6553
|
+
if (!response.ok) {
|
|
6554
|
+
return /* @__PURE__ */ new Map();
|
|
6555
|
+
}
|
|
6556
|
+
const payload = await response.json();
|
|
6557
|
+
if (!isPlainObject(payload)) {
|
|
6558
|
+
return /* @__PURE__ */ new Map();
|
|
6559
|
+
}
|
|
6560
|
+
const pageEvents = Array.isArray(payload.usageEventsDisplay) ? payload.usageEventsDisplay : [];
|
|
6561
|
+
events.push(...pageEvents);
|
|
6562
|
+
const reported = numberField(payload, "totalUsageEventsCount");
|
|
6563
|
+
total = reported ?? pageEvents.length;
|
|
6564
|
+
if (pageEvents.length < pageSize) {
|
|
6565
|
+
break;
|
|
6566
|
+
}
|
|
6567
|
+
page += 1;
|
|
6568
|
+
}
|
|
6569
|
+
return groupCursorUsageEvents(events);
|
|
6570
|
+
}
|
|
6571
|
+
function serializeCursorCloudUsageCache(sessions) {
|
|
6572
|
+
const sorted = [...sessions].sort((a, b) => a.conversationId.localeCompare(b.conversationId));
|
|
6573
|
+
return `${JSON.stringify({ version: CURSOR_CLOUD_USAGE_CACHE_VERSION, sessions: sorted }, null, 2)}
|
|
6574
|
+
`;
|
|
6575
|
+
}
|
|
6576
|
+
function parseCursorCloudUsageCache(raw) {
|
|
6577
|
+
if (!isPlainObject(raw) || raw.version !== CURSOR_CLOUD_USAGE_CACHE_VERSION || !Array.isArray(raw.sessions)) {
|
|
6578
|
+
return [];
|
|
6579
|
+
}
|
|
6580
|
+
const sessions = [];
|
|
6581
|
+
for (const item of raw.sessions) {
|
|
6582
|
+
if (!isPlainObject(item)) {
|
|
6583
|
+
continue;
|
|
6584
|
+
}
|
|
6585
|
+
const conversationId = stringField(item, "conversationId")?.trim();
|
|
6586
|
+
const ts = stringField(item, "ts");
|
|
6587
|
+
const startedAt = stringField(item, "startedAt") || ts;
|
|
6588
|
+
if (!conversationId || !ts || !startedAt) {
|
|
6589
|
+
continue;
|
|
6590
|
+
}
|
|
6591
|
+
sessions.push({
|
|
6592
|
+
conversationId,
|
|
6593
|
+
model: stringField(item, "model"),
|
|
6594
|
+
ts,
|
|
6595
|
+
startedAt,
|
|
6596
|
+
tokensInput: numberField(item, "tokensInput") || 0,
|
|
6597
|
+
tokensOutput: numberField(item, "tokensOutput") || 0,
|
|
6598
|
+
tokensCacheReadInput: numberField(item, "tokensCacheReadInput") || 0,
|
|
6599
|
+
tokensCacheCreationInput: numberField(item, "tokensCacheCreationInput") || 0
|
|
6600
|
+
});
|
|
6601
|
+
}
|
|
6602
|
+
return sessions;
|
|
6603
|
+
}
|
|
6604
|
+
function jwtPayload(token) {
|
|
6605
|
+
const segment = token.split(".")[1];
|
|
6606
|
+
if (!segment) {
|
|
6607
|
+
return void 0;
|
|
6608
|
+
}
|
|
6609
|
+
try {
|
|
6610
|
+
const json = Buffer.from(segment, "base64url").toString("utf8");
|
|
6611
|
+
const parsed = JSON.parse(json);
|
|
6612
|
+
return isPlainObject(parsed) ? parsed : void 0;
|
|
6613
|
+
} catch {
|
|
6614
|
+
return void 0;
|
|
6615
|
+
}
|
|
6616
|
+
}
|
|
6617
|
+
|
|
6618
|
+
// src/adapters/cursor.ts
|
|
6403
6619
|
var SOURCE_ID = "cursor";
|
|
6404
6620
|
var AGENT_NAME = "cursor";
|
|
6405
6621
|
var HOOK_COMMAND = `vibetime hook --agent ${SOURCE_ID}`;
|
|
@@ -6468,6 +6684,297 @@ function cursorStateDbCandidates(home, env) {
|
|
|
6468
6684
|
}
|
|
6469
6685
|
return candidates;
|
|
6470
6686
|
}
|
|
6687
|
+
var cursorCloudUsageByOptions = /* @__PURE__ */ new WeakMap();
|
|
6688
|
+
function isCursorStateDbPath(filePath) {
|
|
6689
|
+
if (!filePath) {
|
|
6690
|
+
return false;
|
|
6691
|
+
}
|
|
6692
|
+
const base = path13.basename(filePath);
|
|
6693
|
+
return base === "state.vscdb" || base.endsWith(".vscdb");
|
|
6694
|
+
}
|
|
6695
|
+
function injectedCloudEvent(conversationId, item) {
|
|
6696
|
+
const tokensInput = numberField(item, "tokensInput") || numberField(item, "inputTokens") || 0;
|
|
6697
|
+
const tokensOutput = numberField(item, "tokensOutput") || numberField(item, "outputTokens") || 0;
|
|
6698
|
+
const tokensCacheReadInput = numberField(item, "tokensCacheReadInput") || numberField(item, "cacheReadTokens") || 0;
|
|
6699
|
+
const tokensCacheCreationInput = numberField(item, "tokensCacheCreationInput") || numberField(item, "cacheWriteTokens") || 0;
|
|
6700
|
+
if (tokensInput <= 0 && tokensOutput <= 0 && tokensCacheReadInput <= 0 && tokensCacheCreationInput <= 0) {
|
|
6701
|
+
return void 0;
|
|
6702
|
+
}
|
|
6703
|
+
const ts = stringField(item, "ts") || (/* @__PURE__ */ new Date(0)).toISOString();
|
|
6704
|
+
return {
|
|
6705
|
+
conversationId,
|
|
6706
|
+
model: stringField(item, "model"),
|
|
6707
|
+
ts,
|
|
6708
|
+
startedAt: stringField(item, "startedAt") || void 0,
|
|
6709
|
+
tokensInput,
|
|
6710
|
+
tokensOutput,
|
|
6711
|
+
tokensCacheReadInput,
|
|
6712
|
+
tokensCacheCreationInput
|
|
6713
|
+
};
|
|
6714
|
+
}
|
|
6715
|
+
function injectedCursorCloudUsage(options) {
|
|
6716
|
+
if (!Object.prototype.hasOwnProperty.call(options, "cursorCloudUsage")) {
|
|
6717
|
+
return void 0;
|
|
6718
|
+
}
|
|
6719
|
+
const raw = options.cursorCloudUsage;
|
|
6720
|
+
const map = /* @__PURE__ */ new Map();
|
|
6721
|
+
if (!isPlainObject(raw)) {
|
|
6722
|
+
return map;
|
|
6723
|
+
}
|
|
6724
|
+
for (const [conversationId, item] of Object.entries(raw)) {
|
|
6725
|
+
if (!conversationId) {
|
|
6726
|
+
continue;
|
|
6727
|
+
}
|
|
6728
|
+
const events = [];
|
|
6729
|
+
if (Array.isArray(item)) {
|
|
6730
|
+
for (const entry of item) {
|
|
6731
|
+
if (isPlainObject(entry)) {
|
|
6732
|
+
const parsed = injectedCloudEvent(conversationId, entry);
|
|
6733
|
+
if (parsed) {
|
|
6734
|
+
events.push(parsed);
|
|
6735
|
+
}
|
|
6736
|
+
}
|
|
6737
|
+
}
|
|
6738
|
+
} else if (isPlainObject(item) && Array.isArray(item.events)) {
|
|
6739
|
+
for (const entry of item.events) {
|
|
6740
|
+
if (isPlainObject(entry)) {
|
|
6741
|
+
const parsed = injectedCloudEvent(conversationId, entry);
|
|
6742
|
+
if (parsed) {
|
|
6743
|
+
events.push(parsed);
|
|
6744
|
+
}
|
|
6745
|
+
}
|
|
6746
|
+
}
|
|
6747
|
+
} else if (isPlainObject(item)) {
|
|
6748
|
+
const parsed = injectedCloudEvent(conversationId, item);
|
|
6749
|
+
if (parsed) {
|
|
6750
|
+
events.push(parsed);
|
|
6751
|
+
}
|
|
6752
|
+
}
|
|
6753
|
+
if (events.length > 0) {
|
|
6754
|
+
map.set(conversationId, events);
|
|
6755
|
+
}
|
|
6756
|
+
}
|
|
6757
|
+
return map;
|
|
6758
|
+
}
|
|
6759
|
+
async function readCursorAccessToken(dbPath) {
|
|
6760
|
+
if (!isCursorStateDbPath(dbPath)) {
|
|
6761
|
+
return void 0;
|
|
6762
|
+
}
|
|
6763
|
+
const info = await stat8(dbPath).catch(() => null);
|
|
6764
|
+
if (!info) {
|
|
6765
|
+
return void 0;
|
|
6766
|
+
}
|
|
6767
|
+
try {
|
|
6768
|
+
const opened = await openCursorDb(dbPath);
|
|
6769
|
+
try {
|
|
6770
|
+
const row = opened.db.prepare(
|
|
6771
|
+
"SELECT value FROM ItemTable WHERE key = 'cursorAuth/accessToken'"
|
|
6772
|
+
).get();
|
|
6773
|
+
const token = decodeKv(row?.value)?.trim();
|
|
6774
|
+
return token || void 0;
|
|
6775
|
+
} finally {
|
|
6776
|
+
opened.db.close();
|
|
6777
|
+
await opened.cleanup();
|
|
6778
|
+
}
|
|
6779
|
+
} catch {
|
|
6780
|
+
return void 0;
|
|
6781
|
+
}
|
|
6782
|
+
}
|
|
6783
|
+
async function loadCursorCloudUsageMap(options, filePath) {
|
|
6784
|
+
const injected = injectedCursorCloudUsage(options);
|
|
6785
|
+
if (injected) {
|
|
6786
|
+
return injected;
|
|
6787
|
+
}
|
|
6788
|
+
if (cursorCloudUsageDisabled()) {
|
|
6789
|
+
return /* @__PURE__ */ new Map();
|
|
6790
|
+
}
|
|
6791
|
+
const cached = cursorCloudUsageByOptions.get(options);
|
|
6792
|
+
if (cached) {
|
|
6793
|
+
return cached;
|
|
6794
|
+
}
|
|
6795
|
+
const pending = (async () => {
|
|
6796
|
+
try {
|
|
6797
|
+
const token = isCursorStateDbPath(filePath) ? await readCursorAccessToken(filePath) : await readCursorAccessTokenFromHome(options);
|
|
6798
|
+
if (!token) {
|
|
6799
|
+
return /* @__PURE__ */ new Map();
|
|
6800
|
+
}
|
|
6801
|
+
const fetchImpl = typeof options.cursorCloudFetch === "function" ? options.cursorCloudFetch : void 0;
|
|
6802
|
+
return await fetchCursorDashboardUsage({ accessToken: token, fetchImpl });
|
|
6803
|
+
} catch {
|
|
6804
|
+
return /* @__PURE__ */ new Map();
|
|
6805
|
+
}
|
|
6806
|
+
})();
|
|
6807
|
+
cursorCloudUsageByOptions.set(options, pending);
|
|
6808
|
+
return pending;
|
|
6809
|
+
}
|
|
6810
|
+
async function readCursorAccessTokenFromHome(options) {
|
|
6811
|
+
const home = stringOption(options.home) || os6.homedir();
|
|
6812
|
+
const env = {
|
|
6813
|
+
CURSOR_HOME: process.env.CURSOR_HOME,
|
|
6814
|
+
CURSOR_USER_DIR: process.env.CURSOR_USER_DIR
|
|
6815
|
+
};
|
|
6816
|
+
for (const candidate of cursorStateDbCandidates(home, env)) {
|
|
6817
|
+
const token = await readCursorAccessToken(candidate);
|
|
6818
|
+
if (token) {
|
|
6819
|
+
return token;
|
|
6820
|
+
}
|
|
6821
|
+
}
|
|
6822
|
+
return void 0;
|
|
6823
|
+
}
|
|
6824
|
+
function cloudUsageToPersisted(row, index = 0) {
|
|
6825
|
+
return {
|
|
6826
|
+
generationId: `${CURSOR_CLOUD_USAGE_GENERATION_ID}:${index}:${row.tokensInput}:${row.tokensOutput}:${row.tokensCacheReadInput}`,
|
|
6827
|
+
ts: row.ts,
|
|
6828
|
+
model: row.model,
|
|
6829
|
+
tokensInput: row.tokensInput || void 0,
|
|
6830
|
+
tokensOutput: row.tokensOutput || void 0,
|
|
6831
|
+
tokensCacheReadInput: row.tokensCacheReadInput || void 0,
|
|
6832
|
+
tokensCacheCreationInput: row.tokensCacheCreationInput || void 0
|
|
6833
|
+
};
|
|
6834
|
+
}
|
|
6835
|
+
async function resolveCursorSessionUsage(options, sessionId, filePath) {
|
|
6836
|
+
const persisted = await readPersistedSessionContextFromOptions(options, sessionId);
|
|
6837
|
+
const cloudEvents = (await loadCursorCloudUsageMap(options, filePath)).get(sessionId) || [];
|
|
6838
|
+
if (persisted?.usage?.length) {
|
|
6839
|
+
return [
|
|
6840
|
+
...persisted.usage,
|
|
6841
|
+
...unmatchedCloudEvents(cloudEvents, persisted.usage).map((event, index) => cloudUsageToPersisted(event, index))
|
|
6842
|
+
];
|
|
6843
|
+
}
|
|
6844
|
+
return cloudEvents.map((event, index) => cloudUsageToPersisted(event, index));
|
|
6845
|
+
}
|
|
6846
|
+
function cursorCloudUsageCachePath(home) {
|
|
6847
|
+
return path13.join(home, ".vibetime", CURSOR_CLOUD_USAGE_FILENAME);
|
|
6848
|
+
}
|
|
6849
|
+
async function listLocalCursorSessionIds(home, env) {
|
|
6850
|
+
const ids = /* @__PURE__ */ new Set();
|
|
6851
|
+
for (const dbPath of cursorStateDbCandidates(home, env)) {
|
|
6852
|
+
const composerIds = await listCursorComposerIds(dbPath);
|
|
6853
|
+
for (const id of composerIds) {
|
|
6854
|
+
ids.add(id);
|
|
6855
|
+
}
|
|
6856
|
+
if (composerIds.size > 0 || await stat8(dbPath).catch(() => null)) {
|
|
6857
|
+
break;
|
|
6858
|
+
}
|
|
6859
|
+
}
|
|
6860
|
+
const projects = cursorProjectsDir(home, env);
|
|
6861
|
+
for (const filePath of await listJsonlFiles(projects)) {
|
|
6862
|
+
if (!isCursorTranscriptPath(filePath) && path13.basename(path13.dirname(filePath)) !== "agent-transcripts") {
|
|
6863
|
+
continue;
|
|
6864
|
+
}
|
|
6865
|
+
const sessionId = path13.basename(filePath, ".jsonl");
|
|
6866
|
+
if (sessionId) {
|
|
6867
|
+
ids.add(sessionId);
|
|
6868
|
+
}
|
|
6869
|
+
}
|
|
6870
|
+
return ids;
|
|
6871
|
+
}
|
|
6872
|
+
async function writeCursorCloudUsageCache(cachePath, sessions) {
|
|
6873
|
+
const next = serializeCursorCloudUsageCache(sessions);
|
|
6874
|
+
const existing = await readFile8(cachePath, "utf8").catch(() => "");
|
|
6875
|
+
if (existing === next) {
|
|
6876
|
+
const info2 = await stat8(cachePath);
|
|
6877
|
+
return info2.mtime.toISOString();
|
|
6878
|
+
}
|
|
6879
|
+
await mkdir4(path13.dirname(cachePath), { recursive: true });
|
|
6880
|
+
await writeFile4(cachePath, next, "utf8");
|
|
6881
|
+
const info = await stat8(cachePath);
|
|
6882
|
+
return info.mtime.toISOString();
|
|
6883
|
+
}
|
|
6884
|
+
async function appendCursorCloudAgentSource(files, home, env, options) {
|
|
6885
|
+
const dbPath = files.find((file) => isCursorStateDbPath(file.path))?.path;
|
|
6886
|
+
const map = await loadCursorCloudUsageMap(options, dbPath);
|
|
6887
|
+
const localIds = await listLocalCursorSessionIds(home, env);
|
|
6888
|
+
const cloudOnly = [];
|
|
6889
|
+
for (const [conversationId, events] of map) {
|
|
6890
|
+
if (localIds.has(conversationId)) {
|
|
6891
|
+
continue;
|
|
6892
|
+
}
|
|
6893
|
+
const summed = sumCursorCloudEvents(conversationId, events);
|
|
6894
|
+
if (summed) {
|
|
6895
|
+
cloudOnly.push(summed);
|
|
6896
|
+
}
|
|
6897
|
+
}
|
|
6898
|
+
if (cloudOnly.length === 0) {
|
|
6899
|
+
return;
|
|
6900
|
+
}
|
|
6901
|
+
const cachePath = cursorCloudUsageCachePath(home);
|
|
6902
|
+
files.push({
|
|
6903
|
+
path: cachePath,
|
|
6904
|
+
modifiedAt: await writeCursorCloudUsageCache(cachePath, cloudOnly)
|
|
6905
|
+
});
|
|
6906
|
+
}
|
|
6907
|
+
function parseCursorCloudAgentSessions(filePath, options, sessions, localIds) {
|
|
6908
|
+
const events = [];
|
|
6909
|
+
const sourcePathHash = `sha256:${createStableHash(filePath)}`;
|
|
6910
|
+
const project = CURSOR_CLOUD_AGENT_PROJECT;
|
|
6911
|
+
const workspaceId = createWorkspaceId({ projectName: project });
|
|
6912
|
+
let lineNumber = 0;
|
|
6913
|
+
for (const row of sessions) {
|
|
6914
|
+
if (localIds.has(row.conversationId) || !row.startedAt) {
|
|
6915
|
+
continue;
|
|
6916
|
+
}
|
|
6917
|
+
const sessionId = row.conversationId;
|
|
6918
|
+
const model = row.model;
|
|
6919
|
+
const endedAt = row.ts || row.startedAt;
|
|
6920
|
+
const push = (partial, topType) => {
|
|
6921
|
+
lineNumber += 1;
|
|
6922
|
+
const event = {
|
|
6923
|
+
schemaVersion: AGENT_TIME_SCHEMA_VERSION,
|
|
6924
|
+
source: SOURCE_ID,
|
|
6925
|
+
agent: AGENT_NAME,
|
|
6926
|
+
workspaceId,
|
|
6927
|
+
project,
|
|
6928
|
+
model,
|
|
6929
|
+
sessionId,
|
|
6930
|
+
...partial
|
|
6931
|
+
};
|
|
6932
|
+
events.push(withBackfillRefs(event, {
|
|
6933
|
+
filePath,
|
|
6934
|
+
sourcePathHash,
|
|
6935
|
+
lineNumber,
|
|
6936
|
+
topType,
|
|
6937
|
+
payloadType: event.type,
|
|
6938
|
+
options
|
|
6939
|
+
}));
|
|
6940
|
+
};
|
|
6941
|
+
push({
|
|
6942
|
+
ts: row.startedAt,
|
|
6943
|
+
type: "session.started",
|
|
6944
|
+
confidence: "partial",
|
|
6945
|
+
refs: stringRefs({ sourceId: `${sessionId}:started` })
|
|
6946
|
+
}, "cloud-agent");
|
|
6947
|
+
emitPersistedCursorUsage(
|
|
6948
|
+
push,
|
|
6949
|
+
[cloudUsageToPersisted(row)],
|
|
6950
|
+
endedAt,
|
|
6951
|
+
void 0,
|
|
6952
|
+
model,
|
|
6953
|
+
sessionId
|
|
6954
|
+
);
|
|
6955
|
+
push({
|
|
6956
|
+
ts: endedAt,
|
|
6957
|
+
type: "session.ended",
|
|
6958
|
+
confidence: "partial",
|
|
6959
|
+
refs: stringRefs({ sourceId: `${sessionId}:ended` })
|
|
6960
|
+
}, "cloud-agent");
|
|
6961
|
+
}
|
|
6962
|
+
return events;
|
|
6963
|
+
}
|
|
6964
|
+
async function parseCursorCloudAgentFile(filePath, options) {
|
|
6965
|
+
const home = stringOption(options.home) || os6.homedir();
|
|
6966
|
+
const env = {
|
|
6967
|
+
CURSOR_HOME: process.env.CURSOR_HOME,
|
|
6968
|
+
CURSOR_USER_DIR: process.env.CURSOR_USER_DIR
|
|
6969
|
+
};
|
|
6970
|
+
const injected = injectedCursorCloudUsage(options);
|
|
6971
|
+
const sessions = injected ? [...injected.entries()].flatMap(([conversationId, events]) => {
|
|
6972
|
+
const summed = sumCursorCloudEvents(conversationId, events);
|
|
6973
|
+
return summed ? [summed] : [];
|
|
6974
|
+
}) : parseCursorCloudUsageCache(await readJsonIfExists(filePath));
|
|
6975
|
+
const localIds = await listLocalCursorSessionIds(home, env);
|
|
6976
|
+
return parseCursorCloudAgentSessions(filePath, options, sessions, localIds);
|
|
6977
|
+
}
|
|
6471
6978
|
function decodeKv(value) {
|
|
6472
6979
|
if (typeof value === "string") {
|
|
6473
6980
|
return value;
|
|
@@ -7133,6 +7640,7 @@ async function parseCursorTranscriptFile(filePath, options) {
|
|
|
7133
7640
|
push,
|
|
7134
7641
|
sessionId,
|
|
7135
7642
|
options,
|
|
7643
|
+
filePath,
|
|
7136
7644
|
fallbackTs: endedAt || lastTs,
|
|
7137
7645
|
lastTurnId,
|
|
7138
7646
|
model,
|
|
@@ -7144,10 +7652,9 @@ async function appendPersistedCursorUsage(args) {
|
|
|
7144
7652
|
if (args.skip) {
|
|
7145
7653
|
return;
|
|
7146
7654
|
}
|
|
7147
|
-
const persisted = await readPersistedSessionContextFromOptions(args.options, args.sessionId);
|
|
7148
7655
|
emitPersistedCursorUsage(
|
|
7149
7656
|
args.push,
|
|
7150
|
-
|
|
7657
|
+
await resolveCursorSessionUsage(args.options, args.sessionId, args.filePath),
|
|
7151
7658
|
args.fallbackTs,
|
|
7152
7659
|
args.lastTurnId,
|
|
7153
7660
|
args.model,
|
|
@@ -7168,15 +7675,16 @@ function emitPersistedCursorUsage(push, usage, fallbackTs, lastTurnId, model, se
|
|
|
7168
7675
|
if (!metrics) {
|
|
7169
7676
|
continue;
|
|
7170
7677
|
}
|
|
7678
|
+
const fromCloud = item.generationId.startsWith(CURSOR_CLOUD_USAGE_GENERATION_ID);
|
|
7171
7679
|
push({
|
|
7172
7680
|
ts: timestampFrom(item.ts) || fallbackTs,
|
|
7173
7681
|
type: "model.usage",
|
|
7174
7682
|
turnId: lastTurnId,
|
|
7175
7683
|
model: item.model || model,
|
|
7176
|
-
confidence: "exact",
|
|
7684
|
+
confidence: fromCloud ? "partial" : "exact",
|
|
7177
7685
|
metrics,
|
|
7178
7686
|
refs: stringRefs({ sourceId: `${sessionId}:${item.generationId}:usage` })
|
|
7179
|
-
}, "hook-usage");
|
|
7687
|
+
}, fromCloud ? "cloud-usage" : "hook-usage");
|
|
7180
7688
|
}
|
|
7181
7689
|
}
|
|
7182
7690
|
async function listCursorComposerIds(dbPath) {
|
|
@@ -7235,6 +7743,9 @@ async function collectCursorTranscriptFiles(root, home, skipSessionIds) {
|
|
|
7235
7743
|
}
|
|
7236
7744
|
async function parseCursorSessionFile(filePath, options) {
|
|
7237
7745
|
const base = path13.basename(filePath);
|
|
7746
|
+
if (base === CURSOR_CLOUD_USAGE_FILENAME) {
|
|
7747
|
+
return parseCursorCloudAgentFile(filePath, options);
|
|
7748
|
+
}
|
|
7238
7749
|
if (base.endsWith(".jsonl")) {
|
|
7239
7750
|
return parseCursorTranscriptFile(filePath, options);
|
|
7240
7751
|
}
|
|
@@ -7250,8 +7761,8 @@ async function parseCursorSessionFile(filePath, options) {
|
|
|
7250
7761
|
try {
|
|
7251
7762
|
const composers = listComposers(opened.db);
|
|
7252
7763
|
for (const composer of composers) {
|
|
7253
|
-
const
|
|
7254
|
-
events.push(...parseComposer(opened.db, composer, filePath, sourcePathHash, options,
|
|
7764
|
+
const usage = await resolveCursorSessionUsage(options, composer.composerId, filePath);
|
|
7765
|
+
events.push(...parseComposer(opened.db, composer, filePath, sourcePathHash, options, usage));
|
|
7255
7766
|
}
|
|
7256
7767
|
} finally {
|
|
7257
7768
|
opened.db.close();
|
|
@@ -7472,7 +7983,7 @@ function parseComposer(db, composer, filePath, sourcePathHash, options, persiste
|
|
|
7472
7983
|
emitPersistedCursorUsage(push, persistedUsage, endedAt || startedAt, currentTurnId, model, sessionId, events.some((event) => event.type === "model.usage"));
|
|
7473
7984
|
return events;
|
|
7474
7985
|
}
|
|
7475
|
-
async function cursorBackfillFiles(sourceRoot, home = os6.homedir(), env) {
|
|
7986
|
+
async function cursorBackfillFiles(sourceRoot, home = os6.homedir(), env, options) {
|
|
7476
7987
|
if (sourceRoot) {
|
|
7477
7988
|
const info = await stat8(sourceRoot).catch(() => null);
|
|
7478
7989
|
if (!info) {
|
|
@@ -7539,6 +8050,9 @@ async function cursorBackfillFiles(sourceRoot, home = os6.homedir(), env) {
|
|
|
7539
8050
|
break;
|
|
7540
8051
|
}
|
|
7541
8052
|
files.push(...await collectCursorTranscriptFiles(cursorProjectsDir(home, env), home, skipIds));
|
|
8053
|
+
if (options) {
|
|
8054
|
+
await appendCursorCloudAgentSource(files, home, env, options);
|
|
8055
|
+
}
|
|
7542
8056
|
return files;
|
|
7543
8057
|
}
|
|
7544
8058
|
function cursorHookConfig() {
|
|
@@ -13984,7 +14498,7 @@ async function uninstallEntry(entry, options) {
|
|
|
13984
14498
|
await uninstallGeneratedFile(entry.path, options);
|
|
13985
14499
|
}
|
|
13986
14500
|
async function mergeHooksJson(filePath, content, { dryRun, force, onWrite }) {
|
|
13987
|
-
const { mkdir:
|
|
14501
|
+
const { mkdir: mkdir7, writeFile: writeFile6 } = await import("node:fs/promises");
|
|
13988
14502
|
const pathMod = await import("node:path");
|
|
13989
14503
|
if (dryRun) {
|
|
13990
14504
|
onWrite(`Would merge ${filePath}`);
|
|
@@ -14005,12 +14519,12 @@ async function mergeHooksJson(filePath, content, { dryRun, force, onWrite }) {
|
|
|
14005
14519
|
onWrite(`Already installed ${filePath}`);
|
|
14006
14520
|
return;
|
|
14007
14521
|
}
|
|
14008
|
-
await
|
|
14009
|
-
await
|
|
14522
|
+
await mkdir7(pathMod.dirname(filePath), { recursive: true });
|
|
14523
|
+
await writeFile6(filePath, nextText, "utf8");
|
|
14010
14524
|
onWrite(`Installed ${filePath}`);
|
|
14011
14525
|
}
|
|
14012
14526
|
async function mergeCursorHooksFile(filePath, content, { dryRun, force, onWrite }) {
|
|
14013
|
-
const { mkdir:
|
|
14527
|
+
const { mkdir: mkdir7, writeFile: writeFile6 } = await import("node:fs/promises");
|
|
14014
14528
|
const pathMod = await import("node:path");
|
|
14015
14529
|
if (dryRun) {
|
|
14016
14530
|
onWrite(`Would merge ${filePath}`);
|
|
@@ -14030,8 +14544,8 @@ async function mergeCursorHooksFile(filePath, content, { dryRun, force, onWrite
|
|
|
14030
14544
|
onWrite(`Already installed ${filePath}`);
|
|
14031
14545
|
return;
|
|
14032
14546
|
}
|
|
14033
|
-
await
|
|
14034
|
-
await
|
|
14547
|
+
await mkdir7(pathMod.dirname(filePath), { recursive: true });
|
|
14548
|
+
await writeFile6(filePath, nextText, "utf8");
|
|
14035
14549
|
onWrite(`Installed ${filePath}`);
|
|
14036
14550
|
}
|
|
14037
14551
|
async function uninstallCursorHooksFile(filePath, content, { dryRun, onWrite }) {
|
|
@@ -14065,8 +14579,8 @@ async function uninstallCursorHooksFile(filePath, content, { dryRun, onWrite })
|
|
|
14065
14579
|
onWrite(`Would uninstall ${filePath}`);
|
|
14066
14580
|
return;
|
|
14067
14581
|
}
|
|
14068
|
-
const { writeFile:
|
|
14069
|
-
await
|
|
14582
|
+
const { writeFile: writeFile6 } = await import("node:fs/promises");
|
|
14583
|
+
await writeFile6(filePath, `${JSON.stringify(next, null, 2)}
|
|
14070
14584
|
`, "utf8");
|
|
14071
14585
|
onWrite(`Uninstalled ${filePath}`);
|
|
14072
14586
|
}
|
|
@@ -14141,7 +14655,7 @@ function hookCommandFromGroup(group) {
|
|
|
14141
14655
|
return isPlainObject(hook) && typeof hook.command === "string" ? hook.command : void 0;
|
|
14142
14656
|
}
|
|
14143
14657
|
async function mergeHooksToml(filePath, content, { dryRun, force, onWrite }) {
|
|
14144
|
-
const { mkdir:
|
|
14658
|
+
const { mkdir: mkdir7, writeFile: writeFile6 } = await import("node:fs/promises");
|
|
14145
14659
|
const pathMod = await import("node:path");
|
|
14146
14660
|
if (dryRun) {
|
|
14147
14661
|
onWrite(`Would merge ${filePath}`);
|
|
@@ -14169,8 +14683,8 @@ async function mergeHooksToml(filePath, content, { dryRun, force, onWrite }) {
|
|
|
14169
14683
|
return;
|
|
14170
14684
|
}
|
|
14171
14685
|
}
|
|
14172
|
-
await
|
|
14173
|
-
await
|
|
14686
|
+
await mkdir7(pathMod.dirname(filePath), { recursive: true });
|
|
14687
|
+
await writeFile6(filePath, nextText, "utf8");
|
|
14174
14688
|
onWrite(`Installed ${filePath}`);
|
|
14175
14689
|
}
|
|
14176
14690
|
async function uninstallHooksToml(filePath, content, { dryRun, onWrite }) {
|
|
@@ -14195,8 +14709,8 @@ async function uninstallHooksToml(filePath, content, { dryRun, onWrite }) {
|
|
|
14195
14709
|
onWrite(`Would uninstall ${filePath}`);
|
|
14196
14710
|
return;
|
|
14197
14711
|
}
|
|
14198
|
-
const { writeFile:
|
|
14199
|
-
await
|
|
14712
|
+
const { writeFile: writeFile6 } = await import("node:fs/promises");
|
|
14713
|
+
await writeFile6(filePath, nextText, "utf8");
|
|
14200
14714
|
onWrite(`Uninstalled ${filePath}`);
|
|
14201
14715
|
}
|
|
14202
14716
|
function collectHookCommandsFromJsonContent(content) {
|
|
@@ -14329,8 +14843,8 @@ async function uninstallHooksJson(filePath, content, { dryRun, onWrite }) {
|
|
|
14329
14843
|
onWrite(`Would uninstall ${filePath}`);
|
|
14330
14844
|
return;
|
|
14331
14845
|
}
|
|
14332
|
-
const { writeFile:
|
|
14333
|
-
await
|
|
14846
|
+
const { writeFile: writeFile6 } = await import("node:fs/promises");
|
|
14847
|
+
await writeFile6(filePath, `${JSON.stringify(next, null, 2)}
|
|
14334
14848
|
`, "utf8");
|
|
14335
14849
|
onWrite(`Uninstalled ${filePath}`);
|
|
14336
14850
|
}
|
|
@@ -14412,7 +14926,7 @@ function defaultMachineName() {
|
|
|
14412
14926
|
init_fs();
|
|
14413
14927
|
|
|
14414
14928
|
// src/lib/logger.ts
|
|
14415
|
-
import { appendFile, mkdir as
|
|
14929
|
+
import { appendFile, mkdir as mkdir5, rename, stat as stat15 } from "node:fs/promises";
|
|
14416
14930
|
import { homedir as homedir2 } from "node:os";
|
|
14417
14931
|
import path25 from "node:path";
|
|
14418
14932
|
var MAX_BYTES = 1 * 1024 * 1024;
|
|
@@ -14441,7 +14955,7 @@ async function rotateIfNeeded(file) {
|
|
|
14441
14955
|
async function writeLog(entry, home = homedir2(), fileName = "cli.log") {
|
|
14442
14956
|
try {
|
|
14443
14957
|
const dir = logDir(home);
|
|
14444
|
-
await
|
|
14958
|
+
await mkdir5(dir, { recursive: true });
|
|
14445
14959
|
const file = logPath(home, fileName);
|
|
14446
14960
|
await rotateIfNeeded(file);
|
|
14447
14961
|
const record = {
|
|
@@ -14666,7 +15180,7 @@ async function deleteMachine(remote, id) {
|
|
|
14666
15180
|
}
|
|
14667
15181
|
|
|
14668
15182
|
// src/lib/types.ts
|
|
14669
|
-
var BACKFILL_STATE_SCHEMA_VERSION =
|
|
15183
|
+
var BACKFILL_STATE_SCHEMA_VERSION = 9;
|
|
14670
15184
|
|
|
14671
15185
|
// src/cli.ts
|
|
14672
15186
|
function createRegistry() {
|
|
@@ -15245,7 +15759,7 @@ async function listBackfillSourceFiles(source, options, ctx) {
|
|
|
15245
15759
|
return zedBackfillFiles(stringOption(options["source-root"]), resolveHome3(options, ctx), ctx.env);
|
|
15246
15760
|
}
|
|
15247
15761
|
if (source.id === "cursor") {
|
|
15248
|
-
return cursorBackfillFiles(stringOption(options["source-root"]), resolveHome3(options, ctx), ctx.env);
|
|
15762
|
+
return cursorBackfillFiles(stringOption(options["source-root"]), resolveHome3(options, ctx), ctx.env, options);
|
|
15249
15763
|
}
|
|
15250
15764
|
if (source.id === "pi") {
|
|
15251
15765
|
return piBackfillFiles(stringOption(options["source-root"]), resolveHome3(options, ctx), ctx.env);
|
|
@@ -15654,8 +16168,8 @@ async function readBackfillIncrementalStateFile(home, ctx) {
|
|
|
15654
16168
|
}
|
|
15655
16169
|
async function writeBackfillIncrementalStateFile(home, file) {
|
|
15656
16170
|
const statePath = backfillIncrementalStatePath(home);
|
|
15657
|
-
await
|
|
15658
|
-
await
|
|
16171
|
+
await mkdir6(path26.dirname(statePath), { recursive: true });
|
|
16172
|
+
await writeFile5(statePath, `${JSON.stringify(file, null, 2)}
|
|
15659
16173
|
`, "utf8");
|
|
15660
16174
|
}
|
|
15661
16175
|
async function readBackfillIncrementalState(home, remoteKey, ctx) {
|
|
@@ -15703,8 +16217,8 @@ async function readSyncLocalTriggerState(statePath) {
|
|
|
15703
16217
|
return nextState;
|
|
15704
16218
|
}
|
|
15705
16219
|
async function writeSyncLocalTriggerState(statePath, state) {
|
|
15706
|
-
await
|
|
15707
|
-
await
|
|
16220
|
+
await mkdir6(path26.dirname(statePath), { recursive: true });
|
|
16221
|
+
await writeFile5(statePath, `${JSON.stringify(state, null, 2)}
|
|
15708
16222
|
`, "utf8");
|
|
15709
16223
|
}
|
|
15710
16224
|
async function readSyncLocalLock(lockPath) {
|
|
@@ -15718,12 +16232,12 @@ async function readSyncLocalLock(lockPath) {
|
|
|
15718
16232
|
return { pid: lock.pid, startedAt: lock.startedAt };
|
|
15719
16233
|
}
|
|
15720
16234
|
async function writeSyncLocalLock(lockPath, lock) {
|
|
15721
|
-
await
|
|
15722
|
-
await
|
|
16235
|
+
await mkdir6(path26.dirname(lockPath), { recursive: true });
|
|
16236
|
+
await writeFile5(lockPath, `${JSON.stringify(lock, null, 2)}
|
|
15723
16237
|
`, "utf8");
|
|
15724
16238
|
}
|
|
15725
16239
|
async function acquireSyncLocalLock(lockPath, lock) {
|
|
15726
|
-
await
|
|
16240
|
+
await mkdir6(path26.dirname(lockPath), { recursive: true });
|
|
15727
16241
|
try {
|
|
15728
16242
|
const handle = await open(lockPath, "wx");
|
|
15729
16243
|
try {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yhong91/vibetime",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.1.
|
|
4
|
+
"version": "0.1.59",
|
|
5
5
|
"description": "vibetime CLI — install AI-agent hooks (Claude Code, Codex, OpenCode, Pi, Cursor) and report activity to vibetime.",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"publishConfig": {
|