@vm0/cli 9.0.0 → 9.2.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 +624 -393
- 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 Command48 } from "commander";
|
|
5
|
+
import chalk48 from "chalk";
|
|
6
6
|
|
|
7
7
|
// src/lib/api/auth.ts
|
|
8
8
|
import chalk from "chalk";
|
|
@@ -12,20 +12,27 @@ import { homedir } from "os";
|
|
|
12
12
|
import { join } from "path";
|
|
13
13
|
import { readFile, writeFile, mkdir, unlink } from "fs/promises";
|
|
14
14
|
import { existsSync } from "fs";
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
function getConfigDir() {
|
|
16
|
+
return join(homedir(), ".vm0");
|
|
17
|
+
}
|
|
18
|
+
function getConfigFile() {
|
|
19
|
+
return join(getConfigDir(), "config.json");
|
|
20
|
+
}
|
|
17
21
|
async function loadConfig() {
|
|
18
|
-
|
|
22
|
+
const configFile = getConfigFile();
|
|
23
|
+
if (!existsSync(configFile)) {
|
|
19
24
|
return {};
|
|
20
25
|
}
|
|
21
|
-
const content = await readFile(
|
|
26
|
+
const content = await readFile(configFile, "utf8");
|
|
22
27
|
return JSON.parse(content);
|
|
23
28
|
}
|
|
24
29
|
async function saveConfig(config) {
|
|
25
|
-
|
|
30
|
+
const configDir = getConfigDir();
|
|
31
|
+
const configFile = getConfigFile();
|
|
32
|
+
await mkdir(configDir, { recursive: true });
|
|
26
33
|
const existing = await loadConfig();
|
|
27
34
|
const merged = { ...existing, ...config };
|
|
28
|
-
await writeFile(
|
|
35
|
+
await writeFile(configFile, JSON.stringify(merged, null, 2), "utf8");
|
|
29
36
|
}
|
|
30
37
|
async function getToken() {
|
|
31
38
|
if (process.env.VM0_TOKEN) {
|
|
@@ -43,8 +50,9 @@ async function getApiUrl() {
|
|
|
43
50
|
return config.apiUrl ?? "https://www.vm0.ai";
|
|
44
51
|
}
|
|
45
52
|
async function clearConfig() {
|
|
46
|
-
|
|
47
|
-
|
|
53
|
+
const configFile = getConfigFile();
|
|
54
|
+
if (existsSync(configFile)) {
|
|
55
|
+
await unlink(configFile);
|
|
48
56
|
}
|
|
49
57
|
}
|
|
50
58
|
|
|
@@ -86,7 +94,7 @@ async function authenticate(apiUrl) {
|
|
|
86
94
|
console.log("Initiating authentication...");
|
|
87
95
|
const deviceAuth = await requestDeviceCode(targetApiUrl);
|
|
88
96
|
console.log(chalk.green("\nDevice code generated"));
|
|
89
|
-
const verificationUrl = `${targetApiUrl}
|
|
97
|
+
const verificationUrl = `${targetApiUrl}${deviceAuth.verification_path}`;
|
|
90
98
|
console.log(chalk.cyan(`
|
|
91
99
|
To authenticate, visit: ${verificationUrl}`));
|
|
92
100
|
console.log(`And enter this code: ${chalk.bold(deviceAuth.user_code)}`);
|
|
@@ -182,8 +190,14 @@ async function setupToken() {
|
|
|
182
190
|
);
|
|
183
191
|
}
|
|
184
192
|
|
|
185
|
-
// src/commands/
|
|
193
|
+
// src/commands/auth/login.ts
|
|
186
194
|
import { Command } from "commander";
|
|
195
|
+
var loginCommand = new Command().name("login").description("Log in to VM0 (use VM0_API_URL env var to set API URL)").action(async () => {
|
|
196
|
+
await authenticate();
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
// src/commands/compose.ts
|
|
200
|
+
import { Command as Command2 } from "commander";
|
|
187
201
|
import chalk2 from "chalk";
|
|
188
202
|
import { readFile as readFile4 } from "fs/promises";
|
|
189
203
|
import { existsSync as existsSync3 } from "fs";
|
|
@@ -711,7 +725,8 @@ var runsMainContract = c3.router({
|
|
|
711
725
|
201: createRunResponseSchema,
|
|
712
726
|
400: apiErrorSchema,
|
|
713
727
|
401: apiErrorSchema,
|
|
714
|
-
404: apiErrorSchema
|
|
728
|
+
404: apiErrorSchema,
|
|
729
|
+
429: apiErrorSchema
|
|
715
730
|
},
|
|
716
731
|
summary: "Create and execute agent run"
|
|
717
732
|
}
|
|
@@ -1483,7 +1498,7 @@ var cliAuthDeviceContract = c6.router({
|
|
|
1483
1498
|
200: z8.object({
|
|
1484
1499
|
device_code: z8.string(),
|
|
1485
1500
|
user_code: z8.string(),
|
|
1486
|
-
|
|
1501
|
+
verification_path: z8.string(),
|
|
1487
1502
|
expires_in: z8.number(),
|
|
1488
1503
|
interval: z8.number()
|
|
1489
1504
|
}),
|
|
@@ -2296,8 +2311,10 @@ var publicApiErrorTypeSchema = z18.enum([
|
|
|
2296
2311
|
// Auth failure (401)
|
|
2297
2312
|
"not_found_error",
|
|
2298
2313
|
// Resource missing (404)
|
|
2299
|
-
"conflict_error"
|
|
2314
|
+
"conflict_error",
|
|
2300
2315
|
// Resource conflict (409)
|
|
2316
|
+
"rate_limit_error"
|
|
2317
|
+
// Rate limit exceeded (429)
|
|
2301
2318
|
]);
|
|
2302
2319
|
var publicApiErrorSchema = z18.object({
|
|
2303
2320
|
error: z18.object({
|
|
@@ -2327,6 +2344,11 @@ var timestampSchema = z18.string().datetime();
|
|
|
2327
2344
|
|
|
2328
2345
|
// ../../packages/core/src/contracts/platform.ts
|
|
2329
2346
|
var c15 = initContract();
|
|
2347
|
+
var platformPaginationSchema = z19.object({
|
|
2348
|
+
hasMore: z19.boolean(),
|
|
2349
|
+
nextCursor: z19.string().nullable(),
|
|
2350
|
+
totalPages: z19.number()
|
|
2351
|
+
});
|
|
2330
2352
|
var platformLogStatusSchema = z19.enum([
|
|
2331
2353
|
"pending",
|
|
2332
2354
|
"running",
|
|
@@ -2338,9 +2360,10 @@ var platformLogStatusSchema = z19.enum([
|
|
|
2338
2360
|
var platformLogEntrySchema = z19.object({
|
|
2339
2361
|
id: z19.string().uuid()
|
|
2340
2362
|
});
|
|
2341
|
-
var platformLogsListResponseSchema =
|
|
2342
|
-
platformLogEntrySchema
|
|
2343
|
-
|
|
2363
|
+
var platformLogsListResponseSchema = z19.object({
|
|
2364
|
+
data: z19.array(platformLogEntrySchema),
|
|
2365
|
+
pagination: platformPaginationSchema
|
|
2366
|
+
});
|
|
2344
2367
|
var artifactSchema = z19.object({
|
|
2345
2368
|
name: z19.string().nullable(),
|
|
2346
2369
|
version: z19.string().nullable()
|
|
@@ -2349,7 +2372,7 @@ var platformLogDetailSchema = z19.object({
|
|
|
2349
2372
|
id: z19.string().uuid(),
|
|
2350
2373
|
sessionId: z19.string().nullable(),
|
|
2351
2374
|
agentName: z19.string(),
|
|
2352
|
-
|
|
2375
|
+
framework: z19.string().nullable(),
|
|
2353
2376
|
status: platformLogStatusSchema,
|
|
2354
2377
|
prompt: z19.string(),
|
|
2355
2378
|
error: z19.string().nullable(),
|
|
@@ -2387,6 +2410,26 @@ var platformLogsByIdContract = c15.router({
|
|
|
2387
2410
|
summary: "Get agent run log details by ID"
|
|
2388
2411
|
}
|
|
2389
2412
|
});
|
|
2413
|
+
var artifactDownloadResponseSchema = z19.object({
|
|
2414
|
+
url: z19.string().url(),
|
|
2415
|
+
expiresAt: z19.string()
|
|
2416
|
+
});
|
|
2417
|
+
var platformArtifactDownloadContract = c15.router({
|
|
2418
|
+
getDownloadUrl: {
|
|
2419
|
+
method: "GET",
|
|
2420
|
+
path: "/api/platform/artifacts/download",
|
|
2421
|
+
query: z19.object({
|
|
2422
|
+
name: z19.string().min(1, "Artifact name is required"),
|
|
2423
|
+
version: z19.string().optional()
|
|
2424
|
+
}),
|
|
2425
|
+
responses: {
|
|
2426
|
+
200: artifactDownloadResponseSchema,
|
|
2427
|
+
401: apiErrorSchema,
|
|
2428
|
+
404: apiErrorSchema
|
|
2429
|
+
},
|
|
2430
|
+
summary: "Get presigned URL for artifact download"
|
|
2431
|
+
}
|
|
2432
|
+
});
|
|
2390
2433
|
|
|
2391
2434
|
// ../../packages/core/src/contracts/public/agents.ts
|
|
2392
2435
|
import { z as z20 } from "zod";
|
|
@@ -2519,9 +2562,7 @@ var createRunRequestSchema = z21.object({
|
|
|
2519
2562
|
// volume_name -> version
|
|
2520
2563
|
});
|
|
2521
2564
|
var runListQuerySchema = listQuerySchema.extend({
|
|
2522
|
-
|
|
2523
|
-
status: publicRunStatusSchema.optional(),
|
|
2524
|
-
since: timestampSchema.optional()
|
|
2565
|
+
status: publicRunStatusSchema.optional()
|
|
2525
2566
|
});
|
|
2526
2567
|
var publicRunsListContract = c17.router({
|
|
2527
2568
|
list: {
|
|
@@ -2535,7 +2576,7 @@ var publicRunsListContract = c17.router({
|
|
|
2535
2576
|
500: publicApiErrorSchema
|
|
2536
2577
|
},
|
|
2537
2578
|
summary: "List runs",
|
|
2538
|
-
description: "List runs with optional filtering by
|
|
2579
|
+
description: "List runs with optional filtering by status"
|
|
2539
2580
|
},
|
|
2540
2581
|
create: {
|
|
2541
2582
|
method: "POST",
|
|
@@ -2548,6 +2589,7 @@ var publicRunsListContract = c17.router({
|
|
|
2548
2589
|
400: publicApiErrorSchema,
|
|
2549
2590
|
401: publicApiErrorSchema,
|
|
2550
2591
|
404: publicApiErrorSchema,
|
|
2592
|
+
429: publicApiErrorSchema,
|
|
2551
2593
|
500: publicApiErrorSchema
|
|
2552
2594
|
},
|
|
2553
2595
|
summary: "Create run",
|
|
@@ -3094,10 +3136,10 @@ async function getRawHeaders() {
|
|
|
3094
3136
|
}
|
|
3095
3137
|
return headers;
|
|
3096
3138
|
}
|
|
3097
|
-
async function httpGet(
|
|
3139
|
+
async function httpGet(path15) {
|
|
3098
3140
|
const baseUrl = await getBaseUrl();
|
|
3099
3141
|
const headers = await getRawHeaders();
|
|
3100
|
-
return fetch(`${baseUrl}${
|
|
3142
|
+
return fetch(`${baseUrl}${path15}`, {
|
|
3101
3143
|
method: "GET",
|
|
3102
3144
|
headers
|
|
3103
3145
|
});
|
|
@@ -3577,49 +3619,49 @@ var cliComposeSchema = z24.object({
|
|
|
3577
3619
|
function formatZodError(error) {
|
|
3578
3620
|
const issue = error.issues[0];
|
|
3579
3621
|
if (!issue) return "Validation failed";
|
|
3580
|
-
const
|
|
3622
|
+
const path15 = issue.path.join(".");
|
|
3581
3623
|
const message = issue.message;
|
|
3582
|
-
if (!
|
|
3624
|
+
if (!path15) return message;
|
|
3583
3625
|
if (issue.code === "invalid_type") {
|
|
3584
3626
|
const received = issue.received;
|
|
3585
3627
|
const isMissing = received === "undefined" || message.includes("received undefined") || message === "Required";
|
|
3586
|
-
if (
|
|
3628
|
+
if (path15 === "version" && isMissing) {
|
|
3587
3629
|
return "Missing config.version";
|
|
3588
3630
|
}
|
|
3589
|
-
if (
|
|
3631
|
+
if (path15 === "agents" && isMissing) {
|
|
3590
3632
|
return "Missing agents object in config";
|
|
3591
3633
|
}
|
|
3592
|
-
if (
|
|
3593
|
-
const volumeKey =
|
|
3634
|
+
if (path15.startsWith("volumes.") && path15.endsWith(".name")) {
|
|
3635
|
+
const volumeKey = path15.split(".")[1];
|
|
3594
3636
|
return `Volume "${volumeKey}" must have a 'name' field (string)`;
|
|
3595
3637
|
}
|
|
3596
|
-
if (
|
|
3597
|
-
const volumeKey =
|
|
3638
|
+
if (path15.startsWith("volumes.") && path15.endsWith(".version")) {
|
|
3639
|
+
const volumeKey = path15.split(".")[1];
|
|
3598
3640
|
return `Volume "${volumeKey}" must have a 'version' field (string)`;
|
|
3599
3641
|
}
|
|
3600
3642
|
if (issue.expected === "array") {
|
|
3601
|
-
const fieldName =
|
|
3643
|
+
const fieldName = path15.replace(/^agents\.[^.]+\./, "agent.");
|
|
3602
3644
|
return `${fieldName} must be an array`;
|
|
3603
3645
|
}
|
|
3604
3646
|
if (issue.expected === "string" && received === "number") {
|
|
3605
|
-
const fieldName =
|
|
3647
|
+
const fieldName = path15.replace(/^agents\.[^.]+\./, "agent.");
|
|
3606
3648
|
const match = fieldName.match(/^(agent\.[^.]+)\.\d+$/);
|
|
3607
3649
|
if (match) {
|
|
3608
3650
|
return `Each entry in ${match[1]?.replace("agent.", "")} must be a string`;
|
|
3609
3651
|
}
|
|
3610
3652
|
}
|
|
3611
3653
|
}
|
|
3612
|
-
if (issue.code === "invalid_key" &&
|
|
3654
|
+
if (issue.code === "invalid_key" && path15.startsWith("agents.")) {
|
|
3613
3655
|
return "Invalid agent name format. Must be 3-64 characters, letters, numbers, and hyphens only. Must start and end with letter or number.";
|
|
3614
3656
|
}
|
|
3615
|
-
if (message === "Invalid key in record" &&
|
|
3657
|
+
if (message === "Invalid key in record" && path15.startsWith("agents.")) {
|
|
3616
3658
|
return "Invalid agent name format. Must be 3-64 characters, letters, numbers, and hyphens only. Must start and end with letter or number.";
|
|
3617
3659
|
}
|
|
3618
3660
|
if (issue.code === "custom") {
|
|
3619
3661
|
return message;
|
|
3620
3662
|
}
|
|
3621
|
-
if (
|
|
3622
|
-
const cleanPath =
|
|
3663
|
+
if (path15.startsWith("agents.")) {
|
|
3664
|
+
const cleanPath = path15.replace(/^agents\.[^.]+\./, "agent.");
|
|
3623
3665
|
if (message.startsWith("Invalid input:")) {
|
|
3624
3666
|
const match = message.match(/expected (\w+), received (\w+)/);
|
|
3625
3667
|
if (match && match[1] === "string" && match[2] === "number") {
|
|
@@ -3631,7 +3673,7 @@ function formatZodError(error) {
|
|
|
3631
3673
|
}
|
|
3632
3674
|
return `${cleanPath}: ${message}`;
|
|
3633
3675
|
}
|
|
3634
|
-
return `${
|
|
3676
|
+
return `${path15}: ${message}`;
|
|
3635
3677
|
}
|
|
3636
3678
|
function validateAgentName(name) {
|
|
3637
3679
|
return cliAgentNameSchema.safeParse(name).success;
|
|
@@ -4205,7 +4247,7 @@ function getSecretsFromComposeContent(content) {
|
|
|
4205
4247
|
const grouped = groupVariablesBySource(refs);
|
|
4206
4248
|
return new Set(grouped.secrets.map((r) => r.name));
|
|
4207
4249
|
}
|
|
4208
|
-
var composeCommand = new
|
|
4250
|
+
var composeCommand = new Command2().name("compose").description("Create or update agent compose (e.g., vm0.yaml)").argument("<agent-yaml>", "Path to agent YAML file").option("-y, --yes", "Skip confirmation prompts for skill requirements").action(async (configFile, options) => {
|
|
4209
4251
|
try {
|
|
4210
4252
|
if (!existsSync3(configFile)) {
|
|
4211
4253
|
console.error(chalk2.red(`\u2717 Config file not found: ${configFile}`));
|
|
@@ -4409,7 +4451,7 @@ var composeCommand = new Command().name("compose").description("Create or update
|
|
|
4409
4451
|
});
|
|
4410
4452
|
|
|
4411
4453
|
// src/commands/run/run.ts
|
|
4412
|
-
import { Command as
|
|
4454
|
+
import { Command as Command3, Option } from "commander";
|
|
4413
4455
|
import chalk6 from "chalk";
|
|
4414
4456
|
|
|
4415
4457
|
// src/lib/events/event-renderer.ts
|
|
@@ -4428,25 +4470,6 @@ var EventRenderer = class {
|
|
|
4428
4470
|
console.log(chalk3.dim(` (use "vm0 logs ${info.runId}" to view logs)`));
|
|
4429
4471
|
console.log();
|
|
4430
4472
|
}
|
|
4431
|
-
/**
|
|
4432
|
-
* Format elapsed time between two timestamps
|
|
4433
|
-
* Returns [+Nms] for < 1000ms, [+N.Ns] for >= 1000ms
|
|
4434
|
-
*/
|
|
4435
|
-
static formatElapsed(previous, current) {
|
|
4436
|
-
const elapsedMs = current.getTime() - previous.getTime();
|
|
4437
|
-
if (elapsedMs < 1e3) {
|
|
4438
|
-
return `[+${elapsedMs}ms]`;
|
|
4439
|
-
}
|
|
4440
|
-
return `[+${(elapsedMs / 1e3).toFixed(1)}s]`;
|
|
4441
|
-
}
|
|
4442
|
-
/**
|
|
4443
|
-
* Format total elapsed time
|
|
4444
|
-
* Returns N.Ns format
|
|
4445
|
-
*/
|
|
4446
|
-
static formatTotalTime(start, end) {
|
|
4447
|
-
const elapsedMs = end.getTime() - start.getTime();
|
|
4448
|
-
return `${(elapsedMs / 1e3).toFixed(1)}s`;
|
|
4449
|
-
}
|
|
4450
4473
|
/**
|
|
4451
4474
|
* Format timestamp for display (without milliseconds, matching metrics format)
|
|
4452
4475
|
*/
|
|
@@ -4458,24 +4481,21 @@ var EventRenderer = class {
|
|
|
4458
4481
|
*/
|
|
4459
4482
|
static render(event, options) {
|
|
4460
4483
|
const timestampPrefix = options?.showTimestamp ? `[${this.formatTimestamp(event.timestamp)}] ` : "";
|
|
4461
|
-
const elapsedSuffix = options?.verbose && options?.previousTimestamp ? " " + chalk3.dim(
|
|
4462
|
-
this.formatElapsed(options.previousTimestamp, event.timestamp)
|
|
4463
|
-
) : "";
|
|
4464
4484
|
switch (event.type) {
|
|
4465
4485
|
case "init":
|
|
4466
|
-
this.renderInit(event, timestampPrefix
|
|
4486
|
+
this.renderInit(event, timestampPrefix);
|
|
4467
4487
|
break;
|
|
4468
4488
|
case "text":
|
|
4469
|
-
this.renderText(event, timestampPrefix
|
|
4489
|
+
this.renderText(event, timestampPrefix);
|
|
4470
4490
|
break;
|
|
4471
4491
|
case "tool_use":
|
|
4472
|
-
this.renderToolUse(event, timestampPrefix
|
|
4492
|
+
this.renderToolUse(event, timestampPrefix);
|
|
4473
4493
|
break;
|
|
4474
4494
|
case "tool_result":
|
|
4475
|
-
this.renderToolResult(event, timestampPrefix
|
|
4495
|
+
this.renderToolResult(event, timestampPrefix);
|
|
4476
4496
|
break;
|
|
4477
4497
|
case "result":
|
|
4478
|
-
this.renderResult(event, timestampPrefix
|
|
4498
|
+
this.renderResult(event, timestampPrefix);
|
|
4479
4499
|
break;
|
|
4480
4500
|
}
|
|
4481
4501
|
}
|
|
@@ -4483,8 +4503,7 @@ var EventRenderer = class {
|
|
|
4483
4503
|
* Render run completed state
|
|
4484
4504
|
* Note: This is run lifecycle status, not an event
|
|
4485
4505
|
*/
|
|
4486
|
-
static renderRunCompleted(result
|
|
4487
|
-
const now = /* @__PURE__ */ new Date();
|
|
4506
|
+
static renderRunCompleted(result) {
|
|
4488
4507
|
console.log("");
|
|
4489
4508
|
console.log(chalk3.green("\u2713 Run completed successfully"));
|
|
4490
4509
|
if (result) {
|
|
@@ -4504,10 +4523,6 @@ var EventRenderer = class {
|
|
|
4504
4523
|
}
|
|
4505
4524
|
}
|
|
4506
4525
|
}
|
|
4507
|
-
if (options?.verbose && options?.startTimestamp) {
|
|
4508
|
-
const totalTime = this.formatTotalTime(options.startTimestamp, now);
|
|
4509
|
-
console.log(` Total time: ${chalk3.dim(totalTime)}`);
|
|
4510
|
-
}
|
|
4511
4526
|
}
|
|
4512
4527
|
/**
|
|
4513
4528
|
* Render run failed state
|
|
@@ -4521,10 +4536,10 @@ var EventRenderer = class {
|
|
|
4521
4536
|
chalk3.dim(` (use "vm0 logs ${runId} --system" to view system logs)`)
|
|
4522
4537
|
);
|
|
4523
4538
|
}
|
|
4524
|
-
static renderInit(event, prefix
|
|
4539
|
+
static renderInit(event, prefix) {
|
|
4525
4540
|
const frameworkStr = String(event.data.framework || "claude-code");
|
|
4526
4541
|
const displayName = isSupportedFramework(frameworkStr) ? getFrameworkDisplayName(frameworkStr) : frameworkStr;
|
|
4527
|
-
console.log(prefix +
|
|
4542
|
+
console.log(prefix + `[init] Starting ${displayName} agent`);
|
|
4528
4543
|
console.log(` Session: ${chalk3.dim(String(event.data.sessionId || ""))}`);
|
|
4529
4544
|
if (event.data.model) {
|
|
4530
4545
|
console.log(` Model: ${chalk3.dim(String(event.data.model))}`);
|
|
@@ -4535,13 +4550,13 @@ var EventRenderer = class {
|
|
|
4535
4550
|
)}`
|
|
4536
4551
|
);
|
|
4537
4552
|
}
|
|
4538
|
-
static renderText(event, prefix
|
|
4553
|
+
static renderText(event, prefix) {
|
|
4539
4554
|
const text = String(event.data.text || "");
|
|
4540
|
-
console.log(prefix + "[text]
|
|
4555
|
+
console.log(prefix + "[text] " + text);
|
|
4541
4556
|
}
|
|
4542
|
-
static renderToolUse(event, prefix
|
|
4557
|
+
static renderToolUse(event, prefix) {
|
|
4543
4558
|
const tool = String(event.data.tool || "");
|
|
4544
|
-
console.log(prefix + "[tool_use]
|
|
4559
|
+
console.log(prefix + "[tool_use] " + tool);
|
|
4545
4560
|
const input = event.data.input;
|
|
4546
4561
|
if (input && typeof input === "object") {
|
|
4547
4562
|
for (const [key, value] of Object.entries(input)) {
|
|
@@ -4552,17 +4567,17 @@ var EventRenderer = class {
|
|
|
4552
4567
|
}
|
|
4553
4568
|
}
|
|
4554
4569
|
}
|
|
4555
|
-
static renderToolResult(event, prefix
|
|
4570
|
+
static renderToolResult(event, prefix) {
|
|
4556
4571
|
const isError = Boolean(event.data.isError);
|
|
4557
4572
|
const status = isError ? "Error" : "Completed";
|
|
4558
|
-
console.log(prefix + "[tool_result]
|
|
4573
|
+
console.log(prefix + "[tool_result] " + status);
|
|
4559
4574
|
const result = String(event.data.result || "");
|
|
4560
4575
|
console.log(` ${chalk3.dim(result)}`);
|
|
4561
4576
|
}
|
|
4562
|
-
static renderResult(event, prefix
|
|
4577
|
+
static renderResult(event, prefix) {
|
|
4563
4578
|
const success = Boolean(event.data.success);
|
|
4564
4579
|
const status = success ? "\u2713 completed successfully" : "\u2717 failed";
|
|
4565
|
-
console.log(prefix + "[result]
|
|
4580
|
+
console.log(prefix + "[result] " + status);
|
|
4566
4581
|
const durationMs = Number(event.data.durationMs || 0);
|
|
4567
4582
|
const durationSec = (durationMs / 1e3).toFixed(1);
|
|
4568
4583
|
console.log(` Duration: ${chalk3.dim(durationSec + "s")}`);
|
|
@@ -5834,7 +5849,7 @@ var ApiClient = class {
|
|
|
5834
5849
|
/**
|
|
5835
5850
|
* Generic GET request
|
|
5836
5851
|
*/
|
|
5837
|
-
async get(
|
|
5852
|
+
async get(path15) {
|
|
5838
5853
|
const baseUrl = await this.getBaseUrl();
|
|
5839
5854
|
const token = await getToken();
|
|
5840
5855
|
if (!token) {
|
|
@@ -5847,7 +5862,7 @@ var ApiClient = class {
|
|
|
5847
5862
|
if (bypassSecret) {
|
|
5848
5863
|
headers["x-vercel-protection-bypass"] = bypassSecret;
|
|
5849
5864
|
}
|
|
5850
|
-
return fetch(`${baseUrl}${
|
|
5865
|
+
return fetch(`${baseUrl}${path15}`, {
|
|
5851
5866
|
method: "GET",
|
|
5852
5867
|
headers
|
|
5853
5868
|
});
|
|
@@ -5855,7 +5870,7 @@ var ApiClient = class {
|
|
|
5855
5870
|
/**
|
|
5856
5871
|
* Generic POST request
|
|
5857
5872
|
*/
|
|
5858
|
-
async post(
|
|
5873
|
+
async post(path15, options) {
|
|
5859
5874
|
const baseUrl = await this.getBaseUrl();
|
|
5860
5875
|
const token = await getToken();
|
|
5861
5876
|
if (!token) {
|
|
@@ -5871,7 +5886,7 @@ var ApiClient = class {
|
|
|
5871
5886
|
if (bypassSecret) {
|
|
5872
5887
|
headers["x-vercel-protection-bypass"] = bypassSecret;
|
|
5873
5888
|
}
|
|
5874
|
-
return fetch(`${baseUrl}${
|
|
5889
|
+
return fetch(`${baseUrl}${path15}`, {
|
|
5875
5890
|
method: "POST",
|
|
5876
5891
|
headers,
|
|
5877
5892
|
body: options?.body
|
|
@@ -5880,7 +5895,7 @@ var ApiClient = class {
|
|
|
5880
5895
|
/**
|
|
5881
5896
|
* Generic DELETE request
|
|
5882
5897
|
*/
|
|
5883
|
-
async delete(
|
|
5898
|
+
async delete(path15) {
|
|
5884
5899
|
const baseUrl = await this.getBaseUrl();
|
|
5885
5900
|
const token = await getToken();
|
|
5886
5901
|
if (!token) {
|
|
@@ -5893,7 +5908,7 @@ var ApiClient = class {
|
|
|
5893
5908
|
if (bypassSecret) {
|
|
5894
5909
|
headers["x-vercel-protection-bypass"] = bypassSecret;
|
|
5895
5910
|
}
|
|
5896
|
-
return fetch(`${baseUrl}${
|
|
5911
|
+
return fetch(`${baseUrl}${path15}`, {
|
|
5897
5912
|
method: "DELETE",
|
|
5898
5913
|
headers
|
|
5899
5914
|
});
|
|
@@ -5926,15 +5941,7 @@ function getRunChannelName(runId) {
|
|
|
5926
5941
|
|
|
5927
5942
|
// src/lib/realtime/stream-events.ts
|
|
5928
5943
|
async function streamEvents(runId, options) {
|
|
5929
|
-
const {
|
|
5930
|
-
verbose,
|
|
5931
|
-
startTimestamp,
|
|
5932
|
-
onEvent,
|
|
5933
|
-
onRunCompleted,
|
|
5934
|
-
onRunFailed,
|
|
5935
|
-
onTimeout
|
|
5936
|
-
} = options;
|
|
5937
|
-
let previousTimestamp = startTimestamp;
|
|
5944
|
+
const { onEvent, onRunCompleted, onRunFailed, onTimeout } = options;
|
|
5938
5945
|
const ablyClient = createRealtimeClient(async () => {
|
|
5939
5946
|
return apiClient.getRealtimeToken(runId);
|
|
5940
5947
|
});
|
|
@@ -5971,20 +5978,12 @@ async function streamEvents(runId, options) {
|
|
|
5971
5978
|
}
|
|
5972
5979
|
nextExpectedSequence = Math.max(nextExpectedSequence, seq + 1);
|
|
5973
5980
|
}
|
|
5974
|
-
|
|
5975
|
-
verbose,
|
|
5976
|
-
previousTimestamp,
|
|
5977
|
-
startTimestamp
|
|
5978
|
-
});
|
|
5981
|
+
onEvent(event);
|
|
5979
5982
|
}
|
|
5980
5983
|
} else if (message.name === "status") {
|
|
5981
5984
|
const data = message.data;
|
|
5982
5985
|
if (data.status === "completed") {
|
|
5983
|
-
onRunCompleted(data.result
|
|
5984
|
-
verbose,
|
|
5985
|
-
previousTimestamp,
|
|
5986
|
-
startTimestamp
|
|
5987
|
-
});
|
|
5986
|
+
onRunCompleted(data.result);
|
|
5988
5987
|
result = {
|
|
5989
5988
|
succeeded: true,
|
|
5990
5989
|
runId,
|
|
@@ -6093,28 +6092,18 @@ function parseIdentifier(identifier) {
|
|
|
6093
6092
|
}
|
|
6094
6093
|
return { scope, name: rest };
|
|
6095
6094
|
}
|
|
6096
|
-
function renderEvent(event
|
|
6095
|
+
function renderEvent(event) {
|
|
6097
6096
|
const eventData = event;
|
|
6098
6097
|
const parsed = parseEvent(eventData);
|
|
6099
6098
|
if (parsed) {
|
|
6100
|
-
EventRenderer.render(parsed
|
|
6101
|
-
verbose: options.verbose,
|
|
6102
|
-
previousTimestamp: options.previousTimestamp,
|
|
6103
|
-
startTimestamp: options.startTimestamp
|
|
6104
|
-
});
|
|
6105
|
-
return parsed.timestamp;
|
|
6099
|
+
EventRenderer.render(parsed);
|
|
6106
6100
|
}
|
|
6107
|
-
return options.previousTimestamp;
|
|
6108
6101
|
}
|
|
6109
|
-
async function streamRealtimeEvents(runId
|
|
6110
|
-
const startTimestamp = options.startTimestamp;
|
|
6111
|
-
const verbose = options.verbose;
|
|
6102
|
+
async function streamRealtimeEvents(runId) {
|
|
6112
6103
|
return streamEvents(runId, {
|
|
6113
|
-
verbose,
|
|
6114
|
-
startTimestamp,
|
|
6115
6104
|
onEvent: renderEvent,
|
|
6116
|
-
onRunCompleted: (result
|
|
6117
|
-
EventRenderer.renderRunCompleted(result
|
|
6105
|
+
onRunCompleted: (result) => {
|
|
6106
|
+
EventRenderer.renderRunCompleted(result);
|
|
6118
6107
|
},
|
|
6119
6108
|
onRunFailed: (error, rid) => {
|
|
6120
6109
|
EventRenderer.renderRunFailed(error, rid);
|
|
@@ -6127,14 +6116,11 @@ async function streamRealtimeEvents(runId, options) {
|
|
|
6127
6116
|
}
|
|
6128
6117
|
});
|
|
6129
6118
|
}
|
|
6130
|
-
async function pollEvents(runId
|
|
6119
|
+
async function pollEvents(runId) {
|
|
6131
6120
|
let nextSequence = -1;
|
|
6132
6121
|
let complete = false;
|
|
6133
6122
|
let result = { succeeded: true, runId };
|
|
6134
6123
|
const pollIntervalMs = 1e3;
|
|
6135
|
-
const startTimestamp = options.startTimestamp;
|
|
6136
|
-
let previousTimestamp = startTimestamp;
|
|
6137
|
-
const verbose = options.verbose;
|
|
6138
6124
|
while (!complete) {
|
|
6139
6125
|
const response = await getEvents(runId, {
|
|
6140
6126
|
since: nextSequence
|
|
@@ -6146,12 +6132,7 @@ async function pollEvents(runId, options) {
|
|
|
6146
6132
|
} else {
|
|
6147
6133
|
const parsed = parseEvent(eventData);
|
|
6148
6134
|
if (parsed) {
|
|
6149
|
-
EventRenderer.render(parsed
|
|
6150
|
-
verbose,
|
|
6151
|
-
previousTimestamp,
|
|
6152
|
-
startTimestamp
|
|
6153
|
-
});
|
|
6154
|
-
previousTimestamp = parsed.timestamp;
|
|
6135
|
+
EventRenderer.render(parsed);
|
|
6155
6136
|
}
|
|
6156
6137
|
}
|
|
6157
6138
|
}
|
|
@@ -6159,11 +6140,7 @@ async function pollEvents(runId, options) {
|
|
|
6159
6140
|
const runStatus = response.run.status;
|
|
6160
6141
|
if (runStatus === "completed") {
|
|
6161
6142
|
complete = true;
|
|
6162
|
-
EventRenderer.renderRunCompleted(response.run.result
|
|
6163
|
-
verbose,
|
|
6164
|
-
previousTimestamp,
|
|
6165
|
-
startTimestamp
|
|
6166
|
-
});
|
|
6143
|
+
EventRenderer.renderRunCompleted(response.run.result);
|
|
6167
6144
|
result = {
|
|
6168
6145
|
succeeded: true,
|
|
6169
6146
|
runId,
|
|
@@ -6188,18 +6165,6 @@ async function pollEvents(runId, options) {
|
|
|
6188
6165
|
}
|
|
6189
6166
|
return result;
|
|
6190
6167
|
}
|
|
6191
|
-
function logVerbosePreFlight(action, details) {
|
|
6192
|
-
console.log(`
|
|
6193
|
-
${action}...`);
|
|
6194
|
-
for (const { label, value } of details) {
|
|
6195
|
-
if (value !== void 0) {
|
|
6196
|
-
console.log(chalk5.dim(` ${label}: ${value}`));
|
|
6197
|
-
}
|
|
6198
|
-
}
|
|
6199
|
-
console.log();
|
|
6200
|
-
console.log("Executing in sandbox...");
|
|
6201
|
-
console.log();
|
|
6202
|
-
}
|
|
6203
6168
|
function showNextSteps(result) {
|
|
6204
6169
|
const { runId, sessionId, checkpointId } = result;
|
|
6205
6170
|
console.log();
|
|
@@ -6222,7 +6187,7 @@ function showNextSteps(result) {
|
|
|
6222
6187
|
}
|
|
6223
6188
|
|
|
6224
6189
|
// src/commands/run/run.ts
|
|
6225
|
-
var mainRunCommand = new
|
|
6190
|
+
var mainRunCommand = new Command3().name("run").description("Run an agent").argument(
|
|
6226
6191
|
"<agent-name>",
|
|
6227
6192
|
"Agent reference: [scope/]name[:version] (e.g., 'my-agent', 'lancy/my-agent:abc123', 'my-agent:latest')"
|
|
6228
6193
|
).argument("<prompt>", "Prompt for the agent").option(
|
|
@@ -6249,33 +6214,23 @@ var mainRunCommand = new Command2().name("run").description("Run an agent").argu
|
|
|
6249
6214
|
).option(
|
|
6250
6215
|
"--conversation <id>",
|
|
6251
6216
|
"Resume from conversation ID (for fine-grained control)"
|
|
6252
|
-
).option(
|
|
6217
|
+
).option(
|
|
6253
6218
|
"--experimental-realtime",
|
|
6254
6219
|
"Use realtime event streaming instead of polling (experimental)"
|
|
6255
6220
|
).option(
|
|
6256
6221
|
"--model-provider <type>",
|
|
6257
6222
|
"Override model provider (e.g., anthropic-api-key)"
|
|
6258
6223
|
).addOption(new Option("--debug-no-mock-claude").hideHelp()).action(
|
|
6259
|
-
// eslint-disable-next-line complexity -- TODO: refactor complex function
|
|
6260
6224
|
async (identifier, prompt, options) => {
|
|
6261
|
-
const startTimestamp = /* @__PURE__ */ new Date();
|
|
6262
|
-
const verbose = options.verbose;
|
|
6263
6225
|
try {
|
|
6264
6226
|
const { scope, name, version } = parseIdentifier(identifier);
|
|
6265
6227
|
let composeId;
|
|
6266
6228
|
let composeContent;
|
|
6267
6229
|
if (isUUID(name)) {
|
|
6268
|
-
if (verbose) {
|
|
6269
|
-
console.log(chalk6.dim(` Using compose ID: ${identifier}`));
|
|
6270
|
-
}
|
|
6271
6230
|
const compose = await getComposeById(name);
|
|
6272
6231
|
composeId = compose.id;
|
|
6273
6232
|
composeContent = compose.content;
|
|
6274
6233
|
} else {
|
|
6275
|
-
if (verbose) {
|
|
6276
|
-
const displayRef = scope ? `${scope}/${name}` : name;
|
|
6277
|
-
console.log(chalk6.dim(` Resolving agent: ${displayRef}`));
|
|
6278
|
-
}
|
|
6279
6234
|
const compose = await getComposeByName(name, scope);
|
|
6280
6235
|
if (!compose) {
|
|
6281
6236
|
console.error(chalk6.red(`\u2717 Agent not found: ${identifier}`));
|
|
@@ -6288,25 +6243,12 @@ var mainRunCommand = new Command2().name("run").description("Run an agent").argu
|
|
|
6288
6243
|
}
|
|
6289
6244
|
composeId = compose.id;
|
|
6290
6245
|
composeContent = compose.content;
|
|
6291
|
-
if (verbose) {
|
|
6292
|
-
console.log(chalk6.dim(` Resolved to compose ID: ${composeId}`));
|
|
6293
|
-
}
|
|
6294
6246
|
}
|
|
6295
6247
|
let agentComposeVersionId;
|
|
6296
6248
|
if (version && version !== "latest") {
|
|
6297
|
-
if (verbose) {
|
|
6298
|
-
console.log(chalk6.dim(` Resolving version: ${version}`));
|
|
6299
|
-
}
|
|
6300
6249
|
try {
|
|
6301
6250
|
const versionInfo = await getComposeVersion(composeId, version);
|
|
6302
6251
|
agentComposeVersionId = versionInfo.versionId;
|
|
6303
|
-
if (verbose) {
|
|
6304
|
-
console.log(
|
|
6305
|
-
chalk6.dim(
|
|
6306
|
-
` Resolved to version ID: ${agentComposeVersionId.slice(0, 8)}...`
|
|
6307
|
-
)
|
|
6308
|
-
);
|
|
6309
|
-
}
|
|
6310
6252
|
} catch {
|
|
6311
6253
|
throw new Error(`Version not found: ${version}`);
|
|
6312
6254
|
}
|
|
@@ -6319,45 +6261,6 @@ var mainRunCommand = new Command2().name("run").description("Run an agent").argu
|
|
|
6319
6261
|
secretNames,
|
|
6320
6262
|
options.envFile
|
|
6321
6263
|
);
|
|
6322
|
-
if (verbose && varNames.length > 0) {
|
|
6323
|
-
console.log(chalk6.dim(` Required vars: ${varNames.join(", ")}`));
|
|
6324
|
-
if (vars) {
|
|
6325
|
-
console.log(
|
|
6326
|
-
chalk6.dim(` Loaded vars: ${Object.keys(vars).join(", ")}`)
|
|
6327
|
-
);
|
|
6328
|
-
}
|
|
6329
|
-
}
|
|
6330
|
-
if (verbose && secretNames.length > 0) {
|
|
6331
|
-
console.log(
|
|
6332
|
-
chalk6.dim(` Required secrets: ${secretNames.join(", ")}`)
|
|
6333
|
-
);
|
|
6334
|
-
if (secrets) {
|
|
6335
|
-
console.log(
|
|
6336
|
-
chalk6.dim(` Loaded secrets: ${Object.keys(secrets).join(", ")}`)
|
|
6337
|
-
);
|
|
6338
|
-
}
|
|
6339
|
-
}
|
|
6340
|
-
if (verbose) {
|
|
6341
|
-
logVerbosePreFlight("Creating agent run", [
|
|
6342
|
-
{ label: "Prompt", value: prompt },
|
|
6343
|
-
{ label: "Version", value: version || "latest (HEAD)" },
|
|
6344
|
-
{
|
|
6345
|
-
label: "Variables",
|
|
6346
|
-
value: vars && Object.keys(vars).length > 0 ? JSON.stringify(vars) : void 0
|
|
6347
|
-
},
|
|
6348
|
-
{
|
|
6349
|
-
label: "Secrets",
|
|
6350
|
-
value: secrets && Object.keys(secrets).length > 0 ? `${Object.keys(secrets).length} loaded` : void 0
|
|
6351
|
-
},
|
|
6352
|
-
{ label: "Artifact", value: options.artifactName },
|
|
6353
|
-
{ label: "Artifact version", value: options.artifactVersion },
|
|
6354
|
-
{
|
|
6355
|
-
label: "Volume versions",
|
|
6356
|
-
value: Object.keys(options.volumeVersion).length > 0 ? JSON.stringify(options.volumeVersion) : void 0
|
|
6357
|
-
},
|
|
6358
|
-
{ label: "Conversation", value: options.conversation }
|
|
6359
|
-
]);
|
|
6360
|
-
}
|
|
6361
6264
|
const response = await createRun({
|
|
6362
6265
|
// Use agentComposeVersionId if resolved, otherwise use agentComposeId (resolves to HEAD)
|
|
6363
6266
|
...agentComposeVersionId ? { agentComposeVersionId } : { agentComposeId: composeId },
|
|
@@ -6382,13 +6285,7 @@ var mainRunCommand = new Command2().name("run").description("Run an agent").argu
|
|
|
6382
6285
|
runId: response.runId,
|
|
6383
6286
|
sandboxId: response.sandboxId
|
|
6384
6287
|
});
|
|
6385
|
-
const result = options.experimentalRealtime ? await streamRealtimeEvents(response.runId
|
|
6386
|
-
verbose,
|
|
6387
|
-
startTimestamp
|
|
6388
|
-
}) : await pollEvents(response.runId, {
|
|
6389
|
-
verbose,
|
|
6390
|
-
startTimestamp
|
|
6391
|
-
});
|
|
6288
|
+
const result = options.experimentalRealtime ? await streamRealtimeEvents(response.runId) : await pollEvents(response.runId);
|
|
6392
6289
|
if (!result.succeeded) {
|
|
6393
6290
|
process.exit(1);
|
|
6394
6291
|
}
|
|
@@ -6430,9 +6327,9 @@ var mainRunCommand = new Command2().name("run").description("Run an agent").argu
|
|
|
6430
6327
|
);
|
|
6431
6328
|
|
|
6432
6329
|
// src/commands/run/resume.ts
|
|
6433
|
-
import { Command as
|
|
6330
|
+
import { Command as Command4, Option as Option2 } from "commander";
|
|
6434
6331
|
import chalk7 from "chalk";
|
|
6435
|
-
var resumeCommand = new
|
|
6332
|
+
var resumeCommand = new Command4().name("resume").description("Resume an agent run from a checkpoint (uses all snapshot data)").argument("<checkpointId>", "Checkpoint ID to resume from").argument("<prompt>", "Prompt for the resumed agent").option(
|
|
6436
6333
|
"--env-file <path>",
|
|
6437
6334
|
"Load environment variables from file (priority: CLI flags > file > env vars)"
|
|
6438
6335
|
).option(
|
|
@@ -6450,18 +6347,15 @@ var resumeCommand = new Command3().name("resume").description("Resume an agent r
|
|
|
6450
6347
|
"Volume version override (repeatable)",
|
|
6451
6348
|
collectVolumeVersions,
|
|
6452
6349
|
{}
|
|
6453
|
-
).option(
|
|
6350
|
+
).option(
|
|
6454
6351
|
"--experimental-realtime",
|
|
6455
6352
|
"Use realtime event streaming instead of polling (experimental)"
|
|
6456
6353
|
).option(
|
|
6457
6354
|
"--model-provider <type>",
|
|
6458
6355
|
"Override model provider (e.g., anthropic-api-key)"
|
|
6459
6356
|
).addOption(new Option2("--debug-no-mock-claude").hideHelp()).action(
|
|
6460
|
-
// eslint-disable-next-line complexity -- TODO: refactor complex function
|
|
6461
6357
|
async (checkpointId, prompt, options, command) => {
|
|
6462
|
-
const startTimestamp = /* @__PURE__ */ new Date();
|
|
6463
6358
|
const allOpts = command.optsWithGlobals();
|
|
6464
|
-
const verbose = options.verbose || allOpts.verbose;
|
|
6465
6359
|
const vars = { ...allOpts.vars, ...options.vars };
|
|
6466
6360
|
const secrets = { ...allOpts.secrets, ...options.secrets };
|
|
6467
6361
|
try {
|
|
@@ -6476,24 +6370,6 @@ var resumeCommand = new Command3().name("resume").description("Resume an agent r
|
|
|
6476
6370
|
const requiredSecretNames = checkpointInfo.agentComposeSnapshot.secretNames || [];
|
|
6477
6371
|
const envFile = options.envFile || allOpts.envFile;
|
|
6478
6372
|
const loadedSecrets = loadValues(secrets, requiredSecretNames, envFile);
|
|
6479
|
-
if (verbose) {
|
|
6480
|
-
logVerbosePreFlight("Resuming agent run from checkpoint", [
|
|
6481
|
-
{ label: "Checkpoint ID", value: checkpointId },
|
|
6482
|
-
{ label: "Prompt", value: prompt },
|
|
6483
|
-
{
|
|
6484
|
-
label: "Variables",
|
|
6485
|
-
value: Object.keys(vars).length > 0 ? JSON.stringify(vars) : void 0
|
|
6486
|
-
},
|
|
6487
|
-
{
|
|
6488
|
-
label: "Secrets",
|
|
6489
|
-
value: loadedSecrets && Object.keys(loadedSecrets).length > 0 ? `${Object.keys(loadedSecrets).length} loaded` : void 0
|
|
6490
|
-
},
|
|
6491
|
-
{
|
|
6492
|
-
label: "Volume overrides",
|
|
6493
|
-
value: Object.keys(allOpts.volumeVersion).length > 0 ? JSON.stringify(allOpts.volumeVersion) : void 0
|
|
6494
|
-
}
|
|
6495
|
-
]);
|
|
6496
|
-
}
|
|
6497
6373
|
const response = await createRun({
|
|
6498
6374
|
checkpointId,
|
|
6499
6375
|
prompt,
|
|
@@ -6515,13 +6391,7 @@ var resumeCommand = new Command3().name("resume").description("Resume an agent r
|
|
|
6515
6391
|
sandboxId: response.sandboxId
|
|
6516
6392
|
});
|
|
6517
6393
|
const experimentalRealtime = options.experimentalRealtime || allOpts.experimentalRealtime;
|
|
6518
|
-
const result = experimentalRealtime ? await streamRealtimeEvents(response.runId
|
|
6519
|
-
verbose,
|
|
6520
|
-
startTimestamp
|
|
6521
|
-
}) : await pollEvents(response.runId, {
|
|
6522
|
-
verbose,
|
|
6523
|
-
startTimestamp
|
|
6524
|
-
});
|
|
6394
|
+
const result = experimentalRealtime ? await streamRealtimeEvents(response.runId) : await pollEvents(response.runId);
|
|
6525
6395
|
if (!result.succeeded) {
|
|
6526
6396
|
process.exit(1);
|
|
6527
6397
|
}
|
|
@@ -6555,9 +6425,9 @@ var resumeCommand = new Command3().name("resume").description("Resume an agent r
|
|
|
6555
6425
|
);
|
|
6556
6426
|
|
|
6557
6427
|
// src/commands/run/continue.ts
|
|
6558
|
-
import { Command as
|
|
6428
|
+
import { Command as Command5, Option as Option3 } from "commander";
|
|
6559
6429
|
import chalk8 from "chalk";
|
|
6560
|
-
var continueCommand = new
|
|
6430
|
+
var continueCommand = new Command5().name("continue").description(
|
|
6561
6431
|
"Continue an agent run from a session (uses latest artifact version)"
|
|
6562
6432
|
).argument("<agentSessionId>", "Agent session ID to continue from").argument("<prompt>", "Prompt for the continued agent").option(
|
|
6563
6433
|
"--env-file <path>",
|
|
@@ -6577,18 +6447,15 @@ var continueCommand = new Command4().name("continue").description(
|
|
|
6577
6447
|
"Volume version override (repeatable)",
|
|
6578
6448
|
collectVolumeVersions,
|
|
6579
6449
|
{}
|
|
6580
|
-
).option(
|
|
6450
|
+
).option(
|
|
6581
6451
|
"--experimental-realtime",
|
|
6582
6452
|
"Use realtime event streaming instead of polling (experimental)"
|
|
6583
6453
|
).option(
|
|
6584
6454
|
"--model-provider <type>",
|
|
6585
6455
|
"Override model provider (e.g., anthropic-api-key)"
|
|
6586
6456
|
).addOption(new Option3("--debug-no-mock-claude").hideHelp()).action(
|
|
6587
|
-
// eslint-disable-next-line complexity -- TODO: refactor complex function
|
|
6588
6457
|
async (agentSessionId, prompt, options, command) => {
|
|
6589
|
-
const startTimestamp = /* @__PURE__ */ new Date();
|
|
6590
6458
|
const allOpts = command.optsWithGlobals();
|
|
6591
|
-
const verbose = options.verbose || allOpts.verbose;
|
|
6592
6459
|
const vars = { ...allOpts.vars, ...options.vars };
|
|
6593
6460
|
const secrets = { ...allOpts.secrets, ...options.secrets };
|
|
6594
6461
|
try {
|
|
@@ -6603,25 +6470,6 @@ var continueCommand = new Command4().name("continue").description(
|
|
|
6603
6470
|
const requiredSecretNames = sessionInfo.secretNames || [];
|
|
6604
6471
|
const envFile = options.envFile || allOpts.envFile;
|
|
6605
6472
|
const loadedSecrets = loadValues(secrets, requiredSecretNames, envFile);
|
|
6606
|
-
if (verbose) {
|
|
6607
|
-
logVerbosePreFlight("Continuing agent run from session", [
|
|
6608
|
-
{ label: "Session ID", value: agentSessionId },
|
|
6609
|
-
{ label: "Prompt", value: prompt },
|
|
6610
|
-
{ label: "Note", value: "Using latest artifact version" },
|
|
6611
|
-
{
|
|
6612
|
-
label: "Variables",
|
|
6613
|
-
value: Object.keys(vars).length > 0 ? JSON.stringify(vars) : void 0
|
|
6614
|
-
},
|
|
6615
|
-
{
|
|
6616
|
-
label: "Secrets",
|
|
6617
|
-
value: loadedSecrets && Object.keys(loadedSecrets).length > 0 ? `${Object.keys(loadedSecrets).length} loaded` : void 0
|
|
6618
|
-
},
|
|
6619
|
-
{
|
|
6620
|
-
label: "Volume overrides",
|
|
6621
|
-
value: Object.keys(allOpts.volumeVersion).length > 0 ? JSON.stringify(allOpts.volumeVersion) : void 0
|
|
6622
|
-
}
|
|
6623
|
-
]);
|
|
6624
|
-
}
|
|
6625
6473
|
const response = await createRun({
|
|
6626
6474
|
sessionId: agentSessionId,
|
|
6627
6475
|
prompt,
|
|
@@ -6643,13 +6491,7 @@ var continueCommand = new Command4().name("continue").description(
|
|
|
6643
6491
|
sandboxId: response.sandboxId
|
|
6644
6492
|
});
|
|
6645
6493
|
const experimentalRealtime = options.experimentalRealtime || allOpts.experimentalRealtime;
|
|
6646
|
-
const result = experimentalRealtime ? await streamRealtimeEvents(response.runId
|
|
6647
|
-
verbose,
|
|
6648
|
-
startTimestamp
|
|
6649
|
-
}) : await pollEvents(response.runId, {
|
|
6650
|
-
verbose,
|
|
6651
|
-
startTimestamp
|
|
6652
|
-
});
|
|
6494
|
+
const result = experimentalRealtime ? await streamRealtimeEvents(response.runId) : await pollEvents(response.runId);
|
|
6653
6495
|
if (!result.succeeded) {
|
|
6654
6496
|
process.exit(1);
|
|
6655
6497
|
}
|
|
@@ -6690,10 +6532,10 @@ mainRunCommand.addCommand(continueCommand);
|
|
|
6690
6532
|
var runCommand = mainRunCommand;
|
|
6691
6533
|
|
|
6692
6534
|
// src/commands/volume/index.ts
|
|
6693
|
-
import { Command as
|
|
6535
|
+
import { Command as Command12 } from "commander";
|
|
6694
6536
|
|
|
6695
6537
|
// src/commands/volume/init.ts
|
|
6696
|
-
import { Command as
|
|
6538
|
+
import { Command as Command6 } from "commander";
|
|
6697
6539
|
import chalk9 from "chalk";
|
|
6698
6540
|
import path6 from "path";
|
|
6699
6541
|
|
|
@@ -6702,8 +6544,8 @@ import { readFile as readFile5, writeFile as writeFile4, mkdir as mkdir4 } from
|
|
|
6702
6544
|
import { existsSync as existsSync5 } from "fs";
|
|
6703
6545
|
import { parse as parseYaml3, stringify as stringifyYaml } from "yaml";
|
|
6704
6546
|
import path5 from "path";
|
|
6705
|
-
var
|
|
6706
|
-
var
|
|
6547
|
+
var CONFIG_DIR = ".vm0";
|
|
6548
|
+
var CONFIG_FILE = "storage.yaml";
|
|
6707
6549
|
function isValidStorageName(name) {
|
|
6708
6550
|
if (name.length < 3 || name.length > 64) {
|
|
6709
6551
|
return false;
|
|
@@ -6712,8 +6554,8 @@ function isValidStorageName(name) {
|
|
|
6712
6554
|
return pattern.test(name) && !name.includes("--");
|
|
6713
6555
|
}
|
|
6714
6556
|
async function readStorageConfig(basePath = process.cwd()) {
|
|
6715
|
-
const configPath = path5.join(basePath,
|
|
6716
|
-
const legacyConfigPath = path5.join(basePath,
|
|
6557
|
+
const configPath = path5.join(basePath, CONFIG_DIR, CONFIG_FILE);
|
|
6558
|
+
const legacyConfigPath = path5.join(basePath, CONFIG_DIR, "volume.yaml");
|
|
6717
6559
|
let actualPath = null;
|
|
6718
6560
|
if (existsSync5(configPath)) {
|
|
6719
6561
|
actualPath = configPath;
|
|
@@ -6731,8 +6573,8 @@ async function readStorageConfig(basePath = process.cwd()) {
|
|
|
6731
6573
|
return config;
|
|
6732
6574
|
}
|
|
6733
6575
|
async function writeStorageConfig(storageName, basePath = process.cwd(), type = "volume") {
|
|
6734
|
-
const configDir = path5.join(basePath,
|
|
6735
|
-
const configPath = path5.join(configDir,
|
|
6576
|
+
const configDir = path5.join(basePath, CONFIG_DIR);
|
|
6577
|
+
const configPath = path5.join(configDir, CONFIG_FILE);
|
|
6736
6578
|
if (!existsSync5(configDir)) {
|
|
6737
6579
|
await mkdir4(configDir, { recursive: true });
|
|
6738
6580
|
}
|
|
@@ -6745,7 +6587,7 @@ async function writeStorageConfig(storageName, basePath = process.cwd(), type =
|
|
|
6745
6587
|
}
|
|
6746
6588
|
|
|
6747
6589
|
// src/commands/volume/init.ts
|
|
6748
|
-
var initCommand = new
|
|
6590
|
+
var initCommand = new Command6().name("init").description("Initialize a volume in the current directory").option("-n, --name <name>", "Volume name (required in non-interactive mode)").action(async (options) => {
|
|
6749
6591
|
try {
|
|
6750
6592
|
const cwd = process.cwd();
|
|
6751
6593
|
const dirName = path6.basename(cwd);
|
|
@@ -6817,9 +6659,9 @@ var initCommand = new Command5().name("init").description("Initialize a volume i
|
|
|
6817
6659
|
});
|
|
6818
6660
|
|
|
6819
6661
|
// src/commands/volume/push.ts
|
|
6820
|
-
import { Command as
|
|
6662
|
+
import { Command as Command7 } from "commander";
|
|
6821
6663
|
import chalk10 from "chalk";
|
|
6822
|
-
var pushCommand = new
|
|
6664
|
+
var pushCommand = new Command7().name("push").description("Push local files to cloud volume").option(
|
|
6823
6665
|
"-f, --force",
|
|
6824
6666
|
"Force upload even if content unchanged (recreate archive)"
|
|
6825
6667
|
).action(async (options) => {
|
|
@@ -6863,7 +6705,7 @@ var pushCommand = new Command6().name("push").description("Push local files to c
|
|
|
6863
6705
|
});
|
|
6864
6706
|
|
|
6865
6707
|
// src/commands/volume/pull.ts
|
|
6866
|
-
import { Command as
|
|
6708
|
+
import { Command as Command8 } from "commander";
|
|
6867
6709
|
import chalk12 from "chalk";
|
|
6868
6710
|
import path7 from "path";
|
|
6869
6711
|
import * as fs6 from "fs";
|
|
@@ -6883,7 +6725,7 @@ async function handleEmptyStorageResponse(cwd) {
|
|
|
6883
6725
|
}
|
|
6884
6726
|
|
|
6885
6727
|
// src/commands/volume/pull.ts
|
|
6886
|
-
var pullCommand = new
|
|
6728
|
+
var pullCommand = new Command8().name("pull").description("Pull cloud files to local directory").argument("[versionId]", "Version ID to pull (default: latest)").action(async (versionId) => {
|
|
6887
6729
|
try {
|
|
6888
6730
|
const cwd = process.cwd();
|
|
6889
6731
|
const config = await readStorageConfig(cwd);
|
|
@@ -6956,9 +6798,9 @@ var pullCommand = new Command7().name("pull").description("Pull cloud files to l
|
|
|
6956
6798
|
});
|
|
6957
6799
|
|
|
6958
6800
|
// src/commands/volume/status.ts
|
|
6959
|
-
import { Command as
|
|
6801
|
+
import { Command as Command9 } from "commander";
|
|
6960
6802
|
import chalk13 from "chalk";
|
|
6961
|
-
var statusCommand = new
|
|
6803
|
+
var statusCommand = new Command9().name("status").description("Show status of cloud volume").action(async () => {
|
|
6962
6804
|
try {
|
|
6963
6805
|
const cwd = process.cwd();
|
|
6964
6806
|
const config = await readStorageConfig(cwd);
|
|
@@ -7010,9 +6852,9 @@ var statusCommand = new Command8().name("status").description("Show status of cl
|
|
|
7010
6852
|
});
|
|
7011
6853
|
|
|
7012
6854
|
// src/commands/volume/list.ts
|
|
7013
|
-
import { Command as
|
|
6855
|
+
import { Command as Command10 } from "commander";
|
|
7014
6856
|
import chalk14 from "chalk";
|
|
7015
|
-
var listCommand = new
|
|
6857
|
+
var listCommand = new Command10().name("list").alias("ls").description("List all remote volumes").action(async () => {
|
|
7016
6858
|
try {
|
|
7017
6859
|
const items = await listStorages({ type: "volume" });
|
|
7018
6860
|
if (items.length === 0) {
|
|
@@ -7061,7 +6903,7 @@ var listCommand = new Command9().name("list").alias("ls").description("List all
|
|
|
7061
6903
|
});
|
|
7062
6904
|
|
|
7063
6905
|
// src/commands/volume/clone.ts
|
|
7064
|
-
import { Command as
|
|
6906
|
+
import { Command as Command11 } from "commander";
|
|
7065
6907
|
import chalk16 from "chalk";
|
|
7066
6908
|
|
|
7067
6909
|
// src/lib/storage/clone-utils.ts
|
|
@@ -7131,7 +6973,7 @@ async function cloneStorage(name, type, destination, options = {}) {
|
|
|
7131
6973
|
}
|
|
7132
6974
|
|
|
7133
6975
|
// src/commands/volume/clone.ts
|
|
7134
|
-
var cloneCommand = new
|
|
6976
|
+
var cloneCommand = new Command11().name("clone").description("Clone a remote volume to local directory (latest version)").argument("<name>", "Volume name to clone").argument("[destination]", "Destination directory (default: volume name)").action(async (name, destination) => {
|
|
7135
6977
|
try {
|
|
7136
6978
|
const targetDir = destination || name;
|
|
7137
6979
|
console.log(`Cloning volume: ${name}`);
|
|
@@ -7154,16 +6996,16 @@ var cloneCommand = new Command10().name("clone").description("Clone a remote vol
|
|
|
7154
6996
|
});
|
|
7155
6997
|
|
|
7156
6998
|
// src/commands/volume/index.ts
|
|
7157
|
-
var volumeCommand = new
|
|
6999
|
+
var volumeCommand = new Command12().name("volume").description("Manage volumes (defined in compose, not versioned after run)").addCommand(initCommand).addCommand(pushCommand).addCommand(pullCommand).addCommand(statusCommand).addCommand(listCommand).addCommand(cloneCommand);
|
|
7158
7000
|
|
|
7159
7001
|
// src/commands/artifact/index.ts
|
|
7160
|
-
import { Command as
|
|
7002
|
+
import { Command as Command19 } from "commander";
|
|
7161
7003
|
|
|
7162
7004
|
// src/commands/artifact/init.ts
|
|
7163
|
-
import { Command as
|
|
7005
|
+
import { Command as Command13 } from "commander";
|
|
7164
7006
|
import chalk17 from "chalk";
|
|
7165
7007
|
import path9 from "path";
|
|
7166
|
-
var initCommand2 = new
|
|
7008
|
+
var initCommand2 = new Command13().name("init").description("Initialize an artifact in the current directory").option(
|
|
7167
7009
|
"-n, --name <name>",
|
|
7168
7010
|
"Artifact name (required in non-interactive mode)"
|
|
7169
7011
|
).action(async (options) => {
|
|
@@ -7253,9 +7095,9 @@ var initCommand2 = new Command12().name("init").description("Initialize an artif
|
|
|
7253
7095
|
});
|
|
7254
7096
|
|
|
7255
7097
|
// src/commands/artifact/push.ts
|
|
7256
|
-
import { Command as
|
|
7098
|
+
import { Command as Command14 } from "commander";
|
|
7257
7099
|
import chalk18 from "chalk";
|
|
7258
|
-
var pushCommand2 = new
|
|
7100
|
+
var pushCommand2 = new Command14().name("push").description("Push local files to cloud artifact").option(
|
|
7259
7101
|
"-f, --force",
|
|
7260
7102
|
"Force upload even if content unchanged (recreate archive)"
|
|
7261
7103
|
).action(async (options) => {
|
|
@@ -7304,13 +7146,13 @@ var pushCommand2 = new Command13().name("push").description("Push local files to
|
|
|
7304
7146
|
});
|
|
7305
7147
|
|
|
7306
7148
|
// src/commands/artifact/pull.ts
|
|
7307
|
-
import { Command as
|
|
7149
|
+
import { Command as Command15 } from "commander";
|
|
7308
7150
|
import chalk19 from "chalk";
|
|
7309
7151
|
import path10 from "path";
|
|
7310
7152
|
import * as fs8 from "fs";
|
|
7311
7153
|
import * as os6 from "os";
|
|
7312
7154
|
import * as tar5 from "tar";
|
|
7313
|
-
var pullCommand2 = new
|
|
7155
|
+
var pullCommand2 = new Command15().name("pull").description("Pull cloud artifact to local directory").argument("[versionId]", "Version ID to pull (default: latest)").action(async (versionId) => {
|
|
7314
7156
|
try {
|
|
7315
7157
|
const cwd = process.cwd();
|
|
7316
7158
|
const config = await readStorageConfig(cwd);
|
|
@@ -7388,9 +7230,9 @@ var pullCommand2 = new Command14().name("pull").description("Pull cloud artifact
|
|
|
7388
7230
|
});
|
|
7389
7231
|
|
|
7390
7232
|
// src/commands/artifact/status.ts
|
|
7391
|
-
import { Command as
|
|
7233
|
+
import { Command as Command16 } from "commander";
|
|
7392
7234
|
import chalk20 from "chalk";
|
|
7393
|
-
var statusCommand2 = new
|
|
7235
|
+
var statusCommand2 = new Command16().name("status").description("Show status of cloud artifact").action(async () => {
|
|
7394
7236
|
try {
|
|
7395
7237
|
const cwd = process.cwd();
|
|
7396
7238
|
const config = await readStorageConfig(cwd);
|
|
@@ -7438,9 +7280,9 @@ var statusCommand2 = new Command15().name("status").description("Show status of
|
|
|
7438
7280
|
});
|
|
7439
7281
|
|
|
7440
7282
|
// src/commands/artifact/list.ts
|
|
7441
|
-
import { Command as
|
|
7283
|
+
import { Command as Command17 } from "commander";
|
|
7442
7284
|
import chalk21 from "chalk";
|
|
7443
|
-
var listCommand2 = new
|
|
7285
|
+
var listCommand2 = new Command17().name("list").alias("ls").description("List all remote artifacts").action(async () => {
|
|
7444
7286
|
try {
|
|
7445
7287
|
const items = await listStorages({ type: "artifact" });
|
|
7446
7288
|
if (items.length === 0) {
|
|
@@ -7491,9 +7333,9 @@ var listCommand2 = new Command16().name("list").alias("ls").description("List al
|
|
|
7491
7333
|
});
|
|
7492
7334
|
|
|
7493
7335
|
// src/commands/artifact/clone.ts
|
|
7494
|
-
import { Command as
|
|
7336
|
+
import { Command as Command18 } from "commander";
|
|
7495
7337
|
import chalk22 from "chalk";
|
|
7496
|
-
var cloneCommand2 = new
|
|
7338
|
+
var cloneCommand2 = new Command18().name("clone").description("Clone a remote artifact to local directory (latest version)").argument("<name>", "Artifact name to clone").argument("[destination]", "Destination directory (default: artifact name)").action(async (name, destination) => {
|
|
7497
7339
|
try {
|
|
7498
7340
|
const targetDir = destination || name;
|
|
7499
7341
|
console.log(`Cloning artifact: ${name}`);
|
|
@@ -7516,10 +7358,10 @@ var cloneCommand2 = new Command17().name("clone").description("Clone a remote ar
|
|
|
7516
7358
|
});
|
|
7517
7359
|
|
|
7518
7360
|
// src/commands/artifact/index.ts
|
|
7519
|
-
var artifactCommand = new
|
|
7361
|
+
var artifactCommand = new Command19().name("artifact").description("Manage artifacts (specified at run, versioned after run)").addCommand(initCommand2).addCommand(pushCommand2).addCommand(pullCommand2).addCommand(statusCommand2).addCommand(listCommand2).addCommand(cloneCommand2);
|
|
7520
7362
|
|
|
7521
7363
|
// src/commands/cook.ts
|
|
7522
|
-
import { Command as
|
|
7364
|
+
import { Command as Command20, Option as Option4 } from "commander";
|
|
7523
7365
|
import chalk24 from "chalk";
|
|
7524
7366
|
import { readFile as readFile7, mkdir as mkdir6 } from "fs/promises";
|
|
7525
7367
|
import { existsSync as existsSync8 } from "fs";
|
|
@@ -7672,8 +7514,8 @@ import { homedir as homedir2 } from "os";
|
|
|
7672
7514
|
import { join as join6 } from "path";
|
|
7673
7515
|
import { readFile as readFile6, writeFile as writeFile5, mkdir as mkdir5 } from "fs/promises";
|
|
7674
7516
|
import { existsSync as existsSync7 } from "fs";
|
|
7675
|
-
var
|
|
7676
|
-
var COOK_STATE_FILE = join6(
|
|
7517
|
+
var CONFIG_DIR2 = join6(homedir2(), ".vm0");
|
|
7518
|
+
var COOK_STATE_FILE = join6(CONFIG_DIR2, "cook.json");
|
|
7677
7519
|
var STALE_THRESHOLD_MS = 48 * 60 * 60 * 1e3;
|
|
7678
7520
|
async function loadCookStateFile() {
|
|
7679
7521
|
if (!existsSync7(COOK_STATE_FILE)) {
|
|
@@ -7712,7 +7554,7 @@ async function loadCookState() {
|
|
|
7712
7554
|
};
|
|
7713
7555
|
}
|
|
7714
7556
|
async function saveCookState(state) {
|
|
7715
|
-
await mkdir5(
|
|
7557
|
+
await mkdir5(CONFIG_DIR2, { recursive: true });
|
|
7716
7558
|
const file = await loadCookStateFile();
|
|
7717
7559
|
const ppid = String(process.ppid);
|
|
7718
7560
|
const now = Date.now();
|
|
@@ -7733,7 +7575,7 @@ async function saveCookState(state) {
|
|
|
7733
7575
|
}
|
|
7734
7576
|
|
|
7735
7577
|
// src/commands/cook.ts
|
|
7736
|
-
var
|
|
7578
|
+
var CONFIG_FILE2 = "vm0.yaml";
|
|
7737
7579
|
var ARTIFACT_DIR = "artifact";
|
|
7738
7580
|
function printCommand(cmd) {
|
|
7739
7581
|
console.log(chalk24.dim(`> ${cmd}`));
|
|
@@ -7880,7 +7722,7 @@ async function autoPullArtifact(runOutput, artifactDir) {
|
|
|
7880
7722
|
}
|
|
7881
7723
|
}
|
|
7882
7724
|
}
|
|
7883
|
-
var cookCmd = new
|
|
7725
|
+
var cookCmd = new Command20().name("cook").description("Quick start: prepare, compose and run agent from vm0.yaml");
|
|
7884
7726
|
cookCmd.argument("[prompt]", "Prompt for the agent").option(
|
|
7885
7727
|
"--env-file <path>",
|
|
7886
7728
|
"Load environment variables from file (priority: CLI flags > file > env vars)"
|
|
@@ -7888,20 +7730,20 @@ cookCmd.argument("[prompt]", "Prompt for the agent").option(
|
|
|
7888
7730
|
// eslint-disable-next-line complexity -- TODO: refactor complex function
|
|
7889
7731
|
async (prompt, options) => {
|
|
7890
7732
|
if (!options.noAutoUpdate) {
|
|
7891
|
-
const shouldExit = await checkAndUpgrade("9.
|
|
7733
|
+
const shouldExit = await checkAndUpgrade("9.2.0", prompt);
|
|
7892
7734
|
if (shouldExit) {
|
|
7893
7735
|
process.exit(0);
|
|
7894
7736
|
}
|
|
7895
7737
|
}
|
|
7896
7738
|
const cwd = process.cwd();
|
|
7897
|
-
console.log(chalk24.bold(`Reading config: ${
|
|
7898
|
-
if (!existsSync8(
|
|
7899
|
-
console.error(chalk24.red(`\u2717 Config file not found: ${
|
|
7739
|
+
console.log(chalk24.bold(`Reading config: ${CONFIG_FILE2}`));
|
|
7740
|
+
if (!existsSync8(CONFIG_FILE2)) {
|
|
7741
|
+
console.error(chalk24.red(`\u2717 Config file not found: ${CONFIG_FILE2}`));
|
|
7900
7742
|
process.exit(1);
|
|
7901
7743
|
}
|
|
7902
7744
|
let config;
|
|
7903
7745
|
try {
|
|
7904
|
-
const content = await readFile7(
|
|
7746
|
+
const content = await readFile7(CONFIG_FILE2, "utf8");
|
|
7905
7747
|
config = parseYaml4(content);
|
|
7906
7748
|
} catch (error) {
|
|
7907
7749
|
console.error(chalk24.red("\u2717 Invalid YAML format"));
|
|
@@ -8022,7 +7864,7 @@ cookCmd.argument("[prompt]", "Prompt for the agent").option(
|
|
|
8022
7864
|
}
|
|
8023
7865
|
console.log();
|
|
8024
7866
|
console.log(chalk24.bold("Composing agent:"));
|
|
8025
|
-
const composeArgs = options.yes ? ["compose", "--yes",
|
|
7867
|
+
const composeArgs = options.yes ? ["compose", "--yes", CONFIG_FILE2] : ["compose", CONFIG_FILE2];
|
|
8026
7868
|
printCommand(`vm0 ${composeArgs.join(" ")}`);
|
|
8027
7869
|
try {
|
|
8028
7870
|
await execVm0Command(composeArgs, {
|
|
@@ -8216,7 +8058,7 @@ cookCmd.command("resume").description(
|
|
|
8216
8058
|
var cookCommand = cookCmd;
|
|
8217
8059
|
|
|
8218
8060
|
// src/commands/logs/index.ts
|
|
8219
|
-
import { Command as
|
|
8061
|
+
import { Command as Command21 } from "commander";
|
|
8220
8062
|
import chalk25 from "chalk";
|
|
8221
8063
|
|
|
8222
8064
|
// src/lib/utils/time-parser.ts
|
|
@@ -8334,7 +8176,7 @@ function getLogType(options) {
|
|
|
8334
8176
|
if (options.network) return "network";
|
|
8335
8177
|
return "agent";
|
|
8336
8178
|
}
|
|
8337
|
-
var logsCommand = new
|
|
8179
|
+
var logsCommand = new Command21().name("logs").description("View logs for an agent run").argument("<runId>", "Run ID to fetch logs for").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(
|
|
8338
8180
|
"--since <time>",
|
|
8339
8181
|
"Show logs since timestamp (e.g., 5m, 2h, 1d, 2024-01-15T10:30:00Z, 1705312200)"
|
|
8340
8182
|
).option("--tail <n>", "Show last N entries (default: 5, max: 100)").option("--head <n>", "Show first N entries (max: 100)").action(
|
|
@@ -8470,12 +8312,12 @@ function handleError2(error, runId) {
|
|
|
8470
8312
|
}
|
|
8471
8313
|
|
|
8472
8314
|
// src/commands/scope/index.ts
|
|
8473
|
-
import { Command as
|
|
8315
|
+
import { Command as Command24 } from "commander";
|
|
8474
8316
|
|
|
8475
8317
|
// src/commands/scope/status.ts
|
|
8476
|
-
import { Command as
|
|
8318
|
+
import { Command as Command22 } from "commander";
|
|
8477
8319
|
import chalk26 from "chalk";
|
|
8478
|
-
var statusCommand3 = new
|
|
8320
|
+
var statusCommand3 = new Command22().name("status").description("View current scope status").action(async () => {
|
|
8479
8321
|
try {
|
|
8480
8322
|
const scope = await getScope();
|
|
8481
8323
|
console.log(chalk26.bold("Scope Information:"));
|
|
@@ -8507,9 +8349,9 @@ var statusCommand3 = new Command21().name("status").description("View current sc
|
|
|
8507
8349
|
});
|
|
8508
8350
|
|
|
8509
8351
|
// src/commands/scope/set.ts
|
|
8510
|
-
import { Command as
|
|
8352
|
+
import { Command as Command23 } from "commander";
|
|
8511
8353
|
import chalk27 from "chalk";
|
|
8512
|
-
var setCommand = new
|
|
8354
|
+
var setCommand = new Command23().name("set").description("Set your scope slug").argument("<slug>", "The scope slug (e.g., your username)").option("--force", "Force change existing scope (may break references)").action(async (slug, options) => {
|
|
8513
8355
|
try {
|
|
8514
8356
|
let existingScope;
|
|
8515
8357
|
try {
|
|
@@ -8574,15 +8416,15 @@ var setCommand = new Command22().name("set").description("Set your scope slug").
|
|
|
8574
8416
|
});
|
|
8575
8417
|
|
|
8576
8418
|
// src/commands/scope/index.ts
|
|
8577
|
-
var scopeCommand = new
|
|
8419
|
+
var scopeCommand = new Command24().name("scope").description("Manage your scope (namespace for agents)").addCommand(statusCommand3).addCommand(setCommand);
|
|
8578
8420
|
|
|
8579
8421
|
// src/commands/agent/index.ts
|
|
8580
|
-
import { Command as
|
|
8422
|
+
import { Command as Command27 } from "commander";
|
|
8581
8423
|
|
|
8582
8424
|
// src/commands/agent/list.ts
|
|
8583
|
-
import { Command as
|
|
8425
|
+
import { Command as Command25 } from "commander";
|
|
8584
8426
|
import chalk28 from "chalk";
|
|
8585
|
-
var listCommand3 = new
|
|
8427
|
+
var listCommand3 = new Command25().name("list").alias("ls").description("List all agent composes").action(async () => {
|
|
8586
8428
|
try {
|
|
8587
8429
|
const response = await httpGet("/api/agent/composes/list");
|
|
8588
8430
|
if (!response.ok) {
|
|
@@ -8625,7 +8467,7 @@ var listCommand3 = new Command24().name("list").alias("ls").description("List al
|
|
|
8625
8467
|
});
|
|
8626
8468
|
|
|
8627
8469
|
// src/commands/agent/status.ts
|
|
8628
|
-
import { Command as
|
|
8470
|
+
import { Command as Command26 } from "commander";
|
|
8629
8471
|
import chalk29 from "chalk";
|
|
8630
8472
|
|
|
8631
8473
|
// src/lib/domain/source-derivation.ts
|
|
@@ -8798,7 +8640,7 @@ function formatComposeOutput(name, versionId, content, variableSources) {
|
|
|
8798
8640
|
formatAgentDetails(agentName, agent, agentSources, content.volumes);
|
|
8799
8641
|
}
|
|
8800
8642
|
}
|
|
8801
|
-
var statusCommand4 = new
|
|
8643
|
+
var statusCommand4 = new Command26().name("status").description("Show status of agent compose").argument(
|
|
8802
8644
|
"<name[:version]>",
|
|
8803
8645
|
"Agent name with optional version (e.g., my-agent:latest or my-agent:a1b2c3d4)"
|
|
8804
8646
|
).option("--no-sources", "Skip fetching skills to determine variable sources").action(async (argument, options) => {
|
|
@@ -8878,10 +8720,10 @@ var statusCommand4 = new Command25().name("status").description("Show status of
|
|
|
8878
8720
|
});
|
|
8879
8721
|
|
|
8880
8722
|
// src/commands/agent/index.ts
|
|
8881
|
-
var agentCommand = new
|
|
8723
|
+
var agentCommand = new Command27().name("agent").description("Manage agent composes").addCommand(listCommand3).addCommand(statusCommand4);
|
|
8882
8724
|
|
|
8883
8725
|
// src/commands/init.ts
|
|
8884
|
-
import { Command as
|
|
8726
|
+
import { Command as Command28 } from "commander";
|
|
8885
8727
|
import chalk30 from "chalk";
|
|
8886
8728
|
import path13 from "path";
|
|
8887
8729
|
import { existsSync as existsSync9 } from "fs";
|
|
@@ -8920,7 +8762,7 @@ function checkExistingFiles() {
|
|
|
8920
8762
|
if (existsSync9(AGENTS_MD_FILE)) existingFiles.push(AGENTS_MD_FILE);
|
|
8921
8763
|
return existingFiles;
|
|
8922
8764
|
}
|
|
8923
|
-
var initCommand3 = new
|
|
8765
|
+
var initCommand3 = new Command28().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) => {
|
|
8924
8766
|
const existingFiles = checkExistingFiles();
|
|
8925
8767
|
if (existingFiles.length > 0 && !options.force) {
|
|
8926
8768
|
for (const file of existingFiles) {
|
|
@@ -8986,10 +8828,10 @@ var initCommand3 = new Command27().name("init").description("Initialize a new VM
|
|
|
8986
8828
|
});
|
|
8987
8829
|
|
|
8988
8830
|
// src/commands/schedule/index.ts
|
|
8989
|
-
import { Command as
|
|
8831
|
+
import { Command as Command35 } from "commander";
|
|
8990
8832
|
|
|
8991
8833
|
// src/commands/schedule/setup.ts
|
|
8992
|
-
import { Command as
|
|
8834
|
+
import { Command as Command29 } from "commander";
|
|
8993
8835
|
import chalk32 from "chalk";
|
|
8994
8836
|
|
|
8995
8837
|
// src/lib/domain/schedule-utils.ts
|
|
@@ -9568,7 +9410,7 @@ Deploying schedule for agent ${chalk32.cyan(params.agentName)}...`
|
|
|
9568
9410
|
secrets: expandedSecrets,
|
|
9569
9411
|
artifactName: params.artifactName
|
|
9570
9412
|
});
|
|
9571
|
-
|
|
9413
|
+
return deployResult;
|
|
9572
9414
|
}
|
|
9573
9415
|
function handleSetupError(error) {
|
|
9574
9416
|
console.error(chalk32.red("\u2717 Failed to setup schedule"));
|
|
@@ -9608,14 +9450,53 @@ function displayDeployResult(agentName, deployResult) {
|
|
|
9608
9450
|
);
|
|
9609
9451
|
console.log(chalk32.dim(` At: ${atTimeFormatted}`));
|
|
9610
9452
|
}
|
|
9611
|
-
|
|
9612
|
-
|
|
9453
|
+
}
|
|
9454
|
+
async function tryEnableSchedule(scheduleName, composeId, agentName) {
|
|
9455
|
+
try {
|
|
9456
|
+
await enableSchedule({ name: scheduleName, composeId });
|
|
9613
9457
|
console.log(
|
|
9614
|
-
|
|
9458
|
+
chalk32.green(`\u2713 Enabled schedule for agent ${chalk32.cyan(agentName)}`)
|
|
9615
9459
|
);
|
|
9460
|
+
} catch (error) {
|
|
9461
|
+
console.error(chalk32.yellow("\u26A0 Failed to enable schedule"));
|
|
9462
|
+
if (error instanceof ApiRequestError) {
|
|
9463
|
+
if (error.code === "SCHEDULE_PAST") {
|
|
9464
|
+
console.error(chalk32.dim(" Scheduled time has already passed"));
|
|
9465
|
+
} else {
|
|
9466
|
+
console.error(chalk32.dim(` ${error.message}`));
|
|
9467
|
+
}
|
|
9468
|
+
} else if (error instanceof Error) {
|
|
9469
|
+
console.error(chalk32.dim(` ${error.message}`));
|
|
9470
|
+
}
|
|
9471
|
+
console.log(
|
|
9472
|
+
` To enable manually: ${chalk32.cyan(`vm0 schedule enable ${agentName}`)}`
|
|
9473
|
+
);
|
|
9474
|
+
}
|
|
9475
|
+
}
|
|
9476
|
+
function showEnableHint(agentName) {
|
|
9477
|
+
console.log();
|
|
9478
|
+
console.log(` To enable: ${chalk32.cyan(`vm0 schedule enable ${agentName}`)}`);
|
|
9479
|
+
}
|
|
9480
|
+
async function handleScheduleEnabling(params) {
|
|
9481
|
+
const { scheduleName, composeId, agentName, enableFlag, shouldPromptEnable } = params;
|
|
9482
|
+
if (enableFlag) {
|
|
9483
|
+
await tryEnableSchedule(scheduleName, composeId, agentName);
|
|
9484
|
+
return;
|
|
9485
|
+
}
|
|
9486
|
+
if (shouldPromptEnable && isInteractive()) {
|
|
9487
|
+
const enableNow = await promptConfirm("Enable this schedule?", true);
|
|
9488
|
+
if (enableNow) {
|
|
9489
|
+
await tryEnableSchedule(scheduleName, composeId, agentName);
|
|
9490
|
+
} else {
|
|
9491
|
+
showEnableHint(agentName);
|
|
9492
|
+
}
|
|
9493
|
+
return;
|
|
9494
|
+
}
|
|
9495
|
+
if (shouldPromptEnable) {
|
|
9496
|
+
showEnableHint(agentName);
|
|
9616
9497
|
}
|
|
9617
9498
|
}
|
|
9618
|
-
var setupCommand = new
|
|
9499
|
+
var setupCommand = new Command29().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").option("-e, --enable", "Enable schedule immediately after creation").action(async (agentName, options) => {
|
|
9619
9500
|
try {
|
|
9620
9501
|
const { composeId, scheduleName, composeContent } = await resolveAgent(agentName);
|
|
9621
9502
|
const requiredConfig = extractRequiredConfiguration(composeContent);
|
|
@@ -9662,7 +9543,7 @@ var setupCommand = new Command28().name("setup").description("Create or edit a s
|
|
|
9662
9543
|
optionVars: options.var || [],
|
|
9663
9544
|
existingSchedule
|
|
9664
9545
|
});
|
|
9665
|
-
await buildAndDeploy({
|
|
9546
|
+
const deployResult = await buildAndDeploy({
|
|
9666
9547
|
scheduleName,
|
|
9667
9548
|
composeId,
|
|
9668
9549
|
agentName,
|
|
@@ -9676,15 +9557,24 @@ var setupCommand = new Command28().name("setup").description("Create or edit a s
|
|
|
9676
9557
|
secrets: config.preserveExistingSecrets ? void 0 : Object.keys(config.secrets).length > 0 ? config.secrets : void 0,
|
|
9677
9558
|
artifactName: options.artifactName
|
|
9678
9559
|
});
|
|
9560
|
+
displayDeployResult(agentName, deployResult);
|
|
9561
|
+
const shouldPromptEnable = deployResult.created || existingSchedule !== void 0 && !existingSchedule.enabled;
|
|
9562
|
+
await handleScheduleEnabling({
|
|
9563
|
+
scheduleName,
|
|
9564
|
+
composeId,
|
|
9565
|
+
agentName,
|
|
9566
|
+
enableFlag: options.enable ?? false,
|
|
9567
|
+
shouldPromptEnable
|
|
9568
|
+
});
|
|
9679
9569
|
} catch (error) {
|
|
9680
9570
|
handleSetupError(error);
|
|
9681
9571
|
}
|
|
9682
9572
|
});
|
|
9683
9573
|
|
|
9684
9574
|
// src/commands/schedule/list.ts
|
|
9685
|
-
import { Command as
|
|
9575
|
+
import { Command as Command30 } from "commander";
|
|
9686
9576
|
import chalk33 from "chalk";
|
|
9687
|
-
var listCommand4 = new
|
|
9577
|
+
var listCommand4 = new Command30().name("list").alias("ls").description("List all schedules").action(async () => {
|
|
9688
9578
|
try {
|
|
9689
9579
|
const result = await listSchedules();
|
|
9690
9580
|
if (result.schedules.length === 0) {
|
|
@@ -9738,7 +9628,7 @@ var listCommand4 = new Command29().name("list").alias("ls").description("List al
|
|
|
9738
9628
|
});
|
|
9739
9629
|
|
|
9740
9630
|
// src/commands/schedule/status.ts
|
|
9741
|
-
import { Command as
|
|
9631
|
+
import { Command as Command31 } from "commander";
|
|
9742
9632
|
import chalk34 from "chalk";
|
|
9743
9633
|
function formatDateTimeStyled(dateStr) {
|
|
9744
9634
|
if (!dateStr) return chalk34.dim("-");
|
|
@@ -9841,7 +9731,7 @@ function handleStatusError(error, agentName) {
|
|
|
9841
9731
|
}
|
|
9842
9732
|
process.exit(1);
|
|
9843
9733
|
}
|
|
9844
|
-
var statusCommand5 = new
|
|
9734
|
+
var statusCommand5 = new Command31().name("status").description("Show detailed status of a schedule").argument("<agent-name>", "Agent name").option(
|
|
9845
9735
|
"-l, --limit <number>",
|
|
9846
9736
|
"Number of recent runs to show (0 to hide)",
|
|
9847
9737
|
"5"
|
|
@@ -9867,9 +9757,9 @@ var statusCommand5 = new Command30().name("status").description("Show detailed s
|
|
|
9867
9757
|
});
|
|
9868
9758
|
|
|
9869
9759
|
// src/commands/schedule/delete.ts
|
|
9870
|
-
import { Command as
|
|
9760
|
+
import { Command as Command32 } from "commander";
|
|
9871
9761
|
import chalk35 from "chalk";
|
|
9872
|
-
var deleteCommand = new
|
|
9762
|
+
var deleteCommand = new Command32().name("delete").alias("rm").description("Delete a schedule").argument("<agent-name>", "Agent name").option("-f, --force", "Skip confirmation prompt").action(async (agentName, options) => {
|
|
9873
9763
|
try {
|
|
9874
9764
|
const resolved = await resolveScheduleByAgent(agentName);
|
|
9875
9765
|
if (!options.force) {
|
|
@@ -9914,9 +9804,9 @@ var deleteCommand = new Command31().name("delete").alias("rm").description("Dele
|
|
|
9914
9804
|
});
|
|
9915
9805
|
|
|
9916
9806
|
// src/commands/schedule/enable.ts
|
|
9917
|
-
import { Command as
|
|
9807
|
+
import { Command as Command33 } from "commander";
|
|
9918
9808
|
import chalk36 from "chalk";
|
|
9919
|
-
var enableCommand = new
|
|
9809
|
+
var enableCommand = new Command33().name("enable").description("Enable a schedule").argument("<agent-name>", "Agent name").action(async (agentName) => {
|
|
9920
9810
|
try {
|
|
9921
9811
|
const resolved = await resolveScheduleByAgent(agentName);
|
|
9922
9812
|
await enableSchedule({
|
|
@@ -9959,9 +9849,9 @@ var enableCommand = new Command32().name("enable").description("Enable a schedul
|
|
|
9959
9849
|
});
|
|
9960
9850
|
|
|
9961
9851
|
// src/commands/schedule/disable.ts
|
|
9962
|
-
import { Command as
|
|
9852
|
+
import { Command as Command34 } from "commander";
|
|
9963
9853
|
import chalk37 from "chalk";
|
|
9964
|
-
var disableCommand = new
|
|
9854
|
+
var disableCommand = new Command34().name("disable").description("Disable a schedule").argument("<agent-name>", "Agent name").action(async (agentName) => {
|
|
9965
9855
|
try {
|
|
9966
9856
|
const resolved = await resolveScheduleByAgent(agentName);
|
|
9967
9857
|
await disableSchedule({
|
|
@@ -9990,10 +9880,10 @@ var disableCommand = new Command33().name("disable").description("Disable a sche
|
|
|
9990
9880
|
});
|
|
9991
9881
|
|
|
9992
9882
|
// src/commands/schedule/index.ts
|
|
9993
|
-
var scheduleCommand = new
|
|
9883
|
+
var scheduleCommand = new Command35().name("schedule").description("Manage agent schedules").addCommand(setupCommand).addCommand(listCommand4).addCommand(statusCommand5).addCommand(deleteCommand).addCommand(enableCommand).addCommand(disableCommand);
|
|
9994
9884
|
|
|
9995
9885
|
// src/commands/usage.ts
|
|
9996
|
-
import { Command as
|
|
9886
|
+
import { Command as Command36 } from "commander";
|
|
9997
9887
|
import chalk38 from "chalk";
|
|
9998
9888
|
|
|
9999
9889
|
// src/lib/utils/duration-formatter.ts
|
|
@@ -10067,7 +9957,7 @@ function fillMissingDates(daily, startDate, endDate) {
|
|
|
10067
9957
|
result.sort((a, b) => b.date.localeCompare(a.date));
|
|
10068
9958
|
return result;
|
|
10069
9959
|
}
|
|
10070
|
-
var usageCommand = new
|
|
9960
|
+
var usageCommand = new Command36().name("usage").description("View usage statistics").option("--since <date>", "Start date (ISO format or relative: 7d, 30d)").option(
|
|
10071
9961
|
"--until <date>",
|
|
10072
9962
|
"End date (ISO format or relative, defaults to now)"
|
|
10073
9963
|
).action(async (options) => {
|
|
@@ -10164,12 +10054,12 @@ var usageCommand = new Command35().name("usage").description("View usage statist
|
|
|
10164
10054
|
});
|
|
10165
10055
|
|
|
10166
10056
|
// src/commands/credential/index.ts
|
|
10167
|
-
import { Command as
|
|
10057
|
+
import { Command as Command40 } from "commander";
|
|
10168
10058
|
|
|
10169
10059
|
// src/commands/credential/list.ts
|
|
10170
|
-
import { Command as
|
|
10060
|
+
import { Command as Command37 } from "commander";
|
|
10171
10061
|
import chalk39 from "chalk";
|
|
10172
|
-
var listCommand5 = new
|
|
10062
|
+
var listCommand5 = new Command37().name("list").alias("ls").description("List all credentials").action(async () => {
|
|
10173
10063
|
try {
|
|
10174
10064
|
const result = await listCredentials();
|
|
10175
10065
|
if (result.credentials.length === 0) {
|
|
@@ -10210,9 +10100,9 @@ var listCommand5 = new Command36().name("list").alias("ls").description("List al
|
|
|
10210
10100
|
});
|
|
10211
10101
|
|
|
10212
10102
|
// src/commands/credential/set.ts
|
|
10213
|
-
import { Command as
|
|
10103
|
+
import { Command as Command38 } from "commander";
|
|
10214
10104
|
import chalk40 from "chalk";
|
|
10215
|
-
var setCommand2 = new
|
|
10105
|
+
var setCommand2 = new Command38().name("set").description("Create or update a credential").argument("<name>", "Credential name (uppercase, e.g., MY_API_KEY)").argument("<value>", "Credential value").option("-d, --description <description>", "Optional description").action(
|
|
10216
10106
|
async (name, value, options) => {
|
|
10217
10107
|
try {
|
|
10218
10108
|
const credential = await setCredential({
|
|
@@ -10250,9 +10140,9 @@ var setCommand2 = new Command37().name("set").description("Create or update a cr
|
|
|
10250
10140
|
);
|
|
10251
10141
|
|
|
10252
10142
|
// src/commands/credential/delete.ts
|
|
10253
|
-
import { Command as
|
|
10143
|
+
import { Command as Command39 } from "commander";
|
|
10254
10144
|
import chalk41 from "chalk";
|
|
10255
|
-
var deleteCommand2 = new
|
|
10145
|
+
var deleteCommand2 = new Command39().name("delete").description("Delete a credential").argument("<name>", "Credential name to delete").option("-y, --yes", "Skip confirmation prompt").action(async (name, options) => {
|
|
10256
10146
|
try {
|
|
10257
10147
|
try {
|
|
10258
10148
|
await getCredential(name);
|
|
@@ -10293,15 +10183,15 @@ var deleteCommand2 = new Command38().name("delete").description("Delete a creden
|
|
|
10293
10183
|
});
|
|
10294
10184
|
|
|
10295
10185
|
// src/commands/credential/index.ts
|
|
10296
|
-
var credentialCommand = new
|
|
10186
|
+
var credentialCommand = new Command40().name("credential").description("Manage stored credentials for agent runs").addCommand(listCommand5).addCommand(setCommand2).addCommand(deleteCommand2);
|
|
10297
10187
|
|
|
10298
10188
|
// src/commands/model-provider/index.ts
|
|
10299
|
-
import { Command as
|
|
10189
|
+
import { Command as Command45 } from "commander";
|
|
10300
10190
|
|
|
10301
10191
|
// src/commands/model-provider/list.ts
|
|
10302
|
-
import { Command as
|
|
10192
|
+
import { Command as Command41 } from "commander";
|
|
10303
10193
|
import chalk42 from "chalk";
|
|
10304
|
-
var listCommand6 = new
|
|
10194
|
+
var listCommand6 = new Command41().name("list").alias("ls").description("List all model providers").action(async () => {
|
|
10305
10195
|
try {
|
|
10306
10196
|
const result = await listModelProviders();
|
|
10307
10197
|
if (result.modelProviders.length === 0) {
|
|
@@ -10355,7 +10245,7 @@ var listCommand6 = new Command40().name("list").alias("ls").description("List al
|
|
|
10355
10245
|
});
|
|
10356
10246
|
|
|
10357
10247
|
// src/commands/model-provider/setup.ts
|
|
10358
|
-
import { Command as
|
|
10248
|
+
import { Command as Command42 } from "commander";
|
|
10359
10249
|
import chalk43 from "chalk";
|
|
10360
10250
|
import prompts2 from "prompts";
|
|
10361
10251
|
var providerChoices = Object.entries(MODEL_PROVIDER_TYPES).map(
|
|
@@ -10364,7 +10254,7 @@ var providerChoices = Object.entries(MODEL_PROVIDER_TYPES).map(
|
|
|
10364
10254
|
value: type
|
|
10365
10255
|
})
|
|
10366
10256
|
);
|
|
10367
|
-
var setupCommand2 = new
|
|
10257
|
+
var setupCommand2 = new Command42().name("setup").description("Configure a model provider").option("-t, --type <type>", "Provider type (for non-interactive mode)").option(
|
|
10368
10258
|
"-c, --credential <credential>",
|
|
10369
10259
|
"Credential value (for non-interactive mode)"
|
|
10370
10260
|
).option("--convert", "Convert existing user credential to model provider").action(
|
|
@@ -10485,9 +10375,9 @@ var setupCommand2 = new Command41().name("setup").description("Configure a model
|
|
|
10485
10375
|
);
|
|
10486
10376
|
|
|
10487
10377
|
// src/commands/model-provider/delete.ts
|
|
10488
|
-
import { Command as
|
|
10378
|
+
import { Command as Command43 } from "commander";
|
|
10489
10379
|
import chalk44 from "chalk";
|
|
10490
|
-
var deleteCommand3 = new
|
|
10380
|
+
var deleteCommand3 = new Command43().name("delete").description("Delete a model provider").argument("<type>", "Model provider type to delete").action(async (type) => {
|
|
10491
10381
|
try {
|
|
10492
10382
|
if (!Object.keys(MODEL_PROVIDER_TYPES).includes(type)) {
|
|
10493
10383
|
console.error(chalk44.red(`\u2717 Invalid type "${type}"`));
|
|
@@ -10517,9 +10407,9 @@ var deleteCommand3 = new Command42().name("delete").description("Delete a model
|
|
|
10517
10407
|
});
|
|
10518
10408
|
|
|
10519
10409
|
// src/commands/model-provider/set-default.ts
|
|
10520
|
-
import { Command as
|
|
10410
|
+
import { Command as Command44 } from "commander";
|
|
10521
10411
|
import chalk45 from "chalk";
|
|
10522
|
-
var setDefaultCommand = new
|
|
10412
|
+
var setDefaultCommand = new Command44().name("set-default").description("Set a model provider as default for its framework").argument("<type>", "Model provider type to set as default").action(async (type) => {
|
|
10523
10413
|
try {
|
|
10524
10414
|
if (!Object.keys(MODEL_PROVIDER_TYPES).includes(type)) {
|
|
10525
10415
|
console.error(chalk45.red(`\u2717 Invalid type "${type}"`));
|
|
@@ -10553,13 +10443,354 @@ var setDefaultCommand = new Command43().name("set-default").description("Set a m
|
|
|
10553
10443
|
});
|
|
10554
10444
|
|
|
10555
10445
|
// src/commands/model-provider/index.ts
|
|
10556
|
-
var modelProviderCommand = new
|
|
10446
|
+
var modelProviderCommand = new Command45().name("model-provider").description("Manage model providers for agent runs").addCommand(listCommand6).addCommand(setupCommand2).addCommand(deleteCommand3).addCommand(setDefaultCommand);
|
|
10447
|
+
|
|
10448
|
+
// src/commands/onboard.ts
|
|
10449
|
+
import { Command as Command47 } from "commander";
|
|
10450
|
+
import chalk47 from "chalk";
|
|
10451
|
+
import prompts3 from "prompts";
|
|
10452
|
+
import { mkdir as mkdir8 } from "fs/promises";
|
|
10453
|
+
import { existsSync as existsSync10 } from "fs";
|
|
10454
|
+
|
|
10455
|
+
// src/commands/setup-claude.ts
|
|
10456
|
+
import { Command as Command46 } from "commander";
|
|
10457
|
+
import chalk46 from "chalk";
|
|
10458
|
+
import { mkdir as mkdir7, writeFile as writeFile7 } from "fs/promises";
|
|
10459
|
+
import path14 from "path";
|
|
10460
|
+
var SKILL_DIR = ".claude/skills/vm0-agent-builder";
|
|
10461
|
+
var SKILL_CONTENT = `---
|
|
10462
|
+
name: vm0-agent-builder
|
|
10463
|
+
description: Guide for building VM0 agents with Claude's help. Use this skill when users want to create or improve their agent's AGENTS.md and vm0.yaml configuration.
|
|
10464
|
+
---
|
|
10465
|
+
|
|
10466
|
+
# VM0 Agent Builder
|
|
10467
|
+
|
|
10468
|
+
Help users create effective AI agents using the VM0 platform. This skill guides the process of designing agent workflows, writing AGENTS.md instructions, and configuring vm0.yaml.
|
|
10469
|
+
|
|
10470
|
+
## When to Use
|
|
10471
|
+
|
|
10472
|
+
- User wants to create a new VM0 agent from scratch
|
|
10473
|
+
- User wants to improve an existing agent's instructions
|
|
10474
|
+
- User needs help configuring vm0.yaml with skills
|
|
10475
|
+
- User is unsure how to structure their agent's workflow
|
|
10476
|
+
|
|
10477
|
+
## Workflow
|
|
10478
|
+
|
|
10479
|
+
### Step 1: Understand the Goal
|
|
10480
|
+
|
|
10481
|
+
Ask the user what they want their agent to accomplish:
|
|
10482
|
+
- What is the main task or problem to solve?
|
|
10483
|
+
- What inputs will the agent receive?
|
|
10484
|
+
- What outputs should the agent produce?
|
|
10485
|
+
- Are there any constraints or requirements?
|
|
10486
|
+
|
|
10487
|
+
### Step 2: Design the Workflow
|
|
10488
|
+
|
|
10489
|
+
Break down the task into clear, sequential steps:
|
|
10490
|
+
1. Each step should be a single, focused action
|
|
10491
|
+
2. Steps should build on each other logically
|
|
10492
|
+
3. Include error handling and edge cases
|
|
10493
|
+
4. Consider what tools/skills the agent will need
|
|
10494
|
+
|
|
10495
|
+
### Step 3: Write AGENTS.md
|
|
10496
|
+
|
|
10497
|
+
Create the agent instructions file with:
|
|
10498
|
+
|
|
10499
|
+
\`\`\`markdown
|
|
10500
|
+
# Agent Instructions
|
|
10501
|
+
|
|
10502
|
+
You are a [role description].
|
|
10503
|
+
|
|
10504
|
+
## Goal
|
|
10505
|
+
|
|
10506
|
+
[Clear statement of what the agent should accomplish]
|
|
10507
|
+
|
|
10508
|
+
## Workflow
|
|
10509
|
+
|
|
10510
|
+
1. [First step with specific instructions]
|
|
10511
|
+
2. [Second step with specific instructions]
|
|
10512
|
+
3. [Continue with remaining steps...]
|
|
10513
|
+
|
|
10514
|
+
## Output
|
|
10515
|
+
|
|
10516
|
+
[Describe the expected output format and location]
|
|
10517
|
+
|
|
10518
|
+
## Constraints
|
|
10519
|
+
|
|
10520
|
+
[Any limitations or rules the agent should follow]
|
|
10521
|
+
\`\`\`
|
|
10522
|
+
|
|
10523
|
+
### Step 4: Configure vm0.yaml
|
|
10524
|
+
|
|
10525
|
+
Update the vm0.yaml to include necessary skills:
|
|
10526
|
+
|
|
10527
|
+
\`\`\`yaml
|
|
10528
|
+
version: "1.0"
|
|
10529
|
+
|
|
10530
|
+
agents:
|
|
10531
|
+
agent-name:
|
|
10532
|
+
framework: claude-code
|
|
10533
|
+
instructions: AGENTS.md
|
|
10534
|
+
skills:
|
|
10535
|
+
- https://github.com/vm0-ai/vm0-skills/tree/main/skill-name
|
|
10536
|
+
environment:
|
|
10537
|
+
# Add any required environment variables
|
|
10538
|
+
API_KEY: "\${{ secrets.API_KEY }}"
|
|
10539
|
+
\`\`\`
|
|
10540
|
+
|
|
10541
|
+
### Step 5: Test the Agent
|
|
10542
|
+
|
|
10543
|
+
Guide the user to test their agent:
|
|
10544
|
+
|
|
10545
|
+
\`\`\`bash
|
|
10546
|
+
# Deploy the agent configuration
|
|
10547
|
+
vm0 compose vm0.yaml
|
|
10548
|
+
|
|
10549
|
+
# Run the agent with a test prompt
|
|
10550
|
+
vm0 cook "start working on the task"
|
|
10551
|
+
|
|
10552
|
+
# Check the logs if needed
|
|
10553
|
+
vm0 logs <run-id>
|
|
10554
|
+
\`\`\`
|
|
10555
|
+
|
|
10556
|
+
## Available Skills
|
|
10557
|
+
|
|
10558
|
+
Common skills from vm0-skills repository:
|
|
10559
|
+
|
|
10560
|
+
| Skill | Purpose |
|
|
10561
|
+
|-------|---------|
|
|
10562
|
+
| \`github\` | GitHub API operations (issues, PRs, repos) |
|
|
10563
|
+
| \`slack\` | Send messages to Slack channels |
|
|
10564
|
+
| \`notion\` | Read/write Notion pages and databases |
|
|
10565
|
+
| \`firecrawl\` | Web scraping and content extraction |
|
|
10566
|
+
| \`browserbase\` | Browser automation |
|
|
10567
|
+
| \`openai\` | OpenAI API for embeddings, completions |
|
|
10568
|
+
| \`supabase\` | Database operations with Supabase |
|
|
10569
|
+
|
|
10570
|
+
Browse all skills: https://github.com/vm0-ai/vm0-skills
|
|
10571
|
+
|
|
10572
|
+
## Example Agents
|
|
10573
|
+
|
|
10574
|
+
### Content Curator Agent
|
|
10575
|
+
|
|
10576
|
+
\`\`\`markdown
|
|
10577
|
+
# Agent Instructions
|
|
10578
|
+
|
|
10579
|
+
You are a content curator that monitors HackerNews for AI-related articles.
|
|
10580
|
+
|
|
10581
|
+
## Workflow
|
|
10582
|
+
|
|
10583
|
+
1. Go to HackerNews and read the top 30 stories
|
|
10584
|
+
2. Filter for AI, ML, and LLM related content
|
|
10585
|
+
3. For each relevant article, extract:
|
|
10586
|
+
- Title and URL
|
|
10587
|
+
- Key points (2-3 sentences)
|
|
10588
|
+
- Why it's interesting
|
|
10589
|
+
4. Write a summary to \`daily-digest.md\`
|
|
10590
|
+
|
|
10591
|
+
## Output
|
|
10592
|
+
|
|
10593
|
+
Create \`daily-digest.md\` with today's date as the header.
|
|
10594
|
+
\`\`\`
|
|
10595
|
+
|
|
10596
|
+
### GitHub Issue Tracker Agent
|
|
10597
|
+
|
|
10598
|
+
\`\`\`markdown
|
|
10599
|
+
# Agent Instructions
|
|
10600
|
+
|
|
10601
|
+
You are a GitHub issue tracker that summarizes open issues.
|
|
10602
|
+
|
|
10603
|
+
## Workflow
|
|
10604
|
+
|
|
10605
|
+
1. List all open issues in the repository
|
|
10606
|
+
2. Group issues by labels (bug, feature, docs)
|
|
10607
|
+
3. For each group, summarize:
|
|
10608
|
+
- Number of issues
|
|
10609
|
+
- Oldest issue age
|
|
10610
|
+
- Most discussed issues
|
|
10611
|
+
4. Create a report in \`issue-report.md\`
|
|
10612
|
+
|
|
10613
|
+
## Skills Required
|
|
10614
|
+
|
|
10615
|
+
- github (for API access)
|
|
10616
|
+
\`\`\`
|
|
10617
|
+
|
|
10618
|
+
### Data Pipeline Agent
|
|
10619
|
+
|
|
10620
|
+
\`\`\`markdown
|
|
10621
|
+
# Agent Instructions
|
|
10622
|
+
|
|
10623
|
+
You are a data pipeline agent that processes CSV files.
|
|
10624
|
+
|
|
10625
|
+
## Workflow
|
|
10626
|
+
|
|
10627
|
+
1. Read all CSV files from the input volume
|
|
10628
|
+
2. For each file:
|
|
10629
|
+
- Validate the schema
|
|
10630
|
+
- Clean missing values
|
|
10631
|
+
- Transform dates to ISO format
|
|
10632
|
+
3. Merge all files into \`combined.csv\`
|
|
10633
|
+
4. Generate a summary report
|
|
10634
|
+
|
|
10635
|
+
## Input
|
|
10636
|
+
|
|
10637
|
+
Files are provided via volume mount.
|
|
10638
|
+
|
|
10639
|
+
## Output
|
|
10640
|
+
|
|
10641
|
+
Write results to the artifact directory.
|
|
10642
|
+
\`\`\`
|
|
10643
|
+
|
|
10644
|
+
## Best Practices
|
|
10645
|
+
|
|
10646
|
+
1. **Be Specific**: Vague instructions lead to unpredictable results
|
|
10647
|
+
2. **One Task Per Step**: Keep workflow steps focused and atomic
|
|
10648
|
+
3. **Define Output Clearly**: Specify exact file names and formats
|
|
10649
|
+
4. **Handle Errors**: Include what to do when things go wrong
|
|
10650
|
+
5. **Test Incrementally**: Start with simple workflows, add complexity
|
|
10651
|
+
6. **Use Skills Wisely**: Only include skills the agent actually needs
|
|
10652
|
+
|
|
10653
|
+
## Troubleshooting
|
|
10654
|
+
|
|
10655
|
+
### Agent doesn't follow instructions
|
|
10656
|
+
- Make instructions more specific and explicit
|
|
10657
|
+
- Add examples of expected behavior
|
|
10658
|
+
- Break complex steps into smaller sub-steps
|
|
10659
|
+
|
|
10660
|
+
### Agent uses wrong tools
|
|
10661
|
+
- Specify which tools/skills to use for each step
|
|
10662
|
+
- Add constraints about what NOT to do
|
|
10663
|
+
|
|
10664
|
+
### Output format is wrong
|
|
10665
|
+
- Provide exact templates for output files
|
|
10666
|
+
- Include example output in the instructions
|
|
10667
|
+
`;
|
|
10668
|
+
var setupClaudeCommand = new Command46().name("setup-claude").description("Add/update Claude skill for agent building").action(async () => {
|
|
10669
|
+
console.log(chalk46.dim("Installing vm0-agent-builder skill..."));
|
|
10670
|
+
await mkdir7(SKILL_DIR, { recursive: true });
|
|
10671
|
+
await writeFile7(path14.join(SKILL_DIR, "SKILL.md"), SKILL_CONTENT);
|
|
10672
|
+
console.log(
|
|
10673
|
+
chalk46.green(`Done Installed vm0-agent-builder skill to ${SKILL_DIR}`)
|
|
10674
|
+
);
|
|
10675
|
+
console.log();
|
|
10676
|
+
console.log("Next step:");
|
|
10677
|
+
console.log(
|
|
10678
|
+
chalk46.cyan(
|
|
10679
|
+
' claude /vm0-agent-builder "I want to build an agent that..."'
|
|
10680
|
+
)
|
|
10681
|
+
);
|
|
10682
|
+
});
|
|
10683
|
+
|
|
10684
|
+
// src/commands/onboard.ts
|
|
10685
|
+
var DEMO_AGENT_DIR = "vm0-demo-agent";
|
|
10686
|
+
var DEMO_AGENT_NAME = "vm0-demo-agent";
|
|
10687
|
+
var onboardCommand = new Command47().name("onboard").description("Guided setup for new VM0 users").option("-y, --yes", "Skip confirmation prompts").option(
|
|
10688
|
+
"--method <method>",
|
|
10689
|
+
"Agent building method: claude or manual",
|
|
10690
|
+
void 0
|
|
10691
|
+
).action(async (options) => {
|
|
10692
|
+
const token = await getToken();
|
|
10693
|
+
if (token) {
|
|
10694
|
+
console.log(chalk47.green("Done Authenticated"));
|
|
10695
|
+
} else {
|
|
10696
|
+
console.log(chalk47.dim("Authentication required..."));
|
|
10697
|
+
console.log();
|
|
10698
|
+
await loginCommand.parseAsync([], { from: "user" });
|
|
10699
|
+
}
|
|
10700
|
+
try {
|
|
10701
|
+
const result = await listModelProviders();
|
|
10702
|
+
if (result.modelProviders.length > 0) {
|
|
10703
|
+
console.log(chalk47.green("Done Model provider configured"));
|
|
10704
|
+
} else {
|
|
10705
|
+
console.log(chalk47.dim("Model provider setup required..."));
|
|
10706
|
+
console.log();
|
|
10707
|
+
await setupCommand2.parseAsync([], { from: "user" });
|
|
10708
|
+
}
|
|
10709
|
+
} catch {
|
|
10710
|
+
console.log(chalk47.dim("Setting up model provider..."));
|
|
10711
|
+
console.log();
|
|
10712
|
+
await setupCommand2.parseAsync([], { from: "user" });
|
|
10713
|
+
}
|
|
10714
|
+
let createAgent = options.yes;
|
|
10715
|
+
if (!createAgent && isInteractive()) {
|
|
10716
|
+
const response = await prompts3(
|
|
10717
|
+
{
|
|
10718
|
+
type: "confirm",
|
|
10719
|
+
name: "create",
|
|
10720
|
+
message: `Create ${DEMO_AGENT_DIR}?`,
|
|
10721
|
+
initial: true
|
|
10722
|
+
},
|
|
10723
|
+
{ onCancel: () => process.exit(0) }
|
|
10724
|
+
);
|
|
10725
|
+
createAgent = response.create;
|
|
10726
|
+
}
|
|
10727
|
+
if (!createAgent) {
|
|
10728
|
+
console.log(chalk47.dim("Skipped agent creation"));
|
|
10729
|
+
return;
|
|
10730
|
+
}
|
|
10731
|
+
if (existsSync10(DEMO_AGENT_DIR)) {
|
|
10732
|
+
console.log(chalk47.red(`x ${DEMO_AGENT_DIR}/ already exists`));
|
|
10733
|
+
console.log();
|
|
10734
|
+
console.log("Remove it first or use a different directory:");
|
|
10735
|
+
console.log(chalk47.cyan(` rm -rf ${DEMO_AGENT_DIR}`));
|
|
10736
|
+
process.exit(1);
|
|
10737
|
+
}
|
|
10738
|
+
await mkdir8(DEMO_AGENT_DIR, { recursive: true });
|
|
10739
|
+
const originalDir = process.cwd();
|
|
10740
|
+
process.chdir(DEMO_AGENT_DIR);
|
|
10741
|
+
try {
|
|
10742
|
+
await initCommand3.parseAsync(["--name", DEMO_AGENT_NAME], {
|
|
10743
|
+
from: "user"
|
|
10744
|
+
});
|
|
10745
|
+
} finally {
|
|
10746
|
+
process.chdir(originalDir);
|
|
10747
|
+
}
|
|
10748
|
+
console.log();
|
|
10749
|
+
let method = options.method;
|
|
10750
|
+
if (!method && isInteractive()) {
|
|
10751
|
+
const response = await prompts3(
|
|
10752
|
+
{
|
|
10753
|
+
type: "select",
|
|
10754
|
+
name: "method",
|
|
10755
|
+
message: "How would you like to build your agent?",
|
|
10756
|
+
choices: [
|
|
10757
|
+
{
|
|
10758
|
+
title: "Use `vm0 setup-claude` to let Claude help (Recommended)",
|
|
10759
|
+
value: "claude"
|
|
10760
|
+
},
|
|
10761
|
+
{
|
|
10762
|
+
title: "I will do it myself (Edit `AGENTS.md` and `vm0.yaml`)",
|
|
10763
|
+
value: "manual"
|
|
10764
|
+
}
|
|
10765
|
+
]
|
|
10766
|
+
},
|
|
10767
|
+
{ onCancel: () => process.exit(0) }
|
|
10768
|
+
);
|
|
10769
|
+
method = response.method;
|
|
10770
|
+
}
|
|
10771
|
+
if (method === "claude") {
|
|
10772
|
+
process.chdir(DEMO_AGENT_DIR);
|
|
10773
|
+
try {
|
|
10774
|
+
await setupClaudeCommand.parseAsync([], { from: "user" });
|
|
10775
|
+
} finally {
|
|
10776
|
+
process.chdir(originalDir);
|
|
10777
|
+
}
|
|
10778
|
+
} else {
|
|
10779
|
+
console.log("Next steps:");
|
|
10780
|
+
console.log(` 1. ${chalk47.cyan(`cd ${DEMO_AGENT_DIR}`)}`);
|
|
10781
|
+
console.log(
|
|
10782
|
+
` 2. Edit ${chalk47.cyan("AGENTS.md")} to define your agent's workflow`
|
|
10783
|
+
);
|
|
10784
|
+
console.log(` 3. Edit ${chalk47.cyan("vm0.yaml")} to configure skills`);
|
|
10785
|
+
console.log(` 4. Run ${chalk47.cyan('vm0 cook "start working"')} to test`);
|
|
10786
|
+
}
|
|
10787
|
+
});
|
|
10557
10788
|
|
|
10558
10789
|
// src/index.ts
|
|
10559
|
-
var program = new
|
|
10560
|
-
program.name("vm0").description("VM0 CLI - Build and run agents with natural language").version("9.
|
|
10790
|
+
var program = new Command48();
|
|
10791
|
+
program.name("vm0").description("VM0 CLI - Build and run agents with natural language").version("9.2.0");
|
|
10561
10792
|
program.command("info").description("Display environment information").action(async () => {
|
|
10562
|
-
console.log(
|
|
10793
|
+
console.log(chalk48.bold("System Information:"));
|
|
10563
10794
|
console.log(`Node Version: ${process.version}`);
|
|
10564
10795
|
console.log(`Platform: ${process.platform}`);
|
|
10565
10796
|
console.log(`Architecture: ${process.arch}`);
|
|
@@ -10567,9 +10798,7 @@ program.command("info").description("Display environment information").action(as
|
|
|
10567
10798
|
console.log(`API Host: ${apiUrl}`);
|
|
10568
10799
|
});
|
|
10569
10800
|
var authCommand = program.command("auth").description("Authenticate vm0");
|
|
10570
|
-
authCommand.
|
|
10571
|
-
await authenticate();
|
|
10572
|
-
});
|
|
10801
|
+
authCommand.addCommand(loginCommand);
|
|
10573
10802
|
authCommand.command("logout").description("Log out of VM0").action(async () => {
|
|
10574
10803
|
await logout();
|
|
10575
10804
|
});
|
|
@@ -10592,6 +10821,8 @@ program.addCommand(scheduleCommand);
|
|
|
10592
10821
|
program.addCommand(usageCommand);
|
|
10593
10822
|
program.addCommand(credentialCommand);
|
|
10594
10823
|
program.addCommand(modelProviderCommand);
|
|
10824
|
+
program.addCommand(onboardCommand);
|
|
10825
|
+
program.addCommand(setupClaudeCommand);
|
|
10595
10826
|
if (process.argv[1]?.endsWith("index.js") || process.argv[1]?.endsWith("index.ts") || process.argv[1]?.endsWith("vm0")) {
|
|
10596
10827
|
program.parse();
|
|
10597
10828
|
}
|