@vm0/runner 3.12.1 → 3.12.3

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 +563 -965
  2. package/package.json +1 -1
package/index.js CHANGED
@@ -48,7 +48,9 @@ var runnerPaths = {
48
48
  /** Check if a directory name is a VM workspace */
49
49
  isVmWorkspace: (dirname) => dirname.startsWith(VM_WORKSPACE_PREFIX),
50
50
  /** Extract vmId from workspace directory name */
51
- extractVmId: (dirname) => createVmId(dirname.replace(VM_WORKSPACE_PREFIX, ""))
51
+ extractVmId: (dirname) => createVmId(dirname.replace(VM_WORKSPACE_PREFIX, "")),
52
+ /** VM registry file for proxy IP → run mapping */
53
+ vmRegistry: (baseDir) => path.join(baseDir, "vm-registry.json")
52
54
  };
53
55
  var vmPaths = {
54
56
  /** Firecracker config file (used with --config-file) */
@@ -73,8 +75,6 @@ var snapshotOutputPaths = {
73
75
  var tempPaths = {
74
76
  /** Default proxy CA directory */
75
77
  proxyDir: `${VM0_TMP_PREFIX}-proxy`,
76
- /** VM registry for proxy */
77
- vmRegistry: `${VM0_TMP_PREFIX}-vm-registry.json`,
78
78
  /** Network log file for a run */
79
79
  networkLog: (runId) => `${VM0_TMP_PREFIX}-network-${runId}.jsonl`
80
80
  };
@@ -7896,10 +7896,109 @@ var secretsByNameContract = c11.router({
7896
7896
  }
7897
7897
  });
7898
7898
 
7899
- // ../../packages/core/src/contracts/model-providers.ts
7899
+ // ../../packages/core/src/contracts/variables.ts
7900
7900
  import { z as z19 } from "zod";
7901
7901
  var c12 = initContract();
7902
- var modelProviderTypeSchema = z19.enum([
7902
+ var variableNameSchema = z19.string().min(1, "Variable name is required").max(255, "Variable name must be at most 255 characters").regex(
7903
+ /^[A-Z][A-Z0-9_]*$/,
7904
+ "Variable name must contain only uppercase letters, numbers, and underscores, and must start with a letter (e.g., MY_VAR)"
7905
+ );
7906
+ var variableResponseSchema = z19.object({
7907
+ id: z19.string().uuid(),
7908
+ name: z19.string(),
7909
+ value: z19.string(),
7910
+ description: z19.string().nullable(),
7911
+ createdAt: z19.string(),
7912
+ updatedAt: z19.string()
7913
+ });
7914
+ var variableListResponseSchema = z19.object({
7915
+ variables: z19.array(variableResponseSchema)
7916
+ });
7917
+ var setVariableRequestSchema = z19.object({
7918
+ name: variableNameSchema,
7919
+ value: z19.string().min(1, "Variable value is required"),
7920
+ description: z19.string().max(1e3).optional()
7921
+ });
7922
+ var variablesMainContract = c12.router({
7923
+ /**
7924
+ * GET /api/variables
7925
+ * List all variables for the current user's scope (includes values)
7926
+ */
7927
+ list: {
7928
+ method: "GET",
7929
+ path: "/api/variables",
7930
+ headers: authHeadersSchema,
7931
+ responses: {
7932
+ 200: variableListResponseSchema,
7933
+ 401: apiErrorSchema,
7934
+ 500: apiErrorSchema
7935
+ },
7936
+ summary: "List all variables (includes values)"
7937
+ },
7938
+ /**
7939
+ * PUT /api/variables
7940
+ * Create or update a variable
7941
+ */
7942
+ set: {
7943
+ method: "PUT",
7944
+ path: "/api/variables",
7945
+ headers: authHeadersSchema,
7946
+ body: setVariableRequestSchema,
7947
+ responses: {
7948
+ 200: variableResponseSchema,
7949
+ 201: variableResponseSchema,
7950
+ 400: apiErrorSchema,
7951
+ 401: apiErrorSchema,
7952
+ 500: apiErrorSchema
7953
+ },
7954
+ summary: "Create or update a variable"
7955
+ }
7956
+ });
7957
+ var variablesByNameContract = c12.router({
7958
+ /**
7959
+ * GET /api/variables/:name
7960
+ * Get a variable by name (includes value)
7961
+ */
7962
+ get: {
7963
+ method: "GET",
7964
+ path: "/api/variables/:name",
7965
+ headers: authHeadersSchema,
7966
+ pathParams: z19.object({
7967
+ name: variableNameSchema
7968
+ }),
7969
+ responses: {
7970
+ 200: variableResponseSchema,
7971
+ 401: apiErrorSchema,
7972
+ 404: apiErrorSchema,
7973
+ 500: apiErrorSchema
7974
+ },
7975
+ summary: "Get variable by name"
7976
+ },
7977
+ /**
7978
+ * DELETE /api/variables/:name
7979
+ * Delete a variable by name
7980
+ */
7981
+ delete: {
7982
+ method: "DELETE",
7983
+ path: "/api/variables/:name",
7984
+ headers: authHeadersSchema,
7985
+ pathParams: z19.object({
7986
+ name: variableNameSchema
7987
+ }),
7988
+ responses: {
7989
+ 204: c12.noBody(),
7990
+ 401: apiErrorSchema,
7991
+ 404: apiErrorSchema,
7992
+ 500: apiErrorSchema
7993
+ },
7994
+ summary: "Delete a variable"
7995
+ }
7996
+ });
7997
+
7998
+ // ../../packages/core/src/contracts/model-providers.ts
7999
+ import { z as z20 } from "zod";
8000
+ var c13 = initContract();
8001
+ var modelProviderTypeSchema = z20.enum([
7903
8002
  "claude-code-oauth-token",
7904
8003
  "anthropic-api-key",
7905
8004
  "openrouter-api-key",
@@ -7910,46 +8009,46 @@ var modelProviderTypeSchema = z19.enum([
7910
8009
  "azure-foundry",
7911
8010
  "aws-bedrock"
7912
8011
  ]);
7913
- var modelProviderFrameworkSchema = z19.enum(["claude-code", "codex"]);
7914
- var modelProviderResponseSchema = z19.object({
7915
- id: z19.string().uuid(),
8012
+ var modelProviderFrameworkSchema = z20.enum(["claude-code", "codex"]);
8013
+ var modelProviderResponseSchema = z20.object({
8014
+ id: z20.string().uuid(),
7916
8015
  type: modelProviderTypeSchema,
7917
8016
  framework: modelProviderFrameworkSchema,
7918
- credentialName: z19.string().nullable(),
8017
+ credentialName: z20.string().nullable(),
7919
8018
  // Legacy single-credential (deprecated for multi-auth)
7920
- authMethod: z19.string().nullable(),
8019
+ authMethod: z20.string().nullable(),
7921
8020
  // For multi-auth providers
7922
- credentialNames: z19.array(z19.string()).nullable(),
8021
+ credentialNames: z20.array(z20.string()).nullable(),
7923
8022
  // For multi-auth providers
7924
- isDefault: z19.boolean(),
7925
- selectedModel: z19.string().nullable(),
7926
- createdAt: z19.string(),
7927
- updatedAt: z19.string()
8023
+ isDefault: z20.boolean(),
8024
+ selectedModel: z20.string().nullable(),
8025
+ createdAt: z20.string(),
8026
+ updatedAt: z20.string()
7928
8027
  });
7929
- var modelProviderListResponseSchema = z19.object({
7930
- modelProviders: z19.array(modelProviderResponseSchema)
8028
+ var modelProviderListResponseSchema = z20.object({
8029
+ modelProviders: z20.array(modelProviderResponseSchema)
7931
8030
  });
7932
- var upsertModelProviderRequestSchema = z19.object({
8031
+ var upsertModelProviderRequestSchema = z20.object({
7933
8032
  type: modelProviderTypeSchema,
7934
- credential: z19.string().min(1).optional(),
8033
+ credential: z20.string().min(1).optional(),
7935
8034
  // Legacy single credential
7936
- authMethod: z19.string().optional(),
8035
+ authMethod: z20.string().optional(),
7937
8036
  // For multi-auth providers
7938
- credentials: z19.record(z19.string(), z19.string()).optional(),
8037
+ credentials: z20.record(z20.string(), z20.string()).optional(),
7939
8038
  // For multi-auth providers
7940
- convert: z19.boolean().optional(),
7941
- selectedModel: z19.string().optional()
8039
+ convert: z20.boolean().optional(),
8040
+ selectedModel: z20.string().optional()
7942
8041
  });
7943
- var upsertModelProviderResponseSchema = z19.object({
8042
+ var upsertModelProviderResponseSchema = z20.object({
7944
8043
  provider: modelProviderResponseSchema,
7945
- created: z19.boolean()
8044
+ created: z20.boolean()
7946
8045
  });
7947
- var checkCredentialResponseSchema = z19.object({
7948
- exists: z19.boolean(),
7949
- credentialName: z19.string(),
7950
- currentType: z19.enum(["user", "model-provider"]).optional()
8046
+ var checkCredentialResponseSchema = z20.object({
8047
+ exists: z20.boolean(),
8048
+ credentialName: z20.string(),
8049
+ currentType: z20.enum(["user", "model-provider"]).optional()
7951
8050
  });
7952
- var modelProvidersMainContract = c12.router({
8051
+ var modelProvidersMainContract = c13.router({
7953
8052
  list: {
7954
8053
  method: "GET",
7955
8054
  path: "/api/model-providers",
@@ -7977,12 +8076,12 @@ var modelProvidersMainContract = c12.router({
7977
8076
  summary: "Create or update a model provider"
7978
8077
  }
7979
8078
  });
7980
- var modelProvidersCheckContract = c12.router({
8079
+ var modelProvidersCheckContract = c13.router({
7981
8080
  check: {
7982
8081
  method: "GET",
7983
8082
  path: "/api/model-providers/check/:type",
7984
8083
  headers: authHeadersSchema,
7985
- pathParams: z19.object({
8084
+ pathParams: z20.object({
7986
8085
  type: modelProviderTypeSchema
7987
8086
  }),
7988
8087
  responses: {
@@ -7993,16 +8092,16 @@ var modelProvidersCheckContract = c12.router({
7993
8092
  summary: "Check if credential exists for a model provider type"
7994
8093
  }
7995
8094
  });
7996
- var modelProvidersByTypeContract = c12.router({
8095
+ var modelProvidersByTypeContract = c13.router({
7997
8096
  delete: {
7998
8097
  method: "DELETE",
7999
8098
  path: "/api/model-providers/:type",
8000
8099
  headers: authHeadersSchema,
8001
- pathParams: z19.object({
8100
+ pathParams: z20.object({
8002
8101
  type: modelProviderTypeSchema
8003
8102
  }),
8004
8103
  responses: {
8005
- 204: c12.noBody(),
8104
+ 204: c13.noBody(),
8006
8105
  401: apiErrorSchema,
8007
8106
  404: apiErrorSchema,
8008
8107
  500: apiErrorSchema
@@ -8010,15 +8109,15 @@ var modelProvidersByTypeContract = c12.router({
8010
8109
  summary: "Delete a model provider"
8011
8110
  }
8012
8111
  });
8013
- var modelProvidersConvertContract = c12.router({
8112
+ var modelProvidersConvertContract = c13.router({
8014
8113
  convert: {
8015
8114
  method: "POST",
8016
8115
  path: "/api/model-providers/:type/convert",
8017
8116
  headers: authHeadersSchema,
8018
- pathParams: z19.object({
8117
+ pathParams: z20.object({
8019
8118
  type: modelProviderTypeSchema
8020
8119
  }),
8021
- body: z19.undefined(),
8120
+ body: z20.undefined(),
8022
8121
  responses: {
8023
8122
  200: modelProviderResponseSchema,
8024
8123
  400: apiErrorSchema,
@@ -8029,15 +8128,15 @@ var modelProvidersConvertContract = c12.router({
8029
8128
  summary: "Convert existing user credential to model provider"
8030
8129
  }
8031
8130
  });
8032
- var modelProvidersSetDefaultContract = c12.router({
8131
+ var modelProvidersSetDefaultContract = c13.router({
8033
8132
  setDefault: {
8034
8133
  method: "POST",
8035
8134
  path: "/api/model-providers/:type/set-default",
8036
8135
  headers: authHeadersSchema,
8037
- pathParams: z19.object({
8136
+ pathParams: z20.object({
8038
8137
  type: modelProviderTypeSchema
8039
8138
  }),
8040
- body: z19.undefined(),
8139
+ body: z20.undefined(),
8041
8140
  responses: {
8042
8141
  200: modelProviderResponseSchema,
8043
8142
  401: apiErrorSchema,
@@ -8047,15 +8146,15 @@ var modelProvidersSetDefaultContract = c12.router({
8047
8146
  summary: "Set a model provider as default for its framework"
8048
8147
  }
8049
8148
  });
8050
- var updateModelRequestSchema = z19.object({
8051
- selectedModel: z19.string().optional()
8149
+ var updateModelRequestSchema = z20.object({
8150
+ selectedModel: z20.string().optional()
8052
8151
  });
8053
- var modelProvidersUpdateModelContract = c12.router({
8152
+ var modelProvidersUpdateModelContract = c13.router({
8054
8153
  updateModel: {
8055
8154
  method: "PATCH",
8056
8155
  path: "/api/model-providers/:type/model",
8057
8156
  headers: authHeadersSchema,
8058
- pathParams: z19.object({
8157
+ pathParams: z20.object({
8059
8158
  type: modelProviderTypeSchema
8060
8159
  }),
8061
8160
  body: updateModelRequestSchema,
@@ -8070,42 +8169,42 @@ var modelProvidersUpdateModelContract = c12.router({
8070
8169
  });
8071
8170
 
8072
8171
  // ../../packages/core/src/contracts/sessions.ts
8073
- import { z as z20 } from "zod";
8074
- var c13 = initContract();
8075
- var sessionResponseSchema = z20.object({
8076
- id: z20.string(),
8077
- agentComposeId: z20.string(),
8078
- agentComposeVersionId: z20.string().nullable(),
8079
- conversationId: z20.string().nullable(),
8080
- artifactName: z20.string().nullable(),
8081
- vars: z20.record(z20.string(), z20.string()).nullable(),
8082
- secretNames: z20.array(z20.string()).nullable(),
8083
- volumeVersions: z20.record(z20.string(), z20.string()).nullable(),
8084
- createdAt: z20.string(),
8085
- updatedAt: z20.string()
8172
+ import { z as z21 } from "zod";
8173
+ var c14 = initContract();
8174
+ var sessionResponseSchema = z21.object({
8175
+ id: z21.string(),
8176
+ agentComposeId: z21.string(),
8177
+ agentComposeVersionId: z21.string().nullable(),
8178
+ conversationId: z21.string().nullable(),
8179
+ artifactName: z21.string().nullable(),
8180
+ vars: z21.record(z21.string(), z21.string()).nullable(),
8181
+ secretNames: z21.array(z21.string()).nullable(),
8182
+ volumeVersions: z21.record(z21.string(), z21.string()).nullable(),
8183
+ createdAt: z21.string(),
8184
+ updatedAt: z21.string()
8086
8185
  });
8087
- var agentComposeSnapshotSchema = z20.object({
8088
- agentComposeVersionId: z20.string(),
8089
- vars: z20.record(z20.string(), z20.string()).optional(),
8090
- secretNames: z20.array(z20.string()).optional()
8186
+ var agentComposeSnapshotSchema = z21.object({
8187
+ agentComposeVersionId: z21.string(),
8188
+ vars: z21.record(z21.string(), z21.string()).optional(),
8189
+ secretNames: z21.array(z21.string()).optional()
8091
8190
  });
8092
- var artifactSnapshotSchema2 = z20.object({
8093
- artifactName: z20.string(),
8094
- artifactVersion: z20.string()
8191
+ var artifactSnapshotSchema2 = z21.object({
8192
+ artifactName: z21.string(),
8193
+ artifactVersion: z21.string()
8095
8194
  });
8096
- var volumeVersionsSnapshotSchema2 = z20.object({
8097
- versions: z20.record(z20.string(), z20.string())
8195
+ var volumeVersionsSnapshotSchema2 = z21.object({
8196
+ versions: z21.record(z21.string(), z21.string())
8098
8197
  });
8099
- var checkpointResponseSchema = z20.object({
8100
- id: z20.string(),
8101
- runId: z20.string(),
8102
- conversationId: z20.string(),
8198
+ var checkpointResponseSchema = z21.object({
8199
+ id: z21.string(),
8200
+ runId: z21.string(),
8201
+ conversationId: z21.string(),
8103
8202
  agentComposeSnapshot: agentComposeSnapshotSchema,
8104
8203
  artifactSnapshot: artifactSnapshotSchema2.nullable(),
8105
8204
  volumeVersionsSnapshot: volumeVersionsSnapshotSchema2.nullable(),
8106
- createdAt: z20.string()
8205
+ createdAt: z21.string()
8107
8206
  });
8108
- var sessionsByIdContract = c13.router({
8207
+ var sessionsByIdContract = c14.router({
8109
8208
  /**
8110
8209
  * GET /api/agent/sessions/:id
8111
8210
  * Get session by ID
@@ -8114,8 +8213,8 @@ var sessionsByIdContract = c13.router({
8114
8213
  method: "GET",
8115
8214
  path: "/api/agent/sessions/:id",
8116
8215
  headers: authHeadersSchema,
8117
- pathParams: z20.object({
8118
- id: z20.string().min(1, "Session ID is required")
8216
+ pathParams: z21.object({
8217
+ id: z21.string().min(1, "Session ID is required")
8119
8218
  }),
8120
8219
  responses: {
8121
8220
  200: sessionResponseSchema,
@@ -8126,7 +8225,7 @@ var sessionsByIdContract = c13.router({
8126
8225
  summary: "Get session by ID"
8127
8226
  }
8128
8227
  });
8129
- var checkpointsByIdContract = c13.router({
8228
+ var checkpointsByIdContract = c14.router({
8130
8229
  /**
8131
8230
  * GET /api/agent/checkpoints/:id
8132
8231
  * Get checkpoint by ID
@@ -8135,8 +8234,8 @@ var checkpointsByIdContract = c13.router({
8135
8234
  method: "GET",
8136
8235
  path: "/api/agent/checkpoints/:id",
8137
8236
  headers: authHeadersSchema,
8138
- pathParams: z20.object({
8139
- id: z20.string().min(1, "Checkpoint ID is required")
8237
+ pathParams: z21.object({
8238
+ id: z21.string().min(1, "Checkpoint ID is required")
8140
8239
  }),
8141
8240
  responses: {
8142
8241
  200: checkpointResponseSchema,
@@ -8149,93 +8248,93 @@ var checkpointsByIdContract = c13.router({
8149
8248
  });
8150
8249
 
8151
8250
  // ../../packages/core/src/contracts/schedules.ts
8152
- import { z as z21 } from "zod";
8153
- var c14 = initContract();
8154
- var scheduleTriggerSchema = z21.object({
8155
- cron: z21.string().optional(),
8156
- at: z21.string().optional(),
8157
- timezone: z21.string().default("UTC")
8251
+ import { z as z22 } from "zod";
8252
+ var c15 = initContract();
8253
+ var scheduleTriggerSchema = z22.object({
8254
+ cron: z22.string().optional(),
8255
+ at: z22.string().optional(),
8256
+ timezone: z22.string().default("UTC")
8158
8257
  }).refine((data) => data.cron && !data.at || !data.cron && data.at, {
8159
8258
  message: "Exactly one of 'cron' or 'at' must be specified"
8160
8259
  });
8161
- var scheduleRunConfigSchema = z21.object({
8162
- agent: z21.string().min(1, "Agent reference required"),
8163
- prompt: z21.string().min(1, "Prompt required"),
8164
- vars: z21.record(z21.string(), z21.string()).optional(),
8165
- secrets: z21.record(z21.string(), z21.string()).optional(),
8166
- artifactName: z21.string().optional(),
8167
- artifactVersion: z21.string().optional(),
8168
- volumeVersions: z21.record(z21.string(), z21.string()).optional()
8260
+ var scheduleRunConfigSchema = z22.object({
8261
+ agent: z22.string().min(1, "Agent reference required"),
8262
+ prompt: z22.string().min(1, "Prompt required"),
8263
+ vars: z22.record(z22.string(), z22.string()).optional(),
8264
+ secrets: z22.record(z22.string(), z22.string()).optional(),
8265
+ artifactName: z22.string().optional(),
8266
+ artifactVersion: z22.string().optional(),
8267
+ volumeVersions: z22.record(z22.string(), z22.string()).optional()
8169
8268
  });
8170
- var scheduleDefinitionSchema = z21.object({
8269
+ var scheduleDefinitionSchema = z22.object({
8171
8270
  on: scheduleTriggerSchema,
8172
8271
  run: scheduleRunConfigSchema
8173
8272
  });
8174
- var scheduleYamlSchema = z21.object({
8175
- version: z21.literal("1.0"),
8176
- schedules: z21.record(z21.string(), scheduleDefinitionSchema)
8177
- });
8178
- var deployScheduleRequestSchema = z21.object({
8179
- name: z21.string().min(1).max(64, "Schedule name max 64 chars"),
8180
- cronExpression: z21.string().optional(),
8181
- atTime: z21.string().optional(),
8182
- timezone: z21.string().default("UTC"),
8183
- prompt: z21.string().min(1, "Prompt required"),
8184
- vars: z21.record(z21.string(), z21.string()).optional(),
8185
- secrets: z21.record(z21.string(), z21.string()).optional(),
8186
- artifactName: z21.string().optional(),
8187
- artifactVersion: z21.string().optional(),
8188
- volumeVersions: z21.record(z21.string(), z21.string()).optional(),
8273
+ var scheduleYamlSchema = z22.object({
8274
+ version: z22.literal("1.0"),
8275
+ schedules: z22.record(z22.string(), scheduleDefinitionSchema)
8276
+ });
8277
+ var deployScheduleRequestSchema = z22.object({
8278
+ name: z22.string().min(1).max(64, "Schedule name max 64 chars"),
8279
+ cronExpression: z22.string().optional(),
8280
+ atTime: z22.string().optional(),
8281
+ timezone: z22.string().default("UTC"),
8282
+ prompt: z22.string().min(1, "Prompt required"),
8283
+ vars: z22.record(z22.string(), z22.string()).optional(),
8284
+ secrets: z22.record(z22.string(), z22.string()).optional(),
8285
+ artifactName: z22.string().optional(),
8286
+ artifactVersion: z22.string().optional(),
8287
+ volumeVersions: z22.record(z22.string(), z22.string()).optional(),
8189
8288
  // Resolved agent compose ID (CLI resolves scope/name:version → composeId)
8190
- composeId: z21.string().uuid("Invalid compose ID")
8289
+ composeId: z22.string().uuid("Invalid compose ID")
8191
8290
  }).refine(
8192
8291
  (data) => data.cronExpression && !data.atTime || !data.cronExpression && data.atTime,
8193
8292
  {
8194
8293
  message: "Exactly one of 'cronExpression' or 'atTime' must be specified"
8195
8294
  }
8196
8295
  );
8197
- var scheduleResponseSchema = z21.object({
8198
- id: z21.string().uuid(),
8199
- composeId: z21.string().uuid(),
8200
- composeName: z21.string(),
8201
- scopeSlug: z21.string(),
8202
- name: z21.string(),
8203
- cronExpression: z21.string().nullable(),
8204
- atTime: z21.string().nullable(),
8205
- timezone: z21.string(),
8206
- prompt: z21.string(),
8207
- vars: z21.record(z21.string(), z21.string()).nullable(),
8296
+ var scheduleResponseSchema = z22.object({
8297
+ id: z22.string().uuid(),
8298
+ composeId: z22.string().uuid(),
8299
+ composeName: z22.string(),
8300
+ scopeSlug: z22.string(),
8301
+ name: z22.string(),
8302
+ cronExpression: z22.string().nullable(),
8303
+ atTime: z22.string().nullable(),
8304
+ timezone: z22.string(),
8305
+ prompt: z22.string(),
8306
+ vars: z22.record(z22.string(), z22.string()).nullable(),
8208
8307
  // Secret names only (values are never returned)
8209
- secretNames: z21.array(z21.string()).nullable(),
8210
- artifactName: z21.string().nullable(),
8211
- artifactVersion: z21.string().nullable(),
8212
- volumeVersions: z21.record(z21.string(), z21.string()).nullable(),
8213
- enabled: z21.boolean(),
8214
- nextRunAt: z21.string().nullable(),
8215
- lastRunAt: z21.string().nullable(),
8216
- retryStartedAt: z21.string().nullable(),
8217
- createdAt: z21.string(),
8218
- updatedAt: z21.string()
8219
- });
8220
- var runSummarySchema = z21.object({
8221
- id: z21.string().uuid(),
8222
- status: z21.enum(["pending", "running", "completed", "failed", "timeout"]),
8223
- createdAt: z21.string(),
8224
- completedAt: z21.string().nullable(),
8225
- error: z21.string().nullable()
8226
- });
8227
- var scheduleRunsResponseSchema = z21.object({
8228
- runs: z21.array(runSummarySchema)
8229
- });
8230
- var scheduleListResponseSchema = z21.object({
8231
- schedules: z21.array(scheduleResponseSchema)
8232
- });
8233
- var deployScheduleResponseSchema = z21.object({
8308
+ secretNames: z22.array(z22.string()).nullable(),
8309
+ artifactName: z22.string().nullable(),
8310
+ artifactVersion: z22.string().nullable(),
8311
+ volumeVersions: z22.record(z22.string(), z22.string()).nullable(),
8312
+ enabled: z22.boolean(),
8313
+ nextRunAt: z22.string().nullable(),
8314
+ lastRunAt: z22.string().nullable(),
8315
+ retryStartedAt: z22.string().nullable(),
8316
+ createdAt: z22.string(),
8317
+ updatedAt: z22.string()
8318
+ });
8319
+ var runSummarySchema = z22.object({
8320
+ id: z22.string().uuid(),
8321
+ status: z22.enum(["pending", "running", "completed", "failed", "timeout"]),
8322
+ createdAt: z22.string(),
8323
+ completedAt: z22.string().nullable(),
8324
+ error: z22.string().nullable()
8325
+ });
8326
+ var scheduleRunsResponseSchema = z22.object({
8327
+ runs: z22.array(runSummarySchema)
8328
+ });
8329
+ var scheduleListResponseSchema = z22.object({
8330
+ schedules: z22.array(scheduleResponseSchema)
8331
+ });
8332
+ var deployScheduleResponseSchema = z22.object({
8234
8333
  schedule: scheduleResponseSchema,
8235
- created: z21.boolean()
8334
+ created: z22.boolean()
8236
8335
  // true if created, false if updated
8237
8336
  });
8238
- var schedulesMainContract = c14.router({
8337
+ var schedulesMainContract = c15.router({
8239
8338
  /**
8240
8339
  * POST /api/agent/schedules
8241
8340
  * Deploy (create or update) a schedule
@@ -8273,7 +8372,7 @@ var schedulesMainContract = c14.router({
8273
8372
  summary: "List all schedules"
8274
8373
  }
8275
8374
  });
8276
- var schedulesByNameContract = c14.router({
8375
+ var schedulesByNameContract = c15.router({
8277
8376
  /**
8278
8377
  * GET /api/agent/schedules/:name
8279
8378
  * Get schedule by name
@@ -8282,11 +8381,11 @@ var schedulesByNameContract = c14.router({
8282
8381
  method: "GET",
8283
8382
  path: "/api/agent/schedules/:name",
8284
8383
  headers: authHeadersSchema,
8285
- pathParams: z21.object({
8286
- name: z21.string().min(1, "Schedule name required")
8384
+ pathParams: z22.object({
8385
+ name: z22.string().min(1, "Schedule name required")
8287
8386
  }),
8288
- query: z21.object({
8289
- composeId: z21.string().uuid("Compose ID required")
8387
+ query: z22.object({
8388
+ composeId: z22.string().uuid("Compose ID required")
8290
8389
  }),
8291
8390
  responses: {
8292
8391
  200: scheduleResponseSchema,
@@ -8303,21 +8402,21 @@ var schedulesByNameContract = c14.router({
8303
8402
  method: "DELETE",
8304
8403
  path: "/api/agent/schedules/:name",
8305
8404
  headers: authHeadersSchema,
8306
- pathParams: z21.object({
8307
- name: z21.string().min(1, "Schedule name required")
8405
+ pathParams: z22.object({
8406
+ name: z22.string().min(1, "Schedule name required")
8308
8407
  }),
8309
- query: z21.object({
8310
- composeId: z21.string().uuid("Compose ID required")
8408
+ query: z22.object({
8409
+ composeId: z22.string().uuid("Compose ID required")
8311
8410
  }),
8312
8411
  responses: {
8313
- 204: c14.noBody(),
8412
+ 204: c15.noBody(),
8314
8413
  401: apiErrorSchema,
8315
8414
  404: apiErrorSchema
8316
8415
  },
8317
8416
  summary: "Delete schedule"
8318
8417
  }
8319
8418
  });
8320
- var schedulesEnableContract = c14.router({
8419
+ var schedulesEnableContract = c15.router({
8321
8420
  /**
8322
8421
  * POST /api/agent/schedules/:name/enable
8323
8422
  * Enable a disabled schedule
@@ -8326,11 +8425,11 @@ var schedulesEnableContract = c14.router({
8326
8425
  method: "POST",
8327
8426
  path: "/api/agent/schedules/:name/enable",
8328
8427
  headers: authHeadersSchema,
8329
- pathParams: z21.object({
8330
- name: z21.string().min(1, "Schedule name required")
8428
+ pathParams: z22.object({
8429
+ name: z22.string().min(1, "Schedule name required")
8331
8430
  }),
8332
- body: z21.object({
8333
- composeId: z21.string().uuid("Compose ID required")
8431
+ body: z22.object({
8432
+ composeId: z22.string().uuid("Compose ID required")
8334
8433
  }),
8335
8434
  responses: {
8336
8435
  200: scheduleResponseSchema,
@@ -8347,11 +8446,11 @@ var schedulesEnableContract = c14.router({
8347
8446
  method: "POST",
8348
8447
  path: "/api/agent/schedules/:name/disable",
8349
8448
  headers: authHeadersSchema,
8350
- pathParams: z21.object({
8351
- name: z21.string().min(1, "Schedule name required")
8449
+ pathParams: z22.object({
8450
+ name: z22.string().min(1, "Schedule name required")
8352
8451
  }),
8353
- body: z21.object({
8354
- composeId: z21.string().uuid("Compose ID required")
8452
+ body: z22.object({
8453
+ composeId: z22.string().uuid("Compose ID required")
8355
8454
  }),
8356
8455
  responses: {
8357
8456
  200: scheduleResponseSchema,
@@ -8361,7 +8460,7 @@ var schedulesEnableContract = c14.router({
8361
8460
  summary: "Disable schedule"
8362
8461
  }
8363
8462
  });
8364
- var scheduleRunsContract = c14.router({
8463
+ var scheduleRunsContract = c15.router({
8365
8464
  /**
8366
8465
  * GET /api/agent/schedules/:name/runs
8367
8466
  * List recent runs for a schedule
@@ -8370,12 +8469,12 @@ var scheduleRunsContract = c14.router({
8370
8469
  method: "GET",
8371
8470
  path: "/api/agent/schedules/:name/runs",
8372
8471
  headers: authHeadersSchema,
8373
- pathParams: z21.object({
8374
- name: z21.string().min(1, "Schedule name required")
8472
+ pathParams: z22.object({
8473
+ name: z22.string().min(1, "Schedule name required")
8375
8474
  }),
8376
- query: z21.object({
8377
- composeId: z21.string().uuid("Compose ID required"),
8378
- limit: z21.coerce.number().min(0).max(100).default(5)
8475
+ query: z22.object({
8476
+ composeId: z22.string().uuid("Compose ID required"),
8477
+ limit: z22.coerce.number().min(0).max(100).default(5)
8379
8478
  }),
8380
8479
  responses: {
8381
8480
  200: scheduleRunsResponseSchema,
@@ -8387,18 +8486,18 @@ var scheduleRunsContract = c14.router({
8387
8486
  });
8388
8487
 
8389
8488
  // ../../packages/core/src/contracts/realtime.ts
8390
- import { z as z22 } from "zod";
8391
- var c15 = initContract();
8392
- var ablyTokenRequestSchema = z22.object({
8393
- keyName: z22.string(),
8394
- ttl: z22.number().optional(),
8395
- timestamp: z22.number(),
8396
- capability: z22.string(),
8397
- clientId: z22.string().optional(),
8398
- nonce: z22.string(),
8399
- mac: z22.string()
8489
+ import { z as z23 } from "zod";
8490
+ var c16 = initContract();
8491
+ var ablyTokenRequestSchema = z23.object({
8492
+ keyName: z23.string(),
8493
+ ttl: z23.number().optional(),
8494
+ timestamp: z23.number(),
8495
+ capability: z23.string(),
8496
+ clientId: z23.string().optional(),
8497
+ nonce: z23.string(),
8498
+ mac: z23.string()
8400
8499
  });
8401
- var realtimeTokenContract = c15.router({
8500
+ var realtimeTokenContract = c16.router({
8402
8501
  /**
8403
8502
  * POST /api/realtime/token
8404
8503
  * Get an Ably token to subscribe to a run's events channel
@@ -8407,8 +8506,8 @@ var realtimeTokenContract = c15.router({
8407
8506
  method: "POST",
8408
8507
  path: "/api/realtime/token",
8409
8508
  headers: authHeadersSchema,
8410
- body: z22.object({
8411
- runId: z22.string().uuid("runId must be a valid UUID")
8509
+ body: z23.object({
8510
+ runId: z23.string().uuid("runId must be a valid UUID")
8412
8511
  }),
8413
8512
  responses: {
8414
8513
  200: ablyTokenRequestSchema,
@@ -8420,7 +8519,7 @@ var realtimeTokenContract = c15.router({
8420
8519
  summary: "Get Ably token for run event subscription"
8421
8520
  }
8422
8521
  });
8423
- var runnerRealtimeTokenContract = c15.router({
8522
+ var runnerRealtimeTokenContract = c16.router({
8424
8523
  /**
8425
8524
  * POST /api/runners/realtime/token
8426
8525
  * Get an Ably token to subscribe to a runner group's job notification channel
@@ -8429,7 +8528,7 @@ var runnerRealtimeTokenContract = c15.router({
8429
8528
  method: "POST",
8430
8529
  path: "/api/runners/realtime/token",
8431
8530
  headers: authHeadersSchema,
8432
- body: z22.object({
8531
+ body: z23.object({
8433
8532
  group: runnerGroupSchema
8434
8533
  }),
8435
8534
  responses: {
@@ -8443,11 +8542,11 @@ var runnerRealtimeTokenContract = c15.router({
8443
8542
  });
8444
8543
 
8445
8544
  // ../../packages/core/src/contracts/platform.ts
8446
- import { z as z24 } from "zod";
8545
+ import { z as z25 } from "zod";
8447
8546
 
8448
8547
  // ../../packages/core/src/contracts/public/common.ts
8449
- import { z as z23 } from "zod";
8450
- var publicApiErrorTypeSchema = z23.enum([
8548
+ import { z as z24 } from "zod";
8549
+ var publicApiErrorTypeSchema = z24.enum([
8451
8550
  "api_error",
8452
8551
  // Internal server error (5xx)
8453
8552
  "invalid_request_error",
@@ -8461,40 +8560,40 @@ var publicApiErrorTypeSchema = z23.enum([
8461
8560
  "rate_limit_error"
8462
8561
  // Rate limit exceeded (429)
8463
8562
  ]);
8464
- var publicApiErrorSchema = z23.object({
8465
- error: z23.object({
8563
+ var publicApiErrorSchema = z24.object({
8564
+ error: z24.object({
8466
8565
  type: publicApiErrorTypeSchema,
8467
- code: z23.string(),
8468
- message: z23.string(),
8469
- param: z23.string().optional(),
8470
- docUrl: z23.string().url().optional()
8566
+ code: z24.string(),
8567
+ message: z24.string(),
8568
+ param: z24.string().optional(),
8569
+ docUrl: z24.string().url().optional()
8471
8570
  })
8472
8571
  });
8473
- var paginationSchema = z23.object({
8474
- hasMore: z23.boolean(),
8475
- nextCursor: z23.string().nullable()
8572
+ var paginationSchema = z24.object({
8573
+ hasMore: z24.boolean(),
8574
+ nextCursor: z24.string().nullable()
8476
8575
  });
8477
8576
  function createPaginatedResponseSchema(dataSchema) {
8478
- return z23.object({
8479
- data: z23.array(dataSchema),
8577
+ return z24.object({
8578
+ data: z24.array(dataSchema),
8480
8579
  pagination: paginationSchema
8481
8580
  });
8482
8581
  }
8483
- var listQuerySchema = z23.object({
8484
- cursor: z23.string().optional(),
8485
- limit: z23.coerce.number().min(1).max(100).default(20)
8582
+ var listQuerySchema = z24.object({
8583
+ cursor: z24.string().optional(),
8584
+ limit: z24.coerce.number().min(1).max(100).default(20)
8486
8585
  });
8487
- var requestIdSchema = z23.string().uuid();
8488
- var timestampSchema = z23.string().datetime();
8586
+ var requestIdSchema = z24.string().uuid();
8587
+ var timestampSchema = z24.string().datetime();
8489
8588
 
8490
8589
  // ../../packages/core/src/contracts/platform.ts
8491
- var c16 = initContract();
8492
- var platformPaginationSchema = z24.object({
8493
- hasMore: z24.boolean(),
8494
- nextCursor: z24.string().nullable(),
8495
- totalPages: z24.number()
8590
+ var c17 = initContract();
8591
+ var platformPaginationSchema = z25.object({
8592
+ hasMore: z25.boolean(),
8593
+ nextCursor: z25.string().nullable(),
8594
+ totalPages: z25.number()
8496
8595
  });
8497
- var platformLogStatusSchema = z24.enum([
8596
+ var platformLogStatusSchema = z25.enum([
8498
8597
  "pending",
8499
8598
  "running",
8500
8599
  "completed",
@@ -8502,41 +8601,41 @@ var platformLogStatusSchema = z24.enum([
8502
8601
  "timeout",
8503
8602
  "cancelled"
8504
8603
  ]);
8505
- var platformLogEntrySchema = z24.object({
8506
- id: z24.string().uuid(),
8507
- sessionId: z24.string().nullable(),
8508
- agentName: z24.string(),
8509
- framework: z24.string().nullable(),
8604
+ var platformLogEntrySchema = z25.object({
8605
+ id: z25.string().uuid(),
8606
+ sessionId: z25.string().nullable(),
8607
+ agentName: z25.string(),
8608
+ framework: z25.string().nullable(),
8510
8609
  status: platformLogStatusSchema,
8511
- createdAt: z24.string()
8610
+ createdAt: z25.string()
8512
8611
  });
8513
- var platformLogsListResponseSchema = z24.object({
8514
- data: z24.array(platformLogEntrySchema),
8612
+ var platformLogsListResponseSchema = z25.object({
8613
+ data: z25.array(platformLogEntrySchema),
8515
8614
  pagination: platformPaginationSchema
8516
8615
  });
8517
- var artifactSchema = z24.object({
8518
- name: z24.string().nullable(),
8519
- version: z24.string().nullable()
8616
+ var artifactSchema = z25.object({
8617
+ name: z25.string().nullable(),
8618
+ version: z25.string().nullable()
8520
8619
  });
8521
- var platformLogDetailSchema = z24.object({
8522
- id: z24.string().uuid(),
8523
- sessionId: z24.string().nullable(),
8524
- agentName: z24.string(),
8525
- framework: z24.string().nullable(),
8620
+ var platformLogDetailSchema = z25.object({
8621
+ id: z25.string().uuid(),
8622
+ sessionId: z25.string().nullable(),
8623
+ agentName: z25.string(),
8624
+ framework: z25.string().nullable(),
8526
8625
  status: platformLogStatusSchema,
8527
- prompt: z24.string(),
8528
- error: z24.string().nullable(),
8529
- createdAt: z24.string(),
8530
- startedAt: z24.string().nullable(),
8531
- completedAt: z24.string().nullable(),
8626
+ prompt: z25.string(),
8627
+ error: z25.string().nullable(),
8628
+ createdAt: z25.string(),
8629
+ startedAt: z25.string().nullable(),
8630
+ completedAt: z25.string().nullable(),
8532
8631
  artifact: artifactSchema
8533
8632
  });
8534
- var platformLogsListContract = c16.router({
8633
+ var platformLogsListContract = c17.router({
8535
8634
  list: {
8536
8635
  method: "GET",
8537
8636
  path: "/api/platform/logs",
8538
8637
  query: listQuerySchema.extend({
8539
- search: z24.string().optional()
8638
+ search: z25.string().optional()
8540
8639
  }),
8541
8640
  responses: {
8542
8641
  200: platformLogsListResponseSchema,
@@ -8545,12 +8644,12 @@ var platformLogsListContract = c16.router({
8545
8644
  summary: "List agent run logs with pagination"
8546
8645
  }
8547
8646
  });
8548
- var platformLogsByIdContract = c16.router({
8647
+ var platformLogsByIdContract = c17.router({
8549
8648
  getById: {
8550
8649
  method: "GET",
8551
8650
  path: "/api/platform/logs/:id",
8552
- pathParams: z24.object({
8553
- id: z24.string().uuid("Invalid log ID")
8651
+ pathParams: z25.object({
8652
+ id: z25.string().uuid("Invalid log ID")
8554
8653
  }),
8555
8654
  responses: {
8556
8655
  200: platformLogDetailSchema,
@@ -8560,17 +8659,17 @@ var platformLogsByIdContract = c16.router({
8560
8659
  summary: "Get agent run log details by ID"
8561
8660
  }
8562
8661
  });
8563
- var artifactDownloadResponseSchema = z24.object({
8564
- url: z24.string().url(),
8565
- expiresAt: z24.string()
8662
+ var artifactDownloadResponseSchema = z25.object({
8663
+ url: z25.string().url(),
8664
+ expiresAt: z25.string()
8566
8665
  });
8567
- var platformArtifactDownloadContract = c16.router({
8666
+ var platformArtifactDownloadContract = c17.router({
8568
8667
  getDownloadUrl: {
8569
8668
  method: "GET",
8570
8669
  path: "/api/platform/artifacts/download",
8571
- query: z24.object({
8572
- name: z24.string().min(1, "Artifact name is required"),
8573
- version: z24.string().optional()
8670
+ query: z25.object({
8671
+ name: z25.string().min(1, "Artifact name is required"),
8672
+ version: z25.string().optional()
8574
8673
  }),
8575
8674
  responses: {
8576
8675
  200: artifactDownloadResponseSchema,
@@ -8582,29 +8681,29 @@ var platformArtifactDownloadContract = c16.router({
8582
8681
  });
8583
8682
 
8584
8683
  // ../../packages/core/src/contracts/llm.ts
8585
- import { z as z25 } from "zod";
8586
- var c17 = initContract();
8587
- var messageRoleSchema = z25.enum(["user", "assistant", "system"]);
8588
- var chatMessageSchema = z25.object({
8684
+ import { z as z26 } from "zod";
8685
+ var c18 = initContract();
8686
+ var messageRoleSchema = z26.enum(["user", "assistant", "system"]);
8687
+ var chatMessageSchema = z26.object({
8589
8688
  role: messageRoleSchema,
8590
- content: z25.string()
8689
+ content: z26.string()
8591
8690
  });
8592
- var tokenUsageSchema = z25.object({
8593
- promptTokens: z25.number(),
8594
- completionTokens: z25.number(),
8595
- totalTokens: z25.number()
8691
+ var tokenUsageSchema = z26.object({
8692
+ promptTokens: z26.number(),
8693
+ completionTokens: z26.number(),
8694
+ totalTokens: z26.number()
8596
8695
  });
8597
- var llmChatRequestSchema = z25.object({
8598
- model: z25.string().min(1).optional(),
8599
- messages: z25.array(chatMessageSchema).min(1, "At least one message is required"),
8600
- stream: z25.boolean().optional().default(false)
8696
+ var llmChatRequestSchema = z26.object({
8697
+ model: z26.string().min(1).optional(),
8698
+ messages: z26.array(chatMessageSchema).min(1, "At least one message is required"),
8699
+ stream: z26.boolean().optional().default(false)
8601
8700
  });
8602
- var llmChatResponseSchema = z25.object({
8603
- content: z25.string(),
8604
- model: z25.string(),
8701
+ var llmChatResponseSchema = z26.object({
8702
+ content: z26.string(),
8703
+ model: z26.string(),
8605
8704
  usage: tokenUsageSchema
8606
8705
  });
8607
- var llmChatContract = c17.router({
8706
+ var llmChatContract = c18.router({
8608
8707
  chat: {
8609
8708
  method: "POST",
8610
8709
  path: "/api/llm/chat",
@@ -8620,28 +8719,28 @@ var llmChatContract = c17.router({
8620
8719
  });
8621
8720
 
8622
8721
  // ../../packages/core/src/contracts/public/agents.ts
8623
- import { z as z26 } from "zod";
8624
- var c18 = initContract();
8625
- var publicAgentSchema = z26.object({
8626
- id: z26.string(),
8627
- name: z26.string(),
8628
- currentVersionId: z26.string().nullable(),
8722
+ import { z as z27 } from "zod";
8723
+ var c19 = initContract();
8724
+ var publicAgentSchema = z27.object({
8725
+ id: z27.string(),
8726
+ name: z27.string(),
8727
+ currentVersionId: z27.string().nullable(),
8629
8728
  createdAt: timestampSchema,
8630
8729
  updatedAt: timestampSchema
8631
8730
  });
8632
- var agentVersionSchema = z26.object({
8633
- id: z26.string(),
8634
- agentId: z26.string(),
8635
- versionNumber: z26.number(),
8731
+ var agentVersionSchema = z27.object({
8732
+ id: z27.string(),
8733
+ agentId: z27.string(),
8734
+ versionNumber: z27.number(),
8636
8735
  createdAt: timestampSchema
8637
8736
  });
8638
8737
  var publicAgentDetailSchema = publicAgentSchema;
8639
8738
  var paginatedAgentsSchema = createPaginatedResponseSchema(publicAgentSchema);
8640
8739
  var paginatedAgentVersionsSchema = createPaginatedResponseSchema(agentVersionSchema);
8641
8740
  var agentListQuerySchema = listQuerySchema.extend({
8642
- name: z26.string().optional()
8741
+ name: z27.string().optional()
8643
8742
  });
8644
- var publicAgentsListContract = c18.router({
8743
+ var publicAgentsListContract = c19.router({
8645
8744
  list: {
8646
8745
  method: "GET",
8647
8746
  path: "/v1/agents",
@@ -8656,13 +8755,13 @@ var publicAgentsListContract = c18.router({
8656
8755
  description: "List all agents in the current scope with pagination. Use the `name` query parameter to filter by agent name."
8657
8756
  }
8658
8757
  });
8659
- var publicAgentByIdContract = c18.router({
8758
+ var publicAgentByIdContract = c19.router({
8660
8759
  get: {
8661
8760
  method: "GET",
8662
8761
  path: "/v1/agents/:id",
8663
8762
  headers: authHeadersSchema,
8664
- pathParams: z26.object({
8665
- id: z26.string().min(1, "Agent ID is required")
8763
+ pathParams: z27.object({
8764
+ id: z27.string().min(1, "Agent ID is required")
8666
8765
  }),
8667
8766
  responses: {
8668
8767
  200: publicAgentDetailSchema,
@@ -8674,13 +8773,13 @@ var publicAgentByIdContract = c18.router({
8674
8773
  description: "Get agent details by ID"
8675
8774
  }
8676
8775
  });
8677
- var publicAgentVersionsContract = c18.router({
8776
+ var publicAgentVersionsContract = c19.router({
8678
8777
  list: {
8679
8778
  method: "GET",
8680
8779
  path: "/v1/agents/:id/versions",
8681
8780
  headers: authHeadersSchema,
8682
- pathParams: z26.object({
8683
- id: z26.string().min(1, "Agent ID is required")
8781
+ pathParams: z27.object({
8782
+ id: z27.string().min(1, "Agent ID is required")
8684
8783
  }),
8685
8784
  query: listQuerySchema,
8686
8785
  responses: {
@@ -8695,9 +8794,9 @@ var publicAgentVersionsContract = c18.router({
8695
8794
  });
8696
8795
 
8697
8796
  // ../../packages/core/src/contracts/public/runs.ts
8698
- import { z as z27 } from "zod";
8699
- var c19 = initContract();
8700
- var publicRunStatusSchema = z27.enum([
8797
+ import { z as z28 } from "zod";
8798
+ var c20 = initContract();
8799
+ var publicRunStatusSchema = z28.enum([
8701
8800
  "pending",
8702
8801
  "running",
8703
8802
  "completed",
@@ -8705,54 +8804,54 @@ var publicRunStatusSchema = z27.enum([
8705
8804
  "timeout",
8706
8805
  "cancelled"
8707
8806
  ]);
8708
- var publicRunSchema = z27.object({
8709
- id: z27.string(),
8710
- agentId: z27.string(),
8711
- agentName: z27.string(),
8807
+ var publicRunSchema = z28.object({
8808
+ id: z28.string(),
8809
+ agentId: z28.string(),
8810
+ agentName: z28.string(),
8712
8811
  status: publicRunStatusSchema,
8713
- prompt: z27.string(),
8812
+ prompt: z28.string(),
8714
8813
  createdAt: timestampSchema,
8715
8814
  startedAt: timestampSchema.nullable(),
8716
8815
  completedAt: timestampSchema.nullable()
8717
8816
  });
8718
8817
  var publicRunDetailSchema = publicRunSchema.extend({
8719
- error: z27.string().nullable(),
8720
- executionTimeMs: z27.number().nullable(),
8721
- checkpointId: z27.string().nullable(),
8722
- sessionId: z27.string().nullable(),
8723
- artifactName: z27.string().nullable(),
8724
- artifactVersion: z27.string().nullable(),
8725
- volumes: z27.record(z27.string(), z27.string()).optional()
8818
+ error: z28.string().nullable(),
8819
+ executionTimeMs: z28.number().nullable(),
8820
+ checkpointId: z28.string().nullable(),
8821
+ sessionId: z28.string().nullable(),
8822
+ artifactName: z28.string().nullable(),
8823
+ artifactVersion: z28.string().nullable(),
8824
+ volumes: z28.record(z28.string(), z28.string()).optional()
8726
8825
  });
8727
8826
  var paginatedRunsSchema = createPaginatedResponseSchema(publicRunSchema);
8728
- var createRunRequestSchema = z27.object({
8827
+ var createRunRequestSchema = z28.object({
8729
8828
  // Agent identification (one of: agent, agentId, sessionId, checkpointId)
8730
- agent: z27.string().optional(),
8829
+ agent: z28.string().optional(),
8731
8830
  // Agent name
8732
- agentId: z27.string().optional(),
8831
+ agentId: z28.string().optional(),
8733
8832
  // Agent ID
8734
- agentVersion: z27.string().optional(),
8833
+ agentVersion: z28.string().optional(),
8735
8834
  // Version specifier (e.g., "latest", "v1", specific ID)
8736
8835
  // Continue session
8737
- sessionId: z27.string().optional(),
8836
+ sessionId: z28.string().optional(),
8738
8837
  // Resume from checkpoint
8739
- checkpointId: z27.string().optional(),
8838
+ checkpointId: z28.string().optional(),
8740
8839
  // Required
8741
- prompt: z27.string().min(1, "Prompt is required"),
8840
+ prompt: z28.string().min(1, "Prompt is required"),
8742
8841
  // Optional configuration
8743
- variables: z27.record(z27.string(), z27.string()).optional(),
8744
- secrets: z27.record(z27.string(), z27.string()).optional(),
8745
- artifactName: z27.string().optional(),
8842
+ variables: z28.record(z28.string(), z28.string()).optional(),
8843
+ secrets: z28.record(z28.string(), z28.string()).optional(),
8844
+ artifactName: z28.string().optional(),
8746
8845
  // Artifact name to mount
8747
- artifactVersion: z27.string().optional(),
8846
+ artifactVersion: z28.string().optional(),
8748
8847
  // Artifact version (defaults to latest)
8749
- volumes: z27.record(z27.string(), z27.string()).optional()
8848
+ volumes: z28.record(z28.string(), z28.string()).optional()
8750
8849
  // volume_name -> version
8751
8850
  });
8752
8851
  var runListQuerySchema = listQuerySchema.extend({
8753
8852
  status: publicRunStatusSchema.optional()
8754
8853
  });
8755
- var publicRunsListContract = c19.router({
8854
+ var publicRunsListContract = c20.router({
8756
8855
  list: {
8757
8856
  method: "GET",
8758
8857
  path: "/v1/runs",
@@ -8784,13 +8883,13 @@ var publicRunsListContract = c19.router({
8784
8883
  description: "Create and execute a new agent run. Returns 202 Accepted as runs execute asynchronously."
8785
8884
  }
8786
8885
  });
8787
- var publicRunByIdContract = c19.router({
8886
+ var publicRunByIdContract = c20.router({
8788
8887
  get: {
8789
8888
  method: "GET",
8790
8889
  path: "/v1/runs/:id",
8791
8890
  headers: authHeadersSchema,
8792
- pathParams: z27.object({
8793
- id: z27.string().min(1, "Run ID is required")
8891
+ pathParams: z28.object({
8892
+ id: z28.string().min(1, "Run ID is required")
8794
8893
  }),
8795
8894
  responses: {
8796
8895
  200: publicRunDetailSchema,
@@ -8802,15 +8901,15 @@ var publicRunByIdContract = c19.router({
8802
8901
  description: "Get run details by ID"
8803
8902
  }
8804
8903
  });
8805
- var publicRunCancelContract = c19.router({
8904
+ var publicRunCancelContract = c20.router({
8806
8905
  cancel: {
8807
8906
  method: "POST",
8808
8907
  path: "/v1/runs/:id/cancel",
8809
8908
  headers: authHeadersSchema,
8810
- pathParams: z27.object({
8811
- id: z27.string().min(1, "Run ID is required")
8909
+ pathParams: z28.object({
8910
+ id: z28.string().min(1, "Run ID is required")
8812
8911
  }),
8813
- body: z27.undefined(),
8912
+ body: z28.undefined(),
8814
8913
  responses: {
8815
8914
  200: publicRunDetailSchema,
8816
8915
  400: publicApiErrorSchema,
@@ -8823,27 +8922,27 @@ var publicRunCancelContract = c19.router({
8823
8922
  description: "Cancel a pending or running execution"
8824
8923
  }
8825
8924
  });
8826
- var logEntrySchema = z27.object({
8925
+ var logEntrySchema = z28.object({
8827
8926
  timestamp: timestampSchema,
8828
- type: z27.enum(["agent", "system", "network"]),
8829
- level: z27.enum(["debug", "info", "warn", "error"]),
8830
- message: z27.string(),
8831
- metadata: z27.record(z27.string(), z27.unknown()).optional()
8927
+ type: z28.enum(["agent", "system", "network"]),
8928
+ level: z28.enum(["debug", "info", "warn", "error"]),
8929
+ message: z28.string(),
8930
+ metadata: z28.record(z28.string(), z28.unknown()).optional()
8832
8931
  });
8833
8932
  var paginatedLogsSchema = createPaginatedResponseSchema(logEntrySchema);
8834
8933
  var logsQuerySchema = listQuerySchema.extend({
8835
- type: z27.enum(["agent", "system", "network", "all"]).default("all"),
8934
+ type: z28.enum(["agent", "system", "network", "all"]).default("all"),
8836
8935
  since: timestampSchema.optional(),
8837
8936
  until: timestampSchema.optional(),
8838
- order: z27.enum(["asc", "desc"]).default("asc")
8937
+ order: z28.enum(["asc", "desc"]).default("asc")
8839
8938
  });
8840
- var publicRunLogsContract = c19.router({
8939
+ var publicRunLogsContract = c20.router({
8841
8940
  getLogs: {
8842
8941
  method: "GET",
8843
8942
  path: "/v1/runs/:id/logs",
8844
8943
  headers: authHeadersSchema,
8845
- pathParams: z27.object({
8846
- id: z27.string().min(1, "Run ID is required")
8944
+ pathParams: z28.object({
8945
+ id: z28.string().min(1, "Run ID is required")
8847
8946
  }),
8848
8947
  query: logsQuerySchema,
8849
8948
  responses: {
@@ -8856,30 +8955,30 @@ var publicRunLogsContract = c19.router({
8856
8955
  description: "Get unified logs for a run. Combines agent, system, and network logs."
8857
8956
  }
8858
8957
  });
8859
- var metricPointSchema = z27.object({
8958
+ var metricPointSchema = z28.object({
8860
8959
  timestamp: timestampSchema,
8861
- cpuPercent: z27.number(),
8862
- memoryUsedMb: z27.number(),
8863
- memoryTotalMb: z27.number(),
8864
- diskUsedMb: z27.number(),
8865
- diskTotalMb: z27.number()
8866
- });
8867
- var metricsSummarySchema = z27.object({
8868
- avgCpuPercent: z27.number(),
8869
- maxMemoryUsedMb: z27.number(),
8870
- totalDurationMs: z27.number().nullable()
8871
- });
8872
- var metricsResponseSchema2 = z27.object({
8873
- data: z27.array(metricPointSchema),
8960
+ cpuPercent: z28.number(),
8961
+ memoryUsedMb: z28.number(),
8962
+ memoryTotalMb: z28.number(),
8963
+ diskUsedMb: z28.number(),
8964
+ diskTotalMb: z28.number()
8965
+ });
8966
+ var metricsSummarySchema = z28.object({
8967
+ avgCpuPercent: z28.number(),
8968
+ maxMemoryUsedMb: z28.number(),
8969
+ totalDurationMs: z28.number().nullable()
8970
+ });
8971
+ var metricsResponseSchema2 = z28.object({
8972
+ data: z28.array(metricPointSchema),
8874
8973
  summary: metricsSummarySchema
8875
8974
  });
8876
- var publicRunMetricsContract = c19.router({
8975
+ var publicRunMetricsContract = c20.router({
8877
8976
  getMetrics: {
8878
8977
  method: "GET",
8879
8978
  path: "/v1/runs/:id/metrics",
8880
8979
  headers: authHeadersSchema,
8881
- pathParams: z27.object({
8882
- id: z27.string().min(1, "Run ID is required")
8980
+ pathParams: z28.object({
8981
+ id: z28.string().min(1, "Run ID is required")
8883
8982
  }),
8884
8983
  responses: {
8885
8984
  200: metricsResponseSchema2,
@@ -8891,7 +8990,7 @@ var publicRunMetricsContract = c19.router({
8891
8990
  description: "Get CPU, memory, and disk metrics for a run"
8892
8991
  }
8893
8992
  });
8894
- var sseEventTypeSchema = z27.enum([
8993
+ var sseEventTypeSchema = z28.enum([
8895
8994
  "status",
8896
8995
  // Run status change
8897
8996
  "output",
@@ -8903,26 +9002,26 @@ var sseEventTypeSchema = z27.enum([
8903
9002
  "heartbeat"
8904
9003
  // Keep-alive
8905
9004
  ]);
8906
- var sseEventSchema = z27.object({
9005
+ var sseEventSchema = z28.object({
8907
9006
  event: sseEventTypeSchema,
8908
- data: z27.unknown(),
8909
- id: z27.string().optional()
9007
+ data: z28.unknown(),
9008
+ id: z28.string().optional()
8910
9009
  // For Last-Event-ID reconnection
8911
9010
  });
8912
- var publicRunEventsContract = c19.router({
9011
+ var publicRunEventsContract = c20.router({
8913
9012
  streamEvents: {
8914
9013
  method: "GET",
8915
9014
  path: "/v1/runs/:id/events",
8916
9015
  headers: authHeadersSchema,
8917
- pathParams: z27.object({
8918
- id: z27.string().min(1, "Run ID is required")
9016
+ pathParams: z28.object({
9017
+ id: z28.string().min(1, "Run ID is required")
8919
9018
  }),
8920
- query: z27.object({
8921
- lastEventId: z27.string().optional()
9019
+ query: z28.object({
9020
+ lastEventId: z28.string().optional()
8922
9021
  // For reconnection
8923
9022
  }),
8924
9023
  responses: {
8925
- 200: z27.any(),
9024
+ 200: z28.any(),
8926
9025
  // SSE stream - actual content is text/event-stream
8927
9026
  401: publicApiErrorSchema,
8928
9027
  404: publicApiErrorSchema,
@@ -8934,28 +9033,28 @@ var publicRunEventsContract = c19.router({
8934
9033
  });
8935
9034
 
8936
9035
  // ../../packages/core/src/contracts/public/artifacts.ts
8937
- import { z as z28 } from "zod";
8938
- var c20 = initContract();
8939
- var publicArtifactSchema = z28.object({
8940
- id: z28.string(),
8941
- name: z28.string(),
8942
- currentVersionId: z28.string().nullable(),
8943
- size: z28.number(),
9036
+ import { z as z29 } from "zod";
9037
+ var c21 = initContract();
9038
+ var publicArtifactSchema = z29.object({
9039
+ id: z29.string(),
9040
+ name: z29.string(),
9041
+ currentVersionId: z29.string().nullable(),
9042
+ size: z29.number(),
8944
9043
  // Total size in bytes
8945
- fileCount: z28.number(),
9044
+ fileCount: z29.number(),
8946
9045
  createdAt: timestampSchema,
8947
9046
  updatedAt: timestampSchema
8948
9047
  });
8949
- var artifactVersionSchema = z28.object({
8950
- id: z28.string(),
9048
+ var artifactVersionSchema = z29.object({
9049
+ id: z29.string(),
8951
9050
  // SHA-256 content hash
8952
- artifactId: z28.string(),
8953
- size: z28.number(),
9051
+ artifactId: z29.string(),
9052
+ size: z29.number(),
8954
9053
  // Size in bytes
8955
- fileCount: z28.number(),
8956
- message: z28.string().nullable(),
9054
+ fileCount: z29.number(),
9055
+ message: z29.string().nullable(),
8957
9056
  // Optional commit message
8958
- createdBy: z28.string(),
9057
+ createdBy: z29.string(),
8959
9058
  createdAt: timestampSchema
8960
9059
  });
8961
9060
  var publicArtifactDetailSchema = publicArtifactSchema.extend({
@@ -8965,7 +9064,7 @@ var paginatedArtifactsSchema = createPaginatedResponseSchema(publicArtifactSchem
8965
9064
  var paginatedArtifactVersionsSchema = createPaginatedResponseSchema(
8966
9065
  artifactVersionSchema
8967
9066
  );
8968
- var publicArtifactsListContract = c20.router({
9067
+ var publicArtifactsListContract = c21.router({
8969
9068
  list: {
8970
9069
  method: "GET",
8971
9070
  path: "/v1/artifacts",
@@ -8980,13 +9079,13 @@ var publicArtifactsListContract = c20.router({
8980
9079
  description: "List all artifacts in the current scope with pagination"
8981
9080
  }
8982
9081
  });
8983
- var publicArtifactByIdContract = c20.router({
9082
+ var publicArtifactByIdContract = c21.router({
8984
9083
  get: {
8985
9084
  method: "GET",
8986
9085
  path: "/v1/artifacts/:id",
8987
9086
  headers: authHeadersSchema,
8988
- pathParams: z28.object({
8989
- id: z28.string().min(1, "Artifact ID is required")
9087
+ pathParams: z29.object({
9088
+ id: z29.string().min(1, "Artifact ID is required")
8990
9089
  }),
8991
9090
  responses: {
8992
9091
  200: publicArtifactDetailSchema,
@@ -8998,13 +9097,13 @@ var publicArtifactByIdContract = c20.router({
8998
9097
  description: "Get artifact details by ID"
8999
9098
  }
9000
9099
  });
9001
- var publicArtifactVersionsContract = c20.router({
9100
+ var publicArtifactVersionsContract = c21.router({
9002
9101
  list: {
9003
9102
  method: "GET",
9004
9103
  path: "/v1/artifacts/:id/versions",
9005
9104
  headers: authHeadersSchema,
9006
- pathParams: z28.object({
9007
- id: z28.string().min(1, "Artifact ID is required")
9105
+ pathParams: z29.object({
9106
+ id: z29.string().min(1, "Artifact ID is required")
9008
9107
  }),
9009
9108
  query: listQuerySchema,
9010
9109
  responses: {
@@ -9017,20 +9116,20 @@ var publicArtifactVersionsContract = c20.router({
9017
9116
  description: "List all versions of an artifact with pagination"
9018
9117
  }
9019
9118
  });
9020
- var publicArtifactDownloadContract = c20.router({
9119
+ var publicArtifactDownloadContract = c21.router({
9021
9120
  download: {
9022
9121
  method: "GET",
9023
9122
  path: "/v1/artifacts/:id/download",
9024
9123
  headers: authHeadersSchema,
9025
- pathParams: z28.object({
9026
- id: z28.string().min(1, "Artifact ID is required")
9124
+ pathParams: z29.object({
9125
+ id: z29.string().min(1, "Artifact ID is required")
9027
9126
  }),
9028
- query: z28.object({
9029
- versionId: z28.string().optional()
9127
+ query: z29.object({
9128
+ versionId: z29.string().optional()
9030
9129
  // Defaults to current version
9031
9130
  }),
9032
9131
  responses: {
9033
- 302: z28.undefined(),
9132
+ 302: z29.undefined(),
9034
9133
  // Redirect to presigned URL
9035
9134
  401: publicApiErrorSchema,
9036
9135
  404: publicApiErrorSchema,
@@ -9042,28 +9141,28 @@ var publicArtifactDownloadContract = c20.router({
9042
9141
  });
9043
9142
 
9044
9143
  // ../../packages/core/src/contracts/public/volumes.ts
9045
- import { z as z29 } from "zod";
9046
- var c21 = initContract();
9047
- var publicVolumeSchema = z29.object({
9048
- id: z29.string(),
9049
- name: z29.string(),
9050
- currentVersionId: z29.string().nullable(),
9051
- size: z29.number(),
9144
+ import { z as z30 } from "zod";
9145
+ var c22 = initContract();
9146
+ var publicVolumeSchema = z30.object({
9147
+ id: z30.string(),
9148
+ name: z30.string(),
9149
+ currentVersionId: z30.string().nullable(),
9150
+ size: z30.number(),
9052
9151
  // Total size in bytes
9053
- fileCount: z29.number(),
9152
+ fileCount: z30.number(),
9054
9153
  createdAt: timestampSchema,
9055
9154
  updatedAt: timestampSchema
9056
9155
  });
9057
- var volumeVersionSchema = z29.object({
9058
- id: z29.string(),
9156
+ var volumeVersionSchema = z30.object({
9157
+ id: z30.string(),
9059
9158
  // SHA-256 content hash
9060
- volumeId: z29.string(),
9061
- size: z29.number(),
9159
+ volumeId: z30.string(),
9160
+ size: z30.number(),
9062
9161
  // Size in bytes
9063
- fileCount: z29.number(),
9064
- message: z29.string().nullable(),
9162
+ fileCount: z30.number(),
9163
+ message: z30.string().nullable(),
9065
9164
  // Optional commit message
9066
- createdBy: z29.string(),
9165
+ createdBy: z30.string(),
9067
9166
  createdAt: timestampSchema
9068
9167
  });
9069
9168
  var publicVolumeDetailSchema = publicVolumeSchema.extend({
@@ -9071,7 +9170,7 @@ var publicVolumeDetailSchema = publicVolumeSchema.extend({
9071
9170
  });
9072
9171
  var paginatedVolumesSchema = createPaginatedResponseSchema(publicVolumeSchema);
9073
9172
  var paginatedVolumeVersionsSchema = createPaginatedResponseSchema(volumeVersionSchema);
9074
- var publicVolumesListContract = c21.router({
9173
+ var publicVolumesListContract = c22.router({
9075
9174
  list: {
9076
9175
  method: "GET",
9077
9176
  path: "/v1/volumes",
@@ -9086,13 +9185,13 @@ var publicVolumesListContract = c21.router({
9086
9185
  description: "List all volumes in the current scope with pagination"
9087
9186
  }
9088
9187
  });
9089
- var publicVolumeByIdContract = c21.router({
9188
+ var publicVolumeByIdContract = c22.router({
9090
9189
  get: {
9091
9190
  method: "GET",
9092
9191
  path: "/v1/volumes/:id",
9093
9192
  headers: authHeadersSchema,
9094
- pathParams: z29.object({
9095
- id: z29.string().min(1, "Volume ID is required")
9193
+ pathParams: z30.object({
9194
+ id: z30.string().min(1, "Volume ID is required")
9096
9195
  }),
9097
9196
  responses: {
9098
9197
  200: publicVolumeDetailSchema,
@@ -9104,13 +9203,13 @@ var publicVolumeByIdContract = c21.router({
9104
9203
  description: "Get volume details by ID"
9105
9204
  }
9106
9205
  });
9107
- var publicVolumeVersionsContract = c21.router({
9206
+ var publicVolumeVersionsContract = c22.router({
9108
9207
  list: {
9109
9208
  method: "GET",
9110
9209
  path: "/v1/volumes/:id/versions",
9111
9210
  headers: authHeadersSchema,
9112
- pathParams: z29.object({
9113
- id: z29.string().min(1, "Volume ID is required")
9211
+ pathParams: z30.object({
9212
+ id: z30.string().min(1, "Volume ID is required")
9114
9213
  }),
9115
9214
  query: listQuerySchema,
9116
9215
  responses: {
@@ -9123,20 +9222,20 @@ var publicVolumeVersionsContract = c21.router({
9123
9222
  description: "List all versions of a volume with pagination"
9124
9223
  }
9125
9224
  });
9126
- var publicVolumeDownloadContract = c21.router({
9225
+ var publicVolumeDownloadContract = c22.router({
9127
9226
  download: {
9128
9227
  method: "GET",
9129
9228
  path: "/v1/volumes/:id/download",
9130
9229
  headers: authHeadersSchema,
9131
- pathParams: z29.object({
9132
- id: z29.string().min(1, "Volume ID is required")
9230
+ pathParams: z30.object({
9231
+ id: z30.string().min(1, "Volume ID is required")
9133
9232
  }),
9134
- query: z29.object({
9135
- versionId: z29.string().optional()
9233
+ query: z30.object({
9234
+ versionId: z30.string().optional()
9136
9235
  // Defaults to current version
9137
9236
  }),
9138
9237
  responses: {
9139
- 302: z29.undefined(),
9238
+ 302: z30.undefined(),
9140
9239
  // Redirect to presigned URL
9141
9240
  401: publicApiErrorSchema,
9142
9241
  404: publicApiErrorSchema,
@@ -9195,11 +9294,10 @@ var ENV_LOADER_PATH = "/usr/local/bin/vm0-agent/env-loader.mjs";
9195
9294
  // src/lib/proxy/vm-registry.ts
9196
9295
  import fs6 from "fs";
9197
9296
  var logger5 = createLogger("VMRegistry");
9198
- var DEFAULT_REGISTRY_PATH = tempPaths.vmRegistry;
9199
9297
  var VMRegistry = class {
9200
9298
  registryPath;
9201
9299
  data;
9202
- constructor(registryPath = DEFAULT_REGISTRY_PATH) {
9300
+ constructor(registryPath) {
9203
9301
  this.registryPath = registryPath;
9204
9302
  this.data = this.load();
9205
9303
  }
@@ -9286,7 +9384,9 @@ var VMRegistry = class {
9286
9384
  var globalRegistry = null;
9287
9385
  function getVMRegistry() {
9288
9386
  if (!globalRegistry) {
9289
- globalRegistry = new VMRegistry();
9387
+ throw new Error(
9388
+ "VMRegistry not initialized. Call initVMRegistry(registryPath) first."
9389
+ );
9290
9390
  }
9291
9391
  return globalRegistry;
9292
9392
  }
@@ -9299,502 +9399,16 @@ function initVMRegistry(registryPath) {
9299
9399
  import { spawn as spawn2 } from "child_process";
9300
9400
  import fs7 from "fs";
9301
9401
  import path5 from "path";
9302
-
9303
- // src/lib/proxy/mitm-addon-script.ts
9304
- var RUNNER_MITM_ADDON_SCRIPT = `#!/usr/bin/env python3
9305
- """
9306
- mitmproxy addon for VM0 runner-level network security mode.
9307
-
9308
- This addon runs on the runner HOST (not inside VMs) and:
9309
- 1. Intercepts all HTTPS requests from VMs
9310
- 2. Looks up the source VM's runId and firewall rules from the VM registry
9311
- 3. Evaluates firewall rules (first-match-wins) to ALLOW or DENY
9312
- 4. For MITM mode: Rewrites requests to go through VM0 Proxy endpoint
9313
- 5. For SNI-only mode: Passes through or blocks without decryption
9314
- 6. Logs network activity per-run to JSONL files
9315
- """
9316
- import os
9317
- import json
9318
- import time
9319
- import urllib.parse
9320
- import ipaddress
9321
- import socket
9322
- from mitmproxy import http, ctx, tls
9323
-
9324
-
9325
- # VM0 Proxy configuration from environment
9326
- API_URL = os.environ.get("VM0_API_URL", "https://www.vm0.ai")
9327
- REGISTRY_PATH = os.environ.get("VM0_REGISTRY_PATH", "/tmp/vm0-vm-registry.json")
9328
- VERCEL_BYPASS = os.environ.get("VERCEL_AUTOMATION_BYPASS_SECRET", "")
9329
-
9330
- # Construct proxy URL
9331
- PROXY_URL = f"{API_URL}/api/webhooks/agent/proxy"
9332
-
9333
- # Cache for VM registry (reloaded periodically)
9334
- _registry_cache = {}
9335
- _registry_cache_time = 0
9336
- REGISTRY_CACHE_TTL = 2 # seconds
9337
-
9338
- # Track request start times for latency calculation
9339
- request_start_times = {}
9340
-
9341
-
9342
- def load_registry() -> dict:
9343
- """Load the VM registry from file, with caching."""
9344
- global _registry_cache, _registry_cache_time
9345
-
9346
- now = time.time()
9347
- if now - _registry_cache_time < REGISTRY_CACHE_TTL:
9348
- return _registry_cache
9349
-
9350
- try:
9351
- if os.path.exists(REGISTRY_PATH):
9352
- with open(REGISTRY_PATH, "r") as f:
9353
- data = json.load(f)
9354
- _registry_cache = data.get("vms", {})
9355
- _registry_cache_time = now
9356
- return _registry_cache
9357
- except Exception as e:
9358
- ctx.log.warn(f"Failed to load VM registry: {e}")
9359
-
9360
- return _registry_cache
9361
-
9362
-
9363
- def get_vm_info(client_ip: str) -> dict | None:
9364
- """Look up VM info by client IP address."""
9365
- registry = load_registry()
9366
- return registry.get(client_ip)
9367
-
9368
-
9369
- def get_network_log_path(run_id: str) -> str:
9370
- """Get the network log file path for a run."""
9371
- return f"/tmp/vm0-network-{run_id}.jsonl"
9372
-
9373
-
9374
- def log_network_entry(run_id: str, entry: dict) -> None:
9375
- """Write a network log entry to the per-run JSONL file."""
9376
- if not run_id:
9377
- return
9378
-
9379
- log_path = get_network_log_path(run_id)
9380
- try:
9381
- fd = os.open(log_path, os.O_CREAT | os.O_APPEND | os.O_WRONLY, 0o644)
9382
- try:
9383
- os.write(fd, (json.dumps(entry) + "\\n").encode())
9384
- finally:
9385
- os.close(fd)
9386
- except Exception as e:
9387
- ctx.log.warn(f"Failed to write network log: {e}")
9388
-
9389
-
9390
- def get_original_url(flow: http.HTTPFlow) -> str:
9391
- """Reconstruct the original target URL from the request."""
9392
- scheme = "https" if flow.request.port == 443 else "http"
9393
- host = flow.request.pretty_host
9394
- port = flow.request.port
9395
-
9396
- if (scheme == "https" and port != 443) or (scheme == "http" and port != 80):
9397
- host_with_port = f"{host}:{port}"
9398
- else:
9399
- host_with_port = host
9400
-
9401
- path = flow.request.path
9402
- return f"{scheme}://{host_with_port}{path}"
9403
-
9404
-
9405
- # ============================================================================
9406
- # Firewall Rule Matching
9407
- # ============================================================================
9408
-
9409
- def match_domain(pattern: str, hostname: str) -> bool:
9410
- """
9411
- Match hostname against domain pattern.
9412
- Supports exact match and wildcard prefix (*.example.com).
9413
- """
9414
- if not pattern or not hostname:
9415
- return False
9416
-
9417
- pattern = pattern.lower()
9418
- hostname = hostname.lower()
9419
-
9420
- if pattern.startswith("*."):
9421
- # Wildcard: *.example.com matches sub.example.com, www.example.com
9422
- # Also matches example.com itself (without subdomain)
9423
- suffix = pattern[1:] # .example.com
9424
- base = pattern[2:] # example.com
9425
- return hostname.endswith(suffix) or hostname == base
9426
-
9427
- return hostname == pattern
9428
-
9429
-
9430
- def match_ip(cidr: str, ip_str: str) -> bool:
9431
- """
9432
- Match IP address against CIDR range.
9433
- Supports single IPs (1.2.3.4) and ranges (10.0.0.0/8).
9434
- """
9435
- if not cidr or not ip_str:
9436
- return False
9437
-
9438
- try:
9439
- # Parse CIDR (automatically handles single IPs as /32)
9440
- if "/" not in cidr:
9441
- cidr = f"{cidr}/32"
9442
- network = ipaddress.ip_network(cidr, strict=False)
9443
- ip = ipaddress.ip_address(ip_str)
9444
- return ip in network
9445
- except ValueError:
9446
- return False
9447
-
9448
-
9449
- def resolve_hostname_to_ip(hostname: str) -> str | None:
9450
- """Resolve hostname to IP address for IP-based rule matching."""
9451
- try:
9452
- return socket.gethostbyname(hostname)
9453
- except socket.gaierror:
9454
- return None
9455
-
9456
-
9457
- def evaluate_rules(rules: list, hostname: str, ip_str: str = None) -> tuple[str, str | None]:
9458
- """
9459
- Evaluate firewall rules against hostname/IP.
9460
- Returns (action, matched_rule_description).
9461
-
9462
- Rule evaluation is first-match-wins (top to bottom).
9463
-
9464
- Rule formats:
9465
- - Domain/IP rule: { domain: "*.example.com", action: "ALLOW" }
9466
- - Terminal rule: { final: "DENY" }
9467
- """
9468
- if not rules:
9469
- return ("ALLOW", None) # No rules = allow all
9470
-
9471
- for rule in rules:
9472
- # Final/terminal rule - value is the action
9473
- final_action = rule.get("final")
9474
- if final_action:
9475
- return (final_action, "final")
9476
-
9477
- # Domain rule
9478
- domain = rule.get("domain")
9479
- if domain and match_domain(domain, hostname):
9480
- return (rule.get("action", "DENY"), f"domain:{domain}")
9481
-
9482
- # IP rule
9483
- ip_pattern = rule.get("ip")
9484
- if ip_pattern:
9485
- target_ip = ip_str
9486
- if not target_ip:
9487
- target_ip = resolve_hostname_to_ip(hostname)
9488
- if target_ip and match_ip(ip_pattern, target_ip):
9489
- return (rule.get("action", "DENY"), f"ip:{ip_pattern}")
9490
-
9491
- # No rule matched - default deny (zero-trust)
9492
- return ("DENY", "default")
9493
-
9494
-
9495
- # ============================================================================
9496
- # TLS ClientHello Handler (SNI-only mode)
9497
- # ============================================================================
9498
-
9499
- def tls_clienthello(data: tls.ClientHelloData) -> None:
9500
- """
9501
- Handle TLS ClientHello for SNI-based filtering.
9502
- This is called BEFORE TLS decryption, allowing SNI-only filtering.
9503
- """
9504
- client_ip = data.context.client.peername[0] if data.context.client.peername else None
9505
- if not client_ip:
9506
- return
9507
-
9508
- vm_info = get_vm_info(client_ip)
9509
- if not vm_info:
9510
- # Not a registered VM - pass through without MITM interception
9511
- # This is critical for CIDR-based rules where all VM traffic is redirected
9512
- data.ignore_connection = True
9513
- return
9514
-
9515
- # If MITM is enabled, let the normal flow handle it
9516
- if vm_info.get("mitmEnabled", False):
9517
- return
9518
-
9519
- # SNI-only mode: check rules based on SNI
9520
- sni = data.context.client.sni
9521
- run_id = vm_info.get("runId", "")
9522
- rules = vm_info.get("firewallRules", [])
9523
-
9524
- # Auto-allow VM0 API requests - the agent MUST be able to communicate with VM0
9525
- if API_URL and sni:
9526
- parsed_api = urllib.parse.urlparse(API_URL)
9527
- api_hostname = parsed_api.hostname.lower() if parsed_api.hostname else ""
9528
- sni_lower = sni.lower()
9529
- if api_hostname and (sni_lower == api_hostname or sni_lower.endswith(f".{api_hostname}")):
9530
- ctx.log.info(f"[{run_id}] SNI-only auto-allow VM0 API: {sni}")
9531
- log_network_entry(run_id, {
9532
- "timestamp": time.strftime("%Y-%m-%dT%H:%M:%S", time.gmtime()),
9533
- "mode": "sni",
9534
- "action": "ALLOW",
9535
- "host": sni,
9536
- "port": 443,
9537
- "rule_matched": "vm0-api",
9538
- })
9539
- data.ignore_connection = True # Pass through without MITM
9540
- return
9541
-
9542
- if not sni:
9543
- # No SNI, can't determine target - block for security
9544
- ctx.log.warn(f"[{run_id}] SNI-only: No SNI in ClientHello, blocking")
9545
- log_network_entry(run_id, {
9546
- "timestamp": time.strftime("%Y-%m-%dT%H:%M:%S", time.gmtime()),
9547
- "mode": "sni",
9548
- "action": "DENY",
9549
- "host": "",
9550
- "port": 443,
9551
- "rule_matched": "no-sni",
9552
- })
9553
- # Don't set ignore_connection - mitmproxy will attempt MITM handshake
9554
- # Since VM doesn't have CA cert (SNI-only mode), TLS will fail immediately
9555
- return
9556
-
9557
- # Evaluate rules
9558
- action, matched_rule = evaluate_rules(rules, sni)
9559
-
9560
- # Log the connection
9561
- log_network_entry(run_id, {
9562
- "timestamp": time.strftime("%Y-%m-%dT%H:%M:%S", time.gmtime()),
9563
- "mode": "sni",
9564
- "action": action,
9565
- "host": sni,
9566
- "port": 443,
9567
- "rule_matched": matched_rule,
9568
- })
9569
-
9570
- if action == "ALLOW":
9571
- # Pass through without MITM - mitmproxy will relay without decryption
9572
- ctx.log.info(f"[{run_id}] SNI-only ALLOW: {sni} (rule: {matched_rule})")
9573
- data.ignore_connection = True
9574
- else:
9575
- # Block the connection by NOT setting ignore_connection
9576
- # mitmproxy will attempt MITM handshake, but since VM doesn't have
9577
- # our CA certificate installed (SNI-only mode), the TLS handshake
9578
- # will fail immediately with a certificate error.
9579
- ctx.log.warn(f"[{run_id}] SNI-only DENY: {sni} (rule: {matched_rule})")
9580
- # Client will see: SSL certificate problem / certificate verify failed
9581
-
9582
-
9583
- # ============================================================================
9584
- # HTTP Request Handler (MITM mode)
9585
- # ============================================================================
9586
-
9587
- def request(flow: http.HTTPFlow) -> None:
9588
- """
9589
- Intercept request and apply firewall rules.
9590
- For MITM mode, rewrites allowed requests to VM0 Proxy.
9591
- """
9592
- # Track request start time
9593
- request_start_times[flow.id] = time.time()
9594
-
9595
- # Get client IP (source VM)
9596
- client_ip = flow.client_conn.peername[0] if flow.client_conn.peername else None
9597
-
9598
- if not client_ip:
9599
- ctx.log.warn("No client IP available, passing through")
9600
- return
9601
-
9602
- # Look up VM info from registry
9603
- vm_info = get_vm_info(client_ip)
9604
-
9605
- if not vm_info:
9606
- # Not a registered VM, pass through without proxying
9607
- ctx.log.info(f"No VM registration for {client_ip}, passing through")
9608
- return
9609
-
9610
- run_id = vm_info.get("runId", "")
9611
- sandbox_token = vm_info.get("sandboxToken", "")
9612
- mitm_enabled = vm_info.get("mitmEnabled", False)
9613
- rules = vm_info.get("firewallRules", [])
9614
-
9615
- # Store info for response handler
9616
- flow.metadata["vm_run_id"] = run_id
9617
- flow.metadata["vm_client_ip"] = client_ip
9618
- flow.metadata["vm_mitm_enabled"] = mitm_enabled
9619
-
9620
- # Get target hostname
9621
- hostname = flow.request.pretty_host.lower()
9622
-
9623
- # Auto-allow VM0 API requests - the agent MUST be able to communicate with VM0
9624
- # This is checked before user firewall rules to ensure agent functionality
9625
- if API_URL:
9626
- parsed_api = urllib.parse.urlparse(API_URL)
9627
- api_hostname = parsed_api.hostname.lower() if parsed_api.hostname else ""
9628
- if api_hostname and (hostname == api_hostname or hostname.endswith(f".{api_hostname}")):
9629
- ctx.log.info(f"[{run_id}] Auto-allow VM0 API: {hostname}")
9630
- flow.metadata["firewall_action"] = "ALLOW"
9631
- flow.metadata["firewall_rule"] = "vm0-api"
9632
- # Continue to skip rewrite check below
9633
- flow.metadata["original_url"] = get_original_url(flow)
9634
- flow.metadata["skip_rewrite"] = True
9635
- return
9636
-
9637
- # Evaluate firewall rules
9638
- action, matched_rule = evaluate_rules(rules, hostname)
9639
- flow.metadata["firewall_action"] = action
9640
- flow.metadata["firewall_rule"] = matched_rule
9641
-
9642
- if action == "DENY":
9643
- ctx.log.warn(f"[{run_id}] Firewall DENY: {hostname} (rule: {matched_rule})")
9644
- # Kill the flow and return error response
9645
- flow.response = http.Response.make(
9646
- 403,
9647
- b"Blocked by firewall",
9648
- {"Content-Type": "text/plain"}
9649
- )
9650
- return
9651
-
9652
- # Request is ALLOWED - proceed with processing
9653
-
9654
- # Skip if no API URL configured
9655
- if not API_URL:
9656
- ctx.log.warn("VM0_API_URL not set, passing through")
9657
- return
9658
-
9659
- # Skip rewriting requests already going to VM0 (avoid loops)
9660
- if API_URL in flow.request.pretty_url:
9661
- flow.metadata["original_url"] = flow.request.pretty_url
9662
- flow.metadata["skip_rewrite"] = True
9663
- return
9664
-
9665
- # Skip rewriting requests to trusted storage domains (S3, etc.)
9666
- # S3 presigned URLs have signatures that break when proxied
9667
- TRUSTED_DOMAINS = [
9668
- ".s3.amazonaws.com",
9669
- ".s3-", # Regional S3 endpoints like s3-us-west-2.amazonaws.com
9670
- "s3.amazonaws.com",
9671
- ".r2.cloudflarestorage.com",
9672
- ".storage.googleapis.com",
9673
- ]
9674
- for domain in TRUSTED_DOMAINS:
9675
- if domain in hostname or hostname.endswith(domain.lstrip(".")):
9676
- ctx.log.info(f"[{run_id}] Skipping trusted storage domain: {hostname}")
9677
- flow.metadata["original_url"] = get_original_url(flow)
9678
- flow.metadata["skip_rewrite"] = True
9679
- return
9680
-
9681
- # Get original target URL
9682
- original_url = get_original_url(flow)
9683
- flow.metadata["original_url"] = original_url
9684
-
9685
- # If MITM is not enabled, just allow the request through without rewriting
9686
- if not mitm_enabled:
9687
- ctx.log.info(f"[{run_id}] Firewall ALLOW (no MITM): {hostname}")
9688
- return
9689
-
9690
- # MITM mode: rewrite to VM0 Proxy
9691
- ctx.log.info(f"[{run_id}] Proxying via MITM: {original_url}")
9692
-
9693
- # Parse proxy URL
9694
- parsed = urllib.parse.urlparse(PROXY_URL)
9695
-
9696
- # Build query params
9697
- query_params = {"url": original_url}
9698
- if run_id:
9699
- query_params["runId"] = run_id
9700
- query_string = urllib.parse.urlencode(query_params)
9701
-
9702
- # Rewrite request to proxy
9703
- flow.request.host = parsed.hostname
9704
- flow.request.port = 443 if parsed.scheme == "https" else 80
9705
- flow.request.scheme = parsed.scheme
9706
- flow.request.path = f"{parsed.path}?{query_string}"
9707
-
9708
- # Save original Authorization header before overwriting
9709
- if "Authorization" in flow.request.headers:
9710
- flow.request.headers["x-vm0-original-authorization"] = flow.request.headers["Authorization"]
9711
-
9712
- # Add sandbox authentication token
9713
- if sandbox_token:
9714
- flow.request.headers["Authorization"] = f"Bearer {sandbox_token}"
9715
-
9716
- # Add Vercel bypass header if configured
9717
- if VERCEL_BYPASS:
9718
- flow.request.headers["x-vercel-protection-bypass"] = VERCEL_BYPASS
9719
-
9720
-
9721
- def response(flow: http.HTTPFlow) -> None:
9722
- """
9723
- Handle response and log network activity.
9724
- """
9725
- # Calculate latency
9726
- start_time = request_start_times.pop(flow.id, None)
9727
- latency_ms = int((time.time() - start_time) * 1000) if start_time else 0
9728
-
9729
- # Get stored info
9730
- run_id = flow.metadata.get("vm_run_id", "")
9731
- original_url = flow.metadata.get("original_url", flow.request.pretty_url)
9732
- mitm_enabled = flow.metadata.get("vm_mitm_enabled", False)
9733
- firewall_action = flow.metadata.get("firewall_action", "ALLOW")
9734
- firewall_rule = flow.metadata.get("firewall_rule")
9735
-
9736
- # Calculate sizes
9737
- request_size = len(flow.request.content) if flow.request.content else 0
9738
- response_size = len(flow.response.content) if flow.response and flow.response.content else 0
9739
- status_code = flow.response.status_code if flow.response else 0
9740
-
9741
- # Parse URL for host
9742
- try:
9743
- parsed_url = urllib.parse.urlparse(original_url)
9744
- host = parsed_url.hostname or flow.request.pretty_host
9745
- port = parsed_url.port or (443 if parsed_url.scheme == "https" else 80)
9746
- except:
9747
- host = flow.request.pretty_host
9748
- port = flow.request.port
9749
-
9750
- # Log network entry for this run
9751
- if run_id:
9752
- log_entry = {
9753
- "timestamp": time.strftime("%Y-%m-%dT%H:%M:%S", time.gmtime()),
9754
- "mode": "mitm" if mitm_enabled else "sni",
9755
- "action": firewall_action,
9756
- "host": host,
9757
- "port": port,
9758
- "rule_matched": firewall_rule,
9759
- }
9760
-
9761
- # Add HTTP details only in MITM mode
9762
- if mitm_enabled:
9763
- log_entry.update({
9764
- "method": flow.request.method,
9765
- "path": flow.request.path.split("?")[0], # Path without query
9766
- "url": original_url,
9767
- "status": status_code,
9768
- "latency_ms": latency_ms,
9769
- "request_size": request_size,
9770
- "response_size": response_size,
9771
- })
9772
-
9773
- log_network_entry(run_id, log_entry)
9774
-
9775
- # Log errors to mitmproxy console
9776
- if flow.response and flow.response.status_code >= 400:
9777
- ctx.log.warn(
9778
- f"[{run_id}] Response {flow.response.status_code}: {original_url}"
9779
- )
9780
-
9781
-
9782
- # mitmproxy addon registration
9783
- addons = [tls_clienthello, request, response]
9784
- `;
9785
-
9786
- // src/lib/proxy/proxy-manager.ts
9787
9402
  var logger6 = createLogger("ProxyManager");
9788
9403
  var DEFAULT_PROXY_OPTIONS = {
9789
- port: 8080,
9790
- registryPath: DEFAULT_REGISTRY_PATH
9404
+ port: 8080
9791
9405
  };
9792
9406
  var ProxyManager = class {
9793
9407
  config;
9794
9408
  process = null;
9795
9409
  isRunning = false;
9796
9410
  constructor(config) {
9797
- const addonPath = path5.join(config.caDir, "mitm_addon.py");
9411
+ const addonPath = path5.join(config.caDir, "mitm-addon.py");
9798
9412
  this.config = {
9799
9413
  ...DEFAULT_PROXY_OPTIONS,
9800
9414
  ...config,
@@ -9817,19 +9431,6 @@ var ProxyManager = class {
9817
9431
  });
9818
9432
  });
9819
9433
  }
9820
- /**
9821
- * Ensure the addon script exists at the configured path
9822
- */
9823
- ensureAddonScript() {
9824
- const addonDir = path5.dirname(this.config.addonPath);
9825
- if (!fs7.existsSync(addonDir)) {
9826
- fs7.mkdirSync(addonDir, { recursive: true });
9827
- }
9828
- fs7.writeFileSync(this.config.addonPath, RUNNER_MITM_ADDON_SCRIPT, {
9829
- mode: 493
9830
- });
9831
- logger6.log(`Addon script written to ${this.config.addonPath}`);
9832
- }
9833
9434
  /**
9834
9435
  * Validate proxy configuration
9835
9436
  */
@@ -9841,7 +9442,9 @@ var ProxyManager = class {
9841
9442
  if (!fs7.existsSync(caCertPath)) {
9842
9443
  throw new Error(`Proxy CA certificate not found: ${caCertPath}`);
9843
9444
  }
9844
- this.ensureAddonScript();
9445
+ if (!fs7.existsSync(this.config.addonPath)) {
9446
+ throw new Error(`Addon script not found: ${this.config.addonPath}`);
9447
+ }
9845
9448
  }
9846
9449
  /**
9847
9450
  * Start mitmproxy
@@ -9871,17 +9474,15 @@ var ProxyManager = class {
9871
9474
  String(this.config.port),
9872
9475
  "--set",
9873
9476
  `confdir=${this.config.caDir}`,
9477
+ "--set",
9478
+ `vm0_api_url=${this.config.apiUrl}`,
9479
+ "--set",
9480
+ `vm0_registry_path=${this.config.registryPath}`,
9874
9481
  "--scripts",
9875
9482
  this.config.addonPath,
9876
9483
  "--quiet"
9877
9484
  ];
9878
- const env = {
9879
- ...process.env,
9880
- VM0_API_URL: this.config.apiUrl,
9881
- VM0_REGISTRY_PATH: this.config.registryPath
9882
- };
9883
9485
  this.process = spawn2("mitmdump", args, {
9884
- env,
9885
9486
  stdio: ["ignore", "pipe", "pipe"],
9886
9487
  detached: false
9887
9488
  });
@@ -10527,14 +10128,6 @@ function checkNetworkPrerequisites() {
10527
10128
  errors
10528
10129
  };
10529
10130
  }
10530
- async function isPortInUse(port) {
10531
- try {
10532
- await execAsync3(`ss -tln | grep -q ":${port} "`);
10533
- return true;
10534
- } catch {
10535
- return false;
10536
- }
10537
- }
10538
10131
 
10539
10132
  // src/lib/runner/runner-lock.ts
10540
10133
  import fs10 from "fs";
@@ -10588,11 +10181,13 @@ async function setupEnvironment(options) {
10588
10181
  process.exit(1);
10589
10182
  }
10590
10183
  logger12.log("Initializing network proxy...");
10591
- initVMRegistry();
10184
+ const registryPath = runnerPaths.vmRegistry(config.base_dir);
10185
+ initVMRegistry(registryPath);
10592
10186
  const proxyManager = initProxyManager({
10593
10187
  apiUrl: config.server.url,
10594
10188
  port: config.proxy.port,
10595
- caDir: config.proxy.ca_dir
10189
+ caDir: config.proxy.ca_dir,
10190
+ registryPath
10596
10191
  });
10597
10192
  let proxyEnabled = false;
10598
10193
  try {
@@ -10942,19 +10537,24 @@ function parseFirecrackerCmdline(cmdline) {
10942
10537
  }
10943
10538
  }
10944
10539
  if (!filePath) return null;
10945
- const match = filePath.match(/vm0-([a-f0-9]+)\//);
10946
- if (!match?.[1]) return null;
10947
- return createVmId(match[1]);
10540
+ const vmIdMatch = filePath.match(/vm0-([a-f0-9]+)\//);
10541
+ if (!vmIdMatch?.[1]) return null;
10542
+ const baseDirMatch = filePath.match(/^(.+)\/workspaces\/vm0-[a-f0-9]+\//);
10543
+ if (!baseDirMatch?.[1]) return null;
10544
+ return { vmId: createVmId(vmIdMatch[1]), baseDir: baseDirMatch[1] };
10948
10545
  }
10949
10546
  function parseMitmproxyCmdline(cmdline) {
10950
10547
  if (!cmdline.includes("mitmproxy") && !cmdline.includes("mitmdump")) {
10951
10548
  return null;
10952
10549
  }
10953
10550
  const args = cmdline.split("\0");
10954
- const portIdx = args.findIndex((a) => a === "-p" || a === "--listen-port");
10955
- const portArg = args[portIdx + 1];
10956
- const port = portIdx !== -1 && portArg ? parseInt(portArg, 10) : void 0;
10957
- return { port };
10551
+ for (const arg of args) {
10552
+ const match = arg.match(/^vm0_registry_path=(.+)\/vm-registry\.json$/);
10553
+ if (match?.[1]) {
10554
+ return match[1];
10555
+ }
10556
+ }
10557
+ return null;
10958
10558
  }
10959
10559
  function findFirecrackerProcesses() {
10960
10560
  const processes = [];
@@ -10972,9 +10572,9 @@ function findFirecrackerProcesses() {
10972
10572
  if (!existsSync4(cmdlinePath)) continue;
10973
10573
  try {
10974
10574
  const cmdline = readFileSync2(cmdlinePath, "utf-8");
10975
- const vmId = parseFirecrackerCmdline(cmdline);
10976
- if (vmId) {
10977
- processes.push({ pid, vmId });
10575
+ const parsed = parseFirecrackerCmdline(cmdline);
10576
+ if (parsed) {
10577
+ processes.push({ pid, vmId: parsed.vmId, baseDir: parsed.baseDir });
10978
10578
  }
10979
10579
  } catch {
10980
10580
  continue;
@@ -11007,13 +10607,14 @@ async function killProcess(pid, timeoutMs = 5e3) {
11007
10607
  }
11008
10608
  return !isProcessRunning(pid);
11009
10609
  }
11010
- function findMitmproxyProcess() {
10610
+ function findMitmproxyProcesses() {
10611
+ const processes = [];
11011
10612
  const procDir = "/proc";
11012
10613
  let entries;
11013
10614
  try {
11014
10615
  entries = readdirSync(procDir);
11015
10616
  } catch {
11016
- return null;
10617
+ return [];
11017
10618
  }
11018
10619
  for (const entry of entries) {
11019
10620
  if (!/^\d+$/.test(entry)) continue;
@@ -11022,26 +10623,26 @@ function findMitmproxyProcess() {
11022
10623
  if (!existsSync4(cmdlinePath)) continue;
11023
10624
  try {
11024
10625
  const cmdline = readFileSync2(cmdlinePath, "utf-8");
11025
- const parsed = parseMitmproxyCmdline(cmdline);
11026
- if (parsed) {
11027
- return { pid, port: parsed.port };
10626
+ const baseDir = parseMitmproxyCmdline(cmdline);
10627
+ if (baseDir) {
10628
+ processes.push({ pid, baseDir });
11028
10629
  }
11029
10630
  } catch {
11030
10631
  continue;
11031
10632
  }
11032
10633
  }
11033
- return null;
10634
+ return processes;
11034
10635
  }
11035
10636
 
11036
10637
  // src/lib/runner/types.ts
11037
- import { z as z30 } from "zod";
11038
- var RunnerModeSchema = z30.enum(["running", "draining", "stopping", "stopped"]);
11039
- var RunnerStatusSchema = z30.object({
10638
+ import { z as z31 } from "zod";
10639
+ var RunnerModeSchema = z31.enum(["running", "draining", "stopping", "stopped"]);
10640
+ var RunnerStatusSchema = z31.object({
11040
10641
  mode: RunnerModeSchema,
11041
- active_runs: z30.number(),
11042
- active_run_ids: z30.array(z30.string()),
11043
- started_at: z30.string(),
11044
- updated_at: z30.string()
10642
+ active_runs: z31.number(),
10643
+ active_run_ids: z31.array(z31.string()),
10644
+ started_at: z31.string(),
10645
+ updated_at: z31.string()
11045
10646
  });
11046
10647
 
11047
10648
  // src/commands/doctor.ts
@@ -11083,20 +10684,14 @@ async function checkApiConnectivity(config, warnings) {
11083
10684
  });
11084
10685
  }
11085
10686
  }
11086
- async function checkNetwork(config, warnings) {
10687
+ function checkNetwork(config, warnings) {
11087
10688
  console.log("Network:");
11088
- const proxyPort = config.proxy.port;
11089
- const mitmProc = findMitmproxyProcess();
11090
- const portInUse = await isPortInUse(proxyPort);
10689
+ const mitmProcesses = findMitmproxyProcesses();
10690
+ const mitmProc = mitmProcesses.find((p) => p.baseDir === config.base_dir);
11091
10691
  if (mitmProc) {
11092
- console.log(` \u2713 Proxy mitmproxy (PID ${mitmProc.pid}) on :${proxyPort}`);
11093
- } else if (portInUse) {
11094
10692
  console.log(
11095
- ` \u26A0\uFE0F Proxy port :${proxyPort} in use but mitmproxy process not found`
10693
+ ` \u2713 Proxy mitmproxy (PID ${mitmProc.pid}) on :${config.proxy.port}`
11096
10694
  );
11097
- warnings.push({
11098
- message: `Port ${proxyPort} is in use but mitmproxy process not detected`
11099
- });
11100
10695
  } else {
11101
10696
  console.log(` \u2717 Proxy mitmproxy not running`);
11102
10697
  warnings.push({ message: "Proxy mitmproxy is not running" });
@@ -11182,7 +10777,8 @@ async function findOrphanNetworkNamespaces(warnings) {
11182
10777
  return [];
11183
10778
  }
11184
10779
  }
11185
- async function detectOrphanResources(jobs, processes, workspaces, statusVmIds, warnings) {
10780
+ async function detectOrphanResources(jobs, allProcesses, workspaces, statusVmIds, baseDir, warnings) {
10781
+ const processes = allProcesses.filter((p) => p.baseDir === baseDir);
11186
10782
  for (const job of jobs) {
11187
10783
  if (!job.firecrackerPid) {
11188
10784
  warnings.push({
@@ -11244,7 +10840,7 @@ var doctorCommand = new Command2("doctor").description("Diagnose runner health,
11244
10840
  console.log("");
11245
10841
  await checkApiConnectivity(config, warnings);
11246
10842
  console.log("");
11247
- await checkNetwork(config, warnings);
10843
+ checkNetwork(config, warnings);
11248
10844
  console.log("");
11249
10845
  const processes = findFirecrackerProcesses();
11250
10846
  const workspaces = existsSync5(workspacesDir) ? readdirSync2(workspacesDir).filter(runnerPaths.isVmWorkspace) : [];
@@ -11256,6 +10852,7 @@ var doctorCommand = new Command2("doctor").description("Diagnose runner health,
11256
10852
  processes,
11257
10853
  workspaces,
11258
10854
  statusVmIds,
10855
+ config.base_dir,
11259
10856
  warnings
11260
10857
  );
11261
10858
  displayWarnings(warnings);
@@ -11502,6 +11099,7 @@ var benchmarkCommand = new Command4("benchmark").description(
11502
11099
  }
11503
11100
  process.exit(1);
11504
11101
  }
11102
+ initVMRegistry(runnerPaths.vmRegistry(config.base_dir));
11505
11103
  timer.log("Initializing pools...");
11506
11104
  const snapshotConfig = config.firecracker.snapshot;
11507
11105
  await initOverlayPool({
@@ -11747,7 +11345,7 @@ var snapshotCommand = new Command5("snapshot").description("Generate a Firecrack
11747
11345
  );
11748
11346
 
11749
11347
  // src/index.ts
11750
- var version = true ? "3.12.1" : "0.1.0";
11348
+ var version = true ? "3.12.3" : "0.1.0";
11751
11349
  program.name("vm0-runner").version(version).description("Self-hosted runner for VM0 agents");
11752
11350
  program.addCommand(startCommand);
11753
11351
  program.addCommand(doctorCommand);