@vm0/cli 4.30.0 → 4.31.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 +188 -25
- package/package.json +2 -1
package/index.js
CHANGED
|
@@ -190,10 +190,11 @@ async function setupToken() {
|
|
|
190
190
|
// src/commands/compose.ts
|
|
191
191
|
import { Command } from "commander";
|
|
192
192
|
import chalk2 from "chalk";
|
|
193
|
-
import { readFile as
|
|
193
|
+
import { readFile as readFile4 } from "fs/promises";
|
|
194
194
|
import { existsSync as existsSync3 } from "fs";
|
|
195
195
|
import { dirname as dirname2 } from "path";
|
|
196
|
-
import { parse as
|
|
196
|
+
import { parse as parseYaml2 } from "yaml";
|
|
197
|
+
import prompts from "prompts";
|
|
197
198
|
|
|
198
199
|
// ../../packages/core/src/variable-expander.ts
|
|
199
200
|
var VARIABLE_PATTERN = /\$\{\{\s*(env|vars|secrets)\.([a-zA-Z_][a-zA-Z0-9_]*)\s*\}\}/g;
|
|
@@ -14250,6 +14251,7 @@ import * as path from "path";
|
|
|
14250
14251
|
import * as os from "os";
|
|
14251
14252
|
import { exec } from "child_process";
|
|
14252
14253
|
import { promisify } from "util";
|
|
14254
|
+
import { parse as parseYaml } from "yaml";
|
|
14253
14255
|
var execAsync = promisify(exec);
|
|
14254
14256
|
function parseGitHubTreeUrl2(url2) {
|
|
14255
14257
|
const parsed = parseGitHubTreeUrl(url2);
|
|
@@ -14295,6 +14297,37 @@ async function validateSkillDirectory(skillDir) {
|
|
|
14295
14297
|
);
|
|
14296
14298
|
}
|
|
14297
14299
|
}
|
|
14300
|
+
function parseSkillFrontmatter(content) {
|
|
14301
|
+
const frontmatterMatch = content.match(/^---\r?\n([\s\S]*?)\r?\n---/);
|
|
14302
|
+
if (!frontmatterMatch) {
|
|
14303
|
+
return {};
|
|
14304
|
+
}
|
|
14305
|
+
const yamlContent = frontmatterMatch[1];
|
|
14306
|
+
if (!yamlContent) {
|
|
14307
|
+
return {};
|
|
14308
|
+
}
|
|
14309
|
+
let parsed;
|
|
14310
|
+
try {
|
|
14311
|
+
parsed = parseYaml(yamlContent);
|
|
14312
|
+
} catch {
|
|
14313
|
+
return {};
|
|
14314
|
+
}
|
|
14315
|
+
if (!parsed || typeof parsed !== "object") {
|
|
14316
|
+
return {};
|
|
14317
|
+
}
|
|
14318
|
+
const data = parsed;
|
|
14319
|
+
return {
|
|
14320
|
+
name: typeof data.name === "string" ? data.name : void 0,
|
|
14321
|
+
description: typeof data.description === "string" ? data.description : void 0,
|
|
14322
|
+
vm0_secrets: Array.isArray(data.vm0_secrets) ? data.vm0_secrets.filter((s) => typeof s === "string") : void 0,
|
|
14323
|
+
vm0_vars: Array.isArray(data.vm0_vars) ? data.vm0_vars.filter((s) => typeof s === "string") : void 0
|
|
14324
|
+
};
|
|
14325
|
+
}
|
|
14326
|
+
async function readSkillFrontmatter(skillDir) {
|
|
14327
|
+
const skillMdPath = path.join(skillDir, "SKILL.md");
|
|
14328
|
+
const content = await fs.readFile(skillMdPath, "utf8");
|
|
14329
|
+
return parseSkillFrontmatter(content);
|
|
14330
|
+
}
|
|
14298
14331
|
|
|
14299
14332
|
// src/lib/direct-upload.ts
|
|
14300
14333
|
import { createHash } from "crypto";
|
|
@@ -14631,11 +14664,14 @@ async function uploadSkill(skillUrl) {
|
|
|
14631
14664
|
try {
|
|
14632
14665
|
const skillDir = await downloadGitHubSkill(parsed, tmpDir);
|
|
14633
14666
|
await validateSkillDirectory(skillDir);
|
|
14667
|
+
const frontmatter = await readSkillFrontmatter(skillDir);
|
|
14634
14668
|
const result = await directUpload(storageName, "volume", skillDir);
|
|
14635
14669
|
return {
|
|
14636
14670
|
name: storageName,
|
|
14637
14671
|
versionId: result.versionId,
|
|
14638
|
-
action: result.deduplicated ? "deduplicated" : "created"
|
|
14672
|
+
action: result.deduplicated ? "deduplicated" : "created",
|
|
14673
|
+
skillName: parsed.skillName,
|
|
14674
|
+
frontmatter
|
|
14639
14675
|
};
|
|
14640
14676
|
} finally {
|
|
14641
14677
|
await fs4.rm(tmpDir, { recursive: true, force: true });
|
|
@@ -14670,16 +14706,16 @@ function transformExperimentalShorthand(agent) {
|
|
|
14670
14706
|
agent.environment = environment;
|
|
14671
14707
|
}
|
|
14672
14708
|
}
|
|
14673
|
-
var composeCommand = new Command().name("compose").description("Create or update agent compose").argument("<config-file>", "Path to config YAML file").action(async (configFile) => {
|
|
14709
|
+
var composeCommand = new Command().name("compose").description("Create or update agent compose").argument("<config-file>", "Path to config YAML file").option("-y, --yes", "Skip confirmation prompts for skill requirements").action(async (configFile, options) => {
|
|
14674
14710
|
try {
|
|
14675
14711
|
if (!existsSync3(configFile)) {
|
|
14676
14712
|
console.error(chalk2.red(`\u2717 Config file not found: ${configFile}`));
|
|
14677
14713
|
process.exit(1);
|
|
14678
14714
|
}
|
|
14679
|
-
const content = await
|
|
14715
|
+
const content = await readFile4(configFile, "utf8");
|
|
14680
14716
|
let config2;
|
|
14681
14717
|
try {
|
|
14682
|
-
config2 =
|
|
14718
|
+
config2 = parseYaml2(content);
|
|
14683
14719
|
} catch (error43) {
|
|
14684
14720
|
console.error(chalk2.red("\u2717 Invalid YAML format"));
|
|
14685
14721
|
if (error43 instanceof Error) {
|
|
@@ -14756,6 +14792,7 @@ var composeCommand = new Command().name("compose").description("Create or update
|
|
|
14756
14792
|
process.exit(1);
|
|
14757
14793
|
}
|
|
14758
14794
|
}
|
|
14795
|
+
const skillResults = [];
|
|
14759
14796
|
if (agent.skills && Array.isArray(agent.skills)) {
|
|
14760
14797
|
const skillUrls = agent.skills;
|
|
14761
14798
|
console.log(`Uploading ${skillUrls.length} skill(s)...`);
|
|
@@ -14763,9 +14800,10 @@ var composeCommand = new Command().name("compose").description("Create or update
|
|
|
14763
14800
|
try {
|
|
14764
14801
|
console.log(chalk2.dim(` Downloading: ${skillUrl}`));
|
|
14765
14802
|
const result = await uploadSkill(skillUrl);
|
|
14803
|
+
skillResults.push(result);
|
|
14766
14804
|
console.log(
|
|
14767
14805
|
chalk2.green(
|
|
14768
|
-
` \u2713 Skill ${result.action === "deduplicated" ? "(unchanged)" : "uploaded"}: ${result.versionId.slice(0, 8)}`
|
|
14806
|
+
` \u2713 Skill ${result.action === "deduplicated" ? "(unchanged)" : "uploaded"}: ${result.skillName} (${result.versionId.slice(0, 8)})`
|
|
14769
14807
|
)
|
|
14770
14808
|
);
|
|
14771
14809
|
} catch (error43) {
|
|
@@ -14777,6 +14815,83 @@ var composeCommand = new Command().name("compose").description("Create or update
|
|
|
14777
14815
|
}
|
|
14778
14816
|
}
|
|
14779
14817
|
}
|
|
14818
|
+
const skillSecrets = /* @__PURE__ */ new Map();
|
|
14819
|
+
const skillVars = /* @__PURE__ */ new Map();
|
|
14820
|
+
for (const result of skillResults) {
|
|
14821
|
+
const { frontmatter, skillName } = result;
|
|
14822
|
+
if (frontmatter.vm0_secrets) {
|
|
14823
|
+
for (const secret of frontmatter.vm0_secrets) {
|
|
14824
|
+
if (!skillSecrets.has(secret)) {
|
|
14825
|
+
skillSecrets.set(secret, []);
|
|
14826
|
+
}
|
|
14827
|
+
skillSecrets.get(secret).push(skillName);
|
|
14828
|
+
}
|
|
14829
|
+
}
|
|
14830
|
+
if (frontmatter.vm0_vars) {
|
|
14831
|
+
for (const varName of frontmatter.vm0_vars) {
|
|
14832
|
+
if (!skillVars.has(varName)) {
|
|
14833
|
+
skillVars.set(varName, []);
|
|
14834
|
+
}
|
|
14835
|
+
skillVars.get(varName).push(skillName);
|
|
14836
|
+
}
|
|
14837
|
+
}
|
|
14838
|
+
}
|
|
14839
|
+
const environment = agent.environment || {};
|
|
14840
|
+
const newSecrets = [...skillSecrets.entries()].filter(
|
|
14841
|
+
([name]) => !(name in environment)
|
|
14842
|
+
);
|
|
14843
|
+
const newVars = [...skillVars.entries()].filter(
|
|
14844
|
+
([name]) => !(name in environment)
|
|
14845
|
+
);
|
|
14846
|
+
if (newSecrets.length > 0 || newVars.length > 0) {
|
|
14847
|
+
console.log();
|
|
14848
|
+
console.log(
|
|
14849
|
+
chalk2.bold("Skills require the following environment variables:")
|
|
14850
|
+
);
|
|
14851
|
+
console.log();
|
|
14852
|
+
if (newSecrets.length > 0) {
|
|
14853
|
+
console.log(chalk2.cyan(" Secrets:"));
|
|
14854
|
+
for (const [name, skills] of newSecrets) {
|
|
14855
|
+
console.log(` ${name.padEnd(24)} <- ${skills.join(", ")}`);
|
|
14856
|
+
}
|
|
14857
|
+
}
|
|
14858
|
+
if (newVars.length > 0) {
|
|
14859
|
+
console.log(chalk2.cyan(" Vars:"));
|
|
14860
|
+
for (const [name, skills] of newVars) {
|
|
14861
|
+
console.log(` ${name.padEnd(24)} <- ${skills.join(", ")}`);
|
|
14862
|
+
}
|
|
14863
|
+
}
|
|
14864
|
+
console.log();
|
|
14865
|
+
if (!options.yes) {
|
|
14866
|
+
if (!process.stdin.isTTY) {
|
|
14867
|
+
console.error(
|
|
14868
|
+
chalk2.red(
|
|
14869
|
+
"\u2717 Non-interactive terminal. Use --yes flag to skip confirmation."
|
|
14870
|
+
)
|
|
14871
|
+
);
|
|
14872
|
+
process.exit(1);
|
|
14873
|
+
}
|
|
14874
|
+
const response2 = await prompts({
|
|
14875
|
+
type: "confirm",
|
|
14876
|
+
name: "value",
|
|
14877
|
+
message: "Proceed with compose?",
|
|
14878
|
+
initial: true
|
|
14879
|
+
});
|
|
14880
|
+
if (!response2.value) {
|
|
14881
|
+
console.log(chalk2.yellow("Compose cancelled."));
|
|
14882
|
+
process.exit(0);
|
|
14883
|
+
}
|
|
14884
|
+
}
|
|
14885
|
+
for (const [name] of newSecrets) {
|
|
14886
|
+
environment[name] = `\${{ secrets.${name} }}`;
|
|
14887
|
+
}
|
|
14888
|
+
for (const [name] of newVars) {
|
|
14889
|
+
environment[name] = `\${{ vars.${name} }}`;
|
|
14890
|
+
}
|
|
14891
|
+
if (Object.keys(environment).length > 0) {
|
|
14892
|
+
agent.environment = environment;
|
|
14893
|
+
}
|
|
14894
|
+
}
|
|
14780
14895
|
console.log("Uploading compose...");
|
|
14781
14896
|
const response = await apiClient.createOrUpdateCompose({
|
|
14782
14897
|
content: config2
|
|
@@ -15815,6 +15930,16 @@ var runCmd = new Command2().name("run").description("Execute an agent").argument
|
|
|
15815
15930
|
}
|
|
15816
15931
|
);
|
|
15817
15932
|
runCmd.command("resume").description("Resume an agent run from a checkpoint (uses all snapshot data)").argument("<checkpointId>", "Checkpoint ID to resume from").argument("<prompt>", "Prompt for the resumed agent").option(
|
|
15933
|
+
"--vars <KEY=value>",
|
|
15934
|
+
"Variables for ${{ vars.xxx }} (repeatable, falls back to env vars and .env)",
|
|
15935
|
+
collectKeyValue,
|
|
15936
|
+
{}
|
|
15937
|
+
).option(
|
|
15938
|
+
"--secrets <KEY=value>",
|
|
15939
|
+
"Secrets for ${{ secrets.xxx }} (repeatable, required for resume)",
|
|
15940
|
+
collectKeyValue,
|
|
15941
|
+
{}
|
|
15942
|
+
).option(
|
|
15818
15943
|
"--volume-version <name=version>",
|
|
15819
15944
|
"Volume version override (repeatable)",
|
|
15820
15945
|
collectVolumeVersions,
|
|
@@ -15824,6 +15949,8 @@ runCmd.command("resume").description("Resume an agent run from a checkpoint (use
|
|
|
15824
15949
|
const startTimestamp = /* @__PURE__ */ new Date();
|
|
15825
15950
|
const allOpts = command.optsWithGlobals();
|
|
15826
15951
|
const verbose = options.verbose || allOpts.verbose;
|
|
15952
|
+
const vars = { ...allOpts.vars, ...options.vars };
|
|
15953
|
+
const secrets = { ...allOpts.secrets, ...options.secrets };
|
|
15827
15954
|
try {
|
|
15828
15955
|
if (!isUUID(checkpointId)) {
|
|
15829
15956
|
console.error(
|
|
@@ -15832,10 +15959,20 @@ runCmd.command("resume").description("Resume an agent run from a checkpoint (use
|
|
|
15832
15959
|
console.error(chalk5.dim(" Checkpoint ID must be a valid UUID"));
|
|
15833
15960
|
process.exit(1);
|
|
15834
15961
|
}
|
|
15962
|
+
const secretNames = Object.keys(secrets);
|
|
15963
|
+
const loadedSecrets = secretNames.length > 0 ? secrets : loadValues({}, []);
|
|
15835
15964
|
if (verbose) {
|
|
15836
15965
|
logVerbosePreFlight("Resuming agent run from checkpoint", [
|
|
15837
15966
|
{ label: "Checkpoint ID", value: checkpointId },
|
|
15838
15967
|
{ label: "Prompt", value: prompt },
|
|
15968
|
+
{
|
|
15969
|
+
label: "Variables",
|
|
15970
|
+
value: Object.keys(vars).length > 0 ? JSON.stringify(vars) : void 0
|
|
15971
|
+
},
|
|
15972
|
+
{
|
|
15973
|
+
label: "Secrets",
|
|
15974
|
+
value: loadedSecrets && Object.keys(loadedSecrets).length > 0 ? `${Object.keys(loadedSecrets).length} loaded` : void 0
|
|
15975
|
+
},
|
|
15839
15976
|
{
|
|
15840
15977
|
label: "Volume overrides",
|
|
15841
15978
|
value: Object.keys(allOpts.volumeVersion).length > 0 ? JSON.stringify(allOpts.volumeVersion) : void 0
|
|
@@ -15845,6 +15982,8 @@ runCmd.command("resume").description("Resume an agent run from a checkpoint (use
|
|
|
15845
15982
|
const response = await apiClient.createRun({
|
|
15846
15983
|
checkpointId,
|
|
15847
15984
|
prompt,
|
|
15985
|
+
vars: Object.keys(vars).length > 0 ? vars : void 0,
|
|
15986
|
+
secrets: loadedSecrets,
|
|
15848
15987
|
volumeVersions: Object.keys(allOpts.volumeVersion).length > 0 ? allOpts.volumeVersion : void 0
|
|
15849
15988
|
});
|
|
15850
15989
|
if (response.status === "failed") {
|
|
@@ -15888,6 +16027,16 @@ runCmd.command("resume").description("Resume an agent run from a checkpoint (use
|
|
|
15888
16027
|
runCmd.command("continue").description(
|
|
15889
16028
|
"Continue an agent run from a session (uses latest artifact version)"
|
|
15890
16029
|
).argument("<agentSessionId>", "Agent session ID to continue from").argument("<prompt>", "Prompt for the continued agent").option(
|
|
16030
|
+
"--vars <KEY=value>",
|
|
16031
|
+
"Variables for ${{ vars.xxx }} (repeatable, falls back to env vars and .env)",
|
|
16032
|
+
collectKeyValue,
|
|
16033
|
+
{}
|
|
16034
|
+
).option(
|
|
16035
|
+
"--secrets <KEY=value>",
|
|
16036
|
+
"Secrets for ${{ secrets.xxx }} (repeatable, required for continue)",
|
|
16037
|
+
collectKeyValue,
|
|
16038
|
+
{}
|
|
16039
|
+
).option(
|
|
15891
16040
|
"--volume-version <name=version>",
|
|
15892
16041
|
"Volume version override (repeatable)",
|
|
15893
16042
|
collectVolumeVersions,
|
|
@@ -15897,6 +16046,8 @@ runCmd.command("continue").description(
|
|
|
15897
16046
|
const startTimestamp = /* @__PURE__ */ new Date();
|
|
15898
16047
|
const allOpts = command.optsWithGlobals();
|
|
15899
16048
|
const verbose = options.verbose || allOpts.verbose;
|
|
16049
|
+
const vars = { ...allOpts.vars, ...options.vars };
|
|
16050
|
+
const secrets = { ...allOpts.secrets, ...options.secrets };
|
|
15900
16051
|
try {
|
|
15901
16052
|
if (!isUUID(agentSessionId)) {
|
|
15902
16053
|
console.error(
|
|
@@ -15905,11 +16056,21 @@ runCmd.command("continue").description(
|
|
|
15905
16056
|
console.error(chalk5.dim(" Agent session ID must be a valid UUID"));
|
|
15906
16057
|
process.exit(1);
|
|
15907
16058
|
}
|
|
16059
|
+
const secretNames = Object.keys(secrets);
|
|
16060
|
+
const loadedSecrets = secretNames.length > 0 ? secrets : loadValues({}, []);
|
|
15908
16061
|
if (verbose) {
|
|
15909
16062
|
logVerbosePreFlight("Continuing agent run from session", [
|
|
15910
16063
|
{ label: "Session ID", value: agentSessionId },
|
|
15911
16064
|
{ label: "Prompt", value: prompt },
|
|
15912
16065
|
{ label: "Note", value: "Using latest artifact version" },
|
|
16066
|
+
{
|
|
16067
|
+
label: "Variables",
|
|
16068
|
+
value: Object.keys(vars).length > 0 ? JSON.stringify(vars) : void 0
|
|
16069
|
+
},
|
|
16070
|
+
{
|
|
16071
|
+
label: "Secrets",
|
|
16072
|
+
value: loadedSecrets && Object.keys(loadedSecrets).length > 0 ? `${Object.keys(loadedSecrets).length} loaded` : void 0
|
|
16073
|
+
},
|
|
15913
16074
|
{
|
|
15914
16075
|
label: "Volume overrides",
|
|
15915
16076
|
value: Object.keys(allOpts.volumeVersion).length > 0 ? JSON.stringify(allOpts.volumeVersion) : void 0
|
|
@@ -15919,6 +16080,8 @@ runCmd.command("continue").description(
|
|
|
15919
16080
|
const response = await apiClient.createRun({
|
|
15920
16081
|
sessionId: agentSessionId,
|
|
15921
16082
|
prompt,
|
|
16083
|
+
vars: Object.keys(vars).length > 0 ? vars : void 0,
|
|
16084
|
+
secrets: loadedSecrets,
|
|
15922
16085
|
volumeVersions: Object.keys(allOpts.volumeVersion).length > 0 ? allOpts.volumeVersion : void 0
|
|
15923
16086
|
});
|
|
15924
16087
|
if (response.status === "failed") {
|
|
@@ -15972,9 +16135,9 @@ import chalk6 from "chalk";
|
|
|
15972
16135
|
import path7 from "path";
|
|
15973
16136
|
|
|
15974
16137
|
// src/lib/storage-utils.ts
|
|
15975
|
-
import { readFile as
|
|
16138
|
+
import { readFile as readFile5, writeFile as writeFile4, mkdir as mkdir4 } from "fs/promises";
|
|
15976
16139
|
import { existsSync as existsSync5 } from "fs";
|
|
15977
|
-
import { parse as
|
|
16140
|
+
import { parse as parseYaml3, stringify as stringifyYaml } from "yaml";
|
|
15978
16141
|
import path6 from "path";
|
|
15979
16142
|
var CONFIG_DIR2 = ".vm0";
|
|
15980
16143
|
var CONFIG_FILE2 = "storage.yaml";
|
|
@@ -15997,8 +16160,8 @@ async function readStorageConfig(basePath = process.cwd()) {
|
|
|
15997
16160
|
if (!actualPath) {
|
|
15998
16161
|
return null;
|
|
15999
16162
|
}
|
|
16000
|
-
const content = await
|
|
16001
|
-
const config2 =
|
|
16163
|
+
const content = await readFile5(actualPath, "utf8");
|
|
16164
|
+
const config2 = parseYaml3(content);
|
|
16002
16165
|
if (!config2.type) {
|
|
16003
16166
|
config2.type = "volume";
|
|
16004
16167
|
}
|
|
@@ -16586,11 +16749,11 @@ var artifactCommand = new Command12().name("artifact").description("Manage cloud
|
|
|
16586
16749
|
// src/commands/cook.ts
|
|
16587
16750
|
import { Command as Command13 } from "commander";
|
|
16588
16751
|
import chalk16 from "chalk";
|
|
16589
|
-
import { readFile as
|
|
16752
|
+
import { readFile as readFile7, mkdir as mkdir6, writeFile as writeFile6, appendFile } from "fs/promises";
|
|
16590
16753
|
import { existsSync as existsSync7, readFileSync } from "fs";
|
|
16591
16754
|
import path11 from "path";
|
|
16592
16755
|
import { spawn as spawn2 } from "child_process";
|
|
16593
|
-
import { parse as
|
|
16756
|
+
import { parse as parseYaml4 } from "yaml";
|
|
16594
16757
|
import { config as dotenvConfig2 } from "dotenv";
|
|
16595
16758
|
|
|
16596
16759
|
// src/lib/update-checker.ts
|
|
@@ -16704,7 +16867,7 @@ async function checkAndUpgrade(currentVersion, prompt) {
|
|
|
16704
16867
|
// src/lib/cook-state.ts
|
|
16705
16868
|
import { homedir as homedir2 } from "os";
|
|
16706
16869
|
import { join as join6 } from "path";
|
|
16707
|
-
import { readFile as
|
|
16870
|
+
import { readFile as readFile6, writeFile as writeFile5, mkdir as mkdir5 } from "fs/promises";
|
|
16708
16871
|
import { existsSync as existsSync6 } from "fs";
|
|
16709
16872
|
var CONFIG_DIR3 = join6(homedir2(), ".vm0");
|
|
16710
16873
|
var COOK_STATE_FILE = join6(CONFIG_DIR3, "cook.json");
|
|
@@ -16714,7 +16877,7 @@ async function loadCookStateFile() {
|
|
|
16714
16877
|
return { ppid: {} };
|
|
16715
16878
|
}
|
|
16716
16879
|
try {
|
|
16717
|
-
const content = await
|
|
16880
|
+
const content = await readFile6(COOK_STATE_FILE, "utf8");
|
|
16718
16881
|
const data = JSON.parse(content);
|
|
16719
16882
|
if (!data.ppid) {
|
|
16720
16883
|
const oldState = data;
|
|
@@ -16925,7 +17088,7 @@ async function autoPullArtifact(runOutput, artifactDir) {
|
|
|
16925
17088
|
}
|
|
16926
17089
|
var cookCmd = new Command13().name("cook").description("One-click agent preparation and execution from vm0.yaml");
|
|
16927
17090
|
cookCmd.argument("[prompt]", "Prompt for the agent").action(async (prompt) => {
|
|
16928
|
-
const shouldExit = await checkAndUpgrade("4.
|
|
17091
|
+
const shouldExit = await checkAndUpgrade("4.31.0", prompt);
|
|
16929
17092
|
if (shouldExit) {
|
|
16930
17093
|
process.exit(0);
|
|
16931
17094
|
}
|
|
@@ -16937,8 +17100,8 @@ cookCmd.argument("[prompt]", "Prompt for the agent").action(async (prompt) => {
|
|
|
16937
17100
|
}
|
|
16938
17101
|
let config2;
|
|
16939
17102
|
try {
|
|
16940
|
-
const content = await
|
|
16941
|
-
config2 =
|
|
17103
|
+
const content = await readFile7(CONFIG_FILE3, "utf8");
|
|
17104
|
+
config2 = parseYaml4(content);
|
|
16942
17105
|
} catch (error43) {
|
|
16943
17106
|
console.error(chalk16.red("\u2717 Invalid YAML format"));
|
|
16944
17107
|
if (error43 instanceof Error) {
|
|
@@ -17212,7 +17375,7 @@ import { Command as Command18 } from "commander";
|
|
|
17212
17375
|
// src/commands/image/build.ts
|
|
17213
17376
|
import { Command as Command14 } from "commander";
|
|
17214
17377
|
import chalk17 from "chalk";
|
|
17215
|
-
import { readFile as
|
|
17378
|
+
import { readFile as readFile8 } from "fs/promises";
|
|
17216
17379
|
import { existsSync as existsSync8 } from "fs";
|
|
17217
17380
|
|
|
17218
17381
|
// src/lib/dockerfile-validator.ts
|
|
@@ -17273,7 +17436,7 @@ var buildCommand = new Command14().name("build").description("Build a custom ima
|
|
|
17273
17436
|
}
|
|
17274
17437
|
try {
|
|
17275
17438
|
const scope = await apiClient.getScope();
|
|
17276
|
-
const dockerfile = await
|
|
17439
|
+
const dockerfile = await readFile8(file2, "utf8");
|
|
17277
17440
|
const validation = validateDockerfile(dockerfile);
|
|
17278
17441
|
if (!validation.valid) {
|
|
17279
17442
|
console.error(chalk17.red("\u2717 Dockerfile validation failed\n"));
|
|
@@ -18079,9 +18242,9 @@ import { Command as Command24 } from "commander";
|
|
|
18079
18242
|
import chalk25 from "chalk";
|
|
18080
18243
|
import * as readline3 from "readline";
|
|
18081
18244
|
import { existsSync as existsSync10 } from "fs";
|
|
18082
|
-
import { mkdir as mkdir7, readFile as
|
|
18245
|
+
import { mkdir as mkdir7, readFile as readFile9, writeFile as writeFile8 } from "fs/promises";
|
|
18083
18246
|
import { execSync, spawnSync } from "child_process";
|
|
18084
|
-
import { parse as
|
|
18247
|
+
import { parse as parseYaml5 } from "yaml";
|
|
18085
18248
|
function isGhInstalled() {
|
|
18086
18249
|
try {
|
|
18087
18250
|
execSync("gh --version", { stdio: "ignore" });
|
|
@@ -18401,8 +18564,8 @@ var setupGithubCommand = new Command24().name("setup-github").description("Initi
|
|
|
18401
18564
|
}
|
|
18402
18565
|
console.log();
|
|
18403
18566
|
console.log("Analyzing vm0.yaml...");
|
|
18404
|
-
const content = await
|
|
18405
|
-
const config2 =
|
|
18567
|
+
const content = await readFile9("vm0.yaml", "utf8");
|
|
18568
|
+
const config2 = parseYaml5(content);
|
|
18406
18569
|
const agents = config2.agents;
|
|
18407
18570
|
const agentName = Object.keys(agents)[0];
|
|
18408
18571
|
console.log(chalk25.green(`\u2713 Agent: ${agentName}`));
|
|
@@ -18538,7 +18701,7 @@ var setupGithubCommand = new Command24().name("setup-github").description("Initi
|
|
|
18538
18701
|
|
|
18539
18702
|
// src/index.ts
|
|
18540
18703
|
var program = new Command25();
|
|
18541
|
-
program.name("vm0").description("VM0 CLI - A modern build tool").version("4.
|
|
18704
|
+
program.name("vm0").description("VM0 CLI - A modern build tool").version("4.31.0");
|
|
18542
18705
|
program.command("info").description("Display environment information").action(async () => {
|
|
18543
18706
|
console.log(chalk26.bold("System Information:"));
|
|
18544
18707
|
console.log(`Node Version: ${process.version}`);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vm0/cli",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.31.0",
|
|
4
4
|
"description": "CLI application",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -19,6 +19,7 @@
|
|
|
19
19
|
"chalk": "^5.6.0",
|
|
20
20
|
"commander": "^14.0.0",
|
|
21
21
|
"dotenv": "^17.2.1",
|
|
22
|
+
"prompts": "^2.4.2",
|
|
22
23
|
"tar": "^7.5.2",
|
|
23
24
|
"yaml": "^2.3.4"
|
|
24
25
|
}
|