u1s1-cli 1.15.2 → 1.16.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/dist/api.js +1 -1
- package/dist/index.js +6 -4
- package/dist/usage.d.ts +44 -1
- package/dist/usage.js +64 -2
- package/package.json +1 -1
package/dist/api.js
CHANGED
|
@@ -356,7 +356,7 @@ export async function fetchMe(cfg) {
|
|
|
356
356
|
throw new Error(unreachableMessage(cfg.baseUrl));
|
|
357
357
|
}
|
|
358
358
|
if (resp.status === 401)
|
|
359
|
-
throw new
|
|
359
|
+
throw new AuthError(sessionExpiredMessage());
|
|
360
360
|
if (!resp.ok)
|
|
361
361
|
throw new Error(await errorMessageFromResponse(resp, tr(`服务端返回 ${resp.status},稍后再试`, `Server returned ${resp.status}. Please try again later.`)));
|
|
362
362
|
const body = await readJsonResponseCapped(resp);
|
package/dist/index.js
CHANGED
|
@@ -165,9 +165,9 @@ const COMMANDS = {
|
|
|
165
165
|
await login(parsed.key, { site: parsed.site });
|
|
166
166
|
},
|
|
167
167
|
logout: logoutCommand,
|
|
168
|
-
usage: async () => {
|
|
168
|
+
usage: async (rest) => {
|
|
169
169
|
const { usage } = await import("./usage.js");
|
|
170
|
-
await usage();
|
|
170
|
+
await usage(rest);
|
|
171
171
|
},
|
|
172
172
|
whoami: whoamiCommand,
|
|
173
173
|
feedback: async (rest) => {
|
|
@@ -284,8 +284,9 @@ const SIMPLE_COMMAND_HELP = {
|
|
|
284
284
|
" 退出本机登录,并注销这台设备在服务端的授权(连不上服务器时只清本机)。",
|
|
285
285
|
],
|
|
286
286
|
usage: [
|
|
287
|
-
"用法: u1s1 usage",
|
|
287
|
+
"用法: u1s1 usage [--json]",
|
|
288
288
|
" 查看剩余额度:免费包、已购用量包与余额。会话内也可输入 /usage。",
|
|
289
|
+
" --json 输出 JSON,给别的程序读(字段见 usage.ts 的 UsageJson)",
|
|
289
290
|
],
|
|
290
291
|
whoami: [
|
|
291
292
|
"用法: u1s1 whoami",
|
|
@@ -309,8 +310,9 @@ const SIMPLE_COMMAND_HELP_EN = {
|
|
|
309
310
|
" Sign out on this machine and revoke this device's authorization on the server (only clears local data if the server is unreachable).",
|
|
310
311
|
],
|
|
311
312
|
usage: [
|
|
312
|
-
"Usage: u1s1 usage",
|
|
313
|
+
"Usage: u1s1 usage [--json]",
|
|
313
314
|
" Show your remaining balance. In a session you can also type /usage.",
|
|
315
|
+
" --json Print JSON for other programs to read",
|
|
314
316
|
],
|
|
315
317
|
whoami: [
|
|
316
318
|
"Usage: u1s1 whoami",
|
package/dist/usage.d.ts
CHANGED
|
@@ -18,4 +18,47 @@ export declare function usageEntryData(): Promise<{
|
|
|
18
18
|
lines?: string[];
|
|
19
19
|
error?: string;
|
|
20
20
|
}>;
|
|
21
|
-
|
|
21
|
+
/**
|
|
22
|
+
* `u1s1 usage --json` 的输出,给别的程序读(比如 Hearth 在界面上显示 u1s1 用量)。
|
|
23
|
+
* 字段只增不改;要改含义就升 v。金额是美元,Token 是网关记的个数(不是按默认模型折算的约数)。
|
|
24
|
+
* 不含凭证;email 是登录账号,方便调用方标明是哪个号。
|
|
25
|
+
*/
|
|
26
|
+
export interface UsageJson {
|
|
27
|
+
v: 1;
|
|
28
|
+
site: "cn" | "intl";
|
|
29
|
+
email: string | null;
|
|
30
|
+
/** 可用余额(美元):用量包网关是按量余额 bonus_balance_usd,老网关是 remaining_usd */
|
|
31
|
+
balance_usd: number;
|
|
32
|
+
/** 本月已用(美元) */
|
|
33
|
+
month_usd: number;
|
|
34
|
+
/** 美元折默认模型 Token 的比率;老网关没有时为 null */
|
|
35
|
+
tokens_per_usd: number | null;
|
|
36
|
+
/** 生效中的用量包,同类同到期日的合成一项;老网关为 null */
|
|
37
|
+
packages: {
|
|
38
|
+
kind: string;
|
|
39
|
+
label: string;
|
|
40
|
+
/** free:只能用于免费包适用模型;其余为全模型 */
|
|
41
|
+
scope: string;
|
|
42
|
+
/** true:每日额度(total 是每天的量,0 点恢复);false:一次性总量 */
|
|
43
|
+
daily: boolean;
|
|
44
|
+
total_tokens: number;
|
|
45
|
+
remaining_tokens: number;
|
|
46
|
+
expires_at: string | null;
|
|
47
|
+
count: number;
|
|
48
|
+
}[] | null;
|
|
49
|
+
/** 仪表盘、充值入口;支付通道没开放时 topup 为 null */
|
|
50
|
+
dashboard: string;
|
|
51
|
+
topup: string | null;
|
|
52
|
+
}
|
|
53
|
+
/** 出错时的 --json 输出:login 没登录 / 登录失效,其余是 failed,message 是给人看的原因 */
|
|
54
|
+
export interface UsageJsonError {
|
|
55
|
+
v: 1;
|
|
56
|
+
error: "login" | "failed";
|
|
57
|
+
message: string;
|
|
58
|
+
}
|
|
59
|
+
export declare function usageJson(me: MeResponse, site: Site): UsageJson;
|
|
60
|
+
export declare function parseUsageArgs(rest: string[]): {
|
|
61
|
+
json: boolean;
|
|
62
|
+
error?: string;
|
|
63
|
+
};
|
|
64
|
+
export declare function usage(rest?: string[]): Promise<void>;
|
package/dist/usage.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { fetchMe } from "./api.js";
|
|
1
|
+
import { AuthError, fetchMe } from "./api.js";
|
|
2
2
|
import { activeSite, loadConfig } from "./config.js";
|
|
3
3
|
import { hasDeviceCredential } from "./device-auth.js";
|
|
4
4
|
import { isEnglish, tr } from "./i18n.js";
|
|
@@ -221,8 +221,70 @@ export async function usageEntryData() {
|
|
|
221
221
|
return { error: e instanceof Error ? e.message : String(e) };
|
|
222
222
|
}
|
|
223
223
|
}
|
|
224
|
-
export
|
|
224
|
+
export function usageJson(me, site) {
|
|
225
|
+
const { dashboard, topup } = siteLinks(site);
|
|
226
|
+
return {
|
|
227
|
+
v: 1,
|
|
228
|
+
site: site.id,
|
|
229
|
+
email: me.email ?? null,
|
|
230
|
+
balance_usd: me.packages ? me.bonus_balance_usd : me.remaining_usd,
|
|
231
|
+
month_usd: me.mtd_usd,
|
|
232
|
+
tokens_per_usd: me.tokens_per_usd && me.tokens_per_usd > 0 ? me.tokens_per_usd : null,
|
|
233
|
+
packages: me.packages
|
|
234
|
+
? groupPackages(me.packages).map((pkg) => {
|
|
235
|
+
const daily = pkg.daily_tokens != null;
|
|
236
|
+
return {
|
|
237
|
+
kind: pkg.kind,
|
|
238
|
+
label: packageLabels()[pkg.kind] ?? pkg.kind,
|
|
239
|
+
scope: pkg.scope,
|
|
240
|
+
daily,
|
|
241
|
+
total_tokens: (daily ? pkg.daily_tokens : pkg.total_tokens) ?? 0,
|
|
242
|
+
remaining_tokens: pkg.remaining,
|
|
243
|
+
expires_at: pkg.expires_at,
|
|
244
|
+
count: pkg.count,
|
|
245
|
+
};
|
|
246
|
+
})
|
|
247
|
+
: null,
|
|
248
|
+
dashboard,
|
|
249
|
+
topup: me.pay_enabled === false ? null : topup,
|
|
250
|
+
};
|
|
251
|
+
}
|
|
252
|
+
export function parseUsageArgs(rest) {
|
|
253
|
+
let json = false;
|
|
254
|
+
for (const a of rest) {
|
|
255
|
+
if (a === "--json")
|
|
256
|
+
json = true;
|
|
257
|
+
else
|
|
258
|
+
return { json, error: tr(`不认识的参数 ${a};用法: u1s1 usage [--json]`, `Unknown option ${a}. Usage: u1s1 usage [--json]`) };
|
|
259
|
+
}
|
|
260
|
+
return { json };
|
|
261
|
+
}
|
|
262
|
+
export async function usage(rest = []) {
|
|
263
|
+
const args = parseUsageArgs(rest);
|
|
264
|
+
if (args.error) {
|
|
265
|
+
console.error(args.error);
|
|
266
|
+
process.exitCode = 1;
|
|
267
|
+
return;
|
|
268
|
+
}
|
|
225
269
|
const cfg = loadConfig();
|
|
270
|
+
if (args.json) {
|
|
271
|
+
const fail = (error, message) => {
|
|
272
|
+
console.log(JSON.stringify({ v: 1, error, message }));
|
|
273
|
+
process.exitCode = 1;
|
|
274
|
+
};
|
|
275
|
+
if (!hasDeviceCredential(cfg))
|
|
276
|
+
return fail("login", tr("还没登录,先跑 u1s1 login", "Not signed in. Run u1s1 login first."));
|
|
277
|
+
let me;
|
|
278
|
+
try {
|
|
279
|
+
me = await fetchMe(cfg);
|
|
280
|
+
}
|
|
281
|
+
catch (e) {
|
|
282
|
+
const message = e instanceof Error ? e.message : String(e);
|
|
283
|
+
return fail(e instanceof AuthError ? "login" : "failed", message);
|
|
284
|
+
}
|
|
285
|
+
console.log(JSON.stringify(usageJson(me, siteOf(cfg))));
|
|
286
|
+
return;
|
|
287
|
+
}
|
|
226
288
|
if (!hasDeviceCredential(cfg)) {
|
|
227
289
|
console.error(tr("还没登录,先跑 u1s1 login", "Not signed in. Run u1s1 login first."));
|
|
228
290
|
process.exit(1);
|