@vm0/cli 5.5.0 → 5.6.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.
- package/index.js +478 -502
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
// src/index.ts
|
|
4
4
|
import { Command as Command35 } from "commander";
|
|
5
|
-
import
|
|
5
|
+
import chalk36 from "chalk";
|
|
6
6
|
|
|
7
7
|
// src/lib/api/auth.ts
|
|
8
8
|
import chalk from "chalk";
|
|
@@ -5132,7 +5132,7 @@ import { Command as Command9 } from "commander";
|
|
|
5132
5132
|
|
|
5133
5133
|
// src/commands/volume/init.ts
|
|
5134
5134
|
import { Command as Command3 } from "commander";
|
|
5135
|
-
import
|
|
5135
|
+
import chalk6 from "chalk";
|
|
5136
5136
|
import path7 from "path";
|
|
5137
5137
|
|
|
5138
5138
|
// src/lib/storage/storage-utils.ts
|
|
@@ -5184,7 +5184,6 @@ async function writeStorageConfig(storageName, basePath = process.cwd(), type =
|
|
|
5184
5184
|
|
|
5185
5185
|
// src/lib/utils/prompt-utils.ts
|
|
5186
5186
|
import prompts2 from "prompts";
|
|
5187
|
-
import chalk6 from "chalk";
|
|
5188
5187
|
function isInteractive() {
|
|
5189
5188
|
return process.stdout.isTTY === true;
|
|
5190
5189
|
}
|
|
@@ -5247,48 +5246,6 @@ async function promptSelect(message, choices, initial) {
|
|
|
5247
5246
|
);
|
|
5248
5247
|
return response.value;
|
|
5249
5248
|
}
|
|
5250
|
-
async function promptTextWithHint(message, hint, initial, validate) {
|
|
5251
|
-
if (!isInteractive()) {
|
|
5252
|
-
return void 0;
|
|
5253
|
-
}
|
|
5254
|
-
const hintedInitial = `${hint} ${initial}`;
|
|
5255
|
-
const response = await prompts2(
|
|
5256
|
-
{
|
|
5257
|
-
type: "text",
|
|
5258
|
-
name: "value",
|
|
5259
|
-
message,
|
|
5260
|
-
initial: hintedInitial,
|
|
5261
|
-
// Custom render to show hint in gray
|
|
5262
|
-
onRender() {
|
|
5263
|
-
if (this.value.startsWith(hint + " ")) {
|
|
5264
|
-
const hintPart = hint + " ";
|
|
5265
|
-
const valuePart = this.value.slice(hintPart.length);
|
|
5266
|
-
this.rendered = chalk6.dim(hintPart) + valuePart;
|
|
5267
|
-
}
|
|
5268
|
-
},
|
|
5269
|
-
// Validate after stripping hint
|
|
5270
|
-
validate: validate ? (value) => {
|
|
5271
|
-
const stripped = stripHintPrefix(value, hint);
|
|
5272
|
-
return validate(stripped);
|
|
5273
|
-
} : void 0,
|
|
5274
|
-
// Format the final value to strip hint
|
|
5275
|
-
format: (value) => stripHintPrefix(value, hint)
|
|
5276
|
-
},
|
|
5277
|
-
{
|
|
5278
|
-
onCancel: () => {
|
|
5279
|
-
return false;
|
|
5280
|
-
}
|
|
5281
|
-
}
|
|
5282
|
-
);
|
|
5283
|
-
return response.value;
|
|
5284
|
-
}
|
|
5285
|
-
function stripHintPrefix(value, hint) {
|
|
5286
|
-
const prefix = hint + " ";
|
|
5287
|
-
if (value.startsWith(prefix)) {
|
|
5288
|
-
return value.slice(prefix.length);
|
|
5289
|
-
}
|
|
5290
|
-
return value;
|
|
5291
|
-
}
|
|
5292
5249
|
|
|
5293
5250
|
// src/commands/volume/init.ts
|
|
5294
5251
|
var initCommand = new Command3().name("init").description("Initialize a volume in the current directory").option("-n, --name <name>", "Volume name (required in non-interactive mode)").action(async (options) => {
|
|
@@ -5298,10 +5255,10 @@ var initCommand = new Command3().name("init").description("Initialize a volume i
|
|
|
5298
5255
|
const existingConfig = await readStorageConfig(cwd);
|
|
5299
5256
|
if (existingConfig) {
|
|
5300
5257
|
console.log(
|
|
5301
|
-
|
|
5258
|
+
chalk6.yellow(`Volume already initialized: ${existingConfig.name}`)
|
|
5302
5259
|
);
|
|
5303
5260
|
console.log(
|
|
5304
|
-
|
|
5261
|
+
chalk6.dim(`Config file: ${path7.join(cwd, ".vm0", "storage.yaml")}`)
|
|
5305
5262
|
);
|
|
5306
5263
|
return;
|
|
5307
5264
|
}
|
|
@@ -5310,10 +5267,10 @@ var initCommand = new Command3().name("init").description("Initialize a volume i
|
|
|
5310
5267
|
volumeName = options.name;
|
|
5311
5268
|
} else if (!isInteractive()) {
|
|
5312
5269
|
console.error(
|
|
5313
|
-
|
|
5270
|
+
chalk6.red("\u2717 --name flag is required in non-interactive mode")
|
|
5314
5271
|
);
|
|
5315
5272
|
console.error(
|
|
5316
|
-
|
|
5273
|
+
chalk6.dim(" Usage: vm0 volume init --name <volume-name>")
|
|
5317
5274
|
);
|
|
5318
5275
|
process.exit(1);
|
|
5319
5276
|
} else {
|
|
@@ -5329,34 +5286,34 @@ var initCommand = new Command3().name("init").description("Initialize a volume i
|
|
|
5329
5286
|
}
|
|
5330
5287
|
);
|
|
5331
5288
|
if (name === void 0) {
|
|
5332
|
-
console.log(
|
|
5289
|
+
console.log(chalk6.dim("Cancelled"));
|
|
5333
5290
|
return;
|
|
5334
5291
|
}
|
|
5335
5292
|
volumeName = name;
|
|
5336
5293
|
}
|
|
5337
5294
|
if (!isValidStorageName(volumeName)) {
|
|
5338
|
-
console.error(
|
|
5295
|
+
console.error(chalk6.red(`\u2717 Invalid volume name: "${volumeName}"`));
|
|
5339
5296
|
console.error(
|
|
5340
|
-
|
|
5297
|
+
chalk6.dim(
|
|
5341
5298
|
" Volume names must be 3-64 characters, lowercase alphanumeric with hyphens"
|
|
5342
5299
|
)
|
|
5343
5300
|
);
|
|
5344
5301
|
console.error(
|
|
5345
|
-
|
|
5302
|
+
chalk6.dim(" Example: my-dataset, user-data-v2, training-set-2024")
|
|
5346
5303
|
);
|
|
5347
5304
|
process.exit(1);
|
|
5348
5305
|
}
|
|
5349
5306
|
await writeStorageConfig(volumeName, cwd);
|
|
5350
|
-
console.log(
|
|
5307
|
+
console.log(chalk6.green(`\u2713 Initialized volume: ${volumeName}`));
|
|
5351
5308
|
console.log(
|
|
5352
|
-
|
|
5309
|
+
chalk6.dim(
|
|
5353
5310
|
`\u2713 Config saved to ${path7.join(cwd, ".vm0", "storage.yaml")}`
|
|
5354
5311
|
)
|
|
5355
5312
|
);
|
|
5356
5313
|
} catch (error) {
|
|
5357
|
-
console.error(
|
|
5314
|
+
console.error(chalk6.red("\u2717 Failed to initialize volume"));
|
|
5358
5315
|
if (error instanceof Error) {
|
|
5359
|
-
console.error(
|
|
5316
|
+
console.error(chalk6.dim(` ${error.message}`));
|
|
5360
5317
|
}
|
|
5361
5318
|
process.exit(1);
|
|
5362
5319
|
}
|
|
@@ -5364,7 +5321,7 @@ var initCommand = new Command3().name("init").description("Initialize a volume i
|
|
|
5364
5321
|
|
|
5365
5322
|
// src/commands/volume/push.ts
|
|
5366
5323
|
import { Command as Command4 } from "commander";
|
|
5367
|
-
import
|
|
5324
|
+
import chalk7 from "chalk";
|
|
5368
5325
|
function formatBytes2(bytes) {
|
|
5369
5326
|
if (bytes === 0) return "0 B";
|
|
5370
5327
|
const k = 1024;
|
|
@@ -5380,35 +5337,35 @@ var pushCommand = new Command4().name("push").description("Push local files to c
|
|
|
5380
5337
|
const cwd = process.cwd();
|
|
5381
5338
|
const config = await readStorageConfig(cwd);
|
|
5382
5339
|
if (!config) {
|
|
5383
|
-
console.error(
|
|
5384
|
-
console.error(
|
|
5340
|
+
console.error(chalk7.red("\u2717 No volume initialized in this directory"));
|
|
5341
|
+
console.error(chalk7.dim(" Run: vm0 volume init"));
|
|
5385
5342
|
process.exit(1);
|
|
5386
5343
|
}
|
|
5387
5344
|
console.log(`Pushing volume: ${config.name}`);
|
|
5388
5345
|
const result = await directUpload(config.name, "volume", cwd, {
|
|
5389
5346
|
onProgress: (message) => {
|
|
5390
|
-
console.log(
|
|
5347
|
+
console.log(chalk7.dim(message));
|
|
5391
5348
|
},
|
|
5392
5349
|
force: options.force
|
|
5393
5350
|
});
|
|
5394
5351
|
const shortVersion = result.versionId.slice(0, 8);
|
|
5395
5352
|
if (result.empty) {
|
|
5396
|
-
console.log(
|
|
5353
|
+
console.log(chalk7.yellow("No files found (empty volume)"));
|
|
5397
5354
|
} else if (result.deduplicated) {
|
|
5398
|
-
console.log(
|
|
5355
|
+
console.log(chalk7.green("\u2713 Content unchanged (deduplicated)"));
|
|
5399
5356
|
} else {
|
|
5400
|
-
console.log(
|
|
5357
|
+
console.log(chalk7.green("\u2713 Upload complete"));
|
|
5401
5358
|
}
|
|
5402
|
-
console.log(
|
|
5403
|
-
console.log(
|
|
5404
|
-
console.log(
|
|
5359
|
+
console.log(chalk7.dim(` Version: ${shortVersion}`));
|
|
5360
|
+
console.log(chalk7.dim(` Files: ${result.fileCount.toLocaleString()}`));
|
|
5361
|
+
console.log(chalk7.dim(` Size: ${formatBytes2(result.size)}`));
|
|
5405
5362
|
} catch (error) {
|
|
5406
|
-
console.error(
|
|
5363
|
+
console.error(chalk7.red("\u2717 Push failed"));
|
|
5407
5364
|
if (error instanceof Error) {
|
|
5408
5365
|
if (error.message.includes("Not authenticated")) {
|
|
5409
|
-
console.error(
|
|
5366
|
+
console.error(chalk7.dim(" Run: vm0 auth login"));
|
|
5410
5367
|
} else {
|
|
5411
|
-
console.error(
|
|
5368
|
+
console.error(chalk7.dim(` ${error.message}`));
|
|
5412
5369
|
}
|
|
5413
5370
|
}
|
|
5414
5371
|
process.exit(1);
|
|
@@ -5417,21 +5374,21 @@ var pushCommand = new Command4().name("push").description("Push local files to c
|
|
|
5417
5374
|
|
|
5418
5375
|
// src/commands/volume/pull.ts
|
|
5419
5376
|
import { Command as Command5 } from "commander";
|
|
5420
|
-
import
|
|
5377
|
+
import chalk9 from "chalk";
|
|
5421
5378
|
import path8 from "path";
|
|
5422
5379
|
import * as fs6 from "fs";
|
|
5423
5380
|
import * as os4 from "os";
|
|
5424
5381
|
import * as tar3 from "tar";
|
|
5425
5382
|
|
|
5426
5383
|
// src/lib/storage/pull-utils.ts
|
|
5427
|
-
import
|
|
5384
|
+
import chalk8 from "chalk";
|
|
5428
5385
|
async function handleEmptyStorageResponse(cwd) {
|
|
5429
|
-
console.log(
|
|
5386
|
+
console.log(chalk8.dim("Syncing local files..."));
|
|
5430
5387
|
const removedCount = await removeExtraFiles(cwd, /* @__PURE__ */ new Set());
|
|
5431
5388
|
if (removedCount > 0) {
|
|
5432
|
-
console.log(
|
|
5389
|
+
console.log(chalk8.green(`\u2713 Removed ${removedCount} files not in remote`));
|
|
5433
5390
|
}
|
|
5434
|
-
console.log(
|
|
5391
|
+
console.log(chalk8.green("\u2713 Synced (0 files)"));
|
|
5435
5392
|
return { removedCount };
|
|
5436
5393
|
}
|
|
5437
5394
|
|
|
@@ -5448,8 +5405,8 @@ var pullCommand = new Command5().name("pull").description("Pull cloud files to l
|
|
|
5448
5405
|
const cwd = process.cwd();
|
|
5449
5406
|
const config = await readStorageConfig(cwd);
|
|
5450
5407
|
if (!config) {
|
|
5451
|
-
console.error(
|
|
5452
|
-
console.error(
|
|
5408
|
+
console.error(chalk9.red("\u2717 No volume initialized in this directory"));
|
|
5409
|
+
console.error(chalk9.dim(" Run: vm0 volume init"));
|
|
5453
5410
|
process.exit(1);
|
|
5454
5411
|
}
|
|
5455
5412
|
if (versionId) {
|
|
@@ -5457,7 +5414,7 @@ var pullCommand = new Command5().name("pull").description("Pull cloud files to l
|
|
|
5457
5414
|
} else {
|
|
5458
5415
|
console.log(`Pulling volume: ${config.name}`);
|
|
5459
5416
|
}
|
|
5460
|
-
console.log(
|
|
5417
|
+
console.log(chalk9.dim("Getting download URL..."));
|
|
5461
5418
|
let url = `/api/storages/download?name=${encodeURIComponent(config.name)}&type=volume`;
|
|
5462
5419
|
if (versionId) {
|
|
5463
5420
|
const quotedVersion = JSON.stringify(versionId);
|
|
@@ -5466,14 +5423,14 @@ var pullCommand = new Command5().name("pull").description("Pull cloud files to l
|
|
|
5466
5423
|
const response = await apiClient.get(url);
|
|
5467
5424
|
if (!response.ok) {
|
|
5468
5425
|
if (response.status === 404) {
|
|
5469
|
-
console.error(
|
|
5426
|
+
console.error(chalk9.red(`\u2717 Volume "${config.name}" not found`));
|
|
5470
5427
|
console.error(
|
|
5471
|
-
|
|
5428
|
+
chalk9.dim(
|
|
5472
5429
|
" Make sure the volume name is correct in .vm0/storage.yaml"
|
|
5473
5430
|
)
|
|
5474
5431
|
);
|
|
5475
5432
|
console.error(
|
|
5476
|
-
|
|
5433
|
+
chalk9.dim(" Or push the volume first with: vm0 volume push")
|
|
5477
5434
|
);
|
|
5478
5435
|
} else {
|
|
5479
5436
|
const error = await response.json();
|
|
@@ -5489,18 +5446,18 @@ var pullCommand = new Command5().name("pull").description("Pull cloud files to l
|
|
|
5489
5446
|
if (!downloadInfo.url) {
|
|
5490
5447
|
throw new Error("No download URL returned");
|
|
5491
5448
|
}
|
|
5492
|
-
console.log(
|
|
5449
|
+
console.log(chalk9.dim("Downloading from S3..."));
|
|
5493
5450
|
const s3Response = await fetch(downloadInfo.url);
|
|
5494
5451
|
if (!s3Response.ok) {
|
|
5495
5452
|
throw new Error(`S3 download failed: ${s3Response.status}`);
|
|
5496
5453
|
}
|
|
5497
5454
|
const arrayBuffer = await s3Response.arrayBuffer();
|
|
5498
5455
|
const tarBuffer = Buffer.from(arrayBuffer);
|
|
5499
|
-
console.log(
|
|
5456
|
+
console.log(chalk9.green(`\u2713 Downloaded ${formatBytes3(tarBuffer.length)}`));
|
|
5500
5457
|
const tmpDir = fs6.mkdtempSync(path8.join(os4.tmpdir(), "vm0-"));
|
|
5501
5458
|
const tarPath = path8.join(tmpDir, "volume.tar.gz");
|
|
5502
5459
|
await fs6.promises.writeFile(tarPath, tarBuffer);
|
|
5503
|
-
console.log(
|
|
5460
|
+
console.log(chalk9.dim("Syncing local files..."));
|
|
5504
5461
|
const remoteFiles = await listTarFiles(tarPath);
|
|
5505
5462
|
const remoteFilesSet = new Set(
|
|
5506
5463
|
remoteFiles.map((f) => f.replace(/\\/g, "/"))
|
|
@@ -5508,10 +5465,10 @@ var pullCommand = new Command5().name("pull").description("Pull cloud files to l
|
|
|
5508
5465
|
const removedCount = await removeExtraFiles(cwd, remoteFilesSet);
|
|
5509
5466
|
if (removedCount > 0) {
|
|
5510
5467
|
console.log(
|
|
5511
|
-
|
|
5468
|
+
chalk9.green(`\u2713 Removed ${removedCount} files not in remote`)
|
|
5512
5469
|
);
|
|
5513
5470
|
}
|
|
5514
|
-
console.log(
|
|
5471
|
+
console.log(chalk9.dim("Extracting files..."));
|
|
5515
5472
|
await tar3.extract({
|
|
5516
5473
|
file: tarPath,
|
|
5517
5474
|
cwd,
|
|
@@ -5519,14 +5476,14 @@ var pullCommand = new Command5().name("pull").description("Pull cloud files to l
|
|
|
5519
5476
|
});
|
|
5520
5477
|
await fs6.promises.unlink(tarPath);
|
|
5521
5478
|
await fs6.promises.rmdir(tmpDir);
|
|
5522
|
-
console.log(
|
|
5479
|
+
console.log(chalk9.green(`\u2713 Extracted ${remoteFiles.length} files`));
|
|
5523
5480
|
} catch (error) {
|
|
5524
|
-
console.error(
|
|
5481
|
+
console.error(chalk9.red("\u2717 Pull failed"));
|
|
5525
5482
|
if (error instanceof Error) {
|
|
5526
5483
|
if (error.message.includes("Not authenticated")) {
|
|
5527
|
-
console.error(
|
|
5484
|
+
console.error(chalk9.dim(" Run: vm0 auth login"));
|
|
5528
5485
|
} else {
|
|
5529
|
-
console.error(
|
|
5486
|
+
console.error(chalk9.dim(` ${error.message}`));
|
|
5530
5487
|
}
|
|
5531
5488
|
}
|
|
5532
5489
|
process.exit(1);
|
|
@@ -5535,7 +5492,7 @@ var pullCommand = new Command5().name("pull").description("Pull cloud files to l
|
|
|
5535
5492
|
|
|
5536
5493
|
// src/commands/volume/status.ts
|
|
5537
5494
|
import { Command as Command6 } from "commander";
|
|
5538
|
-
import
|
|
5495
|
+
import chalk10 from "chalk";
|
|
5539
5496
|
function formatBytes4(bytes) {
|
|
5540
5497
|
if (bytes === 0) return "0 B";
|
|
5541
5498
|
const k = 1024;
|
|
@@ -5548,17 +5505,17 @@ var statusCommand = new Command6().name("status").description("Show status of cl
|
|
|
5548
5505
|
const cwd = process.cwd();
|
|
5549
5506
|
const config = await readStorageConfig(cwd);
|
|
5550
5507
|
if (!config) {
|
|
5551
|
-
console.error(
|
|
5552
|
-
console.error(
|
|
5508
|
+
console.error(chalk10.red("\u2717 No volume initialized in this directory"));
|
|
5509
|
+
console.error(chalk10.dim(" Run: vm0 volume init"));
|
|
5553
5510
|
process.exit(1);
|
|
5554
5511
|
}
|
|
5555
5512
|
if (config.type !== "volume") {
|
|
5556
5513
|
console.error(
|
|
5557
|
-
|
|
5514
|
+
chalk10.red(
|
|
5558
5515
|
"\u2717 This directory is initialized as an artifact, not a volume"
|
|
5559
5516
|
)
|
|
5560
5517
|
);
|
|
5561
|
-
console.error(
|
|
5518
|
+
console.error(chalk10.dim(" Use: vm0 artifact status"));
|
|
5562
5519
|
process.exit(1);
|
|
5563
5520
|
}
|
|
5564
5521
|
console.log(`Checking volume: ${config.name}`);
|
|
@@ -5566,8 +5523,8 @@ var statusCommand = new Command6().name("status").description("Show status of cl
|
|
|
5566
5523
|
const response = await apiClient.get(url);
|
|
5567
5524
|
if (!response.ok) {
|
|
5568
5525
|
if (response.status === 404) {
|
|
5569
|
-
console.error(
|
|
5570
|
-
console.error(
|
|
5526
|
+
console.error(chalk10.red("\u2717 Not found on remote"));
|
|
5527
|
+
console.error(chalk10.dim(" Run: vm0 volume push"));
|
|
5571
5528
|
} else {
|
|
5572
5529
|
const error = await response.json();
|
|
5573
5530
|
throw new Error(error.error?.message || "Status check failed");
|
|
@@ -5577,21 +5534,21 @@ var statusCommand = new Command6().name("status").description("Show status of cl
|
|
|
5577
5534
|
const info = await response.json();
|
|
5578
5535
|
const shortVersion = info.versionId.slice(0, 8);
|
|
5579
5536
|
if (info.empty) {
|
|
5580
|
-
console.log(
|
|
5581
|
-
console.log(
|
|
5537
|
+
console.log(chalk10.green("\u2713 Found (empty)"));
|
|
5538
|
+
console.log(chalk10.dim(` Version: ${shortVersion}`));
|
|
5582
5539
|
} else {
|
|
5583
|
-
console.log(
|
|
5584
|
-
console.log(
|
|
5585
|
-
console.log(
|
|
5586
|
-
console.log(
|
|
5540
|
+
console.log(chalk10.green("\u2713 Found"));
|
|
5541
|
+
console.log(chalk10.dim(` Version: ${shortVersion}`));
|
|
5542
|
+
console.log(chalk10.dim(` Files: ${info.fileCount.toLocaleString()}`));
|
|
5543
|
+
console.log(chalk10.dim(` Size: ${formatBytes4(info.size)}`));
|
|
5587
5544
|
}
|
|
5588
5545
|
} catch (error) {
|
|
5589
|
-
console.error(
|
|
5546
|
+
console.error(chalk10.red("\u2717 Status check failed"));
|
|
5590
5547
|
if (error instanceof Error) {
|
|
5591
5548
|
if (error.message.includes("Not authenticated")) {
|
|
5592
|
-
console.error(
|
|
5549
|
+
console.error(chalk10.dim(" Run: vm0 auth login"));
|
|
5593
5550
|
} else {
|
|
5594
|
-
console.error(
|
|
5551
|
+
console.error(chalk10.dim(` ${error.message}`));
|
|
5595
5552
|
}
|
|
5596
5553
|
}
|
|
5597
5554
|
process.exit(1);
|
|
@@ -5600,7 +5557,7 @@ var statusCommand = new Command6().name("status").description("Show status of cl
|
|
|
5600
5557
|
|
|
5601
5558
|
// src/commands/volume/list.ts
|
|
5602
5559
|
import { Command as Command7 } from "commander";
|
|
5603
|
-
import
|
|
5560
|
+
import chalk11 from "chalk";
|
|
5604
5561
|
var listCommand = new Command7().name("list").alias("ls").description("List all remote volumes").action(async () => {
|
|
5605
5562
|
try {
|
|
5606
5563
|
const url = "/api/storages/list?type=volume";
|
|
@@ -5611,9 +5568,9 @@ var listCommand = new Command7().name("list").alias("ls").description("List all
|
|
|
5611
5568
|
}
|
|
5612
5569
|
const items = await response.json();
|
|
5613
5570
|
if (items.length === 0) {
|
|
5614
|
-
console.log(
|
|
5571
|
+
console.log(chalk11.dim("No volumes found"));
|
|
5615
5572
|
console.log(
|
|
5616
|
-
|
|
5573
|
+
chalk11.dim(" Create one with: vm0 volume init && vm0 volume push")
|
|
5617
5574
|
);
|
|
5618
5575
|
return;
|
|
5619
5576
|
}
|
|
@@ -5632,7 +5589,7 @@ var listCommand = new Command7().name("list").alias("ls").description("List all
|
|
|
5632
5589
|
"FILES".padStart(filesWidth),
|
|
5633
5590
|
"UPDATED"
|
|
5634
5591
|
].join(" ");
|
|
5635
|
-
console.log(
|
|
5592
|
+
console.log(chalk11.dim(header));
|
|
5636
5593
|
for (const item of items) {
|
|
5637
5594
|
const row = [
|
|
5638
5595
|
item.name.padEnd(nameWidth),
|
|
@@ -5643,12 +5600,12 @@ var listCommand = new Command7().name("list").alias("ls").description("List all
|
|
|
5643
5600
|
console.log(row);
|
|
5644
5601
|
}
|
|
5645
5602
|
} catch (error) {
|
|
5646
|
-
console.error(
|
|
5603
|
+
console.error(chalk11.red("\u2717 Failed to list volumes"));
|
|
5647
5604
|
if (error instanceof Error) {
|
|
5648
5605
|
if (error.message.includes("Not authenticated")) {
|
|
5649
|
-
console.error(
|
|
5606
|
+
console.error(chalk11.dim(" Run: vm0 auth login"));
|
|
5650
5607
|
} else {
|
|
5651
|
-
console.error(
|
|
5608
|
+
console.error(chalk11.dim(` ${error.message}`));
|
|
5652
5609
|
}
|
|
5653
5610
|
}
|
|
5654
5611
|
process.exit(1);
|
|
@@ -5657,10 +5614,10 @@ var listCommand = new Command7().name("list").alias("ls").description("List all
|
|
|
5657
5614
|
|
|
5658
5615
|
// src/commands/volume/clone.ts
|
|
5659
5616
|
import { Command as Command8 } from "commander";
|
|
5660
|
-
import
|
|
5617
|
+
import chalk13 from "chalk";
|
|
5661
5618
|
|
|
5662
5619
|
// src/lib/storage/clone-utils.ts
|
|
5663
|
-
import
|
|
5620
|
+
import chalk12 from "chalk";
|
|
5664
5621
|
import path9 from "path";
|
|
5665
5622
|
import * as fs7 from "fs";
|
|
5666
5623
|
import * as os5 from "os";
|
|
@@ -5670,7 +5627,7 @@ async function cloneStorage(name, type, destination, options = {}) {
|
|
|
5670
5627
|
if (fs7.existsSync(destination)) {
|
|
5671
5628
|
throw new Error(`Directory "${destination}" already exists`);
|
|
5672
5629
|
}
|
|
5673
|
-
console.log(
|
|
5630
|
+
console.log(chalk12.dim(`Checking remote ${typeLabel}...`));
|
|
5674
5631
|
let url = `/api/storages/download?name=${encodeURIComponent(name)}&type=${type}`;
|
|
5675
5632
|
if (options.version) {
|
|
5676
5633
|
const quotedVersion = JSON.stringify(options.version);
|
|
@@ -5687,12 +5644,12 @@ async function cloneStorage(name, type, destination, options = {}) {
|
|
|
5687
5644
|
throw new Error(error.error?.message || "Clone failed");
|
|
5688
5645
|
}
|
|
5689
5646
|
const downloadInfo = await response.json();
|
|
5690
|
-
console.log(
|
|
5647
|
+
console.log(chalk12.dim(`Creating directory: ${destination}/`));
|
|
5691
5648
|
await fs7.promises.mkdir(destination, { recursive: true });
|
|
5692
5649
|
if (downloadInfo.empty) {
|
|
5693
5650
|
await writeStorageConfig(name, destination, type);
|
|
5694
|
-
console.log(
|
|
5695
|
-
console.log(
|
|
5651
|
+
console.log(chalk12.green(`\u2713 Cloned empty ${typeLabel}: ${name}`));
|
|
5652
|
+
console.log(chalk12.dim(`\u2713 Initialized .vm0/storage.yaml`));
|
|
5696
5653
|
return {
|
|
5697
5654
|
success: true,
|
|
5698
5655
|
fileCount: 0,
|
|
@@ -5703,7 +5660,7 @@ async function cloneStorage(name, type, destination, options = {}) {
|
|
|
5703
5660
|
if (!downloadInfo.url) {
|
|
5704
5661
|
throw new Error("No download URL returned");
|
|
5705
5662
|
}
|
|
5706
|
-
console.log(
|
|
5663
|
+
console.log(chalk12.dim("Downloading from S3..."));
|
|
5707
5664
|
const s3Response = await fetch(downloadInfo.url);
|
|
5708
5665
|
if (!s3Response.ok) {
|
|
5709
5666
|
await fs7.promises.rm(destination, { recursive: true, force: true });
|
|
@@ -5711,12 +5668,12 @@ async function cloneStorage(name, type, destination, options = {}) {
|
|
|
5711
5668
|
}
|
|
5712
5669
|
const arrayBuffer = await s3Response.arrayBuffer();
|
|
5713
5670
|
const tarBuffer = Buffer.from(arrayBuffer);
|
|
5714
|
-
console.log(
|
|
5671
|
+
console.log(chalk12.green(`\u2713 Downloaded ${formatBytes(tarBuffer.length)}`));
|
|
5715
5672
|
const tmpDir = fs7.mkdtempSync(path9.join(os5.tmpdir(), "vm0-clone-"));
|
|
5716
5673
|
const tarPath = path9.join(tmpDir, "archive.tar.gz");
|
|
5717
5674
|
await fs7.promises.writeFile(tarPath, tarBuffer);
|
|
5718
5675
|
const files = await listTarFiles(tarPath);
|
|
5719
|
-
console.log(
|
|
5676
|
+
console.log(chalk12.dim("Extracting files..."));
|
|
5720
5677
|
await tar4.extract({
|
|
5721
5678
|
file: tarPath,
|
|
5722
5679
|
cwd: destination,
|
|
@@ -5724,9 +5681,9 @@ async function cloneStorage(name, type, destination, options = {}) {
|
|
|
5724
5681
|
});
|
|
5725
5682
|
await fs7.promises.unlink(tarPath);
|
|
5726
5683
|
await fs7.promises.rmdir(tmpDir);
|
|
5727
|
-
console.log(
|
|
5684
|
+
console.log(chalk12.green(`\u2713 Extracted ${files.length} files`));
|
|
5728
5685
|
await writeStorageConfig(name, destination, type);
|
|
5729
|
-
console.log(
|
|
5686
|
+
console.log(chalk12.green(`\u2713 Initialized .vm0/storage.yaml`));
|
|
5730
5687
|
return {
|
|
5731
5688
|
success: true,
|
|
5732
5689
|
fileCount: downloadInfo.fileCount,
|
|
@@ -5741,17 +5698,17 @@ var cloneCommand = new Command8().name("clone").description("Clone a remote volu
|
|
|
5741
5698
|
const targetDir = destination || name;
|
|
5742
5699
|
console.log(`Cloning volume: ${name}`);
|
|
5743
5700
|
const result = await cloneStorage(name, "volume", targetDir);
|
|
5744
|
-
console.log(
|
|
5701
|
+
console.log(chalk13.green(`
|
|
5745
5702
|
\u2713 Successfully cloned volume: ${name}`));
|
|
5746
|
-
console.log(
|
|
5747
|
-
console.log(
|
|
5703
|
+
console.log(chalk13.dim(` Location: ${targetDir}/`));
|
|
5704
|
+
console.log(chalk13.dim(` Version: ${result.versionId.slice(0, 8)}`));
|
|
5748
5705
|
} catch (error) {
|
|
5749
|
-
console.error(
|
|
5706
|
+
console.error(chalk13.red("\u2717 Clone failed"));
|
|
5750
5707
|
if (error instanceof Error) {
|
|
5751
5708
|
if (error.message.includes("Not authenticated")) {
|
|
5752
|
-
console.error(
|
|
5709
|
+
console.error(chalk13.dim(" Run: vm0 auth login"));
|
|
5753
5710
|
} else {
|
|
5754
|
-
console.error(
|
|
5711
|
+
console.error(chalk13.dim(` ${error.message}`));
|
|
5755
5712
|
}
|
|
5756
5713
|
}
|
|
5757
5714
|
process.exit(1);
|
|
@@ -5766,7 +5723,7 @@ import { Command as Command16 } from "commander";
|
|
|
5766
5723
|
|
|
5767
5724
|
// src/commands/artifact/init.ts
|
|
5768
5725
|
import { Command as Command10 } from "commander";
|
|
5769
|
-
import
|
|
5726
|
+
import chalk14 from "chalk";
|
|
5770
5727
|
import path10 from "path";
|
|
5771
5728
|
var initCommand2 = new Command10().name("init").description("Initialize an artifact in the current directory").option(
|
|
5772
5729
|
"-n, --name <name>",
|
|
@@ -5779,24 +5736,24 @@ var initCommand2 = new Command10().name("init").description("Initialize an artif
|
|
|
5779
5736
|
if (existingConfig) {
|
|
5780
5737
|
if (existingConfig.type === "artifact") {
|
|
5781
5738
|
console.log(
|
|
5782
|
-
|
|
5739
|
+
chalk14.yellow(
|
|
5783
5740
|
`Artifact already initialized: ${existingConfig.name}`
|
|
5784
5741
|
)
|
|
5785
5742
|
);
|
|
5786
5743
|
} else {
|
|
5787
5744
|
console.log(
|
|
5788
|
-
|
|
5745
|
+
chalk14.yellow(
|
|
5789
5746
|
`Directory already initialized as volume: ${existingConfig.name}`
|
|
5790
5747
|
)
|
|
5791
5748
|
);
|
|
5792
5749
|
console.log(
|
|
5793
|
-
|
|
5750
|
+
chalk14.dim(
|
|
5794
5751
|
" To change type, delete .vm0/storage.yaml and reinitialize"
|
|
5795
5752
|
)
|
|
5796
5753
|
);
|
|
5797
5754
|
}
|
|
5798
5755
|
console.log(
|
|
5799
|
-
|
|
5756
|
+
chalk14.dim(`Config file: ${path10.join(cwd, ".vm0", "storage.yaml")}`)
|
|
5800
5757
|
);
|
|
5801
5758
|
return;
|
|
5802
5759
|
}
|
|
@@ -5805,10 +5762,10 @@ var initCommand2 = new Command10().name("init").description("Initialize an artif
|
|
|
5805
5762
|
artifactName = options.name;
|
|
5806
5763
|
} else if (!isInteractive()) {
|
|
5807
5764
|
console.error(
|
|
5808
|
-
|
|
5765
|
+
chalk14.red("\u2717 --name flag is required in non-interactive mode")
|
|
5809
5766
|
);
|
|
5810
5767
|
console.error(
|
|
5811
|
-
|
|
5768
|
+
chalk14.dim(" Usage: vm0 artifact init --name <artifact-name>")
|
|
5812
5769
|
);
|
|
5813
5770
|
process.exit(1);
|
|
5814
5771
|
} else {
|
|
@@ -5824,34 +5781,34 @@ var initCommand2 = new Command10().name("init").description("Initialize an artif
|
|
|
5824
5781
|
}
|
|
5825
5782
|
);
|
|
5826
5783
|
if (name === void 0) {
|
|
5827
|
-
console.log(
|
|
5784
|
+
console.log(chalk14.dim("Cancelled"));
|
|
5828
5785
|
return;
|
|
5829
5786
|
}
|
|
5830
5787
|
artifactName = name;
|
|
5831
5788
|
}
|
|
5832
5789
|
if (!isValidStorageName(artifactName)) {
|
|
5833
|
-
console.error(
|
|
5790
|
+
console.error(chalk14.red(`\u2717 Invalid artifact name: "${artifactName}"`));
|
|
5834
5791
|
console.error(
|
|
5835
|
-
|
|
5792
|
+
chalk14.dim(
|
|
5836
5793
|
" Artifact names must be 3-64 characters, lowercase alphanumeric with hyphens"
|
|
5837
5794
|
)
|
|
5838
5795
|
);
|
|
5839
5796
|
console.error(
|
|
5840
|
-
|
|
5797
|
+
chalk14.dim(" Example: my-project, user-workspace, code-artifact")
|
|
5841
5798
|
);
|
|
5842
5799
|
process.exit(1);
|
|
5843
5800
|
}
|
|
5844
5801
|
await writeStorageConfig(artifactName, cwd, "artifact");
|
|
5845
|
-
console.log(
|
|
5802
|
+
console.log(chalk14.green(`\u2713 Initialized artifact: ${artifactName}`));
|
|
5846
5803
|
console.log(
|
|
5847
|
-
|
|
5804
|
+
chalk14.dim(
|
|
5848
5805
|
`\u2713 Config saved to ${path10.join(cwd, ".vm0", "storage.yaml")}`
|
|
5849
5806
|
)
|
|
5850
5807
|
);
|
|
5851
5808
|
} catch (error) {
|
|
5852
|
-
console.error(
|
|
5809
|
+
console.error(chalk14.red("\u2717 Failed to initialize artifact"));
|
|
5853
5810
|
if (error instanceof Error) {
|
|
5854
|
-
console.error(
|
|
5811
|
+
console.error(chalk14.dim(` ${error.message}`));
|
|
5855
5812
|
}
|
|
5856
5813
|
process.exit(1);
|
|
5857
5814
|
}
|
|
@@ -5859,7 +5816,7 @@ var initCommand2 = new Command10().name("init").description("Initialize an artif
|
|
|
5859
5816
|
|
|
5860
5817
|
// src/commands/artifact/push.ts
|
|
5861
5818
|
import { Command as Command11 } from "commander";
|
|
5862
|
-
import
|
|
5819
|
+
import chalk15 from "chalk";
|
|
5863
5820
|
function formatBytes5(bytes) {
|
|
5864
5821
|
if (bytes === 0) return "0 B";
|
|
5865
5822
|
const k = 1024;
|
|
@@ -5875,41 +5832,41 @@ var pushCommand2 = new Command11().name("push").description("Push local files to
|
|
|
5875
5832
|
const cwd = process.cwd();
|
|
5876
5833
|
const config = await readStorageConfig(cwd);
|
|
5877
5834
|
if (!config) {
|
|
5878
|
-
console.error(
|
|
5879
|
-
console.error(
|
|
5835
|
+
console.error(chalk15.red("\u2717 No artifact initialized in this directory"));
|
|
5836
|
+
console.error(chalk15.dim(" Run: vm0 artifact init"));
|
|
5880
5837
|
process.exit(1);
|
|
5881
5838
|
}
|
|
5882
5839
|
if (config.type !== "artifact") {
|
|
5883
5840
|
console.error(
|
|
5884
|
-
|
|
5841
|
+
chalk15.red(
|
|
5885
5842
|
`\u2717 This directory is initialized as a volume, not an artifact`
|
|
5886
5843
|
)
|
|
5887
5844
|
);
|
|
5888
|
-
console.error(
|
|
5845
|
+
console.error(chalk15.dim(" Use: vm0 volume push"));
|
|
5889
5846
|
process.exit(1);
|
|
5890
5847
|
}
|
|
5891
5848
|
console.log(`Pushing artifact: ${config.name}`);
|
|
5892
5849
|
const result = await directUpload(config.name, "artifact", cwd, {
|
|
5893
5850
|
onProgress: (message) => {
|
|
5894
|
-
console.log(
|
|
5851
|
+
console.log(chalk15.dim(message));
|
|
5895
5852
|
},
|
|
5896
5853
|
force: options.force
|
|
5897
5854
|
});
|
|
5898
5855
|
const shortVersion = result.versionId.slice(0, 8);
|
|
5899
5856
|
if (result.empty) {
|
|
5900
|
-
console.log(
|
|
5857
|
+
console.log(chalk15.yellow("No files found (empty artifact)"));
|
|
5901
5858
|
} else if (result.deduplicated) {
|
|
5902
|
-
console.log(
|
|
5859
|
+
console.log(chalk15.green("\u2713 Content unchanged (deduplicated)"));
|
|
5903
5860
|
} else {
|
|
5904
|
-
console.log(
|
|
5861
|
+
console.log(chalk15.green("\u2713 Upload complete"));
|
|
5905
5862
|
}
|
|
5906
|
-
console.log(
|
|
5907
|
-
console.log(
|
|
5908
|
-
console.log(
|
|
5863
|
+
console.log(chalk15.dim(` Version: ${shortVersion}`));
|
|
5864
|
+
console.log(chalk15.dim(` Files: ${result.fileCount.toLocaleString()}`));
|
|
5865
|
+
console.log(chalk15.dim(` Size: ${formatBytes5(result.size)}`));
|
|
5909
5866
|
} catch (error) {
|
|
5910
|
-
console.error(
|
|
5867
|
+
console.error(chalk15.red("\u2717 Push failed"));
|
|
5911
5868
|
if (error instanceof Error) {
|
|
5912
|
-
console.error(
|
|
5869
|
+
console.error(chalk15.dim(` ${error.message}`));
|
|
5913
5870
|
}
|
|
5914
5871
|
process.exit(1);
|
|
5915
5872
|
}
|
|
@@ -5917,7 +5874,7 @@ var pushCommand2 = new Command11().name("push").description("Push local files to
|
|
|
5917
5874
|
|
|
5918
5875
|
// src/commands/artifact/pull.ts
|
|
5919
5876
|
import { Command as Command12 } from "commander";
|
|
5920
|
-
import
|
|
5877
|
+
import chalk16 from "chalk";
|
|
5921
5878
|
import path11 from "path";
|
|
5922
5879
|
import * as fs8 from "fs";
|
|
5923
5880
|
import * as os6 from "os";
|
|
@@ -5934,17 +5891,17 @@ var pullCommand2 = new Command12().name("pull").description("Pull cloud artifact
|
|
|
5934
5891
|
const cwd = process.cwd();
|
|
5935
5892
|
const config = await readStorageConfig(cwd);
|
|
5936
5893
|
if (!config) {
|
|
5937
|
-
console.error(
|
|
5938
|
-
console.error(
|
|
5894
|
+
console.error(chalk16.red("\u2717 No artifact initialized in this directory"));
|
|
5895
|
+
console.error(chalk16.dim(" Run: vm0 artifact init"));
|
|
5939
5896
|
process.exit(1);
|
|
5940
5897
|
}
|
|
5941
5898
|
if (config.type !== "artifact") {
|
|
5942
5899
|
console.error(
|
|
5943
|
-
|
|
5900
|
+
chalk16.red(
|
|
5944
5901
|
`\u2717 This directory is initialized as a volume, not an artifact`
|
|
5945
5902
|
)
|
|
5946
5903
|
);
|
|
5947
|
-
console.error(
|
|
5904
|
+
console.error(chalk16.dim(" Use: vm0 volume pull"));
|
|
5948
5905
|
process.exit(1);
|
|
5949
5906
|
}
|
|
5950
5907
|
if (versionId) {
|
|
@@ -5952,7 +5909,7 @@ var pullCommand2 = new Command12().name("pull").description("Pull cloud artifact
|
|
|
5952
5909
|
} else {
|
|
5953
5910
|
console.log(`Pulling artifact: ${config.name}`);
|
|
5954
5911
|
}
|
|
5955
|
-
console.log(
|
|
5912
|
+
console.log(chalk16.dim("Getting download URL..."));
|
|
5956
5913
|
let url = `/api/storages/download?name=${encodeURIComponent(config.name)}&type=artifact`;
|
|
5957
5914
|
if (versionId) {
|
|
5958
5915
|
const quotedVersion = JSON.stringify(versionId);
|
|
@@ -5961,14 +5918,14 @@ var pullCommand2 = new Command12().name("pull").description("Pull cloud artifact
|
|
|
5961
5918
|
const response = await apiClient.get(url);
|
|
5962
5919
|
if (!response.ok) {
|
|
5963
5920
|
if (response.status === 404) {
|
|
5964
|
-
console.error(
|
|
5921
|
+
console.error(chalk16.red(`\u2717 Artifact "${config.name}" not found`));
|
|
5965
5922
|
console.error(
|
|
5966
|
-
|
|
5923
|
+
chalk16.dim(
|
|
5967
5924
|
" Make sure the artifact name is correct in .vm0/storage.yaml"
|
|
5968
5925
|
)
|
|
5969
5926
|
);
|
|
5970
5927
|
console.error(
|
|
5971
|
-
|
|
5928
|
+
chalk16.dim(" Or push the artifact first with: vm0 artifact push")
|
|
5972
5929
|
);
|
|
5973
5930
|
} else {
|
|
5974
5931
|
const error = await response.json();
|
|
@@ -5984,18 +5941,18 @@ var pullCommand2 = new Command12().name("pull").description("Pull cloud artifact
|
|
|
5984
5941
|
if (!downloadInfo.url) {
|
|
5985
5942
|
throw new Error("No download URL returned");
|
|
5986
5943
|
}
|
|
5987
|
-
console.log(
|
|
5944
|
+
console.log(chalk16.dim("Downloading from S3..."));
|
|
5988
5945
|
const s3Response = await fetch(downloadInfo.url);
|
|
5989
5946
|
if (!s3Response.ok) {
|
|
5990
5947
|
throw new Error(`S3 download failed: ${s3Response.status}`);
|
|
5991
5948
|
}
|
|
5992
5949
|
const arrayBuffer = await s3Response.arrayBuffer();
|
|
5993
5950
|
const tarBuffer = Buffer.from(arrayBuffer);
|
|
5994
|
-
console.log(
|
|
5951
|
+
console.log(chalk16.green(`\u2713 Downloaded ${formatBytes6(tarBuffer.length)}`));
|
|
5995
5952
|
const tmpDir = fs8.mkdtempSync(path11.join(os6.tmpdir(), "vm0-"));
|
|
5996
5953
|
const tarPath = path11.join(tmpDir, "artifact.tar.gz");
|
|
5997
5954
|
await fs8.promises.writeFile(tarPath, tarBuffer);
|
|
5998
|
-
console.log(
|
|
5955
|
+
console.log(chalk16.dim("Syncing local files..."));
|
|
5999
5956
|
const remoteFiles = await listTarFiles(tarPath);
|
|
6000
5957
|
const remoteFilesSet = new Set(
|
|
6001
5958
|
remoteFiles.map((f) => f.replace(/\\/g, "/"))
|
|
@@ -6003,10 +5960,10 @@ var pullCommand2 = new Command12().name("pull").description("Pull cloud artifact
|
|
|
6003
5960
|
const removedCount = await removeExtraFiles(cwd, remoteFilesSet);
|
|
6004
5961
|
if (removedCount > 0) {
|
|
6005
5962
|
console.log(
|
|
6006
|
-
|
|
5963
|
+
chalk16.green(`\u2713 Removed ${removedCount} files not in remote`)
|
|
6007
5964
|
);
|
|
6008
5965
|
}
|
|
6009
|
-
console.log(
|
|
5966
|
+
console.log(chalk16.dim("Extracting files..."));
|
|
6010
5967
|
await tar5.extract({
|
|
6011
5968
|
file: tarPath,
|
|
6012
5969
|
cwd,
|
|
@@ -6014,11 +5971,11 @@ var pullCommand2 = new Command12().name("pull").description("Pull cloud artifact
|
|
|
6014
5971
|
});
|
|
6015
5972
|
await fs8.promises.unlink(tarPath);
|
|
6016
5973
|
await fs8.promises.rmdir(tmpDir);
|
|
6017
|
-
console.log(
|
|
5974
|
+
console.log(chalk16.green(`\u2713 Extracted ${remoteFiles.length} files`));
|
|
6018
5975
|
} catch (error) {
|
|
6019
|
-
console.error(
|
|
5976
|
+
console.error(chalk16.red("\u2717 Pull failed"));
|
|
6020
5977
|
if (error instanceof Error) {
|
|
6021
|
-
console.error(
|
|
5978
|
+
console.error(chalk16.dim(` ${error.message}`));
|
|
6022
5979
|
}
|
|
6023
5980
|
process.exit(1);
|
|
6024
5981
|
}
|
|
@@ -6026,7 +5983,7 @@ var pullCommand2 = new Command12().name("pull").description("Pull cloud artifact
|
|
|
6026
5983
|
|
|
6027
5984
|
// src/commands/artifact/status.ts
|
|
6028
5985
|
import { Command as Command13 } from "commander";
|
|
6029
|
-
import
|
|
5986
|
+
import chalk17 from "chalk";
|
|
6030
5987
|
function formatBytes7(bytes) {
|
|
6031
5988
|
if (bytes === 0) return "0 B";
|
|
6032
5989
|
const k = 1024;
|
|
@@ -6039,17 +5996,17 @@ var statusCommand2 = new Command13().name("status").description("Show status of
|
|
|
6039
5996
|
const cwd = process.cwd();
|
|
6040
5997
|
const config = await readStorageConfig(cwd);
|
|
6041
5998
|
if (!config) {
|
|
6042
|
-
console.error(
|
|
6043
|
-
console.error(
|
|
5999
|
+
console.error(chalk17.red("\u2717 No artifact initialized in this directory"));
|
|
6000
|
+
console.error(chalk17.dim(" Run: vm0 artifact init"));
|
|
6044
6001
|
process.exit(1);
|
|
6045
6002
|
}
|
|
6046
6003
|
if (config.type !== "artifact") {
|
|
6047
6004
|
console.error(
|
|
6048
|
-
|
|
6005
|
+
chalk17.red(
|
|
6049
6006
|
"\u2717 This directory is initialized as a volume, not an artifact"
|
|
6050
6007
|
)
|
|
6051
6008
|
);
|
|
6052
|
-
console.error(
|
|
6009
|
+
console.error(chalk17.dim(" Use: vm0 volume status"));
|
|
6053
6010
|
process.exit(1);
|
|
6054
6011
|
}
|
|
6055
6012
|
console.log(`Checking artifact: ${config.name}`);
|
|
@@ -6057,8 +6014,8 @@ var statusCommand2 = new Command13().name("status").description("Show status of
|
|
|
6057
6014
|
const response = await apiClient.get(url);
|
|
6058
6015
|
if (!response.ok) {
|
|
6059
6016
|
if (response.status === 404) {
|
|
6060
|
-
console.error(
|
|
6061
|
-
console.error(
|
|
6017
|
+
console.error(chalk17.red("\u2717 Not found on remote"));
|
|
6018
|
+
console.error(chalk17.dim(" Run: vm0 artifact push"));
|
|
6062
6019
|
} else {
|
|
6063
6020
|
const error = await response.json();
|
|
6064
6021
|
throw new Error(error.error?.message || "Status check failed");
|
|
@@ -6068,18 +6025,18 @@ var statusCommand2 = new Command13().name("status").description("Show status of
|
|
|
6068
6025
|
const info = await response.json();
|
|
6069
6026
|
const shortVersion = info.versionId.slice(0, 8);
|
|
6070
6027
|
if (info.empty) {
|
|
6071
|
-
console.log(
|
|
6072
|
-
console.log(
|
|
6028
|
+
console.log(chalk17.green("\u2713 Found (empty)"));
|
|
6029
|
+
console.log(chalk17.dim(` Version: ${shortVersion}`));
|
|
6073
6030
|
} else {
|
|
6074
|
-
console.log(
|
|
6075
|
-
console.log(
|
|
6076
|
-
console.log(
|
|
6077
|
-
console.log(
|
|
6031
|
+
console.log(chalk17.green("\u2713 Found"));
|
|
6032
|
+
console.log(chalk17.dim(` Version: ${shortVersion}`));
|
|
6033
|
+
console.log(chalk17.dim(` Files: ${info.fileCount.toLocaleString()}`));
|
|
6034
|
+
console.log(chalk17.dim(` Size: ${formatBytes7(info.size)}`));
|
|
6078
6035
|
}
|
|
6079
6036
|
} catch (error) {
|
|
6080
|
-
console.error(
|
|
6037
|
+
console.error(chalk17.red("\u2717 Status check failed"));
|
|
6081
6038
|
if (error instanceof Error) {
|
|
6082
|
-
console.error(
|
|
6039
|
+
console.error(chalk17.dim(` ${error.message}`));
|
|
6083
6040
|
}
|
|
6084
6041
|
process.exit(1);
|
|
6085
6042
|
}
|
|
@@ -6087,7 +6044,7 @@ var statusCommand2 = new Command13().name("status").description("Show status of
|
|
|
6087
6044
|
|
|
6088
6045
|
// src/commands/artifact/list.ts
|
|
6089
6046
|
import { Command as Command14 } from "commander";
|
|
6090
|
-
import
|
|
6047
|
+
import chalk18 from "chalk";
|
|
6091
6048
|
var listCommand2 = new Command14().name("list").alias("ls").description("List all remote artifacts").action(async () => {
|
|
6092
6049
|
try {
|
|
6093
6050
|
const url = "/api/storages/list?type=artifact";
|
|
@@ -6098,9 +6055,9 @@ var listCommand2 = new Command14().name("list").alias("ls").description("List al
|
|
|
6098
6055
|
}
|
|
6099
6056
|
const items = await response.json();
|
|
6100
6057
|
if (items.length === 0) {
|
|
6101
|
-
console.log(
|
|
6058
|
+
console.log(chalk18.dim("No artifacts found"));
|
|
6102
6059
|
console.log(
|
|
6103
|
-
|
|
6060
|
+
chalk18.dim(
|
|
6104
6061
|
" Create one with: vm0 artifact init && vm0 artifact push"
|
|
6105
6062
|
)
|
|
6106
6063
|
);
|
|
@@ -6121,7 +6078,7 @@ var listCommand2 = new Command14().name("list").alias("ls").description("List al
|
|
|
6121
6078
|
"FILES".padStart(filesWidth),
|
|
6122
6079
|
"UPDATED"
|
|
6123
6080
|
].join(" ");
|
|
6124
|
-
console.log(
|
|
6081
|
+
console.log(chalk18.dim(header));
|
|
6125
6082
|
for (const item of items) {
|
|
6126
6083
|
const row = [
|
|
6127
6084
|
item.name.padEnd(nameWidth),
|
|
@@ -6132,12 +6089,12 @@ var listCommand2 = new Command14().name("list").alias("ls").description("List al
|
|
|
6132
6089
|
console.log(row);
|
|
6133
6090
|
}
|
|
6134
6091
|
} catch (error) {
|
|
6135
|
-
console.error(
|
|
6092
|
+
console.error(chalk18.red("\u2717 Failed to list artifacts"));
|
|
6136
6093
|
if (error instanceof Error) {
|
|
6137
6094
|
if (error.message.includes("Not authenticated")) {
|
|
6138
|
-
console.error(
|
|
6095
|
+
console.error(chalk18.dim(" Run: vm0 auth login"));
|
|
6139
6096
|
} else {
|
|
6140
|
-
console.error(
|
|
6097
|
+
console.error(chalk18.dim(` ${error.message}`));
|
|
6141
6098
|
}
|
|
6142
6099
|
}
|
|
6143
6100
|
process.exit(1);
|
|
@@ -6146,23 +6103,23 @@ var listCommand2 = new Command14().name("list").alias("ls").description("List al
|
|
|
6146
6103
|
|
|
6147
6104
|
// src/commands/artifact/clone.ts
|
|
6148
6105
|
import { Command as Command15 } from "commander";
|
|
6149
|
-
import
|
|
6106
|
+
import chalk19 from "chalk";
|
|
6150
6107
|
var cloneCommand2 = new Command15().name("clone").description("Clone a remote artifact to local directory (latest version)").argument("<name>", "Artifact name to clone").argument("[destination]", "Destination directory (default: artifact name)").action(async (name, destination) => {
|
|
6151
6108
|
try {
|
|
6152
6109
|
const targetDir = destination || name;
|
|
6153
6110
|
console.log(`Cloning artifact: ${name}`);
|
|
6154
6111
|
const result = await cloneStorage(name, "artifact", targetDir);
|
|
6155
|
-
console.log(
|
|
6112
|
+
console.log(chalk19.green(`
|
|
6156
6113
|
\u2713 Successfully cloned artifact: ${name}`));
|
|
6157
|
-
console.log(
|
|
6158
|
-
console.log(
|
|
6114
|
+
console.log(chalk19.dim(` Location: ${targetDir}/`));
|
|
6115
|
+
console.log(chalk19.dim(` Version: ${result.versionId.slice(0, 8)}`));
|
|
6159
6116
|
} catch (error) {
|
|
6160
|
-
console.error(
|
|
6117
|
+
console.error(chalk19.red("\u2717 Clone failed"));
|
|
6161
6118
|
if (error instanceof Error) {
|
|
6162
6119
|
if (error.message.includes("Not authenticated")) {
|
|
6163
|
-
console.error(
|
|
6120
|
+
console.error(chalk19.dim(" Run: vm0 auth login"));
|
|
6164
6121
|
} else {
|
|
6165
|
-
console.error(
|
|
6122
|
+
console.error(chalk19.dim(` ${error.message}`));
|
|
6166
6123
|
}
|
|
6167
6124
|
}
|
|
6168
6125
|
process.exit(1);
|
|
@@ -6174,7 +6131,7 @@ var artifactCommand = new Command16().name("artifact").description("Manage cloud
|
|
|
6174
6131
|
|
|
6175
6132
|
// src/commands/cook.ts
|
|
6176
6133
|
import { Command as Command17 } from "commander";
|
|
6177
|
-
import
|
|
6134
|
+
import chalk21 from "chalk";
|
|
6178
6135
|
import { readFile as readFile7, mkdir as mkdir6, writeFile as writeFile6, appendFile } from "fs/promises";
|
|
6179
6136
|
import { existsSync as existsSync8, readFileSync } from "fs";
|
|
6180
6137
|
import path12 from "path";
|
|
@@ -6185,7 +6142,7 @@ import { config as dotenvConfig2 } from "dotenv";
|
|
|
6185
6142
|
// src/lib/utils/update-checker.ts
|
|
6186
6143
|
import https from "https";
|
|
6187
6144
|
import { spawn } from "child_process";
|
|
6188
|
-
import
|
|
6145
|
+
import chalk20 from "chalk";
|
|
6189
6146
|
var PACKAGE_NAME = "@vm0/cli";
|
|
6190
6147
|
var NPM_REGISTRY_URL = `https://registry.npmjs.org/${encodeURIComponent(PACKAGE_NAME)}/latest`;
|
|
6191
6148
|
var TIMEOUT_MS = 5e3;
|
|
@@ -6250,21 +6207,21 @@ function performUpgrade(packageManager) {
|
|
|
6250
6207
|
async function checkAndUpgrade(currentVersion, prompt) {
|
|
6251
6208
|
const latestVersion = await getLatestVersion();
|
|
6252
6209
|
if (latestVersion === null) {
|
|
6253
|
-
console.log(
|
|
6210
|
+
console.log(chalk20.yellow("Warning: Could not check for updates"));
|
|
6254
6211
|
console.log();
|
|
6255
6212
|
return false;
|
|
6256
6213
|
}
|
|
6257
6214
|
if (latestVersion === currentVersion) {
|
|
6258
6215
|
return false;
|
|
6259
6216
|
}
|
|
6260
|
-
console.log(
|
|
6217
|
+
console.log(chalk20.yellow("vm0 is currently in Early Access (EA)."));
|
|
6261
6218
|
console.log(
|
|
6262
|
-
|
|
6219
|
+
chalk20.yellow(
|
|
6263
6220
|
`Current version: ${currentVersion} -> Latest version: ${latestVersion}`
|
|
6264
6221
|
)
|
|
6265
6222
|
);
|
|
6266
6223
|
console.log(
|
|
6267
|
-
|
|
6224
|
+
chalk20.yellow(
|
|
6268
6225
|
"Please always use the latest version for best compatibility."
|
|
6269
6226
|
)
|
|
6270
6227
|
);
|
|
@@ -6273,20 +6230,20 @@ async function checkAndUpgrade(currentVersion, prompt) {
|
|
|
6273
6230
|
console.log(`Upgrading via ${packageManager}...`);
|
|
6274
6231
|
const success = await performUpgrade(packageManager);
|
|
6275
6232
|
if (success) {
|
|
6276
|
-
console.log(
|
|
6233
|
+
console.log(chalk20.green(`Upgraded to ${latestVersion}`));
|
|
6277
6234
|
console.log();
|
|
6278
6235
|
console.log("To continue, run:");
|
|
6279
|
-
console.log(
|
|
6236
|
+
console.log(chalk20.cyan(` ${buildRerunCommand(prompt)}`));
|
|
6280
6237
|
return true;
|
|
6281
6238
|
}
|
|
6282
6239
|
console.log();
|
|
6283
|
-
console.log(
|
|
6284
|
-
console.log(
|
|
6285
|
-
console.log(
|
|
6286
|
-
console.log(
|
|
6240
|
+
console.log(chalk20.red("Upgrade failed. Please run manually:"));
|
|
6241
|
+
console.log(chalk20.cyan(` npm install -g ${PACKAGE_NAME}@latest`));
|
|
6242
|
+
console.log(chalk20.dim(" # or"));
|
|
6243
|
+
console.log(chalk20.cyan(` pnpm add -g ${PACKAGE_NAME}@latest`));
|
|
6287
6244
|
console.log();
|
|
6288
6245
|
console.log("Then re-run:");
|
|
6289
|
-
console.log(
|
|
6246
|
+
console.log(chalk20.cyan(` ${buildRerunCommand(prompt)}`));
|
|
6290
6247
|
return true;
|
|
6291
6248
|
}
|
|
6292
6249
|
|
|
@@ -6359,7 +6316,7 @@ async function saveCookState(state) {
|
|
|
6359
6316
|
var CONFIG_FILE3 = "vm0.yaml";
|
|
6360
6317
|
var ARTIFACT_DIR = "artifact";
|
|
6361
6318
|
function printCommand(cmd) {
|
|
6362
|
-
console.log(
|
|
6319
|
+
console.log(chalk21.dim(`> ${cmd}`));
|
|
6363
6320
|
}
|
|
6364
6321
|
function execVm0Command(args, options = {}) {
|
|
6365
6322
|
return new Promise((resolve2, reject) => {
|
|
@@ -6496,7 +6453,7 @@ async function autoPullArtifact(runOutput, artifactDir) {
|
|
|
6496
6453
|
);
|
|
6497
6454
|
if (serverVersion && existsSync8(artifactDir)) {
|
|
6498
6455
|
console.log();
|
|
6499
|
-
console.log(
|
|
6456
|
+
console.log(chalk21.bold("Pulling updated artifact:"));
|
|
6500
6457
|
printCommand(`cd ${ARTIFACT_DIR}`);
|
|
6501
6458
|
printCommand(`vm0 artifact pull ${serverVersion}`);
|
|
6502
6459
|
try {
|
|
@@ -6506,23 +6463,23 @@ async function autoPullArtifact(runOutput, artifactDir) {
|
|
|
6506
6463
|
});
|
|
6507
6464
|
printCommand("cd ..");
|
|
6508
6465
|
} catch (error) {
|
|
6509
|
-
console.error(
|
|
6466
|
+
console.error(chalk21.red(`\u2717 Artifact pull failed`));
|
|
6510
6467
|
if (error instanceof Error) {
|
|
6511
|
-
console.error(
|
|
6468
|
+
console.error(chalk21.dim(` ${error.message}`));
|
|
6512
6469
|
}
|
|
6513
6470
|
}
|
|
6514
6471
|
}
|
|
6515
6472
|
}
|
|
6516
6473
|
var cookCmd = new Command17().name("cook").description("One-click agent preparation and execution from vm0.yaml");
|
|
6517
6474
|
cookCmd.argument("[prompt]", "Prompt for the agent").option("-y, --yes", "Skip confirmation prompts").action(async (prompt, options) => {
|
|
6518
|
-
const shouldExit = await checkAndUpgrade("5.
|
|
6475
|
+
const shouldExit = await checkAndUpgrade("5.6.0", prompt);
|
|
6519
6476
|
if (shouldExit) {
|
|
6520
6477
|
process.exit(0);
|
|
6521
6478
|
}
|
|
6522
6479
|
const cwd = process.cwd();
|
|
6523
|
-
console.log(
|
|
6480
|
+
console.log(chalk21.bold(`Reading config: ${CONFIG_FILE3}`));
|
|
6524
6481
|
if (!existsSync8(CONFIG_FILE3)) {
|
|
6525
|
-
console.error(
|
|
6482
|
+
console.error(chalk21.red(`\u2717 Config file not found: ${CONFIG_FILE3}`));
|
|
6526
6483
|
process.exit(1);
|
|
6527
6484
|
}
|
|
6528
6485
|
let config;
|
|
@@ -6530,22 +6487,22 @@ cookCmd.argument("[prompt]", "Prompt for the agent").option("-y, --yes", "Skip c
|
|
|
6530
6487
|
const content = await readFile7(CONFIG_FILE3, "utf8");
|
|
6531
6488
|
config = parseYaml4(content);
|
|
6532
6489
|
} catch (error) {
|
|
6533
|
-
console.error(
|
|
6490
|
+
console.error(chalk21.red("\u2717 Invalid YAML format"));
|
|
6534
6491
|
if (error instanceof Error) {
|
|
6535
|
-
console.error(
|
|
6492
|
+
console.error(chalk21.dim(` ${error.message}`));
|
|
6536
6493
|
}
|
|
6537
6494
|
process.exit(1);
|
|
6538
6495
|
}
|
|
6539
6496
|
const validation = validateAgentCompose(config);
|
|
6540
6497
|
if (!validation.valid) {
|
|
6541
|
-
console.error(
|
|
6498
|
+
console.error(chalk21.red(`\u2717 ${validation.error}`));
|
|
6542
6499
|
process.exit(1);
|
|
6543
6500
|
}
|
|
6544
6501
|
const agentNames = Object.keys(config.agents);
|
|
6545
6502
|
const agentName = agentNames[0];
|
|
6546
6503
|
const volumeCount = config.volumes ? Object.keys(config.volumes).length : 0;
|
|
6547
6504
|
console.log(
|
|
6548
|
-
|
|
6505
|
+
chalk21.green(`\u2713 Config validated: 1 agent, ${volumeCount} volume(s)`)
|
|
6549
6506
|
);
|
|
6550
6507
|
const requiredVarNames = extractRequiredVarNames(config);
|
|
6551
6508
|
if (requiredVarNames.length > 0) {
|
|
@@ -6555,24 +6512,24 @@ cookCmd.argument("[prompt]", "Prompt for the agent").option("-y, --yes", "Skip c
|
|
|
6555
6512
|
await generateEnvPlaceholders(missingVars, envFilePath);
|
|
6556
6513
|
console.log();
|
|
6557
6514
|
console.log(
|
|
6558
|
-
|
|
6515
|
+
chalk21.yellow(
|
|
6559
6516
|
`\u26A0 Missing environment variables. Please fill in values in .env file:`
|
|
6560
6517
|
)
|
|
6561
6518
|
);
|
|
6562
6519
|
for (const varName of missingVars) {
|
|
6563
|
-
console.log(
|
|
6520
|
+
console.log(chalk21.yellow(` ${varName}`));
|
|
6564
6521
|
}
|
|
6565
6522
|
process.exit(1);
|
|
6566
6523
|
}
|
|
6567
6524
|
}
|
|
6568
6525
|
if (config.volumes && Object.keys(config.volumes).length > 0) {
|
|
6569
6526
|
console.log();
|
|
6570
|
-
console.log(
|
|
6527
|
+
console.log(chalk21.bold("Processing volumes:"));
|
|
6571
6528
|
for (const volumeConfig of Object.values(config.volumes)) {
|
|
6572
6529
|
const volumeDir = path12.join(cwd, volumeConfig.name);
|
|
6573
6530
|
if (!existsSync8(volumeDir)) {
|
|
6574
6531
|
console.error(
|
|
6575
|
-
|
|
6532
|
+
chalk21.red(
|
|
6576
6533
|
`\u2717 Directory not found: ${volumeConfig.name}. Create the directory and add files first.`
|
|
6577
6534
|
)
|
|
6578
6535
|
);
|
|
@@ -6598,16 +6555,16 @@ cookCmd.argument("[prompt]", "Prompt for the agent").option("-y, --yes", "Skip c
|
|
|
6598
6555
|
});
|
|
6599
6556
|
printCommand("cd ..");
|
|
6600
6557
|
} catch (error) {
|
|
6601
|
-
console.error(
|
|
6558
|
+
console.error(chalk21.red(`\u2717 Failed`));
|
|
6602
6559
|
if (error instanceof Error) {
|
|
6603
|
-
console.error(
|
|
6560
|
+
console.error(chalk21.dim(` ${error.message}`));
|
|
6604
6561
|
}
|
|
6605
6562
|
process.exit(1);
|
|
6606
6563
|
}
|
|
6607
6564
|
}
|
|
6608
6565
|
}
|
|
6609
6566
|
console.log();
|
|
6610
|
-
console.log(
|
|
6567
|
+
console.log(chalk21.bold("Processing artifact:"));
|
|
6611
6568
|
const artifactDir = path12.join(cwd, ARTIFACT_DIR);
|
|
6612
6569
|
try {
|
|
6613
6570
|
if (!existsSync8(artifactDir)) {
|
|
@@ -6630,14 +6587,14 @@ cookCmd.argument("[prompt]", "Prompt for the agent").option("-y, --yes", "Skip c
|
|
|
6630
6587
|
});
|
|
6631
6588
|
printCommand("cd ..");
|
|
6632
6589
|
} catch (error) {
|
|
6633
|
-
console.error(
|
|
6590
|
+
console.error(chalk21.red(`\u2717 Failed`));
|
|
6634
6591
|
if (error instanceof Error) {
|
|
6635
|
-
console.error(
|
|
6592
|
+
console.error(chalk21.dim(` ${error.message}`));
|
|
6636
6593
|
}
|
|
6637
6594
|
process.exit(1);
|
|
6638
6595
|
}
|
|
6639
6596
|
console.log();
|
|
6640
|
-
console.log(
|
|
6597
|
+
console.log(chalk21.bold("Composing agent:"));
|
|
6641
6598
|
const composeArgs = options.yes ? ["compose", "--yes", CONFIG_FILE3] : ["compose", CONFIG_FILE3];
|
|
6642
6599
|
printCommand(`vm0 ${composeArgs.join(" ")}`);
|
|
6643
6600
|
try {
|
|
@@ -6645,15 +6602,15 @@ cookCmd.argument("[prompt]", "Prompt for the agent").option("-y, --yes", "Skip c
|
|
|
6645
6602
|
cwd
|
|
6646
6603
|
});
|
|
6647
6604
|
} catch (error) {
|
|
6648
|
-
console.error(
|
|
6605
|
+
console.error(chalk21.red(`\u2717 Compose failed`));
|
|
6649
6606
|
if (error instanceof Error) {
|
|
6650
|
-
console.error(
|
|
6607
|
+
console.error(chalk21.dim(` ${error.message}`));
|
|
6651
6608
|
}
|
|
6652
6609
|
process.exit(1);
|
|
6653
6610
|
}
|
|
6654
6611
|
if (prompt) {
|
|
6655
6612
|
console.log();
|
|
6656
|
-
console.log(
|
|
6613
|
+
console.log(chalk21.bold("Running agent:"));
|
|
6657
6614
|
printCommand(
|
|
6658
6615
|
`vm0 run ${agentName} --artifact-name ${ARTIFACT_DIR} "${prompt}"`
|
|
6659
6616
|
);
|
|
@@ -6695,8 +6652,8 @@ cookCmd.command("logs").description("View logs from the last cook run").option("
|
|
|
6695
6652
|
async (options) => {
|
|
6696
6653
|
const state = await loadCookState();
|
|
6697
6654
|
if (!state.lastRunId) {
|
|
6698
|
-
console.error(
|
|
6699
|
-
console.error(
|
|
6655
|
+
console.error(chalk21.red("\u2717 No previous run found"));
|
|
6656
|
+
console.error(chalk21.dim(" Run 'vm0 cook <prompt>' first"));
|
|
6700
6657
|
process.exit(1);
|
|
6701
6658
|
}
|
|
6702
6659
|
const args = ["logs", state.lastRunId];
|
|
@@ -6738,8 +6695,8 @@ cookCmd.command("continue").description(
|
|
|
6738
6695
|
).argument("<prompt>", "Prompt for the continued agent").action(async (prompt) => {
|
|
6739
6696
|
const state = await loadCookState();
|
|
6740
6697
|
if (!state.lastSessionId) {
|
|
6741
|
-
console.error(
|
|
6742
|
-
console.error(
|
|
6698
|
+
console.error(chalk21.red("\u2717 No previous session found"));
|
|
6699
|
+
console.error(chalk21.dim(" Run 'vm0 cook <prompt>' first"));
|
|
6743
6700
|
process.exit(1);
|
|
6744
6701
|
}
|
|
6745
6702
|
const cwd = process.cwd();
|
|
@@ -6770,8 +6727,8 @@ cookCmd.command("resume").description(
|
|
|
6770
6727
|
).argument("<prompt>", "Prompt for the resumed agent").action(async (prompt) => {
|
|
6771
6728
|
const state = await loadCookState();
|
|
6772
6729
|
if (!state.lastCheckpointId) {
|
|
6773
|
-
console.error(
|
|
6774
|
-
console.error(
|
|
6730
|
+
console.error(chalk21.red("\u2717 No previous checkpoint found"));
|
|
6731
|
+
console.error(chalk21.dim(" Run 'vm0 cook <prompt>' first"));
|
|
6775
6732
|
process.exit(1);
|
|
6776
6733
|
}
|
|
6777
6734
|
const cwd = process.cwd();
|
|
@@ -6801,7 +6758,7 @@ var cookCommand = cookCmd;
|
|
|
6801
6758
|
|
|
6802
6759
|
// src/commands/logs/index.ts
|
|
6803
6760
|
import { Command as Command18 } from "commander";
|
|
6804
|
-
import
|
|
6761
|
+
import chalk22 from "chalk";
|
|
6805
6762
|
|
|
6806
6763
|
// src/lib/utils/time-parser.ts
|
|
6807
6764
|
function parseTime(timeStr) {
|
|
@@ -6862,36 +6819,36 @@ function formatMetric(metric) {
|
|
|
6862
6819
|
}
|
|
6863
6820
|
function formatNetworkLog(entry) {
|
|
6864
6821
|
if (entry.mode === "sni" || !entry.method) {
|
|
6865
|
-
const actionColor = entry.action === "ALLOW" ?
|
|
6822
|
+
const actionColor = entry.action === "ALLOW" ? chalk22.green : chalk22.red;
|
|
6866
6823
|
const host = entry.host || "unknown";
|
|
6867
6824
|
const port = entry.port || 443;
|
|
6868
|
-
return `[${entry.timestamp}] ${
|
|
6825
|
+
return `[${entry.timestamp}] ${chalk22.cyan("SNI")} ${actionColor(entry.action || "ALLOW")} ${host}:${port} ${chalk22.dim(entry.rule_matched || "")}`;
|
|
6869
6826
|
}
|
|
6870
6827
|
let statusColor;
|
|
6871
6828
|
const status = entry.status || 0;
|
|
6872
6829
|
if (status >= 200 && status < 300) {
|
|
6873
|
-
statusColor =
|
|
6830
|
+
statusColor = chalk22.green;
|
|
6874
6831
|
} else if (status >= 300 && status < 400) {
|
|
6875
|
-
statusColor =
|
|
6832
|
+
statusColor = chalk22.yellow;
|
|
6876
6833
|
} else if (status >= 400) {
|
|
6877
|
-
statusColor =
|
|
6834
|
+
statusColor = chalk22.red;
|
|
6878
6835
|
} else {
|
|
6879
|
-
statusColor =
|
|
6836
|
+
statusColor = chalk22.gray;
|
|
6880
6837
|
}
|
|
6881
6838
|
let latencyColor;
|
|
6882
6839
|
const latencyMs = entry.latency_ms || 0;
|
|
6883
6840
|
if (latencyMs < 500) {
|
|
6884
|
-
latencyColor =
|
|
6841
|
+
latencyColor = chalk22.green;
|
|
6885
6842
|
} else if (latencyMs < 2e3) {
|
|
6886
|
-
latencyColor =
|
|
6843
|
+
latencyColor = chalk22.yellow;
|
|
6887
6844
|
} else {
|
|
6888
|
-
latencyColor =
|
|
6845
|
+
latencyColor = chalk22.red;
|
|
6889
6846
|
}
|
|
6890
6847
|
const method = entry.method || "???";
|
|
6891
6848
|
const requestSize = entry.request_size || 0;
|
|
6892
6849
|
const responseSize = entry.response_size || 0;
|
|
6893
6850
|
const url = entry.url || entry.host || "unknown";
|
|
6894
|
-
return `[${entry.timestamp}] ${method.padEnd(6)} ${statusColor(status)} ${latencyColor(latencyMs + "ms")} ${formatBytes8(requestSize)}/${formatBytes8(responseSize)} ${
|
|
6851
|
+
return `[${entry.timestamp}] ${method.padEnd(6)} ${statusColor(status)} ${latencyColor(latencyMs + "ms")} ${formatBytes8(requestSize)}/${formatBytes8(responseSize)} ${chalk22.dim(url)}`;
|
|
6895
6852
|
}
|
|
6896
6853
|
function renderAgentEvent(event, provider) {
|
|
6897
6854
|
const eventData = event.eventData;
|
|
@@ -6914,7 +6871,7 @@ function getLogType(options) {
|
|
|
6914
6871
|
].filter(Boolean).length;
|
|
6915
6872
|
if (selected > 1) {
|
|
6916
6873
|
console.error(
|
|
6917
|
-
|
|
6874
|
+
chalk22.red(
|
|
6918
6875
|
"Options --agent, --system, --metrics, and --network are mutually exclusive"
|
|
6919
6876
|
)
|
|
6920
6877
|
);
|
|
@@ -6934,7 +6891,7 @@ var logsCommand = new Command18().name("logs").description("View logs for an age
|
|
|
6934
6891
|
const logType = getLogType(options);
|
|
6935
6892
|
if (options.tail !== void 0 && options.head !== void 0) {
|
|
6936
6893
|
console.error(
|
|
6937
|
-
|
|
6894
|
+
chalk22.red("Options --tail and --head are mutually exclusive")
|
|
6938
6895
|
);
|
|
6939
6896
|
process.exit(1);
|
|
6940
6897
|
}
|
|
@@ -6971,7 +6928,7 @@ var logsCommand = new Command18().name("logs").description("View logs for an age
|
|
|
6971
6928
|
async function showAgentEvents(runId, options) {
|
|
6972
6929
|
const response = await apiClient.getAgentEvents(runId, options);
|
|
6973
6930
|
if (response.events.length === 0) {
|
|
6974
|
-
console.log(
|
|
6931
|
+
console.log(chalk22.yellow("No agent events found for this run."));
|
|
6975
6932
|
return;
|
|
6976
6933
|
}
|
|
6977
6934
|
const events = options.order === "desc" ? [...response.events].reverse() : response.events;
|
|
@@ -6981,7 +6938,7 @@ async function showAgentEvents(runId, options) {
|
|
|
6981
6938
|
if (response.hasMore) {
|
|
6982
6939
|
console.log();
|
|
6983
6940
|
console.log(
|
|
6984
|
-
|
|
6941
|
+
chalk22.dim(
|
|
6985
6942
|
`Showing ${response.events.length} events. Use --tail to see more.`
|
|
6986
6943
|
)
|
|
6987
6944
|
);
|
|
@@ -6990,21 +6947,21 @@ async function showAgentEvents(runId, options) {
|
|
|
6990
6947
|
async function showSystemLog(runId, options) {
|
|
6991
6948
|
const response = await apiClient.getSystemLog(runId, options);
|
|
6992
6949
|
if (!response.systemLog) {
|
|
6993
|
-
console.log(
|
|
6950
|
+
console.log(chalk22.yellow("No system log found for this run."));
|
|
6994
6951
|
return;
|
|
6995
6952
|
}
|
|
6996
6953
|
console.log(response.systemLog);
|
|
6997
6954
|
if (response.hasMore) {
|
|
6998
6955
|
console.log();
|
|
6999
6956
|
console.log(
|
|
7000
|
-
|
|
6957
|
+
chalk22.dim("More log entries available. Use --tail to see more.")
|
|
7001
6958
|
);
|
|
7002
6959
|
}
|
|
7003
6960
|
}
|
|
7004
6961
|
async function showMetrics(runId, options) {
|
|
7005
6962
|
const response = await apiClient.getMetrics(runId, options);
|
|
7006
6963
|
if (response.metrics.length === 0) {
|
|
7007
|
-
console.log(
|
|
6964
|
+
console.log(chalk22.yellow("No metrics found for this run."));
|
|
7008
6965
|
return;
|
|
7009
6966
|
}
|
|
7010
6967
|
const metrics = options.order === "desc" ? [...response.metrics].reverse() : response.metrics;
|
|
@@ -7014,7 +6971,7 @@ async function showMetrics(runId, options) {
|
|
|
7014
6971
|
if (response.hasMore) {
|
|
7015
6972
|
console.log();
|
|
7016
6973
|
console.log(
|
|
7017
|
-
|
|
6974
|
+
chalk22.dim(
|
|
7018
6975
|
`Showing ${response.metrics.length} metrics. Use --tail to see more.`
|
|
7019
6976
|
)
|
|
7020
6977
|
);
|
|
@@ -7024,7 +6981,7 @@ async function showNetworkLogs(runId, options) {
|
|
|
7024
6981
|
const response = await apiClient.getNetworkLogs(runId, options);
|
|
7025
6982
|
if (response.networkLogs.length === 0) {
|
|
7026
6983
|
console.log(
|
|
7027
|
-
|
|
6984
|
+
chalk22.yellow(
|
|
7028
6985
|
"No network logs found for this run. Network logs are only captured when experimental_firewall is enabled on an experimental_runner."
|
|
7029
6986
|
)
|
|
7030
6987
|
);
|
|
@@ -7037,7 +6994,7 @@ async function showNetworkLogs(runId, options) {
|
|
|
7037
6994
|
if (response.hasMore) {
|
|
7038
6995
|
console.log();
|
|
7039
6996
|
console.log(
|
|
7040
|
-
|
|
6997
|
+
chalk22.dim(
|
|
7041
6998
|
`Showing ${response.networkLogs.length} network logs. Use --tail to see more.`
|
|
7042
6999
|
)
|
|
7043
7000
|
);
|
|
@@ -7046,17 +7003,17 @@ async function showNetworkLogs(runId, options) {
|
|
|
7046
7003
|
function handleError(error, runId) {
|
|
7047
7004
|
if (error instanceof Error) {
|
|
7048
7005
|
if (error.message.includes("Not authenticated")) {
|
|
7049
|
-
console.error(
|
|
7006
|
+
console.error(chalk22.red("Not authenticated. Run: vm0 auth login"));
|
|
7050
7007
|
} else if (error.message.includes("not found")) {
|
|
7051
|
-
console.error(
|
|
7008
|
+
console.error(chalk22.red(`Run not found: ${runId}`));
|
|
7052
7009
|
} else if (error.message.includes("Invalid time format")) {
|
|
7053
|
-
console.error(
|
|
7010
|
+
console.error(chalk22.red(error.message));
|
|
7054
7011
|
} else {
|
|
7055
|
-
console.error(
|
|
7056
|
-
console.error(
|
|
7012
|
+
console.error(chalk22.red("Failed to fetch logs"));
|
|
7013
|
+
console.error(chalk22.dim(` ${error.message}`));
|
|
7057
7014
|
}
|
|
7058
7015
|
} else {
|
|
7059
|
-
console.error(
|
|
7016
|
+
console.error(chalk22.red("An unexpected error occurred"));
|
|
7060
7017
|
}
|
|
7061
7018
|
}
|
|
7062
7019
|
|
|
@@ -7065,12 +7022,12 @@ import { Command as Command21 } from "commander";
|
|
|
7065
7022
|
|
|
7066
7023
|
// src/commands/scope/status.ts
|
|
7067
7024
|
import { Command as Command19 } from "commander";
|
|
7068
|
-
import
|
|
7025
|
+
import chalk23 from "chalk";
|
|
7069
7026
|
var statusCommand3 = new Command19().name("status").description("View current scope status").action(async () => {
|
|
7070
7027
|
try {
|
|
7071
7028
|
const scope = await apiClient.getScope();
|
|
7072
|
-
console.log(
|
|
7073
|
-
console.log(` Slug: ${
|
|
7029
|
+
console.log(chalk23.bold("Scope Information:"));
|
|
7030
|
+
console.log(` Slug: ${chalk23.green(scope.slug)}`);
|
|
7074
7031
|
console.log(` Type: ${scope.type}`);
|
|
7075
7032
|
if (scope.displayName) {
|
|
7076
7033
|
console.log(` Display Name: ${scope.displayName}`);
|
|
@@ -7081,20 +7038,20 @@ var statusCommand3 = new Command19().name("status").description("View current sc
|
|
|
7081
7038
|
} catch (error) {
|
|
7082
7039
|
if (error instanceof Error) {
|
|
7083
7040
|
if (error.message.includes("Not authenticated")) {
|
|
7084
|
-
console.error(
|
|
7041
|
+
console.error(chalk23.red("\u2717 Not authenticated. Run: vm0 auth login"));
|
|
7085
7042
|
} else if (error.message.includes("No scope configured")) {
|
|
7086
|
-
console.log(
|
|
7043
|
+
console.log(chalk23.yellow("No scope configured."));
|
|
7087
7044
|
console.log();
|
|
7088
7045
|
console.log("Set your scope with:");
|
|
7089
|
-
console.log(
|
|
7046
|
+
console.log(chalk23.cyan(" vm0 scope set <slug>"));
|
|
7090
7047
|
console.log();
|
|
7091
7048
|
console.log("Example:");
|
|
7092
|
-
console.log(
|
|
7049
|
+
console.log(chalk23.dim(" vm0 scope set myusername"));
|
|
7093
7050
|
} else {
|
|
7094
|
-
console.error(
|
|
7051
|
+
console.error(chalk23.red(`\u2717 ${error.message}`));
|
|
7095
7052
|
}
|
|
7096
7053
|
} else {
|
|
7097
|
-
console.error(
|
|
7054
|
+
console.error(chalk23.red("\u2717 An unexpected error occurred"));
|
|
7098
7055
|
}
|
|
7099
7056
|
process.exit(1);
|
|
7100
7057
|
}
|
|
@@ -7102,7 +7059,7 @@ var statusCommand3 = new Command19().name("status").description("View current sc
|
|
|
7102
7059
|
|
|
7103
7060
|
// src/commands/scope/set.ts
|
|
7104
7061
|
import { Command as Command20 } from "commander";
|
|
7105
|
-
import
|
|
7062
|
+
import chalk24 from "chalk";
|
|
7106
7063
|
var setCommand = new Command20().name("set").description("Set your scope slug").argument("<slug>", "The scope slug (e.g., your username)").option("--force", "Force change existing scope (may break references)").option("--display-name <name>", "Display name for the scope").action(
|
|
7107
7064
|
async (slug, options) => {
|
|
7108
7065
|
try {
|
|
@@ -7118,56 +7075,56 @@ var setCommand = new Command20().name("set").description("Set your scope slug").
|
|
|
7118
7075
|
if (existingScope) {
|
|
7119
7076
|
if (!options.force) {
|
|
7120
7077
|
console.error(
|
|
7121
|
-
|
|
7078
|
+
chalk24.yellow(`You already have a scope: ${existingScope.slug}`)
|
|
7122
7079
|
);
|
|
7123
7080
|
console.error();
|
|
7124
7081
|
console.error("To change your scope, use --force:");
|
|
7125
|
-
console.error(
|
|
7082
|
+
console.error(chalk24.cyan(` vm0 scope set ${slug} --force`));
|
|
7126
7083
|
console.error();
|
|
7127
7084
|
console.error(
|
|
7128
|
-
|
|
7085
|
+
chalk24.yellow(
|
|
7129
7086
|
"Warning: Changing your scope may break existing image references."
|
|
7130
7087
|
)
|
|
7131
7088
|
);
|
|
7132
7089
|
process.exit(1);
|
|
7133
7090
|
}
|
|
7134
7091
|
scope = await apiClient.updateScope({ slug, force: true });
|
|
7135
|
-
console.log(
|
|
7092
|
+
console.log(chalk24.green(`\u2713 Scope updated to ${scope.slug}`));
|
|
7136
7093
|
} else {
|
|
7137
7094
|
scope = await apiClient.createScope({
|
|
7138
7095
|
slug,
|
|
7139
7096
|
displayName: options.displayName
|
|
7140
7097
|
});
|
|
7141
|
-
console.log(
|
|
7098
|
+
console.log(chalk24.green(`\u2713 Scope created: ${scope.slug}`));
|
|
7142
7099
|
}
|
|
7143
7100
|
console.log();
|
|
7144
7101
|
console.log("Your images will now be namespaced as:");
|
|
7145
|
-
console.log(
|
|
7102
|
+
console.log(chalk24.cyan(` ${scope.slug}/<image-name>`));
|
|
7146
7103
|
} catch (error) {
|
|
7147
7104
|
if (error instanceof Error) {
|
|
7148
7105
|
if (error.message.includes("Not authenticated")) {
|
|
7149
7106
|
console.error(
|
|
7150
|
-
|
|
7107
|
+
chalk24.red("\u2717 Not authenticated. Run: vm0 auth login")
|
|
7151
7108
|
);
|
|
7152
7109
|
} else if (error.message.includes("already exists")) {
|
|
7153
7110
|
console.error(
|
|
7154
|
-
|
|
7111
|
+
chalk24.red(
|
|
7155
7112
|
`\u2717 Scope "${slug}" is already taken. Please choose a different slug.`
|
|
7156
7113
|
)
|
|
7157
7114
|
);
|
|
7158
7115
|
} else if (error.message.includes("reserved")) {
|
|
7159
|
-
console.error(
|
|
7116
|
+
console.error(chalk24.red(`\u2717 ${error.message}`));
|
|
7160
7117
|
} else if (error.message.includes("vm0")) {
|
|
7161
7118
|
console.error(
|
|
7162
|
-
|
|
7119
|
+
chalk24.red(
|
|
7163
7120
|
"\u2717 Scope slugs cannot start with 'vm0' (reserved for system use)"
|
|
7164
7121
|
)
|
|
7165
7122
|
);
|
|
7166
7123
|
} else {
|
|
7167
|
-
console.error(
|
|
7124
|
+
console.error(chalk24.red(`\u2717 ${error.message}`));
|
|
7168
7125
|
}
|
|
7169
7126
|
} else {
|
|
7170
|
-
console.error(
|
|
7127
|
+
console.error(chalk24.red("\u2717 An unexpected error occurred"));
|
|
7171
7128
|
}
|
|
7172
7129
|
process.exit(1);
|
|
7173
7130
|
}
|
|
@@ -7182,7 +7139,7 @@ import { Command as Command24 } from "commander";
|
|
|
7182
7139
|
|
|
7183
7140
|
// src/commands/agents/list.ts
|
|
7184
7141
|
import { Command as Command22 } from "commander";
|
|
7185
|
-
import
|
|
7142
|
+
import chalk25 from "chalk";
|
|
7186
7143
|
var listCommand3 = new Command22().name("list").alias("ls").description("List all agent composes").option("-s, --scope <scope>", "Scope to list composes from").action(async (options) => {
|
|
7187
7144
|
try {
|
|
7188
7145
|
const url = options.scope ? `/api/agent/composes/list?scope=${encodeURIComponent(options.scope)}` : "/api/agent/composes/list";
|
|
@@ -7193,9 +7150,9 @@ var listCommand3 = new Command22().name("list").alias("ls").description("List al
|
|
|
7193
7150
|
}
|
|
7194
7151
|
const data = await response.json();
|
|
7195
7152
|
if (data.composes.length === 0) {
|
|
7196
|
-
console.log(
|
|
7153
|
+
console.log(chalk25.dim("No agent composes found"));
|
|
7197
7154
|
console.log(
|
|
7198
|
-
|
|
7155
|
+
chalk25.dim(" Create one with: vm0 compose <agent-compose.yaml>")
|
|
7199
7156
|
);
|
|
7200
7157
|
return;
|
|
7201
7158
|
}
|
|
@@ -7203,9 +7160,9 @@ var listCommand3 = new Command22().name("list").alias("ls").description("List al
|
|
|
7203
7160
|
const header = ["NAME".padEnd(nameWidth), "VERSION", "UPDATED"].join(
|
|
7204
7161
|
" "
|
|
7205
7162
|
);
|
|
7206
|
-
console.log(
|
|
7163
|
+
console.log(chalk25.dim(header));
|
|
7207
7164
|
for (const compose of data.composes) {
|
|
7208
|
-
const versionShort = compose.headVersionId ? compose.headVersionId.slice(0, 8) :
|
|
7165
|
+
const versionShort = compose.headVersionId ? compose.headVersionId.slice(0, 8) : chalk25.dim("-");
|
|
7209
7166
|
const row = [
|
|
7210
7167
|
compose.name.padEnd(nameWidth),
|
|
7211
7168
|
versionShort,
|
|
@@ -7214,12 +7171,12 @@ var listCommand3 = new Command22().name("list").alias("ls").description("List al
|
|
|
7214
7171
|
console.log(row);
|
|
7215
7172
|
}
|
|
7216
7173
|
} catch (error) {
|
|
7217
|
-
console.error(
|
|
7174
|
+
console.error(chalk25.red("\u2717 Failed to list agent composes"));
|
|
7218
7175
|
if (error instanceof Error) {
|
|
7219
7176
|
if (error.message.includes("Not authenticated")) {
|
|
7220
|
-
console.error(
|
|
7177
|
+
console.error(chalk25.dim(" Run: vm0 auth login"));
|
|
7221
7178
|
} else {
|
|
7222
|
-
console.error(
|
|
7179
|
+
console.error(chalk25.dim(` ${error.message}`));
|
|
7223
7180
|
}
|
|
7224
7181
|
}
|
|
7225
7182
|
process.exit(1);
|
|
@@ -7228,7 +7185,7 @@ var listCommand3 = new Command22().name("list").alias("ls").description("List al
|
|
|
7228
7185
|
|
|
7229
7186
|
// src/commands/agents/inspect.ts
|
|
7230
7187
|
import { Command as Command23 } from "commander";
|
|
7231
|
-
import
|
|
7188
|
+
import chalk26 from "chalk";
|
|
7232
7189
|
|
|
7233
7190
|
// src/lib/domain/source-derivation.ts
|
|
7234
7191
|
import * as fs9 from "fs/promises";
|
|
@@ -7338,12 +7295,12 @@ async function deriveComposeVariableSources(content, options) {
|
|
|
7338
7295
|
|
|
7339
7296
|
// src/commands/agents/inspect.ts
|
|
7340
7297
|
function formatComposeOutput(name, versionId, content, variableSources) {
|
|
7341
|
-
console.log(
|
|
7342
|
-
console.log(
|
|
7298
|
+
console.log(chalk26.bold("Name:") + ` ${name}`);
|
|
7299
|
+
console.log(chalk26.bold("Version:") + ` ${versionId}`);
|
|
7343
7300
|
console.log();
|
|
7344
|
-
console.log(
|
|
7301
|
+
console.log(chalk26.bold("Agents:"));
|
|
7345
7302
|
for (const [agentName, agent] of Object.entries(content.agents)) {
|
|
7346
|
-
console.log(` ${
|
|
7303
|
+
console.log(` ${chalk26.cyan(agentName)}:`);
|
|
7347
7304
|
console.log(` Provider: ${agent.provider}`);
|
|
7348
7305
|
if (agent.image) {
|
|
7349
7306
|
console.log(` Image: ${agent.image}`);
|
|
@@ -7379,14 +7336,14 @@ function formatComposeOutput(name, versionId, content, variableSources) {
|
|
|
7379
7336
|
if (agentSources.secrets.length > 0) {
|
|
7380
7337
|
console.log(` Secrets:`);
|
|
7381
7338
|
for (const secret of agentSources.secrets) {
|
|
7382
|
-
const sourceInfo =
|
|
7339
|
+
const sourceInfo = chalk26.dim(`(${secret.source})`);
|
|
7383
7340
|
console.log(` - ${secret.name.padEnd(20)} ${sourceInfo}`);
|
|
7384
7341
|
}
|
|
7385
7342
|
}
|
|
7386
7343
|
if (agentSources.vars.length > 0) {
|
|
7387
7344
|
console.log(` Vars:`);
|
|
7388
7345
|
for (const v of agentSources.vars) {
|
|
7389
|
-
const sourceInfo =
|
|
7346
|
+
const sourceInfo = chalk26.dim(`(${v.source})`);
|
|
7390
7347
|
console.log(` - ${v.name.padEnd(20)} ${sourceInfo}`);
|
|
7391
7348
|
}
|
|
7392
7349
|
}
|
|
@@ -7417,8 +7374,8 @@ var inspectCommand = new Command23().name("inspect").description("Inspect an age
|
|
|
7417
7374
|
compose = await apiClient.getComposeByName(name, options.scope);
|
|
7418
7375
|
} catch (error) {
|
|
7419
7376
|
if (error instanceof Error && error.message.includes("not found")) {
|
|
7420
|
-
console.error(
|
|
7421
|
-
console.error(
|
|
7377
|
+
console.error(chalk26.red(`\u2717 Agent compose not found: ${name}`));
|
|
7378
|
+
console.error(chalk26.dim(" Run: vm0 agents list"));
|
|
7422
7379
|
process.exit(1);
|
|
7423
7380
|
}
|
|
7424
7381
|
throw error;
|
|
@@ -7434,9 +7391,9 @@ var inspectCommand = new Command23().name("inspect").description("Inspect an age
|
|
|
7434
7391
|
resolvedVersionId = versionInfo.versionId;
|
|
7435
7392
|
} catch (error) {
|
|
7436
7393
|
if (error instanceof Error && error.message.includes("not found")) {
|
|
7437
|
-
console.error(
|
|
7394
|
+
console.error(chalk26.red(`\u2717 Version not found: ${version}`));
|
|
7438
7395
|
console.error(
|
|
7439
|
-
|
|
7396
|
+
chalk26.dim(
|
|
7440
7397
|
` HEAD version: ${compose.headVersionId?.slice(0, 8)}`
|
|
7441
7398
|
)
|
|
7442
7399
|
);
|
|
@@ -7449,7 +7406,7 @@ var inspectCommand = new Command23().name("inspect").description("Inspect an age
|
|
|
7449
7406
|
}
|
|
7450
7407
|
}
|
|
7451
7408
|
if (!resolvedVersionId || !compose.content) {
|
|
7452
|
-
console.error(
|
|
7409
|
+
console.error(chalk26.red(`\u2717 No version found for: ${name}`));
|
|
7453
7410
|
process.exit(1);
|
|
7454
7411
|
}
|
|
7455
7412
|
const content = compose.content;
|
|
@@ -7459,7 +7416,7 @@ var inspectCommand = new Command23().name("inspect").description("Inspect an age
|
|
|
7459
7416
|
variableSources = await deriveComposeVariableSources(content);
|
|
7460
7417
|
} catch {
|
|
7461
7418
|
console.error(
|
|
7462
|
-
|
|
7419
|
+
chalk26.yellow(
|
|
7463
7420
|
"\u26A0 Warning: Failed to fetch skill sources, showing basic info"
|
|
7464
7421
|
)
|
|
7465
7422
|
);
|
|
@@ -7472,12 +7429,12 @@ var inspectCommand = new Command23().name("inspect").description("Inspect an age
|
|
|
7472
7429
|
variableSources
|
|
7473
7430
|
);
|
|
7474
7431
|
} catch (error) {
|
|
7475
|
-
console.error(
|
|
7432
|
+
console.error(chalk26.red("\u2717 Failed to inspect agent compose"));
|
|
7476
7433
|
if (error instanceof Error) {
|
|
7477
7434
|
if (error.message.includes("Not authenticated")) {
|
|
7478
|
-
console.error(
|
|
7435
|
+
console.error(chalk26.dim(" Run: vm0 auth login"));
|
|
7479
7436
|
} else {
|
|
7480
|
-
console.error(
|
|
7437
|
+
console.error(chalk26.dim(` ${error.message}`));
|
|
7481
7438
|
}
|
|
7482
7439
|
}
|
|
7483
7440
|
process.exit(1);
|
|
@@ -7490,7 +7447,7 @@ var agentsCommand = new Command24().name("agents").description("Manage agent com
|
|
|
7490
7447
|
|
|
7491
7448
|
// src/commands/init.ts
|
|
7492
7449
|
import { Command as Command25 } from "commander";
|
|
7493
|
-
import
|
|
7450
|
+
import chalk27 from "chalk";
|
|
7494
7451
|
import path14 from "path";
|
|
7495
7452
|
import { existsSync as existsSync9 } from "fs";
|
|
7496
7453
|
import { writeFile as writeFile7 } from "fs/promises";
|
|
@@ -7535,10 +7492,10 @@ var initCommand3 = new Command25().name("init").description("Initialize a new VM
|
|
|
7535
7492
|
const existingFiles = checkExistingFiles();
|
|
7536
7493
|
if (existingFiles.length > 0 && !options.force) {
|
|
7537
7494
|
for (const file of existingFiles) {
|
|
7538
|
-
console.log(
|
|
7495
|
+
console.log(chalk27.red(`\u2717 ${file} already exists`));
|
|
7539
7496
|
}
|
|
7540
7497
|
console.log();
|
|
7541
|
-
console.log(`To overwrite: ${
|
|
7498
|
+
console.log(`To overwrite: ${chalk27.cyan("vm0 init --force")}`);
|
|
7542
7499
|
process.exit(1);
|
|
7543
7500
|
}
|
|
7544
7501
|
let agentName;
|
|
@@ -7546,9 +7503,9 @@ var initCommand3 = new Command25().name("init").description("Initialize a new VM
|
|
|
7546
7503
|
agentName = options.name.trim();
|
|
7547
7504
|
} else if (!isInteractive()) {
|
|
7548
7505
|
console.error(
|
|
7549
|
-
|
|
7506
|
+
chalk27.red("\u2717 --name flag is required in non-interactive mode")
|
|
7550
7507
|
);
|
|
7551
|
-
console.error(
|
|
7508
|
+
console.error(chalk27.dim(" Usage: vm0 init --name <agent-name>"));
|
|
7552
7509
|
process.exit(1);
|
|
7553
7510
|
} else {
|
|
7554
7511
|
const dirName = path14.basename(process.cwd());
|
|
@@ -7564,40 +7521,40 @@ var initCommand3 = new Command25().name("init").description("Initialize a new VM
|
|
|
7564
7521
|
}
|
|
7565
7522
|
);
|
|
7566
7523
|
if (name === void 0) {
|
|
7567
|
-
console.log(
|
|
7524
|
+
console.log(chalk27.dim("Cancelled"));
|
|
7568
7525
|
return;
|
|
7569
7526
|
}
|
|
7570
7527
|
agentName = name;
|
|
7571
7528
|
}
|
|
7572
7529
|
if (!agentName || !validateAgentName(agentName)) {
|
|
7573
|
-
console.log(
|
|
7530
|
+
console.log(chalk27.red("\u2717 Invalid agent name"));
|
|
7574
7531
|
console.log(
|
|
7575
|
-
|
|
7532
|
+
chalk27.dim(" Must be 3-64 characters, alphanumeric and hyphens only")
|
|
7576
7533
|
);
|
|
7577
|
-
console.log(
|
|
7534
|
+
console.log(chalk27.dim(" Must start and end with letter or number"));
|
|
7578
7535
|
process.exit(1);
|
|
7579
7536
|
}
|
|
7580
7537
|
await writeFile7(VM0_YAML_FILE, generateVm0Yaml(agentName));
|
|
7581
7538
|
const vm0Status = existingFiles.includes(VM0_YAML_FILE) ? " (overwritten)" : "";
|
|
7582
|
-
console.log(
|
|
7539
|
+
console.log(chalk27.green(`\u2713 Created ${VM0_YAML_FILE}${vm0Status}`));
|
|
7583
7540
|
await writeFile7(AGENTS_MD_FILE, generateAgentsMd());
|
|
7584
7541
|
const agentsStatus = existingFiles.includes(AGENTS_MD_FILE) ? " (overwritten)" : "";
|
|
7585
|
-
console.log(
|
|
7542
|
+
console.log(chalk27.green(`\u2713 Created ${AGENTS_MD_FILE}${agentsStatus}`));
|
|
7586
7543
|
console.log();
|
|
7587
7544
|
console.log("Next steps:");
|
|
7588
7545
|
console.log(
|
|
7589
|
-
` 1. Get your Claude Code token: ${
|
|
7546
|
+
` 1. Get your Claude Code token: ${chalk27.cyan("claude setup-token")}`
|
|
7590
7547
|
);
|
|
7591
7548
|
console.log(` 2. Set the environment variable (or add to .env file):`);
|
|
7592
|
-
console.log(
|
|
7549
|
+
console.log(chalk27.dim(` export CLAUDE_CODE_OAUTH_TOKEN=<your-token>`));
|
|
7593
7550
|
console.log(
|
|
7594
|
-
` 3. Run your agent: ${
|
|
7551
|
+
` 3. Run your agent: ${chalk27.cyan(`vm0 cook "let's start working."`)}`
|
|
7595
7552
|
);
|
|
7596
7553
|
});
|
|
7597
7554
|
|
|
7598
7555
|
// src/commands/setup-github.ts
|
|
7599
7556
|
import { Command as Command26 } from "commander";
|
|
7600
|
-
import
|
|
7557
|
+
import chalk28 from "chalk";
|
|
7601
7558
|
import { existsSync as existsSync10 } from "fs";
|
|
7602
7559
|
import { mkdir as mkdir7, readFile as readFile8, writeFile as writeFile8 } from "fs/promises";
|
|
7603
7560
|
import { execSync, spawnSync } from "child_process";
|
|
@@ -7640,67 +7597,67 @@ async function checkPrerequisites() {
|
|
|
7640
7597
|
console.log("Checking prerequisites...");
|
|
7641
7598
|
const gitRoot = getGitRoot();
|
|
7642
7599
|
if (!gitRoot) {
|
|
7643
|
-
console.log(
|
|
7600
|
+
console.log(chalk28.red("\u2717 Not in a git repository"));
|
|
7644
7601
|
console.log();
|
|
7645
7602
|
console.log("This command must be run from within a git repository.");
|
|
7646
7603
|
console.log();
|
|
7647
7604
|
console.log("To initialize a git repository, run:");
|
|
7648
|
-
console.log(` ${
|
|
7605
|
+
console.log(` ${chalk28.cyan("git init")}`);
|
|
7649
7606
|
process.exit(1);
|
|
7650
7607
|
}
|
|
7651
|
-
console.log(
|
|
7608
|
+
console.log(chalk28.green("\u2713 Git repository detected"));
|
|
7652
7609
|
if (!isGhInstalled()) {
|
|
7653
|
-
console.log(
|
|
7610
|
+
console.log(chalk28.red("\u2717 GitHub CLI (gh) is not installed"));
|
|
7654
7611
|
console.log();
|
|
7655
7612
|
console.log("GitHub CLI is required for this command.");
|
|
7656
7613
|
console.log();
|
|
7657
|
-
console.log(` macOS: ${
|
|
7658
|
-
console.log(` Other: ${
|
|
7614
|
+
console.log(` macOS: ${chalk28.cyan("brew install gh")}`);
|
|
7615
|
+
console.log(` Other: ${chalk28.cyan("https://cli.github.com/")}`);
|
|
7659
7616
|
console.log();
|
|
7660
7617
|
console.log("After installation, run:");
|
|
7661
|
-
console.log(` ${
|
|
7618
|
+
console.log(` ${chalk28.cyan("gh auth login")}`);
|
|
7662
7619
|
console.log();
|
|
7663
7620
|
console.log("Then try again:");
|
|
7664
|
-
console.log(` ${
|
|
7621
|
+
console.log(` ${chalk28.cyan("vm0 setup-github")}`);
|
|
7665
7622
|
process.exit(1);
|
|
7666
7623
|
}
|
|
7667
|
-
console.log(
|
|
7624
|
+
console.log(chalk28.green("\u2713 GitHub CLI (gh) is installed"));
|
|
7668
7625
|
if (!isGhAuthenticated()) {
|
|
7669
|
-
console.log(
|
|
7626
|
+
console.log(chalk28.red("\u2717 GitHub CLI is not authenticated"));
|
|
7670
7627
|
console.log();
|
|
7671
7628
|
console.log("Please authenticate GitHub CLI first:");
|
|
7672
|
-
console.log(` ${
|
|
7629
|
+
console.log(` ${chalk28.cyan("gh auth login")}`);
|
|
7673
7630
|
console.log();
|
|
7674
7631
|
console.log("Then try again:");
|
|
7675
|
-
console.log(` ${
|
|
7632
|
+
console.log(` ${chalk28.cyan("vm0 setup-github")}`);
|
|
7676
7633
|
process.exit(1);
|
|
7677
7634
|
}
|
|
7678
|
-
console.log(
|
|
7635
|
+
console.log(chalk28.green("\u2713 GitHub CLI is authenticated"));
|
|
7679
7636
|
const token = await getToken();
|
|
7680
7637
|
if (!token) {
|
|
7681
|
-
console.log(
|
|
7638
|
+
console.log(chalk28.red("\u2717 VM0 not authenticated"));
|
|
7682
7639
|
console.log();
|
|
7683
7640
|
console.log("Please authenticate with VM0 first:");
|
|
7684
|
-
console.log(` ${
|
|
7641
|
+
console.log(` ${chalk28.cyan("vm0 auth login")}`);
|
|
7685
7642
|
console.log();
|
|
7686
7643
|
console.log("Then try again:");
|
|
7687
|
-
console.log(` ${
|
|
7644
|
+
console.log(` ${chalk28.cyan("vm0 setup-github")}`);
|
|
7688
7645
|
process.exit(1);
|
|
7689
7646
|
}
|
|
7690
|
-
console.log(
|
|
7647
|
+
console.log(chalk28.green("\u2713 VM0 authenticated"));
|
|
7691
7648
|
if (!existsSync10("vm0.yaml")) {
|
|
7692
|
-
console.log(
|
|
7649
|
+
console.log(chalk28.red("\u2717 vm0.yaml not found"));
|
|
7693
7650
|
console.log();
|
|
7694
7651
|
console.log("This command requires a vm0.yaml configuration file.");
|
|
7695
7652
|
console.log();
|
|
7696
7653
|
console.log("To create one, run:");
|
|
7697
|
-
console.log(` ${
|
|
7654
|
+
console.log(` ${chalk28.cyan("vm0 init")}`);
|
|
7698
7655
|
console.log();
|
|
7699
7656
|
console.log("Then try again:");
|
|
7700
|
-
console.log(` ${
|
|
7657
|
+
console.log(` ${chalk28.cyan("vm0 setup-github")}`);
|
|
7701
7658
|
process.exit(1);
|
|
7702
7659
|
}
|
|
7703
|
-
console.log(
|
|
7660
|
+
console.log(chalk28.green("\u2713 vm0.yaml found"));
|
|
7704
7661
|
return { token, gitRoot };
|
|
7705
7662
|
}
|
|
7706
7663
|
function generatePublishYaml(workingDir) {
|
|
@@ -7857,7 +7814,7 @@ function displaySecretsTable(secretStatuses, varStatuses) {
|
|
|
7857
7814
|
if (secretStatuses.length > 0) {
|
|
7858
7815
|
console.log("\u2502 Secrets: \u2502");
|
|
7859
7816
|
for (const s of secretStatuses) {
|
|
7860
|
-
const status = s.found ?
|
|
7817
|
+
const status = s.found ? chalk28.green("\u2713") : chalk28.red("\u2717");
|
|
7861
7818
|
const source = s.found ? `(from ${s.source})` : "not found";
|
|
7862
7819
|
const paddedName = (s.name + " ").padEnd(23, ".");
|
|
7863
7820
|
console.log(`\u2502 ${status} ${paddedName} ${source.padEnd(19)}\u2502`);
|
|
@@ -7866,7 +7823,7 @@ function displaySecretsTable(secretStatuses, varStatuses) {
|
|
|
7866
7823
|
if (varStatuses.length > 0) {
|
|
7867
7824
|
console.log("\u2502 Variables: \u2502");
|
|
7868
7825
|
for (const v of varStatuses) {
|
|
7869
|
-
const status = v.found ?
|
|
7826
|
+
const status = v.found ? chalk28.green("\u2713") : chalk28.red("\u2717");
|
|
7870
7827
|
const source = v.found ? `(from ${v.source})` : "not found";
|
|
7871
7828
|
const paddedName = (v.name + " ").padEnd(23, ".");
|
|
7872
7829
|
console.log(`\u2502 ${status} ${paddedName} ${source.padEnd(19)}\u2502`);
|
|
@@ -7878,17 +7835,17 @@ function showManualSetupInstructions(secrets, vars) {
|
|
|
7878
7835
|
console.log("Skipped automatic setup. Configure secrets manually:");
|
|
7879
7836
|
console.log();
|
|
7880
7837
|
console.log(" Step 1: Get your VM0 token");
|
|
7881
|
-
console.log(` ${
|
|
7838
|
+
console.log(` ${chalk28.cyan("vm0 auth setup-token")}`);
|
|
7882
7839
|
console.log();
|
|
7883
7840
|
console.log(" Step 2: Set GitHub secrets");
|
|
7884
7841
|
for (const s of secrets) {
|
|
7885
|
-
console.log(` ${
|
|
7842
|
+
console.log(` ${chalk28.cyan(`gh secret set ${s}`)}`);
|
|
7886
7843
|
}
|
|
7887
7844
|
if (vars.length > 0) {
|
|
7888
7845
|
console.log();
|
|
7889
7846
|
console.log(" Step 3: Set GitHub variables");
|
|
7890
7847
|
for (const v of vars) {
|
|
7891
|
-
console.log(` ${
|
|
7848
|
+
console.log(` ${chalk28.cyan(`gh variable set ${v}`)}`);
|
|
7892
7849
|
}
|
|
7893
7850
|
}
|
|
7894
7851
|
}
|
|
@@ -7945,10 +7902,10 @@ var setupGithubCommand = new Command26().name("setup-github").description("Initi
|
|
|
7945
7902
|
const config = parseYaml5(content);
|
|
7946
7903
|
const agents = config.agents;
|
|
7947
7904
|
const agentName = Object.keys(agents)[0];
|
|
7948
|
-
console.log(
|
|
7905
|
+
console.log(chalk28.green(`\u2713 Agent: ${agentName}`));
|
|
7949
7906
|
const { secrets, vars } = extractSecretsAndVars(config);
|
|
7950
7907
|
console.log(
|
|
7951
|
-
|
|
7908
|
+
chalk28.green(
|
|
7952
7909
|
`\u2713 Found ${secrets.length} secrets, ${vars.length} variables`
|
|
7953
7910
|
)
|
|
7954
7911
|
);
|
|
@@ -7961,7 +7918,7 @@ var setupGithubCommand = new Command26().name("setup-github").description("Initi
|
|
|
7961
7918
|
if (existsSync10(publishPath)) existingFiles.push(displayPublishPath);
|
|
7962
7919
|
if (existsSync10(runPath)) existingFiles.push(displayRunPath);
|
|
7963
7920
|
if (existingFiles.length > 0 && !options.force) {
|
|
7964
|
-
console.log(
|
|
7921
|
+
console.log(chalk28.yellow("\u26A0 Existing workflow files detected:"));
|
|
7965
7922
|
for (const file of existingFiles) {
|
|
7966
7923
|
console.log(` \u2022 ${file}`);
|
|
7967
7924
|
}
|
|
@@ -7974,7 +7931,7 @@ var setupGithubCommand = new Command26().name("setup-github").description("Initi
|
|
|
7974
7931
|
if (!overwrite) {
|
|
7975
7932
|
console.log();
|
|
7976
7933
|
console.log("Aborted. To force overwrite, run:");
|
|
7977
|
-
console.log(` ${
|
|
7934
|
+
console.log(` ${chalk28.cyan("vm0 setup-github --force")}`);
|
|
7978
7935
|
process.exit(0);
|
|
7979
7936
|
}
|
|
7980
7937
|
}
|
|
@@ -7984,13 +7941,13 @@ var setupGithubCommand = new Command26().name("setup-github").description("Initi
|
|
|
7984
7941
|
await mkdir7(path15.join(gitRoot, ".github/workflows"), { recursive: true });
|
|
7985
7942
|
await writeFile8(publishPath, generatePublishYaml(workingDir));
|
|
7986
7943
|
const publishStatus = existingFiles.includes(displayPublishPath) ? "Overwrote" : "Created";
|
|
7987
|
-
console.log(
|
|
7944
|
+
console.log(chalk28.green(`\u2713 ${publishStatus} ${displayPublishPath}`));
|
|
7988
7945
|
await writeFile8(runPath, generateRunYaml(agentName, secrets, vars));
|
|
7989
7946
|
const runStatus = existingFiles.includes(displayRunPath) ? "Overwrote" : "Created";
|
|
7990
|
-
console.log(
|
|
7947
|
+
console.log(chalk28.green(`\u2713 ${runStatus} ${displayRunPath}`));
|
|
7991
7948
|
console.log();
|
|
7992
7949
|
if (options.skipSecrets) {
|
|
7993
|
-
console.log(
|
|
7950
|
+
console.log(chalk28.green("\u2713 Done (secrets setup skipped)"));
|
|
7994
7951
|
return;
|
|
7995
7952
|
}
|
|
7996
7953
|
const { secretStatuses, varStatuses } = await detectSecretValues(
|
|
@@ -8030,14 +7987,14 @@ var setupGithubCommand = new Command26().name("setup-github").description("Initi
|
|
|
8030
7987
|
if (s.found && s.value) {
|
|
8031
7988
|
const success = setGitHubSecret(s.name, s.value);
|
|
8032
7989
|
if (success) {
|
|
8033
|
-
console.log(` ${
|
|
7990
|
+
console.log(` ${chalk28.green("\u2713")} ${s.name}`);
|
|
8034
7991
|
} else {
|
|
8035
|
-
console.log(` ${
|
|
7992
|
+
console.log(` ${chalk28.red("\u2717")} ${s.name} (failed)`);
|
|
8036
7993
|
failedSecrets.push(s.name);
|
|
8037
7994
|
}
|
|
8038
7995
|
} else {
|
|
8039
7996
|
console.log(
|
|
8040
|
-
` ${
|
|
7997
|
+
` ${chalk28.yellow("\u26A0")} ${s.name} (skipped - not found)`
|
|
8041
7998
|
);
|
|
8042
7999
|
}
|
|
8043
8000
|
}
|
|
@@ -8049,14 +8006,14 @@ var setupGithubCommand = new Command26().name("setup-github").description("Initi
|
|
|
8049
8006
|
if (v.found && v.value) {
|
|
8050
8007
|
const success = setGitHubVariable(v.name, v.value);
|
|
8051
8008
|
if (success) {
|
|
8052
|
-
console.log(` ${
|
|
8009
|
+
console.log(` ${chalk28.green("\u2713")} ${v.name}`);
|
|
8053
8010
|
} else {
|
|
8054
|
-
console.log(` ${
|
|
8011
|
+
console.log(` ${chalk28.red("\u2717")} ${v.name} (failed)`);
|
|
8055
8012
|
failedVars.push(v.name);
|
|
8056
8013
|
}
|
|
8057
8014
|
} else {
|
|
8058
8015
|
console.log(
|
|
8059
|
-
` ${
|
|
8016
|
+
` ${chalk28.yellow("\u26A0")} ${v.name} (skipped - not found)`
|
|
8060
8017
|
);
|
|
8061
8018
|
}
|
|
8062
8019
|
}
|
|
@@ -8083,7 +8040,7 @@ import { Command as Command34 } from "commander";
|
|
|
8083
8040
|
|
|
8084
8041
|
// src/commands/schedule/init.ts
|
|
8085
8042
|
import { Command as Command27 } from "commander";
|
|
8086
|
-
import
|
|
8043
|
+
import chalk29 from "chalk";
|
|
8087
8044
|
import { existsSync as existsSync12, writeFileSync } from "fs";
|
|
8088
8045
|
import { stringify as stringifyYaml2 } from "yaml";
|
|
8089
8046
|
|
|
@@ -8312,20 +8269,20 @@ var initCommand4 = new Command27().name("init").description("Create a schedule.y
|
|
|
8312
8269
|
try {
|
|
8313
8270
|
const { agentName, error } = loadAgentName();
|
|
8314
8271
|
if (error) {
|
|
8315
|
-
console.error(
|
|
8272
|
+
console.error(chalk29.red(`\u2717 Invalid vm0.yaml: ${error}`));
|
|
8316
8273
|
process.exit(1);
|
|
8317
8274
|
}
|
|
8318
8275
|
if (!agentName) {
|
|
8319
|
-
console.error(
|
|
8276
|
+
console.error(chalk29.red("\u2717 No vm0.yaml found"));
|
|
8320
8277
|
console.error(
|
|
8321
|
-
|
|
8278
|
+
chalk29.dim(" Run this command from an agent directory")
|
|
8322
8279
|
);
|
|
8323
8280
|
process.exit(1);
|
|
8324
8281
|
}
|
|
8325
8282
|
if (existsSync12(SCHEDULE_FILE) && !options.force) {
|
|
8326
8283
|
if (!isInteractive()) {
|
|
8327
|
-
console.error(
|
|
8328
|
-
console.error(
|
|
8284
|
+
console.error(chalk29.red("\u2717 schedule.yaml already exists"));
|
|
8285
|
+
console.error(chalk29.dim(" Use --force to overwrite"));
|
|
8329
8286
|
process.exit(1);
|
|
8330
8287
|
}
|
|
8331
8288
|
const overwrite = await promptConfirm(
|
|
@@ -8333,7 +8290,7 @@ var initCommand4 = new Command27().name("init").description("Create a schedule.y
|
|
|
8333
8290
|
false
|
|
8334
8291
|
);
|
|
8335
8292
|
if (!overwrite) {
|
|
8336
|
-
console.log(
|
|
8293
|
+
console.log(chalk29.dim("Cancelled"));
|
|
8337
8294
|
return;
|
|
8338
8295
|
}
|
|
8339
8296
|
}
|
|
@@ -8341,7 +8298,7 @@ var initCommand4 = new Command27().name("init").description("Create a schedule.y
|
|
|
8341
8298
|
if (!scheduleName) {
|
|
8342
8299
|
if (!isInteractive()) {
|
|
8343
8300
|
console.error(
|
|
8344
|
-
|
|
8301
|
+
chalk29.red("\u2717 --name is required in non-interactive mode")
|
|
8345
8302
|
);
|
|
8346
8303
|
process.exit(1);
|
|
8347
8304
|
}
|
|
@@ -8350,7 +8307,7 @@ var initCommand4 = new Command27().name("init").description("Create a schedule.y
|
|
|
8350
8307
|
`${agentName}-schedule`
|
|
8351
8308
|
);
|
|
8352
8309
|
if (!scheduleName) {
|
|
8353
|
-
console.log(
|
|
8310
|
+
console.log(chalk29.dim("Cancelled"));
|
|
8354
8311
|
return;
|
|
8355
8312
|
}
|
|
8356
8313
|
}
|
|
@@ -8358,7 +8315,7 @@ var initCommand4 = new Command27().name("init").description("Create a schedule.y
|
|
|
8358
8315
|
if (!frequency || !["daily", "weekly", "monthly", "once"].includes(frequency)) {
|
|
8359
8316
|
if (!isInteractive()) {
|
|
8360
8317
|
console.error(
|
|
8361
|
-
|
|
8318
|
+
chalk29.red(
|
|
8362
8319
|
"\u2717 --frequency is required (daily|weekly|monthly|once)"
|
|
8363
8320
|
)
|
|
8364
8321
|
);
|
|
@@ -8370,7 +8327,7 @@ var initCommand4 = new Command27().name("init").description("Create a schedule.y
|
|
|
8370
8327
|
0
|
|
8371
8328
|
);
|
|
8372
8329
|
if (!frequency) {
|
|
8373
|
-
console.log(
|
|
8330
|
+
console.log(chalk29.dim("Cancelled"));
|
|
8374
8331
|
return;
|
|
8375
8332
|
}
|
|
8376
8333
|
}
|
|
@@ -8380,7 +8337,7 @@ var initCommand4 = new Command27().name("init").description("Create a schedule.y
|
|
|
8380
8337
|
day = parseDayOption(options.day, frequency);
|
|
8381
8338
|
if (day === void 0) {
|
|
8382
8339
|
console.error(
|
|
8383
|
-
|
|
8340
|
+
chalk29.red(
|
|
8384
8341
|
`\u2717 Invalid day: ${options.day}. Use mon-sun for weekly or 1-31 for monthly.`
|
|
8385
8342
|
)
|
|
8386
8343
|
);
|
|
@@ -8390,23 +8347,23 @@ var initCommand4 = new Command27().name("init").description("Create a schedule.y
|
|
|
8390
8347
|
if (frequency === "weekly") {
|
|
8391
8348
|
day = await promptSelect("Day of week", DAY_OF_WEEK_CHOICES, 0);
|
|
8392
8349
|
if (day === void 0) {
|
|
8393
|
-
console.log(
|
|
8350
|
+
console.log(chalk29.dim("Cancelled"));
|
|
8394
8351
|
return;
|
|
8395
8352
|
}
|
|
8396
8353
|
} else {
|
|
8397
8354
|
const dayStr = await promptText("Day of month (1-31)", "1");
|
|
8398
8355
|
if (!dayStr) {
|
|
8399
|
-
console.log(
|
|
8356
|
+
console.log(chalk29.dim("Cancelled"));
|
|
8400
8357
|
return;
|
|
8401
8358
|
}
|
|
8402
8359
|
day = parseInt(dayStr, 10);
|
|
8403
8360
|
if (isNaN(day) || day < 1 || day > 31) {
|
|
8404
|
-
console.error(
|
|
8361
|
+
console.error(chalk29.red("\u2717 Day must be between 1 and 31"));
|
|
8405
8362
|
process.exit(1);
|
|
8406
8363
|
}
|
|
8407
8364
|
}
|
|
8408
8365
|
} else {
|
|
8409
|
-
console.error(
|
|
8366
|
+
console.error(chalk29.red("\u2717 --day is required for weekly/monthly"));
|
|
8410
8367
|
process.exit(1);
|
|
8411
8368
|
}
|
|
8412
8369
|
}
|
|
@@ -8415,22 +8372,21 @@ var initCommand4 = new Command27().name("init").description("Create a schedule.y
|
|
|
8415
8372
|
if (frequency === "once") {
|
|
8416
8373
|
if (!isInteractive()) {
|
|
8417
8374
|
console.error(
|
|
8418
|
-
|
|
8375
|
+
chalk29.red("\u2717 One-time schedules require interactive mode")
|
|
8419
8376
|
);
|
|
8420
8377
|
console.error(
|
|
8421
|
-
|
|
8378
|
+
chalk29.dim(" Use cron frequency for non-interactive mode")
|
|
8422
8379
|
);
|
|
8423
8380
|
process.exit(1);
|
|
8424
8381
|
}
|
|
8425
8382
|
const tomorrowDate = getTomorrowDateLocal();
|
|
8426
|
-
const date = await
|
|
8427
|
-
"Date (YYYY-MM-DD)",
|
|
8428
|
-
"tomorrow",
|
|
8383
|
+
const date = await promptText(
|
|
8384
|
+
"Date (YYYY-MM-DD, default tomorrow)",
|
|
8429
8385
|
tomorrowDate,
|
|
8430
8386
|
validateDateFormat
|
|
8431
8387
|
);
|
|
8432
8388
|
if (!date) {
|
|
8433
|
-
console.log(
|
|
8389
|
+
console.log(chalk29.dim("Cancelled"));
|
|
8434
8390
|
return;
|
|
8435
8391
|
}
|
|
8436
8392
|
const currentTime = getCurrentTimeLocal();
|
|
@@ -8440,7 +8396,7 @@ var initCommand4 = new Command27().name("init").description("Create a schedule.y
|
|
|
8440
8396
|
validateTimeFormat
|
|
8441
8397
|
);
|
|
8442
8398
|
if (!time) {
|
|
8443
|
-
console.log(
|
|
8399
|
+
console.log(chalk29.dim("Cancelled"));
|
|
8444
8400
|
return;
|
|
8445
8401
|
}
|
|
8446
8402
|
const dateStr = `${date} ${time}`;
|
|
@@ -8448,7 +8404,7 @@ var initCommand4 = new Command27().name("init").description("Create a schedule.y
|
|
|
8448
8404
|
} else {
|
|
8449
8405
|
if (!time) {
|
|
8450
8406
|
if (!isInteractive()) {
|
|
8451
|
-
console.error(
|
|
8407
|
+
console.error(chalk29.red("\u2717 --time is required (HH:MM format)"));
|
|
8452
8408
|
process.exit(1);
|
|
8453
8409
|
}
|
|
8454
8410
|
time = await promptText(
|
|
@@ -8457,13 +8413,13 @@ var initCommand4 = new Command27().name("init").description("Create a schedule.y
|
|
|
8457
8413
|
validateTimeFormat
|
|
8458
8414
|
);
|
|
8459
8415
|
if (!time) {
|
|
8460
|
-
console.log(
|
|
8416
|
+
console.log(chalk29.dim("Cancelled"));
|
|
8461
8417
|
return;
|
|
8462
8418
|
}
|
|
8463
8419
|
} else {
|
|
8464
8420
|
const validation = validateTimeFormat(time);
|
|
8465
8421
|
if (validation !== true) {
|
|
8466
|
-
console.error(
|
|
8422
|
+
console.error(chalk29.red(`\u2717 Invalid time: ${validation}`));
|
|
8467
8423
|
process.exit(1);
|
|
8468
8424
|
}
|
|
8469
8425
|
}
|
|
@@ -8474,7 +8430,7 @@ var initCommand4 = new Command27().name("init").description("Create a schedule.y
|
|
|
8474
8430
|
if (isInteractive()) {
|
|
8475
8431
|
timezone = await promptText("Timezone", detectedTimezone);
|
|
8476
8432
|
if (!timezone) {
|
|
8477
|
-
console.log(
|
|
8433
|
+
console.log(chalk29.dim("Cancelled"));
|
|
8478
8434
|
return;
|
|
8479
8435
|
}
|
|
8480
8436
|
} else {
|
|
@@ -8484,7 +8440,7 @@ var initCommand4 = new Command27().name("init").description("Create a schedule.y
|
|
|
8484
8440
|
let promptText_ = options.prompt;
|
|
8485
8441
|
if (!promptText_) {
|
|
8486
8442
|
if (!isInteractive()) {
|
|
8487
|
-
console.error(
|
|
8443
|
+
console.error(chalk29.red("\u2717 --prompt is required"));
|
|
8488
8444
|
process.exit(1);
|
|
8489
8445
|
}
|
|
8490
8446
|
promptText_ = await promptText(
|
|
@@ -8492,7 +8448,7 @@ var initCommand4 = new Command27().name("init").description("Create a schedule.y
|
|
|
8492
8448
|
"let's start working."
|
|
8493
8449
|
);
|
|
8494
8450
|
if (!promptText_) {
|
|
8495
|
-
console.log(
|
|
8451
|
+
console.log(chalk29.dim("Cancelled"));
|
|
8496
8452
|
return;
|
|
8497
8453
|
}
|
|
8498
8454
|
}
|
|
@@ -8559,12 +8515,12 @@ var initCommand4 = new Command27().name("init").description("Create a schedule.y
|
|
|
8559
8515
|
scheduleYaml.schedules[scheduleName].run.secrets = secrets;
|
|
8560
8516
|
}
|
|
8561
8517
|
writeFileSync(SCHEDULE_FILE, stringifyYaml2(scheduleYaml));
|
|
8562
|
-
console.log(
|
|
8563
|
-
console.log(
|
|
8518
|
+
console.log(chalk29.green(`\u2713 Created ${SCHEDULE_FILE}`));
|
|
8519
|
+
console.log(chalk29.dim(" Deploy with: vm0 schedule deploy"));
|
|
8564
8520
|
} catch (error) {
|
|
8565
|
-
console.error(
|
|
8521
|
+
console.error(chalk29.red("\u2717 Failed to create schedule.yaml"));
|
|
8566
8522
|
if (error instanceof Error) {
|
|
8567
|
-
console.error(
|
|
8523
|
+
console.error(chalk29.dim(` ${error.message}`));
|
|
8568
8524
|
}
|
|
8569
8525
|
process.exit(1);
|
|
8570
8526
|
}
|
|
@@ -8573,7 +8529,7 @@ var initCommand4 = new Command27().name("init").description("Create a schedule.y
|
|
|
8573
8529
|
|
|
8574
8530
|
// src/commands/schedule/deploy.ts
|
|
8575
8531
|
import { Command as Command28 } from "commander";
|
|
8576
|
-
import
|
|
8532
|
+
import chalk30 from "chalk";
|
|
8577
8533
|
import { existsSync as existsSync13, readFileSync as readFileSync3 } from "fs";
|
|
8578
8534
|
import { parse as parseYaml7 } from "yaml";
|
|
8579
8535
|
function expandEnvVars(value) {
|
|
@@ -8581,7 +8537,7 @@ function expandEnvVars(value) {
|
|
|
8581
8537
|
const envValue = process.env[varName];
|
|
8582
8538
|
if (envValue === void 0) {
|
|
8583
8539
|
console.warn(
|
|
8584
|
-
|
|
8540
|
+
chalk30.yellow(` Warning: Environment variable ${varName} not set`)
|
|
8585
8541
|
);
|
|
8586
8542
|
return match;
|
|
8587
8543
|
}
|
|
@@ -8596,11 +8552,25 @@ function expandEnvVarsInObject(obj) {
|
|
|
8596
8552
|
}
|
|
8597
8553
|
return result;
|
|
8598
8554
|
}
|
|
8555
|
+
function formatInTimezone(isoDate, timezone) {
|
|
8556
|
+
const date = new Date(isoDate);
|
|
8557
|
+
const parts = new Intl.DateTimeFormat("en-CA", {
|
|
8558
|
+
timeZone: timezone,
|
|
8559
|
+
year: "numeric",
|
|
8560
|
+
month: "2-digit",
|
|
8561
|
+
day: "2-digit",
|
|
8562
|
+
hour: "2-digit",
|
|
8563
|
+
minute: "2-digit",
|
|
8564
|
+
hour12: false
|
|
8565
|
+
}).formatToParts(date);
|
|
8566
|
+
const get = (type) => parts.find((p) => p.type === type)?.value ?? "";
|
|
8567
|
+
return `${get("year")}-${get("month")}-${get("day")} ${get("hour")}:${get("minute")}`;
|
|
8568
|
+
}
|
|
8599
8569
|
var deployCommand = new Command28().name("deploy").description("Deploy a schedule from schedule.yaml (create or update)").argument("[file]", "Path to schedule.yaml", "schedule.yaml").action(async (file) => {
|
|
8600
8570
|
try {
|
|
8601
8571
|
if (!existsSync13(file)) {
|
|
8602
|
-
console.error(
|
|
8603
|
-
console.error(
|
|
8572
|
+
console.error(chalk30.red(`\u2717 File not found: ${file}`));
|
|
8573
|
+
console.error(chalk30.dim(" Create a schedule.yaml file first"));
|
|
8604
8574
|
process.exit(1);
|
|
8605
8575
|
}
|
|
8606
8576
|
const content = readFileSync3(file, "utf-8");
|
|
@@ -8608,18 +8578,18 @@ var deployCommand = new Command28().name("deploy").description("Deploy a schedul
|
|
|
8608
8578
|
try {
|
|
8609
8579
|
parsed = parseYaml7(content);
|
|
8610
8580
|
} catch (err) {
|
|
8611
|
-
console.error(
|
|
8581
|
+
console.error(chalk30.red("\u2717 Invalid YAML syntax"));
|
|
8612
8582
|
if (err instanceof Error) {
|
|
8613
|
-
console.error(
|
|
8583
|
+
console.error(chalk30.dim(` ${err.message}`));
|
|
8614
8584
|
}
|
|
8615
8585
|
process.exit(1);
|
|
8616
8586
|
}
|
|
8617
8587
|
const result = scheduleYamlSchema.safeParse(parsed);
|
|
8618
8588
|
if (!result.success) {
|
|
8619
|
-
console.error(
|
|
8589
|
+
console.error(chalk30.red("\u2717 Invalid schedule.yaml format"));
|
|
8620
8590
|
for (const issue of result.error.issues) {
|
|
8621
8591
|
console.error(
|
|
8622
|
-
|
|
8592
|
+
chalk30.dim(` ${issue.path.join(".")}: ${issue.message}`)
|
|
8623
8593
|
);
|
|
8624
8594
|
}
|
|
8625
8595
|
process.exit(1);
|
|
@@ -8627,18 +8597,18 @@ var deployCommand = new Command28().name("deploy").description("Deploy a schedul
|
|
|
8627
8597
|
const scheduleYaml = result.data;
|
|
8628
8598
|
const scheduleEntries = Object.entries(scheduleYaml.schedules);
|
|
8629
8599
|
if (scheduleEntries.length === 0) {
|
|
8630
|
-
console.error(
|
|
8600
|
+
console.error(chalk30.red("\u2717 No schedules defined in file"));
|
|
8631
8601
|
process.exit(1);
|
|
8632
8602
|
}
|
|
8633
8603
|
if (scheduleEntries.length > 1) {
|
|
8634
8604
|
console.error(
|
|
8635
|
-
|
|
8605
|
+
chalk30.red("\u2717 Multiple schedules per file not supported yet")
|
|
8636
8606
|
);
|
|
8637
|
-
console.error(
|
|
8607
|
+
console.error(chalk30.dim(" Please use one schedule per file"));
|
|
8638
8608
|
process.exit(1);
|
|
8639
8609
|
}
|
|
8640
8610
|
const [scheduleName, schedule] = scheduleEntries[0];
|
|
8641
|
-
console.log(`Deploying schedule ${
|
|
8611
|
+
console.log(`Deploying schedule ${chalk30.cyan(scheduleName)}...`);
|
|
8642
8612
|
const agentRef = schedule.run.agent;
|
|
8643
8613
|
let composeId;
|
|
8644
8614
|
try {
|
|
@@ -8647,8 +8617,8 @@ var deployCommand = new Command28().name("deploy").description("Deploy a schedul
|
|
|
8647
8617
|
const compose = await apiClient.getComposeByName(agentName);
|
|
8648
8618
|
composeId = compose.id;
|
|
8649
8619
|
} catch {
|
|
8650
|
-
console.error(
|
|
8651
|
-
console.error(
|
|
8620
|
+
console.error(chalk30.red(`\u2717 Agent not found: ${agentRef}`));
|
|
8621
|
+
console.error(chalk30.dim(" Make sure the agent is pushed first"));
|
|
8652
8622
|
process.exit(1);
|
|
8653
8623
|
}
|
|
8654
8624
|
const expandedVars = expandEnvVarsInObject(schedule.run.vars);
|
|
@@ -8677,33 +8647,39 @@ var deployCommand = new Command28().name("deploy").description("Deploy a schedul
|
|
|
8677
8647
|
const deployResult = await response.json();
|
|
8678
8648
|
if (deployResult.created) {
|
|
8679
8649
|
console.log(
|
|
8680
|
-
|
|
8650
|
+
chalk30.green(`\u2713 Created schedule ${chalk30.cyan(scheduleName)}`)
|
|
8681
8651
|
);
|
|
8682
8652
|
} else {
|
|
8683
8653
|
console.log(
|
|
8684
|
-
|
|
8654
|
+
chalk30.green(`\u2713 Updated schedule ${chalk30.cyan(scheduleName)}`)
|
|
8685
8655
|
);
|
|
8686
8656
|
}
|
|
8687
|
-
|
|
8688
|
-
const nextRun = new Date(deployResult.schedule.nextRunAt);
|
|
8689
|
-
console.log(chalk31.dim(` Next run: ${nextRun.toLocaleString()}`));
|
|
8690
|
-
}
|
|
8657
|
+
console.log(chalk30.dim(` Timezone: ${deployResult.schedule.timezone}`));
|
|
8691
8658
|
if (deployResult.schedule.cronExpression) {
|
|
8692
8659
|
console.log(
|
|
8693
|
-
|
|
8694
|
-
` Cron: ${deployResult.schedule.cronExpression} (${deployResult.schedule.timezone})`
|
|
8695
|
-
)
|
|
8660
|
+
chalk30.dim(` Cron: ${deployResult.schedule.cronExpression}`)
|
|
8696
8661
|
);
|
|
8662
|
+
if (deployResult.schedule.nextRunAt) {
|
|
8663
|
+
const nextRun = formatInTimezone(
|
|
8664
|
+
deployResult.schedule.nextRunAt,
|
|
8665
|
+
deployResult.schedule.timezone
|
|
8666
|
+
);
|
|
8667
|
+
console.log(chalk30.dim(` Next run: ${nextRun}`));
|
|
8668
|
+
}
|
|
8697
8669
|
} else if (deployResult.schedule.atTime) {
|
|
8698
|
-
|
|
8670
|
+
const atTime2 = formatInTimezone(
|
|
8671
|
+
deployResult.schedule.atTime,
|
|
8672
|
+
deployResult.schedule.timezone
|
|
8673
|
+
);
|
|
8674
|
+
console.log(chalk30.dim(` At: ${atTime2}`));
|
|
8699
8675
|
}
|
|
8700
8676
|
} catch (error) {
|
|
8701
|
-
console.error(
|
|
8677
|
+
console.error(chalk30.red("\u2717 Failed to deploy schedule"));
|
|
8702
8678
|
if (error instanceof Error) {
|
|
8703
8679
|
if (error.message.includes("Not authenticated")) {
|
|
8704
|
-
console.error(
|
|
8680
|
+
console.error(chalk30.dim(" Run: vm0 auth login"));
|
|
8705
8681
|
} else {
|
|
8706
|
-
console.error(
|
|
8682
|
+
console.error(chalk30.dim(` ${error.message}`));
|
|
8707
8683
|
}
|
|
8708
8684
|
}
|
|
8709
8685
|
process.exit(1);
|
|
@@ -8712,7 +8688,7 @@ var deployCommand = new Command28().name("deploy").description("Deploy a schedul
|
|
|
8712
8688
|
|
|
8713
8689
|
// src/commands/schedule/list.ts
|
|
8714
8690
|
import { Command as Command29 } from "commander";
|
|
8715
|
-
import
|
|
8691
|
+
import chalk31 from "chalk";
|
|
8716
8692
|
var listCommand4 = new Command29().name("list").alias("ls").description("List all schedules").action(async () => {
|
|
8717
8693
|
try {
|
|
8718
8694
|
const response = await apiClient.get("/api/agent/schedules");
|
|
@@ -8722,9 +8698,9 @@ var listCommand4 = new Command29().name("list").alias("ls").description("List al
|
|
|
8722
8698
|
}
|
|
8723
8699
|
const result = await response.json();
|
|
8724
8700
|
if (result.schedules.length === 0) {
|
|
8725
|
-
console.log(
|
|
8701
|
+
console.log(chalk31.dim("No schedules found"));
|
|
8726
8702
|
console.log(
|
|
8727
|
-
|
|
8703
|
+
chalk31.dim(" Create one with: vm0 schedule deploy schedule.yaml")
|
|
8728
8704
|
);
|
|
8729
8705
|
return;
|
|
8730
8706
|
}
|
|
@@ -8749,10 +8725,10 @@ var listCommand4 = new Command29().name("list").alias("ls").description("List al
|
|
|
8749
8725
|
"STATUS".padEnd(8),
|
|
8750
8726
|
"NEXT RUN"
|
|
8751
8727
|
].join(" ");
|
|
8752
|
-
console.log(
|
|
8728
|
+
console.log(chalk31.dim(header));
|
|
8753
8729
|
for (const schedule of result.schedules) {
|
|
8754
8730
|
const trigger = schedule.cronExpression ? `${schedule.cronExpression} (${schedule.timezone})` : schedule.atTime || "-";
|
|
8755
|
-
const status = schedule.enabled ?
|
|
8731
|
+
const status = schedule.enabled ? chalk31.green("enabled") : chalk31.yellow("disabled");
|
|
8756
8732
|
const nextRun = schedule.enabled ? formatRelativeTime2(schedule.nextRunAt) : "-";
|
|
8757
8733
|
const row = [
|
|
8758
8734
|
schedule.name.padEnd(nameWidth),
|
|
@@ -8765,12 +8741,12 @@ var listCommand4 = new Command29().name("list").alias("ls").description("List al
|
|
|
8765
8741
|
console.log(row);
|
|
8766
8742
|
}
|
|
8767
8743
|
} catch (error) {
|
|
8768
|
-
console.error(
|
|
8744
|
+
console.error(chalk31.red("\u2717 Failed to list schedules"));
|
|
8769
8745
|
if (error instanceof Error) {
|
|
8770
8746
|
if (error.message.includes("Not authenticated")) {
|
|
8771
|
-
console.error(
|
|
8747
|
+
console.error(chalk31.dim(" Run: vm0 auth login"));
|
|
8772
8748
|
} else {
|
|
8773
|
-
console.error(
|
|
8749
|
+
console.error(chalk31.dim(` ${error.message}`));
|
|
8774
8750
|
}
|
|
8775
8751
|
}
|
|
8776
8752
|
process.exit(1);
|
|
@@ -8779,32 +8755,32 @@ var listCommand4 = new Command29().name("list").alias("ls").description("List al
|
|
|
8779
8755
|
|
|
8780
8756
|
// src/commands/schedule/status.ts
|
|
8781
8757
|
import { Command as Command30 } from "commander";
|
|
8782
|
-
import
|
|
8758
|
+
import chalk32 from "chalk";
|
|
8783
8759
|
function formatDateTimeStyled(dateStr) {
|
|
8784
|
-
if (!dateStr) return
|
|
8760
|
+
if (!dateStr) return chalk32.dim("-");
|
|
8785
8761
|
const formatted = formatDateTime(dateStr);
|
|
8786
|
-
return formatted.replace(/\(([^)]+)\)$/,
|
|
8762
|
+
return formatted.replace(/\(([^)]+)\)$/, chalk32.dim("($1)"));
|
|
8787
8763
|
}
|
|
8788
8764
|
function formatTrigger(schedule) {
|
|
8789
8765
|
if (schedule.cronExpression) {
|
|
8790
8766
|
return schedule.cronExpression;
|
|
8791
8767
|
}
|
|
8792
8768
|
if (schedule.atTime) {
|
|
8793
|
-
return `${schedule.atTime} ${
|
|
8769
|
+
return `${schedule.atTime} ${chalk32.dim("(one-time)")}`;
|
|
8794
8770
|
}
|
|
8795
|
-
return
|
|
8771
|
+
return chalk32.dim("-");
|
|
8796
8772
|
}
|
|
8797
8773
|
function formatRunStatus(status) {
|
|
8798
8774
|
switch (status) {
|
|
8799
8775
|
case "completed":
|
|
8800
|
-
return
|
|
8776
|
+
return chalk32.green(status);
|
|
8801
8777
|
case "failed":
|
|
8802
8778
|
case "timeout":
|
|
8803
|
-
return
|
|
8779
|
+
return chalk32.red(status);
|
|
8804
8780
|
case "running":
|
|
8805
|
-
return
|
|
8781
|
+
return chalk32.blue(status);
|
|
8806
8782
|
case "pending":
|
|
8807
|
-
return
|
|
8783
|
+
return chalk32.yellow(status);
|
|
8808
8784
|
default:
|
|
8809
8785
|
return status;
|
|
8810
8786
|
}
|
|
@@ -8817,12 +8793,12 @@ var statusCommand4 = new Command30().name("status").description("Show detailed s
|
|
|
8817
8793
|
try {
|
|
8818
8794
|
const result = loadAgentName();
|
|
8819
8795
|
if (result.error) {
|
|
8820
|
-
console.error(
|
|
8796
|
+
console.error(chalk32.red(`\u2717 Invalid vm0.yaml: ${result.error}`));
|
|
8821
8797
|
process.exit(1);
|
|
8822
8798
|
}
|
|
8823
8799
|
if (!result.agentName) {
|
|
8824
|
-
console.error(
|
|
8825
|
-
console.error(
|
|
8800
|
+
console.error(chalk32.red("\u2717 No vm0.yaml found in current directory"));
|
|
8801
|
+
console.error(chalk32.dim(" Run this command from the agent directory"));
|
|
8826
8802
|
process.exit(1);
|
|
8827
8803
|
}
|
|
8828
8804
|
const agentName = result.agentName;
|
|
@@ -8831,8 +8807,8 @@ var statusCommand4 = new Command30().name("status").description("Show detailed s
|
|
|
8831
8807
|
const compose = await apiClient.getComposeByName(agentName);
|
|
8832
8808
|
composeId = compose.id;
|
|
8833
8809
|
} catch {
|
|
8834
|
-
console.error(
|
|
8835
|
-
console.error(
|
|
8810
|
+
console.error(chalk32.red(`\u2717 Agent not found: ${agentName}`));
|
|
8811
|
+
console.error(chalk32.dim(" Make sure the agent is pushed first"));
|
|
8836
8812
|
process.exit(1);
|
|
8837
8813
|
}
|
|
8838
8814
|
const response = await apiClient.get(
|
|
@@ -8844,15 +8820,15 @@ var statusCommand4 = new Command30().name("status").description("Show detailed s
|
|
|
8844
8820
|
}
|
|
8845
8821
|
const schedule = await response.json();
|
|
8846
8822
|
console.log();
|
|
8847
|
-
console.log(`Schedule: ${
|
|
8848
|
-
console.log(
|
|
8849
|
-
const statusText = schedule.enabled ?
|
|
8823
|
+
console.log(`Schedule: ${chalk32.cyan(schedule.name)}`);
|
|
8824
|
+
console.log(chalk32.dim("\u2501".repeat(50)));
|
|
8825
|
+
const statusText = schedule.enabled ? chalk32.green("enabled") : chalk32.yellow("disabled");
|
|
8850
8826
|
console.log(`${"Status:".padEnd(16)}${statusText}`);
|
|
8851
8827
|
console.log(
|
|
8852
|
-
`${"Agent:".padEnd(16)}${schedule.composeName} ${
|
|
8828
|
+
`${"Agent:".padEnd(16)}${schedule.composeName} ${chalk32.dim(`(${schedule.scopeSlug})`)}`
|
|
8853
8829
|
);
|
|
8854
8830
|
const promptPreview = schedule.prompt.length > 60 ? schedule.prompt.slice(0, 57) + "..." : schedule.prompt;
|
|
8855
|
-
console.log(`${"Prompt:".padEnd(16)}${
|
|
8831
|
+
console.log(`${"Prompt:".padEnd(16)}${chalk32.dim(promptPreview)}`);
|
|
8856
8832
|
if (schedule.vars && Object.keys(schedule.vars).length > 0) {
|
|
8857
8833
|
console.log(
|
|
8858
8834
|
`${"Variables:".padEnd(16)}${Object.keys(schedule.vars).join(", ")}`
|
|
@@ -8894,7 +8870,7 @@ var statusCommand4 = new Command30().name("status").description("Show detailed s
|
|
|
8894
8870
|
console.log();
|
|
8895
8871
|
console.log("Recent Runs:");
|
|
8896
8872
|
console.log(
|
|
8897
|
-
|
|
8873
|
+
chalk32.dim(
|
|
8898
8874
|
"RUN ID STATUS CREATED"
|
|
8899
8875
|
)
|
|
8900
8876
|
);
|
|
@@ -8907,19 +8883,19 @@ var statusCommand4 = new Command30().name("status").description("Show detailed s
|
|
|
8907
8883
|
}
|
|
8908
8884
|
} else {
|
|
8909
8885
|
console.log();
|
|
8910
|
-
console.log(
|
|
8886
|
+
console.log(chalk32.dim("Recent Runs: (unable to fetch)"));
|
|
8911
8887
|
}
|
|
8912
8888
|
}
|
|
8913
8889
|
console.log();
|
|
8914
8890
|
} catch (error) {
|
|
8915
|
-
console.error(
|
|
8891
|
+
console.error(chalk32.red("\u2717 Failed to get schedule status"));
|
|
8916
8892
|
if (error instanceof Error) {
|
|
8917
8893
|
if (error.message.includes("Not authenticated")) {
|
|
8918
|
-
console.error(
|
|
8894
|
+
console.error(chalk32.dim(" Run: vm0 auth login"));
|
|
8919
8895
|
} else if (error.message.includes("not found") || error.message.includes("Not found")) {
|
|
8920
|
-
console.error(
|
|
8896
|
+
console.error(chalk32.dim(` Schedule "${name}" not found`));
|
|
8921
8897
|
} else {
|
|
8922
|
-
console.error(
|
|
8898
|
+
console.error(chalk32.dim(` ${error.message}`));
|
|
8923
8899
|
}
|
|
8924
8900
|
}
|
|
8925
8901
|
process.exit(1);
|
|
@@ -8928,7 +8904,7 @@ var statusCommand4 = new Command30().name("status").description("Show detailed s
|
|
|
8928
8904
|
|
|
8929
8905
|
// src/commands/schedule/delete.ts
|
|
8930
8906
|
import { Command as Command31 } from "commander";
|
|
8931
|
-
import
|
|
8907
|
+
import chalk33 from "chalk";
|
|
8932
8908
|
import * as readline from "readline";
|
|
8933
8909
|
async function confirm(message) {
|
|
8934
8910
|
const rl = readline.createInterface({
|
|
@@ -8946,12 +8922,12 @@ var deleteCommand = new Command31().name("delete").alias("rm").description("Dele
|
|
|
8946
8922
|
try {
|
|
8947
8923
|
const result = loadAgentName();
|
|
8948
8924
|
if (result.error) {
|
|
8949
|
-
console.error(
|
|
8925
|
+
console.error(chalk33.red(`\u2717 Invalid vm0.yaml: ${result.error}`));
|
|
8950
8926
|
process.exit(1);
|
|
8951
8927
|
}
|
|
8952
8928
|
if (!result.agentName) {
|
|
8953
|
-
console.error(
|
|
8954
|
-
console.error(
|
|
8929
|
+
console.error(chalk33.red("\u2717 No vm0.yaml found in current directory"));
|
|
8930
|
+
console.error(chalk33.dim(" Run this command from the agent directory"));
|
|
8955
8931
|
process.exit(1);
|
|
8956
8932
|
}
|
|
8957
8933
|
const agentName = result.agentName;
|
|
@@ -8960,14 +8936,14 @@ var deleteCommand = new Command31().name("delete").alias("rm").description("Dele
|
|
|
8960
8936
|
const compose = await apiClient.getComposeByName(agentName);
|
|
8961
8937
|
composeId = compose.id;
|
|
8962
8938
|
} catch {
|
|
8963
|
-
console.error(
|
|
8964
|
-
console.error(
|
|
8939
|
+
console.error(chalk33.red(`\u2717 Agent not found: ${agentName}`));
|
|
8940
|
+
console.error(chalk33.dim(" Make sure the agent is pushed first"));
|
|
8965
8941
|
process.exit(1);
|
|
8966
8942
|
}
|
|
8967
8943
|
if (!options.force) {
|
|
8968
|
-
const confirmed = await confirm(`Delete schedule ${
|
|
8944
|
+
const confirmed = await confirm(`Delete schedule ${chalk33.cyan(name)}?`);
|
|
8969
8945
|
if (!confirmed) {
|
|
8970
|
-
console.log(
|
|
8946
|
+
console.log(chalk33.dim("Cancelled"));
|
|
8971
8947
|
return;
|
|
8972
8948
|
}
|
|
8973
8949
|
}
|
|
@@ -8978,14 +8954,14 @@ var deleteCommand = new Command31().name("delete").alias("rm").description("Dele
|
|
|
8978
8954
|
const error = await response.json();
|
|
8979
8955
|
throw new Error(error.error?.message || "Delete failed");
|
|
8980
8956
|
}
|
|
8981
|
-
console.log(
|
|
8957
|
+
console.log(chalk33.green(`\u2713 Deleted schedule ${chalk33.cyan(name)}`));
|
|
8982
8958
|
} catch (error) {
|
|
8983
|
-
console.error(
|
|
8959
|
+
console.error(chalk33.red("\u2717 Failed to delete schedule"));
|
|
8984
8960
|
if (error instanceof Error) {
|
|
8985
8961
|
if (error.message.includes("Not authenticated")) {
|
|
8986
|
-
console.error(
|
|
8962
|
+
console.error(chalk33.dim(" Run: vm0 auth login"));
|
|
8987
8963
|
} else {
|
|
8988
|
-
console.error(
|
|
8964
|
+
console.error(chalk33.dim(` ${error.message}`));
|
|
8989
8965
|
}
|
|
8990
8966
|
}
|
|
8991
8967
|
process.exit(1);
|
|
@@ -8994,17 +8970,17 @@ var deleteCommand = new Command31().name("delete").alias("rm").description("Dele
|
|
|
8994
8970
|
|
|
8995
8971
|
// src/commands/schedule/enable.ts
|
|
8996
8972
|
import { Command as Command32 } from "commander";
|
|
8997
|
-
import
|
|
8973
|
+
import chalk34 from "chalk";
|
|
8998
8974
|
var enableCommand = new Command32().name("enable").description("Enable a schedule").argument("<name>", "Schedule name to enable").action(async (name) => {
|
|
8999
8975
|
try {
|
|
9000
8976
|
const result = loadAgentName();
|
|
9001
8977
|
if (result.error) {
|
|
9002
|
-
console.error(
|
|
8978
|
+
console.error(chalk34.red(`\u2717 Invalid vm0.yaml: ${result.error}`));
|
|
9003
8979
|
process.exit(1);
|
|
9004
8980
|
}
|
|
9005
8981
|
if (!result.agentName) {
|
|
9006
|
-
console.error(
|
|
9007
|
-
console.error(
|
|
8982
|
+
console.error(chalk34.red("\u2717 No vm0.yaml found in current directory"));
|
|
8983
|
+
console.error(chalk34.dim(" Run this command from the agent directory"));
|
|
9008
8984
|
process.exit(1);
|
|
9009
8985
|
}
|
|
9010
8986
|
const agentName = result.agentName;
|
|
@@ -9013,8 +8989,8 @@ var enableCommand = new Command32().name("enable").description("Enable a schedul
|
|
|
9013
8989
|
const compose = await apiClient.getComposeByName(agentName);
|
|
9014
8990
|
composeId = compose.id;
|
|
9015
8991
|
} catch {
|
|
9016
|
-
console.error(
|
|
9017
|
-
console.error(
|
|
8992
|
+
console.error(chalk34.red(`\u2717 Agent not found: ${agentName}`));
|
|
8993
|
+
console.error(chalk34.dim(" Make sure the agent is pushed first"));
|
|
9018
8994
|
process.exit(1);
|
|
9019
8995
|
}
|
|
9020
8996
|
const response = await apiClient.post(
|
|
@@ -9025,14 +9001,14 @@ var enableCommand = new Command32().name("enable").description("Enable a schedul
|
|
|
9025
9001
|
const error = await response.json();
|
|
9026
9002
|
throw new Error(error.error?.message || "Enable failed");
|
|
9027
9003
|
}
|
|
9028
|
-
console.log(
|
|
9004
|
+
console.log(chalk34.green(`\u2713 Enabled schedule ${chalk34.cyan(name)}`));
|
|
9029
9005
|
} catch (error) {
|
|
9030
|
-
console.error(
|
|
9006
|
+
console.error(chalk34.red("\u2717 Failed to enable schedule"));
|
|
9031
9007
|
if (error instanceof Error) {
|
|
9032
9008
|
if (error.message.includes("Not authenticated")) {
|
|
9033
|
-
console.error(
|
|
9009
|
+
console.error(chalk34.dim(" Run: vm0 auth login"));
|
|
9034
9010
|
} else {
|
|
9035
|
-
console.error(
|
|
9011
|
+
console.error(chalk34.dim(` ${error.message}`));
|
|
9036
9012
|
}
|
|
9037
9013
|
}
|
|
9038
9014
|
process.exit(1);
|
|
@@ -9041,17 +9017,17 @@ var enableCommand = new Command32().name("enable").description("Enable a schedul
|
|
|
9041
9017
|
|
|
9042
9018
|
// src/commands/schedule/disable.ts
|
|
9043
9019
|
import { Command as Command33 } from "commander";
|
|
9044
|
-
import
|
|
9020
|
+
import chalk35 from "chalk";
|
|
9045
9021
|
var disableCommand = new Command33().name("disable").description("Disable a schedule").argument("<name>", "Schedule name to disable").action(async (name) => {
|
|
9046
9022
|
try {
|
|
9047
9023
|
const result = loadAgentName();
|
|
9048
9024
|
if (result.error) {
|
|
9049
|
-
console.error(
|
|
9025
|
+
console.error(chalk35.red(`\u2717 Invalid vm0.yaml: ${result.error}`));
|
|
9050
9026
|
process.exit(1);
|
|
9051
9027
|
}
|
|
9052
9028
|
if (!result.agentName) {
|
|
9053
|
-
console.error(
|
|
9054
|
-
console.error(
|
|
9029
|
+
console.error(chalk35.red("\u2717 No vm0.yaml found in current directory"));
|
|
9030
|
+
console.error(chalk35.dim(" Run this command from the agent directory"));
|
|
9055
9031
|
process.exit(1);
|
|
9056
9032
|
}
|
|
9057
9033
|
const agentName = result.agentName;
|
|
@@ -9060,8 +9036,8 @@ var disableCommand = new Command33().name("disable").description("Disable a sche
|
|
|
9060
9036
|
const compose = await apiClient.getComposeByName(agentName);
|
|
9061
9037
|
composeId = compose.id;
|
|
9062
9038
|
} catch {
|
|
9063
|
-
console.error(
|
|
9064
|
-
console.error(
|
|
9039
|
+
console.error(chalk35.red(`\u2717 Agent not found: ${agentName}`));
|
|
9040
|
+
console.error(chalk35.dim(" Make sure the agent is pushed first"));
|
|
9065
9041
|
process.exit(1);
|
|
9066
9042
|
}
|
|
9067
9043
|
const response = await apiClient.post(
|
|
@@ -9072,14 +9048,14 @@ var disableCommand = new Command33().name("disable").description("Disable a sche
|
|
|
9072
9048
|
const error = await response.json();
|
|
9073
9049
|
throw new Error(error.error?.message || "Disable failed");
|
|
9074
9050
|
}
|
|
9075
|
-
console.log(
|
|
9051
|
+
console.log(chalk35.green(`\u2713 Disabled schedule ${chalk35.cyan(name)}`));
|
|
9076
9052
|
} catch (error) {
|
|
9077
|
-
console.error(
|
|
9053
|
+
console.error(chalk35.red("\u2717 Failed to disable schedule"));
|
|
9078
9054
|
if (error instanceof Error) {
|
|
9079
9055
|
if (error.message.includes("Not authenticated")) {
|
|
9080
|
-
console.error(
|
|
9056
|
+
console.error(chalk35.dim(" Run: vm0 auth login"));
|
|
9081
9057
|
} else {
|
|
9082
|
-
console.error(
|
|
9058
|
+
console.error(chalk35.dim(` ${error.message}`));
|
|
9083
9059
|
}
|
|
9084
9060
|
}
|
|
9085
9061
|
process.exit(1);
|
|
@@ -9091,9 +9067,9 @@ var scheduleCommand = new Command34().name("schedule").description("Manage agent
|
|
|
9091
9067
|
|
|
9092
9068
|
// src/index.ts
|
|
9093
9069
|
var program = new Command35();
|
|
9094
|
-
program.name("vm0").description("VM0 CLI - A modern build tool").version("5.
|
|
9070
|
+
program.name("vm0").description("VM0 CLI - A modern build tool").version("5.6.0");
|
|
9095
9071
|
program.command("info").description("Display environment information").action(async () => {
|
|
9096
|
-
console.log(
|
|
9072
|
+
console.log(chalk36.bold("System Information:"));
|
|
9097
9073
|
console.log(`Node Version: ${process.version}`);
|
|
9098
9074
|
console.log(`Platform: ${process.platform}`);
|
|
9099
9075
|
console.log(`Architecture: ${process.arch}`);
|