@yhong91/vibetime 0.1.57 → 0.1.58

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.
Files changed (2) hide show
  1. package/bin/vibetime.mjs +201 -61
  2. package/package.json +1 -1
package/bin/vibetime.mjs CHANGED
@@ -884,7 +884,7 @@ var init_esm = __esm({
884
884
 
885
885
  // src/cli.ts
886
886
  import { spawn as spawn2, spawnSync } from "node:child_process";
887
- import { mkdir as mkdir5, open, rm, stat as stat15, writeFile as writeFile4 } from "node:fs/promises";
887
+ import { mkdir as mkdir5, open, rm, stat as stat16, writeFile as writeFile4 } from "node:fs/promises";
888
888
  import os13 from "node:os";
889
889
  import path26 from "node:path";
890
890
  import { fileURLToPath } from "node:url";
@@ -2047,7 +2047,7 @@ function claudeStyleFileMetrics(tool, input) {
2047
2047
  }
2048
2048
 
2049
2049
  // src/lib/constants.ts
2050
- var PACKAGE_VERSION = true ? "0.1.57" : "0.1.1";
2050
+ var PACKAGE_VERSION = true ? "0.1.58" : "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;
@@ -5011,8 +5011,8 @@ async function codebuddyBackfillFiles(sourceRoot, home, env) {
5011
5011
  }
5012
5012
  const filePath = path9.join(traceDir, entry);
5013
5013
  try {
5014
- const stat16 = await import("node:fs/promises").then((fs) => fs.stat(filePath));
5015
- files.push({ path: filePath, modifiedAt: stat16.mtime.toISOString(), groupId: pidDir.name });
5014
+ const stat17 = await import("node:fs/promises").then((fs) => fs.stat(filePath));
5015
+ files.push({ path: filePath, modifiedAt: stat17.mtime.toISOString(), groupId: pidDir.name });
5016
5016
  } catch {
5017
5017
  }
5018
5018
  }
@@ -5099,7 +5099,7 @@ function fileActivitiesFromPatchChanges(changes, ts, cwd, displayFilePath3) {
5099
5099
  }
5100
5100
 
5101
5101
  // src/lib/session-context.ts
5102
- import { mkdir as mkdir3, writeFile as writeFile3 } from "node:fs/promises";
5102
+ import { mkdir as mkdir3, stat as stat6, writeFile as writeFile3 } from "node:fs/promises";
5103
5103
  import os4 from "node:os";
5104
5104
  import path10 from "node:path";
5105
5105
  init_fs();
@@ -5126,32 +5126,86 @@ async function readPersistedSessionContext(home, sessionId) {
5126
5126
  }
5127
5127
  const cwd = typeof raw.cwd === "string" && raw.cwd.length > 0 ? raw.cwd : void 0;
5128
5128
  const project = typeof raw.project === "string" && raw.project.length > 0 ? raw.project : void 0;
5129
- return { version: SESSION_CONTEXT_VERSION, sessionId, cwd, project, updatedAt: raw.updatedAt };
5129
+ const usage = Array.isArray(raw.usage) ? raw.usage.filter((item) => {
5130
+ return isPlainObject(item) && typeof item.generationId === "string" && item.generationId.length > 0 && typeof item.ts === "string";
5131
+ }) : void 0;
5132
+ return { version: SESSION_CONTEXT_VERSION, sessionId, cwd, project, updatedAt: raw.updatedAt, usage };
5130
5133
  }
5131
5134
  async function readPersistedSessionContextFromOptions(options, sessionId) {
5132
5135
  return readPersistedSessionContext(resolveHome2(options), sessionId);
5133
5136
  }
