pi-ark-usage 0.1.4 → 0.1.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/README.md CHANGED
@@ -3,14 +3,15 @@
3
3
  在 pi TUI 中显示**火山引擎方舟 Coding Plan / Agent Plan** 的套餐用量,数据直接来自火山方舟 OpenAPI `GetCodingPlanUsage`(AK/SK 签名,官方 [`@volcengine/openapi`](https://github.com/volcengine/volc-sdk-nodejs) SDK 的 Signer)。
4
4
 
5
5
  ```
6
- Volc Usage: sess 30%(reset after 4h18m) / wk 37%(reset after 4d) / mo 19%(reset after 29d) now
6
+ 1% 4h38m | 15% 5d4h | 54% 23d4h | 3m ago
7
7
  ```
8
8
 
9
9
  ## 特性
10
10
 
11
11
  - **AK/SK 直连 OpenAPI**:不走子进程、不依赖 SSO 登录态;凭据只从环境变量或配置文件读取,本扩展不保存、不上传任何 Key
12
12
  - **三个周期同屏**:session(会话)/ weekly(周)/ monthly(月),并显示各周期重置倒计时
13
- - **Powerline 状态段(唯一展示位)**:通过 `ctx.ui.setStatus("ark-usage", …)` 发布单行摘要(`1% 4h38m | 15% 5d4h | 54% 23d4h`,固定按 session/weekly/monthly 顺序),显示在 [pi-powerline-footer](https://www.npmjs.com/package/pi-powerline-footer) 上;百分比按阈值绿/黄/红着色,时间部分紫色,分隔符跟随主题 `thinkingHigh`(编辑器边框色)。不安装 powerline 时也可通过内置 footer 的 extension statuses 区域或 `/arkusage` 查看
13
+ - **Powerline 状态段(唯一展示位)**:通过 `ctx.ui.setStatus("ark-usage", …)` 发布单行摘要(`1% 4h38m | 15% 5d4h | 54% 23d4h | 3m ago`,固定按 session/weekly/monthly 顺序),显示在 [pi-powerline-footer](https://www.npmjs.com/package/pi-powerline-footer) 上;百分比按阈值绿/黄/红着色,时间部分紫色,分隔符跟随主题 `thinkingHigh`(编辑器边框色),末尾的「上次刷新」用 `dim` 渲染以示区隔。不安装 powerline 时也可通过内置 footer 的 extension statuses 区域或 `/arkusage` 查看
14
+ - **上次刷新时间**:状态段末尾显示距今多久前**成功**刷新过(分钟精度:`just now` / `3m ago` / `4h38m ago` / `5d4h ago`)。抓取失败时沿用上一次成功的时间,因此该值持续变大即表示刷新已经失败或长时间未刷新
14
15
  - **阈值着色**:低用量绿色(<50%)、接近上限黄色(50–79%)、超过红线红色(≥80%,默认值,可用 `/arkset` 调整)
15
16
  - **持久化缓存**:重启 pi 后立即显示上次快照(`~/.pi/agent/pi-ark-usage/cache.json`,0600 权限,临时文件原子写入)
16
17
  - 可选空闲自动刷新(默认关闭)
@@ -97,7 +98,7 @@ pi install npm:pi-ark-usage
97
98
  1. 用官方 `@volcengine/openapi` 的 `Signer` 对 `POST open.volcengineapi.com?Action=GetCodingPlanUsage&Version=2024-01-01`(service `ark`,region `cn-beijing`)做 V4 签名后 fetch。
98
99
  2. 解析 `Result.QuotaUsage[]`(`Level/Percent/ResetTimestamp`,秒级时间戳转 `+08:00` ISO 字符串),做结构与取值校验。
99
100
  3. 快照存入内存 Map,并以原子写(tmp 文件 + rename)持久化到 `~/.pi/agent/pi-ark-usage/`。
100
- 4. 摘要通过 `ctx.ui.setStatus("ark-usage", …)` 发布到 extension status,由 pi-powerline-footer 渲染到 powerline 行;每分钟 ticker 在空闲时重发,保持重置倒计时刷新。
101
+ 4. 摘要通过 `ctx.ui.setStatus("ark-usage", …)` 发布到 extension status,由 pi-powerline-footer 渲染到 powerline 行;每分钟 ticker 在空闲时重发,保持重置倒计时与「上次刷新」时长显示为最新。
101
102
 
102
103
  ## 开发
103
104
 
@@ -6,7 +6,9 @@
6
6
  * the official `@volcengine/openapi` Signer. This extension never stores keys:
7
7
  * credentials come from VOLC_ACCESSKEY/VOLC_SECRETKEY or ~/.volc/config.
8
8
  *
9
- * Powerline status (via `ctx.ui.setStatus`): 1% 4h38m | 15% 5d4h | 54% 23d4h
9
+ * Powerline status (via `ctx.ui.setStatus`):
10
+ * 1% 4h38m | 15% 5d4h | 54% 23d4h | 3m ago
11
+ * The trailing segment is how long ago the data was last refreshed.
10
12
  * Commands:
11
13
  * /arkcheck force refresh
12
14
  * /arkusage show snapshot in a notification
@@ -202,9 +202,25 @@ export function formatCompactRemaining(ms: number): string {
202
202
  return `${m}m`;
203
203
  }
204
204
 
205
+ /**
206
+ * Age of the last successful refresh, for the trailing status segment:
207
+ * `just now`, `3m ago`, `4h38m ago`, `5d4h ago`. Minute is the finest unit —
208
+ * seconds would only make the line jitter — and a stale cached snapshot thus
209
+ * reads as old at a glance.
210
+ */
211
+ export function formatRefreshAgo(ts: number, now: number = Date.now()): string {
212
+ if (!Number.isFinite(ts) || ts <= 0) return "";
213
+ const ms = now - ts;
214
+ // Clock skew can make a fresh fetch look negative; treat it as "now".
215
+ if (ms < 60_000) return "just now";
216
+ // Drop a zero lower unit (`1h0m` -> `1h`, `5d0h` -> `5d`).
217
+ const age = formatCompactRemaining(ms).replace(/([dh])0[mh]$/, "$1");
218
+ return `${age} ago`;
219
+ }
220
+
205
221
  /**
206
222
  * One-line colored summary for the powerline extension-status slot:
207
- * `1% 4h38m | 15% 5d4h | 54% 23d4h`
223
+ * `1% 4h38m | 15% 5d4h | 54% 23d4h | 3m ago`
208
224
  *
209
225
  * Periods are shown in API order (session / weekly / monthly) without
210
226
  * labels — the order itself is the convention. Percent follows the
@@ -212,24 +228,32 @@ export function formatCompactRemaining(ms: number): string {
212
228
  * red); the time part is always purple; the ` | ` separator uses the
213
229
  * editor border color (`thinkingHigh`, pink in the dark theme).
214
230
  *
231
+ * The last segment is how long ago the data was fetched, in `dim` — it is
232
+ * meta information, not usage, so it stays visually secondary.
233
+ *
215
234
  * Returns null when nothing should be shown (the powerline item hides).
216
235
  */
217
236
  export function buildCompactStatus(
218
237
  snapshot: PlanSnapshot | null,
219
238
  status: WidgetStatus,
220
239
  theme: Theme,
240
+ now: number = Date.now(),
221
241
  ): string | null {
222
242
  if (snapshot && snapshot.periods.length > 0) {
223
243
  const sep = theme.fg("thinkingHigh", " | ");
224
- return snapshot.periods
244
+ const periods = snapshot.periods
225
245
  .map((p) => {
226
246
  const pct = coloredPct(clampPct(p.percent));
227
247
  const reset = p.reset_at
228
- ? formatCompactRemaining(new Date(p.reset_at).getTime() - Date.now())
248
+ ? formatCompactRemaining(new Date(p.reset_at).getTime() - now)
229
249
  : "";
230
250
  return reset ? `${pct} ${hexFg(HEX_COLORS.purple, reset)}` : pct;
231
251
  })
232
252
  .join(sep);
253
+ const refreshed = formatRefreshAgo(snapshot.fetchedAt, now);
254
+ return refreshed
255
+ ? `${periods}${sep}${theme.fg("dim", refreshed)}`
256
+ : periods;
233
257
  }
234
258
  if (status === "fetching") return hexFg(HEX_COLORS.purple, "…");
235
259
  if (status === "failed") return hexFg(HEX_COLORS.red, "failed");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-ark-usage",
3
- "version": "0.1.4",
3
+ "version": "0.1.5",
4
4
  "description": "Show Volcengine Ark Coding Plan / Agent Plan usage in the pi TUI (AK/SK OpenAPI)",
5
5
  "keywords": [
6
6
  "pi",