@vm0/runner 3.0.6 → 3.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.
Files changed (2) hide show
  1. package/index.js +281 -204
  2. package/package.json +1 -1
package/index.js CHANGED
@@ -192,10 +192,11 @@ async function completeJob(apiUrl, context, exitCode, error) {
192
192
  import path4 from "path";
193
193
 
194
194
  // src/lib/firecracker/vm.ts
195
- import { execSync as execSync2, spawn } from "child_process";
195
+ import { exec as exec3, spawn } from "child_process";
196
196
  import fs3 from "fs";
197
197
  import path2 from "path";
198
198
  import readline from "readline";
199
+ import { promisify as promisify3 } from "util";
199
200
 
200
201
  // src/lib/firecracker/client.ts
201
202
  import http from "http";
@@ -706,23 +707,24 @@ async function clearStaleIptablesRulesForIP(ip) {
706
707
  } catch {
707
708
  }
708
709
  }
709
- async function createTapDevice(vmId) {
710
+ async function createTapDevice(vmId, logger) {
711
+ const log = logger ?? console.log;
710
712
  const tapDevice = `tap${vmId.substring(0, 8)}`;
711
713
  const guestMac = generateMacAddress(vmId);
712
714
  const guestIp = await allocateIP(vmId);
715
+ log(`[VM ${vmId}] IP allocated: ${guestIp}`);
713
716
  await clearStaleIptablesRulesForIP(guestIp);
714
- console.log(`Creating TAP device ${tapDevice} for VM ${vmId}...`);
715
- await setupBridge();
717
+ log(`[VM ${vmId}] Stale iptables cleared`);
716
718
  if (await tapDeviceExists(tapDevice)) {
717
- console.log(`TAP device ${tapDevice} already exists, deleting it first...`);
719
+ log(`[VM ${vmId}] TAP device ${tapDevice} already exists, deleting...`);
718
720
  await deleteTapDevice(tapDevice);
719
721
  }
720
722
  await execCommand(`ip tuntap add ${tapDevice} mode tap`);
723
+ log(`[VM ${vmId}] TAP device created`);
721
724
  await execCommand(`ip link set ${tapDevice} master ${BRIDGE_NAME2}`);
725
+ log(`[VM ${vmId}] TAP added to bridge`);
722
726
  await execCommand(`ip link set ${tapDevice} up`);
723
- console.log(
724
- `TAP ${tapDevice} created: guest MAC ${guestMac}, guest IP ${guestIp}`
725
- );
727
+ log(`[VM ${vmId}] TAP created: ${tapDevice}, MAC ${guestMac}, IP ${guestIp}`);
726
728
  return {
727
729
  tapDevice,
728
730
  guestMac,
@@ -959,6 +961,7 @@ async function cleanupOrphanedProxyRules(runnerName) {
959
961
  }
960
962
 
961
963
  // src/lib/firecracker/vm.ts
964
+ var execAsync3 = promisify3(exec3);
962
965
  var FirecrackerVM = class {
963
966
  config;
964
967
  process = null;
@@ -978,6 +981,9 @@ var FirecrackerVM = class {
978
981
  this.vmOverlayPath = path2.join(this.workDir, "overlay.ext4");
979
982
  this.vsockPath = path2.join(this.workDir, "vsock.sock");
980
983
  }
984
+ log(msg) {
985
+ (this.config.logger ?? console.log)(msg);
986
+ }
981
987
  /**
982
988
  * Get current VM state
983
989
  */
@@ -1021,15 +1027,21 @@ var FirecrackerVM = class {
1021
1027
  if (fs3.existsSync(this.socketPath)) {
1022
1028
  fs3.unlinkSync(this.socketPath);
1023
1029
  }
1024
- console.log(`[VM ${this.config.vmId}] Creating sparse overlay file...`);
1025
- const overlaySize = 2 * 1024 * 1024 * 1024;
1026
- const fd = fs3.openSync(this.vmOverlayPath, "w");
1027
- fs3.ftruncateSync(fd, overlaySize);
1028
- fs3.closeSync(fd);
1029
- execSync2(`mkfs.ext4 -F -q "${this.vmOverlayPath}"`, { stdio: "ignore" });
1030
- console.log(`[VM ${this.config.vmId}] Setting up network...`);
1031
- this.networkConfig = await createTapDevice(this.config.vmId);
1032
- console.log(`[VM ${this.config.vmId}] Starting Firecracker...`);
1030
+ this.log(`[VM ${this.config.vmId}] Setting up overlay and network...`);
1031
+ const createOverlay = async () => {
1032
+ const overlaySize = 2 * 1024 * 1024 * 1024;
1033
+ const fd = fs3.openSync(this.vmOverlayPath, "w");
1034
+ fs3.ftruncateSync(fd, overlaySize);
1035
+ fs3.closeSync(fd);
1036
+ await execAsync3(`mkfs.ext4 -F -q "${this.vmOverlayPath}"`);
1037
+ this.log(`[VM ${this.config.vmId}] Overlay created`);
1038
+ };
1039
+ const [, networkConfig] = await Promise.all([
1040
+ createOverlay(),
1041
+ createTapDevice(this.config.vmId, this.log.bind(this))
1042
+ ]);
1043
+ this.networkConfig = networkConfig;
1044
+ this.log(`[VM ${this.config.vmId}] Starting Firecracker...`);
1033
1045
  this.process = spawn(
1034
1046
  this.config.firecrackerBinary,
1035
1047
  ["--api-sock", this.socketPath],
@@ -1040,11 +1052,11 @@ var FirecrackerVM = class {
1040
1052
  }
1041
1053
  );
1042
1054
  this.process.on("error", (err) => {
1043
- console.error(`[VM ${this.config.vmId}] Firecracker error:`, err);
1055
+ this.log(`[VM ${this.config.vmId}] Firecracker error: ${err}`);
1044
1056
  this.state = "error";
1045
1057
  });
1046
1058
  this.process.on("exit", (code, signal) => {
1047
- console.log(
1059
+ this.log(
1048
1060
  `[VM ${this.config.vmId}] Firecracker exited: code=${code}, signal=${signal}`
1049
1061
  );
1050
1062
  if (this.state !== "stopped") {
@@ -1057,7 +1069,7 @@ var FirecrackerVM = class {
1057
1069
  });
1058
1070
  stdoutRL.on("line", (line) => {
1059
1071
  if (line.trim()) {
1060
- console.log(`[VM ${this.config.vmId}] ${line}`);
1072
+ this.log(`[VM ${this.config.vmId}] ${line}`);
1061
1073
  }
1062
1074
  });
1063
1075
  }
@@ -1067,19 +1079,19 @@ var FirecrackerVM = class {
1067
1079
  });
1068
1080
  stderrRL.on("line", (line) => {
1069
1081
  if (line.trim()) {
1070
- console.error(`[VM ${this.config.vmId}] stderr: ${line}`);
1082
+ this.log(`[VM ${this.config.vmId}] stderr: ${line}`);
1071
1083
  }
1072
1084
  });
1073
1085
  }
1074
1086
  this.client = new FirecrackerClient(this.socketPath);
1075
- console.log(`[VM ${this.config.vmId}] Waiting for API...`);
1087
+ this.log(`[VM ${this.config.vmId}] Waiting for API...`);
1076
1088
  await this.client.waitUntilReady(1e4, 100);
1077
1089
  this.state = "configuring";
1078
1090
  await this.configure();
1079
- console.log(`[VM ${this.config.vmId}] Booting...`);
1091
+ this.log(`[VM ${this.config.vmId}] Booting...`);
1080
1092
  await this.client.start();
1081
1093
  this.state = "running";
1082
- console.log(
1094
+ this.log(
1083
1095
  `[VM ${this.config.vmId}] Running at ${this.networkConfig.guestIp}`
1084
1096
  );
1085
1097
  } catch (error) {
@@ -1095,7 +1107,7 @@ var FirecrackerVM = class {
1095
1107
  if (!this.client || !this.networkConfig) {
1096
1108
  throw new Error("VM not properly initialized");
1097
1109
  }
1098
- console.log(
1110
+ this.log(
1099
1111
  `[VM ${this.config.vmId}] Configuring: ${this.config.vcpus} vCPUs, ${this.config.memoryMb}MB RAM`
1100
1112
  );
1101
1113
  await this.client.setMachineConfig({
@@ -1104,28 +1116,26 @@ var FirecrackerVM = class {
1104
1116
  });
1105
1117
  const networkBootArgs = generateNetworkBootArgs(this.networkConfig);
1106
1118
  const bootArgs = `console=ttyS0 reboot=k panic=1 pci=off nomodules random.trust_cpu=on quiet loglevel=0 nokaslr audit=0 numa=off mitigations=off noresume init=/sbin/vm-init ${networkBootArgs}`;
1107
- console.log(`[VM ${this.config.vmId}] Boot args: ${bootArgs}`);
1119
+ this.log(`[VM ${this.config.vmId}] Boot args: ${bootArgs}`);
1108
1120
  await this.client.setBootSource({
1109
1121
  kernel_image_path: this.config.kernelPath,
1110
1122
  boot_args: bootArgs
1111
1123
  });
1112
- console.log(
1113
- `[VM ${this.config.vmId}] Base rootfs: ${this.config.rootfsPath}`
1114
- );
1124
+ this.log(`[VM ${this.config.vmId}] Base rootfs: ${this.config.rootfsPath}`);
1115
1125
  await this.client.setDrive({
1116
1126
  drive_id: "rootfs",
1117
1127
  path_on_host: this.config.rootfsPath,
1118
1128
  is_root_device: true,
1119
1129
  is_read_only: true
1120
1130
  });
1121
- console.log(`[VM ${this.config.vmId}] Overlay: ${this.vmOverlayPath}`);
1131
+ this.log(`[VM ${this.config.vmId}] Overlay: ${this.vmOverlayPath}`);
1122
1132
  await this.client.setDrive({
1123
1133
  drive_id: "overlay",
1124
1134
  path_on_host: this.vmOverlayPath,
1125
1135
  is_root_device: false,
1126
1136
  is_read_only: false
1127
1137
  });
1128
- console.log(
1138
+ this.log(
1129
1139
  `[VM ${this.config.vmId}] Network: ${this.networkConfig.tapDevice}`
1130
1140
  );
1131
1141
  await this.client.setNetworkInterface({
@@ -1133,7 +1143,7 @@ var FirecrackerVM = class {
1133
1143
  guest_mac: this.networkConfig.guestMac,
1134
1144
  host_dev_name: this.networkConfig.tapDevice
1135
1145
  });
1136
- console.log(`[VM ${this.config.vmId}] Vsock: ${this.vsockPath}`);
1146
+ this.log(`[VM ${this.config.vmId}] Vsock: ${this.vsockPath}`);
1137
1147
  await this.client.setVsock({
1138
1148
  vsock_id: "vsock0",
1139
1149
  guest_cid: 3,
@@ -1145,17 +1155,16 @@ var FirecrackerVM = class {
1145
1155
  */
1146
1156
  async stop() {
1147
1157
  if (this.state !== "running") {
1148
- console.log(`[VM ${this.config.vmId}] Not running, state: ${this.state}`);
1158
+ this.log(`[VM ${this.config.vmId}] Not running, state: ${this.state}`);
1149
1159
  return;
1150
1160
  }
1151
1161
  this.state = "stopping";
1152
- console.log(`[VM ${this.config.vmId}] Stopping...`);
1162
+ this.log(`[VM ${this.config.vmId}] Stopping...`);
1153
1163
  try {
1154
1164
  if (this.client) {
1155
1165
  await this.client.sendCtrlAltDel().catch((error) => {
1156
- console.log(
1157
- `[VM ${this.config.vmId}] Graceful shutdown signal failed (VM may already be stopping):`,
1158
- error instanceof Error ? error.message : error
1166
+ this.log(
1167
+ `[VM ${this.config.vmId}] Graceful shutdown signal failed (VM may already be stopping): ${error instanceof Error ? error.message : error}`
1159
1168
  );
1160
1169
  });
1161
1170
  }
@@ -1167,7 +1176,7 @@ var FirecrackerVM = class {
1167
1176
  * Force kill the VM
1168
1177
  */
1169
1178
  async kill() {
1170
- console.log(`[VM ${this.config.vmId}] Force killing...`);
1179
+ this.log(`[VM ${this.config.vmId}] Force killing...`);
1171
1180
  await this.cleanup();
1172
1181
  }
1173
1182
  /**
@@ -1192,7 +1201,7 @@ var FirecrackerVM = class {
1192
1201
  }
1193
1202
  this.client = null;
1194
1203
  this.state = "stopped";
1195
- console.log(`[VM ${this.config.vmId}] Stopped`);
1204
+ this.log(`[VM ${this.config.vmId}] Stopped`);
1196
1205
  }
1197
1206
  /**
1198
1207
  * Wait for the VM process to exit
@@ -5626,11 +5635,6 @@ var appStringSchema = z6.string().superRefine((val, ctx) => {
5626
5635
  });
5627
5636
  var agentDefinitionSchema = z6.object({
5628
5637
  description: z6.string().optional(),
5629
- /**
5630
- * @deprecated Use `apps` field instead for pre-installed tools.
5631
- * This field will be removed in a future version.
5632
- */
5633
- image: z6.string().optional(),
5634
5638
  framework: z6.string().min(1, "Framework is required"),
5635
5639
  /**
5636
5640
  * Array of pre-installed apps/tools for the agent environment.
@@ -5640,8 +5644,6 @@ var agentDefinitionSchema = z6.object({
5640
5644
  */
5641
5645
  apps: z6.array(appStringSchema).optional(),
5642
5646
  volumes: z6.array(z6.string()).optional(),
5643
- working_dir: z6.string().optional(),
5644
- // Optional when provider supports auto-config
5645
5647
  environment: z6.record(z6.string(), z6.string()).optional(),
5646
5648
  /**
5647
5649
  * Path to instructions file (e.g., AGENTS.md).
@@ -5668,7 +5670,17 @@ var agentDefinitionSchema = z6.object({
5668
5670
  * Requires experimental_runner to be configured.
5669
5671
  * When enabled, filters outbound traffic by domain/IP rules.
5670
5672
  */
5671
- experimental_firewall: experimentalFirewallSchema.optional()
5673
+ experimental_firewall: experimentalFirewallSchema.optional(),
5674
+ /**
5675
+ * @deprecated Server-resolved field. User input is ignored.
5676
+ * @internal
5677
+ */
5678
+ image: z6.string().optional(),
5679
+ /**
5680
+ * @deprecated Server-resolved field. User input is ignored.
5681
+ * @internal
5682
+ */
5683
+ working_dir: z6.string().optional()
5672
5684
  });
5673
5685
  var agentComposeContentSchema = z6.object({
5674
5686
  version: z6.string().min(1, "Version is required"),
@@ -6800,13 +6812,11 @@ var scopeResponseSchema = z14.object({
6800
6812
  id: z14.string().uuid(),
6801
6813
  slug: z14.string(),
6802
6814
  type: scopeTypeSchema,
6803
- displayName: z14.string().nullable(),
6804
6815
  createdAt: z14.string(),
6805
6816
  updatedAt: z14.string()
6806
6817
  });
6807
6818
  var createScopeRequestSchema = z14.object({
6808
- slug: scopeSlugSchema,
6809
- displayName: z14.string().max(128).optional()
6819
+ slug: scopeSlugSchema
6810
6820
  });
6811
6821
  var updateScopeRequestSchema = z14.object({
6812
6822
  slug: scopeSlugSchema,
@@ -7453,6 +7463,9 @@ var realtimeTokenContract = c14.router({
7453
7463
  }
7454
7464
  });
7455
7465
 
7466
+ // ../../packages/core/src/contracts/platform.ts
7467
+ import { z as z21 } from "zod";
7468
+
7456
7469
  // ../../packages/core/src/contracts/public/common.ts
7457
7470
  import { z as z20 } from "zod";
7458
7471
  var publicApiErrorTypeSchema = z20.enum([
@@ -7493,29 +7506,92 @@ var listQuerySchema = z20.object({
7493
7506
  var requestIdSchema = z20.string().uuid();
7494
7507
  var timestampSchema = z20.string().datetime();
7495
7508
 
7496
- // ../../packages/core/src/contracts/public/agents.ts
7497
- import { z as z21 } from "zod";
7509
+ // ../../packages/core/src/contracts/platform.ts
7498
7510
  var c15 = initContract();
7499
- var publicAgentSchema = z21.object({
7500
- id: z21.string(),
7501
- name: z21.string(),
7502
- current_version_id: z21.string().nullable(),
7511
+ var platformLogStatusSchema = z21.enum([
7512
+ "pending",
7513
+ "running",
7514
+ "completed",
7515
+ "failed",
7516
+ "timeout",
7517
+ "cancelled"
7518
+ ]);
7519
+ var platformLogEntrySchema = z21.object({
7520
+ id: z21.string().uuid()
7521
+ });
7522
+ var platformLogsListResponseSchema = createPaginatedResponseSchema(
7523
+ platformLogEntrySchema
7524
+ );
7525
+ var artifactSchema = z21.object({
7526
+ name: z21.string().nullable(),
7527
+ version: z21.string().nullable()
7528
+ });
7529
+ var platformLogDetailSchema = z21.object({
7530
+ id: z21.string().uuid(),
7531
+ sessionId: z21.string().nullable(),
7532
+ agentName: z21.string(),
7533
+ provider: z21.string(),
7534
+ status: platformLogStatusSchema,
7535
+ prompt: z21.string(),
7536
+ error: z21.string().nullable(),
7537
+ createdAt: z21.string(),
7538
+ startedAt: z21.string().nullable(),
7539
+ completedAt: z21.string().nullable(),
7540
+ artifact: artifactSchema
7541
+ });
7542
+ var platformLogsListContract = c15.router({
7543
+ list: {
7544
+ method: "GET",
7545
+ path: "/api/platform/logs",
7546
+ query: listQuerySchema.extend({
7547
+ search: z21.string().optional()
7548
+ }),
7549
+ responses: {
7550
+ 200: platformLogsListResponseSchema,
7551
+ 401: apiErrorSchema
7552
+ },
7553
+ summary: "List agent run logs with pagination"
7554
+ }
7555
+ });
7556
+ var platformLogsByIdContract = c15.router({
7557
+ getById: {
7558
+ method: "GET",
7559
+ path: "/api/platform/logs/:id",
7560
+ pathParams: z21.object({
7561
+ id: z21.string().uuid("Invalid log ID")
7562
+ }),
7563
+ responses: {
7564
+ 200: platformLogDetailSchema,
7565
+ 401: apiErrorSchema,
7566
+ 404: apiErrorSchema
7567
+ },
7568
+ summary: "Get agent run log details by ID"
7569
+ }
7570
+ });
7571
+
7572
+ // ../../packages/core/src/contracts/public/agents.ts
7573
+ import { z as z22 } from "zod";
7574
+ var c16 = initContract();
7575
+ var publicAgentSchema = z22.object({
7576
+ id: z22.string(),
7577
+ name: z22.string(),
7578
+ current_version_id: z22.string().nullable(),
7503
7579
  created_at: timestampSchema,
7504
7580
  updated_at: timestampSchema
7505
7581
  });
7506
- var agentVersionSchema = z21.object({
7507
- id: z21.string(),
7508
- agent_id: z21.string(),
7509
- version_number: z21.number(),
7582
+ var agentVersionSchema = z22.object({
7583
+ id: z22.string(),
7584
+ agent_id: z22.string(),
7585
+ version_number: z22.number(),
7510
7586
  created_at: timestampSchema
7511
7587
  });
7512
7588
  var publicAgentDetailSchema = publicAgentSchema;
7513
7589
  var paginatedAgentsSchema = createPaginatedResponseSchema(publicAgentSchema);
7514
7590
  var paginatedAgentVersionsSchema = createPaginatedResponseSchema(agentVersionSchema);
7515
7591
  var agentListQuerySchema = listQuerySchema.extend({
7516
- name: z21.string().optional()
7592
+ name: z22.string().optional()
7517
7593
  });
7518
- var publicAgentsListContract = c15.router({
7594
+ var publicAgentsListContract = c16.router({
7519
7595
  list: {
7520
7596
  method: "GET",
7521
7597
  path: "/v1/agents",
@@ -7530,13 +7606,13 @@ var publicAgentsListContract = c15.router({
7530
7606
  description: "List all agents in the current scope with pagination. Use the `name` query parameter to filter by agent name."
7531
7607
  }
7532
7608
  });
7533
- var publicAgentByIdContract = c15.router({
7609
+ var publicAgentByIdContract = c16.router({
7534
7610
  get: {
7535
7611
  method: "GET",
7536
7612
  path: "/v1/agents/:id",
7537
7613
  headers: authHeadersSchema,
7538
- pathParams: z21.object({
7539
- id: z21.string().min(1, "Agent ID is required")
7614
+ pathParams: z22.object({
7615
+ id: z22.string().min(1, "Agent ID is required")
7540
7616
  }),
7541
7617
  responses: {
7542
7618
  200: publicAgentDetailSchema,
@@ -7548,13 +7624,13 @@ var publicAgentByIdContract = c15.router({
7548
7624
  description: "Get agent details by ID"
7549
7625
  }
7550
7626
  });
7551
- var publicAgentVersionsContract = c15.router({
7627
+ var publicAgentVersionsContract = c16.router({
7552
7628
  list: {
7553
7629
  method: "GET",
7554
7630
  path: "/v1/agents/:id/versions",
7555
7631
  headers: authHeadersSchema,
7556
- pathParams: z21.object({
7557
- id: z21.string().min(1, "Agent ID is required")
7632
+ pathParams: z22.object({
7633
+ id: z22.string().min(1, "Agent ID is required")
7558
7634
  }),
7559
7635
  query: listQuerySchema,
7560
7636
  responses: {
@@ -7569,9 +7645,9 @@ var publicAgentVersionsContract = c15.router({
7569
7645
  });
7570
7646
 
7571
7647
  // ../../packages/core/src/contracts/public/runs.ts
7572
- import { z as z22 } from "zod";
7573
- var c16 = initContract();
7574
- var publicRunStatusSchema = z22.enum([
7648
+ import { z as z23 } from "zod";
7649
+ var c17 = initContract();
7650
+ var publicRunStatusSchema = z23.enum([
7575
7651
  "pending",
7576
7652
  "running",
7577
7653
  "completed",
@@ -7579,56 +7655,56 @@ var publicRunStatusSchema = z22.enum([
7579
7655
  "timeout",
7580
7656
  "cancelled"
7581
7657
  ]);
7582
- var publicRunSchema = z22.object({
7583
- id: z22.string(),
7584
- agent_id: z22.string(),
7585
- agent_name: z22.string(),
7658
+ var publicRunSchema = z23.object({
7659
+ id: z23.string(),
7660
+ agent_id: z23.string(),
7661
+ agent_name: z23.string(),
7586
7662
  status: publicRunStatusSchema,
7587
- prompt: z22.string(),
7663
+ prompt: z23.string(),
7588
7664
  created_at: timestampSchema,
7589
7665
  started_at: timestampSchema.nullable(),
7590
7666
  completed_at: timestampSchema.nullable()
7591
7667
  });
7592
7668
  var publicRunDetailSchema = publicRunSchema.extend({
7593
- error: z22.string().nullable(),
7594
- execution_time_ms: z22.number().nullable(),
7595
- checkpoint_id: z22.string().nullable(),
7596
- session_id: z22.string().nullable(),
7597
- artifact_name: z22.string().nullable(),
7598
- artifact_version: z22.string().nullable(),
7599
- volumes: z22.record(z22.string(), z22.string()).optional()
7669
+ error: z23.string().nullable(),
7670
+ execution_time_ms: z23.number().nullable(),
7671
+ checkpoint_id: z23.string().nullable(),
7672
+ session_id: z23.string().nullable(),
7673
+ artifact_name: z23.string().nullable(),
7674
+ artifact_version: z23.string().nullable(),
7675
+ volumes: z23.record(z23.string(), z23.string()).optional()
7600
7676
  });
7601
7677
  var paginatedRunsSchema = createPaginatedResponseSchema(publicRunSchema);
7602
- var createRunRequestSchema = z22.object({
7678
+ var createRunRequestSchema = z23.object({
7603
7679
  // Agent identification (one of: agent, agent_id, session_id, checkpoint_id)
7604
- agent: z22.string().optional(),
7680
+ agent: z23.string().optional(),
7605
7681
  // Agent name
7606
- agent_id: z22.string().optional(),
7682
+ agent_id: z23.string().optional(),
7607
7683
  // Agent ID
7608
- agent_version: z22.string().optional(),
7684
+ agent_version: z23.string().optional(),
7609
7685
  // Version specifier (e.g., "latest", "v1", specific ID)
7610
7686
  // Continue session
7611
- session_id: z22.string().optional(),
7687
+ session_id: z23.string().optional(),
7612
7688
  // Resume from checkpoint
7613
- checkpoint_id: z22.string().optional(),
7689
+ checkpoint_id: z23.string().optional(),
7614
7690
  // Required
7615
- prompt: z22.string().min(1, "Prompt is required"),
7691
+ prompt: z23.string().min(1, "Prompt is required"),
7616
7692
  // Optional configuration
7617
- variables: z22.record(z22.string(), z22.string()).optional(),
7618
- secrets: z22.record(z22.string(), z22.string()).optional(),
7619
- artifact_name: z22.string().optional(),
7693
+ variables: z23.record(z23.string(), z23.string()).optional(),
7694
+ secrets: z23.record(z23.string(), z23.string()).optional(),
7695
+ artifact_name: z23.string().optional(),
7620
7696
  // Artifact name to mount
7621
- artifact_version: z22.string().optional(),
7697
+ artifact_version: z23.string().optional(),
7622
7698
  // Artifact version (defaults to latest)
7623
- volumes: z22.record(z22.string(), z22.string()).optional()
7699
+ volumes: z23.record(z23.string(), z23.string()).optional()
7624
7700
  // volume_name -> version
7625
7701
  });
7626
7702
  var runListQuerySchema = listQuerySchema.extend({
7627
- agent_id: z22.string().optional(),
7703
+ agent_id: z23.string().optional(),
7628
7704
  status: publicRunStatusSchema.optional(),
7629
7705
  since: timestampSchema.optional()
7630
7706
  });
7631
- var publicRunsListContract = c16.router({
7707
+ var publicRunsListContract = c17.router({
7632
7708
  list: {
7633
7709
  method: "GET",
7634
7710
  path: "/v1/runs",
@@ -7659,13 +7735,13 @@ var publicRunsListContract = c16.router({
7659
7735
  description: "Create and execute a new agent run. Returns 202 Accepted as runs execute asynchronously."
7660
7736
  }
7661
7737
  });
7662
- var publicRunByIdContract = c16.router({
7738
+ var publicRunByIdContract = c17.router({
7663
7739
  get: {
7664
7740
  method: "GET",
7665
7741
  path: "/v1/runs/:id",
7666
7742
  headers: authHeadersSchema,
7667
- pathParams: z22.object({
7668
- id: z22.string().min(1, "Run ID is required")
7743
+ pathParams: z23.object({
7744
+ id: z23.string().min(1, "Run ID is required")
7669
7745
  }),
7670
7746
  responses: {
7671
7747
  200: publicRunDetailSchema,
@@ -7677,15 +7753,15 @@ var publicRunByIdContract = c16.router({
7677
7753
  description: "Get run details by ID"
7678
7754
  }
7679
7755
  });
7680
- var publicRunCancelContract = c16.router({
7756
+ var publicRunCancelContract = c17.router({
7681
7757
  cancel: {
7682
7758
  method: "POST",
7683
7759
  path: "/v1/runs/:id/cancel",
7684
7760
  headers: authHeadersSchema,
7685
- pathParams: z22.object({
7686
- id: z22.string().min(1, "Run ID is required")
7761
+ pathParams: z23.object({
7762
+ id: z23.string().min(1, "Run ID is required")
7687
7763
  }),
7688
- body: z22.undefined(),
7764
+ body: z23.undefined(),
7689
7765
  responses: {
7690
7766
  200: publicRunDetailSchema,
7691
7767
  400: publicApiErrorSchema,
@@ -7698,27 +7774,27 @@ var publicRunCancelContract = c16.router({
7698
7774
  description: "Cancel a pending or running execution"
7699
7775
  }
7700
7776
  });
7701
- var logEntrySchema = z22.object({
7777
+ var logEntrySchema = z23.object({
7702
7778
  timestamp: timestampSchema,
7703
- type: z22.enum(["agent", "system", "network"]),
7704
- level: z22.enum(["debug", "info", "warn", "error"]),
7705
- message: z22.string(),
7706
- metadata: z22.record(z22.string(), z22.unknown()).optional()
7779
+ type: z23.enum(["agent", "system", "network"]),
7780
+ level: z23.enum(["debug", "info", "warn", "error"]),
7781
+ message: z23.string(),
7782
+ metadata: z23.record(z23.string(), z23.unknown()).optional()
7707
7783
  });
7708
7784
  var paginatedLogsSchema = createPaginatedResponseSchema(logEntrySchema);
7709
7785
  var logsQuerySchema = listQuerySchema.extend({
7710
- type: z22.enum(["agent", "system", "network", "all"]).default("all"),
7786
+ type: z23.enum(["agent", "system", "network", "all"]).default("all"),
7711
7787
  since: timestampSchema.optional(),
7712
7788
  until: timestampSchema.optional(),
7713
- order: z22.enum(["asc", "desc"]).default("asc")
7789
+ order: z23.enum(["asc", "desc"]).default("asc")
7714
7790
  });
7715
- var publicRunLogsContract = c16.router({
7791
+ var publicRunLogsContract = c17.router({
7716
7792
  getLogs: {
7717
7793
  method: "GET",
7718
7794
  path: "/v1/runs/:id/logs",
7719
7795
  headers: authHeadersSchema,
7720
- pathParams: z22.object({
7721
- id: z22.string().min(1, "Run ID is required")
7796
+ pathParams: z23.object({
7797
+ id: z23.string().min(1, "Run ID is required")
7722
7798
  }),
7723
7799
  query: logsQuerySchema,
7724
7800
  responses: {
@@ -7731,30 +7807,30 @@ var publicRunLogsContract = c16.router({
7731
7807
  description: "Get unified logs for a run. Combines agent, system, and network logs."
7732
7808
  }
7733
7809
  });
7734
- var metricPointSchema = z22.object({
7810
+ var metricPointSchema = z23.object({
7735
7811
  timestamp: timestampSchema,
7736
- cpu_percent: z22.number(),
7737
- memory_used_mb: z22.number(),
7738
- memory_total_mb: z22.number(),
7739
- disk_used_mb: z22.number(),
7740
- disk_total_mb: z22.number()
7741
- });
7742
- var metricsSummarySchema = z22.object({
7743
- avg_cpu_percent: z22.number(),
7744
- max_memory_used_mb: z22.number(),
7745
- total_duration_ms: z22.number().nullable()
7746
- });
7747
- var metricsResponseSchema2 = z22.object({
7748
- data: z22.array(metricPointSchema),
7812
+ cpu_percent: z23.number(),
7813
+ memory_used_mb: z23.number(),
7814
+ memory_total_mb: z23.number(),
7815
+ disk_used_mb: z23.number(),
7816
+ disk_total_mb: z23.number()
7817
+ });
7818
+ var metricsSummarySchema = z23.object({
7819
+ avg_cpu_percent: z23.number(),
7820
+ max_memory_used_mb: z23.number(),
7821
+ total_duration_ms: z23.number().nullable()
7822
+ });
7823
+ var metricsResponseSchema2 = z23.object({
7824
+ data: z23.array(metricPointSchema),
7749
7825
  summary: metricsSummarySchema
7750
7826
  });
7751
- var publicRunMetricsContract = c16.router({
7827
+ var publicRunMetricsContract = c17.router({
7752
7828
  getMetrics: {
7753
7829
  method: "GET",
7754
7830
  path: "/v1/runs/:id/metrics",
7755
7831
  headers: authHeadersSchema,
7756
- pathParams: z22.object({
7757
- id: z22.string().min(1, "Run ID is required")
7832
+ pathParams: z23.object({
7833
+ id: z23.string().min(1, "Run ID is required")
7758
7834
  }),
7759
7835
  responses: {
7760
7836
  200: metricsResponseSchema2,
@@ -7766,7 +7842,7 @@ var publicRunMetricsContract = c16.router({
7766
7842
  description: "Get CPU, memory, and disk metrics for a run"
7767
7843
  }
7768
7844
  });
7769
- var sseEventTypeSchema = z22.enum([
7845
+ var sseEventTypeSchema = z23.enum([
7770
7846
  "status",
7771
7847
  // Run status change
7772
7848
  "output",
@@ -7778,26 +7854,26 @@ var sseEventTypeSchema = z22.enum([
7778
7854
  "heartbeat"
7779
7855
  // Keep-alive
7780
7856
  ]);
7781
- var sseEventSchema = z22.object({
7857
+ var sseEventSchema = z23.object({
7782
7858
  event: sseEventTypeSchema,
7783
- data: z22.unknown(),
7784
- id: z22.string().optional()
7859
+ data: z23.unknown(),
7860
+ id: z23.string().optional()
7785
7861
  // For Last-Event-ID reconnection
7786
7862
  });
7787
- var publicRunEventsContract = c16.router({
7863
+ var publicRunEventsContract = c17.router({
7788
7864
  streamEvents: {
7789
7865
  method: "GET",
7790
7866
  path: "/v1/runs/:id/events",
7791
7867
  headers: authHeadersSchema,
7792
- pathParams: z22.object({
7793
- id: z22.string().min(1, "Run ID is required")
7868
+ pathParams: z23.object({
7869
+ id: z23.string().min(1, "Run ID is required")
7794
7870
  }),
7795
- query: z22.object({
7796
- last_event_id: z22.string().optional()
7871
+ query: z23.object({
7872
+ last_event_id: z23.string().optional()
7797
7873
  // For reconnection
7798
7874
  }),
7799
7875
  responses: {
7800
- 200: z22.any(),
7876
+ 200: z23.any(),
7801
7877
  // SSE stream - actual content is text/event-stream
7802
7878
  401: publicApiErrorSchema,
7803
7879
  404: publicApiErrorSchema,
@@ -7809,28 +7885,28 @@ var publicRunEventsContract = c16.router({
7809
7885
  });
7810
7886
 
7811
7887
  // ../../packages/core/src/contracts/public/artifacts.ts
7812
- import { z as z23 } from "zod";
7813
- var c17 = initContract();
7814
- var publicArtifactSchema = z23.object({
7815
- id: z23.string(),
7816
- name: z23.string(),
7817
- current_version_id: z23.string().nullable(),
7818
- size: z23.number(),
7888
+ import { z as z24 } from "zod";
7889
+ var c18 = initContract();
7890
+ var publicArtifactSchema = z24.object({
7891
+ id: z24.string(),
7892
+ name: z24.string(),
7893
+ current_version_id: z24.string().nullable(),
7894
+ size: z24.number(),
7819
7895
  // Total size in bytes
7820
- file_count: z23.number(),
7896
+ file_count: z24.number(),
7821
7897
  created_at: timestampSchema,
7822
7898
  updated_at: timestampSchema
7823
7899
  });
7824
- var artifactVersionSchema = z23.object({
7825
- id: z23.string(),
7900
+ var artifactVersionSchema = z24.object({
7901
+ id: z24.string(),
7826
7902
  // SHA-256 content hash
7827
- artifact_id: z23.string(),
7828
- size: z23.number(),
7903
+ artifact_id: z24.string(),
7904
+ size: z24.number(),
7829
7905
  // Size in bytes
7830
- file_count: z23.number(),
7831
- message: z23.string().nullable(),
7906
+ file_count: z24.number(),
7907
+ message: z24.string().nullable(),
7832
7908
  // Optional commit message
7833
- created_by: z23.string(),
7909
+ created_by: z24.string(),
7834
7910
  created_at: timestampSchema
7835
7911
  });
7836
7912
  var publicArtifactDetailSchema = publicArtifactSchema.extend({
@@ -7840,7 +7916,7 @@ var paginatedArtifactsSchema = createPaginatedResponseSchema(publicArtifactSchem
7840
7916
  var paginatedArtifactVersionsSchema = createPaginatedResponseSchema(
7841
7917
  artifactVersionSchema
7842
7918
  );
7843
- var publicArtifactsListContract = c17.router({
7919
+ var publicArtifactsListContract = c18.router({
7844
7920
  list: {
7845
7921
  method: "GET",
7846
7922
  path: "/v1/artifacts",
@@ -7855,13 +7931,13 @@ var publicArtifactsListContract = c17.router({
7855
7931
  description: "List all artifacts in the current scope with pagination"
7856
7932
  }
7857
7933
  });
7858
- var publicArtifactByIdContract = c17.router({
7934
+ var publicArtifactByIdContract = c18.router({
7859
7935
  get: {
7860
7936
  method: "GET",
7861
7937
  path: "/v1/artifacts/:id",
7862
7938
  headers: authHeadersSchema,
7863
- pathParams: z23.object({
7864
- id: z23.string().min(1, "Artifact ID is required")
7939
+ pathParams: z24.object({
7940
+ id: z24.string().min(1, "Artifact ID is required")
7865
7941
  }),
7866
7942
  responses: {
7867
7943
  200: publicArtifactDetailSchema,
@@ -7873,13 +7949,13 @@ var publicArtifactByIdContract = c17.router({
7873
7949
  description: "Get artifact details by ID"
7874
7950
  }
7875
7951
  });
7876
- var publicArtifactVersionsContract = c17.router({
7952
+ var publicArtifactVersionsContract = c18.router({
7877
7953
  list: {
7878
7954
  method: "GET",
7879
7955
  path: "/v1/artifacts/:id/versions",
7880
7956
  headers: authHeadersSchema,
7881
- pathParams: z23.object({
7882
- id: z23.string().min(1, "Artifact ID is required")
7957
+ pathParams: z24.object({
7958
+ id: z24.string().min(1, "Artifact ID is required")
7883
7959
  }),
7884
7960
  query: listQuerySchema,
7885
7961
  responses: {
@@ -7892,20 +7968,20 @@ var publicArtifactVersionsContract = c17.router({
7892
7968
  description: "List all versions of an artifact with pagination"
7893
7969
  }
7894
7970
  });
7895
- var publicArtifactDownloadContract = c17.router({
7971
+ var publicArtifactDownloadContract = c18.router({
7896
7972
  download: {
7897
7973
  method: "GET",
7898
7974
  path: "/v1/artifacts/:id/download",
7899
7975
  headers: authHeadersSchema,
7900
- pathParams: z23.object({
7901
- id: z23.string().min(1, "Artifact ID is required")
7976
+ pathParams: z24.object({
7977
+ id: z24.string().min(1, "Artifact ID is required")
7902
7978
  }),
7903
- query: z23.object({
7904
- version_id: z23.string().optional()
7979
+ query: z24.object({
7980
+ version_id: z24.string().optional()
7905
7981
  // Defaults to current version
7906
7982
  }),
7907
7983
  responses: {
7908
- 302: z23.undefined(),
7984
+ 302: z24.undefined(),
7909
7985
  // Redirect to presigned URL
7910
7986
  401: publicApiErrorSchema,
7911
7987
  404: publicApiErrorSchema,
@@ -7917,28 +7993,28 @@ var publicArtifactDownloadContract = c17.router({
7917
7993
  });
7918
7994
 
7919
7995
  // ../../packages/core/src/contracts/public/volumes.ts
7920
- import { z as z24 } from "zod";
7921
- var c18 = initContract();
7922
- var publicVolumeSchema = z24.object({
7923
- id: z24.string(),
7924
- name: z24.string(),
7925
- current_version_id: z24.string().nullable(),
7926
- size: z24.number(),
7996
+ import { z as z25 } from "zod";
7997
+ var c19 = initContract();
7998
+ var publicVolumeSchema = z25.object({
7999
+ id: z25.string(),
8000
+ name: z25.string(),
8001
+ current_version_id: z25.string().nullable(),
8002
+ size: z25.number(),
7927
8003
  // Total size in bytes
7928
- file_count: z24.number(),
8004
+ file_count: z25.number(),
7929
8005
  created_at: timestampSchema,
7930
8006
  updated_at: timestampSchema
7931
8007
  });
7932
- var volumeVersionSchema = z24.object({
7933
- id: z24.string(),
8008
+ var volumeVersionSchema = z25.object({
8009
+ id: z25.string(),
7934
8010
  // SHA-256 content hash
7935
- volume_id: z24.string(),
7936
- size: z24.number(),
8011
+ volume_id: z25.string(),
8012
+ size: z25.number(),
7937
8013
  // Size in bytes
7938
- file_count: z24.number(),
7939
- message: z24.string().nullable(),
8014
+ file_count: z25.number(),
8015
+ message: z25.string().nullable(),
7940
8016
  // Optional commit message
7941
- created_by: z24.string(),
8017
+ created_by: z25.string(),
7942
8018
  created_at: timestampSchema
7943
8019
  });
7944
8020
  var publicVolumeDetailSchema = publicVolumeSchema.extend({
@@ -7946,7 +8022,7 @@ var publicVolumeDetailSchema = publicVolumeSchema.extend({
7946
8022
  });
7947
8023
  var paginatedVolumesSchema = createPaginatedResponseSchema(publicVolumeSchema);
7948
8024
  var paginatedVolumeVersionsSchema = createPaginatedResponseSchema(volumeVersionSchema);
7949
- var publicVolumesListContract = c18.router({
8025
+ var publicVolumesListContract = c19.router({
7950
8026
  list: {
7951
8027
  method: "GET",
7952
8028
  path: "/v1/volumes",
@@ -7961,13 +8037,13 @@ var publicVolumesListContract = c18.router({
7961
8037
  description: "List all volumes in the current scope with pagination"
7962
8038
  }
7963
8039
  });
7964
- var publicVolumeByIdContract = c18.router({
8040
+ var publicVolumeByIdContract = c19.router({
7965
8041
  get: {
7966
8042
  method: "GET",
7967
8043
  path: "/v1/volumes/:id",
7968
8044
  headers: authHeadersSchema,
7969
- pathParams: z24.object({
7970
- id: z24.string().min(1, "Volume ID is required")
8045
+ pathParams: z25.object({
8046
+ id: z25.string().min(1, "Volume ID is required")
7971
8047
  }),
7972
8048
  responses: {
7973
8049
  200: publicVolumeDetailSchema,
@@ -7979,13 +8055,13 @@ var publicVolumeByIdContract = c18.router({
7979
8055
  description: "Get volume details by ID"
7980
8056
  }
7981
8057
  });
7982
- var publicVolumeVersionsContract = c18.router({
8058
+ var publicVolumeVersionsContract = c19.router({
7983
8059
  list: {
7984
8060
  method: "GET",
7985
8061
  path: "/v1/volumes/:id/versions",
7986
8062
  headers: authHeadersSchema,
7987
- pathParams: z24.object({
7988
- id: z24.string().min(1, "Volume ID is required")
8063
+ pathParams: z25.object({
8064
+ id: z25.string().min(1, "Volume ID is required")
7989
8065
  }),
7990
8066
  query: listQuerySchema,
7991
8067
  responses: {
@@ -7998,20 +8074,20 @@ var publicVolumeVersionsContract = c18.router({
7998
8074
  description: "List all versions of a volume with pagination"
7999
8075
  }
8000
8076
  });
8001
- var publicVolumeDownloadContract = c18.router({
8077
+ var publicVolumeDownloadContract = c19.router({
8002
8078
  download: {
8003
8079
  method: "GET",
8004
8080
  path: "/v1/volumes/:id/download",
8005
8081
  headers: authHeadersSchema,
8006
- pathParams: z24.object({
8007
- id: z24.string().min(1, "Volume ID is required")
8082
+ pathParams: z25.object({
8083
+ id: z25.string().min(1, "Volume ID is required")
8008
8084
  }),
8009
- query: z24.object({
8010
- version_id: z24.string().optional()
8085
+ query: z25.object({
8086
+ version_id: z25.string().optional()
8011
8087
  // Defaults to current version
8012
8088
  }),
8013
8089
  responses: {
8014
- 302: z24.undefined(),
8090
+ 302: z25.undefined(),
8015
8091
  // Redirect to presigned URL
8016
8092
  401: publicApiErrorSchema,
8017
8093
  404: publicApiErrorSchema,
@@ -9299,7 +9375,8 @@ async function executeJob(context, config, options = {}) {
9299
9375
  kernelPath: config.firecracker.kernel,
9300
9376
  rootfsPath: config.firecracker.rootfs,
9301
9377
  firecrackerBinary: config.firecracker.binary,
9302
- workDir: path4.join(workspacesDir, `vm0-${vmId}`)
9378
+ workDir: path4.join(workspacesDir, `vm0-${vmId}`),
9379
+ logger: log
9303
9380
  };
9304
9381
  log(`[Executor] Creating VM ${vmId}...`);
9305
9382
  vm = new FirecrackerVM(vmConfig);
@@ -10253,14 +10330,14 @@ var Timer = class {
10253
10330
  this.startTime = Date.now();
10254
10331
  }
10255
10332
  /**
10256
- * Get elapsed time formatted as [MM:SS.s]
10333
+ * Get elapsed time formatted as [MM:SS.mmm]
10257
10334
  */
10258
10335
  elapsed() {
10259
10336
  const ms = Date.now() - this.startTime;
10260
- const totalSeconds = ms / 1e3;
10261
- const minutes = Math.floor(totalSeconds / 60);
10262
- const seconds = (totalSeconds % 60).toFixed(1);
10263
- return `[${String(minutes).padStart(2, "0")}:${seconds.padStart(4, "0")}]`;
10337
+ const minutes = Math.floor(ms / 6e4);
10338
+ const seconds = Math.floor(ms % 6e4 / 1e3);
10339
+ const millis = ms % 1e3;
10340
+ return `[${String(minutes).padStart(2, "0")}:${String(seconds).padStart(2, "0")}.${String(millis).padStart(3, "0")}]`;
10264
10341
  }
10265
10342
  /**
10266
10343
  * Log message with timestamp
@@ -10334,7 +10411,7 @@ var benchmarkCommand = new Command4("benchmark").description(
10334
10411
  });
10335
10412
 
10336
10413
  // src/index.ts
10337
- var version = true ? "3.0.6" : "0.1.0";
10414
+ var version = true ? "3.2.0" : "0.1.0";
10338
10415
  program.name("vm0-runner").version(version).description("Self-hosted runner for VM0 agents");
10339
10416
  program.addCommand(startCommand);
10340
10417
  program.addCommand(doctorCommand);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vm0/runner",
3
- "version": "3.0.6",
3
+ "version": "3.2.0",
4
4
  "description": "Self-hosted runner for VM0 agents",
5
5
  "repository": {
6
6
  "type": "git",