@yhong91/vibetime 0.1.31 → 0.1.33

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 +295 -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.33" : "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,115 @@ 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 preferredModel = resolveSessionPreferredModel(db, sessionId, modelMap);
7476
+ const rows = db.prepare(
7477
+ `select request_id, token_info, model_info from chat_message where session_id = ? and role = 'assistant' and token_info != '' order by gmt_create asc`
7478
+ ).all(sessionId);
7479
+ for (const row of rows) {
7480
+ const usage = parseJsonLine(stringField(row, "token_info") || "") || {};
7481
+ const modelInfo = parseJsonLine(stringField(row, "model_info") || "") || {};
7482
+ const modelKey = stringField(modelInfo, "model_key");
7483
+ const call = {
7484
+ model: modelKey ? modelMap[modelKey] || modelKey : preferredModel,
7485
+ inputTokens: numberField(usage, "prompt_tokens") || 0,
7486
+ outputTokens: numberField(usage, "completion_tokens") || 0,
7487
+ cachedTokens: numberField(usage, "cached_tokens") || 0
7488
+ };
7489
+ calls.ordered.push(call);
7490
+ const requestId = stringField(row, "request_id");
7491
+ if (!requestId) {
7492
+ continue;
7493
+ }
7494
+ const queue = calls.byRequestId.get(requestId);
7495
+ if (queue) {
7496
+ queue.push(call);
7497
+ } else {
7498
+ calls.byRequestId.set(requestId, [call]);
7499
+ }
7500
+ }
7501
+ } finally {
7502
+ db.close();
7503
+ }
7504
+ } catch {
7505
+ }
7506
+ return calls;
7507
+ }
7508
+ function resolveSessionPreferredModel(db, sessionId, modelMap) {
7509
+ let current = sessionId;
7510
+ for (let depth = 0; depth < 5 && current; depth++) {
7511
+ let row;
7512
+ try {
7513
+ row = db.prepare(
7514
+ "select preferred_model_info, parent_session_id from chat_session where session_id = ?"
7515
+ ).get(current);
7516
+ } catch {
7517
+ return void 0;
7518
+ }
7519
+ if (!row) {
7520
+ return void 0;
7521
+ }
7522
+ const info = parseJsonLine(stringField(row, "preferred_model_info") || "") || {};
7523
+ const preferred = stringField(info, "preferred_model");
7524
+ if (preferred) {
7525
+ return modelMap[preferred] || preferred;
7526
+ }
7527
+ current = stringField(row, "parent_session_id");
7528
+ }
7529
+ return void 0;
7530
+ }
7531
+
7532
+ // src/adapters/qoder-cn.ts
7533
+ import { readdir as readdir7, readFile as readFile10, stat as stat8 } from "node:fs/promises";
7534
+ import os8 from "node:os";
7535
+ import path17 from "node:path";
7433
7536
  function parseQoderCnPaths(filePath) {
7434
- const parts = filePath.split(path16.sep);
7537
+ const parts = filePath.split(path17.sep);
7435
7538
  const subagentsIdx = parts.lastIndexOf("subagents");
7436
7539
  let sessionId = "";
7437
7540
  let projectName = "";
@@ -7441,14 +7544,17 @@ function parseQoderCnPaths(filePath) {
7441
7544
  sessionId = parts[subagentsIdx - 1];
7442
7545
  projectName = parts[subagentsIdx - 2];
7443
7546
  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);
7547
+ configDir2 = parts.slice(0, projectsIdx).join(path17.sep);
7548
+ mainTranscriptPath = [...parts.slice(0, subagentsIdx - 1), `${sessionId}.jsonl`].join(path17.sep);
7446
7549
  } else {
7447
7550
  const filename = parts.at(-1) || "";
7448
- sessionId = path16.basename(filename, ".jsonl");
7551
+ sessionId = path17.basename(filename, ".jsonl");
7449
7552
  projectName = parts.at(-2) || "";
7553
+ if (projectName === "transcript") {
7554
+ projectName = parts.at(-3) || "";
7555
+ }
7450
7556
  const projectsIdx = parts.lastIndexOf("projects");
7451
- configDir2 = parts.slice(0, projectsIdx).join(path16.sep);
7557
+ configDir2 = parts.slice(0, projectsIdx).join(path17.sep);
7452
7558
  }
7453
7559
  return { configDir: configDir2, projectName, sessionId, mainTranscriptPath };
7454
7560
  }
@@ -7471,7 +7577,7 @@ function rebuildEventIdentity2(event) {
7471
7577
  }
