@vm0/cli 8.0.0 → 8.0.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 +242 -253
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -432,11 +432,6 @@ var appStringSchema = z4.string().superRefine((val, ctx) => {
|
|
|
432
432
|
});
|
|
433
433
|
var agentDefinitionSchema = z4.object({
|
|
434
434
|
description: z4.string().optional(),
|
|
435
|
-
/**
|
|
436
|
-
* @deprecated Use `apps` field instead for pre-installed tools.
|
|
437
|
-
* This field will be removed in a future version.
|
|
438
|
-
*/
|
|
439
|
-
image: z4.string().optional(),
|
|
440
435
|
framework: z4.string().min(1, "Framework is required"),
|
|
441
436
|
/**
|
|
442
437
|
* Array of pre-installed apps/tools for the agent environment.
|
|
@@ -446,8 +441,6 @@ var agentDefinitionSchema = z4.object({
|
|
|
446
441
|
*/
|
|
447
442
|
apps: z4.array(appStringSchema).optional(),
|
|
448
443
|
volumes: z4.array(z4.string()).optional(),
|
|
449
|
-
working_dir: z4.string().optional(),
|
|
450
|
-
// Optional when provider supports auto-config
|
|
451
444
|
environment: z4.record(z4.string(), z4.string()).optional(),
|
|
452
445
|
/**
|
|
453
446
|
* Path to instructions file (e.g., AGENTS.md).
|
|
@@ -474,7 +467,17 @@ var agentDefinitionSchema = z4.object({
|
|
|
474
467
|
* Requires experimental_runner to be configured.
|
|
475
468
|
* When enabled, filters outbound traffic by domain/IP rules.
|
|
476
469
|
*/
|
|
477
|
-
experimental_firewall: experimentalFirewallSchema.optional()
|
|
470
|
+
experimental_firewall: experimentalFirewallSchema.optional(),
|
|
471
|
+
/**
|
|
472
|
+
* @deprecated Server-resolved field. User input is ignored.
|
|
473
|
+
* @internal
|
|
474
|
+
*/
|
|
475
|
+
image: z4.string().optional(),
|
|
476
|
+
/**
|
|
477
|
+
* @deprecated Server-resolved field. User input is ignored.
|
|
478
|
+
* @internal
|
|
479
|
+
*/
|
|
480
|
+
working_dir: z4.string().optional()
|
|
478
481
|
});
|
|
479
482
|
var agentComposeContentSchema = z4.object({
|
|
480
483
|
version: z4.string().min(1, "Version is required"),
|
|
@@ -2950,10 +2953,6 @@ var FEATURE_SWITCHES = {
|
|
|
2950
2953
|
maintainer: "ethan@vm0.ai",
|
|
2951
2954
|
enabled: true
|
|
2952
2955
|
},
|
|
2953
|
-
["platformOnboarding" /* PlatformOnboarding */]: {
|
|
2954
|
-
maintainer: "ethan@vm0.ai",
|
|
2955
|
-
enabled: false
|
|
2956
|
-
},
|
|
2957
2956
|
["platformAgents" /* PlatformAgents */]: {
|
|
2958
2957
|
maintainer: "ethan@vm0.ai",
|
|
2959
2958
|
enabled: false
|
|
@@ -3425,72 +3424,6 @@ async function getUsage(options) {
|
|
|
3425
3424
|
|
|
3426
3425
|
// src/lib/domain/yaml-validator.ts
|
|
3427
3426
|
import { z as z23 } from "zod";
|
|
3428
|
-
|
|
3429
|
-
// src/lib/domain/framework-config.ts
|
|
3430
|
-
var FRAMEWORK_DEFAULTS = {
|
|
3431
|
-
"claude-code": {
|
|
3432
|
-
workingDir: "/home/user/workspace",
|
|
3433
|
-
image: {
|
|
3434
|
-
production: "vm0/claude-code:latest",
|
|
3435
|
-
development: "vm0/claude-code:dev"
|
|
3436
|
-
}
|
|
3437
|
-
},
|
|
3438
|
-
codex: {
|
|
3439
|
-
workingDir: "/home/user/workspace",
|
|
3440
|
-
image: {
|
|
3441
|
-
production: "vm0/codex:latest",
|
|
3442
|
-
development: "vm0/codex:dev"
|
|
3443
|
-
}
|
|
3444
|
-
}
|
|
3445
|
-
};
|
|
3446
|
-
function getFrameworkDefaults(framework) {
|
|
3447
|
-
return FRAMEWORK_DEFAULTS[framework];
|
|
3448
|
-
}
|
|
3449
|
-
function isFrameworkSupported(framework) {
|
|
3450
|
-
return framework in FRAMEWORK_DEFAULTS;
|
|
3451
|
-
}
|
|
3452
|
-
var FRAMEWORK_APPS_IMAGES = {
|
|
3453
|
-
"claude-code": {
|
|
3454
|
-
github: {
|
|
3455
|
-
production: "vm0/claude-code-github:latest",
|
|
3456
|
-
development: "vm0/claude-code-github:dev"
|
|
3457
|
-
}
|
|
3458
|
-
},
|
|
3459
|
-
codex: {
|
|
3460
|
-
github: {
|
|
3461
|
-
production: "vm0/codex-github:latest",
|
|
3462
|
-
development: "vm0/codex-github:dev"
|
|
3463
|
-
}
|
|
3464
|
-
}
|
|
3465
|
-
};
|
|
3466
|
-
function parseAppString(appString) {
|
|
3467
|
-
const [app, tag] = appString.split(":");
|
|
3468
|
-
return {
|
|
3469
|
-
app: app ?? appString,
|
|
3470
|
-
tag: tag === "dev" ? "dev" : "latest"
|
|
3471
|
-
};
|
|
3472
|
-
}
|
|
3473
|
-
function getDefaultImageWithApps(framework, apps) {
|
|
3474
|
-
const defaults = FRAMEWORK_DEFAULTS[framework];
|
|
3475
|
-
if (!defaults) return void 0;
|
|
3476
|
-
if (apps && apps.length > 0) {
|
|
3477
|
-
const frameworkApps = FRAMEWORK_APPS_IMAGES[framework];
|
|
3478
|
-
if (frameworkApps) {
|
|
3479
|
-
const firstApp = apps[0];
|
|
3480
|
-
if (firstApp) {
|
|
3481
|
-
const { app, tag } = parseAppString(firstApp);
|
|
3482
|
-
const appImage = frameworkApps[app];
|
|
3483
|
-
if (appImage) {
|
|
3484
|
-
return tag === "dev" ? appImage.development : appImage.production;
|
|
3485
|
-
}
|
|
3486
|
-
}
|
|
3487
|
-
}
|
|
3488
|
-
}
|
|
3489
|
-
const isDevelopment = process.env.NODE_ENV === "development" || process.env.NODE_ENV === "test";
|
|
3490
|
-
return isDevelopment ? defaults.image.development : defaults.image.production;
|
|
3491
|
-
}
|
|
3492
|
-
|
|
3493
|
-
// src/lib/domain/yaml-validator.ts
|
|
3494
3427
|
var cliAgentNameSchema = z23.string().min(3, "Agent name must be at least 3 characters").max(64, "Agent name must be 64 characters or less").regex(
|
|
3495
3428
|
/^[a-zA-Z0-9]([a-zA-Z0-9-]{0,62}[a-zA-Z0-9])?$/,
|
|
3496
3429
|
"Agent name must start and end with letter or number, and contain only letters, numbers, and hyphens"
|
|
@@ -3501,21 +3434,6 @@ function validateGitHubTreeUrl(url) {
|
|
|
3501
3434
|
}
|
|
3502
3435
|
var cliAgentDefinitionSchema = agentDefinitionSchema.superRefine(
|
|
3503
3436
|
(agent, ctx) => {
|
|
3504
|
-
const frameworkSupported = isFrameworkSupported(agent.framework);
|
|
3505
|
-
if (!agent.image && !frameworkSupported) {
|
|
3506
|
-
ctx.addIssue({
|
|
3507
|
-
code: z23.ZodIssueCode.custom,
|
|
3508
|
-
message: "Missing agent.image (required when framework is not auto-configured)",
|
|
3509
|
-
path: ["image"]
|
|
3510
|
-
});
|
|
3511
|
-
}
|
|
3512
|
-
if (!agent.working_dir && !frameworkSupported) {
|
|
3513
|
-
ctx.addIssue({
|
|
3514
|
-
code: z23.ZodIssueCode.custom,
|
|
3515
|
-
message: "Missing agent.working_dir (required when framework is not auto-configured)",
|
|
3516
|
-
path: ["working_dir"]
|
|
3517
|
-
});
|
|
3518
|
-
}
|
|
3519
3437
|
if (agent.skills) {
|
|
3520
3438
|
for (let i = 0; i < agent.skills.length; i++) {
|
|
3521
3439
|
const skillUrl = agent.skills[i];
|
|
@@ -4175,24 +4093,6 @@ var composeCommand = new Command().name("compose").description("Create or update
|
|
|
4175
4093
|
const agentName = Object.keys(agents)[0];
|
|
4176
4094
|
const agent = agents[agentName];
|
|
4177
4095
|
const basePath = dirname2(configFile);
|
|
4178
|
-
if (agent.framework) {
|
|
4179
|
-
const defaults = getFrameworkDefaults(agent.framework);
|
|
4180
|
-
if (defaults) {
|
|
4181
|
-
if (!agent.image) {
|
|
4182
|
-
const apps = agent.apps;
|
|
4183
|
-
const defaultImage = getDefaultImageWithApps(
|
|
4184
|
-
agent.framework,
|
|
4185
|
-
apps
|
|
4186
|
-
);
|
|
4187
|
-
if (defaultImage) {
|
|
4188
|
-
agent.image = defaultImage;
|
|
4189
|
-
}
|
|
4190
|
-
}
|
|
4191
|
-
if (!agent.working_dir) {
|
|
4192
|
-
agent.working_dir = defaults.workingDir;
|
|
4193
|
-
}
|
|
4194
|
-
}
|
|
4195
|
-
}
|
|
4196
4096
|
if (agent.instructions) {
|
|
4197
4097
|
const instructionsPath = agent.instructions;
|
|
4198
4098
|
const framework = agent.framework;
|
|
@@ -6758,6 +6658,24 @@ async function promptSelect(message, choices, initial) {
|
|
|
6758
6658
|
);
|
|
6759
6659
|
return response.value;
|
|
6760
6660
|
}
|
|
6661
|
+
async function promptPassword(message) {
|
|
6662
|
+
if (!isInteractive()) {
|
|
6663
|
+
return void 0;
|
|
6664
|
+
}
|
|
6665
|
+
const response = await prompts2(
|
|
6666
|
+
{
|
|
6667
|
+
type: "password",
|
|
6668
|
+
name: "value",
|
|
6669
|
+
message
|
|
6670
|
+
},
|
|
6671
|
+
{
|
|
6672
|
+
onCancel: () => {
|
|
6673
|
+
return false;
|
|
6674
|
+
}
|
|
6675
|
+
}
|
|
6676
|
+
);
|
|
6677
|
+
return response.value;
|
|
6678
|
+
}
|
|
6761
6679
|
|
|
6762
6680
|
// src/commands/volume/init.ts
|
|
6763
6681
|
var initCommand = new Command5().name("init").description("Initialize a volume in the current directory").option("-n, --name <name>", "Volume name (required in non-interactive mode)").action(async (options) => {
|
|
@@ -7945,7 +7863,7 @@ cookCmd.argument("[prompt]", "Prompt for the agent").option(
|
|
|
7945
7863
|
// eslint-disable-next-line complexity -- TODO: refactor complex function
|
|
7946
7864
|
async (prompt, options) => {
|
|
7947
7865
|
if (!options.noAutoUpdate) {
|
|
7948
|
-
const shouldExit = await checkAndUpgrade("8.0.
|
|
7866
|
+
const shouldExit = await checkAndUpgrade("8.0.2", prompt);
|
|
7949
7867
|
if (shouldExit) {
|
|
7950
7868
|
process.exit(0);
|
|
7951
7869
|
}
|
|
@@ -8655,10 +8573,9 @@ import { Command as Command26 } from "commander";
|
|
|
8655
8573
|
// src/commands/agent/list.ts
|
|
8656
8574
|
import { Command as Command24 } from "commander";
|
|
8657
8575
|
import chalk28 from "chalk";
|
|
8658
|
-
var listCommand3 = new Command24().name("list").alias("ls").description("List all agent composes").
|
|
8576
|
+
var listCommand3 = new Command24().name("list").alias("ls").description("List all agent composes").action(async () => {
|
|
8659
8577
|
try {
|
|
8660
|
-
const
|
|
8661
|
-
const response = await httpGet(url);
|
|
8578
|
+
const response = await httpGet("/api/agent/composes/list");
|
|
8662
8579
|
if (!response.ok) {
|
|
8663
8580
|
const error = await response.json();
|
|
8664
8581
|
throw new Error(error.error?.message || "List failed");
|
|
@@ -8706,27 +8623,6 @@ import chalk29 from "chalk";
|
|
|
8706
8623
|
import * as fs9 from "fs/promises";
|
|
8707
8624
|
import * as path12 from "path";
|
|
8708
8625
|
import * as os7 from "os";
|
|
8709
|
-
function extractVariableReferences2(environment) {
|
|
8710
|
-
const secrets = [];
|
|
8711
|
-
const vars = [];
|
|
8712
|
-
for (const value of Object.values(environment)) {
|
|
8713
|
-
const matches = value.matchAll(/\$\{?([A-Z_][A-Z0-9_]*)\}?/g);
|
|
8714
|
-
for (const match of matches) {
|
|
8715
|
-
const varName = match[1];
|
|
8716
|
-
if (!varName) continue;
|
|
8717
|
-
if (varName.endsWith("_KEY") || varName.endsWith("_SECRET") || varName.endsWith("_TOKEN") || varName.endsWith("_PASSWORD") || varName.includes("API_KEY") || varName.includes("SECRET")) {
|
|
8718
|
-
if (!secrets.includes(varName)) {
|
|
8719
|
-
secrets.push(varName);
|
|
8720
|
-
}
|
|
8721
|
-
} else {
|
|
8722
|
-
if (!vars.includes(varName)) {
|
|
8723
|
-
vars.push(varName);
|
|
8724
|
-
}
|
|
8725
|
-
}
|
|
8726
|
-
}
|
|
8727
|
-
}
|
|
8728
|
-
return { secrets: secrets.sort(), vars: vars.sort() };
|
|
8729
|
-
}
|
|
8730
8626
|
async function fetchSkillFrontmatter(skillUrl, tempDir) {
|
|
8731
8627
|
try {
|
|
8732
8628
|
const parsed = parseGitHubTreeUrl2(skillUrl);
|
|
@@ -8738,19 +8634,31 @@ async function fetchSkillFrontmatter(skillUrl, tempDir) {
|
|
|
8738
8634
|
}
|
|
8739
8635
|
}
|
|
8740
8636
|
async function deriveAgentVariableSources(agent, options) {
|
|
8741
|
-
const
|
|
8637
|
+
const refs = agent.environment ? extractVariableReferences(agent.environment) : [];
|
|
8638
|
+
const grouped = groupVariablesBySource(refs);
|
|
8742
8639
|
const secretSources = /* @__PURE__ */ new Map();
|
|
8743
8640
|
const varSources = /* @__PURE__ */ new Map();
|
|
8744
|
-
|
|
8745
|
-
|
|
8641
|
+
const credentialSources = /* @__PURE__ */ new Map();
|
|
8642
|
+
for (const ref of grouped.secrets) {
|
|
8643
|
+
secretSources.set(ref.name, {
|
|
8644
|
+
name: ref.name,
|
|
8645
|
+
source: "agent environment"
|
|
8646
|
+
});
|
|
8746
8647
|
}
|
|
8747
|
-
for (const
|
|
8748
|
-
varSources.set(name, { name, source: "agent environment" });
|
|
8648
|
+
for (const ref of grouped.vars) {
|
|
8649
|
+
varSources.set(ref.name, { name: ref.name, source: "agent environment" });
|
|
8650
|
+
}
|
|
8651
|
+
for (const ref of grouped.credentials) {
|
|
8652
|
+
credentialSources.set(ref.name, {
|
|
8653
|
+
name: ref.name,
|
|
8654
|
+
source: "agent environment"
|
|
8655
|
+
});
|
|
8749
8656
|
}
|
|
8750
8657
|
if (options?.skipNetwork || !agent.skills || agent.skills.length === 0) {
|
|
8751
8658
|
return {
|
|
8752
8659
|
secrets: Array.from(secretSources.values()),
|
|
8753
|
-
vars: Array.from(varSources.values())
|
|
8660
|
+
vars: Array.from(varSources.values()),
|
|
8661
|
+
credentials: Array.from(credentialSources.values())
|
|
8754
8662
|
};
|
|
8755
8663
|
}
|
|
8756
8664
|
const tempDir = await fs9.mkdtemp(
|
|
@@ -8791,7 +8699,8 @@ async function deriveAgentVariableSources(agent, options) {
|
|
|
8791
8699
|
}
|
|
8792
8700
|
return {
|
|
8793
8701
|
secrets: Array.from(secretSources.values()),
|
|
8794
|
-
vars: Array.from(varSources.values())
|
|
8702
|
+
vars: Array.from(varSources.values()),
|
|
8703
|
+
credentials: Array.from(credentialSources.values())
|
|
8795
8704
|
};
|
|
8796
8705
|
}
|
|
8797
8706
|
async function deriveComposeVariableSources(content, options) {
|
|
@@ -8843,6 +8752,13 @@ function formatVariableSources(sources) {
|
|
|
8843
8752
|
console.log(` - ${v.name.padEnd(20)} ${sourceInfo}`);
|
|
8844
8753
|
}
|
|
8845
8754
|
}
|
|
8755
|
+
if (sources.credentials.length > 0) {
|
|
8756
|
+
console.log(` Credentials:`);
|
|
8757
|
+
for (const cred of sources.credentials) {
|
|
8758
|
+
const sourceInfo = chalk29.dim(`(${cred.source})`);
|
|
8759
|
+
console.log(` - ${cred.name.padEnd(20)} ${sourceInfo}`);
|
|
8760
|
+
}
|
|
8761
|
+
}
|
|
8846
8762
|
}
|
|
8847
8763
|
function formatAgentDetails(agentName, agent, agentSources, volumeConfigs) {
|
|
8848
8764
|
console.log(` ${chalk29.cyan(agentName)}:`);
|
|
@@ -8876,83 +8792,81 @@ function formatComposeOutput(name, versionId, content, variableSources) {
|
|
|
8876
8792
|
var statusCommand4 = new Command25().name("status").description("Show status of agent compose").argument(
|
|
8877
8793
|
"<name[:version]>",
|
|
8878
8794
|
"Agent name with optional version (e.g., my-agent:latest or my-agent:a1b2c3d4)"
|
|
8879
|
-
).option("
|
|
8880
|
-
|
|
8881
|
-
|
|
8882
|
-
|
|
8883
|
-
|
|
8884
|
-
|
|
8885
|
-
|
|
8886
|
-
|
|
8887
|
-
|
|
8888
|
-
|
|
8889
|
-
|
|
8890
|
-
|
|
8891
|
-
|
|
8892
|
-
|
|
8893
|
-
|
|
8894
|
-
|
|
8895
|
-
|
|
8896
|
-
|
|
8897
|
-
|
|
8898
|
-
|
|
8899
|
-
if (version
|
|
8900
|
-
if (version.length < 64) {
|
|
8901
|
-
try {
|
|
8902
|
-
const versionInfo = await getComposeVersion(compose.id, version);
|
|
8903
|
-
resolvedVersionId = versionInfo.versionId;
|
|
8904
|
-
} catch (error) {
|
|
8905
|
-
if (error instanceof Error && error.message.includes("not found")) {
|
|
8906
|
-
console.error(chalk29.red(`\u2717 Version not found: ${version}`));
|
|
8907
|
-
console.error(
|
|
8908
|
-
chalk29.dim(
|
|
8909
|
-
` HEAD version: ${compose.headVersionId?.slice(0, 8)}`
|
|
8910
|
-
)
|
|
8911
|
-
);
|
|
8912
|
-
process.exit(1);
|
|
8913
|
-
}
|
|
8914
|
-
throw error;
|
|
8915
|
-
}
|
|
8916
|
-
} else {
|
|
8917
|
-
resolvedVersionId = version;
|
|
8918
|
-
}
|
|
8919
|
-
}
|
|
8920
|
-
if (!resolvedVersionId || !compose.content) {
|
|
8921
|
-
console.error(chalk29.red(`\u2717 No version found for: ${name}`));
|
|
8922
|
-
process.exit(1);
|
|
8923
|
-
}
|
|
8924
|
-
const content = compose.content;
|
|
8925
|
-
let variableSources;
|
|
8926
|
-
if (options.sources !== false) {
|
|
8795
|
+
).option("--no-sources", "Skip fetching skills to determine variable sources").action(async (argument, options) => {
|
|
8796
|
+
try {
|
|
8797
|
+
const colonIndex = argument.lastIndexOf(":");
|
|
8798
|
+
let name;
|
|
8799
|
+
let version;
|
|
8800
|
+
if (colonIndex === -1) {
|
|
8801
|
+
name = argument;
|
|
8802
|
+
version = "latest";
|
|
8803
|
+
} else {
|
|
8804
|
+
name = argument.slice(0, colonIndex);
|
|
8805
|
+
version = argument.slice(colonIndex + 1) || "latest";
|
|
8806
|
+
}
|
|
8807
|
+
const compose = await getComposeByName(name);
|
|
8808
|
+
if (!compose) {
|
|
8809
|
+
console.error(chalk29.red(`\u2717 Agent compose not found: ${name}`));
|
|
8810
|
+
console.error(chalk29.dim(" Run: vm0 agent list"));
|
|
8811
|
+
process.exit(1);
|
|
8812
|
+
}
|
|
8813
|
+
let resolvedVersionId = compose.headVersionId;
|
|
8814
|
+
if (version !== "latest" && compose.headVersionId) {
|
|
8815
|
+
if (version.length < 64) {
|
|
8927
8816
|
try {
|
|
8928
|
-
|
|
8929
|
-
|
|
8930
|
-
|
|
8931
|
-
|
|
8932
|
-
|
|
8933
|
-
|
|
8934
|
-
|
|
8817
|
+
const versionInfo = await getComposeVersion(compose.id, version);
|
|
8818
|
+
resolvedVersionId = versionInfo.versionId;
|
|
8819
|
+
} catch (error) {
|
|
8820
|
+
if (error instanceof Error && error.message.includes("not found")) {
|
|
8821
|
+
console.error(chalk29.red(`\u2717 Version not found: ${version}`));
|
|
8822
|
+
console.error(
|
|
8823
|
+
chalk29.dim(
|
|
8824
|
+
` HEAD version: ${compose.headVersionId?.slice(0, 8)}`
|
|
8825
|
+
)
|
|
8826
|
+
);
|
|
8827
|
+
process.exit(1);
|
|
8828
|
+
}
|
|
8829
|
+
throw error;
|
|
8935
8830
|
}
|
|
8831
|
+
} else {
|
|
8832
|
+
resolvedVersionId = version;
|
|
8936
8833
|
}
|
|
8937
|
-
|
|
8938
|
-
|
|
8939
|
-
|
|
8940
|
-
|
|
8941
|
-
|
|
8834
|
+
}
|
|
8835
|
+
if (!resolvedVersionId || !compose.content) {
|
|
8836
|
+
console.error(chalk29.red(`\u2717 No version found for: ${name}`));
|
|
8837
|
+
process.exit(1);
|
|
8838
|
+
}
|
|
8839
|
+
const content = compose.content;
|
|
8840
|
+
let variableSources;
|
|
8841
|
+
try {
|
|
8842
|
+
variableSources = await deriveComposeVariableSources(content, {
|
|
8843
|
+
skipNetwork: options.sources === false
|
|
8844
|
+
});
|
|
8845
|
+
} catch {
|
|
8846
|
+
console.error(
|
|
8847
|
+
chalk29.yellow(
|
|
8848
|
+
"\u26A0 Warning: Failed to fetch skill sources, showing basic info"
|
|
8849
|
+
)
|
|
8942
8850
|
);
|
|
8943
|
-
}
|
|
8944
|
-
|
|
8945
|
-
|
|
8946
|
-
|
|
8947
|
-
|
|
8948
|
-
|
|
8949
|
-
|
|
8950
|
-
|
|
8851
|
+
}
|
|
8852
|
+
formatComposeOutput(
|
|
8853
|
+
compose.name,
|
|
8854
|
+
resolvedVersionId,
|
|
8855
|
+
content,
|
|
8856
|
+
variableSources
|
|
8857
|
+
);
|
|
8858
|
+
} catch (error) {
|
|
8859
|
+
console.error(chalk29.red("\u2717 Failed to get agent compose status"));
|
|
8860
|
+
if (error instanceof Error) {
|
|
8861
|
+
if (error.message.includes("Not authenticated")) {
|
|
8862
|
+
console.error(chalk29.dim(" Run: vm0 auth login"));
|
|
8863
|
+
} else {
|
|
8864
|
+
console.error(chalk29.dim(` ${error.message}`));
|
|
8951
8865
|
}
|
|
8952
|
-
process.exit(1);
|
|
8953
8866
|
}
|
|
8867
|
+
process.exit(1);
|
|
8954
8868
|
}
|
|
8955
|
-
);
|
|
8869
|
+
});
|
|
8956
8870
|
|
|
8957
8871
|
// src/commands/agent/index.ts
|
|
8958
8872
|
var agentCommand = new Command26().name("agent").description("Manage agent composes").addCommand(listCommand3).addCommand(statusCommand4);
|
|
@@ -9179,6 +9093,22 @@ function toISODateTime(dateTimeStr) {
|
|
|
9179
9093
|
const date = new Date(isoStr);
|
|
9180
9094
|
return date.toISOString();
|
|
9181
9095
|
}
|
|
9096
|
+
function extractRequiredConfiguration(composeContent) {
|
|
9097
|
+
const result = {
|
|
9098
|
+
secrets: [],
|
|
9099
|
+
vars: [],
|
|
9100
|
+
credentials: []
|
|
9101
|
+
};
|
|
9102
|
+
if (!composeContent) {
|
|
9103
|
+
return result;
|
|
9104
|
+
}
|
|
9105
|
+
const refs = extractVariableReferences(composeContent);
|
|
9106
|
+
const grouped = groupVariablesBySource(refs);
|
|
9107
|
+
result.secrets = grouped.secrets.map((r) => r.name);
|
|
9108
|
+
result.vars = grouped.vars.map((r) => r.name);
|
|
9109
|
+
result.credentials = grouped.credentials.map((r) => r.name);
|
|
9110
|
+
return result;
|
|
9111
|
+
}
|
|
9182
9112
|
async function resolveScheduleByAgent(agentName) {
|
|
9183
9113
|
const { schedules } = await listSchedules();
|
|
9184
9114
|
const schedule = schedules.find((s) => s.composeName === agentName);
|
|
@@ -9480,14 +9410,67 @@ async function gatherSecrets(optionSecrets, existingSecretNames) {
|
|
|
9480
9410
|
`Keep existing secrets? (${existingSecretNames.join(", ")})`,
|
|
9481
9411
|
true
|
|
9482
9412
|
);
|
|
9483
|
-
if (
|
|
9484
|
-
|
|
9485
|
-
chalk31.dim(" Note: You'll need to provide new secret values")
|
|
9486
|
-
);
|
|
9413
|
+
if (keepSecrets) {
|
|
9414
|
+
return void 0;
|
|
9487
9415
|
}
|
|
9416
|
+
console.log(chalk31.dim(" Note: You'll need to provide new secret values"));
|
|
9417
|
+
return {};
|
|
9488
9418
|
}
|
|
9489
9419
|
return void 0;
|
|
9490
9420
|
}
|
|
9421
|
+
async function gatherMissingConfiguration(required, providedSecrets, providedVars, existingSecretNames) {
|
|
9422
|
+
const secrets = { ...providedSecrets };
|
|
9423
|
+
const vars = { ...providedVars };
|
|
9424
|
+
const providedSecretNames = Object.keys(providedSecrets);
|
|
9425
|
+
const existingNames = existingSecretNames ?? [];
|
|
9426
|
+
const missingSecrets = required.secrets.filter(
|
|
9427
|
+
(name) => !providedSecretNames.includes(name) && !existingNames.includes(name)
|
|
9428
|
+
);
|
|
9429
|
+
const providedVarNames = Object.keys(providedVars);
|
|
9430
|
+
const missingVars = required.vars.filter(
|
|
9431
|
+
(name) => !providedVarNames.includes(name)
|
|
9432
|
+
);
|
|
9433
|
+
if (missingSecrets.length === 0 && missingVars.length === 0) {
|
|
9434
|
+
return { secrets, vars };
|
|
9435
|
+
}
|
|
9436
|
+
if (!isInteractive()) {
|
|
9437
|
+
return { secrets, vars };
|
|
9438
|
+
}
|
|
9439
|
+
if (missingSecrets.length > 0 || missingVars.length > 0) {
|
|
9440
|
+
console.log(chalk31.yellow("\nAgent requires the following configuration:"));
|
|
9441
|
+
if (missingSecrets.length > 0) {
|
|
9442
|
+
console.log(chalk31.dim(" Secrets:"));
|
|
9443
|
+
for (const name of missingSecrets) {
|
|
9444
|
+
console.log(chalk31.dim(` ${name}`));
|
|
9445
|
+
}
|
|
9446
|
+
}
|
|
9447
|
+
if (missingVars.length > 0) {
|
|
9448
|
+
console.log(chalk31.dim(" Vars:"));
|
|
9449
|
+
for (const name of missingVars) {
|
|
9450
|
+
console.log(chalk31.dim(` ${name}`));
|
|
9451
|
+
}
|
|
9452
|
+
}
|
|
9453
|
+
console.log("");
|
|
9454
|
+
}
|
|
9455
|
+
for (const name of missingSecrets) {
|
|
9456
|
+
const value = await promptPassword(
|
|
9457
|
+
`Enter value for secret ${chalk31.cyan(name)}`
|
|
9458
|
+
);
|
|
9459
|
+
if (value) {
|
|
9460
|
+
secrets[name] = value;
|
|
9461
|
+
}
|
|
9462
|
+
}
|
|
9463
|
+
for (const name of missingVars) {
|
|
9464
|
+
const value = await promptText(
|
|
9465
|
+
`Enter value for var ${chalk31.cyan(name)}`,
|
|
9466
|
+
""
|
|
9467
|
+
);
|
|
9468
|
+
if (value) {
|
|
9469
|
+
vars[name] = value;
|
|
9470
|
+
}
|
|
9471
|
+
}
|
|
9472
|
+
return { secrets, vars };
|
|
9473
|
+
}
|
|
9491
9474
|
async function resolveAgent(agentName) {
|
|
9492
9475
|
const compose = await getComposeByName(agentName);
|
|
9493
9476
|
if (!compose) {
|
|
@@ -9497,9 +9480,28 @@ async function resolveAgent(agentName) {
|
|
|
9497
9480
|
}
|
|
9498
9481
|
return {
|
|
9499
9482
|
composeId: compose.id,
|
|
9500
|
-
scheduleName: `${agentName}-schedule
|
|
9483
|
+
scheduleName: `${agentName}-schedule`,
|
|
9484
|
+
composeContent: compose.content
|
|
9501
9485
|
};
|
|
9502
9486
|
}
|
|
9487
|
+
async function gatherTiming(frequency, options, defaults) {
|
|
9488
|
+
if (frequency === "once") {
|
|
9489
|
+
const result = await gatherOneTimeSchedule(
|
|
9490
|
+
options.day,
|
|
9491
|
+
options.time,
|
|
9492
|
+
defaults.time
|
|
9493
|
+
);
|
|
9494
|
+
if (!result) return null;
|
|
9495
|
+
return { day: void 0, time: void 0, atTime: result };
|
|
9496
|
+
}
|
|
9497
|
+
const day = await gatherDay(frequency, options.day, defaults.day) ?? void 0;
|
|
9498
|
+
if (day === null && (frequency === "weekly" || frequency === "monthly")) {
|
|
9499
|
+
return null;
|
|
9500
|
+
}
|
|
9501
|
+
const time = await gatherRecurringTime(options.time, defaults.time);
|
|
9502
|
+
if (!time) return null;
|
|
9503
|
+
return { day, time, atTime: void 0 };
|
|
9504
|
+
}
|
|
9503
9505
|
async function findExistingSchedule(agentName) {
|
|
9504
9506
|
const { schedules } = await listSchedules();
|
|
9505
9507
|
return schedules.find((s) => s.composeName === agentName);
|
|
@@ -9576,7 +9578,8 @@ function displayDeployResult(agentName, deployResult) {
|
|
|
9576
9578
|
}
|
|
9577
9579
|
var setupCommand = new Command28().name("setup").description("Create or edit a schedule for an agent").argument("<agent-name>", "Agent name to configure schedule for").option("-f, --frequency <type>", "Frequency: daily|weekly|monthly|once").option("-t, --time <HH:MM>", "Time to run (24-hour format)").option("-d, --day <day>", "Day of week (mon-sun) or day of month (1-31)").option("-z, --timezone <tz>", "IANA timezone").option("-p, --prompt <text>", "Prompt to run").option("--var <name=value>", "Variable (can be repeated)", collect, []).option("--secret <name=value>", "Secret (can be repeated)", collect, []).option("--artifact-name <name>", "Artifact name", "artifact").action(async (agentName, options) => {
|
|
9578
9580
|
try {
|
|
9579
|
-
const { composeId, scheduleName } = await resolveAgent(agentName);
|
|
9581
|
+
const { composeId, scheduleName, composeContent } = await resolveAgent(agentName);
|
|
9582
|
+
const requiredConfig = extractRequiredConfiguration(composeContent);
|
|
9580
9583
|
const existingSchedule = await findExistingSchedule(agentName);
|
|
9581
9584
|
console.log(
|
|
9582
9585
|
chalk31.dim(
|
|
@@ -9592,36 +9595,12 @@ var setupCommand = new Command28().name("setup").description("Create or edit a s
|
|
|
9592
9595
|
console.log(chalk31.dim("Cancelled"));
|
|
9593
9596
|
return;
|
|
9594
9597
|
}
|
|
9595
|
-
|
|
9596
|
-
|
|
9597
|
-
|
|
9598
|
-
|
|
9599
|
-
const result = await gatherOneTimeSchedule(
|
|
9600
|
-
options.day,
|
|
9601
|
-
options.time,
|
|
9602
|
-
defaults.time
|
|
9603
|
-
);
|
|
9604
|
-
if (!result) {
|
|
9605
|
-
console.log(chalk31.dim("Cancelled"));
|
|
9606
|
-
return;
|
|
9607
|
-
}
|
|
9608
|
-
atTime = result;
|
|
9609
|
-
} else {
|
|
9610
|
-
day = await gatherDay(frequency, options.day, defaults.day) ?? void 0;
|
|
9611
|
-
if (day === null && (frequency === "weekly" || frequency === "monthly")) {
|
|
9612
|
-
console.log(chalk31.dim("Cancelled"));
|
|
9613
|
-
return;
|
|
9614
|
-
}
|
|
9615
|
-
const timeResult = await gatherRecurringTime(
|
|
9616
|
-
options.time,
|
|
9617
|
-
defaults.time
|
|
9618
|
-
);
|
|
9619
|
-
if (!timeResult) {
|
|
9620
|
-
console.log(chalk31.dim("Cancelled"));
|
|
9621
|
-
return;
|
|
9622
|
-
}
|
|
9623
|
-
time = timeResult;
|
|
9598
|
+
const timing = await gatherTiming(frequency, options, defaults);
|
|
9599
|
+
if (!timing) {
|
|
9600
|
+
console.log(chalk31.dim("Cancelled"));
|
|
9601
|
+
return;
|
|
9624
9602
|
}
|
|
9603
|
+
const { day, time, atTime } = timing;
|
|
9625
9604
|
const timezone = await gatherTimezone(
|
|
9626
9605
|
options.timezone,
|
|
9627
9606
|
existingSchedule?.timezone
|
|
@@ -9638,11 +9617,21 @@ var setupCommand = new Command28().name("setup").description("Create or edit a s
|
|
|
9638
9617
|
console.log(chalk31.dim("Cancelled"));
|
|
9639
9618
|
return;
|
|
9640
9619
|
}
|
|
9641
|
-
const
|
|
9642
|
-
|
|
9620
|
+
const initialVars = await gatherVars(
|
|
9621
|
+
options.var || [],
|
|
9622
|
+
existingSchedule?.vars
|
|
9623
|
+
);
|
|
9624
|
+
const initialSecrets = await gatherSecrets(
|
|
9643
9625
|
options.secret || [],
|
|
9644
9626
|
existingSchedule?.secretNames
|
|
9645
9627
|
);
|
|
9628
|
+
const keepExistingSecrets = initialSecrets === void 0;
|
|
9629
|
+
const { secrets, vars } = await gatherMissingConfiguration(
|
|
9630
|
+
requiredConfig,
|
|
9631
|
+
initialSecrets ?? {},
|
|
9632
|
+
initialVars ?? {},
|
|
9633
|
+
existingSchedule?.secretNames
|
|
9634
|
+
);
|
|
9646
9635
|
await buildAndDeploy({
|
|
9647
9636
|
scheduleName,
|
|
9648
9637
|
composeId,
|
|
@@ -9653,8 +9642,8 @@ var setupCommand = new Command28().name("setup").description("Create or edit a s
|
|
|
9653
9642
|
atTime,
|
|
9654
9643
|
timezone,
|
|
9655
9644
|
prompt: promptText_,
|
|
9656
|
-
vars,
|
|
9657
|
-
secrets,
|
|
9645
|
+
vars: Object.keys(vars).length > 0 ? vars : void 0,
|
|
9646
|
+
secrets: keepExistingSecrets ? void 0 : Object.keys(secrets).length > 0 ? secrets : void 0,
|
|
9658
9647
|
artifactName: options.artifactName
|
|
9659
9648
|
});
|
|
9660
9649
|
} catch (error) {
|
|
@@ -10537,7 +10526,7 @@ var modelProviderCommand = new Command44().name("model-provider").description("M
|
|
|
10537
10526
|
|
|
10538
10527
|
// src/index.ts
|
|
10539
10528
|
var program = new Command45();
|
|
10540
|
-
program.name("vm0").description("VM0 CLI - Build and run agents with natural language").version("8.0.
|
|
10529
|
+
program.name("vm0").description("VM0 CLI - Build and run agents with natural language").version("8.0.2");
|
|
10541
10530
|
program.command("info").description("Display environment information").action(async () => {
|
|
10542
10531
|
console.log(chalk45.bold("System Information:"));
|
|
10543
10532
|
console.log(`Node Version: ${process.version}`);
|