@yhong91/vibetime 0.1.27 → 0.1.28
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 +123 -60
- 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.28" : "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;
|
|
@@ -4894,7 +4894,8 @@ async function parseCodexSessionFile(filePath, options) {
|
|
|
4894
4894
|
let lastTurnIdForComplete;
|
|
4895
4895
|
let turnIdAtLastUserMessage;
|
|
4896
4896
|
let sessionMetaLocked = false;
|
|
4897
|
-
let
|
|
4897
|
+
let lastTotalTokenUsage;
|
|
4898
|
+
let lastPerCallUsageKey;
|
|
4898
4899
|
const pendingToolCalls = /* @__PURE__ */ new Map();
|
|
4899
4900
|
for (const [index, line] of lines.entries()) {
|
|
4900
4901
|
const lineNumber = index + 1;
|
|
@@ -5042,32 +5043,79 @@ async function parseCodexSessionFile(filePath, options) {
|
|
|
5042
5043
|
}
|
|
5043
5044
|
const usage = tokenUsageFromPayload(payload);
|
|
5044
5045
|
if (usage) {
|
|
5045
|
-
const
|
|
5046
|
-
const
|
|
5047
|
-
|
|
5048
|
-
|
|
5049
|
-
|
|
5050
|
-
|
|
5051
|
-
|
|
5052
|
-
|
|
5053
|
-
|
|
5046
|
+
const input = usage.tokensInput ?? 0;
|
|
5047
|
+
const cached = usage.tokensCachedInput ?? 0;
|
|
5048
|
+
const output = usage.tokensOutput ?? 0;
|
|
5049
|
+
const reasoning = usage.tokensReasoningOutput ?? 0;
|
|
5050
|
+
const total = usage.tokensTotal ?? 0;
|
|
5051
|
+
const hasCumulativeUsage = Object.keys(objectField(info, "total_token_usage")).length > 0;
|
|
5052
|
+
const usageKey = [input, cached, output, reasoning, total].join(":");
|
|
5053
|
+
if (!hasCumulativeUsage) {
|
|
5054
|
+
if (usageKey !== lastPerCallUsageKey) {
|
|
5055
|
+
events.push(withBackfillRefs(baseCodexEvent({
|
|
5056
|
+
ts,
|
|
5057
|
+
type: "model.usage",
|
|
5058
|
+
sessionId,
|
|
5059
|
+
turnId: currentTurnId,
|
|
5060
|
+
cwd,
|
|
5061
|
+
project,
|
|
5062
|
+
model: rewriteCodexModelForTier(model, serviceTier),
|
|
5063
|
+
confidence: "partial",
|
|
5064
|
+
metrics: usage
|
|
5065
|
+
}), { filePath, sourcePathHash, lineNumber, topType, payloadType, options }));
|
|
5066
|
+
lastPerCallUsageKey = usageKey;
|
|
5067
|
+
}
|
|
5054
5068
|
break;
|
|
5055
5069
|
}
|
|
5056
|
-
|
|
5057
|
-
|
|
5058
|
-
|
|
5059
|
-
|
|
5060
|
-
|
|
5061
|
-
|
|
5062
|
-
|
|
5063
|
-
|
|
5064
|
-
|
|
5065
|
-
|
|
5066
|
-
|
|
5067
|
-
|
|
5068
|
-
|
|
5069
|
-
|
|
5070
|
-
|
|
5070
|
+
if (lastTotalTokenUsage && total >= lastTotalTokenUsage.total) {
|
|
5071
|
+
const deltaInput = input - lastTotalTokenUsage.input;
|
|
5072
|
+
const deltaCached = cached - lastTotalTokenUsage.cached;
|
|
5073
|
+
const deltaOutput = output - lastTotalTokenUsage.output;
|
|
5074
|
+
const deltaReasoning = reasoning - lastTotalTokenUsage.reasoning;
|
|
5075
|
+
const deltaTotal = total - lastTotalTokenUsage.total;
|
|
5076
|
+
if (deltaInput > 0 || deltaOutput > 0 || deltaTotal > 0) {
|
|
5077
|
+
events.push(withBackfillRefs(baseCodexEvent({
|
|
5078
|
+
ts,
|
|
5079
|
+
type: "model.usage",
|
|
5080
|
+
sessionId,
|
|
5081
|
+
turnId: currentTurnId,
|
|
5082
|
+
cwd,
|
|
5083
|
+
project,
|
|
5084
|
+
model: rewriteCodexModelForTier(model, serviceTier),
|
|
5085
|
+
confidence: "partial",
|
|
5086
|
+
metrics: {
|
|
5087
|
+
tokensInput: deltaInput > 0 ? deltaInput : void 0,
|
|
5088
|
+
tokensCachedInput: deltaCached > 0 ? deltaCached : void 0,
|
|
5089
|
+
tokensOutput: deltaOutput > 0 ? deltaOutput : void 0,
|
|
5090
|
+
tokensReasoningOutput: deltaReasoning > 0 ? deltaReasoning : void 0,
|
|
5091
|
+
tokensTotal: deltaTotal > 0 ? deltaTotal : void 0,
|
|
5092
|
+
modelContextWindow: usage.modelContextWindow,
|
|
5093
|
+
reasoningEffort
|
|
5094
|
+
}
|
|
5095
|
+
}), { filePath, sourcePathHash, lineNumber, topType, payloadType, options }));
|
|
5096
|
+
}
|
|
5097
|
+
} else {
|
|
5098
|
+
events.push(withBackfillRefs(baseCodexEvent({
|
|
5099
|
+
ts,
|
|
5100
|
+
type: "model.usage",
|
|
5101
|
+
sessionId,
|
|
5102
|
+
turnId: currentTurnId,
|
|
5103
|
+
cwd,
|
|
5104
|
+
project,
|
|
5105
|
+
model: rewriteCodexModelForTier(model, serviceTier),
|
|
5106
|
+
confidence: "partial",
|
|
5107
|
+
metrics: {
|
|
5108
|
+
tokensInput: input,
|
|
5109
|
+
tokensCachedInput: cached,
|
|
5110
|
+
tokensOutput: output,
|
|
5111
|
+
tokensReasoningOutput: reasoning,
|
|
5112
|
+
tokensTotal: total,
|
|
5113
|
+
modelContextWindow: usage.modelContextWindow,
|
|
5114
|
+
reasoningEffort
|
|
5115
|
+
}
|
|
5116
|
+
}), { filePath, sourcePathHash, lineNumber, topType, payloadType, options }));
|
|
5117
|
+
}
|
|
5118
|
+
lastTotalTokenUsage = { input, cached, output, reasoning, total };
|
|
5071
5119
|
}
|
|
5072
5120
|
break;
|
|
5073
5121
|
}
|
|
@@ -5284,7 +5332,7 @@ function headlessCodexUsage(raw) {
|
|
|
5284
5332
|
const cached = numberField(usage, "cached_input_tokens") ?? numberField(usage, "cache_read_input_tokens") ?? numberField(usage, "cached_tokens") ?? 0;
|
|
5285
5333
|
const reasoning = numberField(usage, "reasoning_output_tokens") ?? numberField(usage, "reasoning_tokens") ?? 0;
|
|
5286
5334
|
const totalField = numberField(usage, "total_tokens");
|
|
5287
|
-
const total = totalField !== void 0 && (totalField > 0 || input + output
|
|
5335
|
+
const total = totalField !== void 0 && (totalField > 0 || input + output === 0) ? totalField : input + output;
|
|
5288
5336
|
if (input === 0 && cached === 0 && output === 0 && reasoning === 0 && total === 0) {
|
|
5289
5337
|
return;
|
|
5290
5338
|
}
|
|
@@ -5293,7 +5341,7 @@ function headlessCodexUsage(raw) {
|
|
|
5293
5341
|
tokensCachedInput: cached || void 0,
|
|
5294
5342
|
tokensOutput: output || void 0,
|
|
5295
5343
|
tokensReasoningOutput: reasoning || void 0,
|
|
5296
|
-
tokensTotal: total,
|
|
5344
|
+
tokensTotal: total || void 0,
|
|
5297
5345
|
modelCalls: 1
|
|
5298
5346
|
};
|
|
5299
5347
|
}
|
|
@@ -5320,16 +5368,26 @@ function headlessCodexTimestamp(raw) {
|
|
|
5320
5368
|
}
|
|
5321
5369
|
function tokenUsageFromPayload(payload) {
|
|
5322
5370
|
const info = objectField(payload, "info");
|
|
5323
|
-
const
|
|
5371
|
+
const totalUsage = objectField(info, "total_token_usage");
|
|
5372
|
+
const usage = Object.keys(totalUsage).length > 0 ? totalUsage : objectField(info, "last_token_usage");
|
|
5324
5373
|
if (Object.keys(usage).length === 0) {
|
|
5325
5374
|
return;
|
|
5326
5375
|
}
|
|
5376
|
+
const input = numberField(usage, "input_tokens") ?? 0;
|
|
5377
|
+
const cached = numberField(usage, "cached_input_tokens") ?? 0;
|
|
5378
|
+
const output = numberField(usage, "output_tokens") ?? 0;
|
|
5379
|
+
const reasoning = numberField(usage, "reasoning_output_tokens") ?? 0;
|
|
5380
|
+
const totalField = numberField(usage, "total_tokens");
|
|
5381
|
+
const total = totalField !== void 0 && (totalField > 0 || input + output === 0) ? totalField : input + output;
|
|
5382
|
+
if (input === 0 && cached === 0 && output === 0 && reasoning === 0 && total === 0) {
|
|
5383
|
+
return;
|
|
5384
|
+
}
|
|
5327
5385
|
return {
|
|
5328
|
-
tokensInput:
|
|
5329
|
-
tokensCachedInput:
|
|
5330
|
-
tokensOutput:
|
|
5331
|
-
tokensReasoningOutput:
|
|
5332
|
-
tokensTotal:
|
|
5386
|
+
tokensInput: input || void 0,
|
|
5387
|
+
tokensCachedInput: cached || void 0,
|
|
5388
|
+
tokensOutput: output || void 0,
|
|
5389
|
+
tokensReasoningOutput: reasoning || void 0,
|
|
5390
|
+
tokensTotal: total || void 0,
|
|
5333
5391
|
modelContextWindow: numberField(info, "model_context_window")
|
|
5334
5392
|
};
|
|
5335
5393
|
}
|
|
@@ -5666,8 +5724,7 @@ async function parseCopilotSessionFile(filePath, options) {
|
|
|
5666
5724
|
const cacheReadTokens = numberField(usage, "cacheReadTokens") || 0;
|
|
5667
5725
|
const cacheWriteTokens = numberField(usage, "cacheWriteTokens") || 0;
|
|
5668
5726
|
const reasoningTokens = numberField(usage, "reasoningTokens") || 0;
|
|
5669
|
-
const
|
|
5670
|
-
const total = totalInput + outputTokens + reasoningTokens;
|
|
5727
|
+
const total = inputTokens + outputTokens;
|
|
5671
5728
|
if (total <= 0) {
|
|
5672
5729
|
continue;
|
|
5673
5730
|
}
|
|
@@ -5682,7 +5739,7 @@ async function parseCopilotSessionFile(filePath, options) {
|
|
|
5682
5739
|
model: modelName,
|
|
5683
5740
|
confidence: "exact",
|
|
5684
5741
|
metrics: {
|
|
5685
|
-
tokensInput:
|
|
5742
|
+
tokensInput: inputTokens || void 0,
|
|
5686
5743
|
tokensOutput: outputTokens || void 0,
|
|
5687
5744
|
tokensCachedInput: cacheReadTokens + cacheWriteTokens || void 0,
|
|
5688
5745
|
tokensCacheReadInput: cacheReadTokens || void 0,
|
|
@@ -6199,20 +6256,15 @@ async function loadToolInputsFromUpdates(updatesPath) {
|
|
|
6199
6256
|
return map;
|
|
6200
6257
|
}
|
|
6201
6258
|
function metricsFromSignals(signals) {
|
|
6202
|
-
const contextTokens = numberField(signals, "contextTokensUsed");
|
|
6203
6259
|
const toolCallCount = numberField(signals, "toolCallCount");
|
|
6204
6260
|
const turnCount = numberField(signals, "turnCount");
|
|
6205
6261
|
const durationSec = numberField(signals, "sessionDurationSeconds");
|
|
6206
6262
|
const linesAdded = numberField(signals, "agentLinesAdded");
|
|
6207
6263
|
const linesRemoved = numberField(signals, "agentLinesRemoved");
|
|
6208
|
-
if (
|
|
6264
|
+
if (toolCallCount === void 0 && turnCount === void 0 && durationSec === void 0) {
|
|
6209
6265
|
return void 0;
|
|
6210
6266
|
}
|
|
6211
6267
|
const metrics = {};
|
|
6212
|
-
if (contextTokens !== void 0 && contextTokens > 0) {
|
|
6213
|
-
metrics.tokensTotal = contextTokens;
|
|
6214
|
-
metrics.tokensInput = contextTokens;
|
|
6215
|
-
}
|
|
6216
6268
|
if (toolCallCount !== void 0) {
|
|
6217
6269
|
metrics.toolCalls = toolCallCount;
|
|
6218
6270
|
}
|
|
@@ -6651,13 +6703,14 @@ function opencodeUsageFromInfo(info) {
|
|
|
6651
6703
|
const cacheRead = Math.max(0, numberField(cache, "read") || 0);
|
|
6652
6704
|
const cacheWrite = Math.max(0, numberField(cache, "write") || 0);
|
|
6653
6705
|
const totalInput = input + cacheRead + cacheWrite;
|
|
6654
|
-
const
|
|
6706
|
+
const totalOutput = output + reasoning;
|
|
6707
|
+
const total = Math.max(0, numberField(tokensObj, "total") || totalInput + totalOutput);
|
|
6655
6708
|
if (total <= 0) {
|
|
6656
6709
|
return void 0;
|
|
6657
6710
|
}
|
|
6658
6711
|
return {
|
|
6659
6712
|
tokensInput: totalInput || void 0,
|
|
6660
|
-
tokensOutput:
|
|
6713
|
+
tokensOutput: totalOutput || void 0,
|
|
6661
6714
|
tokensReasoningOutput: reasoning || void 0,
|
|
6662
6715
|
tokensCachedInput: cacheRead + cacheWrite || void 0,
|
|
6663
6716
|
tokensCacheReadInput: cacheRead || void 0,
|
|
@@ -8825,28 +8878,29 @@ function workbuddyUsageMetrics(record) {
|
|
|
8825
8878
|
if (!input && !output && !total && !cacheRead && !cacheCreate && !reasoning) {
|
|
8826
8879
|
return void 0;
|
|
8827
8880
|
}
|
|
8881
|
+
const alignedTotal = total || input + output;
|
|
8828
8882
|
return {
|
|
8829
|
-
tokensInput: input,
|
|
8883
|
+
tokensInput: input || void 0,
|
|
8830
8884
|
tokensOutput: output,
|
|
8831
8885
|
tokensCachedInput: cacheRead + cacheCreate,
|
|
8832
8886
|
tokensCacheCreationInput: cacheCreate,
|
|
8833
8887
|
tokensCacheReadInput: cacheRead,
|
|
8834
8888
|
tokensReasoningOutput: reasoning,
|
|
8835
|
-
tokensTotal:
|
|
8889
|
+
tokensTotal: alignedTotal,
|
|
8836
8890
|
modelCalls: 1
|
|
8837
8891
|
};
|
|
8838
8892
|
}
|
|
8839
8893
|
function workbuddyCachedTokens(usage, rawUsage) {
|
|
8840
|
-
const rawCache = numberField(rawUsage, "cache_read_input_tokens") ?? numberField(rawUsage, "prompt_cache_hit_tokens") ?? numberField(rawUsage, "cached_tokens");
|
|
8841
|
-
if (rawCache !== void 0) {
|
|
8842
|
-
return rawCache;
|
|
8843
|
-
}
|
|
8844
8894
|
const details = usage.inputTokensDetails;
|
|
8845
|
-
if (Array.isArray(details) && isPlainObject(details[0])) {
|
|
8846
|
-
return numberField(details[0], "cached_tokens") || 0;
|
|
8847
|
-
}
|
|
8848
8895
|
const rawDetails = objectField(rawUsage, "prompt_tokens_details");
|
|
8849
|
-
return
|
|
8896
|
+
return Math.max(
|
|
8897
|
+
0,
|
|
8898
|
+
numberField(rawUsage, "cache_read_input_tokens") || 0,
|
|
8899
|
+
numberField(rawUsage, "prompt_cache_hit_tokens") || 0,
|
|
8900
|
+
numberField(rawUsage, "cached_tokens") || 0,
|
|
8901
|
+
Array.isArray(details) && isPlainObject(details[0]) ? numberField(details[0], "cached_tokens") || 0 : 0,
|
|
8902
|
+
numberField(rawDetails, "cached_tokens") || 0
|
|
8903
|
+
);
|
|
8850
8904
|
}
|
|
8851
8905
|
function workbuddyReasoningTokens(usage, rawUsage) {
|
|
8852
8906
|
const completionDetails = objectField(rawUsage, "completion_tokens_details");
|
|
@@ -9249,6 +9303,7 @@ async function readZCodeRows(dbPath) {
|
|
|
9249
9303
|
'reasoning_tokens',reasoning_tokens,
|
|
9250
9304
|
'cache_creation_input_tokens',cache_creation_input_tokens,
|
|
9251
9305
|
'cache_read_input_tokens',cache_read_input_tokens,
|
|
9306
|
+
'provider_total_tokens',provider_total_tokens,
|
|
9252
9307
|
'computed_total_tokens',computed_total_tokens,
|
|
9253
9308
|
'tool_call_count',tool_call_count
|
|
9254
9309
|
) from model_usage order by started_at, id;`,
|
|
@@ -9280,16 +9335,24 @@ function modelMetrics(row) {
|
|
|
9280
9335
|
const reasoning = numberField(row, "reasoning_tokens") || 0;
|
|
9281
9336
|
const cacheCreation = numberField(row, "cache_creation_input_tokens") || 0;
|
|
9282
9337
|
const cacheRead = numberField(row, "cache_read_input_tokens") || 0;
|
|
9283
|
-
const
|
|
9338
|
+
const cached = cacheCreation + cacheRead;
|
|
9339
|
+
const providerTotal = numberField(row, "provider_total_tokens");
|
|
9340
|
+
const computedTotal = numberField(row, "computed_total_tokens");
|
|
9341
|
+
const totalWithoutSeparateCache = input + output;
|
|
9342
|
+
const totalWithSeparateCache = input + cached + output;
|
|
9343
|
+
const comparisonTotal = providerTotal ?? computedTotal ?? 0;
|
|
9344
|
+
const cacheIsSeparate = comparisonTotal > 0 && Math.abs(comparisonTotal - totalWithSeparateCache) < Math.abs(comparisonTotal - totalWithoutSeparateCache);
|
|
9345
|
+
const alignedInput = input > 0 ? input + (cacheIsSeparate ? cached : 0) : cached;
|
|
9346
|
+
const alignedTotal = alignedInput + output;
|
|
9284
9347
|
const durationMs = numberField(row, "duration_ms");
|
|
9285
9348
|
return {
|
|
9286
|
-
tokensInput:
|
|
9349
|
+
tokensInput: alignedInput || void 0,
|
|
9287
9350
|
tokensOutput: output,
|
|
9288
9351
|
tokensReasoningOutput: reasoning,
|
|
9289
|
-
tokensCachedInput:
|
|
9352
|
+
tokensCachedInput: cached,
|
|
9290
9353
|
tokensCacheCreationInput: cacheCreation,
|
|
9291
9354
|
tokensCacheReadInput: cacheRead,
|
|
9292
|
-
tokensTotal:
|
|
9355
|
+
tokensTotal: alignedTotal,
|
|
9293
9356
|
modelDurationMs: durationMs,
|
|
9294
9357
|
durationMs,
|
|
9295
9358
|
modelCalls: 1,
|
|
@@ -10284,7 +10347,7 @@ function totalTokensFromEvent(event) {
|
|
|
10284
10347
|
if (typeof explicit === "number" && explicit > 0) {
|
|
10285
10348
|
return explicit;
|
|
10286
10349
|
}
|
|
10287
|
-
return Math.max(0, event.metrics?.tokensInput || 0) + Math.max(0, event.metrics?.tokensOutput || 0)
|
|
10350
|
+
return Math.max(0, event.metrics?.tokensInput || 0) + Math.max(0, event.metrics?.tokensOutput || 0);
|
|
10288
10351
|
}
|
|
10289
10352
|
function lineStatsFromEvent(event) {
|
|
10290
10353
|
const files = event.fileActivities || [];
|
package/package.json
CHANGED