@vm0/cli 1.5.0 → 1.8.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 +419 -113
- package/package.json +6 -1
package/index.js
CHANGED
|
@@ -736,15 +736,15 @@ function mergeDefs(...defs) {
|
|
|
736
736
|
function cloneDef(schema) {
|
|
737
737
|
return mergeDefs(schema._zod.def);
|
|
738
738
|
}
|
|
739
|
-
function getElementAtPath(obj,
|
|
740
|
-
if (!
|
|
739
|
+
function getElementAtPath(obj, path9) {
|
|
740
|
+
if (!path9)
|
|
741
741
|
return obj;
|
|
742
|
-
return
|
|
742
|
+
return path9.reduce((acc, key) => acc?.[key], obj);
|
|
743
743
|
}
|
|
744
744
|
function promiseAllObject(promisesObj) {
|
|
745
745
|
const keys = Object.keys(promisesObj);
|
|
746
|
-
const
|
|
747
|
-
return Promise.all(
|
|
746
|
+
const promises6 = keys.map((key) => promisesObj[key]);
|
|
747
|
+
return Promise.all(promises6).then((results) => {
|
|
748
748
|
const resolvedObj = {};
|
|
749
749
|
for (let i = 0; i < keys.length; i++) {
|
|
750
750
|
resolvedObj[keys[i]] = results[i];
|
|
@@ -1098,11 +1098,11 @@ function aborted(x, startIndex = 0) {
|
|
|
1098
1098
|
}
|
|
1099
1099
|
return false;
|
|
1100
1100
|
}
|
|
1101
|
-
function prefixIssues(
|
|
1101
|
+
function prefixIssues(path9, issues) {
|
|
1102
1102
|
return issues.map((iss) => {
|
|
1103
1103
|
var _a;
|
|
1104
1104
|
(_a = iss).path ?? (_a.path = []);
|
|
1105
|
-
iss.path.unshift(
|
|
1105
|
+
iss.path.unshift(path9);
|
|
1106
1106
|
return iss;
|
|
1107
1107
|
});
|
|
1108
1108
|
}
|
|
@@ -1270,7 +1270,7 @@ function treeifyError(error43, _mapper) {
|
|
|
1270
1270
|
return issue2.message;
|
|
1271
1271
|
};
|
|
1272
1272
|
const result = { errors: [] };
|
|
1273
|
-
const processError = (error44,
|
|
1273
|
+
const processError = (error44, path9 = []) => {
|
|
1274
1274
|
var _a, _b;
|
|
1275
1275
|
for (const issue2 of error44.issues) {
|
|
1276
1276
|
if (issue2.code === "invalid_union" && issue2.errors.length) {
|
|
@@ -1280,7 +1280,7 @@ function treeifyError(error43, _mapper) {
|
|
|
1280
1280
|
} else if (issue2.code === "invalid_element") {
|
|
1281
1281
|
processError({ issues: issue2.issues }, issue2.path);
|
|
1282
1282
|
} else {
|
|
1283
|
-
const fullpath = [...
|
|
1283
|
+
const fullpath = [...path9, ...issue2.path];
|
|
1284
1284
|
if (fullpath.length === 0) {
|
|
1285
1285
|
result.errors.push(mapper(issue2));
|
|
1286
1286
|
continue;
|
|
@@ -1312,8 +1312,8 @@ function treeifyError(error43, _mapper) {
|
|
|
1312
1312
|
}
|
|
1313
1313
|
function toDotPath(_path) {
|
|
1314
1314
|
const segs = [];
|
|
1315
|
-
const
|
|
1316
|
-
for (const seg of
|
|
1315
|
+
const path9 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
|
|
1316
|
+
for (const seg of path9) {
|
|
1317
1317
|
if (typeof seg === "number")
|
|
1318
1318
|
segs.push(`[${seg}]`);
|
|
1319
1319
|
else if (typeof seg === "symbol")
|
|
@@ -12413,10 +12413,37 @@ var ApiClient = class {
|
|
|
12413
12413
|
}
|
|
12414
12414
|
return await response.json();
|
|
12415
12415
|
}
|
|
12416
|
+
async continueSession(body) {
|
|
12417
|
+
const baseUrl = await this.getBaseUrl();
|
|
12418
|
+
const headers = await this.getHeaders();
|
|
12419
|
+
const response = await fetch(`${baseUrl}/api/agent/runs/continue`, {
|
|
12420
|
+
method: "POST",
|
|
12421
|
+
headers,
|
|
12422
|
+
body: JSON.stringify(body)
|
|
12423
|
+
});
|
|
12424
|
+
if (!response.ok) {
|
|
12425
|
+
const error43 = await response.json();
|
|
12426
|
+
throw new Error(error43.error?.message || "Failed to continue session");
|
|
12427
|
+
}
|
|
12428
|
+
return await response.json();
|
|
12429
|
+
}
|
|
12430
|
+
async getAgentSession(id) {
|
|
12431
|
+
const baseUrl = await this.getBaseUrl();
|
|
12432
|
+
const headers = await this.getHeaders();
|
|
12433
|
+
const response = await fetch(`${baseUrl}/api/agent/sessions/${id}`, {
|
|
12434
|
+
method: "GET",
|
|
12435
|
+
headers
|
|
12436
|
+
});
|
|
12437
|
+
if (!response.ok) {
|
|
12438
|
+
const error43 = await response.json();
|
|
12439
|
+
throw new Error(error43.error?.message || "Failed to get agent session");
|
|
12440
|
+
}
|
|
12441
|
+
return await response.json();
|
|
12442
|
+
}
|
|
12416
12443
|
/**
|
|
12417
12444
|
* Generic GET request
|
|
12418
12445
|
*/
|
|
12419
|
-
async get(
|
|
12446
|
+
async get(path9) {
|
|
12420
12447
|
const baseUrl = await this.getBaseUrl();
|
|
12421
12448
|
const token = await getToken();
|
|
12422
12449
|
if (!token) {
|
|
@@ -12429,7 +12456,7 @@ var ApiClient = class {
|
|
|
12429
12456
|
if (bypassSecret) {
|
|
12430
12457
|
headers["x-vercel-protection-bypass"] = bypassSecret;
|
|
12431
12458
|
}
|
|
12432
|
-
return fetch(`${baseUrl}${
|
|
12459
|
+
return fetch(`${baseUrl}${path9}`, {
|
|
12433
12460
|
method: "GET",
|
|
12434
12461
|
headers
|
|
12435
12462
|
});
|
|
@@ -12437,7 +12464,7 @@ var ApiClient = class {
|
|
|
12437
12464
|
/**
|
|
12438
12465
|
* Generic POST request
|
|
12439
12466
|
*/
|
|
12440
|
-
async post(
|
|
12467
|
+
async post(path9, options) {
|
|
12441
12468
|
const baseUrl = await this.getBaseUrl();
|
|
12442
12469
|
const token = await getToken();
|
|
12443
12470
|
if (!token) {
|
|
@@ -12450,7 +12477,7 @@ var ApiClient = class {
|
|
|
12450
12477
|
if (bypassSecret) {
|
|
12451
12478
|
headers["x-vercel-protection-bypass"] = bypassSecret;
|
|
12452
12479
|
}
|
|
12453
|
-
return fetch(`${baseUrl}${
|
|
12480
|
+
return fetch(`${baseUrl}${path9}`, {
|
|
12454
12481
|
method: "POST",
|
|
12455
12482
|
headers,
|
|
12456
12483
|
body: options?.body
|
|
@@ -12464,6 +12491,19 @@ function validateAgentName(name) {
|
|
|
12464
12491
|
const nameRegex = /^[a-zA-Z0-9]([a-zA-Z0-9-]{1,62}[a-zA-Z0-9])?$/;
|
|
12465
12492
|
return nameRegex.test(name);
|
|
12466
12493
|
}
|
|
12494
|
+
function validateVolumeConfig(volumeKey, volumeConfig) {
|
|
12495
|
+
if (!volumeConfig || typeof volumeConfig !== "object") {
|
|
12496
|
+
return `Volume "${volumeKey}" must be an object`;
|
|
12497
|
+
}
|
|
12498
|
+
const vol = volumeConfig;
|
|
12499
|
+
if (!vol.name || typeof vol.name !== "string") {
|
|
12500
|
+
return `Volume "${volumeKey}" must have a 'name' field (string)`;
|
|
12501
|
+
}
|
|
12502
|
+
if (!vol.version || typeof vol.version !== "string") {
|
|
12503
|
+
return `Volume "${volumeKey}" must have a 'version' field (string)`;
|
|
12504
|
+
}
|
|
12505
|
+
return null;
|
|
12506
|
+
}
|
|
12467
12507
|
function validateAgentConfig(config2) {
|
|
12468
12508
|
if (!config2 || typeof config2 !== "object") {
|
|
12469
12509
|
return { valid: false, error: "Config must be an object" };
|
|
@@ -12472,22 +12512,83 @@ function validateAgentConfig(config2) {
|
|
|
12472
12512
|
if (!cfg.version) {
|
|
12473
12513
|
return { valid: false, error: "Missing config.version" };
|
|
12474
12514
|
}
|
|
12475
|
-
if (!cfg.
|
|
12476
|
-
return { valid: false, error: "Missing config.
|
|
12515
|
+
if (!cfg.agents || !Array.isArray(cfg.agents)) {
|
|
12516
|
+
return { valid: false, error: "Missing config.agents array" };
|
|
12517
|
+
}
|
|
12518
|
+
if (cfg.agents.length === 0) {
|
|
12519
|
+
return { valid: false, error: "config.agents array must not be empty" };
|
|
12520
|
+
}
|
|
12521
|
+
const agent = cfg.agents[0];
|
|
12522
|
+
if (!agent || typeof agent !== "object") {
|
|
12523
|
+
return { valid: false, error: "First agent must be an object" };
|
|
12477
12524
|
}
|
|
12478
|
-
const agent = cfg.agent;
|
|
12479
12525
|
if (!agent.name) {
|
|
12480
|
-
return { valid: false, error: "Missing
|
|
12526
|
+
return { valid: false, error: "Missing agents[0].name" };
|
|
12481
12527
|
}
|
|
12482
12528
|
if (typeof agent.name !== "string") {
|
|
12483
|
-
return { valid: false, error: "
|
|
12529
|
+
return { valid: false, error: "agents[0].name must be a string" };
|
|
12484
12530
|
}
|
|
12485
12531
|
if (!validateAgentName(agent.name)) {
|
|
12486
12532
|
return {
|
|
12487
12533
|
valid: false,
|
|
12488
|
-
error: "Invalid
|
|
12534
|
+
error: "Invalid agents[0].name format. Must be 3-64 characters, letters, numbers, and hyphens only. Must start and end with letter or number."
|
|
12489
12535
|
};
|
|
12490
12536
|
}
|
|
12537
|
+
if (!agent.working_dir || typeof agent.working_dir !== "string") {
|
|
12538
|
+
return {
|
|
12539
|
+
valid: false,
|
|
12540
|
+
error: "Missing or invalid agents[0].working_dir (must be a string)"
|
|
12541
|
+
};
|
|
12542
|
+
}
|
|
12543
|
+
if (!agent.image || typeof agent.image !== "string") {
|
|
12544
|
+
return {
|
|
12545
|
+
valid: false,
|
|
12546
|
+
error: "Missing or invalid agents[0].image (must be a string)"
|
|
12547
|
+
};
|
|
12548
|
+
}
|
|
12549
|
+
if (!agent.provider || typeof agent.provider !== "string") {
|
|
12550
|
+
return {
|
|
12551
|
+
valid: false,
|
|
12552
|
+
error: "Missing or invalid agents[0].provider (must be a string)"
|
|
12553
|
+
};
|
|
12554
|
+
}
|
|
12555
|
+
const agentVolumes = agent.volumes;
|
|
12556
|
+
if (agentVolumes && Array.isArray(agentVolumes) && agentVolumes.length > 0) {
|
|
12557
|
+
const volumesSection = cfg.volumes;
|
|
12558
|
+
if (!volumesSection || typeof volumesSection !== "object") {
|
|
12559
|
+
return {
|
|
12560
|
+
valid: false,
|
|
12561
|
+
error: "Agent references volumes but no volumes section defined. Each volume must have explicit name and version."
|
|
12562
|
+
};
|
|
12563
|
+
}
|
|
12564
|
+
for (const volDeclaration of agentVolumes) {
|
|
12565
|
+
if (typeof volDeclaration !== "string") {
|
|
12566
|
+
return {
|
|
12567
|
+
valid: false,
|
|
12568
|
+
error: "Volume declaration must be a string in format 'key:/path'"
|
|
12569
|
+
};
|
|
12570
|
+
}
|
|
12571
|
+
const parts = volDeclaration.split(":");
|
|
12572
|
+
if (parts.length !== 2) {
|
|
12573
|
+
return {
|
|
12574
|
+
valid: false,
|
|
12575
|
+
error: `Invalid volume declaration: ${volDeclaration}. Expected format: volume-key:/mount/path`
|
|
12576
|
+
};
|
|
12577
|
+
}
|
|
12578
|
+
const volumeKey = parts[0].trim();
|
|
12579
|
+
const volumeConfig = volumesSection[volumeKey];
|
|
12580
|
+
if (!volumeConfig) {
|
|
12581
|
+
return {
|
|
12582
|
+
valid: false,
|
|
12583
|
+
error: `Volume "${volumeKey}" is not defined in volumes section. Each volume must have explicit name and version.`
|
|
12584
|
+
};
|
|
12585
|
+
}
|
|
12586
|
+
const volError = validateVolumeConfig(volumeKey, volumeConfig);
|
|
12587
|
+
if (volError) {
|
|
12588
|
+
return { valid: false, error: volError };
|
|
12589
|
+
}
|
|
12590
|
+
}
|
|
12591
|
+
}
|
|
12491
12592
|
return { valid: true };
|
|
12492
12593
|
}
|
|
12493
12594
|
|
|
@@ -12598,7 +12699,11 @@ var buildCommand = new Command().name("build").description("Create or update age
|
|
|
12598
12699
|
console.log(chalk2.gray(` Config ID: ${response.configId}`));
|
|
12599
12700
|
console.log();
|
|
12600
12701
|
console.log(" Run your agent:");
|
|
12601
|
-
console.log(
|
|
12702
|
+
console.log(
|
|
12703
|
+
chalk2.cyan(
|
|
12704
|
+
` vm0 run ${response.name} --artifact-name <artifact> "your prompt"`
|
|
12705
|
+
)
|
|
12706
|
+
);
|
|
12602
12707
|
} catch (error43) {
|
|
12603
12708
|
if (error43 instanceof Error) {
|
|
12604
12709
|
if (error43.message.includes("Not authenticated")) {
|
|
@@ -12737,7 +12842,7 @@ var ClaudeEventParser = class {
|
|
|
12737
12842
|
agentConfigId: event.agentConfigId,
|
|
12738
12843
|
agentName: event.agentName,
|
|
12739
12844
|
prompt: event.prompt,
|
|
12740
|
-
|
|
12845
|
+
templateVars: event.templateVars
|
|
12741
12846
|
}
|
|
12742
12847
|
};
|
|
12743
12848
|
}
|
|
@@ -12748,7 +12853,8 @@ var ClaudeEventParser = class {
|
|
|
12748
12853
|
data: {
|
|
12749
12854
|
runId: event.runId,
|
|
12750
12855
|
checkpointId: event.checkpointId,
|
|
12751
|
-
|
|
12856
|
+
agentSessionId: event.agentSessionId,
|
|
12857
|
+
hasArtifact: event.hasArtifact
|
|
12752
12858
|
}
|
|
12753
12859
|
};
|
|
12754
12860
|
}
|
|
@@ -12821,9 +12927,7 @@ var EventRenderer = class {
|
|
|
12821
12927
|
if (input && typeof input === "object") {
|
|
12822
12928
|
for (const [key, value] of Object.entries(input)) {
|
|
12823
12929
|
if (value !== void 0 && value !== null) {
|
|
12824
|
-
|
|
12825
|
-
const displayValue = valueStr.length > 100 ? valueStr.substring(0, 100) + "..." : valueStr;
|
|
12826
|
-
console.log(` ${key}: ${chalk3.gray(displayValue)}`);
|
|
12930
|
+
console.log(` ${key}: ${chalk3.gray(String(value))}`);
|
|
12827
12931
|
}
|
|
12828
12932
|
}
|
|
12829
12933
|
}
|
|
@@ -12834,8 +12938,7 @@ var EventRenderer = class {
|
|
|
12834
12938
|
const color = isError ? chalk3.red : chalk3.green;
|
|
12835
12939
|
console.log(color("[tool_result]") + " " + status);
|
|
12836
12940
|
const result = String(event.data.result || "");
|
|
12837
|
-
|
|
12838
|
-
console.log(` ${chalk3.gray(displayResult)}`);
|
|
12941
|
+
console.log(` ${chalk3.gray(result)}`);
|
|
12839
12942
|
}
|
|
12840
12943
|
static renderResult(event) {
|
|
12841
12944
|
const success2 = Boolean(event.data.success);
|
|
@@ -12872,8 +12975,7 @@ var EventRenderer = class {
|
|
|
12872
12975
|
console.log(` Run ID: ${chalk3.gray(String(event.data.runId))}`);
|
|
12873
12976
|
}
|
|
12874
12977
|
const prompt = String(event.data.prompt || "");
|
|
12875
|
-
|
|
12876
|
-
console.log(` Prompt: ${chalk3.gray(displayPrompt)}`);
|
|
12978
|
+
console.log(` Prompt: ${chalk3.gray(prompt)}`);
|
|
12877
12979
|
if (event.data.agentName) {
|
|
12878
12980
|
console.log(` Agent: ${chalk3.gray(String(event.data.agentName))}`);
|
|
12879
12981
|
}
|
|
@@ -12883,9 +12985,11 @@ var EventRenderer = class {
|
|
|
12883
12985
|
console.log(
|
|
12884
12986
|
` Checkpoint: ${chalk3.gray(String(event.data.checkpointId || ""))}`
|
|
12885
12987
|
);
|
|
12886
|
-
|
|
12887
|
-
|
|
12888
|
-
|
|
12988
|
+
console.log(
|
|
12989
|
+
` Session: ${chalk3.gray(String(event.data.agentSessionId || ""))}`
|
|
12990
|
+
);
|
|
12991
|
+
if (event.data.hasArtifact) {
|
|
12992
|
+
console.log(` Artifact: ${chalk3.gray("saved")}`);
|
|
12889
12993
|
}
|
|
12890
12994
|
}
|
|
12891
12995
|
static renderVm0Error(event) {
|
|
@@ -12909,29 +13013,31 @@ var EventRenderer = class {
|
|
|
12909
13013
|
};
|
|
12910
13014
|
|
|
12911
13015
|
// src/commands/run.ts
|
|
12912
|
-
function
|
|
13016
|
+
function collectVars(value, previous) {
|
|
12913
13017
|
const [key, ...valueParts] = value.split("=");
|
|
12914
13018
|
const val = valueParts.join("=");
|
|
12915
13019
|
if (!key || val === void 0 || val === "") {
|
|
12916
|
-
throw new Error(`Invalid
|
|
13020
|
+
throw new Error(`Invalid variable format: ${value} (expected key=value)`);
|
|
12917
13021
|
}
|
|
12918
13022
|
return { ...previous, [key]: val };
|
|
12919
13023
|
}
|
|
12920
13024
|
function isUUID(str) {
|
|
12921
13025
|
return /^[0-9a-f-]{36}$/i.test(str);
|
|
12922
13026
|
}
|
|
12923
|
-
|
|
13027
|
+
var DEFAULT_TIMEOUT_SECONDS = 60;
|
|
13028
|
+
async function pollEvents(runId, timeoutSeconds) {
|
|
12924
13029
|
let nextSequence = -1;
|
|
12925
13030
|
let complete = false;
|
|
12926
13031
|
const pollIntervalMs = 500;
|
|
12927
|
-
const timeoutMs =
|
|
13032
|
+
const timeoutMs = timeoutSeconds * 1e3;
|
|
12928
13033
|
const startTime = Date.now();
|
|
12929
13034
|
while (!complete) {
|
|
12930
13035
|
const elapsed = Date.now() - startTime;
|
|
12931
13036
|
if (elapsed > timeoutMs) {
|
|
12932
13037
|
console.error(
|
|
12933
13038
|
chalk4.red(
|
|
12934
|
-
|
|
13039
|
+
`
|
|
13040
|
+
\u2717 Agent execution timed out after ${timeoutSeconds} seconds without receiving events`
|
|
12935
13041
|
)
|
|
12936
13042
|
);
|
|
12937
13043
|
throw new Error("Agent execution timed out");
|
|
@@ -12960,15 +13066,35 @@ var runCmd = new Command2().name("run").description("Execute an agent").argument
|
|
|
12960
13066
|
"<identifier>",
|
|
12961
13067
|
"Agent name or config ID (e.g., 'my-agent' or 'cfg-abc-123')"
|
|
12962
13068
|
).argument("<prompt>", "Prompt for the agent").option(
|
|
12963
|
-
"
|
|
12964
|
-
"
|
|
12965
|
-
|
|
13069
|
+
"--vars <KEY=value>",
|
|
13070
|
+
"Template variables for config placeholders (repeatable)",
|
|
13071
|
+
collectVars,
|
|
12966
13072
|
{}
|
|
13073
|
+
).option("--artifact-name <name>", "Artifact storage name (required for run)").option(
|
|
13074
|
+
"--artifact-version <hash>",
|
|
13075
|
+
"Artifact version hash (defaults to latest)"
|
|
12967
13076
|
).option(
|
|
12968
|
-
"-
|
|
12969
|
-
"
|
|
13077
|
+
"-t, --timeout <seconds>",
|
|
13078
|
+
"Polling timeout in seconds (default: 60)",
|
|
13079
|
+
String(DEFAULT_TIMEOUT_SECONDS)
|
|
12970
13080
|
).action(
|
|
12971
13081
|
async (identifier, prompt, options) => {
|
|
13082
|
+
const timeoutSeconds = parseInt(options.timeout, 10);
|
|
13083
|
+
if (isNaN(timeoutSeconds) || timeoutSeconds <= 0) {
|
|
13084
|
+
console.error(
|
|
13085
|
+
chalk4.red("\u2717 Invalid timeout value. Must be a positive number.")
|
|
13086
|
+
);
|
|
13087
|
+
process.exit(1);
|
|
13088
|
+
}
|
|
13089
|
+
if (!options.artifactName) {
|
|
13090
|
+
console.error(
|
|
13091
|
+
chalk4.red("\u2717 Missing required option: --artifact-name <name>")
|
|
13092
|
+
);
|
|
13093
|
+
console.error(
|
|
13094
|
+
chalk4.gray(" The artifact-name is required for new agent runs.")
|
|
13095
|
+
);
|
|
13096
|
+
process.exit(1);
|
|
13097
|
+
}
|
|
12972
13098
|
try {
|
|
12973
13099
|
let configId;
|
|
12974
13100
|
if (isUUID(identifier)) {
|
|
@@ -12994,13 +13120,16 @@ var runCmd = new Command2().name("run").description("Execute an agent").argument
|
|
|
12994
13120
|
}
|
|
12995
13121
|
console.log(chalk4.blue("\nCreating agent run..."));
|
|
12996
13122
|
console.log(chalk4.gray(` Prompt: ${prompt}`));
|
|
12997
|
-
if (Object.keys(options.
|
|
13123
|
+
if (Object.keys(options.vars).length > 0) {
|
|
12998
13124
|
console.log(
|
|
12999
|
-
chalk4.gray(` Variables: ${JSON.stringify(options.
|
|
13125
|
+
chalk4.gray(` Variables: ${JSON.stringify(options.vars)}`)
|
|
13000
13126
|
);
|
|
13001
13127
|
}
|
|
13002
|
-
|
|
13003
|
-
|
|
13128
|
+
console.log(chalk4.gray(` Artifact: ${options.artifactName}`));
|
|
13129
|
+
if (options.artifactVersion) {
|
|
13130
|
+
console.log(
|
|
13131
|
+
chalk4.gray(` Artifact version: ${options.artifactVersion}`)
|
|
13132
|
+
);
|
|
13004
13133
|
}
|
|
13005
13134
|
console.log();
|
|
13006
13135
|
console.log(chalk4.blue("Executing in sandbox..."));
|
|
@@ -13008,10 +13137,11 @@ var runCmd = new Command2().name("run").description("Execute an agent").argument
|
|
|
13008
13137
|
const response = await apiClient.createRun({
|
|
13009
13138
|
agentConfigId: configId,
|
|
13010
13139
|
prompt,
|
|
13011
|
-
|
|
13012
|
-
|
|
13140
|
+
templateVars: Object.keys(options.vars).length > 0 ? options.vars : void 0,
|
|
13141
|
+
artifactName: options.artifactName,
|
|
13142
|
+
artifactVersion: options.artifactVersion
|
|
13013
13143
|
});
|
|
13014
|
-
await pollEvents(response.runId);
|
|
13144
|
+
await pollEvents(response.runId, timeoutSeconds);
|
|
13015
13145
|
} catch (error43) {
|
|
13016
13146
|
if (error43 instanceof Error) {
|
|
13017
13147
|
if (error43.message.includes("Not authenticated")) {
|
|
@@ -13034,42 +13164,113 @@ var runCmd = new Command2().name("run").description("Execute an agent").argument
|
|
|
13034
13164
|
}
|
|
13035
13165
|
}
|
|
13036
13166
|
);
|
|
13037
|
-
runCmd.command("resume").description("Resume an agent run from a checkpoint").argument("<checkpointId>", "Checkpoint ID to resume from").argument("<prompt>", "Prompt for the resumed agent").
|
|
13038
|
-
|
|
13039
|
-
|
|
13167
|
+
runCmd.command("resume").description("Resume an agent run from a checkpoint (uses all snapshot data)").argument("<checkpointId>", "Checkpoint ID to resume from").argument("<prompt>", "Prompt for the resumed agent").option(
|
|
13168
|
+
"-t, --timeout <seconds>",
|
|
13169
|
+
"Polling timeout in seconds (default: 60)",
|
|
13170
|
+
String(DEFAULT_TIMEOUT_SECONDS)
|
|
13171
|
+
).action(
|
|
13172
|
+
async (checkpointId, prompt, options) => {
|
|
13173
|
+
const timeoutSeconds = parseInt(options.timeout, 10);
|
|
13174
|
+
if (isNaN(timeoutSeconds) || timeoutSeconds <= 0) {
|
|
13040
13175
|
console.error(
|
|
13041
|
-
chalk4.red(
|
|
13176
|
+
chalk4.red("\u2717 Invalid timeout value. Must be a positive number.")
|
|
13042
13177
|
);
|
|
13043
|
-
console.error(chalk4.gray(" Checkpoint ID must be a valid UUID"));
|
|
13044
13178
|
process.exit(1);
|
|
13045
13179
|
}
|
|
13046
|
-
|
|
13047
|
-
|
|
13048
|
-
|
|
13049
|
-
|
|
13050
|
-
|
|
13051
|
-
|
|
13052
|
-
|
|
13053
|
-
|
|
13054
|
-
|
|
13055
|
-
|
|
13056
|
-
|
|
13057
|
-
|
|
13058
|
-
|
|
13059
|
-
|
|
13060
|
-
|
|
13061
|
-
|
|
13062
|
-
|
|
13180
|
+
try {
|
|
13181
|
+
if (!isUUID(checkpointId)) {
|
|
13182
|
+
console.error(
|
|
13183
|
+
chalk4.red(`\u2717 Invalid checkpoint ID format: ${checkpointId}`)
|
|
13184
|
+
);
|
|
13185
|
+
console.error(chalk4.gray(" Checkpoint ID must be a valid UUID"));
|
|
13186
|
+
process.exit(1);
|
|
13187
|
+
}
|
|
13188
|
+
console.log(chalk4.blue("\nResuming agent run from checkpoint..."));
|
|
13189
|
+
console.log(chalk4.gray(` Checkpoint ID: ${checkpointId}`));
|
|
13190
|
+
console.log(chalk4.gray(` Prompt: ${prompt}`));
|
|
13191
|
+
console.log();
|
|
13192
|
+
console.log(chalk4.blue("Executing in sandbox..."));
|
|
13193
|
+
console.log();
|
|
13194
|
+
const response = await apiClient.resumeRun({
|
|
13195
|
+
checkpointId,
|
|
13196
|
+
prompt
|
|
13197
|
+
});
|
|
13198
|
+
await pollEvents(response.runId, timeoutSeconds);
|
|
13199
|
+
} catch (error43) {
|
|
13200
|
+
if (error43 instanceof Error) {
|
|
13201
|
+
if (error43.message.includes("Not authenticated")) {
|
|
13202
|
+
console.error(
|
|
13203
|
+
chalk4.red("\u2717 Not authenticated. Run: vm0 auth login")
|
|
13204
|
+
);
|
|
13205
|
+
} else if (error43.message.includes("not found")) {
|
|
13206
|
+
console.error(chalk4.red(`\u2717 Checkpoint not found: ${checkpointId}`));
|
|
13207
|
+
} else {
|
|
13208
|
+
console.error(chalk4.red("\u2717 Resume failed"));
|
|
13209
|
+
console.error(chalk4.gray(` ${error43.message}`));
|
|
13210
|
+
}
|
|
13063
13211
|
} else {
|
|
13064
|
-
console.error(chalk4.red("\u2717
|
|
13065
|
-
console.error(chalk4.gray(` ${error43.message}`));
|
|
13212
|
+
console.error(chalk4.red("\u2717 An unexpected error occurred"));
|
|
13066
13213
|
}
|
|
13067
|
-
|
|
13068
|
-
console.error(chalk4.red("\u2717 An unexpected error occurred"));
|
|
13214
|
+
process.exit(1);
|
|
13069
13215
|
}
|
|
13070
|
-
process.exit(1);
|
|
13071
13216
|
}
|
|
13072
|
-
|
|
13217
|
+
);
|
|
13218
|
+
runCmd.command("continue").description(
|
|
13219
|
+
"Continue an agent run from a session (uses latest artifact version)"
|
|
13220
|
+
).argument("<agentSessionId>", "Agent session ID to continue from").argument("<prompt>", "Prompt for the continued agent").option(
|
|
13221
|
+
"-t, --timeout <seconds>",
|
|
13222
|
+
"Polling timeout in seconds (default: 60)",
|
|
13223
|
+
String(DEFAULT_TIMEOUT_SECONDS)
|
|
13224
|
+
).action(
|
|
13225
|
+
async (agentSessionId, prompt, options) => {
|
|
13226
|
+
const timeoutSeconds = parseInt(options.timeout, 10);
|
|
13227
|
+
if (isNaN(timeoutSeconds) || timeoutSeconds <= 0) {
|
|
13228
|
+
console.error(
|
|
13229
|
+
chalk4.red("\u2717 Invalid timeout value. Must be a positive number.")
|
|
13230
|
+
);
|
|
13231
|
+
process.exit(1);
|
|
13232
|
+
}
|
|
13233
|
+
try {
|
|
13234
|
+
if (!isUUID(agentSessionId)) {
|
|
13235
|
+
console.error(
|
|
13236
|
+
chalk4.red(`\u2717 Invalid agent session ID format: ${agentSessionId}`)
|
|
13237
|
+
);
|
|
13238
|
+
console.error(chalk4.gray(" Agent session ID must be a valid UUID"));
|
|
13239
|
+
process.exit(1);
|
|
13240
|
+
}
|
|
13241
|
+
console.log(chalk4.blue("\nContinuing agent run from session..."));
|
|
13242
|
+
console.log(chalk4.gray(` Session ID: ${agentSessionId}`));
|
|
13243
|
+
console.log(chalk4.gray(` Prompt: ${prompt}`));
|
|
13244
|
+
console.log(chalk4.gray(` Note: Using latest artifact version`));
|
|
13245
|
+
console.log();
|
|
13246
|
+
console.log(chalk4.blue("Executing in sandbox..."));
|
|
13247
|
+
console.log();
|
|
13248
|
+
const response = await apiClient.continueSession({
|
|
13249
|
+
agentSessionId,
|
|
13250
|
+
prompt
|
|
13251
|
+
});
|
|
13252
|
+
await pollEvents(response.runId, timeoutSeconds);
|
|
13253
|
+
} catch (error43) {
|
|
13254
|
+
if (error43 instanceof Error) {
|
|
13255
|
+
if (error43.message.includes("Not authenticated")) {
|
|
13256
|
+
console.error(
|
|
13257
|
+
chalk4.red("\u2717 Not authenticated. Run: vm0 auth login")
|
|
13258
|
+
);
|
|
13259
|
+
} else if (error43.message.includes("not found")) {
|
|
13260
|
+
console.error(
|
|
13261
|
+
chalk4.red(`\u2717 Agent session not found: ${agentSessionId}`)
|
|
13262
|
+
);
|
|
13263
|
+
} else {
|
|
13264
|
+
console.error(chalk4.red("\u2717 Continue failed"));
|
|
13265
|
+
console.error(chalk4.gray(` ${error43.message}`));
|
|
13266
|
+
}
|
|
13267
|
+
} else {
|
|
13268
|
+
console.error(chalk4.red("\u2717 An unexpected error occurred"));
|
|
13269
|
+
}
|
|
13270
|
+
process.exit(1);
|
|
13271
|
+
}
|
|
13272
|
+
}
|
|
13273
|
+
);
|
|
13073
13274
|
var runCommand = runCmd;
|
|
13074
13275
|
|
|
13075
13276
|
// src/commands/volume/index.ts
|
|
@@ -13269,9 +13470,80 @@ var pushCommand = new Command4().name("push").description("Push local files to c
|
|
|
13269
13470
|
// src/commands/volume/pull.ts
|
|
13270
13471
|
import { Command as Command5 } from "commander";
|
|
13271
13472
|
import chalk7 from "chalk";
|
|
13272
|
-
import
|
|
13273
|
-
import * as
|
|
13473
|
+
import path5 from "path";
|
|
13474
|
+
import * as fs3 from "fs";
|
|
13274
13475
|
import AdmZip2 from "adm-zip";
|
|
13476
|
+
|
|
13477
|
+
// src/lib/file-utils.ts
|
|
13478
|
+
import * as fs2 from "fs";
|
|
13479
|
+
import * as path4 from "path";
|
|
13480
|
+
function getRemoteFilesFromZip(zipEntries) {
|
|
13481
|
+
const remoteFiles = /* @__PURE__ */ new Set();
|
|
13482
|
+
for (const entry of zipEntries) {
|
|
13483
|
+
if (!entry.isDirectory) {
|
|
13484
|
+
remoteFiles.add(entry.entryName.replace(/\\/g, "/"));
|
|
13485
|
+
}
|
|
13486
|
+
}
|
|
13487
|
+
return remoteFiles;
|
|
13488
|
+
}
|
|
13489
|
+
async function listLocalFiles(dir, excludeDirs = [".vm0"]) {
|
|
13490
|
+
const files = [];
|
|
13491
|
+
async function walkDir(currentDir, relativePath = "") {
|
|
13492
|
+
const entries = await fs2.promises.readdir(currentDir, {
|
|
13493
|
+
withFileTypes: true
|
|
13494
|
+
});
|
|
13495
|
+
for (const entry of entries) {
|
|
13496
|
+
const entryRelativePath = relativePath ? path4.join(relativePath, entry.name) : entry.name;
|
|
13497
|
+
if (entry.isDirectory()) {
|
|
13498
|
+
if (!excludeDirs.includes(entry.name)) {
|
|
13499
|
+
await walkDir(path4.join(currentDir, entry.name), entryRelativePath);
|
|
13500
|
+
}
|
|
13501
|
+
} else {
|
|
13502
|
+
files.push(entryRelativePath);
|
|
13503
|
+
}
|
|
13504
|
+
}
|
|
13505
|
+
}
|
|
13506
|
+
await walkDir(dir);
|
|
13507
|
+
return files;
|
|
13508
|
+
}
|
|
13509
|
+
async function removeExtraFiles(dir, remoteFiles, excludeDirs = [".vm0"]) {
|
|
13510
|
+
const localFiles = await listLocalFiles(dir, excludeDirs);
|
|
13511
|
+
let removedCount = 0;
|
|
13512
|
+
for (const localFile of localFiles) {
|
|
13513
|
+
const normalizedPath = localFile.replace(/\\/g, "/");
|
|
13514
|
+
if (!remoteFiles.has(normalizedPath)) {
|
|
13515
|
+
const fullPath = path4.join(dir, localFile);
|
|
13516
|
+
await fs2.promises.unlink(fullPath);
|
|
13517
|
+
removedCount++;
|
|
13518
|
+
}
|
|
13519
|
+
}
|
|
13520
|
+
await removeEmptyDirs(dir, excludeDirs);
|
|
13521
|
+
return removedCount;
|
|
13522
|
+
}
|
|
13523
|
+
async function removeEmptyDirs(dir, excludeDirs = [".vm0"]) {
|
|
13524
|
+
const entries = await fs2.promises.readdir(dir, { withFileTypes: true });
|
|
13525
|
+
let isEmpty = true;
|
|
13526
|
+
for (const entry of entries) {
|
|
13527
|
+
const fullPath = path4.join(dir, entry.name);
|
|
13528
|
+
if (entry.isDirectory()) {
|
|
13529
|
+
if (excludeDirs.includes(entry.name)) {
|
|
13530
|
+
isEmpty = false;
|
|
13531
|
+
} else {
|
|
13532
|
+
const subDirEmpty = await removeEmptyDirs(fullPath, excludeDirs);
|
|
13533
|
+
if (subDirEmpty) {
|
|
13534
|
+
await fs2.promises.rmdir(fullPath);
|
|
13535
|
+
} else {
|
|
13536
|
+
isEmpty = false;
|
|
13537
|
+
}
|
|
13538
|
+
}
|
|
13539
|
+
} else {
|
|
13540
|
+
isEmpty = false;
|
|
13541
|
+
}
|
|
13542
|
+
}
|
|
13543
|
+
return isEmpty;
|
|
13544
|
+
}
|
|
13545
|
+
|
|
13546
|
+
// src/commands/volume/pull.ts
|
|
13275
13547
|
function formatBytes2(bytes) {
|
|
13276
13548
|
if (bytes === 0) return "0 B";
|
|
13277
13549
|
const k = 1024;
|
|
@@ -13279,7 +13551,7 @@ function formatBytes2(bytes) {
|
|
|
13279
13551
|
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
13280
13552
|
return `${(bytes / Math.pow(k, i)).toFixed(2)} ${sizes[i]}`;
|
|
13281
13553
|
}
|
|
13282
|
-
var pullCommand = new Command5().name("pull").description("Pull cloud files to local directory").action(async () => {
|
|
13554
|
+
var pullCommand = new Command5().name("pull").description("Pull cloud files to local directory").argument("[versionId]", "Version ID to pull (default: latest)").action(async (versionId) => {
|
|
13283
13555
|
try {
|
|
13284
13556
|
const cwd = process.cwd();
|
|
13285
13557
|
const config2 = await readStorageConfig(cwd);
|
|
@@ -13288,11 +13560,19 @@ var pullCommand = new Command5().name("pull").description("Pull cloud files to l
|
|
|
13288
13560
|
console.error(chalk7.gray(" Run: vm0 volume init"));
|
|
13289
13561
|
process.exit(1);
|
|
13290
13562
|
}
|
|
13291
|
-
|
|
13563
|
+
if (versionId) {
|
|
13564
|
+
console.log(
|
|
13565
|
+
chalk7.cyan(`Pulling volume: ${config2.name} (version: ${versionId})`)
|
|
13566
|
+
);
|
|
13567
|
+
} else {
|
|
13568
|
+
console.log(chalk7.cyan(`Pulling volume: ${config2.name}`));
|
|
13569
|
+
}
|
|
13292
13570
|
console.log(chalk7.gray("Downloading..."));
|
|
13293
|
-
|
|
13294
|
-
|
|
13295
|
-
|
|
13571
|
+
let url2 = `/api/storages?name=${encodeURIComponent(config2.name)}`;
|
|
13572
|
+
if (versionId) {
|
|
13573
|
+
url2 += `&version=${encodeURIComponent(versionId)}`;
|
|
13574
|
+
}
|
|
13575
|
+
const response = await apiClient.get(url2);
|
|
13296
13576
|
if (!response.ok) {
|
|
13297
13577
|
if (response.status === 404) {
|
|
13298
13578
|
console.error(chalk7.red(`\u2717 Volume "${config2.name}" not found`));
|
|
@@ -13316,14 +13596,22 @@ var pullCommand = new Command5().name("pull").description("Pull cloud files to l
|
|
|
13316
13596
|
console.log(chalk7.gray("Extracting files..."));
|
|
13317
13597
|
const zip = new AdmZip2(zipBuffer);
|
|
13318
13598
|
const zipEntries = zip.getEntries();
|
|
13599
|
+
const remoteFiles = getRemoteFilesFromZip(zipEntries);
|
|
13600
|
+
console.log(chalk7.gray("Syncing local files..."));
|
|
13601
|
+
const removedCount = await removeExtraFiles(cwd, remoteFiles);
|
|
13602
|
+
if (removedCount > 0) {
|
|
13603
|
+
console.log(
|
|
13604
|
+
chalk7.green(`\u2713 Removed ${removedCount} files not in remote`)
|
|
13605
|
+
);
|
|
13606
|
+
}
|
|
13319
13607
|
let extractedCount = 0;
|
|
13320
13608
|
for (const entry of zipEntries) {
|
|
13321
13609
|
if (!entry.isDirectory) {
|
|
13322
|
-
const targetPath =
|
|
13323
|
-
const dir =
|
|
13324
|
-
await
|
|
13610
|
+
const targetPath = path5.join(cwd, entry.entryName);
|
|
13611
|
+
const dir = path5.dirname(targetPath);
|
|
13612
|
+
await fs3.promises.mkdir(dir, { recursive: true });
|
|
13325
13613
|
const data = entry.getData();
|
|
13326
|
-
await
|
|
13614
|
+
await fs3.promises.writeFile(targetPath, data);
|
|
13327
13615
|
extractedCount++;
|
|
13328
13616
|
}
|
|
13329
13617
|
}
|
|
@@ -13346,11 +13634,11 @@ import { Command as Command10 } from "commander";
|
|
|
13346
13634
|
// src/commands/artifact/init.ts
|
|
13347
13635
|
import { Command as Command7 } from "commander";
|
|
13348
13636
|
import chalk8 from "chalk";
|
|
13349
|
-
import
|
|
13637
|
+
import path6 from "path";
|
|
13350
13638
|
var initCommand2 = new Command7().name("init").description("Initialize an artifact in the current directory").action(async () => {
|
|
13351
13639
|
try {
|
|
13352
13640
|
const cwd = process.cwd();
|
|
13353
|
-
const dirName =
|
|
13641
|
+
const dirName = path6.basename(cwd);
|
|
13354
13642
|
const existingConfig = await readStorageConfig(cwd);
|
|
13355
13643
|
if (existingConfig) {
|
|
13356
13644
|
if (existingConfig.type === "artifact") {
|
|
@@ -13372,7 +13660,7 @@ var initCommand2 = new Command7().name("init").description("Initialize an artifa
|
|
|
13372
13660
|
);
|
|
13373
13661
|
}
|
|
13374
13662
|
console.log(
|
|
13375
|
-
chalk8.gray(`Config file: ${
|
|
13663
|
+
chalk8.gray(`Config file: ${path6.join(cwd, ".vm0", "storage.yaml")}`)
|
|
13376
13664
|
);
|
|
13377
13665
|
return;
|
|
13378
13666
|
}
|
|
@@ -13393,7 +13681,7 @@ var initCommand2 = new Command7().name("init").description("Initialize an artifa
|
|
|
13393
13681
|
console.log(chalk8.green(`\u2713 Initialized artifact: ${artifactName}`));
|
|
13394
13682
|
console.log(
|
|
13395
13683
|
chalk8.gray(
|
|
13396
|
-
`\u2713 Config saved to ${
|
|
13684
|
+
`\u2713 Config saved to ${path6.join(cwd, ".vm0", "storage.yaml")}`
|
|
13397
13685
|
)
|
|
13398
13686
|
);
|
|
13399
13687
|
} catch (error43) {
|
|
@@ -13408,15 +13696,15 @@ var initCommand2 = new Command7().name("init").description("Initialize an artifa
|
|
|
13408
13696
|
// src/commands/artifact/push.ts
|
|
13409
13697
|
import { Command as Command8 } from "commander";
|
|
13410
13698
|
import chalk9 from "chalk";
|
|
13411
|
-
import
|
|
13412
|
-
import * as
|
|
13699
|
+
import path7 from "path";
|
|
13700
|
+
import * as fs4 from "fs";
|
|
13413
13701
|
import AdmZip3 from "adm-zip";
|
|
13414
13702
|
async function getAllFiles2(dirPath, baseDir = dirPath) {
|
|
13415
13703
|
const files = [];
|
|
13416
|
-
const entries = await
|
|
13704
|
+
const entries = await fs4.promises.readdir(dirPath, { withFileTypes: true });
|
|
13417
13705
|
for (const entry of entries) {
|
|
13418
|
-
const fullPath =
|
|
13419
|
-
const relativePath =
|
|
13706
|
+
const fullPath = path7.join(dirPath, entry.name);
|
|
13707
|
+
const relativePath = path7.relative(baseDir, fullPath);
|
|
13420
13708
|
if (relativePath.startsWith(".vm0")) {
|
|
13421
13709
|
continue;
|
|
13422
13710
|
}
|
|
@@ -13463,7 +13751,7 @@ var pushCommand2 = new Command8().name("push").description("Push local files to
|
|
|
13463
13751
|
}
|
|
13464
13752
|
let totalSize = 0;
|
|
13465
13753
|
for (const file2 of files) {
|
|
13466
|
-
const stats = await
|
|
13754
|
+
const stats = await fs4.promises.stat(file2);
|
|
13467
13755
|
totalSize += stats.size;
|
|
13468
13756
|
}
|
|
13469
13757
|
console.log(
|
|
@@ -13472,8 +13760,8 @@ var pushCommand2 = new Command8().name("push").description("Push local files to
|
|
|
13472
13760
|
console.log(chalk9.gray("Compressing files..."));
|
|
13473
13761
|
const zip = new AdmZip3();
|
|
13474
13762
|
for (const file2 of files) {
|
|
13475
|
-
const relativePath =
|
|
13476
|
-
zip.addLocalFile(file2,
|
|
13763
|
+
const relativePath = path7.relative(cwd, file2);
|
|
13764
|
+
zip.addLocalFile(file2, path7.dirname(relativePath));
|
|
13477
13765
|
}
|
|
13478
13766
|
const zipBuffer = zip.toBuffer();
|
|
13479
13767
|
console.log(
|
|
@@ -13512,8 +13800,8 @@ var pushCommand2 = new Command8().name("push").description("Push local files to
|
|
|
13512
13800
|
// src/commands/artifact/pull.ts
|
|
13513
13801
|
import { Command as Command9 } from "commander";
|
|
13514
13802
|
import chalk10 from "chalk";
|
|
13515
|
-
import
|
|
13516
|
-
import * as
|
|
13803
|
+
import path8 from "path";
|
|
13804
|
+
import * as fs5 from "fs";
|
|
13517
13805
|
import AdmZip4 from "adm-zip";
|
|
13518
13806
|
function formatBytes4(bytes) {
|
|
13519
13807
|
if (bytes === 0) return "0 B";
|
|
@@ -13522,7 +13810,7 @@ function formatBytes4(bytes) {
|
|
|
13522
13810
|
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
13523
13811
|
return `${(bytes / Math.pow(k, i)).toFixed(2)} ${sizes[i]}`;
|
|
13524
13812
|
}
|
|
13525
|
-
var pullCommand2 = new Command9().name("pull").description("Pull cloud artifact to local directory").action(async () => {
|
|
13813
|
+
var pullCommand2 = new Command9().name("pull").description("Pull cloud artifact to local directory").argument("[versionId]", "Version ID to pull (default: latest)").action(async (versionId) => {
|
|
13526
13814
|
try {
|
|
13527
13815
|
const cwd = process.cwd();
|
|
13528
13816
|
const config2 = await readStorageConfig(cwd);
|
|
@@ -13540,11 +13828,21 @@ var pullCommand2 = new Command9().name("pull").description("Pull cloud artifact
|
|
|
13540
13828
|
console.error(chalk10.gray(" Use: vm0 volume pull"));
|
|
13541
13829
|
process.exit(1);
|
|
13542
13830
|
}
|
|
13543
|
-
|
|
13831
|
+
if (versionId) {
|
|
13832
|
+
console.log(
|
|
13833
|
+
chalk10.cyan(
|
|
13834
|
+
`Pulling artifact: ${config2.name} (version: ${versionId})`
|
|
13835
|
+
)
|
|
13836
|
+
);
|
|
13837
|
+
} else {
|
|
13838
|
+
console.log(chalk10.cyan(`Pulling artifact: ${config2.name}`));
|
|
13839
|
+
}
|
|
13544
13840
|
console.log(chalk10.gray("Downloading..."));
|
|
13545
|
-
|
|
13546
|
-
|
|
13547
|
-
|
|
13841
|
+
let url2 = `/api/storages?name=${encodeURIComponent(config2.name)}`;
|
|
13842
|
+
if (versionId) {
|
|
13843
|
+
url2 += `&version=${encodeURIComponent(versionId)}`;
|
|
13844
|
+
}
|
|
13845
|
+
const response = await apiClient.get(url2);
|
|
13548
13846
|
if (!response.ok) {
|
|
13549
13847
|
if (response.status === 404) {
|
|
13550
13848
|
console.error(chalk10.red(`\u2717 Artifact "${config2.name}" not found`));
|
|
@@ -13568,14 +13866,22 @@ var pullCommand2 = new Command9().name("pull").description("Pull cloud artifact
|
|
|
13568
13866
|
console.log(chalk10.gray("Extracting files..."));
|
|
13569
13867
|
const zip = new AdmZip4(zipBuffer);
|
|
13570
13868
|
const zipEntries = zip.getEntries();
|
|
13869
|
+
const remoteFiles = getRemoteFilesFromZip(zipEntries);
|
|
13870
|
+
console.log(chalk10.gray("Syncing local files..."));
|
|
13871
|
+
const removedCount = await removeExtraFiles(cwd, remoteFiles);
|
|
13872
|
+
if (removedCount > 0) {
|
|
13873
|
+
console.log(
|
|
13874
|
+
chalk10.green(`\u2713 Removed ${removedCount} files not in remote`)
|
|
13875
|
+
);
|
|
13876
|
+
}
|
|
13571
13877
|
let extractedCount = 0;
|
|
13572
13878
|
for (const entry of zipEntries) {
|
|
13573
13879
|
if (!entry.isDirectory) {
|
|
13574
|
-
const targetPath =
|
|
13575
|
-
const dir =
|
|
13576
|
-
await
|
|
13880
|
+
const targetPath = path8.join(cwd, entry.entryName);
|
|
13881
|
+
const dir = path8.dirname(targetPath);
|
|
13882
|
+
await fs5.promises.mkdir(dir, { recursive: true });
|
|
13577
13883
|
const data = entry.getData();
|
|
13578
|
-
await
|
|
13884
|
+
await fs5.promises.writeFile(targetPath, data);
|
|
13579
13885
|
extractedCount++;
|
|
13580
13886
|
}
|
|
13581
13887
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vm0/cli",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.8.1",
|
|
4
4
|
"description": "CLI application",
|
|
5
|
+
"repository": {
|
|
6
|
+
"type": "git",
|
|
7
|
+
"url": "https://github.com/vm0-ai/vm0",
|
|
8
|
+
"directory": "turbo/apps/cli"
|
|
9
|
+
},
|
|
5
10
|
"type": "module",
|
|
6
11
|
"bin": {
|
|
7
12
|
"vm0": "index.js"
|