@vm0/runner 2.6.1 → 2.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.js +815 -224
- package/package.json +6 -1
package/index.js
CHANGED
|
@@ -37,6 +37,42 @@ var runnerConfigSchema = z.object({
|
|
|
37
37
|
port: z.number().int().min(1024).max(65535).default(8080)
|
|
38
38
|
}).default({})
|
|
39
39
|
});
|
|
40
|
+
var debugConfigSchema = z.object({
|
|
41
|
+
name: z.string().default("debug-runner"),
|
|
42
|
+
group: z.string().default("debug/local"),
|
|
43
|
+
server: z.object({
|
|
44
|
+
url: z.string().url().default("http://localhost:3000"),
|
|
45
|
+
token: z.string().default("debug-token")
|
|
46
|
+
}).default({}),
|
|
47
|
+
sandbox: z.object({
|
|
48
|
+
max_concurrent: z.number().int().min(1).default(1),
|
|
49
|
+
vcpu: z.number().int().min(1).default(2),
|
|
50
|
+
memory_mb: z.number().int().min(128).default(2048),
|
|
51
|
+
poll_interval_ms: z.number().int().min(1e3).default(5e3)
|
|
52
|
+
}).default({}),
|
|
53
|
+
firecracker: z.object({
|
|
54
|
+
binary: z.string().min(1, "Firecracker binary path is required"),
|
|
55
|
+
kernel: z.string().min(1, "Kernel path is required"),
|
|
56
|
+
rootfs: z.string().min(1, "Rootfs path is required")
|
|
57
|
+
}),
|
|
58
|
+
proxy: z.object({
|
|
59
|
+
port: z.number().int().min(1024).max(65535).default(8080)
|
|
60
|
+
}).default({})
|
|
61
|
+
});
|
|
62
|
+
function loadDebugConfig(configPath) {
|
|
63
|
+
if (!fs.existsSync(configPath)) {
|
|
64
|
+
throw new Error(`Config file not found: ${configPath}`);
|
|
65
|
+
}
|
|
66
|
+
const content = fs.readFileSync(configPath, "utf-8");
|
|
67
|
+
const raw = yaml.parse(content);
|
|
68
|
+
const result = debugConfigSchema.safeParse(raw);
|
|
69
|
+
if (!result.success) {
|
|
70
|
+
const errors = result.error.errors.map((e) => ` - ${e.path.join(".")}: ${e.message}`).join("\n");
|
|
71
|
+
throw new Error(`Invalid configuration:
|
|
72
|
+
${errors}`);
|
|
73
|
+
}
|
|
74
|
+
return result.data;
|
|
75
|
+
}
|
|
40
76
|
function loadConfig(configPath) {
|
|
41
77
|
if (!fs.existsSync(configPath)) {
|
|
42
78
|
throw new Error(`runner.yaml not found: ${configPath}`);
|
|
@@ -142,7 +178,7 @@ import path4 from "path";
|
|
|
142
178
|
import fs6 from "fs";
|
|
143
179
|
|
|
144
180
|
// src/lib/firecracker/vm.ts
|
|
145
|
-
import { spawn } from "child_process";
|
|
181
|
+
import { execSync as execSync2, spawn } from "child_process";
|
|
146
182
|
import fs2 from "fs";
|
|
147
183
|
import path from "path";
|
|
148
184
|
import readline from "readline";
|
|
@@ -545,13 +581,13 @@ var FirecrackerVM = class {
|
|
|
545
581
|
state = "created";
|
|
546
582
|
workDir;
|
|
547
583
|
socketPath;
|
|
548
|
-
|
|
549
|
-
// Per-VM
|
|
584
|
+
vmOverlayPath;
|
|
585
|
+
// Per-VM sparse overlay for writes
|
|
550
586
|
constructor(config) {
|
|
551
587
|
this.config = config;
|
|
552
588
|
this.workDir = config.workDir || `/tmp/vm0-vm-${config.vmId}`;
|
|
553
589
|
this.socketPath = path.join(this.workDir, "firecracker.sock");
|
|
554
|
-
this.
|
|
590
|
+
this.vmOverlayPath = path.join(this.workDir, "overlay.ext4");
|
|
555
591
|
}
|
|
556
592
|
/**
|
|
557
593
|
* Get current VM state
|
|
@@ -590,8 +626,12 @@ var FirecrackerVM = class {
|
|
|
590
626
|
if (fs2.existsSync(this.socketPath)) {
|
|
591
627
|
fs2.unlinkSync(this.socketPath);
|
|
592
628
|
}
|
|
593
|
-
console.log(`[VM ${this.config.vmId}]
|
|
594
|
-
|
|
629
|
+
console.log(`[VM ${this.config.vmId}] Creating sparse overlay file...`);
|
|
630
|
+
const overlaySize = 2 * 1024 * 1024 * 1024;
|
|
631
|
+
const fd = fs2.openSync(this.vmOverlayPath, "w");
|
|
632
|
+
fs2.ftruncateSync(fd, overlaySize);
|
|
633
|
+
fs2.closeSync(fd);
|
|
634
|
+
execSync2(`mkfs.ext4 -F -q "${this.vmOverlayPath}"`, { stdio: "ignore" });
|
|
595
635
|
console.log(`[VM ${this.config.vmId}] Setting up network...`);
|
|
596
636
|
this.networkConfig = await createTapDevice(this.config.vmId);
|
|
597
637
|
console.log(`[VM ${this.config.vmId}] Starting Firecracker...`);
|
|
@@ -668,19 +708,27 @@ var FirecrackerVM = class {
|
|
|
668
708
|
mem_size_mib: this.config.memoryMb
|
|
669
709
|
});
|
|
670
710
|
const networkBootArgs = generateNetworkBootArgs(this.networkConfig);
|
|
671
|
-
const bootArgs = `console=ttyS0 reboot=k panic=1 pci=off ${networkBootArgs}`;
|
|
711
|
+
const bootArgs = `console=ttyS0 reboot=k panic=1 pci=off init=/sbin/overlay-init ${networkBootArgs}`;
|
|
672
712
|
console.log(`[VM ${this.config.vmId}] Boot args: ${bootArgs}`);
|
|
673
713
|
await this.client.setBootSource({
|
|
674
714
|
kernel_image_path: this.config.kernelPath,
|
|
675
715
|
boot_args: bootArgs
|
|
676
716
|
});
|
|
677
|
-
console.log(
|
|
717
|
+
console.log(
|
|
718
|
+
`[VM ${this.config.vmId}] Base rootfs: ${this.config.rootfsPath}`
|
|
719
|
+
);
|
|
678
720
|
await this.client.setDrive({
|
|
679
721
|
drive_id: "rootfs",
|
|
680
|
-
path_on_host: this.
|
|
722
|
+
path_on_host: this.config.rootfsPath,
|
|
681
723
|
is_root_device: true,
|
|
724
|
+
is_read_only: true
|
|
725
|
+
});
|
|
726
|
+
console.log(`[VM ${this.config.vmId}] Overlay: ${this.vmOverlayPath}`);
|
|
727
|
+
await this.client.setDrive({
|
|
728
|
+
drive_id: "overlay",
|
|
729
|
+
path_on_host: this.vmOverlayPath,
|
|
730
|
+
is_root_device: false,
|
|
682
731
|
is_read_only: false
|
|
683
|
-
// Need write access for agent execution
|
|
684
732
|
});
|
|
685
733
|
console.log(
|
|
686
734
|
`[VM ${this.config.vmId}] Network: ${this.networkConfig.tapDevice}`
|
|
@@ -770,7 +818,7 @@ var FirecrackerVM = class {
|
|
|
770
818
|
};
|
|
771
819
|
|
|
772
820
|
// src/lib/firecracker/guest.ts
|
|
773
|
-
import { exec as exec2, execSync as
|
|
821
|
+
import { exec as exec2, execSync as execSync3 } from "child_process";
|
|
774
822
|
import { promisify as promisify2 } from "util";
|
|
775
823
|
import fs3 from "fs";
|
|
776
824
|
import path2 from "path";
|
|
@@ -6239,9 +6287,207 @@ var checkpointsByIdContract = c10.router({
|
|
|
6239
6287
|
}
|
|
6240
6288
|
});
|
|
6241
6289
|
|
|
6242
|
-
// ../../packages/core/src/contracts/
|
|
6290
|
+
// ../../packages/core/src/contracts/schedules.ts
|
|
6243
6291
|
import { z as z15 } from "zod";
|
|
6244
|
-
var
|
|
6292
|
+
var c11 = initContract();
|
|
6293
|
+
var scheduleTriggerSchema = z15.object({
|
|
6294
|
+
cron: z15.string().optional(),
|
|
6295
|
+
at: z15.string().optional(),
|
|
6296
|
+
timezone: z15.string().default("UTC")
|
|
6297
|
+
}).refine((data) => data.cron && !data.at || !data.cron && data.at, {
|
|
6298
|
+
message: "Exactly one of 'cron' or 'at' must be specified"
|
|
6299
|
+
});
|
|
6300
|
+
var scheduleRunConfigSchema = z15.object({
|
|
6301
|
+
agent: z15.string().min(1, "Agent reference required"),
|
|
6302
|
+
prompt: z15.string().min(1, "Prompt required"),
|
|
6303
|
+
vars: z15.record(z15.string(), z15.string()).optional(),
|
|
6304
|
+
secrets: z15.record(z15.string(), z15.string()).optional(),
|
|
6305
|
+
artifactName: z15.string().optional(),
|
|
6306
|
+
artifactVersion: z15.string().optional(),
|
|
6307
|
+
volumeVersions: z15.record(z15.string(), z15.string()).optional()
|
|
6308
|
+
});
|
|
6309
|
+
var scheduleDefinitionSchema = z15.object({
|
|
6310
|
+
on: scheduleTriggerSchema,
|
|
6311
|
+
run: scheduleRunConfigSchema
|
|
6312
|
+
});
|
|
6313
|
+
var scheduleYamlSchema = z15.object({
|
|
6314
|
+
version: z15.literal("1.0"),
|
|
6315
|
+
schedules: z15.record(z15.string(), scheduleDefinitionSchema)
|
|
6316
|
+
});
|
|
6317
|
+
var deployScheduleRequestSchema = z15.object({
|
|
6318
|
+
name: z15.string().min(1).max(64, "Schedule name max 64 chars"),
|
|
6319
|
+
cronExpression: z15.string().optional(),
|
|
6320
|
+
atTime: z15.string().optional(),
|
|
6321
|
+
timezone: z15.string().default("UTC"),
|
|
6322
|
+
prompt: z15.string().min(1, "Prompt required"),
|
|
6323
|
+
vars: z15.record(z15.string(), z15.string()).optional(),
|
|
6324
|
+
secrets: z15.record(z15.string(), z15.string()).optional(),
|
|
6325
|
+
artifactName: z15.string().optional(),
|
|
6326
|
+
artifactVersion: z15.string().optional(),
|
|
6327
|
+
volumeVersions: z15.record(z15.string(), z15.string()).optional(),
|
|
6328
|
+
// Resolved agent compose ID (CLI resolves scope/name:version → composeId)
|
|
6329
|
+
composeId: z15.string().uuid("Invalid compose ID")
|
|
6330
|
+
}).refine(
|
|
6331
|
+
(data) => data.cronExpression && !data.atTime || !data.cronExpression && data.atTime,
|
|
6332
|
+
{
|
|
6333
|
+
message: "Exactly one of 'cronExpression' or 'atTime' must be specified"
|
|
6334
|
+
}
|
|
6335
|
+
);
|
|
6336
|
+
var scheduleResponseSchema = z15.object({
|
|
6337
|
+
id: z15.string().uuid(),
|
|
6338
|
+
composeId: z15.string().uuid(),
|
|
6339
|
+
composeName: z15.string(),
|
|
6340
|
+
scopeSlug: z15.string(),
|
|
6341
|
+
name: z15.string(),
|
|
6342
|
+
cronExpression: z15.string().nullable(),
|
|
6343
|
+
atTime: z15.string().nullable(),
|
|
6344
|
+
timezone: z15.string(),
|
|
6345
|
+
prompt: z15.string(),
|
|
6346
|
+
vars: z15.record(z15.string(), z15.string()).nullable(),
|
|
6347
|
+
// Secret names only (values are never returned)
|
|
6348
|
+
secretNames: z15.array(z15.string()).nullable(),
|
|
6349
|
+
artifactName: z15.string().nullable(),
|
|
6350
|
+
artifactVersion: z15.string().nullable(),
|
|
6351
|
+
volumeVersions: z15.record(z15.string(), z15.string()).nullable(),
|
|
6352
|
+
enabled: z15.boolean(),
|
|
6353
|
+
nextRunAt: z15.string().nullable(),
|
|
6354
|
+
lastRunAt: z15.string().nullable(),
|
|
6355
|
+
lastRunId: z15.string().nullable(),
|
|
6356
|
+
createdAt: z15.string(),
|
|
6357
|
+
updatedAt: z15.string()
|
|
6358
|
+
});
|
|
6359
|
+
var scheduleListResponseSchema = z15.object({
|
|
6360
|
+
schedules: z15.array(scheduleResponseSchema)
|
|
6361
|
+
});
|
|
6362
|
+
var deployScheduleResponseSchema = z15.object({
|
|
6363
|
+
schedule: scheduleResponseSchema,
|
|
6364
|
+
created: z15.boolean()
|
|
6365
|
+
// true if created, false if updated
|
|
6366
|
+
});
|
|
6367
|
+
var schedulesMainContract = c11.router({
|
|
6368
|
+
/**
|
|
6369
|
+
* POST /api/agent/schedules
|
|
6370
|
+
* Deploy (create or update) a schedule
|
|
6371
|
+
*/
|
|
6372
|
+
deploy: {
|
|
6373
|
+
method: "POST",
|
|
6374
|
+
path: "/api/agent/schedules",
|
|
6375
|
+
body: deployScheduleRequestSchema,
|
|
6376
|
+
responses: {
|
|
6377
|
+
200: deployScheduleResponseSchema,
|
|
6378
|
+
// Updated
|
|
6379
|
+
201: deployScheduleResponseSchema,
|
|
6380
|
+
// Created
|
|
6381
|
+
400: apiErrorSchema,
|
|
6382
|
+
401: apiErrorSchema,
|
|
6383
|
+
404: apiErrorSchema,
|
|
6384
|
+
409: apiErrorSchema
|
|
6385
|
+
// Schedule limit reached
|
|
6386
|
+
},
|
|
6387
|
+
summary: "Deploy schedule (create or update)"
|
|
6388
|
+
},
|
|
6389
|
+
/**
|
|
6390
|
+
* GET /api/agent/schedules
|
|
6391
|
+
* List all schedules for the user
|
|
6392
|
+
*/
|
|
6393
|
+
list: {
|
|
6394
|
+
method: "GET",
|
|
6395
|
+
path: "/api/agent/schedules",
|
|
6396
|
+
responses: {
|
|
6397
|
+
200: scheduleListResponseSchema,
|
|
6398
|
+
401: apiErrorSchema
|
|
6399
|
+
},
|
|
6400
|
+
summary: "List all schedules"
|
|
6401
|
+
}
|
|
6402
|
+
});
|
|
6403
|
+
var schedulesByNameContract = c11.router({
|
|
6404
|
+
/**
|
|
6405
|
+
* GET /api/agent/schedules/:name
|
|
6406
|
+
* Get schedule by name
|
|
6407
|
+
*/
|
|
6408
|
+
getByName: {
|
|
6409
|
+
method: "GET",
|
|
6410
|
+
path: "/api/agent/schedules/:name",
|
|
6411
|
+
pathParams: z15.object({
|
|
6412
|
+
name: z15.string().min(1, "Schedule name required")
|
|
6413
|
+
}),
|
|
6414
|
+
query: z15.object({
|
|
6415
|
+
composeId: z15.string().uuid("Compose ID required")
|
|
6416
|
+
}),
|
|
6417
|
+
responses: {
|
|
6418
|
+
200: scheduleResponseSchema,
|
|
6419
|
+
401: apiErrorSchema,
|
|
6420
|
+
404: apiErrorSchema
|
|
6421
|
+
},
|
|
6422
|
+
summary: "Get schedule by name"
|
|
6423
|
+
},
|
|
6424
|
+
/**
|
|
6425
|
+
* DELETE /api/agent/schedules/:name
|
|
6426
|
+
* Delete schedule by name
|
|
6427
|
+
*/
|
|
6428
|
+
delete: {
|
|
6429
|
+
method: "DELETE",
|
|
6430
|
+
path: "/api/agent/schedules/:name",
|
|
6431
|
+
pathParams: z15.object({
|
|
6432
|
+
name: z15.string().min(1, "Schedule name required")
|
|
6433
|
+
}),
|
|
6434
|
+
query: z15.object({
|
|
6435
|
+
composeId: z15.string().uuid("Compose ID required")
|
|
6436
|
+
}),
|
|
6437
|
+
responses: {
|
|
6438
|
+
204: z15.undefined(),
|
|
6439
|
+
401: apiErrorSchema,
|
|
6440
|
+
404: apiErrorSchema
|
|
6441
|
+
},
|
|
6442
|
+
summary: "Delete schedule"
|
|
6443
|
+
}
|
|
6444
|
+
});
|
|
6445
|
+
var schedulesEnableContract = c11.router({
|
|
6446
|
+
/**
|
|
6447
|
+
* POST /api/agent/schedules/:name/enable
|
|
6448
|
+
* Enable a disabled schedule
|
|
6449
|
+
*/
|
|
6450
|
+
enable: {
|
|
6451
|
+
method: "POST",
|
|
6452
|
+
path: "/api/agent/schedules/:name/enable",
|
|
6453
|
+
pathParams: z15.object({
|
|
6454
|
+
name: z15.string().min(1, "Schedule name required")
|
|
6455
|
+
}),
|
|
6456
|
+
body: z15.object({
|
|
6457
|
+
composeId: z15.string().uuid("Compose ID required")
|
|
6458
|
+
}),
|
|
6459
|
+
responses: {
|
|
6460
|
+
200: scheduleResponseSchema,
|
|
6461
|
+
401: apiErrorSchema,
|
|
6462
|
+
404: apiErrorSchema
|
|
6463
|
+
},
|
|
6464
|
+
summary: "Enable schedule"
|
|
6465
|
+
},
|
|
6466
|
+
/**
|
|
6467
|
+
* POST /api/agent/schedules/:name/disable
|
|
6468
|
+
* Disable an enabled schedule
|
|
6469
|
+
*/
|
|
6470
|
+
disable: {
|
|
6471
|
+
method: "POST",
|
|
6472
|
+
path: "/api/agent/schedules/:name/disable",
|
|
6473
|
+
pathParams: z15.object({
|
|
6474
|
+
name: z15.string().min(1, "Schedule name required")
|
|
6475
|
+
}),
|
|
6476
|
+
body: z15.object({
|
|
6477
|
+
composeId: z15.string().uuid("Compose ID required")
|
|
6478
|
+
}),
|
|
6479
|
+
responses: {
|
|
6480
|
+
200: scheduleResponseSchema,
|
|
6481
|
+
401: apiErrorSchema,
|
|
6482
|
+
404: apiErrorSchema
|
|
6483
|
+
},
|
|
6484
|
+
summary: "Disable schedule"
|
|
6485
|
+
}
|
|
6486
|
+
});
|
|
6487
|
+
|
|
6488
|
+
// ../../packages/core/src/contracts/public/common.ts
|
|
6489
|
+
import { z as z16 } from "zod";
|
|
6490
|
+
var publicApiErrorTypeSchema = z16.enum([
|
|
6245
6491
|
"api_error",
|
|
6246
6492
|
// Internal server error (5xx)
|
|
6247
6493
|
"invalid_request_error",
|
|
@@ -6253,55 +6499,55 @@ var publicApiErrorTypeSchema = z15.enum([
|
|
|
6253
6499
|
"conflict_error"
|
|
6254
6500
|
// Resource conflict (409)
|
|
6255
6501
|
]);
|
|
6256
|
-
var publicApiErrorSchema =
|
|
6257
|
-
error:
|
|
6502
|
+
var publicApiErrorSchema = z16.object({
|
|
6503
|
+
error: z16.object({
|
|
6258
6504
|
type: publicApiErrorTypeSchema,
|
|
6259
|
-
code:
|
|
6260
|
-
message:
|
|
6261
|
-
param:
|
|
6262
|
-
doc_url:
|
|
6505
|
+
code: z16.string(),
|
|
6506
|
+
message: z16.string(),
|
|
6507
|
+
param: z16.string().optional(),
|
|
6508
|
+
doc_url: z16.string().url().optional()
|
|
6263
6509
|
})
|
|
6264
6510
|
});
|
|
6265
|
-
var paginationSchema =
|
|
6266
|
-
has_more:
|
|
6267
|
-
next_cursor:
|
|
6511
|
+
var paginationSchema = z16.object({
|
|
6512
|
+
has_more: z16.boolean(),
|
|
6513
|
+
next_cursor: z16.string().nullable()
|
|
6268
6514
|
});
|
|
6269
6515
|
function createPaginatedResponseSchema(dataSchema) {
|
|
6270
|
-
return
|
|
6271
|
-
data:
|
|
6516
|
+
return z16.object({
|
|
6517
|
+
data: z16.array(dataSchema),
|
|
6272
6518
|
pagination: paginationSchema
|
|
6273
6519
|
});
|
|
6274
6520
|
}
|
|
6275
|
-
var listQuerySchema =
|
|
6276
|
-
cursor:
|
|
6277
|
-
limit:
|
|
6521
|
+
var listQuerySchema = z16.object({
|
|
6522
|
+
cursor: z16.string().optional(),
|
|
6523
|
+
limit: z16.coerce.number().min(1).max(100).default(20)
|
|
6278
6524
|
});
|
|
6279
|
-
var requestIdSchema =
|
|
6280
|
-
var timestampSchema =
|
|
6525
|
+
var requestIdSchema = z16.string().uuid();
|
|
6526
|
+
var timestampSchema = z16.string().datetime();
|
|
6281
6527
|
|
|
6282
6528
|
// ../../packages/core/src/contracts/public/agents.ts
|
|
6283
|
-
import { z as
|
|
6284
|
-
var
|
|
6285
|
-
var publicAgentSchema =
|
|
6286
|
-
id:
|
|
6287
|
-
name:
|
|
6288
|
-
current_version_id:
|
|
6529
|
+
import { z as z17 } from "zod";
|
|
6530
|
+
var c12 = initContract();
|
|
6531
|
+
var publicAgentSchema = z17.object({
|
|
6532
|
+
id: z17.string(),
|
|
6533
|
+
name: z17.string(),
|
|
6534
|
+
current_version_id: z17.string().nullable(),
|
|
6289
6535
|
created_at: timestampSchema,
|
|
6290
6536
|
updated_at: timestampSchema
|
|
6291
6537
|
});
|
|
6292
|
-
var agentVersionSchema =
|
|
6293
|
-
id:
|
|
6294
|
-
agent_id:
|
|
6295
|
-
version_number:
|
|
6538
|
+
var agentVersionSchema = z17.object({
|
|
6539
|
+
id: z17.string(),
|
|
6540
|
+
agent_id: z17.string(),
|
|
6541
|
+
version_number: z17.number(),
|
|
6296
6542
|
created_at: timestampSchema
|
|
6297
6543
|
});
|
|
6298
6544
|
var publicAgentDetailSchema = publicAgentSchema;
|
|
6299
6545
|
var paginatedAgentsSchema = createPaginatedResponseSchema(publicAgentSchema);
|
|
6300
6546
|
var paginatedAgentVersionsSchema = createPaginatedResponseSchema(agentVersionSchema);
|
|
6301
6547
|
var agentListQuerySchema = listQuerySchema.extend({
|
|
6302
|
-
name:
|
|
6548
|
+
name: z17.string().optional()
|
|
6303
6549
|
});
|
|
6304
|
-
var publicAgentsListContract =
|
|
6550
|
+
var publicAgentsListContract = c12.router({
|
|
6305
6551
|
list: {
|
|
6306
6552
|
method: "GET",
|
|
6307
6553
|
path: "/v1/agents",
|
|
@@ -6315,12 +6561,12 @@ var publicAgentsListContract = c11.router({
|
|
|
6315
6561
|
description: "List all agents in the current scope with pagination. Use the `name` query parameter to filter by agent name."
|
|
6316
6562
|
}
|
|
6317
6563
|
});
|
|
6318
|
-
var publicAgentByIdContract =
|
|
6564
|
+
var publicAgentByIdContract = c12.router({
|
|
6319
6565
|
get: {
|
|
6320
6566
|
method: "GET",
|
|
6321
6567
|
path: "/v1/agents/:id",
|
|
6322
|
-
pathParams:
|
|
6323
|
-
id:
|
|
6568
|
+
pathParams: z17.object({
|
|
6569
|
+
id: z17.string().min(1, "Agent ID is required")
|
|
6324
6570
|
}),
|
|
6325
6571
|
responses: {
|
|
6326
6572
|
200: publicAgentDetailSchema,
|
|
@@ -6332,12 +6578,12 @@ var publicAgentByIdContract = c11.router({
|
|
|
6332
6578
|
description: "Get agent details by ID"
|
|
6333
6579
|
}
|
|
6334
6580
|
});
|
|
6335
|
-
var publicAgentVersionsContract =
|
|
6581
|
+
var publicAgentVersionsContract = c12.router({
|
|
6336
6582
|
list: {
|
|
6337
6583
|
method: "GET",
|
|
6338
6584
|
path: "/v1/agents/:id/versions",
|
|
6339
|
-
pathParams:
|
|
6340
|
-
id:
|
|
6585
|
+
pathParams: z17.object({
|
|
6586
|
+
id: z17.string().min(1, "Agent ID is required")
|
|
6341
6587
|
}),
|
|
6342
6588
|
query: listQuerySchema,
|
|
6343
6589
|
responses: {
|
|
@@ -6352,9 +6598,9 @@ var publicAgentVersionsContract = c11.router({
|
|
|
6352
6598
|
});
|
|
6353
6599
|
|
|
6354
6600
|
// ../../packages/core/src/contracts/public/runs.ts
|
|
6355
|
-
import { z as
|
|
6356
|
-
var
|
|
6357
|
-
var publicRunStatusSchema =
|
|
6601
|
+
import { z as z18 } from "zod";
|
|
6602
|
+
var c13 = initContract();
|
|
6603
|
+
var publicRunStatusSchema = z18.enum([
|
|
6358
6604
|
"pending",
|
|
6359
6605
|
"running",
|
|
6360
6606
|
"completed",
|
|
@@ -6362,56 +6608,56 @@ var publicRunStatusSchema = z17.enum([
|
|
|
6362
6608
|
"timeout",
|
|
6363
6609
|
"cancelled"
|
|
6364
6610
|
]);
|
|
6365
|
-
var publicRunSchema =
|
|
6366
|
-
id:
|
|
6367
|
-
agent_id:
|
|
6368
|
-
agent_name:
|
|
6611
|
+
var publicRunSchema = z18.object({
|
|
6612
|
+
id: z18.string(),
|
|
6613
|
+
agent_id: z18.string(),
|
|
6614
|
+
agent_name: z18.string(),
|
|
6369
6615
|
status: publicRunStatusSchema,
|
|
6370
|
-
prompt:
|
|
6616
|
+
prompt: z18.string(),
|
|
6371
6617
|
created_at: timestampSchema,
|
|
6372
6618
|
started_at: timestampSchema.nullable(),
|
|
6373
6619
|
completed_at: timestampSchema.nullable()
|
|
6374
6620
|
});
|
|
6375
6621
|
var publicRunDetailSchema = publicRunSchema.extend({
|
|
6376
|
-
error:
|
|
6377
|
-
execution_time_ms:
|
|
6378
|
-
checkpoint_id:
|
|
6379
|
-
session_id:
|
|
6380
|
-
artifact_name:
|
|
6381
|
-
artifact_version:
|
|
6382
|
-
volumes:
|
|
6622
|
+
error: z18.string().nullable(),
|
|
6623
|
+
execution_time_ms: z18.number().nullable(),
|
|
6624
|
+
checkpoint_id: z18.string().nullable(),
|
|
6625
|
+
session_id: z18.string().nullable(),
|
|
6626
|
+
artifact_name: z18.string().nullable(),
|
|
6627
|
+
artifact_version: z18.string().nullable(),
|
|
6628
|
+
volumes: z18.record(z18.string(), z18.string()).optional()
|
|
6383
6629
|
});
|
|
6384
6630
|
var paginatedRunsSchema = createPaginatedResponseSchema(publicRunSchema);
|
|
6385
|
-
var createRunRequestSchema =
|
|
6631
|
+
var createRunRequestSchema = z18.object({
|
|
6386
6632
|
// Agent identification (one of: agent, agent_id, session_id, checkpoint_id)
|
|
6387
|
-
agent:
|
|
6633
|
+
agent: z18.string().optional(),
|
|
6388
6634
|
// Agent name
|
|
6389
|
-
agent_id:
|
|
6635
|
+
agent_id: z18.string().optional(),
|
|
6390
6636
|
// Agent ID
|
|
6391
|
-
agent_version:
|
|
6637
|
+
agent_version: z18.string().optional(),
|
|
6392
6638
|
// Version specifier (e.g., "latest", "v1", specific ID)
|
|
6393
6639
|
// Continue session
|
|
6394
|
-
session_id:
|
|
6640
|
+
session_id: z18.string().optional(),
|
|
6395
6641
|
// Resume from checkpoint
|
|
6396
|
-
checkpoint_id:
|
|
6642
|
+
checkpoint_id: z18.string().optional(),
|
|
6397
6643
|
// Required
|
|
6398
|
-
prompt:
|
|
6644
|
+
prompt: z18.string().min(1, "Prompt is required"),
|
|
6399
6645
|
// Optional configuration
|
|
6400
|
-
variables:
|
|
6401
|
-
secrets:
|
|
6402
|
-
artifact_name:
|
|
6646
|
+
variables: z18.record(z18.string(), z18.string()).optional(),
|
|
6647
|
+
secrets: z18.record(z18.string(), z18.string()).optional(),
|
|
6648
|
+
artifact_name: z18.string().optional(),
|
|
6403
6649
|
// Artifact name to mount
|
|
6404
|
-
artifact_version:
|
|
6650
|
+
artifact_version: z18.string().optional(),
|
|
6405
6651
|
// Artifact version (defaults to latest)
|
|
6406
|
-
volumes:
|
|
6652
|
+
volumes: z18.record(z18.string(), z18.string()).optional()
|
|
6407
6653
|
// volume_name -> version
|
|
6408
6654
|
});
|
|
6409
6655
|
var runListQuerySchema = listQuerySchema.extend({
|
|
6410
|
-
agent_id:
|
|
6656
|
+
agent_id: z18.string().optional(),
|
|
6411
6657
|
status: publicRunStatusSchema.optional(),
|
|
6412
6658
|
since: timestampSchema.optional()
|
|
6413
6659
|
});
|
|
6414
|
-
var publicRunsListContract =
|
|
6660
|
+
var publicRunsListContract = c13.router({
|
|
6415
6661
|
list: {
|
|
6416
6662
|
method: "GET",
|
|
6417
6663
|
path: "/v1/runs",
|
|
@@ -6440,12 +6686,12 @@ var publicRunsListContract = c12.router({
|
|
|
6440
6686
|
description: "Create and execute a new agent run. Returns 202 Accepted as runs execute asynchronously."
|
|
6441
6687
|
}
|
|
6442
6688
|
});
|
|
6443
|
-
var publicRunByIdContract =
|
|
6689
|
+
var publicRunByIdContract = c13.router({
|
|
6444
6690
|
get: {
|
|
6445
6691
|
method: "GET",
|
|
6446
6692
|
path: "/v1/runs/:id",
|
|
6447
|
-
pathParams:
|
|
6448
|
-
id:
|
|
6693
|
+
pathParams: z18.object({
|
|
6694
|
+
id: z18.string().min(1, "Run ID is required")
|
|
6449
6695
|
}),
|
|
6450
6696
|
responses: {
|
|
6451
6697
|
200: publicRunDetailSchema,
|
|
@@ -6457,14 +6703,14 @@ var publicRunByIdContract = c12.router({
|
|
|
6457
6703
|
description: "Get run details by ID"
|
|
6458
6704
|
}
|
|
6459
6705
|
});
|
|
6460
|
-
var publicRunCancelContract =
|
|
6706
|
+
var publicRunCancelContract = c13.router({
|
|
6461
6707
|
cancel: {
|
|
6462
6708
|
method: "POST",
|
|
6463
6709
|
path: "/v1/runs/:id/cancel",
|
|
6464
|
-
pathParams:
|
|
6465
|
-
id:
|
|
6710
|
+
pathParams: z18.object({
|
|
6711
|
+
id: z18.string().min(1, "Run ID is required")
|
|
6466
6712
|
}),
|
|
6467
|
-
body:
|
|
6713
|
+
body: z18.undefined(),
|
|
6468
6714
|
responses: {
|
|
6469
6715
|
200: publicRunDetailSchema,
|
|
6470
6716
|
400: publicApiErrorSchema,
|
|
@@ -6477,26 +6723,26 @@ var publicRunCancelContract = c12.router({
|
|
|
6477
6723
|
description: "Cancel a pending or running execution"
|
|
6478
6724
|
}
|
|
6479
6725
|
});
|
|
6480
|
-
var logEntrySchema =
|
|
6726
|
+
var logEntrySchema = z18.object({
|
|
6481
6727
|
timestamp: timestampSchema,
|
|
6482
|
-
type:
|
|
6483
|
-
level:
|
|
6484
|
-
message:
|
|
6485
|
-
metadata:
|
|
6728
|
+
type: z18.enum(["agent", "system", "network"]),
|
|
6729
|
+
level: z18.enum(["debug", "info", "warn", "error"]),
|
|
6730
|
+
message: z18.string(),
|
|
6731
|
+
metadata: z18.record(z18.string(), z18.unknown()).optional()
|
|
6486
6732
|
});
|
|
6487
6733
|
var paginatedLogsSchema = createPaginatedResponseSchema(logEntrySchema);
|
|
6488
6734
|
var logsQuerySchema = listQuerySchema.extend({
|
|
6489
|
-
type:
|
|
6735
|
+
type: z18.enum(["agent", "system", "network", "all"]).default("all"),
|
|
6490
6736
|
since: timestampSchema.optional(),
|
|
6491
6737
|
until: timestampSchema.optional(),
|
|
6492
|
-
order:
|
|
6738
|
+
order: z18.enum(["asc", "desc"]).default("asc")
|
|
6493
6739
|
});
|
|
6494
|
-
var publicRunLogsContract =
|
|
6740
|
+
var publicRunLogsContract = c13.router({
|
|
6495
6741
|
getLogs: {
|
|
6496
6742
|
method: "GET",
|
|
6497
6743
|
path: "/v1/runs/:id/logs",
|
|
6498
|
-
pathParams:
|
|
6499
|
-
id:
|
|
6744
|
+
pathParams: z18.object({
|
|
6745
|
+
id: z18.string().min(1, "Run ID is required")
|
|
6500
6746
|
}),
|
|
6501
6747
|
query: logsQuerySchema,
|
|
6502
6748
|
responses: {
|
|
@@ -6509,29 +6755,29 @@ var publicRunLogsContract = c12.router({
|
|
|
6509
6755
|
description: "Get unified logs for a run. Combines agent, system, and network logs."
|
|
6510
6756
|
}
|
|
6511
6757
|
});
|
|
6512
|
-
var metricPointSchema =
|
|
6758
|
+
var metricPointSchema = z18.object({
|
|
6513
6759
|
timestamp: timestampSchema,
|
|
6514
|
-
cpu_percent:
|
|
6515
|
-
memory_used_mb:
|
|
6516
|
-
memory_total_mb:
|
|
6517
|
-
disk_used_mb:
|
|
6518
|
-
disk_total_mb:
|
|
6519
|
-
});
|
|
6520
|
-
var metricsSummarySchema =
|
|
6521
|
-
avg_cpu_percent:
|
|
6522
|
-
max_memory_used_mb:
|
|
6523
|
-
total_duration_ms:
|
|
6524
|
-
});
|
|
6525
|
-
var metricsResponseSchema2 =
|
|
6526
|
-
data:
|
|
6760
|
+
cpu_percent: z18.number(),
|
|
6761
|
+
memory_used_mb: z18.number(),
|
|
6762
|
+
memory_total_mb: z18.number(),
|
|
6763
|
+
disk_used_mb: z18.number(),
|
|
6764
|
+
disk_total_mb: z18.number()
|
|
6765
|
+
});
|
|
6766
|
+
var metricsSummarySchema = z18.object({
|
|
6767
|
+
avg_cpu_percent: z18.number(),
|
|
6768
|
+
max_memory_used_mb: z18.number(),
|
|
6769
|
+
total_duration_ms: z18.number().nullable()
|
|
6770
|
+
});
|
|
6771
|
+
var metricsResponseSchema2 = z18.object({
|
|
6772
|
+
data: z18.array(metricPointSchema),
|
|
6527
6773
|
summary: metricsSummarySchema
|
|
6528
6774
|
});
|
|
6529
|
-
var publicRunMetricsContract =
|
|
6775
|
+
var publicRunMetricsContract = c13.router({
|
|
6530
6776
|
getMetrics: {
|
|
6531
6777
|
method: "GET",
|
|
6532
6778
|
path: "/v1/runs/:id/metrics",
|
|
6533
|
-
pathParams:
|
|
6534
|
-
id:
|
|
6779
|
+
pathParams: z18.object({
|
|
6780
|
+
id: z18.string().min(1, "Run ID is required")
|
|
6535
6781
|
}),
|
|
6536
6782
|
responses: {
|
|
6537
6783
|
200: metricsResponseSchema2,
|
|
@@ -6543,7 +6789,7 @@ var publicRunMetricsContract = c12.router({
|
|
|
6543
6789
|
description: "Get CPU, memory, and disk metrics for a run"
|
|
6544
6790
|
}
|
|
6545
6791
|
});
|
|
6546
|
-
var sseEventTypeSchema =
|
|
6792
|
+
var sseEventTypeSchema = z18.enum([
|
|
6547
6793
|
"status",
|
|
6548
6794
|
// Run status change
|
|
6549
6795
|
"output",
|
|
@@ -6555,25 +6801,25 @@ var sseEventTypeSchema = z17.enum([
|
|
|
6555
6801
|
"heartbeat"
|
|
6556
6802
|
// Keep-alive
|
|
6557
6803
|
]);
|
|
6558
|
-
var sseEventSchema =
|
|
6804
|
+
var sseEventSchema = z18.object({
|
|
6559
6805
|
event: sseEventTypeSchema,
|
|
6560
|
-
data:
|
|
6561
|
-
id:
|
|
6806
|
+
data: z18.unknown(),
|
|
6807
|
+
id: z18.string().optional()
|
|
6562
6808
|
// For Last-Event-ID reconnection
|
|
6563
6809
|
});
|
|
6564
|
-
var publicRunEventsContract =
|
|
6810
|
+
var publicRunEventsContract = c13.router({
|
|
6565
6811
|
streamEvents: {
|
|
6566
6812
|
method: "GET",
|
|
6567
6813
|
path: "/v1/runs/:id/events",
|
|
6568
|
-
pathParams:
|
|
6569
|
-
id:
|
|
6814
|
+
pathParams: z18.object({
|
|
6815
|
+
id: z18.string().min(1, "Run ID is required")
|
|
6570
6816
|
}),
|
|
6571
|
-
query:
|
|
6572
|
-
last_event_id:
|
|
6817
|
+
query: z18.object({
|
|
6818
|
+
last_event_id: z18.string().optional()
|
|
6573
6819
|
// For reconnection
|
|
6574
6820
|
}),
|
|
6575
6821
|
responses: {
|
|
6576
|
-
200:
|
|
6822
|
+
200: z18.any(),
|
|
6577
6823
|
// SSE stream - actual content is text/event-stream
|
|
6578
6824
|
401: publicApiErrorSchema,
|
|
6579
6825
|
404: publicApiErrorSchema,
|
|
@@ -6585,28 +6831,28 @@ var publicRunEventsContract = c12.router({
|
|
|
6585
6831
|
});
|
|
6586
6832
|
|
|
6587
6833
|
// ../../packages/core/src/contracts/public/artifacts.ts
|
|
6588
|
-
import { z as
|
|
6589
|
-
var
|
|
6590
|
-
var publicArtifactSchema =
|
|
6591
|
-
id:
|
|
6592
|
-
name:
|
|
6593
|
-
current_version_id:
|
|
6594
|
-
size:
|
|
6834
|
+
import { z as z19 } from "zod";
|
|
6835
|
+
var c14 = initContract();
|
|
6836
|
+
var publicArtifactSchema = z19.object({
|
|
6837
|
+
id: z19.string(),
|
|
6838
|
+
name: z19.string(),
|
|
6839
|
+
current_version_id: z19.string().nullable(),
|
|
6840
|
+
size: z19.number(),
|
|
6595
6841
|
// Total size in bytes
|
|
6596
|
-
file_count:
|
|
6842
|
+
file_count: z19.number(),
|
|
6597
6843
|
created_at: timestampSchema,
|
|
6598
6844
|
updated_at: timestampSchema
|
|
6599
6845
|
});
|
|
6600
|
-
var artifactVersionSchema =
|
|
6601
|
-
id:
|
|
6846
|
+
var artifactVersionSchema = z19.object({
|
|
6847
|
+
id: z19.string(),
|
|
6602
6848
|
// SHA-256 content hash
|
|
6603
|
-
artifact_id:
|
|
6604
|
-
size:
|
|
6849
|
+
artifact_id: z19.string(),
|
|
6850
|
+
size: z19.number(),
|
|
6605
6851
|
// Size in bytes
|
|
6606
|
-
file_count:
|
|
6607
|
-
message:
|
|
6852
|
+
file_count: z19.number(),
|
|
6853
|
+
message: z19.string().nullable(),
|
|
6608
6854
|
// Optional commit message
|
|
6609
|
-
created_by:
|
|
6855
|
+
created_by: z19.string(),
|
|
6610
6856
|
created_at: timestampSchema
|
|
6611
6857
|
});
|
|
6612
6858
|
var publicArtifactDetailSchema = publicArtifactSchema.extend({
|
|
@@ -6616,7 +6862,7 @@ var paginatedArtifactsSchema = createPaginatedResponseSchema(publicArtifactSchem
|
|
|
6616
6862
|
var paginatedArtifactVersionsSchema = createPaginatedResponseSchema(
|
|
6617
6863
|
artifactVersionSchema
|
|
6618
6864
|
);
|
|
6619
|
-
var publicArtifactsListContract =
|
|
6865
|
+
var publicArtifactsListContract = c14.router({
|
|
6620
6866
|
list: {
|
|
6621
6867
|
method: "GET",
|
|
6622
6868
|
path: "/v1/artifacts",
|
|
@@ -6630,12 +6876,12 @@ var publicArtifactsListContract = c13.router({
|
|
|
6630
6876
|
description: "List all artifacts in the current scope with pagination"
|
|
6631
6877
|
}
|
|
6632
6878
|
});
|
|
6633
|
-
var publicArtifactByIdContract =
|
|
6879
|
+
var publicArtifactByIdContract = c14.router({
|
|
6634
6880
|
get: {
|
|
6635
6881
|
method: "GET",
|
|
6636
6882
|
path: "/v1/artifacts/:id",
|
|
6637
|
-
pathParams:
|
|
6638
|
-
id:
|
|
6883
|
+
pathParams: z19.object({
|
|
6884
|
+
id: z19.string().min(1, "Artifact ID is required")
|
|
6639
6885
|
}),
|
|
6640
6886
|
responses: {
|
|
6641
6887
|
200: publicArtifactDetailSchema,
|
|
@@ -6647,12 +6893,12 @@ var publicArtifactByIdContract = c13.router({
|
|
|
6647
6893
|
description: "Get artifact details by ID"
|
|
6648
6894
|
}
|
|
6649
6895
|
});
|
|
6650
|
-
var publicArtifactVersionsContract =
|
|
6896
|
+
var publicArtifactVersionsContract = c14.router({
|
|
6651
6897
|
list: {
|
|
6652
6898
|
method: "GET",
|
|
6653
6899
|
path: "/v1/artifacts/:id/versions",
|
|
6654
|
-
pathParams:
|
|
6655
|
-
id:
|
|
6900
|
+
pathParams: z19.object({
|
|
6901
|
+
id: z19.string().min(1, "Artifact ID is required")
|
|
6656
6902
|
}),
|
|
6657
6903
|
query: listQuerySchema,
|
|
6658
6904
|
responses: {
|
|
@@ -6665,19 +6911,19 @@ var publicArtifactVersionsContract = c13.router({
|
|
|
6665
6911
|
description: "List all versions of an artifact with pagination"
|
|
6666
6912
|
}
|
|
6667
6913
|
});
|
|
6668
|
-
var publicArtifactDownloadContract =
|
|
6914
|
+
var publicArtifactDownloadContract = c14.router({
|
|
6669
6915
|
download: {
|
|
6670
6916
|
method: "GET",
|
|
6671
6917
|
path: "/v1/artifacts/:id/download",
|
|
6672
|
-
pathParams:
|
|
6673
|
-
id:
|
|
6918
|
+
pathParams: z19.object({
|
|
6919
|
+
id: z19.string().min(1, "Artifact ID is required")
|
|
6674
6920
|
}),
|
|
6675
|
-
query:
|
|
6676
|
-
version_id:
|
|
6921
|
+
query: z19.object({
|
|
6922
|
+
version_id: z19.string().optional()
|
|
6677
6923
|
// Defaults to current version
|
|
6678
6924
|
}),
|
|
6679
6925
|
responses: {
|
|
6680
|
-
302:
|
|
6926
|
+
302: z19.undefined(),
|
|
6681
6927
|
// Redirect to presigned URL
|
|
6682
6928
|
401: publicApiErrorSchema,
|
|
6683
6929
|
404: publicApiErrorSchema,
|
|
@@ -6689,28 +6935,28 @@ var publicArtifactDownloadContract = c13.router({
|
|
|
6689
6935
|
});
|
|
6690
6936
|
|
|
6691
6937
|
// ../../packages/core/src/contracts/public/volumes.ts
|
|
6692
|
-
import { z as
|
|
6693
|
-
var
|
|
6694
|
-
var publicVolumeSchema =
|
|
6695
|
-
id:
|
|
6696
|
-
name:
|
|
6697
|
-
current_version_id:
|
|
6698
|
-
size:
|
|
6938
|
+
import { z as z20 } from "zod";
|
|
6939
|
+
var c15 = initContract();
|
|
6940
|
+
var publicVolumeSchema = z20.object({
|
|
6941
|
+
id: z20.string(),
|
|
6942
|
+
name: z20.string(),
|
|
6943
|
+
current_version_id: z20.string().nullable(),
|
|
6944
|
+
size: z20.number(),
|
|
6699
6945
|
// Total size in bytes
|
|
6700
|
-
file_count:
|
|
6946
|
+
file_count: z20.number(),
|
|
6701
6947
|
created_at: timestampSchema,
|
|
6702
6948
|
updated_at: timestampSchema
|
|
6703
6949
|
});
|
|
6704
|
-
var volumeVersionSchema =
|
|
6705
|
-
id:
|
|
6950
|
+
var volumeVersionSchema = z20.object({
|
|
6951
|
+
id: z20.string(),
|
|
6706
6952
|
// SHA-256 content hash
|
|
6707
|
-
volume_id:
|
|
6708
|
-
size:
|
|
6953
|
+
volume_id: z20.string(),
|
|
6954
|
+
size: z20.number(),
|
|
6709
6955
|
// Size in bytes
|
|
6710
|
-
file_count:
|
|
6711
|
-
message:
|
|
6956
|
+
file_count: z20.number(),
|
|
6957
|
+
message: z20.string().nullable(),
|
|
6712
6958
|
// Optional commit message
|
|
6713
|
-
created_by:
|
|
6959
|
+
created_by: z20.string(),
|
|
6714
6960
|
created_at: timestampSchema
|
|
6715
6961
|
});
|
|
6716
6962
|
var publicVolumeDetailSchema = publicVolumeSchema.extend({
|
|
@@ -6718,7 +6964,7 @@ var publicVolumeDetailSchema = publicVolumeSchema.extend({
|
|
|
6718
6964
|
});
|
|
6719
6965
|
var paginatedVolumesSchema = createPaginatedResponseSchema(publicVolumeSchema);
|
|
6720
6966
|
var paginatedVolumeVersionsSchema = createPaginatedResponseSchema(volumeVersionSchema);
|
|
6721
|
-
var publicVolumesListContract =
|
|
6967
|
+
var publicVolumesListContract = c15.router({
|
|
6722
6968
|
list: {
|
|
6723
6969
|
method: "GET",
|
|
6724
6970
|
path: "/v1/volumes",
|
|
@@ -6732,12 +6978,12 @@ var publicVolumesListContract = c14.router({
|
|
|
6732
6978
|
description: "List all volumes in the current scope with pagination"
|
|
6733
6979
|
}
|
|
6734
6980
|
});
|
|
6735
|
-
var publicVolumeByIdContract =
|
|
6981
|
+
var publicVolumeByIdContract = c15.router({
|
|
6736
6982
|
get: {
|
|
6737
6983
|
method: "GET",
|
|
6738
6984
|
path: "/v1/volumes/:id",
|
|
6739
|
-
pathParams:
|
|
6740
|
-
id:
|
|
6985
|
+
pathParams: z20.object({
|
|
6986
|
+
id: z20.string().min(1, "Volume ID is required")
|
|
6741
6987
|
}),
|
|
6742
6988
|
responses: {
|
|
6743
6989
|
200: publicVolumeDetailSchema,
|
|
@@ -6749,12 +6995,12 @@ var publicVolumeByIdContract = c14.router({
|
|
|
6749
6995
|
description: "Get volume details by ID"
|
|
6750
6996
|
}
|
|
6751
6997
|
});
|
|
6752
|
-
var publicVolumeVersionsContract =
|
|
6998
|
+
var publicVolumeVersionsContract = c15.router({
|
|
6753
6999
|
list: {
|
|
6754
7000
|
method: "GET",
|
|
6755
7001
|
path: "/v1/volumes/:id/versions",
|
|
6756
|
-
pathParams:
|
|
6757
|
-
id:
|
|
7002
|
+
pathParams: z20.object({
|
|
7003
|
+
id: z20.string().min(1, "Volume ID is required")
|
|
6758
7004
|
}),
|
|
6759
7005
|
query: listQuerySchema,
|
|
6760
7006
|
responses: {
|
|
@@ -6767,19 +7013,19 @@ var publicVolumeVersionsContract = c14.router({
|
|
|
6767
7013
|
description: "List all versions of a volume with pagination"
|
|
6768
7014
|
}
|
|
6769
7015
|
});
|
|
6770
|
-
var publicVolumeDownloadContract =
|
|
7016
|
+
var publicVolumeDownloadContract = c15.router({
|
|
6771
7017
|
download: {
|
|
6772
7018
|
method: "GET",
|
|
6773
7019
|
path: "/v1/volumes/:id/download",
|
|
6774
|
-
pathParams:
|
|
6775
|
-
id:
|
|
7020
|
+
pathParams: z20.object({
|
|
7021
|
+
id: z20.string().min(1, "Volume ID is required")
|
|
6776
7022
|
}),
|
|
6777
|
-
query:
|
|
6778
|
-
version_id:
|
|
7023
|
+
query: z20.object({
|
|
7024
|
+
version_id: z20.string().optional()
|
|
6779
7025
|
// Defaults to current version
|
|
6780
7026
|
}),
|
|
6781
7027
|
responses: {
|
|
6782
|
-
302:
|
|
7028
|
+
302: z20.undefined(),
|
|
6783
7029
|
// Redirect to presigned URL
|
|
6784
7030
|
401: publicApiErrorSchema,
|
|
6785
7031
|
404: publicApiErrorSchema,
|
|
@@ -9955,6 +10201,208 @@ function initProxyManager(config) {
|
|
|
9955
10201
|
return globalProxyManager;
|
|
9956
10202
|
}
|
|
9957
10203
|
|
|
10204
|
+
// src/lib/metrics/provider.ts
|
|
10205
|
+
import {
|
|
10206
|
+
MeterProvider,
|
|
10207
|
+
PeriodicExportingMetricReader
|
|
10208
|
+
} from "@opentelemetry/sdk-metrics";
|
|
10209
|
+
import { OTLPMetricExporter } from "@opentelemetry/exporter-metrics-otlp-proto";
|
|
10210
|
+
import { Resource } from "@opentelemetry/resources";
|
|
10211
|
+
import { ATTR_SERVICE_NAME } from "@opentelemetry/semantic-conventions";
|
|
10212
|
+
import { metrics } from "@opentelemetry/api";
|
|
10213
|
+
var meterProvider = null;
|
|
10214
|
+
var initialized = false;
|
|
10215
|
+
var enabled = false;
|
|
10216
|
+
var _runnerLabel = "";
|
|
10217
|
+
function initMetrics(config) {
|
|
10218
|
+
if (initialized) return;
|
|
10219
|
+
initialized = true;
|
|
10220
|
+
_runnerLabel = config.runnerLabel;
|
|
10221
|
+
if (!config.axiomToken) {
|
|
10222
|
+
console.log("[metrics] AXIOM_TOKEN not configured, metrics disabled");
|
|
10223
|
+
return;
|
|
10224
|
+
}
|
|
10225
|
+
const env = config.environment ?? "dev";
|
|
10226
|
+
const exporter = new OTLPMetricExporter({
|
|
10227
|
+
url: "https://api.axiom.co/v1/metrics",
|
|
10228
|
+
headers: {
|
|
10229
|
+
Authorization: `Bearer ${config.axiomToken}`,
|
|
10230
|
+
"X-Axiom-Dataset": `runner-metrics-${env}`
|
|
10231
|
+
}
|
|
10232
|
+
});
|
|
10233
|
+
meterProvider = new MeterProvider({
|
|
10234
|
+
resource: new Resource({
|
|
10235
|
+
[ATTR_SERVICE_NAME]: config.serviceName,
|
|
10236
|
+
"deployment.environment": env,
|
|
10237
|
+
"runner.label": config.runnerLabel
|
|
10238
|
+
}),
|
|
10239
|
+
readers: [
|
|
10240
|
+
new PeriodicExportingMetricReader({
|
|
10241
|
+
exporter,
|
|
10242
|
+
exportIntervalMillis: config.exportIntervalMs ?? 3e4
|
|
10243
|
+
})
|
|
10244
|
+
]
|
|
10245
|
+
});
|
|
10246
|
+
metrics.setGlobalMeterProvider(meterProvider);
|
|
10247
|
+
enabled = true;
|
|
10248
|
+
console.log(
|
|
10249
|
+
`[metrics] initialized for ${config.serviceName} (${env}), runner: ${config.runnerLabel}`
|
|
10250
|
+
);
|
|
10251
|
+
}
|
|
10252
|
+
function isMetricsEnabled() {
|
|
10253
|
+
return enabled;
|
|
10254
|
+
}
|
|
10255
|
+
function getRunnerLabel() {
|
|
10256
|
+
return _runnerLabel;
|
|
10257
|
+
}
|
|
10258
|
+
function getMeter(name) {
|
|
10259
|
+
return metrics.getMeter(name);
|
|
10260
|
+
}
|
|
10261
|
+
async function flushMetrics() {
|
|
10262
|
+
if (meterProvider) {
|
|
10263
|
+
await meterProvider.forceFlush();
|
|
10264
|
+
}
|
|
10265
|
+
}
|
|
10266
|
+
async function shutdownMetrics() {
|
|
10267
|
+
if (meterProvider) {
|
|
10268
|
+
await meterProvider.shutdown();
|
|
10269
|
+
}
|
|
10270
|
+
}
|
|
10271
|
+
|
|
10272
|
+
// src/lib/metrics/instruments.ts
|
|
10273
|
+
var runnerOperationTotal = null;
|
|
10274
|
+
var runnerOperationErrorsTotal = null;
|
|
10275
|
+
var runnerOperationDuration = null;
|
|
10276
|
+
var sandboxOperationTotal = null;
|
|
10277
|
+
var sandboxOperationErrorsTotal = null;
|
|
10278
|
+
var sandboxOperationDuration = null;
|
|
10279
|
+
function getRunnerInstruments() {
|
|
10280
|
+
if (!runnerOperationTotal) {
|
|
10281
|
+
const meter = getMeter("vm0-runner");
|
|
10282
|
+
runnerOperationTotal = meter.createCounter("runner_operation_total", {
|
|
10283
|
+
description: "Total number of runner operations"
|
|
10284
|
+
});
|
|
10285
|
+
runnerOperationErrorsTotal = meter.createCounter(
|
|
10286
|
+
"runner_operation_errors_total",
|
|
10287
|
+
{
|
|
10288
|
+
description: "Total number of runner operation errors"
|
|
10289
|
+
}
|
|
10290
|
+
);
|
|
10291
|
+
runnerOperationDuration = meter.createHistogram(
|
|
10292
|
+
"runner_operation_duration_ms",
|
|
10293
|
+
{
|
|
10294
|
+
description: "Runner operation duration in milliseconds",
|
|
10295
|
+
unit: "ms"
|
|
10296
|
+
}
|
|
10297
|
+
);
|
|
10298
|
+
}
|
|
10299
|
+
return {
|
|
10300
|
+
runnerOperationTotal,
|
|
10301
|
+
runnerOperationErrorsTotal,
|
|
10302
|
+
runnerOperationDuration
|
|
10303
|
+
};
|
|
10304
|
+
}
|
|
10305
|
+
function getSandboxInstruments() {
|
|
10306
|
+
if (!sandboxOperationTotal) {
|
|
10307
|
+
const meter = getMeter("vm0-runner");
|
|
10308
|
+
sandboxOperationTotal = meter.createCounter("sandbox_operation_total", {
|
|
10309
|
+
description: "Total number of sandbox operations"
|
|
10310
|
+
});
|
|
10311
|
+
sandboxOperationErrorsTotal = meter.createCounter(
|
|
10312
|
+
"sandbox_operation_errors_total",
|
|
10313
|
+
{
|
|
10314
|
+
description: "Total number of sandbox operation errors"
|
|
10315
|
+
}
|
|
10316
|
+
);
|
|
10317
|
+
sandboxOperationDuration = meter.createHistogram(
|
|
10318
|
+
"sandbox_operation_duration_ms",
|
|
10319
|
+
{
|
|
10320
|
+
description: "Sandbox operation duration in milliseconds",
|
|
10321
|
+
unit: "ms"
|
|
10322
|
+
}
|
|
10323
|
+
);
|
|
10324
|
+
}
|
|
10325
|
+
return {
|
|
10326
|
+
sandboxOperationTotal,
|
|
10327
|
+
sandboxOperationErrorsTotal,
|
|
10328
|
+
sandboxOperationDuration
|
|
10329
|
+
};
|
|
10330
|
+
}
|
|
10331
|
+
function recordRunnerOperation(attrs) {
|
|
10332
|
+
if (!isMetricsEnabled()) return;
|
|
10333
|
+
const {
|
|
10334
|
+
runnerOperationTotal: runnerOperationTotal2,
|
|
10335
|
+
runnerOperationErrorsTotal: runnerOperationErrorsTotal2,
|
|
10336
|
+
runnerOperationDuration: runnerOperationDuration2
|
|
10337
|
+
} = getRunnerInstruments();
|
|
10338
|
+
const labels = {
|
|
10339
|
+
action_type: attrs.actionType,
|
|
10340
|
+
runner_label: getRunnerLabel()
|
|
10341
|
+
};
|
|
10342
|
+
runnerOperationTotal2.add(1, labels);
|
|
10343
|
+
if (!attrs.success) {
|
|
10344
|
+
runnerOperationErrorsTotal2.add(1, labels);
|
|
10345
|
+
}
|
|
10346
|
+
runnerOperationDuration2.record(attrs.durationMs, {
|
|
10347
|
+
...labels,
|
|
10348
|
+
success: String(attrs.success)
|
|
10349
|
+
});
|
|
10350
|
+
}
|
|
10351
|
+
function recordSandboxOperation(attrs) {
|
|
10352
|
+
if (!isMetricsEnabled()) return;
|
|
10353
|
+
const {
|
|
10354
|
+
sandboxOperationTotal: sandboxOperationTotal2,
|
|
10355
|
+
sandboxOperationErrorsTotal: sandboxOperationErrorsTotal2,
|
|
10356
|
+
sandboxOperationDuration: sandboxOperationDuration2
|
|
10357
|
+
} = getSandboxInstruments();
|
|
10358
|
+
const labels = {
|
|
10359
|
+
sandbox_type: "runner",
|
|
10360
|
+
action_type: attrs.actionType
|
|
10361
|
+
};
|
|
10362
|
+
sandboxOperationTotal2.add(1, labels);
|
|
10363
|
+
if (!attrs.success) {
|
|
10364
|
+
sandboxOperationErrorsTotal2.add(1, labels);
|
|
10365
|
+
}
|
|
10366
|
+
sandboxOperationDuration2.record(attrs.durationMs, {
|
|
10367
|
+
...labels,
|
|
10368
|
+
success: String(attrs.success)
|
|
10369
|
+
});
|
|
10370
|
+
}
|
|
10371
|
+
|
|
10372
|
+
// src/lib/metrics/timing.ts
|
|
10373
|
+
async function withRunnerTiming(actionType, fn) {
|
|
10374
|
+
const startTime = Date.now();
|
|
10375
|
+
let success = true;
|
|
10376
|
+
try {
|
|
10377
|
+
return await fn();
|
|
10378
|
+
} catch (error) {
|
|
10379
|
+
success = false;
|
|
10380
|
+
throw error;
|
|
10381
|
+
} finally {
|
|
10382
|
+
recordRunnerOperation({
|
|
10383
|
+
actionType,
|
|
10384
|
+
durationMs: Date.now() - startTime,
|
|
10385
|
+
success
|
|
10386
|
+
});
|
|
10387
|
+
}
|
|
10388
|
+
}
|
|
10389
|
+
async function withSandboxTiming(actionType, fn) {
|
|
10390
|
+
const startTime = Date.now();
|
|
10391
|
+
let success = true;
|
|
10392
|
+
try {
|
|
10393
|
+
return await fn();
|
|
10394
|
+
} catch (error) {
|
|
10395
|
+
success = false;
|
|
10396
|
+
throw error;
|
|
10397
|
+
} finally {
|
|
10398
|
+
recordSandboxOperation({
|
|
10399
|
+
actionType,
|
|
10400
|
+
durationMs: Date.now() - startTime,
|
|
10401
|
+
success
|
|
10402
|
+
});
|
|
10403
|
+
}
|
|
10404
|
+
}
|
|
10405
|
+
|
|
9958
10406
|
// src/lib/executor.ts
|
|
9959
10407
|
function getVmIdFromRunId(runId) {
|
|
9960
10408
|
return runId.split("-")[0] || runId.substring(0, 8);
|
|
@@ -10142,11 +10590,12 @@ nameserver 1.1.1.1`;
|
|
|
10142
10590
|
`sudo sh -c 'rm -f /etc/resolv.conf && echo "${dnsConfig}" > /etc/resolv.conf'`
|
|
10143
10591
|
);
|
|
10144
10592
|
}
|
|
10145
|
-
async function executeJob(context, config) {
|
|
10593
|
+
async function executeJob(context, config, options = {}) {
|
|
10146
10594
|
const vmId = getVmIdFromRunId(context.runId);
|
|
10147
10595
|
let vm = null;
|
|
10148
10596
|
let guestIp = null;
|
|
10149
|
-
|
|
10597
|
+
const log = options.logger ?? ((msg) => console.log(msg));
|
|
10598
|
+
log(`[Executor] Starting job ${context.runId} in VM ${vmId}`);
|
|
10150
10599
|
try {
|
|
10151
10600
|
const workspacesDir = path4.join(process.cwd(), "workspaces");
|
|
10152
10601
|
const vmConfig = {
|
|
@@ -10158,24 +10607,27 @@ async function executeJob(context, config) {
|
|
|
10158
10607
|
firecrackerBinary: config.firecracker.binary,
|
|
10159
10608
|
workDir: path4.join(workspacesDir, `vm0-${vmId}`)
|
|
10160
10609
|
};
|
|
10161
|
-
|
|
10610
|
+
log(`[Executor] Creating VM ${vmId}...`);
|
|
10162
10611
|
vm = new FirecrackerVM(vmConfig);
|
|
10163
|
-
await vm.start();
|
|
10612
|
+
await withSandboxTiming("vm_create", () => vm.start());
|
|
10164
10613
|
guestIp = vm.getGuestIp();
|
|
10165
10614
|
if (!guestIp) {
|
|
10166
10615
|
throw new Error("VM started but no IP address available");
|
|
10167
10616
|
}
|
|
10168
|
-
|
|
10617
|
+
log(`[Executor] VM ${vmId} started, guest IP: ${guestIp}`);
|
|
10169
10618
|
const privateKeyPath = getRunnerSSHKeyPath();
|
|
10170
10619
|
const ssh = createVMSSHClient(guestIp, "user", privateKeyPath || void 0);
|
|
10171
|
-
|
|
10172
|
-
await
|
|
10173
|
-
|
|
10620
|
+
log(`[Executor] Waiting for SSH on ${guestIp}...`);
|
|
10621
|
+
await withSandboxTiming(
|
|
10622
|
+
"ssh_wait",
|
|
10623
|
+
() => ssh.waitUntilReachable(12e4, 2e3)
|
|
10624
|
+
);
|
|
10625
|
+
log(`[Executor] SSH ready on ${guestIp}`);
|
|
10174
10626
|
const firewallConfig = context.experimentalFirewall;
|
|
10175
10627
|
if (firewallConfig?.enabled) {
|
|
10176
10628
|
const mitmEnabled = firewallConfig.experimental_mitm ?? false;
|
|
10177
10629
|
const sealSecretsEnabled = firewallConfig.experimental_seal_secrets ?? false;
|
|
10178
|
-
|
|
10630
|
+
log(
|
|
10179
10631
|
`[Executor] Setting up network security for VM ${guestIp} (mitm=${mitmEnabled}, sealSecrets=${sealSecretsEnabled})`
|
|
10180
10632
|
);
|
|
10181
10633
|
await setupVMProxyRules(guestIp, config.proxy.port);
|
|
@@ -10188,36 +10640,50 @@ async function executeJob(context, config) {
|
|
|
10188
10640
|
await installProxyCA(ssh);
|
|
10189
10641
|
}
|
|
10190
10642
|
}
|
|
10191
|
-
|
|
10643
|
+
log(`[Executor] Configuring DNS...`);
|
|
10192
10644
|
await configureDNS(ssh);
|
|
10193
|
-
|
|
10194
|
-
await uploadScripts(ssh);
|
|
10195
|
-
|
|
10645
|
+
log(`[Executor] Uploading scripts...`);
|
|
10646
|
+
await withSandboxTiming("script_upload", () => uploadScripts(ssh));
|
|
10647
|
+
log(`[Executor] Scripts uploaded to ${SCRIPT_PATHS.baseDir}`);
|
|
10196
10648
|
if (context.storageManifest) {
|
|
10197
|
-
await
|
|
10649
|
+
await withSandboxTiming(
|
|
10650
|
+
"storage_download",
|
|
10651
|
+
() => downloadStorages(ssh, context.storageManifest)
|
|
10652
|
+
);
|
|
10198
10653
|
}
|
|
10199
10654
|
if (context.resumeSession) {
|
|
10200
|
-
await
|
|
10201
|
-
|
|
10202
|
-
|
|
10203
|
-
|
|
10204
|
-
|
|
10655
|
+
await withSandboxTiming(
|
|
10656
|
+
"session_restore",
|
|
10657
|
+
() => restoreSessionHistory(
|
|
10658
|
+
ssh,
|
|
10659
|
+
context.resumeSession,
|
|
10660
|
+
context.workingDir,
|
|
10661
|
+
context.cliAgentType || "claude-code"
|
|
10662
|
+
)
|
|
10205
10663
|
);
|
|
10206
10664
|
}
|
|
10207
10665
|
const envVars = buildEnvironmentVariables(context, config.server.url);
|
|
10208
10666
|
const envJson = JSON.stringify(envVars);
|
|
10209
|
-
|
|
10667
|
+
log(
|
|
10210
10668
|
`[Executor] Writing env JSON (${envJson.length} bytes) to ${ENV_JSON_PATH}`
|
|
10211
10669
|
);
|
|
10212
10670
|
await ssh.writeFile(ENV_JSON_PATH, envJson);
|
|
10213
10671
|
const systemLogFile = `/tmp/vm0-main-${context.runId}.log`;
|
|
10214
10672
|
const exitCodeFile = `/tmp/vm0-exit-${context.runId}`;
|
|
10215
|
-
console.log(`[Executor] Running agent via env-loader (background)...`);
|
|
10216
10673
|
const startTime = Date.now();
|
|
10217
|
-
|
|
10218
|
-
`
|
|
10219
|
-
|
|
10220
|
-
|
|
10674
|
+
if (options.benchmarkMode) {
|
|
10675
|
+
log(`[Executor] Running command directly (benchmark mode)...`);
|
|
10676
|
+
await ssh.exec(
|
|
10677
|
+
`nohup sh -c '${context.prompt}; echo $? > ${exitCodeFile}' > ${systemLogFile} 2>&1 &`
|
|
10678
|
+
);
|
|
10679
|
+
log(`[Executor] Command started in background`);
|
|
10680
|
+
} else {
|
|
10681
|
+
log(`[Executor] Running agent via env-loader (background)...`);
|
|
10682
|
+
await ssh.exec(
|
|
10683
|
+
`nohup sh -c 'python3 -u ${ENV_LOADER_PATH}; echo $? > ${exitCodeFile}' > ${systemLogFile} 2>&1 &`
|
|
10684
|
+
);
|
|
10685
|
+
log(`[Executor] Agent started in background`);
|
|
10686
|
+
}
|
|
10221
10687
|
const pollIntervalMs = 2e3;
|
|
10222
10688
|
const maxWaitMs = 24 * 60 * 60 * 1e3;
|
|
10223
10689
|
let exitCode = 1;
|
|
@@ -10226,25 +10692,35 @@ async function executeJob(context, config) {
|
|
|
10226
10692
|
await new Promise((resolve) => setTimeout(resolve, pollIntervalMs));
|
|
10227
10693
|
const checkResult = await ssh.exec(`cat ${exitCodeFile} 2>/dev/null`);
|
|
10228
10694
|
if (checkResult.exitCode === 0 && checkResult.stdout.trim()) {
|
|
10229
|
-
|
|
10695
|
+
const parsed = parseInt(checkResult.stdout.trim(), 10);
|
|
10696
|
+
exitCode = Number.isNaN(parsed) ? 1 : parsed;
|
|
10230
10697
|
completed = true;
|
|
10231
10698
|
break;
|
|
10232
10699
|
}
|
|
10233
10700
|
}
|
|
10234
|
-
const
|
|
10701
|
+
const durationMs = Date.now() - startTime;
|
|
10702
|
+
const duration = Math.round(durationMs / 1e3);
|
|
10235
10703
|
if (!completed) {
|
|
10236
|
-
|
|
10704
|
+
log(`[Executor] Agent timed out after ${duration}s`);
|
|
10705
|
+
recordRunnerOperation({
|
|
10706
|
+
actionType: "agent_execute",
|
|
10707
|
+
durationMs,
|
|
10708
|
+
success: false
|
|
10709
|
+
});
|
|
10237
10710
|
return {
|
|
10238
10711
|
exitCode: 1,
|
|
10239
10712
|
error: `Agent execution timed out after ${duration}s`
|
|
10240
10713
|
};
|
|
10241
10714
|
}
|
|
10242
|
-
|
|
10243
|
-
|
|
10244
|
-
|
|
10715
|
+
recordRunnerOperation({
|
|
10716
|
+
actionType: "agent_execute",
|
|
10717
|
+
durationMs,
|
|
10718
|
+
success: exitCode === 0
|
|
10719
|
+
});
|
|
10720
|
+
log(`[Executor] Agent finished in ${duration}s with exit code ${exitCode}`);
|
|
10245
10721
|
const logResult = await ssh.exec(`tail -100 ${systemLogFile} 2>/dev/null`);
|
|
10246
10722
|
if (logResult.stdout) {
|
|
10247
|
-
|
|
10723
|
+
log(
|
|
10248
10724
|
`[Executor] Log output (${logResult.stdout.length} chars): ${logResult.stdout.substring(0, 500)}`
|
|
10249
10725
|
);
|
|
10250
10726
|
}
|
|
@@ -10261,7 +10737,7 @@ async function executeJob(context, config) {
|
|
|
10261
10737
|
};
|
|
10262
10738
|
} finally {
|
|
10263
10739
|
if (context.experimentalFirewall?.enabled && guestIp) {
|
|
10264
|
-
|
|
10740
|
+
log(`[Executor] Cleaning up network security for VM ${guestIp}`);
|
|
10265
10741
|
try {
|
|
10266
10742
|
await removeVMProxyRules(guestIp, config.proxy.port);
|
|
10267
10743
|
} catch (err) {
|
|
@@ -10270,21 +10746,23 @@ async function executeJob(context, config) {
|
|
|
10270
10746
|
);
|
|
10271
10747
|
}
|
|
10272
10748
|
getVMRegistry().unregister(guestIp);
|
|
10273
|
-
|
|
10274
|
-
|
|
10275
|
-
|
|
10276
|
-
|
|
10277
|
-
|
|
10278
|
-
|
|
10279
|
-
|
|
10280
|
-
|
|
10281
|
-
|
|
10282
|
-
|
|
10749
|
+
if (!options.benchmarkMode) {
|
|
10750
|
+
try {
|
|
10751
|
+
await uploadNetworkLogs(
|
|
10752
|
+
config.server.url,
|
|
10753
|
+
context.sandboxToken,
|
|
10754
|
+
context.runId
|
|
10755
|
+
);
|
|
10756
|
+
} catch (err) {
|
|
10757
|
+
console.error(
|
|
10758
|
+
`[Executor] Failed to upload network logs: ${err instanceof Error ? err.message : "Unknown error"}`
|
|
10759
|
+
);
|
|
10760
|
+
}
|
|
10283
10761
|
}
|
|
10284
10762
|
}
|
|
10285
10763
|
if (vm) {
|
|
10286
|
-
|
|
10287
|
-
await vm.kill();
|
|
10764
|
+
log(`[Executor] Cleaning up VM ${vmId}...`);
|
|
10765
|
+
await withSandboxTiming("cleanup", () => vm.kill());
|
|
10288
10766
|
}
|
|
10289
10767
|
}
|
|
10290
10768
|
}
|
|
@@ -10331,6 +10809,18 @@ var startCommand = new Command("start").description("Start the runner").option("
|
|
|
10331
10809
|
const config = loadConfig(options.config);
|
|
10332
10810
|
validateFirecrackerPaths(config.firecracker);
|
|
10333
10811
|
console.log("Config valid");
|
|
10812
|
+
const datasetSuffix = process.env.AXIOM_DATASET_SUFFIX;
|
|
10813
|
+
if (!datasetSuffix) {
|
|
10814
|
+
throw new Error(
|
|
10815
|
+
"AXIOM_DATASET_SUFFIX is required. Set to 'dev' or 'prod'."
|
|
10816
|
+
);
|
|
10817
|
+
}
|
|
10818
|
+
initMetrics({
|
|
10819
|
+
serviceName: "vm0-runner",
|
|
10820
|
+
runnerLabel: config.name,
|
|
10821
|
+
axiomToken: process.env.AXIOM_TOKEN,
|
|
10822
|
+
environment: datasetSuffix
|
|
10823
|
+
});
|
|
10334
10824
|
const networkCheck = checkNetworkPrerequisites();
|
|
10335
10825
|
if (!networkCheck.ok) {
|
|
10336
10826
|
console.error("Network prerequisites not met:");
|
|
@@ -10419,7 +10909,10 @@ var startCommand = new Command("start").description("Start the runner").option("
|
|
|
10419
10909
|
continue;
|
|
10420
10910
|
}
|
|
10421
10911
|
try {
|
|
10422
|
-
const job = await
|
|
10912
|
+
const job = await withRunnerTiming(
|
|
10913
|
+
"poll",
|
|
10914
|
+
() => pollForJob(config.server, config.group)
|
|
10915
|
+
);
|
|
10423
10916
|
if (!job) {
|
|
10424
10917
|
await new Promise(
|
|
10425
10918
|
(resolve) => setTimeout(resolve, config.sandbox.poll_interval_ms)
|
|
@@ -10428,7 +10921,10 @@ var startCommand = new Command("start").description("Start the runner").option("
|
|
|
10428
10921
|
}
|
|
10429
10922
|
console.log(`Found job: ${job.runId}`);
|
|
10430
10923
|
try {
|
|
10431
|
-
const context = await
|
|
10924
|
+
const context = await withRunnerTiming(
|
|
10925
|
+
"claim",
|
|
10926
|
+
() => claimJob(config.server, job.runId)
|
|
10927
|
+
);
|
|
10432
10928
|
console.log(`Claimed job: ${context.runId}`);
|
|
10433
10929
|
activeJobs.add(context.runId);
|
|
10434
10930
|
updateStatus();
|
|
@@ -10467,6 +10963,9 @@ var startCommand = new Command("start").description("Start the runner").option("
|
|
|
10467
10963
|
console.log("Stopping network proxy...");
|
|
10468
10964
|
await getProxyManager().stop();
|
|
10469
10965
|
}
|
|
10966
|
+
console.log("Flushing metrics...");
|
|
10967
|
+
await flushMetrics();
|
|
10968
|
+
await shutdownMetrics();
|
|
10470
10969
|
state.mode = "stopped";
|
|
10471
10970
|
updateStatus();
|
|
10472
10971
|
console.log("Runner stopped");
|
|
@@ -10505,10 +11004,102 @@ var statusCommand = new Command2("status").description("Check runner connectivit
|
|
|
10505
11004
|
}
|
|
10506
11005
|
});
|
|
10507
11006
|
|
|
11007
|
+
// src/commands/benchmark.ts
|
|
11008
|
+
import { Command as Command3 } from "commander";
|
|
11009
|
+
import crypto from "crypto";
|
|
11010
|
+
|
|
11011
|
+
// src/lib/timing.ts
|
|
11012
|
+
var Timer = class {
|
|
11013
|
+
startTime;
|
|
11014
|
+
constructor() {
|
|
11015
|
+
this.startTime = Date.now();
|
|
11016
|
+
}
|
|
11017
|
+
/**
|
|
11018
|
+
* Get elapsed time formatted as [MM:SS.s]
|
|
11019
|
+
*/
|
|
11020
|
+
elapsed() {
|
|
11021
|
+
const ms = Date.now() - this.startTime;
|
|
11022
|
+
const totalSeconds = ms / 1e3;
|
|
11023
|
+
const minutes = Math.floor(totalSeconds / 60);
|
|
11024
|
+
const seconds = (totalSeconds % 60).toFixed(1);
|
|
11025
|
+
return `[${String(minutes).padStart(2, "0")}:${seconds.padStart(4, "0")}]`;
|
|
11026
|
+
}
|
|
11027
|
+
/**
|
|
11028
|
+
* Log message with timestamp
|
|
11029
|
+
*/
|
|
11030
|
+
log(message) {
|
|
11031
|
+
console.log(`${this.elapsed()} ${message}`);
|
|
11032
|
+
}
|
|
11033
|
+
/**
|
|
11034
|
+
* Get total elapsed time in seconds
|
|
11035
|
+
*/
|
|
11036
|
+
totalSeconds() {
|
|
11037
|
+
return (Date.now() - this.startTime) / 1e3;
|
|
11038
|
+
}
|
|
11039
|
+
};
|
|
11040
|
+
|
|
11041
|
+
// src/commands/benchmark.ts
|
|
11042
|
+
function createBenchmarkContext(prompt, options) {
|
|
11043
|
+
return {
|
|
11044
|
+
runId: crypto.randomUUID(),
|
|
11045
|
+
prompt,
|
|
11046
|
+
agentComposeVersionId: "benchmark-local",
|
|
11047
|
+
vars: null,
|
|
11048
|
+
secretNames: null,
|
|
11049
|
+
checkpointId: null,
|
|
11050
|
+
sandboxToken: "benchmark-token-not-used",
|
|
11051
|
+
workingDir: options.workingDir,
|
|
11052
|
+
storageManifest: null,
|
|
11053
|
+
environment: null,
|
|
11054
|
+
resumeSession: null,
|
|
11055
|
+
secretValues: null,
|
|
11056
|
+
cliAgentType: options.agentType
|
|
11057
|
+
};
|
|
11058
|
+
}
|
|
11059
|
+
var benchmarkCommand = new Command3("benchmark").description(
|
|
11060
|
+
"Run a VM performance benchmark (executes bash command directly)"
|
|
11061
|
+
).argument("<prompt>", "The bash command to execute in the VM").option("--config <path>", "Config file path", "./runner.yaml").option("--working-dir <path>", "Working directory in VM", "/home/user").option("--agent-type <type>", "Agent type", "claude-code").action(async (prompt, options) => {
|
|
11062
|
+
const timer = new Timer();
|
|
11063
|
+
try {
|
|
11064
|
+
timer.log("Loading configuration...");
|
|
11065
|
+
const config = loadDebugConfig(options.config);
|
|
11066
|
+
validateFirecrackerPaths(config.firecracker);
|
|
11067
|
+
timer.log("Checking network prerequisites...");
|
|
11068
|
+
const networkCheck = checkNetworkPrerequisites();
|
|
11069
|
+
if (!networkCheck.ok) {
|
|
11070
|
+
console.error("Network prerequisites not met:");
|
|
11071
|
+
for (const error of networkCheck.errors) {
|
|
11072
|
+
console.error(` - ${error}`);
|
|
11073
|
+
}
|
|
11074
|
+
process.exit(1);
|
|
11075
|
+
}
|
|
11076
|
+
timer.log("Setting up network bridge...");
|
|
11077
|
+
await setupBridge();
|
|
11078
|
+
timer.log(`Executing command: ${prompt}`);
|
|
11079
|
+
const context = createBenchmarkContext(prompt, options);
|
|
11080
|
+
const result = await executeJob(context, config, {
|
|
11081
|
+
benchmarkMode: true,
|
|
11082
|
+
logger: timer.log.bind(timer)
|
|
11083
|
+
});
|
|
11084
|
+
timer.log(`Exit code: ${result.exitCode}`);
|
|
11085
|
+
if (result.error) {
|
|
11086
|
+
timer.log(`Error: ${result.error}`);
|
|
11087
|
+
}
|
|
11088
|
+
timer.log(`Total time: ${timer.totalSeconds().toFixed(1)}s`);
|
|
11089
|
+
process.exit(result.exitCode);
|
|
11090
|
+
} catch (error) {
|
|
11091
|
+
timer.log(
|
|
11092
|
+
`Error: ${error instanceof Error ? error.message : "Unknown error"}`
|
|
11093
|
+
);
|
|
11094
|
+
process.exit(1);
|
|
11095
|
+
}
|
|
11096
|
+
});
|
|
11097
|
+
|
|
10508
11098
|
// src/index.ts
|
|
10509
|
-
var version = true ? "2.
|
|
11099
|
+
var version = true ? "2.7.1" : "0.1.0";
|
|
10510
11100
|
program.name("vm0-runner").version(version).description("Self-hosted runner for VM0 agents");
|
|
10511
11101
|
program.addCommand(startCommand);
|
|
10512
11102
|
program.addCommand(statusCommand);
|
|
11103
|
+
program.addCommand(benchmarkCommand);
|
|
10513
11104
|
program.parse();
|
|
10514
11105
|
//# sourceMappingURL=index.js.map
|