@yhong91/vibetime 0.1.28 → 0.1.30
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.
- package/bin/vibetime.mjs +131 -14
- 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.
|
|
1931
|
+
var PACKAGE_VERSION = true ? "0.1.30" : "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
|
|
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(
|
|
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(
|
|
6431
|
+
).all(rawSessionId);
|
|
6387
6432
|
for (const evt of modelSwitchedEvents) {
|
|
6388
6433
|
try {
|
|
6389
6434
|
const evtData = JSON.parse(evt.data);
|
|
@@ -7345,11 +7390,13 @@ function parseQoderCnPaths(filePath) {
|
|
|
7345
7390
|
let sessionId = "";
|
|
7346
7391
|
let projectName = "";
|
|
7347
7392
|
let configDir2 = "";
|
|
7393
|
+
let mainTranscriptPath;
|
|
7348
7394
|
if (subagentsIdx > 2) {
|
|
7349
7395
|
sessionId = parts[subagentsIdx - 1];
|
|
7350
7396
|
projectName = parts[subagentsIdx - 2];
|
|
7351
7397
|
const projectsIdx = parts.lastIndexOf("projects");
|
|
7352
7398
|
configDir2 = parts.slice(0, projectsIdx).join(path16.sep);
|
|
7399
|
+
mainTranscriptPath = [...parts.slice(0, subagentsIdx - 1), `${sessionId}.jsonl`].join(path16.sep);
|
|
7353
7400
|
} else {
|
|
7354
7401
|
const filename = parts.at(-1) || "";
|
|
7355
7402
|
sessionId = path16.basename(filename, ".jsonl");
|
|
@@ -7357,7 +7404,24 @@ function parseQoderCnPaths(filePath) {
|
|
|
7357
7404
|
const projectsIdx = parts.lastIndexOf("projects");
|
|
7358
7405
|
configDir2 = parts.slice(0, projectsIdx).join(path16.sep);
|
|
7359
7406
|
}
|
|
7360
|
-
return { configDir: configDir2, projectName, sessionId };
|
|
7407
|
+
return { configDir: configDir2, projectName, sessionId, mainTranscriptPath };
|
|
7408
|
+
}
|
|
7409
|
+
function rebuildEventIdentity2(event) {
|
|
7410
|
+
const importKey = createImportKey([
|
|
7411
|
+
event.source,
|
|
7412
|
+
event.refs?.sourcePathHash,
|
|
7413
|
+
event.refs?.sourceLine,
|
|
7414
|
+
event.type,
|
|
7415
|
+
event.refs?.sourceId
|
|
7416
|
+
]);
|
|
7417
|
+
return {
|
|
7418
|
+
...event,
|
|
7419
|
+
id: createStableEventId(importKey),
|
|
7420
|
+
refs: {
|
|
7421
|
+
...event.refs,
|
|
7422
|
+
importKey
|
|
7423
|
+
}
|
|
7424
|
+
};
|
|
7361
7425
|
}
|
|
7362
7426
|
async function loadQoderCnModelNames(configDir2) {
|
|
7363
7427
|
try {
|
|
@@ -7707,9 +7771,17 @@ async function parseQoderCnSessionFile(filePath, options) {
|
|
|
7707
7771
|
}
|
|
7708
7772
|
const validEvents = state.events.filter((event) => validateCanonicalEvent(event).valid);
|
|
7709
7773
|
if (isSubagentSession) {
|
|
7710
|
-
const parentSessionId = parseQoderCnPaths(filePath)
|
|
7711
|
-
if (parentSessionId) {
|
|
7712
|
-
|
|
7774
|
+
const { sessionId: parentSessionId, mainTranscriptPath } = parseQoderCnPaths(filePath);
|
|
7775
|
+
if (parentSessionId && mainTranscriptPath) {
|
|
7776
|
+
const parentSourcePathHash = `sha256:${createStableHash(mainTranscriptPath)}`;
|
|
7777
|
+
return validEvents.map((event) => {
|
|
7778
|
+
const mapped = {
|
|
7779
|
+
...event,
|
|
7780
|
+
sessionId: parentSessionId,
|
|
7781
|
+
refs: { ...event.refs, sourcePathHash: parentSourcePathHash }
|
|
7782
|
+
};
|
|
7783
|
+
return rebuildEventIdentity2(mapped);
|
|
7784
|
+
});
|
|
7713
7785
|
}
|
|
7714
7786
|
}
|
|
7715
7787
|
return validEvents;
|
|
@@ -8088,11 +8160,13 @@ function parseQoderPaths(filePath) {
|
|
|
8088
8160
|
let sessionId = "";
|
|
8089
8161
|
let projectName = "";
|
|
8090
8162
|
let configDir2 = "";
|
|
8163
|
+
let mainTranscriptPath;
|
|
8091
8164
|
if (subagentsIdx > 2) {
|
|
8092
8165
|
sessionId = parts[subagentsIdx - 1];
|
|
8093
8166
|
projectName = parts[subagentsIdx - 2];
|
|
8094
8167
|
const projectsIdx = parts.lastIndexOf("projects");
|
|
8095
8168
|
configDir2 = parts.slice(0, projectsIdx).join(path17.sep);
|
|
8169
|
+
mainTranscriptPath = [...parts.slice(0, subagentsIdx - 1), `${sessionId}.jsonl`].join(path17.sep);
|
|
8096
8170
|
} else {
|
|
8097
8171
|
const filename = parts.at(-1) || "";
|
|
8098
8172
|
sessionId = path17.basename(filename, ".jsonl");
|
|
@@ -8100,7 +8174,24 @@ function parseQoderPaths(filePath) {
|
|
|
8100
8174
|
const projectsIdx = parts.lastIndexOf("projects");
|
|
8101
8175
|
configDir2 = parts.slice(0, projectsIdx).join(path17.sep);
|
|
8102
8176
|
}
|
|
8103
|
-
return { configDir: configDir2, projectName, sessionId };
|
|
8177
|
+
return { configDir: configDir2, projectName, sessionId, mainTranscriptPath };
|
|
8178
|
+
}
|
|
8179
|
+
function rebuildEventIdentity3(event) {
|
|
8180
|
+
const importKey = createImportKey([
|
|
8181
|
+
event.source,
|
|
8182
|
+
event.refs?.sourcePathHash,
|
|
8183
|
+
event.refs?.sourceLine,
|
|
8184
|
+
event.type,
|
|
8185
|
+
event.refs?.sourceId
|
|
8186
|
+
]);
|
|
8187
|
+
return {
|
|
8188
|
+
...event,
|
|
8189
|
+
id: createStableEventId(importKey),
|
|
8190
|
+
refs: {
|
|
8191
|
+
...event.refs,
|
|
8192
|
+
importKey
|
|
8193
|
+
}
|
|
8194
|
+
};
|
|
8104
8195
|
}
|
|
8105
8196
|
async function loadQoderModelNames(configDir2) {
|
|
8106
8197
|
try {
|
|
@@ -8450,9 +8541,17 @@ async function parseQoderSessionFile(filePath, options) {
|
|
|
8450
8541
|
}
|
|
8451
8542
|
const validEvents = state.events.filter((event) => validateCanonicalEvent(event).valid);
|
|
8452
8543
|
if (isSubagentSession) {
|
|
8453
|
-
const parentSessionId = parseQoderPaths(filePath)
|
|
8454
|
-
if (parentSessionId) {
|
|
8455
|
-
|
|
8544
|
+
const { sessionId: parentSessionId, mainTranscriptPath } = parseQoderPaths(filePath);
|
|
8545
|
+
if (parentSessionId && mainTranscriptPath) {
|
|
8546
|
+
const parentSourcePathHash = `sha256:${createStableHash(mainTranscriptPath)}`;
|
|
8547
|
+
return validEvents.map((event) => {
|
|
8548
|
+
const mapped = {
|
|
8549
|
+
...event,
|
|
8550
|
+
sessionId: parentSessionId,
|
|
8551
|
+
refs: { ...event.refs, sourcePathHash: parentSourcePathHash }
|
|
8552
|
+
};
|
|
8553
|
+
return rebuildEventIdentity3(mapped);
|
|
8554
|
+
});
|
|
8456
8555
|
}
|
|
8457
8556
|
}
|
|
8458
8557
|
return validEvents;
|
|
@@ -9359,14 +9458,32 @@ function modelMetrics(row) {
|
|
|
9359
9458
|
toolCalls: numberField(row, "tool_call_count")
|
|
9360
9459
|
};
|
|
9361
9460
|
}
|
|
9461
|
+
function resolveRootSessionId(sessionId, sessions) {
|
|
9462
|
+
let current = sessionId;
|
|
9463
|
+
const visited = /* @__PURE__ */ new Set();
|
|
9464
|
+
while (true) {
|
|
9465
|
+
if (visited.has(current)) {
|
|
9466
|
+
break;
|
|
9467
|
+
}
|
|
9468
|
+
visited.add(current);
|
|
9469
|
+
const session = sessions.get(current);
|
|
9470
|
+
const parentId = stringField(session, "parent_id");
|
|
9471
|
+
if (!parentId || !sessions.has(parentId)) {
|
|
9472
|
+
break;
|
|
9473
|
+
}
|
|
9474
|
+
current = parentId;
|
|
9475
|
+
}
|
|
9476
|
+
return current;
|
|
9477
|
+
}
|
|
9362
9478
|
function sessionContext(row, sessions) {
|
|
9363
9479
|
const sessionId = stringField(row, "session_id") || stringField(row, "id") || "unknown";
|
|
9364
9480
|
const session = sessions.get(sessionId);
|
|
9365
9481
|
const cwd = stringField(session, "directory");
|
|
9366
9482
|
const project = projectFromDirectory(cwd);
|
|
9483
|
+
const rootSessionId = resolveRootSessionId(sessionId, sessions);
|
|
9367
9484
|
return {
|
|
9368
9485
|
rawSessionId: sessionId,
|
|
9369
|
-
sessionId: `zcode:${
|
|
9486
|
+
sessionId: `zcode:${rootSessionId}`,
|
|
9370
9487
|
cwd,
|
|
9371
9488
|
project,
|
|
9372
9489
|
workspaceId: createWorkspaceId({ projectName: project, repoRoot: cwd }),
|
package/package.json
CHANGED