@fyeeme/pi-statusline 1.2.4 → 1.2.5

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,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [1.2.5] - 2026-09-18
11
+
12
+ ### Changed
13
+
14
+ - Compact token segment: `tokens 78.9%(↑in ↓out Rcache)` replaces `tokens total(in, out, cache,hit%)`. Cache hit rate moves to the front; the total and cache-write numbers are no longer displayed.
15
+ - ZAI quota segments made symmetric and labeled: `5h 42%(1.2M,1h23m) · wk 35%(12M,3d4h)` replaces `Usage 42%(1h23m) · W:35%(1.2M,3d4h)`. Both windows now show in-window token usage (the 5h window is summed via the model-usage API over `[resetAt - 5h, now]`); the natural-week fallback stays `wk 1.2M`. The context segment gains a `Ctx` prefix (`Ctx 45.2%/64k`).
16
+
10
17
  ## [1.2.4] - 2026-09-10
11
18
 
12
19
  ### Changed
package/README.md CHANGED
@@ -9,7 +9,7 @@ A rich custom status bar for [pi](https://pi.dev) that replaces the default foot
9
9
 
10
10
  - **Provider-aware usage** — special support for DeepSeek and GLM/ZAI (see [Provider Support](#provider-support))
11
11
  - **DeepSeek peak/off-peak pricing** — session cost follows DeepSeek's 2026-08-17 peak/off-peak billing (peak 9:00-12:00 / 14:00-18:00 Beijing time on weekdays; weekends are off-peak all day since 2026-08-23), priced per-message by timestamp, with a live `peak`/`off-peak` indicator in the footer (see [DeepSeek](#deepseek))
12
- - **Token usage**: input, output, cache read/write, total per session, with cache hit rate
12
+ - **Token usage**: compact `tokens 78.9%(↑in ↓out Rcache)` segment with cache hit rate
13
13
  - **Cost**: cumulative session cost with currency auto-detection (¥ for DeepSeek/CNY, $ otherwise)
14
14
  - **Context window**: usage percentage and size
15
15
  - **Timing**: elapsed time + tokens/sec for last response
@@ -62,12 +62,12 @@ Shows **5-hour rolling quota** and **weekly quota** (or natural-week usage as fa
62
62
 
63
63
  | Segment | Example | Source |
64
64
  |---------|---------|--------|
65
- | 5h quota | `Usage 42%(1h23m)` | `GET /api/monitor/usage/quota/limit` (`unit:3`) |
66
- | Weekly quota | `W:35%(1.2M,3d4h)` | `quota/limit` (`unit:6`) + `model-usage` API |
67
- | Natural week | `W:1.2M` | `model-usage` API (Mon 00:00 local → now) |
65
+ | 5h quota | `5h 42%(1.2M,1h23m)` | `quota/limit` (`unit:3`) + `model-usage` API |
66
+ | Weekly quota | `wk 35%(12M,3d4h)` | `quota/limit` (`unit:6`) + `model-usage` API |
67
+ | Natural week | `wk 1.2M` | `model-usage` API (Mon 00:00 local → now) |
68
68
 
69
- - **5-hour rolling window**: percentage used + countdown to reset
70
- - **Weekly quota**: if the plan exposes a `unit:6` weekly limit, shows percentage, tokens, and reset countdown; otherwise falls back to real usage for the current natural week (host local timezone)
69
+ - **5-hour rolling window**: percentage used, in-window token usage, countdown to reset
70
+ - **Weekly quota**: if the plan exposes a `unit:6` weekly limit, shows percentage, in-week token usage, and reset countdown; otherwise falls back to real usage for the current natural week (host local timezone)
71
71
  - **Account level**: also fetched (visible in `/status-debug`)
72
72
  - Supports both `zai` (`api.z.ai`) and `zai-coding-cn` (`open.bigmodel.cn`) endpoints
73
73
 
@@ -121,7 +121,7 @@ See the Pi Packages guide on [pi.dev](https://pi.dev) for the full list of sourc
121
121
 
122
122
  ```
123
123
  ~/projects/my-repo (main) deepseek-v4-pro · xhigh
124
- tokens 65k(in 12k, out 8k, cache 45k) · ¥0.12/50.00 · 7d:1.2M · off-peak · 45.2%/64k · 2m30s 38.2tok/s
124
+ tokens 78.9%(↑12k ↓8k R45k) · ¥0.12/50.00 · 7d:1.2M · off-peak · Ctx 45.2%/64k · 2m30s 38.2tok/s
125
125
  ```
126
126
 
127
127
  **Line 1**: cwd + git branch (left) | model + thinking level (right)
@@ -132,7 +132,7 @@ tokens 65k(in 12k, out 8k, cache 45k) · ¥0.12/50.00 · 7d:1.2M · off-peak ·
132
132
 
133
133
  ```
134
134
  ~/projects/my-repo (main) glm-4.6 · high
135
- tokens 65k(in 12k, out 8k, cache 45k) · Usage 42%(1h23m) · W:35%(1.2M,3d4h) · 45.2%/64k · 2m30s 38.2tok/s
135
+ tokens 78.9%(↑12k ↓8k R45k) · 5h 42%(1.2M,1h23m) · wk 35%(12M,3d4h) · Ctx 45.2%/64k · 2m30s 38.2tok/s
136
136
  ```
137
137
 
138
138
  ## Environment Variables
package/footer.ts CHANGED
@@ -78,22 +78,17 @@ export function buildStatLine(
78
78
  ): string {
79
79
  const mods: string[] = [];
80
80
 
81
- // tokens 566k(in 29k, out 22k, cache 515k,45.2%)
81
+ // tokens 45.2%(↑29k ↓22k R515k)
82
82
  {
83
83
  const tok: string[] = [];
84
- if (stats.input) tok.push(`in ${fmt(stats.input)}`);
85
- if (stats.output) tok.push(`out ${fmt(stats.output)}`);
86
- const cache = stats.cacheRead + stats.cacheWrite;
87
- if (cache) {
88
- const cacheStr = stats.hitRate > 0
89
- ? `cache ${fmt(cache)},${(stats.hitRate * 100).toFixed(1)}%`
90
- : `cache ${fmt(cache)}`;
91
- tok.push(cacheStr);
92
- }
93
- if (tok.length > 0 && stats.total) {
94
- mods.push(`tokens ${fmt(stats.total)}(${tok.join(", ")})`);
95
- } else if (tok.length > 0) {
96
- mods.push(tok.join(", "));
84
+ if (stats.input) tok.push(`↑${fmt(stats.input)}`);
85
+ if (stats.output) tok.push(`↓${fmt(stats.output)}`);
86
+ if (stats.cacheRead) tok.push(`R${fmt(stats.cacheRead)}`);
87
+ if (tok.length > 0) {
88
+ const pct = stats.hitRate > 0 ? ` ${(stats.hitRate * 100).toFixed(1)}%` : "";
89
+ mods.push(`tokens${pct}(${tok.join(" ")})`);
90
+ } else if (stats.total) {
91
+ mods.push(`tokens ${fmt(stats.total)}`);
97
92
  }
98
93
  }
99
94
 
@@ -111,13 +106,13 @@ export function buildStatLine(
111
106
  }
112
107
  }
113
108
 
114
- // context: 45.2%/16k or ?/16k
109
+ // Ctx: 45.2%/16k or ?/16k
115
110
  if (contextUsage) {
116
111
  const w = fmt(contextUsage.contextWindow);
117
112
  mods.push(
118
113
  contextUsage.percent !== null
119
- ? `${contextUsage.percent.toFixed(1)}%/${w}`
120
- : `?/${w}`,
114
+ ? `Ctx ${contextUsage.percent.toFixed(1)}%/${w}`
115
+ : `Ctx ?/${w}`,
121
116
  );
122
117
  }
123
118
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fyeeme/pi-statusline",
3
- "version": "1.2.4",
3
+ "version": "1.2.5",
4
4
  "description": "Rich custom status bar for pi with token usage, cost, DeepSeek balance, context window, and timing.",
5
5
  "type": "module",
6
6
  "license": "MIT",
package/providers/zai.ts CHANGED
@@ -60,6 +60,7 @@ export class ZaiUsageProvider implements UsageProvider {
60
60
  const level = quotaData.data?.level ?? "";
61
61
 
62
62
  const now = Date.now();
63
+ let fiveHourTokens = 0;
63
64
  let weeklyTokens = 0;
64
65
  let weeklyResetAt = 0;
65
66
  let weeklyPct = 0;
@@ -83,10 +84,23 @@ export class ZaiUsageProvider implements UsageProvider {
83
84
  weeklyTokens = await this.fetchCycleUsage(origin, headers, cycleStart, now);
84
85
  }
85
86
 
87
+ // 5h rolling window: GLM starts the 5h window at the first request, so
88
+ // the current window spans [resetAt - 5h, now]. Sum model-usage over it.
89
+ const tokensResetAt = fiveHourLimit?.nextResetTime ?? 0;
90
+ if (tokensResetAt > 0) {
91
+ fiveHourTokens = await this.fetchCycleUsage(
92
+ origin,
93
+ headers,
94
+ tokensResetAt - 5 * 60 * 60 * 1000,
95
+ now,
96
+ );
97
+ }
98
+
86
99
  return {
87
100
  provider: model.provider,
88
101
  tokensLimitPct: fiveHourLimit?.percentage ?? 0,
89
- tokensResetAt: fiveHourLimit?.nextResetTime ?? 0,
102
+ tokensResetAt,
103
+ fiveHourTokens,
90
104
  level,
91
105
  weeklyTokens,
92
106
  weeklyResetAt,
@@ -103,18 +117,18 @@ export class ZaiUsageProvider implements UsageProvider {
103
117
  const zai = result as ZaiResult;
104
118
  const parts: string[] = [];
105
119
 
106
- // 5-hour rolling quota
107
- const countdown = formatCountdown(zai.tokensResetAt);
108
- parts.push(`Usage ${zai.tokensLimitPct}%(${countdown})`);
120
+ // 5h 42%(1.2M,1h23m) — 5-hour rolling window: pct(in-window tokens,reset countdown)
121
+ if (zai.tokensResetAt > 0) {
122
+ parts.push(`5h ${zai.tokensLimitPct}%(${fmt(zai.fiveHourTokens)},${formatCountdown(zai.tokensResetAt)})`);
123
+ }
109
124
 
110
- // Weekly quota
125
+ // wk 35%(12M,3d4h) — weekly quota; natural-week fallback has no pct → wk 1.2M
111
126
  if (zai.isNaturalWeek) {
112
127
  if (zai.weeklyTokens > 0) {
113
- parts.push(`W:${fmt(zai.weeklyTokens)}`);
128
+ parts.push(`wk ${fmt(zai.weeklyTokens)}`);
114
129
  }
115
- } else if (zai.weeklyTokens > 0 || zai.weeklyPct > 0) {
116
- const weeklyCountdown = formatWeeklyCountdown(zai.weeklyResetAt);
117
- parts.push(`W:${zai.weeklyPct}%(${fmt(zai.weeklyTokens)},${weeklyCountdown})`);
130
+ } else if (zai.weeklyResetAt > 0) {
131
+ parts.push(`wk ${zai.weeklyPct}%(${fmt(zai.weeklyTokens)},${formatWeeklyCountdown(zai.weeklyResetAt)})`);
118
132
  }
119
133
 
120
134
  return parts.join(" · ");
@@ -125,6 +139,7 @@ export class ZaiUsageProvider implements UsageProvider {
125
139
  const zai = result as ZaiResult;
126
140
  w(` tokensLimitPct: ${zai.tokensLimitPct}%`);
127
141
  w(` tokensResetAt: ${new Date(zai.tokensResetAt).toISOString()}`);
142
+ w(` fiveHourTokens: ${zai.fiveHourTokens}`);
128
143
  w(` level: ${zai.level}`);
129
144
  w(` weeklyTokens: ${zai.weeklyTokens}`);
130
145
  w(` weeklyPct: ${zai.weeklyPct}%`);
package/types.ts CHANGED
@@ -33,6 +33,8 @@ export type ZaiResult = {
33
33
  provider: "zai" | "zai-coding-cn";
34
34
  tokensLimitPct: number;
35
35
  tokensResetAt: number;
36
+ /** tokens used within the current 5-hour window (0 when unknown) */
37
+ fiveHourTokens: number;
36
38
  level: string;
37
39
  weeklyTokens: number;
38
40
  weeklyResetAt: number;