@fyeeme/pi-statusline 1.0.2 → 1.1.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 CHANGED
@@ -7,6 +7,19 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [1.1.0] - 2026-08-07
11
+
12
+ ### Added
13
+
14
+ - DeepSeek 结算币种感知定价(新模块 `cost.ts`):CNY 计费账户按官方 ¥ 单价重算(flash ¥1/¥2/¥0.02、pro ¥3/¥6/¥0.025 每百万 tokens),修正 pi 内置 USD 价低估约 7 倍;USD 计费账户保持 pi 内置价。
15
+ - balance API 自动探测账户结算币种;`/currency` 手动覆盖(auto/¥/$),切换后即时刷新注册表定价。
16
+ - 币种判定后即时对齐运行时注册表定价(覆盖与还原均可逆、跟随结算币种)。
17
+
18
+ ### Fixed
19
+
20
+ - USD 计费账户启动后不再整场会话停在 CNY 价:balance 探测到币种后立即重新应用定价补丁。
21
+ - 会话内新增 deepseek 模型(编辑 `models.json` + reload)后再次应用定价补丁时,不再因陈旧快照 + `registerProvider` 整表替换丢弃新增模型。
22
+
10
23
  ## [1.0.2] - 2025-07-15
11
24
 
12
25
  ### Fixed
package/README.md CHANGED
@@ -1,17 +1,55 @@
1
1
  # pi-statusline
2
2
 
