@vm0/cli 4.10.0 → 4.12.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 +219 -99
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -7,7 +7,7 @@ var __export = (target, all) => {
|
|
|
7
7
|
|
|
8
8
|
// src/index.ts
|
|
9
9
|
import { Command as Command17 } from "commander";
|
|
10
|
-
import
|
|
10
|
+
import chalk18 from "chalk";
|
|
11
11
|
|
|
12
12
|
// src/lib/auth.ts
|
|
13
13
|
import chalk from "chalk";
|
|
@@ -163,6 +163,21 @@ async function checkAuthStatus() {
|
|
|
163
163
|
console.log(chalk.blue("Using token from VM0_TOKEN environment variable"));
|
|
164
164
|
}
|
|
165
165
|
}
|
|
166
|
+
async function setupToken() {
|
|
167
|
+
const token = await getToken();
|
|
168
|
+
if (!token) {
|
|
169
|
+
console.error(chalk.red("Error: Not authenticated."));
|
|
170
|
+
console.error("");
|
|
171
|
+
console.error("To get a token for CI/CD:");
|
|
172
|
+
console.error(" 1. Run 'vm0 auth login' to authenticate");
|
|
173
|
+
console.error(" 2. Run 'vm0 auth setup-token' to get your token");
|
|
174
|
+
console.error(
|
|
175
|
+
" 3. Store the token in your CI/CD secrets (e.g., VM0_TOKEN)"
|
|
176
|
+
);
|
|
177
|
+
process.exit(1);
|
|
178
|
+
}
|
|
179
|
+
console.log(token);
|
|
180
|
+
}
|
|
166
181
|
|
|
167
182
|
// src/commands/compose.ts
|
|
168
183
|
import { Command } from "commander";
|
|
@@ -15725,18 +15740,116 @@ var artifactCommand = new Command10().name("artifact").description("Manage cloud
|
|
|
15725
15740
|
|
|
15726
15741
|
// src/commands/cook.ts
|
|
15727
15742
|
import { Command as Command11 } from "commander";
|
|
15728
|
-
import
|
|
15743
|
+
import chalk13 from "chalk";
|
|
15729
15744
|
import { readFile as readFile5, mkdir as mkdir5, writeFile as writeFile5, appendFile } from "fs/promises";
|
|
15730
15745
|
import { existsSync as existsSync5, readFileSync } from "fs";
|
|
15731
15746
|
import path12 from "path";
|
|
15732
|
-
import { spawn } from "child_process";
|
|
15747
|
+
import { spawn as spawn2 } from "child_process";
|
|
15733
15748
|
import { parse as parseYaml3 } from "yaml";
|
|
15734
15749
|
import { config as dotenvConfig2 } from "dotenv";
|
|
15750
|
+
|
|
15751
|
+
// src/lib/update-checker.ts
|
|
15752
|
+
import https from "https";
|
|
15753
|
+
import { spawn } from "child_process";
|
|
15754
|
+
import chalk12 from "chalk";
|
|
15755
|
+
var PACKAGE_NAME = "@vm0/cli";
|
|
15756
|
+
var NPM_REGISTRY_URL = `https://registry.npmjs.org/${encodeURIComponent(PACKAGE_NAME)}/latest`;
|
|
15757
|
+
var TIMEOUT_MS = 5e3;
|
|
15758
|
+
function escapeForShell(str) {
|
|
15759
|
+
return `"${str.replace(/"/g, '\\"')}"`;
|
|
15760
|
+
}
|
|
15761
|
+
function buildRerunCommand(prompt) {
|
|
15762
|
+
if (prompt) {
|
|
15763
|
+
return `vm0 cook ${escapeForShell(prompt)}`;
|
|
15764
|
+
}
|
|
15765
|
+
return "vm0 cook";
|
|
15766
|
+
}
|
|
15767
|
+
function getLatestVersion() {
|
|
15768
|
+
return new Promise((resolve2) => {
|
|
15769
|
+
const req = https.get(NPM_REGISTRY_URL, (res) => {
|
|
15770
|
+
let data = "";
|
|
15771
|
+
res.on("data", (chunk) => {
|
|
15772
|
+
data += chunk.toString();
|
|
15773
|
+
});
|
|
15774
|
+
res.on("end", () => {
|
|
15775
|
+
try {
|
|
15776
|
+
const json2 = JSON.parse(data);
|
|
15777
|
+
resolve2(json2.version ?? null);
|
|
15778
|
+
} catch {
|
|
15779
|
+
resolve2(null);
|
|
15780
|
+
}
|
|
15781
|
+
});
|
|
15782
|
+
});
|
|
15783
|
+
req.on("error", () => {
|
|
15784
|
+
resolve2(null);
|
|
15785
|
+
});
|
|
15786
|
+
req.setTimeout(TIMEOUT_MS, () => {
|
|
15787
|
+
req.destroy();
|
|
15788
|
+
resolve2(null);
|
|
15789
|
+
});
|
|
15790
|
+
});
|
|
15791
|
+
}
|
|
15792
|
+
function performUpgrade() {
|
|
15793
|
+
return new Promise((resolve2) => {
|
|
15794
|
+
const npm = process.platform === "win32" ? "npm.cmd" : "npm";
|
|
15795
|
+
const child = spawn(npm, ["install", "-g", `${PACKAGE_NAME}@latest`], {
|
|
15796
|
+
stdio: "inherit",
|
|
15797
|
+
shell: process.platform === "win32"
|
|
15798
|
+
});
|
|
15799
|
+
child.on("close", (code) => {
|
|
15800
|
+
resolve2(code === 0);
|
|
15801
|
+
});
|
|
15802
|
+
child.on("error", () => {
|
|
15803
|
+
resolve2(false);
|
|
15804
|
+
});
|
|
15805
|
+
});
|
|
15806
|
+
}
|
|
15807
|
+
async function checkAndUpgrade(currentVersion, prompt) {
|
|
15808
|
+
const latestVersion = await getLatestVersion();
|
|
15809
|
+
if (latestVersion === null) {
|
|
15810
|
+
console.log(chalk12.yellow("Warning: Could not check for updates"));
|
|
15811
|
+
console.log();
|
|
15812
|
+
return false;
|
|
15813
|
+
}
|
|
15814
|
+
if (latestVersion === currentVersion) {
|
|
15815
|
+
return false;
|
|
15816
|
+
}
|
|
15817
|
+
console.log(chalk12.yellow("vm0 is currently in Early Access (EA)."));
|
|
15818
|
+
console.log(
|
|
15819
|
+
chalk12.yellow(
|
|
15820
|
+
`Current version: ${currentVersion} -> Latest version: ${latestVersion}`
|
|
15821
|
+
)
|
|
15822
|
+
);
|
|
15823
|
+
console.log(
|
|
15824
|
+
chalk12.yellow(
|
|
15825
|
+
"Please always use the latest version for best compatibility."
|
|
15826
|
+
)
|
|
15827
|
+
);
|
|
15828
|
+
console.log();
|
|
15829
|
+
console.log("Upgrading...");
|
|
15830
|
+
const success2 = await performUpgrade();
|
|
15831
|
+
if (success2) {
|
|
15832
|
+
console.log(chalk12.green(`Upgraded to ${latestVersion}`));
|
|
15833
|
+
console.log();
|
|
15834
|
+
console.log("To continue, run:");
|
|
15835
|
+
console.log(chalk12.cyan(` ${buildRerunCommand(prompt)}`));
|
|
15836
|
+
return true;
|
|
15837
|
+
}
|
|
15838
|
+
console.log();
|
|
15839
|
+
console.log(chalk12.red("Upgrade failed. Please run manually:"));
|
|
15840
|
+
console.log(chalk12.cyan(` npm install -g ${PACKAGE_NAME}@latest`));
|
|
15841
|
+
console.log();
|
|
15842
|
+
console.log("Then re-run:");
|
|
15843
|
+
console.log(chalk12.cyan(` ${buildRerunCommand(prompt)}`));
|
|
15844
|
+
return true;
|
|
15845
|
+
}
|
|
15846
|
+
|
|
15847
|
+
// src/commands/cook.ts
|
|
15735
15848
|
var CONFIG_FILE3 = "vm0.yaml";
|
|
15736
15849
|
var ARTIFACT_DIR = "artifact";
|
|
15737
15850
|
function execVm0Command(args, options = {}) {
|
|
15738
15851
|
return new Promise((resolve2, reject) => {
|
|
15739
|
-
const proc =
|
|
15852
|
+
const proc = spawn2("vm0", args, {
|
|
15740
15853
|
cwd: options.cwd,
|
|
15741
15854
|
stdio: options.silent ? "pipe" : ["inherit", "inherit", "inherit"],
|
|
15742
15855
|
shell: process.platform === "win32"
|
|
@@ -15765,7 +15878,7 @@ function execVm0Command(args, options = {}) {
|
|
|
15765
15878
|
}
|
|
15766
15879
|
function execVm0RunWithCapture(args, options = {}) {
|
|
15767
15880
|
return new Promise((resolve2, reject) => {
|
|
15768
|
-
const proc =
|
|
15881
|
+
const proc = spawn2("vm0", args, {
|
|
15769
15882
|
cwd: options.cwd,
|
|
15770
15883
|
stdio: ["inherit", "pipe", "pipe"],
|
|
15771
15884
|
shell: process.platform === "win32"
|
|
@@ -15848,10 +15961,14 @@ async function generateEnvPlaceholders(missingVars, envFilePath) {
|
|
|
15848
15961
|
}
|
|
15849
15962
|
}
|
|
15850
15963
|
var cookCommand = new Command11().name("cook").description("One-click agent preparation and execution from vm0.yaml").argument("[prompt]", "Prompt for the agent").action(async (prompt) => {
|
|
15964
|
+
const shouldExit = await checkAndUpgrade("4.12.0", prompt);
|
|
15965
|
+
if (shouldExit) {
|
|
15966
|
+
process.exit(0);
|
|
15967
|
+
}
|
|
15851
15968
|
const cwd = process.cwd();
|
|
15852
|
-
console.log(
|
|
15969
|
+
console.log(chalk13.blue(`Reading config: ${CONFIG_FILE3}`));
|
|
15853
15970
|
if (!existsSync5(CONFIG_FILE3)) {
|
|
15854
|
-
console.error(
|
|
15971
|
+
console.error(chalk13.red(`\u2717 Config file not found: ${CONFIG_FILE3}`));
|
|
15855
15972
|
process.exit(1);
|
|
15856
15973
|
}
|
|
15857
15974
|
let config2;
|
|
@@ -15859,22 +15976,22 @@ var cookCommand = new Command11().name("cook").description("One-click agent prep
|
|
|
15859
15976
|
const content = await readFile5(CONFIG_FILE3, "utf8");
|
|
15860
15977
|
config2 = parseYaml3(content);
|
|
15861
15978
|
} catch (error43) {
|
|
15862
|
-
console.error(
|
|
15979
|
+
console.error(chalk13.red("\u2717 Invalid YAML format"));
|
|
15863
15980
|
if (error43 instanceof Error) {
|
|
15864
|
-
console.error(
|
|
15981
|
+
console.error(chalk13.gray(` ${error43.message}`));
|
|
15865
15982
|
}
|
|
15866
15983
|
process.exit(1);
|
|
15867
15984
|
}
|
|
15868
15985
|
const validation = validateAgentCompose(config2);
|
|
15869
15986
|
if (!validation.valid) {
|
|
15870
|
-
console.error(
|
|
15987
|
+
console.error(chalk13.red(`\u2717 ${validation.error}`));
|
|
15871
15988
|
process.exit(1);
|
|
15872
15989
|
}
|
|
15873
15990
|
const agentNames = Object.keys(config2.agents);
|
|
15874
15991
|
const agentName = agentNames[0];
|
|
15875
15992
|
const volumeCount = config2.volumes ? Object.keys(config2.volumes).length : 0;
|
|
15876
15993
|
console.log(
|
|
15877
|
-
|
|
15994
|
+
chalk13.green(`\u2713 Config validated: 1 agent, ${volumeCount} volume(s)`)
|
|
15878
15995
|
);
|
|
15879
15996
|
const requiredVarNames = extractRequiredVarNames(config2);
|
|
15880
15997
|
if (requiredVarNames.length > 0) {
|
|
@@ -15884,25 +16001,25 @@ var cookCommand = new Command11().name("cook").description("One-click agent prep
|
|
|
15884
16001
|
await generateEnvPlaceholders(missingVars, envFilePath);
|
|
15885
16002
|
console.log();
|
|
15886
16003
|
console.log(
|
|
15887
|
-
|
|
16004
|
+
chalk13.yellow(
|
|
15888
16005
|
`\u26A0 Missing environment variables. Please fill in values in .env file:`
|
|
15889
16006
|
)
|
|
15890
16007
|
);
|
|
15891
16008
|
for (const varName of missingVars) {
|
|
15892
|
-
console.log(
|
|
16009
|
+
console.log(chalk13.yellow(` ${varName}`));
|
|
15893
16010
|
}
|
|
15894
16011
|
process.exit(1);
|
|
15895
16012
|
}
|
|
15896
16013
|
}
|
|
15897
16014
|
if (config2.volumes && Object.keys(config2.volumes).length > 0) {
|
|
15898
16015
|
console.log();
|
|
15899
|
-
console.log(
|
|
16016
|
+
console.log(chalk13.blue("Processing volumes..."));
|
|
15900
16017
|
for (const volumeConfig of Object.values(config2.volumes)) {
|
|
15901
16018
|
const volumeDir = path12.join(cwd, volumeConfig.name);
|
|
15902
|
-
console.log(
|
|
16019
|
+
console.log(chalk13.gray(` ${volumeConfig.name}/`));
|
|
15903
16020
|
if (!existsSync5(volumeDir)) {
|
|
15904
16021
|
console.error(
|
|
15905
|
-
|
|
16022
|
+
chalk13.red(
|
|
15906
16023
|
` \u2717 Directory not found. Create the directory and add files first.`
|
|
15907
16024
|
)
|
|
15908
16025
|
);
|
|
@@ -15915,30 +16032,30 @@ var cookCommand = new Command11().name("cook").description("One-click agent prep
|
|
|
15915
16032
|
cwd: volumeDir,
|
|
15916
16033
|
silent: true
|
|
15917
16034
|
});
|
|
15918
|
-
console.log(
|
|
16035
|
+
console.log(chalk13.green(` \u2713 Initialized`));
|
|
15919
16036
|
}
|
|
15920
16037
|
await execVm0Command(["volume", "push"], {
|
|
15921
16038
|
cwd: volumeDir,
|
|
15922
16039
|
silent: true
|
|
15923
16040
|
});
|
|
15924
|
-
console.log(
|
|
16041
|
+
console.log(chalk13.green(` \u2713 Pushed`));
|
|
15925
16042
|
} catch (error43) {
|
|
15926
|
-
console.error(
|
|
16043
|
+
console.error(chalk13.red(` \u2717 Failed`));
|
|
15927
16044
|
if (error43 instanceof Error) {
|
|
15928
|
-
console.error(
|
|
16045
|
+
console.error(chalk13.gray(` ${error43.message}`));
|
|
15929
16046
|
}
|
|
15930
16047
|
process.exit(1);
|
|
15931
16048
|
}
|
|
15932
16049
|
}
|
|
15933
16050
|
}
|
|
15934
16051
|
console.log();
|
|
15935
|
-
console.log(
|
|
16052
|
+
console.log(chalk13.blue("Processing artifact..."));
|
|
15936
16053
|
const artifactDir = path12.join(cwd, ARTIFACT_DIR);
|
|
15937
|
-
console.log(
|
|
16054
|
+
console.log(chalk13.gray(` ${ARTIFACT_DIR}/`));
|
|
15938
16055
|
try {
|
|
15939
16056
|
if (!existsSync5(artifactDir)) {
|
|
15940
16057
|
await mkdir5(artifactDir, { recursive: true });
|
|
15941
|
-
console.log(
|
|
16058
|
+
console.log(chalk13.green(` \u2713 Created directory`));
|
|
15942
16059
|
}
|
|
15943
16060
|
const existingConfig = await readStorageConfig(artifactDir);
|
|
15944
16061
|
if (!existingConfig) {
|
|
@@ -15946,38 +16063,38 @@ var cookCommand = new Command11().name("cook").description("One-click agent prep
|
|
|
15946
16063
|
cwd: artifactDir,
|
|
15947
16064
|
silent: true
|
|
15948
16065
|
});
|
|
15949
|
-
console.log(
|
|
16066
|
+
console.log(chalk13.green(` \u2713 Initialized`));
|
|
15950
16067
|
}
|
|
15951
16068
|
await execVm0Command(["artifact", "push"], {
|
|
15952
16069
|
cwd: artifactDir,
|
|
15953
16070
|
silent: true
|
|
15954
16071
|
});
|
|
15955
|
-
console.log(
|
|
16072
|
+
console.log(chalk13.green(` \u2713 Pushed`));
|
|
15956
16073
|
} catch (error43) {
|
|
15957
|
-
console.error(
|
|
16074
|
+
console.error(chalk13.red(` \u2717 Failed`));
|
|
15958
16075
|
if (error43 instanceof Error) {
|
|
15959
|
-
console.error(
|
|
16076
|
+
console.error(chalk13.gray(` ${error43.message}`));
|
|
15960
16077
|
}
|
|
15961
16078
|
process.exit(1);
|
|
15962
16079
|
}
|
|
15963
16080
|
console.log();
|
|
15964
|
-
console.log(
|
|
16081
|
+
console.log(chalk13.blue("Uploading compose..."));
|
|
15965
16082
|
try {
|
|
15966
16083
|
await execVm0Command(["compose", CONFIG_FILE3], {
|
|
15967
16084
|
cwd,
|
|
15968
16085
|
silent: true
|
|
15969
16086
|
});
|
|
15970
|
-
console.log(
|
|
16087
|
+
console.log(chalk13.green(`\u2713 Compose uploaded: ${agentName}`));
|
|
15971
16088
|
} catch (error43) {
|
|
15972
|
-
console.error(
|
|
16089
|
+
console.error(chalk13.red(`\u2717 Compose failed`));
|
|
15973
16090
|
if (error43 instanceof Error) {
|
|
15974
|
-
console.error(
|
|
16091
|
+
console.error(chalk13.gray(` ${error43.message}`));
|
|
15975
16092
|
}
|
|
15976
16093
|
process.exit(1);
|
|
15977
16094
|
}
|
|
15978
16095
|
if (prompt) {
|
|
15979
16096
|
console.log();
|
|
15980
|
-
console.log(
|
|
16097
|
+
console.log(chalk13.blue(`Running agent: ${agentName}`));
|
|
15981
16098
|
console.log();
|
|
15982
16099
|
let runOutput;
|
|
15983
16100
|
try {
|
|
@@ -15998,17 +16115,17 @@ var cookCommand = new Command11().name("cook").description("One-click agent prep
|
|
|
15998
16115
|
);
|
|
15999
16116
|
if (serverVersion) {
|
|
16000
16117
|
console.log();
|
|
16001
|
-
console.log(
|
|
16118
|
+
console.log(chalk13.blue("Pulling updated artifact..."));
|
|
16002
16119
|
try {
|
|
16003
16120
|
await execVm0Command(["artifact", "pull"], {
|
|
16004
16121
|
cwd: artifactDir,
|
|
16005
16122
|
silent: true
|
|
16006
16123
|
});
|
|
16007
|
-
console.log(
|
|
16124
|
+
console.log(chalk13.green(`\u2713 Artifact pulled (${serverVersion})`));
|
|
16008
16125
|
} catch (error43) {
|
|
16009
|
-
console.error(
|
|
16126
|
+
console.error(chalk13.red(`\u2717 Artifact pull failed`));
|
|
16010
16127
|
if (error43 instanceof Error) {
|
|
16011
|
-
console.error(
|
|
16128
|
+
console.error(chalk13.gray(` ${error43.message}`));
|
|
16012
16129
|
}
|
|
16013
16130
|
}
|
|
16014
16131
|
}
|
|
@@ -16016,7 +16133,7 @@ var cookCommand = new Command11().name("cook").description("One-click agent prep
|
|
|
16016
16133
|
console.log();
|
|
16017
16134
|
console.log(" Run your agent:");
|
|
16018
16135
|
console.log(
|
|
16019
|
-
|
|
16136
|
+
chalk13.cyan(
|
|
16020
16137
|
` vm0 run ${agentName} --artifact-name ${ARTIFACT_DIR} "your prompt"`
|
|
16021
16138
|
)
|
|
16022
16139
|
);
|
|
@@ -16028,7 +16145,7 @@ import { Command as Command15 } from "commander";
|
|
|
16028
16145
|
|
|
16029
16146
|
// src/commands/image/build.ts
|
|
16030
16147
|
import { Command as Command12 } from "commander";
|
|
16031
|
-
import
|
|
16148
|
+
import chalk14 from "chalk";
|
|
16032
16149
|
import { readFile as readFile6 } from "fs/promises";
|
|
16033
16150
|
import { existsSync as existsSync6 } from "fs";
|
|
16034
16151
|
var sleep = (ms) => new Promise((resolve2) => setTimeout(resolve2, ms));
|
|
@@ -16036,13 +16153,13 @@ var buildCommand = new Command12().name("build").description("Build a custom ima
|
|
|
16036
16153
|
async (options) => {
|
|
16037
16154
|
const { file: file2, name, deleteExisting } = options;
|
|
16038
16155
|
if (!existsSync6(file2)) {
|
|
16039
|
-
console.error(
|
|
16156
|
+
console.error(chalk14.red(`\u2717 Dockerfile not found: ${file2}`));
|
|
16040
16157
|
process.exit(1);
|
|
16041
16158
|
}
|
|
16042
16159
|
const nameRegex = /^[a-zA-Z0-9][a-zA-Z0-9-]{1,62}[a-zA-Z0-9]$/;
|
|
16043
16160
|
if (!nameRegex.test(name)) {
|
|
16044
16161
|
console.error(
|
|
16045
|
-
|
|
16162
|
+
chalk14.red(
|
|
16046
16163
|
"\u2717 Invalid name format. Must be 3-64 characters, letters, numbers, and hyphens only."
|
|
16047
16164
|
)
|
|
16048
16165
|
);
|
|
@@ -16050,7 +16167,7 @@ var buildCommand = new Command12().name("build").description("Build a custom ima
|
|
|
16050
16167
|
}
|
|
16051
16168
|
if (name.startsWith("vm0-")) {
|
|
16052
16169
|
console.error(
|
|
16053
|
-
|
|
16170
|
+
chalk14.red(
|
|
16054
16171
|
'\u2717 Invalid name. Cannot start with "vm0-" (reserved prefix).'
|
|
16055
16172
|
)
|
|
16056
16173
|
);
|
|
@@ -16058,8 +16175,8 @@ var buildCommand = new Command12().name("build").description("Build a custom ima
|
|
|
16058
16175
|
}
|
|
16059
16176
|
try {
|
|
16060
16177
|
const dockerfile = await readFile6(file2, "utf8");
|
|
16061
|
-
console.log(
|
|
16062
|
-
console.log(
|
|
16178
|
+
console.log(chalk14.blue(`Building image: ${name}`));
|
|
16179
|
+
console.log(chalk14.gray(` Dockerfile: ${file2}`));
|
|
16063
16180
|
console.log();
|
|
16064
16181
|
const buildInfo = await apiClient.createImage({
|
|
16065
16182
|
dockerfile,
|
|
@@ -16067,7 +16184,7 @@ var buildCommand = new Command12().name("build").description("Build a custom ima
|
|
|
16067
16184
|
deleteExisting
|
|
16068
16185
|
});
|
|
16069
16186
|
const { imageId, buildId } = buildInfo;
|
|
16070
|
-
console.log(
|
|
16187
|
+
console.log(chalk14.gray(` Build ID: ${buildId}`));
|
|
16071
16188
|
console.log();
|
|
16072
16189
|
let logsOffset = 0;
|
|
16073
16190
|
let status = "building";
|
|
@@ -16083,7 +16200,7 @@ var buildCommand = new Command12().name("build").description("Build a custom ima
|
|
|
16083
16200
|
}
|
|
16084
16201
|
const statusData = await statusResponse.json();
|
|
16085
16202
|
for (const log of statusData.logs) {
|
|
16086
|
-
console.log(
|
|
16203
|
+
console.log(chalk14.gray(` ${log}`));
|
|
16087
16204
|
}
|
|
16088
16205
|
logsOffset = statusData.logsOffset;
|
|
16089
16206
|
status = statusData.status;
|
|
@@ -16093,27 +16210,27 @@ var buildCommand = new Command12().name("build").description("Build a custom ima
|
|
|
16093
16210
|
}
|
|
16094
16211
|
console.log();
|
|
16095
16212
|
if (status === "ready") {
|
|
16096
|
-
console.log(
|
|
16213
|
+
console.log(chalk14.green(`\u2713 Image built: ${name}`));
|
|
16097
16214
|
console.log();
|
|
16098
16215
|
console.log("Use in vm0.yaml:");
|
|
16099
|
-
console.log(
|
|
16100
|
-
console.log(
|
|
16101
|
-
console.log(
|
|
16216
|
+
console.log(chalk14.cyan(` agents:`));
|
|
16217
|
+
console.log(chalk14.cyan(` your-agent:`));
|
|
16218
|
+
console.log(chalk14.cyan(` image: "${name}"`));
|
|
16102
16219
|
} else {
|
|
16103
|
-
console.error(
|
|
16220
|
+
console.error(chalk14.red(`\u2717 Build failed`));
|
|
16104
16221
|
process.exit(1);
|
|
16105
16222
|
}
|
|
16106
16223
|
} catch (error43) {
|
|
16107
16224
|
if (error43 instanceof Error) {
|
|
16108
16225
|
if (error43.message.includes("Not authenticated")) {
|
|
16109
16226
|
console.error(
|
|
16110
|
-
|
|
16227
|
+
chalk14.red("\u2717 Not authenticated. Run: vm0 auth login")
|
|
16111
16228
|
);
|
|
16112
16229
|
} else {
|
|
16113
|
-
console.error(
|
|
16230
|
+
console.error(chalk14.red(`\u2717 ${error43.message}`));
|
|
16114
16231
|
}
|
|
16115
16232
|
} else {
|
|
16116
|
-
console.error(
|
|
16233
|
+
console.error(chalk14.red("\u2717 An unexpected error occurred"));
|
|
16117
16234
|
}
|
|
16118
16235
|
process.exit(1);
|
|
16119
16236
|
}
|
|
@@ -16122,7 +16239,7 @@ var buildCommand = new Command12().name("build").description("Build a custom ima
|
|
|
16122
16239
|
|
|
16123
16240
|
// src/commands/image/list.ts
|
|
16124
16241
|
import { Command as Command13 } from "commander";
|
|
16125
|
-
import
|
|
16242
|
+
import chalk15 from "chalk";
|
|
16126
16243
|
var listCommand = new Command13().name("list").alias("ls").description("List your custom images").action(async () => {
|
|
16127
16244
|
try {
|
|
16128
16245
|
const response = await apiClient.get("/api/images");
|
|
@@ -16135,43 +16252,43 @@ var listCommand = new Command13().name("list").alias("ls").description("List you
|
|
|
16135
16252
|
const data = await response.json();
|
|
16136
16253
|
const { images } = data;
|
|
16137
16254
|
if (images.length === 0) {
|
|
16138
|
-
console.log(
|
|
16255
|
+
console.log(chalk15.gray("No images found."));
|
|
16139
16256
|
console.log();
|
|
16140
16257
|
console.log("Build your first image:");
|
|
16141
16258
|
console.log(
|
|
16142
|
-
|
|
16259
|
+
chalk15.cyan(" vm0 image build --file Dockerfile --name my-image")
|
|
16143
16260
|
);
|
|
16144
16261
|
return;
|
|
16145
16262
|
}
|
|
16146
|
-
console.log(
|
|
16263
|
+
console.log(chalk15.bold("Your images:"));
|
|
16147
16264
|
console.log();
|
|
16148
16265
|
console.log(
|
|
16149
|
-
|
|
16266
|
+
chalk15.gray(
|
|
16150
16267
|
`${"NAME".padEnd(30)} ${"STATUS".padEnd(12)} ${"CREATED".padEnd(20)}`
|
|
16151
16268
|
)
|
|
16152
16269
|
);
|
|
16153
|
-
console.log(
|
|
16270
|
+
console.log(chalk15.gray("-".repeat(62)));
|
|
16154
16271
|
for (const image of images) {
|
|
16155
|
-
const statusColor = image.status === "ready" ?
|
|
16272
|
+
const statusColor = image.status === "ready" ? chalk15.green : image.status === "building" ? chalk15.yellow : chalk15.red;
|
|
16156
16273
|
const createdAt = new Date(image.createdAt).toLocaleString();
|
|
16157
16274
|
console.log(
|
|
16158
16275
|
`${image.alias.padEnd(30)} ${statusColor(image.status.padEnd(12))} ${createdAt.padEnd(20)}`
|
|
16159
16276
|
);
|
|
16160
16277
|
if (image.status === "error" && image.errorMessage) {
|
|
16161
|
-
console.log(
|
|
16278
|
+
console.log(chalk15.red(` Error: ${image.errorMessage}`));
|
|
16162
16279
|
}
|
|
16163
16280
|
}
|
|
16164
16281
|
console.log();
|
|
16165
|
-
console.log(
|
|
16282
|
+
console.log(chalk15.gray(`Total: ${images.length} image(s)`));
|
|
16166
16283
|
} catch (error43) {
|
|
16167
16284
|
if (error43 instanceof Error) {
|
|
16168
16285
|
if (error43.message.includes("Not authenticated")) {
|
|
16169
|
-
console.error(
|
|
16286
|
+
console.error(chalk15.red("Not authenticated. Run: vm0 auth login"));
|
|
16170
16287
|
} else {
|
|
16171
|
-
console.error(
|
|
16288
|
+
console.error(chalk15.red(`Error: ${error43.message}`));
|
|
16172
16289
|
}
|
|
16173
16290
|
} else {
|
|
16174
|
-
console.error(
|
|
16291
|
+
console.error(chalk15.red("An unexpected error occurred"));
|
|
16175
16292
|
}
|
|
16176
16293
|
process.exit(1);
|
|
16177
16294
|
}
|
|
@@ -16179,7 +16296,7 @@ var listCommand = new Command13().name("list").alias("ls").description("List you
|
|
|
16179
16296
|
|
|
16180
16297
|
// src/commands/image/delete.ts
|
|
16181
16298
|
import { Command as Command14 } from "commander";
|
|
16182
|
-
import
|
|
16299
|
+
import chalk16 from "chalk";
|
|
16183
16300
|
import * as readline from "readline";
|
|
16184
16301
|
var deleteCommand = new Command14().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) => {
|
|
16185
16302
|
try {
|
|
@@ -16193,7 +16310,7 @@ var deleteCommand = new Command14().name("delete").alias("rm").description("Dele
|
|
|
16193
16310
|
const data = await listResponse.json();
|
|
16194
16311
|
const image = data.images.find((img) => img.alias === name);
|
|
16195
16312
|
if (!image) {
|
|
16196
|
-
console.error(
|
|
16313
|
+
console.error(chalk16.red(`Image not found: ${name}`));
|
|
16197
16314
|
process.exit(1);
|
|
16198
16315
|
}
|
|
16199
16316
|
if (!options.force) {
|
|
@@ -16203,7 +16320,7 @@ var deleteCommand = new Command14().name("delete").alias("rm").description("Dele
|
|
|
16203
16320
|
});
|
|
16204
16321
|
const answer = await new Promise((resolve2) => {
|
|
16205
16322
|
rl.question(
|
|
16206
|
-
|
|
16323
|
+
chalk16.yellow(`Delete image "${name}"? [y/N] `),
|
|
16207
16324
|
(answer2) => {
|
|
16208
16325
|
rl.close();
|
|
16209
16326
|
resolve2(answer2);
|
|
@@ -16211,7 +16328,7 @@ var deleteCommand = new Command14().name("delete").alias("rm").description("Dele
|
|
|
16211
16328
|
);
|
|
16212
16329
|
});
|
|
16213
16330
|
if (answer.toLowerCase() !== "y" && answer.toLowerCase() !== "yes") {
|
|
16214
|
-
console.log(
|
|
16331
|
+
console.log(chalk16.gray("Cancelled."));
|
|
16215
16332
|
return;
|
|
16216
16333
|
}
|
|
16217
16334
|
}
|
|
@@ -16222,16 +16339,16 @@ var deleteCommand = new Command14().name("delete").alias("rm").description("Dele
|
|
|
16222
16339
|
error43.error?.message || "Failed to delete image"
|
|
16223
16340
|
);
|
|
16224
16341
|
}
|
|
16225
|
-
console.log(
|
|
16342
|
+
console.log(chalk16.green(`Deleted image: ${name}`));
|
|
16226
16343
|
} catch (error43) {
|
|
16227
16344
|
if (error43 instanceof Error) {
|
|
16228
16345
|
if (error43.message.includes("Not authenticated")) {
|
|
16229
|
-
console.error(
|
|
16346
|
+
console.error(chalk16.red("Not authenticated. Run: vm0 auth login"));
|
|
16230
16347
|
} else {
|
|
16231
|
-
console.error(
|
|
16348
|
+
console.error(chalk16.red(`Error: ${error43.message}`));
|
|
16232
16349
|
}
|
|
16233
16350
|
} else {
|
|
16234
|
-
console.error(
|
|
16351
|
+
console.error(chalk16.red("An unexpected error occurred"));
|
|
16235
16352
|
}
|
|
16236
16353
|
process.exit(1);
|
|
16237
16354
|
}
|
|
@@ -16242,7 +16359,7 @@ var imageCommand = new Command15().name("image").description("Manage custom imag
|
|
|
16242
16359
|
|
|
16243
16360
|
// src/commands/logs/index.ts
|
|
16244
16361
|
import { Command as Command16 } from "commander";
|
|
16245
|
-
import
|
|
16362
|
+
import chalk17 from "chalk";
|
|
16246
16363
|
|
|
16247
16364
|
// src/lib/time-parser.ts
|
|
16248
16365
|
function parseTime(timeStr) {
|
|
@@ -16304,23 +16421,23 @@ function formatMetric(metric) {
|
|
|
16304
16421
|
function formatNetworkLog(entry) {
|
|
16305
16422
|
let statusColor;
|
|
16306
16423
|
if (entry.status >= 200 && entry.status < 300) {
|
|
16307
|
-
statusColor =
|
|
16424
|
+
statusColor = chalk17.green;
|
|
16308
16425
|
} else if (entry.status >= 300 && entry.status < 400) {
|
|
16309
|
-
statusColor =
|
|
16426
|
+
statusColor = chalk17.yellow;
|
|
16310
16427
|
} else if (entry.status >= 400) {
|
|
16311
|
-
statusColor =
|
|
16428
|
+
statusColor = chalk17.red;
|
|
16312
16429
|
} else {
|
|
16313
|
-
statusColor =
|
|
16430
|
+
statusColor = chalk17.gray;
|
|
16314
16431
|
}
|
|
16315
16432
|
let latencyColor;
|
|
16316
16433
|
if (entry.latency_ms < 500) {
|
|
16317
|
-
latencyColor =
|
|
16434
|
+
latencyColor = chalk17.green;
|
|
16318
16435
|
} else if (entry.latency_ms < 2e3) {
|
|
16319
|
-
latencyColor =
|
|
16436
|
+
latencyColor = chalk17.yellow;
|
|
16320
16437
|
} else {
|
|
16321
|
-
latencyColor =
|
|
16438
|
+
latencyColor = chalk17.red;
|
|
16322
16439
|
}
|
|
16323
|
-
return `[${entry.timestamp}] ${
|
|
16440
|
+
return `[${entry.timestamp}] ${chalk17.cyan(entry.method.padEnd(6))} ${statusColor(entry.status)} ${latencyColor(entry.latency_ms + "ms")} ${formatBytes5(entry.request_size)}/${formatBytes5(entry.response_size)} ${chalk17.gray(entry.url)}`;
|
|
16324
16441
|
}
|
|
16325
16442
|
function renderAgentEvent(event) {
|
|
16326
16443
|
const parsed = ClaudeEventParser.parse(
|
|
@@ -16340,7 +16457,7 @@ function getLogType(options) {
|
|
|
16340
16457
|
].filter(Boolean).length;
|
|
16341
16458
|
if (selected > 1) {
|
|
16342
16459
|
console.error(
|
|
16343
|
-
|
|
16460
|
+
chalk17.red(
|
|
16344
16461
|
"Options --agent, --system, --metrics, and --network are mutually exclusive"
|
|
16345
16462
|
)
|
|
16346
16463
|
);
|
|
@@ -16393,7 +16510,7 @@ var logsCommand = new Command16().name("logs").description("View logs for an age
|
|
|
16393
16510
|
async function showAgentEvents(runId, options) {
|
|
16394
16511
|
const response = await apiClient.getAgentEvents(runId, options);
|
|
16395
16512
|
if (response.events.length === 0) {
|
|
16396
|
-
console.log(
|
|
16513
|
+
console.log(chalk17.yellow("No agent events found for this run."));
|
|
16397
16514
|
return;
|
|
16398
16515
|
}
|
|
16399
16516
|
for (const event of response.events) {
|
|
@@ -16402,7 +16519,7 @@ async function showAgentEvents(runId, options) {
|
|
|
16402
16519
|
if (response.hasMore) {
|
|
16403
16520
|
console.log();
|
|
16404
16521
|
console.log(
|
|
16405
|
-
|
|
16522
|
+
chalk17.gray(
|
|
16406
16523
|
`Showing ${response.events.length} events. Use --limit to see more.`
|
|
16407
16524
|
)
|
|
16408
16525
|
);
|
|
@@ -16411,21 +16528,21 @@ async function showAgentEvents(runId, options) {
|
|
|
16411
16528
|
async function showSystemLog(runId, options) {
|
|
16412
16529
|
const response = await apiClient.getSystemLog(runId, options);
|
|
16413
16530
|
if (!response.systemLog) {
|
|
16414
|
-
console.log(
|
|
16531
|
+
console.log(chalk17.yellow("No system log found for this run."));
|
|
16415
16532
|
return;
|
|
16416
16533
|
}
|
|
16417
16534
|
console.log(response.systemLog);
|
|
16418
16535
|
if (response.hasMore) {
|
|
16419
16536
|
console.log();
|
|
16420
16537
|
console.log(
|
|
16421
|
-
|
|
16538
|
+
chalk17.gray("More log entries available. Use --limit to see more.")
|
|
16422
16539
|
);
|
|
16423
16540
|
}
|
|
16424
16541
|
}
|
|
16425
16542
|
async function showMetrics(runId, options) {
|
|
16426
16543
|
const response = await apiClient.getMetrics(runId, options);
|
|
16427
16544
|
if (response.metrics.length === 0) {
|
|
16428
|
-
console.log(
|
|
16545
|
+
console.log(chalk17.yellow("No metrics found for this run."));
|
|
16429
16546
|
return;
|
|
16430
16547
|
}
|
|
16431
16548
|
for (const metric of response.metrics) {
|
|
@@ -16434,7 +16551,7 @@ async function showMetrics(runId, options) {
|
|
|
16434
16551
|
if (response.hasMore) {
|
|
16435
16552
|
console.log();
|
|
16436
16553
|
console.log(
|
|
16437
|
-
|
|
16554
|
+
chalk17.gray(
|
|
16438
16555
|
`Showing ${response.metrics.length} metrics. Use --limit to see more.`
|
|
16439
16556
|
)
|
|
16440
16557
|
);
|
|
@@ -16444,7 +16561,7 @@ async function showNetworkLogs(runId, options) {
|
|
|
16444
16561
|
const response = await apiClient.getNetworkLogs(runId, options);
|
|
16445
16562
|
if (response.networkLogs.length === 0) {
|
|
16446
16563
|
console.log(
|
|
16447
|
-
|
|
16564
|
+
chalk17.yellow(
|
|
16448
16565
|
"No network logs found for this run. Network logs are only captured when beta_network_security is enabled."
|
|
16449
16566
|
)
|
|
16450
16567
|
);
|
|
@@ -16456,7 +16573,7 @@ async function showNetworkLogs(runId, options) {
|
|
|
16456
16573
|
if (response.hasMore) {
|
|
16457
16574
|
console.log();
|
|
16458
16575
|
console.log(
|
|
16459
|
-
|
|
16576
|
+
chalk17.gray(
|
|
16460
16577
|
`Showing ${response.networkLogs.length} network logs. Use --limit to see more.`
|
|
16461
16578
|
)
|
|
16462
16579
|
);
|
|
@@ -16465,25 +16582,25 @@ async function showNetworkLogs(runId, options) {
|
|
|
16465
16582
|
function handleError(error43, runId) {
|
|
16466
16583
|
if (error43 instanceof Error) {
|
|
16467
16584
|
if (error43.message.includes("Not authenticated")) {
|
|
16468
|
-
console.error(
|
|
16585
|
+
console.error(chalk17.red("Not authenticated. Run: vm0 auth login"));
|
|
16469
16586
|
} else if (error43.message.includes("not found")) {
|
|
16470
|
-
console.error(
|
|
16587
|
+
console.error(chalk17.red(`Run not found: ${runId}`));
|
|
16471
16588
|
} else if (error43.message.includes("Invalid time format")) {
|
|
16472
|
-
console.error(
|
|
16589
|
+
console.error(chalk17.red(error43.message));
|
|
16473
16590
|
} else {
|
|
16474
|
-
console.error(
|
|
16475
|
-
console.error(
|
|
16591
|
+
console.error(chalk17.red("Failed to fetch logs"));
|
|
16592
|
+
console.error(chalk17.gray(` ${error43.message}`));
|
|
16476
16593
|
}
|
|
16477
16594
|
} else {
|
|
16478
|
-
console.error(
|
|
16595
|
+
console.error(chalk17.red("An unexpected error occurred"));
|
|
16479
16596
|
}
|
|
16480
16597
|
}
|
|
16481
16598
|
|
|
16482
16599
|
// src/index.ts
|
|
16483
16600
|
var program = new Command17();
|
|
16484
|
-
program.name("vm0").description("VM0 CLI - A modern build tool").version("4.
|
|
16601
|
+
program.name("vm0").description("VM0 CLI - A modern build tool").version("4.12.0");
|
|
16485
16602
|
program.command("info").description("Display environment information").action(async () => {
|
|
16486
|
-
console.log(
|
|
16603
|
+
console.log(chalk18.cyan("System Information:"));
|
|
16487
16604
|
console.log(`Node Version: ${process.version}`);
|
|
16488
16605
|
console.log(`Platform: ${process.platform}`);
|
|
16489
16606
|
console.log(`Architecture: ${process.arch}`);
|
|
@@ -16500,6 +16617,9 @@ authCommand.command("logout").description("Log out of VM0").action(async () => {
|
|
|
16500
16617
|
authCommand.command("status").description("Show current authentication status").action(async () => {
|
|
16501
16618
|
await checkAuthStatus();
|
|
16502
16619
|
});
|
|
16620
|
+
authCommand.command("setup-token").description("Output auth token for CI/CD environments").action(async () => {
|
|
16621
|
+
await setupToken();
|
|
16622
|
+
});
|
|
16503
16623
|
program.addCommand(composeCommand);
|
|
16504
16624
|
program.addCommand(runCommand);
|
|
16505
16625
|
program.addCommand(volumeCommand);
|