pleumrouter 0.3.1 → 0.5.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/src/usage.mjs CHANGED
@@ -3,6 +3,7 @@
3
3
 
4
4
  import { V1, requireKey } from "./config.mjs";
5
5
  import { style, padDisplay, barChart, divider } from "./ansi.mjs";
6
+ import { t } from "./i18n.mjs";
6
7
 
7
8
  const GROUPS = ["model", "provider", "api_key", "day"];
8
9
 
@@ -13,8 +14,8 @@ export function parseUsageArgs(rest = []) {
13
14
  if (rest[i] === "--by") by = rest[++i];
14
15
  else if (rest[i] === "--days") days = Number(rest[++i]);
15
16
  }
16
- if (!GROUPS.includes(by)) throw new Error(`--by 는 ${GROUPS.join("|")} 중 하나: ${by}`);
17
- if (!Number.isInteger(days) || days < 1 || days > 365) throw new Error(`--days 는 1~365 정수: ${days}`);
17
+ if (!GROUPS.includes(by)) throw new Error(t("--by must be one of {groups}: {by}", { groups: GROUPS.join("|"), by }));
18
+ if (!Number.isInteger(days) || days < 1 || days > 365) throw new Error(t("--days must be an integer 1-365: {days}", { days }));
18
19
  return { by, days };
19
20
  }
20
21
 
@@ -23,12 +24,12 @@ const fmtKrw = (n) => `₩${Math.round(n).toLocaleString("en-US")}`;
23
24
  // report 응답 → 표시 문자열(순수 함수 — fixture 테스트 대상).
24
25
  export function renderUsage(data, styler = style) {
25
26
  const lines = [];
26
- const byKo = { model: "모델별", provider: "제공자별", api_key: "키별", day: "일별" }[data.group_by] || data.group_by;
27
- lines.push(`${styler.bold(styler.plum("사용량"))} ${styler.dim(`· ${byKo} · 최근 ${data.days}일`)}`);
27
+ const byLabel = { model: t("by model"), provider: t("by provider"), api_key: t("by key"), day: t("by day") }[data.group_by] || data.group_by;
28
+ lines.push(`${styler.bold(styler.plum(t("Usage")))} ${styler.dim(`· ${byLabel} · ${t("last {days} days", { days: data.days })}`)}`);
28
29
  lines.push(divider(undefined, styler));
29
30
  const items = data.items || [];
30
31
  if (!items.length) {
31
- lines.push(styler.dim("사용 내역 없음"));
32
+ lines.push(styler.dim(t("No usage history")));
32
33
  return lines.join("\n");
33
34
  }
34
35
  const max = Math.max(...items.map((i) => i.cost_krw), 1);
@@ -43,7 +44,7 @@ export function renderUsage(data, styler = style) {
43
44
  );
44
45
  }
45
46
  lines.push(divider(undefined, styler));
46
- lines.push(`${padDisplay("합계", keyW)} ${" ".repeat(20)} ${styler.bold(fmtKrw(total.cost))}${styler.dim(` ${total.calls} calls`)}`);
47
+ lines.push(`${padDisplay(t("Total"), keyW)} ${" ".repeat(20)} ${styler.bold(fmtKrw(total.cost))}${styler.dim(` ${total.calls} calls`)}`);
47
48
  return lines.join("\n");
48
49
  }
49
50
 
@@ -56,14 +57,14 @@ export async function usage(rest) {
56
57
  if (res.status === 403) {
57
58
  // 구버전 로그인 키(usage:read 스코프 없음) — 재로그인으로 새 키를 받으면 해결.
58
59
  console.error(
59
- `${style.red("✗")} 이 API 키에는 usage:read 권한이 없습니다.\n` +
60
- ` ${style.dim("pleum login 을 다시 실행해 새 키를 발급받으세요 (최신 키에는 기본 포함).")}`,
60
+ `${style.red("✗")} ${t("This API key doesn't have usage:read permission.")}\n` +
61
+ ` ${style.dim(t("Run pleum login again to get a new key (recent keys include it by default)."))}`,
61
62
  );
62
63
  process.exit(1);
63
64
  }
64
65
  if (!res.ok) {
65
66
  const body = await res.text().catch(() => "");
66
- throw new Error(`사용량 조회 실패 (${res.status})${body ? `: ${body.slice(0, 200)}` : ""}`);
67
+ throw new Error(`${t("Failed to fetch usage ({status})", { status: res.status })}${body ? `: ${body.slice(0, 200)}` : ""}`);
67
68
  }
68
69
  console.log(renderUsage(await res.json()));
69
70
  }