@vm0/cli 5.7.2 → 5.8.0
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 +406 -176
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
// src/index.ts
|
|
4
|
-
import { Command as
|
|
5
|
-
import
|
|
4
|
+
import { Command as Command36 } from "commander";
|
|
5
|
+
import chalk37 from "chalk";
|
|
6
6
|
|
|
7
7
|
// src/lib/api/auth.ts
|
|
8
8
|
import chalk from "chalk";
|
|
@@ -333,7 +333,9 @@ var storedExecutionContextSchema = z2.object({
|
|
|
333
333
|
encryptedSecrets: z2.string().nullable(),
|
|
334
334
|
// AES-256-GCM encrypted secrets
|
|
335
335
|
cliAgentType: z2.string(),
|
|
336
|
-
experimentalFirewall: experimentalFirewallSchema.optional()
|
|
336
|
+
experimentalFirewall: experimentalFirewallSchema.optional(),
|
|
337
|
+
// Debug flag to force real Claude in mock environments (internal use only)
|
|
338
|
+
debugNoMockClaude: z2.boolean().optional()
|
|
337
339
|
});
|
|
338
340
|
var executionContextSchema = z2.object({
|
|
339
341
|
runId: z2.string().uuid(),
|
|
@@ -351,7 +353,9 @@ var executionContextSchema = z2.object({
|
|
|
351
353
|
secretValues: z2.array(z2.string()).nullable(),
|
|
352
354
|
cliAgentType: z2.string(),
|
|
353
355
|
// Experimental firewall configuration
|
|
354
|
-
experimentalFirewall: experimentalFirewallSchema.optional()
|
|
356
|
+
experimentalFirewall: experimentalFirewallSchema.optional(),
|
|
357
|
+
// Debug flag to force real Claude in mock environments (internal use only)
|
|
358
|
+
debugNoMockClaude: z2.boolean().optional()
|
|
355
359
|
});
|
|
356
360
|
var runnersJobClaimContract = c.router({
|
|
357
361
|
claim: {
|
|
@@ -634,6 +638,8 @@ var unifiedRunRequestSchema = z4.object({
|
|
|
634
638
|
vars: z4.record(z4.string(), z4.string()).optional(),
|
|
635
639
|
secrets: z4.record(z4.string(), z4.string()).optional(),
|
|
636
640
|
volumeVersions: z4.record(z4.string(), z4.string()).optional(),
|
|
641
|
+
// Debug flag to force real Claude in mock environments (internal use only)
|
|
642
|
+
debugNoMockClaude: z4.boolean().optional(),
|
|
637
643
|
// Required
|
|
638
644
|
prompt: z4.string().min(1, "Missing prompt")
|
|
639
645
|
});
|
|
@@ -2586,6 +2592,16 @@ function getProviderDisplayName(provider) {
|
|
|
2586
2592
|
return PROVIDER_DISPLAY_NAMES[provider];
|
|
2587
2593
|
}
|
|
2588
2594
|
|
|
2595
|
+
// ../../packages/core/src/feature-switch.ts
|
|
2596
|
+
var PricingSwitch = {
|
|
2597
|
+
key: "pricing" /* Pricing */,
|
|
2598
|
+
maintainer: "ethan@vm0.ai",
|
|
2599
|
+
enabled: false
|
|
2600
|
+
};
|
|
2601
|
+
var FEATURE_SWITCHES = {
|
|
2602
|
+
["pricing" /* Pricing */]: PricingSwitch
|
|
2603
|
+
};
|
|
2604
|
+
|
|
2589
2605
|
// src/lib/api/api-client.ts
|
|
2590
2606
|
import { initClient } from "@ts-rest/core";
|
|
2591
2607
|
var ApiClient = class {
|
|
@@ -3256,6 +3272,26 @@ var ApiClient = class {
|
|
|
3256
3272
|
const message = errorBody.error?.message || `Volume "${id}" not found`;
|
|
3257
3273
|
throw new Error(message);
|
|
3258
3274
|
}
|
|
3275
|
+
/**
|
|
3276
|
+
* Get usage statistics
|
|
3277
|
+
*/
|
|
3278
|
+
async getUsage(options) {
|
|
3279
|
+
const baseUrl = await this.getBaseUrl();
|
|
3280
|
+
const headers = await this.getHeaders();
|
|
3281
|
+
const params = new URLSearchParams({
|
|
3282
|
+
start_date: options.startDate,
|
|
3283
|
+
end_date: options.endDate
|
|
3284
|
+
});
|
|
3285
|
+
const response = await fetch(`${baseUrl}/api/usage?${params}`, {
|
|
3286
|
+
method: "GET",
|
|
3287
|
+
headers
|
|
3288
|
+
});
|
|
3289
|
+
if (!response.ok) {
|
|
3290
|
+
const error = await response.json();
|
|
3291
|
+
throw new Error(error.error?.message || "Failed to fetch usage data");
|
|
3292
|
+
}
|
|
3293
|
+
return response.json();
|
|
3294
|
+
}
|
|
3259
3295
|
/**
|
|
3260
3296
|
* Generic GET request
|
|
3261
3297
|
*/
|
|
@@ -5103,7 +5139,7 @@ var runCmd = new Command2().name("run").description("Execute an agent").argument
|
|
|
5103
5139
|
).option(
|
|
5104
5140
|
"--conversation <id>",
|
|
5105
5141
|
"Resume from conversation ID (for fine-grained control)"
|
|
5106
|
-
).option("-v, --verbose", "Show verbose output with timing information").action(
|
|
5142
|
+
).option("-v, --verbose", "Show verbose output with timing information").option("--debug-no-mock-claude").action(
|
|
5107
5143
|
async (identifier, prompt, options) => {
|
|
5108
5144
|
const startTimestamp = /* @__PURE__ */ new Date();
|
|
5109
5145
|
const verbose = options.verbose;
|
|
@@ -5204,7 +5240,8 @@ var runCmd = new Command2().name("run").description("Execute an agent").argument
|
|
|
5204
5240
|
artifactName: options.artifactName,
|
|
5205
5241
|
artifactVersion: options.artifactVersion,
|
|
5206
5242
|
volumeVersions: Object.keys(options.volumeVersion).length > 0 ? options.volumeVersion : void 0,
|
|
5207
|
-
conversationId: options.conversation
|
|
5243
|
+
conversationId: options.conversation,
|
|
5244
|
+
debugNoMockClaude: options.debugNoMockClaude || void 0
|
|
5208
5245
|
});
|
|
5209
5246
|
if (response.status === "failed") {
|
|
5210
5247
|
console.error(chalk5.red("\u2717 Run preparation failed"));
|
|
@@ -5269,7 +5306,7 @@ runCmd.command("resume").description("Resume an agent run from a checkpoint (use
|
|
|
5269
5306
|
"Volume version override (repeatable)",
|
|
5270
5307
|
collectVolumeVersions,
|
|
5271
5308
|
{}
|
|
5272
|
-
).option("-v, --verbose", "Show verbose output with timing information").action(
|
|
5309
|
+
).option("-v, --verbose", "Show verbose output with timing information").option("--debug-no-mock-claude").action(
|
|
5273
5310
|
async (checkpointId, prompt, options, command) => {
|
|
5274
5311
|
const startTimestamp = /* @__PURE__ */ new Date();
|
|
5275
5312
|
const allOpts = command.optsWithGlobals();
|
|
@@ -5310,7 +5347,8 @@ runCmd.command("resume").description("Resume an agent run from a checkpoint (use
|
|
|
5310
5347
|
prompt,
|
|
5311
5348
|
vars: Object.keys(vars).length > 0 ? vars : void 0,
|
|
5312
5349
|
secrets: loadedSecrets,
|
|
5313
|
-
volumeVersions: Object.keys(allOpts.volumeVersion).length > 0 ? allOpts.volumeVersion : void 0
|
|
5350
|
+
volumeVersions: Object.keys(allOpts.volumeVersion).length > 0 ? allOpts.volumeVersion : void 0,
|
|
5351
|
+
debugNoMockClaude: options.debugNoMockClaude || allOpts.debugNoMockClaude || void 0
|
|
5314
5352
|
});
|
|
5315
5353
|
if (response.status === "failed") {
|
|
5316
5354
|
console.error(chalk5.red("\u2717 Run preparation failed"));
|
|
@@ -5367,7 +5405,7 @@ runCmd.command("continue").description(
|
|
|
5367
5405
|
"Volume version override (repeatable)",
|
|
5368
5406
|
collectVolumeVersions,
|
|
5369
5407
|
{}
|
|
5370
|
-
).option("-v, --verbose", "Show verbose output with timing information").action(
|
|
5408
|
+
).option("-v, --verbose", "Show verbose output with timing information").option("--debug-no-mock-claude").action(
|
|
5371
5409
|
async (agentSessionId, prompt, options, command) => {
|
|
5372
5410
|
const startTimestamp = /* @__PURE__ */ new Date();
|
|
5373
5411
|
const allOpts = command.optsWithGlobals();
|
|
@@ -5409,7 +5447,8 @@ runCmd.command("continue").description(
|
|
|
5409
5447
|
prompt,
|
|
5410
5448
|
vars: Object.keys(vars).length > 0 ? vars : void 0,
|
|
5411
5449
|
secrets: loadedSecrets,
|
|
5412
|
-
volumeVersions: Object.keys(allOpts.volumeVersion).length > 0 ? allOpts.volumeVersion : void 0
|
|
5450
|
+
volumeVersions: Object.keys(allOpts.volumeVersion).length > 0 ? allOpts.volumeVersion : void 0,
|
|
5451
|
+
debugNoMockClaude: options.debugNoMockClaude || allOpts.debugNoMockClaude || void 0
|
|
5413
5452
|
});
|
|
5414
5453
|
if (response.status === "failed") {
|
|
5415
5454
|
console.error(chalk5.red("\u2717 Run preparation failed"));
|
|
@@ -6731,180 +6770,186 @@ async function autoPullArtifact(runOutput, artifactDir) {
|
|
|
6731
6770
|
}
|
|
6732
6771
|
}
|
|
6733
6772
|
var cookCmd = new Command17().name("cook").description("One-click agent preparation and execution from vm0.yaml");
|
|
6734
|
-
cookCmd.argument("[prompt]", "Prompt for the agent").option("-y, --yes", "Skip confirmation prompts").action(
|
|
6735
|
-
|
|
6736
|
-
|
|
6737
|
-
|
|
6738
|
-
|
|
6739
|
-
const cwd = process.cwd();
|
|
6740
|
-
console.log(chalk21.bold(`Reading config: ${CONFIG_FILE3}`));
|
|
6741
|
-
if (!existsSync8(CONFIG_FILE3)) {
|
|
6742
|
-
console.error(chalk21.red(`\u2717 Config file not found: ${CONFIG_FILE3}`));
|
|
6743
|
-
process.exit(1);
|
|
6744
|
-
}
|
|
6745
|
-
let config;
|
|
6746
|
-
try {
|
|
6747
|
-
const content = await readFile7(CONFIG_FILE3, "utf8");
|
|
6748
|
-
config = parseYaml4(content);
|
|
6749
|
-
} catch (error) {
|
|
6750
|
-
console.error(chalk21.red("\u2717 Invalid YAML format"));
|
|
6751
|
-
if (error instanceof Error) {
|
|
6752
|
-
console.error(chalk21.dim(` ${error.message}`));
|
|
6773
|
+
cookCmd.argument("[prompt]", "Prompt for the agent").option("-y, --yes", "Skip confirmation prompts").option("--debug-no-mock-claude").action(
|
|
6774
|
+
async (prompt, options) => {
|
|
6775
|
+
const shouldExit = await checkAndUpgrade("5.8.0", prompt);
|
|
6776
|
+
if (shouldExit) {
|
|
6777
|
+
process.exit(0);
|
|
6753
6778
|
}
|
|
6754
|
-
process.
|
|
6755
|
-
|
|
6756
|
-
|
|
6757
|
-
|
|
6758
|
-
|
|
6759
|
-
|
|
6760
|
-
|
|
6761
|
-
|
|
6762
|
-
|
|
6763
|
-
|
|
6764
|
-
|
|
6765
|
-
|
|
6766
|
-
|
|
6767
|
-
|
|
6768
|
-
if (requiredVarNames.length > 0) {
|
|
6769
|
-
const envFilePath = path12.join(cwd, ".env");
|
|
6770
|
-
const missingVars = checkMissingVariables(requiredVarNames, envFilePath);
|
|
6771
|
-
if (missingVars.length > 0) {
|
|
6772
|
-
await generateEnvPlaceholders(missingVars, envFilePath);
|
|
6773
|
-
console.log();
|
|
6774
|
-
console.log(
|
|
6775
|
-
chalk21.yellow(
|
|
6776
|
-
`\u26A0 Missing environment variables. Please fill in values in .env file:`
|
|
6777
|
-
)
|
|
6778
|
-
);
|
|
6779
|
-
for (const varName of missingVars) {
|
|
6780
|
-
console.log(chalk21.yellow(` ${varName}`));
|
|
6779
|
+
const cwd = process.cwd();
|
|
6780
|
+
console.log(chalk21.bold(`Reading config: ${CONFIG_FILE3}`));
|
|
6781
|
+
if (!existsSync8(CONFIG_FILE3)) {
|
|
6782
|
+
console.error(chalk21.red(`\u2717 Config file not found: ${CONFIG_FILE3}`));
|
|
6783
|
+
process.exit(1);
|
|
6784
|
+
}
|
|
6785
|
+
let config;
|
|
6786
|
+
try {
|
|
6787
|
+
const content = await readFile7(CONFIG_FILE3, "utf8");
|
|
6788
|
+
config = parseYaml4(content);
|
|
6789
|
+
} catch (error) {
|
|
6790
|
+
console.error(chalk21.red("\u2717 Invalid YAML format"));
|
|
6791
|
+
if (error instanceof Error) {
|
|
6792
|
+
console.error(chalk21.dim(` ${error.message}`));
|
|
6781
6793
|
}
|
|
6782
6794
|
process.exit(1);
|
|
6783
6795
|
}
|
|
6784
|
-
|
|
6785
|
-
|
|
6786
|
-
|
|
6787
|
-
|
|
6788
|
-
|
|
6789
|
-
|
|
6790
|
-
|
|
6791
|
-
|
|
6792
|
-
|
|
6793
|
-
|
|
6796
|
+
const validation = validateAgentCompose(config);
|
|
6797
|
+
if (!validation.valid) {
|
|
6798
|
+
console.error(chalk21.red(`\u2717 ${validation.error}`));
|
|
6799
|
+
process.exit(1);
|
|
6800
|
+
}
|
|
6801
|
+
const agentNames = Object.keys(config.agents);
|
|
6802
|
+
const agentName = agentNames[0];
|
|
6803
|
+
const volumeCount = config.volumes ? Object.keys(config.volumes).length : 0;
|
|
6804
|
+
console.log(
|
|
6805
|
+
chalk21.green(`\u2713 Config validated: 1 agent, ${volumeCount} volume(s)`)
|
|
6806
|
+
);
|
|
6807
|
+
const requiredVarNames = extractRequiredVarNames(config);
|
|
6808
|
+
if (requiredVarNames.length > 0) {
|
|
6809
|
+
const envFilePath = path12.join(cwd, ".env");
|
|
6810
|
+
const missingVars = checkMissingVariables(
|
|
6811
|
+
requiredVarNames,
|
|
6812
|
+
envFilePath
|
|
6813
|
+
);
|
|
6814
|
+
if (missingVars.length > 0) {
|
|
6815
|
+
await generateEnvPlaceholders(missingVars, envFilePath);
|
|
6816
|
+
console.log();
|
|
6817
|
+
console.log(
|
|
6818
|
+
chalk21.yellow(
|
|
6819
|
+
`\u26A0 Missing environment variables. Please fill in values in .env file:`
|
|
6794
6820
|
)
|
|
6795
6821
|
);
|
|
6822
|
+
for (const varName of missingVars) {
|
|
6823
|
+
console.log(chalk21.yellow(` ${varName}`));
|
|
6824
|
+
}
|
|
6796
6825
|
process.exit(1);
|
|
6797
6826
|
}
|
|
6798
|
-
|
|
6799
|
-
|
|
6800
|
-
|
|
6801
|
-
|
|
6802
|
-
|
|
6803
|
-
|
|
6804
|
-
|
|
6805
|
-
|
|
6806
|
-
|
|
6807
|
-
|
|
6808
|
-
|
|
6827
|
+
}
|
|
6828
|
+
if (config.volumes && Object.keys(config.volumes).length > 0) {
|
|
6829
|
+
console.log();
|
|
6830
|
+
console.log(chalk21.bold("Processing volumes:"));
|
|
6831
|
+
for (const volumeConfig of Object.values(config.volumes)) {
|
|
6832
|
+
const volumeDir = path12.join(cwd, volumeConfig.name);
|
|
6833
|
+
if (!existsSync8(volumeDir)) {
|
|
6834
|
+
console.error(
|
|
6835
|
+
chalk21.red(
|
|
6836
|
+
`\u2717 Directory not found: ${volumeConfig.name}. Create the directory and add files first.`
|
|
6837
|
+
)
|
|
6809
6838
|
);
|
|
6839
|
+
process.exit(1);
|
|
6810
6840
|
}
|
|
6811
|
-
|
|
6812
|
-
|
|
6813
|
-
|
|
6814
|
-
|
|
6815
|
-
|
|
6816
|
-
|
|
6817
|
-
|
|
6818
|
-
|
|
6819
|
-
|
|
6820
|
-
|
|
6841
|
+
try {
|
|
6842
|
+
printCommand(`cd ${volumeConfig.name}`);
|
|
6843
|
+
const existingConfig = await readStorageConfig(volumeDir);
|
|
6844
|
+
if (!existingConfig) {
|
|
6845
|
+
printCommand(`vm0 volume init --name ${volumeConfig.name}`);
|
|
6846
|
+
await execVm0Command(
|
|
6847
|
+
["volume", "init", "--name", volumeConfig.name],
|
|
6848
|
+
{
|
|
6849
|
+
cwd: volumeDir,
|
|
6850
|
+
silent: true
|
|
6851
|
+
}
|
|
6852
|
+
);
|
|
6853
|
+
}
|
|
6854
|
+
printCommand("vm0 volume push");
|
|
6855
|
+
await execVm0Command(["volume", "push"], {
|
|
6856
|
+
cwd: volumeDir,
|
|
6857
|
+
silent: true
|
|
6858
|
+
});
|
|
6859
|
+
printCommand("cd ..");
|
|
6860
|
+
} catch (error) {
|
|
6861
|
+
console.error(chalk21.red(`\u2717 Failed`));
|
|
6862
|
+
if (error instanceof Error) {
|
|
6863
|
+
console.error(chalk21.dim(` ${error.message}`));
|
|
6864
|
+
}
|
|
6865
|
+
process.exit(1);
|
|
6821
6866
|
}
|
|
6822
|
-
process.exit(1);
|
|
6823
6867
|
}
|
|
6824
6868
|
}
|
|
6825
|
-
|
|
6826
|
-
|
|
6827
|
-
|
|
6828
|
-
|
|
6829
|
-
|
|
6830
|
-
|
|
6831
|
-
|
|
6832
|
-
|
|
6833
|
-
|
|
6834
|
-
|
|
6835
|
-
|
|
6836
|
-
|
|
6837
|
-
|
|
6838
|
-
|
|
6869
|
+
console.log();
|
|
6870
|
+
console.log(chalk21.bold("Processing artifact:"));
|
|
6871
|
+
const artifactDir = path12.join(cwd, ARTIFACT_DIR);
|
|
6872
|
+
try {
|
|
6873
|
+
if (!existsSync8(artifactDir)) {
|
|
6874
|
+
printCommand(`mkdir ${ARTIFACT_DIR}`);
|
|
6875
|
+
await mkdir6(artifactDir, { recursive: true });
|
|
6876
|
+
}
|
|
6877
|
+
printCommand(`cd ${ARTIFACT_DIR}`);
|
|
6878
|
+
const existingConfig = await readStorageConfig(artifactDir);
|
|
6879
|
+
if (!existingConfig) {
|
|
6880
|
+
printCommand(`vm0 artifact init --name ${ARTIFACT_DIR}`);
|
|
6881
|
+
await execVm0Command(["artifact", "init", "--name", ARTIFACT_DIR], {
|
|
6882
|
+
cwd: artifactDir,
|
|
6883
|
+
silent: true
|
|
6884
|
+
});
|
|
6885
|
+
}
|
|
6886
|
+
printCommand("vm0 artifact push");
|
|
6887
|
+
await execVm0Command(["artifact", "push"], {
|
|
6839
6888
|
cwd: artifactDir,
|
|
6840
6889
|
silent: true
|
|
6841
6890
|
});
|
|
6891
|
+
printCommand("cd ..");
|
|
6892
|
+
} catch (error) {
|
|
6893
|
+
console.error(chalk21.red(`\u2717 Failed`));
|
|
6894
|
+
if (error instanceof Error) {
|
|
6895
|
+
console.error(chalk21.dim(` ${error.message}`));
|
|
6896
|
+
}
|
|
6897
|
+
process.exit(1);
|
|
6842
6898
|
}
|
|
6843
|
-
printCommand("vm0 artifact push");
|
|
6844
|
-
await execVm0Command(["artifact", "push"], {
|
|
6845
|
-
cwd: artifactDir,
|
|
6846
|
-
silent: true
|
|
6847
|
-
});
|
|
6848
|
-
printCommand("cd ..");
|
|
6849
|
-
} catch (error) {
|
|
6850
|
-
console.error(chalk21.red(`\u2717 Failed`));
|
|
6851
|
-
if (error instanceof Error) {
|
|
6852
|
-
console.error(chalk21.dim(` ${error.message}`));
|
|
6853
|
-
}
|
|
6854
|
-
process.exit(1);
|
|
6855
|
-
}
|
|
6856
|
-
console.log();
|
|
6857
|
-
console.log(chalk21.bold("Composing agent:"));
|
|
6858
|
-
const composeArgs = options.yes ? ["compose", "--yes", CONFIG_FILE3] : ["compose", CONFIG_FILE3];
|
|
6859
|
-
printCommand(`vm0 ${composeArgs.join(" ")}`);
|
|
6860
|
-
try {
|
|
6861
|
-
await execVm0Command(composeArgs, {
|
|
6862
|
-
cwd
|
|
6863
|
-
});
|
|
6864
|
-
} catch (error) {
|
|
6865
|
-
console.error(chalk21.red(`\u2717 Compose failed`));
|
|
6866
|
-
if (error instanceof Error) {
|
|
6867
|
-
console.error(chalk21.dim(` ${error.message}`));
|
|
6868
|
-
}
|
|
6869
|
-
process.exit(1);
|
|
6870
|
-
}
|
|
6871
|
-
if (prompt) {
|
|
6872
6899
|
console.log();
|
|
6873
|
-
console.log(chalk21.bold("
|
|
6874
|
-
|
|
6875
|
-
|
|
6876
|
-
);
|
|
6877
|
-
console.log();
|
|
6878
|
-
let runOutput;
|
|
6900
|
+
console.log(chalk21.bold("Composing agent:"));
|
|
6901
|
+
const composeArgs = options.yes ? ["compose", "--yes", CONFIG_FILE3] : ["compose", CONFIG_FILE3];
|
|
6902
|
+
printCommand(`vm0 ${composeArgs.join(" ")}`);
|
|
6879
6903
|
try {
|
|
6880
|
-
|
|
6881
|
-
|
|
6882
|
-
|
|
6883
|
-
|
|
6884
|
-
|
|
6885
|
-
|
|
6886
|
-
|
|
6887
|
-
|
|
6888
|
-
} catch {
|
|
6904
|
+
await execVm0Command(composeArgs, {
|
|
6905
|
+
cwd
|
|
6906
|
+
});
|
|
6907
|
+
} catch (error) {
|
|
6908
|
+
console.error(chalk21.red(`\u2717 Compose failed`));
|
|
6909
|
+
if (error instanceof Error) {
|
|
6910
|
+
console.error(chalk21.dim(` ${error.message}`));
|
|
6911
|
+
}
|
|
6889
6912
|
process.exit(1);
|
|
6890
6913
|
}
|
|
6891
|
-
|
|
6892
|
-
|
|
6893
|
-
|
|
6894
|
-
|
|
6895
|
-
|
|
6896
|
-
|
|
6897
|
-
|
|
6914
|
+
if (prompt) {
|
|
6915
|
+
console.log();
|
|
6916
|
+
console.log(chalk21.bold("Running agent:"));
|
|
6917
|
+
printCommand(
|
|
6918
|
+
`vm0 run ${agentName} --artifact-name ${ARTIFACT_DIR} "${prompt}"`
|
|
6919
|
+
);
|
|
6920
|
+
console.log();
|
|
6921
|
+
let runOutput;
|
|
6922
|
+
try {
|
|
6923
|
+
const runArgs = [
|
|
6924
|
+
"run",
|
|
6925
|
+
agentName,
|
|
6926
|
+
"--artifact-name",
|
|
6927
|
+
ARTIFACT_DIR,
|
|
6928
|
+
...options.debugNoMockClaude ? ["--debug-no-mock-claude"] : [],
|
|
6929
|
+
prompt
|
|
6930
|
+
];
|
|
6931
|
+
runOutput = await execVm0RunWithCapture(runArgs, { cwd });
|
|
6932
|
+
} catch {
|
|
6933
|
+
process.exit(1);
|
|
6934
|
+
}
|
|
6935
|
+
const runIds = parseRunIdsFromOutput(runOutput);
|
|
6936
|
+
if (runIds.runId || runIds.sessionId || runIds.checkpointId) {
|
|
6937
|
+
await saveCookState({
|
|
6938
|
+
lastRunId: runIds.runId,
|
|
6939
|
+
lastSessionId: runIds.sessionId,
|
|
6940
|
+
lastCheckpointId: runIds.checkpointId
|
|
6941
|
+
});
|
|
6942
|
+
}
|
|
6943
|
+
await autoPullArtifact(runOutput, artifactDir);
|
|
6944
|
+
} else {
|
|
6945
|
+
console.log();
|
|
6946
|
+
console.log("To run your agent:");
|
|
6947
|
+
printCommand(
|
|
6948
|
+
`vm0 run ${agentName} --artifact-name ${ARTIFACT_DIR} "your prompt"`
|
|
6949
|
+
);
|
|
6898
6950
|
}
|
|
6899
|
-
await autoPullArtifact(runOutput, artifactDir);
|
|
6900
|
-
} else {
|
|
6901
|
-
console.log();
|
|
6902
|
-
console.log("To run your agent:");
|
|
6903
|
-
printCommand(
|
|
6904
|
-
`vm0 run ${agentName} --artifact-name ${ARTIFACT_DIR} "your prompt"`
|
|
6905
|
-
);
|
|
6906
6951
|
}
|
|
6907
|
-
|
|
6952
|
+
);
|
|
6908
6953
|
cookCmd.command("logs").description("View logs from the last cook run").option("-a, --agent", "Show agent events (default)").option("-s, --system", "Show system log").option("-m, --metrics", "Show metrics").option("-n, --network", "Show network logs (proxy traffic)").option(
|
|
6909
6954
|
"--since <time>",
|
|
6910
6955
|
"Show logs since timestamp (e.g., 5m, 2h, 1d, 2024-01-15T10:30:00Z)"
|
|
@@ -6952,7 +6997,7 @@ cookCmd.command("logs").description("View logs from the last cook run").option("
|
|
|
6952
6997
|
);
|
|
6953
6998
|
cookCmd.command("continue").description(
|
|
6954
6999
|
"Continue from the last session (latest conversation and artifact)"
|
|
6955
|
-
).argument("<prompt>", "Prompt for the continued agent").action(async (prompt) => {
|
|
7000
|
+
).argument("<prompt>", "Prompt for the continued agent").option("--debug-no-mock-claude").action(async (prompt, options) => {
|
|
6956
7001
|
const state = await loadCookState();
|
|
6957
7002
|
if (!state.lastSessionId) {
|
|
6958
7003
|
console.error(chalk21.red("\u2717 No previous session found"));
|
|
@@ -6966,7 +7011,13 @@ cookCmd.command("continue").description(
|
|
|
6966
7011
|
let runOutput;
|
|
6967
7012
|
try {
|
|
6968
7013
|
runOutput = await execVm0RunWithCapture(
|
|
6969
|
-
[
|
|
7014
|
+
[
|
|
7015
|
+
"run",
|
|
7016
|
+
"continue",
|
|
7017
|
+
state.lastSessionId,
|
|
7018
|
+
...options.debugNoMockClaude ? ["--debug-no-mock-claude"] : [],
|
|
7019
|
+
prompt
|
|
7020
|
+
],
|
|
6970
7021
|
{ cwd }
|
|
6971
7022
|
);
|
|
6972
7023
|
} catch {
|
|
@@ -6984,7 +7035,7 @@ cookCmd.command("continue").description(
|
|
|
6984
7035
|
});
|
|
6985
7036
|
cookCmd.command("resume").description(
|
|
6986
7037
|
"Resume from the last checkpoint (snapshotted conversation and artifact)"
|
|
6987
|
-
).argument("<prompt>", "Prompt for the resumed agent").action(async (prompt) => {
|
|
7038
|
+
).argument("<prompt>", "Prompt for the resumed agent").option("--debug-no-mock-claude").action(async (prompt, options) => {
|
|
6988
7039
|
const state = await loadCookState();
|
|
6989
7040
|
if (!state.lastCheckpointId) {
|
|
6990
7041
|
console.error(chalk21.red("\u2717 No previous checkpoint found"));
|
|
@@ -6998,7 +7049,13 @@ cookCmd.command("resume").description(
|
|
|
6998
7049
|
let runOutput;
|
|
6999
7050
|
try {
|
|
7000
7051
|
runOutput = await execVm0RunWithCapture(
|
|
7001
|
-
[
|
|
7052
|
+
[
|
|
7053
|
+
"run",
|
|
7054
|
+
"resume",
|
|
7055
|
+
state.lastCheckpointId,
|
|
7056
|
+
...options.debugNoMockClaude ? ["--debug-no-mock-claude"] : [],
|
|
7057
|
+
prompt
|
|
7058
|
+
],
|
|
7002
7059
|
{ cwd }
|
|
7003
7060
|
);
|
|
7004
7061
|
} catch {
|
|
@@ -7394,10 +7451,10 @@ var setCommand = new Command20().name("set").description("Set your scope slug").
|
|
|
7394
7451
|
// src/commands/scope/index.ts
|
|
7395
7452
|
var scopeCommand = new Command21().name("scope").description("Manage your scope (namespace for images)").addCommand(statusCommand3).addCommand(setCommand);
|
|
7396
7453
|
|
|
7397
|
-
// src/commands/
|
|
7454
|
+
// src/commands/agent/index.ts
|
|
7398
7455
|
import { Command as Command24 } from "commander";
|
|
7399
7456
|
|
|
7400
|
-
// src/commands/
|
|
7457
|
+
// src/commands/agent/list.ts
|
|
7401
7458
|
import { Command as Command22 } from "commander";
|
|
7402
7459
|
import chalk25 from "chalk";
|
|
7403
7460
|
var listCommand3 = new Command22().name("list").alias("ls").description("List all agent composes").option("-s, --scope <scope>", "Scope to list composes from").action(async (options) => {
|
|
@@ -7443,7 +7500,7 @@ var listCommand3 = new Command22().name("list").alias("ls").description("List al
|
|
|
7443
7500
|
}
|
|
7444
7501
|
});
|
|
7445
7502
|
|
|
7446
|
-
// src/commands/
|
|
7503
|
+
// src/commands/agent/inspect.ts
|
|
7447
7504
|
import { Command as Command23 } from "commander";
|
|
7448
7505
|
import chalk26 from "chalk";
|
|
7449
7506
|
|
|
@@ -7553,7 +7610,7 @@ async function deriveComposeVariableSources(content, options) {
|
|
|
7553
7610
|
return results;
|
|
7554
7611
|
}
|
|
7555
7612
|
|
|
7556
|
-
// src/commands/
|
|
7613
|
+
// src/commands/agent/inspect.ts
|
|
7557
7614
|
function formatComposeOutput(name, versionId, content, variableSources) {
|
|
7558
7615
|
console.log(chalk26.bold("Name:") + ` ${name}`);
|
|
7559
7616
|
console.log(chalk26.bold("Version:") + ` ${versionId}`);
|
|
@@ -7635,7 +7692,7 @@ var inspectCommand = new Command23().name("inspect").description("Inspect an age
|
|
|
7635
7692
|
} catch (error) {
|
|
7636
7693
|
if (error instanceof Error && error.message.includes("not found")) {
|
|
7637
7694
|
console.error(chalk26.red(`\u2717 Agent compose not found: ${name}`));
|
|
7638
|
-
console.error(chalk26.dim(" Run: vm0
|
|
7695
|
+
console.error(chalk26.dim(" Run: vm0 agent list"));
|
|
7639
7696
|
process.exit(1);
|
|
7640
7697
|
}
|
|
7641
7698
|
throw error;
|
|
@@ -7702,8 +7759,8 @@ var inspectCommand = new Command23().name("inspect").description("Inspect an age
|
|
|
7702
7759
|
}
|
|
7703
7760
|
);
|
|
7704
7761
|
|
|
7705
|
-
// src/commands/
|
|
7706
|
-
var
|
|
7762
|
+
// src/commands/agent/index.ts
|
|
7763
|
+
var agentCommand = new Command24().name("agent").description("Manage agent composes").addCommand(listCommand3).addCommand(inspectCommand);
|
|
7707
7764
|
|
|
7708
7765
|
// src/commands/init.ts
|
|
7709
7766
|
import { Command as Command25 } from "commander";
|
|
@@ -9398,11 +9455,183 @@ var disableCommand = new Command33().name("disable").description("Disable a sche
|
|
|
9398
9455
|
// src/commands/schedule/index.ts
|
|
9399
9456
|
var scheduleCommand = new Command34().name("schedule").description("Manage agent schedules").addCommand(initCommand4).addCommand(deployCommand).addCommand(listCommand4).addCommand(statusCommand4).addCommand(deleteCommand).addCommand(enableCommand).addCommand(disableCommand);
|
|
9400
9457
|
|
|
9458
|
+
// src/commands/usage.ts
|
|
9459
|
+
import { Command as Command35 } from "commander";
|
|
9460
|
+
import chalk36 from "chalk";
|
|
9461
|
+
|
|
9462
|
+
// src/lib/utils/duration-formatter.ts
|
|
9463
|
+
function formatDuration(ms) {
|
|
9464
|
+
if (ms === null || ms === void 0 || ms === 0) {
|
|
9465
|
+
return "-";
|
|
9466
|
+
}
|
|
9467
|
+
if (ms < 0) {
|
|
9468
|
+
return "-";
|
|
9469
|
+
}
|
|
9470
|
+
const totalSeconds = Math.floor(ms / 1e3);
|
|
9471
|
+
if (totalSeconds === 0) {
|
|
9472
|
+
return "< 1s";
|
|
9473
|
+
}
|
|
9474
|
+
const hours = Math.floor(totalSeconds / 3600);
|
|
9475
|
+
const minutes = Math.floor(totalSeconds % 3600 / 60);
|
|
9476
|
+
const seconds = totalSeconds % 60;
|
|
9477
|
+
const parts = [];
|
|
9478
|
+
if (hours > 0) {
|
|
9479
|
+
parts.push(`${hours}h`);
|
|
9480
|
+
}
|
|
9481
|
+
if (minutes > 0) {
|
|
9482
|
+
parts.push(`${minutes}m`);
|
|
9483
|
+
}
|
|
9484
|
+
if (seconds > 0) {
|
|
9485
|
+
parts.push(`${seconds}s`);
|
|
9486
|
+
}
|
|
9487
|
+
return parts.join(" ");
|
|
9488
|
+
}
|
|
9489
|
+
|
|
9490
|
+
// src/commands/usage.ts
|
|
9491
|
+
var MAX_RANGE_MS = 30 * 24 * 60 * 60 * 1e3;
|
|
9492
|
+
var DEFAULT_RANGE_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
9493
|
+
function formatDateDisplay(dateStr) {
|
|
9494
|
+
const date = new Date(dateStr);
|
|
9495
|
+
return date.toLocaleDateString("en-US", { month: "short", day: "numeric" });
|
|
9496
|
+
}
|
|
9497
|
+
function formatDateRange(start, end) {
|
|
9498
|
+
const startDate = new Date(start);
|
|
9499
|
+
const endDate = new Date(end);
|
|
9500
|
+
endDate.setDate(endDate.getDate() - 1);
|
|
9501
|
+
const startStr = startDate.toLocaleDateString("en-US", {
|
|
9502
|
+
month: "short",
|
|
9503
|
+
day: "numeric"
|
|
9504
|
+
});
|
|
9505
|
+
const endStr = endDate.toLocaleDateString("en-US", {
|
|
9506
|
+
month: "short",
|
|
9507
|
+
day: "numeric",
|
|
9508
|
+
year: "numeric"
|
|
9509
|
+
});
|
|
9510
|
+
return `${startStr} - ${endStr}`;
|
|
9511
|
+
}
|
|
9512
|
+
function fillMissingDates(daily, startDate, endDate) {
|
|
9513
|
+
const dateMap = /* @__PURE__ */ new Map();
|
|
9514
|
+
for (const day of daily) {
|
|
9515
|
+
dateMap.set(day.date, day);
|
|
9516
|
+
}
|
|
9517
|
+
const result = [];
|
|
9518
|
+
const current = new Date(startDate);
|
|
9519
|
+
current.setUTCHours(0, 0, 0, 0);
|
|
9520
|
+
while (current < endDate) {
|
|
9521
|
+
const dateStr = current.toISOString().split("T")[0];
|
|
9522
|
+
const existing = dateMap.get(dateStr);
|
|
9523
|
+
if (existing) {
|
|
9524
|
+
result.push(existing);
|
|
9525
|
+
} else {
|
|
9526
|
+
result.push({ date: dateStr, run_count: 0, run_time_ms: 0 });
|
|
9527
|
+
}
|
|
9528
|
+
current.setDate(current.getDate() + 1);
|
|
9529
|
+
}
|
|
9530
|
+
result.sort((a, b) => b.date.localeCompare(a.date));
|
|
9531
|
+
return result;
|
|
9532
|
+
}
|
|
9533
|
+
var usageCommand = new Command35().name("usage").description("View usage statistics").option("--since <date>", "Start date (ISO format or relative: 7d, 30d)").option(
|
|
9534
|
+
"--until <date>",
|
|
9535
|
+
"End date (ISO format or relative, defaults to now)"
|
|
9536
|
+
).action(async (options) => {
|
|
9537
|
+
try {
|
|
9538
|
+
const now = /* @__PURE__ */ new Date();
|
|
9539
|
+
let endDate;
|
|
9540
|
+
let startDate;
|
|
9541
|
+
if (options.until) {
|
|
9542
|
+
try {
|
|
9543
|
+
const untilMs = parseTime(options.until);
|
|
9544
|
+
endDate = new Date(untilMs);
|
|
9545
|
+
} catch {
|
|
9546
|
+
console.error(
|
|
9547
|
+
chalk36.red(
|
|
9548
|
+
"Error: Invalid --until format. Use ISO (2026-01-01) or relative (7d, 30d)"
|
|
9549
|
+
)
|
|
9550
|
+
);
|
|
9551
|
+
process.exit(1);
|
|
9552
|
+
}
|
|
9553
|
+
} else {
|
|
9554
|
+
endDate = now;
|
|
9555
|
+
}
|
|
9556
|
+
if (options.since) {
|
|
9557
|
+
try {
|
|
9558
|
+
const sinceMs = parseTime(options.since);
|
|
9559
|
+
startDate = new Date(sinceMs);
|
|
9560
|
+
} catch {
|
|
9561
|
+
console.error(
|
|
9562
|
+
chalk36.red(
|
|
9563
|
+
"Error: Invalid --since format. Use ISO (2026-01-01) or relative (7d, 30d)"
|
|
9564
|
+
)
|
|
9565
|
+
);
|
|
9566
|
+
process.exit(1);
|
|
9567
|
+
}
|
|
9568
|
+
} else {
|
|
9569
|
+
startDate = new Date(endDate.getTime() - DEFAULT_RANGE_MS);
|
|
9570
|
+
}
|
|
9571
|
+
if (startDate >= endDate) {
|
|
9572
|
+
console.error(chalk36.red("Error: --since must be before --until"));
|
|
9573
|
+
process.exit(1);
|
|
9574
|
+
}
|
|
9575
|
+
const rangeMs = endDate.getTime() - startDate.getTime();
|
|
9576
|
+
if (rangeMs > MAX_RANGE_MS) {
|
|
9577
|
+
console.error(
|
|
9578
|
+
chalk36.red(
|
|
9579
|
+
"Error: Time range exceeds maximum of 30 days. Use --until to specify an end date."
|
|
9580
|
+
)
|
|
9581
|
+
);
|
|
9582
|
+
process.exit(1);
|
|
9583
|
+
}
|
|
9584
|
+
const usage = await apiClient.getUsage({
|
|
9585
|
+
startDate: startDate.toISOString(),
|
|
9586
|
+
endDate: endDate.toISOString()
|
|
9587
|
+
});
|
|
9588
|
+
const filledDaily = fillMissingDates(
|
|
9589
|
+
usage.daily,
|
|
9590
|
+
new Date(usage.period.start),
|
|
9591
|
+
new Date(usage.period.end)
|
|
9592
|
+
);
|
|
9593
|
+
console.log();
|
|
9594
|
+
console.log(
|
|
9595
|
+
chalk36.bold(
|
|
9596
|
+
`Usage Summary (${formatDateRange(usage.period.start, usage.period.end)})`
|
|
9597
|
+
)
|
|
9598
|
+
);
|
|
9599
|
+
console.log();
|
|
9600
|
+
console.log(chalk36.dim("DATE RUNS RUN TIME"));
|
|
9601
|
+
for (const day of filledDaily) {
|
|
9602
|
+
const dateDisplay = formatDateDisplay(day.date).padEnd(10);
|
|
9603
|
+
const runsDisplay = String(day.run_count).padStart(6);
|
|
9604
|
+
const timeDisplay = formatDuration(day.run_time_ms);
|
|
9605
|
+
console.log(`${dateDisplay}${runsDisplay} ${timeDisplay}`);
|
|
9606
|
+
}
|
|
9607
|
+
console.log(chalk36.dim("\u2500".repeat(29)));
|
|
9608
|
+
const totalRunsDisplay = String(usage.summary.total_runs).padStart(6);
|
|
9609
|
+
const totalTimeDisplay = formatDuration(usage.summary.total_run_time_ms);
|
|
9610
|
+
console.log(
|
|
9611
|
+
`${"TOTAL".padEnd(10)}${totalRunsDisplay} ${totalTimeDisplay}`
|
|
9612
|
+
);
|
|
9613
|
+
console.log();
|
|
9614
|
+
} catch (error) {
|
|
9615
|
+
if (error instanceof Error) {
|
|
9616
|
+
if (error.message.includes("Not authenticated")) {
|
|
9617
|
+
console.error(
|
|
9618
|
+
chalk36.red("Error: Not authenticated. Run: vm0 auth login")
|
|
9619
|
+
);
|
|
9620
|
+
} else {
|
|
9621
|
+
console.error(chalk36.red(`Error: ${error.message}`));
|
|
9622
|
+
}
|
|
9623
|
+
} else {
|
|
9624
|
+
console.error(chalk36.red("Error: An unexpected error occurred"));
|
|
9625
|
+
}
|
|
9626
|
+
process.exit(1);
|
|
9627
|
+
}
|
|
9628
|
+
});
|
|
9629
|
+
|
|
9401
9630
|
// src/index.ts
|
|
9402
|
-
var program = new
|
|
9403
|
-
program.name("vm0").description("VM0 CLI - A modern build tool").version("5.
|
|
9631
|
+
var program = new Command36();
|
|
9632
|
+
program.name("vm0").description("VM0 CLI - A modern build tool").version("5.8.0");
|
|
9404
9633
|
program.command("info").description("Display environment information").action(async () => {
|
|
9405
|
-
console.log(
|
|
9634
|
+
console.log(chalk37.bold("System Information:"));
|
|
9406
9635
|
console.log(`Node Version: ${process.version}`);
|
|
9407
9636
|
console.log(`Platform: ${process.platform}`);
|
|
9408
9637
|
console.log(`Architecture: ${process.arch}`);
|
|
@@ -9429,10 +9658,11 @@ program.addCommand(artifactCommand);
|
|
|
9429
9658
|
program.addCommand(cookCommand);
|
|
9430
9659
|
program.addCommand(logsCommand);
|
|
9431
9660
|
program.addCommand(scopeCommand);
|
|
9432
|
-
program.addCommand(
|
|
9661
|
+
program.addCommand(agentCommand);
|
|
9433
9662
|
program.addCommand(initCommand3);
|
|
9434
9663
|
program.addCommand(setupGithubCommand);
|
|
9435
9664
|
program.addCommand(scheduleCommand);
|
|
9665
|
+
program.addCommand(usageCommand);
|
|
9436
9666
|
if (process.argv[1]?.endsWith("index.js") || process.argv[1]?.endsWith("index.ts") || process.argv[1]?.endsWith("vm0")) {
|
|
9437
9667
|
program.parse();
|
|
9438
9668
|
}
|