@tonbo/cli 0.19.0 → 0.20.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.
Files changed (2) hide show
  1. package/dist/bin/tonbo.js +77 -4
  2. package/package.json +1 -1
package/dist/bin/tonbo.js CHANGED
@@ -364,6 +364,20 @@ var managementOperations = {
364
364
  "idempotencyKey": false,
365
365
  "cli": "tonbo usage series"
366
366
  },
367
+ "getVolumeMetrics": {
368
+ "method": "GET",
369
+ "path": "/metrics/volumes",
370
+ "pathParams": [],
371
+ "query": [
372
+ "series",
373
+ "window",
374
+ "granularity",
375
+ "from",
376
+ "to"
377
+ ],
378
+ "idempotencyKey": false,
379
+ "cli": "tonbo metrics volumes"
380
+ },
367
381
  "getUsageToday": {
368
382
  "method": "GET",
369
383
  "path": "/usage/today",
@@ -414,6 +428,7 @@ var managementOperations = {
414
428
  "pathParams": [],
415
429
  "query": [
416
430
  "device_id",
431
+ "project",
417
432
  "cursor",
418
433
  "limit"
419
434
  ],
@@ -2316,6 +2331,10 @@ var ManagementApi = class {
2316
2331
  getUsageSeries(key, query = {}) {
2317
2332
  return this.call("getUsageSeries", key, { query });
2318
2333
  }
2334
+ /** The account's Volume metrics over a window, such as what they stored each day. */
2335
+ getVolumeMetrics(key, query = {}) {
2336
+ return this.call("getVolumeMetrics", key, { query });
2337
+ }
2319
2338
  /** The account's writes of yesterday and today, hourly, per lane. */
2320
2339
  getUsageToday(key) {
2321
2340
  return this.call("getUsageToday", key);
@@ -2819,7 +2838,8 @@ function accountLogins(login) {
2819
2838
  ...entry,
2820
2839
  account_id,
2821
2840
  kind: entry.kind ?? null,
2822
- name: entry.name ?? null
2841
+ name: entry.name ?? null,
2842
+ role: entry.role ?? null
2823
2843
  }));
2824
2844
  if (!entries.some((entry) => entry.account_id === login.account_id))
2825
2845
  entries.unshift({
@@ -2828,12 +2848,18 @@ function accountLogins(login) {
2828
2848
  key: login.key,
2829
2849
  expires_at: login.expires_at,
2830
2850
  kind: null,
2831
- name: null
2851
+ name: null,
2852
+ role: null
2832
2853
  });
2833
2854
  return entries;
2834
2855
  }
2835
2856
  function personalLogin(login) {
2836
- return accountLogins(login).find((entry) => entry.kind === "user") ?? null;
2857
+ const logins = accountLogins(login);
2858
+ const personal = login.session?.personalAccountId;
2859
+ return (personal ? logins.find((entry) => entry.account_id === personal) : void 0) ?? logins.find((entry) => entry.kind === "user" && !isGuestLogin(entry)) ?? null;
2860
+ }
2861
+ function isGuestLogin(login) {
2862
+ return login.role === "collaborator";
2837
2863
  }
2838
2864
  async function preparePrivateDirectory(directory) {
2839
2865
  const stat3 = await lstat(directory);
@@ -3387,7 +3413,8 @@ var LoginStore = class {
3387
3413
  key: client.bearer(id),
3388
3414
  expires_at: current.session.expires_at,
3389
3415
  kind: current.accounts?.[id]?.kind ?? (id === current.personal_account_id ? "user" : null),
3390
- name: current.accounts?.[id]?.name ?? null
3416
+ name: current.accounts?.[id]?.name ?? null,
3417
+ role: current.accounts?.[id]?.role ?? null
3391
3418
  });
3392
3419
  accounts[current.personal_account_id] = entry(current.personal_account_id);
3393
3420
  for (const id of Object.keys(current.accounts ?? {}))
@@ -5272,6 +5299,37 @@ async function usageSeriesCommand(deps, options = {}) {
5272
5299
  );
5273
5300
  print(deps, options.json, series, lines.join("\n"));
5274
5301
  }
5302
+ async function metricsVolumesCommand(deps, options = {}) {
5303
+ const metrics = await deps.api.getVolumeMetrics(await deps.auth.apiKey(), {
5304
+ series: "stored_bytes",
5305
+ window: options.window,
5306
+ granularity: options.from || options.to ? "day" : void 0,
5307
+ from: options.from,
5308
+ to: options.to
5309
+ });
5310
+ const points = metrics.total.points;
5311
+ const lines = [
5312
+ `What the Volumes stored from ${metrics.from.slice(0, 10)} to ${metrics.to.slice(0, 10)} (UTC, average per day)`,
5313
+ table(
5314
+ ["DAY", "STORED", ""],
5315
+ points.map((point) => [
5316
+ point.start.slice(0, 10),
5317
+ bytes(point.stored_bytes),
5318
+ point.partial ? "so far" : ""
5319
+ ])
5320
+ )
5321
+ ];
5322
+ const complete = points.filter((point) => !point.partial);
5323
+ if (complete.length > 1) {
5324
+ const change = complete[complete.length - 1].stored_bytes - complete[0].stored_bytes;
5325
+ lines.push(
5326
+ `Change over its complete days: ${change < 0 ? "-" : "+"}${bytes(Math.abs(change))}`
5327
+ );
5328
+ }
5329
+ if (metrics.unavailable_regions.length > 0)
5330
+ lines.push(`Not read: ${metrics.unavailable_regions.join(", ")}`);
5331
+ print(deps, options.json, metrics, lines.join("\n"));
5332
+ }
5275
5333
  async function streamActivityCommand(deps, name, options = {}) {
5276
5334
  const activity = await deps.api.getStreamActivity(
5277
5335
  await deps.auth.apiKey(),
@@ -7282,6 +7340,14 @@ var COMMAND_HELP = {
7282
7340
  examples: ["tonbo usage series --days 7 --compare"],
7283
7341
  defaults: { "--days": "30" }
7284
7342
  },
7343
+ "tonbo metrics volumes": {
7344
+ about: [
7345
+ "Prints what the account's Volumes stored, one line per UTC day of the window: the average bytes their files held that day, compressed, summed over every region, which is what they are billed for. Today, and a day not fully rated yet, is marked `so far`. Then the change between the window's first and last complete days.",
7346
+ "Give `--window`, or `--from` and `--to` (at most 92 days); the last 30 days when neither is given."
7347
+ ],
7348
+ examples: ["tonbo metrics volumes --window 7d"],
7349
+ defaults: { "--window": "30d" }
7350
+ },
7285
7351
  "tonbo usage today": {
7286
7352
  about: [
7287
7353
  "Prints the account's write units per UTC hour of yesterday and today, in three columns: databases, streams and other."
@@ -9247,6 +9313,13 @@ function createProgram(makeDependencies = createDependencies) {
9247
9313
  ),
9248
9314
  "getUsageToday"
9249
9315
  ).action(async (options) => usageTodayCommand(dependencies(), options));
9316
+ const metrics = program.command("metrics").description("show how the account's resources are used over time");
9317
+ operationOptions(
9318
+ metrics.command("volumes").description("show what the account's Volumes stored, day by day").option("--window <window>", "the last 7d, 30d or 90d, today included").option("--from <day>", "with --to, the first UTC day, as YYYY-MM-DD").option("--to <day>", "with --from, the UTC day the window ends before, as YYYY-MM-DD"),
9319
+ "getVolumeMetrics"
9320
+ ).action(
9321
+ async (options) => metricsVolumesCommand(dependencies(), options)
9322
+ );
9250
9323
  const ssh = program.command("ssh").description("open a terminal on a Machine, or run a command there, over SSH").argument("<machine>", "the Machine's name").argument("[command...]", "a command to run instead of a shell, after --").action(async (name, command) => sshCommand(dependencies(), name, command));
9251
9324
  ssh.command("config").description(
9252
9325
  "print the ssh_config block that lets ssh, scp, sftp and Remote-SSH reach every Machine"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tonbo/cli",
3
- "version": "0.19.0",
3
+ "version": "0.20.0",
4
4
  "description": "The Tonbo CLI. Compute, disks, databases and streams for AI agents: your agent picks what it needs, sets it up, and knows what it costs, from the command line.",
5
5
  "homepage": "https://tonbo.dev",
6
6
  "bugs": {