# pi-usage-report

[![npm](https://img.shields.io/npm/v/pi-usage-report.svg)](https://www.npmjs.com/package/pi-usage-report)
[![license: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](./LICENSE)

[English](./README.md) | **简体中文**

> 一个 [pi](https://pi.dev) 扩展：统计 **token 用量与费用估算**，支持「当日 / 本周 / 本月 / 任意时间段」，
> 并按**本地货币**折算金额。

零配置、零依赖，读的就是 pi 自己写下的会话记录。

```
/usage
[usage] today  2026-10-24 00:00 → 2026-10-24 02:39
  requests 384   sessions 6   22 transcript file(s)
  input 318,325   cache read 47,127,680   cache write 0
  output 299,840   (reasoning 156,413)
  total 47,745,845 tokens   cache hit 99.3%
  cost  $1.0043  ≈  ¥6.72  (USD/CNY 6.688225, 0m old, live)

  by model
    deepseek-flash         384 req    54.49M tok    $0.8001  ¥5.35

  by day
    2026-10-24    54.49M tok     ¥5.35  ████████████  384 req
```

---

## 特性

- **任意时间段**：`today`、`yesterday`、`week`、`lastweek`、`month`、`lastmonth`、`all`，
  滚动窗口（`12h`、`7d`、`2w`、`3m`、`10天`），以及显式本地日期区间（`2026-09-01..2026-09-30`）。
  中文别名同样可用（`今天`、`昨天`、`本周`、`上周`、`本月`、`上月`、`全部`）。
- **本地货币估算**：pi 已经按 `models.json` 的价格给每条请求记了美元成本，扩展只做求和，再乘以
  USD→本地货币汇率，两个币种一起显示。汇率可自动获取（缓存 12 小时）或手动钉住。
- **多维拆分**：按模型、按日（带柱状图），展开后还能看「最费 token 的会话」。
- **全机器口径**：汇总所有项目的会话，而不只是当前这个目录。
- **输出可留档、且不烧 token**：报告作为「仅显示」的会话条目写入 transcript，随时能翻回来看，
  **不会发给模型**。
- **零依赖、零配置**：不联网也能算（只有取汇率时才联网）。

## 安装

需要 Node.js ≥ 20（pi 自带）。

### 1. 从 npm 安装（推荐）

```bash
pi install npm:pi-usage-report
```

### 2. 从 Gitee 安装

```bash
pi install git:gitee.com/zxh126/pi-usage-report
```

### 3. 手动放进用户扩展目录

```bash
git clone https://gitee.com/zxh126/pi-usage-report "$HOME/.pi/agent/extensions/pi-usage-report"
```

（没有依赖，不需要 `npm install`。）Windows 路径是
`%USERPROFILE%\.pi\agent\extensions\pi-usage-report`。

### 4. 只试用一次

```bash
pi -e npm:pi-usage-report
pi -e ./pi-usage-report
```

### 卸载

```bash
pi remove npm:pi-usage-report
```

## 命令

| 命令 | 区间 |
| --- | --- |
| `/usage` | 今天（本地 0 点 → 现在） |
| `/usage today` / `昨天` | 本地自然日 |
| `/usage week` / `本周` | 周一 00:00 → 现在 |
| `/usage lastweek` / `上周` | 上周一 → 本周一 |
| `/usage month` / `本月` | 1 号 00:00 → 现在 |
| `/usage lastmonth` / `上月` | 上一个自然月 |
| `/usage all` / `全部` | 磁盘上全部历史 |
| `/usage 7d` `12h` `2w` `3m` `10天` | 滚动窗口 |
| `/usage 2026-09-01..2026-09-30` | 含首尾的本地日期区间 |
| `/usage rate 7.15` | 钉住 USD→本地汇率（写配置） |
| `/usage rate auto` | 恢复自动获取汇率 |
| `/usage help` | 上面这张表 |

`/cost` 是 `/usage` 的别名。

在 transcript 里展开该条目（默认 `Ctrl+E`）可以看到「最费 token 的会话」、生成时间和配置提示。

## 费用是怎么估的

1. pi 会为每条 assistant 消息记录 `usage.input / output / cacheRead / cacheWrite / reasoning /
   totalTokens` 以及按 `models.json` 价格算出的 **美元** `cost`。扩展只做累加，不自己编价格。
2. **本地金额 = 美元 × 汇率**，汇率取**公开牌价**：
   `https://open.er-api.com/v6/latest/USD` → `rates[<币种>]` = 1 USD 折多少本地货币
   （例如 CNY ≈ `6.688225`），无需 API key，也不需要手工维护价格表。取值顺序：

   | # | 来源 | 显示为 |
   |---|---|---|
   | 1 | 配置里的 `usdRate`（显式钉住） | `fixed` |
   | 2 | 12 小时内抓取过的缓存 | `cache`，附 `<n>m old` |
   | 3 | 刚刚抓取成功 | `live`，附 `<n>m old` |
   | 4 | 缓存超过 12 小时且本次抓取失败 | `stale`，附 `<n>m old` |
   | 5 | 以上都没有 | `—`，并提示可以钉一个 |

   **绝不臆造汇率**：既没钉住、也没缓存、又没网时，报告只给美元金额和 `—`，
   不会拿一个猜测的数字充数。`PI_OFFLINE=1` 会禁用抓取，于是只会出现 1 / 2 / 4 / 5 这几种情况。
3. 消耗了 token 但没有价格的请求（模型没有价格表）会被单独计数并给出警告，
   不会静悄悄地把金额算低。

配置文件（`<agent-dir>/pi-usage-report.json`，字段都可省略）：

```json
{
  "currency": "CNY",
  "symbol": "¥",
  "usdRate": 6.6882,
  "rateMode": "fixed"
}
```

- `currency` / `symbol` —— 默认 `CNY` 与内置符号表。
- `usdRate` —— 可选的钉住值，**写了就生效**（不需要再写 `rateMode`）。
- `rateMode` —— `"fixed"`（钉住）或 `"auto"`（忽略钉住值，改用公开牌价）。

`/usage rate <数值>` 会写入 `usdRate` + `rateMode: "fixed"`；`/usage rate auto` 会删掉钉住值并立刻重新抓取。

## 工作原理

```
<agent-dir>/sessions/**/*.jsonl       pi 自己的会话记录
        │  只读，单遍扫描
        ▼
带 usage 的 assistant 消息            → 按模型 / 按日 / 按会话分桶
        │
        ▼
报告条目（appendEntry）               → TUI 渲染，永不进入模型上下文
```

- 数据源就是 pi 持久化的会话文件，所以数字和 pi 自己显示的一致；计数过程不联网。
- 同时支持默认的「按项目分目录」布局和 `--session-dir` 指定的扁平目录。
- 除了报告条目，以及在用 `/usage rate` 时的配置文件，不改动任何东西。

## 已知限制

- 只能统计磁盘上还在的记录：被删除或轮转掉的 transcript 不算；`fork`/`clone` 出来的会话会把
  继承的历史再算一遍。
- 金额取决于你 `models.json` 里的定价；没有定价的模型会显示「无价格数据」，而不是猜一个数字。
- 汇率来自上面那个接口的每日参考价，不是你所用平台的计费价，金额列请当**估算**（误差百分之几）。
- 每次命令都会现场扫 transcript：会话特别多时第一次 `/usage all` 会稍慢（本机约 500 MB
  transcript 仍在亚秒级）。

## 开发

```text
pi-usage-report/
├── index.ts          # 扩展本体（单文件，无依赖）
├── package.json      # pi 清单：pi.extensions -> ./index.ts
├── LICENSE           # MIT
├── README.md         # 英文版
└── README.zh-CN.md   # 本文件
```

- 走 pi 的 jiti loader 直接运行，无需编译；渲染器只返回一个带 `render(width)` 的普通对象，
  连 TUI 包都不需要 import。
- 不安装也能试：`pi -e <仓库路径>`，然后在 TUI 里敲 `/usage`；或者用 RPC 驱动
  （`pi --mode rpc` → `{"type":"prompt","message":"/usage month"}`）。

发布流程（维护者）：改 `version` → 提交 → 推 Gitee →
`npm publish --registry=https://registry.npmjs.org`。

## License

[MIT](./LICENSE) © 2026 zxh126
