pi-minimal-footer 0.4.0 → 0.4.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/CHANGELOG.md CHANGED
@@ -7,6 +7,25 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.4.2] - 2026-10-07
11
+
12
+ ### Fixed
13
+
14
+ - Point pi.dev package preview metadata to a dedicated 16:9 PNG (1280×720), preserving the footer image without stretching or cropping
15
+
16
+ ## [0.4.1] - 2026-10-07
17
+
18
+ ### Changed
19
+
20
+ - Restructure README with separate left/right feature lists, clearer context and subscription usage guidance, explicit adapter verification limits, and source installation under development
21
+ - Refresh the vision contract for the two-cell baseline, bracketed bars, and nine-second timeout
22
+ - Explain cache retention, refresh jitter, exact-model quota selection, and readability thresholds with rationale comments; update the source footer example to show brackets
23
+
24
+ ### Fixed
25
+
26
+ - Restore reset-label-only usage on terminals too narrow for a bracketed cell, with regression coverage for reset-only, hidden-usage, and one-cell width boundaries
27
+ - Align usage detection and regression expectations with bracketed bars, the two-cell baseline, bracket-aware width allocation, and ten-cell rounding for small percentages
28
+
10
29
  ## [0.4.0] - 2026-10-07
11
30
 
12
31
  ### Added
@@ -167,7 +186,10 @@ First npm-ready release.
167
186
 
168
187
  - Project scaffold — `extensions/index.ts` with basic footer structure, `package.json` with pi extension manifest, `README.md`, `LICENSE` (MIT)
169
188
 
170
- [Unreleased]: https://github.com/Ryu-CZ/pi-minimal-footer/compare/v0.3.3...HEAD
189
+ [Unreleased]: https://github.com/Ryu-CZ/pi-minimal-footer/compare/v0.4.2...HEAD
190
+ [0.4.2]: https://github.com/Ryu-CZ/pi-minimal-footer/compare/v0.4.1...v0.4.2
191
+ [0.4.1]: https://github.com/Ryu-CZ/pi-minimal-footer/compare/v0.4.0...v0.4.1
192
+ [0.4.0]: https://github.com/Ryu-CZ/pi-minimal-footer/compare/v0.3.3...v0.4.0
171
193
  [0.3.3]: https://github.com/Ryu-CZ/pi-minimal-footer/compare/v0.3.2...v0.3.3
172
194
  [0.3.2]: https://github.com/Ryu-CZ/pi-minimal-footer/compare/v0.3.1...v0.3.2
173
195
  [0.3.1]: https://github.com/Ryu-CZ/pi-minimal-footer/compare/v0.3.0...v0.3.1
package/README.md CHANGED
@@ -9,18 +9,26 @@
9
9
 
