@vm0/cli 9.4.1 → 9.5.1
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 +626 -566
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -1878,7 +1878,7 @@ var credentialsByNameContract = c10.router({
|
|
|
1878
1878
|
name: credentialNameSchema
|
|
1879
1879
|
}),
|
|
1880
1880
|
responses: {
|
|
1881
|
-
204:
|
|
1881
|
+
204: c10.noBody(),
|
|
1882
1882
|
401: apiErrorSchema,
|
|
1883
1883
|
404: apiErrorSchema,
|
|
1884
1884
|
500: apiErrorSchema
|
|
@@ -1990,7 +1990,7 @@ var modelProvidersByTypeContract = c11.router({
|
|
|
1990
1990
|
type: modelProviderTypeSchema
|
|
1991
1991
|
}),
|
|
1992
1992
|
responses: {
|
|
1993
|
-
204:
|
|
1993
|
+
204: c11.noBody(),
|
|
1994
1994
|
401: apiErrorSchema,
|
|
1995
1995
|
404: apiErrorSchema,
|
|
1996
1996
|
500: apiErrorSchema
|
|
@@ -2275,7 +2275,7 @@ var schedulesByNameContract = c13.router({
|
|
|
2275
2275
|
composeId: z16.string().uuid("Compose ID required")
|
|
2276
2276
|
}),
|
|
2277
2277
|
responses: {
|
|
2278
|
-
204:
|
|
2278
|
+
204: c13.noBody(),
|
|
2279
2279
|
401: apiErrorSchema,
|
|
2280
2280
|
404: apiErrorSchema
|
|
2281
2281
|
},
|
|
@@ -3246,10 +3246,10 @@ async function getRawHeaders() {
|
|
|
3246
3246
|
}
|
|
3247
3247
|
return headers;
|
|
3248
3248
|
}
|
|
3249
|
-
async function httpGet(
|
|
3249
|
+
async function httpGet(path16) {
|
|
3250
3250
|
const baseUrl = await getBaseUrl();
|
|
3251
3251
|
const headers = await getRawHeaders();
|
|
3252
|
-
return fetch(`${baseUrl}${
|
|
3252
|
+
return fetch(`${baseUrl}${path16}`, {
|
|
3253
3253
|
method: "GET",
|
|
3254
3254
|
headers
|
|
3255
3255
|
});
|
|
@@ -3754,49 +3754,49 @@ var cliComposeSchema = z24.object({
|
|
|
3754
3754
|
function formatZodError(error) {
|
|
3755
3755
|
const issue = error.issues[0];
|
|
3756
3756
|
if (!issue) return "Validation failed";
|
|
3757
|
-
const
|
|
3757
|
+
const path16 = issue.path.join(".");
|
|
3758
3758
|
const message = issue.message;
|
|
3759
|
-
if (!
|
|
3759
|
+
if (!path16) return message;
|
|
3760
3760
|
if (issue.code === "invalid_type") {
|
|
3761
3761
|
const received = issue.received;
|
|
3762
3762
|
const isMissing = received === "undefined" || message.includes("received undefined") || message === "Required";
|
|
3763
|
-
if (
|
|
3763
|
+
if (path16 === "version" && isMissing) {
|
|
3764
3764
|
return "Missing config.version";
|
|
3765
3765
|
}
|
|
3766
|
-
if (
|
|
3766
|
+
if (path16 === "agents" && isMissing) {
|
|
3767
3767
|
return "Missing agents object in config";
|
|
3768
3768
|
}
|
|
3769
|
-
if (
|
|
3770
|
-
const volumeKey =
|
|
3769
|
+
if (path16.startsWith("volumes.") && path16.endsWith(".name")) {
|
|
3770
|
+
const volumeKey = path16.split(".")[1];
|
|
3771
3771
|
return `Volume "${volumeKey}" must have a 'name' field (string)`;
|
|
3772
3772
|
}
|
|
3773
|
-
if (
|
|
3774
|
-
const volumeKey =
|
|
3773
|
+
if (path16.startsWith("volumes.") && path16.endsWith(".version")) {
|
|
3774
|
+
const volumeKey = path16.split(".")[1];
|
|
3775
3775
|
return `Volume "${volumeKey}" must have a 'version' field (string)`;
|
|
3776
3776
|
}
|
|
3777
3777
|
if (issue.expected === "array") {
|
|
3778
|
-
const fieldName =
|
|
3778
|
+
const fieldName = path16.replace(/^agents\.[^.]+\./, "agent.");
|
|
3779
3779
|
return `${fieldName} must be an array`;
|
|
3780
3780
|
}
|
|
3781
3781
|
if (issue.expected === "string" && received === "number") {
|
|
3782
|
-
const fieldName =
|
|
3782
|
+
const fieldName = path16.replace(/^agents\.[^.]+\./, "agent.");
|
|
3783
3783
|
const match = fieldName.match(/^(agent\.[^.]+)\.\d+$/);
|
|
3784
3784
|
if (match) {
|
|
3785
3785
|
return `Each entry in ${match[1]?.replace("agent.", "")} must be a string`;
|
|
3786
3786
|
}
|
|
3787
3787
|
}
|
|
3788
3788
|
}
|
|
3789
|
-
if (issue.code === "invalid_key" &&
|
|
3789
|
+
if (issue.code === "invalid_key" && path16.startsWith("agents.")) {
|
|
3790
3790
|
return "Invalid agent name format. Must be 3-64 characters, letters, numbers, and hyphens only. Must start and end with letter or number.";
|
|
3791
3791
|
}
|
|
3792
|
-
if (message === "Invalid key in record" &&
|
|
3792
|
+
if (message === "Invalid key in record" && path16.startsWith("agents.")) {
|
|
3793
3793
|
return "Invalid agent name format. Must be 3-64 characters, letters, numbers, and hyphens only. Must start and end with letter or number.";
|
|
3794
3794
|
}
|
|
3795
3795
|
if (issue.code === "custom") {
|
|
3796
3796
|
return message;
|
|
3797
3797
|
}
|
|
3798
|
-
if (
|
|
3799
|
-
const cleanPath =
|
|
3798
|
+
if (path16.startsWith("agents.")) {
|
|
3799
|
+
const cleanPath = path16.replace(/^agents\.[^.]+\./, "agent.");
|
|
3800
3800
|
if (message.startsWith("Invalid input:")) {
|
|
3801
3801
|
const match = message.match(/expected (\w+), received (\w+)/);
|
|
3802
3802
|
if (match && match[1] === "string" && match[2] === "number") {
|
|
@@ -3808,7 +3808,7 @@ function formatZodError(error) {
|
|
|
3808
3808
|
}
|
|
3809
3809
|
return `${cleanPath}: ${message}`;
|
|
3810
3810
|
}
|
|
3811
|
-
return `${
|
|
3811
|
+
return `${path16}: ${message}`;
|
|
3812
3812
|
}
|
|
3813
3813
|
function validateAgentName(name) {
|
|
3814
3814
|
return cliAgentNameSchema.safeParse(name).success;
|
|
@@ -4382,175 +4382,201 @@ function getSecretsFromComposeContent(content) {
|
|
|
4382
4382
|
const grouped = groupVariablesBySource(refs);
|
|
4383
4383
|
return new Set(grouped.secrets.map((r) => r.name));
|
|
4384
4384
|
}
|
|
4385
|
-
|
|
4385
|
+
async function loadAndValidateConfig(configFile) {
|
|
4386
|
+
if (!existsSync3(configFile)) {
|
|
4387
|
+
console.error(chalk3.red(`\u2717 Config file not found: ${configFile}`));
|
|
4388
|
+
process.exit(1);
|
|
4389
|
+
}
|
|
4390
|
+
const content = await readFile4(configFile, "utf8");
|
|
4391
|
+
let config;
|
|
4386
4392
|
try {
|
|
4387
|
-
|
|
4388
|
-
|
|
4389
|
-
|
|
4390
|
-
|
|
4391
|
-
|
|
4392
|
-
let config;
|
|
4393
|
-
try {
|
|
4394
|
-
config = parseYaml2(content);
|
|
4395
|
-
} catch (error) {
|
|
4396
|
-
console.error(chalk3.red("\u2717 Invalid YAML format"));
|
|
4397
|
-
if (error instanceof Error) {
|
|
4398
|
-
console.error(chalk3.dim(` ${error.message}`));
|
|
4399
|
-
}
|
|
4400
|
-
process.exit(1);
|
|
4401
|
-
}
|
|
4402
|
-
const validation = validateAgentCompose(config);
|
|
4403
|
-
if (!validation.valid) {
|
|
4404
|
-
console.error(chalk3.red(`\u2717 ${validation.error}`));
|
|
4405
|
-
process.exit(1);
|
|
4393
|
+
config = parseYaml2(content);
|
|
4394
|
+
} catch (error) {
|
|
4395
|
+
console.error(chalk3.red("\u2717 Invalid YAML format"));
|
|
4396
|
+
if (error instanceof Error) {
|
|
4397
|
+
console.error(chalk3.dim(` ${error.message}`));
|
|
4406
4398
|
}
|
|
4407
|
-
|
|
4408
|
-
|
|
4409
|
-
|
|
4410
|
-
|
|
4411
|
-
|
|
4412
|
-
|
|
4413
|
-
|
|
4414
|
-
|
|
4415
|
-
|
|
4416
|
-
|
|
4417
|
-
|
|
4418
|
-
|
|
4419
|
-
|
|
4420
|
-
|
|
4399
|
+
process.exit(1);
|
|
4400
|
+
}
|
|
4401
|
+
const validation = validateAgentCompose(config);
|
|
4402
|
+
if (!validation.valid) {
|
|
4403
|
+
console.error(chalk3.red(`\u2717 ${validation.error}`));
|
|
4404
|
+
process.exit(1);
|
|
4405
|
+
}
|
|
4406
|
+
const cfg = config;
|
|
4407
|
+
const agentsConfig = cfg.agents;
|
|
4408
|
+
const agentName = Object.keys(agentsConfig)[0];
|
|
4409
|
+
const agent = agentsConfig[agentName];
|
|
4410
|
+
const basePath = dirname2(configFile);
|
|
4411
|
+
return { config, agentName, agent, basePath };
|
|
4412
|
+
}
|
|
4413
|
+
function checkLegacyImageFormat(config) {
|
|
4414
|
+
const cfg = config;
|
|
4415
|
+
const agentsConfig = cfg.agents;
|
|
4416
|
+
for (const [name, agentConfig] of Object.entries(agentsConfig)) {
|
|
4417
|
+
const image = agentConfig.image;
|
|
4418
|
+
if (image) {
|
|
4419
|
+
console.log(
|
|
4420
|
+
chalk3.yellow(
|
|
4421
|
+
`\u26A0 Agent "${name}": 'image' field is deprecated. Use 'apps' field for pre-installed tools.`
|
|
4422
|
+
)
|
|
4423
|
+
);
|
|
4424
|
+
const warning = getLegacySystemTemplateWarning(image);
|
|
4425
|
+
if (warning) {
|
|
4426
|
+
console.log(chalk3.yellow(` ${warning}`));
|
|
4421
4427
|
}
|
|
4422
4428
|
}
|
|
4423
|
-
|
|
4424
|
-
|
|
4425
|
-
|
|
4426
|
-
|
|
4427
|
-
|
|
4428
|
-
|
|
4429
|
-
|
|
4430
|
-
|
|
4431
|
-
|
|
4432
|
-
|
|
4433
|
-
|
|
4434
|
-
|
|
4435
|
-
|
|
4436
|
-
|
|
4429
|
+
}
|
|
4430
|
+
}
|
|
4431
|
+
async function uploadAssets(agentName, agent, basePath) {
|
|
4432
|
+
if (agent.instructions) {
|
|
4433
|
+
console.log(`Uploading instructions: ${agent.instructions}`);
|
|
4434
|
+
const result = await uploadInstructions(
|
|
4435
|
+
agentName,
|
|
4436
|
+
agent.instructions,
|
|
4437
|
+
basePath,
|
|
4438
|
+
agent.framework
|
|
4439
|
+
);
|
|
4440
|
+
console.log(
|
|
4441
|
+
chalk3.green(
|
|
4442
|
+
`\u2713 Instructions ${result.action === "deduplicated" ? "(unchanged)" : "uploaded"}: ${result.versionId.slice(0, 8)}`
|
|
4443
|
+
)
|
|
4444
|
+
);
|
|
4445
|
+
}
|
|
4446
|
+
const skillResults = [];
|
|
4447
|
+
if (agent.skills && Array.isArray(agent.skills)) {
|
|
4448
|
+
console.log(`Uploading ${agent.skills.length} skill(s)...`);
|
|
4449
|
+
for (const skillUrl of agent.skills) {
|
|
4450
|
+
console.log(chalk3.dim(` Downloading: ${skillUrl}`));
|
|
4451
|
+
const result = await uploadSkill(skillUrl);
|
|
4452
|
+
skillResults.push(result);
|
|
4437
4453
|
console.log(
|
|
4438
4454
|
chalk3.green(
|
|
4439
|
-
|
|
4455
|
+
` \u2713 Skill ${result.action === "deduplicated" ? "(unchanged)" : "uploaded"}: ${result.skillName} (${result.versionId.slice(0, 8)})`
|
|
4440
4456
|
)
|
|
4441
4457
|
);
|
|
4442
4458
|
}
|
|
4443
|
-
|
|
4444
|
-
|
|
4445
|
-
|
|
4446
|
-
|
|
4447
|
-
|
|
4448
|
-
|
|
4449
|
-
|
|
4450
|
-
|
|
4451
|
-
|
|
4452
|
-
|
|
4453
|
-
|
|
4454
|
-
)
|
|
4455
|
-
);
|
|
4456
|
-
}
|
|
4457
|
-
}
|
|
4458
|
-
const skillSecrets = /* @__PURE__ */ new Map();
|
|
4459
|
-
const skillVars = /* @__PURE__ */ new Map();
|
|
4460
|
-
for (const result of skillResults) {
|
|
4461
|
-
const { frontmatter, skillName } = result;
|
|
4462
|
-
if (frontmatter.vm0_secrets) {
|
|
4463
|
-
for (const secret of frontmatter.vm0_secrets) {
|
|
4464
|
-
if (!skillSecrets.has(secret)) {
|
|
4465
|
-
skillSecrets.set(secret, []);
|
|
4466
|
-
}
|
|
4467
|
-
skillSecrets.get(secret).push(skillName);
|
|
4459
|
+
}
|
|
4460
|
+
return skillResults;
|
|
4461
|
+
}
|
|
4462
|
+
async function collectSkillVariables(skillResults, environment, agentName) {
|
|
4463
|
+
const skillSecrets = /* @__PURE__ */ new Map();
|
|
4464
|
+
const skillVars = /* @__PURE__ */ new Map();
|
|
4465
|
+
for (const result of skillResults) {
|
|
4466
|
+
const { frontmatter, skillName } = result;
|
|
4467
|
+
if (frontmatter.vm0_secrets) {
|
|
4468
|
+
for (const secret of frontmatter.vm0_secrets) {
|
|
4469
|
+
if (!skillSecrets.has(secret)) {
|
|
4470
|
+
skillSecrets.set(secret, []);
|
|
4468
4471
|
}
|
|
4472
|
+
skillSecrets.get(secret).push(skillName);
|
|
4469
4473
|
}
|
|
4470
|
-
|
|
4471
|
-
|
|
4472
|
-
|
|
4473
|
-
|
|
4474
|
-
|
|
4475
|
-
skillVars.get(varName).push(skillName);
|
|
4474
|
+
}
|
|
4475
|
+
if (frontmatter.vm0_vars) {
|
|
4476
|
+
for (const varName of frontmatter.vm0_vars) {
|
|
4477
|
+
if (!skillVars.has(varName)) {
|
|
4478
|
+
skillVars.set(varName, []);
|
|
4476
4479
|
}
|
|
4480
|
+
skillVars.get(varName).push(skillName);
|
|
4477
4481
|
}
|
|
4478
4482
|
}
|
|
4479
|
-
|
|
4480
|
-
|
|
4481
|
-
|
|
4482
|
-
|
|
4483
|
-
|
|
4484
|
-
|
|
4485
|
-
|
|
4486
|
-
|
|
4487
|
-
|
|
4488
|
-
|
|
4489
|
-
|
|
4483
|
+
}
|
|
4484
|
+
const newSecrets = [...skillSecrets.entries()].filter(
|
|
4485
|
+
([name]) => !(name in environment)
|
|
4486
|
+
);
|
|
4487
|
+
const newVars = [...skillVars.entries()].filter(
|
|
4488
|
+
([name]) => !(name in environment)
|
|
4489
|
+
);
|
|
4490
|
+
let headSecrets = /* @__PURE__ */ new Set();
|
|
4491
|
+
const existingCompose = await getComposeByName(agentName);
|
|
4492
|
+
if (existingCompose?.content) {
|
|
4493
|
+
headSecrets = getSecretsFromComposeContent(existingCompose.content);
|
|
4494
|
+
}
|
|
4495
|
+
const trulyNewSecrets = newSecrets.map(([name]) => name).filter((name) => !headSecrets.has(name));
|
|
4496
|
+
return { newSecrets, newVars, trulyNewSecrets };
|
|
4497
|
+
}
|
|
4498
|
+
async function displayAndConfirmVariables(variables, options) {
|
|
4499
|
+
const { newSecrets, newVars, trulyNewSecrets } = variables;
|
|
4500
|
+
if (newSecrets.length === 0 && newVars.length === 0) {
|
|
4501
|
+
return true;
|
|
4502
|
+
}
|
|
4503
|
+
console.log();
|
|
4504
|
+
console.log(
|
|
4505
|
+
chalk3.bold("Skills require the following environment variables:")
|
|
4506
|
+
);
|
|
4507
|
+
console.log();
|
|
4508
|
+
if (newSecrets.length > 0) {
|
|
4509
|
+
console.log(chalk3.cyan(" Secrets:"));
|
|
4510
|
+
for (const [name, skills] of newSecrets) {
|
|
4511
|
+
const isNew = trulyNewSecrets.includes(name);
|
|
4512
|
+
const newMarker = isNew ? chalk3.yellow(" (new)") : "";
|
|
4513
|
+
console.log(` ${name.padEnd(24)}${newMarker} <- ${skills.join(", ")}`);
|
|
4490
4514
|
}
|
|
4491
|
-
|
|
4492
|
-
|
|
4493
|
-
|
|
4494
|
-
|
|
4495
|
-
|
|
4515
|
+
}
|
|
4516
|
+
if (newVars.length > 0) {
|
|
4517
|
+
console.log(chalk3.cyan(" Vars:"));
|
|
4518
|
+
for (const [name, skills] of newVars) {
|
|
4519
|
+
console.log(` ${name.padEnd(24)} <- ${skills.join(", ")}`);
|
|
4520
|
+
}
|
|
4521
|
+
}
|
|
4522
|
+
console.log();
|
|
4523
|
+
if (trulyNewSecrets.length > 0 && !options.yes) {
|
|
4524
|
+
if (!isInteractive()) {
|
|
4525
|
+
console.error(
|
|
4526
|
+
chalk3.red(`\u2717 New secrets detected: ${trulyNewSecrets.join(", ")}`)
|
|
4496
4527
|
);
|
|
4497
|
-
console.
|
|
4498
|
-
|
|
4499
|
-
|
|
4500
|
-
|
|
4501
|
-
|
|
4502
|
-
|
|
4503
|
-
|
|
4504
|
-
|
|
4505
|
-
|
|
4506
|
-
|
|
4507
|
-
|
|
4508
|
-
|
|
4509
|
-
|
|
4510
|
-
|
|
4511
|
-
console.log(` ${name.padEnd(24)} <- ${skills.join(", ")}`);
|
|
4512
|
-
}
|
|
4513
|
-
}
|
|
4514
|
-
console.log();
|
|
4515
|
-
if (trulyNewSecrets.length > 0) {
|
|
4516
|
-
if (!options.yes) {
|
|
4517
|
-
if (!isInteractive()) {
|
|
4518
|
-
console.error(
|
|
4519
|
-
chalk3.red(
|
|
4520
|
-
`\u2717 New secrets detected: ${trulyNewSecrets.join(", ")}`
|
|
4521
|
-
)
|
|
4522
|
-
);
|
|
4523
|
-
console.error(
|
|
4524
|
-
chalk3.dim(
|
|
4525
|
-
" Use --yes flag to approve new secrets in non-interactive mode."
|
|
4526
|
-
)
|
|
4527
|
-
);
|
|
4528
|
-
process.exit(1);
|
|
4529
|
-
}
|
|
4530
|
-
const confirmed = await promptConfirm(
|
|
4531
|
-
`Approve ${trulyNewSecrets.length} new secret(s)?`,
|
|
4532
|
-
true
|
|
4533
|
-
);
|
|
4534
|
-
if (!confirmed) {
|
|
4535
|
-
console.log(chalk3.yellow("Compose cancelled"));
|
|
4536
|
-
process.exit(0);
|
|
4537
|
-
}
|
|
4538
|
-
}
|
|
4539
|
-
}
|
|
4540
|
-
for (const [name] of newSecrets) {
|
|
4541
|
-
environment[name] = `\${{ secrets.${name} }}`;
|
|
4542
|
-
}
|
|
4543
|
-
for (const [name] of newVars) {
|
|
4544
|
-
environment[name] = `\${{ vars.${name} }}`;
|
|
4545
|
-
}
|
|
4546
|
-
if (Object.keys(environment).length > 0) {
|
|
4547
|
-
agent.environment = environment;
|
|
4548
|
-
}
|
|
4528
|
+
console.error(
|
|
4529
|
+
chalk3.dim(
|
|
4530
|
+
" Use --yes flag to approve new secrets in non-interactive mode."
|
|
4531
|
+
)
|
|
4532
|
+
);
|
|
4533
|
+
process.exit(1);
|
|
4534
|
+
}
|
|
4535
|
+
const confirmed = await promptConfirm(
|
|
4536
|
+
`Approve ${trulyNewSecrets.length} new secret(s)?`,
|
|
4537
|
+
true
|
|
4538
|
+
);
|
|
4539
|
+
if (!confirmed) {
|
|
4540
|
+
console.log(chalk3.yellow("Compose cancelled"));
|
|
4541
|
+
return false;
|
|
4549
4542
|
}
|
|
4543
|
+
}
|
|
4544
|
+
return true;
|
|
4545
|
+
}
|
|
4546
|
+
function mergeSkillVariables(agent, variables) {
|
|
4547
|
+
const { newSecrets, newVars } = variables;
|
|
4548
|
+
if (newSecrets.length === 0 && newVars.length === 0) {
|
|
4549
|
+
return;
|
|
4550
|
+
}
|
|
4551
|
+
const environment = agent.environment || {};
|
|
4552
|
+
for (const [name] of newSecrets) {
|
|
4553
|
+
environment[name] = `\${{ secrets.${name} }}`;
|
|
4554
|
+
}
|
|
4555
|
+
for (const [name] of newVars) {
|
|
4556
|
+
environment[name] = `\${{ vars.${name} }}`;
|
|
4557
|
+
}
|
|
4558
|
+
if (Object.keys(environment).length > 0) {
|
|
4559
|
+
agent.environment = environment;
|
|
4560
|
+
}
|
|
4561
|
+
}
|
|
4562
|
+
var composeCommand = new Command7().name("compose").description("Create or update agent compose (e.g., vm0.yaml)").argument("<agent-yaml>", "Path to agent YAML file").option("-y, --yes", "Skip confirmation prompts for skill requirements").action(async (configFile, options) => {
|
|
4563
|
+
try {
|
|
4564
|
+
const { config, agentName, agent, basePath } = await loadAndValidateConfig(configFile);
|
|
4565
|
+
checkLegacyImageFormat(config);
|
|
4566
|
+
const skillResults = await uploadAssets(agentName, agent, basePath);
|
|
4567
|
+
const environment = agent.environment || {};
|
|
4568
|
+
const variables = await collectSkillVariables(
|
|
4569
|
+
skillResults,
|
|
4570
|
+
environment,
|
|
4571
|
+
agentName
|
|
4572
|
+
);
|
|
4573
|
+
const confirmed = await displayAndConfirmVariables(variables, options);
|
|
4574
|
+
if (!confirmed) {
|
|
4575
|
+
process.exit(0);
|
|
4576
|
+
}
|
|
4577
|
+
mergeSkillVariables(agent, variables);
|
|
4550
4578
|
console.log("Uploading compose...");
|
|
4551
|
-
const response = await createOrUpdateCompose({
|
|
4552
|
-
content: config
|
|
4553
|
-
});
|
|
4579
|
+
const response = await createOrUpdateCompose({ content: config });
|
|
4554
4580
|
const scopeResponse = await getScope();
|
|
4555
4581
|
const shortVersionId = response.versionId.slice(0, 8);
|
|
4556
4582
|
const displayName = `${scopeResponse.slug}/${response.name}`;
|
|
@@ -4571,9 +4597,6 @@ var composeCommand = new Command7().name("compose").description("Create or updat
|
|
|
4571
4597
|
if (error instanceof Error) {
|
|
4572
4598
|
if (error.message.includes("Not authenticated")) {
|
|
4573
4599
|
console.error(chalk3.red("\u2717 Not authenticated. Run: vm0 auth login"));
|
|
4574
|
-
} else if (error.message.includes("Failed to create compose")) {
|
|
4575
|
-
console.error(chalk3.red("\u2717 Failed to create compose"));
|
|
4576
|
-
console.error(chalk3.dim(` ${error.message}`));
|
|
4577
4600
|
} else {
|
|
4578
4601
|
console.error(chalk3.red("\u2717 Failed to create compose"));
|
|
4579
4602
|
console.error(chalk3.dim(` ${error.message}`));
|
|
@@ -5984,7 +6007,7 @@ var ApiClient = class {
|
|
|
5984
6007
|
/**
|
|
5985
6008
|
* Generic GET request
|
|
5986
6009
|
*/
|
|
5987
|
-
async get(
|
|
6010
|
+
async get(path16) {
|
|
5988
6011
|
const baseUrl = await this.getBaseUrl();
|
|
5989
6012
|
const token = await getToken();
|
|
5990
6013
|
if (!token) {
|
|
@@ -5997,7 +6020,7 @@ var ApiClient = class {
|
|
|
5997
6020
|
if (bypassSecret) {
|
|
5998
6021
|
headers["x-vercel-protection-bypass"] = bypassSecret;
|
|
5999
6022
|
}
|
|
6000
|
-
return fetch(`${baseUrl}${
|
|
6023
|
+
return fetch(`${baseUrl}${path16}`, {
|
|
6001
6024
|
method: "GET",
|
|
6002
6025
|
headers
|
|
6003
6026
|
});
|
|
@@ -6005,7 +6028,7 @@ var ApiClient = class {
|
|
|
6005
6028
|
/**
|
|
6006
6029
|
* Generic POST request
|
|
6007
6030
|
*/
|
|
6008
|
-
async post(
|
|
6031
|
+
async post(path16, options) {
|
|
6009
6032
|
const baseUrl = await this.getBaseUrl();
|
|
6010
6033
|
const token = await getToken();
|
|
6011
6034
|
if (!token) {
|
|
@@ -6021,7 +6044,7 @@ var ApiClient = class {
|
|
|
6021
6044
|
if (bypassSecret) {
|
|
6022
6045
|
headers["x-vercel-protection-bypass"] = bypassSecret;
|
|
6023
6046
|
}
|
|
6024
|
-
return fetch(`${baseUrl}${
|
|
6047
|
+
return fetch(`${baseUrl}${path16}`, {
|
|
6025
6048
|
method: "POST",
|
|
6026
6049
|
headers,
|
|
6027
6050
|
body: options?.body
|
|
@@ -6030,7 +6053,7 @@ var ApiClient = class {
|
|
|
6030
6053
|
/**
|
|
6031
6054
|
* Generic DELETE request
|
|
6032
6055
|
*/
|
|
6033
|
-
async delete(
|
|
6056
|
+
async delete(path16) {
|
|
6034
6057
|
const baseUrl = await this.getBaseUrl();
|
|
6035
6058
|
const token = await getToken();
|
|
6036
6059
|
if (!token) {
|
|
@@ -6043,7 +6066,7 @@ var ApiClient = class {
|
|
|
6043
6066
|
if (bypassSecret) {
|
|
6044
6067
|
headers["x-vercel-protection-bypass"] = bypassSecret;
|
|
6045
6068
|
}
|
|
6046
|
-
return fetch(`${baseUrl}${
|
|
6069
|
+
return fetch(`${baseUrl}${path16}`, {
|
|
6047
6070
|
method: "DELETE",
|
|
6048
6071
|
headers
|
|
6049
6072
|
});
|
|
@@ -7848,8 +7871,10 @@ function execVm0Command(args, options = {}) {
|
|
|
7848
7871
|
}
|
|
7849
7872
|
function execVm0RunWithCapture(args, options = {}) {
|
|
7850
7873
|
return new Promise((resolve, reject) => {
|
|
7874
|
+
const env = process.stdout.isTTY ? { ...process.env, FORCE_COLOR: "1" } : process.env;
|
|
7851
7875
|
const proc = spawn2("vm0", args, {
|
|
7852
7876
|
cwd: options.cwd,
|
|
7877
|
+
env,
|
|
7853
7878
|
stdio: ["inherit", "pipe", "pipe"],
|
|
7854
7879
|
shell: process.platform === "win32"
|
|
7855
7880
|
});
|
|
@@ -7960,135 +7985,89 @@ function checkMissingVariables(varNames, envFilePath) {
|
|
|
7960
7985
|
}
|
|
7961
7986
|
return missing;
|
|
7962
7987
|
}
|
|
7963
|
-
|
|
7964
|
-
|
|
7965
|
-
|
|
7966
|
-
|
|
7967
|
-
|
|
7968
|
-
|
|
7969
|
-
|
|
7970
|
-
|
|
7971
|
-
|
|
7972
|
-
|
|
7973
|
-
|
|
7974
|
-
|
|
7975
|
-
|
|
7976
|
-
|
|
7977
|
-
if (!existsSync9(CONFIG_FILE2)) {
|
|
7978
|
-
console.error(chalk28.red(`\u2717 Config file not found: ${CONFIG_FILE2}`));
|
|
7979
|
-
process.exit(1);
|
|
7988
|
+
async function loadAndValidateConfig2() {
|
|
7989
|
+
console.log(chalk28.bold(`Reading config: ${CONFIG_FILE2}`));
|
|
7990
|
+
if (!existsSync9(CONFIG_FILE2)) {
|
|
7991
|
+
console.error(chalk28.red(`\u2717 Config file not found: ${CONFIG_FILE2}`));
|
|
7992
|
+
process.exit(1);
|
|
7993
|
+
}
|
|
7994
|
+
let config;
|
|
7995
|
+
try {
|
|
7996
|
+
const content = await readFile7(CONFIG_FILE2, "utf8");
|
|
7997
|
+
config = parseYaml4(content);
|
|
7998
|
+
} catch (error) {
|
|
7999
|
+
console.error(chalk28.red("\u2717 Invalid YAML format"));
|
|
8000
|
+
if (error instanceof Error) {
|
|
8001
|
+
console.error(chalk28.dim(` ${error.message}`));
|
|
7980
8002
|
}
|
|
7981
|
-
|
|
7982
|
-
|
|
7983
|
-
|
|
7984
|
-
|
|
7985
|
-
|
|
7986
|
-
|
|
7987
|
-
|
|
7988
|
-
|
|
8003
|
+
process.exit(1);
|
|
8004
|
+
}
|
|
8005
|
+
const validation = validateAgentCompose(config);
|
|
8006
|
+
if (!validation.valid) {
|
|
8007
|
+
console.error(chalk28.red(`\u2717 ${validation.error}`));
|
|
8008
|
+
process.exit(1);
|
|
8009
|
+
}
|
|
8010
|
+
const agentNames = Object.keys(config.agents);
|
|
8011
|
+
const agentName = agentNames[0];
|
|
8012
|
+
const volumeCount = config.volumes ? Object.keys(config.volumes).length : 0;
|
|
8013
|
+
console.log(
|
|
8014
|
+
chalk28.green(`\u2713 Config validated: 1 agent, ${volumeCount} volume(s)`)
|
|
8015
|
+
);
|
|
8016
|
+
return { config, agentName, volumeCount };
|
|
8017
|
+
}
|
|
8018
|
+
function validateEnvVariables(config, envFile) {
|
|
8019
|
+
const requiredVarNames = extractRequiredVarNames(config);
|
|
8020
|
+
if (requiredVarNames.length === 0) {
|
|
8021
|
+
return;
|
|
8022
|
+
}
|
|
8023
|
+
try {
|
|
8024
|
+
const missingVars = checkMissingVariables(requiredVarNames, envFile);
|
|
8025
|
+
if (missingVars.length > 0) {
|
|
8026
|
+
console.log();
|
|
8027
|
+
console.error(chalk28.red("\u2717 Missing required variables:"));
|
|
8028
|
+
for (const varName of missingVars) {
|
|
8029
|
+
console.error(chalk28.red(` ${varName}`));
|
|
7989
8030
|
}
|
|
8031
|
+
console.error(
|
|
8032
|
+
chalk28.dim(
|
|
8033
|
+
"\n Provide via --env-file, or set as environment variables"
|
|
8034
|
+
)
|
|
8035
|
+
);
|
|
7990
8036
|
process.exit(1);
|
|
7991
8037
|
}
|
|
7992
|
-
|
|
7993
|
-
if (
|
|
7994
|
-
console.error(chalk28.red(`\u2717 ${
|
|
7995
|
-
process.exit(1);
|
|
7996
|
-
}
|
|
7997
|
-
const agentNames = Object.keys(config.agents);
|
|
7998
|
-
const agentName = agentNames[0];
|
|
7999
|
-
const volumeCount = config.volumes ? Object.keys(config.volumes).length : 0;
|
|
8000
|
-
console.log(
|
|
8001
|
-
chalk28.green(`\u2713 Config validated: 1 agent, ${volumeCount} volume(s)`)
|
|
8002
|
-
);
|
|
8003
|
-
const requiredVarNames = extractRequiredVarNames(config);
|
|
8004
|
-
if (requiredVarNames.length > 0) {
|
|
8005
|
-
try {
|
|
8006
|
-
const missingVars = checkMissingVariables(
|
|
8007
|
-
requiredVarNames,
|
|
8008
|
-
options.envFile
|
|
8009
|
-
);
|
|
8010
|
-
if (missingVars.length > 0) {
|
|
8011
|
-
console.log();
|
|
8012
|
-
console.error(chalk28.red("\u2717 Missing required variables:"));
|
|
8013
|
-
for (const varName of missingVars) {
|
|
8014
|
-
console.error(chalk28.red(` ${varName}`));
|
|
8015
|
-
}
|
|
8016
|
-
console.error(
|
|
8017
|
-
chalk28.dim(
|
|
8018
|
-
"\n Provide via --env-file, or set as environment variables"
|
|
8019
|
-
)
|
|
8020
|
-
);
|
|
8021
|
-
process.exit(1);
|
|
8022
|
-
}
|
|
8023
|
-
} catch (error) {
|
|
8024
|
-
if (error instanceof Error) {
|
|
8025
|
-
console.error(chalk28.red(`\u2717 ${error.message}`));
|
|
8026
|
-
}
|
|
8027
|
-
process.exit(1);
|
|
8028
|
-
}
|
|
8038
|
+
} catch (error) {
|
|
8039
|
+
if (error instanceof Error) {
|
|
8040
|
+
console.error(chalk28.red(`\u2717 ${error.message}`));
|
|
8029
8041
|
}
|
|
8030
|
-
|
|
8031
|
-
|
|
8032
|
-
|
|
8033
|
-
|
|
8034
|
-
|
|
8035
|
-
|
|
8036
|
-
|
|
8037
|
-
|
|
8038
|
-
|
|
8039
|
-
|
|
8040
|
-
|
|
8041
|
-
|
|
8042
|
-
|
|
8043
|
-
|
|
8044
|
-
|
|
8045
|
-
printCommand(`cd ${volumeConfig.name}`);
|
|
8046
|
-
const existingConfig = await readStorageConfig(volumeDir);
|
|
8047
|
-
if (!existingConfig) {
|
|
8048
|
-
printCommand(`vm0 volume init --name ${volumeConfig.name}`);
|
|
8049
|
-
await execVm0Command(
|
|
8050
|
-
["volume", "init", "--name", volumeConfig.name],
|
|
8051
|
-
{
|
|
8052
|
-
cwd: volumeDir,
|
|
8053
|
-
silent: true
|
|
8054
|
-
}
|
|
8055
|
-
);
|
|
8056
|
-
}
|
|
8057
|
-
printCommand("vm0 volume push");
|
|
8058
|
-
await execVm0Command(["volume", "push"], {
|
|
8059
|
-
cwd: volumeDir,
|
|
8060
|
-
silent: true
|
|
8061
|
-
});
|
|
8062
|
-
printCommand("cd ..");
|
|
8063
|
-
} catch (error) {
|
|
8064
|
-
console.error(chalk28.red(`\u2717 Failed`));
|
|
8065
|
-
if (error instanceof Error) {
|
|
8066
|
-
console.error(chalk28.dim(` ${error.message}`));
|
|
8067
|
-
}
|
|
8068
|
-
process.exit(1);
|
|
8069
|
-
}
|
|
8070
|
-
}
|
|
8042
|
+
process.exit(1);
|
|
8043
|
+
}
|
|
8044
|
+
}
|
|
8045
|
+
async function processVolumes(config, cwd) {
|
|
8046
|
+
if (!config.volumes || Object.keys(config.volumes).length === 0) {
|
|
8047
|
+
return;
|
|
8048
|
+
}
|
|
8049
|
+
console.log();
|
|
8050
|
+
console.log(chalk28.bold("Processing volumes:"));
|
|
8051
|
+
for (const volumeConfig of Object.values(config.volumes)) {
|
|
8052
|
+
const volumeDir = path11.join(cwd, volumeConfig.name);
|
|
8053
|
+
if (!existsSync9(volumeDir)) {
|
|
8054
|
+
console.error(chalk28.red(`\u2717 Directory not found: ${volumeConfig.name}`));
|
|
8055
|
+
console.error(chalk28.dim(" Create the directory and add files first"));
|
|
8056
|
+
process.exit(1);
|
|
8071
8057
|
}
|
|
8072
|
-
console.log();
|
|
8073
|
-
console.log(chalk28.bold("Processing artifact:"));
|
|
8074
|
-
const artifactDir = path11.join(cwd, ARTIFACT_DIR);
|
|
8075
8058
|
try {
|
|
8076
|
-
|
|
8077
|
-
|
|
8078
|
-
await mkdir6(artifactDir, { recursive: true });
|
|
8079
|
-
}
|
|
8080
|
-
printCommand(`cd ${ARTIFACT_DIR}`);
|
|
8081
|
-
const existingConfig = await readStorageConfig(artifactDir);
|
|
8059
|
+
printCommand(`cd ${volumeConfig.name}`);
|
|
8060
|
+
const existingConfig = await readStorageConfig(volumeDir);
|
|
8082
8061
|
if (!existingConfig) {
|
|
8083
|
-
printCommand(`vm0
|
|
8084
|
-
await execVm0Command(["
|
|
8085
|
-
cwd:
|
|
8062
|
+
printCommand(`vm0 volume init --name ${volumeConfig.name}`);
|
|
8063
|
+
await execVm0Command(["volume", "init", "--name", volumeConfig.name], {
|
|
8064
|
+
cwd: volumeDir,
|
|
8086
8065
|
silent: true
|
|
8087
8066
|
});
|
|
8088
8067
|
}
|
|
8089
|
-
printCommand("vm0
|
|
8090
|
-
await execVm0Command(["
|
|
8091
|
-
cwd:
|
|
8068
|
+
printCommand("vm0 volume push");
|
|
8069
|
+
await execVm0Command(["volume", "push"], {
|
|
8070
|
+
cwd: volumeDir,
|
|
8092
8071
|
silent: true
|
|
8093
8072
|
});
|
|
8094
8073
|
printCommand("cd ..");
|
|
@@ -8099,51 +8078,112 @@ var cookAction = new Command27().name("cook").description("Quick start: prepare,
|
|
|
8099
8078
|
}
|
|
8100
8079
|
process.exit(1);
|
|
8101
8080
|
}
|
|
8102
|
-
|
|
8103
|
-
|
|
8104
|
-
|
|
8105
|
-
|
|
8106
|
-
|
|
8107
|
-
|
|
8108
|
-
|
|
8081
|
+
}
|
|
8082
|
+
}
|
|
8083
|
+
async function processArtifact(cwd) {
|
|
8084
|
+
console.log();
|
|
8085
|
+
console.log(chalk28.bold("Processing artifact:"));
|
|
8086
|
+
const artifactDir = path11.join(cwd, ARTIFACT_DIR);
|
|
8087
|
+
try {
|
|
8088
|
+
if (!existsSync9(artifactDir)) {
|
|
8089
|
+
printCommand(`mkdir ${ARTIFACT_DIR}`);
|
|
8090
|
+
await mkdir6(artifactDir, { recursive: true });
|
|
8091
|
+
}
|
|
8092
|
+
printCommand(`cd ${ARTIFACT_DIR}`);
|
|
8093
|
+
const existingConfig = await readStorageConfig(artifactDir);
|
|
8094
|
+
if (!existingConfig) {
|
|
8095
|
+
printCommand(`vm0 artifact init --name ${ARTIFACT_DIR}`);
|
|
8096
|
+
await execVm0Command(["artifact", "init", "--name", ARTIFACT_DIR], {
|
|
8097
|
+
cwd: artifactDir,
|
|
8098
|
+
silent: true
|
|
8109
8099
|
});
|
|
8110
|
-
}
|
|
8111
|
-
|
|
8112
|
-
|
|
8113
|
-
|
|
8100
|
+
}
|
|
8101
|
+
printCommand("vm0 artifact push");
|
|
8102
|
+
await execVm0Command(["artifact", "push"], {
|
|
8103
|
+
cwd: artifactDir,
|
|
8104
|
+
silent: true
|
|
8105
|
+
});
|
|
8106
|
+
printCommand("cd ..");
|
|
8107
|
+
} catch (error) {
|
|
8108
|
+
console.error(chalk28.red(`\u2717 Failed`));
|
|
8109
|
+
if (error instanceof Error) {
|
|
8110
|
+
console.error(chalk28.dim(` ${error.message}`));
|
|
8111
|
+
}
|
|
8112
|
+
process.exit(1);
|
|
8113
|
+
}
|
|
8114
|
+
return artifactDir;
|
|
8115
|
+
}
|
|
8116
|
+
async function composeAgent(cwd, skipConfirm) {
|
|
8117
|
+
console.log();
|
|
8118
|
+
console.log(chalk28.bold("Composing agent:"));
|
|
8119
|
+
const composeArgs = skipConfirm ? ["compose", "--yes", CONFIG_FILE2] : ["compose", CONFIG_FILE2];
|
|
8120
|
+
printCommand(`vm0 ${composeArgs.join(" ")}`);
|
|
8121
|
+
try {
|
|
8122
|
+
await execVm0Command(composeArgs, { cwd });
|
|
8123
|
+
} catch (error) {
|
|
8124
|
+
console.error(chalk28.red(`\u2717 Compose failed`));
|
|
8125
|
+
if (error instanceof Error) {
|
|
8126
|
+
console.error(chalk28.dim(` ${error.message}`));
|
|
8127
|
+
}
|
|
8128
|
+
process.exit(1);
|
|
8129
|
+
}
|
|
8130
|
+
}
|
|
8131
|
+
async function runAgent(agentName, artifactDir, prompt, cwd, debugNoMockClaude) {
|
|
8132
|
+
console.log();
|
|
8133
|
+
console.log(chalk28.bold("Running agent:"));
|
|
8134
|
+
printCommand(
|
|
8135
|
+
`vm0 run ${agentName} --artifact-name ${ARTIFACT_DIR} "${prompt}"`
|
|
8136
|
+
);
|
|
8137
|
+
console.log();
|
|
8138
|
+
let runOutput;
|
|
8139
|
+
try {
|
|
8140
|
+
const runArgs = [
|
|
8141
|
+
"run",
|
|
8142
|
+
agentName,
|
|
8143
|
+
"--artifact-name",
|
|
8144
|
+
ARTIFACT_DIR,
|
|
8145
|
+
...debugNoMockClaude ? ["--debug-no-mock-claude"] : [],
|
|
8146
|
+
prompt
|
|
8147
|
+
];
|
|
8148
|
+
runOutput = await execVm0RunWithCapture(runArgs, { cwd });
|
|
8149
|
+
} catch {
|
|
8150
|
+
process.exit(1);
|
|
8151
|
+
}
|
|
8152
|
+
const runIds = parseRunIdsFromOutput(runOutput);
|
|
8153
|
+
if (runIds.runId || runIds.sessionId || runIds.checkpointId) {
|
|
8154
|
+
await saveCookState({
|
|
8155
|
+
lastRunId: runIds.runId,
|
|
8156
|
+
lastSessionId: runIds.sessionId,
|
|
8157
|
+
lastCheckpointId: runIds.checkpointId
|
|
8158
|
+
});
|
|
8159
|
+
}
|
|
8160
|
+
await autoPullArtifact(runOutput, artifactDir);
|
|
8161
|
+
}
|
|
8162
|
+
var cookAction = new Command27().name("cook").description("Quick start: prepare, compose and run agent from vm0.yaml").argument("[prompt]", "Prompt for the agent").option(
|
|
8163
|
+
"--env-file <path>",
|
|
8164
|
+
"Load environment variables from file (priority: CLI flags > file > env vars)"
|
|
8165
|
+
).option("-y, --yes", "Skip confirmation prompts").addOption(new Option4("--debug-no-mock-claude").hideHelp()).addOption(new Option4("--no-auto-update").hideHelp()).action(
|
|
8166
|
+
async (prompt, options) => {
|
|
8167
|
+
if (!options.noAutoUpdate) {
|
|
8168
|
+
const shouldExit = await checkAndUpgrade("9.5.1", prompt);
|
|
8169
|
+
if (shouldExit) {
|
|
8170
|
+
process.exit(0);
|
|
8114
8171
|
}
|
|
8115
|
-
process.exit(1);
|
|
8116
8172
|
}
|
|
8173
|
+
const cwd = process.cwd();
|
|
8174
|
+
const { config, agentName } = await loadAndValidateConfig2();
|
|
8175
|
+
validateEnvVariables(config, options.envFile);
|
|
8176
|
+
await processVolumes(config, cwd);
|
|
8177
|
+
const artifactDir = await processArtifact(cwd);
|
|
8178
|
+
await composeAgent(cwd, options.yes ?? false);
|
|
8117
8179
|
if (prompt) {
|
|
8118
|
-
|
|
8119
|
-
|
|
8120
|
-
|
|
8121
|
-
|
|
8180
|
+
await runAgent(
|
|
8181
|
+
agentName,
|
|
8182
|
+
artifactDir,
|
|
8183
|
+
prompt,
|
|
8184
|
+
cwd,
|
|
8185
|
+
options.debugNoMockClaude ?? false
|
|
8122
8186
|
);
|
|
8123
|
-
console.log();
|
|
8124
|
-
let runOutput;
|
|
8125
|
-
try {
|
|
8126
|
-
const runArgs = [
|
|
8127
|
-
"run",
|
|
8128
|
-
agentName,
|
|
8129
|
-
"--artifact-name",
|
|
8130
|
-
ARTIFACT_DIR,
|
|
8131
|
-
...options.debugNoMockClaude ? ["--debug-no-mock-claude"] : [],
|
|
8132
|
-
prompt
|
|
8133
|
-
];
|
|
8134
|
-
runOutput = await execVm0RunWithCapture(runArgs, { cwd });
|
|
8135
|
-
} catch {
|
|
8136
|
-
process.exit(1);
|
|
8137
|
-
}
|
|
8138
|
-
const runIds = parseRunIdsFromOutput(runOutput);
|
|
8139
|
-
if (runIds.runId || runIds.sessionId || runIds.checkpointId) {
|
|
8140
|
-
await saveCookState({
|
|
8141
|
-
lastRunId: runIds.runId,
|
|
8142
|
-
lastSessionId: runIds.sessionId,
|
|
8143
|
-
lastCheckpointId: runIds.checkpointId
|
|
8144
|
-
});
|
|
8145
|
-
}
|
|
8146
|
-
await autoPullArtifact(runOutput, artifactDir);
|
|
8147
8187
|
} else {
|
|
8148
8188
|
console.log();
|
|
8149
8189
|
console.log("To run your agent:");
|
|
@@ -10706,86 +10746,115 @@ import { Command as Command56 } from "commander";
|
|
|
10706
10746
|
import chalk56 from "chalk";
|
|
10707
10747
|
import { mkdir as mkdir7 } from "fs/promises";
|
|
10708
10748
|
import { existsSync as existsSync11 } from "fs";
|
|
10709
|
-
import path16 from "path";
|
|
10710
10749
|
|
|
10711
10750
|
// src/lib/ui/welcome-box.ts
|
|
10712
10751
|
import chalk53 from "chalk";
|
|
10713
|
-
|
|
10714
|
-
|
|
10715
|
-
|
|
10716
|
-
|
|
10717
|
-
|
|
10718
|
-
|
|
10719
|
-
|
|
10720
|
-
|
|
10721
|
-
|
|
10722
|
-
|
|
10723
|
-
|
|
10724
|
-
|
|
10725
|
-
|
|
10726
|
-
|
|
10727
|
-
|
|
10728
|
-
|
|
10752
|
+
var gradientColors = [
|
|
10753
|
+
chalk53.hex("#FFAB5E"),
|
|
10754
|
+
// Line 1 - lightest
|
|
10755
|
+
chalk53.hex("#FF9642"),
|
|
10756
|
+
// Line 2
|
|
10757
|
+
chalk53.hex("#FF8228"),
|
|
10758
|
+
// Line 3
|
|
10759
|
+
chalk53.hex("#FF6D0A"),
|
|
10760
|
+
// Line 4
|
|
10761
|
+
chalk53.hex("#E85D00"),
|
|
10762
|
+
// Line 5
|
|
10763
|
+
chalk53.hex("#CC4E00")
|
|
10764
|
+
// Line 6 - darkest
|
|
10765
|
+
];
|
|
10766
|
+
var vm0LogoLines = [
|
|
10767
|
+
"\u2588\u2588\u2557 \u2588\u2588\u2557\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557 ",
|
|
10768
|
+
"\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u2550\u2588\u2588\u2557",
|
|
10769
|
+
"\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2554\u2588\u2588\u2588\u2588\u2554\u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551",
|
|
10770
|
+
"\u255A\u2588\u2588\u2557 \u2588\u2588\u2554\u255D\u2588\u2588\u2551\u255A\u2588\u2588\u2554\u255D\u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551",
|
|
10771
|
+
" \u255A\u2588\u2588\u2588\u2588\u2554\u255D \u2588\u2588\u2551 \u255A\u2550\u255D \u2588\u2588\u2551\u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D",
|
|
10772
|
+
" \u255A\u2550\u2550\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D "
|
|
10773
|
+
];
|
|
10774
|
+
function renderVm0Banner() {
|
|
10775
|
+
console.log();
|
|
10776
|
+
for (let i = 0; i < vm0LogoLines.length; i++) {
|
|
10777
|
+
const color = gradientColors[i] ?? gradientColors[gradientColors.length - 1];
|
|
10778
|
+
console.log(` ${color?.(vm0LogoLines[i])}`);
|
|
10779
|
+
}
|
|
10780
|
+
console.log();
|
|
10729
10781
|
}
|
|
10730
10782
|
function renderOnboardWelcome() {
|
|
10731
|
-
|
|
10732
|
-
|
|
10733
|
-
|
|
10734
|
-
""
|
|
10735
|
-
|
|
10736
|
-
|
|
10737
|
-
]);
|
|
10783
|
+
renderVm0Banner();
|
|
10784
|
+
console.log(` ${chalk53.bold("Welcome to VM0!")}`);
|
|
10785
|
+
console.log(
|
|
10786
|
+
` ${chalk53.dim("Build agentic workflows using natural language.")}`
|
|
10787
|
+
);
|
|
10788
|
+
console.log();
|
|
10738
10789
|
}
|
|
10739
10790
|
|
|
10740
|
-
// src/lib/ui/
|
|
10791
|
+
// src/lib/ui/step-runner.ts
|
|
10741
10792
|
import chalk54 from "chalk";
|
|
10742
|
-
|
|
10743
|
-
|
|
10744
|
-
|
|
10745
|
-
|
|
10746
|
-
|
|
10747
|
-
|
|
10748
|
-
|
|
10749
|
-
|
|
10750
|
-
|
|
10751
|
-
|
|
10752
|
-
|
|
10753
|
-
|
|
10754
|
-
|
|
10755
|
-
|
|
10756
|
-
|
|
10757
|
-
|
|
10758
|
-
|
|
10793
|
+
function createStepRunner(options = true) {
|
|
10794
|
+
const opts = typeof options === "boolean" ? { interactive: options } : options;
|
|
10795
|
+
const interactive = opts.interactive ?? true;
|
|
10796
|
+
const headerFn = opts.header;
|
|
10797
|
+
const completedSteps = [];
|
|
10798
|
+
function redrawCompletedSteps(isFinal) {
|
|
10799
|
+
process.stdout.write("\x1B[2J\x1B[H");
|
|
10800
|
+
if (headerFn) {
|
|
10801
|
+
console.log();
|
|
10802
|
+
headerFn();
|
|
10803
|
+
console.log();
|
|
10804
|
+
}
|
|
10805
|
+
for (const [i, step] of completedSteps.entries()) {
|
|
10806
|
+
if (step.failed) {
|
|
10807
|
+
console.log(chalk54.red(`\u2717 ${step.label}`));
|
|
10808
|
+
} else {
|
|
10809
|
+
console.log(chalk54.green(`\u25CF ${step.label}`));
|
|
10810
|
+
}
|
|
10811
|
+
const isLastStep = i === completedSteps.length - 1;
|
|
10812
|
+
if (!isLastStep || !isFinal) {
|
|
10813
|
+
console.log(chalk54.dim("\u2502"));
|
|
10814
|
+
}
|
|
10815
|
+
}
|
|
10759
10816
|
}
|
|
10760
|
-
|
|
10761
|
-
|
|
10762
|
-
|
|
10763
|
-
const
|
|
10764
|
-
|
|
10765
|
-
|
|
10766
|
-
|
|
10767
|
-
|
|
10768
|
-
|
|
10769
|
-
|
|
10817
|
+
async function executeStep(label, fn, isFinal) {
|
|
10818
|
+
let stepFailed = false;
|
|
10819
|
+
console.log(chalk54.yellow(`\u25CB ${label}`));
|
|
10820
|
+
const ctx = {
|
|
10821
|
+
connector() {
|
|
10822
|
+
console.log(chalk54.dim("\u2502"));
|
|
10823
|
+
},
|
|
10824
|
+
detail(message) {
|
|
10825
|
+
console.log(`${chalk54.dim("\u2502")} ${message}`);
|
|
10826
|
+
},
|
|
10827
|
+
async prompt(promptFn) {
|
|
10828
|
+
return await promptFn();
|
|
10829
|
+
}
|
|
10830
|
+
};
|
|
10831
|
+
try {
|
|
10832
|
+
await fn(ctx);
|
|
10833
|
+
} catch (error) {
|
|
10834
|
+
stepFailed = true;
|
|
10835
|
+
throw error;
|
|
10836
|
+
} finally {
|
|
10837
|
+
completedSteps.push({ label, failed: stepFailed });
|
|
10838
|
+
if (interactive) {
|
|
10839
|
+
redrawCompletedSteps(isFinal);
|
|
10840
|
+
} else {
|
|
10841
|
+
if (stepFailed) {
|
|
10842
|
+
console.log(chalk54.red(`\u2717 ${label}`));
|
|
10843
|
+
} else {
|
|
10844
|
+
console.log(chalk54.green(`\u25CF ${label}`));
|
|
10845
|
+
}
|
|
10846
|
+
if (!isFinal) {
|
|
10847
|
+
console.log(chalk54.dim("\u2502"));
|
|
10848
|
+
}
|
|
10849
|
+
}
|
|
10770
10850
|
}
|
|
10771
10851
|
}
|
|
10772
|
-
}
|
|
10773
|
-
function createOnboardProgress() {
|
|
10774
|
-
const steps = [
|
|
10775
|
-
{ label: "Authentication", status: "pending" },
|
|
10776
|
-
{ label: "Model Provider Setup", status: "pending" },
|
|
10777
|
-
{ label: "Create Agent", status: "pending" },
|
|
10778
|
-
{ label: "Claude Plugin Install", status: "pending" },
|
|
10779
|
-
{ label: "Complete", status: "pending" }
|
|
10780
|
-
];
|
|
10781
10852
|
return {
|
|
10782
|
-
|
|
10783
|
-
|
|
10784
|
-
|
|
10785
|
-
|
|
10786
|
-
|
|
10787
|
-
step.status = status;
|
|
10788
|
-
}
|
|
10853
|
+
async step(label, fn) {
|
|
10854
|
+
await executeStep(label, fn, false);
|
|
10855
|
+
},
|
|
10856
|
+
async finalStep(label, fn) {
|
|
10857
|
+
await executeStep(label, fn, true);
|
|
10789
10858
|
}
|
|
10790
10859
|
};
|
|
10791
10860
|
}
|
|
@@ -11022,162 +11091,162 @@ async function installVm0Plugin(scope = "user", cwd) {
|
|
|
11022
11091
|
// src/commands/onboard/index.ts
|
|
11023
11092
|
var DEFAULT_AGENT_NAME = "my-vm0-agent";
|
|
11024
11093
|
async function handleAuthentication(ctx) {
|
|
11025
|
-
ctx.
|
|
11026
|
-
|
|
11027
|
-
|
|
11028
|
-
|
|
11029
|
-
|
|
11030
|
-
|
|
11031
|
-
|
|
11032
|
-
|
|
11033
|
-
console.error("Run 'vm0 auth login' first or set VM0_TOKEN");
|
|
11034
|
-
process.exit(1);
|
|
11035
|
-
}
|
|
11036
|
-
console.log(chalk56.dim("Authentication required..."));
|
|
11037
|
-
console.log();
|
|
11038
|
-
await runAuthFlow({
|
|
11039
|
-
onInitiating: () => {
|
|
11040
|
-
console.log("Initiating authentication...");
|
|
11041
|
-
},
|
|
11042
|
-
onDeviceCodeReady: (url, code, expiresIn) => {
|
|
11043
|
-
console.log(chalk56.green("\nDevice code generated"));
|
|
11044
|
-
console.log(chalk56.cyan(`
|
|
11045
|
-
To authenticate, visit: ${url}`));
|
|
11046
|
-
console.log(`And enter this code: ${chalk56.bold(code)}`);
|
|
11047
|
-
console.log(`
|
|
11048
|
-
The code expires in ${expiresIn} minutes.`);
|
|
11049
|
-
console.log("\nWaiting for authentication...");
|
|
11050
|
-
},
|
|
11051
|
-
onPolling: () => {
|
|
11052
|
-
process.stdout.write(chalk56.dim("."));
|
|
11053
|
-
},
|
|
11054
|
-
onSuccess: () => {
|
|
11055
|
-
console.log(chalk56.green("\nAuthentication successful!"));
|
|
11056
|
-
console.log("Your credentials have been saved.");
|
|
11057
|
-
},
|
|
11058
|
-
onError: (error) => {
|
|
11059
|
-
console.error(chalk56.red(`
|
|
11060
|
-
${error.message}`));
|
|
11094
|
+
await ctx.runner.step("Authenticate to vm0.ai", async (step) => {
|
|
11095
|
+
const authenticated = await isAuthenticated();
|
|
11096
|
+
if (authenticated) {
|
|
11097
|
+
return;
|
|
11098
|
+
}
|
|
11099
|
+
if (!ctx.interactive) {
|
|
11100
|
+
console.error(chalk56.red("Error: Not authenticated"));
|
|
11101
|
+
console.error("Run 'vm0 auth login' first or set VM0_TOKEN");
|
|
11061
11102
|
process.exit(1);
|
|
11062
11103
|
}
|
|
11104
|
+
await runAuthFlow({
|
|
11105
|
+
onInitiating: () => {
|
|
11106
|
+
},
|
|
11107
|
+
onDeviceCodeReady: (url, code, expiresIn) => {
|
|
11108
|
+
step.detail(`Copy code: ${chalk56.cyan.bold(code)}`);
|
|
11109
|
+
step.detail(`Open: ${chalk56.cyan(url)}`);
|
|
11110
|
+
step.detail(chalk56.dim(`Expires in ${expiresIn} minutes`));
|
|
11111
|
+
},
|
|
11112
|
+
onPolling: () => {
|
|
11113
|
+
},
|
|
11114
|
+
onSuccess: () => {
|
|
11115
|
+
},
|
|
11116
|
+
onError: (error) => {
|
|
11117
|
+
console.error(chalk56.red(`
|
|
11118
|
+
${error.message}`));
|
|
11119
|
+
process.exit(1);
|
|
11120
|
+
}
|
|
11121
|
+
});
|
|
11063
11122
|
});
|
|
11064
|
-
ctx.updateProgress(0, "completed");
|
|
11065
11123
|
}
|
|
11066
11124
|
async function handleModelProvider(ctx) {
|
|
11067
|
-
ctx.
|
|
11068
|
-
|
|
11069
|
-
|
|
11070
|
-
|
|
11071
|
-
|
|
11072
|
-
|
|
11073
|
-
|
|
11074
|
-
|
|
11075
|
-
|
|
11076
|
-
|
|
11077
|
-
|
|
11078
|
-
|
|
11079
|
-
|
|
11080
|
-
|
|
11081
|
-
|
|
11082
|
-
|
|
11083
|
-
|
|
11084
|
-
|
|
11085
|
-
|
|
11086
|
-
|
|
11087
|
-
|
|
11088
|
-
|
|
11089
|
-
|
|
11090
|
-
|
|
11091
|
-
|
|
11092
|
-
|
|
11093
|
-
|
|
11094
|
-
|
|
11095
|
-
console.log(chalk56.dim(selectedChoice.helpText));
|
|
11096
|
-
console.log();
|
|
11097
|
-
}
|
|
11098
|
-
const credential = await promptPassword(
|
|
11099
|
-
`Enter your ${selectedChoice?.credentialLabel ?? "credential"}:`
|
|
11100
|
-
);
|
|
11101
|
-
if (!credential) {
|
|
11102
|
-
console.log(chalk56.dim("Cancelled"));
|
|
11103
|
-
process.exit(0);
|
|
11104
|
-
}
|
|
11105
|
-
const result = await setupModelProvider(providerType, credential);
|
|
11106
|
-
console.log(
|
|
11107
|
-
chalk56.green(
|
|
11108
|
-
`
|
|
11109
|
-
\u2713 Model provider "${providerType}" ${result.created ? "created" : "updated"}${result.isDefault ? ` (default for ${result.framework})` : ""}`
|
|
11110
|
-
)
|
|
11111
|
-
);
|
|
11112
|
-
ctx.updateProgress(1, "completed");
|
|
11113
|
-
}
|
|
11114
|
-
async function handleAgentCreation(ctx) {
|
|
11115
|
-
ctx.updateProgress(2, "in-progress");
|
|
11116
|
-
let agentName = ctx.options.name ?? DEFAULT_AGENT_NAME;
|
|
11117
|
-
if (!ctx.options.yes && !ctx.options.name && ctx.interactive) {
|
|
11118
|
-
const inputName = await promptText(
|
|
11119
|
-
"Enter agent name:",
|
|
11120
|
-
DEFAULT_AGENT_NAME,
|
|
11121
|
-
(value) => {
|
|
11122
|
-
if (!validateAgentName(value)) {
|
|
11123
|
-
return "Invalid name: 3-64 chars, alphanumeric + hyphens, start/end with letter/number";
|
|
11124
|
-
}
|
|
11125
|
-
return true;
|
|
11125
|
+
await ctx.runner.step("Set Up Model Provider", async (step) => {
|
|
11126
|
+
const providerStatus = await checkModelProviderStatus();
|
|
11127
|
+
if (providerStatus.hasProvider) {
|
|
11128
|
+
return;
|
|
11129
|
+
}
|
|
11130
|
+
if (!ctx.interactive) {
|
|
11131
|
+
console.error(chalk56.red("Error: No model provider configured"));
|
|
11132
|
+
console.error("Run 'vm0 model-provider setup' first");
|
|
11133
|
+
process.exit(1);
|
|
11134
|
+
}
|
|
11135
|
+
const choices = getProviderChoices();
|
|
11136
|
+
step.connector();
|
|
11137
|
+
const providerType = await step.prompt(
|
|
11138
|
+
() => promptSelect(
|
|
11139
|
+
"Select provider type:",
|
|
11140
|
+
choices.map((c20) => ({
|
|
11141
|
+
title: c20.label,
|
|
11142
|
+
value: c20.type
|
|
11143
|
+
}))
|
|
11144
|
+
)
|
|
11145
|
+
);
|
|
11146
|
+
if (!providerType) {
|
|
11147
|
+
process.exit(0);
|
|
11148
|
+
}
|
|
11149
|
+
const selectedChoice = choices.find((c20) => c20.type === providerType);
|
|
11150
|
+
if (selectedChoice?.helpText) {
|
|
11151
|
+
for (const line of selectedChoice.helpText.split("\n")) {
|
|
11152
|
+
step.detail(chalk56.dim(line));
|
|
11126
11153
|
}
|
|
11154
|
+
}
|
|
11155
|
+
const credential = await step.prompt(
|
|
11156
|
+
() => promptPassword(
|
|
11157
|
+
`Enter your ${selectedChoice?.credentialLabel ?? "credential"}:`
|
|
11158
|
+
)
|
|
11127
11159
|
);
|
|
11128
|
-
if (!
|
|
11160
|
+
if (!credential) {
|
|
11161
|
+
console.log(chalk56.dim("Cancelled"));
|
|
11129
11162
|
process.exit(0);
|
|
11130
11163
|
}
|
|
11131
|
-
|
|
11132
|
-
|
|
11133
|
-
|
|
11134
|
-
|
|
11135
|
-
chalk56.red(
|
|
11136
|
-
"Invalid agent name: must be 3-64 chars, alphanumeric + hyphens"
|
|
11164
|
+
const result = await setupModelProvider(providerType, credential);
|
|
11165
|
+
step.detail(
|
|
11166
|
+
chalk56.green(
|
|
11167
|
+
`${providerType} ${result.created ? "created" : "updated"}${result.isDefault ? ` (default for ${result.framework})` : ""}`
|
|
11137
11168
|
)
|
|
11138
11169
|
);
|
|
11139
|
-
|
|
11140
|
-
|
|
11141
|
-
|
|
11142
|
-
|
|
11143
|
-
|
|
11144
|
-
|
|
11145
|
-
|
|
11146
|
-
|
|
11147
|
-
|
|
11148
|
-
|
|
11149
|
-
|
|
11150
|
-
|
|
11151
|
-
|
|
11170
|
+
});
|
|
11171
|
+
}
|
|
11172
|
+
async function handleAgentCreation(ctx) {
|
|
11173
|
+
let agentName = ctx.options.name ?? DEFAULT_AGENT_NAME;
|
|
11174
|
+
await ctx.runner.step("Create New Project", async (step) => {
|
|
11175
|
+
if (!ctx.options.yes && !ctx.options.name && ctx.interactive) {
|
|
11176
|
+
let folderExists = true;
|
|
11177
|
+
while (folderExists) {
|
|
11178
|
+
step.connector();
|
|
11179
|
+
const inputName = await step.prompt(
|
|
11180
|
+
() => promptText(
|
|
11181
|
+
"Enter project name:",
|
|
11182
|
+
DEFAULT_AGENT_NAME,
|
|
11183
|
+
(value) => {
|
|
11184
|
+
if (!validateAgentName(value)) {
|
|
11185
|
+
return "Invalid name: 3-64 chars, alphanumeric + hyphens, start/end with letter/number";
|
|
11186
|
+
}
|
|
11187
|
+
return true;
|
|
11188
|
+
}
|
|
11189
|
+
)
|
|
11190
|
+
);
|
|
11191
|
+
if (!inputName) {
|
|
11192
|
+
process.exit(0);
|
|
11193
|
+
}
|
|
11194
|
+
agentName = inputName;
|
|
11195
|
+
if (existsSync11(agentName)) {
|
|
11196
|
+
step.detail(
|
|
11197
|
+
chalk56.yellow(`${agentName}/ already exists, choose another name`)
|
|
11198
|
+
);
|
|
11199
|
+
} else {
|
|
11200
|
+
folderExists = false;
|
|
11201
|
+
}
|
|
11202
|
+
}
|
|
11203
|
+
} else {
|
|
11204
|
+
if (!validateAgentName(agentName)) {
|
|
11205
|
+
console.error(
|
|
11206
|
+
chalk56.red(
|
|
11207
|
+
"Invalid agent name: must be 3-64 chars, alphanumeric + hyphens"
|
|
11208
|
+
)
|
|
11209
|
+
);
|
|
11210
|
+
process.exit(1);
|
|
11211
|
+
}
|
|
11212
|
+
if (existsSync11(agentName)) {
|
|
11213
|
+
console.error(chalk56.red(`${agentName}/ already exists`));
|
|
11214
|
+
console.log();
|
|
11215
|
+
console.log("Remove it first or choose a different name:");
|
|
11216
|
+
console.log(chalk56.cyan(` rm -rf ${agentName}`));
|
|
11217
|
+
process.exit(1);
|
|
11218
|
+
}
|
|
11219
|
+
}
|
|
11220
|
+
await mkdir7(agentName, { recursive: true });
|
|
11221
|
+
step.detail(chalk56.green(`Created ${agentName}/`));
|
|
11222
|
+
});
|
|
11152
11223
|
return agentName;
|
|
11153
11224
|
}
|
|
11154
11225
|
async function handlePluginInstallation(ctx, agentName) {
|
|
11155
|
-
ctx.
|
|
11156
|
-
|
|
11157
|
-
|
|
11158
|
-
|
|
11159
|
-
|
|
11160
|
-
|
|
11161
|
-
|
|
11162
|
-
|
|
11163
|
-
|
|
11164
|
-
|
|
11165
|
-
|
|
11166
|
-
|
|
11167
|
-
|
|
11168
|
-
|
|
11169
|
-
|
|
11170
|
-
|
|
11171
|
-
|
|
11172
|
-
|
|
11173
|
-
|
|
11174
|
-
|
|
11175
|
-
|
|
11176
|
-
|
|
11177
|
-
|
|
11178
|
-
|
|
11179
|
-
}
|
|
11180
|
-
ctx.updateProgress(3, "completed");
|
|
11226
|
+
await ctx.runner.step("Install Claude Plugin", async (step) => {
|
|
11227
|
+
let shouldInstall = true;
|
|
11228
|
+
if (!ctx.options.yes && ctx.interactive) {
|
|
11229
|
+
step.connector();
|
|
11230
|
+
const confirmed = await step.prompt(
|
|
11231
|
+
() => promptConfirm("Install VM0 Claude Plugin?", true)
|
|
11232
|
+
);
|
|
11233
|
+
shouldInstall = confirmed ?? true;
|
|
11234
|
+
}
|
|
11235
|
+
if (!shouldInstall) {
|
|
11236
|
+
step.detail(chalk56.dim("Skipped"));
|
|
11237
|
+
return;
|
|
11238
|
+
}
|
|
11239
|
+
const scope = "project";
|
|
11240
|
+
try {
|
|
11241
|
+
const agentDir = `${process.cwd()}/${agentName}`;
|
|
11242
|
+
const result = await installVm0Plugin(scope, agentDir);
|
|
11243
|
+
step.detail(
|
|
11244
|
+
chalk56.green(`Installed ${result.pluginId} (scope: ${result.scope})`)
|
|
11245
|
+
);
|
|
11246
|
+
} catch (error) {
|
|
11247
|
+
handlePluginError(error);
|
|
11248
|
+
}
|
|
11249
|
+
});
|
|
11181
11250
|
}
|
|
11182
11251
|
function printNextSteps(agentName) {
|
|
11183
11252
|
console.log();
|
|
@@ -11191,31 +11260,22 @@ function printNextSteps(agentName) {
|
|
|
11191
11260
|
var onboardCommand = new Command56().name("onboard").description("Guided setup for new VM0 users").option("-y, --yes", "Skip confirmation prompts").option("--name <name>", `Agent name (default: ${DEFAULT_AGENT_NAME})`).action(async (options) => {
|
|
11192
11261
|
const interactive = isInteractive();
|
|
11193
11262
|
if (interactive) {
|
|
11263
|
+
process.stdout.write("\x1B[2J\x1B[H");
|
|
11194
11264
|
console.log();
|
|
11195
11265
|
renderOnboardWelcome();
|
|
11196
11266
|
console.log();
|
|
11197
11267
|
}
|
|
11198
|
-
const
|
|
11199
|
-
|
|
11200
|
-
|
|
11201
|
-
|
|
11202
|
-
|
|
11203
|
-
renderOnboardWelcome();
|
|
11204
|
-
console.log();
|
|
11205
|
-
progress.render();
|
|
11206
|
-
console.log();
|
|
11207
|
-
}
|
|
11208
|
-
};
|
|
11209
|
-
if (interactive) {
|
|
11210
|
-
progress.render();
|
|
11211
|
-
console.log();
|
|
11212
|
-
}
|
|
11213
|
-
const ctx = { interactive, options, updateProgress };
|
|
11268
|
+
const runner = createStepRunner({
|
|
11269
|
+
interactive,
|
|
11270
|
+
header: interactive ? renderOnboardWelcome : void 0
|
|
11271
|
+
});
|
|
11272
|
+
const ctx = { interactive, options, runner };
|
|
11214
11273
|
await handleAuthentication(ctx);
|
|
11215
11274
|
await handleModelProvider(ctx);
|
|
11216
11275
|
const agentName = await handleAgentCreation(ctx);
|
|
11217
11276
|
await handlePluginInstallation(ctx, agentName);
|
|
11218
|
-
ctx.
|
|
11277
|
+
await ctx.runner.finalStep("Completed", async () => {
|
|
11278
|
+
});
|
|
11219
11279
|
printNextSteps(agentName);
|
|
11220
11280
|
});
|
|
11221
11281
|
|
|
@@ -11245,7 +11305,7 @@ var setupClaudeCommand = new Command57().name("setup-claude").description("Insta
|
|
|
11245
11305
|
|
|
11246
11306
|
// src/index.ts
|
|
11247
11307
|
var program = new Command58();
|
|
11248
|
-
program.name("vm0").description("VM0 CLI - Build and run agents with natural language").version("9.
|
|
11308
|
+
program.name("vm0").description("VM0 CLI - Build and run agents with natural language").version("9.5.1");
|
|
11249
11309
|
program.addCommand(authCommand);
|
|
11250
11310
|
program.addCommand(infoCommand);
|
|
11251
11311
|
program.addCommand(composeCommand);
|