5137
+ async function persistedSessionContextModifiedAt(home, sessionId) {
5138
+ const info = await stat6(sessionContextPath(home, sessionId)).catch(() => null);
5139
+ return info?.isFile() ? info.mtime : void 0;
5140
+ }
5134
5141
  async function persistHookSessionContext(home, payload) {
5135
5142
  if (!isPlainObject(payload)) {
5136
5143
  return;
5137
5144
  }
5138
- const sessionId = typeof payload.session_id === "string" ? payload.session_id.trim() : typeof payload.sessionId === "string" ? payload.sessionId.trim() : "";
5139
- const cwd = typeof payload.cwd === "string" ? payload.cwd.trim() : "";
5140
- if (!sessionId || !cwd || !path10.isAbsolute(cwd)) {
5145
+ const sessionId = hookSessionId(payload);
5146
+ const cwdRaw = typeof payload.cwd === "string" ? payload.cwd.trim() : "";
5147
+ const cwd = cwdRaw && path10.isAbsolute(cwdRaw) ? cwdRaw : void 0;
5148
+ const usage = hookUsageFromPayload(payload);
5149
+ if (!sessionId || !cwd && !usage) {
5141
5150
  return;
5142
5151
  }
5143
- const project = path10.basename(cwd) || void 0;
5152
+ const existing = await readPersistedSessionContext(home, sessionId);
5153
+ const nextUsage = mergeHookUsage(existing?.usage, usage);
5154
+ const nextCwd = cwd || existing?.cwd;
5144
5155
  const context = {
5145
5156
  version: SESSION_CONTEXT_VERSION,
5146
5157
  sessionId,
5147
- cwd,
5148
- project,
5149
- updatedAt: (/* @__PURE__ */ new Date()).toISOString()
5158
+ cwd: nextCwd,
5159
+ project: nextCwd ? path10.basename(nextCwd) : existing?.project,
5160
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
5161
+ usage: nextUsage
5150
5162
  };
5151
5163
  await mkdir3(sessionContextDir(home), { recursive: true });
5152
5164
  await writeFile3(sessionContextPath(home, sessionId), `${JSON.stringify(context, null, 2)}
5153
5165
  `, "utf8");
5154
5166
  }
5167
+ function hookSessionId(payload) {
5168
+ for (const key of ["session_id", "sessionId", "conversation_id", "conversationId"]) {
5169
+ const value = stringField(payload, key)?.trim();
5170
+ if (value) {
5171
+ return value;
5172
+ }
5173
+ }
5174
+ return "";
5175
+ }
5176
+ function hookUsageFromPayload(payload) {
5177
+ const nested = objectField(payload, "token_usage").inputTokens !== void 0 || objectField(payload, "tokenUsage").inputTokens !== void 0 ? { ...objectField(payload, "token_usage"), ...objectField(payload, "tokenUsage") } : payload;
5178
+ const tokensInput = numberField(nested, "input_tokens") ?? numberField(nested, "inputTokens") ?? numberField(payload, "input_tokens") ?? numberField(payload, "inputTokens");
5179
+ const tokensOutput = numberField(nested, "output_tokens") ?? numberField(nested, "outputTokens") ?? numberField(payload, "output_tokens") ?? numberField(payload, "outputTokens");
5180
+ const tokensCacheReadInput = numberField(nested, "cache_read_tokens") ?? numberField(nested, "cacheReadTokens") ?? numberField(payload, "cache_read_tokens") ?? numberField(payload, "cacheReadTokens");
5181
+ const tokensCacheCreationInput = numberField(nested, "cache_write_tokens") ?? numberField(nested, "cacheWriteTokens") ?? numberField(payload, "cache_write_tokens") ?? numberField(payload, "cacheWriteTokens");
5182
+ if (!tokensInput && !tokensOutput && !tokensCacheReadInput && !tokensCacheCreationInput) {
5183
+ return void 0;
5184
+ }
5185
+ const generationId = stringField(payload, "generation_id")?.trim() || stringField(payload, "generationId")?.trim() || stringField(payload, "request_id")?.trim() || stringField(payload, "requestId")?.trim() || `${tokensInput || 0}:${tokensOutput || 0}:${tokensCacheReadInput || 0}:${tokensCacheCreationInput || 0}`;
5186
+ return {
5187
+ generationId,
5188
+ ts: stringField(payload, "timestamp") || (/* @__PURE__ */ new Date()).toISOString(),
5189
+ model: stringField(payload, "model") || stringField(payload, "model_name"),
5190
+ tokensInput: tokensInput || void 0,
5191
+ tokensOutput: tokensOutput || void 0,
5192
+ tokensCacheReadInput: tokensCacheReadInput || void 0,
5193
+ tokensCacheCreationInput: tokensCacheCreationInput || void 0
5194
+ };
5195
+ }
5196
+ function mergeHookUsage(existing, next) {
5197
+ if (!next) {
5198
+ return existing;
5199
+ }
5200
+ const current = existing ? [...existing] : [];
5201
+ const index = current.findIndex((item) => item.generationId === next.generationId);
5202
+ if (index >= 0) {
5203
+ current[index] = next;
5204
+ } else {
5205
+ current.push(next);
5206
+ }
5207
+ return current;
5208
+ }
5155
5209
 
5156
5210
  // src/adapters/codex.ts
5157
5211
  async function parseCodexSessionFile(filePath, options) {
@@ -5841,7 +5895,7 @@ function createCodexAdapter() {
5841
5895
  }
5842
5896
 
5843
5897
  // src/adapters/copilot.ts
5844
- import { readdir as readdir5, readFile as readFile7, stat as stat6 } from "node:fs/promises";
5898
+ import { readdir as readdir5, readFile as readFile7, stat as stat7 } from "node:fs/promises";
5845
5899
  import os5 from "node:os";
5846
5900
  import path12 from "node:path";
5847
5901
  async function parseCopilotSessionFile(filePath, options) {
@@ -6182,7 +6236,7 @@ async function copilotBackfillFiles(sourceRoot, home = os5.homedir(), _env) {
6182
6236
  continue;
6183
6237
  }
6184
6238
  const eventsPath = path12.join(sessionDir, entry, "events.jsonl");
6185
- const info = await stat6(eventsPath).catch(() => null);
6239
+ const info = await stat7(eventsPath).catch(() => null);
6186
6240
  if (info) {
6187
6241
  results.push({ path: eventsPath, modifiedAt: info.mtime.toISOString() });
6188
6242
  }
@@ -6238,7 +6292,7 @@ function createCopilotAdapter() {
6238
6292
  }
6239
6293
 
6240
6294
  // src/adapters/cursor.ts
6241
- import { copyFile, readdir as readdir6, readFile as readFile8, stat as stat7 } from "node:fs/promises";
6295
+ import { copyFile, readdir as readdir6, readFile as readFile8, stat as stat8 } from "node:fs/promises";
6242
6296
  import os6 from "node:os";
6243
6297
  import path13 from "node:path";
6244
6298
 
@@ -6362,6 +6416,7 @@ var CURSOR_HOOK_EVENTS = [
6362
6416
  "subagentStart",
6363
6417
  "subagentStop",
6364
6418
  "stop",
6419
+ "afterAgentResponse",
6365
6420
  "afterFileEdit",
6366
6421
  "afterShellExecution",
6367
6422
  "preCompact"
@@ -6778,7 +6833,7 @@ async function buildCursorChatMetaIndex(cursorHome2) {
6778
6833
  return index;
6779
6834
  }
6780
6835
  async function readCursorStoreMeta(storePath) {
6781
- const info = await stat7(storePath).catch(() => null);
6836
+ const info = await stat8(storePath).catch(() => null);
6782
6837
  if (!info) {
6783
6838
  return {};
6784
6839
  }
@@ -6851,7 +6906,7 @@ async function parseCursorTranscriptFile(filePath, options) {
6851
6906
  }
6852
6907
  const sessionId = path13.basename(filePath, ".jsonl");
6853
6908
  const context = await resolveTranscriptContext(filePath, sessionId);
6854
- const fileInfo = await stat7(filePath).catch(() => null);
6909
+ const fileInfo = await stat8(filePath).catch(() => null);
6855
6910
  let cwd = context.cwd;
6856
6911
  let project = context.project;
6857
6912
  let model = context.model;
@@ -7062,6 +7117,7 @@ async function parseCursorTranscriptFile(filePath, options) {
7062
7117
  }
7063
7118
  }
7064
7119
  const endedAt = latestTimestamp(lastTs, context.endedAt, fileMtime);
7120
+ const lastTurnId = currentTurnId;
7065
7121
  if (endedAt) {
7066
7122
  closeTurn(endedAt);
7067
7123
  if (sessionStarted) {
@@ -7073,11 +7129,59 @@ async function parseCursorTranscriptFile(filePath, options) {
7073
7129
  }, "transcript");
7074
7130
  }
7075
7131
  }
7132
+ await appendPersistedCursorUsage({
7133
+ push,
7134
+ sessionId,
7135
+ options,
7136
+ fallbackTs: endedAt || lastTs,
7137
+ lastTurnId,
7138
+ model,
7139
+ skip: events.some((event) => event.type === "model.usage")
7140
+ });
7076
7141
  return events;
7077
7142
  }
7143
+ async function appendPersistedCursorUsage(args) {
7144
+ if (args.skip) {
7145
+ return;
7146
+ }
7147
+ const persisted = await readPersistedSessionContextFromOptions(args.options, args.sessionId);
7148
+ emitPersistedCursorUsage(
7149
+ args.push,
7150
+ persisted?.usage,
7151
+ args.fallbackTs,
7152
+ args.lastTurnId,
7153
+ args.model,
7154
+ args.sessionId
7155
+ );
7156
+ }
7157
+ function emitPersistedCursorUsage(push, usage, fallbackTs, lastTurnId, model, sessionId, skip = false) {
7158
+ if (skip || !usage?.length || !fallbackTs) {
7159
+ return;
7160
+ }
7161
+ for (const item of usage) {
7162
+ const metrics = usageMetrics({
7163
+ inputTokens: item.tokensInput,
7164
+ outputTokens: item.tokensOutput,
7165
+ cacheReadTokens: item.tokensCacheReadInput,
7166
+ cacheWriteTokens: item.tokensCacheCreationInput
7167
+ });
7168
+ if (!metrics) {
7169
+ continue;
7170
+ }
7171
+ push({
7172
+ ts: timestampFrom(item.ts) || fallbackTs,
7173
+ type: "model.usage",
7174
+ turnId: lastTurnId,
7175
+ model: item.model || model,
7176
+ confidence: "exact",
7177
+ metrics,
7178
+ refs: stringRefs({ sourceId: `${sessionId}:${item.generationId}:usage` })
7179
+ }, "hook-usage");
7180
+ }
7181
+ }
7078
7182
  async function listCursorComposerIds(dbPath) {
7079
7183
  const ids = /* @__PURE__ */ new Set();
7080
- const info = await stat7(dbPath).catch(() => null);
7184
+ const info = await stat8(dbPath).catch(() => null);
7081
7185
  if (!info) {
7082
7186
  return ids;
7083
7187
  }
@@ -7096,7 +7200,17 @@ async function listCursorComposerIds(dbPath) {
7096
7200
  }
7097
7201
  return ids;
7098
7202
  }
7099
- async function collectCursorTranscriptFiles(root, skipSessionIds) {
7203
+ async function modifiedAtWithHookUsage(fileMtime, home, sessionIds) {
7204
+ let latest = fileMtime.getTime();
7205
+ for (const sessionId of sessionIds) {
7206
+ const extra = await persistedSessionContextModifiedAt(home, sessionId);
7207
+ if (extra && extra.getTime() > latest) {
7208
+ latest = extra.getTime();
7209
+ }
7210
+ }
7211
+ return new Date(latest).toISOString();
7212
+ }
7213
+ async function collectCursorTranscriptFiles(root, home, skipSessionIds) {
7100
7214
  const files = [];
7101
7215
  const seen = /* @__PURE__ */ new Set();
7102
7216
  for (const filePath of await listJsonlFiles(root)) {
@@ -7108,11 +7222,14 @@ async function collectCursorTranscriptFiles(root, skipSessionIds) {
7108
7222
  continue;
7109
7223
  }
7110
7224
  seen.add(sessionId);
7111
- const info = await stat7(filePath).catch(() => null);
7225
+ const info = await stat8(filePath).catch(() => null);
7112
7226
  if (!info) {
7113
7227
  continue;
7114
7228
  }
7115
- files.push({ path: filePath, modifiedAt: info.mtime.toISOString() });
7229
+ files.push({
7230
+ path: filePath,
7231
+ modifiedAt: await modifiedAtWithHookUsage(info.mtime, home, [sessionId])
7232
+ });
7116
7233
  }
7117
7234
  return files;
7118
7235
  }
@@ -7133,7 +7250,8 @@ async function parseCursorSessionFile(filePath, options) {
7133
7250
  try {
7134
7251
  const composers = listComposers(opened.db);
7135
7252
  for (const composer of composers) {
7136
- events.push(...parseComposer(opened.db, composer, filePath, sourcePathHash, options));
7253
+ const persisted = await readPersistedSessionContextFromOptions(options, composer.composerId);
7254
+ events.push(...parseComposer(opened.db, composer, filePath, sourcePathHash, options, persisted?.usage));
7137
7255
  }
7138
7256
  } finally {
7139
7257
  opened.db.close();
@@ -7141,7 +7259,7 @@ async function parseCursorSessionFile(filePath, options) {
7141
7259
  }
7142
7260
  return events;
7143
7261
  }
7144
- function parseComposer(db, composer, filePath, sourcePathHash, options) {
7262
+ function parseComposer(db, composer, filePath, sourcePathHash, options, persistedUsage) {
7145
7263
  const sessionId = composer.composerId;
7146
7264
  const data = composer.data;
7147
7265
  const { cwd, project } = workspaceFromComposer(data);
@@ -7351,54 +7469,76 @@ function parseComposer(db, composer, filePath, sourcePathHash, options) {
7351
7469
  refs: stringRefs({ sourceId: `${sessionId}:ended` })
7352
7470
  }, "composer");
7353
7471
  }
7472
+ emitPersistedCursorUsage(push, persistedUsage, endedAt || startedAt, currentTurnId, model, sessionId, events.some((event) => event.type === "model.usage"));
7354
7473
  return events;
7355
7474
  }
7356
7475
  async function cursorBackfillFiles(sourceRoot, home = os6.homedir(), env) {
7357
7476
  if (sourceRoot) {
7358
- const info = await stat7(sourceRoot).catch(() => null);
7477
+ const info = await stat8(sourceRoot).catch(() => null);
7359
7478
  if (!info) {
7360
7479
  return [];
7361
7480
  }
7362
7481
  if (info.isDirectory()) {
7363
7482
  const files2 = [];
7483
+ const skipIds2 = /* @__PURE__ */ new Set();
7364
7484
  for (const dbPath of await listFilesByExtensions(sourceRoot, [".vscdb", ".db"])) {
7365
7485
  const base = path13.basename(dbPath);
7366
7486
  if (base === "store.db" || base !== "state.vscdb" && !base.endsWith(".vscdb")) {
7367
7487
  continue;
7368
7488
  }
7369
- const dbInfo = await stat7(dbPath).catch(() => null);
7370
- if (dbInfo) {
7371
- files2.push({ path: dbPath, modifiedAt: dbInfo.mtime.toISOString() });
7489
+ const dbInfo = await stat8(dbPath).catch(() => null);
7490
+ if (!dbInfo) {
7491
+ continue;
7372
7492
  }
7373
- }
7374
- const skipIds2 = /* @__PURE__ */ new Set();
7375
- for (const file of files2) {
7376
- for (const id of await listCursorComposerIds(file.path)) {
7493
+ const composerIds2 = await listCursorComposerIds(dbPath);
7494
+ for (const id of composerIds2) {
7377
7495
  skipIds2.add(id);
7378
7496
  }
7497
+ files2.push({
7498
+ path: dbPath,
7499
+ modifiedAt: await modifiedAtWithHookUsage(dbInfo.mtime, home, composerIds2)
7500
+ });
7379
7501
  }
7380
- files2.push(...await collectCursorTranscriptFiles(sourceRoot, skipIds2));
7502
+ files2.push(...await collectCursorTranscriptFiles(sourceRoot, home, skipIds2));
7381
7503
  return files2;
7382
7504
  }
7383
7505
  if (path13.basename(sourceRoot) === "store.db") {
7384
7506
  return [];
7385
7507
  }
7386
- return [{ path: sourceRoot, modifiedAt: info.mtime.toISOString() }];
7508
+ if (sourceRoot.endsWith(".jsonl")) {
7509
+ return [{
7510
+ path: sourceRoot,
7511
+ modifiedAt: await modifiedAtWithHookUsage(
7512
+ info.mtime,
7513
+ home,
7514
+ [path13.basename(sourceRoot, ".jsonl")]
7515
+ )
7516
+ }];
7517
+ }
7518
+ const composerIds = await listCursorComposerIds(sourceRoot);
7519
+ return [{
7520
+ path: sourceRoot,
7521
+ modifiedAt: await modifiedAtWithHookUsage(info.mtime, home, composerIds)
7522
+ }];
7387
7523
  }
7388
7524
  const files = [];
7389
7525
  const skipIds = /* @__PURE__ */ new Set();
7390
7526
  for (const candidatePath of cursorStateDbCandidates(home, env)) {
7391
- const info = await stat7(candidatePath).catch(() => null);
7527
+ const info = await stat8(candidatePath).catch(() => null);
7392
7528
  if (!info) {
7393
7529
  continue;
7394
7530
  }
7395
- files.push({ path: candidatePath, modifiedAt: info.mtime.toISOString() });
7396
- for (const id of await listCursorComposerIds(candidatePath)) {
7531
+ const composerIds = await listCursorComposerIds(candidatePath);
7532
+ for (const id of composerIds) {
7397
7533
  skipIds.add(id);
7398
7534
  }
7535
+ files.push({
7536
+ path: candidatePath,
7537
+ modifiedAt: await modifiedAtWithHookUsage(info.mtime, home, composerIds)
7538
+ });
7399
7539
  break;
7400
7540
  }
7401
- files.push(...await collectCursorTranscriptFiles(cursorProjectsDir(home, env), skipIds));
7541
+ files.push(...await collectCursorTranscriptFiles(cursorProjectsDir(home, env), home, skipIds));
7402
7542
  return files;
7403
7543
  }
7404
7544
  function cursorHookConfig() {
@@ -7444,7 +7584,7 @@ function createCursorAdapter() {
7444
7584
  }
7445
7585
 
7446
7586
  // src/adapters/grok-build.ts
7447
- import { readdir as readdir7, readFile as readFile9, stat as stat8 } from "node:fs/promises";
7587
+ import { readdir as readdir7, readFile as readFile9, stat as stat9 } from "node:fs/promises";
7448
7588
  import path14 from "node:path";
7449
7589
  init_fs();
7450
7590
  var GROK_COST_TICKS_PER_USD = 1e9;
@@ -7484,7 +7624,7 @@ async function grokBackfillFiles(sourceRoot, home, env) {
7484
7624
  continue;
7485
7625
  }
7486
7626
  try {
7487
- const info = await stat8(entryPath);
7627
+ const info = await stat9(entryPath);
7488
7628
  files.push({ path: entryPath, modifiedAt: info.mtime.toISOString() });
7489
7629
  } catch {
7490
7630
  }
@@ -9244,19 +9384,19 @@ function opencodeDataCandidates(home, env) {
9244
9384
  return [primary, path16.join(home, ".opencode", "opencode.db")];
9245
9385
  }
9246
9386
  async function opencodeBackfillFiles(sourceRoot, home = os7.homedir(), env) {
9247
- const { stat: stat16 } = await import("node:fs/promises");
9387
+ const { stat: stat17 } = await import("node:fs/promises");
9248
9388
  if (sourceRoot) {
9249
9389
  if (!sourceRoot.endsWith(".db")) {
9250
9390
  return [];
9251
9391
  }
9252
- const info = await stat16(sourceRoot).catch(() => null);
9392
+ const info = await stat17(sourceRoot).catch(() => null);
9253
9393
  if (!info) {
9254
9394
  return [];
9255
9395
  }
9256
9396
  return [{ path: sourceRoot, modifiedAt: info.mtime.toISOString() }];
9257
9397
  }
9258
9398
  for (const candidatePath of opencodeDataCandidates(home, env)) {
9259
- const info = await stat16(candidatePath).catch(() => null);
9399
+ const info = await stat17(candidatePath).catch(() => null);
9260
9400
  if (info) {
9261
9401
  return [{ path: candidatePath, modifiedAt: info.mtime.toISOString() }];
9262
9402
  }
@@ -9356,7 +9496,7 @@ function createOpenCodeAdapter() {
9356
9496
  }
9357
9497
 
9358
9498
  // src/adapters/pi.ts
9359
- import { readdir as readdir8, readFile as readFile11, stat as stat9 } from "node:fs/promises";
9499
+ import { readdir as readdir8, readFile as readFile11, stat as stat10 } from "node:fs/promises";
9360
9500
  import os8 from "node:os";
9361
9501
  import path17 from "node:path";
9362
9502
  init_fs();
@@ -10052,7 +10192,7 @@ async function piBackfillFiles(sourceRoot, home = os8.homedir(), env) {
10052
10192
  ]);
10053
10193
  const files = lists.flat().sort();
10054
10194
  return Promise.all(files.map(async (filePath) => {
10055
- const info = await stat9(filePath);
10195
+ const info = await stat10(filePath);
10056
10196
  let groupId = resolvePiBackfillGroupId(filePath);
10057
10197
  if (!groupId && filePath.endsWith(".json")) {
10058
10198
  groupId = await workflowRunGroupId(filePath);
@@ -10099,7 +10239,7 @@ function createPiAdapter() {
10099
10239
  }
10100
10240
 
10101
10241
  // src/adapters/qoder-cn.ts
10102
- import { readdir as readdir9, readFile as readFile12, stat as stat10 } from "node:fs/promises";
10242
+ import { readdir as readdir9, readFile as readFile12, stat as stat11 } from "node:fs/promises";
10103
10243
  import os10 from "node:os";
10104
10244
  import path19 from "node:path";
10105
10245
 
@@ -10996,7 +11136,7 @@ async function gitRootFromCwds2(cwds) {
10996
11136
  while (!seen.has(current)) {
10997
11137
  seen.add(current);
10998
11138
  try {
10999
- await stat10(path19.join(current, ".git"));
11139
+ await stat11(path19.join(current, ".git"));
11000
11140
  return current;
11001
11141
  } catch {
11002
11142
  }
@@ -11146,7 +11286,7 @@ function createQoderCnAdapter() {
11146
11286
 
11147
11287
  // src/adapters/qoder.ts
11148
11288
  import { existsSync } from "node:fs";
11149
- import { readdir as readdir10, readFile as readFile13, stat as stat11 } from "node:fs/promises";
11289
+ import { readdir as readdir10, readFile as readFile13, stat as stat12 } from "node:fs/promises";
11150
11290
  import os11 from "node:os";
11151
11291
  import path20 from "node:path";
11152
11292
  function parseQoderPaths(filePath) {
@@ -11842,7 +11982,7 @@ async function gitRootFromCwds3(cwds) {
11842
11982
  while (!seen.has(current)) {
11843
11983
  seen.add(current);
11844
11984
  try {
11845
- await stat11(path20.join(current, ".git"));
11985
+ await stat12(path20.join(current, ".git"));
11846
11986
  return current;
11847
11987
  } catch {
11848
11988
  }
@@ -12050,7 +12190,7 @@ function normalizeId(id) {
12050
12190
  }
12051
12191
 
12052
12192
  // src/adapters/workbuddy.ts
12053
- import { readdir as readdir11, readFile as readFile14, stat as stat12 } from "node:fs/promises";
12193
+ import { readdir as readdir11, readFile as readFile14, stat as stat13 } from "node:fs/promises";
12054
12194
  import path21 from "node:path";
12055
12195
  function workbuddyProjectsDir(home, env) {
12056
12196
  const override = env?.WORKBUDDY_PROJECTS_DIR || env?.WORKBUDDY_HOME;
@@ -12503,7 +12643,7 @@ async function workbuddyBackfillFiles(sourceRoot, home, env) {
12503
12643
  for (const entry of entries) {
12504
12644
  if (entry.isFile() && entry.name.endsWith(".jsonl")) {
12505
12645
  const filePath = path21.join(projectDir, entry.name);
12506
- const info = await stat12(filePath);
12646
+ const info = await stat13(filePath);
12507
12647
  files.push({ path: filePath, modifiedAt: info.mtime.toISOString() });
12508
12648
  }
12509
12649
  }
@@ -12564,7 +12704,7 @@ function createWorkbuddyAdapter() {
12564
12704
 
12565
12705
  // src/adapters/zcode.ts
12566
12706
  import { execFile } from "node:child_process";
12567
- import { readFile as readFile15, stat as stat13 } from "node:fs/promises";
12707
+ import { readFile as readFile15, stat as stat14 } from "node:fs/promises";
12568
12708
  import path22 from "node:path";
12569
12709
  import { promisify as promisify2 } from "node:util";
12570
12710
  init_fs();
@@ -12583,7 +12723,7 @@ var providerNameCache = null;
12583
12723
  async function loadProviderNames(configPath2) {
12584
12724
  let fileMtime = 0;
12585
12725
  try {
12586
- const info = await stat13(configPath2);
12726
+ const info = await stat14(configPath2);
12587
12727
  fileMtime = info.mtimeMs;
12588
12728
  } catch {
12589
12729
  return /* @__PURE__ */ new Map();
@@ -12800,7 +12940,7 @@ async function parseZCodeDb(filePath, options) {
12800
12940
  for (let i = 0; i < 12; i++) {
12801
12941
  const probe = path22.join(candidate, ".zcode", "v2", "config.json");
12802
12942
  try {
12803
- await stat13(probe);
12943
+ await stat14(probe);
12804
12944
  configPath2 = probe;
12805
12945
  break;
12806
12946
  } catch {
@@ -13026,7 +13166,7 @@ async function zcodeBackfillFiles(sourceRoot, home, env) {
13026
13166
  const candidate = sourceRoot || zcodeDbPath(home, env);
13027
13167
  const filePath = candidate.endsWith(".sqlite") ? candidate : path22.join(candidate, "db", "db.sqlite");
13028
13168
  try {
13029
- const info = await stat13(filePath);
13169
+ const info = await stat14(filePath);
13030
13170
  return [{ path: filePath, modifiedAt: info.mtime.toISOString() }];
13031
13171
  } catch {
13032
13172
  return [];
@@ -13411,19 +13551,19 @@ async function parseZedSessionFile(dbPath, options) {
13411
13551
  return events.filter((event) => matchesBackfillFilters(event, options));
13412
13552
  }
13413
13553
  async function zedBackfillFiles(sourceRoot, home = os12.homedir(), env) {
13414
- const { stat: stat16 } = await import("node:fs/promises");
13554
+ const { stat: stat17 } = await import("node:fs/promises");
13415
13555
  if (sourceRoot) {
13416
13556
  if (!sourceRoot.endsWith(".db")) {
13417
13557
  return [];
13418
13558
  }
13419
- const info = await stat16(sourceRoot).catch(() => null);
13559
+ const info = await stat17(sourceRoot).catch(() => null);
13420
13560
  if (!info) {
13421
13561
  return [];
13422
13562
  }
13423
13563
  return [{ path: sourceRoot, modifiedAt: info.mtime.toISOString() }];
13424
13564
  }
13425
13565
  for (const candidatePath of zedThreadsCandidates(home, env)) {
13426
- const info = await stat16(candidatePath).catch(() => null);
13566
+ const info = await stat17(candidatePath).catch(() => null);
13427
13567
  if (info) {
13428
13568
  return [{ path: candidatePath, modifiedAt: info.mtime.toISOString() }];
13429
13569
  }
@@ -14272,7 +14412,7 @@ function defaultMachineName() {
14272
14412
  init_fs();
14273
14413
 
14274
14414
  // src/lib/logger.ts
14275
- import { appendFile, mkdir as mkdir4, rename, stat as stat14 } from "node:fs/promises";
14415
+ import { appendFile, mkdir as mkdir4, rename, stat as stat15 } from "node:fs/promises";
14276
14416
  import { homedir as homedir2 } from "node:os";
14277
14417
  import path25 from "node:path";
14278
14418
  var MAX_BYTES = 1 * 1024 * 1024;
@@ -14290,7 +14430,7 @@ function serializeError(error) {
14290
14430
  }
14291
14431
  async function rotateIfNeeded(file) {
14292
14432
  try {
14293
- const info = await stat14(file);
14433
+ const info = await stat15(file);
14294
14434
  if (info.size > MAX_BYTES) {
14295
14435
  await rename(file, `${file}.1`).catch(() => {
14296
14436
  });
@@ -15114,7 +15254,7 @@ async function listBackfillSourceFiles(source, options, ctx) {
15114
15254
  const fileLists = await Promise.all(roots.map((r) => listJsonlFiles(r)));
15115
15255
  const files = fileLists.flat().sort().slice(0, numberOption(options.limit) || void 0);
15116
15256
  return Promise.all(files.map(async (filePath) => {
15117
- const info = await stat15(filePath);
15257
+ const info = await stat16(filePath);
15118
15258
  return { path: filePath, modifiedAt: info.mtime.toISOString() };
15119
15259
  }));
15120
15260
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@yhong91/vibetime",
3
3
  "type": "module",
4
- "version": "0.1.57",
4
+ "version": "0.1.58",
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": {