@vm0/cli 9.17.0 → 9.17.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 +146 -113
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -237,7 +237,7 @@ var infoCommand = new Command6().name("info").description("Display environment i
|
|
|
237
237
|
import { Command as Command7, Option } from "commander";
|
|
238
238
|
import chalk4 from "chalk";
|
|
239
239
|
import { readFile as readFile4 } from "fs/promises";
|
|
240
|
-
import { existsSync as
|
|
240
|
+
import { existsSync as existsSync4 } from "fs";
|
|
241
241
|
import { dirname as dirname2 } from "path";
|
|
242
242
|
import { parse as parseYaml2 } from "yaml";
|
|
243
243
|
|
|
@@ -2109,6 +2109,41 @@ var MODEL_PROVIDER_TYPES = {
|
|
|
2109
2109
|
models: ["GLM-4.7", "GLM-4.5-Air"],
|
|
2110
2110
|
defaultModel: "GLM-4.7"
|
|
2111
2111
|
},
|
|
2112
|
+
"azure-foundry": {
|
|
2113
|
+
framework: "claude-code",
|
|
2114
|
+
label: "Azure Foundry",
|
|
2115
|
+
helpText: "Run Claude on Microsoft Azure Foundry.\nSetup guide: https://code.claude.com/docs/en/microsoft-foundry",
|
|
2116
|
+
authMethods: {
|
|
2117
|
+
"api-key": {
|
|
2118
|
+
label: "API Key",
|
|
2119
|
+
helpText: "Use an Azure Foundry API key for authentication",
|
|
2120
|
+
credentials: {
|
|
2121
|
+
ANTHROPIC_FOUNDRY_API_KEY: {
|
|
2122
|
+
label: "ANTHROPIC_FOUNDRY_API_KEY",
|
|
2123
|
+
required: true,
|
|
2124
|
+
helpText: "API key from Azure Foundry portal (Endpoints and keys)"
|
|
2125
|
+
},
|
|
2126
|
+
ANTHROPIC_FOUNDRY_RESOURCE: {
|
|
2127
|
+
label: "ANTHROPIC_FOUNDRY_RESOURCE",
|
|
2128
|
+
required: true,
|
|
2129
|
+
placeholder: "my-resource",
|
|
2130
|
+
helpText: "Azure resource name (from portal URL)"
|
|
2131
|
+
}
|
|
2132
|
+
}
|
|
2133
|
+
}
|
|
2134
|
+
},
|
|
2135
|
+
defaultAuthMethod: "api-key",
|
|
2136
|
+
environmentMapping: {
|
|
2137
|
+
CLAUDE_CODE_USE_FOUNDRY: "1",
|
|
2138
|
+
ANTHROPIC_FOUNDRY_API_KEY: "$credentials.ANTHROPIC_FOUNDRY_API_KEY",
|
|
2139
|
+
ANTHROPIC_FOUNDRY_RESOURCE: "$credentials.ANTHROPIC_FOUNDRY_RESOURCE",
|
|
2140
|
+
ANTHROPIC_MODEL: "$model"
|
|
2141
|
+
},
|
|
2142
|
+
models: [],
|
|
2143
|
+
defaultModel: "",
|
|
2144
|
+
allowCustomModel: true,
|
|
2145
|
+
customModelPlaceholder: "claude-sonnet-4-5"
|
|
2146
|
+
},
|
|
2112
2147
|
"aws-bedrock": {
|
|
2113
2148
|
framework: "claude-code",
|
|
2114
2149
|
label: "AWS Bedrock",
|
|
@@ -2183,6 +2218,7 @@ var modelProviderTypeSchema = z15.enum([
|
|
|
2183
2218
|
"minimax-api-key",
|
|
2184
2219
|
"deepseek-api-key",
|
|
2185
2220
|
"zai-api-key",
|
|
2221
|
+
"azure-foundry",
|
|
2186
2222
|
"aws-bedrock"
|
|
2187
2223
|
]);
|
|
2188
2224
|
var modelProviderFrameworkSchema = z15.enum(["claude-code", "codex"]);
|
|
@@ -3470,15 +3506,9 @@ function getLegacySystemTemplateWarning(legacyFormat) {
|
|
|
3470
3506
|
if (legacyFormat === "vm0-claude-code") {
|
|
3471
3507
|
return `Warning: "${legacyFormat}" format is deprecated. Use "vm0/claude-code" instead.`;
|
|
3472
3508
|
}
|
|
3473
|
-
if (legacyFormat === "vm0-claude-code-dev") {
|
|
3474
|
-
return `Warning: "${legacyFormat}" format is deprecated. Use "vm0/claude-code:dev" instead.`;
|
|
3475
|
-
}
|
|
3476
3509
|
if (legacyFormat === "vm0-codex") {
|
|
3477
3510
|
return `Warning: "${legacyFormat}" format is deprecated. Use "vm0/codex" instead.`;
|
|
3478
3511
|
}
|
|
3479
|
-
if (legacyFormat === "vm0-codex-dev") {
|
|
3480
|
-
return `Warning: "${legacyFormat}" format is deprecated. Use "vm0/codex:dev" instead.`;
|
|
3481
|
-
}
|
|
3482
3512
|
if (legacyFormat.startsWith("vm0-github-cli")) {
|
|
3483
3513
|
return `Warning: "${legacyFormat}" is deprecated. Use "apps: [github]" in vm0.yaml instead.`;
|
|
3484
3514
|
}
|
|
@@ -3932,47 +3962,47 @@ async function listScheduleRuns(params) {
|
|
|
3932
3962
|
handleError(result, `Failed to list runs for schedule "${params.name}"`);
|
|
3933
3963
|
}
|
|
3934
3964
|
|
|
3935
|
-
// src/lib/api/domains/
|
|
3965
|
+
// src/lib/api/domains/secrets.ts
|
|
3936
3966
|
import { initClient as initClient7 } from "@ts-rest/core";
|
|
3937
|
-
async function
|
|
3967
|
+
async function listSecrets() {
|
|
3938
3968
|
const config = await getClientConfig();
|
|
3939
|
-
const client = initClient7(
|
|
3969
|
+
const client = initClient7(secretsMainContract, config);
|
|
3940
3970
|
const result = await client.list({ headers: {} });
|
|
3941
3971
|
if (result.status === 200) {
|
|
3942
3972
|
return result.body;
|
|
3943
3973
|
}
|
|
3944
|
-
handleError(result, "Failed to list
|
|
3974
|
+
handleError(result, "Failed to list secrets");
|
|
3945
3975
|
}
|
|
3946
|
-
async function
|
|
3976
|
+
async function getSecret(name) {
|
|
3947
3977
|
const config = await getClientConfig();
|
|
3948
|
-
const client = initClient7(
|
|
3978
|
+
const client = initClient7(secretsByNameContract, config);
|
|
3949
3979
|
const result = await client.get({
|
|
3950
3980
|
params: { name }
|
|
3951
3981
|
});
|
|
3952
3982
|
if (result.status === 200) {
|
|
3953
3983
|
return result.body;
|
|
3954
3984
|
}
|
|
3955
|
-
handleError(result, `
|
|
3985
|
+
handleError(result, `Secret "${name}" not found`);
|
|
3956
3986
|
}
|
|
3957
|
-
async function
|
|
3987
|
+
async function setSecret(body) {
|
|
3958
3988
|
const config = await getClientConfig();
|
|
3959
|
-
const client = initClient7(
|
|
3989
|
+
const client = initClient7(secretsMainContract, config);
|
|
3960
3990
|
const result = await client.set({ body });
|
|
3961
3991
|
if (result.status === 200 || result.status === 201) {
|
|
3962
3992
|
return result.body;
|
|
3963
3993
|
}
|
|
3964
|
-
handleError(result, "Failed to set
|
|
3994
|
+
handleError(result, "Failed to set secret");
|
|
3965
3995
|
}
|
|
3966
|
-
async function
|
|
3996
|
+
async function deleteSecret(name) {
|
|
3967
3997
|
const config = await getClientConfig();
|
|
3968
|
-
const client = initClient7(
|
|
3998
|
+
const client = initClient7(secretsByNameContract, config);
|
|
3969
3999
|
const result = await client.delete({
|
|
3970
4000
|
params: { name }
|
|
3971
4001
|
});
|
|
3972
4002
|
if (result.status === 204) {
|
|
3973
4003
|
return;
|
|
3974
4004
|
}
|
|
3975
|
-
handleError(result, `
|
|
4005
|
+
handleError(result, `Secret "${name}" not found`);
|
|
3976
4006
|
}
|
|
3977
4007
|
|
|
3978
4008
|
// src/lib/api/domains/model-providers.ts
|
|
@@ -4355,6 +4385,17 @@ import * as tar2 from "tar";
|
|
|
4355
4385
|
import * as fs2 from "fs";
|
|
4356
4386
|
import * as path2 from "path";
|
|
4357
4387
|
import * as tar from "tar";
|
|
4388
|
+
function checkDirectoryStatus(dirPath) {
|
|
4389
|
+
if (!fs2.existsSync(dirPath)) {
|
|
4390
|
+
return { exists: false, empty: true };
|
|
4391
|
+
}
|
|
4392
|
+
const stat = fs2.statSync(dirPath);
|
|
4393
|
+
if (!stat.isDirectory()) {
|
|
4394
|
+
return { exists: true, empty: false };
|
|
4395
|
+
}
|
|
4396
|
+
const entries = fs2.readdirSync(dirPath);
|
|
4397
|
+
return { exists: true, empty: entries.length === 0 };
|
|
4398
|
+
}
|
|
4358
4399
|
function formatBytes(bytes) {
|
|
4359
4400
|
if (bytes === 0) return "0 B";
|
|
4360
4401
|
const k = 1024;
|
|
@@ -4967,7 +5008,7 @@ function getSecretsFromComposeContent(content) {
|
|
|
4967
5008
|
return new Set(grouped.secrets.map((r) => r.name));
|
|
4968
5009
|
}
|
|
4969
5010
|
async function loadAndValidateConfig(configFile) {
|
|
4970
|
-
if (!
|
|
5011
|
+
if (!existsSync4(configFile)) {
|
|
4971
5012
|
console.error(chalk4.red(`\u2717 Config file not found: ${configFile}`));
|
|
4972
5013
|
process.exit(1);
|
|
4973
5014
|
}
|
|
@@ -5183,7 +5224,7 @@ var composeCommand = new Command7().name("compose").description("Create or updat
|
|
|
5183
5224
|
)
|
|
5184
5225
|
);
|
|
5185
5226
|
if (options.autoUpdate !== false) {
|
|
5186
|
-
await silentUpgradeAfterCommand("9.17.
|
|
5227
|
+
await silentUpgradeAfterCommand("9.17.2");
|
|
5187
5228
|
}
|
|
5188
5229
|
} catch (error) {
|
|
5189
5230
|
if (error instanceof Error) {
|
|
@@ -7414,7 +7455,7 @@ var mainRunCommand = new Command8().name("run").description("Run an agent").argu
|
|
|
7414
7455
|
}
|
|
7415
7456
|
showNextSteps(result);
|
|
7416
7457
|
if (options.autoUpdate !== false) {
|
|
7417
|
-
await silentUpgradeAfterCommand("9.17.
|
|
7458
|
+
await silentUpgradeAfterCommand("9.17.2");
|
|
7418
7459
|
}
|
|
7419
7460
|
} catch (error) {
|
|
7420
7461
|
handleRunError(error, identifier);
|
|
@@ -7691,7 +7732,7 @@ import path6 from "path";
|
|
|
7691
7732
|
|
|
7692
7733
|
// src/lib/storage/storage-utils.ts
|
|
7693
7734
|
import { readFile as readFile5, writeFile as writeFile4, mkdir as mkdir4 } from "fs/promises";
|
|
7694
|
-
import { existsSync as
|
|
7735
|
+
import { existsSync as existsSync6 } from "fs";
|
|
7695
7736
|
import { parse as parseYaml3, stringify as stringifyYaml } from "yaml";
|
|
7696
7737
|
import path5 from "path";
|
|
7697
7738
|
var CONFIG_DIR = ".vm0";
|
|
@@ -7707,9 +7748,9 @@ async function readStorageConfig(basePath = process.cwd()) {
|
|
|
7707
7748
|
const configPath = path5.join(basePath, CONFIG_DIR, CONFIG_FILE);
|
|
7708
7749
|
const legacyConfigPath = path5.join(basePath, CONFIG_DIR, "volume.yaml");
|
|
7709
7750
|
let actualPath = null;
|
|
7710
|
-
if (
|
|
7751
|
+
if (existsSync6(configPath)) {
|
|
7711
7752
|
actualPath = configPath;
|
|
7712
|
-
} else if (
|
|
7753
|
+
} else if (existsSync6(legacyConfigPath)) {
|
|
7713
7754
|
actualPath = legacyConfigPath;
|
|
7714
7755
|
}
|
|
7715
7756
|
if (!actualPath) {
|
|
@@ -7725,7 +7766,7 @@ async function readStorageConfig(basePath = process.cwd()) {
|
|
|
7725
7766
|
async function writeStorageConfig(storageName, basePath = process.cwd(), type = "volume") {
|
|
7726
7767
|
const configDir = path5.join(basePath, CONFIG_DIR);
|
|
7727
7768
|
const configPath = path5.join(configDir, CONFIG_FILE);
|
|
7728
|
-
if (!
|
|
7769
|
+
if (!existsSync6(configDir)) {
|
|
7729
7770
|
await mkdir4(configDir, { recursive: true });
|
|
7730
7771
|
}
|
|
7731
7772
|
const config = {
|
|
@@ -8064,8 +8105,9 @@ import * as os5 from "os";
|
|
|
8064
8105
|
import * as tar4 from "tar";
|
|
8065
8106
|
async function cloneStorage(name, type, destination, options = {}) {
|
|
8066
8107
|
const typeLabel = type === "artifact" ? "artifact" : "volume";
|
|
8067
|
-
|
|
8068
|
-
|
|
8108
|
+
const dirStatus = checkDirectoryStatus(destination);
|
|
8109
|
+
if (dirStatus.exists && !dirStatus.empty) {
|
|
8110
|
+
throw new Error(`Directory "${destination}" is not empty`);
|
|
8069
8111
|
}
|
|
8070
8112
|
console.log(chalk20.dim(`Checking remote ${typeLabel}...`));
|
|
8071
8113
|
const downloadInfo = await getStorageDownload({
|
|
@@ -8920,7 +8962,7 @@ var cookAction = new Command27().name("cook").description("Quick start: prepare,
|
|
|
8920
8962
|
).option("-y, --yes", "Skip confirmation prompts").option("-v, --verbose", "Show full tool inputs and outputs").addOption(new Option5("--debug-no-mock-claude").hideHelp()).addOption(new Option5("--no-auto-update").hideHelp()).action(
|
|
8921
8963
|
async (prompt, options) => {
|
|
8922
8964
|
if (options.autoUpdate !== false) {
|
|
8923
|
-
const shouldExit = await checkAndUpgrade("9.17.
|
|
8965
|
+
const shouldExit = await checkAndUpgrade("9.17.2", prompt);
|
|
8924
8966
|
if (shouldExit) {
|
|
8925
8967
|
process.exit(0);
|
|
8926
8968
|
}
|
|
@@ -9500,7 +9542,7 @@ import { Command as Command38 } from "commander";
|
|
|
9500
9542
|
// src/commands/agent/clone.ts
|
|
9501
9543
|
import { Command as Command35 } from "commander";
|
|
9502
9544
|
import chalk36 from "chalk";
|
|
9503
|
-
import {
|
|
9545
|
+
import { mkdtempSync as mkdtempSync5 } from "fs";
|
|
9504
9546
|
import { mkdir as mkdir7, writeFile as writeFile6, readdir, copyFile, rm as rm3 } from "fs/promises";
|
|
9505
9547
|
import { join as join7, dirname as dirname3 } from "path";
|
|
9506
9548
|
import { tmpdir as tmpdir7 } from "os";
|
|
@@ -9558,8 +9600,9 @@ async function downloadInstructions(agentName, instructionsPath, destination) {
|
|
|
9558
9600
|
var cloneCommand3 = new Command35().name("clone").description("Clone agent compose to local directory (latest version)").argument("<name>", "Agent compose name to clone").argument("[destination]", "Destination directory (default: agent name)").action(async (name, destination) => {
|
|
9559
9601
|
try {
|
|
9560
9602
|
const targetDir = destination || name;
|
|
9561
|
-
|
|
9562
|
-
|
|
9603
|
+
const dirStatus = checkDirectoryStatus(targetDir);
|
|
9604
|
+
if (dirStatus.exists && !dirStatus.empty) {
|
|
9605
|
+
console.error(chalk36.red(`\u2717 Directory "${targetDir}" is not empty`));
|
|
9563
9606
|
process.exit(1);
|
|
9564
9607
|
}
|
|
9565
9608
|
console.log(`Cloning agent compose: ${name}`);
|
|
@@ -9921,7 +9964,7 @@ var agentCommand = new Command38().name("agent").description("Manage agent compo
|
|
|
9921
9964
|
import { Command as Command39 } from "commander";
|
|
9922
9965
|
import chalk39 from "chalk";
|
|
9923
9966
|
import path15 from "path";
|
|
9924
|
-
import { existsSync as
|
|
9967
|
+
import { existsSync as existsSync10 } from "fs";
|
|
9925
9968
|
import { writeFile as writeFile7 } from "fs/promises";
|
|
9926
9969
|
var VM0_YAML_FILE = "vm0.yaml";
|
|
9927
9970
|
var AGENTS_MD_FILE = "AGENTS.md";
|
|
@@ -9953,8 +9996,8 @@ You are a HackerNews AI content curator.
|
|
|
9953
9996
|
}
|
|
9954
9997
|
function checkExistingFiles() {
|
|
9955
9998
|
const existingFiles = [];
|
|
9956
|
-
if (
|
|
9957
|
-
if (
|
|
9999
|
+
if (existsSync10(VM0_YAML_FILE)) existingFiles.push(VM0_YAML_FILE);
|
|
10000
|
+
if (existsSync10(AGENTS_MD_FILE)) existingFiles.push(AGENTS_MD_FILE);
|
|
9958
10001
|
return existingFiles;
|
|
9959
10002
|
}
|
|
9960
10003
|
var initCommand3 = new Command39().name("init").description("Initialize a new VM0 project in the current directory").option("-f, --force", "Overwrite existing files").option("-n, --name <name>", "Agent name (required in non-interactive mode)").action(async (options) => {
|
|
@@ -10176,7 +10219,6 @@ import chalk40 from "chalk";
|
|
|
10176
10219
|
var defaultPromptDeps = {
|
|
10177
10220
|
isInteractive,
|
|
10178
10221
|
promptConfirm,
|
|
10179
|
-
promptPassword,
|
|
10180
10222
|
promptText
|
|
10181
10223
|
};
|
|
10182
10224
|
function parseKeyValuePairs(pairs) {
|
|
@@ -10191,25 +10233,23 @@ function parseKeyValuePairs(pairs) {
|
|
|
10191
10233
|
}
|
|
10192
10234
|
return result;
|
|
10193
10235
|
}
|
|
10194
|
-
async function
|
|
10195
|
-
if (optionSecrets.length > 0) {
|
|
10196
|
-
return {
|
|
10197
|
-
secrets: parseKeyValuePairs(optionSecrets),
|
|
10198
|
-
preserveExistingSecrets: false
|
|
10199
|
-
};
|
|
10200
|
-
}
|
|
10236
|
+
async function handleExistingSecrets(existingSecretNames, deps) {
|
|
10201
10237
|
if (existingSecretNames.length > 0 && deps.isInteractive()) {
|
|
10202
10238
|
const keepSecrets = await deps.promptConfirm(
|
|
10203
10239
|
`Keep existing secrets? (${existingSecretNames.join(", ")})`,
|
|
10204
10240
|
true
|
|
10205
10241
|
);
|
|
10206
10242
|
if (keepSecrets) {
|
|
10207
|
-
return
|
|
10243
|
+
return true;
|
|
10208
10244
|
}
|
|
10209
|
-
console.log(
|
|
10210
|
-
|
|
10245
|
+
console.log(
|
|
10246
|
+
chalk40.dim(
|
|
10247
|
+
" Note: Secrets will be cleared. Use 'vm0 secret set' to add platform secrets."
|
|
10248
|
+
)
|
|
10249
|
+
);
|
|
10250
|
+
return false;
|
|
10211
10251
|
}
|
|
10212
|
-
return
|
|
10252
|
+
return false;
|
|
10213
10253
|
}
|
|
10214
10254
|
async function handleVars(optionVars, existingVars, deps) {
|
|
10215
10255
|
if (optionVars.length > 0) {
|
|
@@ -10227,29 +10267,24 @@ async function handleVars(optionVars, existingVars, deps) {
|
|
|
10227
10267
|
return {};
|
|
10228
10268
|
}
|
|
10229
10269
|
function displayMissingRequirements(missingSecrets, missingVars) {
|
|
10230
|
-
console.log(chalk40.yellow("\nAgent requires the following configuration:"));
|
|
10231
10270
|
if (missingSecrets.length > 0) {
|
|
10232
|
-
console.log(chalk40.
|
|
10271
|
+
console.log(chalk40.yellow("\nAgent requires the following secrets:"));
|
|
10272
|
+
for (const name of missingSecrets) {
|
|
10273
|
+
console.log(chalk40.dim(` ${name}`));
|
|
10274
|
+
}
|
|
10275
|
+
console.log();
|
|
10276
|
+
console.log("Set secrets using the platform:");
|
|
10233
10277
|
for (const name of missingSecrets) {
|
|
10234
|
-
console.log(chalk40.
|
|
10278
|
+
console.log(chalk40.cyan(` vm0 secret set ${name} <value>`));
|
|
10235
10279
|
}
|
|
10280
|
+
console.log();
|
|
10236
10281
|
}
|
|
10237
10282
|
if (missingVars.length > 0) {
|
|
10238
|
-
console.log(chalk40.
|
|
10283
|
+
console.log(chalk40.yellow("\nAgent requires the following variables:"));
|
|
10239
10284
|
for (const name of missingVars) {
|
|
10240
|
-
console.log(chalk40.dim(`
|
|
10241
|
-
}
|
|
10242
|
-
}
|
|
10243
|
-
console.log("");
|
|
10244
|
-
}
|
|
10245
|
-
async function promptForMissingSecrets(missingSecrets, secrets, deps) {
|
|
10246
|
-
for (const name of missingSecrets) {
|
|
10247
|
-
const value = await deps.promptPassword(
|
|
10248
|
-
`Enter value for secret ${chalk40.cyan(name)}`
|
|
10249
|
-
);
|
|
10250
|
-
if (value) {
|
|
10251
|
-
secrets[name] = value;
|
|
10285
|
+
console.log(chalk40.dim(` ${name}`));
|
|
10252
10286
|
}
|
|
10287
|
+
console.log();
|
|
10253
10288
|
}
|
|
10254
10289
|
}
|
|
10255
10290
|
async function promptForMissingVars(missingVars, vars, deps) {
|
|
@@ -10264,32 +10299,30 @@ async function promptForMissingVars(missingVars, vars, deps) {
|
|
|
10264
10299
|
}
|
|
10265
10300
|
}
|
|
10266
10301
|
async function gatherConfiguration(params, deps = defaultPromptDeps) {
|
|
10267
|
-
const { required,
|
|
10302
|
+
const { required, optionVars, existingSchedule } = params;
|
|
10268
10303
|
const existingSecretNames = existingSchedule?.secretNames ?? [];
|
|
10269
10304
|
const existingVars = existingSchedule?.vars ?? null;
|
|
10270
|
-
const
|
|
10271
|
-
optionSecrets,
|
|
10305
|
+
const preserveExistingSecrets = await handleExistingSecrets(
|
|
10272
10306
|
existingSecretNames,
|
|
10273
10307
|
deps
|
|
10274
10308
|
);
|
|
10275
10309
|
const vars = await handleVars(optionVars, existingVars, deps);
|
|
10276
10310
|
const effectiveExistingSecrets = preserveExistingSecrets ? existingSecretNames : [];
|
|
10277
10311
|
const missingSecrets = required.secrets.filter(
|
|
10278
|
-
(name) => !
|
|
10312
|
+
(name) => !effectiveExistingSecrets.includes(name)
|
|
10279
10313
|
);
|
|
10280
10314
|
const missingVars = required.vars.filter(
|
|
10281
10315
|
(name) => !Object.keys(vars).includes(name)
|
|
10282
10316
|
);
|
|
10283
10317
|
if (missingSecrets.length === 0 && missingVars.length === 0) {
|
|
10284
|
-
return {
|
|
10318
|
+
return { vars, preserveExistingSecrets };
|
|
10285
10319
|
}
|
|
10286
10320
|
if (!deps.isInteractive()) {
|
|
10287
|
-
return {
|
|
10321
|
+
return { vars, preserveExistingSecrets };
|
|
10288
10322
|
}
|
|
10289
10323
|
displayMissingRequirements(missingSecrets, missingVars);
|
|
10290
|
-
await promptForMissingSecrets(missingSecrets, secrets, deps);
|
|
10291
10324
|
await promptForMissingVars(missingVars, vars, deps);
|
|
10292
|
-
return {
|
|
10325
|
+
return { vars, preserveExistingSecrets };
|
|
10293
10326
|
}
|
|
10294
10327
|
|
|
10295
10328
|
// src/commands/schedule/setup.ts
|
|
@@ -10694,7 +10727,7 @@ async function handleScheduleEnabling(params) {
|
|
|
10694
10727
|
showEnableHint(agentName);
|
|
10695
10728
|
}
|
|
10696
10729
|
}
|
|
10697
|
-
var setupCommand = new Command40().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("--
|
|
10730
|
+
var setupCommand = new Command40().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("--artifact-name <name>", "Artifact name", "artifact").option("-e, --enable", "Enable schedule immediately after creation").action(async (agentName, options) => {
|
|
10698
10731
|
try {
|
|
10699
10732
|
const { composeId, scheduleName, composeContent } = await resolveAgent(agentName);
|
|
10700
10733
|
const requiredConfig = extractRequiredConfiguration(composeContent);
|
|
@@ -10737,7 +10770,8 @@ var setupCommand = new Command40().name("setup").description("Create or edit a s
|
|
|
10737
10770
|
}
|
|
10738
10771
|
const config = await gatherConfiguration({
|
|
10739
10772
|
required: requiredConfig,
|
|
10740
|
-
optionSecrets:
|
|
10773
|
+
optionSecrets: [],
|
|
10774
|
+
// Secrets are no longer passed via CLI
|
|
10741
10775
|
optionVars: options.var || [],
|
|
10742
10776
|
existingSchedule
|
|
10743
10777
|
});
|
|
@@ -10752,7 +10786,8 @@ var setupCommand = new Command40().name("setup").description("Create or edit a s
|
|
|
10752
10786
|
timezone,
|
|
10753
10787
|
prompt: promptText_,
|
|
10754
10788
|
vars: Object.keys(config.vars).length > 0 ? config.vars : void 0,
|
|
10755
|
-
secrets:
|
|
10789
|
+
secrets: void 0,
|
|
10790
|
+
// Secrets managed via platform, not schedule
|
|
10756
10791
|
artifactName: options.artifactName
|
|
10757
10792
|
});
|
|
10758
10793
|
displayDeployResult(agentName, deployResult);
|
|
@@ -11252,38 +11287,36 @@ var usageCommand = new Command47().name("usage").description("View usage statist
|
|
|
11252
11287
|
}
|
|
11253
11288
|
});
|
|
11254
11289
|
|
|
11255
|
-
// src/commands/
|
|
11290
|
+
// src/commands/secret/index.ts
|
|
11256
11291
|
import { Command as Command51 } from "commander";
|
|
11257
11292
|
|
|
11258
|
-
// src/commands/
|
|
11293
|
+
// src/commands/secret/list.ts
|
|
11259
11294
|
import { Command as Command48 } from "commander";
|
|
11260
11295
|
import chalk48 from "chalk";
|
|
11261
|
-
var listCommand6 = new Command48().name("list").alias("ls").description("List all
|
|
11296
|
+
var listCommand6 = new Command48().name("list").alias("ls").description("List all secrets").action(async () => {
|
|
11262
11297
|
try {
|
|
11263
|
-
const result = await
|
|
11264
|
-
if (result.
|
|
11265
|
-
console.log(chalk48.dim("No
|
|
11298
|
+
const result = await listSecrets();
|
|
11299
|
+
if (result.secrets.length === 0) {
|
|
11300
|
+
console.log(chalk48.dim("No secrets found"));
|
|
11266
11301
|
console.log();
|
|
11267
|
-
console.log("To add a
|
|
11268
|
-
console.log(chalk48.cyan(" vm0
|
|
11302
|
+
console.log("To add a secret:");
|
|
11303
|
+
console.log(chalk48.cyan(" vm0 secret set MY_API_KEY <value>"));
|
|
11269
11304
|
return;
|
|
11270
11305
|
}
|
|
11271
|
-
console.log(chalk48.bold("
|
|
11306
|
+
console.log(chalk48.bold("Secrets:"));
|
|
11272
11307
|
console.log();
|
|
11273
|
-
for (const
|
|
11274
|
-
const typeIndicator =
|
|
11275
|
-
console.log(` ${chalk48.cyan(
|
|
11276
|
-
if (
|
|
11277
|
-
console.log(` ${chalk48.dim(
|
|
11308
|
+
for (const secret of result.secrets) {
|
|
11309
|
+
const typeIndicator = secret.type === "model-provider" ? chalk48.dim(" [model-provider]") : "";
|
|
11310
|
+
console.log(` ${chalk48.cyan(secret.name)}${typeIndicator}`);
|
|
11311
|
+
if (secret.description) {
|
|
11312
|
+
console.log(` ${chalk48.dim(secret.description)}`);
|
|
11278
11313
|
}
|
|
11279
11314
|
console.log(
|
|
11280
|
-
` ${chalk48.dim(`Updated: ${new Date(
|
|
11315
|
+
` ${chalk48.dim(`Updated: ${new Date(secret.updatedAt).toLocaleString()}`)}`
|
|
11281
11316
|
);
|
|
11282
11317
|
console.log();
|
|
11283
11318
|
}
|
|
11284
|
-
console.log(
|
|
11285
|
-
chalk48.dim(`Total: ${result.credentials.length} credential(s)`)
|
|
11286
|
-
);
|
|
11319
|
+
console.log(chalk48.dim(`Total: ${result.secrets.length} secret(s)`));
|
|
11287
11320
|
} catch (error) {
|
|
11288
11321
|
if (error instanceof Error) {
|
|
11289
11322
|
if (error.message.includes("Not authenticated")) {
|
|
@@ -11298,22 +11331,22 @@ var listCommand6 = new Command48().name("list").alias("ls").description("List al
|
|
|
11298
11331
|
}
|
|
11299
11332
|
});
|
|
11300
11333
|
|
|
11301
|
-
// src/commands/
|
|
11334
|
+
// src/commands/secret/set.ts
|
|
11302
11335
|
import { Command as Command49 } from "commander";
|
|
11303
11336
|
import chalk49 from "chalk";
|
|
11304
|
-
var setCommand2 = new Command49().name("set").description("Create or update a
|
|
11337
|
+
var setCommand2 = new Command49().name("set").description("Create or update a secret").argument("<name>", "Secret name (uppercase, e.g., MY_API_KEY)").argument("<value>", "Secret value").option("-d, --description <description>", "Optional description").action(
|
|
11305
11338
|
async (name, value, options) => {
|
|
11306
11339
|
try {
|
|
11307
|
-
const
|
|
11340
|
+
const secret = await setSecret({
|
|
11308
11341
|
name,
|
|
11309
11342
|
value,
|
|
11310
11343
|
description: options.description
|
|
11311
11344
|
});
|
|
11312
|
-
console.log(chalk49.green(`\u2713
|
|
11345
|
+
console.log(chalk49.green(`\u2713 Secret "${secret.name}" saved`));
|
|
11313
11346
|
console.log();
|
|
11314
11347
|
console.log("Use in vm0.yaml:");
|
|
11315
11348
|
console.log(chalk49.cyan(` environment:`));
|
|
11316
|
-
console.log(chalk49.cyan(` ${name}: \${{
|
|
11349
|
+
console.log(chalk49.cyan(` ${name}: \${{ secrets.${name} }}`));
|
|
11317
11350
|
} catch (error) {
|
|
11318
11351
|
if (error instanceof Error) {
|
|
11319
11352
|
if (error.message.includes("Not authenticated")) {
|
|
@@ -11323,7 +11356,7 @@ var setCommand2 = new Command49().name("set").description("Create or update a cr
|
|
|
11323
11356
|
} else if (error.message.includes("must contain only uppercase")) {
|
|
11324
11357
|
console.error(chalk49.red(`\u2717 ${error.message}`));
|
|
11325
11358
|
console.log();
|
|
11326
|
-
console.log("Examples of valid
|
|
11359
|
+
console.log("Examples of valid secret names:");
|
|
11327
11360
|
console.log(chalk49.dim(" MY_API_KEY"));
|
|
11328
11361
|
console.log(chalk49.dim(" GITHUB_TOKEN"));
|
|
11329
11362
|
console.log(chalk49.dim(" AWS_ACCESS_KEY_ID"));
|
|
@@ -11338,15 +11371,15 @@ var setCommand2 = new Command49().name("set").description("Create or update a cr
|
|
|
11338
11371
|
}
|
|
11339
11372
|
);
|
|
11340
11373
|
|
|
11341
|
-
// src/commands/
|
|
11374
|
+
// src/commands/secret/delete.ts
|
|
11342
11375
|
import { Command as Command50 } from "commander";
|
|
11343
11376
|
import chalk50 from "chalk";
|
|
11344
|
-
var deleteCommand2 = new Command50().name("delete").description("Delete a
|
|
11377
|
+
var deleteCommand2 = new Command50().name("delete").description("Delete a secret").argument("<name>", "Secret name to delete").option("-y, --yes", "Skip confirmation prompt").action(async (name, options) => {
|
|
11345
11378
|
try {
|
|
11346
11379
|
try {
|
|
11347
|
-
await
|
|
11380
|
+
await getSecret(name);
|
|
11348
11381
|
} catch {
|
|
11349
|
-
console.error(chalk50.red(`\u2717
|
|
11382
|
+
console.error(chalk50.red(`\u2717 Secret "${name}" not found`));
|
|
11350
11383
|
process.exit(1);
|
|
11351
11384
|
}
|
|
11352
11385
|
if (!options.yes) {
|
|
@@ -11357,7 +11390,7 @@ var deleteCommand2 = new Command50().name("delete").description("Delete a creden
|
|
|
11357
11390
|
process.exit(1);
|
|
11358
11391
|
}
|
|
11359
11392
|
const confirmed = await promptConfirm(
|
|
11360
|
-
`Are you sure you want to delete
|
|
11393
|
+
`Are you sure you want to delete secret "${name}"?`,
|
|
11361
11394
|
false
|
|
11362
11395
|
);
|
|
11363
11396
|
if (!confirmed) {
|
|
@@ -11365,8 +11398,8 @@ var deleteCommand2 = new Command50().name("delete").description("Delete a creden
|
|
|
11365
11398
|
return;
|
|
11366
11399
|
}
|
|
11367
11400
|
}
|
|
11368
|
-
await
|
|
11369
|
-
console.log(chalk50.green(`\u2713
|
|
11401
|
+
await deleteSecret(name);
|
|
11402
|
+
console.log(chalk50.green(`\u2713 Secret "${name}" deleted`));
|
|
11370
11403
|
} catch (error) {
|
|
11371
11404
|
if (error instanceof Error) {
|
|
11372
11405
|
if (error.message.includes("Not authenticated")) {
|
|
@@ -11381,8 +11414,8 @@ var deleteCommand2 = new Command50().name("delete").description("Delete a creden
|
|
|
11381
11414
|
}
|
|
11382
11415
|
});
|
|
11383
11416
|
|
|
11384
|
-
// src/commands/
|
|
11385
|
-
var
|
|
11417
|
+
// src/commands/secret/index.ts
|
|
11418
|
+
var secretCommand = new Command51().name("secret").description("Manage stored secrets for agent runs").addCommand(listCommand6).addCommand(setCommand2).addCommand(deleteCommand2);
|
|
11386
11419
|
|
|
11387
11420
|
// src/commands/model-provider/index.ts
|
|
11388
11421
|
import { Command as Command56 } from "commander";
|
|
@@ -12083,7 +12116,7 @@ var modelProviderCommand = new Command56().name("model-provider").description("M
|
|
|
12083
12116
|
import { Command as Command57 } from "commander";
|
|
12084
12117
|
import chalk58 from "chalk";
|
|
12085
12118
|
import { mkdir as mkdir8 } from "fs/promises";
|
|
12086
|
-
import { existsSync as
|
|
12119
|
+
import { existsSync as existsSync11 } from "fs";
|
|
12087
12120
|
|
|
12088
12121
|
// src/lib/ui/welcome-box.ts
|
|
12089
12122
|
import chalk55 from "chalk";
|
|
@@ -12583,7 +12616,7 @@ async function handleAgentCreation(ctx) {
|
|
|
12583
12616
|
process.exit(0);
|
|
12584
12617
|
}
|
|
12585
12618
|
agentName = inputName;
|
|
12586
|
-
if (
|
|
12619
|
+
if (existsSync11(agentName)) {
|
|
12587
12620
|
step.detail(
|
|
12588
12621
|
chalk58.yellow(`${agentName}/ already exists, choose another name`)
|
|
12589
12622
|
);
|
|
@@ -12600,7 +12633,7 @@ async function handleAgentCreation(ctx) {
|
|
|
12600
12633
|
);
|
|
12601
12634
|
process.exit(1);
|
|
12602
12635
|
}
|
|
12603
|
-
if (
|
|
12636
|
+
if (existsSync11(agentName)) {
|
|
12604
12637
|
console.error(chalk58.red(`${agentName}/ already exists`));
|
|
12605
12638
|
console.log();
|
|
12606
12639
|
console.log("Remove it first or choose a different name:");
|
|
@@ -12703,7 +12736,7 @@ var setupClaudeCommand = new Command58().name("setup-claude").description("Insta
|
|
|
12703
12736
|
|
|
12704
12737
|
// src/index.ts
|
|
12705
12738
|
var program = new Command59();
|
|
12706
|
-
program.name("vm0").description("VM0 CLI - Build and run agents with natural language").version("9.17.
|
|
12739
|
+
program.name("vm0").description("VM0 CLI - Build and run agents with natural language").version("9.17.2");
|
|
12707
12740
|
program.addCommand(authCommand);
|
|
12708
12741
|
program.addCommand(infoCommand);
|
|
12709
12742
|
program.addCommand(composeCommand);
|
|
@@ -12717,7 +12750,7 @@ program.addCommand(agentCommand);
|
|
|
12717
12750
|
program.addCommand(initCommand3);
|
|
12718
12751
|
program.addCommand(scheduleCommand);
|
|
12719
12752
|
program.addCommand(usageCommand);
|
|
12720
|
-
program.addCommand(
|
|
12753
|
+
program.addCommand(secretCommand);
|
|
12721
12754
|
program.addCommand(modelProviderCommand);
|
|
12722
12755
|
program.addCommand(onboardCommand);
|
|
12723
12756
|
program.addCommand(setupClaudeCommand);
|