3
- A rich custom status bar for [pi](https://pi.dev) that replaces the default footer.
3
+ [![npm version](https://img.shields.io/npm/v/@fyeeme/pi-statusline)](https://www.npmjs.com/package/@fyeeme/pi-statusline)
4
+ [![License](https://img.shields.io/npm/l/@fyeeme/pi-statusline)](LICENSE)
5
+
6
+ A rich custom status bar for [pi](https://pi.dev) that replaces the default footer. Provider-aware: shows live account balance for **DeepSeek** and rolling quota for **GLM/ZAI**, plus session tokens, cost, context window, and timing.
4
7
 
5
8
  ## Features
6
9
 
7
- - **Token usage**: input, output, cache read/write, total per session
8
- - **Cost**: cumulative cost with currency auto-detection (¥ for DeepSeek, $ otherwise)
9
- - **DeepSeek balance**: live account balance fetched on startup and cached for 5 minutes
10
+ - **Provider-aware usage** — special support for DeepSeek and GLM/ZAI (see [Provider Support](#provider-support))
11
+ - **Token usage**: input, output, cache read/write, total per session, with cache hit rate
12
+ - **Cost**: cumulative session cost with currency auto-detection (¥ for DeepSeek/CNY, $ otherwise)
10
13
  - **Context window**: usage percentage and size
11
14
  - **Timing**: elapsed time + tokens/sec for last response
12
- - **MCP status**: connected server count and total tool count
13
15
  - **Git branch**: current branch shown in cwd display
14
16
 
17
+ ## Provider Support
18
+
19
+ This extension uses a provider-aware strategy: when the active model belongs to a supported provider, the status bar shows live account-level usage data fetched directly from that provider's API. Other providers fall back to session-scoped cost only.
20
+
21
+ ### DeepSeek
22
+
23
+ Shows live **account balance** and **weekly token usage**.
24
+
25
+ | Segment | Example | Source |
26
+ |---------|---------|--------|
27
+ | Balance | `¥0.12/50.00` | `GET /user/balance` (cached 5 min) |
28
+ | Weekly tokens | `7d:1.2M` | Local session file scan (rolling 7 days) |
29
+
30
+ - Currency auto-detected as `¥` (CNY) from the balance API response
31
+ - Balance is fetched on startup and refreshed in the background; cached for 5 minutes
32
+ - Triggered when `model.provider === "deepseek"`
33
+
34
+ ### GLM / ZAI
35
+
36
+ Shows **5-hour rolling quota** and **weekly quota** (or natural-week usage as fallback).
37
+
38
+ | Segment | Example | Source |
39
+ |---------|---------|--------|
40
+ | 5h quota | `Usage 42%(1h23m)` | `GET /api/monitor/usage/quota/limit` (`unit:3`) |
41
+ | Weekly quota | `W:35%(1.2M,3d4h)` | `quota/limit` (`unit:6`) + `model-usage` API |
42
+ | Natural week | `W:1.2M` | `model-usage` API (Mon 00:00 local → now) |
43
+
44
+ - **5-hour rolling window**: percentage used + countdown to reset
45
+ - **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)
46
+ - **Account level**: also fetched (visible in `/status-debug`)
47
+ - Supports both `zai` (`api.z.ai`) and `zai-coding-cn` (`open.bigmodel.cn`) endpoints
48
+
49
+ ### Other providers
50
+
51
+ Session-scoped cost only (`$0.12` or `¥0.12`), with no live account data.
52
+
15
53
  ## Install
16
54
 
17
55
  Requires the [pi](https://pi.dev) CLI.
@@ -20,16 +58,16 @@ Requires the [pi](https://pi.dev) CLI.
20
58
 
21
59
  ```bash
22
60
  # Global (user) install — available in every project
23
- pi install npm:@fyeeme/pi-statusline
61
+ pi install @fyeeme/pi-statusline
24
62
 
25
63
  # Project-local — written to .pi/settings.json, shareable with your team
26
- pi install -l npm:@fyeeme/pi-statusline
64
+ pi install -l @fyeeme/pi-statusline
27
65
 
28
66
  # Pinned version — skipped by `pi update`
29
- pi install npm:@fyeeme/pi-statusline@1.0.0
67
+ pi install @fyeeme/pi-statusline@1.0.2
30
68
 
31
69
  # Try it once without saving (current run only)
32
- pi -e npm:@fyeeme/pi-statusline
70
+ pi -e @fyeeme/pi-statusline
33
71
  ```
34
72
 
35
73
  ### From GitHub
@@ -40,7 +78,7 @@ Source: [`fyeeme/pi-packages`](https://github.com/fyeeme/pi-packages).
40
78
  # HTTPS shorthand
41
79
  pi install git:github.com/fyeeme/pi-packages
42
80
  # Pin to a tag or commit (skipped by `pi update`)
43
- pi install git:github.com/fyeeme/pi-packages@v1.0.0
81
+ pi install git:github.com/fyeeme/pi-packages@v1.0.2
44
82
  # Raw URL form
45
83
  pi install https://github.com/fyeeme/pi-packages
46
84
  ```
@@ -51,20 +89,41 @@ See the Pi Packages guide on [pi.dev](https://pi.dev) for the full list of sourc
51
89
 
52
90
  | Command | Description |
53
91
  |---|---|
54
- | `/balance` | Force refresh DeepSeek account balance |
55
- | `/currency [auto\|¥\|$]` | Toggle cost currency display |
56
- | `/status-debug` | Dump session stats to `/tmp/pi-status-debug.log` |
92
+ | `/currency [auto\|¥\|$]` | Toggle cost currency display (`auto` follows DeepSeek → ¥) |
93
+ | `/status-debug` | Dump session stats + provider usage to `/tmp/pi-status-debug.log` |
57
94
 
58
95
  ## Status Bar Layout
59
96
 
60
97
  ```
61
98
  ~/projects/my-repo (main) deepseek-v3 · xhigh
62
- in 12k, out 8k, cache 45k, total 65k · ¥0.12/50.00 · 12.3%/64k · 45s 38.2tok/s · MCP:2(15)
99
+ tokens 65k(in 12k, out 8k, cache 45k) · ¥0.12/50.00 · 7d:1.2M · 45.2%/64k · 2m30s 38.2tok/s
63
100
  ```
64
101
 
65
- Line 1: cwd + git branch (left) | model + thinking level (right)
66
- Line 2: token stats · cost/balance · context · timing · MCP
102
+ **Line 1**: cwd + git branch (left) | model + thinking level (right)
103
+
104
+ **Line 2**: token stats · provider usage · context window · timing
105
+
106
+ ### GLM/ZAI example
107
+
108
+ ```
109
+ ~/projects/my-repo (main) glm-4.6 · high
110
+ tokens 65k(in 12k, out 8k, cache 45k) · Usage 42%(1h23m) · W:35%(1.2M,3d4h) · 45.2%/64k · 2m30s 38.2tok/s
111
+ ```
112
+
113
+ ## Environment Variables
114
+
115
+ None required. API keys are resolved automatically by pi's model registry for the active provider.
116
+
117
+ ## How It Works
118
+
119
+ The extension registers a `UsageProvider` per supported provider and refreshes usage data in the background (on startup, on model switch, and after each agent run). Results are cached with a 5-minute TTL (DeepSeek) or per-refresh (ZAI) to avoid hammering the provider APIs.
120
+
121
+ All network calls are best-effort with a 5-second timeout — failures stay silent and never block the status bar.
122
+
123
+ ## Changelog
124
+
125
+ See [CHANGELOG.md](CHANGELOG.md).
67
126
 
68
- ## MCP Integration
127
+ ## License
69
128
 
70
- When used with [pi-mcp-adapter](https://www.npmjs.com/package/pi-mcp-adapter), the status bar shows live MCP connection status via `mcp:status` and `mcp:disconnect` events.
129
+ MIT
package/cost.ts ADDED
@@ -0,0 +1,135 @@
1
+ /**
2
+ * DeepSeek 定价修正(跟随结算币种)。
3
+ *
4
+ * 背景:pi 内置的 deepseek 定价数据(pi-ai 的 providers/data/deepseek.json)用的是官方 USD 价
5
+ * (flash $0.14/0.28/0.0028、pro $0.435/0.87/0.003625 每百万 tokens)。DeepSeek 账户分 CNY 与 USD
6
+ * 两种结算:CNY 账户按 ¥1/¥2/¥0.02、¥3/¥6/¥0.025 计费,此时 pi 记录的成本低估约 7 倍;USD 账户
7
+ * 按 USD 计费,pi 内置价本来就是对的。
8
+ *
9
+ * 因此所有"修正"都必须跟随结算币种:
10
+ * 1. `deepSeekBilledInCny()`:判定 DeepSeek 是否按 CNY 计价 —— 用户显式 `/currency` 优先;
11
+ * 否则按 balance API 探测到的账户币种(探测失败/未知时按 CNY,保持原行为)。
12
+ * 2. `deepseekMessageCostCny`:按官方 CNY 单价重算单条消息成本(仅 CNY 计价时用于兜底存量消息,
13
+ * 会话文件里已记录的 cost 无法追溯修正)。
14
+ * 3. `applyDeepSeekPricingPatch`:运行时把注册表中 deepseek 模型定价覆盖为官方 CNY 价(仅 CNY
15
+ * 计价时;USD 计价时还原为 pi 内置 USD 价)。内存补丁,不修改数据文件、pi 升级不丢。
16
+ */
17
+ import type { Model, Api } from "@earendil-works/pi-ai";
18
+ import type { ModelRegistry } from "@earendil-works/pi-coding-agent";
19
+
20
+ export interface DeepSeekPricedUsage {
21
+ input: number;
22
+ output: number;
23
+ cacheRead: number;
24
+ cacheWrite: number;
25
+ }
26
+
27
+ /** DeepSeek 官方 CNY 单价(元 / 百万 tokens):缓存命中输入 / 未命中输入 / 输出(见官方定价页)。 */
28
+ export const DEEPSEEK_CNY_PRICES: Record<string, DeepSeekPricedUsage> = {
29
+ "deepseek-v4-flash": { input: 1, output: 2, cacheRead: 0.02, cacheWrite: 0 },
30
+ "deepseek-v4-pro": { input: 3, output: 6, cacheRead: 0.025, cacheWrite: 0 },
31
+ };
32
+
33
+ const PER_MILLION = 1_000_000;
34
+
35
+ // ---------------------------------------------------------------------------
36
+ // 结算币种状态(DeepSeek)
37
+ // ---------------------------------------------------------------------------
38
+
39
+ /** balance API 探测到的账户结算币种(CNY / USD / 其他)。 */
40
+ let detectedDeepSeekCurrency: string | null = null;
41
+ /** 用户显式 `/currency` 设置,覆盖自动判定。 */
42
+ let costCurrencyOverride: "¥" | "$" | undefined = undefined;
43
+ /** 首次 applyDeepSeekPricingPatch 时缓存的原始模型定义(用于 USD 计价时还原)。 */
44
+ let originalDeepSeekModels: Model<Api>[] | null = null;
45
+
46
+ /** 记录 balance API 探测到的 DeepSeek 账户结算币种(fetchUsage 成功后写入;null 表示未知)。 */
47
+ export function setDetectedDeepSeekCurrency(currency: string | null): void {
48
+ detectedDeepSeekCurrency = currency;
49
+ }
50
+
51
+ /** 设置用户显式币种偏好(`/currency` 命令);undefined 恢复自动判定。 */
52
+ export function setCostCurrencyOverride(override: "¥" | "$" | undefined): void {
53
+ costCurrencyOverride = override;
54
+ }
55
+
56
+ /** 当前用户显式币种偏好(undefined = 自动)。 */
57
+ export function getCostCurrencyOverride(): "¥" | "$" | undefined {
58
+ return costCurrencyOverride;
59
+ }
60
+
61
+ /**
62
+ * DeepSeek 是否按 CNY 计价:用户显式偏好优先;否则仅当探测明确为 USD 时按 USD 计价,
63
+ * 其余情况(CNY 或未知)按 CNY —— 保持原有"deepseek → ¥"的默认行为。
64
+ */
65
+ export function deepSeekBilledInCny(): boolean {
66
+ if (costCurrencyOverride === "$") return false;
67
+ if (costCurrencyOverride === "¥") return true;
68
+ return detectedDeepSeekCurrency !== "USD";
69
+ }
70
+
71
+ /** 重置币种状态与补丁缓存(测试用)。 */
72
+ export function resetDeepSeekPricingState(): void {
73
+ detectedDeepSeekCurrency = null;
74
+ costCurrencyOverride = undefined;
75
+ originalDeepSeekModels = null;
76
+ }
77
+
78
+ // ---------------------------------------------------------------------------
79
+ // 单条消息成本重算
80
+ // ---------------------------------------------------------------------------
81
+
82
+ /**
83
+ * 按官方 CNY 单价重算单条消息成本;模型不在定价表内返回 null(调用方回退 `m.usage.cost`)。
84
+ *
85
+ * @param model 消息模型 id(如 `deepseek-v4-flash`)
86
+ * @param usage 消息的 token 用量分解
87
+ */
88
+ export function deepseekMessageCostCny(
89
+ model: string | undefined,
90
+ usage: DeepSeekPricedUsage,
91
+ ): number | null {
92
+ if (!model) return null;
93
+ const p = DEEPSEEK_CNY_PRICES[model];
94
+ if (!p) return null;
95
+ return (
96
+ (p.input * usage.input +
97
+ p.output * usage.output +
98
+ p.cacheRead * usage.cacheRead +
99
+ p.cacheWrite * usage.cacheWrite) /
100
+ PER_MILLION
101
+ );
102
+ }
103
+
104
+ // ---------------------------------------------------------------------------
105
+ // 运行时注册表补丁(根治 pi 内置定价,可逆、跟随结算币种)
106
+ // ---------------------------------------------------------------------------
107
+
108
+ /**
109
+ * 把注册表中 deepseek 模型的定价与结算币种对齐:
110
+ * - CNY 计价:cost 覆盖为官方 CNY 价;
111
+ * - USD 计价:还原为 pi 内置 USD 价(首次调用时缓存原始定义,之后不再被 CNY 覆盖)。
112
+ * 未知/未来新增模型原样保留;重复调用幂等;注册表未加载模型时静默跳过(由调用方后续重试)。
113
+ */
114
+ export function applyDeepSeekPricingPatch(registry: ModelRegistry): void {
115
+ const dsModels = registry.getAll().filter((m) => m.provider === "deepseek");
116
+ if (dsModels.length === 0) return;
117
+ if (!originalDeepSeekModels) {
118
+ originalDeepSeekModels = dsModels;
119
+ } else {
120
+ // Merge in deepseek models added after the first snapshot, so a later
121
+ // re-patch(币种切换 / model_select / 探测后纠正)不会丢掉它们:registerProvider
122
+ // 是整表替换,用陈旧快照 map 会把新增模型从 registry 里静默删掉。
123
+ const known = new Set(originalDeepSeekModels.map((m) => m.id));
124
+ for (const m of dsModels) if (!known.has(m.id)) originalDeepSeekModels.push(m);
125
+ }
126
+
127
+ const billedInCny = deepSeekBilledInCny();
128
+ const models = originalDeepSeekModels.map((m) => {
129
+ if (!billedInCny) return m;
130
+ const cny = DEEPSEEK_CNY_PRICES[m.id];
131
+ if (!cny) return m;
132
+ return { ...m, cost: { ...m.cost, ...cny } };
133
+ });
134
+ registry.registerProvider("deepseek", { models });
135
+ }
package/index.ts CHANGED
@@ -22,6 +22,11 @@ import { DeepSeekUsageProvider } from "./providers/deepseek.ts";
22
22
  import { ZaiUsageProvider } from "./providers/zai.ts";
23
23
  import type { UsageProvider } from "./providers/types.ts";
24
24
  import { SessionTokenUsageCalculator } from "./token-usage.ts";
25
+ import {
26
+ applyDeepSeekPricingPatch,
27
+ setCostCurrencyOverride,
28
+ getCostCurrencyOverride,
29
+ } from "./cost.ts";
25
30
  import { refreshUsage, getCachedUsage, getUsageCacheAge } from "./cache.ts";
26
31
  import { formatCwd, buildStatLine, buildInfoLine } from "./footer.ts";
27
32
 
@@ -45,9 +50,8 @@ let lastModel: ExtensionContext["model"] = undefined;
45
50
  let agentRunning = false;
46
51
  let lastElapsedSec = 0;
47
52
  let lastTps = 0;
48
- let currencyOverride: "¥" | "$" | undefined = undefined;
49
53
 
50
- const tokenCalculator = new SessionTokenUsageCalculator(() => currencyOverride);
54
+ const tokenCalculator = new SessionTokenUsageCalculator(() => getCostCurrencyOverride());
51
55
 
52
56
  // ---------------------------------------------------------------------------
53
57
  // Helpers
@@ -158,17 +162,20 @@ export default function (pi: ExtensionAPI) {
158
162
  handler: async (args, ctx) => {
159
163
  const a = args.trim().toLowerCase();
160
164
  if (a === "auto" || a === "") {
161
- currencyOverride = undefined;
162
- ctx.ui.notify("Currency: auto (deepseek→¥)", "info");
165
+ setCostCurrencyOverride(undefined);
166
+ ctx.ui.notify("Currency: auto (deepseek→¥ or balance currency)", "info");
163
167
  } else if (a === "¥" || a === "rmb" || a === "cny") {
164
- currencyOverride = "¥";
168
+ setCostCurrencyOverride("¥");
165
169
  ctx.ui.notify("Currency: ¥", "info");
166
170
  } else if (a === "$" || a === "usd") {
167
- currencyOverride = "$";
171
+ setCostCurrencyOverride("$");
168
172
  ctx.ui.notify("Currency: $", "info");
169
173
  } else {
170
174
  ctx.ui.notify("Usage: /currency [auto|¥|$]", "warning");
175
+ return;
171
176
  }
177
+ // 币种变更后立即对齐注册表定价(CNY→覆盖为官方价;USD→还原 pi 内置价)
178
+ applyDeepSeekPricingPatch(ctx.modelRegistry);
172
179
  },
173
180
  });
174
181
 
@@ -176,6 +183,7 @@ export default function (pi: ExtensionAPI) {
176
183
  pi.on("model_select", (event) => {
177
184
  if (lastCtx) {
178
185
  lastModel = event.model;
186
+ applyDeepSeekPricingPatch(lastCtx.modelRegistry);
179
187
  void refreshUsage(providers, lastCtx.modelRegistry, event.model);
180
188
  }
181
189
  });
@@ -188,6 +196,9 @@ export default function (pi: ExtensionAPI) {
188
196
  lastElapsedSec = 0;
189
197
  lastTps = 0;
190
198
 
199
+ // 根治:运行时修正 deepseek 定价(pi 内置定价低估约 7 倍),使后续 usage.cost 记录全局正确
200
+ applyDeepSeekPricingPatch(ctx.modelRegistry);
201
+
191
202
  // Prime usage cache on startup (non-blocking)
192
203
  lastCtx = ctx;
193
204
  lastModel = ctx.model;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fyeeme/pi-statusline",
3
- "version": "1.0.2",
3
+ "version": "1.1.0",
4
4
  "description": "Rich custom status bar for pi with token usage, cost, DeepSeek balance, context window, timing, and MCP connection status.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -1,6 +1,7 @@
1
1
  import type { ExtensionContext } from "@earendil-works/pi-coding-agent";
2
2
  import type { DeepSeekResult, ProviderUsageResult } from "../types.ts";
3
3
  import type { UsageProvider } from "./types.ts";
4
+ import { applyDeepSeekPricingPatch, setDetectedDeepSeekCurrency } from "../cost.ts";
4
5
  import { scanWeeklyTokens } from "../session-scanner.ts";
5
6
  import { fmt } from "../footer.ts";
6
7
 
@@ -39,6 +40,13 @@ export class DeepSeekUsageProvider implements UsageProvider {
39
40
  const info = data.balance_infos?.[0];
40
41
  if (!info) return null;
41
42
 
43
+ // 记录账户结算币种:CNY 账户按官方 ¥ 价计费;USD 账户保持 pi 内置 USD 价(不覆盖)
44
+ setDetectedDeepSeekCurrency(info.currency ?? null);
45
+ // 探测到币种后立即重新对齐注册表定价:session_start 时(detectedDeepSeekCurrency 尚为
46
+ // null)已按默认 CNY 覆盖过一次;此处按真实币种纠正,避免 USD 账户停在被高估约 7 倍的
47
+ // CNY 价上,直到下一次 model_select/​/currency 才修正。
48
+ applyDeepSeekPricingPatch(modelRegistry);
49
+
42
50
  const weeklyTokens = scanWeeklyTokens("deepseek");
43
51
 
44
52
  return {
package/token-usage.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import type { AssistantMessage } from "@earendil-works/pi-ai";
2
2
  import type { ExtensionContext } from "@earendil-works/pi-coding-agent";
3
3
  import type { TokenUsage, TokenUsageCalculator } from "./types.ts";
4
+ import { deepSeekBilledInCny, deepseekMessageCostCny } from "./cost.ts";
4
5
 
5
6
  export class SessionTokenUsageCalculator implements TokenUsageCalculator {
6
7
  private getCurrencyOverride: () => "\u00a5" | "$" | undefined;
@@ -17,6 +18,8 @@ export class SessionTokenUsageCalculator implements TokenUsageCalculator {
17
18
  let total = 0;
18
19
  let cost = 0;
19
20
 
21
+ const billedInCny = deepSeekBilledInCny();
22
+
20
23
  for (const entry of ctx.sessionManager.getEntries()) {
21
24
  if (entry.type === "message" && entry.message.role === "assistant") {
22
25
  const m = entry.message as AssistantMessage;
@@ -25,7 +28,9 @@ export class SessionTokenUsageCalculator implements TokenUsageCalculator {
25
28
  cacheRead += m.usage.cacheRead;
26
29
  cacheWrite += m.usage.cacheWrite;
27
30
  total += m.usage.totalTokens;
28
- cost += m.usage.cost.total;
31
+ // DeepSeek 仅按 CNY 计价时重算(pi 内置 USD 价低估约 7 倍);USD 结算用户沿用 pi 记录的 cost
32
+ const dsCost = billedInCny ? deepseekMessageCostCny(m.model, m.usage) : null;
33
+ cost += dsCost !== null ? dsCost : (m.usage.cost?.total ?? 0);
29
34
  }
30
35
  }
31
36
 
@@ -37,7 +42,7 @@ export class SessionTokenUsageCalculator implements TokenUsageCalculator {
37
42
  currency = override;
38
43
  } else {
39
44
  const p = ctx.model?.provider ?? "";
40
- if (p.toLowerCase().includes("deepseek")) currency = "\u00a5";
45
+ if (p.toLowerCase().includes("deepseek")) currency = deepSeekBilledInCny() ? "\u00a5" : "$";
41
46
  }
42
47
 
43
48
  return { input, output, cacheRead, cacheWrite, total, hitRate, cost, currency };