@vm0/cli 9.38.0 → 9.38.2
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 +206 -172
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -45,7 +45,7 @@ if (DSN) {
|
|
|
45
45
|
Sentry.init({
|
|
46
46
|
dsn: DSN,
|
|
47
47
|
environment: process.env.SENTRY_ENVIRONMENT ?? "production",
|
|
48
|
-
release: "9.38.
|
|
48
|
+
release: "9.38.2",
|
|
49
49
|
sendDefaultPii: false,
|
|
50
50
|
tracesSampleRate: 0,
|
|
51
51
|
shutdownTimeout: 500,
|
|
@@ -64,7 +64,7 @@ if (DSN) {
|
|
|
64
64
|
}
|
|
65
65
|
});
|
|
66
66
|
Sentry.setContext("cli", {
|
|
67
|
-
version: "9.38.
|
|
67
|
+
version: "9.38.2",
|
|
68
68
|
command: process.argv.slice(2).join(" ")
|
|
69
69
|
});
|
|
70
70
|
Sentry.setContext("runtime", {
|
|
@@ -607,7 +607,7 @@ function getConfigPath() {
|
|
|
607
607
|
return join2(homedir2(), ".vm0", "config.json");
|
|
608
608
|
}
|
|
609
609
|
var infoCommand = new Command6().name("info").description("Display environment and debug information").action(async () => {
|
|
610
|
-
console.log(chalk7.bold(`VM0 CLI v${"9.38.
|
|
610
|
+
console.log(chalk7.bold(`VM0 CLI v${"9.38.2"}`));
|
|
611
611
|
console.log();
|
|
612
612
|
const config = await loadConfig();
|
|
613
613
|
const hasEnvToken = !!process.env.VM0_TOKEN;
|
|
@@ -641,7 +641,7 @@ import { Command as Command7, Option } from "commander";
|
|
|
641
641
|
import chalk8 from "chalk";
|
|
642
642
|
import { readFile as readFile4, rm as rm3 } from "fs/promises";
|
|
643
643
|
import { existsSync as existsSync5 } from "fs";
|
|
644
|
-
import { dirname as dirname2, join as
|
|
644
|
+
import { dirname as dirname2, join as join8 } from "path";
|
|
645
645
|
import { parse as parseYaml2 } from "yaml";
|
|
646
646
|
|
|
647
647
|
// ../../packages/core/src/variable-expander.ts
|
|
@@ -4646,18 +4646,18 @@ async function getRawHeaders() {
|
|
|
4646
4646
|
}
|
|
4647
4647
|
return headers;
|
|
4648
4648
|
}
|
|
4649
|
-
async function httpGet(
|
|
4649
|
+
async function httpGet(path17) {
|
|
4650
4650
|
const baseUrl = await getBaseUrl();
|
|
4651
4651
|
const headers = await getRawHeaders();
|
|
4652
|
-
return fetch(`${baseUrl}${
|
|
4652
|
+
return fetch(`${baseUrl}${path17}`, {
|
|
4653
4653
|
method: "GET",
|
|
4654
4654
|
headers
|
|
4655
4655
|
});
|
|
4656
4656
|
}
|
|
4657
|
-
async function httpPost(
|
|
4657
|
+
async function httpPost(path17, body) {
|
|
4658
4658
|
const baseUrl = await getBaseUrl();
|
|
4659
4659
|
const headers = await getRawHeaders();
|
|
4660
|
-
return fetch(`${baseUrl}${
|
|
4660
|
+
return fetch(`${baseUrl}${path17}`, {
|
|
4661
4661
|
method: "POST",
|
|
4662
4662
|
headers: {
|
|
4663
4663
|
...headers,
|
|
@@ -4666,10 +4666,10 @@ async function httpPost(path16, body) {
|
|
|
4666
4666
|
body: JSON.stringify(body)
|
|
4667
4667
|
});
|
|
4668
4668
|
}
|
|
4669
|
-
async function httpDelete(
|
|
4669
|
+
async function httpDelete(path17) {
|
|
4670
4670
|
const baseUrl = await getBaseUrl();
|
|
4671
4671
|
const headers = await getRawHeaders();
|
|
4672
|
-
return fetch(`${baseUrl}${
|
|
4672
|
+
return fetch(`${baseUrl}${path17}`, {
|
|
4673
4673
|
method: "DELETE",
|
|
4674
4674
|
headers
|
|
4675
4675
|
});
|
|
@@ -5287,29 +5287,29 @@ var cliComposeSchema = z29.object({
|
|
|
5287
5287
|
}
|
|
5288
5288
|
}
|
|
5289
5289
|
});
|
|
5290
|
-
function formatInvalidTypeIssue(
|
|
5290
|
+
function formatInvalidTypeIssue(path17, issue) {
|
|
5291
5291
|
const received = issue.received;
|
|
5292
5292
|
const isMissing = received === "undefined" || issue.message.includes("received undefined") || issue.message === "Required";
|
|
5293
|
-
if (
|
|
5293
|
+
if (path17 === "version" && isMissing) {
|
|
5294
5294
|
return "Missing config.version";
|
|
5295
5295
|
}
|
|
5296
|
-
if (
|
|
5296
|
+
if (path17 === "agents" && isMissing) {
|
|
5297
5297
|
return "Missing agents object in config";
|
|
5298
5298
|
}
|
|
5299
|
-
if (
|
|
5300
|
-
const volumeKey =
|
|
5299
|
+
if (path17.startsWith("volumes.") && path17.endsWith(".name")) {
|
|
5300
|
+
const volumeKey = path17.split(".")[1];
|
|
5301
5301
|
return `Volume "${volumeKey}" must have a 'name' field (string)`;
|
|
5302
5302
|
}
|
|
5303
|
-
if (
|
|
5304
|
-
const volumeKey =
|
|
5303
|
+
if (path17.startsWith("volumes.") && path17.endsWith(".version")) {
|
|
5304
|
+
const volumeKey = path17.split(".")[1];
|
|
5305
5305
|
return `Volume "${volumeKey}" must have a 'version' field (string)`;
|
|
5306
5306
|
}
|
|
5307
5307
|
if (issue.expected === "array") {
|
|
5308
|
-
const fieldName =
|
|
5308
|
+
const fieldName = path17.replace(/^agents\.[^.]+\./, "agent.");
|
|
5309
5309
|
return `${fieldName} must be an array`;
|
|
5310
5310
|
}
|
|
5311
5311
|
if (issue.expected === "string" && received === "number") {
|
|
5312
|
-
const fieldName =
|
|
5312
|
+
const fieldName = path17.replace(/^agents\.[^.]+\./, "agent.");
|
|
5313
5313
|
const match = fieldName.match(/^(agent\.[^.]+)\.\d+$/);
|
|
5314
5314
|
if (match) {
|
|
5315
5315
|
return `Each entry in ${match[1]?.replace("agent.", "")} must be a string`;
|
|
@@ -5320,24 +5320,24 @@ function formatInvalidTypeIssue(path16, issue) {
|
|
|
5320
5320
|
function formatZodError(error) {
|
|
5321
5321
|
const issue = error.issues[0];
|
|
5322
5322
|
if (!issue) return "Validation failed";
|
|
5323
|
-
const
|
|
5323
|
+
const path17 = issue.path.join(".");
|
|
5324
5324
|
const message = issue.message;
|
|
5325
|
-
if (!
|
|
5325
|
+
if (!path17) return message;
|
|
5326
5326
|
if (issue.code === "invalid_type") {
|
|
5327
|
-
const formatted = formatInvalidTypeIssue(
|
|
5327
|
+
const formatted = formatInvalidTypeIssue(path17, issue);
|
|
5328
5328
|
if (formatted) return formatted;
|
|
5329
5329
|
}
|
|
5330
|
-
if (issue.code === "invalid_key" &&
|
|
5330
|
+
if (issue.code === "invalid_key" && path17.startsWith("agents.")) {
|
|
5331
5331
|
return "Invalid agent name format. Must be 3-64 characters, letters, numbers, and hyphens only. Must start and end with letter or number.";
|
|
5332
5332
|
}
|
|
5333
|
-
if (message === "Invalid key in record" &&
|
|
5333
|
+
if (message === "Invalid key in record" && path17.startsWith("agents.")) {
|
|
5334
5334
|
return "Invalid agent name format. Must be 3-64 characters, letters, numbers, and hyphens only. Must start and end with letter or number.";
|
|
5335
5335
|
}
|
|
5336
5336
|
if (issue.code === "custom") {
|
|
5337
5337
|
return message;
|
|
5338
5338
|
}
|
|
5339
|
-
if (
|
|
5340
|
-
const cleanPath =
|
|
5339
|
+
if (path17.startsWith("agents.")) {
|
|
5340
|
+
const cleanPath = path17.replace(/^agents\.[^.]+\./, "agent.");
|
|
5341
5341
|
if (message.startsWith("Invalid input:")) {
|
|
5342
5342
|
const match = message.match(/expected (\w+), received (\w+)/);
|
|
5343
5343
|
if (match && match[1] === "string" && match[2] === "number") {
|
|
@@ -5349,7 +5349,7 @@ function formatZodError(error) {
|
|
|
5349
5349
|
}
|
|
5350
5350
|
return `${cleanPath}: ${message}`;
|
|
5351
5351
|
}
|
|
5352
|
-
return `${
|
|
5352
|
+
return `${path17}: ${message}`;
|
|
5353
5353
|
}
|
|
5354
5354
|
function validateAgentName(name) {
|
|
5355
5355
|
return cliAgentNameSchema.safeParse(name).success;
|
|
@@ -5396,25 +5396,17 @@ function validateAgentCompose(config) {
|
|
|
5396
5396
|
}
|
|
5397
5397
|
|
|
5398
5398
|
// src/lib/domain/github-skills.ts
|
|
5399
|
+
import * as fs2 from "fs/promises";
|
|
5400
|
+
import * as path2 from "path";
|
|
5401
|
+
import { parse as parseYaml } from "yaml";
|
|
5402
|
+
|
|
5403
|
+
// src/lib/external/git-client.ts
|
|
5399
5404
|
import * as fs from "fs/promises";
|
|
5400
5405
|
import * as path from "path";
|
|
5401
5406
|
import * as os2 from "os";
|
|
5402
5407
|
import { exec } from "child_process";
|
|
5403
5408
|
import { promisify } from "util";
|
|
5404
|
-
import { parse as parseYaml } from "yaml";
|
|
5405
5409
|
var execAsync = promisify(exec);
|
|
5406
|
-
function parseGitHubTreeUrl2(url) {
|
|
5407
|
-
const parsed = parseGitHubTreeUrl(url);
|
|
5408
|
-
if (!parsed) {
|
|
5409
|
-
throw new Error(
|
|
5410
|
-
`Invalid GitHub tree URL: ${url}. Expected format: https://github.com/{owner}/{repo}/tree/{branch}/{path}`
|
|
5411
|
-
);
|
|
5412
|
-
}
|
|
5413
|
-
return parsed;
|
|
5414
|
-
}
|
|
5415
|
-
function getSkillStorageName2(parsed) {
|
|
5416
|
-
return getSkillStorageName(parsed.fullPath);
|
|
5417
|
-
}
|
|
5418
5410
|
async function downloadGitHubSkill(parsed, destDir) {
|
|
5419
5411
|
const repoUrl = `https://github.com/${parsed.owner}/${parsed.repo}.git`;
|
|
5420
5412
|
const skillDir = path.join(destDir, parsed.skillName);
|
|
@@ -5512,10 +5504,24 @@ async function downloadGitHubDirectory(url) {
|
|
|
5512
5504
|
throw error;
|
|
5513
5505
|
}
|
|
5514
5506
|
}
|
|
5507
|
+
|
|
5508
|
+
// src/lib/domain/github-skills.ts
|
|
5509
|
+
function parseGitHubTreeUrl2(url) {
|
|
5510
|
+
const parsed = parseGitHubTreeUrl(url);
|
|
5511
|
+
if (!parsed) {
|
|
5512
|
+
throw new Error(
|
|
5513
|
+
`Invalid GitHub tree URL: ${url}. Expected format: https://github.com/{owner}/{repo}/tree/{branch}/{path}`
|
|
5514
|
+
);
|
|
5515
|
+
}
|
|
5516
|
+
return parsed;
|
|
5517
|
+
}
|
|
5518
|
+
function getSkillStorageName2(parsed) {
|
|
5519
|
+
return getSkillStorageName(parsed.fullPath);
|
|
5520
|
+
}
|
|
5515
5521
|
async function validateSkillDirectory(skillDir) {
|
|
5516
|
-
const skillMdPath =
|
|
5522
|
+
const skillMdPath = path2.join(skillDir, "SKILL.md");
|
|
5517
5523
|
try {
|
|
5518
|
-
await
|
|
5524
|
+
await fs2.access(skillMdPath);
|
|
5519
5525
|
} catch {
|
|
5520
5526
|
throw new Error(
|
|
5521
5527
|
`Skill directory missing required SKILL.md file: ${skillDir}`
|
|
@@ -5549,36 +5555,36 @@ function parseSkillFrontmatter(content) {
|
|
|
5549
5555
|
};
|
|
5550
5556
|
}
|
|
5551
5557
|
async function readSkillFrontmatter(skillDir) {
|
|
5552
|
-
const skillMdPath =
|
|
5553
|
-
const content = await
|
|
5558
|
+
const skillMdPath = path2.join(skillDir, "SKILL.md");
|
|
5559
|
+
const content = await fs2.readFile(skillMdPath, "utf8");
|
|
5554
5560
|
return parseSkillFrontmatter(content);
|
|
5555
5561
|
}
|
|
5556
5562
|
|
|
5557
5563
|
// src/lib/storage/system-storage.ts
|
|
5558
|
-
import * as
|
|
5559
|
-
import * as
|
|
5564
|
+
import * as fs5 from "fs/promises";
|
|
5565
|
+
import * as path5 from "path";
|
|
5560
5566
|
import * as os4 from "os";
|
|
5561
5567
|
|
|
5562
5568
|
// src/lib/storage/direct-upload.ts
|
|
5563
5569
|
import { createHash } from "crypto";
|
|
5564
|
-
import * as
|
|
5565
|
-
import * as
|
|
5570
|
+
import * as fs4 from "fs";
|
|
5571
|
+
import * as path4 from "path";
|
|
5566
5572
|
import * as os3 from "os";
|
|
5567
5573
|
import * as tar2 from "tar";
|
|
5568
5574
|
|
|
5569
5575
|
// src/lib/utils/file-utils.ts
|
|
5570
|
-
import * as
|
|
5571
|
-
import * as
|
|
5576
|
+
import * as fs3 from "fs";
|
|
5577
|
+
import * as path3 from "path";
|
|
5572
5578
|
import * as tar from "tar";
|
|
5573
5579
|
function checkDirectoryStatus(dirPath) {
|
|
5574
|
-
if (!
|
|
5580
|
+
if (!fs3.existsSync(dirPath)) {
|
|
5575
5581
|
return { exists: false, empty: true };
|
|
5576
5582
|
}
|
|
5577
|
-
const stat =
|
|
5583
|
+
const stat = fs3.statSync(dirPath);
|
|
5578
5584
|
if (!stat.isDirectory()) {
|
|
5579
5585
|
return { exists: true, empty: false };
|
|
5580
5586
|
}
|
|
5581
|
-
const entries =
|
|
5587
|
+
const entries = fs3.readdirSync(dirPath);
|
|
5582
5588
|
return { exists: true, empty: entries.length === 0 };
|
|
5583
5589
|
}
|
|
5584
5590
|
function formatBytes(bytes) {
|
|
@@ -5623,14 +5629,14 @@ function listTarFiles(tarPath) {
|
|
|
5623
5629
|
async function listLocalFiles(dir, excludeDirs = [".vm0"]) {
|
|
5624
5630
|
const files = [];
|
|
5625
5631
|
async function walkDir(currentDir, relativePath = "") {
|
|
5626
|
-
const entries = await
|
|
5632
|
+
const entries = await fs3.promises.readdir(currentDir, {
|
|
5627
5633
|
withFileTypes: true
|
|
5628
5634
|
});
|
|
5629
5635
|
for (const entry of entries) {
|
|
5630
|
-
const entryRelativePath = relativePath ?
|
|
5636
|
+
const entryRelativePath = relativePath ? path3.join(relativePath, entry.name) : entry.name;
|
|
5631
5637
|
if (entry.isDirectory()) {
|
|
5632
5638
|
if (!excludeDirs.includes(entry.name)) {
|
|
5633
|
-
await walkDir(
|
|
5639
|
+
await walkDir(path3.join(currentDir, entry.name), entryRelativePath);
|
|
5634
5640
|
}
|
|
5635
5641
|
} else {
|
|
5636
5642
|
files.push(entryRelativePath);
|
|
@@ -5646,8 +5652,8 @@ async function removeExtraFiles(dir, remoteFiles, excludeDirs = [".vm0"]) {
|
|
|
5646
5652
|
for (const localFile of localFiles) {
|
|
5647
5653
|
const normalizedPath = localFile.replace(/\\/g, "/");
|
|
5648
5654
|
if (!remoteFiles.has(normalizedPath)) {
|
|
5649
|
-
const fullPath =
|
|
5650
|
-
await
|
|
5655
|
+
const fullPath = path3.join(dir, localFile);
|
|
5656
|
+
await fs3.promises.unlink(fullPath);
|
|
5651
5657
|
removedCount++;
|
|
5652
5658
|
}
|
|
5653
5659
|
}
|
|
@@ -5655,17 +5661,17 @@ async function removeExtraFiles(dir, remoteFiles, excludeDirs = [".vm0"]) {
|
|
|
5655
5661
|
return removedCount;
|
|
5656
5662
|
}
|
|
5657
5663
|
async function removeEmptyDirs(dir, excludeDirs = [".vm0"]) {
|
|
5658
|
-
const entries = await
|
|
5664
|
+
const entries = await fs3.promises.readdir(dir, { withFileTypes: true });
|
|
5659
5665
|
let isEmpty = true;
|
|
5660
5666
|
for (const entry of entries) {
|
|
5661
|
-
const fullPath =
|
|
5667
|
+
const fullPath = path3.join(dir, entry.name);
|
|
5662
5668
|
if (entry.isDirectory()) {
|
|
5663
5669
|
if (excludeDirs.includes(entry.name)) {
|
|
5664
5670
|
isEmpty = false;
|
|
5665
5671
|
} else {
|
|
5666
5672
|
const subDirEmpty = await removeEmptyDirs(fullPath, excludeDirs);
|
|
5667
5673
|
if (subDirEmpty) {
|
|
5668
|
-
await
|
|
5674
|
+
await fs3.promises.rmdir(fullPath);
|
|
5669
5675
|
} else {
|
|
5670
5676
|
isEmpty = false;
|
|
5671
5677
|
}
|
|
@@ -5681,7 +5687,7 @@ async function removeEmptyDirs(dir, excludeDirs = [".vm0"]) {
|
|
|
5681
5687
|
async function hashFileStream(filePath) {
|
|
5682
5688
|
return new Promise((resolve, reject) => {
|
|
5683
5689
|
const hash = createHash("sha256");
|
|
5684
|
-
const stream =
|
|
5690
|
+
const stream = fs4.createReadStream(filePath);
|
|
5685
5691
|
stream.on("data", (chunk) => hash.update(chunk));
|
|
5686
5692
|
stream.on("end", () => resolve(hash.digest("hex")));
|
|
5687
5693
|
stream.on("error", reject);
|
|
@@ -5689,10 +5695,10 @@ async function hashFileStream(filePath) {
|
|
|
5689
5695
|
}
|
|
5690
5696
|
async function getAllFiles(dirPath, baseDir = dirPath) {
|
|
5691
5697
|
const files = [];
|
|
5692
|
-
const entries = await
|
|
5698
|
+
const entries = await fs4.promises.readdir(dirPath, { withFileTypes: true });
|
|
5693
5699
|
for (const entry of entries) {
|
|
5694
|
-
const fullPath =
|
|
5695
|
-
const relativePath =
|
|
5700
|
+
const fullPath = path4.join(dirPath, entry.name);
|
|
5701
|
+
const relativePath = path4.relative(baseDir, fullPath);
|
|
5696
5702
|
if (relativePath.startsWith(".vm0")) {
|
|
5697
5703
|
continue;
|
|
5698
5704
|
}
|
|
@@ -5709,10 +5715,10 @@ async function collectFileMetadata(cwd, files, onProgress) {
|
|
|
5709
5715
|
const fileEntries = [];
|
|
5710
5716
|
for (let i = 0; i < files.length; i++) {
|
|
5711
5717
|
const file = files[i];
|
|
5712
|
-
const relativePath =
|
|
5718
|
+
const relativePath = path4.relative(cwd, file);
|
|
5713
5719
|
const [hash, stats] = await Promise.all([
|
|
5714
5720
|
hashFileStream(file),
|
|
5715
|
-
|
|
5721
|
+
fs4.promises.stat(file)
|
|
5716
5722
|
]);
|
|
5717
5723
|
fileEntries.push({
|
|
5718
5724
|
path: relativePath,
|
|
@@ -5726,10 +5732,10 @@ async function collectFileMetadata(cwd, files, onProgress) {
|
|
|
5726
5732
|
return fileEntries;
|
|
5727
5733
|
}
|
|
5728
5734
|
async function createArchive(cwd, files) {
|
|
5729
|
-
const tmpDir =
|
|
5730
|
-
const tarPath =
|
|
5735
|
+
const tmpDir = fs4.mkdtempSync(path4.join(os3.tmpdir(), "vm0-"));
|
|
5736
|
+
const tarPath = path4.join(tmpDir, "archive.tar.gz");
|
|
5731
5737
|
try {
|
|
5732
|
-
const relativePaths = files.map((file) =>
|
|
5738
|
+
const relativePaths = files.map((file) => path4.relative(cwd, file));
|
|
5733
5739
|
if (relativePaths.length > 0) {
|
|
5734
5740
|
await tar2.create(
|
|
5735
5741
|
{
|
|
@@ -5750,13 +5756,13 @@ async function createArchive(cwd, files) {
|
|
|
5750
5756
|
["."]
|
|
5751
5757
|
);
|
|
5752
5758
|
}
|
|
5753
|
-
const tarBuffer = await
|
|
5759
|
+
const tarBuffer = await fs4.promises.readFile(tarPath);
|
|
5754
5760
|
return tarBuffer;
|
|
5755
5761
|
} finally {
|
|
5756
|
-
if (
|
|
5757
|
-
await
|
|
5762
|
+
if (fs4.existsSync(tarPath)) {
|
|
5763
|
+
await fs4.promises.unlink(tarPath);
|
|
5758
5764
|
}
|
|
5759
|
-
await
|
|
5765
|
+
await fs4.promises.rmdir(tmpDir);
|
|
5760
5766
|
}
|
|
5761
5767
|
}
|
|
5762
5768
|
function createManifest(files) {
|
|
@@ -5881,13 +5887,13 @@ function getInstructionsFilename(framework) {
|
|
|
5881
5887
|
}
|
|
5882
5888
|
async function uploadInstructions(agentName, instructionsFilePath, basePath, framework) {
|
|
5883
5889
|
const storageName = getInstructionsStorageName(agentName.toLowerCase());
|
|
5884
|
-
const absolutePath =
|
|
5885
|
-
const content = await
|
|
5886
|
-
const tmpDir = await
|
|
5887
|
-
const instructionsDir =
|
|
5888
|
-
await
|
|
5890
|
+
const absolutePath = path5.isAbsolute(instructionsFilePath) ? instructionsFilePath : path5.join(basePath, instructionsFilePath);
|
|
5891
|
+
const content = await fs5.readFile(absolutePath, "utf8");
|
|
5892
|
+
const tmpDir = await fs5.mkdtemp(path5.join(os4.tmpdir(), "vm0-instructions-"));
|
|
5893
|
+
const instructionsDir = path5.join(tmpDir, "instructions");
|
|
5894
|
+
await fs5.mkdir(instructionsDir);
|
|
5889
5895
|
const filename = getInstructionsFilename(framework);
|
|
5890
|
-
await
|
|
5896
|
+
await fs5.writeFile(path5.join(instructionsDir, filename), content);
|
|
5891
5897
|
try {
|
|
5892
5898
|
const result = await directUpload(storageName, "volume", instructionsDir);
|
|
5893
5899
|
return {
|
|
@@ -5896,13 +5902,13 @@ async function uploadInstructions(agentName, instructionsFilePath, basePath, fra
|
|
|
5896
5902
|
action: result.deduplicated ? "deduplicated" : "created"
|
|
5897
5903
|
};
|
|
5898
5904
|
} finally {
|
|
5899
|
-
await
|
|
5905
|
+
await fs5.rm(tmpDir, { recursive: true, force: true });
|
|
5900
5906
|
}
|
|
5901
5907
|
}
|
|
5902
5908
|
async function uploadSkill(skillUrl) {
|
|
5903
5909
|
const parsed = parseGitHubTreeUrl2(skillUrl);
|
|
5904
5910
|
const storageName = getSkillStorageName2(parsed);
|
|
5905
|
-
const tmpDir = await
|
|
5911
|
+
const tmpDir = await fs5.mkdtemp(path5.join(os4.tmpdir(), "vm0-skill-"));
|
|
5906
5912
|
try {
|
|
5907
5913
|
const skillDir = await downloadGitHubSkill(parsed, tmpDir);
|
|
5908
5914
|
await validateSkillDirectory(skillDir);
|
|
@@ -5916,7 +5922,7 @@ async function uploadSkill(skillUrl) {
|
|
|
5916
5922
|
frontmatter
|
|
5917
5923
|
};
|
|
5918
5924
|
} finally {
|
|
5919
|
-
await
|
|
5925
|
+
await fs5.rm(tmpDir, { recursive: true, force: true });
|
|
5920
5926
|
}
|
|
5921
5927
|
}
|
|
5922
5928
|
|
|
@@ -6347,7 +6353,7 @@ async function handleGitHubCompose(url, options) {
|
|
|
6347
6353
|
console.log(`Downloading from GitHub: ${url}`);
|
|
6348
6354
|
}
|
|
6349
6355
|
const { dir: downloadedDir, tempRoot } = await downloadGitHubDirectory(url);
|
|
6350
|
-
const configFile =
|
|
6356
|
+
const configFile = join8(downloadedDir, "vm0.yaml");
|
|
6351
6357
|
try {
|
|
6352
6358
|
if (!existsSync5(configFile)) {
|
|
6353
6359
|
if (options.json) {
|
|
@@ -6474,7 +6480,7 @@ var composeCommand = new Command7().name("compose").description("Create or updat
|
|
|
6474
6480
|
options.autoUpdate = false;
|
|
6475
6481
|
}
|
|
6476
6482
|
if (options.autoUpdate !== false) {
|
|
6477
|
-
await startSilentUpgrade("9.38.
|
|
6483
|
+
await startSilentUpgrade("9.38.2");
|
|
6478
6484
|
}
|
|
6479
6485
|
try {
|
|
6480
6486
|
let result;
|
|
@@ -6998,7 +7004,7 @@ var EventRenderer = class _EventRenderer {
|
|
|
6998
7004
|
|
|
6999
7005
|
// src/commands/run/shared.ts
|
|
7000
7006
|
import chalk12 from "chalk";
|
|
7001
|
-
import * as
|
|
7007
|
+
import * as fs6 from "fs";
|
|
7002
7008
|
import { config as dotenvConfig } from "dotenv";
|
|
7003
7009
|
|
|
7004
7010
|
// src/lib/events/claude-event-parser.ts
|
|
@@ -8250,7 +8256,7 @@ var ApiClient = class {
|
|
|
8250
8256
|
/**
|
|
8251
8257
|
* Generic GET request
|
|
8252
8258
|
*/
|
|
8253
|
-
async get(
|
|
8259
|
+
async get(path17) {
|
|
8254
8260
|
const baseUrl = await this.getBaseUrl();
|
|
8255
8261
|
const token = await getToken();
|
|
8256
8262
|
if (!token) {
|
|
@@ -8263,7 +8269,7 @@ var ApiClient = class {
|
|
|
8263
8269
|
if (bypassSecret) {
|
|
8264
8270
|
headers["x-vercel-protection-bypass"] = bypassSecret;
|
|
8265
8271
|
}
|
|
8266
|
-
return fetch(`${baseUrl}${
|
|
8272
|
+
return fetch(`${baseUrl}${path17}`, {
|
|
8267
8273
|
method: "GET",
|
|
8268
8274
|
headers
|
|
8269
8275
|
});
|
|
@@ -8271,7 +8277,7 @@ var ApiClient = class {
|
|
|
8271
8277
|
/**
|
|
8272
8278
|
* Generic POST request
|
|
8273
8279
|
*/
|
|
8274
|
-
async post(
|
|
8280
|
+
async post(path17, options) {
|
|
8275
8281
|
const baseUrl = await this.getBaseUrl();
|
|
8276
8282
|
const token = await getToken();
|
|
8277
8283
|
if (!token) {
|
|
@@ -8287,7 +8293,7 @@ var ApiClient = class {
|
|
|
8287
8293
|
if (bypassSecret) {
|
|
8288
8294
|
headers["x-vercel-protection-bypass"] = bypassSecret;
|
|
8289
8295
|
}
|
|
8290
|
-
return fetch(`${baseUrl}${
|
|
8296
|
+
return fetch(`${baseUrl}${path17}`, {
|
|
8291
8297
|
method: "POST",
|
|
8292
8298
|
headers,
|
|
8293
8299
|
body: options?.body
|
|
@@ -8296,7 +8302,7 @@ var ApiClient = class {
|
|
|
8296
8302
|
/**
|
|
8297
8303
|
* Generic DELETE request
|
|
8298
8304
|
*/
|
|
8299
|
-
async delete(
|
|
8305
|
+
async delete(path17) {
|
|
8300
8306
|
const baseUrl = await this.getBaseUrl();
|
|
8301
8307
|
const token = await getToken();
|
|
8302
8308
|
if (!token) {
|
|
@@ -8309,7 +8315,7 @@ var ApiClient = class {
|
|
|
8309
8315
|
if (bypassSecret) {
|
|
8310
8316
|
headers["x-vercel-protection-bypass"] = bypassSecret;
|
|
8311
8317
|
}
|
|
8312
|
-
return fetch(`${baseUrl}${
|
|
8318
|
+
return fetch(`${baseUrl}${path17}`, {
|
|
8313
8319
|
method: "DELETE",
|
|
8314
8320
|
headers
|
|
8315
8321
|
});
|
|
@@ -8456,7 +8462,7 @@ function loadValues(cliValues, configNames, envFilePath) {
|
|
|
8456
8462
|
}
|
|
8457
8463
|
let fileValues = {};
|
|
8458
8464
|
if (envFilePath) {
|
|
8459
|
-
if (!
|
|
8465
|
+
if (!fs6.existsSync(envFilePath)) {
|
|
8460
8466
|
throw new Error(`Environment file not found: ${envFilePath}`);
|
|
8461
8467
|
}
|
|
8462
8468
|
const dotenvResult = dotenvConfig({ path: envFilePath, quiet: true });
|
|
@@ -8688,7 +8694,7 @@ var mainRunCommand = new Command8().name("run").description("Run an agent").argu
|
|
|
8688
8694
|
async (identifier, prompt, options) => {
|
|
8689
8695
|
try {
|
|
8690
8696
|
if (options.autoUpdate !== false) {
|
|
8691
|
-
await startSilentUpgrade("9.38.
|
|
8697
|
+
await startSilentUpgrade("9.38.2");
|
|
8692
8698
|
}
|
|
8693
8699
|
const { scope, name, version } = parseIdentifier(identifier);
|
|
8694
8700
|
if (scope && !options.experimentalSharedAgent) {
|
|
@@ -9169,13 +9175,13 @@ import { Command as Command19 } from "commander";
|
|
|
9169
9175
|
// src/commands/volume/init.ts
|
|
9170
9176
|
import { Command as Command13 } from "commander";
|
|
9171
9177
|
import chalk18 from "chalk";
|
|
9172
|
-
import
|
|
9178
|
+
import path7 from "path";
|
|
9173
9179
|
|
|
9174
9180
|
// src/lib/storage/storage-utils.ts
|
|
9175
9181
|
import { readFile as readFile5, writeFile as writeFile4, mkdir as mkdir4 } from "fs/promises";
|
|
9176
9182
|
import { existsSync as existsSync7 } from "fs";
|
|
9177
9183
|
import { parse as parseYaml3, stringify as stringifyYaml } from "yaml";
|
|
9178
|
-
import
|
|
9184
|
+
import path6 from "path";
|
|
9179
9185
|
var CONFIG_DIR = ".vm0";
|
|
9180
9186
|
var CONFIG_FILE = "storage.yaml";
|
|
9181
9187
|
function isValidStorageName(name) {
|
|
@@ -9186,8 +9192,8 @@ function isValidStorageName(name) {
|
|
|
9186
9192
|
return pattern.test(name) && !name.includes("--");
|
|
9187
9193
|
}
|
|
9188
9194
|
async function readStorageConfig(basePath = process.cwd()) {
|
|
9189
|
-
const configPath =
|
|
9190
|
-
const legacyConfigPath =
|
|
9195
|
+
const configPath = path6.join(basePath, CONFIG_DIR, CONFIG_FILE);
|
|
9196
|
+
const legacyConfigPath = path6.join(basePath, CONFIG_DIR, "volume.yaml");
|
|
9191
9197
|
let actualPath = null;
|
|
9192
9198
|
if (existsSync7(configPath)) {
|
|
9193
9199
|
actualPath = configPath;
|
|
@@ -9205,8 +9211,8 @@ async function readStorageConfig(basePath = process.cwd()) {
|
|
|
9205
9211
|
return config;
|
|
9206
9212
|
}
|
|
9207
9213
|
async function writeStorageConfig(storageName, basePath = process.cwd(), type2 = "volume") {
|
|
9208
|
-
const configDir =
|
|
9209
|
-
const configPath =
|
|
9214
|
+
const configDir = path6.join(basePath, CONFIG_DIR);
|
|
9215
|
+
const configPath = path6.join(configDir, CONFIG_FILE);
|
|
9210
9216
|
if (!existsSync7(configDir)) {
|
|
9211
9217
|
await mkdir4(configDir, { recursive: true });
|
|
9212
9218
|
}
|
|
@@ -9222,14 +9228,14 @@ async function writeStorageConfig(storageName, basePath = process.cwd(), type2 =
|
|
|
9222
9228
|
var initCommand = new Command13().name("init").description("Initialize a volume in the current directory").option("-n, --name <name>", "Volume name (required in non-interactive mode)").action(
|
|
9223
9229
|
withErrorHandler(async (options) => {
|
|
9224
9230
|
const cwd = process.cwd();
|
|
9225
|
-
const dirName =
|
|
9231
|
+
const dirName = path7.basename(cwd);
|
|
9226
9232
|
const existingConfig = await readStorageConfig(cwd);
|
|
9227
9233
|
if (existingConfig) {
|
|
9228
9234
|
console.log(
|
|
9229
9235
|
chalk18.yellow(`Volume already initialized: ${existingConfig.name}`)
|
|
9230
9236
|
);
|
|
9231
9237
|
console.log(
|
|
9232
|
-
chalk18.dim(`Config file: ${
|
|
9238
|
+
chalk18.dim(`Config file: ${path7.join(cwd, ".vm0", "storage.yaml")}`)
|
|
9233
9239
|
);
|
|
9234
9240
|
return;
|
|
9235
9241
|
}
|
|
@@ -9278,7 +9284,7 @@ var initCommand = new Command13().name("init").description("Initialize a volume
|
|
|
9278
9284
|
console.log(chalk18.green(`\u2713 Initialized volume: ${volumeName}`));
|
|
9279
9285
|
console.log(
|
|
9280
9286
|
chalk18.dim(
|
|
9281
|
-
` Config saved to ${
|
|
9287
|
+
` Config saved to ${path7.join(cwd, ".vm0", "storage.yaml")}`
|
|
9282
9288
|
)
|
|
9283
9289
|
);
|
|
9284
9290
|
})
|
|
@@ -9323,8 +9329,8 @@ var pushCommand = new Command14().name("push").description("Push local files to
|
|
|
9323
9329
|
// src/commands/volume/pull.ts
|
|
9324
9330
|
import { Command as Command15 } from "commander";
|
|
9325
9331
|
import chalk21 from "chalk";
|
|
9326
|
-
import
|
|
9327
|
-
import * as
|
|
9332
|
+
import path8 from "path";
|
|
9333
|
+
import * as fs7 from "fs";
|
|
9328
9334
|
import * as os5 from "os";
|
|
9329
9335
|
import * as tar3 from "tar";
|
|
9330
9336
|
|
|
@@ -9377,9 +9383,9 @@ var pullCommand = new Command15().name("pull").description("Pull cloud files to
|
|
|
9377
9383
|
const arrayBuffer = await s3Response.arrayBuffer();
|
|
9378
9384
|
const tarBuffer = Buffer.from(arrayBuffer);
|
|
9379
9385
|
console.log(chalk21.green(`\u2713 Downloaded ${formatBytes(tarBuffer.length)}`));
|
|
9380
|
-
const tmpDir =
|
|
9381
|
-
const tarPath =
|
|
9382
|
-
await
|
|
9386
|
+
const tmpDir = fs7.mkdtempSync(path8.join(os5.tmpdir(), "vm0-"));
|
|
9387
|
+
const tarPath = path8.join(tmpDir, "volume.tar.gz");
|
|
9388
|
+
await fs7.promises.writeFile(tarPath, tarBuffer);
|
|
9383
9389
|
console.log(chalk21.dim("Syncing local files..."));
|
|
9384
9390
|
const remoteFiles = await listTarFiles(tarPath);
|
|
9385
9391
|
const remoteFilesSet = new Set(
|
|
@@ -9397,8 +9403,8 @@ var pullCommand = new Command15().name("pull").description("Pull cloud files to
|
|
|
9397
9403
|
cwd,
|
|
9398
9404
|
gzip: true
|
|
9399
9405
|
});
|
|
9400
|
-
await
|
|
9401
|
-
await
|
|
9406
|
+
await fs7.promises.unlink(tarPath);
|
|
9407
|
+
await fs7.promises.rmdir(tmpDir);
|
|
9402
9408
|
console.log(chalk21.green(`\u2713 Extracted ${remoteFiles.length} files`));
|
|
9403
9409
|
})
|
|
9404
9410
|
);
|
|
@@ -9504,8 +9510,8 @@ import chalk25 from "chalk";
|
|
|
9504
9510
|
|
|
9505
9511
|
// src/lib/storage/clone-utils.ts
|
|
9506
9512
|
import chalk24 from "chalk";
|
|
9507
|
-
import
|
|
9508
|
-
import * as
|
|
9513
|
+
import path9 from "path";
|
|
9514
|
+
import * as fs8 from "fs";
|
|
9509
9515
|
import * as os6 from "os";
|
|
9510
9516
|
import * as tar4 from "tar";
|
|
9511
9517
|
async function cloneStorage(name, type2, destination, options = {}) {
|
|
@@ -9521,7 +9527,7 @@ async function cloneStorage(name, type2, destination, options = {}) {
|
|
|
9521
9527
|
version: options.version
|
|
9522
9528
|
});
|
|
9523
9529
|
console.log(chalk24.dim(`Creating directory: ${destination}/`));
|
|
9524
|
-
await
|
|
9530
|
+
await fs8.promises.mkdir(destination, { recursive: true });
|
|
9525
9531
|
if ("empty" in downloadInfo) {
|
|
9526
9532
|
await writeStorageConfig(name, destination, type2);
|
|
9527
9533
|
console.log(chalk24.green(`\u2713 Cloned empty ${typeLabel}: ${name}`));
|
|
@@ -9540,15 +9546,15 @@ async function cloneStorage(name, type2, destination, options = {}) {
|
|
|
9540
9546
|
console.log(chalk24.dim("Downloading from S3..."));
|
|
9541
9547
|
const s3Response = await fetch(downloadUrl);
|
|
9542
9548
|
if (!s3Response.ok) {
|
|
9543
|
-
await
|
|
9549
|
+
await fs8.promises.rm(destination, { recursive: true, force: true });
|
|
9544
9550
|
throw new Error(`S3 download failed: ${s3Response.status}`);
|
|
9545
9551
|
}
|
|
9546
9552
|
const arrayBuffer = await s3Response.arrayBuffer();
|
|
9547
9553
|
const tarBuffer = Buffer.from(arrayBuffer);
|
|
9548
9554
|
console.log(chalk24.green(`\u2713 Downloaded ${formatBytes(tarBuffer.length)}`));
|
|
9549
|
-
const tmpDir =
|
|
9550
|
-
const tarPath =
|
|
9551
|
-
await
|
|
9555
|
+
const tmpDir = fs8.mkdtempSync(path9.join(os6.tmpdir(), "vm0-clone-"));
|
|
9556
|
+
const tarPath = path9.join(tmpDir, "archive.tar.gz");
|
|
9557
|
+
await fs8.promises.writeFile(tarPath, tarBuffer);
|
|
9552
9558
|
const files = await listTarFiles(tarPath);
|
|
9553
9559
|
console.log(chalk24.dim("Extracting files..."));
|
|
9554
9560
|
await tar4.extract({
|
|
@@ -9556,8 +9562,8 @@ async function cloneStorage(name, type2, destination, options = {}) {
|
|
|
9556
9562
|
cwd: destination,
|
|
9557
9563
|
gzip: true
|
|
9558
9564
|
});
|
|
9559
|
-
await
|
|
9560
|
-
await
|
|
9565
|
+
await fs8.promises.unlink(tarPath);
|
|
9566
|
+
await fs8.promises.rmdir(tmpDir);
|
|
9561
9567
|
console.log(chalk24.green(`\u2713 Extracted ${files.length} files`));
|
|
9562
9568
|
await writeStorageConfig(name, destination, type2);
|
|
9563
9569
|
console.log(chalk24.green(`\u2713 Initialized .vm0/storage.yaml`));
|
|
@@ -9591,14 +9597,14 @@ import { Command as Command26 } from "commander";
|
|
|
9591
9597
|
// src/commands/artifact/init.ts
|
|
9592
9598
|
import { Command as Command20 } from "commander";
|
|
9593
9599
|
import chalk26 from "chalk";
|
|
9594
|
-
import
|
|
9600
|
+
import path10 from "path";
|
|
9595
9601
|
var initCommand2 = new Command20().name("init").description("Initialize an artifact in the current directory").option(
|
|
9596
9602
|
"-n, --name <name>",
|
|
9597
9603
|
"Artifact name (required in non-interactive mode)"
|
|
9598
9604
|
).action(
|
|
9599
9605
|
withErrorHandler(async (options) => {
|
|
9600
9606
|
const cwd = process.cwd();
|
|
9601
|
-
const dirName =
|
|
9607
|
+
const dirName = path10.basename(cwd);
|
|
9602
9608
|
const existingConfig = await readStorageConfig(cwd);
|
|
9603
9609
|
if (existingConfig) {
|
|
9604
9610
|
if (existingConfig.type === "artifact") {
|
|
@@ -9620,7 +9626,7 @@ var initCommand2 = new Command20().name("init").description("Initialize an artif
|
|
|
9620
9626
|
);
|
|
9621
9627
|
}
|
|
9622
9628
|
console.log(
|
|
9623
|
-
chalk26.dim(`Config file: ${
|
|
9629
|
+
chalk26.dim(`Config file: ${path10.join(cwd, ".vm0", "storage.yaml")}`)
|
|
9624
9630
|
);
|
|
9625
9631
|
return;
|
|
9626
9632
|
}
|
|
@@ -9669,7 +9675,7 @@ var initCommand2 = new Command20().name("init").description("Initialize an artif
|
|
|
9669
9675
|
console.log(chalk26.green(`\u2713 Initialized artifact: ${artifactName}`));
|
|
9670
9676
|
console.log(
|
|
9671
9677
|
chalk26.dim(
|
|
9672
|
-
` Config saved to ${
|
|
9678
|
+
` Config saved to ${path10.join(cwd, ".vm0", "storage.yaml")}`
|
|
9673
9679
|
)
|
|
9674
9680
|
);
|
|
9675
9681
|
})
|
|
@@ -9723,8 +9729,8 @@ var pushCommand2 = new Command21().name("push").description("Push local files to
|
|
|
9723
9729
|
// src/commands/artifact/pull.ts
|
|
9724
9730
|
import { Command as Command22 } from "commander";
|
|
9725
9731
|
import chalk28 from "chalk";
|
|
9726
|
-
import
|
|
9727
|
-
import * as
|
|
9732
|
+
import path11 from "path";
|
|
9733
|
+
import * as fs9 from "fs";
|
|
9728
9734
|
import * as os7 from "os";
|
|
9729
9735
|
import * as tar5 from "tar";
|
|
9730
9736
|
var pullCommand2 = new Command22().name("pull").description("Pull cloud artifact to local directory").argument("[versionId]", "Version ID to pull (default: latest)").action(
|
|
@@ -9772,9 +9778,9 @@ var pullCommand2 = new Command22().name("pull").description("Pull cloud artifact
|
|
|
9772
9778
|
const arrayBuffer = await s3Response.arrayBuffer();
|
|
9773
9779
|
const tarBuffer = Buffer.from(arrayBuffer);
|
|
9774
9780
|
console.log(chalk28.green(`\u2713 Downloaded ${formatBytes(tarBuffer.length)}`));
|
|
9775
|
-
const tmpDir =
|
|
9776
|
-
const tarPath =
|
|
9777
|
-
await
|
|
9781
|
+
const tmpDir = fs9.mkdtempSync(path11.join(os7.tmpdir(), "vm0-"));
|
|
9782
|
+
const tarPath = path11.join(tmpDir, "artifact.tar.gz");
|
|
9783
|
+
await fs9.promises.writeFile(tarPath, tarBuffer);
|
|
9778
9784
|
console.log(chalk28.dim("Syncing local files..."));
|
|
9779
9785
|
const remoteFiles = await listTarFiles(tarPath);
|
|
9780
9786
|
const remoteFilesSet = new Set(
|
|
@@ -9792,8 +9798,8 @@ var pullCommand2 = new Command22().name("pull").description("Pull cloud artifact
|
|
|
9792
9798
|
cwd,
|
|
9793
9799
|
gzip: true
|
|
9794
9800
|
});
|
|
9795
|
-
await
|
|
9796
|
-
await
|
|
9801
|
+
await fs9.promises.unlink(tarPath);
|
|
9802
|
+
await fs9.promises.rmdir(tmpDir);
|
|
9797
9803
|
console.log(chalk28.green(`\u2713 Extracted ${remoteFiles.length} files`));
|
|
9798
9804
|
})
|
|
9799
9805
|
);
|
|
@@ -9914,16 +9920,16 @@ import { Command as Command27, Option as Option5 } from "commander";
|
|
|
9914
9920
|
import chalk33 from "chalk";
|
|
9915
9921
|
import { readFile as readFile7, mkdir as mkdir6 } from "fs/promises";
|
|
9916
9922
|
import { existsSync as existsSync10 } from "fs";
|
|
9917
|
-
import
|
|
9923
|
+
import path12 from "path";
|
|
9918
9924
|
import { parse as parseYaml4 } from "yaml";
|
|
9919
9925
|
|
|
9920
9926
|
// src/lib/domain/cook-state.ts
|
|
9921
9927
|
import { homedir as homedir3 } from "os";
|
|
9922
|
-
import { join as
|
|
9928
|
+
import { join as join9 } from "path";
|
|
9923
9929
|
import { readFile as readFile6, writeFile as writeFile5, mkdir as mkdir5 } from "fs/promises";
|
|
9924
9930
|
import { existsSync as existsSync8 } from "fs";
|
|
9925
|
-
var CONFIG_DIR2 =
|
|
9926
|
-
var COOK_STATE_FILE =
|
|
9931
|
+
var CONFIG_DIR2 = join9(homedir3(), ".vm0");
|
|
9932
|
+
var COOK_STATE_FILE = join9(CONFIG_DIR2, "cook.json");
|
|
9927
9933
|
var STALE_THRESHOLD_MS = 48 * 60 * 60 * 1e3;
|
|
9928
9934
|
async function loadCookStateFile() {
|
|
9929
9935
|
if (!existsSync8(COOK_STATE_FILE)) {
|
|
@@ -10146,7 +10152,7 @@ async function processVolumes(config, cwd) {
|
|
|
10146
10152
|
console.log();
|
|
10147
10153
|
console.log(chalk33.bold("Processing volumes:"));
|
|
10148
10154
|
for (const volumeConfig of Object.values(config.volumes)) {
|
|
10149
|
-
const volumeDir =
|
|
10155
|
+
const volumeDir = path12.join(cwd, volumeConfig.name);
|
|
10150
10156
|
if (!existsSync10(volumeDir)) {
|
|
10151
10157
|
console.error(chalk33.red(`\u2717 Directory not found: ${volumeConfig.name}`));
|
|
10152
10158
|
console.error(chalk33.dim(" Create the directory and add files first"));
|
|
@@ -10180,7 +10186,7 @@ async function processVolumes(config, cwd) {
|
|
|
10180
10186
|
async function processArtifact(cwd) {
|
|
10181
10187
|
console.log();
|
|
10182
10188
|
console.log(chalk33.bold("Processing artifact:"));
|
|
10183
|
-
const artifactDir =
|
|
10189
|
+
const artifactDir = path12.join(cwd, ARTIFACT_DIR);
|
|
10184
10190
|
try {
|
|
10185
10191
|
if (!existsSync10(artifactDir)) {
|
|
10186
10192
|
printCommand(`mkdir ${ARTIFACT_DIR}`);
|
|
@@ -10264,7 +10270,7 @@ var cookAction = new Command27().name("cook").description("Quick start: prepare,
|
|
|
10264
10270
|
).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(
|
|
10265
10271
|
async (prompt, options) => {
|
|
10266
10272
|
if (options.autoUpdate !== false) {
|
|
10267
|
-
const shouldExit = await checkAndUpgrade("9.38.
|
|
10273
|
+
const shouldExit = await checkAndUpgrade("9.38.2", prompt);
|
|
10268
10274
|
if (shouldExit) {
|
|
10269
10275
|
process.exit(0);
|
|
10270
10276
|
}
|
|
@@ -10354,7 +10360,7 @@ var logsCommand = new Command28().name("logs").description("View logs from the l
|
|
|
10354
10360
|
// src/commands/cook/continue.ts
|
|
10355
10361
|
import { Command as Command29, Option as Option6 } from "commander";
|
|
10356
10362
|
import chalk35 from "chalk";
|
|
10357
|
-
import
|
|
10363
|
+
import path13 from "path";
|
|
10358
10364
|
var continueCommand2 = new Command29().name("continue").description(
|
|
10359
10365
|
"Continue from the last session (latest conversation and artifact)"
|
|
10360
10366
|
).argument("<prompt>", "Prompt for the continued agent").option(
|
|
@@ -10370,7 +10376,7 @@ var continueCommand2 = new Command29().name("continue").description(
|
|
|
10370
10376
|
process.exit(1);
|
|
10371
10377
|
}
|
|
10372
10378
|
const cwd = process.cwd();
|
|
10373
|
-
const artifactDir =
|
|
10379
|
+
const artifactDir = path13.join(cwd, ARTIFACT_DIR);
|
|
10374
10380
|
const envFileArg = options.envFile ? ` --env-file ${options.envFile}` : "";
|
|
10375
10381
|
printCommand(
|
|
10376
10382
|
`vm0 run continue${envFileArg} ${state.lastSessionId} "${prompt}"`
|
|
@@ -10419,7 +10425,7 @@ var continueCommand2 = new Command29().name("continue").description(
|
|
|
10419
10425
|
// src/commands/cook/resume.ts
|
|
10420
10426
|
import { Command as Command30, Option as Option7 } from "commander";
|
|
10421
10427
|
import chalk36 from "chalk";
|
|
10422
|
-
import
|
|
10428
|
+
import path14 from "path";
|
|
10423
10429
|
var resumeCommand2 = new Command30().name("resume").description(
|
|
10424
10430
|
"Resume from the last checkpoint (snapshotted conversation and artifact)"
|
|
10425
10431
|
).argument("<prompt>", "Prompt for the resumed agent").option(
|
|
@@ -10435,7 +10441,7 @@ var resumeCommand2 = new Command30().name("resume").description(
|
|
|
10435
10441
|
process.exit(1);
|
|
10436
10442
|
}
|
|
10437
10443
|
const cwd = process.cwd();
|
|
10438
|
-
const artifactDir =
|
|
10444
|
+
const artifactDir = path14.join(cwd, ARTIFACT_DIR);
|
|
10439
10445
|
const envFileArg = options.envFile ? ` --env-file ${options.envFile}` : "";
|
|
10440
10446
|
printCommand(
|
|
10441
10447
|
`vm0 run resume${envFileArg} ${state.lastCheckpointId} "${prompt}"`
|
|
@@ -10948,7 +10954,7 @@ import { Command as Command35 } from "commander";
|
|
|
10948
10954
|
import chalk40 from "chalk";
|
|
10949
10955
|
import { mkdtempSync as mkdtempSync5 } from "fs";
|
|
10950
10956
|
import { mkdir as mkdir7, writeFile as writeFile6, readdir, copyFile, rm as rm4 } from "fs/promises";
|
|
10951
|
-
import { join as
|
|
10957
|
+
import { join as join10, dirname as dirname3 } from "path";
|
|
10952
10958
|
import { tmpdir as tmpdir7 } from "os";
|
|
10953
10959
|
import * as tar6 from "tar";
|
|
10954
10960
|
import { stringify as yamlStringify } from "yaml";
|
|
@@ -10984,8 +10990,8 @@ async function downloadInstructions(agentName, instructionsPath, destination) {
|
|
|
10984
10990
|
throw new Error(`Failed to download instructions: ${response.status}`);
|
|
10985
10991
|
}
|
|
10986
10992
|
const buffer = Buffer.from(await response.arrayBuffer());
|
|
10987
|
-
const tmpDir = mkdtempSync5(
|
|
10988
|
-
const tarPath =
|
|
10993
|
+
const tmpDir = mkdtempSync5(join10(tmpdir7(), "vm0-clone-"));
|
|
10994
|
+
const tarPath = join10(tmpDir, "archive.tar.gz");
|
|
10989
10995
|
await writeFile6(tarPath, buffer);
|
|
10990
10996
|
await tar6.extract({ file: tarPath, cwd: tmpDir, gzip: true });
|
|
10991
10997
|
const files = await readdir(tmpDir);
|
|
@@ -10995,9 +11001,9 @@ async function downloadInstructions(agentName, instructionsPath, destination) {
|
|
|
10995
11001
|
await rm4(tmpDir, { recursive: true, force: true });
|
|
10996
11002
|
return false;
|
|
10997
11003
|
}
|
|
10998
|
-
const destPath =
|
|
11004
|
+
const destPath = join10(destination, instructionsPath);
|
|
10999
11005
|
await mkdir7(dirname3(destPath), { recursive: true });
|
|
11000
|
-
await copyFile(
|
|
11006
|
+
await copyFile(join10(tmpDir, mdFile), destPath);
|
|
11001
11007
|
await rm4(tmpDir, { recursive: true, force: true });
|
|
11002
11008
|
return true;
|
|
11003
11009
|
}
|
|
@@ -11023,7 +11029,7 @@ var cloneCommand3 = new Command35().name("clone").description("Clone agent compo
|
|
|
11023
11029
|
const cleanedContent = cleanComposeContent(content);
|
|
11024
11030
|
const yamlContent = yamlStringify(cleanedContent);
|
|
11025
11031
|
await mkdir7(targetDir, { recursive: true });
|
|
11026
|
-
const yamlPath =
|
|
11032
|
+
const yamlPath = join10(targetDir, "vm0.yaml");
|
|
11027
11033
|
await writeFile6(yamlPath, yamlContent, "utf8");
|
|
11028
11034
|
console.log(chalk40.green("\u2713 Created vm0.yaml"));
|
|
11029
11035
|
const agentKey = Object.keys(content.agents)[0];
|
|
@@ -11149,8 +11155,8 @@ import { Command as Command38 } from "commander";
|
|
|
11149
11155
|
import chalk43 from "chalk";
|
|
11150
11156
|
|
|
11151
11157
|
// src/lib/domain/source-derivation.ts
|
|
11152
|
-
import * as
|
|
11153
|
-
import * as
|
|
11158
|
+
import * as fs10 from "fs/promises";
|
|
11159
|
+
import * as path15 from "path";
|
|
11154
11160
|
import * as os8 from "os";
|
|
11155
11161
|
async function fetchSkillFrontmatter(skillUrl, tempDir) {
|
|
11156
11162
|
try {
|
|
@@ -11190,8 +11196,8 @@ async function deriveAgentVariableSources(agent, options) {
|
|
|
11190
11196
|
credentials: Array.from(credentialSources.values())
|
|
11191
11197
|
};
|
|
11192
11198
|
}
|
|
11193
|
-
const tempDir = await
|
|
11194
|
-
|
|
11199
|
+
const tempDir = await fs10.mkdtemp(
|
|
11200
|
+
path15.join(os8.tmpdir(), "vm0-source-derivation-")
|
|
11195
11201
|
);
|
|
11196
11202
|
try {
|
|
11197
11203
|
const skillResults = await Promise.all(
|
|
@@ -11224,7 +11230,7 @@ async function deriveAgentVariableSources(agent, options) {
|
|
|
11224
11230
|
}
|
|
11225
11231
|
}
|
|
11226
11232
|
} finally {
|
|
11227
|
-
await
|
|
11233
|
+
await fs10.rm(tempDir, { recursive: true, force: true });
|
|
11228
11234
|
}
|
|
11229
11235
|
return {
|
|
11230
11236
|
secrets: Array.from(secretSources.values()),
|
|
@@ -11701,7 +11707,7 @@ var agentCommand = new Command44().name("agent").description("Manage agent compo
|
|
|
11701
11707
|
// src/commands/init/index.ts
|
|
11702
11708
|
import { Command as Command45 } from "commander";
|
|
11703
11709
|
import chalk49 from "chalk";
|
|
11704
|
-
import
|
|
11710
|
+
import path16 from "path";
|
|
11705
11711
|
import { existsSync as existsSync11 } from "fs";
|
|
11706
11712
|
import { writeFile as writeFile7 } from "fs/promises";
|
|
11707
11713
|
var VM0_YAML_FILE = "vm0.yaml";
|
|
@@ -11758,7 +11764,7 @@ var initCommand3 = new Command45().name("init").description("Initialize a new VM
|
|
|
11758
11764
|
console.error(chalk49.dim(" Usage: vm0 init --name <agent-name>"));
|
|
11759
11765
|
process.exit(1);
|
|
11760
11766
|
} else {
|
|
11761
|
-
const dirName =
|
|
11767
|
+
const dirName = path16.basename(process.cwd());
|
|
11762
11768
|
const defaultName = validateAgentName(dirName) ? dirName : void 0;
|
|
11763
11769
|
const name = await promptText(
|
|
11764
11770
|
"Enter agent name",
|
|
@@ -13773,9 +13779,10 @@ import { initClient as initClient13 } from "@ts-rest/core";
|
|
|
13773
13779
|
|
|
13774
13780
|
// src/commands/connector/lib/computer/start-services.ts
|
|
13775
13781
|
import { spawn as spawn3 } from "child_process";
|
|
13782
|
+
import { access as access2, constants } from "fs/promises";
|
|
13776
13783
|
import { createServer } from "net";
|
|
13777
13784
|
import { homedir as homedir4 } from "os";
|
|
13778
|
-
import { join as
|
|
13785
|
+
import { join as join12 } from "path";
|
|
13779
13786
|
import chalk67 from "chalk";
|
|
13780
13787
|
|
|
13781
13788
|
// src/commands/connector/lib/computer/ngrok.ts
|
|
@@ -13797,6 +13804,18 @@ async function stopNgrokTunnels() {
|
|
|
13797
13804
|
}
|
|
13798
13805
|
|
|
13799
13806
|
// src/commands/connector/lib/computer/start-services.ts
|
|
13807
|
+
var CHROME_CANDIDATES = [
|
|
13808
|
+
// macOS absolute paths
|
|
13809
|
+
"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome",
|
|
13810
|
+
"/Applications/Google Chrome Canary.app/Contents/MacOS/Google Chrome Canary",
|
|
13811
|
+
"/Applications/Chromium.app/Contents/MacOS/Chromium",
|
|
13812
|
+
// Linux / PATH-based
|
|
13813
|
+
"google-chrome",
|
|
13814
|
+
"google-chrome-stable",
|
|
13815
|
+
"chromium-browser",
|
|
13816
|
+
"chromium",
|
|
13817
|
+
"chrome"
|
|
13818
|
+
];
|
|
13800
13819
|
async function getRandomPort() {
|
|
13801
13820
|
return new Promise((resolve, reject) => {
|
|
13802
13821
|
const server = createServer();
|
|
@@ -13807,37 +13826,51 @@ async function getRandomPort() {
|
|
|
13807
13826
|
server.on("error", reject);
|
|
13808
13827
|
});
|
|
13809
13828
|
}
|
|
13810
|
-
async function
|
|
13811
|
-
for (const
|
|
13812
|
-
|
|
13813
|
-
|
|
13814
|
-
|
|
13815
|
-
|
|
13816
|
-
|
|
13829
|
+
async function findBinary(...candidates) {
|
|
13830
|
+
for (const candidate of candidates) {
|
|
13831
|
+
if (candidate.startsWith("/")) {
|
|
13832
|
+
try {
|
|
13833
|
+
await access2(candidate, constants.X_OK);
|
|
13834
|
+
return candidate;
|
|
13835
|
+
} catch {
|
|
13836
|
+
}
|
|
13837
|
+
} else {
|
|
13838
|
+
const found = await new Promise((resolve) => {
|
|
13839
|
+
const child = spawn3("which", [candidate]);
|
|
13840
|
+
child.on("close", (code) => resolve(code === 0));
|
|
13841
|
+
});
|
|
13842
|
+
if (found) return candidate;
|
|
13843
|
+
}
|
|
13817
13844
|
}
|
|
13818
13845
|
return null;
|
|
13819
13846
|
}
|
|
13847
|
+
async function checkComputerDependencies() {
|
|
13848
|
+
const wsgidavBinary = await findBinary("wsgidav");
|
|
13849
|
+
if (!wsgidavBinary) {
|
|
13850
|
+
throw new Error(
|
|
13851
|
+
"wsgidav not found\n\nInstall with: pip install wsgidav[cheroot]"
|
|
13852
|
+
);
|
|
13853
|
+
}
|
|
13854
|
+
const chromeBinary = await findBinary(...CHROME_CANDIDATES);
|
|
13855
|
+
if (!chromeBinary) {
|
|
13856
|
+
throw new Error("Chrome not found\n\nInstall Google Chrome or Chromium");
|
|
13857
|
+
}
|
|
13858
|
+
}
|
|
13820
13859
|
async function startComputerServices(credentials) {
|
|
13821
13860
|
console.log(chalk67.cyan("Starting computer connector services..."));
|
|
13822
|
-
const wsgidavBinary = await
|
|
13861
|
+
const wsgidavBinary = await findBinary("wsgidav");
|
|
13823
13862
|
if (!wsgidavBinary) {
|
|
13824
13863
|
throw new Error(
|
|
13825
13864
|
"wsgidav not found\n\nInstall with: pip install wsgidav[cheroot]"
|
|
13826
13865
|
);
|
|
13827
13866
|
}
|
|
13828
|
-
const chromeBinary = await
|
|
13829
|
-
"google-chrome",
|
|
13830
|
-
"google-chrome-stable",
|
|
13831
|
-
"chromium",
|
|
13832
|
-
"chromium-browser",
|
|
13833
|
-
"chrome"
|
|
13834
|
-
);
|
|
13867
|
+
const chromeBinary = await findBinary(...CHROME_CANDIDATES);
|
|
13835
13868
|
if (!chromeBinary) {
|
|
13836
13869
|
throw new Error("Chrome not found\n\nInstall Google Chrome or Chromium");
|
|
13837
13870
|
}
|
|
13838
13871
|
const webdavPort = await getRandomPort();
|
|
13839
13872
|
const cdpPort = await getRandomPort();
|
|
13840
|
-
const downloadsPath =
|
|
13873
|
+
const downloadsPath = join12(homedir4(), "Downloads");
|
|
13841
13874
|
const wsgidav = spawn3(
|
|
13842
13875
|
wsgidavBinary,
|
|
13843
13876
|
[
|
|
@@ -13947,6 +13980,7 @@ var connectCommand = new Command67().name("connect").description("Connect a thir
|
|
|
13947
13980
|
const apiUrl = await getApiUrl();
|
|
13948
13981
|
const headers = await getHeaders2();
|
|
13949
13982
|
if (connectorType === "computer") {
|
|
13983
|
+
await checkComputerDependencies();
|
|
13950
13984
|
console.log(chalk68.cyan("Setting up computer connector..."));
|
|
13951
13985
|
const computerClient = initClient13(computerConnectorContract, {
|
|
13952
13986
|
baseUrl: apiUrl,
|
|
@@ -15164,7 +15198,7 @@ var preferenceCommand = new Command77().name("preference").description("View or
|
|
|
15164
15198
|
|
|
15165
15199
|
// src/index.ts
|
|
15166
15200
|
var program = new Command78();
|
|
15167
|
-
program.name("vm0").description("VM0 CLI - Build and run agents with natural language").version("9.38.
|
|
15201
|
+
program.name("vm0").description("VM0 CLI - Build and run agents with natural language").version("9.38.2");
|
|
15168
15202
|
program.addCommand(authCommand);
|
|
15169
15203
|
program.addCommand(infoCommand);
|
|
15170
15204
|
program.addCommand(composeCommand);
|