@krtclcdy/tersio 2.15.0 → 2.17.0

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.
@@ -50,6 +50,12 @@ export function appendUsage(kind, detail) {
50
50
  function zeroBreakdown() {
51
51
  return { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 };
52
52
  }
53
+ // Message-level generation time in ms. OMP writes `duration` (ms, float);
54
+ // codex token_count rows carry none. Non-positive/non-finite → undefined
55
+ // so renderers print – instead of a fake 0.0s.
56
+ function durOf(v) {
57
+ return typeof v === 'number' && Number.isFinite(v) && v > 0 ? v : undefined;
58
+ }
53
59
  function addInto(into, u) {
54
60
  for (const k of ['input', 'output', 'cacheRead', 'cacheWrite']) {
55
61
  const v = u[k];
@@ -118,8 +124,7 @@ export function importSessionTokens() {
118
124
  let codexProvider = null;
119
125
  const recent = [];
120
126
  // Rows from before the reset watermark (and rows with no usable timestamp,
121
- // which may predate it) stay out of every derived statistic.
122
- function ingest(model, usage, ts) {
127
+ function ingest(model, usage, ts, durMs) {
123
128
  const ms = ts === undefined ? NaN : typeof ts === 'number' ? ts : Date.parse(ts);
124
129
  if (watermark > 0 && (!Number.isFinite(ms) || ms < watermark))
125
130
  return false;
@@ -129,7 +134,7 @@ export function importSessionTokens() {
129
134
  byModelMessages[model] = (byModelMessages[model] ?? 0) + 1;
130
135
  const num = (v) => (typeof v === 'number' && Number.isFinite(v) && v > 0 ? Math.floor(v) : 0);
131
136
  if (Number.isFinite(ms))
132
- recent.push({ m: model, i: num(usage.input), o: num(usage.output), t: ms });
137
+ recent.push({ m: model, i: num(usage.input), o: num(usage.output), t: ms, d: durOf(durMs), cr: num(usage.cacheRead), cw: num(usage.cacheWrite) });
133
138
  const day = ts !== undefined ? dayKey(ts) : null;
134
139
  if (day) {
135
140
  byDay[day] ??= zeroBreakdown();
@@ -179,7 +184,7 @@ export function importSessionTokens() {
179
184
  if (!msg || msg.role !== 'assistant' || !msg.usage)
180
185
  continue;
181
186
  const model = typeof msg.model === 'string' && msg.model ? msg.model : 'unknown';
182
- const counted = ingest(model, msg.usage, row.timestamp);
187
+ const counted = ingest(model, msg.usage, row.timestamp, msg.duration);
183
188
  if (counted && typeof msg.usage.cost === 'number' && Number.isFinite(msg.usage.cost))
184
189
  costMeasured += msg.usage.cost;
185
190
  if (!counted)
@@ -222,9 +227,16 @@ export { co2GramsFor, energyWhFor };
222
227
  export function usdCost(t, model) {
223
228
  const { price, known } = model ? priceFor(model) : { price: DEFAULT_PRICE, known: false };
224
229
  const m = 1 / 1_000_000;
230
+ const buckets = {
231
+ input: t.input * price.input * m,
232
+ output: t.output * price.output * m,
233
+ cacheRead: t.cacheRead * price.cacheRead * m,
234
+ cacheWrite: t.cacheWrite * price.cacheWrite * m,
235
+ };
225
236
  return {
226
- usd: (t.input * price.input + t.output * price.output + t.cacheRead * price.cacheRead + t.cacheWrite * price.cacheWrite) * m,
237
+ usd: buckets.input + buckets.output + buckets.cacheRead + buckets.cacheWrite,
227
238
  priced: model ? known : false,
239
+ buckets,
228
240
  };
229
241
  }
230
242
  // CO2 now model-differentiated via ./carbon.ts (EcoLogits 0.8.2 port).
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@krtclcdy/tersio",
3
- "version": "2.15.0",
3
+ "version": "2.17.0",
4
4
  "description": "✂️ Token-saving OMP add-ons: terse Caveman replies, compact RTK shell output, lean Ponytail code calls — one-command combo presets.",
5
5
  "keywords": [
6
6
  "omp",