@v1nvn/zai 0.44.0 → 0.45.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js DELETED
@@ -1,601 +0,0 @@
1
- #!/usr/bin/env node
2
- import { Command, Option } from "commander";
3
- //#region ../core/dist/index.js
4
- var HelpRequested = class extends Error {
5
- command;
6
- constructor(command) {
7
- super(`${command.name()} --help`);
8
- this.command = command;
9
- }
10
- };
11
- function parseQuietly(program, args) {
12
- function quiet(command) {
13
- command.configureOutput({
14
- writeOut: () => void 0,
15
- writeErr: () => void 0
16
- });
17
- command.exitOverride((err) => {
18
- const code = err.code;
19
- if (code === "commander.help" || code === "commander.helpDisplayed") throw new HelpRequested(command);
20
- throw err;
21
- });
22
- command.commands.forEach(quiet);
23
- }
24
- try {
25
- quiet(program);
26
- program.parse([...args], { from: "user" });
27
- return program;
28
- } catch (err) {
29
- return err instanceof HelpRequested ? err : void 0;
30
- }
31
- }
32
- function exitWithCode(code) {
33
- process.exit(code);
34
- }
35
- function printHelpAndExit(command) {
36
- console.log(command.helpInformation());
37
- exitWithCode(0);
38
- }
39
- function printUsageAndExit(program) {
40
- console.error(program.helpInformation());
41
- exitWithCode(1);
42
- }
43
- async function runMain(main) {
44
- try {
45
- await main();
46
- } catch (e) {
47
- console.error(e.message);
48
- exitWithCode(1);
49
- }
50
- }
51
- Number.MAX_SAFE_INTEGER;
52
- //#endregion
53
- //#region ../tokens/dist/assets/text-CwfwZy7j.js
54
- function plain(text) {
55
- return { text };
56
- }
57
- function dim(text) {
58
- return {
59
- text,
60
- ink: "dim"
61
- };
62
- }
63
- function bold(text) {
64
- return {
65
- text,
66
- ink: "bold"
67
- };
68
- }
69
- var MONTHS = [
70
- "Jan",
71
- "Feb",
72
- "Mar",
73
- "Apr",
74
- "May",
75
- "Jun",
76
- "Jul",
77
- "Aug",
78
- "Sep",
79
- "Oct",
80
- "Nov",
81
- "Dec"
82
- ];
83
- var EIGHTHS = [
84
- "",
85
- "▏",
86
- "▎",
87
- "▍",
88
- "▌",
89
- "▋",
90
- "▊",
91
- "▉"
92
- ];
93
- function rule() {
94
- return "─".repeat(68);
95
- }
96
- function pad2(n) {
97
- return String(n).padStart(2, "0");
98
- }
99
- function fmtTokens(n) {
100
- if (n == null || Number.isNaN(n)) return "—";
101
- if (n >= 1e9) return (n / 1e9).toFixed(1) + "B";
102
- if (n >= 1e6) return (n / 1e6).toFixed(1) + "M";
103
- if (n >= 1e3) return (n / 1e3).toFixed(1) + "K";
104
- return String(n);
105
- }
106
- function fmtNum(n) {
107
- return (n || 0).toLocaleString("en-US");
108
- }
109
- function padR(s, n) {
110
- return s.length >= n ? s : s + " ".repeat(n - s.length);
111
- }
112
- function padL(s, n) {
113
- return s.length >= n ? s : " ".repeat(n - s.length) + s;
114
- }
115
- /** Fixed-width bar field (width cols): █ blocks + an eighth-fraction + trailing spaces. */
116
- function barField(v, max, width) {
117
- if (!v || v <= 0 || max <= 0) return " ".repeat(width);
118
- const scaled = v / max * width;
119
- let full = Math.floor(scaled);
120
- let fi = Math.round((scaled - full) * 8);
121
- if (fi === 8) {
122
- full += 1;
123
- fi = 0;
124
- }
125
- if (full === 0 && fi === 0) fi = 1;
126
- let s = "█".repeat(Math.min(full, width));
127
- if (full < width && fi > 0) s += EIGHTHS[fi] ?? "";
128
- if (s.length < width) s += " ".repeat(width - s.length);
129
- return s.slice(0, width);
130
- }
131
- /** Filled/empty meter: █ for used, · for remaining (shade glyphs draw as nothing here). */
132
- function dotMeter(pct, width) {
133
- let filled = Math.round((pct || 0) / 100 * width);
134
- filled = Math.max(0, Math.min(width, filled));
135
- return "█".repeat(filled) + "·".repeat(width - filled);
136
- }
137
- function renderLines(lines) {
138
- return lines.map((line) => line.map((seg) => seg.text).join("")).join("\n");
139
- }
140
- //#endregion
141
- //#region src/format.ts
142
- /**
143
- * Usage-report line model: `reportLines` lays the report out once as ink-tagged
144
- * segments (the pane draws those), and `render` joins them into the CLI's
145
- * monospace terminal / hook-block `reason` bytes — no markdown; alignment comes
146
- * from fixed-width columns and unicode block glyphs. Input is the parsed `data`
147
- * of the three ZAI/ZHIPU monitor endpoints (model-usage, tool-usage,
148
- * quota/limit — the last already passed through processQuotaLimit).
149
- */
150
- var VBLOCKS = "▁▂▃▄▅▆▇";
151
- function parseSlot(s) {
152
- const m = /^(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2})/.exec(s ?? "");
153
- if (!m) return null;
154
- return {
155
- h: +m[4],
156
- day: `${MONTHS[+m[2] - 1]} ${m[3]}`,
157
- time: `${m[4]}:${m[5]}`
158
- };
159
- }
160
- /**
161
- * Re-express a naive "YYYY-MM-DD HH:MM" string from one UTC offset to another.
162
- * Offsets are minutes east of UTC (Beijing = 480, IST = 330). Pure — does not
163
- * depend on the runtime timezone, so it is deterministic under test.
164
- */
165
- function shiftSlot(s, fromOffsetMin, toOffsetMin) {
166
- const m = /^(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2})/.exec(s);
167
- if (!m) return null;
168
- const utcMs = Date.UTC(+m[1], +m[2] - 1, +m[3], +m[4], +m[5]) - fromOffsetMin * 6e4;
169
- const dt = new Date(utcMs + toOffsetMin * 6e4);
170
- return {
171
- h: dt.getUTCHours(),
172
- day: `${MONTHS[dt.getUTCMonth()]} ${pad2(dt.getUTCDate())}`,
173
- time: `${pad2(dt.getUTCHours())}:${pad2(dt.getUTCMinutes())}`
174
- };
175
- }
176
- function friendlyTool(code) {
177
- switch ((code ?? "").toLowerCase()) {
178
- case "search-prime": return "web search";
179
- case "web-reader": return "web read";
180
- default: return code || "other";
181
- }
182
- }
183
- function idleRuns(tok) {
184
- const runs = [];
185
- let i = 0;
186
- while (i < tok.length) if ((tok[i] || 0) === 0) {
187
- let j = i;
188
- while (j < tok.length && (tok[j] || 0) === 0) j++;
189
- runs.push({
190
- i,
191
- j: j - 1,
192
- len: j - i
193
- });
194
- i = j;
195
- } else i++;
196
- return runs;
197
- }
198
- function idleLabel(run, x, slotFn) {
199
- const a = slotFn(x[run.i]);
200
- const b = slotFn(x[run.j]);
201
- if (!a || !b) return `idle (${run.len}h)`;
202
- return `idle ${`${a.day} ${a.time}`} → ${a.day === b.day ? b.time : `${b.day} ${b.time}`} (${run.len}h)`;
203
- }
204
- function isPeakBucket(s) {
205
- const m = /^(\d{4})-(\d{2})-(\d{2}) (\d{2}):/.exec(s ?? "");
206
- if (!m) return false;
207
- const wd = new Date(Date.UTC(+m[1], +m[2] - 1, +m[3])).getUTCDay();
208
- return wd >= 1 && wd <= 5 && +m[4] >= 14 && +m[4] <= 17;
209
- }
210
- /** Local-time start/end of the 14:00–18:00 Beijing peak window (e.g. 11:30 / 15:30). */
211
- function localPeakWindow(apiOffsetMin, toOffsetMin) {
212
- const a = shiftSlot("2000-01-03 14:00", apiOffsetMin, toOffsetMin);
213
- const b = shiftSlot("2000-01-03 18:00", apiOffsetMin, toOffsetMin);
214
- if (!a || !b) return null;
215
- return {
216
- start: a.time,
217
- end: b.time
218
- };
219
- }
220
- /**
221
- * Vertical bar chart of hourly tokens. Returns an array of plain-text lines
222
- * (without the section header), or null if there are fewer than 2 buckets.
223
- *
224
- * Bars are scaled to `maxTok` across `ROWS` rows; the topmost filled cell of a
225
- * bar uses a fractional lower-block glyph (▁▂▃▄▅▆▇) for sub-row height. The
226
- * y-axis labels only the peak (top) and 0 (baseline); the header window and the
227
- * caller's peak annotation carry the exact values.
228
- */
229
- function hourlyVerticalChart({ x, tok, nh, maxTok, peakIdx, slotFn }) {
230
- const ROWS = 6;
231
- if (nh < 2 || maxTok <= 0) return null;
232
- const lines = [];
233
- const maxLab = fmtTokens(maxTok);
234
- const L = maxLab.length;
235
- const AXIS = 1 + L + 1;
236
- const P0 = AXIS + 2;
237
- const PW = 68 - P0;
238
- const slot = Math.max(1, Math.floor(PW / nh));
239
- const barW = slot >= 2 ? slot - 1 : 1;
240
- function barLeft(i) {
241
- return P0 + i * slot;
242
- }
243
- function barCenter(i) {
244
- return barLeft(i) + Math.floor(barW / 2);
245
- }
246
- const usedCols = nh * slot;
247
- function blank() {
248
- return Array(68).fill(" ");
249
- }
250
- function glyph(i, r) {
251
- const v = tok[i] || 0;
252
- if (v <= 0) return " ";
253
- const fill = v / maxTok * ROWS - r;
254
- if (fill >= 1) return "█";
255
- if (fill > 0) {
256
- let e = Math.round(fill * 8);
257
- if (e < 1) e = 1;
258
- if (e > 7) e = 7;
259
- return VBLOCKS[e - 1];
260
- }
261
- return " ";
262
- }
263
- for (let r = 5; r >= 0; r--) {
264
- const line = blank();
265
- line[AXIS] = r === 5 ? "┤" : "│";
266
- if (r === 5) for (let k = 0; k < L; k++) line[AXIS - 1 - L + k] = maxLab[k];
267
- for (let i = 0; i < nh; i++) {
268
- const g = glyph(i, r);
269
- if (g !== " ") for (let c = 0; c < barW; c++) line[barLeft(i) + c] = g;
270
- }
271
- lines.push(line.join("").trimEnd());
272
- }
273
- function slotOf(i) {
274
- return slotFn(x[i]);
275
- }
276
- function isTick(i) {
277
- if (i === 0 || i === nh - 1) return true;
278
- const s = slotOf(i);
279
- return !!s && s.h % 6 === 0;
280
- }
281
- const base = blank();
282
- base[AXIS - 2] = "0";
283
- base[AXIS] = "└";
284
- for (let c = AXIS + 1; c < P0 + usedCols; c++) base[c] = "─";
285
- for (let i = 0; i < nh; i++) if (isTick(i)) base[barCenter(i)] = "┬";
286
- lines.push(base.join("").trimEnd());
287
- const hr = blank();
288
- let last = -10;
289
- for (let i = 0; i < nh; i++) {
290
- if (!isTick(i)) continue;
291
- const col = barCenter(i);
292
- if (col - last < 3) continue;
293
- const s = slotOf(i);
294
- const txt = s ? pad2(s.h) : " ";
295
- hr[col] = txt[0];
296
- hr[col + 1] = txt[1];
297
- last = col;
298
- }
299
- lines.push(hr.join("").trimEnd());
300
- const day = blank();
301
- let lastDay = null;
302
- last = -10;
303
- for (let i = 0; i < nh; i++) {
304
- if (!isTick(i)) continue;
305
- const s = slotOf(i);
306
- if (!s || s.day === lastDay) continue;
307
- const col = barCenter(i);
308
- if (col - last >= s.day.length && col + s.day.length <= 68) {
309
- for (let k = 0; k < s.day.length; k++) day[col + k] = s.day[k];
310
- lastDay = s.day;
311
- last = col + s.day.length;
312
- }
313
- }
314
- if (day.some((c) => c !== " ")) lines.push(day.join("").trimEnd());
315
- const mark = blank();
316
- for (let i = 0; i < nh; i++) if (isPeakBucket(x[i])) mark[barCenter(i)] = "↑";
317
- if (peakIdx >= 0) mark[barCenter(peakIdx)] = "◂";
318
- if (mark.some((c) => c !== " ")) lines.push(mark.join("").trimEnd());
319
- return lines;
320
- }
321
- function reportLines({ platform, model, tool, quota, apiOffsetMin = 480, localOffsetMin, now = /* @__PURE__ */ new Date() }) {
322
- const out = [];
323
- const toOffset = localOffsetMin != null ? localOffsetMin : -(/* @__PURE__ */ new Date()).getTimezoneOffset();
324
- function convertSlot(s) {
325
- return shiftSlot(s, apiOffsetMin, toOffset) ?? parseSlot(s);
326
- }
327
- const x = model.x_time ?? [];
328
- const tok = model.tokensUsage ?? [];
329
- const calls = model.modelCallCount ?? [];
330
- const nh = x.length;
331
- const tu = model.totalUsage ?? {};
332
- const total = tu.totalTokensUsage != null ? tu.totalTokensUsage : tok.reduce((a, b) => a + (b || 0), 0);
333
- const totalCalls = tu.totalModelCallCount != null ? tu.totalModelCallCount : calls.reduce((a, b) => a + (b || 0), 0);
334
- let peakIdx = -1;
335
- let peakTok = 0;
336
- for (let i = 0; i < tok.length; i++) if (tok[i] > peakTok) {
337
- peakTok = tok[i];
338
- peakIdx = i;
339
- }
340
- const peakCalls = peakIdx >= 0 ? calls[peakIdx] || 0 : 0;
341
- const pctPeak = total > 0 ? peakTok / total * 100 : 0;
342
- const peakSlot = peakIdx >= 0 ? convertSlot(x[peakIdx]) : null;
343
- const level = quota.level ? quota.level.charAt(0).toUpperCase() + quota.level.slice(1) : "";
344
- const left = ` GLM Coding Plan${level ? " · " + level : ""}`;
345
- const firstSlot = convertSlot(x[0]);
346
- const lastSlot = convertSlot(x[nh - 1]);
347
- const win = firstSlot && lastSlot ? `${firstSlot.day} ${firstSlot.time} → ${lastSlot.day} ${lastSlot.time} · ${nh}h` : platform;
348
- out.push([plain(rule())]);
349
- out.push([bold(left), dim(padL(win, 68 - left.length))]);
350
- out.push([plain(rule())]);
351
- const head = plain(` ${fmtTokens(total)} tokens across ${fmtNum(totalCalls)} model calls`);
352
- out.push([]);
353
- if (peakIdx >= 0 && peakSlot) {
354
- out.push([head, plain(" — ")]);
355
- out.push([bold(`${Math.round(pctPeak)}%`), plain(" of it in a single hour")]);
356
- out.push([plain(` (${peakSlot.day} ${peakSlot.time}, ${fmtTokens(peakTok)} tokens / ${fmtNum(peakCalls)} calls).`)]);
357
- } else out.push([head, plain(".")]);
358
- const activeHours = tok.filter((t) => t > 0).length;
359
- const longest = idleRuns(tok).filter((r) => r.len >= 2).sort((a, b) => b.len - a.len).at(0);
360
- const tt = tool.totalUsage ?? {};
361
- const searchN = tt.totalNetworkSearchCount || 0;
362
- const readN = tt.totalWebReadMcpCount || 0;
363
- const zreadN = tt.totalZreadMcpCount || 0;
364
- const toolTotal = tt.totalSearchMcpCount != null ? tt.totalSearchMcpCount : searchN + readN + zreadN;
365
- let peakWinActive = 0;
366
- let peakWinTokens = 0;
367
- for (let k = 0; k < nh; k++) if (isPeakBucket(x[k]) && tok[k] > 0) {
368
- peakWinActive++;
369
- peakWinTokens += tok[k];
370
- }
371
- const peakWinPct = total > 0 ? peakWinTokens / total * 100 : 0;
372
- const peakWin = localPeakWindow(apiOffsetMin, toOffset);
373
- out.push([]);
374
- out.push([plain(` Peak ${padR(peakSlot ? peakSlot.day + " " + peakSlot.time : "—", 15)}${padL(fmtTokens(peakTok), 7)} tokens · ${padL(fmtNum(peakCalls), 5)} calls`)]);
375
- out.push([plain(` Active ${padR(`${activeHours} / ${nh} hours`, 15)}${longest ? idleLabel(longest, x, convertSlot) : "no idle gaps"}`)]);
376
- out.push([plain(` Tools ${padR(`${toolTotal} calls`, 15)}${searchN} searches · ${readN} reads${zreadN ? ` · ${zreadN} zread` : ""}`)]);
377
- if (peakWin) out.push([
378
- plain(` Peak hrs Mon–Fri ${peakWin.start}–${peakWin.end} · GLM-5.2 3× · ${peakWinActive}h active · ${fmtTokens(peakWinTokens)} (`),
379
- bold(`${Math.round(peakWinPct)}%`),
380
- plain(")")
381
- ]);
382
- out.push([]);
383
- out.push([dim(" Hourly tokens · ↑ peak hour " + "─".repeat(Math.max(0, 39)))]);
384
- const chartLines = hourlyVerticalChart({
385
- x,
386
- tok,
387
- nh,
388
- maxTok: peakTok || 1,
389
- peakIdx,
390
- slotFn: convertSlot
391
- });
392
- if (chartLines) {
393
- out.push(...chartLines.map((l) => [plain(l)]));
394
- if (peakIdx >= 0 && peakSlot) out.push([plain(` ◂ peak ${peakSlot.day} ${peakSlot.time} ${fmtTokens(peakTok)} tokens · ${fmtNum(peakCalls)} calls`)]);
395
- } else out.push([plain(" (not enough hourly data to chart)")]);
396
- out.push([]);
397
- out.push([dim(" Model mix " + "─".repeat(Math.max(0, 57)))]);
398
- const mixSrc = model.modelSummaryList ?? model.modelDataList ?? [];
399
- const denom = mixSrc.reduce((a, m) => a + (m.totalTokens ?? 0), 0) || 1;
400
- const mixSorted = [...mixSrc].sort((a, b) => (a.sortOrder || 0) - (b.sortOrder || 0));
401
- for (const m of mixSorted) {
402
- const pct = (m.totalTokens ?? 0) / denom * 100;
403
- out.push([
404
- plain(` ${padR(m.modelName || "?", 11)}${padL(fmtTokens(m.totalTokens), 8)} `),
405
- bold(padL(pct.toFixed(1) + "%", 6)),
406
- plain(` ${barField(pct, 100, 20)}`)
407
- ]);
408
- }
409
- out.push([]);
410
- out.push([dim(" Limits " + "─".repeat(Math.max(0, 60)))]);
411
- const bj = new Date(now.getTime() + apiOffsetMin * 6e4);
412
- const bjDay = bj.getUTCDay();
413
- const elapsedMin = bjDay >= 1 && bjDay <= 5 ? Math.max(0, Math.min(240, (bj.getUTCHours() - 14) * 60 + bj.getUTCMinutes())) : 0;
414
- if (peakWin) out.push([dim(` ${padR("Peak", 16)}`), plain(`${padL(peakWin.start, 5)} ${dotMeter(Math.round(elapsedMin / 240 * 100), 22)} ${peakWin.end}`)]);
415
- const limits = quota.limits ?? [];
416
- const mcp = limits.find((l) => /mcp/i.test(l.type ?? ""));
417
- const tok5 = limits.find((l) => /token/i.test(l.type ?? ""));
418
- if (tok5) {
419
- const reset = new Date(tok5.nextResetTime ?? "").toLocaleTimeString("en-IN");
420
- out.push([
421
- dim(` ${padR("Tokens · 5h", 16)}`),
422
- bold(padL(`${tok5.percentage || 0}%`, 5)),
423
- plain(` ${dotMeter(tok5.percentage, 22)} ${reset}`)
424
- ]);
425
- }
426
- if (tok5 && mcp) out.push([]);
427
- if (mcp) {
428
- const reset = new Date(mcp.nextResetTime ?? "").toLocaleString("en-IN");
429
- out.push([
430
- dim(` ${padR("MCP · this month", 16)}`),
431
- bold(padL(`${mcp.percentage || 0}%`, 5)),
432
- plain(` ${dotMeter(mcp.percentage, 22)} ${reset}`)
433
- ]);
434
- const parts = (mcp.usageDetails ?? []).map((d) => `${friendlyTool(d.modelCode)} ${fmtNum(d.usage)}`).join(" ");
435
- if (parts) out.push([plain(` ${fmtNum(mcp.currentUsage)}M / ${fmtNum(mcp.totol)}M · ${parts}`)]);
436
- }
437
- out.push([]);
438
- out.push([plain(rule())]);
439
- return out;
440
- }
441
- function render(input) {
442
- return renderLines(reportLines(input));
443
- }
444
- //#endregion
445
- //#region src/resolve.ts
446
- var DEFAULT_BASE_URL = "https://api.z.ai";
447
- var GLM_HOSTS = /* @__PURE__ */ new Set([
448
- "api.z.ai",
449
- "dev.bigmodel.cn",
450
- "open.bigmodel.cn"
451
- ]);
452
- function fromEnv(value) {
453
- return value ? value : void 0;
454
- }
455
- function originOf(value) {
456
- try {
457
- const url = new URL(value);
458
- return url.protocol === "https:" || url.protocol === "http:" ? url.origin : void 0;
459
- } catch {
460
- return;
461
- }
462
- }
463
- function isGlm(origin) {
464
- return GLM_HOSTS.has(new URL(origin).hostname);
465
- }
466
- function resolveBaseUrl(flag, env) {
467
- if (flag !== void 0) {
468
- const origin = originOf(flag);
469
- if (origin === void 0) throw new Error(`invalid base URL: ${flag}`);
470
- return {
471
- glm: isGlm(origin),
472
- origin
473
- };
474
- }
475
- const inherited = fromEnv(env.ANTHROPIC_BASE_URL);
476
- const origin = inherited === void 0 ? void 0 : originOf(inherited);
477
- if (origin !== void 0 && isGlm(origin)) return {
478
- glm: true,
479
- origin
480
- };
481
- return {
482
- glm: false,
483
- origin: DEFAULT_BASE_URL
484
- };
485
- }
486
- function buildProgram(onUsage) {
487
- 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));
488
- return new Command().name("zai-usage").description("GLM Coding Plan usage — one command, usage").action(() => void 0).addCommand(usage);
489
- }
490
- function parseArgs(args) {
491
- let parsed;
492
- const quiet = parseQuietly(buildProgram((options) => {
493
- const { authToken, baseUrl, json } = options;
494
- parsed = {
495
- authToken: authToken || void 0,
496
- baseUrl: baseUrl || void 0,
497
- command: "usage",
498
- json: json === true
499
- };
500
- }), args);
501
- if (quiet === void 0 || quiet instanceof HelpRequested) return quiet;
502
- return parsed ?? {
503
- authToken: void 0,
504
- baseUrl: void 0,
505
- command: void 0,
506
- json: false
507
- };
508
- }
509
- function resolveConfig(env, parsed) {
510
- const base = resolveBaseUrl(parsed.baseUrl, env);
511
- const token = parsed.authToken ?? (base.glm ? fromEnv(env.ANTHROPIC_AUTH_TOKEN) : void 0);
512
- if (token === void 0) throw new Error(env.ANTHROPIC_AUTH_TOKEN ? "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)" : "no API key: set ZAI_AUTH_TOKEN (or --auth-token)");
513
- return {
514
- token,
515
- url: base.origin
516
- };
517
- }
518
- //#endregion
519
- //#region src/usage.ts
520
- /**
521
- * Usage query: the three GLM monitor endpoints of the resolved base URL,
522
- * assembled into the report input.
523
- */
524
- function queryParams(now = /* @__PURE__ */ new Date()) {
525
- const startDate = new Date(now.getFullYear(), now.getMonth(), now.getDate() - 1, now.getHours(), 0, 0, 0);
526
- const endDate = new Date(now.getFullYear(), now.getMonth(), now.getDate(), now.getHours(), 59, 59, 999);
527
- function formatDateTime(date) {
528
- return `${date.getFullYear()}-${pad2(date.getMonth() + 1)}-${pad2(date.getDate())} ${pad2(date.getHours())}:${pad2(date.getMinutes())}:${pad2(date.getSeconds())}`;
529
- }
530
- return `?startTime=${encodeURIComponent(formatDateTime(startDate))}&endTime=${encodeURIComponent(formatDateTime(endDate))}`;
531
- }
532
- function processQuotaLimit(data) {
533
- if (!data.limits) return data;
534
- data.limits = data.limits.map((item) => {
535
- if (item.type === "TOKENS_LIMIT") return {
536
- type: "Token usage(5 Hour)",
537
- percentage: item.percentage,
538
- nextResetTime: item.nextResetTime
539
- };
540
- if (item.type === "TIME_LIMIT") return {
541
- type: "MCP usage(1 Month)",
542
- percentage: item.percentage,
543
- currentUsage: item.currentValue,
544
- totol: item.usage,
545
- usageDetails: item.usageDetails,
546
- nextResetTime: item.nextResetTime
547
- };
548
- return item;
549
- });
550
- return data;
551
- }
552
- async function fetchJson(apiUrl, label, authToken, query = "") {
553
- const res = await fetch(apiUrl + query, { headers: {
554
- Authorization: authToken,
555
- "Accept-Language": "en-US,en",
556
- "Content-Type": "application/json"
557
- } });
558
- const body = await res.text();
559
- if (res.status !== 200) throw new Error(`[${label}] HTTP ${res.status}\n${body}`);
560
- let json;
561
- try {
562
- json = JSON.parse(body);
563
- } catch (e) {
564
- throw new Error(`[${label}] could not parse response: ${e.message}`, { cause: e });
565
- }
566
- if (json.success === false) throw new Error(`[${label}] ${json.msg ?? "request failed"} (code ${json.code ?? "?"})`);
567
- return json.data ?? json;
568
- }
569
- async function fetchReport(config) {
570
- const platform = config.url.includes("bigmodel") ? "ZHIPU" : "ZAI";
571
- const query = queryParams();
572
- try {
573
- const [model, tool, quotaRaw] = await Promise.all([
574
- fetchJson(`${config.url}/api/monitor/usage/model-usage`, "Model usage", config.token, query),
575
- fetchJson(`${config.url}/api/monitor/usage/tool-usage`, "Tool usage", config.token, query),
576
- fetchJson(`${config.url}/api/monitor/usage/quota/limit`, "Quota limit", config.token)
577
- ]);
578
- return {
579
- platform,
580
- model,
581
- tool,
582
- quota: processQuotaLimit(quotaRaw)
583
- };
584
- } catch (e) {
585
- throw new Error(`Request failed: ${e.message}`, { cause: e });
586
- }
587
- }
588
- //#endregion
589
- //#region src/index.ts
590
- var asked = parseArgs(process.argv.slice(2));
591
- if (asked instanceof HelpRequested) printHelpAndExit(asked.command);
592
- var parsed = asked ?? printUsageAndExit(buildProgram());
593
- if (parsed.command !== "usage") printUsageAndExit(buildProgram());
594
- await runMain(async () => {
595
- const input = await fetchReport(resolveConfig(process.env, parsed));
596
- console.log(parsed.json ? JSON.stringify({ lines: reportLines(input) }) : render(input));
597
- });
598
- //#endregion
599
- export {};
600
-
601
- //# sourceMappingURL=index.js.map