fluncle 0.210.0 → 0.211.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/bin/fluncle.mjs +157 -2
  2. package/package.json +1 -1
package/bin/fluncle.mjs CHANGED
@@ -610,7 +610,7 @@ function parseVersion(version) {
610
610
  var currentVersion;
611
611
  var init_version = __esm(() => {
612
612
  init_output();
613
- currentVersion = "0.210.0".trim() ? "0.210.0".trim() : "0.1.0";
613
+ currentVersion = "0.211.0".trim() ? "0.211.0".trim() : "0.1.0";
614
614
  });
615
615
 
616
616
  // src/update-notifier.ts
@@ -2452,7 +2452,7 @@ function parseVersion2(version) {
2452
2452
  var currentVersion2, latestReleaseUrl = "https://api.github.com/repos/mauricekleine/fluncle/releases/latest";
2453
2453
  var init_version2 = __esm(() => {
2454
2454
  init_output();
2455
- currentVersion2 = "0.210.0".trim() ? "0.210.0".trim() : "0.1.0";
2455
+ currentVersion2 = "0.211.0".trim() ? "0.211.0".trim() : "0.1.0";
2456
2456
  });
2457
2457
 
2458
2458
  // ../../packages/registry/src/index.ts
@@ -4469,6 +4469,101 @@ var init_admin_attention = __esm(() => {
4469
4469
  };
4470
4470
  });
4471
4471
 
4472
+ // src/commands/admin-telemetry.ts
4473
+ var exports_admin_telemetry = {};
4474
+ __export(exports_admin_telemetry, {
4475
+ telemetryLines: () => telemetryLines,
4476
+ telemetryCommand: () => telemetryCommand
4477
+ });
4478
+ async function telemetryCommand(options) {
4479
+ const params = new URLSearchParams({ limit: String(options.limit) });
4480
+ if (options.cursor !== undefined) {
4481
+ params.set("cursor", options.cursor);
4482
+ }
4483
+ if (options.ok !== undefined) {
4484
+ params.set("ok", String(options.ok));
4485
+ }
4486
+ if (options.since !== undefined) {
4487
+ params.set("since", options.since);
4488
+ }
4489
+ if (options.unit !== undefined) {
4490
+ params.set("unit", options.unit);
4491
+ }
4492
+ if (options.until !== undefined) {
4493
+ params.set("until", options.until);
4494
+ }
4495
+ return adminApiGet(`/api/v1/admin/telemetry/runs?${params.toString()}`);
4496
+ }
4497
+ function cell(value) {
4498
+ if (value === null) {
4499
+ return "-";
4500
+ }
4501
+ if (typeof value === "boolean") {
4502
+ return value ? "1" : "0";
4503
+ }
4504
+ return String(value);
4505
+ }
4506
+ function padded(columns, widths) {
4507
+ return columns.map((column, index) => column.padEnd(widths[index] ?? 0)).join(" ").trimEnd();
4508
+ }
4509
+ function telemetryLines(page) {
4510
+ if (!page.available) {
4511
+ return ["Telemetry database is not configured."];
4512
+ }
4513
+ if (page.rows.length === 0) {
4514
+ return ["No run events matched."];
4515
+ }
4516
+ const rollupHeader = ["UNIT", "RUNS", "LAST", "OK=0", "LIAR", "BLIND"];
4517
+ const rollupRows = page.rollups.map((rollup) => [
4518
+ rollup.unit,
4519
+ String(rollup.runCount),
4520
+ rollup.lastOccurredAt,
4521
+ String(rollup.failedCount),
4522
+ String(rollup.liarCount),
4523
+ String(rollup.blindCount)
4524
+ ]);
4525
+ const rollupWidths = rollupHeader.map((header, index) => Math.max(header.length, ...rollupRows.map((row) => row[index]?.length ?? 0)));
4526
+ const runHeader = [
4527
+ "OCCURRED",
4528
+ "UNIT",
4529
+ "OK",
4530
+ "SELF",
4531
+ "CHECKED",
4532
+ "PRODUCED",
4533
+ "QUEUE",
4534
+ "EXIT",
4535
+ "SUMMARY"
4536
+ ];
4537
+ const runRows = page.rows.map((row) => [
4538
+ row.occurredAt,
4539
+ row.unit,
4540
+ cell(row.ok),
4541
+ cell(row.selfAssertedOk),
4542
+ cell(row.checked),
4543
+ cell(row.produced),
4544
+ cell(row.queueDepth),
4545
+ String(row.exitCode),
4546
+ row.summaryStatus
4547
+ ]);
4548
+ const runWidths = runHeader.map((header, index) => Math.max(header.length, ...runRows.map((row) => row[index]?.length ?? 0)));
4549
+ const lines = [
4550
+ `Unit rollups (${page.totalCount} matching runs)`,
4551
+ padded(rollupHeader, rollupWidths),
4552
+ ...rollupRows.map((row) => padded(row, rollupWidths)),
4553
+ "",
4554
+ `Runs (${page.rows.length} on this page)`,
4555
+ padded(runHeader, runWidths),
4556
+ ...runRows.map((row) => padded(row, runWidths))
4557
+ ];
4558
+ if (page.nextCursor !== null) {
4559
+ lines.push("", `Next cursor: ${page.nextCursor}`);
4560
+ }
4561
+ return lines;
4562
+ }
4563
+ var init_admin_telemetry = __esm(() => {
4564
+ init_api();
4565
+ });
4566
+
4472
4567
  // src/commands/add.ts
4473
4568
  var exports_add = {};
4474
4569
  __export(exports_add, {
@@ -9660,6 +9755,14 @@ function addAdminCommands(program2) {
9660
9755
  const { attentionQueueCommand: attentionQueueCommand2 } = await Promise.resolve().then(() => (init_admin_attention(), exports_admin_attention));
9661
9756
  await runAdminAttention(options, attentionQueueCommand2);
9662
9757
  });
9758
+ const adminTelemetry = configureCommand(admin.command("telemetry").description("Run-ledger telemetry"));
9759
+ adminTelemetry.action(() => {
9760
+ adminTelemetry.outputHelp();
9761
+ });
9762
+ adminTelemetry.command("read").description("Run-ledger rows plus per-unit rollups").option("--unit <unit>", "Only this systemd unit").option("--since <iso>", "Only runs at or after this occurred-at instant").option("--until <iso>", "Only runs at or before this occurred-at instant").option("--ok <true|false>", "Filter by the Worker's derived run verdict").option("--limit <limit>", "Rows to show (1-100)", "50").option("--cursor <cursor>", "Opaque cursor from the previous page").option("--json", "Print the lossless 20-column rows as JSON", false).action(async (options) => {
9763
+ const { telemetryCommand: telemetryCommand2 } = await Promise.resolve().then(() => (init_admin_telemetry(), exports_admin_telemetry));
9764
+ await runAdminTelemetry(options, telemetryCommand2);
9765
+ });
9663
9766
  const adminTracks = configureCommand(admin.command("tracks").description("Track admin commands"));
9664
9767
  adminTracks.action(() => {
9665
9768
  adminTracks.outputHelp();
@@ -12485,6 +12588,32 @@ function parseListLimit(value) {
12485
12588
  }
12486
12589
  return limit;
12487
12590
  }
12591
+ function parseTelemetryLimit(value) {
12592
+ const limit = Number.parseInt(value ?? "50", 10);
12593
+ if (!Number.isInteger(limit) || limit < 1 || limit > 100) {
12594
+ throw new Error("Limit must be an integer between 1 and 100");
12595
+ }
12596
+ return limit;
12597
+ }
12598
+ function parseTelemetryOk(value) {
12599
+ if (value === undefined) {
12600
+ return;
12601
+ }
12602
+ if (value !== "true" && value !== "false") {
12603
+ throw new Error("--ok must be true or false");
12604
+ }
12605
+ return value === "true";
12606
+ }
12607
+ function parseTelemetryTimestamp(value, flag) {
12608
+ if (value === undefined) {
12609
+ return;
12610
+ }
12611
+ const timestamp = new Date(value);
12612
+ if (Number.isNaN(timestamp.getTime())) {
12613
+ throw new Error(`${flag} must be an ISO-8601 timestamp`);
12614
+ }
12615
+ return timestamp.toISOString();
12616
+ }
12488
12617
  function parsePage(value) {
12489
12618
  const page = Number.parseInt(value ?? "1", 10);
12490
12619
  if (!Number.isInteger(page) || page < 1) {
@@ -12552,6 +12681,28 @@ async function runAdminAttention(options, attentionQueueCommand2) {
12552
12681
  console.log(attentionQueueLines2(queue).join(`
12553
12682
  `));
12554
12683
  }
12684
+ async function runAdminTelemetry(options, telemetryCommand2) {
12685
+ const since = parseTelemetryTimestamp(options.since, "--since");
12686
+ const until = parseTelemetryTimestamp(options.until, "--until");
12687
+ if (since !== undefined && until !== undefined && since > until) {
12688
+ throw new Error("--since must be before or equal to --until");
12689
+ }
12690
+ const page = await telemetryCommand2({
12691
+ cursor: options.cursor,
12692
+ limit: parseTelemetryLimit(options.limit),
12693
+ ok: parseTelemetryOk(options.ok),
12694
+ since,
12695
+ unit: options.unit,
12696
+ until
12697
+ });
12698
+ if (options.json) {
12699
+ printJson({ ok: true, ...page });
12700
+ return;
12701
+ }
12702
+ const { telemetryLines: telemetryLines2 } = await Promise.resolve().then(() => (init_admin_telemetry(), exports_admin_telemetry));
12703
+ console.log(telemetryLines2(page).join(`
12704
+ `));
12705
+ }
12555
12706
  async function runAdminQueue(options, queueCommand2) {
12556
12707
  const limit = parseListLimit(options.limit);
12557
12708
  const tracks = await queueCommand2(limit, {
@@ -13020,6 +13171,7 @@ var stringOptions = new Set([
13020
13171
  "--min-phrase-words",
13021
13172
  "--model",
13022
13173
  "--note",
13174
+ "--ok",
13023
13175
  "--order",
13024
13176
  "--page",
13025
13177
  "--parent-id",
@@ -13041,6 +13193,7 @@ var stringOptions = new Set([
13041
13193
  "--script-file",
13042
13194
  "--seed",
13043
13195
  "--seed-state",
13196
+ "--since",
13044
13197
  "--soundcloud-url",
13045
13198
  "--source",
13046
13199
  "--status",
@@ -13049,6 +13202,8 @@ var stringOptions = new Set([
13049
13202
  "--token",
13050
13203
  "--tracklist-file",
13051
13204
  "--tracks",
13205
+ "--unit",
13206
+ "--until",
13052
13207
  "--url",
13053
13208
  "--verdict",
13054
13209
  "--verdict-file",
package/package.json CHANGED
@@ -31,5 +31,5 @@
31
31
  "url": "git+https://github.com/mauricekleine/fluncle.git"
32
32
  },
33
33
  "type": "module",
34
- "version": "0.210.0"
34
+ "version": "0.211.0"
35
35
  }