@vm0/cli 9.10.0 → 9.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 +787 -615
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -234,8 +234,8 @@ var infoCommand = new Command6().name("info").description("Display environment i
|
|
|
234
234
|
});
|
|
235
235
|
|
|
236
236
|
// src/commands/compose/index.ts
|
|
237
|
-
import { Command as Command7 } from "commander";
|
|
238
|
-
import
|
|
237
|
+
import { Command as Command7, Option } from "commander";
|
|
238
|
+
import chalk4 from "chalk";
|
|
239
239
|
import { readFile as readFile4 } from "fs/promises";
|
|
240
240
|
import { existsSync as existsSync3 } from "fs";
|
|
241
241
|
import { dirname as dirname2 } from "path";
|
|
@@ -1904,19 +1904,55 @@ var MODEL_PROVIDER_TYPES = {
|
|
|
1904
1904
|
label: "Anthropic API Key",
|
|
1905
1905
|
credentialLabel: "API key",
|
|
1906
1906
|
helpText: "Get your API key at: https://console.anthropic.com/settings/keys"
|
|
1907
|
+
},
|
|
1908
|
+
"moonshot-api-key": {
|
|
1909
|
+
framework: "claude-code",
|
|
1910
|
+
credentialName: "MOONSHOT_API_KEY",
|
|
1911
|
+
label: "Moonshot API Key (Kimi)",
|
|
1912
|
+
credentialLabel: "API key",
|
|
1913
|
+
helpText: "Get your API key at: https://platform.moonshot.ai/console/api-keys",
|
|
1914
|
+
environmentMapping: {
|
|
1915
|
+
ANTHROPIC_AUTH_TOKEN: "$credential",
|
|
1916
|
+
ANTHROPIC_BASE_URL: "https://api.moonshot.ai/anthropic",
|
|
1917
|
+
ANTHROPIC_MODEL: "$model",
|
|
1918
|
+
ANTHROPIC_DEFAULT_OPUS_MODEL: "$model",
|
|
1919
|
+
ANTHROPIC_DEFAULT_SONNET_MODEL: "$model",
|
|
1920
|
+
ANTHROPIC_DEFAULT_HAIKU_MODEL: "$model",
|
|
1921
|
+
CLAUDE_CODE_SUBAGENT_MODEL: "$model"
|
|
1922
|
+
},
|
|
1923
|
+
models: [
|
|
1924
|
+
"kimi-k2.5",
|
|
1925
|
+
"kimi-k2-thinking-turbo",
|
|
1926
|
+
"kimi-k2-thinking"
|
|
1927
|
+
],
|
|
1928
|
+
defaultModel: "kimi-k2.5"
|
|
1907
1929
|
}
|
|
1908
1930
|
};
|
|
1909
1931
|
var modelProviderTypeSchema = z14.enum([
|
|
1910
1932
|
"claude-code-oauth-token",
|
|
1911
|
-
"anthropic-api-key"
|
|
1933
|
+
"anthropic-api-key",
|
|
1934
|
+
"moonshot-api-key"
|
|
1912
1935
|
]);
|
|
1913
1936
|
var modelProviderFrameworkSchema = z14.enum(["claude-code", "codex"]);
|
|
1937
|
+
function getModels(type) {
|
|
1938
|
+
const config = MODEL_PROVIDER_TYPES[type];
|
|
1939
|
+
return "models" in config ? config.models : void 0;
|
|
1940
|
+
}
|
|
1941
|
+
function getDefaultModel(type) {
|
|
1942
|
+
const config = MODEL_PROVIDER_TYPES[type];
|
|
1943
|
+
return "defaultModel" in config ? config.defaultModel : void 0;
|
|
1944
|
+
}
|
|
1945
|
+
function hasModelSelection(type) {
|
|
1946
|
+
const config = MODEL_PROVIDER_TYPES[type];
|
|
1947
|
+
return "models" in config && config.models.length > 0;
|
|
1948
|
+
}
|
|
1914
1949
|
var modelProviderResponseSchema = z14.object({
|
|
1915
1950
|
id: z14.string().uuid(),
|
|
1916
1951
|
type: modelProviderTypeSchema,
|
|
1917
1952
|
framework: modelProviderFrameworkSchema,
|
|
1918
1953
|
credentialName: z14.string(),
|
|
1919
1954
|
isDefault: z14.boolean(),
|
|
1955
|
+
selectedModel: z14.string().nullable(),
|
|
1920
1956
|
createdAt: z14.string(),
|
|
1921
1957
|
updatedAt: z14.string()
|
|
1922
1958
|
});
|
|
@@ -1926,7 +1962,8 @@ var modelProviderListResponseSchema = z14.object({
|
|
|
1926
1962
|
var upsertModelProviderRequestSchema = z14.object({
|
|
1927
1963
|
type: modelProviderTypeSchema,
|
|
1928
1964
|
credential: z14.string().min(1, "Credential is required"),
|
|
1929
|
-
convert: z14.boolean().optional()
|
|
1965
|
+
convert: z14.boolean().optional(),
|
|
1966
|
+
selectedModel: z14.string().optional()
|
|
1930
1967
|
});
|
|
1931
1968
|
var upsertModelProviderResponseSchema = z14.object({
|
|
1932
1969
|
provider: modelProviderResponseSchema,
|
|
@@ -4374,6 +4411,188 @@ async function promptPassword(message) {
|
|
|
4374
4411
|
return response.value;
|
|
4375
4412
|
}
|
|
4376
4413
|
|
|
4414
|
+
// src/lib/utils/update-checker.ts
|
|
4415
|
+
import { spawn } from "child_process";
|
|
4416
|
+
import chalk3 from "chalk";
|
|
4417
|
+
var PACKAGE_NAME = "@vm0/cli";
|
|
4418
|
+
var NPM_REGISTRY_URL = `https://registry.npmjs.org/${encodeURIComponent(PACKAGE_NAME)}/latest`;
|
|
4419
|
+
var TIMEOUT_MS = 5e3;
|
|
4420
|
+
function detectPackageManager() {
|
|
4421
|
+
const execPath = process.argv[1] ?? "";
|
|
4422
|
+
if (execPath.includes("pnpm")) {
|
|
4423
|
+
return "pnpm";
|
|
4424
|
+
}
|
|
4425
|
+
if (execPath.includes("/.bun/") || execPath.includes("/bun/")) {
|
|
4426
|
+
return "bun";
|
|
4427
|
+
}
|
|
4428
|
+
if (execPath.includes("/.yarn/") || execPath.includes("/yarn/")) {
|
|
4429
|
+
return "yarn";
|
|
4430
|
+
}
|
|
4431
|
+
if (execPath.includes("/usr/local/") || execPath.includes("/.nvm/") || execPath.includes("/.fnm/") || execPath.includes("/.volta/") || execPath.includes("/.nodenv/") || execPath.includes("/.n/") || execPath.includes("/node_modules/") || execPath.includes("\\npm\\") || // Windows: AppData\Roaming\npm
|
|
4432
|
+
execPath.includes("\\nodejs\\")) {
|
|
4433
|
+
return "npm";
|
|
4434
|
+
}
|
|
4435
|
+
return "unknown";
|
|
4436
|
+
}
|
|
4437
|
+
function isAutoUpgradeSupported(pm) {
|
|
4438
|
+
return pm === "npm" || pm === "pnpm";
|
|
4439
|
+
}
|
|
4440
|
+
function getManualUpgradeCommand(pm) {
|
|
4441
|
+
switch (pm) {
|
|
4442
|
+
case "bun":
|
|
4443
|
+
return `bun add -g ${PACKAGE_NAME}@latest`;
|
|
4444
|
+
case "yarn":
|
|
4445
|
+
return `yarn global add ${PACKAGE_NAME}@latest`;
|
|
4446
|
+
case "pnpm":
|
|
4447
|
+
return `pnpm add -g ${PACKAGE_NAME}@latest`;
|
|
4448
|
+
case "npm":
|
|
4449
|
+
return `npm install -g ${PACKAGE_NAME}@latest`;
|
|
4450
|
+
case "unknown":
|
|
4451
|
+
return `npm install -g ${PACKAGE_NAME}@latest`;
|
|
4452
|
+
}
|
|
4453
|
+
}
|
|
4454
|
+
function escapeForShell(str) {
|
|
4455
|
+
return `"${str.replace(/"/g, '\\"')}"`;
|
|
4456
|
+
}
|
|
4457
|
+
function buildRerunCommand(prompt) {
|
|
4458
|
+
if (prompt) {
|
|
4459
|
+
return `vm0 cook ${escapeForShell(prompt)}`;
|
|
4460
|
+
}
|
|
4461
|
+
return "vm0 cook";
|
|
4462
|
+
}
|
|
4463
|
+
async function getLatestVersion() {
|
|
4464
|
+
try {
|
|
4465
|
+
const controller = new AbortController();
|
|
4466
|
+
const timeoutId = setTimeout(() => controller.abort(), TIMEOUT_MS);
|
|
4467
|
+
const response = await fetch(NPM_REGISTRY_URL, {
|
|
4468
|
+
signal: controller.signal
|
|
4469
|
+
});
|
|
4470
|
+
clearTimeout(timeoutId);
|
|
4471
|
+
if (!response.ok) {
|
|
4472
|
+
return null;
|
|
4473
|
+
}
|
|
4474
|
+
const json = await response.json();
|
|
4475
|
+
return json.version ?? null;
|
|
4476
|
+
} catch {
|
|
4477
|
+
return null;
|
|
4478
|
+
}
|
|
4479
|
+
}
|
|
4480
|
+
function performUpgrade(packageManager) {
|
|
4481
|
+
return new Promise((resolve) => {
|
|
4482
|
+
const isWindows = process.platform === "win32";
|
|
4483
|
+
const command = isWindows ? `${packageManager}.cmd` : packageManager;
|
|
4484
|
+
const args = packageManager === "pnpm" ? ["add", "-g", `${PACKAGE_NAME}@latest`] : ["install", "-g", `${PACKAGE_NAME}@latest`];
|
|
4485
|
+
const child = spawn(command, args, {
|
|
4486
|
+
stdio: "inherit",
|
|
4487
|
+
shell: isWindows
|
|
4488
|
+
});
|
|
4489
|
+
child.on("close", (code) => {
|
|
4490
|
+
resolve(code === 0);
|
|
4491
|
+
});
|
|
4492
|
+
child.on("error", () => {
|
|
4493
|
+
resolve(false);
|
|
4494
|
+
});
|
|
4495
|
+
});
|
|
4496
|
+
}
|
|
4497
|
+
async function checkAndUpgrade(currentVersion, prompt) {
|
|
4498
|
+
const latestVersion = await getLatestVersion();
|
|
4499
|
+
if (latestVersion === null) {
|
|
4500
|
+
console.log(chalk3.yellow("Warning: Could not check for updates"));
|
|
4501
|
+
console.log();
|
|
4502
|
+
return false;
|
|
4503
|
+
}
|
|
4504
|
+
if (latestVersion === currentVersion) {
|
|
4505
|
+
return false;
|
|
4506
|
+
}
|
|
4507
|
+
console.log(chalk3.yellow("vm0 is currently in beta."));
|
|
4508
|
+
console.log(
|
|
4509
|
+
chalk3.yellow(
|
|
4510
|
+
`Current version: ${currentVersion} -> Latest version: ${latestVersion}`
|
|
4511
|
+
)
|
|
4512
|
+
);
|
|
4513
|
+
console.log(
|
|
4514
|
+
chalk3.yellow(
|
|
4515
|
+
"Please always use the latest version for best compatibility."
|
|
4516
|
+
)
|
|
4517
|
+
);
|
|
4518
|
+
console.log();
|
|
4519
|
+
const packageManager = detectPackageManager();
|
|
4520
|
+
if (!isAutoUpgradeSupported(packageManager)) {
|
|
4521
|
+
if (packageManager === "unknown") {
|
|
4522
|
+
console.log(
|
|
4523
|
+
chalk3.yellow("Could not detect your package manager for auto-upgrade.")
|
|
4524
|
+
);
|
|
4525
|
+
} else {
|
|
4526
|
+
console.log(
|
|
4527
|
+
chalk3.yellow(`Auto-upgrade is not supported for ${packageManager}.`)
|
|
4528
|
+
);
|
|
4529
|
+
}
|
|
4530
|
+
console.log(chalk3.yellow("Please upgrade manually:"));
|
|
4531
|
+
console.log(chalk3.cyan(` ${getManualUpgradeCommand(packageManager)}`));
|
|
4532
|
+
console.log();
|
|
4533
|
+
return false;
|
|
4534
|
+
}
|
|
4535
|
+
console.log(`Upgrading via ${packageManager}...`);
|
|
4536
|
+
const success = await performUpgrade(packageManager);
|
|
4537
|
+
if (success) {
|
|
4538
|
+
console.log(chalk3.green(`Upgraded to ${latestVersion}`));
|
|
4539
|
+
console.log();
|
|
4540
|
+
console.log("To continue, run:");
|
|
4541
|
+
console.log(chalk3.cyan(` ${buildRerunCommand(prompt)}`));
|
|
4542
|
+
return true;
|
|
4543
|
+
}
|
|
4544
|
+
console.log();
|
|
4545
|
+
console.log(chalk3.red("Upgrade failed. Please run manually:"));
|
|
4546
|
+
console.log(chalk3.cyan(` ${getManualUpgradeCommand(packageManager)}`));
|
|
4547
|
+
console.log();
|
|
4548
|
+
console.log("Then re-run:");
|
|
4549
|
+
console.log(chalk3.cyan(` ${buildRerunCommand(prompt)}`));
|
|
4550
|
+
return true;
|
|
4551
|
+
}
|
|
4552
|
+
async function silentUpgradeAfterCommand(currentVersion) {
|
|
4553
|
+
const latestVersion = await getLatestVersion();
|
|
4554
|
+
if (latestVersion === null || latestVersion === currentVersion) {
|
|
4555
|
+
return;
|
|
4556
|
+
}
|
|
4557
|
+
const packageManager = detectPackageManager();
|
|
4558
|
+
if (!isAutoUpgradeSupported(packageManager)) {
|
|
4559
|
+
return;
|
|
4560
|
+
}
|
|
4561
|
+
const isWindows = process.platform === "win32";
|
|
4562
|
+
const command = isWindows ? `${packageManager}.cmd` : packageManager;
|
|
4563
|
+
const args = packageManager === "pnpm" ? ["add", "-g", `${PACKAGE_NAME}@latest`] : ["install", "-g", `${PACKAGE_NAME}@latest`];
|
|
4564
|
+
const upgradeResult = await new Promise((resolve) => {
|
|
4565
|
+
const child = spawn(command, args, {
|
|
4566
|
+
stdio: "pipe",
|
|
4567
|
+
// Capture output instead of inheriting
|
|
4568
|
+
shell: isWindows,
|
|
4569
|
+
detached: !isWindows,
|
|
4570
|
+
// Detach on non-Windows
|
|
4571
|
+
windowsHide: true
|
|
4572
|
+
});
|
|
4573
|
+
const timeoutId = setTimeout(() => {
|
|
4574
|
+
child.kill();
|
|
4575
|
+
resolve(false);
|
|
4576
|
+
}, TIMEOUT_MS);
|
|
4577
|
+
child.on("close", (code) => {
|
|
4578
|
+
clearTimeout(timeoutId);
|
|
4579
|
+
resolve(code === 0);
|
|
4580
|
+
});
|
|
4581
|
+
child.on("error", () => {
|
|
4582
|
+
clearTimeout(timeoutId);
|
|
4583
|
+
resolve(false);
|
|
4584
|
+
});
|
|
4585
|
+
});
|
|
4586
|
+
if (!upgradeResult) {
|
|
4587
|
+
console.log(
|
|
4588
|
+
chalk3.yellow(
|
|
4589
|
+
`
|
|
4590
|
+
\u26A0 vm0 auto upgrade failed. Please run: ${getManualUpgradeCommand(packageManager)}`
|
|
4591
|
+
)
|
|
4592
|
+
);
|
|
4593
|
+
}
|
|
4594
|
+
}
|
|
4595
|
+
|
|
4377
4596
|
// src/commands/compose/index.ts
|
|
4378
4597
|
function getSecretsFromComposeContent(content) {
|
|
4379
4598
|
const refs = extractVariableReferences(content);
|
|
@@ -4382,7 +4601,7 @@ function getSecretsFromComposeContent(content) {
|
|
|
4382
4601
|
}
|
|
4383
4602
|
async function loadAndValidateConfig(configFile) {
|
|
4384
4603
|
if (!existsSync3(configFile)) {
|
|
4385
|
-
console.error(
|
|
4604
|
+
console.error(chalk4.red(`\u2717 Config file not found: ${configFile}`));
|
|
4386
4605
|
process.exit(1);
|
|
4387
4606
|
}
|
|
4388
4607
|
const content = await readFile4(configFile, "utf8");
|
|
@@ -4390,15 +4609,15 @@ async function loadAndValidateConfig(configFile) {
|
|
|
4390
4609
|
try {
|
|
4391
4610
|
config = parseYaml2(content);
|
|
4392
4611
|
} catch (error) {
|
|
4393
|
-
console.error(
|
|
4612
|
+
console.error(chalk4.red("\u2717 Invalid YAML format"));
|
|
4394
4613
|
if (error instanceof Error) {
|
|
4395
|
-
console.error(
|
|
4614
|
+
console.error(chalk4.dim(` ${error.message}`));
|
|
4396
4615
|
}
|
|
4397
4616
|
process.exit(1);
|
|
4398
4617
|
}
|
|
4399
4618
|
const validation = validateAgentCompose(config);
|
|
4400
4619
|
if (!validation.valid) {
|
|
4401
|
-
console.error(
|
|
4620
|
+
console.error(chalk4.red(`\u2717 ${validation.error}`));
|
|
4402
4621
|
process.exit(1);
|
|
4403
4622
|
}
|
|
4404
4623
|
const cfg = config;
|
|
@@ -4415,13 +4634,13 @@ function checkLegacyImageFormat(config) {
|
|
|
4415
4634
|
const image = agentConfig.image;
|
|
4416
4635
|
if (image) {
|
|
4417
4636
|
console.log(
|
|
4418
|
-
|
|
4637
|
+
chalk4.yellow(
|
|
4419
4638
|
`\u26A0 Agent "${name}": 'image' field is deprecated. Use 'apps' field for pre-installed tools.`
|
|
4420
4639
|
)
|
|
4421
4640
|
);
|
|
4422
4641
|
const warning = getLegacySystemTemplateWarning(image);
|
|
4423
4642
|
if (warning) {
|
|
4424
|
-
console.log(
|
|
4643
|
+
console.log(chalk4.yellow(` ${warning}`));
|
|
4425
4644
|
}
|
|
4426
4645
|
}
|
|
4427
4646
|
}
|
|
@@ -4436,7 +4655,7 @@ async function uploadAssets(agentName, agent, basePath) {
|
|
|
4436
4655
|
agent.framework
|
|
4437
4656
|
);
|
|
4438
4657
|
console.log(
|
|
4439
|
-
|
|
4658
|
+
chalk4.green(
|
|
4440
4659
|
`\u2713 Instructions ${result.action === "deduplicated" ? "(unchanged)" : "uploaded"}: ${result.versionId.slice(0, 8)}`
|
|
4441
4660
|
)
|
|
4442
4661
|
);
|
|
@@ -4445,11 +4664,11 @@ async function uploadAssets(agentName, agent, basePath) {
|
|
|
4445
4664
|
if (agent.skills && Array.isArray(agent.skills)) {
|
|
4446
4665
|
console.log(`Uploading ${agent.skills.length} skill(s)...`);
|
|
4447
4666
|
for (const skillUrl of agent.skills) {
|
|
4448
|
-
console.log(
|
|
4667
|
+
console.log(chalk4.dim(` Downloading: ${skillUrl}`));
|
|
4449
4668
|
const result = await uploadSkill(skillUrl);
|
|
4450
4669
|
skillResults.push(result);
|
|
4451
4670
|
console.log(
|
|
4452
|
-
|
|
4671
|
+
chalk4.green(
|
|
4453
4672
|
` \u2713 Skill ${result.action === "deduplicated" ? "(unchanged)" : "uploaded"}: ${result.skillName} (${result.versionId.slice(0, 8)})`
|
|
4454
4673
|
)
|
|
4455
4674
|
);
|
|
@@ -4500,19 +4719,19 @@ async function displayAndConfirmVariables(variables, options) {
|
|
|
4500
4719
|
}
|
|
4501
4720
|
console.log();
|
|
4502
4721
|
console.log(
|
|
4503
|
-
|
|
4722
|
+
chalk4.bold("Skills require the following environment variables:")
|
|
4504
4723
|
);
|
|
4505
4724
|
console.log();
|
|
4506
4725
|
if (newSecrets.length > 0) {
|
|
4507
|
-
console.log(
|
|
4726
|
+
console.log(chalk4.cyan(" Secrets:"));
|
|
4508
4727
|
for (const [name, skills] of newSecrets) {
|
|
4509
4728
|
const isNew = trulyNewSecrets.includes(name);
|
|
4510
|
-
const newMarker = isNew ?
|
|
4729
|
+
const newMarker = isNew ? chalk4.yellow(" (new)") : "";
|
|
4511
4730
|
console.log(` ${name.padEnd(24)}${newMarker} <- ${skills.join(", ")}`);
|
|
4512
4731
|
}
|
|
4513
4732
|
}
|
|
4514
4733
|
if (newVars.length > 0) {
|
|
4515
|
-
console.log(
|
|
4734
|
+
console.log(chalk4.cyan(" Vars:"));
|
|
4516
4735
|
for (const [name, skills] of newVars) {
|
|
4517
4736
|
console.log(` ${name.padEnd(24)} <- ${skills.join(", ")}`);
|
|
4518
4737
|
}
|
|
@@ -4521,10 +4740,10 @@ async function displayAndConfirmVariables(variables, options) {
|
|
|
4521
4740
|
if (trulyNewSecrets.length > 0 && !options.yes) {
|
|
4522
4741
|
if (!isInteractive()) {
|
|
4523
4742
|
console.error(
|
|
4524
|
-
|
|
4743
|
+
chalk4.red(`\u2717 New secrets detected: ${trulyNewSecrets.join(", ")}`)
|
|
4525
4744
|
);
|
|
4526
4745
|
console.error(
|
|
4527
|
-
|
|
4746
|
+
chalk4.dim(
|
|
4528
4747
|
" Use --yes flag to approve new secrets in non-interactive mode."
|
|
4529
4748
|
)
|
|
4530
4749
|
);
|
|
@@ -4535,7 +4754,7 @@ async function displayAndConfirmVariables(variables, options) {
|
|
|
4535
4754
|
true
|
|
4536
4755
|
);
|
|
4537
4756
|
if (!confirmed) {
|
|
4538
|
-
console.log(
|
|
4757
|
+
console.log(chalk4.yellow("Compose cancelled"));
|
|
4539
4758
|
return false;
|
|
4540
4759
|
}
|
|
4541
4760
|
}
|
|
@@ -4557,64 +4776,71 @@ function mergeSkillVariables(agent, variables) {
|
|
|
4557
4776
|
agent.environment = environment;
|
|
4558
4777
|
}
|
|
4559
4778
|
}
|
|
4560
|
-
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").
|
|
4561
|
-
|
|
4562
|
-
|
|
4563
|
-
|
|
4564
|
-
|
|
4565
|
-
|
|
4566
|
-
|
|
4567
|
-
|
|
4568
|
-
|
|
4569
|
-
|
|
4570
|
-
|
|
4571
|
-
|
|
4572
|
-
|
|
4573
|
-
|
|
4574
|
-
|
|
4575
|
-
|
|
4576
|
-
|
|
4577
|
-
|
|
4578
|
-
|
|
4579
|
-
|
|
4580
|
-
|
|
4581
|
-
|
|
4582
|
-
|
|
4583
|
-
|
|
4584
|
-
console.log(chalk3.green(`\u2713 Compose version exists: ${displayName}`));
|
|
4585
|
-
}
|
|
4586
|
-
console.log(chalk3.dim(` Version: ${shortVersionId}`));
|
|
4587
|
-
console.log();
|
|
4588
|
-
console.log(" Run your agent:");
|
|
4589
|
-
console.log(
|
|
4590
|
-
chalk3.cyan(
|
|
4591
|
-
` vm0 run ${displayName}:${shortVersionId} --artifact-name <artifact> "your prompt"`
|
|
4592
|
-
)
|
|
4593
|
-
);
|
|
4594
|
-
} catch (error) {
|
|
4595
|
-
if (error instanceof Error) {
|
|
4596
|
-
if (error.message.includes("Not authenticated")) {
|
|
4597
|
-
console.error(chalk3.red("\u2717 Not authenticated. Run: vm0 auth login"));
|
|
4779
|
+
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").addOption(new Option("--no-auto-update").hideHelp()).action(
|
|
4780
|
+
async (configFile, options) => {
|
|
4781
|
+
try {
|
|
4782
|
+
const { config, agentName, agent, basePath } = await loadAndValidateConfig(configFile);
|
|
4783
|
+
checkLegacyImageFormat(config);
|
|
4784
|
+
const skillResults = await uploadAssets(agentName, agent, basePath);
|
|
4785
|
+
const environment = agent.environment || {};
|
|
4786
|
+
const variables = await collectSkillVariables(
|
|
4787
|
+
skillResults,
|
|
4788
|
+
environment,
|
|
4789
|
+
agentName
|
|
4790
|
+
);
|
|
4791
|
+
const confirmed = await displayAndConfirmVariables(variables, options);
|
|
4792
|
+
if (!confirmed) {
|
|
4793
|
+
process.exit(0);
|
|
4794
|
+
}
|
|
4795
|
+
mergeSkillVariables(agent, variables);
|
|
4796
|
+
console.log("Uploading compose...");
|
|
4797
|
+
const response = await createOrUpdateCompose({ content: config });
|
|
4798
|
+
const scopeResponse = await getScope();
|
|
4799
|
+
const shortVersionId = response.versionId.slice(0, 8);
|
|
4800
|
+
const displayName = `${scopeResponse.slug}/${response.name}`;
|
|
4801
|
+
if (response.action === "created") {
|
|
4802
|
+
console.log(chalk4.green(`\u2713 Compose created: ${displayName}`));
|
|
4598
4803
|
} else {
|
|
4599
|
-
console.
|
|
4600
|
-
console.error(chalk3.dim(` ${error.message}`));
|
|
4804
|
+
console.log(chalk4.green(`\u2713 Compose version exists: ${displayName}`));
|
|
4601
4805
|
}
|
|
4602
|
-
|
|
4603
|
-
console.
|
|
4806
|
+
console.log(chalk4.dim(` Version: ${shortVersionId}`));
|
|
4807
|
+
console.log();
|
|
4808
|
+
console.log(" Run your agent:");
|
|
4809
|
+
console.log(
|
|
4810
|
+
chalk4.cyan(
|
|
4811
|
+
` vm0 run ${displayName}:${shortVersionId} --artifact-name <artifact> "your prompt"`
|
|
4812
|
+
)
|
|
4813
|
+
);
|
|
4814
|
+
if (options.autoUpdate !== false) {
|
|
4815
|
+
await silentUpgradeAfterCommand("9.12.0");
|
|
4816
|
+
}
|
|
4817
|
+
} catch (error) {
|
|
4818
|
+
if (error instanceof Error) {
|
|
4819
|
+
if (error.message.includes("Not authenticated")) {
|
|
4820
|
+
console.error(
|
|
4821
|
+
chalk4.red("\u2717 Not authenticated. Run: vm0 auth login")
|
|
4822
|
+
);
|
|
4823
|
+
} else {
|
|
4824
|
+
console.error(chalk4.red("\u2717 Failed to create compose"));
|
|
4825
|
+
console.error(chalk4.dim(` ${error.message}`));
|
|
4826
|
+
}
|
|
4827
|
+
} else {
|
|
4828
|
+
console.error(chalk4.red("\u2717 An unexpected error occurred"));
|
|
4829
|
+
}
|
|
4830
|
+
process.exit(1);
|
|
4604
4831
|
}
|
|
4605
|
-
process.exit(1);
|
|
4606
4832
|
}
|
|
4607
|
-
|
|
4833
|
+
);
|
|
4608
4834
|
|
|
4609
4835
|
// src/commands/run/run.ts
|
|
4610
|
-
import { Command as Command8, Option } from "commander";
|
|
4611
|
-
import
|
|
4836
|
+
import { Command as Command8, Option as Option2 } from "commander";
|
|
4837
|
+
import chalk9 from "chalk";
|
|
4612
4838
|
|
|
4613
4839
|
// src/lib/events/event-renderer.ts
|
|
4614
|
-
import
|
|
4840
|
+
import chalk6 from "chalk";
|
|
4615
4841
|
|
|
4616
4842
|
// src/lib/events/tool-formatters.ts
|
|
4617
|
-
import
|
|
4843
|
+
import chalk5 from "chalk";
|
|
4618
4844
|
function pluralize(count, singular, plural) {
|
|
4619
4845
|
return count === 1 ? singular : plural;
|
|
4620
4846
|
}
|
|
@@ -4628,15 +4854,15 @@ function formatToolHeader(data) {
|
|
|
4628
4854
|
return [headline];
|
|
4629
4855
|
}
|
|
4630
4856
|
var toolHeadlineFormatters = {
|
|
4631
|
-
Read: (input) => `Read${
|
|
4632
|
-
Edit: (input) => `Edit${
|
|
4633
|
-
Write: (input) => `Write${
|
|
4634
|
-
Bash: (input) => `Bash${
|
|
4635
|
-
Glob: (input) => `Glob${
|
|
4636
|
-
Grep: (input) => `Grep${
|
|
4637
|
-
Task: (input) => `Task${
|
|
4638
|
-
WebFetch: (input) => `WebFetch${
|
|
4639
|
-
WebSearch: (input) => `WebSearch${
|
|
4857
|
+
Read: (input) => `Read${chalk5.dim(`(${String(input.file_path || "")})`)}`,
|
|
4858
|
+
Edit: (input) => `Edit${chalk5.dim(`(${String(input.file_path || "")})`)}`,
|
|
4859
|
+
Write: (input) => `Write${chalk5.dim(`(${String(input.file_path || "")})`)}`,
|
|
4860
|
+
Bash: (input) => `Bash${chalk5.dim(`(${truncate(String(input.command || ""), 60)})`)}`,
|
|
4861
|
+
Glob: (input) => `Glob${chalk5.dim(`(${String(input.pattern || "")})`)}`,
|
|
4862
|
+
Grep: (input) => `Grep${chalk5.dim(`(${String(input.pattern || "")})`)}`,
|
|
4863
|
+
Task: (input) => `Task${chalk5.dim(`(${truncate(String(input.description || ""), 60)})`)}`,
|
|
4864
|
+
WebFetch: (input) => `WebFetch${chalk5.dim(`(${truncate(String(input.url || ""), 60)})`)}`,
|
|
4865
|
+
WebSearch: (input) => `WebSearch${chalk5.dim(`(${truncate(String(input.query || ""), 60)})`)}`,
|
|
4640
4866
|
TodoWrite: () => "TodoWrite"
|
|
4641
4867
|
};
|
|
4642
4868
|
function getToolHeadline(tool, input) {
|
|
@@ -4669,7 +4895,7 @@ function formatToolResult(toolUse, result, verbose) {
|
|
|
4669
4895
|
}
|
|
4670
4896
|
if (isError) {
|
|
4671
4897
|
const errorMsg = resultText ? truncate(resultText, 80) : "Error";
|
|
4672
|
-
lines.push(`\u2514 \u2717 ${
|
|
4898
|
+
lines.push(`\u2514 \u2717 ${chalk5.dim(errorMsg)}`);
|
|
4673
4899
|
return lines;
|
|
4674
4900
|
}
|
|
4675
4901
|
if (resultText) {
|
|
@@ -4677,23 +4903,23 @@ function formatToolResult(toolUse, result, verbose) {
|
|
|
4677
4903
|
if (verbose) {
|
|
4678
4904
|
for (let i = 0; i < resultLines.length; i++) {
|
|
4679
4905
|
const prefix = i === 0 ? "\u2514 " : " ";
|
|
4680
|
-
lines.push(`${prefix}${
|
|
4906
|
+
lines.push(`${prefix}${chalk5.dim(resultLines[i])}`);
|
|
4681
4907
|
}
|
|
4682
4908
|
} else if (resultLines.length > 0) {
|
|
4683
4909
|
const previewCount = Math.min(3, resultLines.length);
|
|
4684
4910
|
for (let i = 0; i < previewCount; i++) {
|
|
4685
4911
|
const prefix = i === 0 ? "\u2514 " : " ";
|
|
4686
|
-
lines.push(`${prefix}${
|
|
4912
|
+
lines.push(`${prefix}${chalk5.dim(resultLines[i])}`);
|
|
4687
4913
|
}
|
|
4688
4914
|
const remaining = resultLines.length - previewCount;
|
|
4689
4915
|
if (remaining > 0) {
|
|
4690
4916
|
lines.push(
|
|
4691
|
-
` ${
|
|
4917
|
+
` ${chalk5.dim(`\u2026 +${remaining} ${pluralize(remaining, "line", "lines")} (vm0 logs <runId> to see all)`)}`
|
|
4692
4918
|
);
|
|
4693
4919
|
}
|
|
4694
4920
|
}
|
|
4695
4921
|
} else {
|
|
4696
|
-
lines.push(`\u2514 \u2713 ${
|
|
4922
|
+
lines.push(`\u2514 \u2713 ${chalk5.dim("Done")}`);
|
|
4697
4923
|
}
|
|
4698
4924
|
return lines;
|
|
4699
4925
|
}
|
|
@@ -4711,24 +4937,24 @@ function formatReadContent(resultText, verbose) {
|
|
|
4711
4937
|
const displayLines = contentLines.length > 0 ? contentLines : rawLines.filter((line) => line.trim().length > 0);
|
|
4712
4938
|
const totalLines = displayLines.length;
|
|
4713
4939
|
if (totalLines === 0) {
|
|
4714
|
-
lines.push(`\u2514 \u2713 ${
|
|
4940
|
+
lines.push(`\u2514 \u2713 ${chalk5.dim("(empty)")}`);
|
|
4715
4941
|
return lines;
|
|
4716
4942
|
}
|
|
4717
4943
|
if (verbose) {
|
|
4718
4944
|
for (let i = 0; i < displayLines.length; i++) {
|
|
4719
4945
|
const prefix = i === 0 ? "\u2514 " : " ";
|
|
4720
|
-
lines.push(`${prefix}${
|
|
4946
|
+
lines.push(`${prefix}${chalk5.dim(displayLines[i] ?? "")}`);
|
|
4721
4947
|
}
|
|
4722
4948
|
} else {
|
|
4723
4949
|
const previewCount = Math.min(3, totalLines);
|
|
4724
4950
|
for (let i = 0; i < previewCount; i++) {
|
|
4725
4951
|
const prefix = i === 0 ? "\u2514 " : " ";
|
|
4726
|
-
lines.push(`${prefix}${
|
|
4952
|
+
lines.push(`${prefix}${chalk5.dim(displayLines[i] ?? "")}`);
|
|
4727
4953
|
}
|
|
4728
4954
|
const remaining = totalLines - previewCount;
|
|
4729
4955
|
if (remaining > 0) {
|
|
4730
4956
|
lines.push(
|
|
4731
|
-
` ${
|
|
4957
|
+
` ${chalk5.dim(`\u2026 +${remaining} ${pluralize(remaining, "line", "lines")} (vm0 logs <runId> to see all)`)}`
|
|
4732
4958
|
);
|
|
4733
4959
|
}
|
|
4734
4960
|
}
|
|
@@ -4742,18 +4968,18 @@ function formatWritePreview(input, verbose) {
|
|
|
4742
4968
|
if (verbose) {
|
|
4743
4969
|
for (let i = 0; i < contentLines.length; i++) {
|
|
4744
4970
|
const prefix = i === 0 ? "\u23BF " : " ";
|
|
4745
|
-
lines.push(`${prefix}${
|
|
4971
|
+
lines.push(`${prefix}${chalk5.dim(contentLines[i] ?? "")}`);
|
|
4746
4972
|
}
|
|
4747
4973
|
} else {
|
|
4748
4974
|
const previewCount = Math.min(3, totalLines);
|
|
4749
4975
|
for (let i = 0; i < previewCount; i++) {
|
|
4750
4976
|
const prefix = i === 0 ? "\u23BF " : " ";
|
|
4751
|
-
lines.push(`${prefix}${
|
|
4977
|
+
lines.push(`${prefix}${chalk5.dim(contentLines[i] ?? "")}`);
|
|
4752
4978
|
}
|
|
4753
4979
|
const remaining = totalLines - previewCount;
|
|
4754
4980
|
if (remaining > 0) {
|
|
4755
4981
|
lines.push(
|
|
4756
|
-
` ${
|
|
4982
|
+
` ${chalk5.dim(`\u2026 +${remaining} ${pluralize(remaining, "line", "lines")} (vm0 logs <runId> to see all)`)}`
|
|
4757
4983
|
);
|
|
4758
4984
|
}
|
|
4759
4985
|
}
|
|
@@ -4768,34 +4994,34 @@ function formatEditDiff(input, verbose) {
|
|
|
4768
4994
|
const removed = oldLines.length;
|
|
4769
4995
|
const added = newLines.length;
|
|
4770
4996
|
const summary = `Added ${added} ${pluralize(added, "line", "lines")}, removed ${removed} ${pluralize(removed, "line", "lines")}`;
|
|
4771
|
-
lines.push(`\u23BF ${
|
|
4997
|
+
lines.push(`\u23BF ${chalk5.dim(summary)}`);
|
|
4772
4998
|
if (verbose) {
|
|
4773
4999
|
for (const line of oldLines) {
|
|
4774
|
-
lines.push(` - ${
|
|
5000
|
+
lines.push(` - ${chalk5.dim(line)}`);
|
|
4775
5001
|
}
|
|
4776
5002
|
for (const line of newLines) {
|
|
4777
|
-
lines.push(` + ${
|
|
5003
|
+
lines.push(` + ${chalk5.dim(line)}`);
|
|
4778
5004
|
}
|
|
4779
5005
|
} else {
|
|
4780
5006
|
const previewLimit = 3;
|
|
4781
5007
|
const showOld = Math.min(previewLimit, oldLines.length);
|
|
4782
5008
|
const showNew = Math.min(previewLimit, newLines.length);
|
|
4783
5009
|
for (let i = 0; i < showOld; i++) {
|
|
4784
|
-
lines.push(` - ${
|
|
5010
|
+
lines.push(` - ${chalk5.dim(truncate(oldLines[i] ?? "", 60))}`);
|
|
4785
5011
|
}
|
|
4786
5012
|
const remainingOld = oldLines.length - previewLimit;
|
|
4787
5013
|
if (remainingOld > 0) {
|
|
4788
5014
|
lines.push(
|
|
4789
|
-
` ${
|
|
5015
|
+
` ${chalk5.dim(`\u2026 +${remainingOld} ${pluralize(remainingOld, "line", "lines")} (vm0 logs <runId> to see all)`)}`
|
|
4790
5016
|
);
|
|
4791
5017
|
}
|
|
4792
5018
|
for (let i = 0; i < showNew; i++) {
|
|
4793
|
-
lines.push(` + ${
|
|
5019
|
+
lines.push(` + ${chalk5.dim(truncate(newLines[i] ?? "", 60))}`);
|
|
4794
5020
|
}
|
|
4795
5021
|
const remainingNew = newLines.length - previewLimit;
|
|
4796
5022
|
if (remainingNew > 0) {
|
|
4797
5023
|
lines.push(
|
|
4798
|
-
` ${
|
|
5024
|
+
` ${chalk5.dim(`\u2026 +${remainingNew} ${pluralize(remainingNew, "line", "lines")} (vm0 logs <runId> to see all)`)}`
|
|
4799
5025
|
);
|
|
4800
5026
|
}
|
|
4801
5027
|
}
|
|
@@ -4833,12 +5059,12 @@ function getTodoStatusIcon(status) {
|
|
|
4833
5059
|
function formatTodoContent(content, status) {
|
|
4834
5060
|
switch (status) {
|
|
4835
5061
|
case "completed":
|
|
4836
|
-
return
|
|
5062
|
+
return chalk5.dim.strikethrough(content);
|
|
4837
5063
|
case "in_progress":
|
|
4838
5064
|
return content;
|
|
4839
5065
|
case "pending":
|
|
4840
5066
|
default:
|
|
4841
|
-
return
|
|
5067
|
+
return chalk5.dim(content);
|
|
4842
5068
|
}
|
|
4843
5069
|
}
|
|
4844
5070
|
|
|
@@ -4856,12 +5082,12 @@ var EventRenderer = class _EventRenderer {
|
|
|
4856
5082
|
* Called immediately after run is created, before polling events
|
|
4857
5083
|
*/
|
|
4858
5084
|
static renderRunStarted(info) {
|
|
4859
|
-
console.log(
|
|
4860
|
-
console.log(` Run ID: ${
|
|
5085
|
+
console.log(chalk6.bold("\u25B6 Run started"));
|
|
5086
|
+
console.log(` Run ID: ${chalk6.dim(info.runId)}`);
|
|
4861
5087
|
if (info.sandboxId) {
|
|
4862
|
-
console.log(` Sandbox: ${
|
|
5088
|
+
console.log(` Sandbox: ${chalk6.dim(info.sandboxId)}`);
|
|
4863
5089
|
}
|
|
4864
|
-
console.log(
|
|
5090
|
+
console.log(chalk6.dim(` (use "vm0 logs ${info.runId}" to view logs)`));
|
|
4865
5091
|
console.log();
|
|
4866
5092
|
}
|
|
4867
5093
|
/**
|
|
@@ -4899,16 +5125,16 @@ var EventRenderer = class _EventRenderer {
|
|
|
4899
5125
|
*/
|
|
4900
5126
|
static renderRunCompleted(result) {
|
|
4901
5127
|
console.log("");
|
|
4902
|
-
console.log(
|
|
5128
|
+
console.log(chalk6.green("\u2713 Run completed successfully"));
|
|
4903
5129
|
if (result) {
|
|
4904
|
-
console.log(` Checkpoint: ${
|
|
4905
|
-
console.log(` Session: ${
|
|
4906
|
-
console.log(` Conversation: ${
|
|
5130
|
+
console.log(` Checkpoint: ${chalk6.dim(result.checkpointId)}`);
|
|
5131
|
+
console.log(` Session: ${chalk6.dim(result.agentSessionId)}`);
|
|
5132
|
+
console.log(` Conversation: ${chalk6.dim(result.conversationId)}`);
|
|
4907
5133
|
if (result.artifact && Object.keys(result.artifact).length > 0) {
|
|
4908
5134
|
console.log(` Artifact:`);
|
|
4909
5135
|
for (const [name, version] of Object.entries(result.artifact)) {
|
|
4910
5136
|
console.log(
|
|
4911
|
-
` ${name}: ${
|
|
5137
|
+
` ${name}: ${chalk6.dim(_EventRenderer.formatVersion(version))}`
|
|
4912
5138
|
);
|
|
4913
5139
|
}
|
|
4914
5140
|
}
|
|
@@ -4916,7 +5142,7 @@ var EventRenderer = class _EventRenderer {
|
|
|
4916
5142
|
console.log(` Volumes:`);
|
|
4917
5143
|
for (const [name, version] of Object.entries(result.volumes)) {
|
|
4918
5144
|
console.log(
|
|
4919
|
-
` ${name}: ${
|
|
5145
|
+
` ${name}: ${chalk6.dim(_EventRenderer.formatVersion(version))}`
|
|
4920
5146
|
);
|
|
4921
5147
|
}
|
|
4922
5148
|
}
|
|
@@ -4928,10 +5154,10 @@ var EventRenderer = class _EventRenderer {
|
|
|
4928
5154
|
*/
|
|
4929
5155
|
static renderRunFailed(error, runId) {
|
|
4930
5156
|
console.log("");
|
|
4931
|
-
console.log(
|
|
4932
|
-
console.log(` Error: ${
|
|
5157
|
+
console.log(chalk6.red("\u2717 Run failed"));
|
|
5158
|
+
console.log(` Error: ${chalk6.red(error || "Unknown error")}`);
|
|
4933
5159
|
console.log(
|
|
4934
|
-
|
|
5160
|
+
chalk6.dim(` (use "vm0 logs ${runId} --system" to view system logs)`)
|
|
4935
5161
|
);
|
|
4936
5162
|
}
|
|
4937
5163
|
/**
|
|
@@ -5015,13 +5241,13 @@ var EventRenderer = class _EventRenderer {
|
|
|
5015
5241
|
const frameworkStr = String(event.data.framework || "claude-code");
|
|
5016
5242
|
const displayName = isSupportedFramework(frameworkStr) ? getFrameworkDisplayName(frameworkStr) : frameworkStr;
|
|
5017
5243
|
this.frameworkDisplayName = displayName;
|
|
5018
|
-
console.log(prefix +
|
|
5019
|
-
console.log(` Session: ${
|
|
5244
|
+
console.log(prefix + chalk6.bold(`\u25B7 ${displayName} Started`));
|
|
5245
|
+
console.log(` Session: ${chalk6.dim(String(event.data.sessionId || ""))}`);
|
|
5020
5246
|
if (event.data.model) {
|
|
5021
|
-
console.log(` Model: ${
|
|
5247
|
+
console.log(` Model: ${chalk6.dim(String(event.data.model))}`);
|
|
5022
5248
|
}
|
|
5023
5249
|
console.log(
|
|
5024
|
-
` Tools: ${
|
|
5250
|
+
` Tools: ${chalk6.dim(
|
|
5025
5251
|
Array.isArray(event.data.tools) ? event.data.tools.join(", ") : String(event.data.tools || "")
|
|
5026
5252
|
)}`
|
|
5027
5253
|
);
|
|
@@ -5038,18 +5264,18 @@ var EventRenderer = class _EventRenderer {
|
|
|
5038
5264
|
const success = Boolean(event.data.success);
|
|
5039
5265
|
if (success) {
|
|
5040
5266
|
console.log(
|
|
5041
|
-
prefix +
|
|
5267
|
+
prefix + chalk6.bold(`\u25C6 ${this.frameworkDisplayName} Completed`)
|
|
5042
5268
|
);
|
|
5043
5269
|
} else {
|
|
5044
|
-
console.log(prefix +
|
|
5270
|
+
console.log(prefix + chalk6.bold(`\u25C6 ${this.frameworkDisplayName} Failed`));
|
|
5045
5271
|
}
|
|
5046
5272
|
const durationMs = Number(event.data.durationMs || 0);
|
|
5047
5273
|
const durationSec = (durationMs / 1e3).toFixed(1);
|
|
5048
|
-
console.log(` Duration: ${
|
|
5274
|
+
console.log(` Duration: ${chalk6.dim(durationSec + "s")}`);
|
|
5049
5275
|
const cost = Number(event.data.cost || 0);
|
|
5050
|
-
console.log(` Cost: ${
|
|
5276
|
+
console.log(` Cost: ${chalk6.dim("$" + cost.toFixed(4))}`);
|
|
5051
5277
|
const numTurns = Number(event.data.numTurns || 0);
|
|
5052
|
-
console.log(` Turns: ${
|
|
5278
|
+
console.log(` Turns: ${chalk6.dim(String(numTurns))}`);
|
|
5053
5279
|
const usage = event.data.usage;
|
|
5054
5280
|
if (usage && typeof usage === "object") {
|
|
5055
5281
|
const inputTokens = Number(usage.input_tokens || 0);
|
|
@@ -5061,7 +5287,7 @@ var EventRenderer = class _EventRenderer {
|
|
|
5061
5287
|
return String(count);
|
|
5062
5288
|
};
|
|
5063
5289
|
console.log(
|
|
5064
|
-
` Tokens: ${
|
|
5290
|
+
` Tokens: ${chalk6.dim(
|
|
5065
5291
|
`input=${formatTokens(inputTokens)} output=${formatTokens(outputTokens)}`
|
|
5066
5292
|
)}`
|
|
5067
5293
|
);
|
|
@@ -5080,7 +5306,7 @@ var EventRenderer = class _EventRenderer {
|
|
|
5080
5306
|
};
|
|
5081
5307
|
|
|
5082
5308
|
// src/commands/run/shared.ts
|
|
5083
|
-
import
|
|
5309
|
+
import chalk8 from "chalk";
|
|
5084
5310
|
import * as fs5 from "fs";
|
|
5085
5311
|
import { config as dotenvConfig } from "dotenv";
|
|
5086
5312
|
|
|
@@ -5406,7 +5632,7 @@ function parseEvent(rawEvent, framework) {
|
|
|
5406
5632
|
}
|
|
5407
5633
|
|
|
5408
5634
|
// src/lib/events/codex-event-renderer.ts
|
|
5409
|
-
import
|
|
5635
|
+
import chalk7 from "chalk";
|
|
5410
5636
|
var CodexEventRenderer = class {
|
|
5411
5637
|
/**
|
|
5412
5638
|
* Check if an event is a Codex event
|
|
@@ -5453,13 +5679,13 @@ var CodexEventRenderer = class {
|
|
|
5453
5679
|
const cached = event.usage.cached_input_tokens || 0;
|
|
5454
5680
|
const cachedStr = cached ? ` (${cached} cached)` : "";
|
|
5455
5681
|
console.log(
|
|
5456
|
-
"[turn.completed]" +
|
|
5682
|
+
"[turn.completed]" + chalk7.dim(` ${input} in / ${output} out${cachedStr}`)
|
|
5457
5683
|
);
|
|
5458
5684
|
}
|
|
5459
5685
|
}
|
|
5460
5686
|
static renderTurnFailed(event) {
|
|
5461
5687
|
console.log(
|
|
5462
|
-
|
|
5688
|
+
chalk7.red("[turn.failed]") + (event.error ? ` ${event.error}` : "")
|
|
5463
5689
|
);
|
|
5464
5690
|
}
|
|
5465
5691
|
// eslint-disable-next-line complexity -- TODO: refactor complex function
|
|
@@ -5485,15 +5711,15 @@ var CodexEventRenderer = class {
|
|
|
5485
5711
|
if (output) {
|
|
5486
5712
|
const lines = output.split("\n").filter((l) => l.trim());
|
|
5487
5713
|
const preview = lines.slice(0, 3).join("\n ");
|
|
5488
|
-
const more = lines.length > 3 ?
|
|
5714
|
+
const more = lines.length > 3 ? chalk7.dim(` ... (${lines.length - 3} more lines)`) : "";
|
|
5489
5715
|
console.log(
|
|
5490
|
-
"[output]" + (exitCode !== 0 ?
|
|
5716
|
+
"[output]" + (exitCode !== 0 ? chalk7.red(` exit=${exitCode}`) : "")
|
|
5491
5717
|
);
|
|
5492
5718
|
if (preview) {
|
|
5493
5719
|
console.log(" " + preview + more);
|
|
5494
5720
|
}
|
|
5495
5721
|
} else if (exitCode !== 0) {
|
|
5496
|
-
console.log(
|
|
5722
|
+
console.log(chalk7.red("[output]") + chalk7.red(` exit=${exitCode}`));
|
|
5497
5723
|
}
|
|
5498
5724
|
}
|
|
5499
5725
|
return;
|
|
@@ -5503,7 +5729,7 @@ var CodexEventRenderer = class {
|
|
|
5503
5729
|
const icon = c20.kind === "add" ? "+" : c20.kind === "delete" ? "-" : "~";
|
|
5504
5730
|
return `${icon}${c20.path}`;
|
|
5505
5731
|
}).join(", ");
|
|
5506
|
-
console.log(
|
|
5732
|
+
console.log(chalk7.green("[files]") + ` ${summary}`);
|
|
5507
5733
|
return;
|
|
5508
5734
|
}
|
|
5509
5735
|
if (itemType === "file_edit" || itemType === "file_write" || itemType === "file_read") {
|
|
@@ -5516,7 +5742,7 @@ var CodexEventRenderer = class {
|
|
|
5516
5742
|
}
|
|
5517
5743
|
static renderError(event) {
|
|
5518
5744
|
console.log(
|
|
5519
|
-
|
|
5745
|
+
chalk7.red("[error]") + ` ${event.message || event.error || "Unknown error"}`
|
|
5520
5746
|
);
|
|
5521
5747
|
}
|
|
5522
5748
|
};
|
|
@@ -6575,9 +6801,9 @@ async function streamRealtimeEvents(runId, options) {
|
|
|
6575
6801
|
EventRenderer.renderRunFailed(error, rid);
|
|
6576
6802
|
},
|
|
6577
6803
|
onTimeout: (rid) => {
|
|
6578
|
-
console.error(
|
|
6804
|
+
console.error(chalk8.red("\n\u2717 Run timed out"));
|
|
6579
6805
|
console.error(
|
|
6580
|
-
|
|
6806
|
+
chalk8.dim(` (use "vm0 logs ${rid} --system" to view system logs)`)
|
|
6581
6807
|
);
|
|
6582
6808
|
}
|
|
6583
6809
|
});
|
|
@@ -6620,9 +6846,9 @@ async function pollEvents(runId, options) {
|
|
|
6620
6846
|
result = { succeeded: false, runId };
|
|
6621
6847
|
} else if (runStatus === "timeout") {
|
|
6622
6848
|
complete = true;
|
|
6623
|
-
console.error(
|
|
6849
|
+
console.error(chalk8.red("\n\u2717 Run timed out"));
|
|
6624
6850
|
console.error(
|
|
6625
|
-
|
|
6851
|
+
chalk8.dim(` (use "vm0 logs ${runId} --system" to view system logs)`)
|
|
6626
6852
|
);
|
|
6627
6853
|
result = { succeeded: false, runId };
|
|
6628
6854
|
}
|
|
@@ -6636,11 +6862,11 @@ function showNextSteps(result) {
|
|
|
6636
6862
|
const { runId, sessionId, checkpointId } = result;
|
|
6637
6863
|
console.log();
|
|
6638
6864
|
console.log(" View agent logs:");
|
|
6639
|
-
console.log(
|
|
6865
|
+
console.log(chalk8.cyan(` vm0 logs ${runId}`));
|
|
6640
6866
|
if (sessionId) {
|
|
6641
6867
|
console.log(" Continue with session (latest conversation and artifact):");
|
|
6642
6868
|
console.log(
|
|
6643
|
-
|
|
6869
|
+
chalk8.cyan(` vm0 run continue ${sessionId} "your next prompt"`)
|
|
6644
6870
|
);
|
|
6645
6871
|
}
|
|
6646
6872
|
if (checkpointId) {
|
|
@@ -6648,40 +6874,66 @@ function showNextSteps(result) {
|
|
|
6648
6874
|
" Resume from checkpoint (snapshotted conversation and artifact):"
|
|
6649
6875
|
);
|
|
6650
6876
|
console.log(
|
|
6651
|
-
|
|
6877
|
+
chalk8.cyan(` vm0 run resume ${checkpointId} "your next prompt"`)
|
|
6652
6878
|
);
|
|
6653
6879
|
}
|
|
6654
6880
|
}
|
|
6655
6881
|
function handleGenericRunError(error, commandLabel) {
|
|
6656
6882
|
if (error instanceof ApiRequestError && error.code === "concurrent_run_limit_exceeded") {
|
|
6657
|
-
console.error(
|
|
6883
|
+
console.error(chalk8.red(`\u2717 ${commandLabel} failed`));
|
|
6658
6884
|
console.error(
|
|
6659
|
-
|
|
6885
|
+
chalk8.dim(
|
|
6660
6886
|
` ${error.message} Use 'vm0 run list' to view runs, 'vm0 run kill <id>' to cancel.`
|
|
6661
6887
|
)
|
|
6662
6888
|
);
|
|
6663
6889
|
} else {
|
|
6664
|
-
console.error(
|
|
6665
|
-
console.error(
|
|
6890
|
+
console.error(chalk8.red(`\u2717 ${commandLabel} failed`));
|
|
6891
|
+
console.error(chalk8.dim(` ${error.message}`));
|
|
6892
|
+
}
|
|
6893
|
+
}
|
|
6894
|
+
function handleRunError(error, identifier) {
|
|
6895
|
+
if (error instanceof Error) {
|
|
6896
|
+
if (error.message.includes("Not authenticated")) {
|
|
6897
|
+
console.error(chalk8.red("\u2717 Not authenticated. Run: vm0 auth login"));
|
|
6898
|
+
} else if (error.message.includes("Realtime connection failed")) {
|
|
6899
|
+
console.error(chalk8.red("\u2717 Realtime streaming failed"));
|
|
6900
|
+
console.error(chalk8.dim(` ${error.message}`));
|
|
6901
|
+
console.error(chalk8.dim(" Try running without --experimental-realtime"));
|
|
6902
|
+
} else if (error.message.startsWith("Version not found:")) {
|
|
6903
|
+
console.error(chalk8.red(`\u2717 ${error.message}`));
|
|
6904
|
+
console.error(chalk8.dim(" Make sure the version hash is correct"));
|
|
6905
|
+
} else if (error.message.startsWith("Environment file not found:")) {
|
|
6906
|
+
console.error(chalk8.red(`\u2717 ${error.message}`));
|
|
6907
|
+
} else if (error.message.includes("not found")) {
|
|
6908
|
+
console.error(chalk8.red(`\u2717 Agent not found: ${identifier}`));
|
|
6909
|
+
console.error(
|
|
6910
|
+
chalk8.dim(" Make sure you've composed the agent with: vm0 compose")
|
|
6911
|
+
);
|
|
6912
|
+
} else {
|
|
6913
|
+
handleGenericRunError(error, "Run");
|
|
6914
|
+
}
|
|
6915
|
+
} else {
|
|
6916
|
+
console.error(chalk8.red("\u2717 An unexpected error occurred"));
|
|
6666
6917
|
}
|
|
6918
|
+
process.exit(1);
|
|
6667
6919
|
}
|
|
6668
6920
|
function handleResumeOrContinueError(error, commandLabel, resourceId, resourceLabel) {
|
|
6669
6921
|
if (error instanceof Error) {
|
|
6670
6922
|
if (error.message.includes("Not authenticated")) {
|
|
6671
|
-
console.error(
|
|
6923
|
+
console.error(chalk8.red("\u2717 Not authenticated. Run: vm0 auth login"));
|
|
6672
6924
|
} else if (error.message.includes("Realtime connection failed")) {
|
|
6673
|
-
console.error(
|
|
6674
|
-
console.error(
|
|
6675
|
-
console.error(
|
|
6925
|
+
console.error(chalk8.red("\u2717 Realtime streaming failed"));
|
|
6926
|
+
console.error(chalk8.dim(` ${error.message}`));
|
|
6927
|
+
console.error(chalk8.dim(" Try running without --experimental-realtime"));
|
|
6676
6928
|
} else if (error.message.startsWith("Environment file not found:")) {
|
|
6677
|
-
console.error(
|
|
6929
|
+
console.error(chalk8.red(`\u2717 ${error.message}`));
|
|
6678
6930
|
} else if (error.message.includes("not found")) {
|
|
6679
|
-
console.error(
|
|
6931
|
+
console.error(chalk8.red(`\u2717 ${resourceLabel} not found: ${resourceId}`));
|
|
6680
6932
|
} else {
|
|
6681
6933
|
handleGenericRunError(error, commandLabel);
|
|
6682
6934
|
}
|
|
6683
6935
|
} else {
|
|
6684
|
-
console.error(
|
|
6936
|
+
console.error(chalk8.red("\u2717 An unexpected error occurred"));
|
|
6685
6937
|
}
|
|
6686
6938
|
process.exit(1);
|
|
6687
6939
|
}
|
|
@@ -6720,7 +6972,7 @@ var mainRunCommand = new Command8().name("run").description("Run an agent").argu
|
|
|
6720
6972
|
).option(
|
|
6721
6973
|
"--model-provider <type>",
|
|
6722
6974
|
"Override model provider (e.g., anthropic-api-key)"
|
|
6723
|
-
).option("--verbose", "Show full tool inputs and outputs").addOption(new
|
|
6975
|
+
).option("--verbose", "Show full tool inputs and outputs").addOption(new Option2("--debug-no-mock-claude").hideHelp()).addOption(new Option2("--no-auto-update").hideHelp()).action(
|
|
6724
6976
|
async (identifier, prompt, options) => {
|
|
6725
6977
|
try {
|
|
6726
6978
|
const { scope, name, version } = parseIdentifier(identifier);
|
|
@@ -6733,9 +6985,9 @@ var mainRunCommand = new Command8().name("run").description("Run an agent").argu
|
|
|
6733
6985
|
} else {
|
|
6734
6986
|
const compose = await getComposeByName(name, scope);
|
|
6735
6987
|
if (!compose) {
|
|
6736
|
-
console.error(
|
|
6988
|
+
console.error(chalk9.red(`\u2717 Agent not found: ${identifier}`));
|
|
6737
6989
|
console.error(
|
|
6738
|
-
|
|
6990
|
+
chalk9.dim(
|
|
6739
6991
|
" Make sure you've composed the agent with: vm0 compose"
|
|
6740
6992
|
)
|
|
6741
6993
|
);
|
|
@@ -6775,9 +7027,9 @@ var mainRunCommand = new Command8().name("run").description("Run an agent").argu
|
|
|
6775
7027
|
debugNoMockClaude: options.debugNoMockClaude || void 0
|
|
6776
7028
|
});
|
|
6777
7029
|
if (response.status === "failed") {
|
|
6778
|
-
console.error(
|
|
7030
|
+
console.error(chalk9.red("\u2717 Run preparation failed"));
|
|
6779
7031
|
if (response.error) {
|
|
6780
|
-
console.error(
|
|
7032
|
+
console.error(chalk9.dim(` ${response.error}`));
|
|
6781
7033
|
}
|
|
6782
7034
|
process.exit(1);
|
|
6783
7035
|
}
|
|
@@ -6792,44 +7044,18 @@ var mainRunCommand = new Command8().name("run").description("Run an agent").argu
|
|
|
6792
7044
|
process.exit(1);
|
|
6793
7045
|
}
|
|
6794
7046
|
showNextSteps(result);
|
|
6795
|
-
|
|
6796
|
-
|
|
6797
|
-
if (error.message.includes("Not authenticated")) {
|
|
6798
|
-
console.error(
|
|
6799
|
-
chalk8.red("\u2717 Not authenticated. Run: vm0 auth login")
|
|
6800
|
-
);
|
|
6801
|
-
} else if (error.message.includes("Realtime connection failed")) {
|
|
6802
|
-
console.error(chalk8.red("\u2717 Realtime streaming failed"));
|
|
6803
|
-
console.error(chalk8.dim(` ${error.message}`));
|
|
6804
|
-
console.error(
|
|
6805
|
-
chalk8.dim(" Try running without --experimental-realtime")
|
|
6806
|
-
);
|
|
6807
|
-
} else if (error.message.startsWith("Version not found:")) {
|
|
6808
|
-
console.error(chalk8.red(`\u2717 ${error.message}`));
|
|
6809
|
-
console.error(chalk8.dim(" Make sure the version hash is correct"));
|
|
6810
|
-
} else if (error.message.startsWith("Environment file not found:")) {
|
|
6811
|
-
console.error(chalk8.red(`\u2717 ${error.message}`));
|
|
6812
|
-
} else if (error.message.includes("not found")) {
|
|
6813
|
-
console.error(chalk8.red(`\u2717 Agent not found: ${identifier}`));
|
|
6814
|
-
console.error(
|
|
6815
|
-
chalk8.dim(
|
|
6816
|
-
" Make sure you've composed the agent with: vm0 compose"
|
|
6817
|
-
)
|
|
6818
|
-
);
|
|
6819
|
-
} else {
|
|
6820
|
-
handleGenericRunError(error, "Run");
|
|
6821
|
-
}
|
|
6822
|
-
} else {
|
|
6823
|
-
console.error(chalk8.red("\u2717 An unexpected error occurred"));
|
|
7047
|
+
if (options.autoUpdate !== false) {
|
|
7048
|
+
await silentUpgradeAfterCommand("9.12.0");
|
|
6824
7049
|
}
|
|
6825
|
-
|
|
7050
|
+
} catch (error) {
|
|
7051
|
+
handleRunError(error, identifier);
|
|
6826
7052
|
}
|
|
6827
7053
|
}
|
|
6828
7054
|
);
|
|
6829
7055
|
|
|
6830
7056
|
// src/commands/run/resume.ts
|
|
6831
|
-
import { Command as Command9, Option as
|
|
6832
|
-
import
|
|
7057
|
+
import { Command as Command9, Option as Option3 } from "commander";
|
|
7058
|
+
import chalk10 from "chalk";
|
|
6833
7059
|
var resumeCommand = new Command9().name("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(
|
|
6834
7060
|
"--env-file <path>",
|
|
6835
7061
|
"Load environment variables from file (priority: CLI flags > file > env vars)"
|
|
@@ -6854,7 +7080,7 @@ var resumeCommand = new Command9().name("resume").description("Resume an agent r
|
|
|
6854
7080
|
).option(
|
|
6855
7081
|
"--model-provider <type>",
|
|
6856
7082
|
"Override model provider (e.g., anthropic-api-key)"
|
|
6857
|
-
).option("--verbose", "Show full tool inputs and outputs").addOption(new
|
|
7083
|
+
).option("--verbose", "Show full tool inputs and outputs").addOption(new Option3("--debug-no-mock-claude").hideHelp()).action(
|
|
6858
7084
|
async (checkpointId, prompt, options, command) => {
|
|
6859
7085
|
const allOpts = command.optsWithGlobals();
|
|
6860
7086
|
const vars = { ...allOpts.vars, ...options.vars };
|
|
@@ -6862,9 +7088,9 @@ var resumeCommand = new Command9().name("resume").description("Resume an agent r
|
|
|
6862
7088
|
try {
|
|
6863
7089
|
if (!isUUID(checkpointId)) {
|
|
6864
7090
|
console.error(
|
|
6865
|
-
|
|
7091
|
+
chalk10.red(`\u2717 Invalid checkpoint ID format: ${checkpointId}`)
|
|
6866
7092
|
);
|
|
6867
|
-
console.error(
|
|
7093
|
+
console.error(chalk10.dim(" Checkpoint ID must be a valid UUID"));
|
|
6868
7094
|
process.exit(1);
|
|
6869
7095
|
}
|
|
6870
7096
|
const checkpointInfo = await getCheckpoint(checkpointId);
|
|
@@ -6881,9 +7107,9 @@ var resumeCommand = new Command9().name("resume").description("Resume an agent r
|
|
|
6881
7107
|
debugNoMockClaude: options.debugNoMockClaude || allOpts.debugNoMockClaude || void 0
|
|
6882
7108
|
});
|
|
6883
7109
|
if (response.status === "failed") {
|
|
6884
|
-
console.error(
|
|
7110
|
+
console.error(chalk10.red("\u2717 Run preparation failed"));
|
|
6885
7111
|
if (response.error) {
|
|
6886
|
-
console.error(
|
|
7112
|
+
console.error(chalk10.dim(` ${response.error}`));
|
|
6887
7113
|
}
|
|
6888
7114
|
process.exit(1);
|
|
6889
7115
|
}
|
|
@@ -6910,8 +7136,8 @@ var resumeCommand = new Command9().name("resume").description("Resume an agent r
|
|
|
6910
7136
|
);
|
|
6911
7137
|
|
|
6912
7138
|
// src/commands/run/continue.ts
|
|
6913
|
-
import { Command as Command10, Option as
|
|
6914
|
-
import
|
|
7139
|
+
import { Command as Command10, Option as Option4 } from "commander";
|
|
7140
|
+
import chalk11 from "chalk";
|
|
6915
7141
|
var continueCommand = new Command10().name("continue").description(
|
|
6916
7142
|
"Continue an agent run from a session (uses latest artifact version)"
|
|
6917
7143
|
).argument("<agentSessionId>", "Agent session ID to continue from").argument("<prompt>", "Prompt for the continued agent").option(
|
|
@@ -6938,7 +7164,7 @@ var continueCommand = new Command10().name("continue").description(
|
|
|
6938
7164
|
).option(
|
|
6939
7165
|
"--model-provider <type>",
|
|
6940
7166
|
"Override model provider (e.g., anthropic-api-key)"
|
|
6941
|
-
).option("--verbose", "Show full tool inputs and outputs").addOption(new
|
|
7167
|
+
).option("--verbose", "Show full tool inputs and outputs").addOption(new Option4("--debug-no-mock-claude").hideHelp()).action(
|
|
6942
7168
|
async (agentSessionId, prompt, options, command) => {
|
|
6943
7169
|
const allOpts = command.optsWithGlobals();
|
|
6944
7170
|
const vars = { ...allOpts.vars, ...options.vars };
|
|
@@ -6946,9 +7172,9 @@ var continueCommand = new Command10().name("continue").description(
|
|
|
6946
7172
|
try {
|
|
6947
7173
|
if (!isUUID(agentSessionId)) {
|
|
6948
7174
|
console.error(
|
|
6949
|
-
|
|
7175
|
+
chalk11.red(`\u2717 Invalid agent session ID format: ${agentSessionId}`)
|
|
6950
7176
|
);
|
|
6951
|
-
console.error(
|
|
7177
|
+
console.error(chalk11.dim(" Agent session ID must be a valid UUID"));
|
|
6952
7178
|
process.exit(1);
|
|
6953
7179
|
}
|
|
6954
7180
|
const sessionInfo = await getSession(agentSessionId);
|
|
@@ -6965,9 +7191,9 @@ var continueCommand = new Command10().name("continue").description(
|
|
|
6965
7191
|
debugNoMockClaude: options.debugNoMockClaude || allOpts.debugNoMockClaude || void 0
|
|
6966
7192
|
});
|
|
6967
7193
|
if (response.status === "failed") {
|
|
6968
|
-
console.error(
|
|
7194
|
+
console.error(chalk11.red("\u2717 Run preparation failed"));
|
|
6969
7195
|
if (response.error) {
|
|
6970
|
-
console.error(
|
|
7196
|
+
console.error(chalk11.dim(` ${response.error}`));
|
|
6971
7197
|
}
|
|
6972
7198
|
process.exit(1);
|
|
6973
7199
|
}
|
|
@@ -6995,20 +7221,20 @@ var continueCommand = new Command10().name("continue").description(
|
|
|
6995
7221
|
|
|
6996
7222
|
// src/commands/run/list.ts
|
|
6997
7223
|
import { Command as Command11 } from "commander";
|
|
6998
|
-
import
|
|
7224
|
+
import chalk12 from "chalk";
|
|
6999
7225
|
var UUID_LENGTH = 36;
|
|
7000
7226
|
function formatRunStatus(status, width) {
|
|
7001
7227
|
const paddedStatus = width ? status.padEnd(width) : status;
|
|
7002
7228
|
switch (status) {
|
|
7003
7229
|
case "running":
|
|
7004
|
-
return
|
|
7230
|
+
return chalk12.green(paddedStatus);
|
|
7005
7231
|
case "pending":
|
|
7006
|
-
return
|
|
7232
|
+
return chalk12.yellow(paddedStatus);
|
|
7007
7233
|
case "completed":
|
|
7008
|
-
return
|
|
7234
|
+
return chalk12.blue(paddedStatus);
|
|
7009
7235
|
case "failed":
|
|
7010
7236
|
case "timeout":
|
|
7011
|
-
return
|
|
7237
|
+
return chalk12.red(paddedStatus);
|
|
7012
7238
|
default:
|
|
7013
7239
|
return paddedStatus;
|
|
7014
7240
|
}
|
|
@@ -7018,7 +7244,7 @@ var listCommand = new Command11().name("list").alias("ls").description("List act
|
|
|
7018
7244
|
const response = await listRuns({ limit: 100 });
|
|
7019
7245
|
const activeRuns = response.runs;
|
|
7020
7246
|
if (activeRuns.length === 0) {
|
|
7021
|
-
console.log(
|
|
7247
|
+
console.log(chalk12.dim("No active runs"));
|
|
7022
7248
|
return;
|
|
7023
7249
|
}
|
|
7024
7250
|
const agentWidth = Math.max(
|
|
@@ -7032,7 +7258,7 @@ var listCommand = new Command11().name("list").alias("ls").description("List act
|
|
|
7032
7258
|
"STATUS".padEnd(statusWidth),
|
|
7033
7259
|
"CREATED"
|
|
7034
7260
|
].join(" ");
|
|
7035
|
-
console.log(
|
|
7261
|
+
console.log(chalk12.dim(header));
|
|
7036
7262
|
for (const run of activeRuns) {
|
|
7037
7263
|
const row = [
|
|
7038
7264
|
run.id.padEnd(UUID_LENGTH),
|
|
@@ -7043,12 +7269,12 @@ var listCommand = new Command11().name("list").alias("ls").description("List act
|
|
|
7043
7269
|
console.log(row);
|
|
7044
7270
|
}
|
|
7045
7271
|
} catch (error) {
|
|
7046
|
-
console.error(
|
|
7272
|
+
console.error(chalk12.red("\u2717 Failed to list runs"));
|
|
7047
7273
|
if (error instanceof Error) {
|
|
7048
7274
|
if (error.message.includes("Not authenticated")) {
|
|
7049
|
-
console.error(
|
|
7275
|
+
console.error(chalk12.dim(" Run: vm0 auth login"));
|
|
7050
7276
|
} else {
|
|
7051
|
-
console.error(
|
|
7277
|
+
console.error(chalk12.dim(` ${error.message}`));
|
|
7052
7278
|
}
|
|
7053
7279
|
}
|
|
7054
7280
|
process.exit(1);
|
|
@@ -7057,22 +7283,22 @@ var listCommand = new Command11().name("list").alias("ls").description("List act
|
|
|
7057
7283
|
|
|
7058
7284
|
// src/commands/run/kill.ts
|
|
7059
7285
|
import { Command as Command12 } from "commander";
|
|
7060
|
-
import
|
|
7286
|
+
import chalk13 from "chalk";
|
|
7061
7287
|
var killCommand = new Command12().name("kill").description("Kill (cancel) a pending or running run").argument("<run-id>", "Run ID to kill").action(async (runId) => {
|
|
7062
7288
|
try {
|
|
7063
7289
|
await cancelRun(runId);
|
|
7064
|
-
console.log(
|
|
7290
|
+
console.log(chalk13.green(`\u2713 Run ${runId} cancelled`));
|
|
7065
7291
|
} catch (error) {
|
|
7066
|
-
console.error(
|
|
7292
|
+
console.error(chalk13.red("\u2717 Failed to kill run"));
|
|
7067
7293
|
if (error instanceof Error) {
|
|
7068
7294
|
if (error.message.includes("Not authenticated")) {
|
|
7069
|
-
console.error(
|
|
7295
|
+
console.error(chalk13.dim(" Run: vm0 auth login"));
|
|
7070
7296
|
} else if (error.message.includes("not found") || error.message.includes("No such run")) {
|
|
7071
|
-
console.error(
|
|
7297
|
+
console.error(chalk13.dim(` Run not found: ${runId}`));
|
|
7072
7298
|
} else if (error.message.includes("cannot be cancelled")) {
|
|
7073
|
-
console.error(
|
|
7299
|
+
console.error(chalk13.dim(` ${error.message}`));
|
|
7074
7300
|
} else {
|
|
7075
|
-
console.error(
|
|
7301
|
+
console.error(chalk13.dim(` ${error.message}`));
|
|
7076
7302
|
}
|
|
7077
7303
|
}
|
|
7078
7304
|
process.exit(1);
|
|
@@ -7091,7 +7317,7 @@ import { Command as Command19 } from "commander";
|
|
|
7091
7317
|
|
|
7092
7318
|
// src/commands/volume/init.ts
|
|
7093
7319
|
import { Command as Command13 } from "commander";
|
|
7094
|
-
import
|
|
7320
|
+
import chalk14 from "chalk";
|
|
7095
7321
|
import path6 from "path";
|
|
7096
7322
|
|
|
7097
7323
|
// src/lib/storage/storage-utils.ts
|
|
@@ -7149,10 +7375,10 @@ var initCommand = new Command13().name("init").description("Initialize a volume
|
|
|
7149
7375
|
const existingConfig = await readStorageConfig(cwd);
|
|
7150
7376
|
if (existingConfig) {
|
|
7151
7377
|
console.log(
|
|
7152
|
-
|
|
7378
|
+
chalk14.yellow(`Volume already initialized: ${existingConfig.name}`)
|
|
7153
7379
|
);
|
|
7154
7380
|
console.log(
|
|
7155
|
-
|
|
7381
|
+
chalk14.dim(`Config file: ${path6.join(cwd, ".vm0", "storage.yaml")}`)
|
|
7156
7382
|
);
|
|
7157
7383
|
return;
|
|
7158
7384
|
}
|
|
@@ -7161,10 +7387,10 @@ var initCommand = new Command13().name("init").description("Initialize a volume
|
|
|
7161
7387
|
volumeName = options.name;
|
|
7162
7388
|
} else if (!isInteractive()) {
|
|
7163
7389
|
console.error(
|
|
7164
|
-
|
|
7390
|
+
chalk14.red("\u2717 --name flag is required in non-interactive mode")
|
|
7165
7391
|
);
|
|
7166
7392
|
console.error(
|
|
7167
|
-
|
|
7393
|
+
chalk14.dim(" Usage: vm0 volume init --name <volume-name>")
|
|
7168
7394
|
);
|
|
7169
7395
|
process.exit(1);
|
|
7170
7396
|
} else {
|
|
@@ -7180,34 +7406,34 @@ var initCommand = new Command13().name("init").description("Initialize a volume
|
|
|
7180
7406
|
}
|
|
7181
7407
|
);
|
|
7182
7408
|
if (name === void 0) {
|
|
7183
|
-
console.log(
|
|
7409
|
+
console.log(chalk14.dim("Cancelled"));
|
|
7184
7410
|
return;
|
|
7185
7411
|
}
|
|
7186
7412
|
volumeName = name;
|
|
7187
7413
|
}
|
|
7188
7414
|
if (!isValidStorageName(volumeName)) {
|
|
7189
|
-
console.error(
|
|
7415
|
+
console.error(chalk14.red(`\u2717 Invalid volume name: "${volumeName}"`));
|
|
7190
7416
|
console.error(
|
|
7191
|
-
|
|
7417
|
+
chalk14.dim(
|
|
7192
7418
|
" Volume names must be 3-64 characters, lowercase alphanumeric with hyphens"
|
|
7193
7419
|
)
|
|
7194
7420
|
);
|
|
7195
7421
|
console.error(
|
|
7196
|
-
|
|
7422
|
+
chalk14.dim(" Example: my-dataset, user-data-v2, training-set-2024")
|
|
7197
7423
|
);
|
|
7198
7424
|
process.exit(1);
|
|
7199
7425
|
}
|
|
7200
7426
|
await writeStorageConfig(volumeName, cwd);
|
|
7201
|
-
console.log(
|
|
7427
|
+
console.log(chalk14.green(`\u2713 Initialized volume: ${volumeName}`));
|
|
7202
7428
|
console.log(
|
|
7203
|
-
|
|
7429
|
+
chalk14.dim(
|
|
7204
7430
|
` Config saved to ${path6.join(cwd, ".vm0", "storage.yaml")}`
|
|
7205
7431
|
)
|
|
7206
7432
|
);
|
|
7207
7433
|
} catch (error) {
|
|
7208
|
-
console.error(
|
|
7434
|
+
console.error(chalk14.red("\u2717 Failed to initialize volume"));
|
|
7209
7435
|
if (error instanceof Error) {
|
|
7210
|
-
console.error(
|
|
7436
|
+
console.error(chalk14.dim(` ${error.message}`));
|
|
7211
7437
|
}
|
|
7212
7438
|
process.exit(1);
|
|
7213
7439
|
}
|
|
@@ -7215,7 +7441,7 @@ var initCommand = new Command13().name("init").description("Initialize a volume
|
|
|
7215
7441
|
|
|
7216
7442
|
// src/commands/volume/push.ts
|
|
7217
7443
|
import { Command as Command14 } from "commander";
|
|
7218
|
-
import
|
|
7444
|
+
import chalk15 from "chalk";
|
|
7219
7445
|
var pushCommand = new Command14().name("push").description("Push local files to cloud volume").option(
|
|
7220
7446
|
"-f, --force",
|
|
7221
7447
|
"Force upload even if content unchanged (recreate archive)"
|
|
@@ -7224,35 +7450,35 @@ var pushCommand = new Command14().name("push").description("Push local files to
|
|
|
7224
7450
|
const cwd = process.cwd();
|
|
7225
7451
|
const config = await readStorageConfig(cwd);
|
|
7226
7452
|
if (!config) {
|
|
7227
|
-
console.error(
|
|
7228
|
-
console.error(
|
|
7453
|
+
console.error(chalk15.red("\u2717 No volume initialized in this directory"));
|
|
7454
|
+
console.error(chalk15.dim(" Run: vm0 volume init"));
|
|
7229
7455
|
process.exit(1);
|
|
7230
7456
|
}
|
|
7231
7457
|
console.log(`Pushing volume: ${config.name}`);
|
|
7232
7458
|
const result = await directUpload(config.name, "volume", cwd, {
|
|
7233
7459
|
onProgress: (message) => {
|
|
7234
|
-
console.log(
|
|
7460
|
+
console.log(chalk15.dim(message));
|
|
7235
7461
|
},
|
|
7236
7462
|
force: options.force
|
|
7237
7463
|
});
|
|
7238
7464
|
const shortVersion = result.versionId.slice(0, 8);
|
|
7239
7465
|
if (result.empty) {
|
|
7240
|
-
console.log(
|
|
7466
|
+
console.log(chalk15.dim("No files found (empty volume)"));
|
|
7241
7467
|
} else if (result.deduplicated) {
|
|
7242
|
-
console.log(
|
|
7468
|
+
console.log(chalk15.green("\u2713 Content unchanged (deduplicated)"));
|
|
7243
7469
|
} else {
|
|
7244
|
-
console.log(
|
|
7470
|
+
console.log(chalk15.green("\u2713 Upload complete"));
|
|
7245
7471
|
}
|
|
7246
|
-
console.log(
|
|
7247
|
-
console.log(
|
|
7248
|
-
console.log(
|
|
7472
|
+
console.log(chalk15.dim(` Version: ${shortVersion}`));
|
|
7473
|
+
console.log(chalk15.dim(` Files: ${result.fileCount.toLocaleString()}`));
|
|
7474
|
+
console.log(chalk15.dim(` Size: ${formatBytes(result.size)}`));
|
|
7249
7475
|
} catch (error) {
|
|
7250
|
-
console.error(
|
|
7476
|
+
console.error(chalk15.red("\u2717 Push failed"));
|
|
7251
7477
|
if (error instanceof Error) {
|
|
7252
7478
|
if (error.message.includes("Not authenticated")) {
|
|
7253
|
-
console.error(
|
|
7479
|
+
console.error(chalk15.dim(" Run: vm0 auth login"));
|
|
7254
7480
|
} else {
|
|
7255
|
-
console.error(
|
|
7481
|
+
console.error(chalk15.dim(` ${error.message}`));
|
|
7256
7482
|
}
|
|
7257
7483
|
}
|
|
7258
7484
|
process.exit(1);
|
|
@@ -7261,21 +7487,21 @@ var pushCommand = new Command14().name("push").description("Push local files to
|
|
|
7261
7487
|
|
|
7262
7488
|
// src/commands/volume/pull.ts
|
|
7263
7489
|
import { Command as Command15 } from "commander";
|
|
7264
|
-
import
|
|
7490
|
+
import chalk17 from "chalk";
|
|
7265
7491
|
import path7 from "path";
|
|
7266
7492
|
import * as fs6 from "fs";
|
|
7267
7493
|
import * as os4 from "os";
|
|
7268
7494
|
import * as tar3 from "tar";
|
|
7269
7495
|
|
|
7270
7496
|
// src/lib/storage/pull-utils.ts
|
|
7271
|
-
import
|
|
7497
|
+
import chalk16 from "chalk";
|
|
7272
7498
|
async function handleEmptyStorageResponse(cwd) {
|
|
7273
|
-
console.log(
|
|
7499
|
+
console.log(chalk16.dim("Syncing local files..."));
|
|
7274
7500
|
const removedCount = await removeExtraFiles(cwd, /* @__PURE__ */ new Set());
|
|
7275
7501
|
if (removedCount > 0) {
|
|
7276
|
-
console.log(
|
|
7502
|
+
console.log(chalk16.green(`\u2713 Removed ${removedCount} files not in remote`));
|
|
7277
7503
|
}
|
|
7278
|
-
console.log(
|
|
7504
|
+
console.log(chalk16.green("\u2713 Synced (0 files)"));
|
|
7279
7505
|
return { removedCount };
|
|
7280
7506
|
}
|
|
7281
7507
|
|
|
@@ -7285,8 +7511,8 @@ var pullCommand = new Command15().name("pull").description("Pull cloud files to
|
|
|
7285
7511
|
const cwd = process.cwd();
|
|
7286
7512
|
const config = await readStorageConfig(cwd);
|
|
7287
7513
|
if (!config) {
|
|
7288
|
-
console.error(
|
|
7289
|
-
console.error(
|
|
7514
|
+
console.error(chalk17.red("\u2717 No volume initialized in this directory"));
|
|
7515
|
+
console.error(chalk17.dim(" Run: vm0 volume init"));
|
|
7290
7516
|
process.exit(1);
|
|
7291
7517
|
}
|
|
7292
7518
|
if (versionId) {
|
|
@@ -7294,7 +7520,7 @@ var pullCommand = new Command15().name("pull").description("Pull cloud files to
|
|
|
7294
7520
|
} else {
|
|
7295
7521
|
console.log(`Pulling volume: ${config.name}`);
|
|
7296
7522
|
}
|
|
7297
|
-
console.log(
|
|
7523
|
+
console.log(chalk17.dim("Getting download URL..."));
|
|
7298
7524
|
const downloadInfo = await getStorageDownload({
|
|
7299
7525
|
name: config.name,
|
|
7300
7526
|
type: "volume",
|
|
@@ -7308,18 +7534,18 @@ var pullCommand = new Command15().name("pull").description("Pull cloud files to
|
|
|
7308
7534
|
if (!downloadUrl) {
|
|
7309
7535
|
throw new Error("No download URL returned");
|
|
7310
7536
|
}
|
|
7311
|
-
console.log(
|
|
7537
|
+
console.log(chalk17.dim("Downloading from S3..."));
|
|
7312
7538
|
const s3Response = await fetch(downloadUrl);
|
|
7313
7539
|
if (!s3Response.ok) {
|
|
7314
7540
|
throw new Error(`S3 download failed: ${s3Response.status}`);
|
|
7315
7541
|
}
|
|
7316
7542
|
const arrayBuffer = await s3Response.arrayBuffer();
|
|
7317
7543
|
const tarBuffer = Buffer.from(arrayBuffer);
|
|
7318
|
-
console.log(
|
|
7544
|
+
console.log(chalk17.green(`\u2713 Downloaded ${formatBytes(tarBuffer.length)}`));
|
|
7319
7545
|
const tmpDir = fs6.mkdtempSync(path7.join(os4.tmpdir(), "vm0-"));
|
|
7320
7546
|
const tarPath = path7.join(tmpDir, "volume.tar.gz");
|
|
7321
7547
|
await fs6.promises.writeFile(tarPath, tarBuffer);
|
|
7322
|
-
console.log(
|
|
7548
|
+
console.log(chalk17.dim("Syncing local files..."));
|
|
7323
7549
|
const remoteFiles = await listTarFiles(tarPath);
|
|
7324
7550
|
const remoteFilesSet = new Set(
|
|
7325
7551
|
remoteFiles.map((f) => f.replace(/\\/g, "/"))
|
|
@@ -7327,10 +7553,10 @@ var pullCommand = new Command15().name("pull").description("Pull cloud files to
|
|
|
7327
7553
|
const removedCount = await removeExtraFiles(cwd, remoteFilesSet);
|
|
7328
7554
|
if (removedCount > 0) {
|
|
7329
7555
|
console.log(
|
|
7330
|
-
|
|
7556
|
+
chalk17.green(`\u2713 Removed ${removedCount} files not in remote`)
|
|
7331
7557
|
);
|
|
7332
7558
|
}
|
|
7333
|
-
console.log(
|
|
7559
|
+
console.log(chalk17.dim("Extracting files..."));
|
|
7334
7560
|
await tar3.extract({
|
|
7335
7561
|
file: tarPath,
|
|
7336
7562
|
cwd,
|
|
@@ -7338,14 +7564,14 @@ var pullCommand = new Command15().name("pull").description("Pull cloud files to
|
|
|
7338
7564
|
});
|
|
7339
7565
|
await fs6.promises.unlink(tarPath);
|
|
7340
7566
|
await fs6.promises.rmdir(tmpDir);
|
|
7341
|
-
console.log(
|
|
7567
|
+
console.log(chalk17.green(`\u2713 Extracted ${remoteFiles.length} files`));
|
|
7342
7568
|
} catch (error) {
|
|
7343
|
-
console.error(
|
|
7569
|
+
console.error(chalk17.red("\u2717 Pull failed"));
|
|
7344
7570
|
if (error instanceof Error) {
|
|
7345
7571
|
if (error.message.includes("Not authenticated")) {
|
|
7346
|
-
console.error(
|
|
7572
|
+
console.error(chalk17.dim(" Run: vm0 auth login"));
|
|
7347
7573
|
} else {
|
|
7348
|
-
console.error(
|
|
7574
|
+
console.error(chalk17.dim(` ${error.message}`));
|
|
7349
7575
|
}
|
|
7350
7576
|
}
|
|
7351
7577
|
process.exit(1);
|
|
@@ -7354,23 +7580,23 @@ var pullCommand = new Command15().name("pull").description("Pull cloud files to
|
|
|
7354
7580
|
|
|
7355
7581
|
// src/commands/volume/status.ts
|
|
7356
7582
|
import { Command as Command16 } from "commander";
|
|
7357
|
-
import
|
|
7583
|
+
import chalk18 from "chalk";
|
|
7358
7584
|
var statusCommand2 = new Command16().name("status").description("Show status of cloud volume").action(async () => {
|
|
7359
7585
|
try {
|
|
7360
7586
|
const cwd = process.cwd();
|
|
7361
7587
|
const config = await readStorageConfig(cwd);
|
|
7362
7588
|
if (!config) {
|
|
7363
|
-
console.error(
|
|
7364
|
-
console.error(
|
|
7589
|
+
console.error(chalk18.red("\u2717 No volume initialized in this directory"));
|
|
7590
|
+
console.error(chalk18.dim(" Run: vm0 volume init"));
|
|
7365
7591
|
process.exit(1);
|
|
7366
7592
|
}
|
|
7367
7593
|
if (config.type !== "volume") {
|
|
7368
7594
|
console.error(
|
|
7369
|
-
|
|
7595
|
+
chalk18.red(
|
|
7370
7596
|
"\u2717 This directory is initialized as an artifact, not a volume"
|
|
7371
7597
|
)
|
|
7372
7598
|
);
|
|
7373
|
-
console.error(
|
|
7599
|
+
console.error(chalk18.dim(" Use: vm0 artifact status"));
|
|
7374
7600
|
process.exit(1);
|
|
7375
7601
|
}
|
|
7376
7602
|
console.log(`Checking volume: ${config.name}`);
|
|
@@ -7380,25 +7606,25 @@ var statusCommand2 = new Command16().name("status").description("Show status of
|
|
|
7380
7606
|
});
|
|
7381
7607
|
const shortVersion = info.versionId.slice(0, 8);
|
|
7382
7608
|
if ("empty" in info) {
|
|
7383
|
-
console.log(
|
|
7384
|
-
console.log(
|
|
7609
|
+
console.log(chalk18.green("\u2713 Found (empty)"));
|
|
7610
|
+
console.log(chalk18.dim(` Version: ${shortVersion}`));
|
|
7385
7611
|
} else {
|
|
7386
|
-
console.log(
|
|
7387
|
-
console.log(
|
|
7388
|
-
console.log(
|
|
7389
|
-
console.log(
|
|
7612
|
+
console.log(chalk18.green("\u2713 Found"));
|
|
7613
|
+
console.log(chalk18.dim(` Version: ${shortVersion}`));
|
|
7614
|
+
console.log(chalk18.dim(` Files: ${info.fileCount.toLocaleString()}`));
|
|
7615
|
+
console.log(chalk18.dim(` Size: ${formatBytes(info.size)}`));
|
|
7390
7616
|
}
|
|
7391
7617
|
} catch (error) {
|
|
7392
7618
|
if (error instanceof Error && error.message.includes("not found")) {
|
|
7393
|
-
console.error(
|
|
7394
|
-
console.error(
|
|
7619
|
+
console.error(chalk18.red("\u2717 Not found on remote"));
|
|
7620
|
+
console.error(chalk18.dim(" Run: vm0 volume push"));
|
|
7395
7621
|
} else {
|
|
7396
|
-
console.error(
|
|
7622
|
+
console.error(chalk18.red("\u2717 Status check failed"));
|
|
7397
7623
|
if (error instanceof Error) {
|
|
7398
7624
|
if (error.message.includes("Not authenticated")) {
|
|
7399
|
-
console.error(
|
|
7625
|
+
console.error(chalk18.dim(" Run: vm0 auth login"));
|
|
7400
7626
|
} else {
|
|
7401
|
-
console.error(
|
|
7627
|
+
console.error(chalk18.dim(` ${error.message}`));
|
|
7402
7628
|
}
|
|
7403
7629
|
}
|
|
7404
7630
|
}
|
|
@@ -7408,14 +7634,14 @@ var statusCommand2 = new Command16().name("status").description("Show status of
|
|
|
7408
7634
|
|
|
7409
7635
|
// src/commands/volume/list.ts
|
|
7410
7636
|
import { Command as Command17 } from "commander";
|
|
7411
|
-
import
|
|
7637
|
+
import chalk19 from "chalk";
|
|
7412
7638
|
var listCommand2 = new Command17().name("list").alias("ls").description("List all remote volumes").action(async () => {
|
|
7413
7639
|
try {
|
|
7414
7640
|
const items = await listStorages({ type: "volume" });
|
|
7415
7641
|
if (items.length === 0) {
|
|
7416
|
-
console.log(
|
|
7642
|
+
console.log(chalk19.dim("No volumes found"));
|
|
7417
7643
|
console.log(
|
|
7418
|
-
|
|
7644
|
+
chalk19.dim(" Create one with: vm0 volume init && vm0 volume push")
|
|
7419
7645
|
);
|
|
7420
7646
|
return;
|
|
7421
7647
|
}
|
|
@@ -7434,7 +7660,7 @@ var listCommand2 = new Command17().name("list").alias("ls").description("List al
|
|
|
7434
7660
|
"FILES".padStart(filesWidth),
|
|
7435
7661
|
"UPDATED"
|
|
7436
7662
|
].join(" ");
|
|
7437
|
-
console.log(
|
|
7663
|
+
console.log(chalk19.dim(header));
|
|
7438
7664
|
for (const item of items) {
|
|
7439
7665
|
const row = [
|
|
7440
7666
|
item.name.padEnd(nameWidth),
|
|
@@ -7445,12 +7671,12 @@ var listCommand2 = new Command17().name("list").alias("ls").description("List al
|
|
|
7445
7671
|
console.log(row);
|
|
7446
7672
|
}
|
|
7447
7673
|
} catch (error) {
|
|
7448
|
-
console.error(
|
|
7674
|
+
console.error(chalk19.red("\u2717 Failed to list volumes"));
|
|
7449
7675
|
if (error instanceof Error) {
|
|
7450
7676
|
if (error.message.includes("Not authenticated")) {
|
|
7451
|
-
console.error(
|
|
7677
|
+
console.error(chalk19.dim(" Run: vm0 auth login"));
|
|
7452
7678
|
} else {
|
|
7453
|
-
console.error(
|
|
7679
|
+
console.error(chalk19.dim(` ${error.message}`));
|
|
7454
7680
|
}
|
|
7455
7681
|
}
|
|
7456
7682
|
process.exit(1);
|
|
@@ -7459,10 +7685,10 @@ var listCommand2 = new Command17().name("list").alias("ls").description("List al
|
|
|
7459
7685
|
|
|
7460
7686
|
// src/commands/volume/clone.ts
|
|
7461
7687
|
import { Command as Command18 } from "commander";
|
|
7462
|
-
import
|
|
7688
|
+
import chalk21 from "chalk";
|
|
7463
7689
|
|
|
7464
7690
|
// src/lib/storage/clone-utils.ts
|
|
7465
|
-
import
|
|
7691
|
+
import chalk20 from "chalk";
|
|
7466
7692
|
import path8 from "path";
|
|
7467
7693
|
import * as fs7 from "fs";
|
|
7468
7694
|
import * as os5 from "os";
|
|
@@ -7472,18 +7698,18 @@ async function cloneStorage(name, type, destination, options = {}) {
|
|
|
7472
7698
|
if (fs7.existsSync(destination)) {
|
|
7473
7699
|
throw new Error(`Directory "${destination}" already exists`);
|
|
7474
7700
|
}
|
|
7475
|
-
console.log(
|
|
7701
|
+
console.log(chalk20.dim(`Checking remote ${typeLabel}...`));
|
|
7476
7702
|
const downloadInfo = await getStorageDownload({
|
|
7477
7703
|
name,
|
|
7478
7704
|
type,
|
|
7479
7705
|
version: options.version
|
|
7480
7706
|
});
|
|
7481
|
-
console.log(
|
|
7707
|
+
console.log(chalk20.dim(`Creating directory: ${destination}/`));
|
|
7482
7708
|
await fs7.promises.mkdir(destination, { recursive: true });
|
|
7483
7709
|
if ("empty" in downloadInfo) {
|
|
7484
7710
|
await writeStorageConfig(name, destination, type);
|
|
7485
|
-
console.log(
|
|
7486
|
-
console.log(
|
|
7711
|
+
console.log(chalk20.green(`\u2713 Cloned empty ${typeLabel}: ${name}`));
|
|
7712
|
+
console.log(chalk20.dim(`\u2713 Initialized .vm0/storage.yaml`));
|
|
7487
7713
|
return {
|
|
7488
7714
|
success: true,
|
|
7489
7715
|
fileCount: 0,
|
|
@@ -7495,7 +7721,7 @@ async function cloneStorage(name, type, destination, options = {}) {
|
|
|
7495
7721
|
if (!downloadUrl) {
|
|
7496
7722
|
throw new Error("No download URL returned");
|
|
7497
7723
|
}
|
|
7498
|
-
console.log(
|
|
7724
|
+
console.log(chalk20.dim("Downloading from S3..."));
|
|
7499
7725
|
const s3Response = await fetch(downloadUrl);
|
|
7500
7726
|
if (!s3Response.ok) {
|
|
7501
7727
|
await fs7.promises.rm(destination, { recursive: true, force: true });
|
|
@@ -7503,12 +7729,12 @@ async function cloneStorage(name, type, destination, options = {}) {
|
|
|
7503
7729
|
}
|
|
7504
7730
|
const arrayBuffer = await s3Response.arrayBuffer();
|
|
7505
7731
|
const tarBuffer = Buffer.from(arrayBuffer);
|
|
7506
|
-
console.log(
|
|
7732
|
+
console.log(chalk20.green(`\u2713 Downloaded ${formatBytes(tarBuffer.length)}`));
|
|
7507
7733
|
const tmpDir = fs7.mkdtempSync(path8.join(os5.tmpdir(), "vm0-clone-"));
|
|
7508
7734
|
const tarPath = path8.join(tmpDir, "archive.tar.gz");
|
|
7509
7735
|
await fs7.promises.writeFile(tarPath, tarBuffer);
|
|
7510
7736
|
const files = await listTarFiles(tarPath);
|
|
7511
|
-
console.log(
|
|
7737
|
+
console.log(chalk20.dim("Extracting files..."));
|
|
7512
7738
|
await tar4.extract({
|
|
7513
7739
|
file: tarPath,
|
|
7514
7740
|
cwd: destination,
|
|
@@ -7516,9 +7742,9 @@ async function cloneStorage(name, type, destination, options = {}) {
|
|
|
7516
7742
|
});
|
|
7517
7743
|
await fs7.promises.unlink(tarPath);
|
|
7518
7744
|
await fs7.promises.rmdir(tmpDir);
|
|
7519
|
-
console.log(
|
|
7745
|
+
console.log(chalk20.green(`\u2713 Extracted ${files.length} files`));
|
|
7520
7746
|
await writeStorageConfig(name, destination, type);
|
|
7521
|
-
console.log(
|
|
7747
|
+
console.log(chalk20.green(`\u2713 Initialized .vm0/storage.yaml`));
|
|
7522
7748
|
return {
|
|
7523
7749
|
success: true,
|
|
7524
7750
|
fileCount: downloadInfo.fileCount,
|
|
@@ -7533,17 +7759,17 @@ var cloneCommand = new Command18().name("clone").description("Clone a remote vol
|
|
|
7533
7759
|
const targetDir = destination || name;
|
|
7534
7760
|
console.log(`Cloning volume: ${name}`);
|
|
7535
7761
|
const result = await cloneStorage(name, "volume", targetDir);
|
|
7536
|
-
console.log(
|
|
7762
|
+
console.log(chalk21.green(`
|
|
7537
7763
|
\u2713 Successfully cloned volume: ${name}`));
|
|
7538
|
-
console.log(
|
|
7539
|
-
console.log(
|
|
7764
|
+
console.log(chalk21.dim(` Location: ${targetDir}/`));
|
|
7765
|
+
console.log(chalk21.dim(` Version: ${result.versionId.slice(0, 8)}`));
|
|
7540
7766
|
} catch (error) {
|
|
7541
|
-
console.error(
|
|
7767
|
+
console.error(chalk21.red("\u2717 Clone failed"));
|
|
7542
7768
|
if (error instanceof Error) {
|
|
7543
7769
|
if (error.message.includes("Not authenticated")) {
|
|
7544
|
-
console.error(
|
|
7770
|
+
console.error(chalk21.dim(" Run: vm0 auth login"));
|
|
7545
7771
|
} else {
|
|
7546
|
-
console.error(
|
|
7772
|
+
console.error(chalk21.dim(` ${error.message}`));
|
|
7547
7773
|
}
|
|
7548
7774
|
}
|
|
7549
7775
|
process.exit(1);
|
|
@@ -7558,7 +7784,7 @@ import { Command as Command26 } from "commander";
|
|
|
7558
7784
|
|
|
7559
7785
|
// src/commands/artifact/init.ts
|
|
7560
7786
|
import { Command as Command20 } from "commander";
|
|
7561
|
-
import
|
|
7787
|
+
import chalk22 from "chalk";
|
|
7562
7788
|
import path9 from "path";
|
|
7563
7789
|
var initCommand2 = new Command20().name("init").description("Initialize an artifact in the current directory").option(
|
|
7564
7790
|
"-n, --name <name>",
|
|
@@ -7571,24 +7797,24 @@ var initCommand2 = new Command20().name("init").description("Initialize an artif
|
|
|
7571
7797
|
if (existingConfig) {
|
|
7572
7798
|
if (existingConfig.type === "artifact") {
|
|
7573
7799
|
console.log(
|
|
7574
|
-
|
|
7800
|
+
chalk22.yellow(
|
|
7575
7801
|
`Artifact already initialized: ${existingConfig.name}`
|
|
7576
7802
|
)
|
|
7577
7803
|
);
|
|
7578
7804
|
} else {
|
|
7579
7805
|
console.log(
|
|
7580
|
-
|
|
7806
|
+
chalk22.yellow(
|
|
7581
7807
|
`Directory already initialized as volume: ${existingConfig.name}`
|
|
7582
7808
|
)
|
|
7583
7809
|
);
|
|
7584
7810
|
console.log(
|
|
7585
|
-
|
|
7811
|
+
chalk22.dim(
|
|
7586
7812
|
" To change type, delete .vm0/storage.yaml and reinitialize"
|
|
7587
7813
|
)
|
|
7588
7814
|
);
|
|
7589
7815
|
}
|
|
7590
7816
|
console.log(
|
|
7591
|
-
|
|
7817
|
+
chalk22.dim(`Config file: ${path9.join(cwd, ".vm0", "storage.yaml")}`)
|
|
7592
7818
|
);
|
|
7593
7819
|
return;
|
|
7594
7820
|
}
|
|
@@ -7597,10 +7823,10 @@ var initCommand2 = new Command20().name("init").description("Initialize an artif
|
|
|
7597
7823
|
artifactName = options.name;
|
|
7598
7824
|
} else if (!isInteractive()) {
|
|
7599
7825
|
console.error(
|
|
7600
|
-
|
|
7826
|
+
chalk22.red("\u2717 --name flag is required in non-interactive mode")
|
|
7601
7827
|
);
|
|
7602
7828
|
console.error(
|
|
7603
|
-
|
|
7829
|
+
chalk22.dim(" Usage: vm0 artifact init --name <artifact-name>")
|
|
7604
7830
|
);
|
|
7605
7831
|
process.exit(1);
|
|
7606
7832
|
} else {
|
|
@@ -7616,34 +7842,34 @@ var initCommand2 = new Command20().name("init").description("Initialize an artif
|
|
|
7616
7842
|
}
|
|
7617
7843
|
);
|
|
7618
7844
|
if (name === void 0) {
|
|
7619
|
-
console.log(
|
|
7845
|
+
console.log(chalk22.dim("Cancelled"));
|
|
7620
7846
|
return;
|
|
7621
7847
|
}
|
|
7622
7848
|
artifactName = name;
|
|
7623
7849
|
}
|
|
7624
7850
|
if (!isValidStorageName(artifactName)) {
|
|
7625
|
-
console.error(
|
|
7851
|
+
console.error(chalk22.red(`\u2717 Invalid artifact name: "${artifactName}"`));
|
|
7626
7852
|
console.error(
|
|
7627
|
-
|
|
7853
|
+
chalk22.dim(
|
|
7628
7854
|
" Artifact names must be 3-64 characters, lowercase alphanumeric with hyphens"
|
|
7629
7855
|
)
|
|
7630
7856
|
);
|
|
7631
7857
|
console.error(
|
|
7632
|
-
|
|
7858
|
+
chalk22.dim(" Example: my-project, user-workspace, code-artifact")
|
|
7633
7859
|
);
|
|
7634
7860
|
process.exit(1);
|
|
7635
7861
|
}
|
|
7636
7862
|
await writeStorageConfig(artifactName, cwd, "artifact");
|
|
7637
|
-
console.log(
|
|
7863
|
+
console.log(chalk22.green(`\u2713 Initialized artifact: ${artifactName}`));
|
|
7638
7864
|
console.log(
|
|
7639
|
-
|
|
7865
|
+
chalk22.dim(
|
|
7640
7866
|
` Config saved to ${path9.join(cwd, ".vm0", "storage.yaml")}`
|
|
7641
7867
|
)
|
|
7642
7868
|
);
|
|
7643
7869
|
} catch (error) {
|
|
7644
|
-
console.error(
|
|
7870
|
+
console.error(chalk22.red("\u2717 Failed to initialize artifact"));
|
|
7645
7871
|
if (error instanceof Error) {
|
|
7646
|
-
console.error(
|
|
7872
|
+
console.error(chalk22.dim(` ${error.message}`));
|
|
7647
7873
|
}
|
|
7648
7874
|
process.exit(1);
|
|
7649
7875
|
}
|
|
@@ -7651,7 +7877,7 @@ var initCommand2 = new Command20().name("init").description("Initialize an artif
|
|
|
7651
7877
|
|
|
7652
7878
|
// src/commands/artifact/push.ts
|
|
7653
7879
|
import { Command as Command21 } from "commander";
|
|
7654
|
-
import
|
|
7880
|
+
import chalk23 from "chalk";
|
|
7655
7881
|
var pushCommand2 = new Command21().name("push").description("Push local files to cloud artifact").option(
|
|
7656
7882
|
"-f, --force",
|
|
7657
7883
|
"Force upload even if content unchanged (recreate archive)"
|
|
@@ -7660,41 +7886,41 @@ var pushCommand2 = new Command21().name("push").description("Push local files to
|
|
|
7660
7886
|
const cwd = process.cwd();
|
|
7661
7887
|
const config = await readStorageConfig(cwd);
|
|
7662
7888
|
if (!config) {
|
|
7663
|
-
console.error(
|
|
7664
|
-
console.error(
|
|
7889
|
+
console.error(chalk23.red("\u2717 No artifact initialized in this directory"));
|
|
7890
|
+
console.error(chalk23.dim(" Run: vm0 artifact init"));
|
|
7665
7891
|
process.exit(1);
|
|
7666
7892
|
}
|
|
7667
7893
|
if (config.type !== "artifact") {
|
|
7668
7894
|
console.error(
|
|
7669
|
-
|
|
7895
|
+
chalk23.red(
|
|
7670
7896
|
`\u2717 This directory is initialized as a volume, not an artifact`
|
|
7671
7897
|
)
|
|
7672
7898
|
);
|
|
7673
|
-
console.error(
|
|
7899
|
+
console.error(chalk23.dim(" Use: vm0 volume push"));
|
|
7674
7900
|
process.exit(1);
|
|
7675
7901
|
}
|
|
7676
7902
|
console.log(`Pushing artifact: ${config.name}`);
|
|
7677
7903
|
const result = await directUpload(config.name, "artifact", cwd, {
|
|
7678
7904
|
onProgress: (message) => {
|
|
7679
|
-
console.log(
|
|
7905
|
+
console.log(chalk23.dim(message));
|
|
7680
7906
|
},
|
|
7681
7907
|
force: options.force
|
|
7682
7908
|
});
|
|
7683
7909
|
const shortVersion = result.versionId.slice(0, 8);
|
|
7684
7910
|
if (result.empty) {
|
|
7685
|
-
console.log(
|
|
7911
|
+
console.log(chalk23.dim("No files found (empty artifact)"));
|
|
7686
7912
|
} else if (result.deduplicated) {
|
|
7687
|
-
console.log(
|
|
7913
|
+
console.log(chalk23.green("\u2713 Content unchanged (deduplicated)"));
|
|
7688
7914
|
} else {
|
|
7689
|
-
console.log(
|
|
7915
|
+
console.log(chalk23.green("\u2713 Upload complete"));
|
|
7690
7916
|
}
|
|
7691
|
-
console.log(
|
|
7692
|
-
console.log(
|
|
7693
|
-
console.log(
|
|
7917
|
+
console.log(chalk23.dim(` Version: ${shortVersion}`));
|
|
7918
|
+
console.log(chalk23.dim(` Files: ${result.fileCount.toLocaleString()}`));
|
|
7919
|
+
console.log(chalk23.dim(` Size: ${formatBytes(result.size)}`));
|
|
7694
7920
|
} catch (error) {
|
|
7695
|
-
console.error(
|
|
7921
|
+
console.error(chalk23.red("\u2717 Push failed"));
|
|
7696
7922
|
if (error instanceof Error) {
|
|
7697
|
-
console.error(
|
|
7923
|
+
console.error(chalk23.dim(` ${error.message}`));
|
|
7698
7924
|
}
|
|
7699
7925
|
process.exit(1);
|
|
7700
7926
|
}
|
|
@@ -7702,7 +7928,7 @@ var pushCommand2 = new Command21().name("push").description("Push local files to
|
|
|
7702
7928
|
|
|
7703
7929
|
// src/commands/artifact/pull.ts
|
|
7704
7930
|
import { Command as Command22 } from "commander";
|
|
7705
|
-
import
|
|
7931
|
+
import chalk24 from "chalk";
|
|
7706
7932
|
import path10 from "path";
|
|
7707
7933
|
import * as fs8 from "fs";
|
|
7708
7934
|
import * as os6 from "os";
|
|
@@ -7712,17 +7938,17 @@ var pullCommand2 = new Command22().name("pull").description("Pull cloud artifact
|
|
|
7712
7938
|
const cwd = process.cwd();
|
|
7713
7939
|
const config = await readStorageConfig(cwd);
|
|
7714
7940
|
if (!config) {
|
|
7715
|
-
console.error(
|
|
7716
|
-
console.error(
|
|
7941
|
+
console.error(chalk24.red("\u2717 No artifact initialized in this directory"));
|
|
7942
|
+
console.error(chalk24.dim(" Run: vm0 artifact init"));
|
|
7717
7943
|
process.exit(1);
|
|
7718
7944
|
}
|
|
7719
7945
|
if (config.type !== "artifact") {
|
|
7720
7946
|
console.error(
|
|
7721
|
-
|
|
7947
|
+
chalk24.red(
|
|
7722
7948
|
`\u2717 This directory is initialized as a volume, not an artifact`
|
|
7723
7949
|
)
|
|
7724
7950
|
);
|
|
7725
|
-
console.error(
|
|
7951
|
+
console.error(chalk24.dim(" Use: vm0 volume pull"));
|
|
7726
7952
|
process.exit(1);
|
|
7727
7953
|
}
|
|
7728
7954
|
if (versionId) {
|
|
@@ -7730,7 +7956,7 @@ var pullCommand2 = new Command22().name("pull").description("Pull cloud artifact
|
|
|
7730
7956
|
} else {
|
|
7731
7957
|
console.log(`Pulling artifact: ${config.name}`);
|
|
7732
7958
|
}
|
|
7733
|
-
console.log(
|
|
7959
|
+
console.log(chalk24.dim("Getting download URL..."));
|
|
7734
7960
|
const downloadInfo = await getStorageDownload({
|
|
7735
7961
|
name: config.name,
|
|
7736
7962
|
type: "artifact",
|
|
@@ -7744,18 +7970,18 @@ var pullCommand2 = new Command22().name("pull").description("Pull cloud artifact
|
|
|
7744
7970
|
if (!downloadUrl) {
|
|
7745
7971
|
throw new Error("No download URL returned");
|
|
7746
7972
|
}
|
|
7747
|
-
console.log(
|
|
7973
|
+
console.log(chalk24.dim("Downloading from S3..."));
|
|
7748
7974
|
const s3Response = await fetch(downloadUrl);
|
|
7749
7975
|
if (!s3Response.ok) {
|
|
7750
7976
|
throw new Error(`S3 download failed: ${s3Response.status}`);
|
|
7751
7977
|
}
|
|
7752
7978
|
const arrayBuffer = await s3Response.arrayBuffer();
|
|
7753
7979
|
const tarBuffer = Buffer.from(arrayBuffer);
|
|
7754
|
-
console.log(
|
|
7980
|
+
console.log(chalk24.green(`\u2713 Downloaded ${formatBytes(tarBuffer.length)}`));
|
|
7755
7981
|
const tmpDir = fs8.mkdtempSync(path10.join(os6.tmpdir(), "vm0-"));
|
|
7756
7982
|
const tarPath = path10.join(tmpDir, "artifact.tar.gz");
|
|
7757
7983
|
await fs8.promises.writeFile(tarPath, tarBuffer);
|
|
7758
|
-
console.log(
|
|
7984
|
+
console.log(chalk24.dim("Syncing local files..."));
|
|
7759
7985
|
const remoteFiles = await listTarFiles(tarPath);
|
|
7760
7986
|
const remoteFilesSet = new Set(
|
|
7761
7987
|
remoteFiles.map((f) => f.replace(/\\/g, "/"))
|
|
@@ -7763,10 +7989,10 @@ var pullCommand2 = new Command22().name("pull").description("Pull cloud artifact
|
|
|
7763
7989
|
const removedCount = await removeExtraFiles(cwd, remoteFilesSet);
|
|
7764
7990
|
if (removedCount > 0) {
|
|
7765
7991
|
console.log(
|
|
7766
|
-
|
|
7992
|
+
chalk24.green(`\u2713 Removed ${removedCount} files not in remote`)
|
|
7767
7993
|
);
|
|
7768
7994
|
}
|
|
7769
|
-
console.log(
|
|
7995
|
+
console.log(chalk24.dim("Extracting files..."));
|
|
7770
7996
|
await tar5.extract({
|
|
7771
7997
|
file: tarPath,
|
|
7772
7998
|
cwd,
|
|
@@ -7774,11 +8000,11 @@ var pullCommand2 = new Command22().name("pull").description("Pull cloud artifact
|
|
|
7774
8000
|
});
|
|
7775
8001
|
await fs8.promises.unlink(tarPath);
|
|
7776
8002
|
await fs8.promises.rmdir(tmpDir);
|
|
7777
|
-
console.log(
|
|
8003
|
+
console.log(chalk24.green(`\u2713 Extracted ${remoteFiles.length} files`));
|
|
7778
8004
|
} catch (error) {
|
|
7779
|
-
console.error(
|
|
8005
|
+
console.error(chalk24.red("\u2717 Pull failed"));
|
|
7780
8006
|
if (error instanceof Error) {
|
|
7781
|
-
console.error(
|
|
8007
|
+
console.error(chalk24.dim(` ${error.message}`));
|
|
7782
8008
|
}
|
|
7783
8009
|
process.exit(1);
|
|
7784
8010
|
}
|
|
@@ -7786,23 +8012,23 @@ var pullCommand2 = new Command22().name("pull").description("Pull cloud artifact
|
|
|
7786
8012
|
|
|
7787
8013
|
// src/commands/artifact/status.ts
|
|
7788
8014
|
import { Command as Command23 } from "commander";
|
|
7789
|
-
import
|
|
8015
|
+
import chalk25 from "chalk";
|
|
7790
8016
|
var statusCommand3 = new Command23().name("status").description("Show status of cloud artifact").action(async () => {
|
|
7791
8017
|
try {
|
|
7792
8018
|
const cwd = process.cwd();
|
|
7793
8019
|
const config = await readStorageConfig(cwd);
|
|
7794
8020
|
if (!config) {
|
|
7795
|
-
console.error(
|
|
7796
|
-
console.error(
|
|
8021
|
+
console.error(chalk25.red("\u2717 No artifact initialized in this directory"));
|
|
8022
|
+
console.error(chalk25.dim(" Run: vm0 artifact init"));
|
|
7797
8023
|
process.exit(1);
|
|
7798
8024
|
}
|
|
7799
8025
|
if (config.type !== "artifact") {
|
|
7800
8026
|
console.error(
|
|
7801
|
-
|
|
8027
|
+
chalk25.red(
|
|
7802
8028
|
"\u2717 This directory is initialized as a volume, not an artifact"
|
|
7803
8029
|
)
|
|
7804
8030
|
);
|
|
7805
|
-
console.error(
|
|
8031
|
+
console.error(chalk25.dim(" Use: vm0 volume status"));
|
|
7806
8032
|
process.exit(1);
|
|
7807
8033
|
}
|
|
7808
8034
|
console.log(`Checking artifact: ${config.name}`);
|
|
@@ -7812,22 +8038,22 @@ var statusCommand3 = new Command23().name("status").description("Show status of
|
|
|
7812
8038
|
});
|
|
7813
8039
|
const shortVersion = info.versionId.slice(0, 8);
|
|
7814
8040
|
if ("empty" in info) {
|
|
7815
|
-
console.log(
|
|
7816
|
-
console.log(
|
|
8041
|
+
console.log(chalk25.green("\u2713 Found (empty)"));
|
|
8042
|
+
console.log(chalk25.dim(` Version: ${shortVersion}`));
|
|
7817
8043
|
} else {
|
|
7818
|
-
console.log(
|
|
7819
|
-
console.log(
|
|
7820
|
-
console.log(
|
|
7821
|
-
console.log(
|
|
8044
|
+
console.log(chalk25.green("\u2713 Found"));
|
|
8045
|
+
console.log(chalk25.dim(` Version: ${shortVersion}`));
|
|
8046
|
+
console.log(chalk25.dim(` Files: ${info.fileCount.toLocaleString()}`));
|
|
8047
|
+
console.log(chalk25.dim(` Size: ${formatBytes(info.size)}`));
|
|
7822
8048
|
}
|
|
7823
8049
|
} catch (error) {
|
|
7824
8050
|
if (error instanceof Error && error.message.includes("not found")) {
|
|
7825
|
-
console.error(
|
|
7826
|
-
console.error(
|
|
8051
|
+
console.error(chalk25.red("\u2717 Not found on remote"));
|
|
8052
|
+
console.error(chalk25.dim(" Run: vm0 artifact push"));
|
|
7827
8053
|
} else {
|
|
7828
|
-
console.error(
|
|
8054
|
+
console.error(chalk25.red("\u2717 Status check failed"));
|
|
7829
8055
|
if (error instanceof Error) {
|
|
7830
|
-
console.error(
|
|
8056
|
+
console.error(chalk25.dim(` ${error.message}`));
|
|
7831
8057
|
}
|
|
7832
8058
|
}
|
|
7833
8059
|
process.exit(1);
|
|
@@ -7836,14 +8062,14 @@ var statusCommand3 = new Command23().name("status").description("Show status of
|
|
|
7836
8062
|
|
|
7837
8063
|
// src/commands/artifact/list.ts
|
|
7838
8064
|
import { Command as Command24 } from "commander";
|
|
7839
|
-
import
|
|
8065
|
+
import chalk26 from "chalk";
|
|
7840
8066
|
var listCommand3 = new Command24().name("list").alias("ls").description("List all remote artifacts").action(async () => {
|
|
7841
8067
|
try {
|
|
7842
8068
|
const items = await listStorages({ type: "artifact" });
|
|
7843
8069
|
if (items.length === 0) {
|
|
7844
|
-
console.log(
|
|
8070
|
+
console.log(chalk26.dim("No artifacts found"));
|
|
7845
8071
|
console.log(
|
|
7846
|
-
|
|
8072
|
+
chalk26.dim(
|
|
7847
8073
|
" Create one with: vm0 artifact init && vm0 artifact push"
|
|
7848
8074
|
)
|
|
7849
8075
|
);
|
|
@@ -7864,7 +8090,7 @@ var listCommand3 = new Command24().name("list").alias("ls").description("List al
|
|
|
7864
8090
|
"FILES".padStart(filesWidth),
|
|
7865
8091
|
"UPDATED"
|
|
7866
8092
|
].join(" ");
|
|
7867
|
-
console.log(
|
|
8093
|
+
console.log(chalk26.dim(header));
|
|
7868
8094
|
for (const item of items) {
|
|
7869
8095
|
const row = [
|
|
7870
8096
|
item.name.padEnd(nameWidth),
|
|
@@ -7875,12 +8101,12 @@ var listCommand3 = new Command24().name("list").alias("ls").description("List al
|
|
|
7875
8101
|
console.log(row);
|
|
7876
8102
|
}
|
|
7877
8103
|
} catch (error) {
|
|
7878
|
-
console.error(
|
|
8104
|
+
console.error(chalk26.red("\u2717 Failed to list artifacts"));
|
|
7879
8105
|
if (error instanceof Error) {
|
|
7880
8106
|
if (error.message.includes("Not authenticated")) {
|
|
7881
|
-
console.error(
|
|
8107
|
+
console.error(chalk26.dim(" Run: vm0 auth login"));
|
|
7882
8108
|
} else {
|
|
7883
|
-
console.error(
|
|
8109
|
+
console.error(chalk26.dim(` ${error.message}`));
|
|
7884
8110
|
}
|
|
7885
8111
|
}
|
|
7886
8112
|
process.exit(1);
|
|
@@ -7889,23 +8115,23 @@ var listCommand3 = new Command24().name("list").alias("ls").description("List al
|
|
|
7889
8115
|
|
|
7890
8116
|
// src/commands/artifact/clone.ts
|
|
7891
8117
|
import { Command as Command25 } from "commander";
|
|
7892
|
-
import
|
|
8118
|
+
import chalk27 from "chalk";
|
|
7893
8119
|
var cloneCommand2 = new Command25().name("clone").description("Clone a remote artifact to local directory (latest version)").argument("<name>", "Artifact name to clone").argument("[destination]", "Destination directory (default: artifact name)").action(async (name, destination) => {
|
|
7894
8120
|
try {
|
|
7895
8121
|
const targetDir = destination || name;
|
|
7896
8122
|
console.log(`Cloning artifact: ${name}`);
|
|
7897
8123
|
const result = await cloneStorage(name, "artifact", targetDir);
|
|
7898
|
-
console.log(
|
|
8124
|
+
console.log(chalk27.green(`
|
|
7899
8125
|
\u2713 Successfully cloned artifact: ${name}`));
|
|
7900
|
-
console.log(
|
|
7901
|
-
console.log(
|
|
8126
|
+
console.log(chalk27.dim(` Location: ${targetDir}/`));
|
|
8127
|
+
console.log(chalk27.dim(` Version: ${result.versionId.slice(0, 8)}`));
|
|
7902
8128
|
} catch (error) {
|
|
7903
|
-
console.error(
|
|
8129
|
+
console.error(chalk27.red("\u2717 Clone failed"));
|
|
7904
8130
|
if (error instanceof Error) {
|
|
7905
8131
|
if (error.message.includes("Not authenticated")) {
|
|
7906
|
-
console.error(
|
|
8132
|
+
console.error(chalk27.dim(" Run: vm0 auth login"));
|
|
7907
8133
|
} else {
|
|
7908
|
-
console.error(
|
|
8134
|
+
console.error(chalk27.dim(` ${error.message}`));
|
|
7909
8135
|
}
|
|
7910
8136
|
}
|
|
7911
8137
|
process.exit(1);
|
|
@@ -7916,7 +8142,7 @@ var cloneCommand2 = new Command25().name("clone").description("Clone a remote ar
|
|
|
7916
8142
|
var artifactCommand = new Command26().name("artifact").description("Manage artifacts (specified at run, versioned after run)").addCommand(initCommand2).addCommand(pushCommand2).addCommand(pullCommand2).addCommand(statusCommand3).addCommand(listCommand3).addCommand(cloneCommand2);
|
|
7917
8143
|
|
|
7918
8144
|
// src/commands/cook/cook.ts
|
|
7919
|
-
import { Command as Command27, Option as
|
|
8145
|
+
import { Command as Command27, Option as Option5 } from "commander";
|
|
7920
8146
|
import chalk29 from "chalk";
|
|
7921
8147
|
import { readFile as readFile7, mkdir as mkdir6 } from "fs/promises";
|
|
7922
8148
|
import { existsSync as existsSync9 } from "fs";
|
|
@@ -7924,145 +8150,6 @@ import path11 from "path";
|
|
|
7924
8150
|
import { parse as parseYaml4 } from "yaml";
|
|
7925
8151
|
import { config as dotenvConfig2 } from "dotenv";
|
|
7926
8152
|
|
|
7927
|
-
// src/lib/utils/update-checker.ts
|
|
7928
|
-
import { spawn } from "child_process";
|
|
7929
|
-
import chalk27 from "chalk";
|
|
7930
|
-
var PACKAGE_NAME = "@vm0/cli";
|
|
7931
|
-
var NPM_REGISTRY_URL = `https://registry.npmjs.org/${encodeURIComponent(PACKAGE_NAME)}/latest`;
|
|
7932
|
-
var TIMEOUT_MS = 5e3;
|
|
7933
|
-
function detectPackageManager() {
|
|
7934
|
-
const execPath = process.argv[1] ?? "";
|
|
7935
|
-
if (execPath.includes("pnpm")) {
|
|
7936
|
-
return "pnpm";
|
|
7937
|
-
}
|
|
7938
|
-
if (execPath.includes("/.bun/") || execPath.includes("/bun/")) {
|
|
7939
|
-
return "bun";
|
|
7940
|
-
}
|
|
7941
|
-
if (execPath.includes("/.yarn/") || execPath.includes("/yarn/")) {
|
|
7942
|
-
return "yarn";
|
|
7943
|
-
}
|
|
7944
|
-
if (execPath.includes("/usr/local/") || execPath.includes("/.nvm/") || execPath.includes("/.fnm/") || execPath.includes("/.volta/") || execPath.includes("/.nodenv/") || execPath.includes("/.n/") || execPath.includes("/node_modules/") || execPath.includes("\\npm\\") || // Windows: AppData\Roaming\npm
|
|
7945
|
-
execPath.includes("\\nodejs\\")) {
|
|
7946
|
-
return "npm";
|
|
7947
|
-
}
|
|
7948
|
-
return "unknown";
|
|
7949
|
-
}
|
|
7950
|
-
function isAutoUpgradeSupported(pm) {
|
|
7951
|
-
return pm === "npm" || pm === "pnpm";
|
|
7952
|
-
}
|
|
7953
|
-
function getManualUpgradeCommand(pm) {
|
|
7954
|
-
switch (pm) {
|
|
7955
|
-
case "bun":
|
|
7956
|
-
return `bun add -g ${PACKAGE_NAME}@latest`;
|
|
7957
|
-
case "yarn":
|
|
7958
|
-
return `yarn global add ${PACKAGE_NAME}@latest`;
|
|
7959
|
-
case "pnpm":
|
|
7960
|
-
return `pnpm add -g ${PACKAGE_NAME}@latest`;
|
|
7961
|
-
case "npm":
|
|
7962
|
-
return `npm install -g ${PACKAGE_NAME}@latest`;
|
|
7963
|
-
case "unknown":
|
|
7964
|
-
return `npm install -g ${PACKAGE_NAME}@latest`;
|
|
7965
|
-
}
|
|
7966
|
-
}
|
|
7967
|
-
function escapeForShell(str) {
|
|
7968
|
-
return `"${str.replace(/"/g, '\\"')}"`;
|
|
7969
|
-
}
|
|
7970
|
-
function buildRerunCommand(prompt) {
|
|
7971
|
-
if (prompt) {
|
|
7972
|
-
return `vm0 cook ${escapeForShell(prompt)}`;
|
|
7973
|
-
}
|
|
7974
|
-
return "vm0 cook";
|
|
7975
|
-
}
|
|
7976
|
-
async function getLatestVersion() {
|
|
7977
|
-
try {
|
|
7978
|
-
const controller = new AbortController();
|
|
7979
|
-
const timeoutId = setTimeout(() => controller.abort(), TIMEOUT_MS);
|
|
7980
|
-
const response = await fetch(NPM_REGISTRY_URL, {
|
|
7981
|
-
signal: controller.signal
|
|
7982
|
-
});
|
|
7983
|
-
clearTimeout(timeoutId);
|
|
7984
|
-
if (!response.ok) {
|
|
7985
|
-
return null;
|
|
7986
|
-
}
|
|
7987
|
-
const json = await response.json();
|
|
7988
|
-
return json.version ?? null;
|
|
7989
|
-
} catch {
|
|
7990
|
-
return null;
|
|
7991
|
-
}
|
|
7992
|
-
}
|
|
7993
|
-
function performUpgrade(packageManager) {
|
|
7994
|
-
return new Promise((resolve) => {
|
|
7995
|
-
const isWindows = process.platform === "win32";
|
|
7996
|
-
const command = isWindows ? `${packageManager}.cmd` : packageManager;
|
|
7997
|
-
const args = packageManager === "pnpm" ? ["add", "-g", `${PACKAGE_NAME}@latest`] : ["install", "-g", `${PACKAGE_NAME}@latest`];
|
|
7998
|
-
const child = spawn(command, args, {
|
|
7999
|
-
stdio: "inherit",
|
|
8000
|
-
shell: isWindows
|
|
8001
|
-
});
|
|
8002
|
-
child.on("close", (code) => {
|
|
8003
|
-
resolve(code === 0);
|
|
8004
|
-
});
|
|
8005
|
-
child.on("error", () => {
|
|
8006
|
-
resolve(false);
|
|
8007
|
-
});
|
|
8008
|
-
});
|
|
8009
|
-
}
|
|
8010
|
-
async function checkAndUpgrade(currentVersion, prompt) {
|
|
8011
|
-
const latestVersion = await getLatestVersion();
|
|
8012
|
-
if (latestVersion === null) {
|
|
8013
|
-
console.log(chalk27.yellow("Warning: Could not check for updates"));
|
|
8014
|
-
console.log();
|
|
8015
|
-
return false;
|
|
8016
|
-
}
|
|
8017
|
-
if (latestVersion === currentVersion) {
|
|
8018
|
-
return false;
|
|
8019
|
-
}
|
|
8020
|
-
console.log(chalk27.yellow("vm0 is currently in Early Access (EA)."));
|
|
8021
|
-
console.log(
|
|
8022
|
-
chalk27.yellow(
|
|
8023
|
-
`Current version: ${currentVersion} -> Latest version: ${latestVersion}`
|
|
8024
|
-
)
|
|
8025
|
-
);
|
|
8026
|
-
console.log(
|
|
8027
|
-
chalk27.yellow(
|
|
8028
|
-
"Please always use the latest version for best compatibility."
|
|
8029
|
-
)
|
|
8030
|
-
);
|
|
8031
|
-
console.log();
|
|
8032
|
-
const packageManager = detectPackageManager();
|
|
8033
|
-
if (!isAutoUpgradeSupported(packageManager)) {
|
|
8034
|
-
if (packageManager === "unknown") {
|
|
8035
|
-
console.log(
|
|
8036
|
-
chalk27.yellow("Could not detect your package manager for auto-upgrade.")
|
|
8037
|
-
);
|
|
8038
|
-
} else {
|
|
8039
|
-
console.log(
|
|
8040
|
-
chalk27.yellow(`Auto-upgrade is not supported for ${packageManager}.`)
|
|
8041
|
-
);
|
|
8042
|
-
}
|
|
8043
|
-
console.log(chalk27.yellow("Please upgrade manually:"));
|
|
8044
|
-
console.log(chalk27.cyan(` ${getManualUpgradeCommand(packageManager)}`));
|
|
8045
|
-
console.log();
|
|
8046
|
-
return false;
|
|
8047
|
-
}
|
|
8048
|
-
console.log(`Upgrading via ${packageManager}...`);
|
|
8049
|
-
const success = await performUpgrade(packageManager);
|
|
8050
|
-
if (success) {
|
|
8051
|
-
console.log(chalk27.green(`Upgraded to ${latestVersion}`));
|
|
8052
|
-
console.log();
|
|
8053
|
-
console.log("To continue, run:");
|
|
8054
|
-
console.log(chalk27.cyan(` ${buildRerunCommand(prompt)}`));
|
|
8055
|
-
return true;
|
|
8056
|
-
}
|
|
8057
|
-
console.log();
|
|
8058
|
-
console.log(chalk27.red("Upgrade failed. Please run manually:"));
|
|
8059
|
-
console.log(chalk27.cyan(` ${getManualUpgradeCommand(packageManager)}`));
|
|
8060
|
-
console.log();
|
|
8061
|
-
console.log("Then re-run:");
|
|
8062
|
-
console.log(chalk27.cyan(` ${buildRerunCommand(prompt)}`));
|
|
8063
|
-
return true;
|
|
8064
|
-
}
|
|
8065
|
-
|
|
8066
8153
|
// src/lib/domain/cook-state.ts
|
|
8067
8154
|
import { homedir as homedir2 } from "os";
|
|
8068
8155
|
import { join as join6 } from "path";
|
|
@@ -8461,10 +8548,10 @@ async function runAgent(agentName, artifactDir, prompt, cwd, options) {
|
|
|
8461
8548
|
var cookAction = new Command27().name("cook").description("Quick start: prepare, compose and run agent from vm0.yaml").argument("[prompt]", "Prompt for the agent").option(
|
|
8462
8549
|
"--env-file <path>",
|
|
8463
8550
|
"Load environment variables from file (priority: CLI flags > file > env vars)"
|
|
8464
|
-
).option("-y, --yes", "Skip confirmation prompts").option("-v, --verbose", "Show full tool inputs and outputs").addOption(new
|
|
8551
|
+
).option("-y, --yes", "Skip confirmation prompts").option("-v, --verbose", "Show full tool inputs and outputs").addOption(new Option5("--debug-no-mock-claude").hideHelp()).addOption(new Option5("--no-auto-update").hideHelp()).action(
|
|
8465
8552
|
async (prompt, options) => {
|
|
8466
8553
|
if (!options.noAutoUpdate) {
|
|
8467
|
-
const shouldExit = await checkAndUpgrade("9.
|
|
8554
|
+
const shouldExit = await checkAndUpgrade("9.12.0", prompt);
|
|
8468
8555
|
if (shouldExit) {
|
|
8469
8556
|
process.exit(0);
|
|
8470
8557
|
}
|
|
@@ -8540,7 +8627,7 @@ var logsCommand = new Command28().name("logs").description("View logs from the l
|
|
|
8540
8627
|
);
|
|
8541
8628
|
|
|
8542
8629
|
// src/commands/cook/continue.ts
|
|
8543
|
-
import { Command as Command29, Option as
|
|
8630
|
+
import { Command as Command29, Option as Option6 } from "commander";
|
|
8544
8631
|
import chalk31 from "chalk";
|
|
8545
8632
|
import path12 from "path";
|
|
8546
8633
|
var continueCommand2 = new Command29().name("continue").description(
|
|
@@ -8548,7 +8635,7 @@ var continueCommand2 = new Command29().name("continue").description(
|
|
|
8548
8635
|
).argument("<prompt>", "Prompt for the continued agent").option(
|
|
8549
8636
|
"--env-file <path>",
|
|
8550
8637
|
"Load environment variables from file (priority: CLI flags > file > env vars)"
|
|
8551
|
-
).option("-v, --verbose", "Show full tool inputs and outputs").addOption(new
|
|
8638
|
+
).option("-v, --verbose", "Show full tool inputs and outputs").addOption(new Option6("--debug-no-mock-claude").hideHelp()).action(
|
|
8552
8639
|
async (prompt, options) => {
|
|
8553
8640
|
const state = await loadCookState();
|
|
8554
8641
|
if (!state.lastSessionId) {
|
|
@@ -8593,7 +8680,7 @@ var continueCommand2 = new Command29().name("continue").description(
|
|
|
8593
8680
|
);
|
|
8594
8681
|
|
|
8595
8682
|
// src/commands/cook/resume.ts
|
|
8596
|
-
import { Command as Command30, Option as
|
|
8683
|
+
import { Command as Command30, Option as Option7 } from "commander";
|
|
8597
8684
|
import chalk32 from "chalk";
|
|
8598
8685
|
import path13 from "path";
|
|
8599
8686
|
var resumeCommand2 = new Command30().name("resume").description(
|
|
@@ -8601,7 +8688,7 @@ var resumeCommand2 = new Command30().name("resume").description(
|
|
|
8601
8688
|
).argument("<prompt>", "Prompt for the resumed agent").option(
|
|
8602
8689
|
"--env-file <path>",
|
|
8603
8690
|
"Load environment variables from file (priority: CLI flags > file > env vars)"
|
|
8604
|
-
).option("-v, --verbose", "Show full tool inputs and outputs").addOption(new
|
|
8691
|
+
).option("-v, --verbose", "Show full tool inputs and outputs").addOption(new Option7("--debug-no-mock-claude").hideHelp()).action(
|
|
8605
8692
|
async (prompt, options) => {
|
|
8606
8693
|
const state = await loadCookState();
|
|
8607
8694
|
if (!state.lastCheckpointId) {
|
|
@@ -10842,7 +10929,8 @@ var listCommand7 = new Command51().name("list").alias("ls").description("List al
|
|
|
10842
10929
|
console.log(` ${chalk50.cyan(framework)}:`);
|
|
10843
10930
|
for (const provider of providers) {
|
|
10844
10931
|
const defaultTag = provider.isDefault ? chalk50.green(" (default)") : "";
|
|
10845
|
-
|
|
10932
|
+
const modelTag = provider.selectedModel ? chalk50.dim(` [${provider.selectedModel}]`) : "";
|
|
10933
|
+
console.log(` ${provider.type}${defaultTag}${modelTag}`);
|
|
10846
10934
|
console.log(
|
|
10847
10935
|
chalk50.dim(
|
|
10848
10936
|
` Updated: ${new Date(provider.updatedAt).toLocaleString()}`
|
|
@@ -10878,122 +10966,184 @@ var providerChoices = Object.entries(MODEL_PROVIDER_TYPES).map(
|
|
|
10878
10966
|
value: type
|
|
10879
10967
|
})
|
|
10880
10968
|
);
|
|
10969
|
+
function validateProviderType(typeStr) {
|
|
10970
|
+
if (!Object.keys(MODEL_PROVIDER_TYPES).includes(typeStr)) {
|
|
10971
|
+
console.error(chalk51.red(`\u2717 Invalid type "${typeStr}"`));
|
|
10972
|
+
console.log();
|
|
10973
|
+
console.log("Valid types:");
|
|
10974
|
+
for (const [t, config] of Object.entries(MODEL_PROVIDER_TYPES)) {
|
|
10975
|
+
console.log(` ${chalk51.cyan(t)} - ${config.label}`);
|
|
10976
|
+
}
|
|
10977
|
+
process.exit(1);
|
|
10978
|
+
}
|
|
10979
|
+
return typeStr;
|
|
10980
|
+
}
|
|
10981
|
+
function validateModel(type, modelStr) {
|
|
10982
|
+
const models = getModels(type);
|
|
10983
|
+
if (models && !models.includes(modelStr)) {
|
|
10984
|
+
console.error(chalk51.red(`\u2717 Invalid model "${modelStr}"`));
|
|
10985
|
+
console.log();
|
|
10986
|
+
console.log("Valid models:");
|
|
10987
|
+
for (const m of models) {
|
|
10988
|
+
console.log(` ${chalk51.cyan(m)}`);
|
|
10989
|
+
}
|
|
10990
|
+
process.exit(1);
|
|
10991
|
+
}
|
|
10992
|
+
return modelStr;
|
|
10993
|
+
}
|
|
10994
|
+
function handleNonInteractiveMode(options) {
|
|
10995
|
+
const type = validateProviderType(options.type);
|
|
10996
|
+
let selectedModel;
|
|
10997
|
+
if (options.model) {
|
|
10998
|
+
selectedModel = validateModel(type, options.model);
|
|
10999
|
+
} else if (hasModelSelection(type)) {
|
|
11000
|
+
selectedModel = getDefaultModel(type);
|
|
11001
|
+
}
|
|
11002
|
+
return { type, credential: options.credential, selectedModel };
|
|
11003
|
+
}
|
|
11004
|
+
async function promptForModelSelection(type) {
|
|
11005
|
+
if (!hasModelSelection(type)) {
|
|
11006
|
+
return void 0;
|
|
11007
|
+
}
|
|
11008
|
+
const models = getModels(type) ?? [];
|
|
11009
|
+
const defaultModel = getDefaultModel(type);
|
|
11010
|
+
const modelChoices = models.map((model) => ({
|
|
11011
|
+
title: model === defaultModel ? `${model} (Recommended)` : model,
|
|
11012
|
+
value: model
|
|
11013
|
+
}));
|
|
11014
|
+
const modelResponse = await prompts2(
|
|
11015
|
+
{
|
|
11016
|
+
type: "select",
|
|
11017
|
+
name: "model",
|
|
11018
|
+
message: "Select model:",
|
|
11019
|
+
choices: modelChoices
|
|
11020
|
+
},
|
|
11021
|
+
{ onCancel: () => process.exit(0) }
|
|
11022
|
+
);
|
|
11023
|
+
return modelResponse.model;
|
|
11024
|
+
}
|
|
11025
|
+
async function handleInteractiveMode() {
|
|
11026
|
+
if (!isInteractive()) {
|
|
11027
|
+
console.error(chalk51.red("\u2717 Interactive mode requires a TTY"));
|
|
11028
|
+
console.log();
|
|
11029
|
+
console.log("Use non-interactive mode:");
|
|
11030
|
+
console.log(
|
|
11031
|
+
chalk51.cyan(
|
|
11032
|
+
' vm0 model-provider setup --type <type> --credential "<value>"'
|
|
11033
|
+
)
|
|
11034
|
+
);
|
|
11035
|
+
process.exit(1);
|
|
11036
|
+
}
|
|
11037
|
+
const typeResponse = await prompts2(
|
|
11038
|
+
{
|
|
11039
|
+
type: "select",
|
|
11040
|
+
name: "type",
|
|
11041
|
+
message: "Select provider type:",
|
|
11042
|
+
choices: providerChoices
|
|
11043
|
+
},
|
|
11044
|
+
{ onCancel: () => process.exit(0) }
|
|
11045
|
+
);
|
|
11046
|
+
const type = typeResponse.type;
|
|
11047
|
+
const checkResult = await checkModelProviderCredential(type);
|
|
11048
|
+
if (checkResult.exists && checkResult.currentType === "user") {
|
|
11049
|
+
const convertResponse = await prompts2(
|
|
11050
|
+
{
|
|
11051
|
+
type: "confirm",
|
|
11052
|
+
name: "convert",
|
|
11053
|
+
message: `Credential "${checkResult.credentialName}" already exists. Convert to model provider?`,
|
|
11054
|
+
initial: true
|
|
11055
|
+
},
|
|
11056
|
+
{ onCancel: () => process.exit(0) }
|
|
11057
|
+
);
|
|
11058
|
+
if (convertResponse.convert) {
|
|
11059
|
+
const provider = await convertModelProviderCredential(type);
|
|
11060
|
+
const defaultNote = provider.isDefault ? ` (default for ${provider.framework})` : "";
|
|
11061
|
+
console.log(
|
|
11062
|
+
chalk51.green(
|
|
11063
|
+
`\u2713 Converted "${checkResult.credentialName}" to model provider${defaultNote}`
|
|
11064
|
+
)
|
|
11065
|
+
);
|
|
11066
|
+
return null;
|
|
11067
|
+
}
|
|
11068
|
+
console.log(chalk51.dim("Aborted"));
|
|
11069
|
+
process.exit(0);
|
|
11070
|
+
}
|
|
11071
|
+
const config = MODEL_PROVIDER_TYPES[type];
|
|
11072
|
+
console.log();
|
|
11073
|
+
console.log(chalk51.dim(config.helpText));
|
|
11074
|
+
console.log();
|
|
11075
|
+
const credentialResponse = await prompts2(
|
|
11076
|
+
{
|
|
11077
|
+
type: "password",
|
|
11078
|
+
name: "credential",
|
|
11079
|
+
message: `Enter your ${config.credentialLabel}:`,
|
|
11080
|
+
validate: (value) => value.length > 0 || `${config.credentialLabel} is required`
|
|
11081
|
+
},
|
|
11082
|
+
{ onCancel: () => process.exit(0) }
|
|
11083
|
+
);
|
|
11084
|
+
const credential = credentialResponse.credential;
|
|
11085
|
+
const selectedModel = await promptForModelSelection(type);
|
|
11086
|
+
return { type, credential, selectedModel };
|
|
11087
|
+
}
|
|
11088
|
+
function handleSetupError2(error) {
|
|
11089
|
+
if (error instanceof Error) {
|
|
11090
|
+
if (error.message.includes("already exists")) {
|
|
11091
|
+
console.error(chalk51.red(`\u2717 ${error.message}`));
|
|
11092
|
+
console.log();
|
|
11093
|
+
console.log("To convert the existing credential, run:");
|
|
11094
|
+
console.log(chalk51.cyan(" vm0 model-provider setup --convert"));
|
|
11095
|
+
} else if (error.message.includes("Not authenticated")) {
|
|
11096
|
+
console.error(chalk51.red("\u2717 Not authenticated. Run: vm0 auth login"));
|
|
11097
|
+
} else {
|
|
11098
|
+
console.error(chalk51.red(`\u2717 ${error.message}`));
|
|
11099
|
+
}
|
|
11100
|
+
} else {
|
|
11101
|
+
console.error(chalk51.red("\u2717 An unexpected error occurred"));
|
|
11102
|
+
}
|
|
11103
|
+
process.exit(1);
|
|
11104
|
+
}
|
|
10881
11105
|
var setupCommand2 = new Command52().name("setup").description("Configure a model provider").option("-t, --type <type>", "Provider type (for non-interactive mode)").option(
|
|
10882
11106
|
"-c, --credential <credential>",
|
|
10883
11107
|
"Credential value (for non-interactive mode)"
|
|
10884
|
-
).option("--convert", "Convert existing user credential to model provider").action(
|
|
11108
|
+
).option("-m, --model <model>", "Model selection (for non-interactive mode)").option("--convert", "Convert existing user credential to model provider").action(
|
|
10885
11109
|
async (options) => {
|
|
10886
11110
|
try {
|
|
10887
|
-
let
|
|
10888
|
-
let credential;
|
|
11111
|
+
let input;
|
|
10889
11112
|
const shouldConvert = options.convert ?? false;
|
|
10890
11113
|
if (options.type && options.credential) {
|
|
10891
|
-
|
|
10892
|
-
|
|
10893
|
-
|
|
10894
|
-
|
|
10895
|
-
|
|
10896
|
-
console.log(` ${chalk51.cyan(t)} - ${config.label}`);
|
|
10897
|
-
}
|
|
10898
|
-
process.exit(1);
|
|
10899
|
-
}
|
|
10900
|
-
type = options.type;
|
|
10901
|
-
credential = options.credential;
|
|
11114
|
+
input = handleNonInteractiveMode({
|
|
11115
|
+
type: options.type,
|
|
11116
|
+
credential: options.credential,
|
|
11117
|
+
model: options.model
|
|
11118
|
+
});
|
|
10902
11119
|
} else if (options.type || options.credential) {
|
|
10903
11120
|
console.error(
|
|
10904
11121
|
chalk51.red("\u2717 Both --type and --credential are required")
|
|
10905
11122
|
);
|
|
10906
11123
|
process.exit(1);
|
|
10907
11124
|
} else {
|
|
10908
|
-
|
|
10909
|
-
|
|
10910
|
-
|
|
10911
|
-
console.log("Use non-interactive mode:");
|
|
10912
|
-
console.log(
|
|
10913
|
-
chalk51.cyan(
|
|
10914
|
-
' vm0 model-provider setup --type <type> --credential "<value>"'
|
|
10915
|
-
)
|
|
10916
|
-
);
|
|
10917
|
-
process.exit(1);
|
|
11125
|
+
const result = await handleInteractiveMode();
|
|
11126
|
+
if (result === null) {
|
|
11127
|
+
return;
|
|
10918
11128
|
}
|
|
10919
|
-
|
|
10920
|
-
{
|
|
10921
|
-
type: "select",
|
|
10922
|
-
name: "type",
|
|
10923
|
-
message: "Select provider type:",
|
|
10924
|
-
choices: providerChoices
|
|
10925
|
-
},
|
|
10926
|
-
{ onCancel: () => process.exit(0) }
|
|
10927
|
-
);
|
|
10928
|
-
type = typeResponse.type;
|
|
10929
|
-
const checkResult = await checkModelProviderCredential(type);
|
|
10930
|
-
if (checkResult.exists && checkResult.currentType === "user") {
|
|
10931
|
-
const convertResponse = await prompts2(
|
|
10932
|
-
{
|
|
10933
|
-
type: "confirm",
|
|
10934
|
-
name: "convert",
|
|
10935
|
-
message: `Credential "${checkResult.credentialName}" already exists. Convert to model provider?`,
|
|
10936
|
-
initial: true
|
|
10937
|
-
},
|
|
10938
|
-
{ onCancel: () => process.exit(0) }
|
|
10939
|
-
);
|
|
10940
|
-
if (convertResponse.convert) {
|
|
10941
|
-
const provider2 = await convertModelProviderCredential(type);
|
|
10942
|
-
const defaultNote2 = provider2.isDefault ? ` (default for ${provider2.framework})` : "";
|
|
10943
|
-
console.log(
|
|
10944
|
-
chalk51.green(
|
|
10945
|
-
`\u2713 Converted "${checkResult.credentialName}" to model provider${defaultNote2}`
|
|
10946
|
-
)
|
|
10947
|
-
);
|
|
10948
|
-
return;
|
|
10949
|
-
} else {
|
|
10950
|
-
console.log(chalk51.dim("Aborted"));
|
|
10951
|
-
process.exit(0);
|
|
10952
|
-
}
|
|
10953
|
-
}
|
|
10954
|
-
const config = MODEL_PROVIDER_TYPES[type];
|
|
10955
|
-
console.log();
|
|
10956
|
-
console.log(chalk51.dim(config.helpText));
|
|
10957
|
-
console.log();
|
|
10958
|
-
const credentialResponse = await prompts2(
|
|
10959
|
-
{
|
|
10960
|
-
type: "password",
|
|
10961
|
-
name: "credential",
|
|
10962
|
-
message: `Enter your ${config.credentialLabel}:`,
|
|
10963
|
-
validate: (value) => value.length > 0 || `${config.credentialLabel} is required`
|
|
10964
|
-
},
|
|
10965
|
-
{ onCancel: () => process.exit(0) }
|
|
10966
|
-
);
|
|
10967
|
-
credential = credentialResponse.credential;
|
|
11129
|
+
input = result;
|
|
10968
11130
|
}
|
|
10969
11131
|
const { provider, created } = await upsertModelProvider({
|
|
10970
|
-
type,
|
|
10971
|
-
credential,
|
|
10972
|
-
convert: shouldConvert
|
|
11132
|
+
type: input.type,
|
|
11133
|
+
credential: input.credential,
|
|
11134
|
+
convert: shouldConvert,
|
|
11135
|
+
selectedModel: input.selectedModel
|
|
10973
11136
|
});
|
|
10974
11137
|
const action = created ? "created" : "updated";
|
|
10975
11138
|
const defaultNote = provider.isDefault ? ` (default for ${provider.framework})` : "";
|
|
11139
|
+
const modelNote = provider.selectedModel ? ` with model: ${provider.selectedModel}` : "";
|
|
10976
11140
|
console.log(
|
|
10977
|
-
chalk51.green(
|
|
11141
|
+
chalk51.green(
|
|
11142
|
+
`\u2713 Model provider "${input.type}" ${action}${defaultNote}${modelNote}`
|
|
11143
|
+
)
|
|
10978
11144
|
);
|
|
10979
11145
|
} catch (error) {
|
|
10980
|
-
|
|
10981
|
-
if (error.message.includes("already exists")) {
|
|
10982
|
-
console.error(chalk51.red(`\u2717 ${error.message}`));
|
|
10983
|
-
console.log();
|
|
10984
|
-
console.log("To convert the existing credential, run:");
|
|
10985
|
-
console.log(chalk51.cyan(" vm0 model-provider setup --convert"));
|
|
10986
|
-
} else if (error.message.includes("Not authenticated")) {
|
|
10987
|
-
console.error(
|
|
10988
|
-
chalk51.red("\u2717 Not authenticated. Run: vm0 auth login")
|
|
10989
|
-
);
|
|
10990
|
-
} else {
|
|
10991
|
-
console.error(chalk51.red(`\u2717 ${error.message}`));
|
|
10992
|
-
}
|
|
10993
|
-
} else {
|
|
10994
|
-
console.error(chalk51.red("\u2717 An unexpected error occurred"));
|
|
10995
|
-
}
|
|
10996
|
-
process.exit(1);
|
|
11146
|
+
handleSetupError2(error);
|
|
10997
11147
|
}
|
|
10998
11148
|
}
|
|
10999
11149
|
);
|
|
@@ -11299,7 +11449,9 @@ function getProviderChoices() {
|
|
|
11299
11449
|
type,
|
|
11300
11450
|
label: MODEL_PROVIDER_TYPES[type].label,
|
|
11301
11451
|
helpText: MODEL_PROVIDER_TYPES[type].helpText,
|
|
11302
|
-
credentialLabel: MODEL_PROVIDER_TYPES[type].credentialLabel
|
|
11452
|
+
credentialLabel: MODEL_PROVIDER_TYPES[type].credentialLabel,
|
|
11453
|
+
models: getModels(type),
|
|
11454
|
+
defaultModel: getDefaultModel(type)
|
|
11303
11455
|
})
|
|
11304
11456
|
);
|
|
11305
11457
|
}
|
|
@@ -11307,7 +11459,8 @@ async function setupModelProvider(type, credential, options) {
|
|
|
11307
11459
|
const response = await upsertModelProvider({
|
|
11308
11460
|
type,
|
|
11309
11461
|
credential,
|
|
11310
|
-
convert: options?.convert
|
|
11462
|
+
convert: options?.convert,
|
|
11463
|
+
selectedModel: options?.selectedModel
|
|
11311
11464
|
});
|
|
11312
11465
|
return {
|
|
11313
11466
|
provider: response.provider,
|
|
@@ -11507,10 +11660,29 @@ async function handleModelProvider(ctx) {
|
|
|
11507
11660
|
console.log(chalk57.dim("Cancelled"));
|
|
11508
11661
|
process.exit(0);
|
|
11509
11662
|
}
|
|
11510
|
-
|
|
11663
|
+
let selectedModel;
|
|
11664
|
+
if (selectedChoice?.models && selectedChoice.models.length > 0) {
|
|
11665
|
+
selectedModel = await step.prompt(
|
|
11666
|
+
() => promptSelect(
|
|
11667
|
+
"Select model:",
|
|
11668
|
+
selectedChoice.models.map((model) => ({
|
|
11669
|
+
title: model === selectedChoice.defaultModel ? `${model} (Recommended)` : model,
|
|
11670
|
+
value: model
|
|
11671
|
+
}))
|
|
11672
|
+
)
|
|
11673
|
+
);
|
|
11674
|
+
if (!selectedModel) {
|
|
11675
|
+
console.log(chalk57.dim("Cancelled"));
|
|
11676
|
+
process.exit(0);
|
|
11677
|
+
}
|
|
11678
|
+
}
|
|
11679
|
+
const result = await setupModelProvider(providerType, credential, {
|
|
11680
|
+
selectedModel
|
|
11681
|
+
});
|
|
11682
|
+
const modelNote = result.provider.selectedModel ? ` with model: ${result.provider.selectedModel}` : "";
|
|
11511
11683
|
step.detail(
|
|
11512
11684
|
chalk57.green(
|
|
11513
|
-
`${providerType} ${result.created ? "created" : "updated"}${result.isDefault ? ` (default for ${result.framework})` : ""}`
|
|
11685
|
+
`${providerType} ${result.created ? "created" : "updated"}${result.isDefault ? ` (default for ${result.framework})` : ""}${modelNote}`
|
|
11514
11686
|
)
|
|
11515
11687
|
);
|
|
11516
11688
|
});
|
|
@@ -11658,7 +11830,7 @@ var setupClaudeCommand = new Command57().name("setup-claude").description("Insta
|
|
|
11658
11830
|
|
|
11659
11831
|
// src/index.ts
|
|
11660
11832
|
var program = new Command58();
|
|
11661
|
-
program.name("vm0").description("VM0 CLI - Build and run agents with natural language").version("9.
|
|
11833
|
+
program.name("vm0").description("VM0 CLI - Build and run agents with natural language").version("9.12.0");
|
|
11662
11834
|
program.addCommand(authCommand);
|
|
11663
11835
|
program.addCommand(infoCommand);
|
|
11664
11836
|
program.addCommand(composeCommand);
|