@yhong91/vibetime 0.1.31 → 0.1.32

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 +271 -126
  2. package/package.json +1 -1
package/bin/vibetime.mjs CHANGED
@@ -885,8 +885,8 @@ var init_esm = __esm({
885
885
  // src/cli.ts
886
886
  import { spawn as spawn2, spawnSync } from "node:child_process";
887
887
  import { mkdir as mkdir5, open, rm, stat as stat13, writeFile as writeFile4 } from "node:fs/promises";
888
- import os10 from "node:os";
889
- import path23 from "node:path";
888
+ import os11 from "node:os";
889
+ import path24 from "node:path";
890
890
  import { fileURLToPath } from "node:url";
891
891
 
892
892
  // ../shared/src/index.ts
@@ -1928,7 +1928,7 @@ function countTextLines(text) {
1928
1928
  }
1929
1929
 
1930
1930
  // src/lib/constants.ts
1931
- var PACKAGE_VERSION = true ? "0.1.31" : "0.1.1";
1931
+ var PACKAGE_VERSION = true ? "0.1.32" : "0.1.1";
1932
1932
  var DEFAULT_API_URL = "http://121.196.224.82:3001";
1933
1933
  var DEFAULT_BACKFILL_BATCH_SIZE = 50;
1934
1934
  var DEFAULT_BACKFILL_BATCH_BYTES = 800 * 1024;
@@ -7426,12 +7426,91 @@ function createPiAdapter() {
7426
7426
  };
7427
7427
  }
7428
7428
 
7429
- // src/adapters/qoder-cn.ts
7430
- import { readdir as readdir7, readFile as readFile10, stat as stat8 } from "node:fs/promises";
7429
+ // src/adapters/qoder-local-db.ts
7430
+ import { access } from "node:fs/promises";
7431
7431
  import os7 from "node:os";
7432
7432
  import path16 from "node:path";
7433
+ function qoderLocalDbCandidates(appDirName) {
7434
+ const candidates = [];
7435
+ const envPath = process.env.QODER_LOCAL_DB_PATH;
7436
+ if (envPath) {
7437
+ candidates.push(envPath);
7438
+ }
7439
+ const home = os7.homedir();
7440
+ let configRoot;
7441
+ if (process.platform === "darwin") {
7442
+ configRoot = path16.join(home, "Library", "Application Support", appDirName);
7443
+ } else if (process.platform === "win32") {
7444
+ configRoot = path16.join(process.env.APPDATA || path16.join(home, "AppData", "Roaming"), appDirName);
7445
+ } else {
7446
+ configRoot = path16.join(home, ".config", appDirName);
7447
+ }
7448
+ candidates.push(
7449
+ path16.join(configRoot, "SharedClientCache", "cache", "db", "local.db"),
7450
+ path16.join(configRoot, "SharedClientCache", "db", "local.db")
7451
+ );
7452
+ return candidates;
7453
+ }
7454
+ async function loadQoderDbModelCalls(appDirName, sessionId, modelMap) {
7455
+ const calls = { byRequestId: /* @__PURE__ */ new Map(), ordered: [] };
7456
+ if (!sessionId) {
7457
+ return calls;
7458
+ }
7459
+ try {
7460
+ const { DatabaseSync } = await import("node:sqlite");
7461
+ let dbPath;
7462
+ for (const candidate of qoderLocalDbCandidates(appDirName)) {
7463
+ try {
7464
+ await access(candidate);
7465
+ dbPath = candidate;
7466
+ break;
7467
+ } catch {
7468
+ }
7469
+ }
7470
+ if (!dbPath) {
7471
+ return calls;
7472
+ }
7473
+ const db = new DatabaseSync(dbPath, { readOnly: true });
7474
+ try {
7475
+ const rows = db.prepare(
7476
+ `select request_id, token_info, model_info from chat_message where session_id = ? and role = 'assistant' and token_info != '' order by gmt_create asc`
7477
+ ).all(sessionId);
7478
+ for (const row of rows) {
7479
+ const usage = parseJsonLine(stringField(row, "token_info") || "") || {};
7480
+ const modelInfo = parseJsonLine(stringField(row, "model_info") || "") || {};
7481
+ const modelKey = stringField(modelInfo, "model_key");
7482
+ const call = {
7483
+ model: modelKey ? modelMap[modelKey] || modelKey : void 0,
7484
+ inputTokens: numberField(usage, "prompt_tokens") || 0,
7485
+ outputTokens: numberField(usage, "completion_tokens") || 0,
7486
+ cachedTokens: numberField(usage, "cached_tokens") || 0
7487
+ };
7488
+ calls.ordered.push(call);
7489
+ const requestId = stringField(row, "request_id");
7490
+ if (!requestId) {
7491
+ continue;
7492
+ }
7493
+ const queue = calls.byRequestId.get(requestId);
7494
+ if (queue) {
7495
+ queue.push(call);
7496
+ } else {
7497
+ calls.byRequestId.set(requestId, [call]);
7498
+ }
7499
+ }
7500
+ } finally {
7501
+ db.close();
7502
+ }
7503
+ } catch {
7504
+ }
7505
+ return calls;
7506
+ }
7507
+
7508
+ // src/adapters/qoder-cn.ts
7509
+ import { readdir as readdir7, readFile as readFile10, stat as stat8 } from "node:fs/promises";
7510
+ import os8 from "node:os";
7511
+ import path17 from "node:path";
7433
7512
  function parseQoderCnPaths(filePath) {
7434
- const parts = filePath.split(path16.sep);
7513
+ const parts = filePath.split(path17.sep);
7435
7514
  const subagentsIdx = parts.lastIndexOf("subagents");
7436
7515
  let sessionId = "";
7437
7516
  let projectName = "";
@@ -7441,14 +7520,17 @@ function parseQoderCnPaths(filePath) {
7441
7520
  sessionId = parts[subagentsIdx - 1];
7442
7521
  projectName = parts[subagentsIdx - 2];
7443
7522
  const projectsIdx = parts.lastIndexOf("projects");
7444
- configDir2 = parts.slice(0, projectsIdx).join(path16.sep);
7445
- mainTranscriptPath = [...parts.slice(0, subagentsIdx - 1), `${sessionId}.jsonl`].join(path16.sep);
7523
+ configDir2 = parts.slice(0, projectsIdx).join(path17.sep);
7524
+ mainTranscriptPath = [...parts.slice(0, subagentsIdx - 1), `${sessionId}.jsonl`].join(path17.sep);
7446
7525
  } else {
7447
7526
  const filename = parts.at(-1) || "";
7448
- sessionId = path16.basename(filename, ".jsonl");
7527
+ sessionId = path17.basename(filename, ".jsonl");
7449
7528
  projectName = parts.at(-2) || "";
7529
+ if (projectName === "transcript") {
7530
+ projectName = parts.at(-3) || "";
7531
+ }
7450
7532
  const projectsIdx = parts.lastIndexOf("projects");
7451
- configDir2 = parts.slice(0, projectsIdx).join(path16.sep);
7533
+ configDir2 = parts.slice(0, projectsIdx).join(path17.sep);
7452
7534
  }
7453
7535
  return { configDir: configDir2, projectName, sessionId, mainTranscriptPath };
7454
7536
  }
@@ -7471,7 +7553,7 @@ function rebuildEventIdentity2(event) {
7471
7553
  }
7472
7554
  async function loadQoderCnModelNames(configDir2) {
7473
7555
  try {
7474
- const dynamicTextsPath = path16.join(configDir2, ".auth", "dynamic-texts.json");
7556
+ const dynamicTextsPath = path17.join(configDir2, ".auth", "dynamic-texts.json");
7475
7557
  const content = await readFile10(dynamicTextsPath, "utf8");
7476
7558
  const json = JSON.parse(content);
7477
7559
  const texts = json.texts || {};
@@ -7489,7 +7571,7 @@ async function loadQoderCnModelNames(configDir2) {
7489
7571
  }
7490
7572
  async function loadQoderCnSegmentModelCalls(filePath, isSubagentSession, modelMap) {
7491
7573
  const { configDir: configDir2, projectName, sessionId } = parseQoderCnPaths(filePath);
7492
- const segmentsPath = path16.join(configDir2, "logs", "sessions", projectName, sessionId, "segments");
7574
+ const segmentsPath = path17.join(configDir2, "logs", "sessions", projectName, sessionId, "segments");
7493
7575
  const modelCalls = [];
7494
7576
  try {
7495
7577
  const files = await readdir7(segmentsPath);
@@ -7497,7 +7579,7 @@ async function loadQoderCnSegmentModelCalls(filePath, isSubagentSession, modelMa
7497
7579
  if (!file.endsWith(".jsonl")) {
7498
7580
  continue;
7499
7581
  }
7500
- const content = await readFile10(path16.join(segmentsPath, file), "utf8");
7582
+ const content = await readFile10(path17.join(segmentsPath, file), "utf8");
7501
7583
  let currentTurnIsSubagent = false;
7502
7584
  for (const line of content.split("\n").filter(Boolean)) {
7503
7585
  const raw = parseJsonLine(line);
@@ -7544,6 +7626,17 @@ async function parseQoderCnSessionFile(filePath, options) {
7544
7626
  const isSubagentSession = filePath.includes("subagents");
7545
7627
  const segmentModelCalls = await loadQoderCnSegmentModelCalls(filePath, isSubagentSession, modelMap);
7546
7628
  let modelCallIndex = 0;
7629
+ let dbModelCalls;
7630
+ const nextDbModelCall = async (requestId, blockStart) => {
7631
+ dbModelCalls ??= await loadQoderDbModelCalls("QoderCN", sessionId, modelMap);
7632
+ if (requestId) {
7633
+ return dbModelCalls.byRequestId.get(requestId)?.shift();
7634
+ }
7635
+ if (!blockStart) {
7636
+ return void 0;
7637
+ }
7638
+ return dbModelCalls.ordered.shift();
7639
+ };
7547
7640
  const state = new SessionParserState(filePath, options, (event) => baseQoderCnEvent({ ...event, cwd, project, model }));
7548
7641
  state.sessionId = sessionId;
7549
7642
  const push = (event, ln, topType, payloadType) => {
@@ -7554,6 +7647,7 @@ async function parseQoderCnSessionFile(filePath, options) {
7554
7647
  payloadType
7555
7648
  );
7556
7649
  };
7650
+ let assistantBlockOpen = false;
7557
7651
  for (const [index, line] of lines.entries()) {
7558
7652
  const lineNumber = index + 1;
7559
7653
  const raw = parseJsonLine(line);
@@ -7561,11 +7655,14 @@ async function parseQoderCnSessionFile(filePath, options) {
7561
7655
  continue;
7562
7656
  }
7563
7657
  const topType = stringField(raw, "type");
7658
+ if (topType !== "assistant") {
7659
+ assistantBlockOpen = false;
7660
+ }
7564
7661
  const ts = timestampFrom(raw.timestamp);
7565
7662
  sessionId = stringField(raw, "sessionId") || sessionId;
7566
7663
  state.sessionId = sessionId;
7567
7664
  cwd = stringField(raw, "cwd") || cwd;
7568
- project = projectContext.project || (cwd ? path16.basename(cwd) : project || await qoderCnProjectFromFilePath(filePath, options));
7665
+ project = projectContext.project || (cwd ? path17.basename(cwd) : project || await qoderCnProjectFromFilePath(filePath, options));
7569
7666
  if (!ts) {
7570
7667
  continue;
7571
7668
  }
@@ -7698,6 +7795,8 @@ async function parseQoderCnSessionFile(filePath, options) {
7698
7795
  model = rawModel ? modelMap[rawModel] || rawModel : void 0;
7699
7796
  const messageId = stringField(message, "id");
7700
7797
  const requestId = stringField(raw, "requestId");
7798
+ const isBlockStart = !assistantBlockOpen;
7799
+ assistantBlockOpen = true;
7701
7800
  const usageKey = messageId ? `${messageId}:${requestId}` : null;
7702
7801
  const shouldEmitUsage = usageKey == null || !seenUsageKeys.has(usageKey);
7703
7802
  if (usageKey != null) {
@@ -7722,6 +7821,19 @@ async function parseQoderCnSessionFile(filePath, options) {
7722
7821
  modelCalls: 1
7723
7822
  };
7724
7823
  model = call.model || model;
7824
+ } else if (shouldEmitUsage) {
7825
+ const dbCall = await nextDbModelCall(requestId, isBlockStart);
7826
+ if (dbCall) {
7827
+ usage = {
7828
+ tokensInput: dbCall.inputTokens || void 0,
7829
+ tokensCachedInput: dbCall.cachedTokens || void 0,
7830
+ tokensCacheReadInput: dbCall.cachedTokens || void 0,
7831
+ tokensOutput: dbCall.outputTokens || void 0,
7832
+ tokensTotal: dbCall.inputTokens + dbCall.outputTokens || void 0,
7833
+ modelCalls: 1
7834
+ };
7835
+ model = dbCall.model || model;
7836
+ }
7725
7837
  }
7726
7838
  if (usage) {
7727
7839
  const speed = stringField(objectField(message, "usage"), "speed");
@@ -8002,28 +8114,28 @@ function isNoisePrompt(text) {
8002
8114
  }
8003
8115
  async function qoderCnProjectContextFromLines(filePath, lines, options, configDir2) {
8004
8116
  const { projectName: projectDir, sessionId } = parseQoderCnPaths(filePath);
8005
- const isSubagent = filePath.includes(`${path16.sep}subagents${path16.sep}`);
8117
+ const isSubagent = filePath.includes(`${path17.sep}subagents${path17.sep}`);
8006
8118
  const inherited = isSubagent ? await readPersistedSessionContextFromOptions(options, sessionId) : void 0;
8007
8119
  let cwds = [];
8008
8120
  for (const line of lines) {
8009
8121
  const raw = parseJsonLine(line);
8010
8122
  const cwd = raw ? stringField(raw, "cwd") : void 0;
8011
- if (cwd && path16.isAbsolute(cwd)) {
8123
+ if (cwd && path17.isAbsolute(cwd)) {
8012
8124
  cwds.push(cwd);
8013
8125
  }
8014
8126
  }
8015
8127
  if (isSubagent) {
8016
- if (inherited?.cwd && path16.isAbsolute(inherited.cwd)) {
8128
+ if (inherited?.cwd && path17.isAbsolute(inherited.cwd)) {
8017
8129
  cwds = [inherited.cwd];
8018
8130
  } else {
8019
- const parentSessionPath = path16.join(configDir2, "projects", projectDir, `${sessionId}.jsonl`);
8131
+ const parentSessionPath = path17.join(configDir2, "projects", projectDir, `${sessionId}.jsonl`);
8020
8132
  try {
8021
8133
  const parentText = await readFile10(parentSessionPath, "utf8");
8022
8134
  const parentCwds = [];
8023
8135
  for (const line of parentText.split("\n").filter(Boolean)) {
8024
8136
  const raw = parseJsonLine(line);
8025
8137
  const cwd = raw ? stringField(raw, "cwd") : void 0;
8026
- if (cwd && path16.isAbsolute(cwd)) {
8138
+ if (cwd && path17.isAbsolute(cwd)) {
8027
8139
  parentCwds.push(cwd);
8028
8140
  }
8029
8141
  }
@@ -8035,7 +8147,7 @@ async function qoderCnProjectContextFromLines(filePath, lines, options, configDi
8035
8147
  }
8036
8148
  }
8037
8149
  const root = await gitRootFromCwds2(cwds) || qoderCnProjectRootFromCwds(projectDir, cwds);
8038
- const project = inherited?.project || (cwds.length > 0 ? path16.basename(cwds[0]) : root ? path16.basename(root) : await qoderCnProjectFromFilePath(filePath, options));
8150
+ const project = inherited?.project || (cwds.length > 0 ? path17.basename(cwds[0]) : root ? path17.basename(root) : await qoderCnProjectFromFilePath(filePath, options));
8039
8151
  return {
8040
8152
  project,
8041
8153
  workspaceId: createWorkspaceId({ projectName: project, repoRoot: root })
@@ -8044,15 +8156,15 @@ async function qoderCnProjectContextFromLines(filePath, lines, options, configDi
8044
8156
  async function gitRootFromCwds2(cwds) {
8045
8157
  const seen = /* @__PURE__ */ new Set();
8046
8158
  for (const cwd of cwds) {
8047
- let current = path16.resolve(cwd);
8159
+ let current = path17.resolve(cwd);
8048
8160
  while (!seen.has(current)) {
8049
8161
  seen.add(current);
8050
8162
  try {
8051
- await stat8(path16.join(current, ".git"));
8163
+ await stat8(path17.join(current, ".git"));
8052
8164
  return current;
8053
8165
  } catch {
8054
8166
  }
8055
- const parent = path16.dirname(current);
8167
+ const parent = path17.dirname(current);
8056
8168
  if (parent === current) {
8057
8169
  break;
8058
8170
  }
@@ -8063,12 +8175,12 @@ async function gitRootFromCwds2(cwds) {
8063
8175
  }
8064
8176
  function qoderCnProjectRootFromCwds(projectDir, cwds) {
8065
8177
  for (const cwd of cwds) {
8066
- let current = path16.resolve(cwd);
8178
+ let current = path17.resolve(cwd);
8067
8179
  while (true) {
8068
8180
  if (encodeQoderCnProjectPath(current) === projectDir) {
8069
8181
  return current;
8070
8182
  }
8071
- const parent = path16.dirname(current);
8183
+ const parent = path17.dirname(current);
8072
8184
  if (parent === current) {
8073
8185
  break;
8074
8186
  }
@@ -8078,14 +8190,14 @@ function qoderCnProjectRootFromCwds(projectDir, cwds) {
8078
8190
  return void 0;
8079
8191
  }
8080
8192
  function encodeQoderCnProjectPath(value) {
8081
- return path16.resolve(value).split(path16.sep).join("-").replace(/_/g, "-");
8193
+ return path17.resolve(value).split(path17.sep).join("-").replace(/_/g, "-");
8082
8194
  }
8083
8195
  async function qoderCnProjectFromFilePath(filePath, options) {
8084
- const projectDir = path16.basename(path16.dirname(filePath));
8085
- const home = options ? path16.resolve(stringOption(options.home) || os7.homedir()) : os7.homedir();
8196
+ const projectDir = path17.basename(path17.dirname(filePath));
8197
+ const home = options ? path17.resolve(stringOption(options.home) || os8.homedir()) : os8.homedir();
8086
8198
  const resolved = await resolveQoderCnProjectPath(projectDir, home);
8087
8199
  if (resolved) {
8088
- return path16.basename(resolved);
8200
+ return path17.basename(resolved);
8089
8201
  }
8090
8202
  const homePrefix = `${encodeQoderCnProjectPath(home)}-`;
8091
8203
  if (projectDir.startsWith(homePrefix)) {
@@ -8110,7 +8222,7 @@ async function resolveQoderCnProjectPath(projectDir, home) {
8110
8222
  if (!entry.isDirectory()) {
8111
8223
  continue;
8112
8224
  }
8113
- const candidate = path16.join(current, entry.name);
8225
+ const candidate = path17.join(current, entry.name);
8114
8226
  const encoded = encodeQoderCnProjectPath(candidate);
8115
8227
  if (encoded === projectDir) {
8116
8228
  return candidate;
@@ -8155,9 +8267,9 @@ function hookConfig6() {
8155
8267
  function qoderCnConfigDir(home, env) {
8156
8268
  const override = env?.QODER_CN_CONFIG_DIR;
8157
8269
  if (override && override.trim()) {
8158
- return path16.resolve(override);
8270
+ return path17.resolve(override);
8159
8271
  }
8160
- return path16.join(home, ".qoder-cn");
8272
+ return path17.join(home, ".qoder-cn");
8161
8273
  }
8162
8274
  function createQoderCnAdapter() {
8163
8275
  return {
@@ -8169,27 +8281,27 @@ function createQoderCnAdapter() {
8169
8281
  return qoderCnConfigDir(home, env);
8170
8282
  },
8171
8283
  installedPath(home, env) {
8172
- return path16.join(qoderCnConfigDir(home, env), "settings.json");
8284
+ return path17.join(qoderCnConfigDir(home, env), "settings.json");
8173
8285
  },
8174
8286
  async isInstalled(home, env) {
8175
8287
  return isHooksJsonInstalled(
8176
- path16.join(qoderCnConfigDir(home, env), "settings.json"),
8288
+ path17.join(qoderCnConfigDir(home, env), "settings.json"),
8177
8289
  "vibetime hook --agent qoder-cn"
8178
8290
  );
8179
8291
  },
8180
8292
  installEntries(home, env) {
8181
8293
  return [{
8182
8294
  kind: "hooks-json",
8183
- path: path16.join(qoderCnConfigDir(home, env), "settings.json"),
8295
+ path: path17.join(qoderCnConfigDir(home, env), "settings.json"),
8184
8296
  content: hookConfig6()
8185
8297
  }];
8186
8298
  },
8187
8299
  sourcePaths(home, env) {
8188
8300
  const base = qoderCnConfigDir(home, env);
8189
8301
  return [
8190
- path16.join(base, "projects"),
8191
- path16.join(base, ".qoder.json"),
8192
- path16.join(home, ".qoder.json")
8302
+ path17.join(base, "projects"),
8303
+ path17.join(base, ".qoder.json"),
8304
+ path17.join(home, ".qoder.json")
8193
8305
  ];
8194
8306
  },
8195
8307
  parseSessionFile: parseQoderCnSessionFile
@@ -8198,10 +8310,10 @@ function createQoderCnAdapter() {
8198
8310
 
8199
8311
  // src/adapters/qoder.ts
8200
8312
  import { readdir as readdir8, readFile as readFile11, stat as stat9 } from "node:fs/promises";
8201
- import os8 from "node:os";
8202
- import path17 from "node:path";
8313
+ import os9 from "node:os";
8314
+ import path18 from "node:path";
8203
8315
  function parseQoderPaths(filePath) {
8204
- const parts = filePath.split(path17.sep);
8316
+ const parts = filePath.split(path18.sep);
8205
8317
  const subagentsIdx = parts.lastIndexOf("subagents");
8206
8318
  let sessionId = "";
8207
8319
  let projectName = "";
@@ -8211,14 +8323,17 @@ function parseQoderPaths(filePath) {
8211
8323
  sessionId = parts[subagentsIdx - 1];
8212
8324
  projectName = parts[subagentsIdx - 2];
8213
8325
  const projectsIdx = parts.lastIndexOf("projects");
8214
- configDir2 = parts.slice(0, projectsIdx).join(path17.sep);
8215
- mainTranscriptPath = [...parts.slice(0, subagentsIdx - 1), `${sessionId}.jsonl`].join(path17.sep);
8326
+ configDir2 = parts.slice(0, projectsIdx).join(path18.sep);
8327
+ mainTranscriptPath = [...parts.slice(0, subagentsIdx - 1), `${sessionId}.jsonl`].join(path18.sep);
8216
8328
  } else {
8217
8329
  const filename = parts.at(-1) || "";
8218
- sessionId = path17.basename(filename, ".jsonl");
8330
+ sessionId = path18.basename(filename, ".jsonl");
8219
8331
  projectName = parts.at(-2) || "";
8332
+ if (projectName === "transcript") {
8333
+ projectName = parts.at(-3) || "";
8334
+ }
8220
8335
  const projectsIdx = parts.lastIndexOf("projects");
8221
- configDir2 = parts.slice(0, projectsIdx).join(path17.sep);
8336
+ configDir2 = parts.slice(0, projectsIdx).join(path18.sep);
8222
8337
  }
8223
8338
  return { configDir: configDir2, projectName, sessionId, mainTranscriptPath };
8224
8339
  }
@@ -8241,7 +8356,7 @@ function rebuildEventIdentity3(event) {
8241
8356
  }
8242
8357
  async function loadQoderModelNames(configDir2) {
8243
8358
  try {
8244
- const dynamicTextsPath = path17.join(configDir2, ".auth", "dynamic-texts.json");
8359
+ const dynamicTextsPath = path18.join(configDir2, ".auth", "dynamic-texts.json");
8245
8360
  const content = await readFile11(dynamicTextsPath, "utf8");
8246
8361
  const json = JSON.parse(content);
8247
8362
  const texts = json.texts || {};
@@ -8259,7 +8374,7 @@ async function loadQoderModelNames(configDir2) {
8259
8374
  }
8260
8375
  async function loadQoderSegmentModelCalls(filePath, isSubagentSession, modelMap) {
8261
8376
  const { configDir: configDir2, projectName, sessionId } = parseQoderPaths(filePath);
8262
- const segmentsPath = path17.join(configDir2, "logs", "sessions", projectName, sessionId, "segments");
8377
+ const segmentsPath = path18.join(configDir2, "logs", "sessions", projectName, sessionId, "segments");
8263
8378
  const modelCalls = [];
8264
8379
  try {
8265
8380
  const files = await readdir8(segmentsPath);
@@ -8267,7 +8382,7 @@ async function loadQoderSegmentModelCalls(filePath, isSubagentSession, modelMap)
8267
8382
  if (!file.endsWith(".jsonl")) {
8268
8383
  continue;
8269
8384
  }
8270
- const content = await readFile11(path17.join(segmentsPath, file), "utf8");
8385
+ const content = await readFile11(path18.join(segmentsPath, file), "utf8");
8271
8386
  let currentTurnIsSubagent = false;
8272
8387
  for (const line of content.split("\n").filter(Boolean)) {
8273
8388
  const raw = parseJsonLine(line);
@@ -8314,6 +8429,17 @@ async function parseQoderSessionFile(filePath, options) {
8314
8429
  const isSubagentSession = filePath.includes("subagents");
8315
8430
  const segmentModelCalls = await loadQoderSegmentModelCalls(filePath, isSubagentSession, modelMap);
8316
8431
  let modelCallIndex = 0;
8432
+ let dbModelCalls;
8433
+ const nextDbModelCall = async (requestId, blockStart) => {
8434
+ dbModelCalls ??= await loadQoderDbModelCalls("Qoder", sessionId, modelMap);
8435
+ if (requestId) {
8436
+ return dbModelCalls.byRequestId.get(requestId)?.shift();
8437
+ }
8438
+ if (!blockStart) {
8439
+ return void 0;
8440
+ }
8441
+ return dbModelCalls.ordered.shift();
8442
+ };
8317
8443
  const state = new SessionParserState(filePath, options, (event) => baseQoderEvent({ ...event, cwd, project, model }));
8318
8444
  state.sessionId = sessionId;
8319
8445
  const push = (event, ln, topType, payloadType) => {
@@ -8324,6 +8450,7 @@ async function parseQoderSessionFile(filePath, options) {
8324
8450
  payloadType
8325
8451
  );
8326
8452
  };
8453
+ let assistantBlockOpen = false;
8327
8454
  for (const [index, line] of lines.entries()) {
8328
8455
  const lineNumber = index + 1;
8329
8456
  const raw = parseJsonLine(line);
@@ -8331,11 +8458,14 @@ async function parseQoderSessionFile(filePath, options) {
8331
8458
  continue;
8332
8459
  }
8333
8460
  const topType = stringField(raw, "type");
8461
+ if (topType !== "assistant") {
8462
+ assistantBlockOpen = false;
8463
+ }
8334
8464
  const ts = timestampFrom(raw.timestamp);
8335
8465
  sessionId = stringField(raw, "sessionId") || sessionId;
8336
8466
  state.sessionId = sessionId;
8337
8467
  cwd = stringField(raw, "cwd") || cwd;
8338
- project = projectContext.project || (cwd ? path17.basename(cwd) : project || await qoderProjectFromFilePath(filePath, options));
8468
+ project = projectContext.project || (cwd ? path18.basename(cwd) : project || await qoderProjectFromFilePath(filePath, options));
8339
8469
  if (!ts) {
8340
8470
  continue;
8341
8471
  }
@@ -8468,6 +8598,8 @@ async function parseQoderSessionFile(filePath, options) {
8468
8598
  model = rawModel ? modelMap[rawModel] || rawModel : void 0;
8469
8599
  const messageId = stringField(message, "id");
8470
8600
  const requestId = stringField(raw, "requestId");
8601
+ const isBlockStart = !assistantBlockOpen;
8602
+ assistantBlockOpen = true;
8471
8603
  const usageKey = messageId ? `${messageId}:${requestId}` : null;
8472
8604
  const shouldEmitUsage = usageKey == null || !seenUsageKeys.has(usageKey);
8473
8605
  if (usageKey != null) {
@@ -8492,6 +8624,19 @@ async function parseQoderSessionFile(filePath, options) {
8492
8624
  modelCalls: 1
8493
8625
  };
8494
8626
  model = call.model || model;
8627
+ } else if (shouldEmitUsage) {
8628
+ const dbCall = await nextDbModelCall(requestId, isBlockStart);
8629
+ if (dbCall) {
8630
+ usage = {
8631
+ tokensInput: dbCall.inputTokens || void 0,
8632
+ tokensCachedInput: dbCall.cachedTokens || void 0,
8633
+ tokensCacheReadInput: dbCall.cachedTokens || void 0,
8634
+ tokensOutput: dbCall.outputTokens || void 0,
8635
+ tokensTotal: dbCall.inputTokens + dbCall.outputTokens || void 0,
8636
+ modelCalls: 1
8637
+ };
8638
+ model = dbCall.model || model;
8639
+ }
8495
8640
  }
8496
8641
  if (usage) {
8497
8642
  const speed = stringField(objectField(message, "usage"), "speed");
@@ -8738,28 +8883,28 @@ function qoderExtractText(value) {
8738
8883
  }
8739
8884
  async function qoderProjectContextFromLines(filePath, lines, options, configDir2) {
8740
8885
  const { projectName: projectDir, sessionId } = parseQoderPaths(filePath);
8741
- const isSubagent = filePath.includes(`${path17.sep}subagents${path17.sep}`);
8886
+ const isSubagent = filePath.includes(`${path18.sep}subagents${path18.sep}`);
8742
8887
  const inherited = isSubagent ? await readPersistedSessionContextFromOptions(options, sessionId) : void 0;
8743
8888
  let cwds = [];
8744
8889
  for (const line of lines) {
8745
8890
  const raw = parseJsonLine(line);
8746
8891
  const cwd = raw ? stringField(raw, "cwd") : void 0;
8747
- if (cwd && path17.isAbsolute(cwd)) {
8892
+ if (cwd && path18.isAbsolute(cwd)) {
8748
8893
  cwds.push(cwd);
8749
8894
  }
8750
8895
  }
8751
8896
  if (isSubagent) {
8752
- if (inherited?.cwd && path17.isAbsolute(inherited.cwd)) {
8897
+ if (inherited?.cwd && path18.isAbsolute(inherited.cwd)) {
8753
8898
  cwds = [inherited.cwd];
8754
8899
  } else {
8755
- const parentSessionPath = path17.join(configDir2, "projects", projectDir, `${sessionId}.jsonl`);
8900
+ const parentSessionPath = path18.join(configDir2, "projects", projectDir, `${sessionId}.jsonl`);
8756
8901
  try {
8757
8902
  const parentText = await readFile11(parentSessionPath, "utf8");
8758
8903
  const parentCwds = [];
8759
8904
  for (const line of parentText.split("\n").filter(Boolean)) {
8760
8905
  const raw = parseJsonLine(line);
8761
8906
  const cwd = raw ? stringField(raw, "cwd") : void 0;
8762
- if (cwd && path17.isAbsolute(cwd)) {
8907
+ if (cwd && path18.isAbsolute(cwd)) {
8763
8908
  parentCwds.push(cwd);
8764
8909
  }
8765
8910
  }
@@ -8771,7 +8916,7 @@ async function qoderProjectContextFromLines(filePath, lines, options, configDir2
8771
8916
  }
8772
8917
  }
8773
8918
  const root = await gitRootFromCwds3(cwds) || qoderProjectRootFromCwds(projectDir, cwds);
8774
- const project = inherited?.project || (cwds.length > 0 ? path17.basename(cwds[0]) : root ? path17.basename(root) : await qoderProjectFromFilePath(filePath, options));
8919
+ const project = inherited?.project || (cwds.length > 0 ? path18.basename(cwds[0]) : root ? path18.basename(root) : await qoderProjectFromFilePath(filePath, options));
8775
8920
  return {
8776
8921
  project,
8777
8922
  workspaceId: createWorkspaceId({ projectName: project, repoRoot: root })
@@ -8780,15 +8925,15 @@ async function qoderProjectContextFromLines(filePath, lines, options, configDir2
8780
8925
  async function gitRootFromCwds3(cwds) {
8781
8926
  const seen = /* @__PURE__ */ new Set();
8782
8927
  for (const cwd of cwds) {
8783
- let current = path17.resolve(cwd);
8928
+ let current = path18.resolve(cwd);
8784
8929
  while (!seen.has(current)) {
8785
8930
  seen.add(current);
8786
8931
  try {
8787
- await stat9(path17.join(current, ".git"));
8932
+ await stat9(path18.join(current, ".git"));
8788
8933
  return current;
8789
8934
  } catch {
8790
8935
  }
8791
- const parent = path17.dirname(current);
8936
+ const parent = path18.dirname(current);
8792
8937
  if (parent === current) {
8793
8938
  break;
8794
8939
  }
@@ -8799,12 +8944,12 @@ async function gitRootFromCwds3(cwds) {
8799
8944
  }
8800
8945
  function qoderProjectRootFromCwds(projectDir, cwds) {
8801
8946
  for (const cwd of cwds) {
8802
- let current = path17.resolve(cwd);
8947
+ let current = path18.resolve(cwd);
8803
8948
  while (true) {
8804
8949
  if (encodeQoderProjectPath(current) === projectDir) {
8805
8950
  return current;
8806
8951
  }
8807
- const parent = path17.dirname(current);
8952
+ const parent = path18.dirname(current);
8808
8953
  if (parent === current) {
8809
8954
  break;
8810
8955
  }
@@ -8814,10 +8959,10 @@ function qoderProjectRootFromCwds(projectDir, cwds) {
8814
8959
  return void 0;
8815
8960
  }
8816
8961
  function encodeQoderProjectPath(value) {
8817
- return path17.resolve(value).split(path17.sep).join("-").replace(/_/g, "-");
8962
+ return path18.resolve(value).split(path18.sep).join("-").replace(/_/g, "-");
8818
8963
  }
8819
8964
  function rawQoderProjectPath(value) {
8820
- return path17.resolve(value).split(path17.sep).join("-");
8965
+ return path18.resolve(value).split(path18.sep).join("-");
8821
8966
  }
8822
8967
  function qoderEncodedVariants(value) {
8823
8968
  const raw = rawQoderProjectPath(value);
@@ -8833,11 +8978,11 @@ function qoderEncodedProjectSuffix(projectDir, home) {
8833
8978
  return void 0;
8834
8979
  }
8835
8980
  async function qoderProjectFromFilePath(filePath, options) {
8836
- const projectDir = path17.basename(path17.dirname(filePath));
8837
- const home = options ? path17.resolve(stringOption(options.home) || os8.homedir()) : os8.homedir();
8981
+ const projectDir = path18.basename(path18.dirname(filePath));
8982
+ const home = options ? path18.resolve(stringOption(options.home) || os9.homedir()) : os9.homedir();
8838
8983
  const resolved = await resolveQoderProjectPath(projectDir, home);
8839
8984
  if (resolved) {
8840
- return path17.basename(resolved);
8985
+ return path18.basename(resolved);
8841
8986
  }
8842
8987
  const suffix = qoderEncodedProjectSuffix(projectDir, home);
8843
8988
  if (suffix) {
@@ -8863,7 +9008,7 @@ async function resolveQoderProjectPath(projectDir, home) {
8863
9008
  if (!entry.isDirectory()) {
8864
9009
  continue;
8865
9010
  }
8866
- const candidate = path17.join(current, entry.name);
9011
+ const candidate = path18.join(current, entry.name);
8867
9012
  const candidateVariants = qoderEncodedVariants(candidate);
8868
9013
  if (candidateVariants.includes(projectDir)) {
8869
9014
  return candidate;
@@ -8908,9 +9053,9 @@ function hookConfig7() {
8908
9053
  function qoderConfigDir(home, env) {
8909
9054
  const override = env?.QODER_CONFIG_DIR;
8910
9055
  if (override && override.trim()) {
8911
- return path17.resolve(override);
9056
+ return path18.resolve(override);
8912
9057
  }
8913
- return path17.join(home, ".qoder");
9058
+ return path18.join(home, ".qoder");
8914
9059
  }
8915
9060
  function createQoderAdapter() {
8916
9061
  return {
@@ -8922,27 +9067,27 @@ function createQoderAdapter() {
8922
9067
  return qoderConfigDir(home, env);
8923
9068
  },
8924
9069
  installedPath(home, env) {
8925
- return path17.join(qoderConfigDir(home, env), "settings.json");
9070
+ return path18.join(qoderConfigDir(home, env), "settings.json");
8926
9071
  },
8927
9072
  async isInstalled(home, env) {
8928
9073
  return isHooksJsonInstalled(
8929
- path17.join(qoderConfigDir(home, env), "settings.json"),
9074
+ path18.join(qoderConfigDir(home, env), "settings.json"),
8930
9075
  "vibetime hook --agent qoder"
8931
9076
  );
8932
9077
  },
8933
9078
  installEntries(home, env) {
8934
9079
  return [{
8935
9080
  kind: "hooks-json",
8936
- path: path17.join(qoderConfigDir(home, env), "settings.json"),
9081
+ path: path18.join(qoderConfigDir(home, env), "settings.json"),
8937
9082
  content: hookConfig7()
8938
9083
  }];
8939
9084
  },
8940
9085
  sourcePaths(home, env) {
8941
9086
  const base = qoderConfigDir(home, env);
8942
9087
  return [
8943
- path17.join(base, "projects"),
8944
- path17.join(base, ".qoder.json"),
8945
- path17.join(home, ".qoder.json")
9088
+ path18.join(base, "projects"),
9089
+ path18.join(base, ".qoder.json"),
9090
+ path18.join(home, ".qoder.json")
8946
9091
  ];
8947
9092
  },
8948
9093
  parseSessionFile: parseQoderSessionFile
@@ -8978,20 +9123,20 @@ function normalizeId(id) {
8978
9123
 
8979
9124
  // src/adapters/workbuddy.ts
8980
9125
  import { readFile as readFile12, readdir as readdir9, stat as stat10 } from "node:fs/promises";
8981
- import path18 from "node:path";
9126
+ import path19 from "node:path";
8982
9127
  init_fs();
8983
9128
  function workbuddyProjectsDir(home, env) {
8984
9129
  const override = env?.WORKBUDDY_PROJECTS_DIR || env?.WORKBUDDY_HOME;
8985
9130
  if (override && override.trim()) {
8986
- return path18.resolve(override, override.endsWith("projects") ? "" : "projects");
9131
+ return path19.resolve(override, override.endsWith("projects") ? "" : "projects");
8987
9132
  }
8988
- return path18.join(home, ".workbuddy", "projects");
9133
+ return path19.join(home, ".workbuddy", "projects");
8989
9134
  }
8990
9135
  function projectFromCwd(cwd, fallback) {
8991
9136
  if (!cwd) {
8992
9137
  return fallback;
8993
9138
  }
8994
- return path18.basename(cwd) || fallback;
9139
+ return path19.basename(cwd) || fallback;
8995
9140
  }
8996
9141
  function sourceHash(filePath) {
8997
9142
  return `sha256:${createStableHash(filePath)}`;
@@ -9094,8 +9239,8 @@ async function parseWorkbuddySessionFile(filePath, options) {
9094
9239
  }
9095
9240
  const events = [];
9096
9241
  const first = lines[0].record;
9097
- const sessionId = stringField(first, "sessionId") || path18.basename(filePath, ".jsonl");
9098
- const fallbackProject = path18.basename(path18.dirname(filePath));
9242
+ const sessionId = stringField(first, "sessionId") || path19.basename(filePath, ".jsonl");
9243
+ const fallbackProject = path19.basename(path19.dirname(filePath));
9099
9244
  const cwd = lines.map((line) => stringField(line.record, "cwd")).find(Boolean);
9100
9245
  const project = projectFromCwd(cwd, fallbackProject);
9101
9246
  const workspaceId = createWorkspaceId({ projectName: project, repoRoot: cwd });
@@ -9269,11 +9414,11 @@ async function workbuddyBackfillFiles(sourceRoot, home, env) {
9269
9414
  if (!project.isDirectory()) {
9270
9415
  continue;
9271
9416
  }
9272
- const projectDir = path18.join(base, project.name);
9417
+ const projectDir = path19.join(base, project.name);
9273
9418
  const entries = await readdir9(projectDir, { withFileTypes: true });
9274
9419
  for (const entry of entries) {
9275
9420
  if (entry.isFile() && entry.name.endsWith(".jsonl")) {
9276
- const filePath = path18.join(projectDir, entry.name);
9421
+ const filePath = path19.join(projectDir, entry.name);
9277
9422
  const info = await stat10(filePath);
9278
9423
  files.push({ path: filePath, modifiedAt: info.mtime.toISOString() });
9279
9424
  }
@@ -9312,19 +9457,19 @@ function createWorkbuddyAdapter() {
9312
9457
  // src/adapters/zcode.ts
9313
9458
  import { execFile } from "node:child_process";
9314
9459
  import { readFile as readFile13, stat as stat11 } from "node:fs/promises";
9315
- import path19 from "node:path";
9460
+ import path20 from "node:path";
9316
9461
  import { promisify as promisify2 } from "node:util";
9317
9462
  init_fs();
9318
9463
  var execFileAsync = promisify2(execFile);
9319
9464
  function zcodeCliDir(home, env) {
9320
9465
  const override = env?.ZCODE_CLI_DIR || env?.ZCODE_HOME;
9321
9466
  if (override && override.trim()) {
9322
- return path19.resolve(override, override.endsWith("cli") ? "" : "cli");
9467
+ return path20.resolve(override, override.endsWith("cli") ? "" : "cli");
9323
9468
  }
9324
- return path19.join(home, ".zcode", "cli");
9469
+ return path20.join(home, ".zcode", "cli");
9325
9470
  }
9326
9471
  function zcodeDbPath(home, env) {
9327
- return path19.join(zcodeCliDir(home, env), "db", "db.sqlite");
9472
+ return path20.join(zcodeCliDir(home, env), "db", "db.sqlite");
9328
9473
  }
9329
9474
  var providerNameCache = null;
9330
9475
  async function loadProviderNames(configPath2) {
@@ -9358,7 +9503,7 @@ function sourceHash2(filePath) {
9358
9503
  return `sha256:${createStableHash(filePath)}`;
9359
9504
  }
9360
9505
  function projectFromDirectory(directory) {
9361
- return directory ? path19.basename(directory) || "zcode" : "zcode";
9506
+ return directory ? path20.basename(directory) || "zcode" : "zcode";
9362
9507
  }
9363
9508
  function isoFromMs(value) {
9364
9509
  return timestampFrom(typeof value === "number" ? value : Number(value));
@@ -9541,16 +9686,16 @@ async function parseZCodeDb(filePath, options) {
9541
9686
  if (rows.length === 0) {
9542
9687
  return [];
9543
9688
  }
9544
- let candidate = path19.resolve(filePath);
9689
+ let candidate = path20.resolve(filePath);
9545
9690
  let configPath2 = "";
9546
9691
  for (let i = 0; i < 12; i++) {
9547
- const probe = path19.join(candidate, ".zcode", "v2", "config.json");
9692
+ const probe = path20.join(candidate, ".zcode", "v2", "config.json");
9548
9693
  try {
9549
9694
  await stat11(probe);
9550
9695
  configPath2 = probe;
9551
9696
  break;
9552
9697
  } catch {
9553
- const parent = path19.dirname(candidate);
9698
+ const parent = path20.dirname(candidate);
9554
9699
  if (parent === candidate) break;
9555
9700
  candidate = parent;
9556
9701
  }
@@ -9766,7 +9911,7 @@ async function parseZCodeDb(filePath, options) {
9766
9911
  }
9767
9912
  async function zcodeBackfillFiles(sourceRoot, home, env) {
9768
9913
  const candidate = sourceRoot || zcodeDbPath(home, env);
9769
- const filePath = candidate.endsWith(".sqlite") ? candidate : path19.join(candidate, "db", "db.sqlite");
9914
+ const filePath = candidate.endsWith(".sqlite") ? candidate : path20.join(candidate, "db", "db.sqlite");
9770
9915
  try {
9771
9916
  const info = await stat11(filePath);
9772
9917
  return [{ path: filePath, modifiedAt: info.mtime.toISOString() }];
@@ -9800,50 +9945,50 @@ function createZCodeAdapter() {
9800
9945
  }
9801
9946
 
9802
9947
  // src/adapters/zed.ts
9803
- import os9 from "node:os";
9804
- import path20 from "node:path";
9948
+ import os10 from "node:os";
9949
+ import path21 from "node:path";
9805
9950
  function zedThreadsCandidates(home, env) {
9806
9951
  const candidates = [];
9807
9952
  const platform2 = process.platform;
9808
9953
  if (platform2 === "darwin") {
9809
- candidates.push(path20.join(home, "Library", "Application Support", "Zed", "threads", "threads.db"));
9954
+ candidates.push(path21.join(home, "Library", "Application Support", "Zed", "threads", "threads.db"));
9810
9955
  } else if (platform2 === "win32") {
9811
9956
  const appdata = env?.APPDATA;
9812
9957
  if (appdata && appdata.trim()) {
9813
- candidates.push(path20.join(path20.resolve(appdata), "Zed", "threads", "threads.db"));
9958
+ candidates.push(path21.join(path21.resolve(appdata), "Zed", "threads", "threads.db"));
9814
9959
  }
9815
- candidates.push(path20.join(home, "AppData", "Roaming", "Zed", "threads", "threads.db"));
9960
+ candidates.push(path21.join(home, "AppData", "Roaming", "Zed", "threads", "threads.db"));
9816
9961
  } else {
9817
9962
  const xdgData = env?.XDG_DATA_HOME;
9818
9963
  if (xdgData && xdgData.trim()) {
9819
- candidates.push(path20.join(path20.resolve(xdgData), "zed", "threads", "threads.db"));
9964
+ candidates.push(path21.join(path21.resolve(xdgData), "zed", "threads", "threads.db"));
9820
9965
  }
9821
- candidates.push(path20.join(home, ".local", "share", "zed", "threads", "threads.db"));
9966
+ candidates.push(path21.join(home, ".local", "share", "zed", "threads", "threads.db"));
9822
9967
  const xdgConfig = env?.XDG_CONFIG_HOME;
9823
9968
  if (xdgConfig && xdgConfig.trim()) {
9824
- candidates.push(path20.join(path20.resolve(xdgConfig), "zed", "threads", "threads.db"));
9969
+ candidates.push(path21.join(path21.resolve(xdgConfig), "zed", "threads", "threads.db"));
9825
9970
  }
9826
- candidates.push(path20.join(home, ".config", "zed", "threads", "threads.db"));
9971
+ candidates.push(path21.join(home, ".config", "zed", "threads", "threads.db"));
9827
9972
  }
9828
9973
  return candidates;
9829
9974
  }
9830
9975
  function zedConfigDir(home, env) {
9831
9976
  const platform2 = process.platform;
9832
9977
  if (platform2 === "darwin") {
9833
- return path20.join(home, "Library", "Application Support", "Zed");
9978
+ return path21.join(home, "Library", "Application Support", "Zed");
9834
9979
  }
9835
9980
  if (platform2 === "win32") {
9836
9981
  const appdata = env?.APPDATA;
9837
9982
  if (appdata && appdata.trim()) {
9838
- return path20.join(path20.resolve(appdata), "Zed");
9983
+ return path21.join(path21.resolve(appdata), "Zed");
9839
9984
  }
9840
- return path20.join(home, "AppData", "Roaming", "Zed");
9985
+ return path21.join(home, "AppData", "Roaming", "Zed");
9841
9986
  }
9842
9987
  const xdgConfig = env?.XDG_CONFIG_HOME;
9843
9988
  if (xdgConfig && xdgConfig.trim()) {
9844
- return path20.join(path20.resolve(xdgConfig), "zed");
9989
+ return path21.join(path21.resolve(xdgConfig), "zed");
9845
9990
  }
9846
- return path20.join(home, ".config", "zed");
9991
+ return path21.join(home, ".config", "zed");
9847
9992
  }
9848
9993
  function baseZedEvent(event) {
9849
9994
  return {
@@ -9907,7 +10052,7 @@ async function parseZedSessionFile(dbPath, options) {
9907
10052
  const folderRaw = row.folder_paths || "";
9908
10053
  const folder = folderRaw.split(/[\n,]/).map((s) => s.trim()).find(Boolean);
9909
10054
  const cwd = folder || void 0;
9910
- const project = cwd ? path20.basename(cwd) : row.summary ? row.summary.slice(0, 40) : void 0;
10055
+ const project = cwd ? path21.basename(cwd) : row.summary ? row.summary.slice(0, 40) : void 0;
9911
10056
  let json;
9912
10057
  try {
9913
10058
  const bytes = row.data_type === "zstd" ? decompress2(new Uint8Array(row.data)) : new Uint8Array(row.data);
@@ -10152,7 +10297,7 @@ async function parseZedSessionFile(dbPath, options) {
10152
10297
  }
10153
10298
  return events.filter((event) => matchesBackfillFilters(event, options));
10154
10299
  }
10155
- async function zedBackfillFiles(sourceRoot, home = os9.homedir(), env) {
10300
+ async function zedBackfillFiles(sourceRoot, home = os10.homedir(), env) {
10156
10301
  const { stat: stat14 } = await import("node:fs/promises");
10157
10302
  if (sourceRoot) {
10158
10303
  if (!sourceRoot.endsWith(".db")) {
@@ -10182,7 +10327,7 @@ function createZedAdapter() {
10182
10327
  return zedConfigDir(home, env);
10183
10328
  },
10184
10329
  installedPath(home, env) {
10185
- return path20.join(zedConfigDir(home, env), "vibetime-marker");
10330
+ return path21.join(zedConfigDir(home, env), "vibetime-marker");
10186
10331
  },
10187
10332
  async isInstalled() {
10188
10333
  return false;
@@ -10641,15 +10786,15 @@ function hookCommandFromGroup(group) {
10641
10786
  import { randomUUID } from "node:crypto";
10642
10787
  import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
10643
10788
  import { homedir, hostname } from "node:os";
10644
- import path21 from "node:path";
10789
+ import path22 from "node:path";
10645
10790
  function configDir(home = homedir()) {
10646
- return path21.join(home, ".vibetime");
10791
+ return path22.join(home, ".vibetime");
10647
10792
  }
10648
10793
  function configPath(home = homedir()) {
10649
- return path21.join(configDir(home), "config.json");
10794
+ return path22.join(configDir(home), "config.json");
10650
10795
  }
10651
10796
  function machineIdPath(home = homedir()) {
10652
- return path21.join(configDir(home), "machine-id");
10797
+ return path22.join(configDir(home), "machine-id");
10653
10798
  }
10654
10799
  function readConfig(home = homedir()) {
10655
10800
  const file = configPath(home);
@@ -10698,13 +10843,13 @@ init_fs();
10698
10843
  // src/lib/logger.ts
10699
10844
  import { appendFile, mkdir as mkdir4, rename, stat as stat12 } from "node:fs/promises";
10700
10845
  import { homedir as homedir2 } from "node:os";
10701
- import path22 from "node:path";
10846
+ import path23 from "node:path";
10702
10847
  var MAX_BYTES = 1 * 1024 * 1024;
10703
10848
  function logDir(home = homedir2()) {
10704
- return path22.join(home, ".vibetime", "logs");
10849
+ return path23.join(home, ".vibetime", "logs");
10705
10850
  }
10706
10851
  function logPath(home = homedir2(), name = "cli.log") {
10707
- return path22.join(logDir(home), name);
10852
+ return path23.join(logDir(home), name);
10708
10853
  }
10709
10854
  function serializeError(error) {
10710
10855
  if (error instanceof Error) {
@@ -10879,8 +11024,8 @@ function buildHeaders(token, machine) {
10879
11024
  ...machine?.platform ? { "x-machine-platform": machine.platform } : {}
10880
11025
  };
10881
11026
  }
10882
- function joinUrl(base, path24) {
10883
- return new URL(path24, base.endsWith("/") ? base : `${base}/`).toString();
11027
+ function joinUrl(base, path25) {
11028
+ return new URL(path25, base.endsWith("/") ? base : `${base}/`).toString();
10884
11029
  }
10885
11030
  async function postRollupBatch(remote, rollups, options = {}) {
10886
11031
  const response = await remote.fetchImpl(joinUrl(remote.baseUrl, "/v3/agent/ingest"), {
@@ -11799,13 +11944,13 @@ function selectBackfillFilesForImport(files, watermarkTs) {
11799
11944
  });
11800
11945
  }
11801
11946
  function backfillIncrementalStatePath(home) {
11802
- return path23.join(home, ".vibetime", "backfill-state.json");
11947
+ return path24.join(home, ".vibetime", "backfill-state.json");
11803
11948
  }
11804
11949
  function syncLocalTriggerStatePath(home) {
11805
- return path23.join(home, ".vibetime", "sync-local-trigger.json");
11950
+ return path24.join(home, ".vibetime", "sync-local-trigger.json");
11806
11951
  }
11807
11952
  function syncLocalTriggerLockPath(home) {
11808
- return path23.join(home, ".vibetime", "sync-local-trigger.lock");
11953
+ return path24.join(home, ".vibetime", "sync-local-trigger.lock");
11809
11954
  }
11810
11955
  function backfillRemoteKey(baseUrl) {
11811
11956
  try {
@@ -11867,7 +12012,7 @@ async function readBackfillIncrementalStateFile(home, ctx) {
11867
12012
  }
11868
12013
  async function writeBackfillIncrementalStateFile(home, file) {
11869
12014
  const statePath = backfillIncrementalStatePath(home);
11870
- await mkdir5(path23.dirname(statePath), { recursive: true });
12015
+ await mkdir5(path24.dirname(statePath), { recursive: true });
11871
12016
  await writeFile4(statePath, `${JSON.stringify(file, null, 2)}
11872
12017
  `, "utf8");
11873
12018
  }
@@ -11916,7 +12061,7 @@ async function readSyncLocalTriggerState(statePath) {
11916
12061
  return nextState;
11917
12062
  }
11918
12063
  async function writeSyncLocalTriggerState(statePath, state) {
11919
- await mkdir5(path23.dirname(statePath), { recursive: true });
12064
+ await mkdir5(path24.dirname(statePath), { recursive: true });
11920
12065
  await writeFile4(statePath, `${JSON.stringify(state, null, 2)}
11921
12066
  `, "utf8");
11922
12067
  }
@@ -11931,12 +12076,12 @@ async function readSyncLocalLock(lockPath) {
11931
12076
  return { pid: lock.pid, startedAt: lock.startedAt };
11932
12077
  }
11933
12078
  async function writeSyncLocalLock(lockPath, lock) {
11934
- await mkdir5(path23.dirname(lockPath), { recursive: true });
12079
+ await mkdir5(path24.dirname(lockPath), { recursive: true });
11935
12080
  await writeFile4(lockPath, `${JSON.stringify(lock, null, 2)}
11936
12081
  `, "utf8");
11937
12082
  }
11938
12083
  async function acquireSyncLocalLock(lockPath, lock) {
11939
- await mkdir5(path23.dirname(lockPath), { recursive: true });
12084
+ await mkdir5(path24.dirname(lockPath), { recursive: true });
11940
12085
  try {
11941
12086
  const handle = await open(lockPath, "wx");
11942
12087
  try {
@@ -12016,10 +12161,10 @@ function syncLocalRunnerEntryArgs(cliPath) {
12016
12161
  if (cliPath.endsWith(".ts")) {
12017
12162
  return ["--import", "tsx", cliPath];
12018
12163
  }
12019
- return [path23.resolve(path23.dirname(cliPath), "../bin/vibetime.mjs")];
12164
+ return [path24.resolve(path24.dirname(cliPath), "../bin/vibetime.mjs")];
12020
12165
  }
12021
12166
  function resolveHome3(options, ctx) {
12022
- return path23.resolve(stringOption(options.home) || ctx.env.HOME || os10.homedir());
12167
+ return path24.resolve(stringOption(options.home) || ctx.env.HOME || os11.homedir());
12023
12168
  }
12024
12169
  function requestedTargets(options) {
12025
12170
  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.31",
4
+ "version": "0.1.32",
5
5
  "description": "vibetime CLI — install AI-agent hooks (Claude Code, Codex, OpenCode, Pi) and report activity to vibetime.",
6
6
  "license": "MIT",
7
7
  "publishConfig": {