@yhong91/vibetime 0.1.29 → 0.1.31
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 +114 -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.31" : "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;
|
|
@@ -4913,8 +4913,10 @@ async function parseCodexSessionFile(filePath, options) {
|
|
|
4913
4913
|
let lastTurnIdForComplete;
|
|
4914
4914
|
let turnIdAtLastUserMessage;
|
|
4915
4915
|
let sessionMetaLocked = false;
|
|
4916
|
+
let forkedSession = false;
|
|
4916
4917
|
let lastTotalTokenUsage;
|
|
4917
4918
|
let lastPerCallUsageKey;
|
|
4919
|
+
let compactionPending = false;
|
|
4918
4920
|
const pendingToolCalls = /* @__PURE__ */ new Map();
|
|
4919
4921
|
for (const [index, line] of lines.entries()) {
|
|
4920
4922
|
const lineNumber = index + 1;
|
|
@@ -4932,6 +4934,7 @@ async function parseCodexSessionFile(filePath, options) {
|
|
|
4932
4934
|
}
|
|
4933
4935
|
sessionMetaLocked = true;
|
|
4934
4936
|
const forkedFromId = stringField(payload, "forked_from_id");
|
|
4937
|
+
forkedSession = Boolean(forkedFromId);
|
|
4935
4938
|
const inherited = forkedFromId ? await readPersistedSessionContextFromOptions(options, forkedFromId) : void 0;
|
|
4936
4939
|
sessionId = stringField(payload, "id") || sessionId;
|
|
4937
4940
|
cwd = inherited?.cwd || stringField(payload, "cwd") || cwd;
|
|
@@ -4953,6 +4956,10 @@ async function parseCodexSessionFile(filePath, options) {
|
|
|
4953
4956
|
sessionStartEmitted = true;
|
|
4954
4957
|
continue;
|
|
4955
4958
|
}
|
|
4959
|
+
if (topType === "compacted") {
|
|
4960
|
+
compactionPending = true;
|
|
4961
|
+
continue;
|
|
4962
|
+
}
|
|
4956
4963
|
if (topType === "turn_context") {
|
|
4957
4964
|
currentTurnId = stringField(payload, "turn_id") || currentTurnId;
|
|
4958
4965
|
cwd = stringField(payload, "cwd") || cwd;
|
|
@@ -5080,12 +5087,32 @@ async function parseCodexSessionFile(filePath, options) {
|
|
|
5080
5087
|
project,
|
|
5081
5088
|
model: rewriteCodexModelForTier(model, serviceTier),
|
|
5082
5089
|
confidence: "partial",
|
|
5083
|
-
metrics: usage
|
|
5090
|
+
metrics: excludeForkInheritedCache(usage, forkedSession)
|
|
5084
5091
|
}), { filePath, sourcePathHash, lineNumber, topType, payloadType, options }));
|
|
5085
5092
|
lastPerCallUsageKey = usageKey;
|
|
5086
5093
|
}
|
|
5087
5094
|
break;
|
|
5088
5095
|
}
|
|
5096
|
+
if (compactionPending && lastTotalTokenUsage && total < lastTotalTokenUsage.total) {
|
|
5097
|
+
const lastUsage = lastTokenUsageFromPayload(payload);
|
|
5098
|
+
if (lastUsage) {
|
|
5099
|
+
events.push(withBackfillRefs(baseCodexEvent({
|
|
5100
|
+
ts,
|
|
5101
|
+
type: "model.usage",
|
|
5102
|
+
sessionId,
|
|
5103
|
+
turnId: currentTurnId,
|
|
5104
|
+
cwd,
|
|
5105
|
+
project,
|
|
5106
|
+
model: rewriteCodexModelForTier(model, serviceTier),
|
|
5107
|
+
confidence: "partial",
|
|
5108
|
+
metrics: excludeForkInheritedCache({ ...lastUsage, reasoningEffort }, forkedSession)
|
|
5109
|
+
}), { filePath, sourcePathHash, lineNumber, topType, payloadType, options }));
|
|
5110
|
+
}
|
|
5111
|
+
lastTotalTokenUsage = { input, cached, output, reasoning, total };
|
|
5112
|
+
compactionPending = false;
|
|
5113
|
+
break;
|
|
5114
|
+
}
|
|
5115
|
+
compactionPending = false;
|
|
5089
5116
|
if (lastTotalTokenUsage && total >= lastTotalTokenUsage.total) {
|
|
5090
5117
|
const deltaInput = input - lastTotalTokenUsage.input;
|
|
5091
5118
|
const deltaCached = cached - lastTotalTokenUsage.cached;
|
|
@@ -5102,7 +5129,7 @@ async function parseCodexSessionFile(filePath, options) {
|
|
|
5102
5129
|
project,
|
|
5103
5130
|
model: rewriteCodexModelForTier(model, serviceTier),
|
|
5104
5131
|
confidence: "partial",
|
|
5105
|
-
metrics: {
|
|
5132
|
+
metrics: excludeForkInheritedCache({
|
|
5106
5133
|
tokensInput: deltaInput > 0 ? deltaInput : void 0,
|
|
5107
5134
|
tokensCachedInput: deltaCached > 0 ? deltaCached : void 0,
|
|
5108
5135
|
tokensOutput: deltaOutput > 0 ? deltaOutput : void 0,
|
|
@@ -5110,7 +5137,7 @@ async function parseCodexSessionFile(filePath, options) {
|
|
|
5110
5137
|
tokensTotal: deltaTotal > 0 ? deltaTotal : void 0,
|
|
5111
5138
|
modelContextWindow: usage.modelContextWindow,
|
|
5112
5139
|
reasoningEffort
|
|
5113
|
-
}
|
|
5140
|
+
}, forkedSession)
|
|
5114
5141
|
}), { filePath, sourcePathHash, lineNumber, topType, payloadType, options }));
|
|
5115
5142
|
}
|
|
5116
5143
|
} else {
|
|
@@ -5123,7 +5150,7 @@ async function parseCodexSessionFile(filePath, options) {
|
|
|
5123
5150
|
project,
|
|
5124
5151
|
model: rewriteCodexModelForTier(model, serviceTier),
|
|
5125
5152
|
confidence: "partial",
|
|
5126
|
-
metrics: {
|
|
5153
|
+
metrics: excludeForkInheritedCache({
|
|
5127
5154
|
tokensInput: input,
|
|
5128
5155
|
tokensCachedInput: cached,
|
|
5129
5156
|
tokensOutput: output,
|
|
@@ -5131,7 +5158,7 @@ async function parseCodexSessionFile(filePath, options) {
|
|
|
5131
5158
|
tokensTotal: total,
|
|
5132
5159
|
modelContextWindow: usage.modelContextWindow,
|
|
5133
5160
|
reasoningEffort
|
|
5134
|
-
}
|
|
5161
|
+
}, forkedSession)
|
|
5135
5162
|
}), { filePath, sourcePathHash, lineNumber, topType, payloadType, options }));
|
|
5136
5163
|
}
|
|
5137
5164
|
lastTotalTokenUsage = { input, cached, output, reasoning, total };
|
|
@@ -5389,6 +5416,13 @@ function tokenUsageFromPayload(payload) {
|
|
|
5389
5416
|
const info = objectField(payload, "info");
|
|
5390
5417
|
const totalUsage = objectField(info, "total_token_usage");
|
|
5391
5418
|
const usage = Object.keys(totalUsage).length > 0 ? totalUsage : objectField(info, "last_token_usage");
|
|
5419
|
+
return tokenUsageFromRecord(usage, info);
|
|
5420
|
+
}
|
|
5421
|
+
function lastTokenUsageFromPayload(payload) {
|
|
5422
|
+
const info = objectField(payload, "info");
|
|
5423
|
+
return tokenUsageFromRecord(objectField(info, "last_token_usage"), info);
|
|
5424
|
+
}
|
|
5425
|
+
function tokenUsageFromRecord(usage, info) {
|
|
5392
5426
|
if (Object.keys(usage).length === 0) {
|
|
5393
5427
|
return;
|
|
5394
5428
|
}
|
|
@@ -5410,6 +5444,18 @@ function tokenUsageFromPayload(payload) {
|
|
|
5410
5444
|
modelContextWindow: numberField(info, "model_context_window")
|
|
5411
5445
|
};
|
|
5412
5446
|
}
|
|
5447
|
+
function excludeForkInheritedCache(usage, forked) {
|
|
5448
|
+
if (!forked || !usage) {
|
|
5449
|
+
return usage;
|
|
5450
|
+
}
|
|
5451
|
+
const cached = usage.tokensCachedInput ?? 0;
|
|
5452
|
+
return {
|
|
5453
|
+
...usage,
|
|
5454
|
+
tokensInput: Math.max(0, (usage.tokensInput ?? 0) - cached) || void 0,
|
|
5455
|
+
tokensCachedInput: void 0,
|
|
5456
|
+
tokensTotal: Math.max(0, (usage.tokensTotal ?? 0) - cached) || void 0
|
|
5457
|
+
};
|
|
5458
|
+
}
|
|
5413
5459
|
function toolNameFromPayload(payload, payloadType) {
|
|
5414
5460
|
if (payloadType === "web_search_call") {
|
|
5415
5461
|
return "web_search";
|
|
@@ -7390,11 +7436,13 @@ function parseQoderCnPaths(filePath) {
|
|
|
7390
7436
|
let sessionId = "";
|
|
7391
7437
|
let projectName = "";
|
|
7392
7438
|
let configDir2 = "";
|
|
7439
|
+
let mainTranscriptPath;
|
|
7393
7440
|
if (subagentsIdx > 2) {
|
|
7394
7441
|
sessionId = parts[subagentsIdx - 1];
|
|
7395
7442
|
projectName = parts[subagentsIdx - 2];
|
|
7396
7443
|
const projectsIdx = parts.lastIndexOf("projects");
|
|
7397
7444
|
configDir2 = parts.slice(0, projectsIdx).join(path16.sep);
|
|
7445
|
+
mainTranscriptPath = [...parts.slice(0, subagentsIdx - 1), `${sessionId}.jsonl`].join(path16.sep);
|
|
7398
7446
|
} else {
|
|
7399
7447
|
const filename = parts.at(-1) || "";
|
|
7400
7448
|
sessionId = path16.basename(filename, ".jsonl");
|
|
@@ -7402,7 +7450,24 @@ function parseQoderCnPaths(filePath) {
|
|
|
7402
7450
|
const projectsIdx = parts.lastIndexOf("projects");
|
|
7403
7451
|
configDir2 = parts.slice(0, projectsIdx).join(path16.sep);
|
|
7404
7452
|
}
|
|
7405
|
-
return { configDir: configDir2, projectName, sessionId };
|
|
7453
|
+
return { configDir: configDir2, projectName, sessionId, mainTranscriptPath };
|
|
7454
|
+
}
|
|
7455
|
+
function rebuildEventIdentity2(event) {
|
|
7456
|
+
const importKey = createImportKey([
|
|
7457
|
+
event.source,
|
|
7458
|
+
event.refs?.sourcePathHash,
|
|
7459
|
+
event.refs?.sourceLine,
|
|
7460
|
+
event.type,
|
|
7461
|
+
event.refs?.sourceId
|
|
7462
|
+
]);
|
|
7463
|
+
return {
|
|
7464
|
+
...event,
|
|
7465
|
+
id: createStableEventId(importKey),
|
|
7466
|
+
refs: {
|
|
7467
|
+
...event.refs,
|
|
7468
|
+
importKey
|
|
7469
|
+
}
|
|
7470
|
+
};
|
|
7406
7471
|
}
|
|
7407
7472
|
async function loadQoderCnModelNames(configDir2) {
|
|
7408
7473
|
try {
|
|
@@ -7752,9 +7817,17 @@ async function parseQoderCnSessionFile(filePath, options) {
|
|
|
7752
7817
|
}
|
|
7753
7818
|
const validEvents = state.events.filter((event) => validateCanonicalEvent(event).valid);
|
|
7754
7819
|
if (isSubagentSession) {
|
|
7755
|
-
const parentSessionId = parseQoderCnPaths(filePath)
|
|
7756
|
-
if (parentSessionId) {
|
|
7757
|
-
|
|
7820
|
+
const { sessionId: parentSessionId, mainTranscriptPath } = parseQoderCnPaths(filePath);
|
|
7821
|
+
if (parentSessionId && mainTranscriptPath) {
|
|
7822
|
+
const parentSourcePathHash = `sha256:${createStableHash(mainTranscriptPath)}`;
|
|
7823
|
+
return validEvents.map((event) => {
|
|
7824
|
+
const mapped = {
|
|
7825
|
+
...event,
|
|
7826
|
+
sessionId: parentSessionId,
|
|
7827
|
+
refs: { ...event.refs, sourcePathHash: parentSourcePathHash }
|
|
7828
|
+
};
|
|
7829
|
+
return rebuildEventIdentity2(mapped);
|
|
7830
|
+
});
|
|
7758
7831
|
}
|
|
7759
7832
|
}
|
|
7760
7833
|
return validEvents;
|
|
@@ -8133,11 +8206,13 @@ function parseQoderPaths(filePath) {
|
|
|
8133
8206
|
let sessionId = "";
|
|
8134
8207
|
let projectName = "";
|
|
8135
8208
|
let configDir2 = "";
|
|
8209
|
+
let mainTranscriptPath;
|
|
8136
8210
|
if (subagentsIdx > 2) {
|
|
8137
8211
|
sessionId = parts[subagentsIdx - 1];
|
|
8138
8212
|
projectName = parts[subagentsIdx - 2];
|
|
8139
8213
|
const projectsIdx = parts.lastIndexOf("projects");
|
|
8140
8214
|
configDir2 = parts.slice(0, projectsIdx).join(path17.sep);
|
|
8215
|
+
mainTranscriptPath = [...parts.slice(0, subagentsIdx - 1), `${sessionId}.jsonl`].join(path17.sep);
|
|
8141
8216
|
} else {
|
|
8142
8217
|
const filename = parts.at(-1) || "";
|
|
8143
8218
|
sessionId = path17.basename(filename, ".jsonl");
|
|
@@ -8145,7 +8220,24 @@ function parseQoderPaths(filePath) {
|
|
|
8145
8220
|
const projectsIdx = parts.lastIndexOf("projects");
|
|
8146
8221
|
configDir2 = parts.slice(0, projectsIdx).join(path17.sep);
|
|
8147
8222
|
}
|
|
8148
|
-
return { configDir: configDir2, projectName, sessionId };
|
|
8223
|
+
return { configDir: configDir2, projectName, sessionId, mainTranscriptPath };
|
|
8224
|
+
}
|
|
8225
|
+
function rebuildEventIdentity3(event) {
|
|
8226
|
+
const importKey = createImportKey([
|
|
8227
|
+
event.source,
|
|
8228
|
+
event.refs?.sourcePathHash,
|
|
8229
|
+
event.refs?.sourceLine,
|
|
8230
|
+
event.type,
|
|
8231
|
+
event.refs?.sourceId
|
|
8232
|
+
]);
|
|
8233
|
+
return {
|
|
8234
|
+
...event,
|
|
8235
|
+
id: createStableEventId(importKey),
|
|
8236
|
+
refs: {
|
|
8237
|
+
...event.refs,
|
|
8238
|
+
importKey
|
|
8239
|
+
}
|
|
8240
|
+
};
|
|
8149
8241
|
}
|
|
8150
8242
|
async function loadQoderModelNames(configDir2) {
|
|
8151
8243
|
try {
|
|
@@ -8495,9 +8587,17 @@ async function parseQoderSessionFile(filePath, options) {
|
|
|
8495
8587
|
}
|
|
8496
8588
|
const validEvents = state.events.filter((event) => validateCanonicalEvent(event).valid);
|
|
8497
8589
|
if (isSubagentSession) {
|
|
8498
|
-
const parentSessionId = parseQoderPaths(filePath)
|
|
8499
|
-
if (parentSessionId) {
|
|
8500
|
-
|
|
8590
|
+
const { sessionId: parentSessionId, mainTranscriptPath } = parseQoderPaths(filePath);
|
|
8591
|
+
if (parentSessionId && mainTranscriptPath) {
|
|
8592
|
+
const parentSourcePathHash = `sha256:${createStableHash(mainTranscriptPath)}`;
|
|
8593
|
+
return validEvents.map((event) => {
|
|
8594
|
+
const mapped = {
|
|
8595
|
+
...event,
|
|
8596
|
+
sessionId: parentSessionId,
|
|
8597
|
+
refs: { ...event.refs, sourcePathHash: parentSourcePathHash }
|
|
8598
|
+
};
|
|
8599
|
+
return rebuildEventIdentity3(mapped);
|
|
8600
|
+
});
|
|
8501
8601
|
}
|
|
8502
8602
|
}
|
|
8503
8603
|
return validEvents;
|
package/package.json
CHANGED