@tmustier/pi-usage-extension 0.6.0 → 0.6.1

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/CHANGELOG.md CHANGED
@@ -1,5 +1,10 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.6.1] - 2026-07-17
4
+
5
+ ### Changed
6
+ - Graph lines are clipped to each series' active range (first to last bucket with usage). Applies to every grouping — provider, model, thinking level, `other`, and Total — so a model that starts late (e.g. reasoning tokens, only recorded since pi 0.80.3) or gets retired no longer draws a flat zero/flat cumulative tail across the whole period.
7
+
3
8
  ## [0.6.0] - 2026-07-17
4
9
 
5
10
  ### Added
package/README.md CHANGED
@@ -7,7 +7,7 @@ A Pi extension that displays aggregated usage statistics across all sessions.
7
7
  ## Compatibility
8
8
 
9
9
  - **Pi version:** 0.42.4+
10
- - **Last updated:** 2026-07-17 (0.6.0)
10
+ - **Last updated:** 2026-07-17 (0.6.1)
11
11
 
12
12
  ## Installation
13
13
 
@@ -76,8 +76,9 @@ The **Graphs** view plots usage over time for the active period as a braille lin
76
76
  - **Cumulative vs per-bucket** (`c` to toggle): running total across the period (default), or the raw per-bucket rate.
77
77
  - **Filtering**: move the legend cursor with `↑`/`↓` and toggle series visibility with `Enter`/`Space` (`a` shows all again). The y-axis rescales to the visible series — hide the big lines to zoom into the small ones.
78
78
  - **Buckets**: hourly for Today / This Week / Last Week, daily for Last 30 Days / All Time.
79
+ - **Line clipping**: every series (provider, model, thinking level, `other`, Total) is drawn only between its first and last bucket with usage, so late-starting or retired series don't drag a flat zero/flat tail across the whole period.
79
80
 
80
- Thinking levels are replayed from `thinking_level_change` entries in each session file; messages before the first recorded change appear as `unknown`. Reasoning token counts come from `usage.reasoning` where providers report them.
81
+ Thinking levels are replayed from `thinking_level_change` entries in each session file; messages before the first recorded change appear as `unknown`. Reasoning token counts come from `usage.reasoning` where providers report them; pi only records this field since **pi 0.80.3 (30 June 2026)**, so earlier sessions show zero reasoning tokens even though thinking models were in use.
81
82
 
82
83
  The insights currently shown:
83
84
 
package/graph.ts CHANGED
@@ -60,6 +60,10 @@ export interface GraphSeries {
60
60
  /** Period total for this series (not affected by cumulative). */
61
61
  total: number;
62
62
  hidden: boolean;
63
+ /** First bucket index with activity, or -1 when the series is empty. */
64
+ firstIdx: number;
65
+ /** Last bucket index with activity, or -1 when the series is empty. */
66
+ lastIdx: number;
63
67
  }
64
68
 
65
69
  export interface GraphModel {
@@ -183,21 +187,40 @@ export function buildGraphModel(
183
187
  const hidden = options.hidden ?? new Set<string>();
184
188
  const series: GraphSeries[] = [];
185
189
 
190
+ // Active range per series (computed on raw per-bucket values, before any
191
+ // cumulative transform): lines are later drawn only between the first and
192
+ // last bucket with usage, so late-starting or retired series do not drag a
193
+ // flat zero/flat tail across the whole period.
194
+ const activeRange = (points: number[]): { firstIdx: number; lastIdx: number } => {
195
+ let firstIdx = -1;
196
+ let lastIdx = -1;
197
+ for (let i = 0; i < points.length; i++) {
198
+ if (points[i] !== 0) {
199
+ if (firstIdx === -1) firstIdx = i;
200
+ lastIdx = i;
201
+ }
202
+ }
203
+ return { firstIdx, lastIdx };
204
+ };
205
+
186
206
  series.push({
187
207
  key: TOTAL_SERIES_KEY,
188
208
  label: "Total",
189
209
  points: totalPoints.slice(),
190
210
  total: totalSum,
191
211
  hidden: hidden.has(TOTAL_SERIES_KEY),
212
+ ...activeRange(totalPoints),
192
213
  });
193
214
 
194
215
  for (const [groupKey, total] of kept) {
216
+ const points = groupValues.get(groupKey)!;
195
217
  series.push({
196
218
  key: groupKey,
197
219
  label: groupKey,
198
- points: groupValues.get(groupKey)!,
220
+ points,
199
221
  total,
200
222
  hidden: hidden.has(groupKey),
223
+ ...activeRange(points),
201
224
  });
202
225
  }
203
226
 
@@ -215,6 +238,7 @@ export function buildGraphModel(
215
238
  points,
216
239
  total,
217
240
  hidden: hidden.has(OTHER_SERIES_KEY),
241
+ ...activeRange(points),
218
242
  });
219
243
  }
220
244
 
@@ -295,10 +319,11 @@ export function renderChart(model: GraphModel, options: ChartRenderOptions): str
295
319
  const yMax = model.yMax > 0 ? model.yMax : 1;
296
320
  const bucketCount = model.bucketStarts.length;
297
321
 
298
- const plot = (seriesIndex: number, points: number[]) => {
322
+ const plot = (seriesIndex: number, points: number[], firstIdx: number, lastIdx: number) => {
323
+ if (firstIdx < 0) return;
299
324
  let prevX = -1;
300
325
  let prevY = -1;
301
- for (let i = 0; i < bucketCount; i++) {
326
+ for (let i = firstIdx; i <= lastIdx; i++) {
302
327
  const x = bucketCount === 1 ? dotW - 1 : Math.round((i / (bucketCount - 1)) * (dotW - 1));
303
328
  const y = Math.round((1 - (points[i]! / yMax)) * (dotH - 1));
304
329
  if (prevX >= 0) {
@@ -335,7 +360,7 @@ export function renderChart(model: GraphModel, options: ChartRenderOptions): str
335
360
  entry.s.key === TOTAL_SERIES_KEY ? Number.POSITIVE_INFINITY : entry.s.key === OTHER_SERIES_KEY ? -1 : entry.s.total;
336
361
  return rank(a) - rank(b);
337
362
  });
338
- for (const { s, i } of drawOrder) plot(i, s.points);
363
+ for (const { s, i } of drawOrder) plot(i, s.points, s.firstIdx, s.lastIdx);
339
364
 
340
365
  // Compose text rows.
341
366
  const lines: string[] = [];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tmustier/pi-usage-extension",
3
- "version": "0.6.0",
3
+ "version": "0.6.1",
4
4
  "description": "Usage statistics dashboard for Pi sessions.",
5
5
  "license": "MIT",
6
6
  "author": "Thomas Mustier",