@vm0/runner 2.0.3 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.js +72 -4
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -5,6 +5,8 @@ import { program } from "commander";
|
|
|
5
5
|
|
|
6
6
|
// src/commands/start.ts
|
|
7
7
|
import { Command } from "commander";
|
|
8
|
+
import { writeFileSync } from "fs";
|
|
9
|
+
import { dirname, join } from "path";
|
|
8
10
|
|
|
9
11
|
// src/lib/config.ts
|
|
10
12
|
import { z } from "zod";
|
|
@@ -4766,6 +4768,13 @@ var apiErrorSchema = z3.object({
|
|
|
4766
4768
|
// ../../packages/core/src/contracts/composes.ts
|
|
4767
4769
|
import { z as z4 } from "zod";
|
|
4768
4770
|
var c = initContract();
|
|
4771
|
+
var composeVersionQuerySchema = z4.preprocess(
|
|
4772
|
+
(val) => val === void 0 || val === null ? void 0 : String(val),
|
|
4773
|
+
z4.string().min(1, "Missing version query parameter").regex(
|
|
4774
|
+
/^[a-f0-9]{8,64}$|^latest$/i,
|
|
4775
|
+
"Version must be 8-64 hex characters or 'latest'"
|
|
4776
|
+
)
|
|
4777
|
+
);
|
|
4769
4778
|
var agentNameSchema = z4.string().min(3, "Agent name must be at least 3 characters").max(64, "Agent name must be 64 characters or less").regex(
|
|
4770
4779
|
/^[a-zA-Z0-9][a-zA-Z0-9-]{1,62}[a-zA-Z0-9]$/,
|
|
4771
4780
|
"Agent name must start and end with letter or number, and contain only letters, numbers, and hyphens"
|
|
@@ -4902,7 +4911,7 @@ var composesVersionsContract = c.router({
|
|
|
4902
4911
|
path: "/api/agent/composes/versions",
|
|
4903
4912
|
query: z4.object({
|
|
4904
4913
|
composeId: z4.string().min(1, "Missing composeId query parameter"),
|
|
4905
|
-
version:
|
|
4914
|
+
version: composeVersionQuerySchema
|
|
4906
4915
|
}),
|
|
4907
4916
|
responses: {
|
|
4908
4917
|
200: z4.object({
|
|
@@ -5213,6 +5222,10 @@ var runNetworkLogsContract = c2.router({
|
|
|
5213
5222
|
import { z as z6 } from "zod";
|
|
5214
5223
|
var c3 = initContract();
|
|
5215
5224
|
var storageTypeSchema = z6.enum(["volume", "artifact"]);
|
|
5225
|
+
var versionQuerySchema = z6.preprocess(
|
|
5226
|
+
(val) => val === void 0 || val === null ? void 0 : String(val),
|
|
5227
|
+
z6.string().regex(/^[a-f0-9]{8,64}$/i, "Version must be 8-64 hex characters").optional()
|
|
5228
|
+
);
|
|
5216
5229
|
var uploadStorageResponseSchema = z6.object({
|
|
5217
5230
|
name: z6.string(),
|
|
5218
5231
|
versionId: z6.string(),
|
|
@@ -5261,7 +5274,7 @@ var storagesContract = c3.router({
|
|
|
5261
5274
|
path: "/api/storages",
|
|
5262
5275
|
query: z6.object({
|
|
5263
5276
|
name: z6.string().min(1, "Storage name is required"),
|
|
5264
|
-
version:
|
|
5277
|
+
version: versionQuerySchema
|
|
5265
5278
|
}),
|
|
5266
5279
|
responses: {
|
|
5267
5280
|
// Binary response - actual handling done at route level
|
|
@@ -5361,7 +5374,7 @@ var storagesDownloadContract = c3.router({
|
|
|
5361
5374
|
query: z6.object({
|
|
5362
5375
|
name: z6.string().min(1, "Storage name is required"),
|
|
5363
5376
|
type: storageTypeSchema,
|
|
5364
|
-
version:
|
|
5377
|
+
version: versionQuerySchema
|
|
5365
5378
|
}),
|
|
5366
5379
|
responses: {
|
|
5367
5380
|
// Normal response with presigned URL
|
|
@@ -9235,6 +9248,22 @@ async function executeJob(context, config) {
|
|
|
9235
9248
|
|
|
9236
9249
|
// src/commands/start.ts
|
|
9237
9250
|
var activeJobs = /* @__PURE__ */ new Set();
|
|
9251
|
+
function writeStatusFile(statusFilePath, mode, startedAt) {
|
|
9252
|
+
const status = {
|
|
9253
|
+
mode,
|
|
9254
|
+
active_jobs: activeJobs.size,
|
|
9255
|
+
active_job_ids: Array.from(activeJobs),
|
|
9256
|
+
started_at: startedAt.toISOString(),
|
|
9257
|
+
updated_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
9258
|
+
};
|
|
9259
|
+
try {
|
|
9260
|
+
writeFileSync(statusFilePath, JSON.stringify(status, null, 2));
|
|
9261
|
+
} catch (err) {
|
|
9262
|
+
console.error(
|
|
9263
|
+
`Failed to write status file: ${err instanceof Error ? err.message : "Unknown error"}`
|
|
9264
|
+
);
|
|
9265
|
+
}
|
|
9266
|
+
}
|
|
9238
9267
|
async function executeJob2(context, config) {
|
|
9239
9268
|
console.log(` Executing job ${context.runId}...`);
|
|
9240
9269
|
console.log(` Prompt: ${context.prompt.substring(0, 100)}...`);
|
|
@@ -9269,26 +9298,61 @@ var startCommand = new Command("start").description("Start the runner").option("
|
|
|
9269
9298
|
}
|
|
9270
9299
|
console.log("Setting up network bridge...");
|
|
9271
9300
|
await setupBridge();
|
|
9301
|
+
const statusFilePath = join(dirname(options.config), "status.json");
|
|
9302
|
+
const startedAt = /* @__PURE__ */ new Date();
|
|
9303
|
+
const state = { mode: "running" };
|
|
9304
|
+
const updateStatus = () => {
|
|
9305
|
+
writeStatusFile(statusFilePath, state.mode, startedAt);
|
|
9306
|
+
};
|
|
9272
9307
|
console.log(
|
|
9273
9308
|
`Starting runner '${config.name}' for group '${config.group}'...`
|
|
9274
9309
|
);
|
|
9275
9310
|
console.log(`Max concurrent jobs: ${config.sandbox.max_concurrent}`);
|
|
9311
|
+
console.log(`Status file: ${statusFilePath}`);
|
|
9276
9312
|
console.log("Press Ctrl+C to stop");
|
|
9277
9313
|
console.log("");
|
|
9314
|
+
updateStatus();
|
|
9278
9315
|
let running = true;
|
|
9279
9316
|
process.on("SIGINT", () => {
|
|
9280
9317
|
console.log("\nShutting down...");
|
|
9281
9318
|
running = false;
|
|
9319
|
+
state.mode = "stopped";
|
|
9320
|
+
updateStatus();
|
|
9282
9321
|
});
|
|
9283
9322
|
process.on("SIGTERM", () => {
|
|
9284
9323
|
console.log("\nShutting down...");
|
|
9285
9324
|
running = false;
|
|
9325
|
+
state.mode = "stopped";
|
|
9326
|
+
updateStatus();
|
|
9327
|
+
});
|
|
9328
|
+
process.on("SIGUSR1", () => {
|
|
9329
|
+
if (state.mode === "running") {
|
|
9330
|
+
console.log("\n[Maintenance] Entering drain mode...");
|
|
9331
|
+
console.log(
|
|
9332
|
+
`[Maintenance] Active jobs: ${activeJobs.size} (will wait for completion)`
|
|
9333
|
+
);
|
|
9334
|
+
state.mode = "draining";
|
|
9335
|
+
updateStatus();
|
|
9336
|
+
}
|
|
9286
9337
|
});
|
|
9287
9338
|
const jobPromises = /* @__PURE__ */ new Set();
|
|
9288
9339
|
while (running) {
|
|
9340
|
+
if (state.mode === "draining") {
|
|
9341
|
+
if (activeJobs.size === 0) {
|
|
9342
|
+
console.log("[Maintenance] All jobs completed, exiting drain mode");
|
|
9343
|
+
running = false;
|
|
9344
|
+
break;
|
|
9345
|
+
}
|
|
9346
|
+
if (jobPromises.size > 0) {
|
|
9347
|
+
await Promise.race(jobPromises);
|
|
9348
|
+
updateStatus();
|
|
9349
|
+
}
|
|
9350
|
+
continue;
|
|
9351
|
+
}
|
|
9289
9352
|
if (activeJobs.size >= config.sandbox.max_concurrent) {
|
|
9290
9353
|
if (jobPromises.size > 0) {
|
|
9291
9354
|
await Promise.race(jobPromises);
|
|
9355
|
+
updateStatus();
|
|
9292
9356
|
}
|
|
9293
9357
|
continue;
|
|
9294
9358
|
}
|
|
@@ -9305,6 +9369,7 @@ var startCommand = new Command("start").description("Start the runner").option("
|
|
|
9305
9369
|
const context = await claimJob(config.server, job.runId);
|
|
9306
9370
|
console.log(`Claimed job: ${context.runId}`);
|
|
9307
9371
|
activeJobs.add(context.runId);
|
|
9372
|
+
updateStatus();
|
|
9308
9373
|
const jobPromise = executeJob2(context, config).catch((error) => {
|
|
9309
9374
|
console.error(
|
|
9310
9375
|
`Job ${context.runId} failed:`,
|
|
@@ -9313,6 +9378,7 @@ var startCommand = new Command("start").description("Start the runner").option("
|
|
|
9313
9378
|
}).finally(() => {
|
|
9314
9379
|
activeJobs.delete(context.runId);
|
|
9315
9380
|
jobPromises.delete(jobPromise);
|
|
9381
|
+
updateStatus();
|
|
9316
9382
|
});
|
|
9317
9383
|
jobPromises.add(jobPromise);
|
|
9318
9384
|
} catch (error) {
|
|
@@ -9335,6 +9401,8 @@ var startCommand = new Command("start").description("Start the runner").option("
|
|
|
9335
9401
|
);
|
|
9336
9402
|
await Promise.all(jobPromises);
|
|
9337
9403
|
}
|
|
9404
|
+
state.mode = "stopped";
|
|
9405
|
+
updateStatus();
|
|
9338
9406
|
console.log("Runner stopped");
|
|
9339
9407
|
process.exit(0);
|
|
9340
9408
|
} catch (error) {
|
|
@@ -9355,7 +9423,7 @@ var statusCommand = new Command2("status").description("Show runner status").act
|
|
|
9355
9423
|
});
|
|
9356
9424
|
|
|
9357
9425
|
// src/index.ts
|
|
9358
|
-
var version = true ? "2.0
|
|
9426
|
+
var version = true ? "2.1.0" : "0.1.0";
|
|
9359
9427
|
program.name("vm0-runner").version(version).description("Self-hosted runner for VM0 agents");
|
|
9360
9428
|
program.addCommand(startCommand);
|
|
9361
9429
|
program.addCommand(statusCommand);
|