@yhong91/vibetime 0.1.68 → 0.1.69
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 +64 -31
- package/package.json +1 -1
package/bin/vibetime.mjs
CHANGED
|
@@ -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.69" : "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;
|
|
@@ -5024,7 +5024,7 @@ function fileActivitiesFromPatchChanges(changes, ts, cwd, displayFilePath3) {
|
|
|
5024
5024
|
}
|
|
5025
5025
|
|
|
5026
5026
|
// src/lib/session-context.ts
|
|
5027
|
-
import { mkdir as mkdir3, stat as stat6, writeFile as writeFile3 } from "node:fs/promises";
|
|
5027
|
+
import { mkdir as mkdir3, rename, stat as stat6, unlink, writeFile as writeFile3 } from "node:fs/promises";
|
|
5028
5028
|
import os4 from "node:os";
|
|
5029
5029
|
import path10 from "node:path";
|
|
5030
5030
|
init_fs();
|
|
@@ -5039,7 +5039,12 @@ function resolveHome2(options) {
|
|
|
5039
5039
|
return options ? path10.resolve(stringOption(options.home) || os4.homedir()) : os4.homedir();
|
|
5040
5040
|
}
|
|
5041
5041
|
async function readPersistedSessionContext(home, sessionId) {
|
|
5042
|
-
|
|
5042
|
+
let raw;
|
|
5043
|
+
try {
|
|
5044
|
+
raw = await readJsonIfExists(sessionContextPath(home, sessionId));
|
|
5045
|
+
} catch {
|
|
5046
|
+
return void 0;
|
|
5047
|
+
}
|
|
5043
5048
|
if (!isPlainObject(raw)) {
|
|
5044
5049
|
return void 0;
|
|
5045
5050
|
}
|
|
@@ -5086,8 +5091,17 @@ async function persistHookSessionContext(home, payload) {
|
|
|
5086
5091
|
usage: nextUsage
|
|
5087
5092
|
};
|
|
5088
5093
|
await mkdir3(sessionContextDir(home), { recursive: true });
|
|
5089
|
-
|
|
5094
|
+
const dest = sessionContextPath(home, sessionId);
|
|
5095
|
+
const tmp = `${dest}.${process.pid}.tmp`;
|
|
5096
|
+
await writeFile3(tmp, `${JSON.stringify(context, null, 2)}
|
|
5090
5097
|
`, "utf8");
|
|
5098
|
+
try {
|
|
5099
|
+
await rename(tmp, dest);
|
|
5100
|
+
} catch (error) {
|
|
5101
|
+
await unlink(tmp).catch(() => {
|
|
5102
|
+
});
|
|
5103
|
+
throw error;
|
|
5104
|
+
}
|
|
5091
5105
|
}
|
|
5092
5106
|
function hookSessionId(payload) {
|
|
5093
5107
|
for (const key of ["session_id", "sessionId", "conversation_id", "conversationId"]) {
|
|
@@ -6499,6 +6513,22 @@ function cloudAgentSessionFromEvents(conversationId, events) {
|
|
|
6499
6513
|
events: sorted.map((event) => ({ ...event, conversationId }))
|
|
6500
6514
|
};
|
|
6501
6515
|
}
|
|
6516
|
+
function hookUncachedInputTokens(turn) {
|
|
6517
|
+
return Math.max(0, (turn.tokensInput || 0) - (turn.tokensCacheReadInput || 0));
|
|
6518
|
+
}
|
|
6519
|
+
function cloudEventMatchesHookTurn(event, turn) {
|
|
6520
|
+
return event.tokensInput === hookUncachedInputTokens(turn) && event.tokensOutput === (turn.tokensOutput || 0) && event.tokensCacheReadInput === (turn.tokensCacheReadInput || 0);
|
|
6521
|
+
}
|
|
6522
|
+
function unmatchedCloudEvents(events, turns) {
|
|
6523
|
+
const used = /* @__PURE__ */ new Set();
|
|
6524
|
+
for (const turn of turns) {
|
|
6525
|
+
const index = events.findIndex((event, i) => !used.has(i) && cloudEventMatchesHookTurn(event, turn));
|
|
6526
|
+
if (index >= 0) {
|
|
6527
|
+
used.add(index);
|
|
6528
|
+
}
|
|
6529
|
+
}
|
|
6530
|
+
return events.filter((_, i) => !used.has(i));
|
|
6531
|
+
}
|
|
6502
6532
|
async function fetchCursorDashboardUsage(args) {
|
|
6503
6533
|
const cookie = cursorSessionCookie(args.accessToken);
|
|
6504
6534
|
if (!cookie) {
|
|
@@ -6742,6 +6772,13 @@ function injectedCloudEvent(conversationId, item) {
|
|
|
6742
6772
|
tokensCacheCreationInput
|
|
6743
6773
|
};
|
|
6744
6774
|
}
|
|
6775
|
+
function cloudUsageMapFromSessions(sessions) {
|
|
6776
|
+
const map = /* @__PURE__ */ new Map();
|
|
6777
|
+
for (const session of sessions) {
|
|
6778
|
+
map.set(session.conversationId, session.events);
|
|
6779
|
+
}
|
|
6780
|
+
return map;
|
|
6781
|
+
}
|
|
6745
6782
|
function injectedCursorCloudUsage(options) {
|
|
6746
6783
|
if (!Object.prototype.hasOwnProperty.call(options, "cursorCloudUsage")) {
|
|
6747
6784
|
return void 0;
|
|
@@ -6827,7 +6864,9 @@ async function loadCursorCloudUsageMap(options, filePath) {
|
|
|
6827
6864
|
if (intervalSeconds > 0 && !options.force) {
|
|
6828
6865
|
const lastFetchedMs = await readLastCloudFetchAt(home);
|
|
6829
6866
|
if (lastFetchedMs !== void 0 && Date.now() - lastFetchedMs < intervalSeconds * 1e3) {
|
|
6830
|
-
return
|
|
6867
|
+
return cloudUsageMapFromSessions(
|
|
6868
|
+
parseCursorCloudUsageCache(await readJsonIfExists(cursorCloudUsageCachePath(home)))
|
|
6869
|
+
);
|
|
6831
6870
|
}
|
|
6832
6871
|
}
|
|
6833
6872
|
const pending = (async () => {
|
|
@@ -6877,15 +6916,13 @@ function cloudUsageToPersisted(row, index = 0) {
|
|
|
6877
6916
|
async function resolveCursorSessionUsage(options, sessionId, filePath) {
|
|
6878
6917
|
const persisted = await readPersistedSessionContextFromOptions(options, sessionId);
|
|
6879
6918
|
const hookUsage = persisted?.usage ?? [];
|
|
6880
|
-
if (hookUsage.length > 0) {
|
|
6881
|
-
return hookUsage;
|
|
6882
|
-
}
|
|
6883
6919
|
const cloudMap = await loadCursorCloudUsageMap(options, filePath);
|
|
6884
|
-
const cloudEvents = cloudMap.get(sessionId);
|
|
6885
|
-
|
|
6886
|
-
|
|
6887
|
-
|
|
6888
|
-
|
|
6920
|
+
const cloudEvents = cloudMap.get(sessionId) ?? [];
|
|
6921
|
+
const leftover = unmatchedCloudEvents(cloudEvents, hookUsage);
|
|
6922
|
+
return [
|
|
6923
|
+
...hookUsage,
|
|
6924
|
+
...leftover.map((event, index) => cloudUsageToPersisted(event, index))
|
|
6925
|
+
];
|
|
6889
6926
|
}
|
|
6890
6927
|
function cursorCloudUsageCachePath(home) {
|
|
6891
6928
|
return path13.join(home, ".vibetime", CURSOR_CLOUD_USAGE_FILENAME);
|
|
@@ -7082,10 +7119,10 @@ async function openCursorDb(dbPath) {
|
|
|
7082
7119
|
return {
|
|
7083
7120
|
db: new DatabaseSync(tmp, { readOnly: true }),
|
|
7084
7121
|
cleanup: async () => {
|
|
7085
|
-
const { unlink } = await import("node:fs/promises");
|
|
7086
|
-
await
|
|
7087
|
-
await
|
|
7088
|
-
await
|
|
7122
|
+
const { unlink: unlink2 } = await import("node:fs/promises");
|
|
7123
|
+
await unlink2(tmp).catch(() => void 0);
|
|
7124
|
+
await unlink2(`${tmp}-wal`).catch(() => void 0);
|
|
7125
|
+
await unlink2(`${tmp}-shm`).catch(() => void 0);
|
|
7089
7126
|
}
|
|
7090
7127
|
};
|
|
7091
7128
|
}
|
|
@@ -8241,7 +8278,7 @@ import os7 from "node:os";
|
|
|
8241
8278
|
var SOURCE_ID2 = "grok-bot";
|
|
8242
8279
|
var AGENT_NAME2 = "grok-bot";
|
|
8243
8280
|
var IDENTITY = { source: SOURCE_ID2, agent: AGENT_NAME2 };
|
|
8244
|
-
async function grokBotBackfillFiles(sourceRoot, home = os7.homedir(),
|
|
8281
|
+
async function grokBotBackfillFiles(sourceRoot, home = os7.homedir(), _env, options) {
|
|
8245
8282
|
if (sourceRoot) {
|
|
8246
8283
|
const info = await stat9(sourceRoot).catch(() => null);
|
|
8247
8284
|
return info ? [{ path: sourceRoot, modifiedAt: info.mtime.toISOString() }] : [];
|
|
@@ -8255,29 +8292,25 @@ async function grokBotBackfillFiles(sourceRoot, home = os7.homedir(), env, optio
|
|
|
8255
8292
|
const info = await stat9(cachePath).catch(() => null);
|
|
8256
8293
|
return info ? [{ path: cachePath, modifiedAt: info.mtime.toISOString() }] : [];
|
|
8257
8294
|
}
|
|
8258
|
-
const
|
|
8259
|
-
const cloudOnly = [];
|
|
8295
|
+
const sessions = [];
|
|
8260
8296
|
for (const [conversationId, events] of map) {
|
|
8261
|
-
if (localIds.has(conversationId)) {
|
|
8262
|
-
continue;
|
|
8263
|
-
}
|
|
8264
8297
|
const session = cloudAgentSessionFromEvents(conversationId, events);
|
|
8265
8298
|
if (session) {
|
|
8266
|
-
|
|
8299
|
+
sessions.push(session);
|
|
8267
8300
|
}
|
|
8268
8301
|
}
|
|
8269
|
-
if (
|
|
8302
|
+
if (sessions.length === 0) {
|
|
8270
8303
|
return [];
|
|
8271
8304
|
}
|
|
8272
8305
|
return [{
|
|
8273
8306
|
path: cachePath,
|
|
8274
|
-
modifiedAt: await writeCursorCloudUsageCache(cachePath,
|
|
8307
|
+
modifiedAt: await writeCursorCloudUsageCache(cachePath, sessions)
|
|
8275
8308
|
}];
|
|
8276
8309
|
}
|
|
8277
8310
|
function createGrokBotAdapter() {
|
|
8278
8311
|
return {
|
|
8279
8312
|
id: SOURCE_ID2,
|
|
8280
|
-
label: "
|
|
8313
|
+
label: "Grok Bot",
|
|
8281
8314
|
agentName: AGENT_NAME2,
|
|
8282
8315
|
kind: "agent",
|
|
8283
8316
|
// No hooks to install — data arrives via the Cursor dashboard API.
|
|
@@ -15190,8 +15223,8 @@ async function uninstallGeneratedFile(filePath, { dryRun, onWrite }) {
|
|
|
15190
15223
|
onWrite(`Would uninstall ${filePath}`);
|
|
15191
15224
|
return;
|
|
15192
15225
|
}
|
|
15193
|
-
const { unlink } = await import("node:fs/promises");
|
|
15194
|
-
await
|
|
15226
|
+
const { unlink: unlink2 } = await import("node:fs/promises");
|
|
15227
|
+
await unlink2(filePath);
|
|
15195
15228
|
onWrite(`Uninstalled ${filePath}`);
|
|
15196
15229
|
}
|
|
15197
15230
|
|
|
@@ -15258,7 +15291,7 @@ function defaultMachineName() {
|
|
|
15258
15291
|
init_fs();
|
|
15259
15292
|
|
|
15260
15293
|
// src/lib/logger.ts
|
|
15261
|
-
import { appendFile, mkdir as mkdir5, rename, stat as stat16 } from "node:fs/promises";
|
|
15294
|
+
import { appendFile, mkdir as mkdir5, rename as rename2, stat as stat16 } from "node:fs/promises";
|
|
15262
15295
|
import { homedir as homedir2 } from "node:os";
|
|
15263
15296
|
import path25 from "node:path";
|
|
15264
15297
|
var MAX_BYTES = 1 * 1024 * 1024;
|
|
@@ -15278,7 +15311,7 @@ async function rotateIfNeeded(file) {
|
|
|
15278
15311
|
try {
|
|
15279
15312
|
const info = await stat16(file);
|
|
15280
15313
|
if (info.size > MAX_BYTES) {
|
|
15281
|
-
await
|
|
15314
|
+
await rename2(file, `${file}.1`).catch(() => {
|
|
15282
15315
|
});
|
|
15283
15316
|
}
|
|
15284
15317
|
} catch {
|
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.69",
|
|
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": {
|