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