@asteroidai/cli 1.9.2 → 1.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.
package/dist/asteroid.js CHANGED
@@ -48,12 +48,13 @@ function indent(text2) {
48
48
  function text(value2) {
49
49
  return clean(isScalar(value2) ? String(value2) : JSON.stringify(value2));
50
50
  }
51
- function cell(value2) {
51
+ function cell(value2, options = {}) {
52
52
  if (value2 === null || value2 === void 0) return "";
53
53
  const line = text(value2).replace(/\s+/g, " ");
54
- return line.length > MAX_CELL ? `${line.slice(0, MAX_CELL - 1)}\u2026` : line;
54
+ if (options.full || line.length <= MAX_CELL) return line;
55
+ return `${line.slice(0, MAX_CELL - 1)}\u2026`;
55
56
  }
56
- function columns(rows) {
57
+ function columns(rows, options) {
57
58
  const scalarKeys = [];
58
59
  for (const row of rows) {
59
60
  for (const [key, value2] of Object.entries(row)) {
@@ -65,7 +66,7 @@ function columns(rows) {
65
66
  ...PREFERRED.filter((key) => scalarKeys.includes(key)),
66
67
  ...scalarKeys.filter((key) => !PREFERRED.includes(key))
67
68
  ];
68
- return ordered.slice(0, MAX_COLUMNS);
69
+ return options.full ? ordered : ordered.slice(0, MAX_COLUMNS);
69
70
  }
70
71
  function style(format, value2, options) {
71
72
  return options.styled ? styleText(format, value2, { validateStream: false }) : value2;
@@ -85,9 +86,9 @@ function flatten(row) {
85
86
  function table(input, options = {}) {
86
87
  if (input.length === 0) return "No results.";
87
88
  const rows = input.map(flatten);
88
- const keys = columns(rows);
89
+ const keys = columns(rows, options);
89
90
  if (keys.length === 0) return rows.map((row) => text(row)).join("\n");
90
- const cells = rows.map((row) => keys.map((key) => cell(row[key])));
91
+ const cells = rows.map((row) => keys.map((key) => cell(row[key], options)));
91
92
  if (options.styled) {
92
93
  const grid = new Table({
93
94
  head: keys.map((key) => style("bold", key, options)),
@@ -104,10 +105,10 @@ function table(input, options = {}) {
104
105
  "\n"
105
106
  );
106
107
  }
107
- function summary(value2) {
108
+ function summary(value2, options) {
108
109
  if (Array.isArray(value2))
109
110
  return `[${value2.length} item${value2.length === 1 ? "" : "s"}]`;
110
- if (value2 && typeof value2 === "object") return cell(value2);
111
+ if (value2 && typeof value2 === "object") return cell(value2, options);
111
112
  return text(value2);
112
113
  }
113
114
  function record(value2, options) {
@@ -126,7 +127,7 @@ ${" ".repeat(width + 2)}`)}`;
126
127
  return `${style("bold", key, options)}:
127
128
  ${indent(record(v, options))}`;
128
129
  }
129
- return `${label(key)} ${isScalar(v) ? text(v) : summary(v)}`;
130
+ return `${label(key)} ${isScalar(v) ? text(v) : summary(v, options)}`;
130
131
  }).join("\n");
131
132
  }
132
133
  function render(value2, options = {}) {
@@ -5329,7 +5330,7 @@ var ApiError = class extends Error {
5329
5330
  status;
5330
5331
  body;
5331
5332
  };
5332
- var VERSION = "1.9.2";
5333
+ var VERSION = "1.9.4";
5333
5334
  function problem(status, body, fallback) {
5334
5335
  if (body && typeof body === "object") {
5335
5336
  const record2 = body;
@@ -5878,7 +5879,10 @@ async function runCommand(command, parsed, deps) {
5878
5879
  }
5879
5880
  if (response.json !== void 0) {
5880
5881
  deps.stdout(
5881
- `${parsed.json ? JSON.stringify(response.json, null, 2) : render(response.json, { styled: deps.styled })}
5882
+ `${parsed.json ? JSON.stringify(response.json, null, 2) : render(response.json, {
5883
+ styled: deps.styled,
5884
+ full: !deps.stdoutIsTTY
5885
+ })}
5882
5886
  `
5883
5887
  );
5884
5888
  return 0;
@@ -5887,7 +5891,7 @@ async function runCommand(command, parsed, deps) {
5887
5891
  `);
5888
5892
  return 0;
5889
5893
  }
5890
- var DESCRIPTION = "The Asteroid CLI. Sign in with `asteroid login`, or set ASTEROID_API_KEY.";
5894
+ var DESCRIPTION = "The Asteroid CLI. Sign in with `asteroid login`, or set ASTEROID_API_KEY.\nAt a terminal, tables show up to 6 columns and cut long cells to fit; when output is piped, they show every column in full. Use `--json` for every field.";
5891
5895
  async function run(argv2, deps) {
5892
5896
  try {
5893
5897
  const invocation = await parseInvocation(argv2, {
package/dist/core.js CHANGED
@@ -4560,12 +4560,13 @@ function indent(text2) {
4560
4560
  function text(value2) {
4561
4561
  return clean(isScalar(value2) ? String(value2) : JSON.stringify(value2));
4562
4562
  }
4563
- function cell(value2) {
4563
+ function cell(value2, options = {}) {
4564
4564
  if (value2 === null || value2 === void 0) return "";
4565
4565
  const line = text(value2).replace(/\s+/g, " ");
4566
- return line.length > MAX_CELL ? `${line.slice(0, MAX_CELL - 1)}\u2026` : line;
4566
+ if (options.full || line.length <= MAX_CELL) return line;
4567
+ return `${line.slice(0, MAX_CELL - 1)}\u2026`;
4567
4568
  }
4568
- function columns(rows) {
4569
+ function columns(rows, options) {
4569
4570
  const scalarKeys = [];
4570
4571
  for (const row of rows) {
4571
4572
  for (const [key, value2] of Object.entries(row)) {
@@ -4577,7 +4578,7 @@ function columns(rows) {
4577
4578
  ...PREFERRED.filter((key) => scalarKeys.includes(key)),
4578
4579
  ...scalarKeys.filter((key) => !PREFERRED.includes(key))
4579
4580
  ];
4580
- return ordered.slice(0, MAX_COLUMNS);
4581
+ return options.full ? ordered : ordered.slice(0, MAX_COLUMNS);
4581
4582
  }
4582
4583
  function style(format, value2, options) {
4583
4584
  return options.styled ? styleText(format, value2, { validateStream: false }) : value2;
@@ -4597,9 +4598,9 @@ function flatten(row) {
4597
4598
  function table(input, options = {}) {
4598
4599
  if (input.length === 0) return "No results.";
4599
4600
  const rows = input.map(flatten);
4600
- const keys = columns(rows);
4601
+ const keys = columns(rows, options);
4601
4602
  if (keys.length === 0) return rows.map((row) => text(row)).join("\n");
4602
- const cells = rows.map((row) => keys.map((key) => cell(row[key])));
4603
+ const cells = rows.map((row) => keys.map((key) => cell(row[key], options)));
4603
4604
  if (options.styled) {
4604
4605
  const grid = new Table({
4605
4606
  head: keys.map((key) => style("bold", key, options)),
@@ -4616,10 +4617,10 @@ function table(input, options = {}) {
4616
4617
  "\n"
4617
4618
  );
4618
4619
  }
4619
- function summary(value2) {
4620
+ function summary(value2, options) {
4620
4621
  if (Array.isArray(value2))
4621
4622
  return `[${value2.length} item${value2.length === 1 ? "" : "s"}]`;
4622
- if (value2 && typeof value2 === "object") return cell(value2);
4623
+ if (value2 && typeof value2 === "object") return cell(value2, options);
4623
4624
  return text(value2);
4624
4625
  }
4625
4626
  function record(value2, options) {
@@ -4638,7 +4639,7 @@ ${" ".repeat(width + 2)}`)}`;
4638
4639
  return `${style("bold", key, options)}:
4639
4640
  ${indent(record(v, options))}`;
4640
4641
  }
4641
- return `${label(key)} ${isScalar(v) ? text(v) : summary(v)}`;
4642
+ return `${label(key)} ${isScalar(v) ? text(v) : summary(v, options)}`;
4642
4643
  }).join("\n");
4643
4644
  }
4644
4645
  function render(value2, options = {}) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@asteroidai/cli",
3
- "version": "1.9.2",
3
+ "version": "1.9.4",
4
4
  "description": "The asteroid command-line interface for the Asteroid platform.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -49,4 +49,23 @@ describe("render", () => {
49
49
  expect(out).toContain("EXECUTION.STATUS");
50
50
  expect(out).not.toContain("AGENTID");
51
51
  });
52
+
53
+ it("keeps long cells whole when asked", () => {
54
+ const secrets = `ECW(51d1db07-a6e1-4b1d-8303-a472b78923e8)[PASSWORD=##ECW_PASSWORD##]`;
55
+ const rows = [{ id: "p-1", secrets }];
56
+ expect(render(rows)).toContain("…");
57
+ expect(render(rows, { full: true })).toContain(secrets);
58
+ });
59
+
60
+ it("shows every column when asked, six otherwise", () => {
61
+ const row = Object.fromEntries(
62
+ ["id", "a", "b", "c", "d", "e", "f", "g"].map((key) => [
63
+ key,
64
+ key.toUpperCase(),
65
+ ]),
66
+ );
67
+ const header = (out: string) => out.split("\n")[0].trim().split(/\s+/);
68
+ expect(header(render([row]))).toHaveLength(6);
69
+ expect(header(render([row], { full: true }))).toHaveLength(8);
70
+ });
52
71
  });
package/src/output.ts CHANGED
@@ -22,6 +22,7 @@ type Row = Record<string, unknown>;
22
22
 
23
23
  export interface RenderOptions {
24
24
  styled?: boolean;
25
+ full?: boolean;
25
26
  }
26
27
 
27
28
  export function clean(text: string): string {
@@ -49,13 +50,14 @@ function text(value: unknown): string {
49
50
  return clean(isScalar(value) ? String(value) : JSON.stringify(value));
50
51
  }
51
52
 
52
- function cell(value: unknown): string {
53
+ function cell(value: unknown, options: RenderOptions = {}): string {
53
54
  if (value === null || value === undefined) return "";
54
55
  const line = text(value).replace(/\s+/g, " ");
55
- return line.length > MAX_CELL ? `${line.slice(0, MAX_CELL - 1)}…` : line;
56
+ if (options.full || line.length <= MAX_CELL) return line;
57
+ return `${line.slice(0, MAX_CELL - 1)}…`;
56
58
  }
57
59
 
58
- function columns(rows: Row[]): string[] {
60
+ function columns(rows: Row[], options: RenderOptions): string[] {
59
61
  const scalarKeys: string[] = [];
60
62
  for (const row of rows) {
61
63
  for (const [key, value] of Object.entries(row)) {
@@ -71,7 +73,7 @@ function columns(rows: Row[]): string[] {
71
73
  ...PREFERRED.filter((key) => scalarKeys.includes(key)),
72
74
  ...scalarKeys.filter((key) => !PREFERRED.includes(key)),
73
75
  ];
74
- return ordered.slice(0, MAX_COLUMNS);
76
+ return options.full ? ordered : ordered.slice(0, MAX_COLUMNS);
75
77
  }
76
78
 
77
79
  function style(
@@ -100,9 +102,9 @@ function flatten(row: Row): Row {
100
102
  export function table(input: Row[], options: RenderOptions = {}): string {
101
103
  if (input.length === 0) return "No results.";
102
104
  const rows = input.map(flatten);
103
- const keys = columns(rows);
105
+ const keys = columns(rows, options);
104
106
  if (keys.length === 0) return rows.map((row) => text(row)).join("\n");
105
- const cells = rows.map((row) => keys.map((key) => cell(row[key])));
107
+ const cells = rows.map((row) => keys.map((key) => cell(row[key], options)));
106
108
  if (options.styled) {
107
109
  const grid = new Table({
108
110
  head: keys.map((key) => style("bold", key, options)),
@@ -124,10 +126,10 @@ export function table(input: Row[], options: RenderOptions = {}): string {
124
126
  );
125
127
  }
126
128
 
127
- function summary(value: unknown): string {
129
+ function summary(value: unknown, options: RenderOptions): string {
128
130
  if (Array.isArray(value))
129
131
  return `[${value.length} item${value.length === 1 ? "" : "s"}]`;
130
- if (value && typeof value === "object") return cell(value);
132
+ if (value && typeof value === "object") return cell(value, options);
131
133
  return text(value);
132
134
  }
133
135
 
@@ -145,7 +147,7 @@ function record(value: Row, options: RenderOptions): string {
145
147
  if (isObject(v) && Object.keys(v as Row).length > 0) {
146
148
  return `${style("bold", key, options)}:\n${indent(record(v as Row, options))}`;
147
149
  }
148
- return `${label(key)} ${isScalar(v) ? text(v) : summary(v)}`;
150
+ return `${label(key)} ${isScalar(v) ? text(v) : summary(v, options)}`;
149
151
  })
150
152
  .join("\n");
151
153
  }
package/src/reference.ts CHANGED
@@ -138,6 +138,7 @@ export function renderReference(commands: CliCommand[]): string {
138
138
  "Sign in with `asteroid login`, or set `ASTEROID_API_KEY` for CI and agents.",
139
139
  "Commands that return data print compact text. Add `--json` to get the response as JSON.",
140
140
  "The text output may change between releases. Scripts should read `--json`.",
141
+ "At a terminal, tables show up to 6 columns and cut long cells to fit; when output is piped, they show every column in full. Use `--json` for every field.",
141
142
  "Downloads write raw bytes. `login`, `logout` and `use` only report status on stderr.",
142
143
  "Exit codes: 0 ok, 1 API error, 2 usage error.",
143
144
  "",
package/src/run.test.ts CHANGED
@@ -269,6 +269,26 @@ describe("guards", () => {
269
269
  });
270
270
  });
271
271
 
272
+ describe("cell width", () => {
273
+ const long = "x".repeat(80);
274
+ const reply = () => json({ items: [{ id: "w-1", name: long }] });
275
+
276
+ it("keeps cells whole when stdout is not a terminal", async () => {
277
+ const h = harness({ ASTEROID_API_KEY: "sk_test" }, reply);
278
+ await run(["workflow", "list"], h.deps);
279
+ expect(h.out.join("")).toContain(long);
280
+ });
281
+
282
+ it("cuts long cells at a terminal", async () => {
283
+ const h = harness({ ASTEROID_API_KEY: "sk_test" }, reply);
284
+ h.deps.stdoutIsTTY = true;
285
+ await run(["workflow", "list"], h.deps);
286
+ const out = h.out.join("");
287
+ expect(out).toContain(`${"x".repeat(59)}…`);
288
+ expect(out).not.toContain(long);
289
+ });
290
+ });
291
+
272
292
  describe("terminal safety", () => {
273
293
  it("refuses to print a download to a terminal", async () => {
274
294
  const h = harness(
package/src/run.ts CHANGED
@@ -138,7 +138,14 @@ async function runCommand(
138
138
  }
139
139
  if (response.json !== undefined) {
140
140
  deps.stdout(
141
- `${parsed.json ? JSON.stringify(response.json, null, 2) : render(response.json, { styled: deps.styled })}\n`,
141
+ `${
142
+ parsed.json
143
+ ? JSON.stringify(response.json, null, 2)
144
+ : render(response.json, {
145
+ styled: deps.styled,
146
+ full: !deps.stdoutIsTTY,
147
+ })
148
+ }\n`,
142
149
  );
143
150
  return 0;
144
151
  }
@@ -147,7 +154,7 @@ async function runCommand(
147
154
  }
148
155
 
149
156
  const DESCRIPTION =
150
- "The Asteroid CLI. Sign in with `asteroid login`, or set ASTEROID_API_KEY.";
157
+ "The Asteroid CLI. Sign in with `asteroid login`, or set ASTEROID_API_KEY.\nAt a terminal, tables show up to 6 columns and cut long cells to fit; when output is piped, they show every column in full. Use `--json` for every field.";
151
158
 
152
159
  export async function run(argv: string[], deps: Deps): Promise<number> {
153
160
  try {