@inferhub/usage 0.1.5 → 0.1.6
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/dist/format.js +12 -13
- package/dist/format.test.js +5 -4
- package/package.json +1 -1
- package/src/format.test.ts +5 -4
- package/src/format.ts +11 -14
package/dist/format.js
CHANGED
|
@@ -24,16 +24,20 @@ export function shortModel(model) {
|
|
|
24
24
|
const parts = model.split("/");
|
|
25
25
|
return parts[parts.length - 1] || model;
|
|
26
26
|
}
|
|
27
|
-
/** Compact metric
|
|
28
|
-
|
|
27
|
+
/** Compact metric for one-line status.
|
|
28
|
+
* - billed: "$0.41" (no req clutter on all-time)
|
|
29
|
+
* - free/zero: "19r"
|
|
30
|
+
* - billed + wantReq: "$0.12/5r" when showReq=true
|
|
31
|
+
*/
|
|
32
|
+
function compact(spendUsdc, requests, opts) {
|
|
29
33
|
const spend = Number(spendUsdc ?? 0);
|
|
30
34
|
const req = Number(requests ?? 0);
|
|
31
35
|
if (spend > 0) {
|
|
32
|
-
|
|
33
|
-
|
|
36
|
+
if (opts?.showReq && req > 0)
|
|
37
|
+
return `${money(spend)}/${req}r`;
|
|
38
|
+
return money(spend);
|
|
34
39
|
}
|
|
35
|
-
|
|
36
|
-
if (req <= 0 && Number(totalTokens ?? 0) <= 0)
|
|
40
|
+
if (req <= 0)
|
|
37
41
|
return "—";
|
|
38
42
|
return `${req}r`;
|
|
39
43
|
}
|
|
@@ -45,20 +49,15 @@ function compact(spendUsdc, requests, totalTokens) {
|
|
|
45
49
|
*/
|
|
46
50
|
export function formatStatusLine(usage, extras) {
|
|
47
51
|
const parts = ["InferHub"];
|
|
48
|
-
// Session (latest IH conversation) — omit if empty
|
|
49
52
|
if (usage.session && (usage.session.requests > 0 || Number(usage.session.spend_usdc) > 0)) {
|
|
50
|
-
parts.push(`sess ${compact(usage.session.spend_usdc, usage.session.requests
|
|
53
|
+
parts.push(`sess ${compact(usage.session.spend_usdc, usage.session.requests)}`);
|
|
51
54
|
}
|
|
52
|
-
parts.push(`day ${compact(usage.window.spend_usdc, usage.window.requests
|
|
55
|
+
parts.push(`day ${compact(usage.window.spend_usdc, usage.window.requests)}`);
|
|
53
56
|
parts.push(`all ${compact(usage.all_time.spend_usdc, usage.all_time.requests)}`);
|
|
54
57
|
parts.push(`bal ${money(usage.balance.amount_usdc)}`);
|
|
55
58
|
const top = shortModel(usage.top_model?.model);
|
|
56
59
|
if (top && top !== "—")
|
|
57
60
|
parts.push(`top ${top}`);
|
|
58
|
-
// context % is useful but optional — only if provided and non-zero space
|
|
59
|
-
if (extras?.contextPct != null && Number.isFinite(extras.contextPct)) {
|
|
60
|
-
parts.push(`${Math.round(extras.contextPct)}%`);
|
|
61
|
-
}
|
|
62
61
|
return parts.join(" · ");
|
|
63
62
|
}
|
|
64
63
|
/** Multi-line human report for /usage skills. */
|
package/dist/format.test.js
CHANGED
|
@@ -54,16 +54,17 @@ test("formatStatusLine is compact one-liner", () => {
|
|
|
54
54
|
});
|
|
55
55
|
// Must be short enough for one Claude status row
|
|
56
56
|
assert.ok(line.length < 100, `too long: ${line.length} ${line}`);
|
|
57
|
-
assert.equal(line, "InferHub · sess 19r · day 129r · all $0.41 · bal $1.31 · top gpt-5.5
|
|
58
|
-
assert.
|
|
59
|
-
// paid day shows money
|
|
57
|
+
assert.equal(line, "InferHub · sess 19r · day 129r · all $0.41 · bal $1.31 · top gpt-5.5");
|
|
58
|
+
assert.ok(line.length <= 72, `too long: ${line.length}`);
|
|
59
|
+
// paid day shows money only (no req clutter)
|
|
60
60
|
const paid = {
|
|
61
61
|
...usage,
|
|
62
62
|
window: { ...usage.window, spend_usdc: "0.12", requests: 5 },
|
|
63
63
|
session: null,
|
|
64
64
|
};
|
|
65
65
|
const paidLine = formatStatusLine(paid);
|
|
66
|
-
assert.match(paidLine, /day \$0\.12
|
|
66
|
+
assert.match(paidLine, /day \$0\.12/);
|
|
67
67
|
assert.doesNotMatch(paidLine, /sess /);
|
|
68
|
+
assert.doesNotMatch(paidLine, /\/5r/);
|
|
68
69
|
assert.equal(money("0"), "$0");
|
|
69
70
|
});
|
package/package.json
CHANGED
package/src/format.test.ts
CHANGED
|
@@ -65,19 +65,20 @@ test("formatStatusLine is compact one-liner", () => {
|
|
|
65
65
|
assert.ok(line.length < 100, `too long: ${line.length} ${line}`);
|
|
66
66
|
assert.equal(
|
|
67
67
|
line,
|
|
68
|
-
"InferHub · sess 19r · day 129r · all $0.41 · bal $1.31 · top gpt-5.5
|
|
68
|
+
"InferHub · sess 19r · day 129r · all $0.41 · bal $1.31 · top gpt-5.5",
|
|
69
69
|
);
|
|
70
|
-
assert.
|
|
70
|
+
assert.ok(line.length <= 72, `too long: ${line.length}`);
|
|
71
71
|
|
|
72
|
-
// paid day shows money
|
|
72
|
+
// paid day shows money only (no req clutter)
|
|
73
73
|
const paid: AccountUsage = {
|
|
74
74
|
...usage,
|
|
75
75
|
window: { ...usage.window, spend_usdc: "0.12", requests: 5 },
|
|
76
76
|
session: null,
|
|
77
77
|
};
|
|
78
78
|
const paidLine = formatStatusLine(paid);
|
|
79
|
-
assert.match(paidLine, /day \$0\.12
|
|
79
|
+
assert.match(paidLine, /day \$0\.12/);
|
|
80
80
|
assert.doesNotMatch(paidLine, /sess /);
|
|
81
|
+
assert.doesNotMatch(paidLine, /\/5r/);
|
|
81
82
|
|
|
82
83
|
assert.equal(money("0"), "$0");
|
|
83
84
|
});
|
package/src/format.ts
CHANGED
|
@@ -22,20 +22,23 @@ export function shortModel(model: string | null | undefined): string {
|
|
|
22
22
|
return parts[parts.length - 1] || model;
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
-
/** Compact metric
|
|
25
|
+
/** Compact metric for one-line status.
|
|
26
|
+
* - billed: "$0.41" (no req clutter on all-time)
|
|
27
|
+
* - free/zero: "19r"
|
|
28
|
+
* - billed + wantReq: "$0.12/5r" when showReq=true
|
|
29
|
+
*/
|
|
26
30
|
function compact(
|
|
27
31
|
spendUsdc: string | number | null | undefined,
|
|
28
32
|
requests: number | null | undefined,
|
|
29
|
-
|
|
33
|
+
opts?: { showReq?: boolean },
|
|
30
34
|
): string {
|
|
31
35
|
const spend = Number(spendUsdc ?? 0);
|
|
32
36
|
const req = Number(requests ?? 0);
|
|
33
37
|
if (spend > 0) {
|
|
34
|
-
|
|
35
|
-
return
|
|
38
|
+
if (opts?.showReq && req > 0) return `${money(spend)}/${req}r`;
|
|
39
|
+
return money(spend);
|
|
36
40
|
}
|
|
37
|
-
|
|
38
|
-
if (req <= 0 && Number(totalTokens ?? 0) <= 0) return "—";
|
|
41
|
+
if (req <= 0) return "—";
|
|
39
42
|
return `${req}r`;
|
|
40
43
|
}
|
|
41
44
|
|
|
@@ -56,23 +59,17 @@ export function formatStatusLine(
|
|
|
56
59
|
): string {
|
|
57
60
|
const parts: string[] = ["InferHub"];
|
|
58
61
|
|
|
59
|
-
// Session (latest IH conversation) — omit if empty
|
|
60
62
|
if (usage.session && (usage.session.requests > 0 || Number(usage.session.spend_usdc) > 0)) {
|
|
61
|
-
parts.push(`sess ${compact(usage.session.spend_usdc, usage.session.requests
|
|
63
|
+
parts.push(`sess ${compact(usage.session.spend_usdc, usage.session.requests)}`);
|
|
62
64
|
}
|
|
63
65
|
|
|
64
|
-
parts.push(`day ${compact(usage.window.spend_usdc, usage.window.requests
|
|
66
|
+
parts.push(`day ${compact(usage.window.spend_usdc, usage.window.requests)}`);
|
|
65
67
|
parts.push(`all ${compact(usage.all_time.spend_usdc, usage.all_time.requests)}`);
|
|
66
68
|
parts.push(`bal ${money(usage.balance.amount_usdc)}`);
|
|
67
69
|
|
|
68
70
|
const top = shortModel(usage.top_model?.model);
|
|
69
71
|
if (top && top !== "—") parts.push(`top ${top}`);
|
|
70
72
|
|
|
71
|
-
// context % is useful but optional — only if provided and non-zero space
|
|
72
|
-
if (extras?.contextPct != null && Number.isFinite(extras.contextPct)) {
|
|
73
|
-
parts.push(`${Math.round(extras.contextPct)}%`);
|
|
74
|
-
}
|
|
75
|
-
|
|
76
73
|
return parts.join(" · ");
|
|
77
74
|
}
|
|
78
75
|
|