10
10
  An opinionated, compact one-line footer for [Pi](https://github.com/earendil-works/pi).
11
11
 
12
- Path and branch on the left; extension statuses, model, context, and subscription usage bar on the right. Shrinks to fit narrow terminals, with one space of padding at each edge. Interactive terminal UI only.
13
-
14
12
  ![Footer preview: ~/git/project   main  🧠 Karpathy  🪽 Icarus  model · 42/200k · [⣿⣿⣿⣤⠀⠀⠀⠀⠀⠀]↻1d8h](media/github-preview.png)
15
13
 
14
+ **Left**
15
+
16
+ - Working directory: `~/git/project`
17
+ - Git branch: ` main`
18
+
19
+ **Right**
20
+
21
+ - Extension statuses: ` 🧠 Karpathy  🪽 Icarus`
22
+ - Model: `model`
23
+ - Context usage: `42/200k`
24
+ - Subscription usage bar with reset time: `[⣿⣿⣿⣤⠀⠀⠀⠀⠀⠀]↻1d8h`
25
+
16
26
  ## Install
17
27
 
18
- Requires Node.js >=22.19.0.
28
+ Requires Node.js >=22.19.0. Interactive terminal UI only.
19
29
 
20
30
  ```bash
21
31
  pi install npm:pi-minimal-footer
22
- # Or install from source:
23
- pi install git:github.com/Ryu-CZ/pi-minimal-footer
24
32
  ```
25
33
 
26
34
  ## Commands
@@ -53,20 +61,33 @@ Edit `minFooter` in Pi's agent `settings.json` (normally `~/.pi/agent/settings.j
53
61
  - `showSkills` shows **extension status text**, not installed skills. The footer does not add the example statuses itself.
54
62
  - Set `powerlineSeparator` to `false` for plain spaces instead of `` / `` if your font lacks those glyphs. The git icon `` also needs a compatible font; hide it with `showGitBranch: false` if needed.
55
63
  - `maxUsageBarCells` caps the Braille bar length (excluding brackets and reset time). Use a positive integer, e.g. `4` for a compact bar; invalid values fall back to `10`.
56
- - Context `42/200k` means tokens used / context window. `?` means Pi has not reported usage yet, including immediately after compaction.
57
64
 
58
- ## Reading subscription usage
65
+ ## Reading the footer
66
+
67
+ ### Context
68
+
69
+ `42/200k` means tokens used / context window. `?` means Pi has not reported usage yet, including immediately after compaction.
70
+
71
+ ### Subscription usage
59
72
 
60
73
  `[⣿⣿⣿⣤⠀⠀⠀⠀⠀⠀]↻1d8h` shows **subscription allowance used**, not context usage.
61
74
 
62
- - Bar: shown as `[cells]` with 2–10 cells by default, expanding into spare space up to `maxUsageBarCells` (or fewer when the cap is below 2); green below 85%, amber from 85%, red from 92%. The brackets keep the bar’s beginning and end visible even when it is empty. Dim means cached after a refresh failure. Very narrow terminals may show fewer cells or only the reset label.
75
+ - **Bar:** expands into spare space, using 2–10 cells by default, capped by `maxUsageBarCells`. Smaller caps and very narrow terminals may show fewer cells or only the reset label.
76
+ - **Colors:** green below 85%, amber from 85%, red from 92%.
77
+ - **Cached data:** dim after a refresh failure.
63
78
  - Reset: local `↻HH:mm` through 24 hours; whole days/hours above 24 hours (`↻1d8h`); whole days above 10 days (`↻12d`). Remaining durations round down. No reset reported means bar only.
64
79
  - Shows the shortest available usage window for the selected provider. Missing credentials, unsupported/local models, or absent limits hide the usage bar. Custom proxy endpoints are not polled.
65
80
 
66
- Supported adapters: **OpenAI Codex, Claude OAuth, GitHub Copilot, Gemini CLI, MiniMax, Kimi Coding, and OpenCode Go**. Uses Pi's existing credentials; ordinary Claude API keys do not expose subscription usage. Provider availability varies; authenticated endpoints remain unverified live.
81
+ Implemented adapters: **OpenAI Codex, Claude OAuth, GitHub Copilot, Gemini CLI, MiniMax, Kimi Coding, and OpenCode Go**. Uses Pi's existing credentials; ordinary Claude API keys do not expose subscription usage. Authenticated endpoints remain unverified live; see [verification limits](VISION.md).
67
82
 
68
83
  ## Development & design
69
84
 
85
+ Install from source:
86
+
87
+ ```bash
88
+ pi install git:github.com/Ryu-CZ/pi-minimal-footer
89
+ ```
90
+
70
91
  See [VISION.md](VISION.md) for design constraints, local development, provider details, and verification limits. Release history: [CHANGELOG.md](CHANGELOG.md).
71
92
 
72
93
  ## Credits
package/VISION.md CHANGED
@@ -18,9 +18,9 @@ The [README](README.md) is the user manual. This document records current design
18
18
 
19
19
  Reserve the usage bar and model/context before allocating location and statuses. Statuses and location may shorten or disappear; on sufficiently narrow terminals, model/context can also shorten or disappear.
20
20
 
21
- Lay out other fields with a five-cell usage bar first. Grow the bar only into leftover columns, up to ten cells—never truncate another field solely to enlarge it. At extreme widths, shrink below five cells, show only the reset label, or hide the usage bar if the label cannot fit.
21
+ Lay out other fields with a two-cell usage bar first. Grow the bar only into leftover columns, up to ten cells—never truncate another field solely to enlarge it. At extreme widths, shrink to one cell, show only the reset label, or hide usage if neither can fit. Brackets keep an empty bar's edges visible and count toward its width, but not its cell cap.
22
22
 
23
- Five cells give 2.5% steps; ten give 1.25%. Fill rounds to the nearest eighth-cell step. Only the final partially filled cell uses an intermediate shade:
23
+ Two cells give 6.25% steps; ten give 1.25%. Fill rounds to the nearest eighth-cell step. Only the final partially filled cell uses an intermediate shade:
24
24
 
25
25
  | Cell | Fill |
26
26
  |---|---|
@@ -57,7 +57,7 @@ Reuse Pi's selected-provider credentials. Copilot uses the GitHub login token fr
57
57
  - Consume passive Codex response headers/stream events and Claude quota headers when available.
58
58
  - Otherwise fetch on startup/provider switch, then roughly every four minutes without a fresh response update. Sample independent uniform ±⅛ jitter (3.5–4.5 minutes) for each attempt or fresh displayed-window update to spread fallback requests across sessions. Keep that deadline across unrelated window updates; a reported reset time still triggers an earlier refresh.
59
59
  - Merge partial windows. A weekly-only signal must not replace a cached shorter window or postpone its refresh.
60
- - Bound authentication, fetch, and response-body parsing by a shared five-second timeout. Release stalled work so polling can recover.
60
+ - Bound authentication, fetch, and response-body parsing by a shared nine-second timeout. Release stalled work so polling can recover.
61
61
  - Provider switches clear usage immediately, cancel pending work, and invalidate late results. Gemini model switches also refresh model-specific usage.
62
62
  - Missing credentials and explicit empty/unlimited responses clear usage. Temporary authentication, network, or parsing failures retain only the current provider's cached usage, dimmed; without cache, hide it.
63
63
  - Invalid optional reset metadata must not discard otherwise valid usage. Zero usage is an empty bar, not an absent usage bar.
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Minimal footer — replaces pi's default footer with a clean status line:
3
3
  *
4
- * ~/path/to/dir   main  status1  status2  sonnet · 12/128k · ⣿⣶⠀⠀⠀↻16:40
4
+ * ~/path/to/dir   main  status1  status2  sonnet · 12/128k · [⣿⣶⠀⠀⠀]↻16:40
5
5
  *
6
6
  * Settings are persisted in the agent directory (usually ~/.pi/agent)
7
7
  * settings.json under "minFooter".
@@ -141,6 +141,7 @@ function updateState(ctx: ExtensionContext, state: FooterState): void {
141
141
  const MODEL_GAP = " · ";
142
142
  const USAGE_GAP = " · ";
143
143
  const LOCATION_GAP_WIDTH = 3;
144
+ // Below these budgets, ellipses dominate text and status tabs stop being useful at a glance.
144
145
  const MIN_TEXT_WIDTH = 4;
145
146
  const MIN_STATUS_WIDTH = 12;
146
147
 
@@ -186,6 +186,7 @@ export class UsageLimits {
186
186
  this.render();
187
187
  }
188
188
 
189
+ // Independent deadlines spread fallback requests across sessions sharing a subscription.
189
190
  private randomizeRefresh(): void {
190
191
  this.refreshDelay = REFRESH_MS + (Math.random() * 2 - 1) * REFRESH_JITTER_MS;
191
192
  }
@@ -246,8 +247,11 @@ export class UsageLimits {
246
247
  if (!this.ctx || !window) return null;
247
248
  const now = Date.now();
248
249
  const resetLabel = formatResetLabel(window.resetAt, now);
249
- // Reserve two columns for brackets so an empty bar still has clear edges.
250
- if (width < (resetLabel.length || 1) + 3) return null;
250
+ // Keep the reset useful when the terminal cannot fit even one bracketed cell.
251
+ if (width < resetLabel.length + 3) {
252
+ return resetLabel && width >= resetLabel.length ? theme.fg("dim", resetLabel) : null;
253
+ }
254
+ // Brackets keep the edges of a zero-usage bar visible.
251
255
  const cells = Math.min(maxCells, Math.max(1, width - resetLabel.length - 2));
252
256
  const steps = Math.round(window.used / 100 * cells * CELL_STEPS);
253
257
  const filled = "⣿".repeat(Math.floor(steps / CELL_STEPS)) + PARTIAL_CELL_FILLS[steps % CELL_STEPS];
@@ -136,6 +136,8 @@ export function parseUsageWindows(provider: string, model: string, payload: unkn
136
136
  if (window) windows[key] = window;
137
137
  else malformed = true;
138
138
  };
139
+ // Valid siblings remain useful; explicit absence clears cache, while malformed
140
+ // snapshots throw so a temporary provider failure retains dimmed cached usage.
139
141
  const finish = () => {
140
142
  if (Object.keys(windows).length) return windows;
141
143
  if (recognized && !malformed) return null;
@@ -247,6 +249,7 @@ export function parseUsageWindows(provider: string, model: string, payload: unkn
247
249
  if (!ok) malformed = true;
248
250
  return ok;
249
251
  });
252
+ // A malformed exact match must not substitute another model family's quota.
250
253
  const hasExact = buckets.some((b) => b.modelId === model);
251
254
  const family = model.toLowerCase().includes("flash") ? "flash" : model.toLowerCase().includes("pro") ? "pro" : null;
252
255
  const selected = valid.filter((b) => hasExact ? b.modelId === model : family && String(b.modelId).toLowerCase().includes(family));
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-minimal-footer",
3
- "version": "0.4.0",
3
+ "version": "0.4.2",
4
4
  "description": "An opinionated minimal footer extension for Pi — clean status line with path, extension statuses, model, and context usage.",
5
5
  "keywords": [
6
6
  "pi-package",
@@ -49,6 +49,6 @@
49
49
  "extensions": [
50
50
  "./extensions"
51
51
  ],
52
- "image": "https://raw.githubusercontent.com/Ryu-CZ/pi-minimal-footer/main/media/preview.png"
52
+ "image": "https://raw.githubusercontent.com/Ryu-CZ/pi-minimal-footer/main/media/pi-preview.png"
53
53
  }
54
54
  }