@vm0/runner 2.0.0 → 2.0.2
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 +51 -54
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -105,7 +105,7 @@ async function claimJob(server, runId) {
|
|
|
105
105
|
}
|
|
106
106
|
return response.json();
|
|
107
107
|
}
|
|
108
|
-
async function completeJob(context, exitCode, error) {
|
|
108
|
+
async function completeJob(apiUrl, context, exitCode, error) {
|
|
109
109
|
const headers = {
|
|
110
110
|
Authorization: `Bearer ${context.sandboxToken}`,
|
|
111
111
|
"Content-Type": "application/json"
|
|
@@ -114,18 +114,15 @@ async function completeJob(context, exitCode, error) {
|
|
|
114
114
|
if (bypassSecret) {
|
|
115
115
|
headers["x-vercel-protection-bypass"] = bypassSecret;
|
|
116
116
|
}
|
|
117
|
-
const response = await fetch(
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
})
|
|
127
|
-
}
|
|
128
|
-
);
|
|
117
|
+
const response = await fetch(`${apiUrl}/api/webhooks/agent/complete`, {
|
|
118
|
+
method: "POST",
|
|
119
|
+
headers,
|
|
120
|
+
body: JSON.stringify({
|
|
121
|
+
runId: context.runId,
|
|
122
|
+
exitCode,
|
|
123
|
+
error
|
|
124
|
+
})
|
|
125
|
+
});
|
|
129
126
|
if (!response.ok) {
|
|
130
127
|
const errorData = await response.json();
|
|
131
128
|
throw new Error(
|
|
@@ -654,10 +651,12 @@ var FirecrackerVM = class {
|
|
|
654
651
|
console.log(`[VM ${this.config.vmId}] Stopping...`);
|
|
655
652
|
try {
|
|
656
653
|
if (this.client) {
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
654
|
+
await this.client.sendCtrlAltDel().catch((error) => {
|
|
655
|
+
console.log(
|
|
656
|
+
`[VM ${this.config.vmId}] Graceful shutdown signal failed (VM may already be stopping):`,
|
|
657
|
+
error instanceof Error ? error.message : error
|
|
658
|
+
);
|
|
659
|
+
});
|
|
661
660
|
}
|
|
662
661
|
} finally {
|
|
663
662
|
await this.cleanup();
|
|
@@ -851,14 +850,9 @@ var SSHClient = class {
|
|
|
851
850
|
*/
|
|
852
851
|
async waitUntilReachable(timeoutMs = 12e4, intervalMs = 2e3) {
|
|
853
852
|
const start = Date.now();
|
|
854
|
-
let lastError = null;
|
|
855
853
|
while (Date.now() - start < timeoutMs) {
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
return;
|
|
859
|
-
}
|
|
860
|
-
} catch (err) {
|
|
861
|
-
lastError = err instanceof Error ? err : new Error(String(err));
|
|
854
|
+
if (await this.isReachable()) {
|
|
855
|
+
return;
|
|
862
856
|
}
|
|
863
857
|
await new Promise((resolve) => {
|
|
864
858
|
const remaining = timeoutMs - (Date.now() - start);
|
|
@@ -870,7 +864,7 @@ var SSHClient = class {
|
|
|
870
864
|
});
|
|
871
865
|
}
|
|
872
866
|
throw new Error(
|
|
873
|
-
`SSH not reachable after ${timeoutMs}ms at ${this.config.host}
|
|
867
|
+
`SSH not reachable after ${timeoutMs}ms at ${this.config.host}`
|
|
874
868
|
);
|
|
875
869
|
}
|
|
876
870
|
/**
|
|
@@ -6172,7 +6166,6 @@ var executionContextSchema = z15.object({
|
|
|
6172
6166
|
secretNames: z15.array(z15.string()).nullable(),
|
|
6173
6167
|
checkpointId: z15.string().uuid().nullable(),
|
|
6174
6168
|
sandboxToken: z15.string(),
|
|
6175
|
-
apiUrl: z15.string(),
|
|
6176
6169
|
// New fields for E2B parity:
|
|
6177
6170
|
workingDir: z15.string(),
|
|
6178
6171
|
storageManifest: storageManifestSchema.nullable(),
|
|
@@ -9013,9 +9006,9 @@ function getAllScripts() {
|
|
|
9013
9006
|
function getVmIdFromRunId(runId) {
|
|
9014
9007
|
return runId.split("-")[0] || runId.substring(0, 8);
|
|
9015
9008
|
}
|
|
9016
|
-
function buildEnvironmentVariables(context) {
|
|
9009
|
+
function buildEnvironmentVariables(context, apiUrl) {
|
|
9017
9010
|
const envVars = {
|
|
9018
|
-
VM0_API_URL:
|
|
9011
|
+
VM0_API_URL: apiUrl,
|
|
9019
9012
|
VM0_RUN_ID: context.runId,
|
|
9020
9013
|
VM0_API_TOKEN: context.sandboxToken,
|
|
9021
9014
|
VM0_PROMPT: context.prompt,
|
|
@@ -9155,23 +9148,41 @@ async function executeJob(context, config) {
|
|
|
9155
9148
|
context.cliAgentType || "claude-code"
|
|
9156
9149
|
);
|
|
9157
9150
|
}
|
|
9158
|
-
const envVars = buildEnvironmentVariables(context);
|
|
9151
|
+
const envVars = buildEnvironmentVariables(context, config.server.url);
|
|
9159
9152
|
const envJson = JSON.stringify(envVars);
|
|
9160
9153
|
console.log(
|
|
9161
9154
|
`[Executor] Writing env JSON (${envJson.length} bytes) to ${ENV_JSON_PATH}`
|
|
9162
9155
|
);
|
|
9163
9156
|
await ssh.writeFile(ENV_JSON_PATH, envJson);
|
|
9164
9157
|
const systemLogFile = `/tmp/vm0-main-${context.runId}.log`;
|
|
9165
|
-
|
|
9158
|
+
const exitCodeFile = `/tmp/vm0-exit-${context.runId}`;
|
|
9159
|
+
console.log(`[Executor] Running agent via env-loader (background)...`);
|
|
9166
9160
|
const startTime = Date.now();
|
|
9167
|
-
|
|
9168
|
-
`
|
|
9161
|
+
await ssh.exec(
|
|
9162
|
+
`nohup sh -c 'python3 -u ${ENV_LOADER_PATH}; echo $? > ${exitCodeFile}' > ${systemLogFile} 2>&1 &`
|
|
9169
9163
|
);
|
|
9170
|
-
|
|
9171
|
-
const
|
|
9172
|
-
const
|
|
9173
|
-
|
|
9164
|
+
console.log(`[Executor] Agent started in background`);
|
|
9165
|
+
const pollIntervalMs = 2e3;
|
|
9166
|
+
const maxWaitMs = 24 * 60 * 60 * 1e3;
|
|
9167
|
+
let exitCode = 1;
|
|
9168
|
+
let completed = false;
|
|
9169
|
+
while (Date.now() - startTime < maxWaitMs) {
|
|
9170
|
+
await new Promise((resolve) => setTimeout(resolve, pollIntervalMs));
|
|
9171
|
+
const checkResult = await ssh.exec(`cat ${exitCodeFile} 2>/dev/null`);
|
|
9172
|
+
if (checkResult.exitCode === 0 && checkResult.stdout.trim()) {
|
|
9173
|
+
exitCode = parseInt(checkResult.stdout.trim(), 10) || 1;
|
|
9174
|
+
completed = true;
|
|
9175
|
+
break;
|
|
9176
|
+
}
|
|
9177
|
+
}
|
|
9174
9178
|
const duration = Math.round((Date.now() - startTime) / 1e3);
|
|
9179
|
+
if (!completed) {
|
|
9180
|
+
console.log(`[Executor] Agent timed out after ${duration}s`);
|
|
9181
|
+
return {
|
|
9182
|
+
exitCode: 1,
|
|
9183
|
+
error: `Agent execution timed out after ${duration}s`
|
|
9184
|
+
};
|
|
9185
|
+
}
|
|
9175
9186
|
console.log(
|
|
9176
9187
|
`[Executor] Agent finished in ${duration}s with exit code ${exitCode}`
|
|
9177
9188
|
);
|
|
@@ -9195,14 +9206,7 @@ async function executeJob(context, config) {
|
|
|
9195
9206
|
} finally {
|
|
9196
9207
|
if (vm) {
|
|
9197
9208
|
console.log(`[Executor] Cleaning up VM ${vmId}...`);
|
|
9198
|
-
|
|
9199
|
-
await vm.kill();
|
|
9200
|
-
} catch (error) {
|
|
9201
|
-
console.error(
|
|
9202
|
-
`[Executor] Failed to cleanup VM ${vmId}:`,
|
|
9203
|
-
error instanceof Error ? error.message : error
|
|
9204
|
-
);
|
|
9205
|
-
}
|
|
9209
|
+
await vm.kill();
|
|
9206
9210
|
}
|
|
9207
9211
|
}
|
|
9208
9212
|
}
|
|
@@ -9224,15 +9228,8 @@ async function executeJob2(context, config) {
|
|
|
9224
9228
|
} catch (err) {
|
|
9225
9229
|
const error = err instanceof Error ? err.message : "Unknown execution error";
|
|
9226
9230
|
console.error(` Job ${context.runId} execution failed: ${error}`);
|
|
9227
|
-
|
|
9228
|
-
|
|
9229
|
-
console.log(` Job ${context.runId} reported as ${result.status}`);
|
|
9230
|
-
} catch (reportErr) {
|
|
9231
|
-
console.error(
|
|
9232
|
-
` Failed to report job ${context.runId} completion:`,
|
|
9233
|
-
reportErr instanceof Error ? reportErr.message : "Unknown error"
|
|
9234
|
-
);
|
|
9235
|
-
}
|
|
9231
|
+
const result = await completeJob(config.server.url, context, 1, error);
|
|
9232
|
+
console.log(` Job ${context.runId} reported as ${result.status}`);
|
|
9236
9233
|
}
|
|
9237
9234
|
}
|
|
9238
9235
|
var startCommand = new Command("start").description("Start the runner").option("--config <path>", "Config file path", "./runner.yaml").action(async (options) => {
|
|
@@ -9336,7 +9333,7 @@ var statusCommand = new Command2("status").description("Show runner status").act
|
|
|
9336
9333
|
});
|
|
9337
9334
|
|
|
9338
9335
|
// src/index.ts
|
|
9339
|
-
var version = true ? "2.0.
|
|
9336
|
+
var version = true ? "2.0.2" : "0.1.0";
|
|
9340
9337
|
program.name("vm0-runner").version(version).description("Self-hosted runner for VM0 agents");
|
|
9341
9338
|
program.addCommand(startCommand);
|
|
9342
9339
|
program.addCommand(statusCommand);
|