@vm0/runner 2.0.4 → 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 +58 -1
- 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";
|
|
@@ -9246,6 +9248,22 @@ async function executeJob(context, config) {
|
|
|
9246
9248
|
|
|
9247
9249
|
// src/commands/start.ts
|
|
9248
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
|
+
}
|
|
9249
9267
|
async function executeJob2(context, config) {
|
|
9250
9268
|
console.log(` Executing job ${context.runId}...`);
|
|
9251
9269
|
console.log(` Prompt: ${context.prompt.substring(0, 100)}...`);
|
|
@@ -9280,26 +9298,61 @@ var startCommand = new Command("start").description("Start the runner").option("
|
|
|
9280
9298
|
}
|
|
9281
9299
|
console.log("Setting up network bridge...");
|
|
9282
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
|
+
};
|
|
9283
9307
|
console.log(
|
|
9284
9308
|
`Starting runner '${config.name}' for group '${config.group}'...`
|
|
9285
9309
|
);
|
|
9286
9310
|
console.log(`Max concurrent jobs: ${config.sandbox.max_concurrent}`);
|
|
9311
|
+
console.log(`Status file: ${statusFilePath}`);
|
|
9287
9312
|
console.log("Press Ctrl+C to stop");
|
|
9288
9313
|
console.log("");
|
|
9314
|
+
updateStatus();
|
|
9289
9315
|
let running = true;
|
|
9290
9316
|
process.on("SIGINT", () => {
|
|
9291
9317
|
console.log("\nShutting down...");
|
|
9292
9318
|
running = false;
|
|
9319
|
+
state.mode = "stopped";
|
|
9320
|
+
updateStatus();
|
|
9293
9321
|
});
|
|
9294
9322
|
process.on("SIGTERM", () => {
|
|
9295
9323
|
console.log("\nShutting down...");
|
|
9296
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
|
+
}
|
|
9297
9337
|
});
|
|
9298
9338
|
const jobPromises = /* @__PURE__ */ new Set();
|
|
9299
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
|
+
}
|
|
9300
9352
|
if (activeJobs.size >= config.sandbox.max_concurrent) {
|
|
9301
9353
|
if (jobPromises.size > 0) {
|
|
9302
9354
|
await Promise.race(jobPromises);
|
|
9355
|
+
updateStatus();
|
|
9303
9356
|
}
|
|
9304
9357
|
continue;
|
|
9305
9358
|
}
|
|
@@ -9316,6 +9369,7 @@ var startCommand = new Command("start").description("Start the runner").option("
|
|
|
9316
9369
|
const context = await claimJob(config.server, job.runId);
|
|
9317
9370
|
console.log(`Claimed job: ${context.runId}`);
|
|
9318
9371
|
activeJobs.add(context.runId);
|
|
9372
|
+
updateStatus();
|
|
9319
9373
|
const jobPromise = executeJob2(context, config).catch((error) => {
|
|
9320
9374
|
console.error(
|
|
9321
9375
|
`Job ${context.runId} failed:`,
|
|
@@ -9324,6 +9378,7 @@ var startCommand = new Command("start").description("Start the runner").option("
|
|
|
9324
9378
|
}).finally(() => {
|
|
9325
9379
|
activeJobs.delete(context.runId);
|
|
9326
9380
|
jobPromises.delete(jobPromise);
|
|
9381
|
+
updateStatus();
|
|
9327
9382
|
});
|
|
9328
9383
|
jobPromises.add(jobPromise);
|
|
9329
9384
|
} catch (error) {
|
|
@@ -9346,6 +9401,8 @@ var startCommand = new Command("start").description("Start the runner").option("
|
|
|
9346
9401
|
);
|
|
9347
9402
|
await Promise.all(jobPromises);
|
|
9348
9403
|
}
|
|
9404
|
+
state.mode = "stopped";
|
|
9405
|
+
updateStatus();
|
|
9349
9406
|
console.log("Runner stopped");
|
|
9350
9407
|
process.exit(0);
|
|
9351
9408
|
} catch (error) {
|
|
@@ -9366,7 +9423,7 @@ var statusCommand = new Command2("status").description("Show runner status").act
|
|
|
9366
9423
|
});
|
|
9367
9424
|
|
|
9368
9425
|
// src/index.ts
|
|
9369
|
-
var version = true ? "2.0
|
|
9426
|
+
var version = true ? "2.1.0" : "0.1.0";
|
|
9370
9427
|
program.name("vm0-runner").version(version).description("Self-hosted runner for VM0 agents");
|
|
9371
9428
|
program.addCommand(startCommand);
|
|
9372
9429
|
program.addCommand(statusCommand);
|