@yhong91/vibetime 0.1.63 → 0.1.64
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 +240 -173
- package/package.json +1 -1
package/bin/vibetime.mjs
CHANGED
|
@@ -884,8 +884,8 @@ 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 mkdir6, open, rm, stat as
|
|
888
|
-
import
|
|
887
|
+
import { mkdir as mkdir6, open, rm, stat as stat17, writeFile as writeFile5 } from "node:fs/promises";
|
|
888
|
+
import os14 from "node:os";
|
|
889
889
|
import path26 from "node:path";
|
|
890
890
|
import { fileURLToPath } from "node:url";
|
|
891
891
|
|
|
@@ -924,7 +924,7 @@ var TELEMETRY_EVENT_TYPES = [
|
|
|
924
924
|
"agent.operation"
|
|
925
925
|
];
|
|
926
926
|
var FILE_ACTIVITY_OPERATIONS = ["read", "search", "create", "write", "edit", "delete"];
|
|
927
|
-
var BACKFILL_SOURCE_IDS = ["codex", "claude-code", "claude-cowork", "copilot", "opencode", "pi", "agy", "codebuddy", "qoder", "qoder-cn", "workbuddy", "zcode", "grok-build", "zed", "kimi-code", "cursor"];
|
|
927
|
+
var BACKFILL_SOURCE_IDS = ["codex", "claude-code", "claude-cowork", "copilot", "opencode", "pi", "agy", "codebuddy", "qoder", "qoder-cn", "workbuddy", "zcode", "grok-build", "zed", "kimi-code", "cursor", "grok-bot"];
|
|
928
928
|
function createWorkspaceId(input) {
|
|
929
929
|
const basis = input.repoUrl || input.repoRoot || input.projectName || "unknown";
|
|
930
930
|
return `workspace_${fnv1a(basis)}`;
|
|
@@ -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.64" : "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;
|
|
@@ -4936,8 +4936,8 @@ async function codebuddyBackfillFiles(sourceRoot, home, env) {
|
|
|
4936
4936
|
}
|
|
4937
4937
|
const filePath = path9.join(traceDir, entry);
|
|
4938
4938
|
try {
|
|
4939
|
-
const
|
|
4940
|
-
files.push({ path: filePath, modifiedAt:
|
|
4939
|
+
const stat18 = await import("node:fs/promises").then((fs) => fs.stat(filePath));
|
|
4940
|
+
files.push({ path: filePath, modifiedAt: stat18.mtime.toISOString(), groupId: pidDir.name });
|
|
4941
4941
|
} catch {
|
|
4942
4942
|
}
|
|
4943
4943
|
}
|
|
@@ -6331,7 +6331,7 @@ var CURSOR_CLOUD_USAGE_GENERATION_ID = "cursor-cloud";
|
|
|
6331
6331
|
var CURSOR_CLOUD_USAGE_FILENAME = "cursor-cloud-usage.json";
|
|
6332
6332
|
var CURSOR_CLOUD_AGENT_PROJECT = "Cloud Agent";
|
|
6333
6333
|
var CURSOR_DASHBOARD_USAGE_URL = "https://cursor.com/api/dashboard/get-filtered-usage-events";
|
|
6334
|
-
var CURSOR_CLOUD_USAGE_CACHE_VERSION =
|
|
6334
|
+
var CURSOR_CLOUD_USAGE_CACHE_VERSION = 2;
|
|
6335
6335
|
var DEFAULT_WINDOW_DAYS = 90;
|
|
6336
6336
|
var PAGE_SIZE = 1e3;
|
|
6337
6337
|
function cursorCloudUsageDisabled(env = process.env) {
|
|
@@ -6396,55 +6396,25 @@ function groupCursorUsageEvents(events) {
|
|
|
6396
6396
|
}
|
|
6397
6397
|
return byConversation;
|
|
6398
6398
|
}
|
|
6399
|
-
function
|
|
6399
|
+
function cloudAgentSessionFromEvents(conversationId, events) {
|
|
6400
6400
|
if (events.length === 0) {
|
|
6401
6401
|
return void 0;
|
|
6402
6402
|
}
|
|
6403
|
-
const
|
|
6404
|
-
|
|
6405
|
-
|
|
6403
|
+
const sorted = [...events].sort((a, b) => {
|
|
6404
|
+
const byTs = Date.parse(a.ts) - Date.parse(b.ts);
|
|
6405
|
+
if (byTs !== 0) {
|
|
6406
|
+
return byTs;
|
|
6407
|
+
}
|
|
6408
|
+
return a.tokensInput - b.tokensInput || a.tokensOutput - b.tokensOutput || a.tokensCacheReadInput - b.tokensCacheReadInput || (a.model || "").localeCompare(b.model || "");
|
|
6409
|
+
});
|
|
6410
|
+
const first = sorted[0];
|
|
6411
|
+
const last = sorted[sorted.length - 1];
|
|
6412
|
+
return {
|
|
6406
6413
|
conversationId,
|
|
6407
|
-
|
|
6408
|
-
ts:
|
|
6409
|
-
|
|
6410
|
-
tokensInput: 0,
|
|
6411
|
-
tokensOutput: 0,
|
|
6412
|
-
tokensCacheReadInput: 0,
|
|
6413
|
-
tokensCacheCreationInput: 0
|
|
6414
|
+
startedAt: first.startedAt || first.ts,
|
|
6415
|
+
ts: last.ts,
|
|
6416
|
+
events: sorted.map((event) => ({ ...event, conversationId }))
|
|
6414
6417
|
};
|
|
6415
|
-
for (const event of events) {
|
|
6416
|
-
summed.tokensInput += event.tokensInput;
|
|
6417
|
-
summed.tokensOutput += event.tokensOutput;
|
|
6418
|
-
summed.tokensCacheReadInput += event.tokensCacheReadInput;
|
|
6419
|
-
summed.tokensCacheCreationInput += event.tokensCacheCreationInput;
|
|
6420
|
-
const eventStart = event.startedAt || event.ts;
|
|
6421
|
-
if (Date.parse(eventStart) < Date.parse(summed.startedAt)) {
|
|
6422
|
-
summed.startedAt = eventStart;
|
|
6423
|
-
}
|
|
6424
|
-
if (Date.parse(event.ts) >= Date.parse(summed.ts)) {
|
|
6425
|
-
summed.ts = event.ts;
|
|
6426
|
-
if (event.model) {
|
|
6427
|
-
summed.model = event.model;
|
|
6428
|
-
}
|
|
6429
|
-
}
|
|
6430
|
-
}
|
|
6431
|
-
return summed;
|
|
6432
|
-
}
|
|
6433
|
-
function hookUncachedInputTokens(turn) {
|
|
6434
|
-
return Math.max(0, (turn.tokensInput || 0) - (turn.tokensCacheReadInput || 0));
|
|
6435
|
-
}
|
|
6436
|
-
function cloudEventMatchesHookTurn(event, turn) {
|
|
6437
|
-
return event.tokensInput === hookUncachedInputTokens(turn) && event.tokensOutput === (turn.tokensOutput || 0) && event.tokensCacheReadInput === (turn.tokensCacheReadInput || 0);
|
|
6438
|
-
}
|
|
6439
|
-
function unmatchedCloudEvents(events, turns) {
|
|
6440
|
-
const used = /* @__PURE__ */ new Set();
|
|
6441
|
-
for (const turn of turns) {
|
|
6442
|
-
const index = events.findIndex((event, i) => !used.has(i) && cloudEventMatchesHookTurn(event, turn));
|
|
6443
|
-
if (index >= 0) {
|
|
6444
|
-
used.add(index);
|
|
6445
|
-
}
|
|
6446
|
-
}
|
|
6447
|
-
return events.filter((_, i) => !used.has(i));
|
|
6448
6418
|
}
|
|
6449
6419
|
async function fetchCursorDashboardUsage(args) {
|
|
6450
6420
|
const cookie = cursorSessionCookie(args.accessToken);
|
|
@@ -6499,11 +6469,46 @@ async function fetchCursorDashboardUsage(args) {
|
|
|
6499
6469
|
}
|
|
6500
6470
|
function serializeCursorCloudUsageCache(sessions) {
|
|
6501
6471
|
const sorted = [...sessions].sort((a, b) => a.conversationId.localeCompare(b.conversationId));
|
|
6502
|
-
|
|
6472
|
+
const payload = {
|
|
6473
|
+
version: CURSOR_CLOUD_USAGE_CACHE_VERSION,
|
|
6474
|
+
sessions: sorted.map((session) => ({
|
|
6475
|
+
conversationId: session.conversationId,
|
|
6476
|
+
startedAt: session.startedAt,
|
|
6477
|
+
ts: session.ts,
|
|
6478
|
+
events: session.events.map((event) => ({
|
|
6479
|
+
model: event.model,
|
|
6480
|
+
ts: event.ts,
|
|
6481
|
+
tokensInput: event.tokensInput,
|
|
6482
|
+
tokensOutput: event.tokensOutput,
|
|
6483
|
+
tokensCacheReadInput: event.tokensCacheReadInput,
|
|
6484
|
+
tokensCacheCreationInput: event.tokensCacheCreationInput
|
|
6485
|
+
}))
|
|
6486
|
+
}))
|
|
6487
|
+
};
|
|
6488
|
+
return `${JSON.stringify(payload, null, 2)}
|
|
6503
6489
|
`;
|
|
6504
6490
|
}
|
|
6491
|
+
function cacheEventFromObject(conversationId, item) {
|
|
6492
|
+
const ts = stringField(item, "ts");
|
|
6493
|
+
if (!ts) {
|
|
6494
|
+
return void 0;
|
|
6495
|
+
}
|
|
6496
|
+
return {
|
|
6497
|
+
conversationId,
|
|
6498
|
+
model: stringField(item, "model"),
|
|
6499
|
+
ts,
|
|
6500
|
+
tokensInput: numberField(item, "tokensInput") || 0,
|
|
6501
|
+
tokensOutput: numberField(item, "tokensOutput") || 0,
|
|
6502
|
+
tokensCacheReadInput: numberField(item, "tokensCacheReadInput") || 0,
|
|
6503
|
+
tokensCacheCreationInput: numberField(item, "tokensCacheCreationInput") || 0
|
|
6504
|
+
};
|
|
6505
|
+
}
|
|
6505
6506
|
function parseCursorCloudUsageCache(raw) {
|
|
6506
|
-
if (!isPlainObject(raw) ||
|
|
6507
|
+
if (!isPlainObject(raw) || !Array.isArray(raw.sessions)) {
|
|
6508
|
+
return [];
|
|
6509
|
+
}
|
|
6510
|
+
const version = numberField(raw, "version");
|
|
6511
|
+
if (version !== 1 && version !== CURSOR_CLOUD_USAGE_CACHE_VERSION) {
|
|
6507
6512
|
return [];
|
|
6508
6513
|
}
|
|
6509
6514
|
const sessions = [];
|
|
@@ -6517,16 +6522,29 @@ function parseCursorCloudUsageCache(raw) {
|
|
|
6517
6522
|
if (!conversationId || !ts || !startedAt) {
|
|
6518
6523
|
continue;
|
|
6519
6524
|
}
|
|
6520
|
-
|
|
6521
|
-
|
|
6522
|
-
|
|
6523
|
-
|
|
6524
|
-
|
|
6525
|
-
|
|
6526
|
-
|
|
6527
|
-
|
|
6528
|
-
|
|
6529
|
-
|
|
6525
|
+
const events = [];
|
|
6526
|
+
if (Array.isArray(item.events)) {
|
|
6527
|
+
for (const entry of item.events) {
|
|
6528
|
+
if (!isPlainObject(entry)) {
|
|
6529
|
+
continue;
|
|
6530
|
+
}
|
|
6531
|
+
const parsed = cacheEventFromObject(conversationId, entry);
|
|
6532
|
+
if (parsed) {
|
|
6533
|
+
events.push(parsed);
|
|
6534
|
+
}
|
|
6535
|
+
}
|
|
6536
|
+
} else {
|
|
6537
|
+
const parsed = cacheEventFromObject(conversationId, item);
|
|
6538
|
+
if (parsed) {
|
|
6539
|
+
events.push(parsed);
|
|
6540
|
+
}
|
|
6541
|
+
}
|
|
6542
|
+
const session = cloudAgentSessionFromEvents(conversationId, events);
|
|
6543
|
+
if (session) {
|
|
6544
|
+
session.startedAt = startedAt;
|
|
6545
|
+
session.ts = ts;
|
|
6546
|
+
sessions.push(session);
|
|
6547
|
+
}
|
|
6530
6548
|
}
|
|
6531
6549
|
return sessions;
|
|
6532
6550
|
}
|
|
@@ -6753,7 +6771,7 @@ async function readCursorAccessTokenFromHome(options) {
|
|
|
6753
6771
|
function cloudUsageToPersisted(row, index = 0) {
|
|
6754
6772
|
const tokensInput = (row.tokensInput || 0) + (row.tokensCacheReadInput || 0) + (row.tokensCacheCreationInput || 0);
|
|
6755
6773
|
return {
|
|
6756
|
-
generationId: `${CURSOR_CLOUD_USAGE_GENERATION_ID}:${index}:${row.tokensInput}:${row.tokensOutput}:${row.tokensCacheReadInput}`,
|
|
6774
|
+
generationId: `${CURSOR_CLOUD_USAGE_GENERATION_ID}:${index}:${row.ts}:${row.tokensInput}:${row.tokensOutput}:${row.tokensCacheReadInput}`,
|
|
6757
6775
|
ts: row.ts,
|
|
6758
6776
|
model: row.model,
|
|
6759
6777
|
tokensInput: tokensInput || void 0,
|
|
@@ -6762,16 +6780,9 @@ function cloudUsageToPersisted(row, index = 0) {
|
|
|
6762
6780
|
tokensCacheCreationInput: row.tokensCacheCreationInput || void 0
|
|
6763
6781
|
};
|
|
6764
6782
|
}
|
|
6765
|
-
async function resolveCursorSessionUsage(options, sessionId
|
|
6783
|
+
async function resolveCursorSessionUsage(options, sessionId) {
|
|
6766
6784
|
const persisted = await readPersistedSessionContextFromOptions(options, sessionId);
|
|
6767
|
-
|
|
6768
|
-
if (persisted?.usage?.length) {
|
|
6769
|
-
return [
|
|
6770
|
-
...persisted.usage,
|
|
6771
|
-
...unmatchedCloudEvents(cloudEvents, persisted.usage).map((event, index) => cloudUsageToPersisted(event, index))
|
|
6772
|
-
];
|
|
6773
|
-
}
|
|
6774
|
-
return cloudEvents.map((event, index) => cloudUsageToPersisted(event, index));
|
|
6785
|
+
return persisted?.usage ?? [];
|
|
6775
6786
|
}
|
|
6776
6787
|
function cursorCloudUsageCachePath(home) {
|
|
6777
6788
|
return path13.join(home, ".vibetime", CURSOR_CLOUD_USAGE_FILENAME);
|
|
@@ -6811,30 +6822,7 @@ async function writeCursorCloudUsageCache(cachePath, sessions) {
|
|
|
6811
6822
|
const info = await stat8(cachePath);
|
|
6812
6823
|
return info.mtime.toISOString();
|
|
6813
6824
|
}
|
|
6814
|
-
|
|
6815
|
-
const dbPath = files.find((file) => isCursorStateDbPath(file.path))?.path;
|
|
6816
|
-
const map = await loadCursorCloudUsageMap(options, dbPath);
|
|
6817
|
-
const localIds = await listLocalCursorSessionIds(home, env);
|
|
6818
|
-
const cloudOnly = [];
|
|
6819
|
-
for (const [conversationId, events] of map) {
|
|
6820
|
-
if (localIds.has(conversationId)) {
|
|
6821
|
-
continue;
|
|
6822
|
-
}
|
|
6823
|
-
const summed = sumCursorCloudEvents(conversationId, events);
|
|
6824
|
-
if (summed) {
|
|
6825
|
-
cloudOnly.push(summed);
|
|
6826
|
-
}
|
|
6827
|
-
}
|
|
6828
|
-
if (cloudOnly.length === 0) {
|
|
6829
|
-
return;
|
|
6830
|
-
}
|
|
6831
|
-
const cachePath = cursorCloudUsageCachePath(home);
|
|
6832
|
-
files.push({
|
|
6833
|
-
path: cachePath,
|
|
6834
|
-
modifiedAt: await writeCursorCloudUsageCache(cachePath, cloudOnly)
|
|
6835
|
-
});
|
|
6836
|
-
}
|
|
6837
|
-
function parseCursorCloudAgentSessions(filePath, options, sessions, localIds) {
|
|
6825
|
+
function parseCursorCloudAgentSessions(filePath, options, sessions, localIds, identity) {
|
|
6838
6826
|
const events = [];
|
|
6839
6827
|
const sourcePathHash = `sha256:${createStableHash(filePath)}`;
|
|
6840
6828
|
const project = CURSOR_CLOUD_AGENT_PROJECT;
|
|
@@ -6845,17 +6833,17 @@ function parseCursorCloudAgentSessions(filePath, options, sessions, localIds) {
|
|
|
6845
6833
|
continue;
|
|
6846
6834
|
}
|
|
6847
6835
|
const sessionId = row.conversationId;
|
|
6848
|
-
const
|
|
6836
|
+
const lastModel = row.events.at(-1)?.model;
|
|
6849
6837
|
const endedAt = row.ts || row.startedAt;
|
|
6850
6838
|
const push = (partial, topType) => {
|
|
6851
6839
|
lineNumber += 1;
|
|
6852
6840
|
const event = {
|
|
6853
6841
|
schemaVersion: AGENT_TIME_SCHEMA_VERSION,
|
|
6854
|
-
source:
|
|
6855
|
-
agent:
|
|
6842
|
+
source: identity.source,
|
|
6843
|
+
agent: identity.agent,
|
|
6856
6844
|
workspaceId,
|
|
6857
6845
|
project,
|
|
6858
|
-
model,
|
|
6846
|
+
model: lastModel,
|
|
6859
6847
|
sessionId,
|
|
6860
6848
|
...partial
|
|
6861
6849
|
};
|
|
@@ -6874,14 +6862,32 @@ function parseCursorCloudAgentSessions(filePath, options, sessions, localIds) {
|
|
|
6874
6862
|
confidence: "partial",
|
|
6875
6863
|
refs: stringRefs({ sourceId: `${sessionId}:started` })
|
|
6876
6864
|
}, "cloud-agent");
|
|
6877
|
-
|
|
6878
|
-
|
|
6879
|
-
|
|
6880
|
-
|
|
6881
|
-
|
|
6882
|
-
|
|
6883
|
-
|
|
6884
|
-
|
|
6865
|
+
for (const [index, event] of row.events.entries()) {
|
|
6866
|
+
const item = cloudUsageToPersisted(event, index);
|
|
6867
|
+
const ts = timestampFrom(item.ts) || endedAt;
|
|
6868
|
+
const turnId = `${sessionId}:${item.generationId}`;
|
|
6869
|
+
const model = item.model || lastModel;
|
|
6870
|
+
const nextTs = timestampFrom(row.events[index + 1]?.ts) || endedAt;
|
|
6871
|
+
const completedAt = Date.parse(nextTs) > Date.parse(ts) ? nextTs : ts;
|
|
6872
|
+
push({
|
|
6873
|
+
ts,
|
|
6874
|
+
type: "turn.started",
|
|
6875
|
+
turnId,
|
|
6876
|
+
model,
|
|
6877
|
+
confidence: "partial",
|
|
6878
|
+
refs: stringRefs({ sourceId: `${turnId}:started` })
|
|
6879
|
+
}, "cloud-agent");
|
|
6880
|
+
emitPersistedCursorUsage(push, [item], ts, turnId, model, sessionId);
|
|
6881
|
+
push({
|
|
6882
|
+
ts: completedAt,
|
|
6883
|
+
type: "turn.completed",
|
|
6884
|
+
turnId,
|
|
6885
|
+
model,
|
|
6886
|
+
success: true,
|
|
6887
|
+
confidence: "partial",
|
|
6888
|
+
refs: stringRefs({ sourceId: `${turnId}:completed` })
|
|
6889
|
+
}, "cloud-agent");
|
|
6890
|
+
}
|
|
6885
6891
|
push({
|
|
6886
6892
|
ts: endedAt,
|
|
6887
6893
|
type: "session.ended",
|
|
@@ -6891,7 +6897,7 @@ function parseCursorCloudAgentSessions(filePath, options, sessions, localIds) {
|
|
|
6891
6897
|
}
|
|
6892
6898
|
return events;
|
|
6893
6899
|
}
|
|
6894
|
-
async function parseCursorCloudAgentFile(filePath, options) {
|
|
6900
|
+
async function parseCursorCloudAgentFile(filePath, options, identity) {
|
|
6895
6901
|
const home = stringOption(options.home) || os6.homedir();
|
|
6896
6902
|
const env = {
|
|
6897
6903
|
CURSOR_HOME: process.env.CURSOR_HOME,
|
|
@@ -6899,11 +6905,11 @@ async function parseCursorCloudAgentFile(filePath, options) {
|
|
|
6899
6905
|
};
|
|
6900
6906
|
const injected = injectedCursorCloudUsage(options);
|
|
6901
6907
|
const sessions = injected ? [...injected.entries()].flatMap(([conversationId, events]) => {
|
|
6902
|
-
const
|
|
6903
|
-
return
|
|
6908
|
+
const session = cloudAgentSessionFromEvents(conversationId, events);
|
|
6909
|
+
return session ? [session] : [];
|
|
6904
6910
|
}) : parseCursorCloudUsageCache(await readJsonIfExists(filePath));
|
|
6905
6911
|
const localIds = await listLocalCursorSessionIds(home, env);
|
|
6906
|
-
return parseCursorCloudAgentSessions(filePath, options, sessions, localIds);
|
|
6912
|
+
return parseCursorCloudAgentSessions(filePath, options, sessions, localIds, identity);
|
|
6907
6913
|
}
|
|
6908
6914
|
function decodeKv(value) {
|
|
6909
6915
|
if (typeof value === "string") {
|
|
@@ -7570,7 +7576,6 @@ async function parseCursorTranscriptFile(filePath, options) {
|
|
|
7570
7576
|
push,
|
|
7571
7577
|
sessionId,
|
|
7572
7578
|
options,
|
|
7573
|
-
filePath,
|
|
7574
7579
|
fallbackTs: endedAt || lastTs,
|
|
7575
7580
|
lastTurnId,
|
|
7576
7581
|
model,
|
|
@@ -7584,7 +7589,7 @@ async function appendPersistedCursorUsage(args) {
|
|
|
7584
7589
|
}
|
|
7585
7590
|
emitPersistedCursorUsage(
|
|
7586
7591
|
args.push,
|
|
7587
|
-
await resolveCursorSessionUsage(args.options, args.sessionId
|
|
7592
|
+
await resolveCursorSessionUsage(args.options, args.sessionId),
|
|
7588
7593
|
args.fallbackTs,
|
|
7589
7594
|
args.lastTurnId,
|
|
7590
7595
|
args.model,
|
|
@@ -7673,9 +7678,6 @@ async function collectCursorTranscriptFiles(root, home, skipSessionIds) {
|
|
|
7673
7678
|
}
|
|
7674
7679
|
async function parseCursorSessionFile(filePath, options) {
|
|
7675
7680
|
const base = path13.basename(filePath);
|
|
7676
|
-
if (base === CURSOR_CLOUD_USAGE_FILENAME) {
|
|
7677
|
-
return parseCursorCloudAgentFile(filePath, options);
|
|
7678
|
-
}
|
|
7679
7681
|
if (base.endsWith(".jsonl")) {
|
|
7680
7682
|
return parseCursorTranscriptFile(filePath, options);
|
|
7681
7683
|
}
|
|
@@ -7691,7 +7693,7 @@ async function parseCursorSessionFile(filePath, options) {
|
|
|
7691
7693
|
try {
|
|
7692
7694
|
const composers = listComposers(opened.db);
|
|
7693
7695
|
for (const composer of composers) {
|
|
7694
|
-
const usage = await resolveCursorSessionUsage(options, composer.composerId
|
|
7696
|
+
const usage = await resolveCursorSessionUsage(options, composer.composerId);
|
|
7695
7697
|
events.push(...parseComposer(opened.db, composer, filePath, sourcePathHash, options, usage));
|
|
7696
7698
|
}
|
|
7697
7699
|
} finally {
|
|
@@ -7913,7 +7915,7 @@ function parseComposer(db, composer, filePath, sourcePathHash, options, persiste
|
|
|
7913
7915
|
emitPersistedCursorUsage(push, persistedUsage, endedAt || startedAt, currentTurnId, model, sessionId, events.some((event) => event.type === "model.usage"));
|
|
7914
7916
|
return events;
|
|
7915
7917
|
}
|
|
7916
|
-
async function cursorBackfillFiles(sourceRoot, home = os6.homedir(), env
|
|
7918
|
+
async function cursorBackfillFiles(sourceRoot, home = os6.homedir(), env) {
|
|
7917
7919
|
if (sourceRoot) {
|
|
7918
7920
|
const info = await stat8(sourceRoot).catch(() => null);
|
|
7919
7921
|
if (!info) {
|
|
@@ -7980,9 +7982,6 @@ async function cursorBackfillFiles(sourceRoot, home = os6.homedir(), env, option
|
|
|
7980
7982
|
break;
|
|
7981
7983
|
}
|
|
7982
7984
|
files.push(...await collectCursorTranscriptFiles(cursorProjectsDir(home, env), home, skipIds));
|
|
7983
|
-
if (options) {
|
|
7984
|
-
await appendCursorCloudAgentSource(files, home, env, options);
|
|
7985
|
-
}
|
|
7986
7985
|
return files;
|
|
7987
7986
|
}
|
|
7988
7987
|
function cursorHookConfig() {
|
|
@@ -8027,14 +8026,78 @@ function createCursorAdapter() {
|
|
|
8027
8026
|
};
|
|
8028
8027
|
}
|
|
8029
8028
|
|
|
8029
|
+
// src/adapters/grok-bot.ts
|
|
8030
|
+
import { stat as stat9 } from "node:fs/promises";
|
|
8031
|
+
import os7 from "node:os";
|
|
8032
|
+
var SOURCE_ID2 = "grok-bot";
|
|
8033
|
+
var AGENT_NAME2 = "grok-bot";
|
|
8034
|
+
var IDENTITY = { source: SOURCE_ID2, agent: AGENT_NAME2 };
|
|
8035
|
+
async function grokBotBackfillFiles(sourceRoot, home = os7.homedir(), env, options) {
|
|
8036
|
+
if (sourceRoot) {
|
|
8037
|
+
const info = await stat9(sourceRoot).catch(() => null);
|
|
8038
|
+
return info ? [{ path: sourceRoot, modifiedAt: info.mtime.toISOString() }] : [];
|
|
8039
|
+
}
|
|
8040
|
+
if (!options) {
|
|
8041
|
+
return [];
|
|
8042
|
+
}
|
|
8043
|
+
const map = await loadCursorCloudUsageMap(options);
|
|
8044
|
+
const localIds = await listLocalCursorSessionIds(home, env);
|
|
8045
|
+
const cloudOnly = [];
|
|
8046
|
+
for (const [conversationId, events] of map) {
|
|
8047
|
+
if (localIds.has(conversationId)) {
|
|
8048
|
+
continue;
|
|
8049
|
+
}
|
|
8050
|
+
const session = cloudAgentSessionFromEvents(conversationId, events);
|
|
8051
|
+
if (session) {
|
|
8052
|
+
cloudOnly.push(session);
|
|
8053
|
+
}
|
|
8054
|
+
}
|
|
8055
|
+
if (cloudOnly.length === 0) {
|
|
8056
|
+
return [];
|
|
8057
|
+
}
|
|
8058
|
+
const cachePath = cursorCloudUsageCachePath(home);
|
|
8059
|
+
return [{
|
|
8060
|
+
path: cachePath,
|
|
8061
|
+
modifiedAt: await writeCursorCloudUsageCache(cachePath, cloudOnly)
|
|
8062
|
+
}];
|
|
8063
|
+
}
|
|
8064
|
+
function createGrokBotAdapter() {
|
|
8065
|
+
return {
|
|
8066
|
+
id: SOURCE_ID2,
|
|
8067
|
+
label: "Grok Bot",
|
|
8068
|
+
agentName: AGENT_NAME2,
|
|
8069
|
+
kind: "agent",
|
|
8070
|
+
// No hooks to install — data arrives via the Cursor dashboard API.
|
|
8071
|
+
// The cache file stands in as the detect/install marker.
|
|
8072
|
+
detectPath(home) {
|
|
8073
|
+
return cursorCloudUsageCachePath(home);
|
|
8074
|
+
},
|
|
8075
|
+
installedPath(home) {
|
|
8076
|
+
return cursorCloudUsageCachePath(home);
|
|
8077
|
+
},
|
|
8078
|
+
async isInstalled() {
|
|
8079
|
+
return false;
|
|
8080
|
+
},
|
|
8081
|
+
installEntries() {
|
|
8082
|
+
return [];
|
|
8083
|
+
},
|
|
8084
|
+
sourcePaths(home) {
|
|
8085
|
+
return [cursorCloudUsageCachePath(home)];
|
|
8086
|
+
},
|
|
8087
|
+
parseSessionFile(filePath, options) {
|
|
8088
|
+
return parseCursorCloudAgentFile(filePath, options, IDENTITY);
|
|
8089
|
+
}
|
|
8090
|
+
};
|
|
8091
|
+
}
|
|
8092
|
+
|
|
8030
8093
|
// src/adapters/grok-build.ts
|
|
8031
|
-
import { readdir as readdir7, readFile as readFile9, stat as
|
|
8094
|
+
import { readdir as readdir7, readFile as readFile9, stat as stat10 } from "node:fs/promises";
|
|
8032
8095
|
import path14 from "node:path";
|
|
8033
8096
|
init_fs();
|
|
8034
8097
|
var GROK_COST_TICKS_PER_USD = 1e9;
|
|
8035
|
-
var
|
|
8036
|
-
var
|
|
8037
|
-
var HOOK_COMMAND2 = `vibetime hook --agent ${
|
|
8098
|
+
var SOURCE_ID3 = "grok-build";
|
|
8099
|
+
var AGENT_NAME3 = "grok-build";
|
|
8100
|
+
var HOOK_COMMAND2 = `vibetime hook --agent ${SOURCE_ID3}`;
|
|
8038
8101
|
function grokHome(home, env) {
|
|
8039
8102
|
const override = env?.GROK_HOME;
|
|
8040
8103
|
if (override && override.trim()) {
|
|
@@ -8068,7 +8131,7 @@ async function grokBackfillFiles(sourceRoot, home, env) {
|
|
|
8068
8131
|
continue;
|
|
8069
8132
|
}
|
|
8070
8133
|
try {
|
|
8071
|
-
const info = await
|
|
8134
|
+
const info = await stat10(entryPath);
|
|
8072
8135
|
files.push({ path: entryPath, modifiedAt: info.mtime.toISOString() });
|
|
8073
8136
|
} catch {
|
|
8074
8137
|
}
|
|
@@ -8120,8 +8183,8 @@ async function parseGrokSessionFile(filePath, options) {
|
|
|
8120
8183
|
};
|
|
8121
8184
|
const base = (partial) => ({
|
|
8122
8185
|
schemaVersion: AGENT_TIME_SCHEMA_VERSION,
|
|
8123
|
-
source:
|
|
8124
|
-
agent:
|
|
8186
|
+
source: SOURCE_ID3,
|
|
8187
|
+
agent: AGENT_NAME3,
|
|
8125
8188
|
workspaceId,
|
|
8126
8189
|
project,
|
|
8127
8190
|
cwd,
|
|
@@ -8681,7 +8744,7 @@ async function loadHunkFileActivities(hunkPath, cwd) {
|
|
|
8681
8744
|
}
|
|
8682
8745
|
return activities;
|
|
8683
8746
|
}
|
|
8684
|
-
var grokHandler = (msg) => hookHandler(
|
|
8747
|
+
var grokHandler = (msg) => hookHandler(SOURCE_ID3, msg);
|
|
8685
8748
|
function hookConfig5() {
|
|
8686
8749
|
const anyTool = [{ matcher: ".*", hooks: [grokHandler("Reporting tool activity")] }];
|
|
8687
8750
|
return {
|
|
@@ -8703,9 +8766,9 @@ function hookConfig5() {
|
|
|
8703
8766
|
}
|
|
8704
8767
|
function createGrokBuildAdapter() {
|
|
8705
8768
|
return {
|
|
8706
|
-
id:
|
|
8769
|
+
id: SOURCE_ID3,
|
|
8707
8770
|
label: "Grok Build",
|
|
8708
|
-
agentName:
|
|
8771
|
+
agentName: AGENT_NAME3,
|
|
8709
8772
|
kind: "agent",
|
|
8710
8773
|
detectPath(home, env) {
|
|
8711
8774
|
return grokHome(home, env);
|
|
@@ -9372,7 +9435,7 @@ function createKimiCodeAdapter() {
|
|
|
9372
9435
|
}
|
|
9373
9436
|
|
|
9374
9437
|
// src/adapters/opencode.ts
|
|
9375
|
-
import
|
|
9438
|
+
import os8 from "node:os";
|
|
9376
9439
|
import path16 from "node:path";
|
|
9377
9440
|
async function parseOpenCodeSessionFile(dbPath, options) {
|
|
9378
9441
|
const { DatabaseSync } = await import("node:sqlite");
|
|
@@ -9827,20 +9890,20 @@ function opencodeDataCandidates(home, env) {
|
|
|
9827
9890
|
const primary = xdgData && xdgData.trim() ? path16.join(path16.resolve(xdgData), "opencode", "opencode.db") : path16.join(home, ".local", "share", "opencode", "opencode.db");
|
|
9828
9891
|
return [primary, path16.join(home, ".opencode", "opencode.db")];
|
|
9829
9892
|
}
|
|
9830
|
-
async function opencodeBackfillFiles(sourceRoot, home =
|
|
9831
|
-
const { stat:
|
|
9893
|
+
async function opencodeBackfillFiles(sourceRoot, home = os8.homedir(), env) {
|
|
9894
|
+
const { stat: stat18 } = await import("node:fs/promises");
|
|
9832
9895
|
if (sourceRoot) {
|
|
9833
9896
|
if (!sourceRoot.endsWith(".db")) {
|
|
9834
9897
|
return [];
|
|
9835
9898
|
}
|
|
9836
|
-
const info = await
|
|
9899
|
+
const info = await stat18(sourceRoot).catch(() => null);
|
|
9837
9900
|
if (!info) {
|
|
9838
9901
|
return [];
|
|
9839
9902
|
}
|
|
9840
9903
|
return [{ path: sourceRoot, modifiedAt: info.mtime.toISOString() }];
|
|
9841
9904
|
}
|
|
9842
9905
|
for (const candidatePath of opencodeDataCandidates(home, env)) {
|
|
9843
|
-
const info = await
|
|
9906
|
+
const info = await stat18(candidatePath).catch(() => null);
|
|
9844
9907
|
if (info) {
|
|
9845
9908
|
return [{ path: candidatePath, modifiedAt: info.mtime.toISOString() }];
|
|
9846
9909
|
}
|
|
@@ -9940,8 +10003,8 @@ function createOpenCodeAdapter() {
|
|
|
9940
10003
|
}
|
|
9941
10004
|
|
|
9942
10005
|
// src/adapters/pi.ts
|
|
9943
|
-
import { readdir as readdir8, readFile as readFile11, stat as
|
|
9944
|
-
import
|
|
10006
|
+
import { readdir as readdir8, readFile as readFile11, stat as stat11 } from "node:fs/promises";
|
|
10007
|
+
import os9 from "node:os";
|
|
9945
10008
|
import path17 from "node:path";
|
|
9946
10009
|
init_fs();
|
|
9947
10010
|
function piHostSessionIdFromBasename(basename) {
|
|
@@ -10352,7 +10415,7 @@ async function parsePiWorkflowRunFile(filePath, options) {
|
|
|
10352
10415
|
return state.events.filter((event) => matchesBackfillFilters(event, options));
|
|
10353
10416
|
}
|
|
10354
10417
|
async function findPiSessionFileById(sessionId, options) {
|
|
10355
|
-
const sessionsDir = piSessionDir(path17.resolve(stringOption(options.home) ||
|
|
10418
|
+
const sessionsDir = piSessionDir(path17.resolve(stringOption(options.home) || os9.homedir()));
|
|
10356
10419
|
try {
|
|
10357
10420
|
const projectDirs = await readdir8(sessionsDir, { withFileTypes: true });
|
|
10358
10421
|
for (const dir of projectDirs) {
|
|
@@ -10629,14 +10692,14 @@ async function workflowRunGroupId(filePath) {
|
|
|
10629
10692
|
return void 0;
|
|
10630
10693
|
}
|
|
10631
10694
|
}
|
|
10632
|
-
async function piBackfillFiles(sourceRoot, home =
|
|
10695
|
+
async function piBackfillFiles(sourceRoot, home = os9.homedir(), env) {
|
|
10633
10696
|
const lists = sourceRoot ? [await listFilesByExtensions(sourceRoot, [".jsonl", ".json"])] : await Promise.all([
|
|
10634
10697
|
listFilesByExtensions(piSessionDir(home, env), [".jsonl"]),
|
|
10635
10698
|
listFilesByExtensions(piWorkflowProjectsDir(home), [".json"])
|
|
10636
10699
|
]);
|
|
10637
10700
|
const files = lists.flat().sort();
|
|
10638
10701
|
return Promise.all(files.map(async (filePath) => {
|
|
10639
|
-
const info = await
|
|
10702
|
+
const info = await stat11(filePath);
|
|
10640
10703
|
let groupId = resolvePiBackfillGroupId(filePath);
|
|
10641
10704
|
if (!groupId && filePath.endsWith(".json")) {
|
|
10642
10705
|
groupId = await workflowRunGroupId(filePath);
|
|
@@ -10683,13 +10746,13 @@ function createPiAdapter() {
|
|
|
10683
10746
|
}
|
|
10684
10747
|
|
|
10685
10748
|
// src/adapters/qoder-cn.ts
|
|
10686
|
-
import { readdir as readdir9, readFile as readFile12, stat as
|
|
10687
|
-
import
|
|
10749
|
+
import { readdir as readdir9, readFile as readFile12, stat as stat12 } from "node:fs/promises";
|
|
10750
|
+
import os11 from "node:os";
|
|
10688
10751
|
import path19 from "node:path";
|
|
10689
10752
|
|
|
10690
10753
|
// src/adapters/qoder-local-db.ts
|
|
10691
10754
|
import { access } from "node:fs/promises";
|
|
10692
|
-
import
|
|
10755
|
+
import os10 from "node:os";
|
|
10693
10756
|
import path18 from "node:path";
|
|
10694
10757
|
function takeQoderDbModelCall(calls, requestId, blockStart) {
|
|
10695
10758
|
if (requestId) {
|
|
@@ -10707,7 +10770,7 @@ function takeQoderDbModelCall(calls, requestId, blockStart) {
|
|
|
10707
10770
|
}
|
|
10708
10771
|
return calls.ordered.shift();
|
|
10709
10772
|
}
|
|
10710
|
-
function appDataRoot(appDirName, home =
|
|
10773
|
+
function appDataRoot(appDirName, home = os10.homedir()) {
|
|
10711
10774
|
if (process.platform === "darwin") {
|
|
10712
10775
|
return path18.join(home, "Library", "Application Support", appDirName);
|
|
10713
10776
|
}
|
|
@@ -11010,7 +11073,7 @@ async function parseQoderCnSessionFile(filePath, options) {
|
|
|
11010
11073
|
let cwd;
|
|
11011
11074
|
let project = projectContext.project;
|
|
11012
11075
|
let model;
|
|
11013
|
-
const home = path19.resolve(stringOption(options.home) ||
|
|
11076
|
+
const home = path19.resolve(stringOption(options.home) || os11.homedir());
|
|
11014
11077
|
const modelMap = await loadQoderCnModelNames(configDir2, home);
|
|
11015
11078
|
const isSubagentSession = filePath.includes("subagents");
|
|
11016
11079
|
const segmentModelCalls = await loadQoderCnSegmentModelCalls(filePath, isSubagentSession, modelMap);
|
|
@@ -11580,7 +11643,7 @@ async function gitRootFromCwds2(cwds) {
|
|
|
11580
11643
|
while (!seen.has(current)) {
|
|
11581
11644
|
seen.add(current);
|
|
11582
11645
|
try {
|
|
11583
|
-
await
|
|
11646
|
+
await stat12(path19.join(current, ".git"));
|
|
11584
11647
|
return current;
|
|
11585
11648
|
} catch {
|
|
11586
11649
|
}
|
|
@@ -11614,7 +11677,7 @@ function encodeQoderCnProjectPath(value) {
|
|
|
11614
11677
|
}
|
|
11615
11678
|
async function qoderCnProjectFromFilePath(filePath, options) {
|
|
11616
11679
|
const projectDir = path19.basename(path19.dirname(filePath));
|
|
11617
|
-
const home = options ? path19.resolve(stringOption(options.home) ||
|
|
11680
|
+
const home = options ? path19.resolve(stringOption(options.home) || os11.homedir()) : os11.homedir();
|
|
11618
11681
|
const resolved = await resolveQoderCnProjectPath(projectDir, home);
|
|
11619
11682
|
if (resolved) {
|
|
11620
11683
|
return path19.basename(resolved);
|
|
@@ -11730,8 +11793,8 @@ function createQoderCnAdapter() {
|
|
|
11730
11793
|
|
|
11731
11794
|
// src/adapters/qoder.ts
|
|
11732
11795
|
import { existsSync } from "node:fs";
|
|
11733
|
-
import { readdir as readdir10, readFile as readFile13, stat as
|
|
11734
|
-
import
|
|
11796
|
+
import { readdir as readdir10, readFile as readFile13, stat as stat13 } from "node:fs/promises";
|
|
11797
|
+
import os12 from "node:os";
|
|
11735
11798
|
import path20 from "node:path";
|
|
11736
11799
|
function parseQoderPaths(filePath) {
|
|
11737
11800
|
const parts = filePath.split(path20.sep);
|
|
@@ -11890,7 +11953,7 @@ async function parseQoderSessionFile(filePath, options) {
|
|
|
11890
11953
|
let cwd;
|
|
11891
11954
|
let project = projectContext.project;
|
|
11892
11955
|
let model;
|
|
11893
|
-
const home = path20.resolve(stringOption(options.home) ||
|
|
11956
|
+
const home = path20.resolve(stringOption(options.home) || os12.homedir());
|
|
11894
11957
|
const modelMap = await loadQoderModelNames(configDir2, home);
|
|
11895
11958
|
const qwenworkRoot = isQwenworkConfigRoot(configDir2);
|
|
11896
11959
|
const isSubagentSession = filePath.includes("subagents");
|
|
@@ -12426,7 +12489,7 @@ async function gitRootFromCwds3(cwds) {
|
|
|
12426
12489
|
while (!seen.has(current)) {
|
|
12427
12490
|
seen.add(current);
|
|
12428
12491
|
try {
|
|
12429
|
-
await
|
|
12492
|
+
await stat13(path20.join(current, ".git"));
|
|
12430
12493
|
return current;
|
|
12431
12494
|
} catch {
|
|
12432
12495
|
}
|
|
@@ -12478,7 +12541,7 @@ function qoderEncodedProjectSuffix(projectDir, home) {
|
|
|
12478
12541
|
}
|
|
12479
12542
|
async function qoderProjectFromFilePath(filePath, options) {
|
|
12480
12543
|
const projectDir = path20.basename(path20.dirname(filePath));
|
|
12481
|
-
const home = options ? path20.resolve(stringOption(options.home) ||
|
|
12544
|
+
const home = options ? path20.resolve(stringOption(options.home) || os12.homedir()) : os12.homedir();
|
|
12482
12545
|
const resolved = await resolveQoderProjectPath(projectDir, home);
|
|
12483
12546
|
if (resolved) {
|
|
12484
12547
|
return path20.basename(resolved);
|
|
@@ -12634,7 +12697,7 @@ function normalizeId(id) {
|
|
|
12634
12697
|
}
|
|
12635
12698
|
|
|
12636
12699
|
// src/adapters/workbuddy.ts
|
|
12637
|
-
import { readdir as readdir11, readFile as readFile14, stat as
|
|
12700
|
+
import { readdir as readdir11, readFile as readFile14, stat as stat14 } from "node:fs/promises";
|
|
12638
12701
|
import path21 from "node:path";
|
|
12639
12702
|
function workbuddyProjectsDir(home, env) {
|
|
12640
12703
|
const override = env?.WORKBUDDY_PROJECTS_DIR || env?.WORKBUDDY_HOME;
|
|
@@ -13087,7 +13150,7 @@ async function workbuddyBackfillFiles(sourceRoot, home, env) {
|
|
|
13087
13150
|
for (const entry of entries) {
|
|
13088
13151
|
if (entry.isFile() && entry.name.endsWith(".jsonl")) {
|
|
13089
13152
|
const filePath = path21.join(projectDir, entry.name);
|
|
13090
|
-
const info = await
|
|
13153
|
+
const info = await stat14(filePath);
|
|
13091
13154
|
files.push({ path: filePath, modifiedAt: info.mtime.toISOString() });
|
|
13092
13155
|
}
|
|
13093
13156
|
}
|
|
@@ -13148,7 +13211,7 @@ function createWorkbuddyAdapter() {
|
|
|
13148
13211
|
|
|
13149
13212
|
// src/adapters/zcode.ts
|
|
13150
13213
|
import { execFile } from "node:child_process";
|
|
13151
|
-
import { readFile as readFile15, stat as
|
|
13214
|
+
import { readFile as readFile15, stat as stat15 } from "node:fs/promises";
|
|
13152
13215
|
import path22 from "node:path";
|
|
13153
13216
|
import { promisify as promisify2 } from "node:util";
|
|
13154
13217
|
var execFileAsync = promisify2(execFile);
|
|
@@ -13187,7 +13250,7 @@ var providerNameCache = null;
|
|
|
13187
13250
|
async function loadProviderNames(configPath2) {
|
|
13188
13251
|
let fileMtime = 0;
|
|
13189
13252
|
try {
|
|
13190
|
-
const info = await
|
|
13253
|
+
const info = await stat15(configPath2);
|
|
13191
13254
|
fileMtime = info.mtimeMs;
|
|
13192
13255
|
} catch {
|
|
13193
13256
|
return /* @__PURE__ */ new Map();
|
|
@@ -13415,7 +13478,7 @@ async function parseZCodeDb(filePath, options) {
|
|
|
13415
13478
|
for (let i = 0; i < 12; i++) {
|
|
13416
13479
|
const probe = path22.join(candidate, ".zcode", "v2", "config.json");
|
|
13417
13480
|
try {
|
|
13418
|
-
await
|
|
13481
|
+
await stat15(probe);
|
|
13419
13482
|
configPath2 = probe;
|
|
13420
13483
|
break;
|
|
13421
13484
|
} catch {
|
|
@@ -13649,11 +13712,11 @@ async function zcodeBackfillFiles(sourceRoot, home, env) {
|
|
|
13649
13712
|
const candidate = sourceRoot || zcodeDbPath(home, env);
|
|
13650
13713
|
const filePath = candidate.endsWith(".sqlite") ? candidate : path22.join(candidate, "db", "db.sqlite");
|
|
13651
13714
|
try {
|
|
13652
|
-
const info = await
|
|
13715
|
+
const info = await stat15(filePath);
|
|
13653
13716
|
let modifiedMs = info.mtimeMs;
|
|
13654
13717
|
for (const suffix of ["-wal", "-shm"]) {
|
|
13655
13718
|
try {
|
|
13656
|
-
const sidecar = await
|
|
13719
|
+
const sidecar = await stat15(`${filePath}${suffix}`);
|
|
13657
13720
|
modifiedMs = Math.max(modifiedMs, sidecar.mtimeMs);
|
|
13658
13721
|
} catch {
|
|
13659
13722
|
}
|
|
@@ -13696,7 +13759,7 @@ function createZCodeAdapter() {
|
|
|
13696
13759
|
}
|
|
13697
13760
|
|
|
13698
13761
|
// src/adapters/zed.ts
|
|
13699
|
-
import
|
|
13762
|
+
import os13 from "node:os";
|
|
13700
13763
|
import path23 from "node:path";
|
|
13701
13764
|
function zedThreadsCandidates(home, env) {
|
|
13702
13765
|
const candidates = [];
|
|
@@ -14048,20 +14111,20 @@ async function parseZedSessionFile(dbPath, options) {
|
|
|
14048
14111
|
}
|
|
14049
14112
|
return events.filter((event) => matchesBackfillFilters(event, options));
|
|
14050
14113
|
}
|
|
14051
|
-
async function zedBackfillFiles(sourceRoot, home =
|
|
14052
|
-
const { stat:
|
|
14114
|
+
async function zedBackfillFiles(sourceRoot, home = os13.homedir(), env) {
|
|
14115
|
+
const { stat: stat18 } = await import("node:fs/promises");
|
|
14053
14116
|
if (sourceRoot) {
|
|
14054
14117
|
if (!sourceRoot.endsWith(".db")) {
|
|
14055
14118
|
return [];
|
|
14056
14119
|
}
|
|
14057
|
-
const info = await
|
|
14120
|
+
const info = await stat18(sourceRoot).catch(() => null);
|
|
14058
14121
|
if (!info) {
|
|
14059
14122
|
return [];
|
|
14060
14123
|
}
|
|
14061
14124
|
return [{ path: sourceRoot, modifiedAt: info.mtime.toISOString() }];
|
|
14062
14125
|
}
|
|
14063
14126
|
for (const candidatePath of zedThreadsCandidates(home, env)) {
|
|
14064
|
-
const info = await
|
|
14127
|
+
const info = await stat18(candidatePath).catch(() => null);
|
|
14065
14128
|
if (info) {
|
|
14066
14129
|
return [{ path: candidatePath, modifiedAt: info.mtime.toISOString() }];
|
|
14067
14130
|
}
|
|
@@ -14958,7 +15021,7 @@ function defaultMachineName() {
|
|
|
14958
15021
|
init_fs();
|
|
14959
15022
|
|
|
14960
15023
|
// src/lib/logger.ts
|
|
14961
|
-
import { appendFile, mkdir as mkdir5, rename, stat as
|
|
15024
|
+
import { appendFile, mkdir as mkdir5, rename, stat as stat16 } from "node:fs/promises";
|
|
14962
15025
|
import { homedir as homedir2 } from "node:os";
|
|
14963
15026
|
import path25 from "node:path";
|
|
14964
15027
|
var MAX_BYTES = 1 * 1024 * 1024;
|
|
@@ -14976,7 +15039,7 @@ function serializeError(error) {
|
|
|
14976
15039
|
}
|
|
14977
15040
|
async function rotateIfNeeded(file) {
|
|
14978
15041
|
try {
|
|
14979
|
-
const info = await
|
|
15042
|
+
const info = await stat16(file);
|
|
14980
15043
|
if (info.size > MAX_BYTES) {
|
|
14981
15044
|
await rename(file, `${file}.1`).catch(() => {
|
|
14982
15045
|
});
|
|
@@ -15212,7 +15275,7 @@ async function deleteMachine(remote, id) {
|
|
|
15212
15275
|
}
|
|
15213
15276
|
|
|
15214
15277
|
// src/lib/types.ts
|
|
15215
|
-
var BACKFILL_STATE_SCHEMA_VERSION =
|
|
15278
|
+
var BACKFILL_STATE_SCHEMA_VERSION = 10;
|
|
15216
15279
|
|
|
15217
15280
|
// src/cli.ts
|
|
15218
15281
|
function createRegistry() {
|
|
@@ -15233,6 +15296,7 @@ function createRegistry() {
|
|
|
15233
15296
|
registry.register(createZedAdapter());
|
|
15234
15297
|
registry.register(createKimiCodeAdapter());
|
|
15235
15298
|
registry.register(createCursorAdapter());
|
|
15299
|
+
registry.register(createGrokBotAdapter());
|
|
15236
15300
|
return registry;
|
|
15237
15301
|
}
|
|
15238
15302
|
var defaultContext = {
|
|
@@ -15792,7 +15856,10 @@ async function listBackfillSourceFiles(source, options, ctx) {
|
|
|
15792
15856
|
return zedBackfillFiles(stringOption(options["source-root"]), resolveHome3(options, ctx), ctx.env);
|
|
15793
15857
|
}
|
|
15794
15858
|
if (source.id === "cursor") {
|
|
15795
|
-
return cursorBackfillFiles(stringOption(options["source-root"]), resolveHome3(options, ctx), ctx.env
|
|
15859
|
+
return cursorBackfillFiles(stringOption(options["source-root"]), resolveHome3(options, ctx), ctx.env);
|
|
15860
|
+
}
|
|
15861
|
+
if (source.id === "grok-bot") {
|
|
15862
|
+
return grokBotBackfillFiles(stringOption(options["source-root"]), resolveHome3(options, ctx), ctx.env, options);
|
|
15796
15863
|
}
|
|
15797
15864
|
if (source.id === "pi") {
|
|
15798
15865
|
return piBackfillFiles(stringOption(options["source-root"]), resolveHome3(options, ctx), ctx.env);
|
|
@@ -15801,7 +15868,7 @@ async function listBackfillSourceFiles(source, options, ctx) {
|
|
|
15801
15868
|
const fileLists = await Promise.all(roots.map((r) => listJsonlFiles(r)));
|
|
15802
15869
|
const files = fileLists.flat().sort().slice(0, numberOption(options.limit) || void 0);
|
|
15803
15870
|
return Promise.all(files.map(async (filePath) => {
|
|
15804
|
-
const info = await
|
|
15871
|
+
const info = await stat17(filePath);
|
|
15805
15872
|
return { path: filePath, modifiedAt: info.mtime.toISOString() };
|
|
15806
15873
|
}));
|
|
15807
15874
|
}
|
|
@@ -16353,7 +16420,7 @@ function syncLocalRunnerEntryArgs(cliPath) {
|
|
|
16353
16420
|
return [path26.resolve(path26.dirname(cliPath), "../bin/vibetime.mjs")];
|
|
16354
16421
|
}
|
|
16355
16422
|
function resolveHome3(options, ctx) {
|
|
16356
|
-
return path26.resolve(stringOption(options.home) || ctx.env.HOME ||
|
|
16423
|
+
return path26.resolve(stringOption(options.home) || ctx.env.HOME || os14.homedir());
|
|
16357
16424
|
}
|
|
16358
16425
|
function requestedTargets(options) {
|
|
16359
16426
|
const value = options.target || options.targets;
|
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.64",
|
|
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": {
|