@vm0/cli 4.13.0 → 4.14.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 +319 -192
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -6,8 +6,8 @@ var __export = (target, all) => {
|
|
|
6
6
|
};
|
|
7
7
|
|
|
8
8
|
// src/index.ts
|
|
9
|
-
import { Command as
|
|
10
|
-
import
|
|
9
|
+
import { Command as Command19 } from "commander";
|
|
10
|
+
import chalk20 from "chalk";
|
|
11
11
|
|
|
12
12
|
// src/lib/auth.ts
|
|
13
13
|
import chalk from "chalk";
|
|
@@ -1035,18 +1035,23 @@ async function directUpload(storageName, storageType, cwd, options) {
|
|
|
1035
1035
|
empty: fileEntries.length === 0
|
|
1036
1036
|
};
|
|
1037
1037
|
}
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1038
|
+
if (files.length > 0) {
|
|
1039
|
+
onProgress?.("Compressing files...");
|
|
1040
|
+
const archiveBuffer = await createArchive(cwd, files);
|
|
1041
|
+
onProgress?.("Uploading archive to S3...");
|
|
1042
|
+
if (!prepareResult.uploads) {
|
|
1043
|
+
throw new Error("No upload URLs received from prepare endpoint");
|
|
1044
|
+
}
|
|
1045
|
+
await uploadToPresignedUrl(
|
|
1046
|
+
prepareResult.uploads.archive.presignedUrl,
|
|
1047
|
+
archiveBuffer,
|
|
1048
|
+
"application/gzip"
|
|
1049
|
+
);
|
|
1050
|
+
}
|
|
1051
|
+
onProgress?.("Uploading manifest...");
|
|
1041
1052
|
if (!prepareResult.uploads) {
|
|
1042
1053
|
throw new Error("No upload URLs received from prepare endpoint");
|
|
1043
1054
|
}
|
|
1044
|
-
await uploadToPresignedUrl(
|
|
1045
|
-
prepareResult.uploads.archive.presignedUrl,
|
|
1046
|
-
archiveBuffer,
|
|
1047
|
-
"application/gzip"
|
|
1048
|
-
);
|
|
1049
|
-
onProgress?.("Uploading manifest...");
|
|
1050
1055
|
const manifestBuffer = createManifest(fileEntries);
|
|
1051
1056
|
await uploadToPresignedUrl(
|
|
1052
1057
|
prepareResult.uploads.manifest.presignedUrl,
|
|
@@ -15253,7 +15258,7 @@ runCmd.command("continue").description(
|
|
|
15253
15258
|
var runCommand = runCmd;
|
|
15254
15259
|
|
|
15255
15260
|
// src/commands/volume/index.ts
|
|
15256
|
-
import { Command as
|
|
15261
|
+
import { Command as Command7 } from "commander";
|
|
15257
15262
|
|
|
15258
15263
|
// src/commands/volume/init.ts
|
|
15259
15264
|
import { Command as Command3 } from "commander";
|
|
@@ -15515,17 +15520,78 @@ var pullCommand = new Command5().name("pull").description("Pull cloud files to l
|
|
|
15515
15520
|
}
|
|
15516
15521
|
});
|
|
15517
15522
|
|
|
15523
|
+
// src/commands/volume/status.ts
|
|
15524
|
+
import { Command as Command6 } from "commander";
|
|
15525
|
+
import chalk9 from "chalk";
|
|
15526
|
+
function formatBytes3(bytes) {
|
|
15527
|
+
if (bytes === 0) return "0 B";
|
|
15528
|
+
const k = 1024;
|
|
15529
|
+
const sizes = ["B", "KB", "MB", "GB"];
|
|
15530
|
+
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
15531
|
+
return `${(bytes / Math.pow(k, i)).toFixed(2)} ${sizes[i]}`;
|
|
15532
|
+
}
|
|
15533
|
+
var statusCommand = new Command6().name("status").description("Show status of cloud volume").action(async () => {
|
|
15534
|
+
try {
|
|
15535
|
+
const cwd = process.cwd();
|
|
15536
|
+
const config2 = await readStorageConfig(cwd);
|
|
15537
|
+
if (!config2) {
|
|
15538
|
+
console.error(chalk9.red("\u2717 No volume initialized in this directory"));
|
|
15539
|
+
console.error(chalk9.gray(" Run: vm0 volume init"));
|
|
15540
|
+
process.exit(1);
|
|
15541
|
+
}
|
|
15542
|
+
if (config2.type !== "volume") {
|
|
15543
|
+
console.error(
|
|
15544
|
+
chalk9.red(
|
|
15545
|
+
"\u2717 This directory is initialized as an artifact, not a volume"
|
|
15546
|
+
)
|
|
15547
|
+
);
|
|
15548
|
+
console.error(chalk9.gray(" Use: vm0 artifact status"));
|
|
15549
|
+
process.exit(1);
|
|
15550
|
+
}
|
|
15551
|
+
console.log(chalk9.cyan(`Checking volume: ${config2.name}`));
|
|
15552
|
+
const url2 = `/api/storages/download?name=${encodeURIComponent(config2.name)}&type=volume`;
|
|
15553
|
+
const response = await apiClient.get(url2);
|
|
15554
|
+
if (!response.ok) {
|
|
15555
|
+
if (response.status === 404) {
|
|
15556
|
+
console.error(chalk9.red("\u2717 Not found on remote"));
|
|
15557
|
+
console.error(chalk9.gray(" Run: vm0 volume push"));
|
|
15558
|
+
} else {
|
|
15559
|
+
const error43 = await response.json();
|
|
15560
|
+
throw new Error(error43.error?.message || "Status check failed");
|
|
15561
|
+
}
|
|
15562
|
+
process.exit(1);
|
|
15563
|
+
}
|
|
15564
|
+
const info = await response.json();
|
|
15565
|
+
const shortVersion = info.versionId.slice(0, 8);
|
|
15566
|
+
if (info.empty) {
|
|
15567
|
+
console.log(chalk9.green("\u2713 Found (empty)"));
|
|
15568
|
+
console.log(chalk9.gray(` Version: ${shortVersion}`));
|
|
15569
|
+
} else {
|
|
15570
|
+
console.log(chalk9.green("\u2713 Found"));
|
|
15571
|
+
console.log(chalk9.gray(` Version: ${shortVersion}`));
|
|
15572
|
+
console.log(chalk9.gray(` Files: ${info.fileCount.toLocaleString()}`));
|
|
15573
|
+
console.log(chalk9.gray(` Size: ${formatBytes3(info.size)}`));
|
|
15574
|
+
}
|
|
15575
|
+
} catch (error43) {
|
|
15576
|
+
console.error(chalk9.red("\u2717 Status check failed"));
|
|
15577
|
+
if (error43 instanceof Error) {
|
|
15578
|
+
console.error(chalk9.gray(` ${error43.message}`));
|
|
15579
|
+
}
|
|
15580
|
+
process.exit(1);
|
|
15581
|
+
}
|
|
15582
|
+
});
|
|
15583
|
+
|
|
15518
15584
|
// src/commands/volume/index.ts
|
|
15519
|
-
var volumeCommand = new
|
|
15585
|
+
var volumeCommand = new Command7().name("volume").description("Manage cloud volumes").addCommand(initCommand).addCommand(pushCommand).addCommand(pullCommand).addCommand(statusCommand);
|
|
15520
15586
|
|
|
15521
15587
|
// src/commands/artifact/index.ts
|
|
15522
|
-
import { Command as
|
|
15588
|
+
import { Command as Command12 } from "commander";
|
|
15523
15589
|
|
|
15524
15590
|
// src/commands/artifact/init.ts
|
|
15525
|
-
import { Command as
|
|
15526
|
-
import
|
|
15591
|
+
import { Command as Command8 } from "commander";
|
|
15592
|
+
import chalk10 from "chalk";
|
|
15527
15593
|
import path9 from "path";
|
|
15528
|
-
var initCommand2 = new
|
|
15594
|
+
var initCommand2 = new Command8().name("init").description("Initialize an artifact in the current directory").action(async () => {
|
|
15529
15595
|
try {
|
|
15530
15596
|
const cwd = process.cwd();
|
|
15531
15597
|
const dirName = path9.basename(cwd);
|
|
@@ -15533,67 +15599,67 @@ var initCommand2 = new Command7().name("init").description("Initialize an artifa
|
|
|
15533
15599
|
if (existingConfig) {
|
|
15534
15600
|
if (existingConfig.type === "artifact") {
|
|
15535
15601
|
console.log(
|
|
15536
|
-
|
|
15602
|
+
chalk10.yellow(
|
|
15537
15603
|
`Artifact already initialized: ${existingConfig.name}`
|
|
15538
15604
|
)
|
|
15539
15605
|
);
|
|
15540
15606
|
} else {
|
|
15541
15607
|
console.log(
|
|
15542
|
-
|
|
15608
|
+
chalk10.yellow(
|
|
15543
15609
|
`Directory already initialized as volume: ${existingConfig.name}`
|
|
15544
15610
|
)
|
|
15545
15611
|
);
|
|
15546
15612
|
console.log(
|
|
15547
|
-
|
|
15613
|
+
chalk10.gray(
|
|
15548
15614
|
" To change type, delete .vm0/storage.yaml and reinitialize"
|
|
15549
15615
|
)
|
|
15550
15616
|
);
|
|
15551
15617
|
}
|
|
15552
15618
|
console.log(
|
|
15553
|
-
|
|
15619
|
+
chalk10.gray(`Config file: ${path9.join(cwd, ".vm0", "storage.yaml")}`)
|
|
15554
15620
|
);
|
|
15555
15621
|
return;
|
|
15556
15622
|
}
|
|
15557
15623
|
const artifactName = dirName;
|
|
15558
15624
|
if (!isValidStorageName(artifactName)) {
|
|
15559
|
-
console.error(
|
|
15625
|
+
console.error(chalk10.red(`\u2717 Invalid artifact name: "${dirName}"`));
|
|
15560
15626
|
console.error(
|
|
15561
|
-
|
|
15627
|
+
chalk10.gray(
|
|
15562
15628
|
" Artifact names must be 3-64 characters, lowercase alphanumeric with hyphens"
|
|
15563
15629
|
)
|
|
15564
15630
|
);
|
|
15565
15631
|
console.error(
|
|
15566
|
-
|
|
15632
|
+
chalk10.gray(" Example: my-project, user-workspace, code-artifact")
|
|
15567
15633
|
);
|
|
15568
15634
|
process.exit(1);
|
|
15569
15635
|
}
|
|
15570
15636
|
await writeStorageConfig(artifactName, cwd, "artifact");
|
|
15571
|
-
console.log(
|
|
15637
|
+
console.log(chalk10.green(`\u2713 Initialized artifact: ${artifactName}`));
|
|
15572
15638
|
console.log(
|
|
15573
|
-
|
|
15639
|
+
chalk10.gray(
|
|
15574
15640
|
`\u2713 Config saved to ${path9.join(cwd, ".vm0", "storage.yaml")}`
|
|
15575
15641
|
)
|
|
15576
15642
|
);
|
|
15577
15643
|
} catch (error43) {
|
|
15578
|
-
console.error(
|
|
15644
|
+
console.error(chalk10.red("\u2717 Failed to initialize artifact"));
|
|
15579
15645
|
if (error43 instanceof Error) {
|
|
15580
|
-
console.error(
|
|
15646
|
+
console.error(chalk10.gray(` ${error43.message}`));
|
|
15581
15647
|
}
|
|
15582
15648
|
process.exit(1);
|
|
15583
15649
|
}
|
|
15584
15650
|
});
|
|
15585
15651
|
|
|
15586
15652
|
// src/commands/artifact/push.ts
|
|
15587
|
-
import { Command as
|
|
15588
|
-
import
|
|
15589
|
-
function
|
|
15653
|
+
import { Command as Command9 } from "commander";
|
|
15654
|
+
import chalk11 from "chalk";
|
|
15655
|
+
function formatBytes4(bytes) {
|
|
15590
15656
|
if (bytes === 0) return "0 B";
|
|
15591
15657
|
const k = 1024;
|
|
15592
15658
|
const sizes = ["B", "KB", "MB", "GB"];
|
|
15593
15659
|
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
15594
15660
|
return `${(bytes / Math.pow(k, i)).toFixed(2)} ${sizes[i]}`;
|
|
15595
15661
|
}
|
|
15596
|
-
var pushCommand2 = new
|
|
15662
|
+
var pushCommand2 = new Command9().name("push").description("Push local files to cloud artifact").option(
|
|
15597
15663
|
"-f, --force",
|
|
15598
15664
|
"Force upload even if content unchanged (recreate archive)"
|
|
15599
15665
|
).action(async (options) => {
|
|
@@ -15601,88 +15667,88 @@ var pushCommand2 = new Command8().name("push").description("Push local files to
|
|
|
15601
15667
|
const cwd = process.cwd();
|
|
15602
15668
|
const config2 = await readStorageConfig(cwd);
|
|
15603
15669
|
if (!config2) {
|
|
15604
|
-
console.error(
|
|
15605
|
-
console.error(
|
|
15670
|
+
console.error(chalk11.red("\u2717 No artifact initialized in this directory"));
|
|
15671
|
+
console.error(chalk11.gray(" Run: vm0 artifact init"));
|
|
15606
15672
|
process.exit(1);
|
|
15607
15673
|
}
|
|
15608
15674
|
if (config2.type !== "artifact") {
|
|
15609
15675
|
console.error(
|
|
15610
|
-
|
|
15676
|
+
chalk11.red(
|
|
15611
15677
|
`\u2717 This directory is initialized as a volume, not an artifact`
|
|
15612
15678
|
)
|
|
15613
15679
|
);
|
|
15614
|
-
console.error(
|
|
15680
|
+
console.error(chalk11.gray(" Use: vm0 volume push"));
|
|
15615
15681
|
process.exit(1);
|
|
15616
15682
|
}
|
|
15617
|
-
console.log(
|
|
15683
|
+
console.log(chalk11.cyan(`Pushing artifact: ${config2.name}`));
|
|
15618
15684
|
const result = await directUpload(config2.name, "artifact", cwd, {
|
|
15619
15685
|
onProgress: (message) => {
|
|
15620
|
-
console.log(
|
|
15686
|
+
console.log(chalk11.gray(message));
|
|
15621
15687
|
},
|
|
15622
15688
|
force: options.force
|
|
15623
15689
|
});
|
|
15624
15690
|
const shortVersion = result.versionId.slice(0, 8);
|
|
15625
15691
|
if (result.empty) {
|
|
15626
|
-
console.log(
|
|
15692
|
+
console.log(chalk11.yellow("No files found (empty artifact)"));
|
|
15627
15693
|
} else if (result.deduplicated) {
|
|
15628
|
-
console.log(
|
|
15694
|
+
console.log(chalk11.green("\u2713 Content unchanged (deduplicated)"));
|
|
15629
15695
|
} else {
|
|
15630
|
-
console.log(
|
|
15696
|
+
console.log(chalk11.green("\u2713 Upload complete"));
|
|
15631
15697
|
}
|
|
15632
|
-
console.log(
|
|
15633
|
-
console.log(
|
|
15634
|
-
console.log(
|
|
15698
|
+
console.log(chalk11.gray(` Version: ${shortVersion}`));
|
|
15699
|
+
console.log(chalk11.gray(` Files: ${result.fileCount.toLocaleString()}`));
|
|
15700
|
+
console.log(chalk11.gray(` Size: ${formatBytes4(result.size)}`));
|
|
15635
15701
|
} catch (error43) {
|
|
15636
|
-
console.error(
|
|
15702
|
+
console.error(chalk11.red("\u2717 Push failed"));
|
|
15637
15703
|
if (error43 instanceof Error) {
|
|
15638
|
-
console.error(
|
|
15704
|
+
console.error(chalk11.gray(` ${error43.message}`));
|
|
15639
15705
|
}
|
|
15640
15706
|
process.exit(1);
|
|
15641
15707
|
}
|
|
15642
15708
|
});
|
|
15643
15709
|
|
|
15644
15710
|
// src/commands/artifact/pull.ts
|
|
15645
|
-
import { Command as
|
|
15646
|
-
import
|
|
15711
|
+
import { Command as Command10 } from "commander";
|
|
15712
|
+
import chalk12 from "chalk";
|
|
15647
15713
|
import path10 from "path";
|
|
15648
15714
|
import * as fs7 from "fs";
|
|
15649
15715
|
import * as os5 from "os";
|
|
15650
15716
|
import * as tar4 from "tar";
|
|
15651
|
-
function
|
|
15717
|
+
function formatBytes5(bytes) {
|
|
15652
15718
|
if (bytes === 0) return "0 B";
|
|
15653
15719
|
const k = 1024;
|
|
15654
15720
|
const sizes = ["B", "KB", "MB", "GB"];
|
|
15655
15721
|
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
15656
15722
|
return `${(bytes / Math.pow(k, i)).toFixed(2)} ${sizes[i]}`;
|
|
15657
15723
|
}
|
|
15658
|
-
var pullCommand2 = new
|
|
15724
|
+
var pullCommand2 = new Command10().name("pull").description("Pull cloud artifact to local directory").argument("[versionId]", "Version ID to pull (default: latest)").action(async (versionId) => {
|
|
15659
15725
|
try {
|
|
15660
15726
|
const cwd = process.cwd();
|
|
15661
15727
|
const config2 = await readStorageConfig(cwd);
|
|
15662
15728
|
if (!config2) {
|
|
15663
|
-
console.error(
|
|
15664
|
-
console.error(
|
|
15729
|
+
console.error(chalk12.red("\u2717 No artifact initialized in this directory"));
|
|
15730
|
+
console.error(chalk12.gray(" Run: vm0 artifact init"));
|
|
15665
15731
|
process.exit(1);
|
|
15666
15732
|
}
|
|
15667
15733
|
if (config2.type !== "artifact") {
|
|
15668
15734
|
console.error(
|
|
15669
|
-
|
|
15735
|
+
chalk12.red(
|
|
15670
15736
|
`\u2717 This directory is initialized as a volume, not an artifact`
|
|
15671
15737
|
)
|
|
15672
15738
|
);
|
|
15673
|
-
console.error(
|
|
15739
|
+
console.error(chalk12.gray(" Use: vm0 volume pull"));
|
|
15674
15740
|
process.exit(1);
|
|
15675
15741
|
}
|
|
15676
15742
|
if (versionId) {
|
|
15677
15743
|
console.log(
|
|
15678
|
-
|
|
15744
|
+
chalk12.cyan(
|
|
15679
15745
|
`Pulling artifact: ${config2.name} (version: ${versionId})`
|
|
15680
15746
|
)
|
|
15681
15747
|
);
|
|
15682
15748
|
} else {
|
|
15683
|
-
console.log(
|
|
15749
|
+
console.log(chalk12.cyan(`Pulling artifact: ${config2.name}`));
|
|
15684
15750
|
}
|
|
15685
|
-
console.log(
|
|
15751
|
+
console.log(chalk12.gray("Getting download URL..."));
|
|
15686
15752
|
let url2 = `/api/storages/download?name=${encodeURIComponent(config2.name)}&type=artifact`;
|
|
15687
15753
|
if (versionId) {
|
|
15688
15754
|
url2 += `&version=${encodeURIComponent(versionId)}`;
|
|
@@ -15690,14 +15756,14 @@ var pullCommand2 = new Command9().name("pull").description("Pull cloud artifact
|
|
|
15690
15756
|
const response = await apiClient.get(url2);
|
|
15691
15757
|
if (!response.ok) {
|
|
15692
15758
|
if (response.status === 404) {
|
|
15693
|
-
console.error(
|
|
15759
|
+
console.error(chalk12.red(`\u2717 Artifact "${config2.name}" not found`));
|
|
15694
15760
|
console.error(
|
|
15695
|
-
|
|
15761
|
+
chalk12.gray(
|
|
15696
15762
|
" Make sure the artifact name is correct in .vm0/storage.yaml"
|
|
15697
15763
|
)
|
|
15698
15764
|
);
|
|
15699
15765
|
console.error(
|
|
15700
|
-
|
|
15766
|
+
chalk12.gray(" Or push the artifact first with: vm0 artifact push")
|
|
15701
15767
|
);
|
|
15702
15768
|
} else {
|
|
15703
15769
|
const error43 = await response.json();
|
|
@@ -15713,18 +15779,18 @@ var pullCommand2 = new Command9().name("pull").description("Pull cloud artifact
|
|
|
15713
15779
|
if (!downloadInfo.url) {
|
|
15714
15780
|
throw new Error("No download URL returned");
|
|
15715
15781
|
}
|
|
15716
|
-
console.log(
|
|
15782
|
+
console.log(chalk12.gray("Downloading from S3..."));
|
|
15717
15783
|
const s3Response = await fetch(downloadInfo.url);
|
|
15718
15784
|
if (!s3Response.ok) {
|
|
15719
15785
|
throw new Error(`S3 download failed: ${s3Response.status}`);
|
|
15720
15786
|
}
|
|
15721
15787
|
const arrayBuffer = await s3Response.arrayBuffer();
|
|
15722
15788
|
const tarBuffer = Buffer.from(arrayBuffer);
|
|
15723
|
-
console.log(
|
|
15789
|
+
console.log(chalk12.green(`\u2713 Downloaded ${formatBytes5(tarBuffer.length)}`));
|
|
15724
15790
|
const tmpDir = fs7.mkdtempSync(path10.join(os5.tmpdir(), "vm0-"));
|
|
15725
15791
|
const tarPath = path10.join(tmpDir, "artifact.tar.gz");
|
|
15726
15792
|
await fs7.promises.writeFile(tarPath, tarBuffer);
|
|
15727
|
-
console.log(
|
|
15793
|
+
console.log(chalk12.gray("Syncing local files..."));
|
|
15728
15794
|
const remoteFiles = await listTarFiles(tarPath);
|
|
15729
15795
|
const remoteFilesSet = new Set(
|
|
15730
15796
|
remoteFiles.map((f) => f.replace(/\\/g, "/"))
|
|
@@ -15732,10 +15798,10 @@ var pullCommand2 = new Command9().name("pull").description("Pull cloud artifact
|
|
|
15732
15798
|
const removedCount = await removeExtraFiles(cwd, remoteFilesSet);
|
|
15733
15799
|
if (removedCount > 0) {
|
|
15734
15800
|
console.log(
|
|
15735
|
-
|
|
15801
|
+
chalk12.green(`\u2713 Removed ${removedCount} files not in remote`)
|
|
15736
15802
|
);
|
|
15737
15803
|
}
|
|
15738
|
-
console.log(
|
|
15804
|
+
console.log(chalk12.gray("Extracting files..."));
|
|
15739
15805
|
await tar4.extract({
|
|
15740
15806
|
file: tarPath,
|
|
15741
15807
|
cwd,
|
|
@@ -15743,22 +15809,83 @@ var pullCommand2 = new Command9().name("pull").description("Pull cloud artifact
|
|
|
15743
15809
|
});
|
|
15744
15810
|
await fs7.promises.unlink(tarPath);
|
|
15745
15811
|
await fs7.promises.rmdir(tmpDir);
|
|
15746
|
-
console.log(
|
|
15812
|
+
console.log(chalk12.green(`\u2713 Extracted ${remoteFiles.length} files`));
|
|
15747
15813
|
} catch (error43) {
|
|
15748
|
-
console.error(
|
|
15814
|
+
console.error(chalk12.red("\u2717 Pull failed"));
|
|
15749
15815
|
if (error43 instanceof Error) {
|
|
15750
|
-
console.error(
|
|
15816
|
+
console.error(chalk12.gray(` ${error43.message}`));
|
|
15817
|
+
}
|
|
15818
|
+
process.exit(1);
|
|
15819
|
+
}
|
|
15820
|
+
});
|
|
15821
|
+
|
|
15822
|
+
// src/commands/artifact/status.ts
|
|
15823
|
+
import { Command as Command11 } from "commander";
|
|
15824
|
+
import chalk13 from "chalk";
|
|
15825
|
+
function formatBytes6(bytes) {
|
|
15826
|
+
if (bytes === 0) return "0 B";
|
|
15827
|
+
const k = 1024;
|
|
15828
|
+
const sizes = ["B", "KB", "MB", "GB"];
|
|
15829
|
+
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
15830
|
+
return `${(bytes / Math.pow(k, i)).toFixed(2)} ${sizes[i]}`;
|
|
15831
|
+
}
|
|
15832
|
+
var statusCommand2 = new Command11().name("status").description("Show status of cloud artifact").action(async () => {
|
|
15833
|
+
try {
|
|
15834
|
+
const cwd = process.cwd();
|
|
15835
|
+
const config2 = await readStorageConfig(cwd);
|
|
15836
|
+
if (!config2) {
|
|
15837
|
+
console.error(chalk13.red("\u2717 No artifact initialized in this directory"));
|
|
15838
|
+
console.error(chalk13.gray(" Run: vm0 artifact init"));
|
|
15839
|
+
process.exit(1);
|
|
15840
|
+
}
|
|
15841
|
+
if (config2.type !== "artifact") {
|
|
15842
|
+
console.error(
|
|
15843
|
+
chalk13.red(
|
|
15844
|
+
"\u2717 This directory is initialized as a volume, not an artifact"
|
|
15845
|
+
)
|
|
15846
|
+
);
|
|
15847
|
+
console.error(chalk13.gray(" Use: vm0 volume status"));
|
|
15848
|
+
process.exit(1);
|
|
15849
|
+
}
|
|
15850
|
+
console.log(chalk13.cyan(`Checking artifact: ${config2.name}`));
|
|
15851
|
+
const url2 = `/api/storages/download?name=${encodeURIComponent(config2.name)}&type=artifact`;
|
|
15852
|
+
const response = await apiClient.get(url2);
|
|
15853
|
+
if (!response.ok) {
|
|
15854
|
+
if (response.status === 404) {
|
|
15855
|
+
console.error(chalk13.red("\u2717 Not found on remote"));
|
|
15856
|
+
console.error(chalk13.gray(" Run: vm0 artifact push"));
|
|
15857
|
+
} else {
|
|
15858
|
+
const error43 = await response.json();
|
|
15859
|
+
throw new Error(error43.error?.message || "Status check failed");
|
|
15860
|
+
}
|
|
15861
|
+
process.exit(1);
|
|
15862
|
+
}
|
|
15863
|
+
const info = await response.json();
|
|
15864
|
+
const shortVersion = info.versionId.slice(0, 8);
|
|
15865
|
+
if (info.empty) {
|
|
15866
|
+
console.log(chalk13.green("\u2713 Found (empty)"));
|
|
15867
|
+
console.log(chalk13.gray(` Version: ${shortVersion}`));
|
|
15868
|
+
} else {
|
|
15869
|
+
console.log(chalk13.green("\u2713 Found"));
|
|
15870
|
+
console.log(chalk13.gray(` Version: ${shortVersion}`));
|
|
15871
|
+
console.log(chalk13.gray(` Files: ${info.fileCount.toLocaleString()}`));
|
|
15872
|
+
console.log(chalk13.gray(` Size: ${formatBytes6(info.size)}`));
|
|
15873
|
+
}
|
|
15874
|
+
} catch (error43) {
|
|
15875
|
+
console.error(chalk13.red("\u2717 Status check failed"));
|
|
15876
|
+
if (error43 instanceof Error) {
|
|
15877
|
+
console.error(chalk13.gray(` ${error43.message}`));
|
|
15751
15878
|
}
|
|
15752
15879
|
process.exit(1);
|
|
15753
15880
|
}
|
|
15754
15881
|
});
|
|
15755
15882
|
|
|
15756
15883
|
// src/commands/artifact/index.ts
|
|
15757
|
-
var artifactCommand = new
|
|
15884
|
+
var artifactCommand = new Command12().name("artifact").description("Manage cloud artifacts (work products)").addCommand(initCommand2).addCommand(pushCommand2).addCommand(pullCommand2).addCommand(statusCommand2);
|
|
15758
15885
|
|
|
15759
15886
|
// src/commands/cook.ts
|
|
15760
|
-
import { Command as
|
|
15761
|
-
import
|
|
15887
|
+
import { Command as Command13 } from "commander";
|
|
15888
|
+
import chalk15 from "chalk";
|
|
15762
15889
|
import { readFile as readFile5, mkdir as mkdir5, writeFile as writeFile5, appendFile } from "fs/promises";
|
|
15763
15890
|
import { existsSync as existsSync6, readFileSync } from "fs";
|
|
15764
15891
|
import path11 from "path";
|
|
@@ -15769,7 +15896,7 @@ import { config as dotenvConfig2 } from "dotenv";
|
|
|
15769
15896
|
// src/lib/update-checker.ts
|
|
15770
15897
|
import https from "https";
|
|
15771
15898
|
import { spawn } from "child_process";
|
|
15772
|
-
import
|
|
15899
|
+
import chalk14 from "chalk";
|
|
15773
15900
|
var PACKAGE_NAME = "@vm0/cli";
|
|
15774
15901
|
var NPM_REGISTRY_URL = `https://registry.npmjs.org/${encodeURIComponent(PACKAGE_NAME)}/latest`;
|
|
15775
15902
|
var TIMEOUT_MS = 5e3;
|
|
@@ -15834,21 +15961,21 @@ function performUpgrade(packageManager) {
|
|
|
15834
15961
|
async function checkAndUpgrade(currentVersion, prompt) {
|
|
15835
15962
|
const latestVersion = await getLatestVersion();
|
|
15836
15963
|
if (latestVersion === null) {
|
|
15837
|
-
console.log(
|
|
15964
|
+
console.log(chalk14.yellow("Warning: Could not check for updates"));
|
|
15838
15965
|
console.log();
|
|
15839
15966
|
return false;
|
|
15840
15967
|
}
|
|
15841
15968
|
if (latestVersion === currentVersion) {
|
|
15842
15969
|
return false;
|
|
15843
15970
|
}
|
|
15844
|
-
console.log(
|
|
15971
|
+
console.log(chalk14.yellow("vm0 is currently in Early Access (EA)."));
|
|
15845
15972
|
console.log(
|
|
15846
|
-
|
|
15973
|
+
chalk14.yellow(
|
|
15847
15974
|
`Current version: ${currentVersion} -> Latest version: ${latestVersion}`
|
|
15848
15975
|
)
|
|
15849
15976
|
);
|
|
15850
15977
|
console.log(
|
|
15851
|
-
|
|
15978
|
+
chalk14.yellow(
|
|
15852
15979
|
"Please always use the latest version for best compatibility."
|
|
15853
15980
|
)
|
|
15854
15981
|
);
|
|
@@ -15857,20 +15984,20 @@ async function checkAndUpgrade(currentVersion, prompt) {
|
|
|
15857
15984
|
console.log(`Upgrading via ${packageManager}...`);
|
|
15858
15985
|
const success2 = await performUpgrade(packageManager);
|
|
15859
15986
|
if (success2) {
|
|
15860
|
-
console.log(
|
|
15987
|
+
console.log(chalk14.green(`Upgraded to ${latestVersion}`));
|
|
15861
15988
|
console.log();
|
|
15862
15989
|
console.log("To continue, run:");
|
|
15863
|
-
console.log(
|
|
15990
|
+
console.log(chalk14.cyan(` ${buildRerunCommand(prompt)}`));
|
|
15864
15991
|
return true;
|
|
15865
15992
|
}
|
|
15866
15993
|
console.log();
|
|
15867
|
-
console.log(
|
|
15868
|
-
console.log(
|
|
15869
|
-
console.log(
|
|
15870
|
-
console.log(
|
|
15994
|
+
console.log(chalk14.red("Upgrade failed. Please run manually:"));
|
|
15995
|
+
console.log(chalk14.cyan(` npm install -g ${PACKAGE_NAME}@latest`));
|
|
15996
|
+
console.log(chalk14.gray(" # or"));
|
|
15997
|
+
console.log(chalk14.cyan(` pnpm add -g ${PACKAGE_NAME}@latest`));
|
|
15871
15998
|
console.log();
|
|
15872
15999
|
console.log("Then re-run:");
|
|
15873
|
-
console.log(
|
|
16000
|
+
console.log(chalk14.cyan(` ${buildRerunCommand(prompt)}`));
|
|
15874
16001
|
return true;
|
|
15875
16002
|
}
|
|
15876
16003
|
|
|
@@ -15990,15 +16117,15 @@ async function generateEnvPlaceholders(missingVars, envFilePath) {
|
|
|
15990
16117
|
`);
|
|
15991
16118
|
}
|
|
15992
16119
|
}
|
|
15993
|
-
var cookCommand = new
|
|
15994
|
-
const shouldExit = await checkAndUpgrade("4.
|
|
16120
|
+
var cookCommand = new Command13().name("cook").description("One-click agent preparation and execution from vm0.yaml").argument("[prompt]", "Prompt for the agent").action(async (prompt) => {
|
|
16121
|
+
const shouldExit = await checkAndUpgrade("4.14.0", prompt);
|
|
15995
16122
|
if (shouldExit) {
|
|
15996
16123
|
process.exit(0);
|
|
15997
16124
|
}
|
|
15998
16125
|
const cwd = process.cwd();
|
|
15999
|
-
console.log(
|
|
16126
|
+
console.log(chalk15.blue(`Reading config: ${CONFIG_FILE3}`));
|
|
16000
16127
|
if (!existsSync6(CONFIG_FILE3)) {
|
|
16001
|
-
console.error(
|
|
16128
|
+
console.error(chalk15.red(`\u2717 Config file not found: ${CONFIG_FILE3}`));
|
|
16002
16129
|
process.exit(1);
|
|
16003
16130
|
}
|
|
16004
16131
|
let config2;
|
|
@@ -16006,22 +16133,22 @@ var cookCommand = new Command11().name("cook").description("One-click agent prep
|
|
|
16006
16133
|
const content = await readFile5(CONFIG_FILE3, "utf8");
|
|
16007
16134
|
config2 = parseYaml3(content);
|
|
16008
16135
|
} catch (error43) {
|
|
16009
|
-
console.error(
|
|
16136
|
+
console.error(chalk15.red("\u2717 Invalid YAML format"));
|
|
16010
16137
|
if (error43 instanceof Error) {
|
|
16011
|
-
console.error(
|
|
16138
|
+
console.error(chalk15.gray(` ${error43.message}`));
|
|
16012
16139
|
}
|
|
16013
16140
|
process.exit(1);
|
|
16014
16141
|
}
|
|
16015
16142
|
const validation = validateAgentCompose(config2);
|
|
16016
16143
|
if (!validation.valid) {
|
|
16017
|
-
console.error(
|
|
16144
|
+
console.error(chalk15.red(`\u2717 ${validation.error}`));
|
|
16018
16145
|
process.exit(1);
|
|
16019
16146
|
}
|
|
16020
16147
|
const agentNames = Object.keys(config2.agents);
|
|
16021
16148
|
const agentName = agentNames[0];
|
|
16022
16149
|
const volumeCount = config2.volumes ? Object.keys(config2.volumes).length : 0;
|
|
16023
16150
|
console.log(
|
|
16024
|
-
|
|
16151
|
+
chalk15.green(`\u2713 Config validated: 1 agent, ${volumeCount} volume(s)`)
|
|
16025
16152
|
);
|
|
16026
16153
|
const requiredVarNames = extractRequiredVarNames(config2);
|
|
16027
16154
|
if (requiredVarNames.length > 0) {
|
|
@@ -16031,25 +16158,25 @@ var cookCommand = new Command11().name("cook").description("One-click agent prep
|
|
|
16031
16158
|
await generateEnvPlaceholders(missingVars, envFilePath);
|
|
16032
16159
|
console.log();
|
|
16033
16160
|
console.log(
|
|
16034
|
-
|
|
16161
|
+
chalk15.yellow(
|
|
16035
16162
|
`\u26A0 Missing environment variables. Please fill in values in .env file:`
|
|
16036
16163
|
)
|
|
16037
16164
|
);
|
|
16038
16165
|
for (const varName of missingVars) {
|
|
16039
|
-
console.log(
|
|
16166
|
+
console.log(chalk15.yellow(` ${varName}`));
|
|
16040
16167
|
}
|
|
16041
16168
|
process.exit(1);
|
|
16042
16169
|
}
|
|
16043
16170
|
}
|
|
16044
16171
|
if (config2.volumes && Object.keys(config2.volumes).length > 0) {
|
|
16045
16172
|
console.log();
|
|
16046
|
-
console.log(
|
|
16173
|
+
console.log(chalk15.blue("Processing volumes..."));
|
|
16047
16174
|
for (const volumeConfig of Object.values(config2.volumes)) {
|
|
16048
16175
|
const volumeDir = path11.join(cwd, volumeConfig.name);
|
|
16049
|
-
console.log(
|
|
16176
|
+
console.log(chalk15.gray(` ${volumeConfig.name}/`));
|
|
16050
16177
|
if (!existsSync6(volumeDir)) {
|
|
16051
16178
|
console.error(
|
|
16052
|
-
|
|
16179
|
+
chalk15.red(
|
|
16053
16180
|
` \u2717 Directory not found. Create the directory and add files first.`
|
|
16054
16181
|
)
|
|
16055
16182
|
);
|
|
@@ -16062,30 +16189,30 @@ var cookCommand = new Command11().name("cook").description("One-click agent prep
|
|
|
16062
16189
|
cwd: volumeDir,
|
|
16063
16190
|
silent: true
|
|
16064
16191
|
});
|
|
16065
|
-
console.log(
|
|
16192
|
+
console.log(chalk15.green(` \u2713 Initialized`));
|
|
16066
16193
|
}
|
|
16067
16194
|
await execVm0Command(["volume", "push"], {
|
|
16068
16195
|
cwd: volumeDir,
|
|
16069
16196
|
silent: true
|
|
16070
16197
|
});
|
|
16071
|
-
console.log(
|
|
16198
|
+
console.log(chalk15.green(` \u2713 Pushed`));
|
|
16072
16199
|
} catch (error43) {
|
|
16073
|
-
console.error(
|
|
16200
|
+
console.error(chalk15.red(` \u2717 Failed`));
|
|
16074
16201
|
if (error43 instanceof Error) {
|
|
16075
|
-
console.error(
|
|
16202
|
+
console.error(chalk15.gray(` ${error43.message}`));
|
|
16076
16203
|
}
|
|
16077
16204
|
process.exit(1);
|
|
16078
16205
|
}
|
|
16079
16206
|
}
|
|
16080
16207
|
}
|
|
16081
16208
|
console.log();
|
|
16082
|
-
console.log(
|
|
16209
|
+
console.log(chalk15.blue("Processing artifact..."));
|
|
16083
16210
|
const artifactDir = path11.join(cwd, ARTIFACT_DIR);
|
|
16084
|
-
console.log(
|
|
16211
|
+
console.log(chalk15.gray(` ${ARTIFACT_DIR}/`));
|
|
16085
16212
|
try {
|
|
16086
16213
|
if (!existsSync6(artifactDir)) {
|
|
16087
16214
|
await mkdir5(artifactDir, { recursive: true });
|
|
16088
|
-
console.log(
|
|
16215
|
+
console.log(chalk15.green(` \u2713 Created directory`));
|
|
16089
16216
|
}
|
|
16090
16217
|
const existingConfig = await readStorageConfig(artifactDir);
|
|
16091
16218
|
if (!existingConfig) {
|
|
@@ -16093,38 +16220,38 @@ var cookCommand = new Command11().name("cook").description("One-click agent prep
|
|
|
16093
16220
|
cwd: artifactDir,
|
|
16094
16221
|
silent: true
|
|
16095
16222
|
});
|
|
16096
|
-
console.log(
|
|
16223
|
+
console.log(chalk15.green(` \u2713 Initialized`));
|
|
16097
16224
|
}
|
|
16098
16225
|
await execVm0Command(["artifact", "push"], {
|
|
16099
16226
|
cwd: artifactDir,
|
|
16100
16227
|
silent: true
|
|
16101
16228
|
});
|
|
16102
|
-
console.log(
|
|
16229
|
+
console.log(chalk15.green(` \u2713 Pushed`));
|
|
16103
16230
|
} catch (error43) {
|
|
16104
|
-
console.error(
|
|
16231
|
+
console.error(chalk15.red(` \u2717 Failed`));
|
|
16105
16232
|
if (error43 instanceof Error) {
|
|
16106
|
-
console.error(
|
|
16233
|
+
console.error(chalk15.gray(` ${error43.message}`));
|
|
16107
16234
|
}
|
|
16108
16235
|
process.exit(1);
|
|
16109
16236
|
}
|
|
16110
16237
|
console.log();
|
|
16111
|
-
console.log(
|
|
16238
|
+
console.log(chalk15.blue("Uploading compose..."));
|
|
16112
16239
|
try {
|
|
16113
16240
|
await execVm0Command(["compose", CONFIG_FILE3], {
|
|
16114
16241
|
cwd,
|
|
16115
16242
|
silent: true
|
|
16116
16243
|
});
|
|
16117
|
-
console.log(
|
|
16244
|
+
console.log(chalk15.green(`\u2713 Compose uploaded: ${agentName}`));
|
|
16118
16245
|
} catch (error43) {
|
|
16119
|
-
console.error(
|
|
16246
|
+
console.error(chalk15.red(`\u2717 Compose failed`));
|
|
16120
16247
|
if (error43 instanceof Error) {
|
|
16121
|
-
console.error(
|
|
16248
|
+
console.error(chalk15.gray(` ${error43.message}`));
|
|
16122
16249
|
}
|
|
16123
16250
|
process.exit(1);
|
|
16124
16251
|
}
|
|
16125
16252
|
if (prompt) {
|
|
16126
16253
|
console.log();
|
|
16127
|
-
console.log(
|
|
16254
|
+
console.log(chalk15.blue(`Running agent: ${agentName}`));
|
|
16128
16255
|
console.log();
|
|
16129
16256
|
let runOutput;
|
|
16130
16257
|
try {
|
|
@@ -16145,17 +16272,17 @@ var cookCommand = new Command11().name("cook").description("One-click agent prep
|
|
|
16145
16272
|
);
|
|
16146
16273
|
if (serverVersion) {
|
|
16147
16274
|
console.log();
|
|
16148
|
-
console.log(
|
|
16275
|
+
console.log(chalk15.blue("Pulling updated artifact..."));
|
|
16149
16276
|
try {
|
|
16150
16277
|
await execVm0Command(["artifact", "pull"], {
|
|
16151
16278
|
cwd: artifactDir,
|
|
16152
16279
|
silent: true
|
|
16153
16280
|
});
|
|
16154
|
-
console.log(
|
|
16281
|
+
console.log(chalk15.green(`\u2713 Artifact pulled (${serverVersion})`));
|
|
16155
16282
|
} catch (error43) {
|
|
16156
|
-
console.error(
|
|
16283
|
+
console.error(chalk15.red(`\u2717 Artifact pull failed`));
|
|
16157
16284
|
if (error43 instanceof Error) {
|
|
16158
|
-
console.error(
|
|
16285
|
+
console.error(chalk15.gray(` ${error43.message}`));
|
|
16159
16286
|
}
|
|
16160
16287
|
}
|
|
16161
16288
|
}
|
|
@@ -16163,7 +16290,7 @@ var cookCommand = new Command11().name("cook").description("One-click agent prep
|
|
|
16163
16290
|
console.log();
|
|
16164
16291
|
console.log(" Run your agent:");
|
|
16165
16292
|
console.log(
|
|
16166
|
-
|
|
16293
|
+
chalk15.cyan(
|
|
16167
16294
|
` vm0 run ${agentName} --artifact-name ${ARTIFACT_DIR} "your prompt"`
|
|
16168
16295
|
)
|
|
16169
16296
|
);
|
|
@@ -16171,25 +16298,25 @@ var cookCommand = new Command11().name("cook").description("One-click agent prep
|
|
|
16171
16298
|
});
|
|
16172
16299
|
|
|
16173
16300
|
// src/commands/image/index.ts
|
|
16174
|
-
import { Command as
|
|
16301
|
+
import { Command as Command17 } from "commander";
|
|
16175
16302
|
|
|
16176
16303
|
// src/commands/image/build.ts
|
|
16177
|
-
import { Command as
|
|
16178
|
-
import
|
|
16304
|
+
import { Command as Command14 } from "commander";
|
|
16305
|
+
import chalk16 from "chalk";
|
|
16179
16306
|
import { readFile as readFile6 } from "fs/promises";
|
|
16180
16307
|
import { existsSync as existsSync7 } from "fs";
|
|
16181
16308
|
var sleep2 = (ms) => new Promise((resolve2) => setTimeout(resolve2, ms));
|
|
16182
|
-
var buildCommand = new
|
|
16309
|
+
var buildCommand = new Command14().name("build").description("Build a custom image from a Dockerfile").requiredOption("-f, --file <path>", "Path to Dockerfile").requiredOption("-n, --name <name>", "Name for the image").option("--delete-existing", "Delete existing image before building").action(
|
|
16183
16310
|
async (options) => {
|
|
16184
16311
|
const { file: file2, name, deleteExisting } = options;
|
|
16185
16312
|
if (!existsSync7(file2)) {
|
|
16186
|
-
console.error(
|
|
16313
|
+
console.error(chalk16.red(`\u2717 Dockerfile not found: ${file2}`));
|
|
16187
16314
|
process.exit(1);
|
|
16188
16315
|
}
|
|
16189
16316
|
const nameRegex = /^[a-zA-Z0-9][a-zA-Z0-9-]{1,62}[a-zA-Z0-9]$/;
|
|
16190
16317
|
if (!nameRegex.test(name)) {
|
|
16191
16318
|
console.error(
|
|
16192
|
-
|
|
16319
|
+
chalk16.red(
|
|
16193
16320
|
"\u2717 Invalid name format. Must be 3-64 characters, letters, numbers, and hyphens only."
|
|
16194
16321
|
)
|
|
16195
16322
|
);
|
|
@@ -16197,7 +16324,7 @@ var buildCommand = new Command12().name("build").description("Build a custom ima
|
|
|
16197
16324
|
}
|
|
16198
16325
|
if (name.startsWith("vm0-")) {
|
|
16199
16326
|
console.error(
|
|
16200
|
-
|
|
16327
|
+
chalk16.red(
|
|
16201
16328
|
'\u2717 Invalid name. Cannot start with "vm0-" (reserved prefix).'
|
|
16202
16329
|
)
|
|
16203
16330
|
);
|
|
@@ -16205,8 +16332,8 @@ var buildCommand = new Command12().name("build").description("Build a custom ima
|
|
|
16205
16332
|
}
|
|
16206
16333
|
try {
|
|
16207
16334
|
const dockerfile = await readFile6(file2, "utf8");
|
|
16208
|
-
console.log(
|
|
16209
|
-
console.log(
|
|
16335
|
+
console.log(chalk16.blue(`Building image: ${name}`));
|
|
16336
|
+
console.log(chalk16.gray(` Dockerfile: ${file2}`));
|
|
16210
16337
|
console.log();
|
|
16211
16338
|
const buildInfo = await apiClient.createImage({
|
|
16212
16339
|
dockerfile,
|
|
@@ -16214,7 +16341,7 @@ var buildCommand = new Command12().name("build").description("Build a custom ima
|
|
|
16214
16341
|
deleteExisting
|
|
16215
16342
|
});
|
|
16216
16343
|
const { imageId, buildId } = buildInfo;
|
|
16217
|
-
console.log(
|
|
16344
|
+
console.log(chalk16.gray(` Build ID: ${buildId}`));
|
|
16218
16345
|
console.log();
|
|
16219
16346
|
let logsOffset = 0;
|
|
16220
16347
|
let status = "building";
|
|
@@ -16230,7 +16357,7 @@ var buildCommand = new Command12().name("build").description("Build a custom ima
|
|
|
16230
16357
|
}
|
|
16231
16358
|
const statusData = await statusResponse.json();
|
|
16232
16359
|
for (const log of statusData.logs) {
|
|
16233
|
-
console.log(
|
|
16360
|
+
console.log(chalk16.gray(` ${log}`));
|
|
16234
16361
|
}
|
|
16235
16362
|
logsOffset = statusData.logsOffset;
|
|
16236
16363
|
status = statusData.status;
|
|
@@ -16240,27 +16367,27 @@ var buildCommand = new Command12().name("build").description("Build a custom ima
|
|
|
16240
16367
|
}
|
|
16241
16368
|
console.log();
|
|
16242
16369
|
if (status === "ready") {
|
|
16243
|
-
console.log(
|
|
16370
|
+
console.log(chalk16.green(`\u2713 Image built: ${name}`));
|
|
16244
16371
|
console.log();
|
|
16245
16372
|
console.log("Use in vm0.yaml:");
|
|
16246
|
-
console.log(
|
|
16247
|
-
console.log(
|
|
16248
|
-
console.log(
|
|
16373
|
+
console.log(chalk16.cyan(` agents:`));
|
|
16374
|
+
console.log(chalk16.cyan(` your-agent:`));
|
|
16375
|
+
console.log(chalk16.cyan(` image: "${name}"`));
|
|
16249
16376
|
} else {
|
|
16250
|
-
console.error(
|
|
16377
|
+
console.error(chalk16.red(`\u2717 Build failed`));
|
|
16251
16378
|
process.exit(1);
|
|
16252
16379
|
}
|
|
16253
16380
|
} catch (error43) {
|
|
16254
16381
|
if (error43 instanceof Error) {
|
|
16255
16382
|
if (error43.message.includes("Not authenticated")) {
|
|
16256
16383
|
console.error(
|
|
16257
|
-
|
|
16384
|
+
chalk16.red("\u2717 Not authenticated. Run: vm0 auth login")
|
|
16258
16385
|
);
|
|
16259
16386
|
} else {
|
|
16260
|
-
console.error(
|
|
16387
|
+
console.error(chalk16.red(`\u2717 ${error43.message}`));
|
|
16261
16388
|
}
|
|
16262
16389
|
} else {
|
|
16263
|
-
console.error(
|
|
16390
|
+
console.error(chalk16.red("\u2717 An unexpected error occurred"));
|
|
16264
16391
|
}
|
|
16265
16392
|
process.exit(1);
|
|
16266
16393
|
}
|
|
@@ -16268,9 +16395,9 @@ var buildCommand = new Command12().name("build").description("Build a custom ima
|
|
|
16268
16395
|
);
|
|
16269
16396
|
|
|
16270
16397
|
// src/commands/image/list.ts
|
|
16271
|
-
import { Command as
|
|
16272
|
-
import
|
|
16273
|
-
var listCommand = new
|
|
16398
|
+
import { Command as Command15 } from "commander";
|
|
16399
|
+
import chalk17 from "chalk";
|
|
16400
|
+
var listCommand = new Command15().name("list").alias("ls").description("List your custom images").action(async () => {
|
|
16274
16401
|
try {
|
|
16275
16402
|
const response = await apiClient.get("/api/images");
|
|
16276
16403
|
if (!response.ok) {
|
|
@@ -16282,53 +16409,53 @@ var listCommand = new Command13().name("list").alias("ls").description("List you
|
|
|
16282
16409
|
const data = await response.json();
|
|
16283
16410
|
const { images } = data;
|
|
16284
16411
|
if (images.length === 0) {
|
|
16285
|
-
console.log(
|
|
16412
|
+
console.log(chalk17.gray("No images found."));
|
|
16286
16413
|
console.log();
|
|
16287
16414
|
console.log("Build your first image:");
|
|
16288
16415
|
console.log(
|
|
16289
|
-
|
|
16416
|
+
chalk17.cyan(" vm0 image build --file Dockerfile --name my-image")
|
|
16290
16417
|
);
|
|
16291
16418
|
return;
|
|
16292
16419
|
}
|
|
16293
|
-
console.log(
|
|
16420
|
+
console.log(chalk17.bold("Your images:"));
|
|
16294
16421
|
console.log();
|
|
16295
16422
|
console.log(
|
|
16296
|
-
|
|
16423
|
+
chalk17.gray(
|
|
16297
16424
|
`${"NAME".padEnd(30)} ${"STATUS".padEnd(12)} ${"CREATED".padEnd(20)}`
|
|
16298
16425
|
)
|
|
16299
16426
|
);
|
|
16300
|
-
console.log(
|
|
16427
|
+
console.log(chalk17.gray("-".repeat(62)));
|
|
16301
16428
|
for (const image of images) {
|
|
16302
|
-
const statusColor = image.status === "ready" ?
|
|
16429
|
+
const statusColor = image.status === "ready" ? chalk17.green : image.status === "building" ? chalk17.yellow : chalk17.red;
|
|
16303
16430
|
const createdAt = new Date(image.createdAt).toLocaleString();
|
|
16304
16431
|
console.log(
|
|
16305
16432
|
`${image.alias.padEnd(30)} ${statusColor(image.status.padEnd(12))} ${createdAt.padEnd(20)}`
|
|
16306
16433
|
);
|
|
16307
16434
|
if (image.status === "error" && image.errorMessage) {
|
|
16308
|
-
console.log(
|
|
16435
|
+
console.log(chalk17.red(` Error: ${image.errorMessage}`));
|
|
16309
16436
|
}
|
|
16310
16437
|
}
|
|
16311
16438
|
console.log();
|
|
16312
|
-
console.log(
|
|
16439
|
+
console.log(chalk17.gray(`Total: ${images.length} image(s)`));
|
|
16313
16440
|
} catch (error43) {
|
|
16314
16441
|
if (error43 instanceof Error) {
|
|
16315
16442
|
if (error43.message.includes("Not authenticated")) {
|
|
16316
|
-
console.error(
|
|
16443
|
+
console.error(chalk17.red("Not authenticated. Run: vm0 auth login"));
|
|
16317
16444
|
} else {
|
|
16318
|
-
console.error(
|
|
16445
|
+
console.error(chalk17.red(`Error: ${error43.message}`));
|
|
16319
16446
|
}
|
|
16320
16447
|
} else {
|
|
16321
|
-
console.error(
|
|
16448
|
+
console.error(chalk17.red("An unexpected error occurred"));
|
|
16322
16449
|
}
|
|
16323
16450
|
process.exit(1);
|
|
16324
16451
|
}
|
|
16325
16452
|
});
|
|
16326
16453
|
|
|
16327
16454
|
// src/commands/image/delete.ts
|
|
16328
|
-
import { Command as
|
|
16329
|
-
import
|
|
16455
|
+
import { Command as Command16 } from "commander";
|
|
16456
|
+
import chalk18 from "chalk";
|
|
16330
16457
|
import * as readline from "readline";
|
|
16331
|
-
var deleteCommand = new
|
|
16458
|
+
var deleteCommand = new Command16().name("delete").alias("rm").description("Delete a custom image").argument("<name>", "Name of the image to delete").option("-f, --force", "Skip confirmation prompt").action(async (name, options) => {
|
|
16332
16459
|
try {
|
|
16333
16460
|
const listResponse = await apiClient.get("/api/images");
|
|
16334
16461
|
if (!listResponse.ok) {
|
|
@@ -16340,7 +16467,7 @@ var deleteCommand = new Command14().name("delete").alias("rm").description("Dele
|
|
|
16340
16467
|
const data = await listResponse.json();
|
|
16341
16468
|
const image = data.images.find((img) => img.alias === name);
|
|
16342
16469
|
if (!image) {
|
|
16343
|
-
console.error(
|
|
16470
|
+
console.error(chalk18.red(`Image not found: ${name}`));
|
|
16344
16471
|
process.exit(1);
|
|
16345
16472
|
}
|
|
16346
16473
|
if (!options.force) {
|
|
@@ -16350,7 +16477,7 @@ var deleteCommand = new Command14().name("delete").alias("rm").description("Dele
|
|
|
16350
16477
|
});
|
|
16351
16478
|
const answer = await new Promise((resolve2) => {
|
|
16352
16479
|
rl.question(
|
|
16353
|
-
|
|
16480
|
+
chalk18.yellow(`Delete image "${name}"? [y/N] `),
|
|
16354
16481
|
(answer2) => {
|
|
16355
16482
|
rl.close();
|
|
16356
16483
|
resolve2(answer2);
|
|
@@ -16358,7 +16485,7 @@ var deleteCommand = new Command14().name("delete").alias("rm").description("Dele
|
|
|
16358
16485
|
);
|
|
16359
16486
|
});
|
|
16360
16487
|
if (answer.toLowerCase() !== "y" && answer.toLowerCase() !== "yes") {
|
|
16361
|
-
console.log(
|
|
16488
|
+
console.log(chalk18.gray("Cancelled."));
|
|
16362
16489
|
return;
|
|
16363
16490
|
}
|
|
16364
16491
|
}
|
|
@@ -16369,27 +16496,27 @@ var deleteCommand = new Command14().name("delete").alias("rm").description("Dele
|
|
|
16369
16496
|
error43.error?.message || "Failed to delete image"
|
|
16370
16497
|
);
|
|
16371
16498
|
}
|
|
16372
|
-
console.log(
|
|
16499
|
+
console.log(chalk18.green(`Deleted image: ${name}`));
|
|
16373
16500
|
} catch (error43) {
|
|
16374
16501
|
if (error43 instanceof Error) {
|
|
16375
16502
|
if (error43.message.includes("Not authenticated")) {
|
|
16376
|
-
console.error(
|
|
16503
|
+
console.error(chalk18.red("Not authenticated. Run: vm0 auth login"));
|
|
16377
16504
|
} else {
|
|
16378
|
-
console.error(
|
|
16505
|
+
console.error(chalk18.red(`Error: ${error43.message}`));
|
|
16379
16506
|
}
|
|
16380
16507
|
} else {
|
|
16381
|
-
console.error(
|
|
16508
|
+
console.error(chalk18.red("An unexpected error occurred"));
|
|
16382
16509
|
}
|
|
16383
16510
|
process.exit(1);
|
|
16384
16511
|
}
|
|
16385
16512
|
});
|
|
16386
16513
|
|
|
16387
16514
|
// src/commands/image/index.ts
|
|
16388
|
-
var imageCommand = new
|
|
16515
|
+
var imageCommand = new Command17().name("image").description("Manage custom images").addCommand(buildCommand).addCommand(listCommand).addCommand(deleteCommand);
|
|
16389
16516
|
|
|
16390
16517
|
// src/commands/logs/index.ts
|
|
16391
|
-
import { Command as
|
|
16392
|
-
import
|
|
16518
|
+
import { Command as Command18 } from "commander";
|
|
16519
|
+
import chalk19 from "chalk";
|
|
16393
16520
|
|
|
16394
16521
|
// src/lib/time-parser.ts
|
|
16395
16522
|
function parseTime(timeStr) {
|
|
@@ -16436,7 +16563,7 @@ function parseRelativeTime(value, unit) {
|
|
|
16436
16563
|
}
|
|
16437
16564
|
|
|
16438
16565
|
// src/commands/logs/index.ts
|
|
16439
|
-
function
|
|
16566
|
+
function formatBytes7(bytes) {
|
|
16440
16567
|
if (bytes === 0) return "0 B";
|
|
16441
16568
|
const k = 1024;
|
|
16442
16569
|
const sizes = ["B", "KB", "MB", "GB"];
|
|
@@ -16446,28 +16573,28 @@ function formatBytes5(bytes) {
|
|
|
16446
16573
|
function formatMetric(metric) {
|
|
16447
16574
|
const memPercent = (metric.mem_used / metric.mem_total * 100).toFixed(1);
|
|
16448
16575
|
const diskPercent = (metric.disk_used / metric.disk_total * 100).toFixed(1);
|
|
16449
|
-
return `[${metric.ts}] CPU: ${metric.cpu.toFixed(1)}% | Mem: ${
|
|
16576
|
+
return `[${metric.ts}] CPU: ${metric.cpu.toFixed(1)}% | Mem: ${formatBytes7(metric.mem_used)}/${formatBytes7(metric.mem_total)} (${memPercent}%) | Disk: ${formatBytes7(metric.disk_used)}/${formatBytes7(metric.disk_total)} (${diskPercent}%)`;
|
|
16450
16577
|
}
|
|
16451
16578
|
function formatNetworkLog(entry) {
|
|
16452
16579
|
let statusColor;
|
|
16453
16580
|
if (entry.status >= 200 && entry.status < 300) {
|
|
16454
|
-
statusColor =
|
|
16581
|
+
statusColor = chalk19.green;
|
|
16455
16582
|
} else if (entry.status >= 300 && entry.status < 400) {
|
|
16456
|
-
statusColor =
|
|
16583
|
+
statusColor = chalk19.yellow;
|
|
16457
16584
|
} else if (entry.status >= 400) {
|
|
16458
|
-
statusColor =
|
|
16585
|
+
statusColor = chalk19.red;
|
|
16459
16586
|
} else {
|
|
16460
|
-
statusColor =
|
|
16587
|
+
statusColor = chalk19.gray;
|
|
16461
16588
|
}
|
|
16462
16589
|
let latencyColor;
|
|
16463
16590
|
if (entry.latency_ms < 500) {
|
|
16464
|
-
latencyColor =
|
|
16591
|
+
latencyColor = chalk19.green;
|
|
16465
16592
|
} else if (entry.latency_ms < 2e3) {
|
|
16466
|
-
latencyColor =
|
|
16593
|
+
latencyColor = chalk19.yellow;
|
|
16467
16594
|
} else {
|
|
16468
|
-
latencyColor =
|
|
16595
|
+
latencyColor = chalk19.red;
|
|
16469
16596
|
}
|
|
16470
|
-
return `[${entry.timestamp}] ${
|
|
16597
|
+
return `[${entry.timestamp}] ${chalk19.cyan(entry.method.padEnd(6))} ${statusColor(entry.status)} ${latencyColor(entry.latency_ms + "ms")} ${formatBytes7(entry.request_size)}/${formatBytes7(entry.response_size)} ${chalk19.gray(entry.url)}`;
|
|
16471
16598
|
}
|
|
16472
16599
|
function renderAgentEvent(event) {
|
|
16473
16600
|
const parsed = ClaudeEventParser.parse(
|
|
@@ -16487,7 +16614,7 @@ function getLogType(options) {
|
|
|
16487
16614
|
].filter(Boolean).length;
|
|
16488
16615
|
if (selected > 1) {
|
|
16489
16616
|
console.error(
|
|
16490
|
-
|
|
16617
|
+
chalk19.red(
|
|
16491
16618
|
"Options --agent, --system, --metrics, and --network are mutually exclusive"
|
|
16492
16619
|
)
|
|
16493
16620
|
);
|
|
@@ -16498,7 +16625,7 @@ function getLogType(options) {
|
|
|
16498
16625
|
if (options.network) return "network";
|
|
16499
16626
|
return "agent";
|
|
16500
16627
|
}
|
|
16501
|
-
var logsCommand = new
|
|
16628
|
+
var logsCommand = new Command18().name("logs").description("View logs for an agent run").argument("<runId>", "Run ID to fetch logs for").option("-a, --agent", "Show agent events (default)").option("-s, --system", "Show system log").option("-m, --metrics", "Show metrics").option("-n, --network", "Show network logs (proxy traffic)").option(
|
|
16502
16629
|
"--since <time>",
|
|
16503
16630
|
"Show logs since timestamp (e.g., 5m, 2h, 1d, 2024-01-15T10:30:00Z, 1705312200)"
|
|
16504
16631
|
).option(
|
|
@@ -16540,7 +16667,7 @@ var logsCommand = new Command16().name("logs").description("View logs for an age
|
|
|
16540
16667
|
async function showAgentEvents(runId, options) {
|
|
16541
16668
|
const response = await apiClient.getAgentEvents(runId, options);
|
|
16542
16669
|
if (response.events.length === 0) {
|
|
16543
|
-
console.log(
|
|
16670
|
+
console.log(chalk19.yellow("No agent events found for this run."));
|
|
16544
16671
|
return;
|
|
16545
16672
|
}
|
|
16546
16673
|
for (const event of response.events) {
|
|
@@ -16549,7 +16676,7 @@ async function showAgentEvents(runId, options) {
|
|
|
16549
16676
|
if (response.hasMore) {
|
|
16550
16677
|
console.log();
|
|
16551
16678
|
console.log(
|
|
16552
|
-
|
|
16679
|
+
chalk19.gray(
|
|
16553
16680
|
`Showing ${response.events.length} events. Use --limit to see more.`
|
|
16554
16681
|
)
|
|
16555
16682
|
);
|
|
@@ -16558,21 +16685,21 @@ async function showAgentEvents(runId, options) {
|
|
|
16558
16685
|
async function showSystemLog(runId, options) {
|
|
16559
16686
|
const response = await apiClient.getSystemLog(runId, options);
|
|
16560
16687
|
if (!response.systemLog) {
|
|
16561
|
-
console.log(
|
|
16688
|
+
console.log(chalk19.yellow("No system log found for this run."));
|
|
16562
16689
|
return;
|
|
16563
16690
|
}
|
|
16564
16691
|
console.log(response.systemLog);
|
|
16565
16692
|
if (response.hasMore) {
|
|
16566
16693
|
console.log();
|
|
16567
16694
|
console.log(
|
|
16568
|
-
|
|
16695
|
+
chalk19.gray("More log entries available. Use --limit to see more.")
|
|
16569
16696
|
);
|
|
16570
16697
|
}
|
|
16571
16698
|
}
|
|
16572
16699
|
async function showMetrics(runId, options) {
|
|
16573
16700
|
const response = await apiClient.getMetrics(runId, options);
|
|
16574
16701
|
if (response.metrics.length === 0) {
|
|
16575
|
-
console.log(
|
|
16702
|
+
console.log(chalk19.yellow("No metrics found for this run."));
|
|
16576
16703
|
return;
|
|
16577
16704
|
}
|
|
16578
16705
|
for (const metric of response.metrics) {
|
|
@@ -16581,7 +16708,7 @@ async function showMetrics(runId, options) {
|
|
|
16581
16708
|
if (response.hasMore) {
|
|
16582
16709
|
console.log();
|
|
16583
16710
|
console.log(
|
|
16584
|
-
|
|
16711
|
+
chalk19.gray(
|
|
16585
16712
|
`Showing ${response.metrics.length} metrics. Use --limit to see more.`
|
|
16586
16713
|
)
|
|
16587
16714
|
);
|
|
@@ -16591,7 +16718,7 @@ async function showNetworkLogs(runId, options) {
|
|
|
16591
16718
|
const response = await apiClient.getNetworkLogs(runId, options);
|
|
16592
16719
|
if (response.networkLogs.length === 0) {
|
|
16593
16720
|
console.log(
|
|
16594
|
-
|
|
16721
|
+
chalk19.yellow(
|
|
16595
16722
|
"No network logs found for this run. Network logs are only captured when beta_network_security is enabled."
|
|
16596
16723
|
)
|
|
16597
16724
|
);
|
|
@@ -16603,7 +16730,7 @@ async function showNetworkLogs(runId, options) {
|
|
|
16603
16730
|
if (response.hasMore) {
|
|
16604
16731
|
console.log();
|
|
16605
16732
|
console.log(
|
|
16606
|
-
|
|
16733
|
+
chalk19.gray(
|
|
16607
16734
|
`Showing ${response.networkLogs.length} network logs. Use --limit to see more.`
|
|
16608
16735
|
)
|
|
16609
16736
|
);
|
|
@@ -16612,25 +16739,25 @@ async function showNetworkLogs(runId, options) {
|
|
|
16612
16739
|
function handleError(error43, runId) {
|
|
16613
16740
|
if (error43 instanceof Error) {
|
|
16614
16741
|
if (error43.message.includes("Not authenticated")) {
|
|
16615
|
-
console.error(
|
|
16742
|
+
console.error(chalk19.red("Not authenticated. Run: vm0 auth login"));
|
|
16616
16743
|
} else if (error43.message.includes("not found")) {
|
|
16617
|
-
console.error(
|
|
16744
|
+
console.error(chalk19.red(`Run not found: ${runId}`));
|
|
16618
16745
|
} else if (error43.message.includes("Invalid time format")) {
|
|
16619
|
-
console.error(
|
|
16746
|
+
console.error(chalk19.red(error43.message));
|
|
16620
16747
|
} else {
|
|
16621
|
-
console.error(
|
|
16622
|
-
console.error(
|
|
16748
|
+
console.error(chalk19.red("Failed to fetch logs"));
|
|
16749
|
+
console.error(chalk19.gray(` ${error43.message}`));
|
|
16623
16750
|
}
|
|
16624
16751
|
} else {
|
|
16625
|
-
console.error(
|
|
16752
|
+
console.error(chalk19.red("An unexpected error occurred"));
|
|
16626
16753
|
}
|
|
16627
16754
|
}
|
|
16628
16755
|
|
|
16629
16756
|
// src/index.ts
|
|
16630
|
-
var program = new
|
|
16631
|
-
program.name("vm0").description("VM0 CLI - A modern build tool").version("4.
|
|
16757
|
+
var program = new Command19();
|
|
16758
|
+
program.name("vm0").description("VM0 CLI - A modern build tool").version("4.14.0");
|
|
16632
16759
|
program.command("info").description("Display environment information").action(async () => {
|
|
16633
|
-
console.log(
|
|
16760
|
+
console.log(chalk20.cyan("System Information:"));
|
|
16634
16761
|
console.log(`Node Version: ${process.version}`);
|
|
16635
16762
|
console.log(`Platform: ${process.platform}`);
|
|
16636
16763
|
console.log(`Architecture: ${process.arch}`);
|