@yhong91/vibetime 0.1.48 → 0.1.49

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 +93 -7
  2. package/package.json +1 -1
package/bin/vibetime.mjs CHANGED
@@ -2047,7 +2047,7 @@ function claudeStyleFileMetrics(tool, input) {
2047
2047
  }
2048
2048
 
2049
2049
  // src/lib/constants.ts
2050
- var PACKAGE_VERSION = true ? "0.1.48" : "0.1.1";
2050
+ var PACKAGE_VERSION = true ? "0.1.49" : "0.1.1";
2051
2051
  var DEFAULT_API_URL = "http://121.196.224.82:3001";
2052
2052
  var DEFAULT_BACKFILL_BATCH_SIZE = 50;
2053
2053
  var DEFAULT_BACKFILL_BATCH_BYTES = 800 * 1024;
@@ -7501,6 +7501,79 @@ function createOpenCodeAdapter() {
7501
7501
  // src/adapters/pi.ts
7502
7502
  import { readFile as readFile9 } from "node:fs/promises";
7503
7503
  import path15 from "node:path";
7504
+ function parsePiSubagentLink(filePath, headerParentSession) {
7505
+ if (headerParentSession) {
7506
+ const parentFile = path15.isAbsolute(headerParentSession) ? headerParentSession : void 0;
7507
+ const parentSessionId2 = parentFile ? path15.basename(parentFile, ".jsonl") : headerParentSession;
7508
+ return { parentSessionId: parentSessionId2, parentSessionFile: parentFile, explicit: true };
7509
+ }
7510
+ const normalized = filePath.replaceAll("\\", "/");
7511
+ const match = normalized.match(/([^/]+)\/[^/]+\/run-\d+\/session\.jsonl$/);
7512
+ if (!match) {
7513
+ return void 0;
7514
+ }
7515
+ const parentBasename = match[1];
7516
+ if (!parentBasename || parentBasename === "session") {
7517
+ return void 0;
7518
+ }
7519
+ const parentSessionId = parentBasename.endsWith(".jsonl") ? parentBasename.slice(0, -".jsonl".length) : parentBasename;
7520
+ const parentDir = path15.dirname(path15.dirname(path15.dirname(filePath)));
7521
+ const parentSessionFile = path15.join(path15.dirname(parentDir), `${parentBasename}.jsonl`);
7522
+ return { parentSessionId, parentSessionFile, explicit: false };
7523
+ }
7524
+ async function resolveParentContext(link, options) {
7525
+ if (link.parentSessionFile) {
7526
+ try {
7527
+ const text = await readFile9(link.parentSessionFile, "utf8");
7528
+ const firstLine = text.split("\n").find((line) => line.trim().length > 0);
7529
+ const raw = firstLine ? parseJsonLine(firstLine) : void 0;
7530
+ if (raw) {
7531
+ const id = stringField(raw, "id");
7532
+ const cwd = stringField(raw, "cwd");
7533
+ const project = cwd ? path15.basename(cwd) : void 0;
7534
+ if (id || cwd || project) {
7535
+ return { sessionId: id, cwd, project };
7536
+ }
7537
+ }
7538
+ } catch {
7539
+ }
7540
+ }
7541
+ const persisted = await readPersistedSessionContextFromOptions(options, link.parentSessionId);
7542
+ if (persisted) {
7543
+ return { cwd: persisted.cwd, project: persisted.project };
7544
+ }
7545
+ return void 0;
7546
+ }
7547
+ function foldEventsIntoParent(events, link) {
7548
+ const childSessionId = events.find((event) => event.sessionId)?.sessionId;
7549
+ return events.map((event) => {
7550
+ const rewritten = {
7551
+ ...event,
7552
+ sessionId: link.parentSessionId
7553
+ };
7554
+ if (childSessionId && childSessionId !== link.parentSessionId) {
7555
+ rewritten.refs = {
7556
+ ...event.refs,
7557
+ supersededSessionId: childSessionId
7558
+ };
7559
+ }
7560
+ return rebuildEventIdentity2(rewritten);
7561
+ });
7562
+ }
7563
+ function rebuildEventIdentity2(event) {
7564
+ const importKey = createImportKey([
7565
+ event.source,
7566
+ event.refs?.sourcePathHash,
7567
+ event.refs?.sourceLine,
7568
+ event.type,
7569
+ event.refs?.sourceId
7570
+ ]);
7571
+ return {
7572
+ ...event,
7573
+ id: createStableEventId(importKey),
7574
+ refs: { ...event.refs, importKey }
7575
+ };
7576
+ }
7504
7577
  async function parsePiSessionFile(filePath, options) {
7505
7578
  const text = await readFile9(filePath, "utf8");
7506
7579
  const lines = text.split("\n").filter(Boolean);
@@ -7511,6 +7584,7 @@ async function parsePiSessionFile(filePath, options) {
7511
7584
  let provider;
7512
7585
  let turnStartedAt;
7513
7586
  let reasoningEffort;
7587
+ let headerParentSession;
7514
7588
  const pendingToolCalls = /* @__PURE__ */ new Map();
7515
7589
  const state = new SessionParserState(filePath, options, (event) => basePiEvent({ ...event, cwd, project, model }));
7516
7590
  const push = (event, ln) => {
@@ -7534,6 +7608,7 @@ async function parsePiSessionFile(filePath, options) {
7534
7608
  state.sessionId = sessionId || state.sessionId;
7535
7609
  cwd = stringField(raw, "cwd") || cwd;
7536
7610
  project = cwd ? path15.basename(cwd) : project;
7611
+ headerParentSession = stringField(raw, "parentSession") || headerParentSession;
7537
7612
  continue;
7538
7613
  }
7539
7614
  if (entryType === "model_change") {
@@ -7717,6 +7792,17 @@ async function parsePiSessionFile(filePath, options) {
7717
7792
  if (isTurnIdle(state.currentTurnLastEventAt)) {
7718
7793
  state.closeTurn(state.currentTurnLastEventAt, lines.length);
7719
7794
  }
7795
+ const link = parsePiSubagentLink(filePath, headerParentSession);
7796
+ if (link) {
7797
+ const parentContext = await resolveParentContext(link, options);
7798
+ const effectiveLink = parentContext?.sessionId ? { ...link, parentSessionId: parentContext.sessionId } : link;
7799
+ if (parentContext) {
7800
+ cwd = cwd || parentContext.cwd;
7801
+ project = project || parentContext.project;
7802
+ }
7803
+ const events = state.events.filter((event) => matchesBackfillFilters(event, options));
7804
+ return foldEventsIntoParent(events, effectiveLink);
7805
+ }
7720
7806
  return state.events.filter((event) => matchesBackfillFilters(event, options));
7721
7807
  }
7722
7808
  function basePiEvent(event) {
@@ -8146,7 +8232,7 @@ function parseQoderCnPaths(filePath) {
8146
8232
  }
8147
8233
  return { configDir: configDir2, projectName, sessionId, mainTranscriptPath };
8148
8234
  }
8149
- function rebuildEventIdentity2(event) {
8235
+ function rebuildEventIdentity3(event) {
8150
8236
  const importKey = createImportKey([
8151
8237
  event.source,
8152
8238
  event.refs?.sourcePathHash,
@@ -8567,7 +8653,7 @@ async function parseQoderCnSessionFile(filePath, options) {
8567
8653
  ...event.sessionId && event.sessionId !== parentSessionId ? { supersededSessionId: event.sessionId } : {}
8568
8654
  }
8569
8655
  };
8570
- return rebuildEventIdentity2(mapped);
8656
+ return rebuildEventIdentity3(mapped);
8571
8657
  });
8572
8658
  }
8573
8659
  }
@@ -8575,7 +8661,7 @@ async function parseQoderCnSessionFile(filePath, options) {
8575
8661
  if (dbModelCalls.rootSessionId) {
8576
8662
  const parentPath = path17.join(path17.dirname(filePath), `${dbModelCalls.rootSessionId}.jsonl`);
8577
8663
  const parentSourcePathHash = `sha256:${createStableHash(parentPath)}`;
8578
- return validEvents.map((event) => rebuildEventIdentity2({
8664
+ return validEvents.map((event) => rebuildEventIdentity3({
8579
8665
  ...event,
8580
8666
  sessionId: dbModelCalls.rootSessionId,
8581
8667
  refs: {
@@ -8924,7 +9010,7 @@ function parseQoderPaths(filePath) {
8924
9010
  }
8925
9011
  return { configDir: configDir2, projectName, sessionId, mainTranscriptPath };
8926
9012
  }
8927
- function rebuildEventIdentity3(event) {
9013
+ function rebuildEventIdentity4(event) {
8928
9014
  const importKey = createImportKey([
8929
9015
  event.source,
8930
9016
  event.refs?.sourcePathHash,
@@ -9345,7 +9431,7 @@ async function parseQoderSessionFile(filePath, options) {
9345
9431
  ...event.sessionId && event.sessionId !== parentSessionId ? { supersededSessionId: event.sessionId } : {}
9346
9432
  }
9347
9433
  };
9348
- return rebuildEventIdentity3(mapped);
9434
+ return rebuildEventIdentity4(mapped);
9349
9435
  });
9350
9436
  }
9351
9437
  }
@@ -9353,7 +9439,7 @@ async function parseQoderSessionFile(filePath, options) {
9353
9439
  if (dbModelCalls.rootSessionId) {
9354
9440
  const parentPath = path18.join(path18.dirname(filePath), `${dbModelCalls.rootSessionId}.jsonl`);
9355
9441
  const parentSourcePathHash = `sha256:${createStableHash(parentPath)}`;
9356
- return validEvents.map((event) => rebuildEventIdentity3({
9442
+ return validEvents.map((event) => rebuildEventIdentity4({
9357
9443
  ...event,
9358
9444
  sessionId: dbModelCalls.rootSessionId,
9359
9445
  refs: {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@yhong91/vibetime",
3
3
  "type": "module",
4
- "version": "0.1.48",
4
+ "version": "0.1.49",
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": {