tokentracker-cli 0.96.4 → 0.97.2
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/README.de.md +3 -3
- package/README.ja.md +3 -3
- package/README.ko.md +3 -3
- package/README.md +7 -5
- package/README.zh-CN.md +3 -3
- package/dashboard/dist/assets/{AchievementBadge-CCcvmz6R.js → AchievementBadge-Bf2T612R.js} +1 -1
- package/dashboard/dist/assets/{AchievementsPage-C5jdktOK.js → AchievementsPage-CnkSNpJx.js} +2 -2
- package/dashboard/dist/assets/{AchievementsSection-BFMtUzn1.js → AchievementsSection-CPwsy04Y.js} +1 -1
- package/dashboard/dist/assets/{BadgeDetailModal-Be8gM7tM.js → BadgeDetailModal-BJBrgn24.js} +1 -1
- package/dashboard/dist/assets/{BotAnimated-CXTGR71z.js → BotAnimated-BJM20N9T.js} +1 -1
- package/dashboard/dist/assets/{Card-CsUsp3CV.js → Card-BRWOMoBk.js} +1 -1
- package/dashboard/dist/assets/{ClawdAnimated-BEjpZjEE.js → ClawdAnimated-CtX8cne4.js} +2 -2
- package/dashboard/dist/assets/{CommandPalette-CHc_Z1r8.js → CommandPalette-C8BwOnSn.js} +1 -1
- package/dashboard/dist/assets/{CommunityStatsModal-Gs6kZ_Mp.js → CommunityStatsModal-BGMbgSjq.js} +1 -1
- package/dashboard/dist/assets/{ConfirmModal-niHkpv2O.js → ConfirmModal-ZZXg_OLV.js} +1 -1
- package/dashboard/dist/assets/{Controls-X2Z1UNUx.js → Controls-VDvgw_ed.js} +1 -1
- package/dashboard/dist/assets/{DashboardPage-B66s3Exi.js → DashboardPage-BcJGzQWK.js} +1 -1
- package/dashboard/dist/assets/{DevicePage-DQdLdEI8.js → DevicePage-CP5m8azV.js} +1 -1
- package/dashboard/dist/assets/{DialogClose-CCUjTxl8.js → DialogClose-8pTCallP.js} +1 -1
- package/dashboard/dist/assets/DialogDescription-DRQEfAWH.js +1 -0
- package/dashboard/dist/assets/{DialogTitle-CgkUGAag.js → DialogTitle-BWYdq4TT.js} +1 -1
- package/dashboard/dist/assets/{FadeIn-D4QD1bPo.js → FadeIn-CEJfaKnL.js} +1 -1
- package/dashboard/dist/assets/{HeaderGithubStar-D0my-Z3a.js → HeaderGithubStar-Bg2vijF8.js} +1 -1
- package/dashboard/dist/assets/{HoverTooltip-nSWgrKlK.js → HoverTooltip-B03JQ3PO.js} +1 -1
- package/dashboard/dist/assets/{IpCheckPage-4hfqHAgi.js → IpCheckPage-DYZucBOf.js} +1 -1
- package/dashboard/dist/assets/{LandingPage-wIc4tVRI.js → LandingPage-m-byhnVx.js} +2 -2
- package/dashboard/dist/assets/{LeaderboardAvatar-DGlN8Vy8.js → LeaderboardAvatar-JtGhJC1s.js} +1 -1
- package/dashboard/dist/assets/{LeaderboardPage-CybuzE87.js → LeaderboardPage-vVDKFLhl.js} +2 -2
- package/dashboard/dist/assets/{LeaderboardProfileModal-D9la3tNd.js → LeaderboardProfileModal-Cm4DDrcY.js} +3 -3
- package/dashboard/dist/assets/{LeaderboardProfilePage-gxXSeJYb.js → LeaderboardProfilePage-bKbMm856.js} +1 -1
- package/dashboard/dist/assets/{LimitsPage-CZH3G54Y.js → LimitsPage-B271tZOj.js} +1 -1
- package/dashboard/dist/assets/{LocalOnlyNotice-Ckc7zohC.js → LocalOnlyNotice-DKIxuBP0.js} +1 -1
- package/dashboard/dist/assets/{LoginCard-BqeRHqWK.js → LoginCard-DA46RXDo.js} +1 -1
- package/dashboard/dist/assets/{LoginModal-BjH6aIBG.js → LoginModal-PxTgIoLk.js} +1 -1
- package/dashboard/dist/assets/{LoginPage-BOyPLNU3.js → LoginPage-uEUnU7NP.js} +1 -1
- package/dashboard/dist/assets/{PetPage-BXRXG40D.js → PetPage-DDPZtxMw.js} +1 -1
- package/dashboard/dist/assets/{PopoverPopup-Dad1ZYVd.js → PopoverPopup-DWIMb8D6.js} +1 -1
- package/dashboard/dist/assets/{ProviderIcon-BDmrNJSl.js → ProviderIcon-DqqwXu3b.js} +1 -1
- package/dashboard/dist/assets/{ResetPasswordPage-CZpE6qfa.js → ResetPasswordPage-BVuJTR9A.js} +1 -1
- package/dashboard/dist/assets/{SegmentedControl-CE1hrQFi.js → SegmentedControl-iHtWKWtc.js} +1 -1
- package/dashboard/dist/assets/{Select-YVj7u6Nv.js → Select-Cr9wq8mD.js} +1 -1
- package/dashboard/dist/assets/{SelectItemText-BMYGgQ3o.js → SelectItemText-BWnP4yuq.js} +1 -1
- package/dashboard/dist/assets/{ServiceStatusPage-HehjDbZg.js → ServiceStatusPage-DLuiUUYV.js} +1 -1
- package/dashboard/dist/assets/{SessionsPage-Chvu4YqZ.js → SessionsPage-CBAH4ieT.js} +1 -1
- package/dashboard/dist/assets/{SettingsPage-BXjS7u9_.js → SettingsPage-Djku-i8K.js} +2 -2
- package/dashboard/dist/assets/{SkillsPage-q3Rjlj9h.js → SkillsPage-DtBRoB8R.js} +1 -1
- package/dashboard/dist/assets/{TokenGalaxy-BqZyj82r.js → TokenGalaxy-nvyPu5eV.js} +1 -1
- package/dashboard/dist/assets/{ToolbarRootContext-Ch8ueI_C.js → ToolbarRootContext-DhpHv55w.js} +1 -1
- package/dashboard/dist/assets/{TrendMonitor-C2aTL9p1.js → TrendMonitor-CCzwGDst.js} +1 -1
- package/dashboard/dist/assets/{WidgetsPage-DYaIai8j.js → WidgetsPage-CcWCidAd.js} +1 -1
- package/dashboard/dist/assets/{WrappedPage-51B0v-Sr.js → WrappedPage-B6dn8eyh.js} +1 -1
- package/dashboard/dist/assets/__vite-browser-external-sJsF0ioo.js +45 -0
- package/dashboard/dist/assets/{agent-logos-DXrPSAdX.js → agent-logos-Dh2k8E_G.js} +1 -1
- package/dashboard/dist/assets/{arrow-up-right-BFkf7l0U.js → arrow-up-right-BLDQog1A.js} +1 -1
- package/dashboard/dist/assets/{check--N8wmgIJ.js → check-DNq_ySSn.js} +1 -1
- package/dashboard/dist/assets/{composite-zF5Pj94e.js → composite-CSBcryzA.js} +1 -1
- package/dashboard/dist/assets/{copy-BG0JMr6A.js → copy-DHRrNtRb.js} +1 -1
- package/dashboard/dist/assets/{download-CPFJf-Sf.js → download-CluyujgG.js} +1 -1
- package/dashboard/dist/assets/{external-link-D2yF0kgP.js → external-link-Cf12tdLf.js} +1 -1
- package/dashboard/dist/assets/{flame-l460AFx9.js → flame-CJEYinxo.js} +1 -1
- package/dashboard/dist/assets/{format-tokens-DKO4ljuH.js → format-tokens-CqiCmYtk.js} +1 -1
- package/dashboard/dist/assets/{icons-RoxRGkz4.js → icons-DD8OvYVG.js} +1 -1
- package/dashboard/dist/assets/{index--ouT5L4N.js → index-21lDN4rA.js} +1 -1
- package/dashboard/dist/assets/{index-PTJ4368-.js → index-Cm8jn8Va.js} +1 -1
- package/dashboard/dist/assets/{index-DhyLCvvv.js → index-DLLivlEh.js} +1 -1
- package/dashboard/dist/assets/{info-DNWMO4Ca.js → info-dv3Y0z8Q.js} +1 -1
- package/dashboard/dist/assets/{link-2-DzWXAz1h.js → link-2-CWHBxVuk.js} +1 -1
- package/dashboard/dist/assets/{loader-circle-BzGMqXNu.js → loader-circle-9l5p9Dwa.js} +1 -1
- package/dashboard/dist/assets/{maximize-2-Dkpyk4x3.js → maximize-2-DQ2t3MJB.js} +1 -1
- package/dashboard/dist/assets/{modifiers.esm-lggHUQpW.js → modifiers.esm-Cwj0l9Zb.js} +1 -1
- package/dashboard/dist/assets/{monitor-smartphone-Ck0-gz9l.js → monitor-smartphone-B-9at3iV.js} +1 -1
- package/dashboard/dist/assets/{plus-qTJpnn43.js → plus-C_CTQjDD.js} +1 -1
- package/dashboard/dist/assets/{provider-display-psY26qmp.js → provider-display-XJQod7k9.js} +2 -2
- package/dashboard/dist/assets/{react-CYS24KmX.js → react-xH4nkyuj.js} +1 -1
- package/dashboard/dist/assets/{search-CUzE6zxr.js → search-Ut41Fw1G.js} +1 -1
- package/dashboard/dist/assets/{skills-api-D9SzxPFG.js → skills-api-B7lb1cjO.js} +1 -1
- package/dashboard/dist/assets/{sortable.esm-Bl2hAUyR.js → sortable.esm-BUPRsWL6.js} +1 -1
- package/dashboard/dist/assets/{store-mHSJAJtE.js → store-DneqOW0h.js} +1 -1
- package/dashboard/dist/assets/{terminal-BlQNEvn1.js → terminal-DPQyZyHR.js} +1 -1
- package/dashboard/dist/assets/{trash-CHdgmOyk.js → trash-CVdV1bBR.js} +1 -1
- package/dashboard/dist/assets/{use-community-stats-DUiCs91N.js → use-community-stats-DB98TGn9.js} +1 -1
- package/dashboard/dist/assets/{use-latest-request-guard-ehXfkvuU.js → use-latest-request-guard-DK3KulKx.js} +1 -1
- package/dashboard/dist/assets/{use-limits-display-prefs-CcwwQ0Fq.js → use-limits-display-prefs-BACCRUMZ.js} +1 -1
- package/dashboard/dist/assets/{use-ordered-list-CCOtI3Wa.js → use-ordered-list-DnKFdI9a.js} +1 -1
- package/dashboard/dist/assets/use-reduced-motion-BfdrKOsS.js +1 -0
- package/dashboard/dist/assets/{use-session-efficiency-pref-CYRDpcc_.js → use-session-efficiency-pref-BTm6RoSm.js} +1 -1
- package/dashboard/dist/assets/{use-transform-btLlTJpj.js → use-transform-DweC2iKa.js} +1 -1
- package/dashboard/dist/assets/{use-usage-limits-BGr5sR-c.js → use-usage-limits-CN5xWIBs.js} +1 -1
- package/dashboard/dist/assets/{useCurrency-CNutuEKd.js → useCurrency-CFjvWawL.js} +1 -1
- package/dashboard/dist/assets/{useTokenFormat-C0bAJFMC.js → useTokenFormat-Cf81HqWi.js} +1 -1
- package/dashboard/dist/assets/{zap-B2fbyjbc.js → zap-Vx_j5oJN.js} +1 -1
- package/dashboard/dist/index.html +13 -11
- package/dashboard/dist/ip-check.html +1 -1
- package/dashboard/dist/leaderboard.html +1 -1
- package/dashboard/dist/llms.txt +3 -2
- package/dashboard/dist/share.html +1 -1
- package/package.json +2 -2
- package/src/commands/init.js +1 -0
- package/src/commands/status.js +13 -0
- package/src/commands/sync.js +46 -0
- package/src/lib/codex-rollout-parser.js +48 -1
- package/src/lib/codex-service-tier.js +49 -0
- package/src/lib/pricing/curated-overrides.json +2 -1
- package/src/lib/pricing/index.js +68 -4
- package/src/lib/pricing/seed-snapshot.json +1 -1
- package/src/lib/rollout.js +283 -34
- package/src/lib/session-analytics.js +11 -0
- package/dashboard/dist/assets/DialogDescription-CjMjYG3N.js +0 -1
- package/dashboard/dist/assets/__vite-browser-external-Cp7dNuCm.js +0 -45
- package/dashboard/dist/assets/use-reduced-motion-CDlahPqe.js +0 -1
package/src/lib/rollout.js
CHANGED
|
@@ -21,6 +21,11 @@ const {
|
|
|
21
21
|
currentCodexModel,
|
|
22
22
|
snapshotCodexModelAttributionState,
|
|
23
23
|
} = require("./codex-model-attribution");
|
|
24
|
+
const {
|
|
25
|
+
CODEX_SERVICE_TIER_MARKER,
|
|
26
|
+
readCodexServiceTier,
|
|
27
|
+
isPriorityServiceTier,
|
|
28
|
+
} = require("./codex-service-tier");
|
|
24
29
|
const {
|
|
25
30
|
DEVIN_TABLE_PROBE_SQL,
|
|
26
31
|
devinUsageSql,
|
|
@@ -471,6 +476,7 @@ async function parseRolloutIncremental({
|
|
|
471
476
|
? prev.tokenUsageBaselines || null
|
|
472
477
|
: null;
|
|
473
478
|
const lastModel = sameInode && !truncated ? prev.lastModel || null : null;
|
|
479
|
+
const lastServiceTier = sameInode && !truncated ? prev.lastServiceTier || null : null;
|
|
474
480
|
const modelAttributionState = sameInode && !truncated
|
|
475
481
|
? prev.modelAttributionState || null
|
|
476
482
|
: null;
|
|
@@ -551,6 +557,7 @@ async function parseRolloutIncremental({
|
|
|
551
557
|
lastTotal,
|
|
552
558
|
tokenUsageBaselines,
|
|
553
559
|
lastModel,
|
|
560
|
+
lastServiceTier,
|
|
554
561
|
modelAttributionState,
|
|
555
562
|
projectState,
|
|
556
563
|
projectMetaCache,
|
|
@@ -566,6 +573,7 @@ async function parseRolloutIncremental({
|
|
|
566
573
|
lastTotal,
|
|
567
574
|
tokenUsageBaselines,
|
|
568
575
|
lastModel,
|
|
576
|
+
lastServiceTier,
|
|
569
577
|
modelAttributionState,
|
|
570
578
|
hourlyState,
|
|
571
579
|
touchedBuckets,
|
|
@@ -589,6 +597,7 @@ async function parseRolloutIncremental({
|
|
|
589
597
|
lastTotal: result.lastTotal,
|
|
590
598
|
tokenUsageBaselines: result.tokenUsageBaselines,
|
|
591
599
|
lastModel: result.lastModel,
|
|
600
|
+
lastServiceTier: result.lastServiceTier || null,
|
|
592
601
|
modelAttributionState: result.modelAttributionState,
|
|
593
602
|
updatedAt: new Date().toISOString(),
|
|
594
603
|
};
|
|
@@ -2060,6 +2069,7 @@ async function parseRolloutFile({
|
|
|
2060
2069
|
lastTotal,
|
|
2061
2070
|
tokenUsageBaselines,
|
|
2062
2071
|
lastModel,
|
|
2072
|
+
lastServiceTier,
|
|
2063
2073
|
modelAttributionState: previousModelAttributionState,
|
|
2064
2074
|
hourlyState,
|
|
2065
2075
|
touchedBuckets,
|
|
@@ -2086,6 +2096,7 @@ async function parseRolloutFile({
|
|
|
2086
2096
|
lastTotal,
|
|
2087
2097
|
tokenUsageBaselines,
|
|
2088
2098
|
lastModel,
|
|
2099
|
+
lastServiceTier: typeof lastServiceTier === "string" ? lastServiceTier : null,
|
|
2089
2100
|
modelAttributionState: previousModelAttributionState,
|
|
2090
2101
|
eventsAggregated: 0,
|
|
2091
2102
|
projectFileContexts,
|
|
@@ -2098,6 +2109,12 @@ async function parseRolloutFile({
|
|
|
2098
2109
|
});
|
|
2099
2110
|
|
|
2100
2111
|
let model = typeof lastModel === "string" ? lastModel : null;
|
|
2112
|
+
// Codex writes thread_settings_applied before the turn_context of the turn it
|
|
2113
|
+
// takes effect on, and token_count rows carry no turn id, so a row's tier is
|
|
2114
|
+
// whatever the last such record said. A session's first turn has none, and
|
|
2115
|
+
// most CLI sessions have none at all — that stays null, and null is billed at
|
|
2116
|
+
// Standard rather than guessed from the current config.
|
|
2117
|
+
let serviceTier = typeof lastServiceTier === "string" ? lastServiceTier : null;
|
|
2101
2118
|
const modelAttributionState = createCodexModelAttributionState(
|
|
2102
2119
|
previousModelAttributionState || { model },
|
|
2103
2120
|
);
|
|
@@ -2148,7 +2165,10 @@ async function parseRolloutFile({
|
|
|
2148
2165
|
line.includes('"cwd"') ||
|
|
2149
2166
|
line.includes('"current_date"') ||
|
|
2150
2167
|
line.includes('"forked_from_id"'));
|
|
2151
|
-
|
|
2168
|
+
const maybeServiceTier =
|
|
2169
|
+
!maybeTokenCount && !maybeModelReroute && !maybeTurnContext &&
|
|
2170
|
+
line.includes(CODEX_SERVICE_TIER_MARKER);
|
|
2171
|
+
if (!maybeTokenCount && !maybeTurnContext && !maybeModelReroute && !maybeServiceTier) {
|
|
2152
2172
|
if (invalidRecordPolicy === "throw" || !record.terminated) {
|
|
2153
2173
|
try {
|
|
2154
2174
|
JSON.parse(line);
|
|
@@ -2174,6 +2194,12 @@ async function parseRolloutFile({
|
|
|
2174
2194
|
applyCodexModelEvent(modelAttributionState, obj);
|
|
2175
2195
|
model = currentCodexModel(modelAttributionState) || model;
|
|
2176
2196
|
|
|
2197
|
+
const appliedServiceTier = readCodexServiceTier(obj);
|
|
2198
|
+
if (appliedServiceTier) {
|
|
2199
|
+
serviceTier = appliedServiceTier;
|
|
2200
|
+
continue;
|
|
2201
|
+
}
|
|
2202
|
+
|
|
2177
2203
|
if (
|
|
2178
2204
|
(obj?.type === "turn_context" || obj?.type === "session_meta") &&
|
|
2179
2205
|
obj?.payload &&
|
|
@@ -2301,6 +2327,9 @@ async function parseRolloutFile({
|
|
|
2301
2327
|
|
|
2302
2328
|
const bucket = getHourlyBucket(hourlyState, source, model, bucketStart);
|
|
2303
2329
|
addTotals(bucket.totals, delta);
|
|
2330
|
+
// Only the model bucket gets the subset: the project bucket below carries
|
|
2331
|
+
// no model, so no per-model rate can be applied to it anyway.
|
|
2332
|
+
if (isPriorityServiceTier(serviceTier)) addPriorityUsage(bucket.totals, delta);
|
|
2304
2333
|
touchedBuckets.add(bucketKey(source, model, bucketStart));
|
|
2305
2334
|
if (currentProjectKey && projectState && projectTouchedBuckets) {
|
|
2306
2335
|
const projectBucket = getProjectBucket(
|
|
@@ -2321,6 +2350,7 @@ async function parseRolloutFile({
|
|
|
2321
2350
|
lastTotal: latestTotal,
|
|
2322
2351
|
tokenUsageBaselines: snapshotUsageBaselines(usageDeltaState),
|
|
2323
2352
|
lastModel: model,
|
|
2353
|
+
lastServiceTier: serviceTier,
|
|
2324
2354
|
modelAttributionState: snapshotCodexModelAttributionState(modelAttributionState),
|
|
2325
2355
|
eventsAggregated,
|
|
2326
2356
|
projectFileContexts,
|
|
@@ -2333,6 +2363,7 @@ async function scanRolloutProjectFileContexts({
|
|
|
2333
2363
|
lastTotal,
|
|
2334
2364
|
tokenUsageBaselines,
|
|
2335
2365
|
lastModel,
|
|
2366
|
+
lastServiceTier,
|
|
2336
2367
|
modelAttributionState,
|
|
2337
2368
|
projectState,
|
|
2338
2369
|
projectMetaCache,
|
|
@@ -2351,6 +2382,7 @@ async function scanRolloutProjectFileContexts({
|
|
|
2351
2382
|
lastTotal,
|
|
2352
2383
|
tokenUsageBaselines,
|
|
2353
2384
|
lastModel,
|
|
2385
|
+
lastServiceTier: lastServiceTier || null,
|
|
2354
2386
|
modelAttributionState,
|
|
2355
2387
|
eventsAggregated: 0,
|
|
2356
2388
|
projectFileContexts,
|
|
@@ -2428,6 +2460,7 @@ async function scanRolloutProjectFileContexts({
|
|
|
2428
2460
|
lastTotal,
|
|
2429
2461
|
tokenUsageBaselines,
|
|
2430
2462
|
lastModel,
|
|
2463
|
+
lastServiceTier: lastServiceTier || null,
|
|
2431
2464
|
modelAttributionState,
|
|
2432
2465
|
eventsAggregated: 0,
|
|
2433
2466
|
projectFileContexts,
|
|
@@ -3003,6 +3036,7 @@ async function enqueueTouchedBuckets({ queuePath, hourlyState, touchedBuckets })
|
|
|
3003
3036
|
billable_total_tokens: totals.billable_total_tokens ?? totals.total_tokens,
|
|
3004
3037
|
total_cost_usd: totals.total_cost_usd || 0,
|
|
3005
3038
|
usage_precision: usagePrecision || undefined,
|
|
3039
|
+
...prioritySubsetOf(totals),
|
|
3006
3040
|
conversation_count: totals.conversation_count,
|
|
3007
3041
|
}),
|
|
3008
3042
|
);
|
|
@@ -3083,6 +3117,7 @@ async function enqueueTouchedBuckets({ queuePath, hourlyState, touchedBuckets })
|
|
|
3083
3117
|
billable_total_tokens: unknownBucket.totals.billable_total_tokens ?? unknownBucket.totals.total_tokens,
|
|
3084
3118
|
total_cost_usd: unknownBucket.totals.total_cost_usd || 0,
|
|
3085
3119
|
usage_precision: usagePrecision || undefined,
|
|
3120
|
+
...prioritySubsetOf(unknownBucket.totals),
|
|
3086
3121
|
conversation_count: unknownBucket.totals.conversation_count,
|
|
3087
3122
|
}),
|
|
3088
3123
|
);
|
|
@@ -3131,6 +3166,7 @@ async function enqueueTouchedBuckets({ queuePath, hourlyState, touchedBuckets })
|
|
|
3131
3166
|
total_tokens: group.totals.total_tokens,
|
|
3132
3167
|
billable_total_tokens: group.totals.billable_total_tokens ?? group.totals.total_tokens,
|
|
3133
3168
|
total_cost_usd: group.totals.total_cost_usd || 0,
|
|
3169
|
+
...prioritySubsetOf(group.totals),
|
|
3134
3170
|
conversation_count: group.totals.conversation_count,
|
|
3135
3171
|
}),
|
|
3136
3172
|
);
|
|
@@ -3716,7 +3752,43 @@ function initTotals() {
|
|
|
3716
3752
|
};
|
|
3717
3753
|
}
|
|
3718
3754
|
|
|
3755
|
+
// Observed-subset markers, same shape as the session sidecar's
|
|
3756
|
+
// long_context_* columns: "how much of the columns above came from requests on
|
|
3757
|
+
// the priority (Astra Fast) service tier". They annotate the existing columns
|
|
3758
|
+
// and are NEVER part of any sum — total_tokens stays
|
|
3759
|
+
// input + output + cache_creation + cache_read + reasoning_output. They are
|
|
3760
|
+
// omitted entirely when zero so no other provider's queue rows change.
|
|
3761
|
+
const PRIORITY_SUBSET_FIELDS = [
|
|
3762
|
+
["priority_input_tokens", "input_tokens"],
|
|
3763
|
+
["priority_cached_input_tokens", "cached_input_tokens"],
|
|
3764
|
+
["priority_cache_creation_input_tokens", "cache_creation_input_tokens"],
|
|
3765
|
+
["priority_output_tokens", "output_tokens"],
|
|
3766
|
+
["priority_reasoning_output_tokens", "reasoning_output_tokens"],
|
|
3767
|
+
];
|
|
3768
|
+
|
|
3769
|
+
// The whole delta belongs to a priority request, so every base column it
|
|
3770
|
+
// carries is priority usage.
|
|
3771
|
+
function addPriorityUsage(target, delta) {
|
|
3772
|
+
for (const [field, base] of PRIORITY_SUBSET_FIELDS) {
|
|
3773
|
+
const value = Number(delta?.[base] || 0);
|
|
3774
|
+
if (value > 0) target[field] = (Number(target[field]) || 0) + value;
|
|
3775
|
+
}
|
|
3776
|
+
}
|
|
3777
|
+
|
|
3778
|
+
function prioritySubsetOf(totals) {
|
|
3779
|
+
const subset = {};
|
|
3780
|
+
for (const [field] of PRIORITY_SUBSET_FIELDS) {
|
|
3781
|
+
const value = Number(totals?.[field]) || 0;
|
|
3782
|
+
if (value > 0) subset[field] = value;
|
|
3783
|
+
}
|
|
3784
|
+
return subset;
|
|
3785
|
+
}
|
|
3786
|
+
|
|
3719
3787
|
function addTotals(target, delta) {
|
|
3788
|
+
for (const [field] of PRIORITY_SUBSET_FIELDS) {
|
|
3789
|
+
const value = Number(delta?.[field]) || 0;
|
|
3790
|
+
if (value > 0) target[field] = (Number(target[field]) || 0) + value;
|
|
3791
|
+
}
|
|
3720
3792
|
target.input_tokens += delta.input_tokens || 0;
|
|
3721
3793
|
target.cached_input_tokens += delta.cached_input_tokens || 0;
|
|
3722
3794
|
target.cache_creation_input_tokens += delta.cache_creation_input_tokens || 0;
|
|
@@ -3731,6 +3803,11 @@ function addTotals(target, delta) {
|
|
|
3731
3803
|
}
|
|
3732
3804
|
|
|
3733
3805
|
function subtractTotals(target, totals) {
|
|
3806
|
+
for (const [field] of PRIORITY_SUBSET_FIELDS) {
|
|
3807
|
+
const current = Number(target[field]) || 0;
|
|
3808
|
+
if (current <= 0) continue;
|
|
3809
|
+
target[field] = Math.max(0, current - (Number(totals?.[field]) || 0));
|
|
3810
|
+
}
|
|
3734
3811
|
target.input_tokens = Math.max(0, target.input_tokens - (totals.input_tokens || 0));
|
|
3735
3812
|
target.cached_input_tokens = Math.max(
|
|
3736
3813
|
0,
|
|
@@ -3764,7 +3841,7 @@ function subtractTotals(target, totals) {
|
|
|
3764
3841
|
}
|
|
3765
3842
|
|
|
3766
3843
|
function totalsKey(totals) {
|
|
3767
|
-
|
|
3844
|
+
const base = [
|
|
3768
3845
|
totals.input_tokens || 0,
|
|
3769
3846
|
totals.cached_input_tokens || 0,
|
|
3770
3847
|
totals.cache_creation_input_tokens || 0,
|
|
@@ -3775,6 +3852,10 @@ function totalsKey(totals) {
|
|
|
3775
3852
|
totals.total_cost_usd || 0,
|
|
3776
3853
|
totals.conversation_count || 0,
|
|
3777
3854
|
].join("|");
|
|
3855
|
+
// Appended only when a priority subset exists, so buckets that never see the
|
|
3856
|
+
// tier keep their previously persisted queuedKey and are not re-enqueued.
|
|
3857
|
+
const priority = PRIORITY_SUBSET_FIELDS.map(([field]) => Number(totals[field]) || 0);
|
|
3858
|
+
return priority.some((value) => value > 0) ? `${base}|p:${priority.join(",")}` : base;
|
|
3778
3859
|
}
|
|
3779
3860
|
|
|
3780
3861
|
function toUtcHalfHourStart(ts) {
|
|
@@ -10815,8 +10896,10 @@ function resolveOmpAgentDir(env = process.env) {
|
|
|
10815
10896
|
return ompHome ? path.join(ompHome, "agent") : null;
|
|
10816
10897
|
}
|
|
10817
10898
|
|
|
10818
|
-
|
|
10819
|
-
|
|
10899
|
+
// Session-file discovery is shared with OmO (omo), which persists the exact
|
|
10900
|
+
// same on-disk layout under its own agent dir:
|
|
10901
|
+
// <agentDir>/sessions/--<cwd-encoded>--/<timestamp>_<sessionId>.jsonl
|
|
10902
|
+
function collectPiStyleSessionFiles(agentDir) {
|
|
10820
10903
|
if (!agentDir) return [];
|
|
10821
10904
|
const sessionsDir = path.join(agentDir, "sessions");
|
|
10822
10905
|
if (!fssync.existsSync(sessionsDir)) return [];
|
|
@@ -10841,6 +10924,10 @@ function resolveOmpSessionFiles(env = process.env) {
|
|
|
10841
10924
|
return files;
|
|
10842
10925
|
}
|
|
10843
10926
|
|
|
10927
|
+
function resolveOmpSessionFiles(env = process.env) {
|
|
10928
|
+
return collectPiStyleSessionFiles(resolveOmpAgentDir(env));
|
|
10929
|
+
}
|
|
10930
|
+
|
|
10844
10931
|
// Subagent transcripts live in a directory named after the session file:
|
|
10845
10932
|
// ~/.omp/agent/sessions/<cwd>/<session>.jsonl (main agent)
|
|
10846
10933
|
// ~/.omp/agent/sessions/<cwd>/<session>/<Agent>.jsonl (task subagent)
|
|
@@ -10849,8 +10936,8 @@ function resolveOmpSessionFiles(env = process.env) {
|
|
|
10849
10936
|
// rel path <= 2 segments → main, deeper → subagent/advisor), so we mirror
|
|
10850
10937
|
// that: everything below the cwd level is subagent traffic. Session dirs also
|
|
10851
10938
|
// hold non-JSONL artefacts (*.bash-original.log, *.md) — skipped by extension.
|
|
10852
|
-
|
|
10853
|
-
|
|
10939
|
+
// OmO nests the same way, so it reuses this walker.
|
|
10940
|
+
function collectPiStyleSubagentFiles(agentDir) {
|
|
10854
10941
|
if (!agentDir) return [];
|
|
10855
10942
|
const sessionsDir = path.join(agentDir, "sessions");
|
|
10856
10943
|
if (!fssync.existsSync(sessionsDir)) return [];
|
|
@@ -10898,20 +10985,24 @@ function resolveOmpSubagentFiles(env = process.env) {
|
|
|
10898
10985
|
return files;
|
|
10899
10986
|
}
|
|
10900
10987
|
|
|
10988
|
+
function resolveOmpSubagentFiles(env = process.env) {
|
|
10989
|
+
return collectPiStyleSubagentFiles(resolveOmpAgentDir(env));
|
|
10990
|
+
}
|
|
10991
|
+
|
|
10901
10992
|
function resolveOmpDefaultModel() {
|
|
10902
10993
|
// oh-my-pi has no global default model setting; model is per-message.
|
|
10903
10994
|
return "omp-unknown";
|
|
10904
10995
|
}
|
|
10905
10996
|
|
|
10906
|
-
const
|
|
10997
|
+
const PI_STYLE_HEADER_SCAN_MAX_BYTES = 65536;
|
|
10907
10998
|
|
|
10908
|
-
async function
|
|
10999
|
+
async function readPiStyleSessionCwd(filePath) {
|
|
10909
11000
|
let stream;
|
|
10910
11001
|
try {
|
|
10911
11002
|
stream = fssync.createReadStream(filePath, {
|
|
10912
11003
|
encoding: "utf8",
|
|
10913
11004
|
start: 0,
|
|
10914
|
-
end:
|
|
11005
|
+
end: PI_STYLE_HEADER_SCAN_MAX_BYTES,
|
|
10915
11006
|
});
|
|
10916
11007
|
} catch {
|
|
10917
11008
|
return null;
|
|
@@ -10932,6 +11023,95 @@ async function resolveOmpFileCwd(filePath) {
|
|
|
10932
11023
|
return null;
|
|
10933
11024
|
}
|
|
10934
11025
|
|
|
11026
|
+
async function resolveOmpFileCwd(filePath) {
|
|
11027
|
+
return readPiStyleSessionCwd(filePath);
|
|
11028
|
+
}
|
|
11029
|
+
|
|
11030
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
11031
|
+
// OmO (omo) — passive JSONL reader (~/.omo/agent/sessions/**/*.jsonl)
|
|
11032
|
+
//
|
|
11033
|
+
// OmO shares oh-my-pi's session persistence format, so it reuses the same
|
|
11034
|
+
// collectors and parser. Layout:
|
|
11035
|
+
// ~/.omo/agent/sessions/--<cwd-encoded>--/<timestamp>_<sessionId>.jsonl
|
|
11036
|
+
//
|
|
11037
|
+
// First line is the type:"session" header (carries the real, unencoded cwd).
|
|
11038
|
+
// Only type:"message" lines with message.role=="assistant" carry usage:
|
|
11039
|
+
//
|
|
11040
|
+
// {
|
|
11041
|
+
// "type": "message",
|
|
11042
|
+
// "id": "7ae3734f", ← 8-char dedup key
|
|
11043
|
+
// "timestamp": "2026-08-27T23:28:16.699Z",
|
|
11044
|
+
// "message": {
|
|
11045
|
+
// "role": "assistant",
|
|
11046
|
+
// "provider": "xai",
|
|
11047
|
+
// "model": "grok-4.6",
|
|
11048
|
+
// "usage": {
|
|
11049
|
+
// "input": 28646, "output": 630, "cacheRead": 512, "cacheWrite": 0,
|
|
11050
|
+
// "reasoning": 218, "totalTokens": 29788,
|
|
11051
|
+
// "cost": { ... } ← OmO's own estimate; ignored, we price it
|
|
11052
|
+
// },
|
|
11053
|
+
// "timestamp": 1787873284870 ← ms epoch, preferred for bucketing
|
|
11054
|
+
// }
|
|
11055
|
+
// }
|
|
11056
|
+
//
|
|
11057
|
+
// Two deliberate differences from oh-my-pi:
|
|
11058
|
+
// 1. The reasoning field is `reasoning`, not `reasoningTokens`.
|
|
11059
|
+
// 2. Reasoning is a SUBSET of `output`, and `totalTokens` excludes it —
|
|
11060
|
+
// verified across a 2,586-message corpus where
|
|
11061
|
+
// input+output+cacheRead+cacheWrite === totalTokens for every row, and
|
|
11062
|
+
// `usage.cost` bills no separate reasoning component. So omo follows the
|
|
11063
|
+
// Codex convention: reasoning_output_tokens is informational and must not
|
|
11064
|
+
// be billed on top of output (see computeRowCost in lib/pricing/index.js).
|
|
11065
|
+
//
|
|
11066
|
+
// OmO is a router — the upstream model name is recorded per message and there
|
|
11067
|
+
// is no global default (fallback: "omo-unknown").
|
|
11068
|
+
//
|
|
11069
|
+
// Path overrides are TokenTracker-only (TOKENTRACKER_OMO_AGENT_DIR /
|
|
11070
|
+
// TOKENTRACKER_OMO_HOME / OMO_HOME). PI_CONFIG_DIR and PI_CODING_AGENT_DIR are
|
|
11071
|
+
// deliberately NOT honored here: those belong to pi/omp, and routing them to a
|
|
11072
|
+
// third provider would reintroduce the ambiguity decidePiCodingAgentDirOwner
|
|
11073
|
+
// exists to resolve.
|
|
11074
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
11075
|
+
|
|
11076
|
+
function resolveOmoHome(env = process.env) {
|
|
11077
|
+
if (env.TOKENTRACKER_OMO_HOME) return expandHomePath(env.TOKENTRACKER_OMO_HOME, env);
|
|
11078
|
+
if (env.OMO_HOME) return expandHomePath(env.OMO_HOME, env);
|
|
11079
|
+
const home = env.HOME || require("node:os").homedir();
|
|
11080
|
+
if (process.platform === "win32") {
|
|
11081
|
+
return pickWin32ProviderPath({
|
|
11082
|
+
env,
|
|
11083
|
+
nativeValue: path.join(home, ".omo"),
|
|
11084
|
+
wslProviderDir: ".omo",
|
|
11085
|
+
});
|
|
11086
|
+
}
|
|
11087
|
+
return path.join(home, ".omo");
|
|
11088
|
+
}
|
|
11089
|
+
|
|
11090
|
+
function resolveOmoAgentDir(env = process.env) {
|
|
11091
|
+
if (env.TOKENTRACKER_OMO_AGENT_DIR) {
|
|
11092
|
+
return expandHomePath(env.TOKENTRACKER_OMO_AGENT_DIR, env);
|
|
11093
|
+
}
|
|
11094
|
+
const omoHome = resolveOmoHome(env);
|
|
11095
|
+
return omoHome ? path.join(omoHome, "agent") : null;
|
|
11096
|
+
}
|
|
11097
|
+
|
|
11098
|
+
function resolveOmoSessionFiles(env = process.env) {
|
|
11099
|
+
return collectPiStyleSessionFiles(resolveOmoAgentDir(env));
|
|
11100
|
+
}
|
|
11101
|
+
|
|
11102
|
+
function resolveOmoSubagentFiles(env = process.env) {
|
|
11103
|
+
return collectPiStyleSubagentFiles(resolveOmoAgentDir(env));
|
|
11104
|
+
}
|
|
11105
|
+
|
|
11106
|
+
function resolveOmoDefaultModel() {
|
|
11107
|
+
// OmO has no global default model setting; model is per-message.
|
|
11108
|
+
return "omo-unknown";
|
|
11109
|
+
}
|
|
11110
|
+
|
|
11111
|
+
async function resolveOmoFileCwd(filePath) {
|
|
11112
|
+
return readPiStyleSessionCwd(filePath);
|
|
11113
|
+
}
|
|
11114
|
+
|
|
10935
11115
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
10936
11116
|
// Kilo Code VS Code extension — passive reader for VS Code-family
|
|
10937
11117
|
// globalStorage/kilocode.kilo-code/tasks/<uuid>/ui_messages.json files.
|
|
@@ -14513,7 +14693,23 @@ async function parseKilocodeIncremental({
|
|
|
14513
14693
|
return { recordsProcessed, eventsAggregated, bucketsQueued };
|
|
14514
14694
|
}
|
|
14515
14695
|
|
|
14516
|
-
|
|
14696
|
+
// Reads the first present numeric field. oh-my-pi emits `reasoningTokens`;
|
|
14697
|
+
// OmO emits `reasoning`. Listing the accepted keys per provider keeps each
|
|
14698
|
+
// one's accounting exact instead of guessing across both spellings.
|
|
14699
|
+
function pickUsageInt(usage, fields) {
|
|
14700
|
+
for (const field of fields) {
|
|
14701
|
+
const raw = usage?.[field];
|
|
14702
|
+
if (raw == null) continue;
|
|
14703
|
+
const value = Number(raw);
|
|
14704
|
+
if (Number.isFinite(value)) return toNonNegativeInt(value);
|
|
14705
|
+
}
|
|
14706
|
+
return 0;
|
|
14707
|
+
}
|
|
14708
|
+
|
|
14709
|
+
// Shared implementation for the oh-my-pi session format. omp and omo both
|
|
14710
|
+
// persist it verbatim, so they differ only in where the sessions live, which
|
|
14711
|
+
// cursor namespace they own, and how reasoning tokens are spelled.
|
|
14712
|
+
async function parseOmpLikeIncremental({
|
|
14517
14713
|
sessionFiles,
|
|
14518
14714
|
subagentFiles,
|
|
14519
14715
|
cursors,
|
|
@@ -14523,41 +14719,50 @@ async function parseOmpIncremental({
|
|
|
14523
14719
|
onProgress,
|
|
14524
14720
|
env,
|
|
14525
14721
|
defaultModel,
|
|
14722
|
+
stateKey,
|
|
14723
|
+
source,
|
|
14724
|
+
resolveSessionFiles,
|
|
14725
|
+
resolveSubagentFiles,
|
|
14726
|
+
resolveDefaultModel,
|
|
14727
|
+
resolveFileCwd,
|
|
14728
|
+
reasoningFields,
|
|
14729
|
+
reasoningIncludedInOutput = false,
|
|
14526
14730
|
} = {}) {
|
|
14527
14731
|
await ensureDir(path.dirname(queuePath));
|
|
14528
14732
|
const projectEnabled = typeof projectQueuePath === "string" && projectQueuePath.length > 0;
|
|
14529
|
-
const
|
|
14530
|
-
|
|
14733
|
+
const providerState =
|
|
14734
|
+
cursors[stateKey] && typeof cursors[stateKey] === "object" ? cursors[stateKey] : {};
|
|
14735
|
+
const seenIds = new Set(Array.isArray(providerState.seenIds) ? providerState.seenIds : []);
|
|
14531
14736
|
const projectSeenIds = new Set(
|
|
14532
|
-
Array.isArray(
|
|
14737
|
+
Array.isArray(providerState.projectSeenIds) ? providerState.projectSeenIds : [],
|
|
14533
14738
|
);
|
|
14534
14739
|
const fileOffsets =
|
|
14535
|
-
|
|
14536
|
-
? { ...
|
|
14740
|
+
providerState.fileOffsets && typeof providerState.fileOffsets === "object"
|
|
14741
|
+
? { ...providerState.fileOffsets }
|
|
14537
14742
|
: {};
|
|
14538
14743
|
const projectFileOffsets =
|
|
14539
|
-
|
|
14540
|
-
? { ...
|
|
14744
|
+
providerState.projectFileOffsets && typeof providerState.projectFileOffsets === "object"
|
|
14745
|
+
? { ...providerState.projectFileOffsets }
|
|
14541
14746
|
: {};
|
|
14542
14747
|
|
|
14543
14748
|
const mainFiles = Array.isArray(sessionFiles)
|
|
14544
14749
|
? sessionFiles
|
|
14545
|
-
:
|
|
14750
|
+
: resolveSessionFiles(env || process.env);
|
|
14546
14751
|
// Subagent transcripts share the session format and count toward the same
|
|
14547
|
-
//
|
|
14752
|
+
// provider totals; they're discovered separately because they nest below the
|
|
14548
14753
|
// cwd level. When the caller supplies explicit sessionFiles (tests), don't
|
|
14549
14754
|
// auto-resolve — keep the parse hermetic.
|
|
14550
14755
|
const subFiles = Array.isArray(subagentFiles)
|
|
14551
14756
|
? subagentFiles
|
|
14552
14757
|
: Array.isArray(sessionFiles)
|
|
14553
14758
|
? []
|
|
14554
|
-
:
|
|
14759
|
+
: resolveSubagentFiles(env || process.env);
|
|
14555
14760
|
const files = [...mainFiles, ...subFiles];
|
|
14556
|
-
const fallbackModel = defaultModel ||
|
|
14761
|
+
const fallbackModel = defaultModel || resolveDefaultModel();
|
|
14557
14762
|
|
|
14558
14763
|
if (files.length === 0) {
|
|
14559
|
-
cursors
|
|
14560
|
-
...
|
|
14764
|
+
cursors[stateKey] = {
|
|
14765
|
+
...providerState,
|
|
14561
14766
|
seenIds: Array.from(seenIds),
|
|
14562
14767
|
fileOffsets,
|
|
14563
14768
|
...(projectEnabled
|
|
@@ -14635,7 +14840,7 @@ async function parseOmpIncremental({
|
|
|
14635
14840
|
const output = toNonNegativeInt(usage.output);
|
|
14636
14841
|
const cacheRead = toNonNegativeInt(usage.cacheRead);
|
|
14637
14842
|
const cacheWrite = toNonNegativeInt(usage.cacheWrite);
|
|
14638
|
-
const reasoningTokens =
|
|
14843
|
+
const reasoningTokens = pickUsageInt(usage, reasoningFields);
|
|
14639
14844
|
|
|
14640
14845
|
if (
|
|
14641
14846
|
input === 0 &&
|
|
@@ -14668,10 +14873,12 @@ async function parseOmpIncremental({
|
|
|
14668
14873
|
if (!bucketStart) continue;
|
|
14669
14874
|
|
|
14670
14875
|
// Use provided totalTokens when available; otherwise sum all components.
|
|
14876
|
+
// OmO folds reasoning into output, so the fallback must not add it again.
|
|
14671
14877
|
const totalTokens =
|
|
14672
14878
|
Number.isFinite(Number(usage.totalTokens)) && Number(usage.totalTokens) > 0
|
|
14673
14879
|
? toNonNegativeInt(usage.totalTokens)
|
|
14674
|
-
: input + output + cacheRead + cacheWrite +
|
|
14880
|
+
: input + output + cacheRead + cacheWrite +
|
|
14881
|
+
(reasoningIncludedInOutput ? 0 : reasoningTokens);
|
|
14675
14882
|
|
|
14676
14883
|
const model = normalizeModelInput(msg.model) || fallbackModel;
|
|
14677
14884
|
|
|
@@ -14685,9 +14892,9 @@ async function parseOmpIncremental({
|
|
|
14685
14892
|
conversation_count: 1,
|
|
14686
14893
|
};
|
|
14687
14894
|
|
|
14688
|
-
const bucket = getHourlyBucket(hourlyState,
|
|
14895
|
+
const bucket = getHourlyBucket(hourlyState, source, model, bucketStart);
|
|
14689
14896
|
addTotals(bucket.totals, delta);
|
|
14690
|
-
touchedBuckets.add(bucketKey(
|
|
14897
|
+
touchedBuckets.add(bucketKey(source, model, bucketStart));
|
|
14691
14898
|
seenIds.add(entryId);
|
|
14692
14899
|
eventsAggregated++;
|
|
14693
14900
|
|
|
@@ -14728,7 +14935,7 @@ async function parseOmpIncremental({
|
|
|
14728
14935
|
const startOffset = stat.size < prevSize || inodeChanged ? 0 : prevSize;
|
|
14729
14936
|
if (stat.size <= startOffset) continue;
|
|
14730
14937
|
|
|
14731
|
-
const cwd = await
|
|
14938
|
+
const cwd = await resolveFileCwd(filePath);
|
|
14732
14939
|
const projectContext = cwd
|
|
14733
14940
|
? await resolveProjectContextForPath({
|
|
14734
14941
|
startDir: wsl.mapWslCwdToUnc(cwd, filePath),
|
|
@@ -14767,7 +14974,7 @@ async function parseOmpIncremental({
|
|
|
14767
14974
|
const output = toNonNegativeInt(usage.output);
|
|
14768
14975
|
const cacheRead = toNonNegativeInt(usage.cacheRead);
|
|
14769
14976
|
const cacheWrite = toNonNegativeInt(usage.cacheWrite);
|
|
14770
|
-
const reasoningTokens =
|
|
14977
|
+
const reasoningTokens = pickUsageInt(usage, reasoningFields);
|
|
14771
14978
|
if (
|
|
14772
14979
|
input === 0 &&
|
|
14773
14980
|
output === 0 &&
|
|
@@ -14797,7 +15004,8 @@ async function parseOmpIncremental({
|
|
|
14797
15004
|
const totalTokens =
|
|
14798
15005
|
Number.isFinite(Number(usage.totalTokens)) && Number(usage.totalTokens) > 0
|
|
14799
15006
|
? toNonNegativeInt(usage.totalTokens)
|
|
14800
|
-
: input + output + cacheRead + cacheWrite +
|
|
15007
|
+
: input + output + cacheRead + cacheWrite +
|
|
15008
|
+
(reasoningIncludedInOutput ? 0 : reasoningTokens);
|
|
14801
15009
|
const delta = {
|
|
14802
15010
|
input_tokens: input,
|
|
14803
15011
|
cached_input_tokens: cacheRead,
|
|
@@ -14810,12 +15018,12 @@ async function parseOmpIncremental({
|
|
|
14810
15018
|
const projectBucket = getProjectBucket(
|
|
14811
15019
|
projectState,
|
|
14812
15020
|
projectKey,
|
|
14813
|
-
|
|
15021
|
+
source,
|
|
14814
15022
|
bucketStart,
|
|
14815
15023
|
projectRef,
|
|
14816
15024
|
);
|
|
14817
15025
|
addTotals(projectBucket.totals, delta);
|
|
14818
|
-
projectTouchedBuckets.add(projectBucketKey(projectKey,
|
|
15026
|
+
projectTouchedBuckets.add(projectBucketKey(projectKey, source, bucketStart));
|
|
14819
15027
|
projectSeenIds.add(entryId);
|
|
14820
15028
|
}
|
|
14821
15029
|
}
|
|
@@ -14860,8 +15068,8 @@ async function parseOmpIncremental({
|
|
|
14860
15068
|
projectState.updatedAt = updatedAt;
|
|
14861
15069
|
cursors.projectHourly = projectState;
|
|
14862
15070
|
}
|
|
14863
|
-
cursors
|
|
14864
|
-
...
|
|
15071
|
+
cursors[stateKey] = {
|
|
15072
|
+
...providerState,
|
|
14865
15073
|
seenIds: cappedSeen,
|
|
14866
15074
|
fileOffsets,
|
|
14867
15075
|
...(projectEnabled
|
|
@@ -14876,6 +15084,33 @@ async function parseOmpIncremental({
|
|
|
14876
15084
|
return { recordsProcessed, eventsAggregated, bucketsQueued, projectBucketsQueued };
|
|
14877
15085
|
}
|
|
14878
15086
|
|
|
15087
|
+
async function parseOmpIncremental(options = {}) {
|
|
15088
|
+
return parseOmpLikeIncremental({
|
|
15089
|
+
...options,
|
|
15090
|
+
stateKey: "omp",
|
|
15091
|
+
source: "omp",
|
|
15092
|
+
resolveSessionFiles: resolveOmpSessionFiles,
|
|
15093
|
+
resolveSubagentFiles: resolveOmpSubagentFiles,
|
|
15094
|
+
resolveDefaultModel: resolveOmpDefaultModel,
|
|
15095
|
+
resolveFileCwd: resolveOmpFileCwd,
|
|
15096
|
+
reasoningFields: ["reasoningTokens"],
|
|
15097
|
+
});
|
|
15098
|
+
}
|
|
15099
|
+
|
|
15100
|
+
async function parseOmoIncremental(options = {}) {
|
|
15101
|
+
return parseOmpLikeIncremental({
|
|
15102
|
+
...options,
|
|
15103
|
+
stateKey: "omo",
|
|
15104
|
+
source: "omo",
|
|
15105
|
+
resolveSessionFiles: resolveOmoSessionFiles,
|
|
15106
|
+
resolveSubagentFiles: resolveOmoSubagentFiles,
|
|
15107
|
+
resolveDefaultModel: resolveOmoDefaultModel,
|
|
15108
|
+
resolveFileCwd: resolveOmoFileCwd,
|
|
15109
|
+
reasoningFields: ["reasoningTokens", "reasoning"],
|
|
15110
|
+
reasoningIncludedInOutput: true,
|
|
15111
|
+
});
|
|
15112
|
+
}
|
|
15113
|
+
|
|
14879
15114
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
14880
15115
|
// pi (@mariozechner/pi-coding-agent) — passive JSONL reader
|
|
14881
15116
|
// (~/.pi/agent/sessions/**/*.jsonl)
|
|
@@ -14926,6 +15161,13 @@ function piAgentDirCollidesWithOmp(env = process.env) {
|
|
|
14926
15161
|
return path.resolve(piAgentDir) === path.resolve(ompAgentDir);
|
|
14927
15162
|
}
|
|
14928
15163
|
|
|
15164
|
+
function omoAgentDirCollidesWithOmp(env = process.env) {
|
|
15165
|
+
const omoAgentDir = resolveOmoAgentDir(env);
|
|
15166
|
+
const ompAgentDir = resolveOmpAgentDir(env);
|
|
15167
|
+
if (!omoAgentDir || !ompAgentDir) return false;
|
|
15168
|
+
return path.resolve(omoAgentDir) === path.resolve(ompAgentDir);
|
|
15169
|
+
}
|
|
15170
|
+
|
|
14929
15171
|
function resolvePiSessionFiles(env = process.env) {
|
|
14930
15172
|
const agentDir = resolvePiAgentDir(env);
|
|
14931
15173
|
if (!agentDir) return [];
|
|
@@ -21692,6 +21934,12 @@ module.exports = {
|
|
|
21692
21934
|
resolveOmpSubagentFiles,
|
|
21693
21935
|
resolveOmpDefaultModel,
|
|
21694
21936
|
parseOmpIncremental,
|
|
21937
|
+
resolveOmoHome,
|
|
21938
|
+
resolveOmoAgentDir,
|
|
21939
|
+
resolveOmoSessionFiles,
|
|
21940
|
+
resolveOmoSubagentFiles,
|
|
21941
|
+
resolveOmoDefaultModel,
|
|
21942
|
+
parseOmoIncremental,
|
|
21695
21943
|
resolveKilocodeRoots,
|
|
21696
21944
|
resolveKilocodeTaskFiles,
|
|
21697
21945
|
normalizeKilocodeProviderToModel,
|
|
@@ -21745,6 +21993,7 @@ module.exports = {
|
|
|
21745
21993
|
resolvePiDefaultModel,
|
|
21746
21994
|
parsePiIncremental,
|
|
21747
21995
|
piAgentDirCollidesWithOmp,
|
|
21996
|
+
omoAgentDirCollidesWithOmp,
|
|
21748
21997
|
resolvePrimeAgentHome,
|
|
21749
21998
|
resolvePrimeAgentDir,
|
|
21750
21999
|
resolvePrimeAgentSessionFiles,
|
|
@@ -131,9 +131,20 @@ const MODEL_USAGE_SUM_FIELDS = [
|
|
|
131
131
|
"long_context_cache_creation_input_tokens",
|
|
132
132
|
"long_context_output_tokens",
|
|
133
133
|
"long_context_reasoning_output_tokens",
|
|
134
|
+
"priority_input_tokens",
|
|
135
|
+
"priority_cached_input_tokens",
|
|
136
|
+
"priority_cache_creation_input_tokens",
|
|
137
|
+
"priority_output_tokens",
|
|
138
|
+
"priority_reasoning_output_tokens",
|
|
139
|
+
"priority_long_context_input_tokens",
|
|
140
|
+
"priority_long_context_cached_input_tokens",
|
|
141
|
+
"priority_long_context_cache_creation_input_tokens",
|
|
142
|
+
"priority_long_context_output_tokens",
|
|
143
|
+
"priority_long_context_reasoning_output_tokens",
|
|
134
144
|
"usage_events",
|
|
135
145
|
"rerouted_usage_events",
|
|
136
146
|
"long_context_usage_events",
|
|
147
|
+
"priority_usage_events",
|
|
137
148
|
// Not a token counter: an edit turn is a turn, and turn_context both marks
|
|
138
149
|
// where a turn begins and names its model, so an edit turn has exactly one
|
|
139
150
|
// owner. Splitting it here keeps by_model.tokens_per_edit a ratio over one
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{r as n,v as a}from"./__vite-browser-external-Cp7dNuCm.js";import{u as p}from"./DialogTitle-CgkUGAag.js";import{u as c}from"./composite-zF5Pj94e.js";const x=n.forwardRef(function(e,r){const{render:l,className:u,style:m,id:s,...t}=e,i=p(),o=c(s);return i.useSyncedValueWithCleanup("descriptionElementId",o),a("p",e,{ref:r,props:[{id:o},t]})});export{x as D};
|