@ohgodtamit/pi-usage 0.1.0-alpha.0 → 0.2.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.
- package/CHANGELOG.md +19 -0
- package/README.md +56 -68
- package/dist/aggregate.d.ts +2 -2
- package/dist/aggregate.d.ts.map +1 -1
- package/dist/provider.d.ts +6 -9
- package/dist/provider.d.ts.map +1 -1
- package/dist/view.d.ts +8 -4
- package/dist/view.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/aggregate.ts +7 -2
- package/src/index.ts +2 -1
- package/src/provider.ts +80 -41
- package/src/view.ts +72 -24
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,24 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.2.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 8c0c6fb: Add a rolling 30-day Month window to the Overview, Models, and Delegation usage views,
|
|
8
|
+
available from the TUI with `m` and from the RPC action menu.
|
|
9
|
+
|
|
10
|
+
### Patch Changes
|
|
11
|
+
|
|
12
|
+
- 0fc067d: Classify OpenAI Codex quota windows by their reported duration so weekly-only Pro quotas are not mislabeled as 5-hour quotas.
|
|
13
|
+
- 9e5334c: Fix TUI redraw corruption after visiting the Delegation tab: sanitize session-derived task, parent, agent-type, and status text so rendered lines never contain embedded newlines, tabs, or escape bytes. Previously one logical line could wrap into extra physical terminal rows, desyncing pi-tui's differential renderer and leaving stale rows, a duplicated header, and remnants of adjacent tabs when switching views or closing the panel.
|
|
14
|
+
|
|
15
|
+
## 0.1.0
|
|
16
|
+
|
|
17
|
+
### Minor Changes
|
|
18
|
+
|
|
19
|
+
- 64d2adf: Introduce the @ohgodtamit/pi-usage package with cost and token attribution, live provider quotas, incremental caching, model-registry credential resolution, and complete usage and provenance documentation.
|
|
20
|
+
- 64d2adf: Add an eight-view keyboard TUI with RPC-compatible paginated rendering and navigation, delegation analytics, progress and freshness reporting, headless guards, and broad provider compatibility.
|
|
21
|
+
|
|
3
22
|
## 0.1.0-alpha.0
|
|
4
23
|
|
|
5
24
|
### Minor Changes
|
package/README.md
CHANGED
|
@@ -3,15 +3,17 @@
|
|
|
3
3
|
A Claude Code–style `/usage` panel for [pi](https://github.com/earendil-works/pi-mono).
|
|
4
4
|
|
|
5
5
|
Shows how your spend and tokens are distributed across **models, skills, plugins,
|
|
6
|
-
tools, projects, and delegated child sessions**, bucketed by
|
|
6
|
+
tools, projects, and delegated child sessions**, bucketed by 5-hour, day, week,
|
|
7
|
+
month, or all-time windows — with
|
|
7
8
|
always-visible **5-hour** and **weekly** quota bars. The Overview includes input,
|
|
8
9
|
output, cache-read/cache-write, reasoning (as an output subset), component costs,
|
|
9
10
|
and the cache-input reuse ratio. Mirrors the layout and wording of Claude Code's
|
|
10
11
|
`/usage` screen.
|
|
11
12
|
|
|
12
|
-
|
|
13
|
+
## Installation
|
|
13
14
|
|
|
14
|
-
|
|
15
|
+
Requirements: Node `>=22.22.2` and Pi `>=0.84.3 <0.85.0`. No build step; Pi loads
|
|
16
|
+
TypeScript directly via jiti.
|
|
15
17
|
|
|
16
18
|
> ⚠️ **Use `pi install` — NOT `npm install`.**
|
|
17
19
|
> Plain `npm install` only drops files in `node_modules`. Pi does **not** scan
|
|
@@ -19,33 +21,47 @@ and the cache-input reuse ratio. Mirrors the layout and wording of Claude Code's
|
|
|
19
21
|
> You must register it with `pi install` so it lands in `"packages"` in
|
|
20
22
|
> `~/.pi/agent/settings.json`.
|
|
21
23
|
|
|
24
|
+
For a persistent installation:
|
|
25
|
+
|
|
22
26
|
```bash
|
|
23
|
-
pi install npm:@ohgodtamit/pi-usage
|
|
27
|
+
pi install npm:@ohgodtamit/pi-usage
|
|
24
28
|
```
|
|
25
29
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
Then inside pi:
|
|
30
|
+
For a single run without changing Pi's saved package list:
|
|
29
31
|
|
|
30
|
-
```
|
|
31
|
-
/
|
|
32
|
+
```bash
|
|
33
|
+
pi -e npm:@ohgodtamit/pi-usage
|
|
32
34
|
```
|
|
33
35
|
|
|
34
|
-
|
|
36
|
+
From this repository checkout:
|
|
35
37
|
|
|
36
38
|
```bash
|
|
37
|
-
pi
|
|
39
|
+
pi install ./packages/pi-usage
|
|
38
40
|
```
|
|
39
41
|
|
|
40
|
-
Type `/` — `/usage` should appear in slash
|
|
42
|
+
Then inside Pi run `/reload` (or restart). Type `/` — `/usage` should appear in slash
|
|
43
|
+
autocomplete. Verify the registration:
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
pi list # should show npm:@ohgodtamit/pi-usage
|
|
47
|
+
```
|
|
41
48
|
|
|
42
|
-
**Don't do this** (common mistake — package installs but
|
|
49
|
+
**Don't do this** (common mistake — package installs but Pi ignores it):
|
|
43
50
|
|
|
44
51
|
```bash
|
|
45
|
-
npm install -g @ohgodtamit/pi-usage
|
|
52
|
+
npm install -g @ohgodtamit/pi-usage # ❌ Pi will not detect this
|
|
46
53
|
```
|
|
47
54
|
|
|
48
|
-
|
|
55
|
+
### Installation troubleshooting
|
|
56
|
+
|
|
57
|
+
| Symptom | Fix |
|
|
58
|
+
|---------|-----|
|
|
59
|
+
| `/usage` not in autocomplete | Run `pi install npm:@ohgodtamit/pi-usage`, then `/reload` |
|
|
60
|
+
| Installed with `npm install -g` but Pi ignores it | Use `pi install npm:@ohgodtamit/pi-usage` instead |
|
|
61
|
+
| Added `npm:...` to `"extensions"` in settings | Wrong key — use `"packages"`, or run `pi install` |
|
|
62
|
+
| Extension listed but disabled | Run `pi config` and enable the extension resource |
|
|
63
|
+
|
|
64
|
+
## Panel tour
|
|
49
65
|
|
|
50
66
|
### Overview (`/usage`)
|
|
51
67
|
|
|
@@ -53,7 +69,7 @@ Eight views via `Tab` or `1`–`8`. The navigation bar is a **two-row menu**: co
|
|
|
53
69
|
|
|
54
70
|
```
|
|
55
71
|
────────────────────────────────────────────────────────────────
|
|
56
|
-
Usage ──────────────────────────────── 5H │ DAY │ WEEK │ ALL
|
|
72
|
+
Usage ──────────────────────────────── 5H │ DAY │ WEEK │ MONTH │ ALL
|
|
57
73
|
|
|
58
74
|
╭─ views ◈1 Overview │ ◎2 Models │ … │ ✦8 Wrapped ─────────╮
|
|
59
75
|
(◕‿◕) Pi-chan Quota bars & headline stats… Tab · 1-8 jump
|
|
@@ -167,6 +183,18 @@ The panel uses a lightweight TUI mascot, **Pi-chan**, to make navigation feel fr
|
|
|
167
183
|
|
|
168
184
|
Pi-chan copy is informational, not decorative — footer captions summarize your standout stat in plain language.
|
|
169
185
|
|
|
186
|
+
## RPC and print/JSON modes
|
|
187
|
+
|
|
188
|
+
In RPC mode the panel stays fully operable: `/usage` and its view shortcuts render the same
|
|
189
|
+
report as an **ANSI-free** plain-text widget, paginated into fixed-size pages and driven by a
|
|
190
|
+
`ui.select` action menu (switch views, change window, turn pages, refresh, configure budgets,
|
|
191
|
+
close). The widget never emits terminal escape sequences, so RPC clients receive clean
|
|
192
|
+
`string[]` content at a fixed portable width.
|
|
193
|
+
|
|
194
|
+
All panel commands require an interactive surface. In print or JSON mode they fail fast with an
|
|
195
|
+
actionable error asking you to rerun Pi without print/JSON mode, rather than hanging on a hidden
|
|
196
|
+
prompt.
|
|
197
|
+
|
|
170
198
|
## Commands
|
|
171
199
|
|
|
172
200
|
| Command | Description |
|
|
@@ -180,7 +208,7 @@ Pi-chan copy is informational, not decorative — footer captions summarize your
|
|
|
180
208
|
| `/usage-providers` | Open the panel directly on the **Providers** view. |
|
|
181
209
|
| `/usage-agents` | Compatibility alias for `/usage-providers`. |
|
|
182
210
|
| `/usage-wrapped` | Open the panel directly on the **Wrapped AI** year-in-review view. |
|
|
183
|
-
| `/usage-config` | Set your 5-hour and weekly USD
|
|
211
|
+
| `/usage-config` | Set your 5-hour and weekly budgets: USD limits for priced providers, token limits for token-priced providers. |
|
|
184
212
|
| `/usage-pricing` | Set a manual per-model price ($/M tokens) so cost shows for token-priced / proxied models pi records as $0. |
|
|
185
213
|
| `/usage-widget` | Toggle a compact always-on spend widget above the editor. |
|
|
186
214
|
|
|
@@ -190,7 +218,7 @@ Pi-chan copy is informational, not decorative — footer captions summarize your
|
|
|
190
218
|
|-----|--------|
|
|
191
219
|
| `Tab` / `Shift+Tab`, `←` / `→` | Switch view (Overview ↔ … ↔ Wrapped AI) |
|
|
192
220
|
| `1`–`8` | Jump to Overview / Models / Delegation / Daily / Stats / Hourly / Providers / Wrapped |
|
|
193
|
-
| `5` / `d` / `w` / `a` | Switch window (5 hours / day / week / all). On Overview & Models all
|
|
221
|
+
| `5` / `d` / `w` / `m` / `a` | Switch the generic window (5 hours / day / week / month / all). On Overview & Models all five work; on Delegation use `d`/`w`/`m`/`a` (`5` opens **Stats**). Daily, Hourly, Providers, and Wrapped have no generic window. |
|
|
194
222
|
| `a` / `w` / `m` | Stats range: all time / last 7 days / last 30 days (Stats view) |
|
|
195
223
|
| `c` / `t` / `n` | Models or Providers view: sort by usage (`c`/`t`) or name (`n`) |
|
|
196
224
|
| `t` / `c` / `d` | Daily view: sort by tokens / cost / date — press the same key again to flip ascending ↔ descending |
|
|
@@ -334,56 +362,6 @@ quota integration can still surface captured rate-limit headers.
|
|
|
334
362
|
| `freshness.ts` | Report-cache freshness decision (TTL + new-turn invalidation), unit-tested in isolation |
|
|
335
363
|
| `zai.ts` | Pure ZAI quota-limit classification, dependency-free for unit testing |
|
|
336
364
|
|
|
337
|
-
## Install
|
|
338
|
-
|
|
339
|
-
Use **`pi install`**, not plain `npm install`. Pi registers packages in `settings.json` under `"packages"` and loads extensions from the `pi.extensions` manifest in `package.json`.
|
|
340
|
-
|
|
341
|
-
```bash
|
|
342
|
-
pi install npm:@ohgodtamit/pi-usage@alpha
|
|
343
|
-
```
|
|
344
|
-
|
|
345
|
-
The `alpha` tag is required until the first stable release is available on `latest`.
|
|
346
|
-
|
|
347
|
-
Then run `/reload` in pi (or restart the CLI). Commands like `/usage` should appear in slash autocomplete.
|
|
348
|
-
|
|
349
|
-
Quick test without persisting to settings:
|
|
350
|
-
|
|
351
|
-
```bash
|
|
352
|
-
pi -e npm:@ohgodtamit/pi-usage@alpha
|
|
353
|
-
```
|
|
354
|
-
|
|
355
|
-
From this repository checkout:
|
|
356
|
-
|
|
357
|
-
```bash
|
|
358
|
-
pi install ./packages/pi-usage
|
|
359
|
-
```
|
|
360
|
-
|
|
361
|
-
From a local path:
|
|
362
|
-
|
|
363
|
-
```bash
|
|
364
|
-
pi install ./packages/pi-usage
|
|
365
|
-
```
|
|
366
|
-
|
|
367
|
-
### Troubleshooting
|
|
368
|
-
|
|
369
|
-
| Symptom | Fix |
|
|
370
|
-
|---------|-----|
|
|
371
|
-
| `/usage` not in autocomplete | Run `pi install npm:@ohgodtamit/pi-usage@alpha`, then `/reload` |
|
|
372
|
-
| Installed with `npm install -g` but pi ignores it | Use `pi install npm:@ohgodtamit/pi-usage@alpha` instead |
|
|
373
|
-
| Added `npm:...` to `"extensions"` in settings | Wrong key — use `"packages"`, or run `pi install` |
|
|
374
|
-
| Extension listed but disabled | Run `pi config` and enable the extension resource |
|
|
375
|
-
|
|
376
|
-
Verify install:
|
|
377
|
-
|
|
378
|
-
```bash
|
|
379
|
-
pi list
|
|
380
|
-
# should show: npm:@ohgodtamit/pi-usage@alpha
|
|
381
|
-
```
|
|
382
|
-
|
|
383
|
-
> **Note:** `npm install` only downloads the package to disk. Pi does not auto-scan global or local `node_modules` — you must register the package with `pi install` so it appears in `"packages"`.
|
|
384
|
-
|
|
385
|
-
No build step; pi loads TypeScript directly via jiti.
|
|
386
|
-
|
|
387
365
|
## Changelog
|
|
388
366
|
|
|
389
367
|
Upstream donor release history (this fork starts at 0.1.0 and pins `@zaganjade/pi-usage` 1.9.2):
|
|
@@ -401,3 +379,13 @@ Upstream donor release history (this fork starts at 0.1.0 and pins `@zaganjade/p
|
|
|
401
379
|
### v1.8.0
|
|
402
380
|
|
|
403
381
|
- Seven views including Wrapped AI, Agents, Hourly; live ZAI/Codex quota; incremental scan cache
|
|
382
|
+
|
|
383
|
+
## Provenance
|
|
384
|
+
|
|
385
|
+
This package is a fork of `@zaganjade/pi-usage` 1.9.2. Pinned commit, author, license, and
|
|
386
|
+
path-level source mappings are recorded in [`THIRD_PARTY_NOTICES.md`](./THIRD_PARTY_NOTICES.md).
|
|
387
|
+
|
|
388
|
+
## License
|
|
389
|
+
|
|
390
|
+
[MIT](./LICENSE) © 2026 Christopher Tam. Third-party adaptations remain subject to their retained
|
|
391
|
+
MIT notices.
|
package/dist/aggregate.d.ts
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*
|
|
4
4
|
* The usage panel mirrors Claude Code's `/usage` view: it shows how spend and
|
|
5
5
|
* tokens are distributed across models, skills, plugins, tools, and projects,
|
|
6
|
-
* bucketed by time window (5h / 24h / 7d / all).
|
|
6
|
+
* bucketed by time window (5h / 24h / 7d / 30d / all).
|
|
7
7
|
*
|
|
8
8
|
* Data source
|
|
9
9
|
* -----------
|
|
@@ -35,7 +35,7 @@ export declare function resolveModelPrice(model: string, prices: PriceMap | unde
|
|
|
35
35
|
/** Compute a USD cost from token usage and a manual price ($/Mtok). */
|
|
36
36
|
export declare function costFromPrice(usage: Usage, price: ModelPrice): number;
|
|
37
37
|
/** Time windows selectable in the panel. */
|
|
38
|
-
export type WindowKey = "5h" | "24h" | "7d" | "all";
|
|
38
|
+
export type WindowKey = "5h" | "24h" | "7d" | "30d" | "all";
|
|
39
39
|
export declare function windowMs(key: WindowKey): number;
|
|
40
40
|
export declare function windowLabel(key: WindowKey): string;
|
|
41
41
|
/** Mutable usage totals for a bucket. */
|
package/dist/aggregate.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"aggregate.d.ts","sourceRoot":"","sources":["../src/aggregate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,OAAO,KAAK,EAA8B,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAC/E,OAAO,EACL,KAAK,YAAY,EAGjB,KAAK,WAAW,EAEjB,MAAM,iCAAiC,CAAC;AAWzC,OAAO,KAAK,EAAiB,SAAS,EAAE,MAAM,YAAY,CAAC;AAE3D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAG9C,mEAAmE;AACnE,MAAM,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;AAElD;;;;GAIG;AACH,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,QAAQ,GAAG,SAAS,GAC3B,UAAU,GAAG,SAAS,CASxB;AAED,uEAAuE;AACvE,wBAAgB,aAAa,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,UAAU,GAAG,MAAM,CAOrE;AAED,4CAA4C;AAC5C,MAAM,MAAM,SAAS,GAAG,IAAI,GAAG,KAAK,GAAG,IAAI,GAAG,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"aggregate.d.ts","sourceRoot":"","sources":["../src/aggregate.ts"],"names":[],"mappings":"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"}
|
package/dist/provider.d.ts
CHANGED
|
@@ -108,18 +108,15 @@ export declare function parseRateLimits(headers: Record<string, string>, now?: n
|
|
|
108
108
|
export declare function parseReset(value: string | undefined, now: number): number;
|
|
109
109
|
/**
|
|
110
110
|
* Parse OpenAI Codex subscription quota from response headers captured via
|
|
111
|
-
* `after_provider_response`.
|
|
112
|
-
*
|
|
113
|
-
* management (unlike the `/wham/usage` REST endpoint, whose OAuth token in
|
|
114
|
-
* `~/.codex/auth.json` is frequently stale/rotated).
|
|
111
|
+
* `after_provider_response`. Window durations determine the labels because
|
|
112
|
+
* OpenAI may report a weekly-only quota in the primary slot.
|
|
115
113
|
*
|
|
116
114
|
* Header families (authoritative: openai/codex rate_limits.rs):
|
|
117
|
-
* x-codex-primary-used-percent
|
|
118
|
-
* x-codex-primary-
|
|
119
|
-
* x-codex-secondary-
|
|
120
|
-
* x-codex-secondary-reset-at — unix SECONDS
|
|
115
|
+
* x-codex-{primary,secondary}-used-percent — window used % (0-100)
|
|
116
|
+
* x-codex-{primary,secondary}-window-minutes — window duration
|
|
117
|
+
* x-codex-{primary,secondary}-reset-at — unix seconds of next reset
|
|
121
118
|
* x-codex-credits-has-credits / -unlimited / -balance — purchased credits
|
|
122
|
-
* x-codex-limit-name
|
|
119
|
+
* x-codex-limit-name — plan/limit display name
|
|
123
120
|
*
|
|
124
121
|
* Returns the planQuota shape (shared with ZAI) when any Codex window is present.
|
|
125
122
|
*/
|
package/dist/provider.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../src/provider.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AACH,OAAO,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,KAAK,aAAa,EAAwB,MAAM,iCAAiC,CAAC;AAM3F,kFAAkF;AAClF,wBAAsB,aAAa,CACjC,aAAa,EAAE,aAAa,EAC5B,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAU7B;AAED,4EAA4E;AAC5E,wBAAsB,cAAc,CAClC,aAAa,EAAE,aAAa,EAC5B,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,OAAO,CAAC,CAUlB;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;IACZ,iFAAiF;IACjF,MAAM,EAAE,OAAO,CAAC;CACjB;AAED,2EAA2E;AAC3E,wBAAsB,oBAAoB,CACxC,aAAa,EAAE,aAAa,EAC5B,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,GAAG,SAAS,GAC5B,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CAUhC;AAED,MAAM,WAAW,eAAe;IAC9B,+DAA+D;IAC/D,QAAQ,EAAE,MAAM,CAAC;IACjB,gFAAgF;IAChF,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,wDAAwD;IACxD,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,cAAc,GAAG,IAAI,CAAC;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,kFAAkF;IAClF,OAAO,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC;IAC7D,+EAA+E;IAC/E,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;;OAIG;IACH,SAAS,CAAC,EAAE;QACV,IAAI,EAAE,MAAM,CAAC;QACb,SAAS,CAAC,EAAE;YAAE,OAAO,EAAE,MAAM,CAAC;YAAC,OAAO,EAAE,MAAM,CAAA;SAAE,CAAC;QACjD,MAAM,CAAC,EAAE;YAAE,OAAO,EAAE,MAAM,CAAC;YAAC,OAAO,EAAE,MAAM,CAAA;SAAE,CAAC;QAC9C,WAAW,CAAC,EAAE;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,KAAK,EAAE,MAAM,CAAC;YAAC,OAAO,EAAE,MAAM,CAAA;SAAE,CAAC;QAC/D,+DAA+D;QAC/D,OAAO,CAAC,EAAE;YAAE,OAAO,EAAE,MAAM,CAAC;YAAC,SAAS,EAAE,OAAO,CAAA;SAAE,CAAC;KACnD,CAAC;IACF,0EAA0E;IAC1E,UAAU,EAAE,eAAe,EAAE,CAAC;IAC9B,iGAAiG;IACjG,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAAC;IACpC,wDAAwD;IACxD,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;;;;GASG;AACH,wBAAgB,eAAe,CAC7B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC/B,GAAG,GAAE,MAAmB,GACvB,eAAe,EAAE,CAiEnB;AAiBD;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CA2BzE;
|
|
1
|
+
{"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../src/provider.ts"],"names":[],"mappings":"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"}
|
package/dist/view.d.ts
CHANGED
|
@@ -2,8 +2,9 @@
|
|
|
2
2
|
* Interactive usage panel TUI component.
|
|
3
3
|
*
|
|
4
4
|
* Rendered via ctx.ui.custom(). Mirrors Claude Code's `/usage` screen:
|
|
5
|
-
* always-visible 5-hour and weekly quota bars, a selectable
|
|
6
|
-
*
|
|
5
|
+
* always-visible 5-hour and weekly quota bars, a selectable 5-hour/day/week/
|
|
6
|
+
* month/all window on the generic-window views, and independent-characteristic
|
|
7
|
+
* breakdowns by model / skill / plugin / tool /
|
|
7
8
|
* project. Supports vertical scrolling for small terminals.
|
|
8
9
|
*/
|
|
9
10
|
import type { Theme } from "@earendil-works/pi-coding-agent";
|
|
@@ -84,7 +85,11 @@ export declare class UsageView {
|
|
|
84
85
|
render(width: number): string[];
|
|
85
86
|
/** Render all lines without terminal viewport assumptions or key-based instructions. */
|
|
86
87
|
renderPortable(width: number): string[];
|
|
87
|
-
/**
|
|
88
|
+
/**
|
|
89
|
+
* Final width clamp so one long line can never break the TUI layout. Also
|
|
90
|
+
* flattens every line to a single physical row (pi-tui's render contract);
|
|
91
|
+
* theme SGR escapes survive, stray control characters do not.
|
|
92
|
+
*/
|
|
88
93
|
private clampLine;
|
|
89
94
|
invalidate(): void;
|
|
90
95
|
private availableHeight;
|
|
@@ -114,7 +119,6 @@ export declare class UsageView {
|
|
|
114
119
|
*/
|
|
115
120
|
private appendModelTable;
|
|
116
121
|
private renderDelegation;
|
|
117
|
-
private windowDuration;
|
|
118
122
|
private zeroBucket;
|
|
119
123
|
private addUsageToBucket;
|
|
120
124
|
private renderDaily;
|
package/dist/view.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"view.d.ts","sourceRoot":"","sources":["../src/view.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"view.d.ts","sourceRoot":"","sources":["../src/view.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
package/src/aggregate.ts
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*
|
|
4
4
|
* The usage panel mirrors Claude Code's `/usage` view: it shows how spend and
|
|
5
5
|
* tokens are distributed across models, skills, plugins, tools, and projects,
|
|
6
|
-
* bucketed by time window (5h / 24h / 7d / all).
|
|
6
|
+
* bucketed by time window (5h / 24h / 7d / 30d / all).
|
|
7
7
|
*
|
|
8
8
|
* Data source
|
|
9
9
|
* -----------
|
|
@@ -76,10 +76,11 @@ export function costFromPrice(usage: Usage, price: ModelPrice): number {
|
|
|
76
76
|
}
|
|
77
77
|
|
|
78
78
|
/** Time windows selectable in the panel. */
|
|
79
|
-
export type WindowKey = "5h" | "24h" | "7d" | "all";
|
|
79
|
+
export type WindowKey = "5h" | "24h" | "7d" | "30d" | "all";
|
|
80
80
|
|
|
81
81
|
const HOUR = 60 * 60 * 1000;
|
|
82
82
|
const DAY = 24 * HOUR;
|
|
83
|
+
const MONTH = 30 * DAY;
|
|
83
84
|
|
|
84
85
|
export function windowMs(key: WindowKey): number {
|
|
85
86
|
switch (key) {
|
|
@@ -89,6 +90,8 @@ export function windowMs(key: WindowKey): number {
|
|
|
89
90
|
return DAY;
|
|
90
91
|
case "7d":
|
|
91
92
|
return 7 * DAY;
|
|
93
|
+
case "30d":
|
|
94
|
+
return MONTH;
|
|
92
95
|
case "all":
|
|
93
96
|
return Number.POSITIVE_INFINITY;
|
|
94
97
|
}
|
|
@@ -102,6 +105,8 @@ export function windowLabel(key: WindowKey): string {
|
|
|
102
105
|
return "Last 24 hours";
|
|
103
106
|
case "7d":
|
|
104
107
|
return "Last 7 days";
|
|
108
|
+
case "30d":
|
|
109
|
+
return "Last 30 days";
|
|
105
110
|
case "all":
|
|
106
111
|
return "All time";
|
|
107
112
|
}
|
package/src/index.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Pi usage extension — a Claude Code-style `/usage` panel for pi.
|
|
3
3
|
*
|
|
4
4
|
* Commands:
|
|
5
|
-
* /usage Open the interactive usage panel (5H / day / week / all
|
|
5
|
+
* /usage Open the interactive usage panel (5H / day / week / month / all
|
|
6
6
|
* windows, quota bars, model/skill/plugin/tool/project
|
|
7
7
|
* breakdowns).
|
|
8
8
|
* /usage-config Set your 5-hour and weekly USD budgets.
|
|
@@ -548,6 +548,7 @@ function rpcActions(view: UsageView, page: number, pageCount: number): RpcMenuIt
|
|
|
548
548
|
["Window: 5 hours", "5h"],
|
|
549
549
|
["Window: 24 hours", "24h"],
|
|
550
550
|
["Window: 7 days", "7d"],
|
|
551
|
+
["Window: 30 days", "30d"],
|
|
551
552
|
["Window: All time", "all"],
|
|
552
553
|
] as const) {
|
|
553
554
|
actions.push({ label, kind: "action", action: { type: "window", window } });
|
package/src/provider.ts
CHANGED
|
@@ -393,20 +393,51 @@ async function fetchZaiPlanQuota(
|
|
|
393
393
|
return classifyZaiLimits(payload.data.limits, payload.data.level ?? "");
|
|
394
394
|
}
|
|
395
395
|
|
|
396
|
+
const CODEX_FIVE_HOUR_SECONDS = 5 * 60 * 60;
|
|
397
|
+
const CODEX_WEEK_SECONDS = 7 * 24 * 60 * 60;
|
|
398
|
+
|
|
399
|
+
type PlanQuotaWindow = NonNullable<NonNullable<ProviderQuota["planQuota"]>["session5h"]>;
|
|
400
|
+
|
|
401
|
+
interface CodexQuotaWindow {
|
|
402
|
+
usedPct?: number;
|
|
403
|
+
resetAtSeconds?: number;
|
|
404
|
+
windowSeconds?: number;
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
function classifyCodexWindows(
|
|
408
|
+
primary?: CodexQuotaWindow | null,
|
|
409
|
+
secondary?: CodexQuotaWindow | null,
|
|
410
|
+
): { session5h?: PlanQuotaWindow; weekly?: PlanQuotaWindow } {
|
|
411
|
+
const windows = [primary, secondary].filter((window): window is CodexQuotaWindow => !!window);
|
|
412
|
+
const fiveHour = windows.find((window) => window.windowSeconds === CODEX_FIVE_HOUR_SECONDS);
|
|
413
|
+
const weekly = windows.find((window) => window.windowSeconds === CODEX_WEEK_SECONDS);
|
|
414
|
+
|
|
415
|
+
// Older responses omitted durations and consistently used primary for 5h and
|
|
416
|
+
// secondary for weekly. Only use that positional fallback for an unclassified window.
|
|
417
|
+
const sessionSource = fiveHour ?? (primary?.windowSeconds == null ? primary : undefined);
|
|
418
|
+
const weeklySource = weekly ?? (secondary?.windowSeconds == null ? secondary : undefined);
|
|
419
|
+
const materialize = (window?: CodexQuotaWindow | null): PlanQuotaWindow | undefined =>
|
|
420
|
+
window?.usedPct != null && window.resetAtSeconds != null
|
|
421
|
+
? { usedPct: window.usedPct, resetMs: window.resetAtSeconds * 1000 }
|
|
422
|
+
: undefined;
|
|
423
|
+
|
|
424
|
+
return {
|
|
425
|
+
session5h: materialize(sessionSource),
|
|
426
|
+
weekly: materialize(weeklySource),
|
|
427
|
+
};
|
|
428
|
+
}
|
|
429
|
+
|
|
396
430
|
/**
|
|
397
431
|
* Parse OpenAI Codex subscription quota from response headers captured via
|
|
398
|
-
* `after_provider_response`.
|
|
399
|
-
*
|
|
400
|
-
* management (unlike the `/wham/usage` REST endpoint, whose OAuth token in
|
|
401
|
-
* `~/.codex/auth.json` is frequently stale/rotated).
|
|
432
|
+
* `after_provider_response`. Window durations determine the labels because
|
|
433
|
+
* OpenAI may report a weekly-only quota in the primary slot.
|
|
402
434
|
*
|
|
403
435
|
* Header families (authoritative: openai/codex rate_limits.rs):
|
|
404
|
-
* x-codex-primary-used-percent
|
|
405
|
-
* x-codex-primary-
|
|
406
|
-
* x-codex-secondary-
|
|
407
|
-
* x-codex-secondary-reset-at — unix SECONDS
|
|
436
|
+
* x-codex-{primary,secondary}-used-percent — window used % (0-100)
|
|
437
|
+
* x-codex-{primary,secondary}-window-minutes — window duration
|
|
438
|
+
* x-codex-{primary,secondary}-reset-at — unix seconds of next reset
|
|
408
439
|
* x-codex-credits-has-credits / -unlimited / -balance — purchased credits
|
|
409
|
-
* x-codex-limit-name
|
|
440
|
+
* x-codex-limit-name — plan/limit display name
|
|
410
441
|
*
|
|
411
442
|
* Returns the planQuota shape (shared with ZAI) when any Codex window is present.
|
|
412
443
|
*/
|
|
@@ -425,8 +456,10 @@ export function parseCodexQuota(
|
|
|
425
456
|
|
|
426
457
|
const pctPrimary = num(get("x-codex-primary-used-percent"));
|
|
427
458
|
const pctSecondary = num(get("x-codex-secondary-used-percent"));
|
|
428
|
-
const resetPrimary = num(get("x-codex-primary-reset-at"));
|
|
459
|
+
const resetPrimary = num(get("x-codex-primary-reset-at"));
|
|
429
460
|
const resetSecondary = num(get("x-codex-secondary-reset-at"));
|
|
461
|
+
const minutesPrimary = num(get("x-codex-primary-window-minutes"));
|
|
462
|
+
const minutesSecondary = num(get("x-codex-secondary-window-minutes"));
|
|
430
463
|
const limitName = get("x-codex-limit-name");
|
|
431
464
|
|
|
432
465
|
if (pctPrimary == null && pctSecondary == null) return undefined;
|
|
@@ -441,35 +474,40 @@ export function parseCodexQuota(
|
|
|
441
474
|
credits = { balance, unlimited };
|
|
442
475
|
}
|
|
443
476
|
|
|
477
|
+
const windows = classifyCodexWindows(
|
|
478
|
+
{
|
|
479
|
+
usedPct: pctPrimary,
|
|
480
|
+
resetAtSeconds: resetPrimary,
|
|
481
|
+
windowSeconds: minutesPrimary == null ? undefined : minutesPrimary * 60,
|
|
482
|
+
},
|
|
483
|
+
{
|
|
484
|
+
usedPct: pctSecondary,
|
|
485
|
+
resetAtSeconds: resetSecondary,
|
|
486
|
+
windowSeconds: minutesSecondary == null ? undefined : minutesSecondary * 60,
|
|
487
|
+
},
|
|
488
|
+
);
|
|
489
|
+
|
|
444
490
|
return {
|
|
445
491
|
plan: limitName ?? "codex",
|
|
446
|
-
|
|
447
|
-
pctPrimary != null && resetPrimary != null
|
|
448
|
-
? { usedPct: pctPrimary, resetMs: resetPrimary * 1000 }
|
|
449
|
-
: undefined,
|
|
450
|
-
weekly:
|
|
451
|
-
pctSecondary != null && resetSecondary != null
|
|
452
|
-
? { usedPct: pctSecondary, resetMs: resetSecondary * 1000 }
|
|
453
|
-
: undefined,
|
|
492
|
+
...windows,
|
|
454
493
|
credits,
|
|
455
494
|
};
|
|
456
495
|
}
|
|
457
496
|
|
|
458
497
|
const CODEX_USAGE_URL = "https://chatgpt.com/backend-api/wham/usage";
|
|
459
498
|
|
|
499
|
+
interface CodexUsageWindow {
|
|
500
|
+
used_percent?: number;
|
|
501
|
+
reset_at?: number;
|
|
502
|
+
limit_window_seconds?: number;
|
|
503
|
+
}
|
|
504
|
+
|
|
460
505
|
interface CodexUsage {
|
|
461
506
|
plan_type?: string;
|
|
462
507
|
rate_limit?: {
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
limit_window_seconds?: number;
|
|
467
|
-
};
|
|
468
|
-
secondary_window?: {
|
|
469
|
-
used_percent?: number;
|
|
470
|
-
reset_at?: number;
|
|
471
|
-
limit_window_seconds?: number;
|
|
472
|
-
};
|
|
508
|
+
limit_name?: string;
|
|
509
|
+
primary_window?: CodexUsageWindow | null;
|
|
510
|
+
secondary_window?: CodexUsageWindow | null;
|
|
473
511
|
};
|
|
474
512
|
credits?: {
|
|
475
513
|
has_credits?: boolean;
|
|
@@ -561,23 +599,24 @@ export async function fetchCodexQuota(
|
|
|
561
599
|
const rl = json.rate_limit;
|
|
562
600
|
const primary = rl?.primary_window;
|
|
563
601
|
const secondary = rl?.secondary_window;
|
|
564
|
-
const plan
|
|
565
|
-
|
|
602
|
+
const plan = rl?.limit_name || json.plan_type || "codex";
|
|
603
|
+
const windows = classifyCodexWindows(
|
|
604
|
+
primary && {
|
|
605
|
+
usedPct: primary.used_percent,
|
|
606
|
+
resetAtSeconds: primary.reset_at,
|
|
607
|
+
windowSeconds: primary.limit_window_seconds,
|
|
608
|
+
},
|
|
609
|
+
secondary && {
|
|
610
|
+
usedPct: secondary.used_percent,
|
|
611
|
+
resetAtSeconds: secondary.reset_at,
|
|
612
|
+
windowSeconds: secondary.limit_window_seconds,
|
|
613
|
+
},
|
|
614
|
+
);
|
|
566
615
|
|
|
567
616
|
return {
|
|
568
617
|
quota: {
|
|
569
618
|
plan,
|
|
570
|
-
|
|
571
|
-
primary?.used_percent != null && primary.reset_at != null
|
|
572
|
-
? { usedPct: primary.used_percent, resetMs: primary.reset_at * 1000 }
|
|
573
|
-
: undefined,
|
|
574
|
-
weekly:
|
|
575
|
-
secondary?.used_percent != null && secondary.reset_at != null
|
|
576
|
-
? {
|
|
577
|
-
usedPct: secondary.used_percent,
|
|
578
|
-
resetMs: secondary.reset_at * 1000,
|
|
579
|
-
}
|
|
580
|
-
: undefined,
|
|
619
|
+
...windows,
|
|
581
620
|
credits: json.credits
|
|
582
621
|
? {
|
|
583
622
|
balance: Number(json.credits.balance ?? 0),
|
package/src/view.ts
CHANGED
|
@@ -2,13 +2,20 @@
|
|
|
2
2
|
* Interactive usage panel TUI component.
|
|
3
3
|
*
|
|
4
4
|
* Rendered via ctx.ui.custom(). Mirrors Claude Code's `/usage` screen:
|
|
5
|
-
* always-visible 5-hour and weekly quota bars, a selectable
|
|
6
|
-
*
|
|
5
|
+
* always-visible 5-hour and weekly quota bars, a selectable 5-hour/day/week/
|
|
6
|
+
* month/all window on the generic-window views, and independent-characteristic
|
|
7
|
+
* breakdowns by model / skill / plugin / tool /
|
|
7
8
|
* project. Supports vertical scrolling for small terminals.
|
|
8
9
|
*/
|
|
9
10
|
import type { Theme, ThemeColor } from "@earendil-works/pi-coding-agent";
|
|
10
11
|
import type { TUI } from "@earendil-works/pi-tui";
|
|
11
|
-
import {
|
|
12
|
+
import {
|
|
13
|
+
Key,
|
|
14
|
+
matchesKey,
|
|
15
|
+
stripTerminalSequences,
|
|
16
|
+
truncateToWidth,
|
|
17
|
+
visibleWidth,
|
|
18
|
+
} from "@earendil-works/pi-tui";
|
|
12
19
|
import {
|
|
13
20
|
type AttributionMaps,
|
|
14
21
|
agentStats,
|
|
@@ -36,6 +43,7 @@ import {
|
|
|
36
43
|
type WindowedReport,
|
|
37
44
|
type WindowKey,
|
|
38
45
|
type WrappedStats,
|
|
46
|
+
windowMs,
|
|
39
47
|
windowize,
|
|
40
48
|
wrappedStats,
|
|
41
49
|
} from "./aggregate.ts";
|
|
@@ -67,6 +75,32 @@ import type { ProviderQuota } from "./provider.ts";
|
|
|
67
75
|
|
|
68
76
|
export type { ViewKey } from "./mascot.ts";
|
|
69
77
|
|
|
78
|
+
/**
|
|
79
|
+
* Control characters (besides ESC, which introduces legitimate theme SGR)
|
|
80
|
+
* that would move the cursor or occupy extra physical rows, desyncing
|
|
81
|
+
* pi-tui's one-string-per-row render accounting.
|
|
82
|
+
*/
|
|
83
|
+
// biome-ignore lint/suspicious/noControlCharactersInRegex: These ranges intentionally match display control characters.
|
|
84
|
+
const ROW_BREAKING_CHARS = /[\x00-\x08\x0a-\x1a\x1c-\x1f\x7f-\x9f]/g;
|
|
85
|
+
|
|
86
|
+
/** Flatten a composed line to one physical row; tabs match pi-tui's width model. */
|
|
87
|
+
function flattenLine(line: string): string {
|
|
88
|
+
return line.replace(/\t/g, " ").replace(ROW_BREAKING_CHARS, "");
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Sanitize untrusted session metadata (task text, agent/parent labels,
|
|
93
|
+
* statuses) for single-line rendering: drop smuggled terminal escapes and
|
|
94
|
+
* collapse all whitespace — newlines included — into single spaces. Without
|
|
95
|
+
* this, one logical "line" wraps into extra physical rows and the host's
|
|
96
|
+
* differential renderer clears and redraws the wrong rows.
|
|
97
|
+
*/
|
|
98
|
+
function inlineText(text: string): string {
|
|
99
|
+
const collapsed = stripTerminalSequences(text).replace(/\s+/g, " ");
|
|
100
|
+
// biome-ignore lint/suspicious/noControlCharactersInRegex: This pattern intentionally removes stray terminal escapes.
|
|
101
|
+
return flattenLine(collapsed).replace(/\x1b/g, "").trim();
|
|
102
|
+
}
|
|
103
|
+
|
|
70
104
|
/** Sort field for the Models table. */
|
|
71
105
|
type SortKey = "value" | "name";
|
|
72
106
|
|
|
@@ -74,6 +108,10 @@ type SortKey = "value" | "name";
|
|
|
74
108
|
type DailySortField = "tokens" | "cost" | "date";
|
|
75
109
|
type SortDir = "asc" | "desc";
|
|
76
110
|
|
|
111
|
+
function hasGenericWindow(view: ViewKey): boolean {
|
|
112
|
+
return view === "overview" || view === "models" || view === "delegation";
|
|
113
|
+
}
|
|
114
|
+
|
|
77
115
|
/** Semantic controls shared by terminal key handling and portable UI clients. */
|
|
78
116
|
export type UsageAction =
|
|
79
117
|
| { type: "view"; view: ViewKey }
|
|
@@ -339,6 +377,10 @@ export class UsageView {
|
|
|
339
377
|
return;
|
|
340
378
|
}
|
|
341
379
|
}
|
|
380
|
+
if (hasGenericWindow(this.state.view) && matchesKey(data, "m")) {
|
|
381
|
+
this.applyAction({ type: "window", window: "30d" });
|
|
382
|
+
return;
|
|
383
|
+
}
|
|
342
384
|
// Daily view: t/c/d choose the sort field; pressing the same key flips
|
|
343
385
|
// direction. Intercept before the global sort/window handlers.
|
|
344
386
|
if (this.state.view === "daily") {
|
|
@@ -445,9 +487,14 @@ export class UsageView {
|
|
|
445
487
|
}
|
|
446
488
|
}
|
|
447
489
|
|
|
448
|
-
/**
|
|
490
|
+
/**
|
|
491
|
+
* Final width clamp so one long line can never break the TUI layout. Also
|
|
492
|
+
* flattens every line to a single physical row (pi-tui's render contract);
|
|
493
|
+
* theme SGR escapes survive, stray control characters do not.
|
|
494
|
+
*/
|
|
449
495
|
private clampLine(line: string, width: number): string {
|
|
450
|
-
|
|
496
|
+
const flat = flattenLine(line);
|
|
497
|
+
return visibleWidth(flat) > width ? truncateToWidth(flat, width) : flat;
|
|
451
498
|
}
|
|
452
499
|
|
|
453
500
|
invalidate(): void {
|
|
@@ -463,6 +510,7 @@ export class UsageView {
|
|
|
463
510
|
}
|
|
464
511
|
|
|
465
512
|
private setWindow(key: WindowKey): void {
|
|
513
|
+
if (!hasGenericWindow(this.state.view)) return;
|
|
466
514
|
this.state.windowKey = key;
|
|
467
515
|
this.state.scroll = 0;
|
|
468
516
|
this.deps.tui?.requestRender();
|
|
@@ -858,7 +906,8 @@ export class UsageView {
|
|
|
858
906
|
const total = bucketTokens(win.total);
|
|
859
907
|
const unit = this.unitForWindow(win);
|
|
860
908
|
const delegatedValue = unit === "usd" ? win.delegated.cost : delegated;
|
|
861
|
-
const
|
|
909
|
+
const horizon = windowMs(win.window);
|
|
910
|
+
const cutoff = Number.isFinite(horizon) ? Date.now() - horizon : -1;
|
|
862
911
|
const selectedTurns = report.entries.filter((turn) => cutoff === -1 || turn.ts >= cutoff);
|
|
863
912
|
lines.push(` ${theme.fg("accent", theme.bold("Composition"))}`);
|
|
864
913
|
if (w < 54) {
|
|
@@ -949,13 +998,15 @@ export class UsageView {
|
|
|
949
998
|
const duration =
|
|
950
999
|
child.endedAt > child.startedAt ? formatDuration(child.endedAt - child.startedAt) : "—";
|
|
951
1000
|
const mode = child.isBackground == null ? "" : child.isBackground ? " bg" : " fg";
|
|
952
|
-
return { value, duration, status: `${child.status}${mode}` };
|
|
1001
|
+
return { value, duration, status: `${inlineText(child.status) || "unknown"}${mode}` };
|
|
953
1002
|
};
|
|
954
1003
|
if (w < 54) {
|
|
955
1004
|
// Narrow terminals: two-line rows keep the task name readable.
|
|
956
1005
|
for (const child of win.children.slice(0, 20)) {
|
|
957
1006
|
const row = childRow(child);
|
|
958
|
-
lines.push(
|
|
1007
|
+
lines.push(
|
|
1008
|
+
` ${theme.fg("text", truncateToWidth(inlineText(child.task) || "(untitled)", Math.max(10, w - 4)))}`,
|
|
1009
|
+
);
|
|
959
1010
|
lines.push(
|
|
960
1011
|
` ${theme.fg("dim", `${row.value} · ${row.duration} · `)}${theme.fg("success", row.status)}`,
|
|
961
1012
|
);
|
|
@@ -968,7 +1019,7 @@ export class UsageView {
|
|
|
968
1019
|
for (const child of win.children.slice(0, 20)) {
|
|
969
1020
|
const row = childRow(child);
|
|
970
1021
|
lines.push(
|
|
971
|
-
` ${theme.fg("text", truncateToWidth(child.task, taskW).padEnd(taskW))} ${theme.fg("muted", truncateToWidth(row.value, 8).padStart(8))} ${theme.fg("dim", truncateToWidth(row.duration, 7).padStart(7))} ${theme.fg("success", truncateToWidth(row.status, 12))}`,
|
|
1022
|
+
` ${theme.fg("text", truncateToWidth(inlineText(child.task) || "(untitled)", taskW).padEnd(taskW))} ${theme.fg("muted", truncateToWidth(row.value, 8).padStart(8))} ${theme.fg("dim", truncateToWidth(row.duration, 7).padStart(7))} ${theme.fg("success", truncateToWidth(row.status, 12))}`,
|
|
972
1023
|
);
|
|
973
1024
|
}
|
|
974
1025
|
}
|
|
@@ -977,16 +1028,6 @@ export class UsageView {
|
|
|
977
1028
|
lines.push("");
|
|
978
1029
|
}
|
|
979
1030
|
|
|
980
|
-
private windowDuration(key: WindowKey): number {
|
|
981
|
-
return key === "5h"
|
|
982
|
-
? 5 * 60 * 60 * 1000
|
|
983
|
-
: key === "24h"
|
|
984
|
-
? 24 * 60 * 60 * 1000
|
|
985
|
-
: key === "7d"
|
|
986
|
-
? 7 * 24 * 60 * 60 * 1000
|
|
987
|
-
: Number.POSITIVE_INFINITY;
|
|
988
|
-
}
|
|
989
|
-
|
|
990
1031
|
private zeroBucket(): Bucket {
|
|
991
1032
|
return {
|
|
992
1033
|
cost: 0,
|
|
@@ -1929,11 +1970,16 @@ export class UsageView {
|
|
|
1929
1970
|
}
|
|
1930
1971
|
|
|
1931
1972
|
private windowTabs(): string {
|
|
1973
|
+
if (!hasGenericWindow(this.state.view)) return "";
|
|
1932
1974
|
const { theme } = this.deps;
|
|
1933
1975
|
const cur = this.state.windowKey;
|
|
1934
1976
|
const tabs: string[] = [];
|
|
1935
|
-
for (const key of ["5h", "24h", "7d", "all"] as WindowKey[]) {
|
|
1936
|
-
const label = key
|
|
1977
|
+
for (const key of ["5h", "24h", "7d", "30d", "all"] as WindowKey[]) {
|
|
1978
|
+
const label = key
|
|
1979
|
+
.toUpperCase()
|
|
1980
|
+
.replace("24H", "DAY")
|
|
1981
|
+
.replace("7D", "WEEK")
|
|
1982
|
+
.replace("30D", "MONTH");
|
|
1937
1983
|
const text = ` ${label} `;
|
|
1938
1984
|
tabs.push(
|
|
1939
1985
|
key === cur
|
|
@@ -2366,7 +2412,7 @@ export class UsageView {
|
|
|
2366
2412
|
|
|
2367
2413
|
for (const [key, bucket] of shown) {
|
|
2368
2414
|
const value = bucketValue(bucket);
|
|
2369
|
-
const name = truncateToWidth(labelFn(key), labelW).padEnd(labelW);
|
|
2415
|
+
const name = truncateToWidth(inlineText(labelFn(key)) || "—", labelW).padEnd(labelW);
|
|
2370
2416
|
const pct = percent(value, total);
|
|
2371
2417
|
const ratio = total > 0 ? value / total : 0;
|
|
2372
2418
|
const filled = Math.max(ratio > 0 ? 1 : 0, Math.round(ratio * barW));
|
|
@@ -2473,10 +2519,10 @@ export class UsageView {
|
|
|
2473
2519
|
const view = this.state.view;
|
|
2474
2520
|
const keys: Array<[string, string]> = [["⇥/←→", "views"]];
|
|
2475
2521
|
if (view === "overview" || view === "models") {
|
|
2476
|
-
keys.push(["5/d/w/a", "window"]);
|
|
2522
|
+
keys.push(["5/d/w/m/a", "window"]);
|
|
2477
2523
|
} else if (view === "delegation") {
|
|
2478
2524
|
// Delegation honours the window too (5 stays reserved for the Stats tab).
|
|
2479
|
-
keys.push(["d/w/a", "window"]);
|
|
2525
|
+
keys.push(["d/w/m/a", "window"]);
|
|
2480
2526
|
}
|
|
2481
2527
|
if (view === "models") {
|
|
2482
2528
|
keys.push(["c/n", "sort"]);
|
|
@@ -2530,6 +2576,8 @@ function labelForWindow(key: WindowKey): string {
|
|
|
2530
2576
|
return "last 24 hours";
|
|
2531
2577
|
case "7d":
|
|
2532
2578
|
return "last 7 days";
|
|
2579
|
+
case "30d":
|
|
2580
|
+
return "last 30 days";
|
|
2533
2581
|
case "all":
|
|
2534
2582
|
return "all time";
|
|
2535
2583
|
}
|