7472
7578
  async function loadQoderCnModelNames(configDir2) {
7473
7579
  try {
7474
- const dynamicTextsPath = path16.join(configDir2, ".auth", "dynamic-texts.json");
7580
+ const dynamicTextsPath = path17.join(configDir2, ".auth", "dynamic-texts.json");
7475
7581
  const content = await readFile10(dynamicTextsPath, "utf8");
7476
7582
  const json = JSON.parse(content);
7477
7583
  const texts = json.texts || {};
@@ -7489,7 +7595,7 @@ async function loadQoderCnModelNames(configDir2) {
7489
7595
  }
7490
7596
  async function loadQoderCnSegmentModelCalls(filePath, isSubagentSession, modelMap) {
7491
7597
  const { configDir: configDir2, projectName, sessionId } = parseQoderCnPaths(filePath);
7492
- const segmentsPath = path16.join(configDir2, "logs", "sessions", projectName, sessionId, "segments");
7598
+ const segmentsPath = path17.join(configDir2, "logs", "sessions", projectName, sessionId, "segments");
7493
7599
  const modelCalls = [];
7494
7600
  try {
7495
7601
  const files = await readdir7(segmentsPath);
@@ -7497,7 +7603,7 @@ async function loadQoderCnSegmentModelCalls(filePath, isSubagentSession, modelMa
7497
7603
  if (!file.endsWith(".jsonl")) {
7498
7604
  continue;
7499
7605
  }
7500
- const content = await readFile10(path16.join(segmentsPath, file), "utf8");
7606
+ const content = await readFile10(path17.join(segmentsPath, file), "utf8");
7501
7607
  let currentTurnIsSubagent = false;
7502
7608
  for (const line of content.split("\n").filter(Boolean)) {
7503
7609
  const raw = parseJsonLine(line);
@@ -7544,6 +7650,17 @@ async function parseQoderCnSessionFile(filePath, options) {
7544
7650
  const isSubagentSession = filePath.includes("subagents");
7545
7651
  const segmentModelCalls = await loadQoderCnSegmentModelCalls(filePath, isSubagentSession, modelMap);
7546
7652
  let modelCallIndex = 0;
7653
+ let dbModelCalls;
7654
+ const nextDbModelCall = async (requestId, blockStart) => {
7655
+ dbModelCalls ??= await loadQoderDbModelCalls("QoderCN", sessionId, modelMap);
7656
+ if (requestId) {
7657
+ return dbModelCalls.byRequestId.get(requestId)?.shift();
7658
+ }
7659
+ if (!blockStart) {
7660
+ return void 0;
7661
+ }
7662
+ return dbModelCalls.ordered.shift();
7663
+ };
7547
7664
  const state = new SessionParserState(filePath, options, (event) => baseQoderCnEvent({ ...event, cwd, project, model }));
7548
7665
  state.sessionId = sessionId;
7549
7666
  const push = (event, ln, topType, payloadType) => {
@@ -7554,6 +7671,7 @@ async function parseQoderCnSessionFile(filePath, options) {
7554
7671
  payloadType
7555
7672
  );
7556
7673
  };
7674
+ let assistantBlockOpen = false;
7557
7675
  for (const [index, line] of lines.entries()) {
7558
7676
  const lineNumber = index + 1;
7559
7677
  const raw = parseJsonLine(line);
@@ -7561,11 +7679,14 @@ async function parseQoderCnSessionFile(filePath, options) {
7561
7679
  continue;
7562
7680
  }
7563
7681
  const topType = stringField(raw, "type");
7682
+ if (topType !== "assistant") {
7683
+ assistantBlockOpen = false;
7684
+ }
7564
7685
  const ts = timestampFrom(raw.timestamp);
7565
7686
  sessionId = stringField(raw, "sessionId") || sessionId;
7566
7687
  state.sessionId = sessionId;
7567
7688
  cwd = stringField(raw, "cwd") || cwd;
7568
- project = projectContext.project || (cwd ? path16.basename(cwd) : project || await qoderCnProjectFromFilePath(filePath, options));
7689
+ project = projectContext.project || (cwd ? path17.basename(cwd) : project || await qoderCnProjectFromFilePath(filePath, options));
7569
7690
  if (!ts) {
7570
7691
  continue;
7571
7692
  }
@@ -7698,6 +7819,8 @@ async function parseQoderCnSessionFile(filePath, options) {
7698
7819
  model = rawModel ? modelMap[rawModel] || rawModel : void 0;
7699
7820
  const messageId = stringField(message, "id");
7700
7821
  const requestId = stringField(raw, "requestId");
7822
+ const isBlockStart = !assistantBlockOpen;
7823
+ assistantBlockOpen = true;
7701
7824
  const usageKey = messageId ? `${messageId}:${requestId}` : null;
7702
7825
  const shouldEmitUsage = usageKey == null || !seenUsageKeys.has(usageKey);
7703
7826
  if (usageKey != null) {
@@ -7722,6 +7845,19 @@ async function parseQoderCnSessionFile(filePath, options) {
7722
7845
  modelCalls: 1
7723
7846
  };
7724
7847
  model = call.model || model;
7848
+ } else if (shouldEmitUsage) {
7849
+ const dbCall = await nextDbModelCall(requestId, isBlockStart);
7850
+ if (dbCall) {
7851
+ usage = {
7852
+ tokensInput: dbCall.inputTokens || void 0,
7853
+ tokensCachedInput: dbCall.cachedTokens || void 0,
7854
+ tokensCacheReadInput: dbCall.cachedTokens || void 0,
7855
+ tokensOutput: dbCall.outputTokens || void 0,
7856
+ tokensTotal: dbCall.inputTokens + dbCall.outputTokens || void 0,
7857
+ modelCalls: 1
7858
+ };
7859
+ model = dbCall.model || model;
7860
+ }
7725
7861
  }
7726
7862
  if (usage) {
7727
7863
  const speed = stringField(objectField(message, "usage"), "speed");
@@ -8002,28 +8138,28 @@ function isNoisePrompt(text) {
8002
8138
  }
8003
8139
  async function qoderCnProjectContextFromLines(filePath, lines, options, configDir2) {
8004
8140
  const { projectName: projectDir, sessionId } = parseQoderCnPaths(filePath);
8005
- const isSubagent = filePath.includes(`${path16.sep}subagents${path16.sep}`);
8141
+ const isSubagent = filePath.includes(`${path17.sep}subagents${path17.sep}`);
8006
8142
  const inherited = isSubagent ? await readPersistedSessionContextFromOptions(options, sessionId) : void 0;
8007
8143
  let cwds = [];
8008
8144
  for (const line of lines) {
8009
8145
  const raw = parseJsonLine(line);
8010
8146
  const cwd = raw ? stringField(raw, "cwd") : void 0;
8011
- if (cwd && path16.isAbsolute(cwd)) {
8147
+ if (cwd && path17.isAbsolute(cwd)) {
8012
8148
  cwds.push(cwd);
8013
8149
  }
8014
8150
  }
8015
8151
  if (isSubagent) {
8016
- if (inherited?.cwd && path16.isAbsolute(inherited.cwd)) {
8152
+ if (inherited?.cwd && path17.isAbsolute(inherited.cwd)) {
8017
8153
  cwds = [inherited.cwd];
8018
8154
  } else {
8019
- const parentSessionPath = path16.join(configDir2, "projects", projectDir, `${sessionId}.jsonl`);
8155
+ const parentSessionPath = path17.join(configDir2, "projects", projectDir, `${sessionId}.jsonl`);
8020
8156
  try {
8021
8157
  const parentText = await readFile10(parentSessionPath, "utf8");
8022
8158
  const parentCwds = [];
8023
8159
  for (const line of parentText.split("\n").filter(Boolean)) {
8024
8160
  const raw = parseJsonLine(line);
8025
8161
  const cwd = raw ? stringField(raw, "cwd") : void 0;
8026
- if (cwd && path16.isAbsolute(cwd)) {
8162
+ if (cwd && path17.isAbsolute(cwd)) {
8027
8163
  parentCwds.push(cwd);
8028
8164
  }
8029
8165
  }
@@ -8035,7 +8171,7 @@ async function qoderCnProjectContextFromLines(filePath, lines, options, configDi
8035
8171
  }
8036
8172
  }
8037
8173
  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));
8174
+ const project = inherited?.project || (cwds.length > 0 ? path17.basename(cwds[0]) : root ? path17.basename(root) : await qoderCnProjectFromFilePath(filePath, options));
8039
8175
  return {
8040
8176
  project,
8041
8177
  workspaceId: createWorkspaceId({ projectName: project, repoRoot: root })
@@ -8044,15 +8180,15 @@ async function qoderCnProjectContextFromLines(filePath, lines, options, configDi
8044
8180
  async function gitRootFromCwds2(cwds) {
8045
8181
  const seen = /* @__PURE__ */ new Set();
8046
8182
  for (const cwd of cwds) {
8047
- let current = path16.resolve(cwd);
8183
+ let current = path17.resolve(cwd);
8048
8184
  while (!seen.has(current)) {
8049
8185
  seen.add(current);
8050
8186
  try {
8051
- await stat8(path16.join(current, ".git"));
8187
+ await stat8(path17.join(current, ".git"));
8052
8188
  return current;
8053
8189
  } catch {
8054
8190
  }
8055
- const parent = path16.dirname(current);
8191
+ const parent = path17.dirname(current);
8056
8192
  if (parent === current) {
8057
8193
  break;
8058
8194
  }
@@ -8063,12 +8199,12 @@ async function gitRootFromCwds2(cwds) {
8063
8199
  }
8064
8200
  function qoderCnProjectRootFromCwds(projectDir, cwds) {
8065
8201
  for (const cwd of cwds) {
8066
- let current = path16.resolve(cwd);
8202
+ let current = path17.resolve(cwd);
8067
8203
  while (true) {
8068
8204
  if (encodeQoderCnProjectPath(current) === projectDir) {
8069
8205
  return current;
8070
8206
  }
8071
- const parent = path16.dirname(current);
8207
+ const parent = path17.dirname(current);
8072
8208
  if (parent === current) {
8073
8209
  break;
8074
8210
  }
@@ -8078,14 +8214,14 @@ function qoderCnProjectRootFromCwds(projectDir, cwds) {
8078
8214
  return void 0;
8079
8215
  }
8080
8216
  function encodeQoderCnProjectPath(value) {
8081
- return path16.resolve(value).split(path16.sep).join("-").replace(/_/g, "-");
8217
+ return path17.resolve(value).split(path17.sep).join("-").replace(/_/g, "-");
8082
8218
  }
8083
8219
  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();
8220
+ const projectDir = path17.basename(path17.dirname(filePath));
8221
+ const home = options ? path17.resolve(stringOption(options.home) || os8.homedir()) : os8.homedir();
8086
8222
  const resolved = await resolveQoderCnProjectPath(projectDir, home);
8087
8223
  if (resolved) {
8088
- return path16.basename(resolved);
8224
+ return path17.basename(resolved);
8089
8225
  }
8090
8226
  const homePrefix = `${encodeQoderCnProjectPath(home)}-`;
8091
8227
  if (projectDir.startsWith(homePrefix)) {
@@ -8110,7 +8246,7 @@ async function resolveQoderCnProjectPath(projectDir, home) {
8110
8246
  if (!entry.isDirectory()) {
8111
8247
  continue;
8112
8248
  }
8113
- const candidate = path16.join(current, entry.name);
8249
+ const candidate = path17.join(current, entry.name);
8114
8250
  const encoded = encodeQoderCnProjectPath(candidate);
8115
8251
  if (encoded === projectDir) {
8116
8252
  return candidate;
@@ -8155,9 +8291,9 @@ function hookConfig6() {
8155
8291
  function qoderCnConfigDir(home, env) {
8156
8292
  const override = env?.QODER_CN_CONFIG_DIR;
8157
8293
  if (override && override.trim()) {
8158
- return path16.resolve(override);
8294
+ return path17.resolve(override);
8159
8295
  }
8160
- return path16.join(home, ".qoder-cn");
8296
+ return path17.join(home, ".qoder-cn");
8161
8297
  }
8162
8298
  function createQoderCnAdapter() {
8163
8299
  return {
@@ -8169,27 +8305,27 @@ function createQoderCnAdapter() {
8169
8305
  return qoderCnConfigDir(home, env);
8170
8306
  },
8171
8307
  installedPath(home, env) {
8172
- return path16.join(qoderCnConfigDir(home, env), "settings.json");
8308
+ return path17.join(qoderCnConfigDir(home, env), "settings.json");
8173
8309
  },
8174
8310
  async isInstalled(home, env) {
8175
8311
  return isHooksJsonInstalled(
8176
- path16.join(qoderCnConfigDir(home, env), "settings.json"),
8312
+ path17.join(qoderCnConfigDir(home, env), "settings.json"),
8177
8313
  "vibetime hook --agent qoder-cn"
8178
8314
  );
8179
8315
  },
8180
8316
  installEntries(home, env) {
8181
8317
  return [{
8182
8318
  kind: "hooks-json",
8183
- path: path16.join(qoderCnConfigDir(home, env), "settings.json"),
8319
+ path: path17.join(qoderCnConfigDir(home, env), "settings.json"),
8184
8320
  content: hookConfig6()
8185
8321
  }];
8186
8322
  },
8187
8323
  sourcePaths(home, env) {
8188
8324
  const base = qoderCnConfigDir(home, env);
8189
8325
  return [
8190
- path16.join(base, "projects"),
8191
- path16.join(base, ".qoder.json"),
8192
- path16.join(home, ".qoder.json")
8326
+ path17.join(base, "projects"),
8327
+ path17.join(base, ".qoder.json"),
8328
+ path17.join(home, ".qoder.json")
8193
8329
  ];
8194
8330
  },
8195
8331
  parseSessionFile: parseQoderCnSessionFile
@@ -8198,10 +8334,10 @@ function createQoderCnAdapter() {
8198
8334
 
8199
8335
  // src/adapters/qoder.ts
8200
8336
  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";
8337
+ import os9 from "node:os";
8338
+ import path18 from "node:path";
8203
8339
  function parseQoderPaths(filePath) {
8204
- const parts = filePath.split(path17.sep);
8340
+ const parts = filePath.split(path18.sep);
8205
8341
  const subagentsIdx = parts.lastIndexOf("subagents");
8206
8342
  let sessionId = "";
8207
8343
  let projectName = "";
@@ -8211,14 +8347,17 @@ function parseQoderPaths(filePath) {
8211
8347
  sessionId = parts[subagentsIdx - 1];
8212
8348
  projectName = parts[subagentsIdx - 2];
8213
8349
  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);
8350
+ configDir2 = parts.slice(0, projectsIdx).join(path18.sep);
8351
+ mainTranscriptPath = [...parts.slice(0, subagentsIdx - 1), `${sessionId}.jsonl`].join(path18.sep);
8216
8352
  } else {
8217
8353
  const filename = parts.at(-1) || "";
8218
- sessionId = path17.basename(filename, ".jsonl");
8354
+ sessionId = path18.basename(filename, ".jsonl");
8219
8355
  projectName = parts.at(-2) || "";
8356
+ if (projectName === "transcript") {
8357
+ projectName = parts.at(-3) || "";
8358
+ }
8220
8359
  const projectsIdx = parts.lastIndexOf("projects");
8221
- configDir2 = parts.slice(0, projectsIdx).join(path17.sep);
8360
+ configDir2 = parts.slice(0, projectsIdx).join(path18.sep);
8222
8361
  }
8223
8362
  return { configDir: configDir2, projectName, sessionId, mainTranscriptPath };
8224
8363
  }
@@ -8241,7 +8380,7 @@ function rebuildEventIdentity3(event) {
8241
8380
  }
8242
8381
  async function loadQoderModelNames(configDir2) {
8243
8382
  try {
8244
- const dynamicTextsPath = path17.join(configDir2, ".auth", "dynamic-texts.json");
8383
+ const dynamicTextsPath = path18.join(configDir2, ".auth", "dynamic-texts.json");
8245
8384
  const content = await readFile11(dynamicTextsPath, "utf8");
8246
8385
  const json = JSON.parse(content);
8247
8386
  const texts = json.texts || {};
@@ -8259,7 +8398,7 @@ async function loadQoderModelNames(configDir2) {
8259
8398
  }
8260
8399
  async function loadQoderSegmentModelCalls(filePath, isSubagentSession, modelMap) {
8261
8400
  const { configDir: configDir2, projectName, sessionId } = parseQoderPaths(filePath);
8262
- const segmentsPath = path17.join(configDir2, "logs", "sessions", projectName, sessionId, "segments");
8401
+ const segmentsPath = path18.join(configDir2, "logs", "sessions", projectName, sessionId, "segments");
8263
8402
  const modelCalls = [];
8264
8403
  try {
8265
8404
  const files = await readdir8(segmentsPath);
@@ -8267,7 +8406,7 @@ async function loadQoderSegmentModelCalls(filePath, isSubagentSession, modelMap)
8267
8406
  if (!file.endsWith(".jsonl")) {
8268
8407
  continue;
8269
8408
  }
8270
- const content = await readFile11(path17.join(segmentsPath, file), "utf8");
8409
+ const content = await readFile11(path18.join(segmentsPath, file), "utf8");
8271
8410
  let currentTurnIsSubagent = false;
8272
8411
  for (const line of content.split("\n").filter(Boolean)) {
8273
8412
  const raw = parseJsonLine(line);
@@ -8314,6 +8453,17 @@ async function parseQoderSessionFile(filePath, options) {
8314
8453
  const isSubagentSession = filePath.includes("subagents");
8315
8454
  const segmentModelCalls = await loadQoderSegmentModelCalls(filePath, isSubagentSession, modelMap);
8316
8455
  let modelCallIndex = 0;
8456
+ let dbModelCalls;
8457
+ const nextDbModelCall = async (requestId, blockStart) => {
8458
+ dbModelCalls ??= await loadQoderDbModelCalls("Qoder", sessionId, modelMap);
8459
+ if (requestId) {
8460
+ return dbModelCalls.byRequestId.get(requestId)?.shift();
8461
+ }
8462
+ if (!blockStart) {
8463
+ return void 0;
8464
+ }
8465
+ return dbModelCalls.ordered.shift();
8466
+ };
8317
8467
  const state = new SessionParserState(filePath, options, (event) => baseQoderEvent({ ...event, cwd, project, model }));
8318
8468
  state.sessionId = sessionId;
8319
8469
  const push = (event, ln, topType, payloadType) => {
@@ -8324,6 +8474,7 @@ async function parseQoderSessionFile(filePath, options) {
8324
8474
  payloadType
8325
8475
  );
8326
8476
  };
8477
+ let assistantBlockOpen = false;
8327
8478
  for (const [index, line] of lines.entries()) {
8328
8479
  const lineNumber = index + 1;
8329
8480
  const raw = parseJsonLine(line);
@@ -8331,11 +8482,14 @@ async function parseQoderSessionFile(filePath, options) {
8331
8482
  continue;
8332
8483
  }
8333
8484
  const topType = stringField(raw, "type");
8485
+ if (topType !== "assistant") {
8486
+ assistantBlockOpen = false;
8487
+ }
8334
8488
  const ts = timestampFrom(raw.timestamp);
8335
8489
  sessionId = stringField(raw, "sessionId") || sessionId;
8336
8490
  state.sessionId = sessionId;
8337
8491
  cwd = stringField(raw, "cwd") || cwd;
8338
- project = projectContext.project || (cwd ? path17.basename(cwd) : project || await qoderProjectFromFilePath(filePath, options));
8492
+ project = projectContext.project || (cwd ? path18.basename(cwd) : project || await qoderProjectFromFilePath(filePath, options));
8339
8493
  if (!ts) {
8340
8494
  continue;
8341
8495
  }
@@ -8468,6 +8622,8 @@ async function parseQoderSessionFile(filePath, options) {
8468
8622
  model = rawModel ? modelMap[rawModel] || rawModel : void 0;
8469
8623
  const messageId = stringField(message, "id");
8470
8624
  const requestId = stringField(raw, "requestId");
8625
+ const isBlockStart = !assistantBlockOpen;
8626
+ assistantBlockOpen = true;
8471
8627
  const usageKey = messageId ? `${messageId}:${requestId}` : null;
8472
8628
  const shouldEmitUsage = usageKey == null || !seenUsageKeys.has(usageKey);
8473
8629
  if (usageKey != null) {
@@ -8492,6 +8648,19 @@ async function parseQoderSessionFile(filePath, options) {
8492
8648
  modelCalls: 1
8493
8649
  };
8494
8650
  model = call.model || model;
8651
+ } else if (shouldEmitUsage) {
8652
+ const dbCall = await nextDbModelCall(requestId, isBlockStart);
8653
+ if (dbCall) {
8654
+ usage = {
8655
+ tokensInput: dbCall.inputTokens || void 0,
8656
+ tokensCachedInput: dbCall.cachedTokens || void 0,
8657
+ tokensCacheReadInput: dbCall.cachedTokens || void 0,
8658
+ tokensOutput: dbCall.outputTokens || void 0,
8659
+ tokensTotal: dbCall.inputTokens + dbCall.outputTokens || void 0,
8660
+ modelCalls: 1
8661
+ };
8662
+ model = dbCall.model || model;
8663
+ }
8495
8664
  }
8496
8665
  if (usage) {
8497
8666
  const speed = stringField(objectField(message, "usage"), "speed");
@@ -8738,28 +8907,28 @@ function qoderExtractText(value) {
8738
8907
  }
8739
8908
  async function qoderProjectContextFromLines(filePath, lines, options, configDir2) {
8740
8909
  const { projectName: projectDir, sessionId } = parseQoderPaths(filePath);
8741
- const isSubagent = filePath.includes(`${path17.sep}subagents${path17.sep}`);
8910
+ const isSubagent = filePath.includes(`${path18.sep}subagents${path18.sep}`);
8742
8911
  const inherited = isSubagent ? await readPersistedSessionContextFromOptions(options, sessionId) : void 0;
8743
8912
  let cwds = [];
8744
8913
  for (const line of lines) {
8745
8914
  const raw = parseJsonLine(line);
8746
8915
  const cwd = raw ? stringField(raw, "cwd") : void 0;
8747
- if (cwd && path17.isAbsolute(cwd)) {
8916
+ if (cwd && path18.isAbsolute(cwd)) {
8748
8917
  cwds.push(cwd);
8749
8918
  }
8750
8919
  }
8751
8920
  if (isSubagent) {
8752
- if (inherited?.cwd && path17.isAbsolute(inherited.cwd)) {
8921
+ if (inherited?.cwd && path18.isAbsolute(inherited.cwd)) {
8753
8922
  cwds = [inherited.cwd];
8754
8923
  } else {
8755
- const parentSessionPath = path17.join(configDir2, "projects", projectDir, `${sessionId}.jsonl`);
8924
+ const parentSessionPath = path18.join(configDir2, "projects", projectDir, `${sessionId}.jsonl`);
8756
8925
  try {
8757
8926
  const parentText = await readFile11(parentSessionPath, "utf8");
8758
8927
  const parentCwds = [];
8759
8928
  for (const line of parentText.split("\n").filter(Boolean)) {
8760
8929
  const raw = parseJsonLine(line);
8761
8930
  const cwd = raw ? stringField(raw, "cwd") : void 0;
8762
- if (cwd && path17.isAbsolute(cwd)) {
8931
+ if (cwd && path18.isAbsolute(cwd)) {
8763
8932
  parentCwds.push(cwd);
8764
8933
  }
8765
8934
  }
@@ -8771,7 +8940,7 @@ async function qoderProjectContextFromLines(filePath, lines, options, configDir2
8771
8940
  }
8772
8941
  }
8773
8942
  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));
8943
+ const project = inherited?.project || (cwds.length > 0 ? path18.basename(cwds[0]) : root ? path18.basename(root) : await qoderProjectFromFilePath(filePath, options));
8775
8944
  return {
8776
8945
  project,
8777
8946
  workspaceId: createWorkspaceId({ projectName: project, repoRoot: root })
@@ -8780,15 +8949,15 @@ async function qoderProjectContextFromLines(filePath, lines, options, configDir2
8780
8949
  async function gitRootFromCwds3(cwds) {
8781
8950
  const seen = /* @__PURE__ */ new Set();
8782
8951
  for (const cwd of cwds) {
8783
- let current = path17.resolve(cwd);
8952
+ let current = path18.resolve(cwd);
8784
8953
  while (!seen.has(current)) {
8785
8954
  seen.add(current);
8786
8955
  try {
8787
- await stat9(path17.join(current, ".git"));
8956
+ await stat9(path18.join(current, ".git"));
8788
8957
  return current;
8789
8958
  } catch {
8790
8959
  }
8791
- const parent = path17.dirname(current);
8960
+ const parent = path18.dirname(current);
8792
8961
  if (parent === current) {
8793
8962
  break;
8794
8963
  }
@@ -8799,12 +8968,12 @@ async function gitRootFromCwds3(cwds) {
8799
8968
  }
8800
8969
  function qoderProjectRootFromCwds(projectDir, cwds) {
8801
8970
  for (const cwd of cwds) {
8802
- let current = path17.resolve(cwd);
8971
+ let current = path18.resolve(cwd);
8803
8972
  while (true) {
8804
8973
  if (encodeQoderProjectPath(current) === projectDir) {
8805
8974
  return current;
8806
8975
  }
8807
- const parent = path17.dirname(current);
8976
+ const parent = path18.dirname(current);
8808
8977
  if (parent === current) {
8809
8978
  break;
8810
8979
  }
@@ -8814,10 +8983,10 @@ function qoderProjectRootFromCwds(projectDir, cwds) {
8814
8983
  return void 0;
8815
8984
  }
8816
8985
  function encodeQoderProjectPath(value) {
8817
- return path17.resolve(value).split(path17.sep).join("-").replace(/_/g, "-");
8986
+ return path18.resolve(value).split(path18.sep).join("-").replace(/_/g, "-");
8818
8987
  }
8819
8988
  function rawQoderProjectPath(value) {
8820
- return path17.resolve(value).split(path17.sep).join("-");
8989
+ return path18.resolve(value).split(path18.sep).join("-");
8821
8990
  }
8822
8991
  function qoderEncodedVariants(value) {
8823
8992
  const raw = rawQoderProjectPath(value);
@@ -8833,11 +9002,11 @@ function qoderEncodedProjectSuffix(projectDir, home) {
8833
9002
  return void 0;
8834
9003
  }
8835
9004
  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();
9005
+ const projectDir = path18.basename(path18.dirname(filePath));
9006
+ const home = options ? path18.resolve(stringOption(options.home) || os9.homedir()) : os9.homedir();
8838
9007
  const resolved = await resolveQoderProjectPath(projectDir, home);
8839
9008
  if (resolved) {
8840
- return path17.basename(resolved);
9009
+ return path18.basename(resolved);
8841
9010
  }
8842
9011
  const suffix = qoderEncodedProjectSuffix(projectDir, home);
8843
9012
  if (suffix) {
@@ -8863,7 +9032,7 @@ async function resolveQoderProjectPath(projectDir, home) {
8863
9032
  if (!entry.isDirectory()) {
8864
9033
  continue;
8865
9034
  }
8866
- const candidate = path17.join(current, entry.name);
9035
+ const candidate = path18.join(current, entry.name);
8867
9036
  const candidateVariants = qoderEncodedVariants(candidate);
8868
9037
  if (candidateVariants.includes(projectDir)) {
8869
9038
  return candidate;
@@ -8908,9 +9077,9 @@ function hookConfig7() {
8908
9077
  function qoderConfigDir(home, env) {
8909
9078
  const override = env?.QODER_CONFIG_DIR;
8910
9079
  if (override && override.trim()) {
8911
- return path17.resolve(override);
9080
+ return path18.resolve(override);
8912
9081
  }
8913
- return path17.join(home, ".qoder");
9082
+ return path18.join(home, ".qoder");
8914
9083
  }
8915
9084
  function createQoderAdapter() {
8916
9085
  return {
@@ -8922,27 +9091,27 @@ function createQoderAdapter() {
8922
9091
  return qoderConfigDir(home, env);
8923
9092
  },
8924
9093
  installedPath(home, env) {
8925
- return path17.join(qoderConfigDir(home, env), "settings.json");
9094
+ return path18.join(qoderConfigDir(home, env), "settings.json");
8926
9095
  },
8927
9096
  async isInstalled(home, env) {
8928
9097
  return isHooksJsonInstalled(
8929
- path17.join(qoderConfigDir(home, env), "settings.json"),
9098
+ path18.join(qoderConfigDir(home, env), "settings.json"),
8930
9099
  "vibetime hook --agent qoder"
8931
9100
  );
8932
9101
  },
8933
9102
  installEntries(home, env) {
8934
9103
  return [{
8935
9104
  kind: "hooks-json",
8936
- path: path17.join(qoderConfigDir(home, env), "settings.json"),
9105
+ path: path18.join(qoderConfigDir(home, env), "settings.json"),
8937
9106
  content: hookConfig7()
8938
9107
  }];
8939
9108
  },
8940
9109
  sourcePaths(home, env) {
8941
9110
  const base = qoderConfigDir(home, env);
8942
9111
  return [
8943
- path17.join(base, "projects"),
8944
- path17.join(base, ".qoder.json"),
8945
- path17.join(home, ".qoder.json")
9112
+ path18.join(base, "projects"),
9113
+ path18.join(base, ".qoder.json"),
9114
+ path18.join(home, ".qoder.json")
8946
9115
  ];
8947
9116
  },
8948
9117
  parseSessionFile: parseQoderSessionFile
@@ -8978,20 +9147,20 @@ function normalizeId(id) {
8978
9147
 
8979
9148
  // src/adapters/workbuddy.ts
8980
9149
  import { readFile as readFile12, readdir as readdir9, stat as stat10 } from "node:fs/promises";
8981
- import path18 from "node:path";
9150
+ import path19 from "node:path";
8982
9151
  init_fs();
8983
9152
  function workbuddyProjectsDir(home, env) {
8984
9153
  const override = env?.WORKBUDDY_PROJECTS_DIR || env?.WORKBUDDY_HOME;
8985
9154
  if (override && override.trim()) {
8986
- return path18.resolve(override, override.endsWith("projects") ? "" : "projects");
9155
+ return path19.resolve(override, override.endsWith("projects") ? "" : "projects");
8987
9156
  }
8988
- return path18.join(home, ".workbuddy", "projects");
9157
+ return path19.join(home, ".workbuddy", "projects");
8989
9158
  }
8990
9159
  function projectFromCwd(cwd, fallback) {
8991
9160
  if (!cwd) {
8992
9161
  return fallback;
8993
9162
  }
8994
- return path18.basename(cwd) || fallback;
9163
+ return path19.basename(cwd) || fallback;
8995
9164
  }
8996
9165
  function sourceHash(filePath) {
8997
9166
  return `sha256:${createStableHash(filePath)}`;
@@ -9094,8 +9263,8 @@ async function parseWorkbuddySessionFile(filePath, options) {
9094
9263
  }
9095
9264
  const events = [];
9096
9265
  const first = lines[0].record;
9097
- const sessionId = stringField(first, "sessionId") || path18.basename(filePath, ".jsonl");
9098
- const fallbackProject = path18.basename(path18.dirname(filePath));
9266
+ const sessionId = stringField(first, "sessionId") || path19.basename(filePath, ".jsonl");
9267
+ const fallbackProject = path19.basename(path19.dirname(filePath));
9099
9268
  const cwd = lines.map((line) => stringField(line.record, "cwd")).find(Boolean);
9100
9269
  const project = projectFromCwd(cwd, fallbackProject);
9101
9270
  const workspaceId = createWorkspaceId({ projectName: project, repoRoot: cwd });
@@ -9269,11 +9438,11 @@ async function workbuddyBackfillFiles(sourceRoot, home, env) {
9269
9438
  if (!project.isDirectory()) {
9270
9439
  continue;
9271
9440
  }
9272
- const projectDir = path18.join(base, project.name);
9441
+ const projectDir = path19.join(base, project.name);
9273
9442
  const entries = await readdir9(projectDir, { withFileTypes: true });
9274
9443
  for (const entry of entries) {
9275
9444
  if (entry.isFile() && entry.name.endsWith(".jsonl")) {
9276
- const filePath = path18.join(projectDir, entry.name);
9445
+ const filePath = path19.join(projectDir, entry.name);
9277
9446
  const info = await stat10(filePath);
9278
9447
  files.push({ path: filePath, modifiedAt: info.mtime.toISOString() });
9279
9448
  }
@@ -9312,19 +9481,19 @@ function createWorkbuddyAdapter() {
9312
9481
  // src/adapters/zcode.ts
9313
9482
  import { execFile } from "node:child_process";
9314
9483
  import { readFile as readFile13, stat as stat11 } from "node:fs/promises";
9315
- import path19 from "node:path";
9484
+ import path20 from "node:path";
9316
9485
  import { promisify as promisify2 } from "node:util";
9317
9486
  init_fs();
9318
9487
  var execFileAsync = promisify2(execFile);
9319
9488
  function zcodeCliDir(home, env) {
9320
9489
  const override = env?.ZCODE_CLI_DIR || env?.ZCODE_HOME;
9321
9490
  if (override && override.trim()) {
9322
- return path19.resolve(override, override.endsWith("cli") ? "" : "cli");
9491
+ return path20.resolve(override, override.endsWith("cli") ? "" : "cli");
9323
9492
  }
9324
- return path19.join(home, ".zcode", "cli");
9493
+ return path20.join(home, ".zcode", "cli");
9325
9494
  }
9326
9495
  function zcodeDbPath(home, env) {
9327
- return path19.join(zcodeCliDir(home, env), "db", "db.sqlite");
9496
+ return path20.join(zcodeCliDir(home, env), "db", "db.sqlite");
9328
9497
  }
9329
9498
  var providerNameCache = null;
9330
9499
  async function loadProviderNames(configPath2) {
@@ -9358,7 +9527,7 @@ function sourceHash2(filePath) {
9358
9527
  return `sha256:${createStableHash(filePath)}`;
9359
9528
  }
9360
9529
  function projectFromDirectory(directory) {
9361
- return directory ? path19.basename(directory) || "zcode" : "zcode";
9530
+ return directory ? path20.basename(directory) || "zcode" : "zcode";
9362
9531
  }
9363
9532
  function isoFromMs(value) {
9364
9533
  return timestampFrom(typeof value === "number" ? value : Number(value));
@@ -9541,16 +9710,16 @@ async function parseZCodeDb(filePath, options) {
9541
9710
  if (rows.length === 0) {
9542
9711
  return [];
9543
9712
  }
9544
- let candidate = path19.resolve(filePath);
9713
+ let candidate = path20.resolve(filePath);
9545
9714
  let configPath2 = "";
9546
9715
  for (let i = 0; i < 12; i++) {
9547
- const probe = path19.join(candidate, ".zcode", "v2", "config.json");
9716
+ const probe = path20.join(candidate, ".zcode", "v2", "config.json");
9548
9717
  try {
9549
9718
  await stat11(probe);
9550
9719
  configPath2 = probe;
9551
9720
  break;
9552
9721
  } catch {
9553
- const parent = path19.dirname(candidate);
9722
+ const parent = path20.dirname(candidate);
9554
9723
  if (parent === candidate) break;
9555
9724
  candidate = parent;
9556
9725
  }
@@ -9766,7 +9935,7 @@ async function parseZCodeDb(filePath, options) {
9766
9935
  }
9767
9936
  async function zcodeBackfillFiles(sourceRoot, home, env) {
9768
9937
  const candidate = sourceRoot || zcodeDbPath(home, env);
9769
- const filePath = candidate.endsWith(".sqlite") ? candidate : path19.join(candidate, "db", "db.sqlite");
9938
+ const filePath = candidate.endsWith(".sqlite") ? candidate : path20.join(candidate, "db", "db.sqlite");
9770
9939
  try {
9771
9940
  const info = await stat11(filePath);
9772
9941
  return [{ path: filePath, modifiedAt: info.mtime.toISOString() }];
@@ -9800,50 +9969,50 @@ function createZCodeAdapter() {
9800
9969
  }
9801
9970
 
9802
9971
  // src/adapters/zed.ts
9803
- import os9 from "node:os";
9804
- import path20 from "node:path";
9972
+ import os10 from "node:os";
9973
+ import path21 from "node:path";
9805
9974
  function zedThreadsCandidates(home, env) {
9806
9975
  const candidates = [];
9807
9976
  const platform2 = process.platform;
9808
9977
  if (platform2 === "darwin") {
9809
- candidates.push(path20.join(home, "Library", "Application Support", "Zed", "threads", "threads.db"));
9978
+ candidates.push(path21.join(home, "Library", "Application Support", "Zed", "threads", "threads.db"));
9810
9979
  } else if (platform2 === "win32") {
9811
9980
  const appdata = env?.APPDATA;
9812
9981
  if (appdata && appdata.trim()) {
9813
- candidates.push(path20.join(path20.resolve(appdata), "Zed", "threads", "threads.db"));
9982
+ candidates.push(path21.join(path21.resolve(appdata), "Zed", "threads", "threads.db"));
9814
9983
  }
9815
- candidates.push(path20.join(home, "AppData", "Roaming", "Zed", "threads", "threads.db"));
9984
+ candidates.push(path21.join(home, "AppData", "Roaming", "Zed", "threads", "threads.db"));
9816
9985
  } else {
9817
9986
  const xdgData = env?.XDG_DATA_HOME;
9818
9987
  if (xdgData && xdgData.trim()) {
9819
- candidates.push(path20.join(path20.resolve(xdgData), "zed", "threads", "threads.db"));
9988
+ candidates.push(path21.join(path21.resolve(xdgData), "zed", "threads", "threads.db"));
9820
9989
  }
9821
- candidates.push(path20.join(home, ".local", "share", "zed", "threads", "threads.db"));
9990
+ candidates.push(path21.join(home, ".local", "share", "zed", "threads", "threads.db"));
9822
9991
  const xdgConfig = env?.XDG_CONFIG_HOME;
9823
9992
  if (xdgConfig && xdgConfig.trim()) {
9824
- candidates.push(path20.join(path20.resolve(xdgConfig), "zed", "threads", "threads.db"));
9993
+ candidates.push(path21.join(path21.resolve(xdgConfig), "zed", "threads", "threads.db"));
9825
9994
  }
9826
- candidates.push(path20.join(home, ".config", "zed", "threads", "threads.db"));
9995
+ candidates.push(path21.join(home, ".config", "zed", "threads", "threads.db"));
9827
9996
  }
9828
9997
  return candidates;
9829
9998
  }
9830
9999
  function zedConfigDir(home, env) {
9831
10000
  const platform2 = process.platform;
9832
10001
  if (platform2 === "darwin") {
9833
- return path20.join(home, "Library", "Application Support", "Zed");
10002
+ return path21.join(home, "Library", "Application Support", "Zed");
9834
10003
  }
9835
10004
  if (platform2 === "win32") {
9836
10005
  const appdata = env?.APPDATA;
9837
10006
  if (appdata && appdata.trim()) {
9838
- return path20.join(path20.resolve(appdata), "Zed");
10007
+ return path21.join(path21.resolve(appdata), "Zed");
9839
10008
  }
9840
- return path20.join(home, "AppData", "Roaming", "Zed");
10009
+ return path21.join(home, "AppData", "Roaming", "Zed");
9841
10010
  }
9842
10011
  const xdgConfig = env?.XDG_CONFIG_HOME;
9843
10012
  if (xdgConfig && xdgConfig.trim()) {
9844
- return path20.join(path20.resolve(xdgConfig), "zed");
10013
+ return path21.join(path21.resolve(xdgConfig), "zed");
9845
10014
  }
9846
- return path20.join(home, ".config", "zed");
10015
+ return path21.join(home, ".config", "zed");
9847
10016
  }
9848
10017
  function baseZedEvent(event) {
9849
10018
  return {
@@ -9907,7 +10076,7 @@ async function parseZedSessionFile(dbPath, options) {
9907
10076
  const folderRaw = row.folder_paths || "";
9908
10077
  const folder = folderRaw.split(/[\n,]/).map((s) => s.trim()).find(Boolean);
9909
10078
  const cwd = folder || void 0;
9910
- const project = cwd ? path20.basename(cwd) : row.summary ? row.summary.slice(0, 40) : void 0;
10079
+ const project = cwd ? path21.basename(cwd) : row.summary ? row.summary.slice(0, 40) : void 0;
9911
10080
  let json;
9912
10081
  try {
9913
10082
  const bytes = row.data_type === "zstd" ? decompress2(new Uint8Array(row.data)) : new Uint8Array(row.data);
@@ -10152,7 +10321,7 @@ async function parseZedSessionFile(dbPath, options) {
10152
10321
  }
10153
10322
  return events.filter((event) => matchesBackfillFilters(event, options));
10154
10323
  }
10155
- async function zedBackfillFiles(sourceRoot, home = os9.homedir(), env) {
10324
+ async function zedBackfillFiles(sourceRoot, home = os10.homedir(), env) {
10156
10325
  const { stat: stat14 } = await import("node:fs/promises");
10157
10326
  if (sourceRoot) {
10158
10327
  if (!sourceRoot.endsWith(".db")) {
@@ -10182,7 +10351,7 @@ function createZedAdapter() {
10182
10351
  return zedConfigDir(home, env);
10183
10352
  },
10184
10353
  installedPath(home, env) {
10185
- return path20.join(zedConfigDir(home, env), "vibetime-marker");
10354
+ return path21.join(zedConfigDir(home, env), "vibetime-marker");
10186
10355
  },
10187
10356
  async isInstalled() {
10188
10357
  return false;
@@ -10641,15 +10810,15 @@ function hookCommandFromGroup(group) {
10641
10810
  import { randomUUID } from "node:crypto";
10642
10811
  import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
10643
10812
  import { homedir, hostname } from "node:os";
10644
- import path21 from "node:path";
10813
+ import path22 from "node:path";
10645
10814
  function configDir(home = homedir()) {
10646
- return path21.join(home, ".vibetime");
10815
+ return path22.join(home, ".vibetime");
10647
10816
  }
10648
10817
  function configPath(home = homedir()) {
10649
- return path21.join(configDir(home), "config.json");
10818
+ return path22.join(configDir(home), "config.json");
10650
10819
  }
10651
10820
  function machineIdPath(home = homedir()) {
10652
- return path21.join(configDir(home), "machine-id");
10821
+ return path22.join(configDir(home), "machine-id");
10653
10822
  }
10654
10823
  function readConfig(home = homedir()) {
10655
10824
  const file = configPath(home);
@@ -10698,13 +10867,13 @@ init_fs();
10698
10867
  // src/lib/logger.ts
10699
10868
  import { appendFile, mkdir as mkdir4, rename, stat as stat12 } from "node:fs/promises";
10700
10869
  import { homedir as homedir2 } from "node:os";
10701
- import path22 from "node:path";
10870
+ import path23 from "node:path";
10702
10871
  var MAX_BYTES = 1 * 1024 * 1024;
10703
10872
  function logDir(home = homedir2()) {
10704
- return path22.join(home, ".vibetime", "logs");
10873
+ return path23.join(home, ".vibetime", "logs");
10705
10874
  }
10706
10875
  function logPath(home = homedir2(), name = "cli.log") {
10707
- return path22.join(logDir(home), name);
10876
+ return path23.join(logDir(home), name);
10708
10877
  }
10709
10878
  function serializeError(error) {
10710
10879
  if (error instanceof Error) {
@@ -10879,8 +11048,8 @@ function buildHeaders(token, machine) {
10879
11048
  ...machine?.platform ? { "x-machine-platform": machine.platform } : {}
10880
11049
  };
10881
11050
  }
10882
- function joinUrl(base, path24) {
10883
- return new URL(path24, base.endsWith("/") ? base : `${base}/`).toString();
11051
+ function joinUrl(base, path25) {
11052
+ return new URL(path25, base.endsWith("/") ? base : `${base}/`).toString();
10884
11053
  }
10885
11054
  async function postRollupBatch(remote, rollups, options = {}) {
10886
11055
  const response = await remote.fetchImpl(joinUrl(remote.baseUrl, "/v3/agent/ingest"), {
@@ -11799,13 +11968,13 @@ function selectBackfillFilesForImport(files, watermarkTs) {
11799
11968
  });
11800
11969
  }
11801
11970
  function backfillIncrementalStatePath(home) {
11802
- return path23.join(home, ".vibetime", "backfill-state.json");
11971
+ return path24.join(home, ".vibetime", "backfill-state.json");
11803
11972
  }
11804
11973
  function syncLocalTriggerStatePath(home) {
11805
- return path23.join(home, ".vibetime", "sync-local-trigger.json");
11974
+ return path24.join(home, ".vibetime", "sync-local-trigger.json");
11806
11975
  }
11807
11976
  function syncLocalTriggerLockPath(home) {
11808
- return path23.join(home, ".vibetime", "sync-local-trigger.lock");
11977
+ return path24.join(home, ".vibetime", "sync-local-trigger.lock");
11809
11978
  }
11810
11979
  function backfillRemoteKey(baseUrl) {
11811
11980
  try {
@@ -11867,7 +12036,7 @@ async function readBackfillIncrementalStateFile(home, ctx) {
11867
12036
  }
11868
12037
  async function writeBackfillIncrementalStateFile(home, file) {
11869
12038
  const statePath = backfillIncrementalStatePath(home);
11870
- await mkdir5(path23.dirname(statePath), { recursive: true });
12039
+ await mkdir5(path24.dirname(statePath), { recursive: true });
11871
12040
  await writeFile4(statePath, `${JSON.stringify(file, null, 2)}
11872
12041
  `, "utf8");
11873
12042
  }
@@ -11916,7 +12085,7 @@ async function readSyncLocalTriggerState(statePath) {
11916
12085
  return nextState;
11917
12086
  }
11918
12087
  async function writeSyncLocalTriggerState(statePath, state) {
11919
- await mkdir5(path23.dirname(statePath), { recursive: true });
12088
+ await mkdir5(path24.dirname(statePath), { recursive: true });
11920
12089
  await writeFile4(statePath, `${JSON.stringify(state, null, 2)}
11921
12090
  `, "utf8");
11922
12091
  }
@@ -11931,12 +12100,12 @@ async function readSyncLocalLock(lockPath) {
11931
12100
  return { pid: lock.pid, startedAt: lock.startedAt };
11932
12101
  }
11933
12102
  async function writeSyncLocalLock(lockPath, lock) {
11934
- await mkdir5(path23.dirname(lockPath), { recursive: true });
12103
+ await mkdir5(path24.dirname(lockPath), { recursive: true });
11935
12104
  await writeFile4(lockPath, `${JSON.stringify(lock, null, 2)}
11936
12105
  `, "utf8");
11937
12106
  }
11938
12107
  async function acquireSyncLocalLock(lockPath, lock) {
11939
- await mkdir5(path23.dirname(lockPath), { recursive: true });
12108
+ await mkdir5(path24.dirname(lockPath), { recursive: true });
11940
12109
  try {
11941
12110
  const handle = await open(lockPath, "wx");
11942
12111
  try {
@@ -12016,10 +12185,10 @@ function syncLocalRunnerEntryArgs(cliPath) {
12016
12185
  if (cliPath.endsWith(".ts")) {
12017
12186
  return ["--import", "tsx", cliPath];
12018
12187
  }
12019
- return [path23.resolve(path23.dirname(cliPath), "../bin/vibetime.mjs")];
12188
+ return [path24.resolve(path24.dirname(cliPath), "../bin/vibetime.mjs")];
12020
12189
  }
12021
12190
  function resolveHome3(options, ctx) {
12022
- return path23.resolve(stringOption(options.home) || ctx.env.HOME || os10.homedir());
12191
+ return path24.resolve(stringOption(options.home) || ctx.env.HOME || os11.homedir());
12023
12192
  }
12024
12193
  function requestedTargets(options) {
12025
12194
  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.33",
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": {