@pify/usage 0.5.0 → 0.5.2

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
@@ -1,13 +1,22 @@
1
1
  # @pify/usage
2
2
 
3
- Token and cost reporting for [pi](https://github.com/earendil-works/pi) sessions — a live footer, a `/usage` dashboard, and an agent-callable status tool. Entirely local: no network calls, no LLM tokens spent asking about tokens.
3
+ Token and cost reporting for [pi](https://github.com/earendil-works/pi) sessions — a live footer, a `/usage` dashboard, and an agent-callable status tool. Local by default: no network calls, and no LLM tokens spent asking about tokens.
4
4
 
5
5
  Part of the [Pify suite](https://github.com/pifydev). Install with [`pify install usage`](https://github.com/pifydev/cli) or `pi install npm:@pify/usage`.
6
6
 
7
- ## What it does
7
+ ## Why
8
8
 
9
- - **Live footer**: `📊 12.3k tok · $0.45` folded from each message's `usage.cost` that pi already computes; survives `/reload` by replaying the session branch.
10
- - **`/usage` dashboard**:
9
+ Spend is invisible until the invoice arrives, and by then you cannot tell which session did it. Everything needed to answer that is already on disk pi writes usage and cost into every session file — so the answer should cost nothing to produce.
10
+
11
+ ## Live footer
12
+
13
+ ```
14
+ 📊 12.3k tok · $0.45
15
+ ```
16
+
17
+ Folded from each message's `usage.cost`, which pi already computes. It survives `/reload` by replaying the session branch rather than keeping a running total in memory.
18
+
19
+ ## `/usage`
11
20
 
12
21
  ```
13
22
  Session
@@ -27,8 +36,11 @@ By project (all time)
27
36
  D--project-shop-api $6.60 · 3.6M tok
28
37
  ```
29
38
 
30
- - **History done right** (tmustier's lessons): counts every usage-bearing entry in pi's session JSONL — assistant turns plus the tool-result/compaction usage pi 0.81+ persists; negative/NaN fields clamp to zero; days are your local calendar days; a per-file mtime cache keeps repeat scans instant.
31
- - **Where the window went** (v0.4): `/usage context` breaks the context window into system prompt, context files, skills, tool definitions, tool results, and conversation — so "why am I at 60%?" has an answer that is usually "one `read` of a 4,000-line file", not a mystery.
39
+ History counts every usage-bearing entry in pi's session JSONL — assistant turns plus the tool-result and compaction usage pi persists — so a session's total matches what you were billed rather than what the visible messages add up to. Negative and NaN fields clamp to zero, days are your **local** calendar days, and a per-file mtime cache keeps repeat scans instant.
40
+
41
+ Per-project totals come for free: pi stores sessions one directory per project, so the dashboard can show where the money actually went.
42
+
43
+ ## `/usage context`
32
44
 
33
45
  ```
34
46
  Context window: 22.6k of 200.0k used (11%)
@@ -40,14 +52,15 @@ Context window: 22.6k of 200.0k used (11%)
40
52
  Free space █████████████████████████··· 89% 177.4k
41
53
  ```
42
54
 
43
- Computed from what pi already holds the assembled system prompt, the files and skills embedded in it, the enabled tool definitions, and the entries that would be sent. No network, no model call. Context files and skills are counted only when their text is genuinely embedded in the prompt, and the system-prompt row is the remainder after subtracting them, so the rows sum to the whole instead of double-counting. When the provider reports more than we can attribute, the difference is shown as **Other** rather than dropped. (The idea is from [`pi-cc-extensions`](https://github.com/minuque/pi-cc-extensions)' `/context`.)
55
+ "Why am I at 60%?" usually has a boring answer one `read` of a 4,000-line file and this is where you find it.
44
56
 
45
- - **Per-project spend** (v0.2): pi stores sessions one directory per project, so the dashboard can show where the money actually went the top 5 projects by cost, all time.
46
- - **`usage_status` tool**: the agent can check session + today totals before committing to expensive work (subagent fan-outs, large reads).
57
+ Computed entirely from what pi already holds: the assembled system prompt, the files and skills embedded in it, the enabled tool definitions, and the entries that would be sent. No network, no model call.
47
58
 
48
- ## `/usage quota` (v0.5)
59
+ Context files and skills are counted only when their text is genuinely embedded in the prompt, and the system-prompt row is the remainder after subtracting them, so the rows sum to the whole instead of double-counting. When the provider reports more than can be attributed, the difference is shown as **Other** rather than quietly dropped.
49
60
 
50
- The one command in this package that touches the network, and only when you run it:
61
+ ## `/usage quota`
62
+
63
+ The one command here that touches the network, and only when you run it:
51
64
 
52
65
  ```
53
66
  Quota (OpenRouter · sk-or-v1-abc...xyz)
@@ -58,20 +71,23 @@ Quota (DeepSeek · granted 10 · topped up 100)
58
71
  balance CNY 110.00
59
72
  ```
60
73
 
61
- **Documented endpoints only.** OpenRouter's `/api/v1/key` and DeepSeek's `/user/balance` are published APIs that report a real balance. The subscription-quota endpoints some plugins use for OpenAI, Anthropic and Gemini are undocumented private APIs reverse-engineered from vendor CLIs — they break without notice and were never offered to third parties, so this package does not call them. Providers you have not configured are simply not shown; they are not failures.
74
+ **Documented endpoints only.** OpenRouter's `/api/v1/key` and DeepSeek's `/user/balance` are published APIs that report a real balance. The subscription-quota endpoints available for some other providers are undocumented private APIs reverse-engineered from vendor CLIs — they break without notice and were never offered to third parties, so this package does not call them. A provider you have not configured is simply not shown; that is not a failure.
62
75
 
63
- **A credentialed request is pinned down** (v0.5), because it carries your provider key:
76
+ **A credentialed request is pinned down**, because it carries your provider key:
64
77
 
65
78
  - HTTPS only, and the host must be on that provider's allowlist.
66
79
  - Redirects are refused outright. Following one lets whatever answered choose where the next request goes, with the header already attached.
67
80
  - A non-2xx body is **never read**. Error bodies echo request details back, and an echoed `Authorization` header pasted into a notification is exactly the leak this must not cause — the status alone becomes the message.
68
81
  - Raw exception text is dropped rather than shown, and everything printed passes a redactor as a last line of defence.
82
+ - An 8-second timeout per provider; any failure renders as `unavailable — the provider rejected the key` rather than throwing.
83
+
84
+ **The key comes from pi**, resolved through `modelRegistry` rather than by reading `auth.json`. pi owns credential storage — env precedence, OAuth, whatever it grows next — and parsing that file here would mean handling secrets this package has no business touching, using a stale copy of pi's rules. Only the provider's own masked label is ever printed.
69
85
 
70
- **The key comes from pi** (v0.5): resolved through `modelRegistry`, not by reading `auth.json`. pi owns credential storage — env precedence, OAuth, whatever it grows next — and parsing that file here meant handling secrets this package has no business touching, with a stale copy of pi's rules. Only the provider's own masked label is ever printed.
86
+ ## Tool
71
87
 
72
- An 8-second timeout per provider, and any failure renders as `unavailable — the provider rejected the key` rather than throwing.
88
+ ### `usage_status`
73
89
 
74
- The hardening, the multi-provider shape, and the documented-APIs-only stance are from [`@imdlan/pi-usage`](https://github.com/imdlan/pi-usage), which supports Z.ai as well.
90
+ No parameters. Returns session and today's totals, so the agent can check the cost before committing to expensive work — a wide subagent fan-out, a large read instead of finding out afterwards.
75
91
 
76
92
  ## License
77
93
 
@@ -200,6 +200,7 @@ export default function usage(pi: ExtensionAPI) {
200
200
  pi.registerTool({
201
201
  name: "usage_status",
202
202
  label: "Usage status",
203
+ promptSnippet: "Tokens, cost, and context used so far this session",
203
204
  description:
204
205
  "Current session token/cost totals plus today's local aggregate. Use when deciding whether " +
205
206
  "an expensive approach (large reads, many subagents) is proportionate.",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pify/usage",
3
- "version": "0.5.0",
3
+ "version": "0.5.2",
4
4
  "description": "Token and cost reporting for pi sessions: live footer, local-history dashboard with per-project costs, opt-in provider quota",
5
5
  "keywords": [
6
6
  "pi-package",
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: usage
3
- description: Use when cost or token consumption matters to a decision - before expensive operations (large reads, many subagents, long loops) or when the user asks about spend - explains usage_status and /usage
3
+ description: Use when cost or token consumption matters to a decision - before expensive operations (large reads, many subagents, long loops) or when the user asks about spend
4
4
  ---
5
5
 
6
6
  # Usage awareness