@neta-art/cohub-cli 3.9.2 → 3.9.4

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.
@@ -5,7 +5,7 @@ import { basename, dirname, relative, resolve, sep } from "node:path";
5
5
  import { resolveCohubEnvironment } from "@neta-art/cohub";
6
6
  import { uploadAvatarAsset, uploadChatImageAsset } from "../avatar.js";
7
7
  import { createClient } from "../client.js";
8
- import { table, json as outJson, jsonRequested, ok, error, handleHttp } from "../output.js";
8
+ import { table, json as outJson, jsonRequested, ok, error, handleHttp, formatEpochMs } from "../output.js";
9
9
  import { resolveSpace } from "../space.js";
10
10
  import { registerSpaceCommerce } from "./space-commerce.js";
11
11
  import { registerSpaceInvitations } from "./space-invitations.js";
@@ -1116,7 +1116,7 @@ function registerFiles(spacesCmd) {
1116
1116
  { key: "name", label: "Name" },
1117
1117
  { key: "type", label: "Type" },
1118
1118
  { key: "size", label: "Size" },
1119
- { key: "mtimeMs", label: "Modified" },
1119
+ { key: "mtimeMs", label: "Modified", format: formatEpochMs },
1120
1120
  ]);
1121
1121
  }
1122
1122
  catch (e) {
@@ -1838,7 +1838,7 @@ function registerCheckpoints(spacesCmd) {
1838
1838
  { key: "type", label: "Type" },
1839
1839
  { key: "size", label: "Size" },
1840
1840
  { key: "mimeType", label: "MIME" },
1841
- { key: "mtimeMs", label: "Modified" },
1841
+ { key: "mtimeMs", label: "Modified", format: formatEpochMs },
1842
1842
  ]);
1843
1843
  }
1844
1844
  catch (e) {
package/dist/output.d.ts CHANGED
@@ -1,8 +1,23 @@
1
1
  export type Row = Record<string, unknown>;
2
- export declare function table(rows: Row[], columns: {
2
+ /**
3
+ * A table column. `format` maps a raw cell value to its display string, so
4
+ * machine-oriented fields (epoch timestamps, byte counts) stay unmodified in
5
+ * `--json` output while the human-facing table shows something readable.
6
+ */
7
+ export type Column = {
3
8
  key: string;
4
9
  label: string;
5
- }[]): void;
10
+ format?: (value: unknown, row: Row) => string;
11
+ };
12
+ /**
13
+ * Epoch milliseconds → ISO 8601, matching the ISO timestamps other tables print.
14
+ *
15
+ * Absent values render empty rather than falling through `Number()` coercion:
16
+ * `null` and `""` both become 0 there, which would print a confident-looking
17
+ * `1970-01-01T00:00:00.000Z` for a timestamp the server never sent.
18
+ */
19
+ export declare function formatEpochMs(value: unknown): string;
20
+ export declare function table(rows: Row[], columns: Column[]): void;
6
21
  export declare function json(data: unknown): void;
7
22
  export declare function jsonRequested(opts?: {
8
23
  json?: boolean;
package/dist/output.js CHANGED
@@ -1,19 +1,40 @@
1
1
  import process from "node:process";
2
2
  import { extractBillingPayload } from "@neta-art/cohub";
3
- function colWidth(rows, key, label) {
4
- const maxVal = rows.reduce((m, r) => {
5
- const v = r[key] ?? "";
6
- const s = typeof v === "object" ? JSON.stringify(v) : String(v);
7
- return Math.max(m, s.length);
8
- }, 0);
9
- return Math.max(label.length, maxVal) + 2;
3
+ /**
4
+ * Epoch milliseconds → ISO 8601, matching the ISO timestamps other tables print.
5
+ *
6
+ * Absent values render empty rather than falling through `Number()` coercion:
7
+ * `null` and `""` both become 0 there, which would print a confident-looking
8
+ * `1970-01-01T00:00:00.000Z` for a timestamp the server never sent.
9
+ */
10
+ export function formatEpochMs(value) {
11
+ const ms = typeof value === "number"
12
+ ? value
13
+ : typeof value === "string" && value.trim() !== ""
14
+ ? Number(value)
15
+ : Number.NaN;
16
+ if (!Number.isFinite(ms))
17
+ return "";
18
+ const date = new Date(ms);
19
+ return Number.isNaN(date.getTime()) ? "" : date.toISOString();
20
+ }
21
+ function cellText(column, row) {
22
+ const raw = row[column.key];
23
+ if (column.format)
24
+ return column.format(raw, row);
25
+ const v = raw ?? "";
26
+ return typeof v === "object" ? JSON.stringify(v) : String(v);
27
+ }
28
+ function colWidth(rows, column) {
29
+ const maxVal = rows.reduce((m, r) => Math.max(m, cellText(column, r).length), 0);
30
+ return Math.max(column.label.length, maxVal) + 2;
10
31
  }
11
32
  export function table(rows, columns) {
12
33
  if (rows.length === 0) {
13
34
  console.log(" (empty)");
14
35
  return;
15
36
  }
16
- const widths = columns.map((c) => colWidth(rows, c.key, c.label));
37
+ const widths = columns.map((c) => colWidth(rows, c));
17
38
  const header = columns
18
39
  .map((c, i) => c.label.padEnd(widths[i] ?? 0))
19
40
  .join(" │ ")
@@ -22,11 +43,7 @@ export function table(rows, columns) {
22
43
  console.log("─".repeat(header.length));
23
44
  for (const row of rows) {
24
45
  const line = columns
25
- .map((c, i) => {
26
- const v = row[c.key] ?? "";
27
- const s = typeof v === "object" ? JSON.stringify(v) : String(v);
28
- return s.padEnd(widths[i] ?? 0);
29
- })
46
+ .map((c, i) => cellText(c, row).padEnd(widths[i] ?? 0))
30
47
  .join(" │ ")
31
48
  .trimEnd();
32
49
  console.log(line);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@neta-art/cohub-cli",
3
- "version": "3.9.2",
3
+ "version": "3.9.4",
4
4
  "description": "CLI for Cohub — spaces, sessions, and agent collaboration.",
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",
@@ -15,11 +15,11 @@
15
15
  "NOTICE"
16
16
  ],
17
17
  "dependencies": {
18
- "@neta-art/generation": "^0.1.20",
18
+ "@neta-art/generation": "^0.1.21",
19
19
  "commander": "^15.0.0",
20
20
  "pixi.js": "^8.19.0",
21
21
  "sharp": "^0.35.3",
22
- "@neta-art/cohub": "5.4.3"
22
+ "@neta-art/cohub": "5.5.0"
23
23
  },
24
24
  "publishConfig": {
25
25
  "access": "public"