@layr-labs/ecloud-cli 0.2.0-dev.2 → 0.2.0-dev.3

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 (58) hide show
  1. package/VERSION +2 -2
  2. package/dist/commands/auth/generate.js +2 -2
  3. package/dist/commands/auth/generate.js.map +1 -1
  4. package/dist/commands/auth/login.js.map +1 -1
  5. package/dist/commands/auth/logout.js.map +1 -1
  6. package/dist/commands/auth/migrate.js.map +1 -1
  7. package/dist/commands/auth/whoami.js +5 -3
  8. package/dist/commands/auth/whoami.js.map +1 -1
  9. package/dist/commands/billing/cancel.js +6 -3
  10. package/dist/commands/billing/cancel.js.map +1 -1
  11. package/dist/commands/billing/status.js +6 -3
  12. package/dist/commands/billing/status.js.map +1 -1
  13. package/dist/commands/billing/subscribe.js +12 -7
  14. package/dist/commands/billing/subscribe.js.map +1 -1
  15. package/dist/commands/compute/app/create.js.map +1 -1
  16. package/dist/commands/compute/app/deploy.js +614 -86
  17. package/dist/commands/compute/app/deploy.js.map +1 -1
  18. package/dist/commands/compute/app/info.js +59 -10
  19. package/dist/commands/compute/app/info.js.map +1 -1
  20. package/dist/commands/compute/app/list.js +10 -9
  21. package/dist/commands/compute/app/list.js.map +1 -1
  22. package/dist/commands/compute/app/logs.js +61 -11
  23. package/dist/commands/compute/app/logs.js.map +1 -1
  24. package/dist/commands/compute/app/profile/set.js +145 -20
  25. package/dist/commands/compute/app/profile/set.js.map +1 -1
  26. package/dist/commands/compute/app/releases.js +1111 -0
  27. package/dist/commands/compute/app/releases.js.map +1 -0
  28. package/dist/commands/compute/app/start.js +61 -11
  29. package/dist/commands/compute/app/start.js.map +1 -1
  30. package/dist/commands/compute/app/stop.js +61 -11
  31. package/dist/commands/compute/app/stop.js.map +1 -1
  32. package/dist/commands/compute/app/terminate.js +61 -11
  33. package/dist/commands/compute/app/terminate.js.map +1 -1
  34. package/dist/commands/compute/app/upgrade.js +615 -52
  35. package/dist/commands/compute/app/upgrade.js.map +1 -1
  36. package/dist/commands/compute/build/info.js +500 -0
  37. package/dist/commands/compute/build/info.js.map +1 -0
  38. package/dist/commands/compute/build/list.js +494 -0
  39. package/dist/commands/compute/build/list.js.map +1 -0
  40. package/dist/commands/compute/build/logs.js +459 -0
  41. package/dist/commands/compute/build/logs.js.map +1 -0
  42. package/dist/commands/compute/build/status.js +481 -0
  43. package/dist/commands/compute/build/status.js.map +1 -0
  44. package/dist/commands/compute/build/submit.js +618 -0
  45. package/dist/commands/compute/build/submit.js.map +1 -0
  46. package/dist/commands/compute/build/verify.js +439 -0
  47. package/dist/commands/compute/build/verify.js.map +1 -0
  48. package/dist/commands/compute/environment/list.js.map +1 -1
  49. package/dist/commands/compute/environment/set.js.map +1 -1
  50. package/dist/commands/compute/environment/show.js.map +1 -1
  51. package/dist/commands/compute/undelegate.js +11 -9
  52. package/dist/commands/compute/undelegate.js.map +1 -1
  53. package/dist/commands/telemetry/disable.js.map +1 -1
  54. package/dist/commands/telemetry/enable.js.map +1 -1
  55. package/dist/commands/telemetry/status.js.map +1 -1
  56. package/dist/commands/upgrade.js.map +1 -1
  57. package/dist/commands/version.js.map +1 -1
  58. package/package.json +7 -2
