@beyona/pi-zai-usage 0.3.2 → 0.3.4
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 +24 -4
- package/dist/api.d.ts +17 -5
- package/dist/api.d.ts.map +1 -1
- package/dist/api.js +34 -11
- package/dist/api.js.map +1 -1
- package/dist/index.d.ts +7 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +255 -17
- package/dist/index.js.map +1 -1
- package/dist/usage-lib/datetime.d.ts +1 -1
- package/dist/usage-lib/datetime.d.ts.map +1 -1
- package/dist/usage-lib/datetime.js +10 -7
- package/dist/usage-lib/datetime.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
# Pi coding agent Z.ai Usage Extension
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
3
|
A [Pi coding agent](https://pi.dev/) extension that monitors [Z.ai subscription](https://z.ai/subscribe) API token usage quota and automatically displays usage in the footer when using the Z.ai provider.
|
|
6
4
|
|
|
7
5
|

|
|
@@ -14,11 +12,27 @@ A [Pi coding agent](https://pi.dev/) extension that monitors [Z.ai subscription]
|
|
|
14
12
|
|
|
15
13
|
## Install
|
|
16
14
|
|
|
15
|
+
Published package: <https://www.npmjs.com/package/@beyona/pi-zai-usage>
|
|
16
|
+
|
|
17
|
+
### Install as a Pi extension from npm
|
|
18
|
+
|
|
17
19
|
```bash
|
|
18
20
|
pi install npm:@beyona/pi-zai-usage
|
|
19
21
|
```
|
|
20
22
|
|
|
21
|
-
|
|
23
|
+
The package declares its Pi extension entry point in `package.json`, so `pi install` adds the package to your Pi configuration and loads the extension automatically in new Pi sessions. When using a Z.ai model, the footer displays usage after session start, model selection, and each turn.
|
|
24
|
+
|
|
25
|
+
### Update the installed extension
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
pi install npm:@beyona/pi-zai-usage@latest
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Restart Pi or run `/reload` in an existing session after updating.
|
|
32
|
+
|
|
33
|
+
### Install from a local checkout
|
|
34
|
+
|
|
35
|
+
If you prefer to build and keep a source checkout locally, clone your fork and run:
|
|
22
36
|
|
|
23
37
|
```bash
|
|
24
38
|
# Install dependencies
|
|
@@ -93,7 +107,13 @@ This project uses automated publishing to NPM via GitHub Actions. The workflow w
|
|
|
93
107
|
|
|
94
108
|
## Redistribution notes
|
|
95
109
|
|
|
96
|
-
|
|
110
|
+
Current redistribution progress:
|
|
111
|
+
|
|
112
|
+
- `@beyona/pi-zai-usage@0.3.2` is published publicly on npm.
|
|
113
|
+
- The source repository uses `main` as the default branch.
|
|
114
|
+
- The package vendors the helper code formerly provided by `@alexanderfortin/pi-usage-lib` and has no runtime dependency on that package.
|
|
115
|
+
|
|
116
|
+
The vendored helper code and original extension are MIT-licensed by Alexander Fortin.
|
|
97
117
|
|
|
98
118
|
## License
|
|
99
119
|
|
package/dist/api.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Z.ai Usage Checker - Pi Extension
|
|
3
|
-
* Provider-specific API interaction using
|
|
3
|
+
* Provider-specific API interaction using vendored helper primitives.
|
|
4
4
|
*/
|
|
5
5
|
import type { ModelRegistry } from "@earendil-works/pi-coding-agent";
|
|
6
6
|
import { UsageError } from "./usage-lib";
|
|
@@ -8,6 +8,7 @@ export interface ZaiUsageResponse {
|
|
|
8
8
|
data: {
|
|
9
9
|
limits: Array<{
|
|
10
10
|
type: string;
|
|
11
|
+
unit: number;
|
|
11
12
|
percentage: number;
|
|
12
13
|
nextResetTime?: number;
|
|
13
14
|
}>;
|
|
@@ -18,16 +19,27 @@ export interface ZaiApiError {
|
|
|
18
19
|
msg: string;
|
|
19
20
|
success: boolean;
|
|
20
21
|
}
|
|
21
|
-
|
|
22
|
+
/** Single quota bucket (e.g. 5-hour or weekly) */
|
|
23
|
+
export interface QuotaInfo {
|
|
24
|
+
/** Usage percentage (0–100) */
|
|
22
25
|
percentage: number;
|
|
26
|
+
/** Localized reset date/time string (only when nextResetTime is known) */
|
|
23
27
|
resetTime?: string;
|
|
28
|
+
/** Formatted time remaining string (e.g. "2d 7h 35m") or "0" when unknown */
|
|
24
29
|
timeRemaining?: string;
|
|
25
30
|
}
|
|
31
|
+
/** Z.ai usage data: 5-hour, weekly, and monthly quotas */
|
|
32
|
+
export interface ZaiUsageData {
|
|
33
|
+
fiveHour: QuotaInfo;
|
|
34
|
+
weekly: QuotaInfo;
|
|
35
|
+
/** Monthly TIME_LIMIT quota (may be absent on some plans) */
|
|
36
|
+
monthly?: QuotaInfo;
|
|
37
|
+
}
|
|
26
38
|
/**
|
|
27
|
-
* Fetch Z.ai usage from the API
|
|
39
|
+
* Fetch Z.ai usage from the API.
|
|
28
40
|
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
41
|
+
* Returns the same quota buckets as the local installed extension:
|
|
42
|
+
* 5-hour TOKENS_LIMIT, weekly TOKENS_LIMIT, and optional monthly TIME_LIMIT.
|
|
31
43
|
*/
|
|
32
44
|
export declare function getZaiUsage(modelRegistry: Pick<ModelRegistry, "getApiKeyForProvider">): Promise<ZaiUsageData>;
|
|
33
45
|
export { UsageError };
|
package/dist/api.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iCAAiC,CAAA;AACpE,OAAO,EAML,UAAU,EACX,MAAM,aAAa,CAAA;AAIpB,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE;QACJ,MAAM,EAAE,KAAK,CAAC;YACZ,IAAI,EAAE,MAAM,CAAA;YACZ,UAAU,EAAE,MAAM,CAAA;YAClB,aAAa,CAAC,EAAE,MAAM,CAAA;SACvB,CAAC,CAAA;KACH,CAAA;CACF;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAA;IACZ,GAAG,EAAE,MAAM,CAAA;IACX,OAAO,EAAE,OAAO,CAAA;CACjB;AAED,MAAM,WAAW,
|
|
1
|
+
{"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iCAAiC,CAAA;AACpE,OAAO,EAML,UAAU,EACX,MAAM,aAAa,CAAA;AAIpB,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE;QACJ,MAAM,EAAE,KAAK,CAAC;YACZ,IAAI,EAAE,MAAM,CAAA;YACZ,IAAI,EAAE,MAAM,CAAA;YACZ,UAAU,EAAE,MAAM,CAAA;YAClB,aAAa,CAAC,EAAE,MAAM,CAAA;SACvB,CAAC,CAAA;KACH,CAAA;CACF;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAA;IACZ,GAAG,EAAE,MAAM,CAAA;IACX,OAAO,EAAE,OAAO,CAAA;CACjB;AAED,kDAAkD;AAClD,MAAM,WAAW,SAAS;IACxB,+BAA+B;IAC/B,UAAU,EAAE,MAAM,CAAA;IAClB,0EAA0E;IAC1E,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,6EAA6E;IAC7E,aAAa,CAAC,EAAE,MAAM,CAAA;CACvB;AAED,0DAA0D;AAC1D,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,SAAS,CAAA;IACnB,MAAM,EAAE,SAAS,CAAA;IACjB,6DAA6D;IAC7D,OAAO,CAAC,EAAE,SAAS,CAAA;CACpB;AASD;;;;;GAKG;AACH,wBAAsB,WAAW,CAC/B,aAAa,EAAE,IAAI,CAAC,aAAa,EAAE,sBAAsB,CAAC,GACzD,OAAO,CAAC,YAAY,CAAC,CAmDvB;AAGD,OAAO,EAAE,UAAU,EAAE,CAAA"}
|
package/dist/api.js
CHANGED
|
@@ -1,14 +1,18 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Z.ai Usage Checker - Pi Extension
|
|
3
|
-
* Provider-specific API interaction using
|
|
3
|
+
* Provider-specific API interaction using vendored helper primitives.
|
|
4
4
|
*/
|
|
5
5
|
import { buildAuthHeaders, formatInstantFromEpochMs, formatTimeRemainingFromEpochMs, safeFetch, safeParseJson, UsageError, } from "./usage-lib";
|
|
6
6
|
const ZAI_USAGE_API_URL = "https://api.z.ai/api/monitor/usage/quota/limit";
|
|
7
|
+
// Z.ai limit unit constants from the local installed extension.
|
|
8
|
+
const UNIT_FIVE_HOUR = 3; // 5-hour TOKENS_LIMIT quota
|
|
9
|
+
const UNIT_WEEKLY = 6; // weekly TOKENS_LIMIT quota
|
|
10
|
+
const UNIT_MONTHLY = 5; // monthly TIME_LIMIT quota
|
|
7
11
|
/**
|
|
8
|
-
* Fetch Z.ai usage from the API
|
|
12
|
+
* Fetch Z.ai usage from the API.
|
|
9
13
|
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
14
|
+
* Returns the same quota buckets as the local installed extension:
|
|
15
|
+
* 5-hour TOKENS_LIMIT, weekly TOKENS_LIMIT, and optional monthly TIME_LIMIT.
|
|
12
16
|
*/
|
|
13
17
|
export async function getZaiUsage(modelRegistry) {
|
|
14
18
|
const headers = await buildAuthHeaders(modelRegistry, "zai");
|
|
@@ -21,16 +25,35 @@ export async function getZaiUsage(modelRegistry) {
|
|
|
21
25
|
throw new UsageError(`Z.ai API error: ${apiError.msg}`, `api${apiError.code ?? "unknown"}`);
|
|
22
26
|
}
|
|
23
27
|
const data = parsed;
|
|
24
|
-
const
|
|
25
|
-
|
|
26
|
-
|
|
28
|
+
const limits = data.data?.limits ?? [];
|
|
29
|
+
const tokenLimits = limits.filter((limit) => limit.type === "TOKENS_LIMIT");
|
|
30
|
+
const timeLimits = limits.filter((limit) => limit.type === "TIME_LIMIT");
|
|
31
|
+
const fiveHourLimit = tokenLimits.find((limit) => limit.unit === UNIT_FIVE_HOUR);
|
|
32
|
+
const weeklyLimit = tokenLimits.find((limit) => limit.unit === UNIT_WEEKLY);
|
|
33
|
+
const monthlyLimit = timeLimits.find((limit) => limit.unit === UNIT_MONTHLY);
|
|
34
|
+
if (!fiveHourLimit || !weeklyLimit) {
|
|
35
|
+
throw new UsageError("Required TOKENS_LIMIT entries (5h + weekly) not found in API response", "nolimit");
|
|
27
36
|
}
|
|
37
|
+
const buildQuota = (limit) => {
|
|
38
|
+
const quota = {
|
|
39
|
+
percentage: limit.percentage,
|
|
40
|
+
};
|
|
41
|
+
if (limit.nextResetTime) {
|
|
42
|
+
quota.resetTime = formatInstantFromEpochMs(limit.nextResetTime);
|
|
43
|
+
quota.timeRemaining = formatTimeRemainingFromEpochMs(limit.nextResetTime);
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
// No reset time available — signal unknown, matching the local installed extension.
|
|
47
|
+
quota.timeRemaining = "0";
|
|
48
|
+
}
|
|
49
|
+
return quota;
|
|
50
|
+
};
|
|
28
51
|
const result = {
|
|
29
|
-
|
|
52
|
+
fiveHour: buildQuota(fiveHourLimit),
|
|
53
|
+
weekly: buildQuota(weeklyLimit),
|
|
30
54
|
};
|
|
31
|
-
if (
|
|
32
|
-
result.
|
|
33
|
-
result.timeRemaining = formatTimeRemainingFromEpochMs(tokensLimit.nextResetTime);
|
|
55
|
+
if (monthlyLimit) {
|
|
56
|
+
result.monthly = buildQuota(monthlyLimit);
|
|
34
57
|
}
|
|
35
58
|
return result;
|
|
36
59
|
}
|
package/dist/api.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api.js","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EACL,gBAAgB,EAChB,wBAAwB,EACxB,8BAA8B,EAC9B,SAAS,EACT,aAAa,EACb,UAAU,GACX,MAAM,aAAa,CAAA;
|
|
1
|
+
{"version":3,"file":"api.js","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Z.ai Usage Checker - Pi Extension
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
4
|
+
* Renders Z.ai quota usage on the first footer line (path/branch line),
|
|
5
|
+
* right-aligned. Uses a custom footer via ctx.ui.setFooter() to control
|
|
6
|
+
* placement, while replicating the default footer's remaining lines.
|
|
6
7
|
*/
|
|
8
|
+
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
7
9
|
import { type ZaiUsageData } from "./api";
|
|
8
|
-
import {
|
|
9
|
-
/** Render Z.ai usage data into a themed
|
|
10
|
+
import { type Theme } from "./usage-lib";
|
|
11
|
+
/** Render Z.ai usage data into a themed string showing 5h, weekly, and monthly quotas */
|
|
10
12
|
export declare function renderZaiStatus(data: ZaiUsageData, theme: Theme): string;
|
|
11
|
-
|
|
12
|
-
export default extension;
|
|
13
|
+
export default function extension(pi: ExtensionAPI): void;
|
|
13
14
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,KAAK,EAAE,YAAY,EAAoB,MAAM,iCAAiC,CAAA;AAGrF,OAAO,EAAe,KAAK,YAAY,EAAE,MAAM,OAAO,CAAA;AACtD,OAAO,EAAsB,KAAK,KAAK,EAAE,MAAM,aAAa,CAAA;AAoD5D,yFAAyF;AACzF,wBAAgB,eAAe,CAAC,IAAI,EAAE,YAAY,EAAE,KAAK,EAAE,KAAK,GAAG,MAAM,CA+BxE;AAMD,MAAM,CAAC,OAAO,UAAU,SAAS,CAAC,EAAE,EAAE,YAAY,GAAG,IAAI,CA6MxD"}
|
package/dist/index.js
CHANGED
|
@@ -1,26 +1,264 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Z.ai Usage Checker - Pi Extension
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
4
|
+
* Renders Z.ai quota usage on the first footer line (path/branch line),
|
|
5
|
+
* right-aligned. Uses a custom footer via ctx.ui.setFooter() to control
|
|
6
|
+
* placement, while replicating the default footer's remaining lines.
|
|
6
7
|
*/
|
|
8
|
+
import { isAbsolute, relative, resolve, sep } from "node:path";
|
|
9
|
+
import { truncateToWidth, visibleWidth } from "@earendil-works/pi-tui";
|
|
10
|
+
import { Temporal } from "temporal-polyfill";
|
|
7
11
|
import { getZaiUsage } from "./api";
|
|
8
|
-
import { colorForPercentage
|
|
9
|
-
|
|
12
|
+
import { colorForPercentage } from "./usage-lib";
|
|
13
|
+
const COOLDOWN_MS = 30_000;
|
|
14
|
+
// --- helpers (mirrors footer.js) ---
|
|
15
|
+
/** Sanitize text for display in a single-line status. */
|
|
16
|
+
function sanitizeStatusText(text) {
|
|
17
|
+
return text
|
|
18
|
+
.replace(/[\r\n\t]/g, " ")
|
|
19
|
+
.replace(/ +/g, " ")
|
|
20
|
+
.trim();
|
|
21
|
+
}
|
|
22
|
+
/** Format token counts for compact display. */
|
|
23
|
+
function formatTokens(count) {
|
|
24
|
+
if (count < 1000)
|
|
25
|
+
return count.toString();
|
|
26
|
+
if (count < 10000)
|
|
27
|
+
return `${(count / 1000).toFixed(1)}k`;
|
|
28
|
+
if (count < 1000000)
|
|
29
|
+
return `${Math.round(count / 1000)}k`;
|
|
30
|
+
if (count < 10000000)
|
|
31
|
+
return `${(count / 1000000).toFixed(1)}M`;
|
|
32
|
+
return `${Math.round(count / 1000000)}M`;
|
|
33
|
+
}
|
|
34
|
+
/** Replace home directory with ~ */
|
|
35
|
+
function formatCwdForFooter(cwd, home) {
|
|
36
|
+
if (!home)
|
|
37
|
+
return cwd;
|
|
38
|
+
const resolvedCwd = resolve(cwd);
|
|
39
|
+
const resolvedHome = resolve(home);
|
|
40
|
+
const relativeToHome = relative(resolvedHome, resolvedCwd);
|
|
41
|
+
const isInsideHome = relativeToHome === "" ||
|
|
42
|
+
(relativeToHome !== ".." &&
|
|
43
|
+
!relativeToHome.startsWith(`..${sep}`) &&
|
|
44
|
+
!isAbsolute(relativeToHome));
|
|
45
|
+
if (!isInsideHome)
|
|
46
|
+
return cwd;
|
|
47
|
+
return relativeToHome === "" ? "~" : `~${sep}${relativeToHome}`;
|
|
48
|
+
}
|
|
49
|
+
function isZaiProvider(ctx) {
|
|
50
|
+
return ctx.model?.provider?.toLowerCase()?.startsWith("zai") ?? false;
|
|
51
|
+
}
|
|
52
|
+
/** Render Z.ai usage data into a themed string showing 5h, weekly, and monthly quotas */
|
|
10
53
|
export function renderZaiStatus(data, theme) {
|
|
11
|
-
const
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
54
|
+
const parts = [];
|
|
55
|
+
// 5-hour quota
|
|
56
|
+
{
|
|
57
|
+
const pct = Math.round(data.fiveHour.percentage * 10) / 10;
|
|
58
|
+
const reset = data.fiveHour.timeRemaining ?? "";
|
|
59
|
+
parts.push(`${theme.fg("muted", "5h")} ${colorForPercentage(pct, theme)(`${pct}%`)} ${theme.fg("dim", `(${reset})`)}`);
|
|
60
|
+
}
|
|
61
|
+
// Weekly quota
|
|
62
|
+
{
|
|
63
|
+
const pct = Math.round(data.weekly.percentage * 10) / 10;
|
|
64
|
+
const reset = data.weekly.timeRemaining ?? "";
|
|
65
|
+
parts.push(`${theme.fg("muted", "W")} ${colorForPercentage(pct, theme)(`${pct}%`)} ${theme.fg("dim", `(${reset})`)}`);
|
|
66
|
+
}
|
|
67
|
+
// Monthly quota
|
|
68
|
+
if (data.monthly) {
|
|
69
|
+
const pct = Math.round(data.monthly.percentage * 10) / 10;
|
|
70
|
+
const reset = data.monthly.timeRemaining ?? "";
|
|
71
|
+
parts.push(`${theme.fg("muted", "M")} ${colorForPercentage(pct, theme)(`${pct}%`)} ${theme.fg("dim", `(${reset})`)}`);
|
|
72
|
+
}
|
|
73
|
+
return `${theme.fg("muted", "Z.ai:")} ${parts.join(` ${theme.fg("dim", "·")} `)}`;
|
|
74
|
+
}
|
|
75
|
+
function nowEpochMilliseconds() {
|
|
76
|
+
return Temporal.Now.instant().epochMilliseconds;
|
|
77
|
+
}
|
|
78
|
+
export default function extension(pi) {
|
|
79
|
+
let lastData = null;
|
|
80
|
+
let lastFetchTime = 0;
|
|
81
|
+
let footerActive = false;
|
|
82
|
+
/** The most recent context, updated on each event so the footer reads fresh state. */
|
|
83
|
+
let ctxRef = null;
|
|
84
|
+
const HOME = process.env.HOME || process.env.USERPROFILE || "";
|
|
85
|
+
async function updateStatus(ctx) {
|
|
86
|
+
ctxRef = ctx;
|
|
87
|
+
try {
|
|
88
|
+
const now = nowEpochMilliseconds();
|
|
89
|
+
if (!lastData || now - lastFetchTime >= COOLDOWN_MS) {
|
|
90
|
+
lastData = await getZaiUsage(ctx.modelRegistry);
|
|
91
|
+
lastFetchTime = now;
|
|
92
|
+
}
|
|
93
|
+
installFooter();
|
|
94
|
+
}
|
|
95
|
+
catch {
|
|
96
|
+
lastData = null;
|
|
97
|
+
installFooter();
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
function installFooter() {
|
|
101
|
+
if (!footerActive) {
|
|
102
|
+
footerActive = true;
|
|
103
|
+
ctxRef?.ui.setFooter((tui, theme, footerData) => {
|
|
104
|
+
const unsub = footerData.onBranchChange(() => tui.requestRender());
|
|
105
|
+
return {
|
|
106
|
+
dispose: unsub,
|
|
107
|
+
invalidate() { },
|
|
108
|
+
render(width) {
|
|
109
|
+
const ctx = ctxRef;
|
|
110
|
+
if (!ctx)
|
|
111
|
+
return [theme.fg("dim", "…")];
|
|
112
|
+
const lines = [];
|
|
113
|
+
// ========================================================
|
|
114
|
+
// Line 1: pwd / branch / session name (left) + Z.ai (right)
|
|
115
|
+
// ========================================================
|
|
116
|
+
let pwd = formatCwdForFooter(ctx.sessionManager.getCwd(), HOME);
|
|
117
|
+
const branch = footerData.getGitBranch();
|
|
118
|
+
if (branch)
|
|
119
|
+
pwd = `${pwd} (${branch})`;
|
|
120
|
+
const sessionName = ctx.sessionManager.getSessionName();
|
|
121
|
+
if (sessionName)
|
|
122
|
+
pwd = `${pwd} • ${sessionName}`;
|
|
123
|
+
let zaiText = "";
|
|
124
|
+
if (lastData) {
|
|
125
|
+
zaiText = renderZaiStatus(lastData, theme);
|
|
126
|
+
}
|
|
127
|
+
const pwdStyled = theme.fg("dim", pwd);
|
|
128
|
+
if (zaiText) {
|
|
129
|
+
const pwdW = visibleWidth(pwdStyled);
|
|
130
|
+
const zaiW = visibleWidth(zaiText);
|
|
131
|
+
const spacing = Math.max(1, width - pwdW - zaiW);
|
|
132
|
+
lines.push(truncateToWidth(pwdStyled + " ".repeat(spacing) + zaiText, width, theme.fg("dim", "...")));
|
|
133
|
+
}
|
|
134
|
+
else {
|
|
135
|
+
lines.push(truncateToWidth(pwdStyled, width, theme.fg("dim", "...")));
|
|
136
|
+
}
|
|
137
|
+
// ========================================================
|
|
138
|
+
// Line 2: Token stats + context % (left) / model (right)
|
|
139
|
+
// ========================================================
|
|
140
|
+
let totalInput = 0;
|
|
141
|
+
let totalOutput = 0;
|
|
142
|
+
let totalCacheRead = 0;
|
|
143
|
+
let totalCacheWrite = 0;
|
|
144
|
+
let totalCost = 0;
|
|
145
|
+
for (const entry of ctx.sessionManager.getEntries()) {
|
|
146
|
+
if (entry.type === "message" && entry.message.role === "assistant") {
|
|
147
|
+
totalInput += entry.message.usage.input;
|
|
148
|
+
totalOutput += entry.message.usage.output;
|
|
149
|
+
totalCacheRead += entry.message.usage.cacheRead;
|
|
150
|
+
totalCacheWrite += entry.message.usage.cacheWrite;
|
|
151
|
+
totalCost += entry.message.usage.cost.total;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
const contextUsage = ctx.getContextUsage();
|
|
155
|
+
const contextWindow = contextUsage?.contextWindow ?? ctx.model?.contextWindow ?? 0;
|
|
156
|
+
const contextPercent = contextUsage?.percent !== null && contextUsage?.percent !== undefined
|
|
157
|
+
? contextUsage.percent.toFixed(1)
|
|
158
|
+
: "?";
|
|
159
|
+
const statsParts = [];
|
|
160
|
+
if (totalInput)
|
|
161
|
+
statsParts.push(`↑${formatTokens(totalInput)}`);
|
|
162
|
+
if (totalOutput)
|
|
163
|
+
statsParts.push(`↓${formatTokens(totalOutput)}`);
|
|
164
|
+
if (totalCacheRead)
|
|
165
|
+
statsParts.push(`R${formatTokens(totalCacheRead)}`);
|
|
166
|
+
if (totalCacheWrite)
|
|
167
|
+
statsParts.push(`W${formatTokens(totalCacheWrite)}`);
|
|
168
|
+
const usingSubscription = ctx.model ? ctx.modelRegistry.isUsingOAuth(ctx.model) : false;
|
|
169
|
+
if (totalCost || usingSubscription) {
|
|
170
|
+
const costStr = `$${totalCost.toFixed(3)}${usingSubscription ? " (sub)" : ""}`;
|
|
171
|
+
statsParts.push(costStr);
|
|
172
|
+
}
|
|
173
|
+
const contextDisplay = contextPercent === "?"
|
|
174
|
+
? `?/${formatTokens(contextWindow)}`
|
|
175
|
+
: `${contextPercent}%/${formatTokens(contextWindow)}`;
|
|
176
|
+
const contextPercentValue = contextUsage?.percent ?? 0;
|
|
177
|
+
let contextPercentStr;
|
|
178
|
+
if (contextPercentValue > 90) {
|
|
179
|
+
contextPercentStr = theme.fg("error", contextDisplay);
|
|
180
|
+
}
|
|
181
|
+
else if (contextPercentValue > 70) {
|
|
182
|
+
contextPercentStr = theme.fg("warning", contextDisplay);
|
|
183
|
+
}
|
|
184
|
+
else {
|
|
185
|
+
contextPercentStr = contextDisplay;
|
|
186
|
+
}
|
|
187
|
+
statsParts.push(contextPercentStr);
|
|
188
|
+
let statsLeft = statsParts.join(" ");
|
|
189
|
+
const modelName = ctx.model?.id || "no-model";
|
|
190
|
+
const statsLeftWidth = visibleWidth(statsLeft);
|
|
191
|
+
// Truncate stats if too wide
|
|
192
|
+
if (statsLeftWidth > width) {
|
|
193
|
+
statsLeft = truncateToWidth(statsLeft, width, "...");
|
|
194
|
+
}
|
|
195
|
+
const rightSide = modelName;
|
|
196
|
+
const totalNeeded = visibleWidth(statsLeft) + 2 + visibleWidth(rightSide);
|
|
197
|
+
let statsLine;
|
|
198
|
+
if (totalNeeded <= width) {
|
|
199
|
+
const padding = " ".repeat(width - visibleWidth(statsLeft) - visibleWidth(rightSide));
|
|
200
|
+
statsLine = theme.fg("dim", statsLeft) + theme.fg("dim", padding + rightSide);
|
|
201
|
+
}
|
|
202
|
+
else {
|
|
203
|
+
const availableForRight = width - visibleWidth(statsLeft) - 2;
|
|
204
|
+
if (availableForRight > 0) {
|
|
205
|
+
const truncatedRight = truncateToWidth(rightSide, availableForRight, "");
|
|
206
|
+
const padding = " ".repeat(width - visibleWidth(statsLeft) - visibleWidth(truncatedRight));
|
|
207
|
+
statsLine = theme.fg("dim", statsLeft) + theme.fg("dim", padding + truncatedRight);
|
|
208
|
+
}
|
|
209
|
+
else {
|
|
210
|
+
statsLine = theme.fg("dim", statsLeft);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
lines.push(statsLine);
|
|
214
|
+
// ========================================================
|
|
215
|
+
// Line 3+: Other extension statuses (excluding zai-usage)
|
|
216
|
+
// ========================================================
|
|
217
|
+
const extensionStatuses = footerData.getExtensionStatuses();
|
|
218
|
+
if (extensionStatuses.size > 0) {
|
|
219
|
+
const sortedStatuses = Array.from(extensionStatuses.entries())
|
|
220
|
+
.sort(([a], [b]) => a.localeCompare(b))
|
|
221
|
+
.filter(([k]) => k !== "zai-usage")
|
|
222
|
+
.map(([, text]) => sanitizeStatusText(text));
|
|
223
|
+
if (sortedStatuses.length > 0) {
|
|
224
|
+
const statusLine = sortedStatuses.join(" ");
|
|
225
|
+
lines.push(truncateToWidth(statusLine, width, theme.fg("dim", "...")));
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
return lines;
|
|
229
|
+
},
|
|
230
|
+
};
|
|
231
|
+
});
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
function clearStatus(ctx) {
|
|
235
|
+
lastData = null;
|
|
236
|
+
lastFetchTime = 0;
|
|
237
|
+
ctxRef = null;
|
|
238
|
+
if (footerActive) {
|
|
239
|
+
footerActive = false;
|
|
240
|
+
ctx.ui.setFooter(undefined);
|
|
241
|
+
}
|
|
15
242
|
}
|
|
16
|
-
|
|
243
|
+
// --- Event handlers ---
|
|
244
|
+
pi.on("session_start", async (_event, ctx) => {
|
|
245
|
+
if (isZaiProvider(ctx))
|
|
246
|
+
await updateStatus(ctx);
|
|
247
|
+
});
|
|
248
|
+
pi.on("model_select", async (event, ctx) => {
|
|
249
|
+
if (event.model?.provider?.toLowerCase()?.startsWith("zai")) {
|
|
250
|
+
await updateStatus(ctx);
|
|
251
|
+
}
|
|
252
|
+
else {
|
|
253
|
+
clearStatus(ctx);
|
|
254
|
+
}
|
|
255
|
+
});
|
|
256
|
+
pi.on("turn_end", async (_event, ctx) => {
|
|
257
|
+
if (isZaiProvider(ctx))
|
|
258
|
+
await updateStatus(ctx);
|
|
259
|
+
});
|
|
260
|
+
pi.on("session_shutdown", async (_event, ctx) => {
|
|
261
|
+
clearStatus(ctx);
|
|
262
|
+
});
|
|
17
263
|
}
|
|
18
|
-
const extension = createUsageExtension({
|
|
19
|
-
providerPrefix: "zai",
|
|
20
|
-
statusKey: "zai-usage",
|
|
21
|
-
label: "Z.ai",
|
|
22
|
-
fetchUsage: getZaiUsage,
|
|
23
|
-
renderStatus: renderZaiStatus,
|
|
24
|
-
});
|
|
25
|
-
export default extension;
|
|
26
264
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,WAAW,EAAqB,MAAM,OAAO,CAAA;AACtD,OAAO,EAAE,kBAAkB,EAAE,oBAAoB,EAAc,MAAM,aAAa,CAAA;AAElF,yDAAyD;AACzD,MAAM,UAAU,eAAe,CAAC,IAAkB,EAAE,KAAY;IAC9D,MAAM,iBAAiB,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,GAAG,EAAE,CAAC,GAAG,EAAE,CAAA;IAC/D,IAAI,MAAM,GAAG,GAAG,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC,GAAG,kBAAkB,CAAC,iBAAiB,EAAE,KAAK,CAAC,CAAC,GAAG,iBAAiB,GAAG,CAAC,EAAE,CAAA;IACpH,IAAI,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;QACzC,MAAM,IAAI,IAAI,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,IAAI,IAAI,CAAC,aAAa,GAAG,CAAC,EAAE,CAAA;IAC5D,CAAC;IACD,OAAO,MAAM,CAAA;AACf,CAAC;AAED,MAAM,SAAS,GACb,oBAAoB,CAAe;IACjC,cAAc,EAAE,KAAK;IACrB,SAAS,EAAE,WAAW;IACtB,KAAK,EAAE,MAAM;IACb,UAAU,EAAE,WAAW;IACvB,YAAY,EAAE,eAAe;CAC9B,CAAC,CAAA;AAEJ,eAAe,SAAS,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"datetime.d.ts","sourceRoot":"","sources":["../../src/usage-lib/datetime.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH;;GAEG;AACH,wBAAgB,wBAAwB,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAa3D;AAED;;GAEG;AACH,wBAAgB,8BAA8B,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,
|
|
1
|
+
{"version":3,"file":"datetime.d.ts","sourceRoot":"","sources":["../../src/usage-lib/datetime.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH;;GAEG;AACH,wBAAgB,wBAAwB,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAa3D;AAED;;GAEG;AACH,wBAAgB,8BAA8B,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CA0BjE"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Vendored from @alexanderfortin/pi-usage-lib (MIT).
|
|
2
|
+
* Vendored from the locally installed @alexanderfortin/pi-usage-lib (MIT).
|
|
3
3
|
* Date/time formatting utilities using Temporal.
|
|
4
4
|
*/
|
|
5
5
|
import { Temporal } from "temporal-polyfill";
|
|
@@ -28,19 +28,22 @@ export function formatTimeRemainingFromEpochMs(ms) {
|
|
|
28
28
|
const target = Temporal.Instant.fromEpochMilliseconds(ms);
|
|
29
29
|
// If the target time is in the past, return zero
|
|
30
30
|
if (target.epochMilliseconds < now.epochMilliseconds) {
|
|
31
|
-
return "0h 0m
|
|
31
|
+
return "0h 0m";
|
|
32
32
|
}
|
|
33
33
|
const duration = target.since(now);
|
|
34
34
|
const totalSeconds = Math.round(Math.abs(duration.seconds));
|
|
35
|
-
const
|
|
35
|
+
const days = Math.floor(totalSeconds / 86400);
|
|
36
|
+
const hours = Math.floor((totalSeconds % 86400) / 3600);
|
|
36
37
|
const minutes = Math.floor((totalSeconds % 3600) / 60);
|
|
37
|
-
|
|
38
|
+
if (days > 0) {
|
|
39
|
+
return `${days}d ${hours}h ${minutes}m`;
|
|
40
|
+
}
|
|
38
41
|
if (hours > 0) {
|
|
39
|
-
return `${hours}h ${minutes}m
|
|
42
|
+
return `${hours}h ${minutes}m`;
|
|
40
43
|
}
|
|
41
44
|
if (minutes > 0) {
|
|
42
|
-
return `${minutes}m
|
|
45
|
+
return `${minutes}m`;
|
|
43
46
|
}
|
|
44
|
-
return
|
|
47
|
+
return "<1m";
|
|
45
48
|
}
|
|
46
49
|
//# sourceMappingURL=datetime.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"datetime.js","sourceRoot":"","sources":["../../src/usage-lib/datetime.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAE5C;;GAEG;AACH,MAAM,UAAU,wBAAwB,CAAC,EAAU;IACjD,MAAM,OAAO,GAAG,QAAQ,CAAC,OAAO,CAAC,qBAAqB,CAAC,EAAE,CAAC,CAAA;IAC1D,MAAM,aAAa,GAAG,OAAO,CAAC,kBAAkB,CAAC,QAAQ,CAAC,GAAG,CAAC,UAAU,EAAE,IAAI,KAAK,CAAC,CAAA;IACpF,OAAO,aAAa,CAAC,cAAc,CAAC,SAAS,EAAE;QAC7C,OAAO,EAAE,OAAO;QAChB,GAAG,EAAE,SAAS;QACd,KAAK,EAAE,OAAO;QACd,IAAI,EAAE,SAAS;QACf,IAAI,EAAE,SAAS;QACf,MAAM,EAAE,SAAS;QACjB,MAAM,EAAE,SAAS;QACjB,YAAY,EAAE,OAAO;KACtB,CAAC,CAAA;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,8BAA8B,CAAC,EAAU;IACvD,MAAM,GAAG,GAAG,QAAQ,CAAC,GAAG,CAAC,OAAO,EAAE,CAAA;IAClC,MAAM,MAAM,GAAG,QAAQ,CAAC,OAAO,CAAC,qBAAqB,CAAC,EAAE,CAAC,CAAA;IAEzD,iDAAiD;IACjD,IAAI,MAAM,CAAC,iBAAiB,GAAG,GAAG,CAAC,iBAAiB,EAAE,CAAC;QACrD,OAAO,
|
|
1
|
+
{"version":3,"file":"datetime.js","sourceRoot":"","sources":["../../src/usage-lib/datetime.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAE5C;;GAEG;AACH,MAAM,UAAU,wBAAwB,CAAC,EAAU;IACjD,MAAM,OAAO,GAAG,QAAQ,CAAC,OAAO,CAAC,qBAAqB,CAAC,EAAE,CAAC,CAAA;IAC1D,MAAM,aAAa,GAAG,OAAO,CAAC,kBAAkB,CAAC,QAAQ,CAAC,GAAG,CAAC,UAAU,EAAE,IAAI,KAAK,CAAC,CAAA;IACpF,OAAO,aAAa,CAAC,cAAc,CAAC,SAAS,EAAE;QAC7C,OAAO,EAAE,OAAO;QAChB,GAAG,EAAE,SAAS;QACd,KAAK,EAAE,OAAO;QACd,IAAI,EAAE,SAAS;QACf,IAAI,EAAE,SAAS;QACf,MAAM,EAAE,SAAS;QACjB,MAAM,EAAE,SAAS;QACjB,YAAY,EAAE,OAAO;KACtB,CAAC,CAAA;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,8BAA8B,CAAC,EAAU;IACvD,MAAM,GAAG,GAAG,QAAQ,CAAC,GAAG,CAAC,OAAO,EAAE,CAAA;IAClC,MAAM,MAAM,GAAG,QAAQ,CAAC,OAAO,CAAC,qBAAqB,CAAC,EAAE,CAAC,CAAA;IAEzD,iDAAiD;IACjD,IAAI,MAAM,CAAC,iBAAiB,GAAG,GAAG,CAAC,iBAAiB,EAAE,CAAC;QACrD,OAAO,OAAO,CAAA;IAChB,CAAC;IAED,MAAM,QAAQ,GAAG,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;IAElC,MAAM,YAAY,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAA;IAC3D,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,GAAG,KAAK,CAAC,CAAA;IAC7C,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,YAAY,GAAG,KAAK,CAAC,GAAG,IAAI,CAAC,CAAA;IACvD,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,YAAY,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,CAAA;IAEtD,IAAI,IAAI,GAAG,CAAC,EAAE,CAAC;QACb,OAAO,GAAG,IAAI,KAAK,KAAK,KAAK,OAAO,GAAG,CAAA;IACzC,CAAC;IACD,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;QACd,OAAO,GAAG,KAAK,KAAK,OAAO,GAAG,CAAA;IAChC,CAAC;IACD,IAAI,OAAO,GAAG,CAAC,EAAE,CAAC;QAChB,OAAO,GAAG,OAAO,GAAG,CAAA;IACtB,CAAC;IACD,OAAO,KAAK,CAAA;AACd,CAAC"}
|