@yhong91/vibetime 0.1.74 → 0.1.76
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 +191 -154
- 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 os13 from "node:os";
|
|
889
889
|
import path27 from "node:path";
|
|
890
890
|
import { fileURLToPath } from "node:url";
|
|
891
891
|
|
|
@@ -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.76" : "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;
|
|
@@ -2103,6 +2103,9 @@ function msToIso(ms) {
|
|
|
2103
2103
|
}
|
|
2104
2104
|
|
|
2105
2105
|
// src/lib/backfill.ts
|
|
2106
|
+
function rollupKeyForSourceSession(source, sessionId) {
|
|
2107
|
+
return createImportKey(["rollup", source, sessionId]);
|
|
2108
|
+
}
|
|
2106
2109
|
function withBackfillRefs(event, context) {
|
|
2107
2110
|
const importKey = createImportKey([
|
|
2108
2111
|
event.source,
|
|
@@ -4936,8 +4939,8 @@ async function codebuddyBackfillFiles(sourceRoot, home, env) {
|
|
|
4936
4939
|
}
|
|
4937
4940
|
const filePath = path9.join(traceDir, entry);
|
|
4938
4941
|
try {
|
|
4939
|
-
const
|
|
4940
|
-
files.push({ path: filePath, modifiedAt:
|
|
4942
|
+
const stat18 = await import("node:fs/promises").then((fs) => fs.stat(filePath));
|
|
4943
|
+
files.push({ path: filePath, modifiedAt: stat18.mtime.toISOString(), groupId: pidDir.name });
|
|
4941
4944
|
} catch {
|
|
4942
4945
|
}
|
|
4943
4946
|
}
|
|
@@ -6500,10 +6503,10 @@ function cloudAgentSessionFromEvents(conversationId, events) {
|
|
|
6500
6503
|
};
|
|
6501
6504
|
}
|
|
6502
6505
|
function hookUncachedInputTokens(turn) {
|
|
6503
|
-
return Math.max(0, (turn.tokensInput || 0) - (turn.tokensCacheReadInput || 0));
|
|
6506
|
+
return Math.max(0, (turn.tokensInput || 0) - (turn.tokensCacheReadInput || 0) - (turn.tokensCacheCreationInput || 0));
|
|
6504
6507
|
}
|
|
6505
6508
|
function cloudEventMatchesHookTurn(event, turn) {
|
|
6506
|
-
return event.tokensInput === hookUncachedInputTokens(turn) && event.tokensOutput === (turn.tokensOutput || 0) && event.tokensCacheReadInput === (turn.tokensCacheReadInput || 0);
|
|
6509
|
+
return event.tokensInput === hookUncachedInputTokens(turn) && event.tokensOutput === (turn.tokensOutput || 0) && event.tokensCacheReadInput === (turn.tokensCacheReadInput || 0) && event.tokensCacheCreationInput === (turn.tokensCacheCreationInput || 0);
|
|
6507
6510
|
}
|
|
6508
6511
|
function unmatchedCloudEvents(events, turns) {
|
|
6509
6512
|
const used = /* @__PURE__ */ new Set();
|
|
@@ -6846,6 +6849,11 @@ async function loadCursorCloudUsageMap(options, filePath) {
|
|
|
6846
6849
|
return cached;
|
|
6847
6850
|
}
|
|
6848
6851
|
const home = stringOption(options.home) || os6.homedir();
|
|
6852
|
+
if (options.skipCursorCloud) {
|
|
6853
|
+
return cloudUsageMapFromSessions(
|
|
6854
|
+
parseCursorCloudUsageCache(await readJsonIfExists(cursorCloudUsageCachePath(home)))
|
|
6855
|
+
);
|
|
6856
|
+
}
|
|
6849
6857
|
const intervalSeconds = cursorCloudFetchIntervalSeconds();
|
|
6850
6858
|
if (intervalSeconds > 0 && !options.force) {
|
|
6851
6859
|
const lastFetchedMs = await readLastCloudFetchAt(home);
|
|
@@ -6967,7 +6975,7 @@ async function writeCursorCloudUsageCache(cachePath, sessions) {
|
|
|
6967
6975
|
const info = await stat8(cachePath);
|
|
6968
6976
|
return info.mtime.toISOString();
|
|
6969
6977
|
}
|
|
6970
|
-
function parseCursorCloudAgentSessions(filePath, options, sessions, localIds
|
|
6978
|
+
function parseCursorCloudAgentSessions(filePath, options, sessions, localIds) {
|
|
6971
6979
|
const events = [];
|
|
6972
6980
|
const sourcePathHash = `sha256:${createStableHash(filePath)}`;
|
|
6973
6981
|
const project = CURSOR_CLOUD_AGENT_PROJECT;
|
|
@@ -6984,8 +6992,8 @@ function parseCursorCloudAgentSessions(filePath, options, sessions, localIds, id
|
|
|
6984
6992
|
lineNumber += 1;
|
|
6985
6993
|
const event = {
|
|
6986
6994
|
schemaVersion: AGENT_TIME_SCHEMA_VERSION,
|
|
6987
|
-
source:
|
|
6988
|
-
agent:
|
|
6995
|
+
source: SOURCE_ID,
|
|
6996
|
+
agent: AGENT_NAME,
|
|
6989
6997
|
workspaceId,
|
|
6990
6998
|
project,
|
|
6991
6999
|
model: lastModel,
|
|
@@ -7042,7 +7050,7 @@ function parseCursorCloudAgentSessions(filePath, options, sessions, localIds, id
|
|
|
7042
7050
|
}
|
|
7043
7051
|
return events;
|
|
7044
7052
|
}
|
|
7045
|
-
async function parseCursorCloudAgentFile(filePath, options
|
|
7053
|
+
async function parseCursorCloudAgentFile(filePath, options) {
|
|
7046
7054
|
const home = stringOption(options.home) || os6.homedir();
|
|
7047
7055
|
const env = {
|
|
7048
7056
|
CURSOR_HOME: process.env.CURSOR_HOME,
|
|
@@ -7054,7 +7062,7 @@ async function parseCursorCloudAgentFile(filePath, options, identity) {
|
|
|
7054
7062
|
return session ? [session] : [];
|
|
7055
7063
|
}) : parseCursorCloudUsageCache(await readJsonIfExists(filePath));
|
|
7056
7064
|
const localIds = await listLocalCursorSessionIds(home, env);
|
|
7057
|
-
return parseCursorCloudAgentSessions(filePath, options, sessions, localIds
|
|
7065
|
+
return parseCursorCloudAgentSessions(filePath, options, sessions, localIds);
|
|
7058
7066
|
}
|
|
7059
7067
|
function decodeKv(value) {
|
|
7060
7068
|
if (typeof value === "string") {
|
|
@@ -7913,6 +7921,9 @@ async function parseCursorSessionFile(filePath, options) {
|
|
|
7913
7921
|
if (base.endsWith(".jsonl")) {
|
|
7914
7922
|
return parseCursorTranscriptFile(filePath, options);
|
|
7915
7923
|
}
|
|
7924
|
+
if (base === CURSOR_CLOUD_USAGE_FILENAME) {
|
|
7925
|
+
return parseCursorCloudAgentFile(filePath, options);
|
|
7926
|
+
}
|
|
7916
7927
|
if (base === "store.db") {
|
|
7917
7928
|
return [];
|
|
7918
7929
|
}
|
|
@@ -8147,7 +8158,36 @@ function parseComposer(db, composer, filePath, sourcePathHash, options, persiste
|
|
|
8147
8158
|
emitPersistedCursorUsage(push, persistedUsage, endedAt || startedAt, currentTurnId, model, sessionId, events.some((event) => event.type === "model.usage"));
|
|
8148
8159
|
return events;
|
|
8149
8160
|
}
|
|
8150
|
-
async function
|
|
8161
|
+
async function cursorCloudUsageBackfillFiles(home, options) {
|
|
8162
|
+
if (options?.skipCursorCloud || cursorCloudUsageDisabled()) {
|
|
8163
|
+
return [];
|
|
8164
|
+
}
|
|
8165
|
+
const cachePath = cursorCloudUsageCachePath(home);
|
|
8166
|
+
if (!options) {
|
|
8167
|
+
const info = await stat8(cachePath).catch(() => null);
|
|
8168
|
+
return info ? [{ path: cachePath, modifiedAt: info.mtime.toISOString() }] : [];
|
|
8169
|
+
}
|
|
8170
|
+
const map = await loadCursorCloudUsageMap(options);
|
|
8171
|
+
if (map.size === 0) {
|
|
8172
|
+
const info = await stat8(cachePath).catch(() => null);
|
|
8173
|
+
return info ? [{ path: cachePath, modifiedAt: info.mtime.toISOString() }] : [];
|
|
8174
|
+
}
|
|
8175
|
+
const sessions = [];
|
|
8176
|
+
for (const [conversationId, events] of map) {
|
|
8177
|
+
const session = cloudAgentSessionFromEvents(conversationId, events);
|
|
8178
|
+
if (session) {
|
|
8179
|
+
sessions.push(session);
|
|
8180
|
+
}
|
|
8181
|
+
}
|
|
8182
|
+
if (sessions.length === 0) {
|
|
8183
|
+
return [];
|
|
8184
|
+
}
|
|
8185
|
+
return [{
|
|
8186
|
+
path: cachePath,
|
|
8187
|
+
modifiedAt: await writeCursorCloudUsageCache(cachePath, sessions)
|
|
8188
|
+
}];
|
|
8189
|
+
}
|
|
8190
|
+
async function cursorBackfillFiles(sourceRoot, home = os6.homedir(), env, options) {
|
|
8151
8191
|
if (sourceRoot) {
|
|
8152
8192
|
const info = await stat8(sourceRoot).catch(() => null);
|
|
8153
8193
|
if (!info) {
|
|
@@ -8177,6 +8217,9 @@ async function cursorBackfillFiles(sourceRoot, home = os6.homedir(), env) {
|
|
|
8177
8217
|
files2.push(...await collectCursorTranscriptFiles(sourceRoot, home, skipIds2));
|
|
8178
8218
|
return files2;
|
|
8179
8219
|
}
|
|
8220
|
+
if (path13.basename(sourceRoot) === CURSOR_CLOUD_USAGE_FILENAME) {
|
|
8221
|
+
return [{ path: sourceRoot, modifiedAt: info.mtime.toISOString() }];
|
|
8222
|
+
}
|
|
8180
8223
|
if (path13.basename(sourceRoot) === "store.db") {
|
|
8181
8224
|
return [];
|
|
8182
8225
|
}
|
|
@@ -8214,6 +8257,7 @@ async function cursorBackfillFiles(sourceRoot, home = os6.homedir(), env) {
|
|
|
8214
8257
|
break;
|
|
8215
8258
|
}
|
|
8216
8259
|
files.push(...await collectCursorTranscriptFiles(cursorProjectsDir(home, env), home, skipIds));
|
|
8260
|
+
files.push(...await cursorCloudUsageBackfillFiles(home, options));
|
|
8217
8261
|
return files;
|
|
8218
8262
|
}
|
|
8219
8263
|
function cursorHookConfig() {
|
|
@@ -8251,85 +8295,22 @@ function createCursorAdapter() {
|
|
|
8251
8295
|
return [
|
|
8252
8296
|
...cursorStateDbCandidates(home, env),
|
|
8253
8297
|
cursorProjectsDir(home, env),
|
|
8254
|
-
cursorChatsDir(home, env)
|
|
8298
|
+
cursorChatsDir(home, env),
|
|
8299
|
+
cursorCloudUsageCachePath(home)
|
|
8255
8300
|
];
|
|
8256
8301
|
},
|
|
8257
8302
|
parseSessionFile: parseCursorSessionFile
|
|
8258
8303
|
};
|
|
8259
8304
|
}
|
|
8260
8305
|
|
|
8261
|
-
// src/adapters/grok-bot.ts
|
|
8262
|
-
import { stat as stat9 } from "node:fs/promises";
|
|
8263
|
-
import os7 from "node:os";
|
|
8264
|
-
var SOURCE_ID2 = "grok-bot";
|
|
8265
|
-
var AGENT_NAME2 = "grok-bot";
|
|
8266
|
-
var IDENTITY = { source: SOURCE_ID2, agent: AGENT_NAME2 };
|
|
8267
|
-
async function grokBotBackfillFiles(sourceRoot, home = os7.homedir(), _env, options) {
|
|
8268
|
-
if (sourceRoot) {
|
|
8269
|
-
const info = await stat9(sourceRoot).catch(() => null);
|
|
8270
|
-
return info ? [{ path: sourceRoot, modifiedAt: info.mtime.toISOString() }] : [];
|
|
8271
|
-
}
|
|
8272
|
-
if (!options) {
|
|
8273
|
-
return [];
|
|
8274
|
-
}
|
|
8275
|
-
const cachePath = cursorCloudUsageCachePath(home);
|
|
8276
|
-
const map = await loadCursorCloudUsageMap(options);
|
|
8277
|
-
if (map.size === 0) {
|
|
8278
|
-
const info = await stat9(cachePath).catch(() => null);
|
|
8279
|
-
return info ? [{ path: cachePath, modifiedAt: info.mtime.toISOString() }] : [];
|
|
8280
|
-
}
|
|
8281
|
-
const sessions = [];
|
|
8282
|
-
for (const [conversationId, events] of map) {
|
|
8283
|
-
const session = cloudAgentSessionFromEvents(conversationId, events);
|
|
8284
|
-
if (session) {
|
|
8285
|
-
sessions.push(session);
|
|
8286
|
-
}
|
|
8287
|
-
}
|
|
8288
|
-
if (sessions.length === 0) {
|
|
8289
|
-
return [];
|
|
8290
|
-
}
|
|
8291
|
-
return [{
|
|
8292
|
-
path: cachePath,
|
|
8293
|
-
modifiedAt: await writeCursorCloudUsageCache(cachePath, sessions)
|
|
8294
|
-
}];
|
|
8295
|
-
}
|
|
8296
|
-
function createGrokBotAdapter() {
|
|
8297
|
-
return {
|
|
8298
|
-
id: SOURCE_ID2,
|
|
8299
|
-
label: "Grok Bot",
|
|
8300
|
-
agentName: AGENT_NAME2,
|
|
8301
|
-
kind: "agent",
|
|
8302
|
-
// No hooks to install — data arrives via the Cursor dashboard API.
|
|
8303
|
-
// The cache file stands in as the detect/install marker.
|
|
8304
|
-
detectPath(home) {
|
|
8305
|
-
return cursorCloudUsageCachePath(home);
|
|
8306
|
-
},
|
|
8307
|
-
installedPath(home) {
|
|
8308
|
-
return cursorCloudUsageCachePath(home);
|
|
8309
|
-
},
|
|
8310
|
-
async isInstalled() {
|
|
8311
|
-
return false;
|
|
8312
|
-
},
|
|
8313
|
-
installEntries() {
|
|
8314
|
-
return [];
|
|
8315
|
-
},
|
|
8316
|
-
sourcePaths(home) {
|
|
8317
|
-
return [cursorCloudUsageCachePath(home)];
|
|
8318
|
-
},
|
|
8319
|
-
parseSessionFile(filePath, options) {
|
|
8320
|
-
return parseCursorCloudAgentFile(filePath, options, IDENTITY);
|
|
8321
|
-
}
|
|
8322
|
-
};
|
|
8323
|
-
}
|
|
8324
|
-
|
|
8325
8306
|
// src/adapters/grok-build.ts
|
|
8326
|
-
import { readdir as readdir7, readFile as readFile9, stat as
|
|
8307
|
+
import { readdir as readdir7, readFile as readFile9, stat as stat9 } from "node:fs/promises";
|
|
8327
8308
|
import path14 from "node:path";
|
|
8328
8309
|
init_fs();
|
|
8329
8310
|
var GROK_COST_TICKS_PER_USD = 1e9;
|
|
8330
|
-
var
|
|
8331
|
-
var
|
|
8332
|
-
var HOOK_COMMAND2 = `vibetime hook --agent ${
|
|
8311
|
+
var SOURCE_ID2 = "grok-build";
|
|
8312
|
+
var AGENT_NAME2 = "grok-build";
|
|
8313
|
+
var HOOK_COMMAND2 = `vibetime hook --agent ${SOURCE_ID2}`;
|
|
8333
8314
|
function grokHome(home, env) {
|
|
8334
8315
|
const override = env?.GROK_HOME;
|
|
8335
8316
|
if (override && override.trim()) {
|
|
@@ -8363,7 +8344,7 @@ async function grokBackfillFiles(sourceRoot, home, env) {
|
|
|
8363
8344
|
continue;
|
|
8364
8345
|
}
|
|
8365
8346
|
try {
|
|
8366
|
-
const info = await
|
|
8347
|
+
const info = await stat9(entryPath);
|
|
8367
8348
|
files.push({ path: entryPath, modifiedAt: info.mtime.toISOString() });
|
|
8368
8349
|
} catch {
|
|
8369
8350
|
}
|
|
@@ -8415,8 +8396,8 @@ async function parseGrokSessionFile(filePath, options) {
|
|
|
8415
8396
|
};
|
|
8416
8397
|
const base = (partial) => ({
|
|
8417
8398
|
schemaVersion: AGENT_TIME_SCHEMA_VERSION,
|
|
8418
|
-
source:
|
|
8419
|
-
agent:
|
|
8399
|
+
source: SOURCE_ID2,
|
|
8400
|
+
agent: AGENT_NAME2,
|
|
8420
8401
|
workspaceId,
|
|
8421
8402
|
project,
|
|
8422
8403
|
cwd,
|
|
@@ -8976,7 +8957,7 @@ async function loadHunkFileActivities(hunkPath, cwd) {
|
|
|
8976
8957
|
}
|
|
8977
8958
|
return activities;
|
|
8978
8959
|
}
|
|
8979
|
-
var grokHandler = (msg) => hookHandler(
|
|
8960
|
+
var grokHandler = (msg) => hookHandler(SOURCE_ID2, msg);
|
|
8980
8961
|
function hookConfig5() {
|
|
8981
8962
|
const anyTool = [{ matcher: ".*", hooks: [grokHandler("Reporting tool activity")] }];
|
|
8982
8963
|
return {
|
|
@@ -8998,9 +8979,9 @@ function hookConfig5() {
|
|
|
8998
8979
|
}
|
|
8999
8980
|
function createGrokBuildAdapter() {
|
|
9000
8981
|
return {
|
|
9001
|
-
id:
|
|
8982
|
+
id: SOURCE_ID2,
|
|
9002
8983
|
label: "Grok Build",
|
|
9003
|
-
agentName:
|
|
8984
|
+
agentName: AGENT_NAME2,
|
|
9004
8985
|
kind: "agent",
|
|
9005
8986
|
detectPath(home, env) {
|
|
9006
8987
|
return grokHome(home, env);
|
|
@@ -9026,7 +9007,7 @@ function createGrokBuildAdapter() {
|
|
|
9026
9007
|
}
|
|
9027
9008
|
|
|
9028
9009
|
// src/adapters/hermes.ts
|
|
9029
|
-
import { readdir as readdir8, stat as
|
|
9010
|
+
import { readdir as readdir8, stat as stat10 } from "node:fs/promises";
|
|
9030
9011
|
import path15 from "node:path";
|
|
9031
9012
|
init_fs();
|
|
9032
9013
|
var SOURCE = "hermes";
|
|
@@ -9319,11 +9300,11 @@ function hermesToolAlias(tool) {
|
|
|
9319
9300
|
}
|
|
9320
9301
|
async function sqliteMtime(filePath) {
|
|
9321
9302
|
try {
|
|
9322
|
-
const info = await
|
|
9303
|
+
const info = await stat10(filePath);
|
|
9323
9304
|
let modifiedMs = info.mtimeMs;
|
|
9324
9305
|
for (const suffix of ["-wal", "-shm"]) {
|
|
9325
9306
|
try {
|
|
9326
|
-
const sidecar = await
|
|
9307
|
+
const sidecar = await stat10(`${filePath}${suffix}`);
|
|
9327
9308
|
modifiedMs = Math.max(modifiedMs, sidecar.mtimeMs);
|
|
9328
9309
|
} catch {
|
|
9329
9310
|
}
|
|
@@ -10616,7 +10597,7 @@ function createKimiCodeAdapter() {
|
|
|
10616
10597
|
}
|
|
10617
10598
|
|
|
10618
10599
|
// src/adapters/opencode.ts
|
|
10619
|
-
import
|
|
10600
|
+
import os7 from "node:os";
|
|
10620
10601
|
import path17 from "node:path";
|
|
10621
10602
|
async function parseOpenCodeSessionFile(dbPath, options) {
|
|
10622
10603
|
const { DatabaseSync } = await import("node:sqlite");
|
|
@@ -11071,20 +11052,20 @@ function opencodeDataCandidates(home, env) {
|
|
|
11071
11052
|
const primary = xdgData && xdgData.trim() ? path17.join(path17.resolve(xdgData), "opencode", "opencode.db") : path17.join(home, ".local", "share", "opencode", "opencode.db");
|
|
11072
11053
|
return [primary, path17.join(home, ".opencode", "opencode.db")];
|
|
11073
11054
|
}
|
|
11074
|
-
async function opencodeBackfillFiles(sourceRoot, home =
|
|
11075
|
-
const { stat:
|
|
11055
|
+
async function opencodeBackfillFiles(sourceRoot, home = os7.homedir(), env) {
|
|
11056
|
+
const { stat: stat18 } = await import("node:fs/promises");
|
|
11076
11057
|
if (sourceRoot) {
|
|
11077
11058
|
if (!sourceRoot.endsWith(".db")) {
|
|
11078
11059
|
return [];
|
|
11079
11060
|
}
|
|
11080
|
-
const info = await
|
|
11061
|
+
const info = await stat18(sourceRoot).catch(() => null);
|
|
11081
11062
|
if (!info) {
|
|
11082
11063
|
return [];
|
|
11083
11064
|
}
|
|
11084
11065
|
return [{ path: sourceRoot, modifiedAt: info.mtime.toISOString() }];
|
|
11085
11066
|
}
|
|
11086
11067
|
for (const candidatePath of opencodeDataCandidates(home, env)) {
|
|
11087
|
-
const info = await
|
|
11068
|
+
const info = await stat18(candidatePath).catch(() => null);
|
|
11088
11069
|
if (info) {
|
|
11089
11070
|
return [{ path: candidatePath, modifiedAt: info.mtime.toISOString() }];
|
|
11090
11071
|
}
|
|
@@ -11184,8 +11165,8 @@ function createOpenCodeAdapter() {
|
|
|
11184
11165
|
}
|
|
11185
11166
|
|
|
11186
11167
|
// src/adapters/pi.ts
|
|
11187
|
-
import { readdir as readdir9, readFile as readFile11, stat as
|
|
11188
|
-
import
|
|
11168
|
+
import { readdir as readdir9, readFile as readFile11, stat as stat11 } from "node:fs/promises";
|
|
11169
|
+
import os8 from "node:os";
|
|
11189
11170
|
import path18 from "node:path";
|
|
11190
11171
|
init_fs();
|
|
11191
11172
|
function piHostSessionIdFromBasename(basename) {
|
|
@@ -11596,7 +11577,7 @@ async function parsePiWorkflowRunFile(filePath, options) {
|
|
|
11596
11577
|
return state.events.filter((event) => matchesBackfillFilters(event, options));
|
|
11597
11578
|
}
|
|
11598
11579
|
async function findPiSessionFileById(sessionId, options) {
|
|
11599
|
-
const sessionsDir = piSessionDir(path18.resolve(stringOption(options.home) ||
|
|
11580
|
+
const sessionsDir = piSessionDir(path18.resolve(stringOption(options.home) || os8.homedir()));
|
|
11600
11581
|
try {
|
|
11601
11582
|
const projectDirs = await readdir9(sessionsDir, { withFileTypes: true });
|
|
11602
11583
|
for (const dir of projectDirs) {
|
|
@@ -11873,14 +11854,14 @@ async function workflowRunGroupId(filePath) {
|
|
|
11873
11854
|
return void 0;
|
|
11874
11855
|
}
|
|
11875
11856
|
}
|
|
11876
|
-
async function piBackfillFiles(sourceRoot, home =
|
|
11857
|
+
async function piBackfillFiles(sourceRoot, home = os8.homedir(), env) {
|
|
11877
11858
|
const lists = sourceRoot ? [await listFilesByExtensions(sourceRoot, [".jsonl", ".json"])] : await Promise.all([
|
|
11878
11859
|
listFilesByExtensions(piSessionDir(home, env), [".jsonl"]),
|
|
11879
11860
|
listFilesByExtensions(piWorkflowProjectsDir(home), [".json"])
|
|
11880
11861
|
]);
|
|
11881
11862
|
const files = lists.flat().sort();
|
|
11882
11863
|
return Promise.all(files.map(async (filePath) => {
|
|
11883
|
-
const info = await
|
|
11864
|
+
const info = await stat11(filePath);
|
|
11884
11865
|
let groupId = resolvePiBackfillGroupId(filePath);
|
|
11885
11866
|
if (!groupId && filePath.endsWith(".json")) {
|
|
11886
11867
|
groupId = await workflowRunGroupId(filePath);
|
|
@@ -11927,13 +11908,13 @@ function createPiAdapter() {
|
|
|
11927
11908
|
}
|
|
11928
11909
|
|
|
11929
11910
|
// src/adapters/qoder-cn.ts
|
|
11930
|
-
import { readdir as readdir10, readFile as readFile12, stat as
|
|
11931
|
-
import
|
|
11911
|
+
import { readdir as readdir10, readFile as readFile12, stat as stat12 } from "node:fs/promises";
|
|
11912
|
+
import os10 from "node:os";
|
|
11932
11913
|
import path20 from "node:path";
|
|
11933
11914
|
|
|
11934
11915
|
// src/adapters/qoder-local-db.ts
|
|
11935
11916
|
import { access } from "node:fs/promises";
|
|
11936
|
-
import
|
|
11917
|
+
import os9 from "node:os";
|
|
11937
11918
|
import path19 from "node:path";
|
|
11938
11919
|
function takeQoderDbModelCall(calls, requestId, blockStart) {
|
|
11939
11920
|
if (requestId) {
|
|
@@ -11951,7 +11932,7 @@ function takeQoderDbModelCall(calls, requestId, blockStart) {
|
|
|
11951
11932
|
}
|
|
11952
11933
|
return calls.ordered.shift();
|
|
11953
11934
|
}
|
|
11954
|
-
function appDataRoot(appDirName, home =
|
|
11935
|
+
function appDataRoot(appDirName, home = os9.homedir()) {
|
|
11955
11936
|
if (process.platform === "darwin") {
|
|
11956
11937
|
return path19.join(home, "Library", "Application Support", appDirName);
|
|
11957
11938
|
}
|
|
@@ -12058,7 +12039,7 @@ async function loadQoderDbModelCalls(appDirName, sessionId, modelMap) {
|
|
|
12058
12039
|
const modelInfo = parseJsonLine(stringField(row, "model_info") || "") || {};
|
|
12059
12040
|
const modelKey = stringField(modelInfo, "model_key");
|
|
12060
12041
|
const call = {
|
|
12061
|
-
model: modelKey
|
|
12042
|
+
model: mappedQoderModel(modelKey, modelMap) || preferredModel,
|
|
12062
12043
|
inputTokens: numberField(usage, "prompt_tokens") || 0,
|
|
12063
12044
|
outputTokens: numberField(usage, "completion_tokens") || 0,
|
|
12064
12045
|
cachedTokens: numberField(usage, "cached_tokens") || 0
|
|
@@ -12094,7 +12075,14 @@ function resolveRootSessionId(db, sessionId) {
|
|
|
12094
12075
|
}
|
|
12095
12076
|
return current === sessionId ? void 0 : current;
|
|
12096
12077
|
}
|
|
12078
|
+
function mappedQoderModel(raw, modelMap) {
|
|
12079
|
+
if (!raw) {
|
|
12080
|
+
return void 0;
|
|
12081
|
+
}
|
|
12082
|
+
return modelMap[raw] || raw;
|
|
12083
|
+
}
|
|
12097
12084
|
function resolveSessionPreferredModel(db, sessionId, modelMap) {
|
|
12085
|
+
const chain = [];
|
|
12098
12086
|
let current = sessionId;
|
|
12099
12087
|
for (let depth = 0; depth < 5 && current; depth++) {
|
|
12100
12088
|
let row;
|
|
@@ -12106,15 +12094,36 @@ function resolveSessionPreferredModel(db, sessionId, modelMap) {
|
|
|
12106
12094
|
return void 0;
|
|
12107
12095
|
}
|
|
12108
12096
|
if (!row) {
|
|
12109
|
-
|
|
12097
|
+
break;
|
|
12110
12098
|
}
|
|
12099
|
+
chain.push(current);
|
|
12111
12100
|
const info = parseJsonLine(stringField(row, "preferred_model_info") || "") || {};
|
|
12112
|
-
const preferred = stringField(info, "preferred_model");
|
|
12101
|
+
const preferred = mappedQoderModel(stringField(info, "preferred_model"), modelMap);
|
|
12113
12102
|
if (preferred) {
|
|
12114
|
-
return
|
|
12103
|
+
return preferred;
|
|
12115
12104
|
}
|
|
12116
12105
|
current = stringField(row, "parent_session_id");
|
|
12117
12106
|
}
|
|
12107
|
+
return resolveModelKeyFromAncestorMessages(db, chain, modelMap);
|
|
12108
|
+
}
|
|
12109
|
+
function resolveModelKeyFromAncestorMessages(db, sessionIds, modelMap) {
|
|
12110
|
+
for (const sid of sessionIds) {
|
|
12111
|
+
let rows;
|
|
12112
|
+
try {
|
|
12113
|
+
rows = db.prepare(
|
|
12114
|
+
`select model_info from chat_message where session_id = ? and role = 'assistant' and instr(model_info, 'model_key') > 0 order by gmt_create desc limit 20`
|
|
12115
|
+
).all(sid);
|
|
12116
|
+
} catch {
|
|
12117
|
+
continue;
|
|
12118
|
+
}
|
|
12119
|
+
for (const row of rows) {
|
|
12120
|
+
const info = parseJsonLine(stringField(row, "model_info") || "") || {};
|
|
12121
|
+
const mapped = mappedQoderModel(stringField(info, "model_key"), modelMap);
|
|
12122
|
+
if (mapped) {
|
|
12123
|
+
return mapped;
|
|
12124
|
+
}
|
|
12125
|
+
}
|
|
12126
|
+
}
|
|
12118
12127
|
return void 0;
|
|
12119
12128
|
}
|
|
12120
12129
|
|
|
@@ -12227,8 +12236,8 @@ async function loadQoderCnSegmentModelCalls(filePath, isSubagentSession, modelMa
|
|
|
12227
12236
|
}
|
|
12228
12237
|
if (type === "model.response.completed") {
|
|
12229
12238
|
const ts = stringField(raw, "ts") || "";
|
|
12230
|
-
const rawModel = stringField(data, "model")
|
|
12231
|
-
const modelName = modelMap[rawModel] || rawModel;
|
|
12239
|
+
const rawModel = stringField(data, "model");
|
|
12240
|
+
const modelName = rawModel ? modelMap[rawModel] || rawModel : void 0;
|
|
12232
12241
|
modelCalls.push({
|
|
12233
12242
|
ts,
|
|
12234
12243
|
isSubagent: currentTurnIsSubagent,
|
|
@@ -12260,7 +12269,7 @@ async function parseQoderCnSessionFile(filePath, options) {
|
|
|
12260
12269
|
let cwd;
|
|
12261
12270
|
let project = projectContext.project;
|
|
12262
12271
|
let model;
|
|
12263
|
-
const home = path20.resolve(stringOption(options.home) ||
|
|
12272
|
+
const home = path20.resolve(stringOption(options.home) || os10.homedir());
|
|
12264
12273
|
const modelMap = await loadQoderCnModelNames(configDir2, home);
|
|
12265
12274
|
const isSubagentSession = filePath.includes("subagents");
|
|
12266
12275
|
const segmentModelCalls = await loadQoderCnSegmentModelCalls(filePath, isSubagentSession, modelMap);
|
|
@@ -12830,7 +12839,7 @@ async function gitRootFromCwds2(cwds) {
|
|
|
12830
12839
|
while (!seen.has(current)) {
|
|
12831
12840
|
seen.add(current);
|
|
12832
12841
|
try {
|
|
12833
|
-
await
|
|
12842
|
+
await stat12(path20.join(current, ".git"));
|
|
12834
12843
|
return current;
|
|
12835
12844
|
} catch {
|
|
12836
12845
|
}
|
|
@@ -12864,7 +12873,7 @@ function encodeQoderCnProjectPath(value) {
|
|
|
12864
12873
|
}
|
|
12865
12874
|
async function qoderCnProjectFromFilePath(filePath, options) {
|
|
12866
12875
|
const projectDir = path20.basename(path20.dirname(filePath));
|
|
12867
|
-
const home = options ? path20.resolve(stringOption(options.home) ||
|
|
12876
|
+
const home = options ? path20.resolve(stringOption(options.home) || os10.homedir()) : os10.homedir();
|
|
12868
12877
|
const resolved = await resolveQoderCnProjectPath(projectDir, home);
|
|
12869
12878
|
if (resolved) {
|
|
12870
12879
|
return path20.basename(resolved);
|
|
@@ -12980,8 +12989,8 @@ function createQoderCnAdapter() {
|
|
|
12980
12989
|
|
|
12981
12990
|
// src/adapters/qoder.ts
|
|
12982
12991
|
import { existsSync } from "node:fs";
|
|
12983
|
-
import { readdir as readdir11, readFile as readFile13, stat as
|
|
12984
|
-
import
|
|
12992
|
+
import { readdir as readdir11, readFile as readFile13, stat as stat13 } from "node:fs/promises";
|
|
12993
|
+
import os11 from "node:os";
|
|
12985
12994
|
import path21 from "node:path";
|
|
12986
12995
|
function parseQoderPaths(filePath) {
|
|
12987
12996
|
const parts = filePath.split(path21.sep);
|
|
@@ -13113,8 +13122,8 @@ async function loadQoderSegmentModelCalls(filePath, isSubagentSession, modelMap)
|
|
|
13113
13122
|
}
|
|
13114
13123
|
if (type === "model.response.completed") {
|
|
13115
13124
|
const ts = stringField(raw, "ts") || "";
|
|
13116
|
-
const rawModel = stringField(data, "model")
|
|
13117
|
-
const modelName = modelMap[rawModel] || rawModel;
|
|
13125
|
+
const rawModel = stringField(data, "model");
|
|
13126
|
+
const modelName = rawModel ? modelMap[rawModel] || rawModel : void 0;
|
|
13118
13127
|
modelCalls.push({
|
|
13119
13128
|
ts,
|
|
13120
13129
|
isSubagent: currentTurnIsSubagent,
|
|
@@ -13146,7 +13155,7 @@ async function parseQoderSessionFile(filePath, options) {
|
|
|
13146
13155
|
let cwd;
|
|
13147
13156
|
let project = projectContext.project;
|
|
13148
13157
|
let model;
|
|
13149
|
-
const home = path21.resolve(stringOption(options.home) ||
|
|
13158
|
+
const home = path21.resolve(stringOption(options.home) || os11.homedir());
|
|
13150
13159
|
const modelMap = await loadQoderModelNames(configDir2, home);
|
|
13151
13160
|
const qwenworkRoot = isQwenworkConfigRoot(configDir2);
|
|
13152
13161
|
const isSubagentSession = filePath.includes("subagents");
|
|
@@ -13682,7 +13691,7 @@ async function gitRootFromCwds3(cwds) {
|
|
|
13682
13691
|
while (!seen.has(current)) {
|
|
13683
13692
|
seen.add(current);
|
|
13684
13693
|
try {
|
|
13685
|
-
await
|
|
13694
|
+
await stat13(path21.join(current, ".git"));
|
|
13686
13695
|
return current;
|
|
13687
13696
|
} catch {
|
|
13688
13697
|
}
|
|
@@ -13734,7 +13743,7 @@ function qoderEncodedProjectSuffix(projectDir, home) {
|
|
|
13734
13743
|
}
|
|
13735
13744
|
async function qoderProjectFromFilePath(filePath, options) {
|
|
13736
13745
|
const projectDir = path21.basename(path21.dirname(filePath));
|
|
13737
|
-
const home = options ? path21.resolve(stringOption(options.home) ||
|
|
13746
|
+
const home = options ? path21.resolve(stringOption(options.home) || os11.homedir()) : os11.homedir();
|
|
13738
13747
|
const resolved = await resolveQoderProjectPath(projectDir, home);
|
|
13739
13748
|
if (resolved) {
|
|
13740
13749
|
return path21.basename(resolved);
|
|
@@ -13886,11 +13895,14 @@ function normalizeId(id) {
|
|
|
13886
13895
|
if (id === "claude") {
|
|
13887
13896
|
return "claude-code";
|
|
13888
13897
|
}
|
|
13898
|
+
if (id === "grok-bot") {
|
|
13899
|
+
return "cursor";
|
|
13900
|
+
}
|
|
13889
13901
|
return id;
|
|
13890
13902
|
}
|
|
13891
13903
|
|
|
13892
13904
|
// src/adapters/workbuddy.ts
|
|
13893
|
-
import { readdir as readdir12, readFile as readFile14, stat as
|
|
13905
|
+
import { readdir as readdir12, readFile as readFile14, stat as stat14 } from "node:fs/promises";
|
|
13894
13906
|
import path22 from "node:path";
|
|
13895
13907
|
function workbuddyProjectsDir(home, env) {
|
|
13896
13908
|
const override = env?.WORKBUDDY_PROJECTS_DIR || env?.WORKBUDDY_HOME;
|
|
@@ -14343,7 +14355,7 @@ async function workbuddyBackfillFiles(sourceRoot, home, env) {
|
|
|
14343
14355
|
for (const entry of entries) {
|
|
14344
14356
|
if (entry.isFile() && entry.name.endsWith(".jsonl")) {
|
|
14345
14357
|
const filePath = path22.join(projectDir, entry.name);
|
|
14346
|
-
const info = await
|
|
14358
|
+
const info = await stat14(filePath);
|
|
14347
14359
|
files.push({ path: filePath, modifiedAt: info.mtime.toISOString() });
|
|
14348
14360
|
}
|
|
14349
14361
|
}
|
|
@@ -14404,7 +14416,7 @@ function createWorkbuddyAdapter() {
|
|
|
14404
14416
|
|
|
14405
14417
|
// src/adapters/zcode.ts
|
|
14406
14418
|
import { execFile } from "node:child_process";
|
|
14407
|
-
import { readFile as readFile15, stat as
|
|
14419
|
+
import { readFile as readFile15, stat as stat15 } from "node:fs/promises";
|
|
14408
14420
|
import path23 from "node:path";
|
|
14409
14421
|
import { promisify as promisify2 } from "node:util";
|
|
14410
14422
|
var execFileAsync = promisify2(execFile);
|
|
@@ -14443,7 +14455,7 @@ var providerNameCache = null;
|
|
|
14443
14455
|
async function loadProviderNames(configPath2) {
|
|
14444
14456
|
let fileMtime = 0;
|
|
14445
14457
|
try {
|
|
14446
|
-
const info = await
|
|
14458
|
+
const info = await stat15(configPath2);
|
|
14447
14459
|
fileMtime = info.mtimeMs;
|
|
14448
14460
|
} catch {
|
|
14449
14461
|
return /* @__PURE__ */ new Map();
|
|
@@ -14671,7 +14683,7 @@ async function parseZCodeDb(filePath, options) {
|
|
|
14671
14683
|
for (let i = 0; i < 12; i++) {
|
|
14672
14684
|
const probe = path23.join(candidate, ".zcode", "v2", "config.json");
|
|
14673
14685
|
try {
|
|
14674
|
-
await
|
|
14686
|
+
await stat15(probe);
|
|
14675
14687
|
configPath2 = probe;
|
|
14676
14688
|
break;
|
|
14677
14689
|
} catch {
|
|
@@ -14905,11 +14917,11 @@ async function zcodeBackfillFiles(sourceRoot, home, env) {
|
|
|
14905
14917
|
const candidate = sourceRoot || zcodeDbPath(home, env);
|
|
14906
14918
|
const filePath = candidate.endsWith(".sqlite") ? candidate : path23.join(candidate, "db", "db.sqlite");
|
|
14907
14919
|
try {
|
|
14908
|
-
const info = await
|
|
14920
|
+
const info = await stat15(filePath);
|
|
14909
14921
|
let modifiedMs = info.mtimeMs;
|
|
14910
14922
|
for (const suffix of ["-wal", "-shm"]) {
|
|
14911
14923
|
try {
|
|
14912
|
-
const sidecar = await
|
|
14924
|
+
const sidecar = await stat15(`${filePath}${suffix}`);
|
|
14913
14925
|
modifiedMs = Math.max(modifiedMs, sidecar.mtimeMs);
|
|
14914
14926
|
} catch {
|
|
14915
14927
|
}
|
|
@@ -14952,7 +14964,7 @@ function createZCodeAdapter() {
|
|
|
14952
14964
|
}
|
|
14953
14965
|
|
|
14954
14966
|
// src/adapters/zed.ts
|
|
14955
|
-
import
|
|
14967
|
+
import os12 from "node:os";
|
|
14956
14968
|
import path24 from "node:path";
|
|
14957
14969
|
function zedThreadsCandidates(home, env) {
|
|
14958
14970
|
const candidates = [];
|
|
@@ -15304,20 +15316,20 @@ async function parseZedSessionFile(dbPath, options) {
|
|
|
15304
15316
|
}
|
|
15305
15317
|
return events.filter((event) => matchesBackfillFilters(event, options));
|
|
15306
15318
|
}
|
|
15307
|
-
async function zedBackfillFiles(sourceRoot, home =
|
|
15308
|
-
const { stat:
|
|
15319
|
+
async function zedBackfillFiles(sourceRoot, home = os12.homedir(), env) {
|
|
15320
|
+
const { stat: stat18 } = await import("node:fs/promises");
|
|
15309
15321
|
if (sourceRoot) {
|
|
15310
15322
|
if (!sourceRoot.endsWith(".db")) {
|
|
15311
15323
|
return [];
|
|
15312
15324
|
}
|
|
15313
|
-
const info = await
|
|
15325
|
+
const info = await stat18(sourceRoot).catch(() => null);
|
|
15314
15326
|
if (!info) {
|
|
15315
15327
|
return [];
|
|
15316
15328
|
}
|
|
15317
15329
|
return [{ path: sourceRoot, modifiedAt: info.mtime.toISOString() }];
|
|
15318
15330
|
}
|
|
15319
15331
|
for (const candidatePath of zedThreadsCandidates(home, env)) {
|
|
15320
|
-
const info = await
|
|
15332
|
+
const info = await stat18(candidatePath).catch(() => null);
|
|
15321
15333
|
if (info) {
|
|
15322
15334
|
return [{ path: candidatePath, modifiedAt: info.mtime.toISOString() }];
|
|
15323
15335
|
}
|
|
@@ -16208,7 +16220,7 @@ function defaultMachineName() {
|
|
|
16208
16220
|
init_fs();
|
|
16209
16221
|
|
|
16210
16222
|
// src/lib/logger.ts
|
|
16211
|
-
import { appendFile, mkdir as mkdir5, rename as rename2, stat as
|
|
16223
|
+
import { appendFile, mkdir as mkdir5, rename as rename2, stat as stat16 } from "node:fs/promises";
|
|
16212
16224
|
import { homedir as homedir2 } from "node:os";
|
|
16213
16225
|
import path26 from "node:path";
|
|
16214
16226
|
var MAX_BYTES = 1 * 1024 * 1024;
|
|
@@ -16226,7 +16238,7 @@ function serializeError(error) {
|
|
|
16226
16238
|
}
|
|
16227
16239
|
async function rotateIfNeeded(file) {
|
|
16228
16240
|
try {
|
|
16229
|
-
const info = await
|
|
16241
|
+
const info = await stat16(file);
|
|
16230
16242
|
if (info.size > MAX_BYTES) {
|
|
16231
16243
|
await rename2(file, `${file}.1`).catch(() => {
|
|
16232
16244
|
});
|
|
@@ -16462,7 +16474,7 @@ async function deleteMachine(remote, id) {
|
|
|
16462
16474
|
}
|
|
16463
16475
|
|
|
16464
16476
|
// src/lib/types.ts
|
|
16465
|
-
var BACKFILL_STATE_SCHEMA_VERSION =
|
|
16477
|
+
var BACKFILL_STATE_SCHEMA_VERSION = 11;
|
|
16466
16478
|
|
|
16467
16479
|
// src/cli.ts
|
|
16468
16480
|
function createRegistry() {
|
|
@@ -16483,7 +16495,6 @@ function createRegistry() {
|
|
|
16483
16495
|
registry.register(createZedAdapter());
|
|
16484
16496
|
registry.register(createKimiCodeAdapter());
|
|
16485
16497
|
registry.register(createCursorAdapter());
|
|
16486
|
-
registry.register(createGrokBotAdapter());
|
|
16487
16498
|
registry.register(createHermesAdapter());
|
|
16488
16499
|
return registry;
|
|
16489
16500
|
}
|
|
@@ -17044,10 +17055,14 @@ async function listBackfillSourceFiles(source, options, ctx) {
|
|
|
17044
17055
|
return zedBackfillFiles(stringOption(options["source-root"]), resolveHome3(options, ctx), ctx.env);
|
|
17045
17056
|
}
|
|
17046
17057
|
if (source.id === "cursor") {
|
|
17047
|
-
|
|
17048
|
-
|
|
17049
|
-
|
|
17050
|
-
|
|
17058
|
+
const requested = normalizeBackfillSource(stringOption(options.source) || "all");
|
|
17059
|
+
const skipCursorCloud = requested === "all" && disabledBackfillSourceSet(readConfig(resolveHome3(options, ctx))).has("grok-bot");
|
|
17060
|
+
return cursorBackfillFiles(
|
|
17061
|
+
stringOption(options["source-root"]),
|
|
17062
|
+
resolveHome3(options, ctx),
|
|
17063
|
+
ctx.env,
|
|
17064
|
+
{ ...options, skipCursorCloud }
|
|
17065
|
+
);
|
|
17051
17066
|
}
|
|
17052
17067
|
if (source.id === "hermes") {
|
|
17053
17068
|
return hermesBackfillFiles(stringOption(options["source-root"]), resolveHome3(options, ctx), ctx.env);
|
|
@@ -17059,7 +17074,7 @@ async function listBackfillSourceFiles(source, options, ctx) {
|
|
|
17059
17074
|
const fileLists = await Promise.all(roots.map((r) => listJsonlFiles(r)));
|
|
17060
17075
|
const files = fileLists.flat().sort().slice(0, numberOption(options.limit) || void 0);
|
|
17061
17076
|
return Promise.all(files.map(async (filePath) => {
|
|
17062
|
-
const info = await
|
|
17077
|
+
const info = await stat17(filePath);
|
|
17063
17078
|
return { path: filePath, modifiedAt: info.mtime.toISOString() };
|
|
17064
17079
|
}));
|
|
17065
17080
|
}
|
|
@@ -17310,20 +17325,36 @@ async function sendSessionRollupBatch(rollups, options, ctx) {
|
|
|
17310
17325
|
machine,
|
|
17311
17326
|
allowHistoricalRewrite: options.force === true
|
|
17312
17327
|
});
|
|
17313
|
-
if (
|
|
17314
|
-
|
|
17315
|
-
for (const
|
|
17316
|
-
|
|
17317
|
-
|
|
17318
|
-
|
|
17319
|
-
|
|
17320
|
-
|
|
17321
|
-
|
|
17322
|
-
|
|
17328
|
+
if (result.conflicts === 0) {
|
|
17329
|
+
if (options.force) {
|
|
17330
|
+
for (const rollup of rollups) {
|
|
17331
|
+
for (const sessionId of rollup.supersededSessionIds ?? []) {
|
|
17332
|
+
try {
|
|
17333
|
+
await deleteRollupsBySource(remote, rollup.source, machine, {
|
|
17334
|
+
rollupKey: rollupKeyForSourceSession(rollup.source, sessionId),
|
|
17335
|
+
allowHistoricalRewrite: true
|
|
17336
|
+
});
|
|
17337
|
+
} catch (error) {
|
|
17338
|
+
debug(ctx, `Failed to delete superseded ${rollup.source} session ${sessionId}: ${error.message}
|
|
17323
17339
|
`);
|
|
17340
|
+
}
|
|
17324
17341
|
}
|
|
17325
17342
|
}
|
|
17326
17343
|
}
|
|
17344
|
+
for (const rollup of rollups) {
|
|
17345
|
+
if (rollup.source !== "cursor") {
|
|
17346
|
+
continue;
|
|
17347
|
+
}
|
|
17348
|
+
try {
|
|
17349
|
+
await deleteRollupsBySource(remote, "grok-bot", machine, {
|
|
17350
|
+
rollupKey: rollupKeyForSourceSession("grok-bot", rollup.sessionId),
|
|
17351
|
+
allowHistoricalRewrite: true
|
|
17352
|
+
});
|
|
17353
|
+
} catch (error) {
|
|
17354
|
+
debug(ctx, `Failed to delete grok-bot twin of cursor session ${rollup.sessionId}: ${error.message}
|
|
17355
|
+
`);
|
|
17356
|
+
}
|
|
17357
|
+
}
|
|
17327
17358
|
}
|
|
17328
17359
|
return result;
|
|
17329
17360
|
}
|
|
@@ -17611,7 +17642,7 @@ function syncLocalRunnerEntryArgs(cliPath) {
|
|
|
17611
17642
|
return [path27.resolve(path27.dirname(cliPath), "../bin/vibetime.mjs")];
|
|
17612
17643
|
}
|
|
17613
17644
|
function resolveHome3(options, ctx) {
|
|
17614
|
-
return path27.resolve(stringOption(options.home) || ctx.env.HOME ||
|
|
17645
|
+
return path27.resolve(stringOption(options.home) || ctx.env.HOME || os13.homedir());
|
|
17615
17646
|
}
|
|
17616
17647
|
function requestedTargets(options) {
|
|
17617
17648
|
const value = options.target || options.targets;
|
|
@@ -17621,7 +17652,13 @@ function requestedTargets(options) {
|
|
|
17621
17652
|
return valuesOption(value).flatMap((item) => item.split(",")).map((t) => t.trim()).filter(Boolean);
|
|
17622
17653
|
}
|
|
17623
17654
|
function normalizeBackfillSource(source) {
|
|
17624
|
-
|
|
17655
|
+
if (source === "claude") {
|
|
17656
|
+
return "claude-code";
|
|
17657
|
+
}
|
|
17658
|
+
if (source === "grok-bot") {
|
|
17659
|
+
return "cursor";
|
|
17660
|
+
}
|
|
17661
|
+
return source;
|
|
17625
17662
|
}
|
|
17626
17663
|
function requiredOption(options, name) {
|
|
17627
17664
|
const value = stringOption(options[name]);
|
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.76",
|
|
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": {
|