@yhong91/vibetime 0.1.28 → 0.1.29

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 +69 -6
  2. package/package.json +1 -1
package/bin/vibetime.mjs CHANGED
@@ -1928,7 +1928,7 @@ function countTextLines(text) {
1928
1928
  }
1929
1929
 
1930
1930
  // src/lib/constants.ts
1931
- var PACKAGE_VERSION = true ? "0.1.28" : "0.1.1";
1931
+ var PACKAGE_VERSION = true ? "0.1.29" : "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;
@@ -4069,6 +4069,19 @@ function prefixCoworkId(value) {
4069
4069
  }
4070
4070
  return value.startsWith(COWORK_PREFIX) ? value : `${COWORK_PREFIX}${value}`;
4071
4071
  }
4072
+ function parseCoworkSubagentPath(filePath) {
4073
+ const parts = filePath.split(path8.sep);
4074
+ const subagentsIdx = parts.lastIndexOf("subagents");
4075
+ if (subagentsIdx < 2) {
4076
+ return void 0;
4077
+ }
4078
+ const cliSessionId = parts[subagentsIdx - 1];
4079
+ if (!cliSessionId) {
4080
+ return void 0;
4081
+ }
4082
+ const mainTranscriptPath = [...parts.slice(0, subagentsIdx - 1), `${cliSessionId}.jsonl`].join(path8.sep);
4083
+ return { cliSessionId, mainTranscriptPath };
4084
+ }
4072
4085
  function rebuildEventIdentity(event) {
4073
4086
  const importKey = createImportKey([
4074
4087
  event.source,
@@ -4094,15 +4107,21 @@ async function parseClaudeCoworkSessionFile(filePath, options) {
4094
4107
  if (!parser) {
4095
4108
  return [];
4096
4109
  }
4110
+ const subagentInfo = parseCoworkSubagentPath(filePath);
4111
+ const parentSourcePathHash = subagentInfo ? `sha256:${createStableHash(subagentInfo.mainTranscriptPath)}` : void 0;
4112
+ const parentSessionId = subagentInfo ? prefixCoworkId(subagentInfo.cliSessionId) : void 0;
4097
4113
  const events = await parser(filePath, options);
4098
4114
  return events.map((event) => {
4099
- const sessionId = prefixCoworkId(event.sessionId);
4115
+ const sessionId = parentSessionId || prefixCoworkId(event.sessionId);
4100
4116
  const turnId = prefixCoworkId(event.turnId);
4101
4117
  const workspaceId = createWorkspaceId({ projectName: project, repoRoot: cwd });
4102
4118
  const refs2 = { ...event.refs };
4103
4119
  if (metadata.title) {
4104
4120
  refs2.coworkTitleHash = `sha256:${createStableHash(metadata.title)}`;
4105
4121
  }
4122
+ if (parentSourcePathHash) {
4123
+ refs2.sourcePathHash = parentSourcePathHash;
4124
+ }
4106
4125
  const mapped = {
4107
4126
  ...event,
4108
4127
  schemaVersion: event.schemaVersion || AGENT_TIME_SCHEMA_VERSION,
@@ -6348,6 +6367,7 @@ async function parseOpenCodeSessionFile(dbPath, options) {
6348
6367
  const hasDirectory = sessionCols.has("directory");
6349
6368
  const hasPath = sessionCols.has("path");
6350
6369
  const hasArchived = sessionCols.has("time_archived");
6370
+ const hasParentId = sessionCols.has("parent_id");
6351
6371
  const selectCols = ["id", "title", "time_created"];
6352
6372
  if (hasDirectory) {
6353
6373
  selectCols.push("directory");
@@ -6358,11 +6378,36 @@ async function parseOpenCodeSessionFile(dbPath, options) {
6358
6378
  if (hasArchived) {
6359
6379
  selectCols.push("time_archived");
6360
6380
  }
6381
+ if (hasParentId) {
6382
+ selectCols.push("parent_id");
6383
+ }
6361
6384
  const sessions = db.prepare(
6362
6385
  `SELECT ${selectCols.join(", ")} FROM session WHERE time_created IS NOT NULL ORDER BY time_created`
6363
6386
  ).all();
6387
+ const rootIdByRawId = /* @__PURE__ */ new Map();
6388
+ if (hasParentId) {
6389
+ const byId = new Map(sessions.map((s) => [s.id, s]));
6390
+ for (const session of sessions) {
6391
+ let current = session.id;
6392
+ const visited = /* @__PURE__ */ new Set();
6393
+ while (true) {
6394
+ if (visited.has(current)) {
6395
+ break;
6396
+ }
6397
+ visited.add(current);
6398
+ const node = byId.get(current);
6399
+ const parentId = node?.parent_id || void 0;
6400
+ if (!parentId || !byId.has(parentId)) {
6401
+ break;
6402
+ }
6403
+ current = parentId;
6404
+ }
6405
+ rootIdByRawId.set(session.id, current);
6406
+ }
6407
+ }
6364
6408
  for (const session of sessions) {
6365
- const sessionId = session.id;
6409
+ const rawSessionId = session.id;
6410
+ const sessionId = rootIdByRawId.get(rawSessionId) || rawSessionId;
6366
6411
  const cwd = session.directory || session.path || void 0;
6367
6412
  const project = cwd ? path14.basename(cwd) : void 0;
6368
6413
  const sessionTs = msToIso(session.time_created);
@@ -6376,14 +6421,14 @@ async function parseOpenCodeSessionFile(dbPath, options) {
6376
6421
  }));
6377
6422
  const messages = db.prepare(
6378
6423
  "SELECT id, data FROM message WHERE session_id = ? ORDER BY time_created"
6379
- ).all(sessionId);
6424
+ ).all(rawSessionId);
6380
6425
  let currentTurnId;
6381
6426
  let currentProvider;
6382
6427
  let turnTs;
6383
6428
  let reasoningEffort;
6384
6429
  const modelSwitchedEvents = db.prepare(
6385
6430
  "SELECT data FROM event WHERE aggregate_id = ? AND type = 'session.next.model.switched.1' ORDER BY seq"
6386
- ).all(sessionId);
6431
+ ).all(rawSessionId);
6387
6432
  for (const evt of modelSwitchedEvents) {
6388
6433
  try {
6389
6434
  const evtData = JSON.parse(evt.data);
@@ -9359,14 +9404,32 @@ function modelMetrics(row) {
9359
9404
  toolCalls: numberField(row, "tool_call_count")
9360
9405
  };
9361
9406
  }
9407
+ function resolveRootSessionId(sessionId, sessions) {
9408
+ let current = sessionId;
9409
+ const visited = /* @__PURE__ */ new Set();
9410
+ while (true) {
9411
+ if (visited.has(current)) {
9412
+ break;
9413
+ }
9414
+ visited.add(current);
9415
+ const session = sessions.get(current);
9416
+ const parentId = stringField(session, "parent_id");
9417
+ if (!parentId || !sessions.has(parentId)) {
9418
+ break;
9419
+ }
9420
+ current = parentId;
9421
+ }
9422
+ return current;
9423
+ }
9362
9424
  function sessionContext(row, sessions) {
9363
9425
  const sessionId = stringField(row, "session_id") || stringField(row, "id") || "unknown";
9364
9426
  const session = sessions.get(sessionId);
9365
9427
  const cwd = stringField(session, "directory");
9366
9428
  const project = projectFromDirectory(cwd);
9429
+ const rootSessionId = resolveRootSessionId(sessionId, sessions);
9367
9430
  return {
9368
9431
  rawSessionId: sessionId,
9369
- sessionId: `zcode:${sessionId}`,
9432
+ sessionId: `zcode:${rootSessionId}`,
9370
9433
  cwd,
9371
9434
  project,
9372
9435
  workspaceId: createWorkspaceId({ projectName: project, repoRoot: cwd }),
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@yhong91/vibetime",
3
3
  "type": "module",
4
- "version": "0.1.28",
4
+ "version": "0.1.29",
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": {