@vm0/cli 4.7.0 → 4.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.js +120 -432
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -167,9 +167,8 @@ async function checkAuthStatus() {
|
|
|
167
167
|
// src/commands/compose.ts
|
|
168
168
|
import { Command } from "commander";
|
|
169
169
|
import chalk2 from "chalk";
|
|
170
|
-
import { readFile as
|
|
170
|
+
import { readFile as readFile2 } from "fs/promises";
|
|
171
171
|
import { existsSync as existsSync2 } from "fs";
|
|
172
|
-
import { dirname as dirname2 } from "path";
|
|
173
172
|
import { parse as parseYaml } from "yaml";
|
|
174
173
|
|
|
175
174
|
// src/lib/api-client.ts
|
|
@@ -431,7 +430,7 @@ var ApiClient = class {
|
|
|
431
430
|
/**
|
|
432
431
|
* Generic GET request
|
|
433
432
|
*/
|
|
434
|
-
async get(
|
|
433
|
+
async get(path11) {
|
|
435
434
|
const baseUrl = await this.getBaseUrl();
|
|
436
435
|
const token = await getToken();
|
|
437
436
|
if (!token) {
|
|
@@ -444,7 +443,7 @@ var ApiClient = class {
|
|
|
444
443
|
if (bypassSecret) {
|
|
445
444
|
headers["x-vercel-protection-bypass"] = bypassSecret;
|
|
446
445
|
}
|
|
447
|
-
return fetch(`${baseUrl}${
|
|
446
|
+
return fetch(`${baseUrl}${path11}`, {
|
|
448
447
|
method: "GET",
|
|
449
448
|
headers
|
|
450
449
|
});
|
|
@@ -452,7 +451,7 @@ var ApiClient = class {
|
|
|
452
451
|
/**
|
|
453
452
|
* Generic POST request
|
|
454
453
|
*/
|
|
455
|
-
async post(
|
|
454
|
+
async post(path11, options) {
|
|
456
455
|
const baseUrl = await this.getBaseUrl();
|
|
457
456
|
const token = await getToken();
|
|
458
457
|
if (!token) {
|
|
@@ -468,7 +467,7 @@ var ApiClient = class {
|
|
|
468
467
|
if (bypassSecret) {
|
|
469
468
|
headers["x-vercel-protection-bypass"] = bypassSecret;
|
|
470
469
|
}
|
|
471
|
-
return fetch(`${baseUrl}${
|
|
470
|
+
return fetch(`${baseUrl}${path11}`, {
|
|
472
471
|
method: "POST",
|
|
473
472
|
headers,
|
|
474
473
|
body: options?.body
|
|
@@ -477,7 +476,7 @@ var ApiClient = class {
|
|
|
477
476
|
/**
|
|
478
477
|
* Generic DELETE request
|
|
479
478
|
*/
|
|
480
|
-
async delete(
|
|
479
|
+
async delete(path11) {
|
|
481
480
|
const baseUrl = await this.getBaseUrl();
|
|
482
481
|
const token = await getToken();
|
|
483
482
|
if (!token) {
|
|
@@ -490,7 +489,7 @@ var ApiClient = class {
|
|
|
490
489
|
if (bypassSecret) {
|
|
491
490
|
headers["x-vercel-protection-bypass"] = bypassSecret;
|
|
492
491
|
}
|
|
493
|
-
return fetch(`${baseUrl}${
|
|
492
|
+
return fetch(`${baseUrl}${path11}`, {
|
|
494
493
|
method: "DELETE",
|
|
495
494
|
headers
|
|
496
495
|
});
|
|
@@ -498,29 +497,11 @@ var ApiClient = class {
|
|
|
498
497
|
};
|
|
499
498
|
var apiClient = new ApiClient();
|
|
500
499
|
|
|
501
|
-
// src/lib/provider-config.ts
|
|
502
|
-
var PROVIDER_DEFAULTS = {
|
|
503
|
-
"claude-code": {
|
|
504
|
-
image: "vm0-claude-code-dev",
|
|
505
|
-
workingDir: "/home/user/workspace"
|
|
506
|
-
}
|
|
507
|
-
};
|
|
508
|
-
function getProviderDefaults(provider) {
|
|
509
|
-
return PROVIDER_DEFAULTS[provider];
|
|
510
|
-
}
|
|
511
|
-
function isProviderSupported(provider) {
|
|
512
|
-
return provider in PROVIDER_DEFAULTS;
|
|
513
|
-
}
|
|
514
|
-
|
|
515
500
|
// src/lib/yaml-validator.ts
|
|
516
501
|
function validateAgentName(name) {
|
|
517
502
|
const nameRegex = /^[a-zA-Z0-9]([a-zA-Z0-9-]{1,62}[a-zA-Z0-9])?$/;
|
|
518
503
|
return nameRegex.test(name);
|
|
519
504
|
}
|
|
520
|
-
function validateGitHubTreeUrl(url2) {
|
|
521
|
-
const githubTreeRegex = /^https:\/\/github\.com\/[a-zA-Z0-9_-]+\/[a-zA-Z0-9_.-]+\/tree\/[^/]+\/.+$/;
|
|
522
|
-
return githubTreeRegex.test(url2);
|
|
523
|
-
}
|
|
524
505
|
function validateVolumeConfig(volumeKey, volumeConfig) {
|
|
525
506
|
if (!volumeConfig || typeof volumeConfig !== "object") {
|
|
526
507
|
return `Volume "${volumeKey}" must be an object`;
|
|
@@ -576,73 +557,24 @@ function validateAgentCompose(config2) {
|
|
|
576
557
|
if (!agent || typeof agent !== "object") {
|
|
577
558
|
return { valid: false, error: "Agent definition must be an object" };
|
|
578
559
|
}
|
|
579
|
-
if (!agent.
|
|
560
|
+
if (!agent.working_dir || typeof agent.working_dir !== "string") {
|
|
580
561
|
return {
|
|
581
562
|
valid: false,
|
|
582
|
-
error: "Missing or invalid agent.
|
|
583
|
-
};
|
|
584
|
-
}
|
|
585
|
-
const providerIsSupported = isProviderSupported(agent.provider);
|
|
586
|
-
if (agent.image !== void 0 && typeof agent.image !== "string") {
|
|
587
|
-
return {
|
|
588
|
-
valid: false,
|
|
589
|
-
error: "agent.image must be a string if provided"
|
|
563
|
+
error: "Missing or invalid agent.working_dir (must be a string)"
|
|
590
564
|
};
|
|
591
565
|
}
|
|
592
|
-
if (!agent.image
|
|
566
|
+
if (!agent.image || typeof agent.image !== "string") {
|
|
593
567
|
return {
|
|
594
568
|
valid: false,
|
|
595
|
-
error: "Missing agent.image (
|
|
569
|
+
error: "Missing or invalid agent.image (must be a string)"
|
|
596
570
|
};
|
|
597
571
|
}
|
|
598
|
-
if (agent.
|
|
599
|
-
return {
|
|
600
|
-
valid: false,
|
|
601
|
-
error: "agent.working_dir must be a string if provided"
|
|
602
|
-
};
|
|
603
|
-
}
|
|
604
|
-
if (!agent.working_dir && !providerIsSupported) {
|
|
572
|
+
if (!agent.provider || typeof agent.provider !== "string") {
|
|
605
573
|
return {
|
|
606
574
|
valid: false,
|
|
607
|
-
error: "Missing agent.
|
|
575
|
+
error: "Missing or invalid agent.provider (must be a string)"
|
|
608
576
|
};
|
|
609
577
|
}
|
|
610
|
-
if (agent.system_prompt !== void 0) {
|
|
611
|
-
if (typeof agent.system_prompt !== "string") {
|
|
612
|
-
return {
|
|
613
|
-
valid: false,
|
|
614
|
-
error: "agent.system_prompt must be a string (path to AGENTS.md file)"
|
|
615
|
-
};
|
|
616
|
-
}
|
|
617
|
-
if (agent.system_prompt.length === 0) {
|
|
618
|
-
return {
|
|
619
|
-
valid: false,
|
|
620
|
-
error: "agent.system_prompt cannot be empty"
|
|
621
|
-
};
|
|
622
|
-
}
|
|
623
|
-
}
|
|
624
|
-
if (agent.system_skills !== void 0) {
|
|
625
|
-
if (!Array.isArray(agent.system_skills)) {
|
|
626
|
-
return {
|
|
627
|
-
valid: false,
|
|
628
|
-
error: "agent.system_skills must be an array of GitHub tree URLs"
|
|
629
|
-
};
|
|
630
|
-
}
|
|
631
|
-
for (const skillUrl of agent.system_skills) {
|
|
632
|
-
if (typeof skillUrl !== "string") {
|
|
633
|
-
return {
|
|
634
|
-
valid: false,
|
|
635
|
-
error: "Each system_skill must be a string URL"
|
|
636
|
-
};
|
|
637
|
-
}
|
|
638
|
-
if (!validateGitHubTreeUrl(skillUrl)) {
|
|
639
|
-
return {
|
|
640
|
-
valid: false,
|
|
641
|
-
error: `Invalid system_skill URL: ${skillUrl}. Expected format: https://github.com/{owner}/{repo}/tree/{branch}/{path}`
|
|
642
|
-
};
|
|
643
|
-
}
|
|
644
|
-
}
|
|
645
|
-
}
|
|
646
578
|
if (agent.environment !== void 0) {
|
|
647
579
|
if (agent.environment === null || typeof agent.environment !== "object" || Array.isArray(agent.environment)) {
|
|
648
580
|
return {
|
|
@@ -700,175 +632,6 @@ function validateAgentCompose(config2) {
|
|
|
700
632
|
return { valid: true };
|
|
701
633
|
}
|
|
702
634
|
|
|
703
|
-
// src/lib/system-storage.ts
|
|
704
|
-
import * as fs2 from "fs/promises";
|
|
705
|
-
import * as path2 from "path";
|
|
706
|
-
import * as os2 from "os";
|
|
707
|
-
import * as tar from "tar";
|
|
708
|
-
|
|
709
|
-
// src/lib/github-skills.ts
|
|
710
|
-
import * as fs from "fs/promises";
|
|
711
|
-
import * as path from "path";
|
|
712
|
-
import * as os from "os";
|
|
713
|
-
import { exec } from "child_process";
|
|
714
|
-
import { promisify } from "util";
|
|
715
|
-
var execAsync = promisify(exec);
|
|
716
|
-
function parseGitHubTreeUrl(url2) {
|
|
717
|
-
const fullPathMatch = url2.match(/^https:\/\/github\.com\/(.+)$/);
|
|
718
|
-
if (!fullPathMatch) {
|
|
719
|
-
throw new Error(
|
|
720
|
-
`Invalid GitHub URL: ${url2}. Expected format: https://github.com/{owner}/{repo}/tree/{branch}/{path}`
|
|
721
|
-
);
|
|
722
|
-
}
|
|
723
|
-
const fullPath = fullPathMatch[1];
|
|
724
|
-
const regex = /^https:\/\/github\.com\/([^/]+)\/([^/]+)\/tree\/([^/]+)\/(.+)$/;
|
|
725
|
-
const match = url2.match(regex);
|
|
726
|
-
if (!match) {
|
|
727
|
-
throw new Error(
|
|
728
|
-
`Invalid GitHub tree URL: ${url2}. Expected format: https://github.com/{owner}/{repo}/tree/{branch}/{path}`
|
|
729
|
-
);
|
|
730
|
-
}
|
|
731
|
-
const [, owner, repo, branch, pathPart] = match;
|
|
732
|
-
const pathSegments = pathPart.split("/");
|
|
733
|
-
const skillName = pathSegments[pathSegments.length - 1];
|
|
734
|
-
return {
|
|
735
|
-
owner,
|
|
736
|
-
repo,
|
|
737
|
-
branch,
|
|
738
|
-
path: pathPart,
|
|
739
|
-
skillName,
|
|
740
|
-
fullPath
|
|
741
|
-
};
|
|
742
|
-
}
|
|
743
|
-
function getSkillStorageName(parsed) {
|
|
744
|
-
return `system-skill@${parsed.fullPath}`;
|
|
745
|
-
}
|
|
746
|
-
function getSystemPromptStorageName(composeName) {
|
|
747
|
-
return `system-prompt@${composeName}`;
|
|
748
|
-
}
|
|
749
|
-
async function downloadGitHubSkill(parsed, destDir) {
|
|
750
|
-
const repoUrl = `https://github.com/${parsed.owner}/${parsed.repo}.git`;
|
|
751
|
-
const skillDir = path.join(destDir, parsed.skillName);
|
|
752
|
-
const tempDir = await fs.mkdtemp(path.join(os.tmpdir(), "vm0-skill-"));
|
|
753
|
-
try {
|
|
754
|
-
await execAsync(`git init`, { cwd: tempDir });
|
|
755
|
-
await execAsync(`git remote add origin "${repoUrl}"`, { cwd: tempDir });
|
|
756
|
-
await execAsync(`git config core.sparseCheckout true`, { cwd: tempDir });
|
|
757
|
-
const sparseFile = path.join(tempDir, ".git", "info", "sparse-checkout");
|
|
758
|
-
await fs.writeFile(sparseFile, parsed.path + "\n");
|
|
759
|
-
await execAsync(`git fetch --depth 1 origin "${parsed.branch}"`, {
|
|
760
|
-
cwd: tempDir
|
|
761
|
-
});
|
|
762
|
-
await execAsync(`git checkout "${parsed.branch}"`, { cwd: tempDir });
|
|
763
|
-
const fetchedPath = path.join(tempDir, parsed.path);
|
|
764
|
-
await fs.mkdir(path.dirname(skillDir), { recursive: true });
|
|
765
|
-
await fs.rename(fetchedPath, skillDir);
|
|
766
|
-
return skillDir;
|
|
767
|
-
} finally {
|
|
768
|
-
await fs.rm(tempDir, { recursive: true, force: true });
|
|
769
|
-
}
|
|
770
|
-
}
|
|
771
|
-
async function validateSkillDirectory(skillDir) {
|
|
772
|
-
const skillMdPath = path.join(skillDir, "SKILL.md");
|
|
773
|
-
try {
|
|
774
|
-
await fs.access(skillMdPath);
|
|
775
|
-
} catch {
|
|
776
|
-
throw new Error(
|
|
777
|
-
`Skill directory missing required SKILL.md file: ${skillDir}`
|
|
778
|
-
);
|
|
779
|
-
}
|
|
780
|
-
}
|
|
781
|
-
|
|
782
|
-
// src/lib/system-storage.ts
|
|
783
|
-
async function uploadSystemPrompt(agentName, promptFilePath, basePath) {
|
|
784
|
-
const storageName = getSystemPromptStorageName(agentName);
|
|
785
|
-
const absolutePath = path2.isAbsolute(promptFilePath) ? promptFilePath : path2.join(basePath, promptFilePath);
|
|
786
|
-
const content = await fs2.readFile(absolutePath, "utf8");
|
|
787
|
-
const tmpDir = await fs2.mkdtemp(path2.join(os2.tmpdir(), "vm0-prompt-"));
|
|
788
|
-
const promptDir = path2.join(tmpDir, "prompt");
|
|
789
|
-
await fs2.mkdir(promptDir);
|
|
790
|
-
await fs2.writeFile(path2.join(promptDir, "CLAUDE.md"), content);
|
|
791
|
-
try {
|
|
792
|
-
const tarPath = path2.join(tmpDir, "prompt.tar.gz");
|
|
793
|
-
await tar.create(
|
|
794
|
-
{
|
|
795
|
-
gzip: true,
|
|
796
|
-
file: tarPath,
|
|
797
|
-
cwd: promptDir
|
|
798
|
-
},
|
|
799
|
-
["."]
|
|
800
|
-
);
|
|
801
|
-
const tarBuffer = await fs2.readFile(tarPath);
|
|
802
|
-
const formData = new FormData();
|
|
803
|
-
formData.append("name", storageName);
|
|
804
|
-
formData.append("type", "volume");
|
|
805
|
-
formData.append(
|
|
806
|
-
"file",
|
|
807
|
-
new Blob([tarBuffer], { type: "application/gzip" }),
|
|
808
|
-
"volume.tar.gz"
|
|
809
|
-
);
|
|
810
|
-
const response = await apiClient.post("/api/storages", {
|
|
811
|
-
body: formData
|
|
812
|
-
});
|
|
813
|
-
if (!response.ok) {
|
|
814
|
-
const errorBody = await response.json();
|
|
815
|
-
const errorMessage = typeof errorBody.error === "string" ? errorBody.error : errorBody.error?.message || "Upload failed";
|
|
816
|
-
throw new Error(errorMessage);
|
|
817
|
-
}
|
|
818
|
-
const result = await response.json();
|
|
819
|
-
return {
|
|
820
|
-
name: storageName,
|
|
821
|
-
versionId: result.versionId,
|
|
822
|
-
action: result.deduplicated ? "deduplicated" : "created"
|
|
823
|
-
};
|
|
824
|
-
} finally {
|
|
825
|
-
await fs2.rm(tmpDir, { recursive: true, force: true });
|
|
826
|
-
}
|
|
827
|
-
}
|
|
828
|
-
async function uploadSystemSkill(skillUrl) {
|
|
829
|
-
const parsed = parseGitHubTreeUrl(skillUrl);
|
|
830
|
-
const storageName = getSkillStorageName(parsed);
|
|
831
|
-
const tmpDir = await fs2.mkdtemp(path2.join(os2.tmpdir(), "vm0-skill-"));
|
|
832
|
-
try {
|
|
833
|
-
const skillDir = await downloadGitHubSkill(parsed, tmpDir);
|
|
834
|
-
await validateSkillDirectory(skillDir);
|
|
835
|
-
const tarPath = path2.join(tmpDir, "skill.tar.gz");
|
|
836
|
-
await tar.create(
|
|
837
|
-
{
|
|
838
|
-
gzip: true,
|
|
839
|
-
file: tarPath,
|
|
840
|
-
cwd: skillDir
|
|
841
|
-
},
|
|
842
|
-
["."]
|
|
843
|
-
);
|
|
844
|
-
const tarBuffer = await fs2.readFile(tarPath);
|
|
845
|
-
const formData = new FormData();
|
|
846
|
-
formData.append("name", storageName);
|
|
847
|
-
formData.append("type", "volume");
|
|
848
|
-
formData.append(
|
|
849
|
-
"file",
|
|
850
|
-
new Blob([tarBuffer], { type: "application/gzip" }),
|
|
851
|
-
"volume.tar.gz"
|
|
852
|
-
);
|
|
853
|
-
const response = await apiClient.post("/api/storages", {
|
|
854
|
-
body: formData
|
|
855
|
-
});
|
|
856
|
-
if (!response.ok) {
|
|
857
|
-
const errorBody = await response.json();
|
|
858
|
-
const errorMessage = typeof errorBody.error === "string" ? errorBody.error : errorBody.error?.message || "Upload failed";
|
|
859
|
-
throw new Error(errorMessage);
|
|
860
|
-
}
|
|
861
|
-
const result = await response.json();
|
|
862
|
-
return {
|
|
863
|
-
name: storageName,
|
|
864
|
-
versionId: result.versionId,
|
|
865
|
-
action: result.deduplicated ? "deduplicated" : "created"
|
|
866
|
-
};
|
|
867
|
-
} finally {
|
|
868
|
-
await fs2.rm(tmpDir, { recursive: true, force: true });
|
|
869
|
-
}
|
|
870
|
-
}
|
|
871
|
-
|
|
872
635
|
// src/commands/compose.ts
|
|
873
636
|
var composeCommand = new Command().name("compose").description("Create or update agent compose").argument("<config-file>", "Path to config YAML file").action(async (configFile) => {
|
|
874
637
|
try {
|
|
@@ -876,7 +639,7 @@ var composeCommand = new Command().name("compose").description("Create or update
|
|
|
876
639
|
console.error(chalk2.red(`\u2717 Config file not found: ${configFile}`));
|
|
877
640
|
process.exit(1);
|
|
878
641
|
}
|
|
879
|
-
const content = await
|
|
642
|
+
const content = await readFile2(configFile, "utf8");
|
|
880
643
|
let config2;
|
|
881
644
|
try {
|
|
882
645
|
config2 = parseYaml(content);
|
|
@@ -892,75 +655,6 @@ var composeCommand = new Command().name("compose").description("Create or update
|
|
|
892
655
|
console.error(chalk2.red(`\u2717 ${validation.error}`));
|
|
893
656
|
process.exit(1);
|
|
894
657
|
}
|
|
895
|
-
const cfg = config2;
|
|
896
|
-
const agents = cfg.agents;
|
|
897
|
-
const agentName = Object.keys(agents)[0];
|
|
898
|
-
const agent = agents[agentName];
|
|
899
|
-
const basePath = dirname2(configFile);
|
|
900
|
-
if (agent.provider) {
|
|
901
|
-
const defaults = getProviderDefaults(agent.provider);
|
|
902
|
-
if (defaults) {
|
|
903
|
-
if (!agent.image) {
|
|
904
|
-
agent.image = defaults.image;
|
|
905
|
-
console.log(
|
|
906
|
-
chalk2.gray(` Auto-configured image: ${defaults.image}`)
|
|
907
|
-
);
|
|
908
|
-
}
|
|
909
|
-
if (!agent.working_dir) {
|
|
910
|
-
agent.working_dir = defaults.workingDir;
|
|
911
|
-
console.log(
|
|
912
|
-
chalk2.gray(
|
|
913
|
-
` Auto-configured working_dir: ${defaults.workingDir}`
|
|
914
|
-
)
|
|
915
|
-
);
|
|
916
|
-
}
|
|
917
|
-
}
|
|
918
|
-
}
|
|
919
|
-
if (agent.system_prompt) {
|
|
920
|
-
const promptPath = agent.system_prompt;
|
|
921
|
-
console.log(chalk2.blue(`Uploading system prompt: ${promptPath}`));
|
|
922
|
-
try {
|
|
923
|
-
const result = await uploadSystemPrompt(
|
|
924
|
-
agentName,
|
|
925
|
-
promptPath,
|
|
926
|
-
basePath
|
|
927
|
-
);
|
|
928
|
-
console.log(
|
|
929
|
-
chalk2.green(
|
|
930
|
-
`\u2713 System prompt ${result.action === "deduplicated" ? "(unchanged)" : "uploaded"}: ${result.versionId.slice(0, 8)}`
|
|
931
|
-
)
|
|
932
|
-
);
|
|
933
|
-
} catch (error43) {
|
|
934
|
-
console.error(chalk2.red(`\u2717 Failed to upload system prompt`));
|
|
935
|
-
if (error43 instanceof Error) {
|
|
936
|
-
console.error(chalk2.gray(` ${error43.message}`));
|
|
937
|
-
}
|
|
938
|
-
process.exit(1);
|
|
939
|
-
}
|
|
940
|
-
}
|
|
941
|
-
if (agent.system_skills && Array.isArray(agent.system_skills)) {
|
|
942
|
-
const skillUrls = agent.system_skills;
|
|
943
|
-
console.log(
|
|
944
|
-
chalk2.blue(`Uploading ${skillUrls.length} system skill(s)...`)
|
|
945
|
-
);
|
|
946
|
-
for (const skillUrl of skillUrls) {
|
|
947
|
-
try {
|
|
948
|
-
console.log(chalk2.gray(` Downloading: ${skillUrl}`));
|
|
949
|
-
const result = await uploadSystemSkill(skillUrl);
|
|
950
|
-
console.log(
|
|
951
|
-
chalk2.green(
|
|
952
|
-
` \u2713 Skill ${result.action === "deduplicated" ? "(unchanged)" : "uploaded"}: ${result.versionId.slice(0, 8)}`
|
|
953
|
-
)
|
|
954
|
-
);
|
|
955
|
-
} catch (error43) {
|
|
956
|
-
console.error(chalk2.red(`\u2717 Failed to upload skill: ${skillUrl}`));
|
|
957
|
-
if (error43 instanceof Error) {
|
|
958
|
-
console.error(chalk2.gray(` ${error43.message}`));
|
|
959
|
-
}
|
|
960
|
-
process.exit(1);
|
|
961
|
-
}
|
|
962
|
-
}
|
|
963
|
-
}
|
|
964
658
|
console.log(chalk2.blue("Uploading compose..."));
|
|
965
659
|
const response = await apiClient.createOrUpdateCompose({
|
|
966
660
|
content: config2
|
|
@@ -1001,8 +695,8 @@ var composeCommand = new Command().name("compose").description("Create or update
|
|
|
1001
695
|
// src/commands/run.ts
|
|
1002
696
|
import { Command as Command2 } from "commander";
|
|
1003
697
|
import chalk4 from "chalk";
|
|
1004
|
-
import * as
|
|
1005
|
-
import * as
|
|
698
|
+
import * as fs from "fs";
|
|
699
|
+
import * as path from "path";
|
|
1006
700
|
import { config as dotenvConfig } from "dotenv";
|
|
1007
701
|
|
|
1008
702
|
// src/lib/event-parser.ts
|
|
@@ -2083,10 +1777,10 @@ function mergeDefs(...defs) {
|
|
|
2083
1777
|
function cloneDef(schema) {
|
|
2084
1778
|
return mergeDefs(schema._zod.def);
|
|
2085
1779
|
}
|
|
2086
|
-
function getElementAtPath(obj,
|
|
2087
|
-
if (!
|
|
1780
|
+
function getElementAtPath(obj, path11) {
|
|
1781
|
+
if (!path11)
|
|
2088
1782
|
return obj;
|
|
2089
|
-
return
|
|
1783
|
+
return path11.reduce((acc, key) => acc?.[key], obj);
|
|
2090
1784
|
}
|
|
2091
1785
|
function promiseAllObject(promisesObj) {
|
|
2092
1786
|
const keys = Object.keys(promisesObj);
|
|
@@ -2445,11 +2139,11 @@ function aborted(x, startIndex = 0) {
|
|
|
2445
2139
|
}
|
|
2446
2140
|
return false;
|
|
2447
2141
|
}
|
|
2448
|
-
function prefixIssues(
|
|
2142
|
+
function prefixIssues(path11, issues) {
|
|
2449
2143
|
return issues.map((iss) => {
|
|
2450
2144
|
var _a;
|
|
2451
2145
|
(_a = iss).path ?? (_a.path = []);
|
|
2452
|
-
iss.path.unshift(
|
|
2146
|
+
iss.path.unshift(path11);
|
|
2453
2147
|
return iss;
|
|
2454
2148
|
});
|
|
2455
2149
|
}
|
|
@@ -2617,7 +2311,7 @@ function treeifyError(error43, _mapper) {
|
|
|
2617
2311
|
return issue2.message;
|
|
2618
2312
|
};
|
|
2619
2313
|
const result = { errors: [] };
|
|
2620
|
-
const processError = (error44,
|
|
2314
|
+
const processError = (error44, path11 = []) => {
|
|
2621
2315
|
var _a, _b;
|
|
2622
2316
|
for (const issue2 of error44.issues) {
|
|
2623
2317
|
if (issue2.code === "invalid_union" && issue2.errors.length) {
|
|
@@ -2627,7 +2321,7 @@ function treeifyError(error43, _mapper) {
|
|
|
2627
2321
|
} else if (issue2.code === "invalid_element") {
|
|
2628
2322
|
processError({ issues: issue2.issues }, issue2.path);
|
|
2629
2323
|
} else {
|
|
2630
|
-
const fullpath = [...
|
|
2324
|
+
const fullpath = [...path11, ...issue2.path];
|
|
2631
2325
|
if (fullpath.length === 0) {
|
|
2632
2326
|
result.errors.push(mapper(issue2));
|
|
2633
2327
|
continue;
|
|
@@ -2659,8 +2353,8 @@ function treeifyError(error43, _mapper) {
|
|
|
2659
2353
|
}
|
|
2660
2354
|
function toDotPath(_path) {
|
|
2661
2355
|
const segs = [];
|
|
2662
|
-
const
|
|
2663
|
-
for (const seg of
|
|
2356
|
+
const path11 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
|
|
2357
|
+
for (const seg of path11) {
|
|
2664
2358
|
if (typeof seg === "number")
|
|
2665
2359
|
segs.push(`[${seg}]`);
|
|
2666
2360
|
else if (typeof seg === "symbol")
|
|
@@ -13457,12 +13151,10 @@ var volumeConfigSchema = external_exports.object({
|
|
|
13457
13151
|
});
|
|
13458
13152
|
var agentDefinitionSchema = external_exports.object({
|
|
13459
13153
|
description: external_exports.string().optional(),
|
|
13460
|
-
image: external_exports.string().
|
|
13461
|
-
// Optional when provider is specified (auto-resolved)
|
|
13154
|
+
image: external_exports.string().min(1, "Image is required"),
|
|
13462
13155
|
provider: external_exports.string().min(1, "Provider is required"),
|
|
13463
13156
|
volumes: external_exports.array(external_exports.string()).optional(),
|
|
13464
|
-
working_dir: external_exports.string().
|
|
13465
|
-
// Optional when provider is specified (defaults to /home/user/workspace)
|
|
13157
|
+
working_dir: external_exports.string().min(1, "Working directory is required"),
|
|
13466
13158
|
environment: external_exports.record(external_exports.string(), external_exports.string()).optional(),
|
|
13467
13159
|
/**
|
|
13468
13160
|
* Enable network security mode for secrets.
|
|
@@ -13470,11 +13162,7 @@ var agentDefinitionSchema = external_exports.object({
|
|
|
13470
13162
|
* is routed through mitmproxy -> VM0 Proxy for decryption.
|
|
13471
13163
|
* Default: false (plaintext secrets in env vars)
|
|
13472
13164
|
*/
|
|
13473
|
-
beta_network_security: external_exports.boolean().optional().default(false)
|
|
13474
|
-
system_prompt: external_exports.string().optional(),
|
|
13475
|
-
// Path to AGENTS.md file
|
|
13476
|
-
system_skills: external_exports.array(external_exports.string()).optional()
|
|
13477
|
-
// GitHub tree URLs for skills
|
|
13165
|
+
beta_network_security: external_exports.boolean().optional().default(false)
|
|
13478
13166
|
});
|
|
13479
13167
|
var agentComposeContentSchema = external_exports.object({
|
|
13480
13168
|
version: external_exports.string().min(1, "Version is required"),
|
|
@@ -14526,9 +14214,9 @@ function loadValues(cliValues, configNames) {
|
|
|
14526
14214
|
const result = { ...cliValues };
|
|
14527
14215
|
const missingNames = configNames.filter((name) => !(name in result));
|
|
14528
14216
|
if (missingNames.length > 0) {
|
|
14529
|
-
const envFilePath =
|
|
14217
|
+
const envFilePath = path.resolve(process.cwd(), ".env");
|
|
14530
14218
|
let dotenvValues = {};
|
|
14531
|
-
if (
|
|
14219
|
+
if (fs.existsSync(envFilePath)) {
|
|
14532
14220
|
const dotenvResult = dotenvConfig({ path: envFilePath });
|
|
14533
14221
|
if (dotenvResult.parsed) {
|
|
14534
14222
|
dotenvValues = Object.fromEntries(
|
|
@@ -15008,13 +14696,13 @@ import { Command as Command6 } from "commander";
|
|
|
15008
14696
|
// src/commands/volume/init.ts
|
|
15009
14697
|
import { Command as Command3 } from "commander";
|
|
15010
14698
|
import chalk5 from "chalk";
|
|
15011
|
-
import
|
|
14699
|
+
import path3 from "path";
|
|
15012
14700
|
|
|
15013
14701
|
// src/lib/storage-utils.ts
|
|
15014
|
-
import { readFile as
|
|
14702
|
+
import { readFile as readFile3, writeFile as writeFile2, mkdir as mkdir2 } from "fs/promises";
|
|
15015
14703
|
import { existsSync as existsSync4 } from "fs";
|
|
15016
14704
|
import { parse as parseYaml2, stringify as stringifyYaml } from "yaml";
|
|
15017
|
-
import
|
|
14705
|
+
import path2 from "path";
|
|
15018
14706
|
var CONFIG_DIR2 = ".vm0";
|
|
15019
14707
|
var CONFIG_FILE2 = "storage.yaml";
|
|
15020
14708
|
function isValidStorageName(name) {
|
|
@@ -15025,8 +14713,8 @@ function isValidStorageName(name) {
|
|
|
15025
14713
|
return pattern.test(name) && !name.includes("--");
|
|
15026
14714
|
}
|
|
15027
14715
|
async function readStorageConfig(basePath = process.cwd()) {
|
|
15028
|
-
const configPath =
|
|
15029
|
-
const legacyConfigPath =
|
|
14716
|
+
const configPath = path2.join(basePath, CONFIG_DIR2, CONFIG_FILE2);
|
|
14717
|
+
const legacyConfigPath = path2.join(basePath, CONFIG_DIR2, "volume.yaml");
|
|
15030
14718
|
let actualPath = null;
|
|
15031
14719
|
if (existsSync4(configPath)) {
|
|
15032
14720
|
actualPath = configPath;
|
|
@@ -15036,7 +14724,7 @@ async function readStorageConfig(basePath = process.cwd()) {
|
|
|
15036
14724
|
if (!actualPath) {
|
|
15037
14725
|
return null;
|
|
15038
14726
|
}
|
|
15039
|
-
const content = await
|
|
14727
|
+
const content = await readFile3(actualPath, "utf8");
|
|
15040
14728
|
const config2 = parseYaml2(content);
|
|
15041
14729
|
if (!config2.type) {
|
|
15042
14730
|
config2.type = "volume";
|
|
@@ -15044,31 +14732,31 @@ async function readStorageConfig(basePath = process.cwd()) {
|
|
|
15044
14732
|
return config2;
|
|
15045
14733
|
}
|
|
15046
14734
|
async function writeStorageConfig(storageName, basePath = process.cwd(), type = "volume") {
|
|
15047
|
-
const configDir =
|
|
15048
|
-
const configPath =
|
|
14735
|
+
const configDir = path2.join(basePath, CONFIG_DIR2);
|
|
14736
|
+
const configPath = path2.join(configDir, CONFIG_FILE2);
|
|
15049
14737
|
if (!existsSync4(configDir)) {
|
|
15050
|
-
await
|
|
14738
|
+
await mkdir2(configDir, { recursive: true });
|
|
15051
14739
|
}
|
|
15052
14740
|
const config2 = {
|
|
15053
14741
|
name: storageName,
|
|
15054
14742
|
type
|
|
15055
14743
|
};
|
|
15056
14744
|
const yamlContent = stringifyYaml(config2);
|
|
15057
|
-
await
|
|
14745
|
+
await writeFile2(configPath, yamlContent, "utf8");
|
|
15058
14746
|
}
|
|
15059
14747
|
|
|
15060
14748
|
// src/commands/volume/init.ts
|
|
15061
14749
|
var initCommand = new Command3().name("init").description("Initialize a volume in the current directory").action(async () => {
|
|
15062
14750
|
try {
|
|
15063
14751
|
const cwd = process.cwd();
|
|
15064
|
-
const dirName =
|
|
14752
|
+
const dirName = path3.basename(cwd);
|
|
15065
14753
|
const existingConfig = await readStorageConfig(cwd);
|
|
15066
14754
|
if (existingConfig) {
|
|
15067
14755
|
console.log(
|
|
15068
14756
|
chalk5.yellow(`Volume already initialized: ${existingConfig.name}`)
|
|
15069
14757
|
);
|
|
15070
14758
|
console.log(
|
|
15071
|
-
chalk5.gray(`Config file: ${
|
|
14759
|
+
chalk5.gray(`Config file: ${path3.join(cwd, ".vm0", "storage.yaml")}`)
|
|
15072
14760
|
);
|
|
15073
14761
|
return;
|
|
15074
14762
|
}
|
|
@@ -15089,7 +14777,7 @@ var initCommand = new Command3().name("init").description("Initialize a volume i
|
|
|
15089
14777
|
console.log(chalk5.green(`\u2713 Initialized volume: ${volumeName}`));
|
|
15090
14778
|
console.log(
|
|
15091
14779
|
chalk5.gray(
|
|
15092
|
-
`\u2713 Config saved to ${
|
|
14780
|
+
`\u2713 Config saved to ${path3.join(cwd, ".vm0", "storage.yaml")}`
|
|
15093
14781
|
)
|
|
15094
14782
|
);
|
|
15095
14783
|
} catch (error43) {
|
|
@@ -15104,15 +14792,15 @@ var initCommand = new Command3().name("init").description("Initialize a volume i
|
|
|
15104
14792
|
// src/commands/volume/push.ts
|
|
15105
14793
|
import { Command as Command4 } from "commander";
|
|
15106
14794
|
import chalk6 from "chalk";
|
|
15107
|
-
import
|
|
15108
|
-
import * as
|
|
15109
|
-
import * as
|
|
15110
|
-
import * as
|
|
14795
|
+
import path5 from "path";
|
|
14796
|
+
import * as fs3 from "fs";
|
|
14797
|
+
import * as os from "os";
|
|
14798
|
+
import * as tar2 from "tar";
|
|
15111
14799
|
|
|
15112
14800
|
// src/lib/file-utils.ts
|
|
15113
|
-
import * as
|
|
15114
|
-
import * as
|
|
15115
|
-
import * as
|
|
14801
|
+
import * as fs2 from "fs";
|
|
14802
|
+
import * as path4 from "path";
|
|
14803
|
+
import * as tar from "tar";
|
|
15116
14804
|
function excludeVm0Filter(filePath) {
|
|
15117
14805
|
const shouldExclude = filePath === ".vm0" || filePath.startsWith(".vm0/") || filePath.startsWith("./.vm0");
|
|
15118
14806
|
return !shouldExclude;
|
|
@@ -15120,7 +14808,7 @@ function excludeVm0Filter(filePath) {
|
|
|
15120
14808
|
function listTarFiles(tarPath) {
|
|
15121
14809
|
return new Promise((resolve2, reject) => {
|
|
15122
14810
|
const files = [];
|
|
15123
|
-
|
|
14811
|
+
tar.list({
|
|
15124
14812
|
file: tarPath,
|
|
15125
14813
|
onReadEntry: (entry) => {
|
|
15126
14814
|
if (entry.type === "File") {
|
|
@@ -15133,14 +14821,14 @@ function listTarFiles(tarPath) {
|
|
|
15133
14821
|
async function listLocalFiles(dir, excludeDirs = [".vm0"]) {
|
|
15134
14822
|
const files = [];
|
|
15135
14823
|
async function walkDir(currentDir, relativePath = "") {
|
|
15136
|
-
const entries = await
|
|
14824
|
+
const entries = await fs2.promises.readdir(currentDir, {
|
|
15137
14825
|
withFileTypes: true
|
|
15138
14826
|
});
|
|
15139
14827
|
for (const entry of entries) {
|
|
15140
|
-
const entryRelativePath = relativePath ?
|
|
14828
|
+
const entryRelativePath = relativePath ? path4.join(relativePath, entry.name) : entry.name;
|
|
15141
14829
|
if (entry.isDirectory()) {
|
|
15142
14830
|
if (!excludeDirs.includes(entry.name)) {
|
|
15143
|
-
await walkDir(
|
|
14831
|
+
await walkDir(path4.join(currentDir, entry.name), entryRelativePath);
|
|
15144
14832
|
}
|
|
15145
14833
|
} else {
|
|
15146
14834
|
files.push(entryRelativePath);
|
|
@@ -15156,8 +14844,8 @@ async function removeExtraFiles(dir, remoteFiles, excludeDirs = [".vm0"]) {
|
|
|
15156
14844
|
for (const localFile of localFiles) {
|
|
15157
14845
|
const normalizedPath = localFile.replace(/\\/g, "/");
|
|
15158
14846
|
if (!remoteFiles.has(normalizedPath)) {
|
|
15159
|
-
const fullPath =
|
|
15160
|
-
await
|
|
14847
|
+
const fullPath = path4.join(dir, localFile);
|
|
14848
|
+
await fs2.promises.unlink(fullPath);
|
|
15161
14849
|
removedCount++;
|
|
15162
14850
|
}
|
|
15163
14851
|
}
|
|
@@ -15165,17 +14853,17 @@ async function removeExtraFiles(dir, remoteFiles, excludeDirs = [".vm0"]) {
|
|
|
15165
14853
|
return removedCount;
|
|
15166
14854
|
}
|
|
15167
14855
|
async function removeEmptyDirs(dir, excludeDirs = [".vm0"]) {
|
|
15168
|
-
const entries = await
|
|
14856
|
+
const entries = await fs2.promises.readdir(dir, { withFileTypes: true });
|
|
15169
14857
|
let isEmpty = true;
|
|
15170
14858
|
for (const entry of entries) {
|
|
15171
|
-
const fullPath =
|
|
14859
|
+
const fullPath = path4.join(dir, entry.name);
|
|
15172
14860
|
if (entry.isDirectory()) {
|
|
15173
14861
|
if (excludeDirs.includes(entry.name)) {
|
|
15174
14862
|
isEmpty = false;
|
|
15175
14863
|
} else {
|
|
15176
14864
|
const subDirEmpty = await removeEmptyDirs(fullPath, excludeDirs);
|
|
15177
14865
|
if (subDirEmpty) {
|
|
15178
|
-
await
|
|
14866
|
+
await fs2.promises.rmdir(fullPath);
|
|
15179
14867
|
} else {
|
|
15180
14868
|
isEmpty = false;
|
|
15181
14869
|
}
|
|
@@ -15190,10 +14878,10 @@ async function removeEmptyDirs(dir, excludeDirs = [".vm0"]) {
|
|
|
15190
14878
|
// src/commands/volume/push.ts
|
|
15191
14879
|
async function getAllFiles(dirPath, baseDir = dirPath) {
|
|
15192
14880
|
const files = [];
|
|
15193
|
-
const entries = await
|
|
14881
|
+
const entries = await fs3.promises.readdir(dirPath, { withFileTypes: true });
|
|
15194
14882
|
for (const entry of entries) {
|
|
15195
|
-
const fullPath =
|
|
15196
|
-
const relativePath =
|
|
14883
|
+
const fullPath = path5.join(dirPath, entry.name);
|
|
14884
|
+
const relativePath = path5.relative(baseDir, fullPath);
|
|
15197
14885
|
if (relativePath.startsWith(".vm0")) {
|
|
15198
14886
|
continue;
|
|
15199
14887
|
}
|
|
@@ -15230,7 +14918,7 @@ var pushCommand = new Command4().name("push").description("Push local files to c
|
|
|
15230
14918
|
const files = await getAllFiles(cwd);
|
|
15231
14919
|
let totalSize = 0;
|
|
15232
14920
|
for (const file2 of files) {
|
|
15233
|
-
const stats = await
|
|
14921
|
+
const stats = await fs3.promises.stat(file2);
|
|
15234
14922
|
totalSize += stats.size;
|
|
15235
14923
|
}
|
|
15236
14924
|
if (files.length === 0) {
|
|
@@ -15241,11 +14929,11 @@ var pushCommand = new Command4().name("push").description("Push local files to c
|
|
|
15241
14929
|
);
|
|
15242
14930
|
}
|
|
15243
14931
|
console.log(chalk6.gray("Compressing files..."));
|
|
15244
|
-
const tmpDir =
|
|
15245
|
-
const tarPath =
|
|
15246
|
-
const relativePaths = files.map((file2) =>
|
|
14932
|
+
const tmpDir = fs3.mkdtempSync(path5.join(os.tmpdir(), "vm0-"));
|
|
14933
|
+
const tarPath = path5.join(tmpDir, "volume.tar.gz");
|
|
14934
|
+
const relativePaths = files.map((file2) => path5.relative(cwd, file2));
|
|
15247
14935
|
if (relativePaths.length > 0) {
|
|
15248
|
-
await
|
|
14936
|
+
await tar2.create(
|
|
15249
14937
|
{
|
|
15250
14938
|
gzip: true,
|
|
15251
14939
|
file: tarPath,
|
|
@@ -15254,7 +14942,7 @@ var pushCommand = new Command4().name("push").description("Push local files to c
|
|
|
15254
14942
|
relativePaths
|
|
15255
14943
|
);
|
|
15256
14944
|
} else {
|
|
15257
|
-
await
|
|
14945
|
+
await tar2.create(
|
|
15258
14946
|
{
|
|
15259
14947
|
gzip: true,
|
|
15260
14948
|
file: tarPath,
|
|
@@ -15264,9 +14952,9 @@ var pushCommand = new Command4().name("push").description("Push local files to c
|
|
|
15264
14952
|
["."]
|
|
15265
14953
|
);
|
|
15266
14954
|
}
|
|
15267
|
-
const tarBuffer = await
|
|
15268
|
-
await
|
|
15269
|
-
await
|
|
14955
|
+
const tarBuffer = await fs3.promises.readFile(tarPath);
|
|
14956
|
+
await fs3.promises.unlink(tarPath);
|
|
14957
|
+
await fs3.promises.rmdir(tmpDir);
|
|
15270
14958
|
console.log(
|
|
15271
14959
|
chalk6.green(`\u2713 Compressed to ${formatBytes(tarBuffer.length)}`)
|
|
15272
14960
|
);
|
|
@@ -15312,10 +15000,10 @@ var pushCommand = new Command4().name("push").description("Push local files to c
|
|
|
15312
15000
|
// src/commands/volume/pull.ts
|
|
15313
15001
|
import { Command as Command5 } from "commander";
|
|
15314
15002
|
import chalk7 from "chalk";
|
|
15315
|
-
import
|
|
15316
|
-
import * as
|
|
15317
|
-
import * as
|
|
15318
|
-
import * as
|
|
15003
|
+
import path6 from "path";
|
|
15004
|
+
import * as fs4 from "fs";
|
|
15005
|
+
import * as os2 from "os";
|
|
15006
|
+
import * as tar3 from "tar";
|
|
15319
15007
|
function formatBytes2(bytes) {
|
|
15320
15008
|
if (bytes === 0) return "0 B";
|
|
15321
15009
|
const k = 1024;
|
|
@@ -15365,9 +15053,9 @@ var pullCommand = new Command5().name("pull").description("Pull cloud files to l
|
|
|
15365
15053
|
const arrayBuffer = await response.arrayBuffer();
|
|
15366
15054
|
const tarBuffer = Buffer.from(arrayBuffer);
|
|
15367
15055
|
console.log(chalk7.green(`\u2713 Downloaded ${formatBytes2(tarBuffer.length)}`));
|
|
15368
|
-
const tmpDir =
|
|
15369
|
-
const tarPath =
|
|
15370
|
-
await
|
|
15056
|
+
const tmpDir = fs4.mkdtempSync(path6.join(os2.tmpdir(), "vm0-"));
|
|
15057
|
+
const tarPath = path6.join(tmpDir, "volume.tar.gz");
|
|
15058
|
+
await fs4.promises.writeFile(tarPath, tarBuffer);
|
|
15371
15059
|
console.log(chalk7.gray("Syncing local files..."));
|
|
15372
15060
|
const remoteFiles = await listTarFiles(tarPath);
|
|
15373
15061
|
const remoteFilesSet = new Set(
|
|
@@ -15380,13 +15068,13 @@ var pullCommand = new Command5().name("pull").description("Pull cloud files to l
|
|
|
15380
15068
|
);
|
|
15381
15069
|
}
|
|
15382
15070
|
console.log(chalk7.gray("Extracting files..."));
|
|
15383
|
-
await
|
|
15071
|
+
await tar3.extract({
|
|
15384
15072
|
file: tarPath,
|
|
15385
15073
|
cwd,
|
|
15386
15074
|
gzip: true
|
|
15387
15075
|
});
|
|
15388
|
-
await
|
|
15389
|
-
await
|
|
15076
|
+
await fs4.promises.unlink(tarPath);
|
|
15077
|
+
await fs4.promises.rmdir(tmpDir);
|
|
15390
15078
|
console.log(chalk7.green(`\u2713 Extracted ${remoteFiles.length} files`));
|
|
15391
15079
|
} catch (error43) {
|
|
15392
15080
|
console.error(chalk7.red("\u2717 Pull failed"));
|
|
@@ -15406,11 +15094,11 @@ import { Command as Command10 } from "commander";
|
|
|
15406
15094
|
// src/commands/artifact/init.ts
|
|
15407
15095
|
import { Command as Command7 } from "commander";
|
|
15408
15096
|
import chalk8 from "chalk";
|
|
15409
|
-
import
|
|
15097
|
+
import path7 from "path";
|
|
15410
15098
|
var initCommand2 = new Command7().name("init").description("Initialize an artifact in the current directory").action(async () => {
|
|
15411
15099
|
try {
|
|
15412
15100
|
const cwd = process.cwd();
|
|
15413
|
-
const dirName =
|
|
15101
|
+
const dirName = path7.basename(cwd);
|
|
15414
15102
|
const existingConfig = await readStorageConfig(cwd);
|
|
15415
15103
|
if (existingConfig) {
|
|
15416
15104
|
if (existingConfig.type === "artifact") {
|
|
@@ -15432,7 +15120,7 @@ var initCommand2 = new Command7().name("init").description("Initialize an artifa
|
|
|
15432
15120
|
);
|
|
15433
15121
|
}
|
|
15434
15122
|
console.log(
|
|
15435
|
-
chalk8.gray(`Config file: ${
|
|
15123
|
+
chalk8.gray(`Config file: ${path7.join(cwd, ".vm0", "storage.yaml")}`)
|
|
15436
15124
|
);
|
|
15437
15125
|
return;
|
|
15438
15126
|
}
|
|
@@ -15453,7 +15141,7 @@ var initCommand2 = new Command7().name("init").description("Initialize an artifa
|
|
|
15453
15141
|
console.log(chalk8.green(`\u2713 Initialized artifact: ${artifactName}`));
|
|
15454
15142
|
console.log(
|
|
15455
15143
|
chalk8.gray(
|
|
15456
|
-
`\u2713 Config saved to ${
|
|
15144
|
+
`\u2713 Config saved to ${path7.join(cwd, ".vm0", "storage.yaml")}`
|
|
15457
15145
|
)
|
|
15458
15146
|
);
|
|
15459
15147
|
} catch (error43) {
|
|
@@ -15468,16 +15156,16 @@ var initCommand2 = new Command7().name("init").description("Initialize an artifa
|
|
|
15468
15156
|
// src/commands/artifact/push.ts
|
|
15469
15157
|
import { Command as Command8 } from "commander";
|
|
15470
15158
|
import chalk9 from "chalk";
|
|
15471
|
-
import
|
|
15472
|
-
import * as
|
|
15473
|
-
import * as
|
|
15474
|
-
import * as
|
|
15159
|
+
import path8 from "path";
|
|
15160
|
+
import * as fs5 from "fs";
|
|
15161
|
+
import * as os3 from "os";
|
|
15162
|
+
import * as tar4 from "tar";
|
|
15475
15163
|
async function getAllFiles2(dirPath, baseDir = dirPath) {
|
|
15476
15164
|
const files = [];
|
|
15477
|
-
const entries = await
|
|
15165
|
+
const entries = await fs5.promises.readdir(dirPath, { withFileTypes: true });
|
|
15478
15166
|
for (const entry of entries) {
|
|
15479
|
-
const fullPath =
|
|
15480
|
-
const relativePath =
|
|
15167
|
+
const fullPath = path8.join(dirPath, entry.name);
|
|
15168
|
+
const relativePath = path8.relative(baseDir, fullPath);
|
|
15481
15169
|
if (relativePath.startsWith(".vm0")) {
|
|
15482
15170
|
continue;
|
|
15483
15171
|
}
|
|
@@ -15523,7 +15211,7 @@ var pushCommand2 = new Command8().name("push").description("Push local files to
|
|
|
15523
15211
|
const files = await getAllFiles2(cwd);
|
|
15524
15212
|
let totalSize = 0;
|
|
15525
15213
|
for (const file2 of files) {
|
|
15526
|
-
const stats = await
|
|
15214
|
+
const stats = await fs5.promises.stat(file2);
|
|
15527
15215
|
totalSize += stats.size;
|
|
15528
15216
|
}
|
|
15529
15217
|
if (files.length === 0) {
|
|
@@ -15534,11 +15222,11 @@ var pushCommand2 = new Command8().name("push").description("Push local files to
|
|
|
15534
15222
|
);
|
|
15535
15223
|
}
|
|
15536
15224
|
console.log(chalk9.gray("Compressing files..."));
|
|
15537
|
-
const tmpDir =
|
|
15538
|
-
const tarPath =
|
|
15539
|
-
const relativePaths = files.map((file2) =>
|
|
15225
|
+
const tmpDir = fs5.mkdtempSync(path8.join(os3.tmpdir(), "vm0-"));
|
|
15226
|
+
const tarPath = path8.join(tmpDir, "artifact.tar.gz");
|
|
15227
|
+
const relativePaths = files.map((file2) => path8.relative(cwd, file2));
|
|
15540
15228
|
if (relativePaths.length > 0) {
|
|
15541
|
-
await
|
|
15229
|
+
await tar4.create(
|
|
15542
15230
|
{
|
|
15543
15231
|
gzip: true,
|
|
15544
15232
|
file: tarPath,
|
|
@@ -15547,7 +15235,7 @@ var pushCommand2 = new Command8().name("push").description("Push local files to
|
|
|
15547
15235
|
relativePaths
|
|
15548
15236
|
);
|
|
15549
15237
|
} else {
|
|
15550
|
-
await
|
|
15238
|
+
await tar4.create(
|
|
15551
15239
|
{
|
|
15552
15240
|
gzip: true,
|
|
15553
15241
|
file: tarPath,
|
|
@@ -15557,9 +15245,9 @@ var pushCommand2 = new Command8().name("push").description("Push local files to
|
|
|
15557
15245
|
["."]
|
|
15558
15246
|
);
|
|
15559
15247
|
}
|
|
15560
|
-
const tarBuffer = await
|
|
15561
|
-
await
|
|
15562
|
-
await
|
|
15248
|
+
const tarBuffer = await fs5.promises.readFile(tarPath);
|
|
15249
|
+
await fs5.promises.unlink(tarPath);
|
|
15250
|
+
await fs5.promises.rmdir(tmpDir);
|
|
15563
15251
|
console.log(
|
|
15564
15252
|
chalk9.green(`\u2713 Compressed to ${formatBytes3(tarBuffer.length)}`)
|
|
15565
15253
|
);
|
|
@@ -15604,10 +15292,10 @@ var pushCommand2 = new Command8().name("push").description("Push local files to
|
|
|
15604
15292
|
// src/commands/artifact/pull.ts
|
|
15605
15293
|
import { Command as Command9 } from "commander";
|
|
15606
15294
|
import chalk10 from "chalk";
|
|
15607
|
-
import
|
|
15608
|
-
import * as
|
|
15609
|
-
import * as
|
|
15610
|
-
import * as
|
|
15295
|
+
import path9 from "path";
|
|
15296
|
+
import * as fs6 from "fs";
|
|
15297
|
+
import * as os4 from "os";
|
|
15298
|
+
import * as tar5 from "tar";
|
|
15611
15299
|
function formatBytes4(bytes) {
|
|
15612
15300
|
if (bytes === 0) return "0 B";
|
|
15613
15301
|
const k = 1024;
|
|
@@ -15668,9 +15356,9 @@ var pullCommand2 = new Command9().name("pull").description("Pull cloud artifact
|
|
|
15668
15356
|
const arrayBuffer = await response.arrayBuffer();
|
|
15669
15357
|
const tarBuffer = Buffer.from(arrayBuffer);
|
|
15670
15358
|
console.log(chalk10.green(`\u2713 Downloaded ${formatBytes4(tarBuffer.length)}`));
|
|
15671
|
-
const tmpDir =
|
|
15672
|
-
const tarPath =
|
|
15673
|
-
await
|
|
15359
|
+
const tmpDir = fs6.mkdtempSync(path9.join(os4.tmpdir(), "vm0-"));
|
|
15360
|
+
const tarPath = path9.join(tmpDir, "artifact.tar.gz");
|
|
15361
|
+
await fs6.promises.writeFile(tarPath, tarBuffer);
|
|
15674
15362
|
console.log(chalk10.gray("Syncing local files..."));
|
|
15675
15363
|
const remoteFiles = await listTarFiles(tarPath);
|
|
15676
15364
|
const remoteFilesSet = new Set(
|
|
@@ -15683,13 +15371,13 @@ var pullCommand2 = new Command9().name("pull").description("Pull cloud artifact
|
|
|
15683
15371
|
);
|
|
15684
15372
|
}
|
|
15685
15373
|
console.log(chalk10.gray("Extracting files..."));
|
|
15686
|
-
await
|
|
15374
|
+
await tar5.extract({
|
|
15687
15375
|
file: tarPath,
|
|
15688
15376
|
cwd,
|
|
15689
15377
|
gzip: true
|
|
15690
15378
|
});
|
|
15691
|
-
await
|
|
15692
|
-
await
|
|
15379
|
+
await fs6.promises.unlink(tarPath);
|
|
15380
|
+
await fs6.promises.rmdir(tmpDir);
|
|
15693
15381
|
console.log(chalk10.green(`\u2713 Extracted ${remoteFiles.length} files`));
|
|
15694
15382
|
} catch (error43) {
|
|
15695
15383
|
console.error(chalk10.red("\u2717 Pull failed"));
|
|
@@ -15706,9 +15394,9 @@ var artifactCommand = new Command10().name("artifact").description("Manage cloud
|
|
|
15706
15394
|
// src/commands/cook.ts
|
|
15707
15395
|
import { Command as Command11 } from "commander";
|
|
15708
15396
|
import chalk11 from "chalk";
|
|
15709
|
-
import { readFile as
|
|
15397
|
+
import { readFile as readFile4, mkdir as mkdir3 } from "fs/promises";
|
|
15710
15398
|
import { existsSync as existsSync5 } from "fs";
|
|
15711
|
-
import
|
|
15399
|
+
import path10 from "path";
|
|
15712
15400
|
import { spawn } from "child_process";
|
|
15713
15401
|
import { parse as parseYaml3 } from "yaml";
|
|
15714
15402
|
var CONFIG_FILE3 = "vm0.yaml";
|
|
@@ -15797,7 +15485,7 @@ var cookCommand = new Command11().name("cook").description("One-click agent prep
|
|
|
15797
15485
|
}
|
|
15798
15486
|
let config2;
|
|
15799
15487
|
try {
|
|
15800
|
-
const content = await
|
|
15488
|
+
const content = await readFile4(CONFIG_FILE3, "utf8");
|
|
15801
15489
|
config2 = parseYaml3(content);
|
|
15802
15490
|
} catch (error43) {
|
|
15803
15491
|
console.error(chalk11.red("\u2717 Invalid YAML format"));
|
|
@@ -15821,7 +15509,7 @@ var cookCommand = new Command11().name("cook").description("One-click agent prep
|
|
|
15821
15509
|
console.log();
|
|
15822
15510
|
console.log(chalk11.blue("Processing volumes..."));
|
|
15823
15511
|
for (const volumeConfig of Object.values(config2.volumes)) {
|
|
15824
|
-
const volumeDir =
|
|
15512
|
+
const volumeDir = path10.join(cwd, volumeConfig.name);
|
|
15825
15513
|
console.log(chalk11.gray(` ${volumeConfig.name}/`));
|
|
15826
15514
|
if (!existsSync5(volumeDir)) {
|
|
15827
15515
|
console.error(
|
|
@@ -15856,11 +15544,11 @@ var cookCommand = new Command11().name("cook").description("One-click agent prep
|
|
|
15856
15544
|
}
|
|
15857
15545
|
console.log();
|
|
15858
15546
|
console.log(chalk11.blue("Processing artifact..."));
|
|
15859
|
-
const artifactDir =
|
|
15547
|
+
const artifactDir = path10.join(cwd, ARTIFACT_DIR);
|
|
15860
15548
|
console.log(chalk11.gray(` ${ARTIFACT_DIR}/`));
|
|
15861
15549
|
try {
|
|
15862
15550
|
if (!existsSync5(artifactDir)) {
|
|
15863
|
-
await
|
|
15551
|
+
await mkdir3(artifactDir, { recursive: true });
|
|
15864
15552
|
console.log(chalk11.green(` \u2713 Created directory`));
|
|
15865
15553
|
}
|
|
15866
15554
|
const existingConfig = await readStorageConfig(artifactDir);
|
|
@@ -15952,7 +15640,7 @@ import { Command as Command15 } from "commander";
|
|
|
15952
15640
|
// src/commands/image/build.ts
|
|
15953
15641
|
import { Command as Command12 } from "commander";
|
|
15954
15642
|
import chalk12 from "chalk";
|
|
15955
|
-
import { readFile as
|
|
15643
|
+
import { readFile as readFile5 } from "fs/promises";
|
|
15956
15644
|
import { existsSync as existsSync6 } from "fs";
|
|
15957
15645
|
var sleep = (ms) => new Promise((resolve2) => setTimeout(resolve2, ms));
|
|
15958
15646
|
var buildCommand = new Command12().name("build").description("Build a custom image from a Dockerfile").requiredOption("-f, --file <path>", "Path to Dockerfile").requiredOption("-n, --name <name>", "Name for the image").option("--delete-existing", "Delete existing image before building").action(
|
|
@@ -15980,7 +15668,7 @@ var buildCommand = new Command12().name("build").description("Build a custom ima
|
|
|
15980
15668
|
process.exit(1);
|
|
15981
15669
|
}
|
|
15982
15670
|
try {
|
|
15983
|
-
const dockerfile = await
|
|
15671
|
+
const dockerfile = await readFile5(file2, "utf8");
|
|
15984
15672
|
console.log(chalk12.blue(`Building image: ${name}`));
|
|
15985
15673
|
console.log(chalk12.gray(` Dockerfile: ${file2}`));
|
|
15986
15674
|
console.log();
|
|
@@ -16404,7 +16092,7 @@ function handleError(error43, runId) {
|
|
|
16404
16092
|
|
|
16405
16093
|
// src/index.ts
|
|
16406
16094
|
var program = new Command17();
|
|
16407
|
-
program.name("vm0").description("VM0 CLI - A modern build tool").version("4.7.
|
|
16095
|
+
program.name("vm0").description("VM0 CLI - A modern build tool").version("4.7.1");
|
|
16408
16096
|
program.command("info").description("Display environment information").action(async () => {
|
|
16409
16097
|
console.log(chalk16.cyan("System Information:"));
|
|
16410
16098
|
console.log(`Node Version: ${process.version}`);
|