@@ -0,0 +1,494 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/commands/compute/build/list.ts
4
+ import { Command, Flags as Flags2 } from "@oclif/core";
5
+ import chalk2 from "chalk";
6
+ import { privateKeyToAccount as privateKeyToAccount3 } from "viem/accounts";
7
+ import { addHexPrefix } from "@layr-labs/ecloud-sdk";
8
+
9
+ // src/flags.ts
10
+ import { Flags } from "@oclif/core";
11
+ import { getBuildType as getBuildType2 } from "@layr-labs/ecloud-sdk";
12
+
13
+ // src/utils/prompts.ts
14
+ import { input, select, password, confirm as inquirerConfirm } from "@inquirer/prompts";
15
+ import fs3 from "fs";
16
+ import path3 from "path";
17
+ import os3 from "os";
18
+ import { isAddress as isAddress2 } from "viem";
19
+ import { privateKeyToAccount as privateKeyToAccount2 } from "viem/accounts";
20
+ import {
21
+ getEnvironmentConfig,
22
+ getAvailableEnvironments,
23
+ isEnvironmentAvailable,
24
+ getAllAppsByDeveloper as getAllAppsByDeveloper2,
25
+ getCategoryDescriptions,
26
+ fetchTemplateCatalog,
27
+ PRIMARY_LANGUAGES,
28
+ validateAppName,
29
+ validateImageReference,
30
+ validateFilePath,
31
+ validatePrivateKeyFormat,
32
+ extractAppNameFromImage,
33
+ UserApiClient as UserApiClient2
34
+ } from "@layr-labs/ecloud-sdk";
35
+
36
+ // src/utils/appResolver.ts
37
+ import { isAddress } from "viem";
38
+ import { privateKeyToAccount } from "viem/accounts";
39
+ import {
40
+ UserApiClient,
41
+ getAllAppsByDeveloper
42
+ } from "@layr-labs/ecloud-sdk";
43
+
44
+ // src/utils/globalConfig.ts
45
+ import * as fs from "fs";
46
+ import * as path from "path";
47
+ import * as os from "os";
48
+ import { load as loadYaml, dump as dumpYaml } from "js-yaml";
49
+ import { getBuildType } from "@layr-labs/ecloud-sdk";
50
+ import * as crypto from "crypto";
51
+ var GLOBAL_CONFIG_FILE = "config.yaml";
52
+ var PROFILE_CACHE_TTL_MS = 24 * 60 * 60 * 1e3;
53
+ function getGlobalConfigDir() {
54
+ const configHome = process.env.XDG_CONFIG_HOME;
55
+ let baseDir;
56
+ if (configHome && path.isAbsolute(configHome)) {
57
+ baseDir = configHome;
58
+ } else {
59
+ baseDir = path.join(os.homedir(), ".config");
60
+ }
61
+ const buildType = getBuildType();
62
+ const buildSuffix = buildType === "dev" ? "-dev" : "";
63
+ const configDirName = `ecloud${buildSuffix}`;
64
+ return path.join(baseDir, configDirName);
65
+ }
66
+ function getGlobalConfigPath() {
67
+ return path.join(getGlobalConfigDir(), GLOBAL_CONFIG_FILE);
68
+ }
69
+ function loadGlobalConfig() {
70
+ const configPath = getGlobalConfigPath();
71
+ if (!fs.existsSync(configPath)) {
72
+ return {
73
+ first_run: true
74
+ };
75
+ }
76
+ try {
77
+ const content = fs.readFileSync(configPath, "utf-8");
78
+ const config = loadYaml(content);
79
+ return config || { first_run: true };
80
+ } catch {
81
+ return {
82
+ first_run: true
83
+ };
84
+ }
85
+ }
86
+ function saveGlobalConfig(config) {
87
+ const configPath = getGlobalConfigPath();
88
+ const configDir = path.dirname(configPath);
89
+ fs.mkdirSync(configDir, { recursive: true, mode: 493 });
90
+ const content = dumpYaml(config, { lineWidth: -1 });
91
+ fs.writeFileSync(configPath, content, { mode: 420 });
92
+ }
93
+ function getDefaultEnvironment() {
94
+ const config = loadGlobalConfig();
95
+ return config.default_environment;
96
+ }
97
+ function getGlobalTelemetryPreference() {
98
+ const config = loadGlobalConfig();
99
+ return config.telemetry_enabled;
100
+ }
101
+ function getOrCreateUserUUID() {
102
+ const config = loadGlobalConfig();
103
+ if (config.user_uuid) {
104
+ return config.user_uuid;
105
+ }
106
+ const uuid = generateUUID();
107
+ config.user_uuid = uuid;
108
+ config.first_run = false;
109
+ saveGlobalConfig(config);
110
+ return uuid;
111
+ }
112
+ function generateUUID() {
113
+ const bytes = crypto.randomBytes(16);
114
+ bytes[6] = bytes[6] & 15 | 64;
115
+ bytes[8] = bytes[8] & 63 | 128;
116
+ const hex = Array.from(bytes, (b) => b.toString(16).padStart(2, "0"));
117
+ return hex.slice(0, 4).join("") + hex.slice(4, 6).join("") + "-" + hex.slice(6, 8).join("") + "-" + hex.slice(8, 10).join("") + "-" + hex.slice(10, 12).join("") + "-" + hex.slice(12, 16).join("");
118
+ }
119
+
120
+ // src/utils/appNames.ts
121
+ import * as fs2 from "fs";
122
+ import * as path2 from "path";
123
+ import * as os2 from "os";
124
+ import { load as loadYaml2, dump as dumpYaml2 } from "js-yaml";
125
+ var CONFIG_DIR = path2.join(os2.homedir(), ".eigenx");
126
+ var APPS_DIR = path2.join(CONFIG_DIR, "apps");
127
+
128
+ // src/utils/version.ts
129
+ function getCliVersion() {
130
+ return true ? "0.2.0-dev.3" : "0.0.0";
131
+ }
132
+ function getClientId() {
133
+ return `ecloud-cli/v${getCliVersion()}`;
134
+ }
135
+
136
+ // src/utils/prompts.ts
137
+ async function getPrivateKeyInteractive(privateKey) {
138
+ if (privateKey) {
139
+ if (!validatePrivateKeyFormat(privateKey)) {
140
+ throw new Error("Invalid private key format");
141
+ }
142
+ return privateKey;
143
+ }
144
+ const { getPrivateKeyWithSource: getPrivateKeyWithSource2 } = await import("@layr-labs/ecloud-sdk");
145
+ const result = await getPrivateKeyWithSource2({ privateKey: void 0 });
146
+ if (result) {
147
+ return result.key;
148
+ }
149
+ const key = await password({
150
+ message: "Enter private key:",
151
+ mask: true,
152
+ validate: (value) => {
153
+ if (!value.trim()) {
154
+ return "Private key is required";
155
+ }
156
+ if (!validatePrivateKeyFormat(value)) {
157
+ return "Invalid private key format (must be 64 hex characters, optionally prefixed with 0x)";
158
+ }
159
+ return true;
160
+ }
161
+ });
162
+ return key.trim();
163
+ }
164
+ async function getEnvironmentInteractive(environment) {
165
+ if (environment) {
166
+ try {
167
+ getEnvironmentConfig(environment);
168
+ if (!isEnvironmentAvailable(environment)) {
169
+ throw new Error(`Environment ${environment} is not available in this build`);
170
+ }
171
+ return environment;
172
+ } catch {
173
+ }
174
+ }
175
+ const availableEnvs = getAvailableEnvironments();
176
+ let defaultEnv;
177
+ const configDefaultEnv = getDefaultEnvironment();
178
+ if (configDefaultEnv && availableEnvs.includes(configDefaultEnv)) {
179
+ try {
180
+ getEnvironmentConfig(configDefaultEnv);
181
+ defaultEnv = configDefaultEnv;
182
+ } catch {
183
+ }
184
+ }
185
+ const choices = [];
186
+ if (availableEnvs.includes("sepolia")) {
187
+ choices.push({ name: "sepolia - Ethereum Sepolia testnet", value: "sepolia" });
188
+ }
189
+ if (availableEnvs.includes("sepolia-dev")) {
190
+ choices.push({ name: "sepolia-dev - Ethereum Sepolia testnet (dev)", value: "sepolia-dev" });
191
+ }
192
+ if (availableEnvs.includes("mainnet-alpha")) {
193
+ choices.push({
194
+ name: "mainnet-alpha - Ethereum mainnet (\u26A0\uFE0F uses real funds)",
195
+ value: "mainnet-alpha"
196
+ });
197
+ }
198
+ if (choices.length === 0) {
199
+ throw new Error("No environments available in this build");
200
+ }
201
+ const env = await select({
202
+ message: "Select environment:",
203
+ choices,
204
+ default: defaultEnv
205
+ });
206
+ return env;
207
+ }
208
+ var MAX_IMAGE_SIZE = 4 * 1024 * 1024;
209
+
210
+ // src/flags.ts
211
+ var commonFlags = {
212
+ environment: Flags.string({
213
+ required: false,
214
+ description: "Deployment environment to use",
215
+ env: "ECLOUD_ENV",
216
+ default: async () => getDefaultEnvironment() || (getBuildType2() === "dev" ? "sepolia-dev" : "sepolia")
217
+ }),
218
+ "private-key": Flags.string({
219
+ required: false,
220
+ description: "Private key for signing transactions",
221
+ env: "ECLOUD_PRIVATE_KEY"
222
+ }),
223
+ "rpc-url": Flags.string({
224
+ required: false,
225
+ description: "RPC URL to connect to blockchain",
226
+ env: "ECLOUD_RPC_URL"
227
+ }),
228
+ verbose: Flags.boolean({
229
+ required: false,
230
+ description: "Enable verbose logging (default: false)",
231
+ default: false
232
+ })
233
+ };
234
+ async function validateCommonFlags(flags, options) {
235
+ flags["environment"] = await getEnvironmentInteractive(flags["environment"]);
236
+ if (options?.requirePrivateKey !== false) {
237
+ flags["private-key"] = await getPrivateKeyInteractive(flags["private-key"]);
238
+ }
239
+ return flags;
240
+ }
241
+
242
+ // src/client.ts
243
+ import {
244
+ createComputeModule,
245
+ createBillingModule,
246
+ createBuildModule,
247
+ getEnvironmentConfig as getEnvironmentConfig2,
248
+ requirePrivateKey,
249
+ getPrivateKeyWithSource
250
+ } from "@layr-labs/ecloud-sdk";
251
+ async function createBuildClient(flags) {
252
+ flags = await validateCommonFlags(flags, { requirePrivateKey: false });
253
+ return createBuildModule({
254
+ verbose: flags.verbose,
255
+ privateKey: flags["private-key"],
256
+ environment: flags.environment,
257
+ clientId: getClientId(),
258
+ skipTelemetry: true
259
+ // CLI already has telemetry, skip SDK telemetry
260
+ });
261
+ }
262
+
263
+ // src/telemetry.ts
264
+ import {
265
+ createTelemetryClient,
266
+ createAppEnvironment,
267
+ createMetricsContext,
268
+ addMetric,
269
+ addMetricWithDimensions,
270
+ emitMetrics,
271
+ getBuildType as getBuildType3
272
+ } from "@layr-labs/ecloud-sdk";
273
+ function createCLITelemetryClient() {
274
+ const userUUID = getOrCreateUserUUID();
275
+ const environment = createAppEnvironment(userUUID);
276
+ const telemetryEnabled = getGlobalTelemetryPreference();
277
+ return createTelemetryClient(environment, "ecloud-cli", {
278
+ telemetryEnabled: telemetryEnabled !== false
279
+ // Enabled by default, disabled only if explicitly set to false
280
+ });
281
+ }
282
+ async function withTelemetry(command, action) {
283
+ const client = createCLITelemetryClient();
284
+ const metrics = createMetricsContext();
285
+ metrics.properties["source"] = "ecloud-cli";
286
+ metrics.properties["command"] = command.id || command.constructor.name;
287
+ const environment = getDefaultEnvironment() || "sepolia";
288
+ metrics.properties["environment"] = environment;
289
+ const buildType = getBuildType3() || "prod";
290
+ metrics.properties["build_type"] = buildType;
291
+ const cliVersion = command.config.version;
292
+ if (cliVersion) {
293
+ metrics.properties["cli_version"] = cliVersion;
294
+ }
295
+ addMetric(metrics, "Count", 1);
296
+ let actionError;
297
+ let result;
298
+ try {
299
+ result = await action();
300
+ return result;
301
+ } catch (err) {
302
+ actionError = err instanceof Error ? err : new Error(String(err));
303
+ throw err;
304
+ } finally {
305
+ const resultValue = actionError ? "Failure" : "Success";
306
+ const dimensions = {};
307
+ if (actionError) {
308
+ dimensions["error"] = actionError.message;
309
+ }
310
+ addMetricWithDimensions(metrics, resultValue, 1, dimensions);
311
+ const duration = Date.now() - metrics.startTime.getTime();
312
+ addMetric(metrics, "DurationMilliseconds", duration);
313
+ try {
314
+ await emitMetrics(client, metrics);
315
+ await client.close();
316
+ } catch {
317
+ }
318
+ }
319
+ }
320
+
321
+ // src/utils/buildInfo.ts
322
+ import { BUILD_STATUS } from "@layr-labs/ecloud-sdk";
323
+ import chalk from "chalk";
324
+ function formatBuildStatus(status) {
325
+ const s = status;
326
+ const color = {
327
+ [BUILD_STATUS.BUILDING]: chalk.yellow,
328
+ [BUILD_STATUS.SUCCESS]: chalk.green,
329
+ [BUILD_STATUS.FAILED]: chalk.red
330
+ }[s];
331
+ return color ? color(status) : status;
332
+ }
333
+
334
+ // src/commands/compute/build/list.ts
335
+ import Table from "cli-table3";
336
+
337
+ // src/utils/cliFormat.ts
338
+ function terminalWidth(fallback = 120) {
339
+ const cols = typeof process.stdout.columns === "number" ? process.stdout.columns : void 0;
340
+ return cols && cols > 0 ? cols : fallback;
341
+ }
342
+ function formatHumanTime(value) {
343
+ const raw = String(value ?? "").trim();
344
+ if (!raw) return "-";
345
+ if (/^\d+$/.test(raw)) {
346
+ const n = Number(raw);
347
+ if (Number.isFinite(n) && n > 0) {
348
+ const ms = raw.length <= 10 ? n * 1e3 : n;
349
+ const d2 = new Date(ms);
350
+ if (!Number.isNaN(d2.getTime())) return d2.toLocaleString();
351
+ }
352
+ return raw;
353
+ }
354
+ const d = new Date(raw);
355
+ if (Number.isNaN(d.getTime())) return raw;
356
+ return d.toLocaleString();
357
+ }
358
+ function formatRepoDisplay(repoUrl) {
359
+ const normalized = String(repoUrl || "").replace(/\.git$/i, "").replace(/\/+$/, "");
360
+ try {
361
+ const url = new URL(normalized);
362
+ const host = url.host.toLowerCase();
363
+ if (host === "github.com") {
364
+ const parts = url.pathname.split("/").filter(Boolean);
365
+ if (parts.length >= 2) return `github.com/${parts[0]}/${parts[1]}`;
366
+ }
367
+ return `${host}${url.pathname}`.replace(/\/+$/, "");
368
+ } catch {
369
+ return normalized;
370
+ }
371
+ }
372
+ function formatImageDisplay(imageUrl) {
373
+ const s = String(imageUrl || "");
374
+ return s.replace(/^docker\.io\//i, "");
375
+ }
376
+ function provenanceSummary(options) {
377
+ const parts = [];
378
+ if (options.provenanceJson) parts.push("prov\u2713");
379
+ if (options.provenanceSignature) parts.push("sig\u2713");
380
+ const depCount = options.dependencies ? Object.keys(options.dependencies).length : 0;
381
+ if (depCount > 0) parts.push(`deps:${depCount}`);
382
+ return parts.length ? parts.join(" ") : "-";
383
+ }
384
+
385
+ // src/commands/compute/build/list.ts
386
+ var BuildList = class _BuildList extends Command {
387
+ static description = "List recent verifiable builds for a billing address (most recent first)";
388
+ static examples = [
389
+ `$ ecloud compute build list`,
390
+ `$ ecloud compute build list --limit 10`,
391
+ `$ ecloud compute build list --json`
392
+ ];
393
+ static flags = {
394
+ ...commonFlags,
395
+ limit: Flags2.integer({
396
+ description: "Maximum number of builds to return (min 1, max 100)",
397
+ default: 20
398
+ }),
399
+ offset: Flags2.integer({
400
+ description: "Number of builds to skip",
401
+ default: 0
402
+ }),
403
+ json: Flags2.boolean({
404
+ description: "Output JSON instead of a table",
405
+ default: false
406
+ })
407
+ };
408
+ async run() {
409
+ return withTelemetry(this, async () => {
410
+ const { flags } = await this.parse(_BuildList);
411
+ const validatedFlags = await validateCommonFlags(flags);
412
+ const client = await createBuildClient(validatedFlags);
413
+ const billingAddress = privateKeyToAccount3(
414
+ addHexPrefix(validatedFlags["private-key"])
415
+ ).address;
416
+ const limit = Math.max(1, Math.min(100, flags.limit ?? 20));
417
+ const offset = Math.max(0, flags.offset ?? 0);
418
+ const builds = (await client.list({ billingAddress, limit, offset })).slice().reverse();
419
+ if (flags.json) {
420
+ this.log(JSON.stringify(builds, null, 2));
421
+ return;
422
+ }
423
+ if (!builds.length) {
424
+ this.log(`No builds found for ${billingAddress}`);
425
+ return;
426
+ }
427
+ const rows = builds.map((b) => ({
428
+ buildId: b.buildId || "-",
429
+ status: formatBuildStatus(b.status),
430
+ repo: formatRepoDisplay(b.repoUrl || "-"),
431
+ commit: b.gitRef || "-",
432
+ image: formatImageDisplay(b.imageUrl || "-"),
433
+ created: formatHumanTime(b.createdAt),
434
+ prov: provenanceSummary({
435
+ provenanceJson: b.provenanceJson,
436
+ provenanceSignature: b.provenanceSignature,
437
+ dependencies: b.dependencies
438
+ })
439
+ }));
440
+ const tw = terminalWidth();
441
+ const shouldStack = tw < 110;
442
+ this.log("");
443
+ this.log(chalk2.bold(`Builds for ${billingAddress} (${validatedFlags.environment}):`));
444
+ this.log("");
445
+ if (shouldStack) {
446
+ for (const r of rows) {
447
+ this.log(`${r.status} ${chalk2.cyan(r.buildId)} ${r.created}`);
448
+ this.log(` Repo: ${r.repo}`);
449
+ this.log(` Commit: ${r.commit}`);
450
+ this.log(` Image: ${r.image}`);
451
+ this.log(` Prov: ${r.prov}`);
452
+ this.log(chalk2.gray(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
453
+ }
454
+ } else {
455
+ const fixed = 37 + 10 + 20 + 14 + 8;
456
+ const remaining = Math.max(30, tw - fixed);
457
+ const repoW = Math.max(18, Math.floor(remaining * 0.28));
458
+ const commitW = Math.max(18, Math.floor(remaining * 0.36));
459
+ const imageW = Math.max(18, remaining - repoW - commitW);
460
+ const table = new Table({
461
+ head: [
462
+ chalk2.bold("ID"),
463
+ chalk2.bold("Status"),
464
+ chalk2.bold("Repo"),
465
+ chalk2.bold("Commit"),
466
+ chalk2.bold("Image"),
467
+ chalk2.bold("Created"),
468
+ chalk2.bold("Prov")
469
+ ],
470
+ colWidths: [37, 10, repoW, commitW, imageW, 20, 14],
471
+ wordWrap: true,
472
+ style: { "padding-left": 0, "padding-right": 1, head: [], border: [] }
473
+ });
474
+ for (const r of rows) {
475
+ table.push([r.buildId, r.status, r.repo, r.commit, r.image, r.created, r.prov]);
476
+ }
477
+ this.log(table.toString());
478
+ }
479
+ this.log("");
480
+ this.log(chalk2.gray(`Showing ${builds.length} build(s) (limit=${limit}, offset=${offset})`));
481
+ this.log(
482
+ chalk2.gray(
483
+ `Tip: use ${chalk2.yellow("ecloud compute build info <buildId>")} for full details, or add ${chalk2.yellow(
484
+ "--json"
485
+ )} to copy/paste.`
486
+ )
487
+ );
488
+ });
489
+ }
490
+ };
491
+ export {
492
+ BuildList as default
493
+ };
494
+ //# sourceMappingURL=list.js.map