@v1nvn/zai 0.39.2 → 0.41.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/README.md +7 -7
- package/dist/index.js +26 -16
- package/dist/index.js.map +1 -1
- package/dist/usage.mjs +26 -16
- package/dist/usage.mjs.map +1 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -22,7 +22,7 @@ claude plugin install zai@agentic
|
|
|
22
22
|
In a terminal, bare:
|
|
23
23
|
|
|
24
24
|
```sh
|
|
25
|
-
npx -y @v1nvn/zai@0.
|
|
25
|
+
npx -y @v1nvn/zai@0.41.0 usage
|
|
26
26
|
```
|
|
27
27
|
|
|
28
28
|
## Usage
|
|
@@ -30,10 +30,10 @@ npx -y @v1nvn/zai@0.39.2
|
|
|
30
30
|
| Invocation | Does |
|
|
31
31
|
|---|---|
|
|
32
32
|
| `/zai-usage` | the account's usage report, as a pane |
|
|
33
|
-
| `npx -y @v1nvn/zai@0.
|
|
34
|
-
| `npx -y @v1nvn/zai@0.
|
|
35
|
-
| `npx -y @v1nvn/zai@0.
|
|
36
|
-
| `npx -y @v1nvn/zai@0.
|
|
33
|
+
| `npx -y @v1nvn/zai@0.41.0 usage` | the same report, printed bare |
|
|
34
|
+
| `npx -y @v1nvn/zai@0.41.0 usage --auth-token TOKEN` | same, key on the command line (visible in `ps`) |
|
|
35
|
+
| `npx -y @v1nvn/zai@0.41.0 usage --auth-token=TOKEN` | `=` form — zsh quoting-safe |
|
|
36
|
+
| `npx -y @v1nvn/zai@0.41.0 usage --base-url URL` | another GLM endpoint (default `api.z.ai`) |
|
|
37
37
|
|
|
38
38
|
Each setting takes the first source that provides it:
|
|
39
39
|
|
|
@@ -82,8 +82,8 @@ and re-vendor `types/claude-code.d.ts` (repo root) from the engine-laid
|
|
|
82
82
|
## Contracts
|
|
83
83
|
|
|
84
84
|
- One job: print the report, exit 0. Nothing is written anywhere.
|
|
85
|
-
- `/zai-usage` is one `node <plugin root>/bin/usage.mjs --json` exec through
|
|
85
|
+
- `/zai-usage` is one `node <plugin root>/bin/usage.mjs usage --json` exec through
|
|
86
86
|
the session's Bash tool — the same query `npx zai-usage` runs, awaited
|
|
87
87
|
as-is. The one allow rule it needs is
|
|
88
|
-
`Bash(node <plugin root>/bin/usage.mjs --json)`; the first run asks for it
|
|
88
|
+
`Bash(node <plugin root>/bin/usage.mjs usage --json)`; the first run asks for it
|
|
89
89
|
once, then it is remembered. Its report is a pane the model never reads.
|
package/dist/index.js
CHANGED
|
@@ -26,7 +26,7 @@ async function runMain(main) {
|
|
|
26
26
|
}
|
|
27
27
|
Number.MAX_SAFE_INTEGER;
|
|
28
28
|
//#endregion
|
|
29
|
-
//#region ../tokens/dist/assets/text-
|
|
29
|
+
//#region ../tokens/dist/assets/text-BF6fhxqq.js
|
|
30
30
|
function plain(text) {
|
|
31
31
|
return { text };
|
|
32
32
|
}
|
|
@@ -104,11 +104,11 @@ function barField(v, max, width) {
|
|
|
104
104
|
if (s.length < width) s += " ".repeat(width - s.length);
|
|
105
105
|
return s.slice(0, width);
|
|
106
106
|
}
|
|
107
|
-
/** Filled/empty meter: █ for used,
|
|
108
|
-
function
|
|
107
|
+
/** Filled/empty meter: █ for used, · for remaining (shade glyphs draw as nothing here). */
|
|
108
|
+
function dotMeter(pct, width) {
|
|
109
109
|
let filled = Math.round((pct || 0) / 100 * width);
|
|
110
110
|
filled = Math.max(0, Math.min(width, filled));
|
|
111
|
-
return "█".repeat(filled) + "
|
|
111
|
+
return "█".repeat(filled) + "·".repeat(width - filled);
|
|
112
112
|
}
|
|
113
113
|
function renderLines(lines) {
|
|
114
114
|
return lines.map((line) => line.map((seg) => seg.text).join("")).join("\n");
|
|
@@ -387,7 +387,7 @@ function reportLines({ platform, model, tool, quota, apiOffsetMin = 480, localOf
|
|
|
387
387
|
const bj = new Date(now.getTime() + apiOffsetMin * 6e4);
|
|
388
388
|
const bjDay = bj.getUTCDay();
|
|
389
389
|
const elapsedMin = bjDay >= 1 && bjDay <= 5 ? Math.max(0, Math.min(240, (bj.getUTCHours() - 14) * 60 + bj.getUTCMinutes())) : 0;
|
|
390
|
-
if (peakWin) out.push([dim(` ${padR("Peak", 16)}`), plain(`${padL(peakWin.start, 5)} ${
|
|
390
|
+
if (peakWin) out.push([dim(` ${padR("Peak", 16)}`), plain(`${padL(peakWin.start, 5)} ${dotMeter(Math.round(elapsedMin / 240 * 100), 22)} ${peakWin.end}`)]);
|
|
391
391
|
const limits = quota.limits ?? [];
|
|
392
392
|
const mcp = limits.find((l) => /mcp/i.test(l.type ?? ""));
|
|
393
393
|
const tok5 = limits.find((l) => /token/i.test(l.type ?? ""));
|
|
@@ -396,7 +396,7 @@ function reportLines({ platform, model, tool, quota, apiOffsetMin = 480, localOf
|
|
|
396
396
|
out.push([
|
|
397
397
|
dim(` ${padR("Tokens · 5h", 16)}`),
|
|
398
398
|
bold(padL(`${tok5.percentage || 0}%`, 5)),
|
|
399
|
-
plain(` ${
|
|
399
|
+
plain(` ${dotMeter(tok5.percentage, 22)} ${reset}`)
|
|
400
400
|
]);
|
|
401
401
|
}
|
|
402
402
|
if (tok5 && mcp) out.push([]);
|
|
@@ -405,7 +405,7 @@ function reportLines({ platform, model, tool, quota, apiOffsetMin = 480, localOf
|
|
|
405
405
|
out.push([
|
|
406
406
|
dim(` ${padR("MCP · this month", 16)}`),
|
|
407
407
|
bold(padL(`${mcp.percentage || 0}%`, 5)),
|
|
408
|
-
plain(` ${
|
|
408
|
+
plain(` ${dotMeter(mcp.percentage, 22)} ${reset}`)
|
|
409
409
|
]);
|
|
410
410
|
const parts = (mcp.usageDetails ?? []).map((d) => `${friendlyTool(d.modelCode)} ${fmtNum(d.usage)}`).join(" ");
|
|
411
411
|
if (parts) out.push([plain(` ${fmtNum(mcp.currentUsage)}M / ${fmtNum(mcp.totol)}M · ${parts}`)]);
|
|
@@ -459,17 +459,26 @@ function resolveBaseUrl(flag, env) {
|
|
|
459
459
|
origin: DEFAULT_BASE_URL
|
|
460
460
|
};
|
|
461
461
|
}
|
|
462
|
-
function buildProgram() {
|
|
463
|
-
|
|
462
|
+
function buildProgram(onUsage) {
|
|
463
|
+
const usage = new Command("usage").description("GLM Coding Plan quota and usage report").addOption(new Option("--auth-token <token>", "API key").env("ZAI_AUTH_TOKEN")).addOption(new Option("--base-url <url>", "base URL").env("ZAI_BASE_URL")).addOption(new Option("--json", "print the report lines as JSON for the zai mod")).action((options) => onUsage?.(options));
|
|
464
|
+
return new Command().name("zai-usage").description("GLM Coding Plan usage — one command, usage").action(() => void 0).addCommand(usage);
|
|
464
465
|
}
|
|
465
466
|
function parseArgs(args) {
|
|
466
|
-
|
|
467
|
-
if (
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
467
|
+
let parsed;
|
|
468
|
+
if (parseQuietly(buildProgram((options) => {
|
|
469
|
+
const { authToken, baseUrl, json } = options;
|
|
470
|
+
parsed = {
|
|
471
|
+
authToken: authToken || void 0,
|
|
472
|
+
baseUrl: baseUrl || void 0,
|
|
473
|
+
command: "usage",
|
|
474
|
+
json: json === true
|
|
475
|
+
};
|
|
476
|
+
}), args) === void 0) return;
|
|
477
|
+
return parsed ?? {
|
|
478
|
+
authToken: void 0,
|
|
479
|
+
baseUrl: void 0,
|
|
480
|
+
command: void 0,
|
|
481
|
+
json: false
|
|
473
482
|
};
|
|
474
483
|
}
|
|
475
484
|
function resolveConfig(env, parsed) {
|
|
@@ -554,6 +563,7 @@ async function fetchReport(config) {
|
|
|
554
563
|
//#endregion
|
|
555
564
|
//#region src/index.ts
|
|
556
565
|
var parsed = parseArgs(process.argv.slice(2)) ?? printUsageAndExit(buildProgram());
|
|
566
|
+
if (parsed.command !== "usage") printUsageAndExit(buildProgram());
|
|
557
567
|
await runMain(async () => {
|
|
558
568
|
const input = await fetchReport(resolveConfig(process.env, parsed));
|
|
559
569
|
console.log(parsed.json ? JSON.stringify({ lines: reportLines(input) }) : render(input));
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../core/dist/index.js","../../tokens/dist/assets/text-D_R3UWAk.js","../src/format.ts","../src/resolve.ts","../src/usage.ts","../src/index.ts"],"sourcesContent":["import { existsSync, readFileSync, readdirSync, statSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\n//#region src/cli.ts\nfunction parseQuietly(program, args, recover) {\n\ttry {\n\t\tprogram.allowExcessArguments(false).exitOverride().configureOutput({\n\t\t\twriteOut: () => void 0,\n\t\t\twriteErr: () => void 0\n\t\t}).parse([...args], { from: \"user\" });\n\t\treturn program;\n\t} catch (err) {\n\t\treturn recover?.(err);\n\t}\n}\nfunction printUsageAndExit(program) {\n\tconsole.error(program.helpInformation());\n\tprocess.exit(1);\n}\nasync function runMain(main) {\n\ttry {\n\t\tawait main();\n\t} catch (e) {\n\t\tconsole.error(e.message);\n\t\tprocess.exit(1);\n\t}\n}\n//#endregion\n//#region src/dev.ts\nvar RELOAD_DEBOUNCE_MS = 150;\nvar IGNORED_SEGMENTS = [\n\t\"/node_modules/\",\n\t\"/dist/\",\n\t\"/.git/\",\n\t\"/coverage/\"\n];\nfunction shouldReload(file) {\n\treturn IGNORED_SEGMENTS.every((seg) => !file.includes(seg));\n}\n/**\n* Debounced file-change reloads, serialized via a promise chain: concurrent\n* saves never overlap, and a mid-reload save still produces a follow-up.\n*/\nfunction watchWithReload(vite, reload) {\n\tlet chain = Promise.resolve();\n\tlet timer;\n\tvite.watcher.on(\"change\", (file) => {\n\t\tif (!shouldReload(file)) return;\n\t\tif (timer) clearTimeout(timer);\n\t\ttimer = setTimeout(() => {\n\t\t\ttimer = void 0;\n\t\t\tchain = chain.then(reload);\n\t\t}, RELOAD_DEBOUNCE_MS);\n\t});\n}\n//#endregion\n//#region src/input.ts\nfunction readAll(stream) {\n\treturn new Promise((resolve, reject) => {\n\t\tlet data = \"\";\n\t\tstream.setEncoding(\"utf8\");\n\t\tstream.on(\"data\", (chunk) => {\n\t\t\tdata += chunk;\n\t\t});\n\t\tstream.on(\"end\", () => {\n\t\t\tresolve(data);\n\t\t});\n\t\tstream.on(\"error\", reject);\n\t});\n}\nfunction readStdin(stream = process.stdin) {\n\treturn readAll(stream);\n}\n/** A markdown file's contents, with the CLI's no-such-file error. */\nfunction readMarkdownFile(path) {\n\tif (!statSync(path, { throwIfNoEntry: false })?.isFile()) throw new Error(`no such file: ${path}`);\n\treturn readFileSync(path, \"utf8\");\n}\n//#endregion\n//#region src/last-reply.ts\nfunction isFile(path) {\n\ttry {\n\t\treturn statSync(path).isFile();\n\t} catch {\n\t\treturn false;\n\t}\n}\nfunction textBlocks(entry) {\n\tconst content = entry.message?.content;\n\tif (entry.type !== \"assistant\" || !Array.isArray(content)) return;\n\tconst blocks = content.filter((b) => typeof b === \"object\" && b !== null && b.type === \"text\");\n\treturn blocks.length > 0 ? blocks : void 0;\n}\nfunction claudeProjectsDir() {\n\tconst claudeDir = process.env.CLAUDE_DIR ?? join(homedir(), \".claude\");\n\treturn join(claudeDir, \"projects\");\n}\n/**\n* The last assistant text reply from a Claude Code session, reproducing Claude\n* Code's `/copy` byte-for-byte: the last assistant entry that contains a\n* `text` block, only its `text` block(s) (tool_use / thinking dropped), blocks\n* joined with a blank line, and no trailing newline.\n*\n* @param arg a transcript file, a session UUID under the project dir, or\n* nothing to use the newest session for the current project.\n*/\nfunction lastReply(arg) {\n\tconst proj = (process.env.CLAUDE_PROJECT_DIR ?? process.cwd()).replaceAll(\"/\", \"-\");\n\tconst projDir = join(claudeProjectsDir(), proj);\n\tlet file;\n\tif (arg !== void 0) file = isFile(arg) ? arg : join(projDir, `${arg}.jsonl`);\n\telse if (existsSync(projDir)) {\n\t\tconst newest = readdirSync(projDir).filter((f) => f.endsWith(\".jsonl\")).map((f) => ({\n\t\t\tf,\n\t\t\tmtimeMs: statSync(join(projDir, f)).mtimeMs\n\t\t})).sort((a, b) => b.mtimeMs - a.mtimeMs).at(0);\n\t\tif (newest) file = join(projDir, newest.f);\n\t}\n\tif (file === void 0 || !isFile(file)) throw new Error(`no session transcript found in ${projDir}`);\n\tlet last;\n\tfor (const line of readFileSync(file, \"utf8\").split(\"\\n\")) {\n\t\tif (!line.includes(\"\\\"assistant\\\"\")) continue;\n\t\tlet entry;\n\t\ttry {\n\t\t\tentry = JSON.parse(line);\n\t\t} catch {\n\t\t\tcontinue;\n\t\t}\n\t\tconst blocks = textBlocks(entry);\n\t\tif (blocks) last = blocks;\n\t}\n\treturn (last ?? []).map((b) => b.text ?? \"\").join(\"\\n\\n\");\n}\n//#endregion\n//#region src/logger.ts\nvar LEVEL_RANK = {\n\tdebug: 10,\n\tinfo: 20,\n\twarn: 30,\n\terror: 40,\n\tsilent: Number.MAX_SAFE_INTEGER\n};\nfunction levelEnabled(active, wanted) {\n\treturn LEVEL_RANK[wanted] >= LEVEL_RANK[active];\n}\nvar LEVEL_LABEL = {\n\tdebug: \"DEBUG\",\n\terror: \"ERROR\",\n\tinfo: \"INFO\",\n\twarn: \"WARN\"\n};\nvar Logger = class {\n\tactiveLevel;\n\tstderr;\n\tconstructor(activeLevel, stderr = (line) => process.stderr.write(`${line}\\n`)) {\n\t\tthis.activeLevel = activeLevel;\n\t\tthis.stderr = stderr;\n\t}\n\tdebug(message) {\n\t\tthis.log(\"debug\", message);\n\t}\n\terror(message) {\n\t\tthis.log(\"error\", message);\n\t}\n\tinfo(message) {\n\t\tthis.log(\"info\", message);\n\t}\n\twarn(message) {\n\t\tthis.log(\"warn\", message);\n\t}\n\tlog(level, message) {\n\t\tif (levelEnabled(this.activeLevel, level)) this.stderr(`${LEVEL_LABEL[level]} ${message}`);\n\t}\n};\n//#endregion\n//#region src/shutdown.ts\n/** Close each closable in order (best-effort), then force-exit. */\nfunction shutdownOnSignals(closables, signals = [\"SIGINT\", \"SIGTERM\"]) {\n\tfunction shutdown() {\n\t\tclosables.reduce((acc, closable) => acc.then(async () => {\n\t\t\ttry {\n\t\t\t\tawait closable.close();\n\t\t\t} catch {}\n\t\t}), Promise.resolve()).finally(() => {\n\t\t\tprocess.exit(0);\n\t\t});\n\t}\n\tfor (const signal of signals) process.on(signal, shutdown);\n}\n//#endregion\nexport { Logger, claudeProjectsDir, lastReply, levelEnabled, parseQuietly, printUsageAndExit, readMarkdownFile, readStdin, runMain, shutdownOnSignals, watchWithReload };\n\n//# sourceMappingURL=index.js.map","//#region src/text.ts\nfunction plain(text) {\n\treturn { text };\n}\nfunction dim(text) {\n\treturn {\n\t\ttext,\n\t\tink: \"dim\"\n\t};\n}\nfunction bold(text) {\n\treturn {\n\t\ttext,\n\t\tink: \"bold\"\n\t};\n}\nvar MONTHS = [\n\t\"Jan\",\n\t\"Feb\",\n\t\"Mar\",\n\t\"Apr\",\n\t\"May\",\n\t\"Jun\",\n\t\"Jul\",\n\t\"Aug\",\n\t\"Sep\",\n\t\"Oct\",\n\t\"Nov\",\n\t\"Dec\"\n];\nvar EIGHTHS = [\n\t\"\",\n\t\"▏\",\n\t\"▎\",\n\t\"▍\",\n\t\"▌\",\n\t\"▋\",\n\t\"▊\",\n\t\"▉\"\n];\nvar RULE_WIDTH = 68;\nfunction rule() {\n\treturn \"─\".repeat(68);\n}\n/** '2026-08-15' → 'Aug 15'. */\nfunction dayLabel(day) {\n\tconst [, , month, date] = /^(\\d{4})-(\\d{2})-(\\d{2})$/.exec(day) ?? [];\n\treturn month !== void 0 && date !== void 0 ? `${MONTHS[+month - 1] ?? day} ${date}` : day;\n}\nfunction fmtClock(date) {\n\treturn `${pad2(date.getHours())}:${pad2(date.getMinutes())}`;\n}\nfunction pad2(n) {\n\treturn String(n).padStart(2, \"0\");\n}\n/** Local-time `YYYY-MM-DD` key. */\nfunction ymd(date) {\n\treturn `${date.getFullYear()}-${pad2(date.getMonth() + 1)}-${pad2(date.getDate())}`;\n}\nfunction fmtTokens(n) {\n\tif (n == null || Number.isNaN(n)) return \"—\";\n\tif (n >= 1e9) return (n / 1e9).toFixed(1) + \"B\";\n\tif (n >= 1e6) return (n / 1e6).toFixed(1) + \"M\";\n\tif (n >= 1e3) return (n / 1e3).toFixed(1) + \"K\";\n\treturn String(n);\n}\nfunction fmtNum(n) {\n\treturn (n || 0).toLocaleString(\"en-US\");\n}\nfunction padR(s, n) {\n\treturn s.length >= n ? s : s + \" \".repeat(n - s.length);\n}\nfunction padL(s, n) {\n\treturn s.length >= n ? s : \" \".repeat(n - s.length) + s;\n}\n/** Fixed-width bar field (width cols): █ blocks + an eighth-fraction + trailing spaces. */\nfunction barField(v, max, width) {\n\tif (!v || v <= 0 || max <= 0) return \" \".repeat(width);\n\tconst scaled = v / max * width;\n\tlet full = Math.floor(scaled);\n\tlet fi = Math.round((scaled - full) * 8);\n\tif (fi === 8) {\n\t\tfull += 1;\n\t\tfi = 0;\n\t}\n\tif (full === 0 && fi === 0) fi = 1;\n\tlet s = \"█\".repeat(Math.min(full, width));\n\tif (full < width && fi > 0) s += EIGHTHS[fi] ?? \"\";\n\tif (s.length < width) s += \" \".repeat(width - s.length);\n\treturn s.slice(0, width);\n}\n/** Filled/empty meter: █ for used, ░ for remaining. */\nfunction meter(pct, width) {\n\tlet filled = Math.round((pct || 0) / 100 * width);\n\tfilled = Math.max(0, Math.min(width, filled));\n\treturn \"█\".repeat(filled) + \"░\".repeat(width - filled);\n}\nfunction renderLines(lines) {\n\treturn lines.map((line) => line.map((seg) => seg.text).join(\"\")).join(\"\\n\");\n}\n//#endregion\nexport { ymd as _, dayLabel as a, fmtNum as c, pad2 as d, padL as f, rule as g, renderLines as h, bold as i, fmtTokens as l, plain as m, RULE_WIDTH as n, dim as o, padR as p, barField as r, fmtClock as s, MONTHS as t, meter as u };\n\n//# sourceMappingURL=text-D_R3UWAk.js.map","/**\n * Usage-report line model: `reportLines` lays the report out once as ink-tagged\n * segments (the pane draws those), and `render` joins them into the CLI's\n * monospace terminal / hook-block `reason` bytes — no markdown; alignment comes\n * from fixed-width columns and unicode block glyphs. Input is the parsed `data`\n * of the three ZAI/ZHIPU monitor endpoints (model-usage, tool-usage,\n * quota/limit — the last already passed through processQuotaLimit).\n */\n\nimport {\n barField,\n bold,\n dim,\n fmtNum,\n fmtTokens,\n meter,\n MONTHS,\n pad2,\n padL,\n padR,\n plain,\n renderLines,\n rule,\n RULE_WIDTH,\n} from '@v1nvn/tokens/text';\n\nimport type { Line } from '@v1nvn/tokens/text';\n\n// Lower-half block eighths for vertical bars (1/8 .. 7/8); a full cell uses '█'.\nconst VBLOCKS = '▁▂▃▄▅▆▇';\n\nexport interface ModelMixEntry {\n modelName?: string;\n sortOrder?: number;\n totalTokens?: number;\n}\n\nexport interface ZaiModelUsage {\n modelCallCount?: number[];\n modelDataList?: ModelMixEntry[];\n modelSummaryList?: ModelMixEntry[];\n tokensUsage?: number[];\n totalUsage?: { totalModelCallCount?: number; totalTokensUsage?: number };\n x_time?: string[];\n}\n\nexport interface ZaiToolUsage {\n totalUsage?: {\n totalNetworkSearchCount?: number;\n totalSearchMcpCount?: number;\n totalWebReadMcpCount?: number;\n totalZreadMcpCount?: number;\n };\n}\n\nexport interface ZaiQuotaLimit {\n currentUsage?: number;\n nextResetTime?: string;\n percentage?: number;\n totol?: number;\n type?: string;\n usageDetails?: { modelCode?: string; usage?: number }[];\n}\n\nexport interface ZaiQuota {\n level?: string;\n limits?: ZaiQuotaLimit[];\n}\n\nexport interface RenderInput {\n apiOffsetMin?: number;\n localOffsetMin?: number;\n model: ZaiModelUsage;\n now?: Date;\n platform: string;\n quota: ZaiQuota;\n tool: ZaiToolUsage;\n}\n\ninterface Slot {\n day: string;\n h: number;\n time: string;\n}\n\nfunction parseSlot(s: string | undefined): null | Slot {\n const m = /^(\\d{4})-(\\d{2})-(\\d{2}) (\\d{2}):(\\d{2})/.exec(s ?? '');\n if (!m) {\n return null;\n }\n return {\n h: +m[4],\n day: `${MONTHS[+m[2] - 1]} ${m[3]}`,\n time: `${m[4]}:${m[5]}`,\n };\n}\n\n/**\n * Re-express a naive \"YYYY-MM-DD HH:MM\" string from one UTC offset to another.\n * Offsets are minutes east of UTC (Beijing = 480, IST = 330). Pure — does not\n * depend on the runtime timezone, so it is deterministic under test.\n */\nfunction shiftSlot(\n s: string,\n fromOffsetMin: number,\n toOffsetMin: number,\n): null | Slot {\n const m = /^(\\d{4})-(\\d{2})-(\\d{2}) (\\d{2}):(\\d{2})/.exec(s);\n if (!m) {\n return null;\n }\n const utcMs =\n Date.UTC(+m[1], +m[2] - 1, +m[3], +m[4], +m[5]) - fromOffsetMin * 60000;\n const dt = new Date(utcMs + toOffsetMin * 60000);\n return {\n h: dt.getUTCHours(),\n day: `${MONTHS[dt.getUTCMonth()]} ${pad2(dt.getUTCDate())}`,\n time: `${pad2(dt.getUTCHours())}:${pad2(dt.getUTCMinutes())}`,\n };\n}\n\nfunction friendlyTool(code: string | undefined): string {\n switch ((code ?? '').toLowerCase()) {\n case 'search-prime':\n return 'web search';\n case 'web-reader':\n return 'web read';\n default:\n return code || 'other';\n }\n}\n\nfunction idleRuns(tok: number[]): { i: number; j: number; len: number }[] {\n const runs: { i: number; j: number; len: number }[] = [];\n let i = 0;\n while (i < tok.length) {\n if ((tok[i] || 0) === 0) {\n let j = i;\n while (j < tok.length && (tok[j] || 0) === 0) {\n j++;\n }\n runs.push({ i, j: j - 1, len: j - i });\n i = j;\n } else {\n i++;\n }\n }\n return runs;\n}\n\nfunction idleLabel(\n run: { i: number; j: number; len: number },\n x: string[],\n slotFn: (s: string) => null | Slot,\n): string {\n const a = slotFn(x[run.i]);\n const b = slotFn(x[run.j]);\n if (!a || !b) {\n return `idle (${run.len}h)`;\n }\n const start = `${a.day} ${a.time}`;\n const end = a.day === b.day ? b.time : `${b.day} ${b.time}`;\n return `idle ${start} → ${end} (${run.len}h)`;\n}\n\n// Per the usage-revision notice: Mon–Fri 14:00–18:00 Beijing (UTC+8) are peak\n// hours, where GLM-5.2 / GLM-5-Turbo tokens are billed at a 3× coefficient\n// (GLM-4.7 stays 1× all day). A bucket labelled \"HH:00\" spans HH:00–HH+1, so\n// the peak buckets are HH ∈ {14,15,16,17} on a weekday.\nfunction isPeakBucket(s: string | undefined): boolean {\n const m = /^(\\d{4})-(\\d{2})-(\\d{2}) (\\d{2}):/.exec(s ?? '');\n if (!m) {\n return false;\n }\n const wd = new Date(Date.UTC(+m[1], +m[2] - 1, +m[3])).getUTCDay(); // 0=Sun … 6=Sat\n return wd >= 1 && wd <= 5 && +m[4] >= 14 && +m[4] <= 17;\n}\n\n/** Local-time start/end of the 14:00–18:00 Beijing peak window (e.g. 11:30 / 15:30). */\nfunction localPeakWindow(\n apiOffsetMin: number,\n toOffsetMin: number,\n): null | { end: string; start: string } {\n const a = shiftSlot('2000-01-03 14:00', apiOffsetMin, toOffsetMin);\n const b = shiftSlot('2000-01-03 18:00', apiOffsetMin, toOffsetMin);\n if (!a || !b) {\n return null;\n }\n return { start: a.time, end: b.time };\n}\n\n/**\n * Vertical bar chart of hourly tokens. Returns an array of plain-text lines\n * (without the section header), or null if there are fewer than 2 buckets.\n *\n * Bars are scaled to `maxTok` across `ROWS` rows; the topmost filled cell of a\n * bar uses a fractional lower-block glyph (▁▂▃▄▅▆▇) for sub-row height. The\n * y-axis labels only the peak (top) and 0 (baseline); the header window and the\n * caller's peak annotation carry the exact values.\n */\nfunction hourlyVerticalChart({\n x,\n tok,\n nh,\n maxTok,\n peakIdx,\n slotFn,\n}: {\n maxTok: number;\n nh: number;\n peakIdx: number;\n slotFn: (s: string) => null | Slot;\n tok: number[];\n x: string[];\n}): null | string[] {\n const ROWS = 6; // bar rows above the baseline\n if (nh < 2 || maxTok <= 0) {\n return null;\n }\n\n const lines: string[] = [];\n const maxLab = fmtTokens(maxTok);\n const L = maxLab.length;\n const IND = 1; // leading indent\n const AXIS = IND + L + 1; // axis spine col (1-space gap after the label)\n const P0 = AXIS + 2; // first bar column (axis + 1-char gap)\n const PW = RULE_WIDTH - P0; // columns available for bars + gaps\n const slot = Math.max(1, Math.floor(PW / nh));\n const barW = slot >= 2 ? slot - 1 : 1;\n function barLeft(i: number): number {\n return P0 + i * slot;\n }\n function barCenter(i: number): number {\n return barLeft(i) + Math.floor(barW / 2);\n }\n const usedCols = nh * slot;\n function blank(): string[] {\n return Array<string>(RULE_WIDTH).fill(' ');\n }\n\n // bar glyph for hour i at row r (0 = bottom bar-row, ROWS-1 = top)\n function glyph(i: number, r: number): string {\n const v = tok[i] || 0;\n if (v <= 0) {\n return ' ';\n }\n const fill = (v / maxTok) * ROWS - r; // how much of row r the bar covers\n if (fill >= 1) {\n return '█';\n }\n if (fill > 0) {\n let e = Math.round(fill * 8); // 1..7 eighths\n if (e < 1) {\n e = 1;\n }\n if (e > 7) {\n e = 7;\n }\n return VBLOCKS[e - 1];\n }\n return ' ';\n }\n\n // bar rows, top → bottom; top row carries the max label + '┤', rest are '│'\n for (let r = ROWS - 1; r >= 0; r--) {\n const line = blank();\n line[AXIS] = r === ROWS - 1 ? '┤' : '│';\n if (r === ROWS - 1) {\n for (let k = 0; k < L; k++) {\n line[AXIS - 1 - L + k] = maxLab[k];\n }\n }\n for (let i = 0; i < nh; i++) {\n const g = glyph(i, r);\n if (g !== ' ') {\n for (let c = 0; c < barW; c++) {\n line[barLeft(i) + c] = g;\n }\n }\n }\n lines.push(line.join('').trimEnd());\n }\n\n // x-axis ticks: first, last, and every bucket landing on a 6h boundary (local)\n function slotOf(i: number): null | Slot {\n return slotFn(x[i]);\n }\n function isTick(i: number): boolean {\n if (i === 0 || i === nh - 1) {\n return true;\n }\n const s = slotOf(i);\n return !!s && s.h % 6 === 0;\n }\n\n // baseline: '0' label + corner '└' + '─' run, with '┬' under each tick\n const base = blank();\n base[AXIS - 2] = '0';\n base[AXIS] = '└';\n for (let c = AXIS + 1; c < P0 + usedCols; c++) {\n base[c] = '─';\n }\n for (let i = 0; i < nh; i++) {\n if (isTick(i)) {\n base[barCenter(i)] = '┬';\n }\n }\n lines.push(base.join('').trimEnd());\n\n // hour labels under ticks (skip if too close to the previous label)\n const hr = blank();\n let last = -10;\n for (let i = 0; i < nh; i++) {\n if (!isTick(i)) {\n continue;\n }\n const col = barCenter(i);\n if (col - last < 3) {\n continue;\n }\n const s = slotOf(i);\n const txt = s ? pad2(s.h) : ' ';\n hr[col] = txt[0];\n hr[col + 1] = txt[1];\n last = col;\n }\n lines.push(hr.join('').trimEnd());\n\n // day labels under the first tick of each new local day\n const day = blank();\n let lastDay: null | string = null;\n last = -10;\n for (let i = 0; i < nh; i++) {\n if (!isTick(i)) {\n continue;\n }\n const s = slotOf(i);\n if (!s || s.day === lastDay) {\n continue;\n }\n const col = barCenter(i);\n if (col - last >= s.day.length && col + s.day.length <= RULE_WIDTH) {\n for (let k = 0; k < s.day.length; k++) {\n day[col + k] = s.day[k];\n }\n lastDay = s.day;\n last = col + s.day.length;\n }\n }\n if (day.some(c => c !== ' ')) {\n lines.push(day.join('').trimEnd());\n }\n\n // peak-window (↑) and peak (◂) markers under bar centers\n const mark = blank();\n for (let i = 0; i < nh; i++) {\n if (isPeakBucket(x[i])) {\n mark[barCenter(i)] = '↑';\n }\n }\n if (peakIdx >= 0) {\n mark[barCenter(peakIdx)] = '◂';\n }\n if (mark.some(c => c !== ' ')) {\n lines.push(mark.join('').trimEnd());\n }\n\n return lines;\n}\n\nexport function reportLines({\n platform,\n model,\n tool,\n quota,\n apiOffsetMin = 480,\n localOffsetMin,\n now = new Date(),\n}: RenderInput): Line[] {\n const out: Line[] = [];\n\n // The monitor API labels every bucket in Beijing time (UTC+8). Shift each\n // timestamp to the caller's offset (minutes east of UTC) for display.\n // Defaults to the JS runtime's local zone.\n const toOffset =\n localOffsetMin != null ? localOffsetMin : -new Date().getTimezoneOffset();\n function convertSlot(s: string): null | Slot {\n return shiftSlot(s, apiOffsetMin, toOffset) ?? parseSlot(s);\n }\n\n const x = model.x_time ?? [];\n const tok = model.tokensUsage ?? [];\n const calls = model.modelCallCount ?? [];\n const nh = x.length;\n\n const tu = model.totalUsage ?? {};\n const total =\n tu.totalTokensUsage != null\n ? tu.totalTokensUsage\n : tok.reduce((a, b) => a + (b || 0), 0);\n const totalCalls =\n tu.totalModelCallCount != null\n ? tu.totalModelCallCount\n : calls.reduce((a, b) => a + (b || 0), 0);\n\n let peakIdx = -1;\n let peakTok = 0;\n for (let i = 0; i < tok.length; i++) {\n if (tok[i] > peakTok) {\n peakTok = tok[i];\n peakIdx = i;\n }\n }\n const peakCalls = peakIdx >= 0 ? calls[peakIdx] || 0 : 0;\n const pctPeak = total > 0 ? (peakTok / total) * 100 : 0;\n const peakSlot = peakIdx >= 0 ? convertSlot(x[peakIdx]) : null;\n\n const level = quota.level\n ? quota.level.charAt(0).toUpperCase() + quota.level.slice(1)\n : '';\n\n const left = ` GLM Coding Plan${level ? ' · ' + level : ''}`;\n const firstSlot = convertSlot(x[0]);\n const lastSlot = convertSlot(x[nh - 1]);\n const win =\n firstSlot && lastSlot\n ? `${firstSlot.day} ${firstSlot.time} → ${lastSlot.day} ${lastSlot.time} · ${nh}h`\n : platform;\n out.push([plain(rule())]);\n out.push([bold(left), dim(padL(win, RULE_WIDTH - left.length))]);\n out.push([plain(rule())]);\n\n const head = plain(\n ` ${fmtTokens(total)} tokens across ${fmtNum(totalCalls)} model calls`,\n );\n out.push([]);\n if (peakIdx >= 0 && peakSlot) {\n out.push([head, plain(' — ')]);\n out.push([\n bold(`${Math.round(pctPeak)}%`),\n plain(' of it in a single hour'),\n ]);\n out.push([\n plain(\n ` (${peakSlot.day} ${peakSlot.time}, ${fmtTokens(peakTok)} tokens / ${fmtNum(peakCalls)} calls).`,\n ),\n ]);\n } else {\n out.push([head, plain('.')]);\n }\n\n const activeHours = tok.filter(t => t > 0).length;\n const longest = idleRuns(tok)\n .filter(r => r.len >= 2)\n .sort((a, b) => b.len - a.len)\n .at(0);\n const tt = tool.totalUsage ?? {};\n const searchN = tt.totalNetworkSearchCount || 0;\n const readN = tt.totalWebReadMcpCount || 0;\n const zreadN = tt.totalZreadMcpCount || 0;\n const toolTotal =\n tt.totalSearchMcpCount != null\n ? tt.totalSearchMcpCount\n : searchN + readN + zreadN;\n\n let peakWinActive = 0;\n let peakWinTokens = 0;\n for (let k = 0; k < nh; k++) {\n if (isPeakBucket(x[k]) && tok[k] > 0) {\n peakWinActive++;\n peakWinTokens += tok[k];\n }\n }\n const peakWinPct = total > 0 ? (peakWinTokens / total) * 100 : 0;\n const peakWin = localPeakWindow(apiOffsetMin, toOffset);\n\n out.push([]);\n out.push([\n plain(\n ` Peak ${padR(peakSlot ? peakSlot.day + ' ' + peakSlot.time : '—', 15)}${padL(fmtTokens(peakTok), 7)} tokens · ${padL(fmtNum(peakCalls), 5)} calls`,\n ),\n ]);\n out.push([\n plain(\n ` Active ${padR(`${activeHours} / ${nh} hours`, 15)}${longest ? idleLabel(longest, x, convertSlot) : 'no idle gaps'}`,\n ),\n ]);\n out.push([\n plain(\n ` Tools ${padR(`${toolTotal} calls`, 15)}${searchN} searches · ${readN} reads${zreadN ? ` · ${zreadN} zread` : ''}`,\n ),\n ]);\n if (peakWin) {\n out.push([\n plain(\n ` Peak hrs Mon–Fri ${peakWin.start}–${peakWin.end} · GLM-5.2 3× · ${peakWinActive}h active · ${fmtTokens(peakWinTokens)} (`,\n ),\n bold(`${Math.round(peakWinPct)}%`),\n plain(')'),\n ]);\n }\n\n out.push([]);\n const chartHdr = ' Hourly tokens · ↑ peak hour ';\n out.push([\n dim(chartHdr + '─'.repeat(Math.max(0, RULE_WIDTH - chartHdr.length))),\n ]);\n const maxTok = peakTok || 1;\n const chartLines = hourlyVerticalChart({\n x,\n tok,\n nh,\n maxTok,\n peakIdx,\n slotFn: convertSlot,\n });\n if (chartLines) {\n out.push(...chartLines.map((l): Line => [plain(l)]));\n if (peakIdx >= 0 && peakSlot) {\n out.push([\n plain(\n ` ◂ peak ${peakSlot.day} ${peakSlot.time} ${fmtTokens(peakTok)} tokens · ${fmtNum(peakCalls)} calls`,\n ),\n ]);\n }\n } else {\n out.push([plain(' (not enough hourly data to chart)')]);\n }\n\n out.push([]);\n out.push([dim(' Model mix ' + '─'.repeat(Math.max(0, RULE_WIDTH - 11)))]);\n const mixSrc = model.modelSummaryList ?? model.modelDataList ?? [];\n const denom = mixSrc.reduce((a, m) => a + (m.totalTokens ?? 0), 0) || 1;\n const mixSorted = [...mixSrc].sort(\n (a, b) => (a.sortOrder || 0) - (b.sortOrder || 0),\n );\n for (const m of mixSorted) {\n const pct = ((m.totalTokens ?? 0) / denom) * 100;\n out.push([\n plain(\n ` ${padR(m.modelName || '?', 11)}${padL(fmtTokens(m.totalTokens), 8)} `,\n ),\n bold(padL(pct.toFixed(1) + '%', 6)),\n plain(` ${barField(pct, 100, 20)}`),\n ]);\n }\n\n out.push([]);\n out.push([dim(' Limits ' + '─'.repeat(Math.max(0, RULE_WIDTH - 8)))]);\n\n // The window does not bill on weekends, so the meter stays empty off Mon–Fri.\n const bj = new Date(now.getTime() + apiOffsetMin * 60000);\n const bjDay = bj.getUTCDay();\n const inWindow = bjDay >= 1 && bjDay <= 5;\n const elapsedMin = inWindow\n ? Math.max(\n 0,\n Math.min(240, (bj.getUTCHours() - 14) * 60 + bj.getUTCMinutes()),\n )\n : 0;\n if (peakWin) {\n out.push([\n dim(` ${padR('Peak', 16)}`),\n plain(\n `${padL(peakWin.start, 5)} ${meter(Math.round((elapsedMin / 240) * 100), 22)} ${peakWin.end}`,\n ),\n ]);\n }\n\n const limits = quota.limits ?? [];\n const mcp = limits.find(l => /mcp/i.test(l.type ?? ''));\n const tok5 = limits.find(l => /token/i.test(l.type ?? ''));\n if (tok5) {\n const reset = new Date(tok5.nextResetTime ?? '').toLocaleTimeString(\n 'en-IN',\n );\n out.push([\n dim(` ${padR('Tokens · 5h', 16)}`),\n bold(padL(`${tok5.percentage || 0}%`, 5)),\n plain(` ${meter(tok5.percentage, 22)} ${reset}`),\n ]);\n }\n\n if (tok5 && mcp) {\n out.push([]);\n }\n\n if (mcp) {\n const reset = new Date(mcp.nextResetTime ?? '').toLocaleString('en-IN');\n out.push([\n dim(` ${padR('MCP · this month', 16)}`),\n bold(padL(`${mcp.percentage || 0}%`, 5)),\n plain(` ${meter(mcp.percentage, 22)} ${reset}`),\n ]);\n const det = mcp.usageDetails ?? [];\n const parts = det\n .map(d => `${friendlyTool(d.modelCode)} ${fmtNum(d.usage)}`)\n .join(' ');\n if (parts) {\n out.push([\n plain(\n ` ${fmtNum(mcp.currentUsage)}M / ${fmtNum(mcp.totol)}M · ${parts}`,\n ),\n ]);\n }\n }\n\n out.push([]);\n out.push([plain(rule())]);\n return out;\n}\n\nexport function render(input: RenderInput): string {\n return renderLines(reportLines(input));\n}\n","import { parseQuietly } from '@v1nvn/agentic-core';\nimport { Command, Option } from 'commander';\n\nconst DEFAULT_BASE_URL = 'https://api.z.ai';\n\nconst GLM_HOSTS = new Set(['api.z.ai', 'dev.bigmodel.cn', 'open.bigmodel.cn']);\n\nexport interface ParsedArgs {\n readonly authToken: string | undefined;\n readonly baseUrl: string | undefined;\n readonly json: boolean;\n}\n\nexport interface ResolvedConfig {\n readonly token: string;\n readonly url: string;\n}\n\ninterface BaseUrl {\n readonly glm: boolean;\n readonly origin: string;\n}\n\nfunction fromEnv(value: string | undefined): string | undefined {\n return value ? value : undefined;\n}\n\nfunction originOf(value: string): string | undefined {\n try {\n const url = new URL(value);\n return url.protocol === 'https:' || url.protocol === 'http:'\n ? url.origin\n : undefined;\n } catch {\n return undefined;\n }\n}\n\nfunction isGlm(origin: string): boolean {\n return GLM_HOSTS.has(new URL(origin).hostname);\n}\n\nfunction resolveBaseUrl(\n flag: string | undefined,\n env: NodeJS.ProcessEnv,\n): BaseUrl {\n if (flag !== undefined) {\n const origin = originOf(flag);\n if (origin === undefined) {\n throw new Error(`invalid base URL: ${flag}`);\n }\n return { glm: isGlm(origin), origin };\n }\n const inherited = fromEnv(env.ANTHROPIC_BASE_URL);\n const origin = inherited === undefined ? undefined : originOf(inherited);\n if (origin !== undefined && isGlm(origin)) {\n return { glm: true, origin };\n }\n return { glm: false, origin: DEFAULT_BASE_URL };\n}\n\nexport function buildProgram(): Command {\n return new Command()\n .name('zai-usage')\n .addOption(\n new Option('--auth-token <token>', 'API key').env('ZAI_AUTH_TOKEN'),\n )\n .addOption(new Option('--base-url <url>', 'base URL').env('ZAI_BASE_URL'))\n .addOption(\n new Option('--json', 'print the report lines as JSON for the zai mod'),\n );\n}\n\nexport function parseArgs(args: readonly string[]): ParsedArgs | undefined {\n const program = parseQuietly(buildProgram(), args);\n if (program === undefined) {\n return undefined;\n }\n const { authToken, baseUrl, json } = program.opts<{\n authToken: string | undefined;\n baseUrl: string | undefined;\n json?: boolean;\n }>();\n return {\n authToken: authToken || undefined,\n baseUrl: baseUrl || undefined,\n json: json === true,\n };\n}\n\nexport function resolveConfig(\n env: NodeJS.ProcessEnv,\n parsed: ParsedArgs,\n): ResolvedConfig {\n const base = resolveBaseUrl(parsed.baseUrl, env);\n const token =\n parsed.authToken ??\n (base.glm ? fromEnv(env.ANTHROPIC_AUTH_TOKEN) : undefined);\n if (token === undefined) {\n throw new Error(\n env.ANTHROPIC_AUTH_TOKEN\n ? 'ANTHROPIC_AUTH_TOKEN is set, but the resolved base URL does not name a GLM host, so it is not a GLM Coding Plan token — set ZAI_AUTH_TOKEN (or --auth-token)'\n : 'no API key: set ZAI_AUTH_TOKEN (or --auth-token)',\n );\n }\n return { token, url: base.origin };\n}\n","/**\n * Usage query: the three GLM monitor endpoints of the resolved base URL,\n * assembled into the report input.\n */\n\nimport { pad2 } from '@v1nvn/tokens/text';\n\nimport type {\n RenderInput,\n ZaiModelUsage,\n ZaiQuota,\n ZaiToolUsage,\n} from './format.js';\nimport type { ResolvedConfig } from './resolve.js';\n\ninterface RawLimit {\n currentValue?: number;\n nextResetTime?: string;\n percentage?: number;\n type?: string;\n usage?: number;\n usageDetails?: { modelCode?: string; usage?: number }[];\n}\n\ninterface RawQuota {\n level?: string;\n limits?: RawLimit[];\n}\n\n// Auth failures arrive as HTTP 200 with success false.\ninterface RawEnvelope {\n code?: number;\n data?: unknown;\n msg?: string;\n success?: boolean;\n}\n\n// The monitor API labels every bucket in Beijing time; the query window runs\n// from yesterday at the current hour to the end of today's current hour.\nfunction queryParams(now = new Date()): string {\n const startDate = new Date(\n now.getFullYear(),\n now.getMonth(),\n now.getDate() - 1,\n now.getHours(),\n 0,\n 0,\n 0,\n );\n const endDate = new Date(\n now.getFullYear(),\n now.getMonth(),\n now.getDate(),\n now.getHours(),\n 59,\n 59,\n 999,\n );\n function formatDateTime(date: Date): string {\n return `${date.getFullYear()}-${pad2(date.getMonth() + 1)}-${pad2(date.getDate())} ${pad2(date.getHours())}:${pad2(date.getMinutes())}:${pad2(date.getSeconds())}`;\n }\n return `?startTime=${encodeURIComponent(formatDateTime(startDate))}&endTime=${encodeURIComponent(formatDateTime(endDate))}`;\n}\n\n// Rename the API's limit kinds to their display names; `totol` is the field the\n// renderer reads (sic — the upstream spelling).\nfunction processQuotaLimit(data: RawQuota): ZaiQuota {\n if (!data.limits) {\n return data;\n }\n data.limits = data.limits.map(item => {\n if (item.type === 'TOKENS_LIMIT') {\n return {\n type: 'Token usage(5 Hour)',\n percentage: item.percentage,\n nextResetTime: item.nextResetTime,\n };\n }\n if (item.type === 'TIME_LIMIT') {\n return {\n type: 'MCP usage(1 Month)',\n percentage: item.percentage,\n currentUsage: item.currentValue,\n totol: item.usage,\n usageDetails: item.usageDetails,\n nextResetTime: item.nextResetTime,\n };\n }\n return item;\n });\n return data;\n}\n\nasync function fetchJson(\n apiUrl: string,\n label: string,\n authToken: string,\n query = '',\n): Promise<unknown> {\n const res = await fetch(apiUrl + query, {\n headers: {\n Authorization: authToken,\n 'Accept-Language': 'en-US,en',\n 'Content-Type': 'application/json',\n },\n });\n const body = await res.text();\n if (res.status !== 200) {\n throw new Error(`[${label}] HTTP ${res.status}\\n${body}`);\n }\n let json: RawEnvelope;\n try {\n json = JSON.parse(body) as RawEnvelope;\n } catch (e) {\n throw new Error(\n `[${label}] could not parse response: ${(e as Error).message}`,\n { cause: e },\n );\n }\n if (json.success === false) {\n throw new Error(\n `[${label}] ${json.msg ?? 'request failed'} (code ${json.code ?? '?'})`,\n );\n }\n return json.data ?? json;\n}\n\nexport async function fetchReport(\n config: ResolvedConfig,\n): Promise<RenderInput> {\n const platform = config.url.includes('bigmodel') ? 'ZHIPU' : 'ZAI';\n\n const query = queryParams();\n try {\n const [model, tool, quotaRaw] = await Promise.all([\n fetchJson(\n `${config.url}/api/monitor/usage/model-usage`,\n 'Model usage',\n config.token,\n query,\n ),\n fetchJson(\n `${config.url}/api/monitor/usage/tool-usage`,\n 'Tool usage',\n config.token,\n query,\n ),\n fetchJson(\n `${config.url}/api/monitor/usage/quota/limit`,\n 'Quota limit',\n config.token,\n ),\n ]);\n return {\n platform,\n model: model as ZaiModelUsage,\n tool: tool as ZaiToolUsage,\n quota: processQuotaLimit(quotaRaw as RawQuota),\n };\n } catch (e) {\n throw new Error(`Request failed: ${(e as Error).message}`, { cause: e });\n }\n}\n","import { printUsageAndExit, runMain } from '@v1nvn/agentic-core';\n\nimport { render, reportLines } from './format.js';\nimport { buildProgram, parseArgs, resolveConfig } from './resolve.js';\nimport { fetchReport } from './usage.js';\n\nconst parsed =\n parseArgs(process.argv.slice(2)) ?? printUsageAndExit(buildProgram());\n\nawait runMain(async () => {\n const input = await fetchReport(resolveConfig(process.env, parsed));\n console.log(\n parsed.json ? JSON.stringify({ lines: reportLines(input) }) : render(input),\n );\n});\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../core/dist/index.js","../../tokens/dist/assets/text-BF6fhxqq.js","../src/format.ts","../src/resolve.ts","../src/usage.ts","../src/index.ts"],"sourcesContent":["import { existsSync, readFileSync, readdirSync, statSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\n//#region src/cli.ts\nfunction parseQuietly(program, args, recover) {\n\ttry {\n\t\tprogram.allowExcessArguments(false).exitOverride().configureOutput({\n\t\t\twriteOut: () => void 0,\n\t\t\twriteErr: () => void 0\n\t\t}).parse([...args], { from: \"user\" });\n\t\treturn program;\n\t} catch (err) {\n\t\treturn recover?.(err);\n\t}\n}\nfunction printUsageAndExit(program) {\n\tconsole.error(program.helpInformation());\n\tprocess.exit(1);\n}\nasync function runMain(main) {\n\ttry {\n\t\tawait main();\n\t} catch (e) {\n\t\tconsole.error(e.message);\n\t\tprocess.exit(1);\n\t}\n}\n//#endregion\n//#region src/dev.ts\nvar RELOAD_DEBOUNCE_MS = 150;\nvar IGNORED_SEGMENTS = [\n\t\"/node_modules/\",\n\t\"/dist/\",\n\t\"/.git/\",\n\t\"/coverage/\"\n];\nfunction shouldReload(file) {\n\treturn IGNORED_SEGMENTS.every((seg) => !file.includes(seg));\n}\n/**\n* Debounced file-change reloads, serialized via a promise chain: concurrent\n* saves never overlap, and a mid-reload save still produces a follow-up.\n*/\nfunction watchWithReload(vite, reload) {\n\tlet chain = Promise.resolve();\n\tlet timer;\n\tvite.watcher.on(\"change\", (file) => {\n\t\tif (!shouldReload(file)) return;\n\t\tif (timer) clearTimeout(timer);\n\t\ttimer = setTimeout(() => {\n\t\t\ttimer = void 0;\n\t\t\tchain = chain.then(reload);\n\t\t}, RELOAD_DEBOUNCE_MS);\n\t});\n}\n//#endregion\n//#region src/input.ts\nfunction readAll(stream) {\n\treturn new Promise((resolve, reject) => {\n\t\tlet data = \"\";\n\t\tstream.setEncoding(\"utf8\");\n\t\tstream.on(\"data\", (chunk) => {\n\t\t\tdata += chunk;\n\t\t});\n\t\tstream.on(\"end\", () => {\n\t\t\tresolve(data);\n\t\t});\n\t\tstream.on(\"error\", reject);\n\t});\n}\nfunction readStdin(stream = process.stdin) {\n\treturn readAll(stream);\n}\n/** A markdown file's contents, with the CLI's no-such-file error. */\nfunction readMarkdownFile(path) {\n\tif (!statSync(path, { throwIfNoEntry: false })?.isFile()) throw new Error(`no such file: ${path}`);\n\treturn readFileSync(path, \"utf8\");\n}\n//#endregion\n//#region src/last-reply.ts\nfunction isFile(path) {\n\ttry {\n\t\treturn statSync(path).isFile();\n\t} catch {\n\t\treturn false;\n\t}\n}\nfunction textBlocks(entry) {\n\tconst content = entry.message?.content;\n\tif (entry.type !== \"assistant\" || !Array.isArray(content)) return;\n\tconst blocks = content.filter((b) => typeof b === \"object\" && b !== null && b.type === \"text\");\n\treturn blocks.length > 0 ? blocks : void 0;\n}\nfunction claudeProjectsDir() {\n\tconst claudeDir = process.env.CLAUDE_DIR ?? join(homedir(), \".claude\");\n\treturn join(claudeDir, \"projects\");\n}\n/**\n* The last assistant text reply from a Claude Code session, reproducing Claude\n* Code's `/copy` byte-for-byte: the last assistant entry that contains a\n* `text` block, only its `text` block(s) (tool_use / thinking dropped), blocks\n* joined with a blank line, and no trailing newline.\n*\n* @param arg a transcript file, a session UUID under the project dir, or\n* nothing to use the newest session for the current project.\n*/\nfunction lastReply(arg) {\n\tconst proj = (process.env.CLAUDE_PROJECT_DIR ?? process.cwd()).replaceAll(\"/\", \"-\");\n\tconst projDir = join(claudeProjectsDir(), proj);\n\tlet file;\n\tif (arg !== void 0) file = isFile(arg) ? arg : join(projDir, `${arg}.jsonl`);\n\telse if (existsSync(projDir)) {\n\t\tconst newest = readdirSync(projDir).filter((f) => f.endsWith(\".jsonl\")).map((f) => ({\n\t\t\tf,\n\t\t\tmtimeMs: statSync(join(projDir, f)).mtimeMs\n\t\t})).sort((a, b) => b.mtimeMs - a.mtimeMs).at(0);\n\t\tif (newest) file = join(projDir, newest.f);\n\t}\n\tif (file === void 0 || !isFile(file)) throw new Error(`no session transcript found in ${projDir}`);\n\tlet last;\n\tfor (const line of readFileSync(file, \"utf8\").split(\"\\n\")) {\n\t\tif (!line.includes(\"\\\"assistant\\\"\")) continue;\n\t\tlet entry;\n\t\ttry {\n\t\t\tentry = JSON.parse(line);\n\t\t} catch {\n\t\t\tcontinue;\n\t\t}\n\t\tconst blocks = textBlocks(entry);\n\t\tif (blocks) last = blocks;\n\t}\n\treturn (last ?? []).map((b) => b.text ?? \"\").join(\"\\n\\n\");\n}\n//#endregion\n//#region src/logger.ts\nvar LEVEL_RANK = {\n\tdebug: 10,\n\tinfo: 20,\n\twarn: 30,\n\terror: 40,\n\tsilent: Number.MAX_SAFE_INTEGER\n};\nfunction levelEnabled(active, wanted) {\n\treturn LEVEL_RANK[wanted] >= LEVEL_RANK[active];\n}\nvar LEVEL_LABEL = {\n\tdebug: \"DEBUG\",\n\terror: \"ERROR\",\n\tinfo: \"INFO\",\n\twarn: \"WARN\"\n};\nvar Logger = class {\n\tactiveLevel;\n\tstderr;\n\tconstructor(activeLevel, stderr = (line) => process.stderr.write(`${line}\\n`)) {\n\t\tthis.activeLevel = activeLevel;\n\t\tthis.stderr = stderr;\n\t}\n\tdebug(message) {\n\t\tthis.log(\"debug\", message);\n\t}\n\terror(message) {\n\t\tthis.log(\"error\", message);\n\t}\n\tinfo(message) {\n\t\tthis.log(\"info\", message);\n\t}\n\twarn(message) {\n\t\tthis.log(\"warn\", message);\n\t}\n\tlog(level, message) {\n\t\tif (levelEnabled(this.activeLevel, level)) this.stderr(`${LEVEL_LABEL[level]} ${message}`);\n\t}\n};\n//#endregion\n//#region src/shutdown.ts\n/** Close each closable in order (best-effort), then force-exit. */\nfunction shutdownOnSignals(closables, signals = [\"SIGINT\", \"SIGTERM\"]) {\n\tfunction shutdown() {\n\t\tclosables.reduce((acc, closable) => acc.then(async () => {\n\t\t\ttry {\n\t\t\t\tawait closable.close();\n\t\t\t} catch {}\n\t\t}), Promise.resolve()).finally(() => {\n\t\t\tprocess.exit(0);\n\t\t});\n\t}\n\tfor (const signal of signals) process.on(signal, shutdown);\n}\n//#endregion\nexport { Logger, claudeProjectsDir, lastReply, levelEnabled, parseQuietly, printUsageAndExit, readMarkdownFile, readStdin, runMain, shutdownOnSignals, watchWithReload };\n\n//# sourceMappingURL=index.js.map","//#region src/text.ts\nfunction plain(text) {\n\treturn { text };\n}\nfunction dim(text) {\n\treturn {\n\t\ttext,\n\t\tink: \"dim\"\n\t};\n}\nfunction bold(text) {\n\treturn {\n\t\ttext,\n\t\tink: \"bold\"\n\t};\n}\nvar MONTHS = [\n\t\"Jan\",\n\t\"Feb\",\n\t\"Mar\",\n\t\"Apr\",\n\t\"May\",\n\t\"Jun\",\n\t\"Jul\",\n\t\"Aug\",\n\t\"Sep\",\n\t\"Oct\",\n\t\"Nov\",\n\t\"Dec\"\n];\nvar EIGHTHS = [\n\t\"\",\n\t\"▏\",\n\t\"▎\",\n\t\"▍\",\n\t\"▌\",\n\t\"▋\",\n\t\"▊\",\n\t\"▉\"\n];\nvar RULE_WIDTH = 68;\nfunction rule() {\n\treturn \"─\".repeat(68);\n}\n/** '2026-08-15' → 'Aug 15'. */\nfunction dayLabel(day) {\n\tconst [, , month, date] = /^(\\d{4})-(\\d{2})-(\\d{2})$/.exec(day) ?? [];\n\treturn month !== void 0 && date !== void 0 ? `${MONTHS[+month - 1] ?? day} ${date}` : day;\n}\nfunction fmtClock(date) {\n\treturn `${pad2(date.getHours())}:${pad2(date.getMinutes())}`;\n}\nfunction pad2(n) {\n\treturn String(n).padStart(2, \"0\");\n}\n/** Local-time `YYYY-MM-DD` key. */\nfunction ymd(date) {\n\treturn `${date.getFullYear()}-${pad2(date.getMonth() + 1)}-${pad2(date.getDate())}`;\n}\nfunction fmtTokens(n) {\n\tif (n == null || Number.isNaN(n)) return \"—\";\n\tif (n >= 1e9) return (n / 1e9).toFixed(1) + \"B\";\n\tif (n >= 1e6) return (n / 1e6).toFixed(1) + \"M\";\n\tif (n >= 1e3) return (n / 1e3).toFixed(1) + \"K\";\n\treturn String(n);\n}\nfunction fmtNum(n) {\n\treturn (n || 0).toLocaleString(\"en-US\");\n}\nfunction padR(s, n) {\n\treturn s.length >= n ? s : s + \" \".repeat(n - s.length);\n}\nfunction padL(s, n) {\n\treturn s.length >= n ? s : \" \".repeat(n - s.length) + s;\n}\n/** Fixed-width bar field (width cols): █ blocks + an eighth-fraction + trailing spaces. */\nfunction barField(v, max, width) {\n\tif (!v || v <= 0 || max <= 0) return \" \".repeat(width);\n\tconst scaled = v / max * width;\n\tlet full = Math.floor(scaled);\n\tlet fi = Math.round((scaled - full) * 8);\n\tif (fi === 8) {\n\t\tfull += 1;\n\t\tfi = 0;\n\t}\n\tif (full === 0 && fi === 0) fi = 1;\n\tlet s = \"█\".repeat(Math.min(full, width));\n\tif (full < width && fi > 0) s += EIGHTHS[fi] ?? \"\";\n\tif (s.length < width) s += \" \".repeat(width - s.length);\n\treturn s.slice(0, width);\n}\n/** Filled/empty meter: █ for used, · for remaining (shade glyphs draw as nothing here). */\nfunction dotMeter(pct, width) {\n\tlet filled = Math.round((pct || 0) / 100 * width);\n\tfilled = Math.max(0, Math.min(width, filled));\n\treturn \"█\".repeat(filled) + \"·\".repeat(width - filled);\n}\nvar SPARK_LEVELS = [\n\t\"▁\",\n\t\"▂\",\n\t\"▃\",\n\t\"▄\",\n\t\"▅\",\n\t\"▆\",\n\t\"▇\",\n\t\"█\"\n];\n/** Sparkline of the last `width` values, solid partial blocks only. */\nfunction sparkField(values, width) {\n\tconst vs = values.slice(-width);\n\tconst max = Math.max(1, ...vs);\n\treturn vs.map((v) => SPARK_LEVELS[Math.min(7, Math.round(v / max * 7))]).join(\"\").padEnd(width, \" \");\n}\nfunction renderLines(lines) {\n\treturn lines.map((line) => line.map((seg) => seg.text).join(\"\")).join(\"\\n\");\n}\n//#endregion\nexport { sparkField as _, dayLabel as a, fmtClock as c, pad2 as d, padL as f, rule as g, renderLines as h, bold as i, fmtNum as l, plain as m, RULE_WIDTH as n, dim as o, padR as p, barField as r, dotMeter as s, MONTHS as t, fmtTokens as u, ymd as v };\n\n//# sourceMappingURL=text-BF6fhxqq.js.map","/**\n * Usage-report line model: `reportLines` lays the report out once as ink-tagged\n * segments (the pane draws those), and `render` joins them into the CLI's\n * monospace terminal / hook-block `reason` bytes — no markdown; alignment comes\n * from fixed-width columns and unicode block glyphs. Input is the parsed `data`\n * of the three ZAI/ZHIPU monitor endpoints (model-usage, tool-usage,\n * quota/limit — the last already passed through processQuotaLimit).\n */\n\nimport {\n barField,\n bold,\n dim,\n dotMeter,\n fmtNum,\n fmtTokens,\n MONTHS,\n pad2,\n padL,\n padR,\n plain,\n renderLines,\n rule,\n RULE_WIDTH,\n} from '@v1nvn/tokens/text';\n\nimport type { Line } from '@v1nvn/tokens/text';\n\n// Lower-half block eighths for vertical bars (1/8 .. 7/8); a full cell uses '█'.\nconst VBLOCKS = '▁▂▃▄▅▆▇';\n\nexport interface ModelMixEntry {\n modelName?: string;\n sortOrder?: number;\n totalTokens?: number;\n}\n\nexport interface ZaiModelUsage {\n modelCallCount?: number[];\n modelDataList?: ModelMixEntry[];\n modelSummaryList?: ModelMixEntry[];\n tokensUsage?: number[];\n totalUsage?: { totalModelCallCount?: number; totalTokensUsage?: number };\n x_time?: string[];\n}\n\nexport interface ZaiToolUsage {\n totalUsage?: {\n totalNetworkSearchCount?: number;\n totalSearchMcpCount?: number;\n totalWebReadMcpCount?: number;\n totalZreadMcpCount?: number;\n };\n}\n\nexport interface ZaiQuotaLimit {\n currentUsage?: number;\n nextResetTime?: string;\n percentage?: number;\n totol?: number;\n type?: string;\n usageDetails?: { modelCode?: string; usage?: number }[];\n}\n\nexport interface ZaiQuota {\n level?: string;\n limits?: ZaiQuotaLimit[];\n}\n\nexport interface RenderInput {\n apiOffsetMin?: number;\n localOffsetMin?: number;\n model: ZaiModelUsage;\n now?: Date;\n platform: string;\n quota: ZaiQuota;\n tool: ZaiToolUsage;\n}\n\ninterface Slot {\n day: string;\n h: number;\n time: string;\n}\n\nfunction parseSlot(s: string | undefined): null | Slot {\n const m = /^(\\d{4})-(\\d{2})-(\\d{2}) (\\d{2}):(\\d{2})/.exec(s ?? '');\n if (!m) {\n return null;\n }\n return {\n h: +m[4],\n day: `${MONTHS[+m[2] - 1]} ${m[3]}`,\n time: `${m[4]}:${m[5]}`,\n };\n}\n\n/**\n * Re-express a naive \"YYYY-MM-DD HH:MM\" string from one UTC offset to another.\n * Offsets are minutes east of UTC (Beijing = 480, IST = 330). Pure — does not\n * depend on the runtime timezone, so it is deterministic under test.\n */\nfunction shiftSlot(\n s: string,\n fromOffsetMin: number,\n toOffsetMin: number,\n): null | Slot {\n const m = /^(\\d{4})-(\\d{2})-(\\d{2}) (\\d{2}):(\\d{2})/.exec(s);\n if (!m) {\n return null;\n }\n const utcMs =\n Date.UTC(+m[1], +m[2] - 1, +m[3], +m[4], +m[5]) - fromOffsetMin * 60000;\n const dt = new Date(utcMs + toOffsetMin * 60000);\n return {\n h: dt.getUTCHours(),\n day: `${MONTHS[dt.getUTCMonth()]} ${pad2(dt.getUTCDate())}`,\n time: `${pad2(dt.getUTCHours())}:${pad2(dt.getUTCMinutes())}`,\n };\n}\n\nfunction friendlyTool(code: string | undefined): string {\n switch ((code ?? '').toLowerCase()) {\n case 'search-prime':\n return 'web search';\n case 'web-reader':\n return 'web read';\n default:\n return code || 'other';\n }\n}\n\nfunction idleRuns(tok: number[]): { i: number; j: number; len: number }[] {\n const runs: { i: number; j: number; len: number }[] = [];\n let i = 0;\n while (i < tok.length) {\n if ((tok[i] || 0) === 0) {\n let j = i;\n while (j < tok.length && (tok[j] || 0) === 0) {\n j++;\n }\n runs.push({ i, j: j - 1, len: j - i });\n i = j;\n } else {\n i++;\n }\n }\n return runs;\n}\n\nfunction idleLabel(\n run: { i: number; j: number; len: number },\n x: string[],\n slotFn: (s: string) => null | Slot,\n): string {\n const a = slotFn(x[run.i]);\n const b = slotFn(x[run.j]);\n if (!a || !b) {\n return `idle (${run.len}h)`;\n }\n const start = `${a.day} ${a.time}`;\n const end = a.day === b.day ? b.time : `${b.day} ${b.time}`;\n return `idle ${start} → ${end} (${run.len}h)`;\n}\n\n// Per the usage-revision notice: Mon–Fri 14:00–18:00 Beijing (UTC+8) are peak\n// hours, where GLM-5.2 / GLM-5-Turbo tokens are billed at a 3× coefficient\n// (GLM-4.7 stays 1× all day). A bucket labelled \"HH:00\" spans HH:00–HH+1, so\n// the peak buckets are HH ∈ {14,15,16,17} on a weekday.\nfunction isPeakBucket(s: string | undefined): boolean {\n const m = /^(\\d{4})-(\\d{2})-(\\d{2}) (\\d{2}):/.exec(s ?? '');\n if (!m) {\n return false;\n }\n const wd = new Date(Date.UTC(+m[1], +m[2] - 1, +m[3])).getUTCDay(); // 0=Sun … 6=Sat\n return wd >= 1 && wd <= 5 && +m[4] >= 14 && +m[4] <= 17;\n}\n\n/** Local-time start/end of the 14:00–18:00 Beijing peak window (e.g. 11:30 / 15:30). */\nfunction localPeakWindow(\n apiOffsetMin: number,\n toOffsetMin: number,\n): null | { end: string; start: string } {\n const a = shiftSlot('2000-01-03 14:00', apiOffsetMin, toOffsetMin);\n const b = shiftSlot('2000-01-03 18:00', apiOffsetMin, toOffsetMin);\n if (!a || !b) {\n return null;\n }\n return { start: a.time, end: b.time };\n}\n\n/**\n * Vertical bar chart of hourly tokens. Returns an array of plain-text lines\n * (without the section header), or null if there are fewer than 2 buckets.\n *\n * Bars are scaled to `maxTok` across `ROWS` rows; the topmost filled cell of a\n * bar uses a fractional lower-block glyph (▁▂▃▄▅▆▇) for sub-row height. The\n * y-axis labels only the peak (top) and 0 (baseline); the header window and the\n * caller's peak annotation carry the exact values.\n */\nfunction hourlyVerticalChart({\n x,\n tok,\n nh,\n maxTok,\n peakIdx,\n slotFn,\n}: {\n maxTok: number;\n nh: number;\n peakIdx: number;\n slotFn: (s: string) => null | Slot;\n tok: number[];\n x: string[];\n}): null | string[] {\n const ROWS = 6; // bar rows above the baseline\n if (nh < 2 || maxTok <= 0) {\n return null;\n }\n\n const lines: string[] = [];\n const maxLab = fmtTokens(maxTok);\n const L = maxLab.length;\n const IND = 1; // leading indent\n const AXIS = IND + L + 1; // axis spine col (1-space gap after the label)\n const P0 = AXIS + 2; // first bar column (axis + 1-char gap)\n const PW = RULE_WIDTH - P0; // columns available for bars + gaps\n const slot = Math.max(1, Math.floor(PW / nh));\n const barW = slot >= 2 ? slot - 1 : 1;\n function barLeft(i: number): number {\n return P0 + i * slot;\n }\n function barCenter(i: number): number {\n return barLeft(i) + Math.floor(barW / 2);\n }\n const usedCols = nh * slot;\n function blank(): string[] {\n return Array<string>(RULE_WIDTH).fill(' ');\n }\n\n // bar glyph for hour i at row r (0 = bottom bar-row, ROWS-1 = top)\n function glyph(i: number, r: number): string {\n const v = tok[i] || 0;\n if (v <= 0) {\n return ' ';\n }\n const fill = (v / maxTok) * ROWS - r; // how much of row r the bar covers\n if (fill >= 1) {\n return '█';\n }\n if (fill > 0) {\n let e = Math.round(fill * 8); // 1..7 eighths\n if (e < 1) {\n e = 1;\n }\n if (e > 7) {\n e = 7;\n }\n return VBLOCKS[e - 1];\n }\n return ' ';\n }\n\n // bar rows, top → bottom; top row carries the max label + '┤', rest are '│'\n for (let r = ROWS - 1; r >= 0; r--) {\n const line = blank();\n line[AXIS] = r === ROWS - 1 ? '┤' : '│';\n if (r === ROWS - 1) {\n for (let k = 0; k < L; k++) {\n line[AXIS - 1 - L + k] = maxLab[k];\n }\n }\n for (let i = 0; i < nh; i++) {\n const g = glyph(i, r);\n if (g !== ' ') {\n for (let c = 0; c < barW; c++) {\n line[barLeft(i) + c] = g;\n }\n }\n }\n lines.push(line.join('').trimEnd());\n }\n\n // x-axis ticks: first, last, and every bucket landing on a 6h boundary (local)\n function slotOf(i: number): null | Slot {\n return slotFn(x[i]);\n }\n function isTick(i: number): boolean {\n if (i === 0 || i === nh - 1) {\n return true;\n }\n const s = slotOf(i);\n return !!s && s.h % 6 === 0;\n }\n\n // baseline: '0' label + corner '└' + '─' run, with '┬' under each tick\n const base = blank();\n base[AXIS - 2] = '0';\n base[AXIS] = '└';\n for (let c = AXIS + 1; c < P0 + usedCols; c++) {\n base[c] = '─';\n }\n for (let i = 0; i < nh; i++) {\n if (isTick(i)) {\n base[barCenter(i)] = '┬';\n }\n }\n lines.push(base.join('').trimEnd());\n\n // hour labels under ticks (skip if too close to the previous label)\n const hr = blank();\n let last = -10;\n for (let i = 0; i < nh; i++) {\n if (!isTick(i)) {\n continue;\n }\n const col = barCenter(i);\n if (col - last < 3) {\n continue;\n }\n const s = slotOf(i);\n const txt = s ? pad2(s.h) : ' ';\n hr[col] = txt[0];\n hr[col + 1] = txt[1];\n last = col;\n }\n lines.push(hr.join('').trimEnd());\n\n // day labels under the first tick of each new local day\n const day = blank();\n let lastDay: null | string = null;\n last = -10;\n for (let i = 0; i < nh; i++) {\n if (!isTick(i)) {\n continue;\n }\n const s = slotOf(i);\n if (!s || s.day === lastDay) {\n continue;\n }\n const col = barCenter(i);\n if (col - last >= s.day.length && col + s.day.length <= RULE_WIDTH) {\n for (let k = 0; k < s.day.length; k++) {\n day[col + k] = s.day[k];\n }\n lastDay = s.day;\n last = col + s.day.length;\n }\n }\n if (day.some(c => c !== ' ')) {\n lines.push(day.join('').trimEnd());\n }\n\n // peak-window (↑) and peak (◂) markers under bar centers\n const mark = blank();\n for (let i = 0; i < nh; i++) {\n if (isPeakBucket(x[i])) {\n mark[barCenter(i)] = '↑';\n }\n }\n if (peakIdx >= 0) {\n mark[barCenter(peakIdx)] = '◂';\n }\n if (mark.some(c => c !== ' ')) {\n lines.push(mark.join('').trimEnd());\n }\n\n return lines;\n}\n\nexport function reportLines({\n platform,\n model,\n tool,\n quota,\n apiOffsetMin = 480,\n localOffsetMin,\n now = new Date(),\n}: RenderInput): Line[] {\n const out: Line[] = [];\n\n // The monitor API labels every bucket in Beijing time (UTC+8). Shift each\n // timestamp to the caller's offset (minutes east of UTC) for display.\n // Defaults to the JS runtime's local zone.\n const toOffset =\n localOffsetMin != null ? localOffsetMin : -new Date().getTimezoneOffset();\n function convertSlot(s: string): null | Slot {\n return shiftSlot(s, apiOffsetMin, toOffset) ?? parseSlot(s);\n }\n\n const x = model.x_time ?? [];\n const tok = model.tokensUsage ?? [];\n const calls = model.modelCallCount ?? [];\n const nh = x.length;\n\n const tu = model.totalUsage ?? {};\n const total =\n tu.totalTokensUsage != null\n ? tu.totalTokensUsage\n : tok.reduce((a, b) => a + (b || 0), 0);\n const totalCalls =\n tu.totalModelCallCount != null\n ? tu.totalModelCallCount\n : calls.reduce((a, b) => a + (b || 0), 0);\n\n let peakIdx = -1;\n let peakTok = 0;\n for (let i = 0; i < tok.length; i++) {\n if (tok[i] > peakTok) {\n peakTok = tok[i];\n peakIdx = i;\n }\n }\n const peakCalls = peakIdx >= 0 ? calls[peakIdx] || 0 : 0;\n const pctPeak = total > 0 ? (peakTok / total) * 100 : 0;\n const peakSlot = peakIdx >= 0 ? convertSlot(x[peakIdx]) : null;\n\n const level = quota.level\n ? quota.level.charAt(0).toUpperCase() + quota.level.slice(1)\n : '';\n\n const left = ` GLM Coding Plan${level ? ' · ' + level : ''}`;\n const firstSlot = convertSlot(x[0]);\n const lastSlot = convertSlot(x[nh - 1]);\n const win =\n firstSlot && lastSlot\n ? `${firstSlot.day} ${firstSlot.time} → ${lastSlot.day} ${lastSlot.time} · ${nh}h`\n : platform;\n out.push([plain(rule())]);\n out.push([bold(left), dim(padL(win, RULE_WIDTH - left.length))]);\n out.push([plain(rule())]);\n\n const head = plain(\n ` ${fmtTokens(total)} tokens across ${fmtNum(totalCalls)} model calls`,\n );\n out.push([]);\n if (peakIdx >= 0 && peakSlot) {\n out.push([head, plain(' — ')]);\n out.push([\n bold(`${Math.round(pctPeak)}%`),\n plain(' of it in a single hour'),\n ]);\n out.push([\n plain(\n ` (${peakSlot.day} ${peakSlot.time}, ${fmtTokens(peakTok)} tokens / ${fmtNum(peakCalls)} calls).`,\n ),\n ]);\n } else {\n out.push([head, plain('.')]);\n }\n\n const activeHours = tok.filter(t => t > 0).length;\n const longest = idleRuns(tok)\n .filter(r => r.len >= 2)\n .sort((a, b) => b.len - a.len)\n .at(0);\n const tt = tool.totalUsage ?? {};\n const searchN = tt.totalNetworkSearchCount || 0;\n const readN = tt.totalWebReadMcpCount || 0;\n const zreadN = tt.totalZreadMcpCount || 0;\n const toolTotal =\n tt.totalSearchMcpCount != null\n ? tt.totalSearchMcpCount\n : searchN + readN + zreadN;\n\n let peakWinActive = 0;\n let peakWinTokens = 0;\n for (let k = 0; k < nh; k++) {\n if (isPeakBucket(x[k]) && tok[k] > 0) {\n peakWinActive++;\n peakWinTokens += tok[k];\n }\n }\n const peakWinPct = total > 0 ? (peakWinTokens / total) * 100 : 0;\n const peakWin = localPeakWindow(apiOffsetMin, toOffset);\n\n out.push([]);\n out.push([\n plain(\n ` Peak ${padR(peakSlot ? peakSlot.day + ' ' + peakSlot.time : '—', 15)}${padL(fmtTokens(peakTok), 7)} tokens · ${padL(fmtNum(peakCalls), 5)} calls`,\n ),\n ]);\n out.push([\n plain(\n ` Active ${padR(`${activeHours} / ${nh} hours`, 15)}${longest ? idleLabel(longest, x, convertSlot) : 'no idle gaps'}`,\n ),\n ]);\n out.push([\n plain(\n ` Tools ${padR(`${toolTotal} calls`, 15)}${searchN} searches · ${readN} reads${zreadN ? ` · ${zreadN} zread` : ''}`,\n ),\n ]);\n if (peakWin) {\n out.push([\n plain(\n ` Peak hrs Mon–Fri ${peakWin.start}–${peakWin.end} · GLM-5.2 3× · ${peakWinActive}h active · ${fmtTokens(peakWinTokens)} (`,\n ),\n bold(`${Math.round(peakWinPct)}%`),\n plain(')'),\n ]);\n }\n\n out.push([]);\n const chartHdr = ' Hourly tokens · ↑ peak hour ';\n out.push([\n dim(chartHdr + '─'.repeat(Math.max(0, RULE_WIDTH - chartHdr.length))),\n ]);\n const maxTok = peakTok || 1;\n const chartLines = hourlyVerticalChart({\n x,\n tok,\n nh,\n maxTok,\n peakIdx,\n slotFn: convertSlot,\n });\n if (chartLines) {\n out.push(...chartLines.map((l): Line => [plain(l)]));\n if (peakIdx >= 0 && peakSlot) {\n out.push([\n plain(\n ` ◂ peak ${peakSlot.day} ${peakSlot.time} ${fmtTokens(peakTok)} tokens · ${fmtNum(peakCalls)} calls`,\n ),\n ]);\n }\n } else {\n out.push([plain(' (not enough hourly data to chart)')]);\n }\n\n out.push([]);\n out.push([dim(' Model mix ' + '─'.repeat(Math.max(0, RULE_WIDTH - 11)))]);\n const mixSrc = model.modelSummaryList ?? model.modelDataList ?? [];\n const denom = mixSrc.reduce((a, m) => a + (m.totalTokens ?? 0), 0) || 1;\n const mixSorted = [...mixSrc].sort(\n (a, b) => (a.sortOrder || 0) - (b.sortOrder || 0),\n );\n for (const m of mixSorted) {\n const pct = ((m.totalTokens ?? 0) / denom) * 100;\n out.push([\n plain(\n ` ${padR(m.modelName || '?', 11)}${padL(fmtTokens(m.totalTokens), 8)} `,\n ),\n bold(padL(pct.toFixed(1) + '%', 6)),\n plain(` ${barField(pct, 100, 20)}`),\n ]);\n }\n\n out.push([]);\n out.push([dim(' Limits ' + '─'.repeat(Math.max(0, RULE_WIDTH - 8)))]);\n\n // The window does not bill on weekends, so the meter stays empty off Mon–Fri.\n const bj = new Date(now.getTime() + apiOffsetMin * 60000);\n const bjDay = bj.getUTCDay();\n const inWindow = bjDay >= 1 && bjDay <= 5;\n const elapsedMin = inWindow\n ? Math.max(\n 0,\n Math.min(240, (bj.getUTCHours() - 14) * 60 + bj.getUTCMinutes()),\n )\n : 0;\n if (peakWin) {\n out.push([\n dim(` ${padR('Peak', 16)}`),\n plain(\n `${padL(peakWin.start, 5)} ${dotMeter(Math.round((elapsedMin / 240) * 100), 22)} ${peakWin.end}`,\n ),\n ]);\n }\n\n const limits = quota.limits ?? [];\n const mcp = limits.find(l => /mcp/i.test(l.type ?? ''));\n const tok5 = limits.find(l => /token/i.test(l.type ?? ''));\n if (tok5) {\n const reset = new Date(tok5.nextResetTime ?? '').toLocaleTimeString(\n 'en-IN',\n );\n out.push([\n dim(` ${padR('Tokens · 5h', 16)}`),\n bold(padL(`${tok5.percentage || 0}%`, 5)),\n plain(` ${dotMeter(tok5.percentage, 22)} ${reset}`),\n ]);\n }\n\n if (tok5 && mcp) {\n out.push([]);\n }\n\n if (mcp) {\n const reset = new Date(mcp.nextResetTime ?? '').toLocaleString('en-IN');\n out.push([\n dim(` ${padR('MCP · this month', 16)}`),\n bold(padL(`${mcp.percentage || 0}%`, 5)),\n plain(` ${dotMeter(mcp.percentage, 22)} ${reset}`),\n ]);\n const det = mcp.usageDetails ?? [];\n const parts = det\n .map(d => `${friendlyTool(d.modelCode)} ${fmtNum(d.usage)}`)\n .join(' ');\n if (parts) {\n out.push([\n plain(\n ` ${fmtNum(mcp.currentUsage)}M / ${fmtNum(mcp.totol)}M · ${parts}`,\n ),\n ]);\n }\n }\n\n out.push([]);\n out.push([plain(rule())]);\n return out;\n}\n\nexport function render(input: RenderInput): string {\n return renderLines(reportLines(input));\n}\n","import { parseQuietly } from '@v1nvn/agentic-core';\nimport { Command, Option } from 'commander';\n\nconst DEFAULT_BASE_URL = 'https://api.z.ai';\n\nconst GLM_HOSTS = new Set(['api.z.ai', 'dev.bigmodel.cn', 'open.bigmodel.cn']);\n\nexport interface ParsedArgs {\n readonly authToken: string | undefined;\n readonly baseUrl: string | undefined;\n readonly command?: 'usage';\n readonly json: boolean;\n}\n\nexport interface ResolvedConfig {\n readonly token: string;\n readonly url: string;\n}\n\ninterface BaseUrl {\n readonly glm: boolean;\n readonly origin: string;\n}\n\nfunction fromEnv(value: string | undefined): string | undefined {\n return value ? value : undefined;\n}\n\nfunction originOf(value: string): string | undefined {\n try {\n const url = new URL(value);\n return url.protocol === 'https:' || url.protocol === 'http:'\n ? url.origin\n : undefined;\n } catch {\n return undefined;\n }\n}\n\nfunction isGlm(origin: string): boolean {\n return GLM_HOSTS.has(new URL(origin).hostname);\n}\n\nfunction resolveBaseUrl(\n flag: string | undefined,\n env: NodeJS.ProcessEnv,\n): BaseUrl {\n if (flag !== undefined) {\n const origin = originOf(flag);\n if (origin === undefined) {\n throw new Error(`invalid base URL: ${flag}`);\n }\n return { glm: isGlm(origin), origin };\n }\n const inherited = fromEnv(env.ANTHROPIC_BASE_URL);\n const origin = inherited === undefined ? undefined : originOf(inherited);\n if (origin !== undefined && isGlm(origin)) {\n return { glm: true, origin };\n }\n return { glm: false, origin: DEFAULT_BASE_URL };\n}\n\nexport function buildProgram(\n onUsage?: (options: Record<string, unknown>) => void,\n): Command {\n const usage = new Command('usage')\n .description('GLM Coding Plan quota and usage report')\n .addOption(\n new Option('--auth-token <token>', 'API key').env('ZAI_AUTH_TOKEN'),\n )\n .addOption(new Option('--base-url <url>', 'base URL').env('ZAI_BASE_URL'))\n .addOption(\n new Option('--json', 'print the report lines as JSON for the zai mod'),\n )\n .action((options: Record<string, unknown>) => onUsage?.(options));\n return new Command()\n .name('zai-usage')\n .description('GLM Coding Plan usage — one command, usage')\n .action(() => undefined)\n .addCommand(usage);\n}\n\nexport function parseArgs(args: readonly string[]): ParsedArgs | undefined {\n let parsed: ParsedArgs | undefined;\n const program = buildProgram(options => {\n const { authToken, baseUrl, json } = options as {\n authToken?: string;\n baseUrl?: string;\n json?: boolean;\n };\n parsed = {\n authToken: authToken || undefined,\n baseUrl: baseUrl || undefined,\n command: 'usage',\n json: json === true,\n };\n });\n if (parseQuietly(program, args) === undefined) {\n return undefined;\n }\n return (\n parsed ?? {\n authToken: undefined,\n baseUrl: undefined,\n command: undefined,\n json: false,\n }\n );\n}\n\nexport function resolveConfig(\n env: NodeJS.ProcessEnv,\n parsed: ParsedArgs,\n): ResolvedConfig {\n const base = resolveBaseUrl(parsed.baseUrl, env);\n const token =\n parsed.authToken ??\n (base.glm ? fromEnv(env.ANTHROPIC_AUTH_TOKEN) : undefined);\n if (token === undefined) {\n throw new Error(\n env.ANTHROPIC_AUTH_TOKEN\n ? 'ANTHROPIC_AUTH_TOKEN is set, but the resolved base URL does not name a GLM host, so it is not a GLM Coding Plan token — set ZAI_AUTH_TOKEN (or --auth-token)'\n : 'no API key: set ZAI_AUTH_TOKEN (or --auth-token)',\n );\n }\n return { token, url: base.origin };\n}\n","/**\n * Usage query: the three GLM monitor endpoints of the resolved base URL,\n * assembled into the report input.\n */\n\nimport { pad2 } from '@v1nvn/tokens/text';\n\nimport type {\n RenderInput,\n ZaiModelUsage,\n ZaiQuota,\n ZaiToolUsage,\n} from './format.js';\nimport type { ResolvedConfig } from './resolve.js';\n\ninterface RawLimit {\n currentValue?: number;\n nextResetTime?: string;\n percentage?: number;\n type?: string;\n usage?: number;\n usageDetails?: { modelCode?: string; usage?: number }[];\n}\n\ninterface RawQuota {\n level?: string;\n limits?: RawLimit[];\n}\n\n// Auth failures arrive as HTTP 200 with success false.\ninterface RawEnvelope {\n code?: number;\n data?: unknown;\n msg?: string;\n success?: boolean;\n}\n\n// The monitor API labels every bucket in Beijing time; the query window runs\n// from yesterday at the current hour to the end of today's current hour.\nfunction queryParams(now = new Date()): string {\n const startDate = new Date(\n now.getFullYear(),\n now.getMonth(),\n now.getDate() - 1,\n now.getHours(),\n 0,\n 0,\n 0,\n );\n const endDate = new Date(\n now.getFullYear(),\n now.getMonth(),\n now.getDate(),\n now.getHours(),\n 59,\n 59,\n 999,\n );\n function formatDateTime(date: Date): string {\n return `${date.getFullYear()}-${pad2(date.getMonth() + 1)}-${pad2(date.getDate())} ${pad2(date.getHours())}:${pad2(date.getMinutes())}:${pad2(date.getSeconds())}`;\n }\n return `?startTime=${encodeURIComponent(formatDateTime(startDate))}&endTime=${encodeURIComponent(formatDateTime(endDate))}`;\n}\n\n// Rename the API's limit kinds to their display names; `totol` is the field the\n// renderer reads (sic — the upstream spelling).\nfunction processQuotaLimit(data: RawQuota): ZaiQuota {\n if (!data.limits) {\n return data;\n }\n data.limits = data.limits.map(item => {\n if (item.type === 'TOKENS_LIMIT') {\n return {\n type: 'Token usage(5 Hour)',\n percentage: item.percentage,\n nextResetTime: item.nextResetTime,\n };\n }\n if (item.type === 'TIME_LIMIT') {\n return {\n type: 'MCP usage(1 Month)',\n percentage: item.percentage,\n currentUsage: item.currentValue,\n totol: item.usage,\n usageDetails: item.usageDetails,\n nextResetTime: item.nextResetTime,\n };\n }\n return item;\n });\n return data;\n}\n\nasync function fetchJson(\n apiUrl: string,\n label: string,\n authToken: string,\n query = '',\n): Promise<unknown> {\n const res = await fetch(apiUrl + query, {\n headers: {\n Authorization: authToken,\n 'Accept-Language': 'en-US,en',\n 'Content-Type': 'application/json',\n },\n });\n const body = await res.text();\n if (res.status !== 200) {\n throw new Error(`[${label}] HTTP ${res.status}\\n${body}`);\n }\n let json: RawEnvelope;\n try {\n json = JSON.parse(body) as RawEnvelope;\n } catch (e) {\n throw new Error(\n `[${label}] could not parse response: ${(e as Error).message}`,\n { cause: e },\n );\n }\n if (json.success === false) {\n throw new Error(\n `[${label}] ${json.msg ?? 'request failed'} (code ${json.code ?? '?'})`,\n );\n }\n return json.data ?? json;\n}\n\nexport async function fetchReport(\n config: ResolvedConfig,\n): Promise<RenderInput> {\n const platform = config.url.includes('bigmodel') ? 'ZHIPU' : 'ZAI';\n\n const query = queryParams();\n try {\n const [model, tool, quotaRaw] = await Promise.all([\n fetchJson(\n `${config.url}/api/monitor/usage/model-usage`,\n 'Model usage',\n config.token,\n query,\n ),\n fetchJson(\n `${config.url}/api/monitor/usage/tool-usage`,\n 'Tool usage',\n config.token,\n query,\n ),\n fetchJson(\n `${config.url}/api/monitor/usage/quota/limit`,\n 'Quota limit',\n config.token,\n ),\n ]);\n return {\n platform,\n model: model as ZaiModelUsage,\n tool: tool as ZaiToolUsage,\n quota: processQuotaLimit(quotaRaw as RawQuota),\n };\n } catch (e) {\n throw new Error(`Request failed: ${(e as Error).message}`, { cause: e });\n }\n}\n","import { printUsageAndExit, runMain } from '@v1nvn/agentic-core';\n\nimport { render, reportLines } from './format.js';\nimport { buildProgram, parseArgs, resolveConfig } from './resolve.js';\nimport { fetchReport } from './usage.js';\n\nconst parsed =\n parseArgs(process.argv.slice(2)) ?? printUsageAndExit(buildProgram());\n\nif (parsed.command !== 'usage') {\n printUsageAndExit(buildProgram());\n}\n\nawait runMain(async () => {\n const input = await fetchReport(resolveConfig(process.env, parsed));\n console.log(\n parsed.json ? JSON.stringify({ lines: reportLines(input) }) : render(input),\n );\n});\n"],"mappings":"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"}
|
package/dist/usage.mjs
CHANGED
|
@@ -31,7 +31,7 @@ async function runMain(main) {
|
|
|
31
31
|
}
|
|
32
32
|
Number.MAX_SAFE_INTEGER;
|
|
33
33
|
//#endregion
|
|
34
|
-
//#region ../tokens/dist/assets/text-
|
|
34
|
+
//#region ../tokens/dist/assets/text-BF6fhxqq.js
|
|
35
35
|
function plain(text) {
|
|
36
36
|
return { text };
|
|
37
37
|
}
|
|
@@ -109,11 +109,11 @@ function barField(v, max, width) {
|
|
|
109
109
|
if (s.length < width) s += " ".repeat(width - s.length);
|
|
110
110
|
return s.slice(0, width);
|
|
111
111
|
}
|
|
112
|
-
/** Filled/empty meter: █ for used,
|
|
113
|
-
function
|
|
112
|
+
/** Filled/empty meter: █ for used, · for remaining (shade glyphs draw as nothing here). */
|
|
113
|
+
function dotMeter(pct, width) {
|
|
114
114
|
let filled = Math.round((pct || 0) / 100 * width);
|
|
115
115
|
filled = Math.max(0, Math.min(width, filled));
|
|
116
|
-
return "█".repeat(filled) + "
|
|
116
|
+
return "█".repeat(filled) + "·".repeat(width - filled);
|
|
117
117
|
}
|
|
118
118
|
function renderLines(lines) {
|
|
119
119
|
return lines.map((line) => line.map((seg) => seg.text).join("")).join("\n");
|
|
@@ -392,7 +392,7 @@ function reportLines({ platform, model, tool, quota, apiOffsetMin = 480, localOf
|
|
|
392
392
|
const bj = new Date(now.getTime() + apiOffsetMin * 6e4);
|
|
393
393
|
const bjDay = bj.getUTCDay();
|
|
394
394
|
const elapsedMin = bjDay >= 1 && bjDay <= 5 ? Math.max(0, Math.min(240, (bj.getUTCHours() - 14) * 60 + bj.getUTCMinutes())) : 0;
|
|
395
|
-
if (peakWin) out.push([dim(` ${padR("Peak", 16)}`), plain(`${padL(peakWin.start, 5)} ${
|
|
395
|
+
if (peakWin) out.push([dim(` ${padR("Peak", 16)}`), plain(`${padL(peakWin.start, 5)} ${dotMeter(Math.round(elapsedMin / 240 * 100), 22)} ${peakWin.end}`)]);
|
|
396
396
|
const limits = quota.limits ?? [];
|
|
397
397
|
const mcp = limits.find((l) => /mcp/i.test(l.type ?? ""));
|
|
398
398
|
const tok5 = limits.find((l) => /token/i.test(l.type ?? ""));
|
|
@@ -401,7 +401,7 @@ function reportLines({ platform, model, tool, quota, apiOffsetMin = 480, localOf
|
|
|
401
401
|
out.push([
|
|
402
402
|
dim(` ${padR("Tokens · 5h", 16)}`),
|
|
403
403
|
bold(padL(`${tok5.percentage || 0}%`, 5)),
|
|
404
|
-
plain(` ${
|
|
404
|
+
plain(` ${dotMeter(tok5.percentage, 22)} ${reset}`)
|
|
405
405
|
]);
|
|
406
406
|
}
|
|
407
407
|
if (tok5 && mcp) out.push([]);
|
|
@@ -410,7 +410,7 @@ function reportLines({ platform, model, tool, quota, apiOffsetMin = 480, localOf
|
|
|
410
410
|
out.push([
|
|
411
411
|
dim(` ${padR("MCP · this month", 16)}`),
|
|
412
412
|
bold(padL(`${mcp.percentage || 0}%`, 5)),
|
|
413
|
-
plain(` ${
|
|
413
|
+
plain(` ${dotMeter(mcp.percentage, 22)} ${reset}`)
|
|
414
414
|
]);
|
|
415
415
|
const parts = (mcp.usageDetails ?? []).map((d) => `${friendlyTool(d.modelCode)} ${fmtNum(d.usage)}`).join(" ");
|
|
416
416
|
if (parts) out.push([plain(` ${fmtNum(mcp.currentUsage)}M / ${fmtNum(mcp.totol)}M · ${parts}`)]);
|
|
@@ -3419,17 +3419,26 @@ function resolveBaseUrl(flag, env) {
|
|
|
3419
3419
|
origin: DEFAULT_BASE_URL
|
|
3420
3420
|
};
|
|
3421
3421
|
}
|
|
3422
|
-
function buildProgram() {
|
|
3423
|
-
|
|
3422
|
+
function buildProgram(onUsage) {
|
|
3423
|
+
const usage = new Command("usage").description("GLM Coding Plan quota and usage report").addOption(new Option("--auth-token <token>", "API key").env("ZAI_AUTH_TOKEN")).addOption(new Option("--base-url <url>", "base URL").env("ZAI_BASE_URL")).addOption(new Option("--json", "print the report lines as JSON for the zai mod")).action((options) => onUsage?.(options));
|
|
3424
|
+
return new Command().name("zai-usage").description("GLM Coding Plan usage — one command, usage").action(() => void 0).addCommand(usage);
|
|
3424
3425
|
}
|
|
3425
3426
|
function parseArgs(args) {
|
|
3426
|
-
|
|
3427
|
-
if (
|
|
3428
|
-
|
|
3429
|
-
|
|
3430
|
-
|
|
3431
|
-
|
|
3432
|
-
|
|
3427
|
+
let parsed;
|
|
3428
|
+
if (parseQuietly(buildProgram((options) => {
|
|
3429
|
+
const { authToken, baseUrl, json } = options;
|
|
3430
|
+
parsed = {
|
|
3431
|
+
authToken: authToken || void 0,
|
|
3432
|
+
baseUrl: baseUrl || void 0,
|
|
3433
|
+
command: "usage",
|
|
3434
|
+
json: json === true
|
|
3435
|
+
};
|
|
3436
|
+
}), args) === void 0) return;
|
|
3437
|
+
return parsed ?? {
|
|
3438
|
+
authToken: void 0,
|
|
3439
|
+
baseUrl: void 0,
|
|
3440
|
+
command: void 0,
|
|
3441
|
+
json: false
|
|
3433
3442
|
};
|
|
3434
3443
|
}
|
|
3435
3444
|
function resolveConfig(env, parsed) {
|
|
@@ -3514,6 +3523,7 @@ async function fetchReport(config) {
|
|
|
3514
3523
|
//#endregion
|
|
3515
3524
|
//#region src/index.ts
|
|
3516
3525
|
var parsed = parseArgs(process.argv.slice(2)) ?? printUsageAndExit(buildProgram());
|
|
3526
|
+
if (parsed.command !== "usage") printUsageAndExit(buildProgram());
|
|
3517
3527
|
await runMain(async () => {
|
|
3518
3528
|
const input = await fetchReport(resolveConfig(process.env, parsed));
|
|
3519
3529
|
console.log(parsed.json ? JSON.stringify({ lines: reportLines(input) }) : render(input));
|