@agent-vm/openclaw-agent-vm-plugin 0.0.80 → 0.0.82
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/dist/index.d.ts +21 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +411 -84
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { EndToolVmActiveUseRequest, HeartbeatToolVmActiveUseResponse, StartToolVmActiveUseRequest, StartToolVmActiveUseResponse, ToolVmLeasePeek, ToolVmSshLease } from "@agent-vm/gateway-interface";
|
|
1
|
+
import { EndToolVmActiveUseRequest, HeartbeatToolVmActiveUseRequest, HeartbeatToolVmActiveUseResponse, StartToolVmActiveUseRequest, StartToolVmActiveUseResponse, ToolVmLeasePeek, ToolVmSshLease } from "@agent-vm/gateway-interface";
|
|
2
2
|
|
|
3
3
|
//#region src/controller-lease-client.d.ts
|
|
4
4
|
type JsonValue = boolean | null | number | string | {
|
|
@@ -22,16 +22,15 @@ interface OpenClawGondolinLeaseSandboxSnapshot {
|
|
|
22
22
|
interface OpenClawGondolinLeaseRequest {
|
|
23
23
|
readonly agentId: string;
|
|
24
24
|
readonly agentWorkspaceDir: string;
|
|
25
|
+
readonly idleTtlMs?: number;
|
|
25
26
|
readonly profileId: string;
|
|
26
|
-
readonly sandbox: OpenClawGondolinLeaseSandboxSnapshot;
|
|
27
|
-
readonly scopeKey: string;
|
|
28
27
|
readonly sessionKey: string;
|
|
29
28
|
readonly workMountDir: string;
|
|
30
29
|
readonly zoneId: string;
|
|
31
30
|
}
|
|
32
31
|
interface LeaseClient {
|
|
33
32
|
endActiveUse(leaseId: string, useId: string, request: EndToolVmActiveUseRequest): Promise<void>;
|
|
34
|
-
heartbeatActiveUse(leaseId: string, useId: string): Promise<HeartbeatToolVmActiveUseResponse>;
|
|
33
|
+
heartbeatActiveUse(leaseId: string, useId: string, request: HeartbeatToolVmActiveUseRequest): Promise<HeartbeatToolVmActiveUseResponse>;
|
|
35
34
|
peekLease(leaseId: string): Promise<ToolVmLeasePeek>;
|
|
36
35
|
publishOpenClawRuntimeStatus?(report: OpenClawRuntimeStatusReport): Promise<void>;
|
|
37
36
|
releaseLease(leaseId: string, options?: {
|
|
@@ -74,7 +73,7 @@ declare const OPENCLAW_GONDOLIN_SANDBOX_REQUIREMENTS: readonly [{
|
|
|
74
73
|
readonly expectedValue: "rw";
|
|
75
74
|
readonly key: "workspaceAccess";
|
|
76
75
|
}];
|
|
77
|
-
declare const OPENCLAW_GONDOLIN_LEASE_SCOPE_GUIDANCE = "Managed OpenClaw/Gondolin
|
|
76
|
+
declare const OPENCLAW_GONDOLIN_LEASE_SCOPE_GUIDANCE = "Managed OpenClaw/Gondolin leases are agent-scoped. The plugin derives agentId from sessionKey and does not send OpenClaw scope keys to the controller.";
|
|
78
77
|
type OpenClawGondolinSandboxRequirement = (typeof OPENCLAW_GONDOLIN_SANDBOX_REQUIREMENTS)[number];
|
|
79
78
|
type OpenClawGondolinSandboxRequirementKey = OpenClawGondolinSandboxRequirement['key'];
|
|
80
79
|
interface OpenClawGondolinSandboxSnapshot {
|
|
@@ -400,8 +399,24 @@ declare const plugin: {
|
|
|
400
399
|
}): void;
|
|
401
400
|
};
|
|
402
401
|
//#endregion
|
|
402
|
+
//#region src/openclaw-runtime-status.d.ts
|
|
403
|
+
interface OpenClawRuntimeRequirementFinding {
|
|
404
|
+
readonly hint: string;
|
|
405
|
+
readonly id: string;
|
|
406
|
+
readonly ok: boolean;
|
|
407
|
+
}
|
|
408
|
+
interface OpenClawRuntimeStatusReport$1 {
|
|
409
|
+
readonly findings: readonly OpenClawRuntimeRequirementFinding[];
|
|
410
|
+
readonly pluginId: 'gondolin';
|
|
411
|
+
readonly zoneId: string;
|
|
412
|
+
}
|
|
413
|
+
declare function buildOpenClawRuntimeStatusReport(options: {
|
|
414
|
+
readonly config: Record<string, unknown>;
|
|
415
|
+
readonly zoneId: string;
|
|
416
|
+
}): OpenClawRuntimeStatusReport$1;
|
|
417
|
+
//#endregion
|
|
403
418
|
//#region src/index.d.ts
|
|
404
419
|
declare const OPENCLAW_GONDOLIN_PLUGIN_PACKAGE_NAME = "@agent-vm/openclaw-agent-vm-plugin";
|
|
405
420
|
//#endregion
|
|
406
|
-
export { ControllerLeaseRequestError, ControllerLeaseRequestErrorKind, type CreateBackendDependencies, JsonValue, LeaseClient, OPENCLAW_DEFAULT_AGENT_ID, OPENCLAW_GONDOLIN_LEASE_SCOPE_GUIDANCE, OPENCLAW_GONDOLIN_PLUGIN_PACKAGE_NAME, OPENCLAW_GONDOLIN_SANDBOX_REQUIREMENTS, OPENCLAW_SSH_SESSION_SCRATCH_ROOT, type OpenClawFsBridgeLeaseContext, OpenClawGondolinAgentConfig, OpenClawGondolinLeaseRequest, OpenClawGondolinLeaseSandboxSnapshot, OpenClawGondolinSandboxRequirement, OpenClawGondolinSandboxRequirementKey, OpenClawGondolinSandboxSnapshot, OpenClawRuntimeStatusReport, type OpenClawSandboxBackendHandle, type OpenClawSandboxFsBridge, ResolvedGondolinPluginConfig, type SshHelpers, createBackendDeps, createGondolinSandboxBackendFactory, createGondolinSandboxBackendManager, createLeaseClient, plugin as default, effectiveOpenClawGondolinSandboxValue, findOpenClawGondolinSandboxMismatch, formatOpenClawGondolinRequirementFieldPath, formatOpenClawGondolinRequirementFindingId, formatOpenClawGondolinRequirementHint, isOpenClawAgentId, isOpenClawAgentSessionKey, normalizeOpenClawAgentId, resolveGondolinPluginConfig, resolveOpenClawAgentIdFromSessionKey, snapshotOpenClawGondolinSandboxConfig };
|
|
421
|
+
export { ControllerLeaseRequestError, ControllerLeaseRequestErrorKind, type CreateBackendDependencies, JsonValue, LeaseClient, OPENCLAW_DEFAULT_AGENT_ID, OPENCLAW_GONDOLIN_LEASE_SCOPE_GUIDANCE, OPENCLAW_GONDOLIN_PLUGIN_PACKAGE_NAME, OPENCLAW_GONDOLIN_SANDBOX_REQUIREMENTS, OPENCLAW_SSH_SESSION_SCRATCH_ROOT, type OpenClawFsBridgeLeaseContext, OpenClawGondolinAgentConfig, OpenClawGondolinLeaseRequest, OpenClawGondolinLeaseSandboxSnapshot, OpenClawGondolinSandboxRequirement, OpenClawGondolinSandboxRequirementKey, OpenClawGondolinSandboxSnapshot, OpenClawRuntimeStatusReport, type OpenClawSandboxBackendHandle, type OpenClawSandboxFsBridge, ResolvedGondolinPluginConfig, type SshHelpers, buildOpenClawRuntimeStatusReport, createBackendDeps, createGondolinSandboxBackendFactory, createGondolinSandboxBackendManager, createLeaseClient, plugin as default, effectiveOpenClawGondolinSandboxValue, findOpenClawGondolinSandboxMismatch, formatOpenClawGondolinRequirementFieldPath, formatOpenClawGondolinRequirementFindingId, formatOpenClawGondolinRequirementHint, isOpenClawAgentId, isOpenClawAgentSessionKey, normalizeOpenClawAgentId, resolveGondolinPluginConfig, resolveOpenClawAgentIdFromSessionKey, snapshotOpenClawGondolinSandboxConfig };
|
|
407
422
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/controller-lease-client.ts","../src/openclaw-gondolin-contract.ts","../src/sandbox-backend/sandbox-backend-contract.ts","../src/sandbox-backend/sandbox-backend-handle-factory.ts","../src/sandbox-backend/sandbox-backend-manager.ts","../src/gondolin-plugin-config.ts","../src/openclaw-sandbox-sdk-contract.ts","../src/openclaw-backend-dependencies.ts","../src/openclaw-plugin-registration.ts","../src/index.ts"],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/controller-lease-client.ts","../src/openclaw-gondolin-contract.ts","../src/sandbox-backend/sandbox-backend-contract.ts","../src/sandbox-backend/sandbox-backend-handle-factory.ts","../src/sandbox-backend/sandbox-backend-manager.ts","../src/gondolin-plugin-config.ts","../src/openclaw-sandbox-sdk-contract.ts","../src/openclaw-backend-dependencies.ts","../src/openclaw-plugin-registration.ts","../src/openclaw-runtime-status.ts","../src/index.ts"],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createToolVmActiveUseHandle, isToolVmLeasePeek, isToolVmSshLease } from "@agent-vm/gateway-interface";
|
|
1
|
+
import { OPENCLAW_STATE_SANDBOXES_VM_ROOT, TOOL_VM_SCRATCH_GUEST_ROOT, TOOL_VM_WORKSPACE_GUEST_ROOT, createToolVmActiveUseHandle, isToolVmLeasePeek, isToolVmSshLease, translateRuntimePath } from "@agent-vm/gateway-interface";
|
|
2
2
|
import { z } from "zod";
|
|
3
3
|
//#region src/controller-lease-client.ts
|
|
4
4
|
var ControllerLeaseRequestError = class extends Error {
|
|
@@ -46,7 +46,7 @@ function isHeartbeatActiveUseResponse(value) {
|
|
|
46
46
|
const record = objectValue(value);
|
|
47
47
|
return record !== void 0 && typeof Reflect.get(record, "expiresAt") === "number" && typeof Reflect.get(record, "heartbeatAfterMs") === "number";
|
|
48
48
|
}
|
|
49
|
-
function formatUnknownError$
|
|
49
|
+
function formatUnknownError$2(error) {
|
|
50
50
|
return error instanceof Error ? error.message : String(error);
|
|
51
51
|
}
|
|
52
52
|
function writeLeaseClientLog(message) {
|
|
@@ -58,7 +58,7 @@ function parseJsonBody(bodyText, context) {
|
|
|
58
58
|
const parsedBody = jsonValueSchema.safeParse(parsedJson);
|
|
59
59
|
return parsedBody.success ? parsedBody.data : void 0;
|
|
60
60
|
} catch (error) {
|
|
61
|
-
writeLeaseClientLog(`${context} returned a non-JSON error body: ${formatUnknownError$
|
|
61
|
+
writeLeaseClientLog(`${context} returned a non-JSON error body: ${formatUnknownError$2(error)}`);
|
|
62
62
|
return;
|
|
63
63
|
}
|
|
64
64
|
}
|
|
@@ -106,8 +106,12 @@ function createLeaseClient(options) {
|
|
|
106
106
|
});
|
|
107
107
|
}
|
|
108
108
|
},
|
|
109
|
-
heartbeatActiveUse: async (leaseId, useId) => {
|
|
110
|
-
return await readJsonResponse(await fetchImpl(`${baseUrl}/lease/${encodeURIComponent(leaseId)}/uses/${encodeURIComponent(useId)}/heartbeat`, {
|
|
109
|
+
heartbeatActiveUse: async (leaseId, useId, request) => {
|
|
110
|
+
return await readJsonResponse(await fetchImpl(`${baseUrl}/lease/${encodeURIComponent(leaseId)}/uses/${encodeURIComponent(useId)}/heartbeat`, {
|
|
111
|
+
body: JSON.stringify(request),
|
|
112
|
+
headers: { "content-type": "application/json" },
|
|
113
|
+
method: "POST"
|
|
114
|
+
}), "Controller active-use heartbeat API", isHeartbeatActiveUseResponse);
|
|
111
115
|
},
|
|
112
116
|
renewLease,
|
|
113
117
|
peekLease: async (leaseId) => {
|
|
@@ -148,9 +152,8 @@ function createLeaseClient(options) {
|
|
|
148
152
|
body: JSON.stringify({
|
|
149
153
|
agentId: request.agentId,
|
|
150
154
|
agentWorkspaceDir: request.agentWorkspaceDir,
|
|
155
|
+
...request.idleTtlMs !== void 0 ? { idleTtlMs: request.idleTtlMs } : {},
|
|
151
156
|
profileId: request.profileId,
|
|
152
|
-
sandbox: request.sandbox,
|
|
153
|
-
scopeKey: request.scopeKey,
|
|
154
157
|
sessionKey: request.sessionKey,
|
|
155
158
|
workMountDir: request.workMountDir,
|
|
156
159
|
zoneId: request.zoneId
|
|
@@ -190,7 +193,7 @@ const OPENCLAW_GONDOLIN_SANDBOX_REQUIREMENTS = [
|
|
|
190
193
|
key: "workspaceAccess"
|
|
191
194
|
}
|
|
192
195
|
];
|
|
193
|
-
const OPENCLAW_GONDOLIN_LEASE_SCOPE_GUIDANCE = "Managed OpenClaw/Gondolin
|
|
196
|
+
const OPENCLAW_GONDOLIN_LEASE_SCOPE_GUIDANCE = "Managed OpenClaw/Gondolin leases are agent-scoped. The plugin derives agentId from sessionKey and does not send OpenClaw scope keys to the controller.";
|
|
194
197
|
function isOpenClawAgentId(value) {
|
|
195
198
|
return agentIdPattern.test(value.trim());
|
|
196
199
|
}
|
|
@@ -231,21 +234,211 @@ function findOpenClawGondolinSandboxMismatch(sandbox) {
|
|
|
231
234
|
return OPENCLAW_GONDOLIN_SANDBOX_REQUIREMENTS.find((requirement) => sandbox[requirement.key] !== requirement.expectedValue);
|
|
232
235
|
}
|
|
233
236
|
//#endregion
|
|
237
|
+
//#region src/sandbox-backend/openclaw-tool-vm-path-mapping.ts
|
|
238
|
+
var OpenClawToolVmPathIntentError = class extends Error {
|
|
239
|
+
details;
|
|
240
|
+
constructor(details) {
|
|
241
|
+
super(`${details.message} ${details.retryGuidance}`);
|
|
242
|
+
this.name = "OpenClawToolVmPathIntentError";
|
|
243
|
+
this.details = details;
|
|
244
|
+
}
|
|
245
|
+
};
|
|
246
|
+
function pathContainsParentTraversal(inputPath) {
|
|
247
|
+
return inputPath.split(/\/+/u).includes("..");
|
|
248
|
+
}
|
|
249
|
+
function normalizedAbsolutePath(inputPath) {
|
|
250
|
+
return `/${inputPath.split("/").filter((segment) => segment !== "" && segment !== ".").join("/")}`;
|
|
251
|
+
}
|
|
252
|
+
function invalidAgentWorkspaceRootError(agentWorkspaceDir) {
|
|
253
|
+
return {
|
|
254
|
+
allowedPathForms: [],
|
|
255
|
+
code: "invalid-runtime-root",
|
|
256
|
+
inputPath: agentWorkspaceDir,
|
|
257
|
+
mappingId: "openclaw-tool-vm",
|
|
258
|
+
message: `OpenClaw agentWorkspaceDir '${agentWorkspaceDir}' must be an absolute non-root path without parent traversal.`,
|
|
259
|
+
purpose: "executionCwd",
|
|
260
|
+
retryGuidance: "Retry with OpenClaw agentWorkspaceDir set to the resolved host RealFS workspace for the requested agent."
|
|
261
|
+
};
|
|
262
|
+
}
|
|
263
|
+
function validateAgentWorkspaceDir(agentWorkspaceDir) {
|
|
264
|
+
if (agentWorkspaceDir.trim() === "" || !agentWorkspaceDir.startsWith("/") || normalizedAbsolutePath(agentWorkspaceDir) === "/" || pathContainsParentTraversal(agentWorkspaceDir)) return invalidAgentWorkspaceRootError(agentWorkspaceDir);
|
|
265
|
+
}
|
|
266
|
+
function createOpenClawToolVmPathMapping(options) {
|
|
267
|
+
return {
|
|
268
|
+
id: "openclaw-tool-vm",
|
|
269
|
+
roots: [
|
|
270
|
+
{
|
|
271
|
+
id: "agent-workspace",
|
|
272
|
+
guestRoot: TOOL_VM_WORKSPACE_GUEST_ROOT,
|
|
273
|
+
hostRoot: options.agentWorkspaceDir,
|
|
274
|
+
backing: {
|
|
275
|
+
kind: "host-realfs",
|
|
276
|
+
durability: "durable",
|
|
277
|
+
backup: "included"
|
|
278
|
+
},
|
|
279
|
+
capabilities: {
|
|
280
|
+
executionCwd: true,
|
|
281
|
+
leaseMount: true
|
|
282
|
+
},
|
|
283
|
+
rootPathAllowed: true,
|
|
284
|
+
guidanceLabel: "agent workspace"
|
|
285
|
+
},
|
|
286
|
+
{
|
|
287
|
+
id: "tool-vm-scratch",
|
|
288
|
+
guestRoot: TOOL_VM_SCRATCH_GUEST_ROOT,
|
|
289
|
+
backing: {
|
|
290
|
+
kind: "guest-rootfs-cow",
|
|
291
|
+
durability: "vm-lifetime"
|
|
292
|
+
},
|
|
293
|
+
capabilities: {
|
|
294
|
+
executionCwd: true,
|
|
295
|
+
leaseMount: false
|
|
296
|
+
},
|
|
297
|
+
rootPathAllowed: true,
|
|
298
|
+
guidanceLabel: "Tool VM scratch"
|
|
299
|
+
},
|
|
300
|
+
{
|
|
301
|
+
id: "openclaw-sandboxes",
|
|
302
|
+
hostRoot: OPENCLAW_STATE_SANDBOXES_VM_ROOT,
|
|
303
|
+
backing: {
|
|
304
|
+
kind: "host-realfs",
|
|
305
|
+
durability: "durable",
|
|
306
|
+
backup: "included"
|
|
307
|
+
},
|
|
308
|
+
capabilities: {
|
|
309
|
+
executionCwd: true,
|
|
310
|
+
leaseMount: true
|
|
311
|
+
},
|
|
312
|
+
rootPathAllowed: false,
|
|
313
|
+
guidanceLabel: "OpenClaw sandbox work directory"
|
|
314
|
+
}
|
|
315
|
+
]
|
|
316
|
+
};
|
|
317
|
+
}
|
|
318
|
+
function resolveOpenClawSandboxPathIntent(translation) {
|
|
319
|
+
const [sandboxChild, ...guestCwdSegments] = translation.relativePath.split("/");
|
|
320
|
+
const leaseWorkMountDir = sandboxChild === void 0 || sandboxChild === "" ? translation.hostPath ?? OPENCLAW_STATE_SANDBOXES_VM_ROOT : `${OPENCLAW_STATE_SANDBOXES_VM_ROOT}/${sandboxChild}`;
|
|
321
|
+
return {
|
|
322
|
+
effectiveGuestCwd: guestCwdSegments.length === 0 ? TOOL_VM_WORKSPACE_GUEST_ROOT : `${TOOL_VM_WORKSPACE_GUEST_ROOT}/${guestCwdSegments.join("/")}`,
|
|
323
|
+
leaseWorkMountDir
|
|
324
|
+
};
|
|
325
|
+
}
|
|
326
|
+
function kindForTranslation(translation) {
|
|
327
|
+
const isRoot = translation.relativePath === "";
|
|
328
|
+
if (translation.rootId === "tool-vm-scratch") return isRoot ? "scratch-root" : "scratch-subpath";
|
|
329
|
+
if (translation.rootId === "openclaw-sandboxes") return "openclaw-sandbox-path";
|
|
330
|
+
if (translation.inputNamespace === "host") return isRoot ? "host-workspace-root" : "host-workspace-subpath";
|
|
331
|
+
return isRoot ? "workspace-root" : "workspace-subpath";
|
|
332
|
+
}
|
|
333
|
+
function resolveOpenClawToolVmPathIntent(options) {
|
|
334
|
+
const agentWorkspaceDirError = validateAgentWorkspaceDir(options.agentWorkspaceDir);
|
|
335
|
+
if (agentWorkspaceDirError !== void 0) return {
|
|
336
|
+
error: agentWorkspaceDirError,
|
|
337
|
+
ok: false
|
|
338
|
+
};
|
|
339
|
+
const translation = translateRuntimePath({
|
|
340
|
+
inputPath: options.inputPath,
|
|
341
|
+
mapping: createOpenClawToolVmPathMapping({ agentWorkspaceDir: options.agentWorkspaceDir }),
|
|
342
|
+
purpose: "executionCwd"
|
|
343
|
+
});
|
|
344
|
+
if (!translation.ok) return translation;
|
|
345
|
+
const sandboxPathIntent = translation.value.rootId === "openclaw-sandboxes" ? resolveOpenClawSandboxPathIntent(translation.value) : void 0;
|
|
346
|
+
return {
|
|
347
|
+
ok: true,
|
|
348
|
+
value: {
|
|
349
|
+
effectiveGuestCwd: sandboxPathIntent !== void 0 ? sandboxPathIntent.effectiveGuestCwd : translation.value.guestPath ?? TOOL_VM_WORKSPACE_GUEST_ROOT,
|
|
350
|
+
...translation.value.hostPath !== void 0 ? { hostEquivalentPath: translation.value.hostPath } : {},
|
|
351
|
+
kind: kindForTranslation(translation.value),
|
|
352
|
+
leaseWorkMountDir: sandboxPathIntent !== void 0 ? sandboxPathIntent.leaseWorkMountDir : translation.value.hostRoot ?? options.agentWorkspaceDir
|
|
353
|
+
}
|
|
354
|
+
};
|
|
355
|
+
}
|
|
356
|
+
function assertOpenClawToolVmPathIntent(options) {
|
|
357
|
+
const result = resolveOpenClawToolVmPathIntent(options);
|
|
358
|
+
if (!result.ok) throw new OpenClawToolVmPathIntentError(result.error);
|
|
359
|
+
return result.value;
|
|
360
|
+
}
|
|
361
|
+
//#endregion
|
|
234
362
|
//#region src/sandbox-backend/sandbox-shell-script.ts
|
|
235
363
|
function buildShellScriptWithArgs(script, args) {
|
|
236
364
|
if (!args || args.length === 0) return script;
|
|
237
365
|
return `set -- ${args.map((arg) => `'${arg.replace(/'/g, "'\\''")}'`).join(" ")}; ${script}`;
|
|
238
366
|
}
|
|
239
367
|
//#endregion
|
|
368
|
+
//#region src/sandbox-backend/tool-vm-ssh-operation-guard.ts
|
|
369
|
+
var ToolVmSshOperationStaleError = class extends Error {
|
|
370
|
+
cause;
|
|
371
|
+
reason;
|
|
372
|
+
constructor(options) {
|
|
373
|
+
super(options.message);
|
|
374
|
+
this.cause = options.cause;
|
|
375
|
+
this.reason = options.reason;
|
|
376
|
+
}
|
|
377
|
+
};
|
|
378
|
+
function formatUnknownError$1(error) {
|
|
379
|
+
return error instanceof Error ? error.message : String(error);
|
|
380
|
+
}
|
|
381
|
+
async function runToolVmSshOperationWithGuard(options) {
|
|
382
|
+
const now = options.now ?? Date.now;
|
|
383
|
+
const setTimeoutImpl = options.setTimeoutImpl ?? setTimeout;
|
|
384
|
+
const clearTimeoutImpl = options.clearTimeoutImpl ?? clearTimeout;
|
|
385
|
+
const abortController = new AbortController();
|
|
386
|
+
let timeoutHandle;
|
|
387
|
+
options.report({
|
|
388
|
+
observedAtMs: now(),
|
|
389
|
+
phase: "running"
|
|
390
|
+
});
|
|
391
|
+
const timeoutPromise = new Promise((_resolve, reject) => {
|
|
392
|
+
timeoutHandle = setTimeoutImpl(() => {
|
|
393
|
+
abortController.abort();
|
|
394
|
+
reject(new ToolVmSshOperationStaleError({
|
|
395
|
+
cause: void 0,
|
|
396
|
+
message: `${options.operationName} exceeded ${String(options.timeoutMs)}ms.`,
|
|
397
|
+
reason: "ssh-command-timed-out"
|
|
398
|
+
}));
|
|
399
|
+
}, options.timeoutMs);
|
|
400
|
+
});
|
|
401
|
+
try {
|
|
402
|
+
const result = await Promise.race([options.operation(abortController.signal), timeoutPromise]);
|
|
403
|
+
options.report({
|
|
404
|
+
observedAtMs: now(),
|
|
405
|
+
phase: "completed",
|
|
406
|
+
ssh: { probeSucceeded: true }
|
|
407
|
+
});
|
|
408
|
+
return result;
|
|
409
|
+
} catch (error) {
|
|
410
|
+
const staleError = error instanceof ToolVmSshOperationStaleError ? error : new ToolVmSshOperationStaleError({
|
|
411
|
+
cause: error,
|
|
412
|
+
message: formatUnknownError$1(error),
|
|
413
|
+
reason: "ssh-command-failed"
|
|
414
|
+
});
|
|
415
|
+
options.report({
|
|
416
|
+
observedAtMs: now(),
|
|
417
|
+
phase: "failed",
|
|
418
|
+
ssh: { failure: {
|
|
419
|
+
kind: staleError.reason,
|
|
420
|
+
message: staleError.message
|
|
421
|
+
} }
|
|
422
|
+
});
|
|
423
|
+
throw staleError;
|
|
424
|
+
} finally {
|
|
425
|
+
if (timeoutHandle !== void 0) clearTimeoutImpl(timeoutHandle);
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
//#endregion
|
|
240
429
|
//#region src/sandbox-backend/sandbox-backend-handle-factory.ts
|
|
241
430
|
function agentLeaseCacheKey(params) {
|
|
242
|
-
return [
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
431
|
+
return [params.zoneId, params.agentId].join("\0");
|
|
432
|
+
}
|
|
433
|
+
function findCachedLeaseCompatibilityMismatch(params) {
|
|
434
|
+
if (params.cachedEntry.agentWorkspaceDir !== params.requestedEntry.agentWorkspaceDir) return "agentWorkspaceDir";
|
|
435
|
+
if (params.cachedEntry.leaseWorkMountDir !== params.requestedEntry.leaseWorkMountDir) return "leaseWorkMountDir";
|
|
436
|
+
if (params.cachedEntry.profileId !== params.requestedEntry.profileId) return "profileId";
|
|
437
|
+
}
|
|
438
|
+
function assertCachedLeaseCompatible(params) {
|
|
439
|
+
const mismatch = findCachedLeaseCompatibilityMismatch(params);
|
|
440
|
+
if (mismatch === void 0) return;
|
|
441
|
+
throw new Error(`Cannot reuse cached Tool VM lease for zone '${params.zoneId}' agent '${params.agentId}': ${mismatch} changed.`);
|
|
249
442
|
}
|
|
250
443
|
function formatControllerLeaseRequestError(error) {
|
|
251
444
|
const responseBody = error.responseBody === void 0 ? error.bodyText : JSON.stringify(error.responseBody);
|
|
@@ -259,7 +452,10 @@ function writeSandboxBackendLog(message) {
|
|
|
259
452
|
process.stderr.write(`[openclaw-agent-vm-plugin] ${message}\n`);
|
|
260
453
|
}
|
|
261
454
|
function shouldRefreshCachedLease(error) {
|
|
262
|
-
return error
|
|
455
|
+
return isRefreshableLeaseError(error);
|
|
456
|
+
}
|
|
457
|
+
function isRefreshableLeaseError(error) {
|
|
458
|
+
return error instanceof ControllerLeaseRequestError && (error.status === 404 || error.status === 410);
|
|
263
459
|
}
|
|
264
460
|
function isCleanupNotFound(error) {
|
|
265
461
|
return error instanceof ControllerLeaseRequestError && error.status === 404;
|
|
@@ -273,6 +469,16 @@ function isActiveUseFinalizeToken(value) {
|
|
|
273
469
|
function activeUseOutcomeForFinalizeParams(finalizeParams) {
|
|
274
470
|
return finalizeParams.timedOut ? "timed-out" : finalizeParams.status === "completed" ? "completed" : "failed";
|
|
275
471
|
}
|
|
472
|
+
function mergedAbortSignal(firstSignal, secondSignal) {
|
|
473
|
+
if (firstSignal === void 0) return secondSignal;
|
|
474
|
+
return AbortSignal.any([firstSignal, secondSignal]);
|
|
475
|
+
}
|
|
476
|
+
function mergedAbortSignals(signals) {
|
|
477
|
+
const presentSignals = signals.filter((signal) => signal !== void 0);
|
|
478
|
+
if (presentSignals.length === 0) return;
|
|
479
|
+
if (presentSignals.length === 1) return presentSignals[0];
|
|
480
|
+
return AbortSignal.any(presentSignals);
|
|
481
|
+
}
|
|
276
482
|
function resolveLeaseRequestAgentId(sessionKey) {
|
|
277
483
|
return resolveOpenClawAgentIdFromSessionKey(sessionKey);
|
|
278
484
|
}
|
|
@@ -281,103 +487,187 @@ function assertPluginLeaseContract(params) {
|
|
|
281
487
|
if (mismatch) throw new Error(`OpenClaw Gondolin sandbox requires ${mismatch.key}=${mismatch.expectedValue}; received ${String(params.cfg[mismatch.key])}.`);
|
|
282
488
|
}
|
|
283
489
|
function createGondolinSandboxBackendFactory(options, dependencies) {
|
|
284
|
-
const
|
|
490
|
+
const agentLeaseCache = /* @__PURE__ */ new Map();
|
|
491
|
+
const inFlightLeaseRequests = /* @__PURE__ */ new Map();
|
|
285
492
|
return async (params) => {
|
|
286
493
|
const profileId = options.profileId ?? "standard";
|
|
287
494
|
const agentId = resolveLeaseRequestAgentId(params.sessionKey);
|
|
288
|
-
assertPluginLeaseContract({
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
495
|
+
assertPluginLeaseContract({ cfg: params.cfg });
|
|
496
|
+
const pathIntent = assertOpenClawToolVmPathIntent({
|
|
497
|
+
agentWorkspaceDir: params.agentWorkspaceDir,
|
|
498
|
+
inputPath: params.workspaceDir
|
|
292
499
|
});
|
|
293
500
|
const cacheKey = agentLeaseCacheKey({
|
|
294
501
|
agentId,
|
|
295
|
-
agentWorkspaceDir: params.agentWorkspaceDir,
|
|
296
|
-
profileId,
|
|
297
|
-
workspaceDir: params.workspaceDir,
|
|
298
502
|
zoneId: options.zoneId
|
|
299
503
|
});
|
|
504
|
+
const requestedCacheEntry = {
|
|
505
|
+
agentWorkspaceDir: params.agentWorkspaceDir,
|
|
506
|
+
leaseWorkMountDir: pathIntent.leaseWorkMountDir,
|
|
507
|
+
profileId
|
|
508
|
+
};
|
|
300
509
|
const leaseClient = dependencies.createLeaseClient?.({ controllerUrl: options.controllerUrl }) ?? createLeaseClient({ controllerUrl: options.controllerUrl });
|
|
301
|
-
const
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
510
|
+
const markLeaseStale = async (lease, reason, error) => {
|
|
511
|
+
agentLeaseCache.delete(cacheKey);
|
|
512
|
+
writeSandboxBackendLog(`lease marked stale for zone '${options.zoneId}' agent '${agentId}' lease '${lease.leaseId}' reason '${reason}': ${formatUnknownError(error)}`);
|
|
513
|
+
await leaseClient.releaseLease(lease.leaseId, { force: true }).catch((releaseError) => {
|
|
514
|
+
writeSandboxBackendLog(`best-effort stale lease release failed for zone '${options.zoneId}' agent '${agentId}' lease '${lease.leaseId}': ${formatUnknownError(releaseError)}`);
|
|
515
|
+
});
|
|
516
|
+
};
|
|
517
|
+
const cachedEntry = agentLeaseCache.get(cacheKey);
|
|
518
|
+
let lease;
|
|
519
|
+
if (cachedEntry) {
|
|
520
|
+
assertCachedLeaseCompatible({
|
|
521
|
+
agentId,
|
|
522
|
+
cachedEntry,
|
|
523
|
+
requestedEntry: requestedCacheEntry,
|
|
524
|
+
zoneId: options.zoneId
|
|
525
|
+
});
|
|
526
|
+
try {
|
|
527
|
+
const renewedLease = await leaseClient.renewLease(cachedEntry.lease.leaseId);
|
|
528
|
+
await runToolVmSshOperationWithGuard({
|
|
529
|
+
operation: async (signal) => await dependencies.runRemoteShellScript({
|
|
530
|
+
allowFailure: false,
|
|
531
|
+
script: "true",
|
|
532
|
+
signal,
|
|
533
|
+
ssh: renewedLease.ssh
|
|
534
|
+
}),
|
|
535
|
+
operationName: "cached-ssh-probe",
|
|
536
|
+
report: () => {},
|
|
537
|
+
timeoutMs: 3e4
|
|
538
|
+
});
|
|
539
|
+
lease = renewedLease;
|
|
540
|
+
agentLeaseCache.set(cacheKey, {
|
|
541
|
+
...requestedCacheEntry,
|
|
542
|
+
lease
|
|
543
|
+
});
|
|
544
|
+
} catch (error) {
|
|
545
|
+
writeSandboxBackendLog(`lease renew failed for zone '${options.zoneId}' agent '${agentId}' lease '${cachedEntry.lease.leaseId}': ${formatUnknownError(error)}`);
|
|
546
|
+
if (error instanceof ToolVmSshOperationStaleError) await markLeaseStale(cachedEntry.lease, error.reason, error);
|
|
547
|
+
else if (shouldRefreshCachedLease(error)) agentLeaseCache.delete(cacheKey);
|
|
548
|
+
else throw error;
|
|
549
|
+
}
|
|
309
550
|
}
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
551
|
+
if (lease === void 0) {
|
|
552
|
+
const inFlightLeaseRequest = inFlightLeaseRequests.get(cacheKey);
|
|
553
|
+
if (inFlightLeaseRequest !== void 0) {
|
|
554
|
+
const inFlightEntry = await inFlightLeaseRequest;
|
|
555
|
+
assertCachedLeaseCompatible({
|
|
556
|
+
agentId,
|
|
557
|
+
cachedEntry: inFlightEntry,
|
|
558
|
+
requestedEntry: requestedCacheEntry,
|
|
559
|
+
zoneId: options.zoneId
|
|
560
|
+
});
|
|
561
|
+
lease = inFlightEntry.lease;
|
|
562
|
+
} else {
|
|
563
|
+
const leaseRequestPromise = (async () => {
|
|
564
|
+
const runtimeStatus = options.openClawRuntimeStatusProvider?.();
|
|
565
|
+
if (runtimeStatus && leaseClient.publishOpenClawRuntimeStatus) await leaseClient.publishOpenClawRuntimeStatus(runtimeStatus);
|
|
566
|
+
const leaseResponse = await leaseClient.requestLease({
|
|
567
|
+
agentId,
|
|
568
|
+
agentWorkspaceDir: params.agentWorkspaceDir,
|
|
569
|
+
profileId,
|
|
570
|
+
sessionKey: params.sessionKey,
|
|
571
|
+
workMountDir: pathIntent.leaseWorkMountDir,
|
|
572
|
+
zoneId: options.zoneId
|
|
573
|
+
});
|
|
574
|
+
if (!isToolVmSshLease(leaseResponse)) throw new TypeError("Controller lease API returned an unexpected response.");
|
|
575
|
+
return {
|
|
576
|
+
...requestedCacheEntry,
|
|
577
|
+
lease: leaseResponse
|
|
578
|
+
};
|
|
579
|
+
})();
|
|
580
|
+
inFlightLeaseRequests.set(cacheKey, leaseRequestPromise);
|
|
581
|
+
try {
|
|
582
|
+
const leaseEntry = await leaseRequestPromise;
|
|
583
|
+
agentLeaseCache.set(cacheKey, leaseEntry);
|
|
584
|
+
lease = leaseEntry.lease;
|
|
585
|
+
} finally {
|
|
586
|
+
if (inFlightLeaseRequests.get(cacheKey) === leaseRequestPromise) inFlightLeaseRequests.delete(cacheKey);
|
|
587
|
+
}
|
|
588
|
+
}
|
|
589
|
+
}
|
|
590
|
+
return createSandboxBackendHandle({
|
|
325
591
|
cfg: params.cfg,
|
|
326
592
|
controllerUrl: options.controllerUrl,
|
|
327
593
|
createFsBridgeBuilder: dependencies.createFsBridgeBuilder,
|
|
594
|
+
effectiveGuestCwd: pathIntent.effectiveGuestCwd,
|
|
328
595
|
lease,
|
|
329
596
|
leaseClient,
|
|
597
|
+
markCachedLeaseStale: async (reason, error) => {
|
|
598
|
+
await markLeaseStale(lease, reason, error);
|
|
599
|
+
},
|
|
330
600
|
runRemoteShellScript: dependencies.runRemoteShellScript,
|
|
331
601
|
buildExecSpec: dependencies.buildExecSpec,
|
|
332
|
-
scopeKey: params.scopeKey,
|
|
333
602
|
sessionKey: params.sessionKey,
|
|
334
603
|
zoneId: options.zoneId
|
|
335
604
|
});
|
|
336
|
-
scopeCache.set(cacheKey, {
|
|
337
|
-
handle,
|
|
338
|
-
lease
|
|
339
|
-
});
|
|
340
|
-
return handle;
|
|
341
605
|
};
|
|
342
606
|
}
|
|
343
607
|
function createSandboxBackendHandle(options) {
|
|
344
|
-
const createActiveUseHandle = async (correlation) =>
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
608
|
+
const createActiveUseHandle = async (correlation) => {
|
|
609
|
+
try {
|
|
610
|
+
return await createToolVmActiveUseHandle({
|
|
611
|
+
correlation,
|
|
612
|
+
endActiveUse: async (useId, request) => {
|
|
613
|
+
await options.leaseClient.endActiveUse(options.lease.leaseId, useId, request);
|
|
614
|
+
},
|
|
615
|
+
heartbeatActiveUse: async (useId, request) => await options.leaseClient.heartbeatActiveUse(options.lease.leaseId, useId, request),
|
|
616
|
+
isEndErrorTolerable: isCleanupNotFound,
|
|
617
|
+
isHeartbeatErrorRefreshable: isRefreshableLeaseError,
|
|
618
|
+
logEndFailure: (error) => {
|
|
619
|
+
writeSandboxBackendLog(`active-use cleanup ignored for zone '${options.zoneId}' lease '${options.lease.leaseId}': ${formatUnknownError(error)}`);
|
|
620
|
+
},
|
|
621
|
+
logHeartbeatFailure: (error) => {
|
|
622
|
+
writeSandboxBackendLog(`active-use heartbeat failed for zone '${options.zoneId}' lease '${options.lease.leaseId}': ${formatUnknownError(error)}`);
|
|
623
|
+
},
|
|
624
|
+
onRefreshableHeartbeatFailure: async (error) => {
|
|
625
|
+
await options.markCachedLeaseStale("active-use-refreshable-failure", error);
|
|
626
|
+
},
|
|
627
|
+
startActiveUse: async (request) => await options.leaseClient.startActiveUse(options.lease.leaseId, request)
|
|
628
|
+
});
|
|
629
|
+
} catch (error) {
|
|
630
|
+
if (isRefreshableLeaseError(error)) await options.markCachedLeaseStale("active-use-refreshable-failure", error);
|
|
631
|
+
throw error;
|
|
632
|
+
}
|
|
633
|
+
};
|
|
359
634
|
const runWithActiveUse = async (correlation, fn) => {
|
|
360
635
|
const activeUseHandle = await createActiveUseHandle(correlation);
|
|
361
636
|
try {
|
|
362
|
-
const result = await fn();
|
|
637
|
+
const result = await fn(activeUseHandle);
|
|
363
638
|
await activeUseHandle.dispose("completed");
|
|
364
639
|
return result;
|
|
365
640
|
} catch (error) {
|
|
366
|
-
await activeUseHandle.dispose("failed").catch((cleanupError) => {
|
|
641
|
+
await activeUseHandle.dispose(error instanceof ToolVmSshOperationStaleError && error.reason === "ssh-command-timed-out" ? "timed-out" : "failed").catch((cleanupError) => {
|
|
367
642
|
writeSandboxBackendLog(`failed to end active use after operation failure for zone '${options.zoneId}' lease '${options.lease.leaseId}': ${formatUnknownError(cleanupError)}`);
|
|
368
643
|
});
|
|
644
|
+
if (error instanceof ToolVmSshOperationStaleError) await options.markCachedLeaseStale(error.reason, error);
|
|
369
645
|
throw error;
|
|
370
646
|
}
|
|
371
647
|
};
|
|
372
648
|
const boundRunRemoteShellScript = async (shellParams) => await runWithActiveUse({
|
|
373
649
|
sessionKey: options.sessionKey,
|
|
374
650
|
toolName: "fs-bridge"
|
|
375
|
-
}, async () => await
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
651
|
+
}, async (activeUseHandle) => await runToolVmSshOperationWithGuard({
|
|
652
|
+
operation: async (signal) => {
|
|
653
|
+
const operationSignal = mergedAbortSignals([
|
|
654
|
+
shellParams.signal,
|
|
655
|
+
activeUseHandle.signal,
|
|
656
|
+
signal
|
|
657
|
+
]);
|
|
658
|
+
return await options.runRemoteShellScript({
|
|
659
|
+
...shellParams.allowFailure !== void 0 ? { allowFailure: shellParams.allowFailure } : {},
|
|
660
|
+
script: buildShellScriptWithArgs(shellParams.script, shellParams.args),
|
|
661
|
+
...operationSignal === void 0 ? {} : { signal: operationSignal },
|
|
662
|
+
ssh: options.lease.ssh,
|
|
663
|
+
...shellParams.stdin !== void 0 ? { stdin: shellParams.stdin } : {}
|
|
664
|
+
});
|
|
665
|
+
},
|
|
666
|
+
operationName: "fs-bridge",
|
|
667
|
+
report: (report) => {
|
|
668
|
+
activeUseHandle.report(report);
|
|
669
|
+
},
|
|
670
|
+
timeoutMs: 3e4
|
|
381
671
|
}));
|
|
382
672
|
const disposeInnerFinalizeToken = async (token) => {
|
|
383
673
|
if (isDisposableFinalizeToken(token)) await token.dispose();
|
|
@@ -400,7 +690,7 @@ function createSandboxBackendHandle(options) {
|
|
|
400
690
|
};
|
|
401
691
|
const createFsBridge = options.createFsBridgeBuilder?.({
|
|
402
692
|
remoteAgentWorkspaceDir: options.lease.workdir,
|
|
403
|
-
remoteWorkspaceDir: options.
|
|
693
|
+
remoteWorkspaceDir: options.effectiveGuestCwd,
|
|
404
694
|
runRemoteShellScript: boundRunRemoteShellScript
|
|
405
695
|
});
|
|
406
696
|
return {
|
|
@@ -411,7 +701,7 @@ function createSandboxBackendHandle(options) {
|
|
|
411
701
|
id: "gondolin",
|
|
412
702
|
runtimeId: options.lease.leaseId,
|
|
413
703
|
runtimeLabel: options.lease.leaseId,
|
|
414
|
-
workdir: options.
|
|
704
|
+
workdir: options.effectiveGuestCwd,
|
|
415
705
|
buildExecSpec: async (execParams) => {
|
|
416
706
|
const activeUseHandle = await createActiveUseHandle({
|
|
417
707
|
sessionKey: options.sessionKey,
|
|
@@ -423,7 +713,7 @@ function createSandboxBackendHandle(options) {
|
|
|
423
713
|
env: execParams.env,
|
|
424
714
|
ssh: options.lease.ssh,
|
|
425
715
|
usePty: execParams.usePty,
|
|
426
|
-
workdir: execParams.workdir ?? options.
|
|
716
|
+
workdir: execParams.workdir ?? options.effectiveGuestCwd
|
|
427
717
|
});
|
|
428
718
|
return {
|
|
429
719
|
...execSpec,
|
|
@@ -441,7 +731,16 @@ function createSandboxBackendHandle(options) {
|
|
|
441
731
|
},
|
|
442
732
|
finalizeExec: async (finalizeParams) => {
|
|
443
733
|
if (isActiveUseFinalizeToken(finalizeParams.token)) {
|
|
734
|
+
if (finalizeParams.timedOut) finalizeParams.token.activeUseHandle.report({
|
|
735
|
+
observedAtMs: Date.now(),
|
|
736
|
+
phase: "failed",
|
|
737
|
+
ssh: { failure: {
|
|
738
|
+
kind: "ssh-command-timed-out",
|
|
739
|
+
message: "exec command timed out."
|
|
740
|
+
} }
|
|
741
|
+
});
|
|
444
742
|
await endActiveUseFinalizeToken(finalizeParams.token, activeUseOutcomeForFinalizeParams(finalizeParams));
|
|
743
|
+
if (finalizeParams.timedOut) await options.markCachedLeaseStale("ssh-command-timed-out", void 0);
|
|
445
744
|
return;
|
|
446
745
|
}
|
|
447
746
|
await disposeInnerFinalizeToken(finalizeParams.token);
|
|
@@ -449,9 +748,17 @@ function createSandboxBackendHandle(options) {
|
|
|
449
748
|
runShellCommand: async (commandParams) => await runWithActiveUse({
|
|
450
749
|
sessionKey: options.sessionKey,
|
|
451
750
|
toolName: "runShellCommand"
|
|
452
|
-
}, async () => await
|
|
453
|
-
|
|
454
|
-
|
|
751
|
+
}, async (activeUseHandle) => await runToolVmSshOperationWithGuard({
|
|
752
|
+
operation: async (signal) => await options.runRemoteShellScript({
|
|
753
|
+
script: commandParams.script,
|
|
754
|
+
signal: mergedAbortSignal(activeUseHandle.signal, signal),
|
|
755
|
+
ssh: options.lease.ssh
|
|
756
|
+
}),
|
|
757
|
+
operationName: "runShellCommand",
|
|
758
|
+
report: (report) => {
|
|
759
|
+
activeUseHandle.report(report);
|
|
760
|
+
},
|
|
761
|
+
timeoutMs: 3e4
|
|
455
762
|
}))
|
|
456
763
|
};
|
|
457
764
|
}
|
|
@@ -693,6 +1000,23 @@ function registerZoneGitTool(options) {
|
|
|
693
1000
|
}
|
|
694
1001
|
//#endregion
|
|
695
1002
|
//#region src/openclaw-plugin-registration.ts
|
|
1003
|
+
const runtimeStatusPublishMaxAttempts = 30;
|
|
1004
|
+
const runtimeStatusPublishRetryDelayMs = 1e3;
|
|
1005
|
+
function sleep(ms) {
|
|
1006
|
+
return new Promise((resolve) => {
|
|
1007
|
+
setTimeout(resolve, ms);
|
|
1008
|
+
});
|
|
1009
|
+
}
|
|
1010
|
+
async function publishRuntimeStatusWithRetry(options) {
|
|
1011
|
+
const leaseClient = createLeaseClient({ controllerUrl: options.controllerUrl });
|
|
1012
|
+
for (let attemptIndex = 0; attemptIndex < runtimeStatusPublishMaxAttempts; attemptIndex += 1) try {
|
|
1013
|
+
await leaseClient.publishOpenClawRuntimeStatus?.(options.report);
|
|
1014
|
+
return;
|
|
1015
|
+
} catch (error) {
|
|
1016
|
+
if (attemptIndex === runtimeStatusPublishMaxAttempts - 1) throw error;
|
|
1017
|
+
await sleep(runtimeStatusPublishRetryDelayMs);
|
|
1018
|
+
}
|
|
1019
|
+
}
|
|
696
1020
|
const plugin = {
|
|
697
1021
|
id: "gondolin",
|
|
698
1022
|
name: "Gondolin VM Sandbox",
|
|
@@ -720,7 +1044,10 @@ const plugin = {
|
|
|
720
1044
|
}) : void 0;
|
|
721
1045
|
};
|
|
722
1046
|
const initialRuntimeStatus = buildRuntimeStatus();
|
|
723
|
-
if (initialRuntimeStatus)
|
|
1047
|
+
if (initialRuntimeStatus) publishRuntimeStatusWithRetry({
|
|
1048
|
+
controllerUrl: pluginConfig.controllerUrl,
|
|
1049
|
+
report: initialRuntimeStatus
|
|
1050
|
+
}).catch((error) => {
|
|
724
1051
|
const message = error instanceof Error ? error.message : JSON.stringify(error);
|
|
725
1052
|
process.stderr.write(`[gondolin] failed to publish OpenClaw runtime status: ${message}\n`);
|
|
726
1053
|
});
|
|
@@ -753,6 +1080,6 @@ const plugin = {
|
|
|
753
1080
|
//#region src/index.ts
|
|
754
1081
|
const OPENCLAW_GONDOLIN_PLUGIN_PACKAGE_NAME = "@agent-vm/openclaw-agent-vm-plugin";
|
|
755
1082
|
//#endregion
|
|
756
|
-
export { ControllerLeaseRequestError, OPENCLAW_DEFAULT_AGENT_ID, OPENCLAW_GONDOLIN_LEASE_SCOPE_GUIDANCE, OPENCLAW_GONDOLIN_PLUGIN_PACKAGE_NAME, OPENCLAW_GONDOLIN_SANDBOX_REQUIREMENTS, OPENCLAW_SSH_SESSION_SCRATCH_ROOT, createBackendDeps, createGondolinSandboxBackendFactory, createGondolinSandboxBackendManager, createLeaseClient, plugin as default, effectiveOpenClawGondolinSandboxValue, findOpenClawGondolinSandboxMismatch, formatOpenClawGondolinRequirementFieldPath, formatOpenClawGondolinRequirementFindingId, formatOpenClawGondolinRequirementHint, isOpenClawAgentId, isOpenClawAgentSessionKey, normalizeOpenClawAgentId, resolveGondolinPluginConfig, resolveOpenClawAgentIdFromSessionKey, snapshotOpenClawGondolinSandboxConfig };
|
|
1083
|
+
export { ControllerLeaseRequestError, OPENCLAW_DEFAULT_AGENT_ID, OPENCLAW_GONDOLIN_LEASE_SCOPE_GUIDANCE, OPENCLAW_GONDOLIN_PLUGIN_PACKAGE_NAME, OPENCLAW_GONDOLIN_SANDBOX_REQUIREMENTS, OPENCLAW_SSH_SESSION_SCRATCH_ROOT, buildOpenClawRuntimeStatusReport, createBackendDeps, createGondolinSandboxBackendFactory, createGondolinSandboxBackendManager, createLeaseClient, plugin as default, effectiveOpenClawGondolinSandboxValue, findOpenClawGondolinSandboxMismatch, formatOpenClawGondolinRequirementFieldPath, formatOpenClawGondolinRequirementFindingId, formatOpenClawGondolinRequirementHint, isOpenClawAgentId, isOpenClawAgentSessionKey, normalizeOpenClawAgentId, resolveGondolinPluginConfig, resolveOpenClawAgentIdFromSessionKey, snapshotOpenClawGondolinSandboxConfig };
|
|
757
1084
|
|
|
758
1085
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["formatUnknownError"],"sources":["../src/controller-lease-client.ts","../src/openclaw-gondolin-contract.ts","../src/sandbox-backend/sandbox-shell-script.ts","../src/sandbox-backend/sandbox-backend-handle-factory.ts","../src/sandbox-backend/sandbox-backend-manager.ts","../src/gondolin-plugin-config.ts","../src/openclaw-backend-dependencies.ts","../src/openclaw-runtime-status.ts","../src/openclaw-sandbox-sdk-contract.ts","../src/zone-git-tool.ts","../src/openclaw-plugin-registration.ts","../src/index.ts"],"sourcesContent":["import {\n\tisToolVmLeasePeek,\n\tisToolVmSshLease,\n\ttype ToolVmLeasePeek,\n\ttype ToolVmSshLease,\n} from '@agent-vm/gateway-interface';\nimport type {\n\tEndToolVmActiveUseRequest,\n\tHeartbeatToolVmActiveUseResponse,\n\tStartToolVmActiveUseRequest,\n\tStartToolVmActiveUseResponse,\n} from '@agent-vm/gateway-interface';\nimport { z } from 'zod';\n\nexport type JsonValue =\n\t| boolean\n\t| null\n\t| number\n\t| string\n\t| { readonly [key: string]: JsonValue }\n\t| readonly JsonValue[];\n\nexport interface OpenClawRuntimeStatusReport {\n\treadonly findings: readonly {\n\t\treadonly hint: string;\n\t\treadonly id: string;\n\t\treadonly ok: boolean;\n\t}[];\n\treadonly pluginId: 'gondolin';\n\treadonly zoneId: string;\n}\n\nexport interface OpenClawGondolinLeaseSandboxSnapshot {\n\treadonly backend: unknown;\n\treadonly mode: unknown;\n\treadonly scope: unknown;\n\treadonly workspaceAccess: unknown;\n}\n\nexport interface OpenClawGondolinLeaseRequest {\n\treadonly agentId: string;\n\treadonly agentWorkspaceDir: string;\n\treadonly profileId: string;\n\treadonly sandbox: OpenClawGondolinLeaseSandboxSnapshot;\n\treadonly scopeKey: string;\n\treadonly sessionKey: string;\n\treadonly workMountDir: string;\n\treadonly zoneId: string;\n}\n\nexport interface LeaseClient {\n\t// Cached handles use renewLease; read-only runtime probes use peekLease.\n\tendActiveUse(leaseId: string, useId: string, request: EndToolVmActiveUseRequest): Promise<void>;\n\theartbeatActiveUse(leaseId: string, useId: string): Promise<HeartbeatToolVmActiveUseResponse>;\n\tpeekLease(leaseId: string): Promise<ToolVmLeasePeek>;\n\tpublishOpenClawRuntimeStatus?(report: OpenClawRuntimeStatusReport): Promise<void>;\n\treleaseLease(leaseId: string, options?: { readonly force?: boolean }): Promise<void>;\n\trenewLease(leaseId: string): Promise<ToolVmSshLease>;\n\trequestLease(request: OpenClawGondolinLeaseRequest): Promise<ToolVmSshLease>;\n\tstartActiveUse(\n\t\tleaseId: string,\n\t\trequest: StartToolVmActiveUseRequest,\n\t): Promise<StartToolVmActiveUseResponse>;\n}\n\nexport type ControllerLeaseRequestErrorKind = 'client-error' | 'server-error';\n\nexport class ControllerLeaseRequestError extends Error {\n\treadonly bodyText: string;\n\treadonly kind: ControllerLeaseRequestErrorKind;\n\treadonly responseBody: JsonValue | undefined;\n\treadonly status: number;\n\n\tconstructor(options: {\n\t\treadonly bodyText: string;\n\t\treadonly context: string;\n\t\treadonly responseBody: JsonValue | undefined;\n\t\treadonly status: number;\n\t}) {\n\t\tconst kind: ControllerLeaseRequestErrorKind =\n\t\t\toptions.status >= 400 && options.status < 500 ? 'client-error' : 'server-error';\n\t\tsuper(\n\t\t\t`${options.context} returned HTTP ${String(options.status)} (${kind})${formatStructuredErrorSuffix(\n\t\t\t\toptions.responseBody,\n\t\t\t)}`,\n\t\t);\n\t\tthis.bodyText = options.bodyText;\n\t\tthis.kind = kind;\n\t\tthis.responseBody = options.responseBody;\n\t\tthis.status = options.status;\n\t}\n}\n\nconst structuredControllerErrorSchema = z.object({\n\tguidance: z.string().trim().min(1).optional(),\n\tmessage: z.string().trim().min(1).optional(),\n});\n\nfunction isJsonObjectRecord(value: unknown): value is { readonly [key: string]: JsonValue } {\n\treturn (\n\t\ttypeof value === 'object' &&\n\t\tvalue !== null &&\n\t\t!Array.isArray(value) &&\n\t\tObject.values(value).every(isJsonValue)\n\t);\n}\n\nfunction isJsonValue(value: unknown): value is JsonValue {\n\tif (\n\t\tvalue === null ||\n\t\ttypeof value === 'string' ||\n\t\ttypeof value === 'boolean' ||\n\t\ttypeof value === 'number'\n\t) {\n\t\treturn true;\n\t}\n\tif (Array.isArray(value)) {\n\t\treturn value.every(isJsonValue);\n\t}\n\treturn isJsonObjectRecord(value);\n}\n\nconst jsonValueSchema = z.custom<JsonValue>(isJsonValue);\n\nfunction objectValue(value: unknown): object | undefined {\n\treturn typeof value === 'object' && value !== null ? value : undefined;\n}\n\nfunction formatStructuredErrorSuffix(responseBody: JsonValue | undefined): string {\n\tconst parsedError = structuredControllerErrorSchema.safeParse(responseBody);\n\tif (!parsedError.success) {\n\t\treturn '';\n\t}\n\tconst { guidance, message } = parsedError.data;\n\tconst parts = [message, guidance ? `Guidance: ${guidance}` : undefined].filter(\n\t\t(part): part is string => part !== undefined,\n\t);\n\treturn parts.length > 0 ? `: ${parts.join(' ')}` : '';\n}\n\nfunction isStartActiveUseResponse(value: unknown): value is StartToolVmActiveUseResponse {\n\tconst record = objectValue(value);\n\treturn (\n\t\trecord !== undefined &&\n\t\ttypeof Reflect.get(record, 'expiresAt') === 'number' &&\n\t\ttypeof Reflect.get(record, 'heartbeatAfterMs') === 'number' &&\n\t\ttypeof Reflect.get(record, 'useId') === 'string'\n\t);\n}\n\nfunction isHeartbeatActiveUseResponse(value: unknown): value is HeartbeatToolVmActiveUseResponse {\n\tconst record = objectValue(value);\n\treturn (\n\t\trecord !== undefined &&\n\t\ttypeof Reflect.get(record, 'expiresAt') === 'number' &&\n\t\ttypeof Reflect.get(record, 'heartbeatAfterMs') === 'number'\n\t);\n}\n\nfunction formatUnknownError(error: unknown): string {\n\treturn error instanceof Error ? error.message : String(error);\n}\n\nfunction writeLeaseClientLog(message: string): void {\n\tprocess.stderr.write(`[openclaw-agent-vm-plugin] ${message}\\n`);\n}\n\nfunction parseJsonBody(bodyText: string, context: string): JsonValue | undefined {\n\ttry {\n\t\tconst parsedJson: unknown = JSON.parse(bodyText);\n\t\tconst parsedBody = jsonValueSchema.safeParse(parsedJson);\n\t\treturn parsedBody.success ? parsedBody.data : undefined;\n\t} catch (error) {\n\t\twriteLeaseClientLog(`${context} returned a non-JSON error body: ${formatUnknownError(error)}`);\n\t\treturn undefined;\n\t}\n}\n\nasync function readErrorBody(\n\tresponse: Response,\n\tcontext: string,\n): Promise<{\n\treadonly bodyText: string;\n\treadonly responseBody: JsonValue | undefined;\n}> {\n\tconst bodyText = await response.text().catch(() => '(unreadable)');\n\treturn {\n\t\tbodyText,\n\t\tresponseBody: bodyText === '(unreadable)' ? undefined : parseJsonBody(bodyText, context),\n\t};\n}\n\nasync function readJsonResponse<TValue>(\n\tresponse: Response,\n\tcontext: string,\n\tisExpectedResponse: (value: unknown) => value is TValue,\n): Promise<TValue> {\n\tif (!response.ok) {\n\t\tconst errorBody = await readErrorBody(response, context);\n\t\tthrow new ControllerLeaseRequestError({\n\t\t\tbodyText: errorBody.bodyText,\n\t\t\tcontext,\n\t\t\tresponseBody: errorBody.responseBody,\n\t\t\tstatus: response.status,\n\t\t});\n\t}\n\tconst payload = await response.json();\n\tif (!isExpectedResponse(payload)) {\n\t\tthrow new TypeError(\n\t\t\t`${context} returned an invalid response: ${JSON.stringify(payload).slice(0, 200)}`,\n\t\t);\n\t}\n\treturn payload;\n}\n\nexport function createLeaseClient(options: {\n\treadonly controllerUrl: string;\n\treadonly fetchImpl?: (input: string | URL | Request, init?: RequestInit) => Promise<Response>;\n}): LeaseClient {\n\tconst fetchImpl = options.fetchImpl ?? fetch;\n\tconst baseUrl = options.controllerUrl.replace(/\\/$/u, '');\n\tconst renewLease = async (leaseId: string): Promise<ToolVmSshLease> => {\n\t\tconst response = await fetchImpl(`${baseUrl}/lease/${encodeURIComponent(leaseId)}/renew`, {\n\t\t\tmethod: 'POST',\n\t\t});\n\t\treturn await readJsonResponse(response, 'Controller lease renew API', isToolVmSshLease);\n\t};\n\n\treturn {\n\t\tendActiveUse: async (\n\t\t\tleaseId: string,\n\t\t\tuseId: string,\n\t\t\trequest: EndToolVmActiveUseRequest,\n\t\t): Promise<void> => {\n\t\t\tconst response = await fetchImpl(\n\t\t\t\t`${baseUrl}/lease/${encodeURIComponent(leaseId)}/uses/${encodeURIComponent(useId)}`,\n\t\t\t\t{\n\t\t\t\t\tbody: JSON.stringify(request),\n\t\t\t\t\theaders: {\n\t\t\t\t\t\t'content-type': 'application/json',\n\t\t\t\t\t},\n\t\t\t\t\tmethod: 'DELETE',\n\t\t\t\t},\n\t\t\t);\n\t\t\tif (!response.ok) {\n\t\t\t\tconst errorBody = await readErrorBody(response, 'Controller active-use end API');\n\t\t\t\tthrow new ControllerLeaseRequestError({\n\t\t\t\t\tbodyText: errorBody.bodyText,\n\t\t\t\t\tcontext: 'Controller active-use end API',\n\t\t\t\t\tresponseBody: errorBody.responseBody,\n\t\t\t\t\tstatus: response.status,\n\t\t\t\t});\n\t\t\t}\n\t\t},\n\t\theartbeatActiveUse: async (\n\t\t\tleaseId: string,\n\t\t\tuseId: string,\n\t\t): Promise<HeartbeatToolVmActiveUseResponse> => {\n\t\t\tconst response = await fetchImpl(\n\t\t\t\t`${baseUrl}/lease/${encodeURIComponent(leaseId)}/uses/${encodeURIComponent(useId)}/heartbeat`,\n\t\t\t\t{\n\t\t\t\t\tmethod: 'POST',\n\t\t\t\t},\n\t\t\t);\n\t\t\treturn await readJsonResponse(\n\t\t\t\tresponse,\n\t\t\t\t'Controller active-use heartbeat API',\n\t\t\t\tisHeartbeatActiveUseResponse,\n\t\t\t);\n\t\t},\n\t\trenewLease,\n\t\tpeekLease: async (leaseId: string): Promise<ToolVmLeasePeek> => {\n\t\t\tconst response = await fetchImpl(`${baseUrl}/lease/${encodeURIComponent(leaseId)}/peek`);\n\t\t\treturn await readJsonResponse(response, 'Controller lease peek API', isToolVmLeasePeek);\n\t\t},\n\t\tpublishOpenClawRuntimeStatus: async (report): Promise<void> => {\n\t\t\tconst response = await fetchImpl(\n\t\t\t\t`${baseUrl}/zones/${encodeURIComponent(report.zoneId)}/openclaw-runtime-status`,\n\t\t\t\t{\n\t\t\t\t\tbody: JSON.stringify(report),\n\t\t\t\t\theaders: {\n\t\t\t\t\t\t'content-type': 'application/json',\n\t\t\t\t\t},\n\t\t\t\t\tmethod: 'POST',\n\t\t\t\t},\n\t\t\t);\n\t\t\tif (!response.ok) {\n\t\t\t\tconst errorBody = await readErrorBody(response, 'Controller OpenClaw runtime status API');\n\t\t\t\tthrow new ControllerLeaseRequestError({\n\t\t\t\t\tbodyText: errorBody.bodyText,\n\t\t\t\t\tcontext: 'Controller OpenClaw runtime status API',\n\t\t\t\t\tresponseBody: errorBody.responseBody,\n\t\t\t\t\tstatus: response.status,\n\t\t\t\t});\n\t\t\t}\n\t\t},\n\t\treleaseLease: async (\n\t\t\tleaseId: string,\n\t\t\treleaseOptions: { readonly force?: boolean } = {},\n\t\t): Promise<void> => {\n\t\t\tconst releaseUrl = new URL(`${baseUrl}/lease/${encodeURIComponent(leaseId)}`);\n\t\t\tif (releaseOptions.force === true) {\n\t\t\t\treleaseUrl.searchParams.set('force', 'true');\n\t\t\t}\n\t\t\tconst response = await fetchImpl(releaseUrl.toString(), {\n\t\t\t\tmethod: 'DELETE',\n\t\t\t});\n\t\t\tif (!response.ok) {\n\t\t\t\tconst errorBody = await readErrorBody(response, 'Controller lease release API');\n\t\t\t\tthrow new ControllerLeaseRequestError({\n\t\t\t\t\tbodyText: errorBody.bodyText,\n\t\t\t\t\tcontext: 'Controller lease release API',\n\t\t\t\t\tresponseBody: errorBody.responseBody,\n\t\t\t\t\tstatus: response.status,\n\t\t\t\t});\n\t\t\t}\n\t\t},\n\t\trequestLease: async (request): Promise<ToolVmSshLease> => {\n\t\t\tconst response = await fetchImpl(`${baseUrl}/lease`, {\n\t\t\t\tbody: JSON.stringify({\n\t\t\t\t\tagentId: request.agentId,\n\t\t\t\t\tagentWorkspaceDir: request.agentWorkspaceDir,\n\t\t\t\t\tprofileId: request.profileId,\n\t\t\t\t\tsandbox: request.sandbox,\n\t\t\t\t\tscopeKey: request.scopeKey,\n\t\t\t\t\tsessionKey: request.sessionKey,\n\t\t\t\t\tworkMountDir: request.workMountDir,\n\t\t\t\t\tzoneId: request.zoneId,\n\t\t\t\t}),\n\t\t\t\theaders: {\n\t\t\t\t\t'content-type': 'application/json',\n\t\t\t\t},\n\t\t\t\tmethod: 'POST',\n\t\t\t});\n\t\t\treturn await readJsonResponse(response, 'Controller lease API', isToolVmSshLease);\n\t\t},\n\t\tstartActiveUse: async (\n\t\t\tleaseId: string,\n\t\t\trequest: StartToolVmActiveUseRequest,\n\t\t): Promise<StartToolVmActiveUseResponse> => {\n\t\t\tconst response = await fetchImpl(`${baseUrl}/lease/${encodeURIComponent(leaseId)}/uses`, {\n\t\t\t\tbody: JSON.stringify(request),\n\t\t\t\theaders: {\n\t\t\t\t\t'content-type': 'application/json',\n\t\t\t\t},\n\t\t\t\tmethod: 'POST',\n\t\t\t});\n\t\t\treturn await readJsonResponse(\n\t\t\t\tresponse,\n\t\t\t\t'Controller active-use start API',\n\t\t\t\tisStartActiveUseResponse,\n\t\t\t);\n\t\t},\n\t};\n}\n","const agentIdPattern = /^[a-z0-9][a-z0-9_-]{0,63}$/iu;\n\nexport const OPENCLAW_DEFAULT_AGENT_ID = 'main';\n\nexport const OPENCLAW_GONDOLIN_SANDBOX_REQUIREMENTS = [\n\t{ expectedValue: 'gondolin', key: 'backend' },\n\t{ expectedValue: 'all', key: 'mode' },\n\t{ expectedValue: 'agent', key: 'scope' },\n\t{ expectedValue: 'rw', key: 'workspaceAccess' },\n] as const;\n\nexport const OPENCLAW_GONDOLIN_LEASE_SCOPE_GUIDANCE =\n\t'Managed OpenClaw/Gondolin requires an explicit agentId. scopeKey is OpenClaw scope provenance and may include channel, session, thread, or subagent segments under that agent.';\n\nexport type OpenClawGondolinSandboxRequirement =\n\t(typeof OPENCLAW_GONDOLIN_SANDBOX_REQUIREMENTS)[number];\n\nexport type OpenClawGondolinSandboxRequirementKey = OpenClawGondolinSandboxRequirement['key'];\n\nexport interface OpenClawGondolinSandboxSnapshot {\n\treadonly backend?: unknown;\n\treadonly mode?: unknown;\n\treadonly scope?: unknown;\n\treadonly workspaceAccess?: unknown;\n}\n\nexport interface OpenClawGondolinAgentConfig {\n\treadonly id?: unknown;\n\treadonly sandbox?: OpenClawGondolinSandboxSnapshot;\n\treadonly workspace?: unknown;\n}\n\nexport function isOpenClawAgentId(value: string): boolean {\n\treturn agentIdPattern.test(value.trim());\n}\n\nexport function effectiveOpenClawGondolinSandboxValue(\n\tdefaults: OpenClawGondolinAgentConfig,\n\tagentConfig: OpenClawGondolinAgentConfig,\n\tkey: OpenClawGondolinSandboxRequirementKey,\n): unknown {\n\treturn agentConfig.sandbox?.[key] ?? defaults.sandbox?.[key];\n}\n\nexport function formatOpenClawGondolinRequirementFieldPath(\n\tlabel: string,\n\tkey: OpenClawGondolinSandboxRequirementKey,\n): string {\n\treturn `agents.${label}.sandbox.${key}`;\n}\n\nexport function formatOpenClawGondolinRequirementFindingId(options: {\n\treadonly fieldPath: string;\n\treadonly label: string;\n\treadonly zoneId: string;\n}): string {\n\treturn `openclaw-tool-vm-${options.fieldPath.replace(/[.[\\]]/gu, '-')}-${options.zoneId}-${options.label}`;\n}\n\nexport function formatOpenClawGondolinRequirementHint(options: {\n\treadonly expectedValue: string;\n\treadonly fieldPath: string;\n\treadonly ok: boolean;\n}): string {\n\treturn options.ok\n\t\t? `${options.fieldPath}=${options.expectedValue}`\n\t\t: `Set ${options.fieldPath} to \"${options.expectedValue}\" for OpenClaw Tool VM mediation.`;\n}\n\nexport function normalizeOpenClawAgentId(value: string | undefined | null): string {\n\tconst trimmed = (value ?? '').trim().toLowerCase();\n\treturn isOpenClawAgentId(trimmed) ? trimmed : OPENCLAW_DEFAULT_AGENT_ID;\n}\n\nexport function resolveOpenClawAgentIdFromSessionKey(sessionKey: string): string {\n\tconst parts = sessionKey.trim().split(':');\n\tif (parts[0] !== 'agent' || !parts[1]) {\n\t\treturn OPENCLAW_DEFAULT_AGENT_ID;\n\t}\n\treturn normalizeOpenClawAgentId(parts[1]);\n}\n\nexport function isOpenClawAgentSessionKey(sessionKey: string): boolean {\n\tconst parts = sessionKey.trim().split(':');\n\treturn parts[0] === 'agent' && parts[1] !== undefined && isOpenClawAgentId(parts[1]);\n}\n\nexport function snapshotOpenClawGondolinSandboxConfig(cfg: OpenClawGondolinSandboxSnapshot): {\n\treadonly backend: unknown;\n\treadonly mode: unknown;\n\treadonly scope: unknown;\n\treadonly workspaceAccess: unknown;\n} {\n\treturn {\n\t\tbackend: cfg.backend,\n\t\tmode: cfg.mode,\n\t\tscope: cfg.scope,\n\t\tworkspaceAccess: cfg.workspaceAccess,\n\t};\n}\n\nexport function findOpenClawGondolinSandboxMismatch(\n\tsandbox: OpenClawGondolinSandboxSnapshot,\n): OpenClawGondolinSandboxRequirement | undefined {\n\treturn OPENCLAW_GONDOLIN_SANDBOX_REQUIREMENTS.find(\n\t\t(requirement) => sandbox[requirement.key] !== requirement.expectedValue,\n\t);\n}\n","export function buildShellScriptWithArgs(script: string, args?: readonly string[]): string {\n\tif (!args || args.length === 0) {\n\t\treturn script;\n\t}\n\n\tconst escapedArgs = args.map((arg) => `'${arg.replace(/'/g, \"'\\\\''\")}'`).join(' ');\n\treturn `set -- ${escapedArgs}; ${script}`;\n}\n","import {\n\tcreateToolVmActiveUseHandle,\n\ttype ToolVmActiveUseHandle,\n\ttype ToolVmActiveUseOutcome,\n\ttype ToolVmActiveUseCorrelation,\n\ttype StartToolVmActiveUseRequest,\n\ttype StartToolVmActiveUseResponse,\n\ttype HeartbeatToolVmActiveUseResponse,\n\ttype EndToolVmActiveUseRequest,\n\tisToolVmSshLease,\n} from '@agent-vm/gateway-interface';\n\nimport {\n\tControllerLeaseRequestError,\n\tcreateLeaseClient,\n\ttype LeaseClient,\n\ttype OpenClawRuntimeStatusReport,\n} from '../controller-lease-client.js';\nimport {\n\tfindOpenClawGondolinSandboxMismatch,\n\tresolveOpenClawAgentIdFromSessionKey,\n\tsnapshotOpenClawGondolinSandboxConfig,\n\ttype OpenClawGondolinSandboxSnapshot,\n} from '../openclaw-gondolin-contract.js';\nimport {\n\ttype CachedScopeEntry,\n\ttype CreateBackendDependencies,\n\ttype OpenClawFsBridgeLeaseContext,\n\ttype OpenClawSandboxBackendHandle,\n} from './sandbox-backend-contract.js';\nimport { buildShellScriptWithArgs } from './sandbox-shell-script.js';\n\nfunction agentLeaseCacheKey(params: {\n\treadonly agentId: string;\n\treadonly agentWorkspaceDir: string;\n\treadonly profileId: string;\n\treadonly workspaceDir: string;\n\treadonly zoneId: string;\n}): string {\n\treturn [\n\t\tparams.zoneId,\n\t\tparams.agentId,\n\t\tparams.profileId,\n\t\tparams.agentWorkspaceDir,\n\t\tparams.workspaceDir,\n\t].join('\\0');\n}\n\nfunction formatControllerLeaseRequestError(error: ControllerLeaseRequestError): string {\n\tconst responseBody =\n\t\terror.responseBody === undefined ? error.bodyText : JSON.stringify(error.responseBody);\n\treturn `${error.message}; response=${responseBody}`;\n}\n\nfunction formatUnknownError(error: unknown): string {\n\tif (error instanceof ControllerLeaseRequestError) {\n\t\treturn formatControllerLeaseRequestError(error);\n\t}\n\treturn error instanceof Error ? error.message : String(error);\n}\n\nfunction writeSandboxBackendLog(message: string): void {\n\tprocess.stderr.write(`[openclaw-agent-vm-plugin] ${message}\\n`);\n}\n\nfunction shouldRefreshCachedLease(error: unknown): boolean {\n\treturn error instanceof ControllerLeaseRequestError && error.status === 404;\n}\n\nfunction isCleanupNotFound(error: unknown): boolean {\n\treturn error instanceof ControllerLeaseRequestError && error.status === 404;\n}\n\ninterface DisposableFinalizeToken {\n\tdispose(): Promise<void>;\n}\n\ninterface ActiveUseFinalizeToken {\n\treadonly activeUseHandle: ToolVmActiveUseHandle;\n\treadonly innerToken?: unknown;\n}\n\nfunction isDisposableFinalizeToken(value: unknown): value is DisposableFinalizeToken {\n\treturn (\n\t\ttypeof value === 'object' &&\n\t\tvalue !== null &&\n\t\t'dispose' in value &&\n\t\ttypeof Reflect.get(value, 'dispose') === 'function'\n\t);\n}\n\nfunction isActiveUseFinalizeToken(value: unknown): value is ActiveUseFinalizeToken {\n\treturn (\n\t\ttypeof value === 'object' &&\n\t\tvalue !== null &&\n\t\t'activeUseHandle' in value &&\n\t\ttypeof Reflect.get(value, 'activeUseHandle') === 'object'\n\t);\n}\n\nfunction activeUseOutcomeForFinalizeParams(finalizeParams: {\n\treadonly status: 'completed' | 'failed';\n\treadonly timedOut: boolean;\n}): ToolVmActiveUseOutcome {\n\treturn finalizeParams.timedOut\n\t\t? 'timed-out'\n\t\t: finalizeParams.status === 'completed'\n\t\t\t? 'completed'\n\t\t\t: 'failed';\n}\n\nfunction resolveLeaseRequestAgentId(sessionKey: string): string {\n\treturn resolveOpenClawAgentIdFromSessionKey(sessionKey);\n}\n\nfunction assertPluginLeaseContract(params: {\n\treadonly agentId: string;\n\treadonly cfg: OpenClawGondolinSandboxSnapshot;\n\treadonly scopeKey: string;\n}): void {\n\tconst mismatch = findOpenClawGondolinSandboxMismatch(params.cfg);\n\tif (mismatch) {\n\t\tthrow new Error(\n\t\t\t`OpenClaw Gondolin sandbox requires ${mismatch.key}=${mismatch.expectedValue}; received ${String(params.cfg[mismatch.key])}.`,\n\t\t);\n\t}\n}\n\nexport function createGondolinSandboxBackendFactory(\n\toptions: {\n\t\treadonly controllerUrl: string;\n\t\treadonly openClawRuntimeStatusProvider?: () => OpenClawRuntimeStatusReport | undefined;\n\t\treadonly profileId?: string;\n\t\treadonly zoneId: string;\n\t},\n\tdependencies: CreateBackendDependencies,\n): (params: {\n\treadonly agentWorkspaceDir: string;\n\treadonly cfg: OpenClawGondolinSandboxSnapshot & {\n\t\treadonly docker?: {\n\t\t\treadonly env?: Record<string, string>;\n\t\t};\n\t};\n\treadonly scopeKey: string;\n\treadonly sessionKey: string;\n\treadonly workspaceDir: string;\n}) => Promise<OpenClawSandboxBackendHandle> {\n\tconst scopeCache = new Map<string, CachedScopeEntry>();\n\n\treturn async (params) => {\n\t\tconst profileId = options.profileId ?? 'standard';\n\t\tconst agentId = resolveLeaseRequestAgentId(params.sessionKey);\n\t\tassertPluginLeaseContract({\n\t\t\tagentId,\n\t\t\tcfg: params.cfg,\n\t\t\tscopeKey: params.scopeKey,\n\t\t});\n\t\tconst cacheKey = agentLeaseCacheKey({\n\t\t\tagentId,\n\t\t\tagentWorkspaceDir: params.agentWorkspaceDir,\n\t\t\tprofileId,\n\t\t\tworkspaceDir: params.workspaceDir,\n\t\t\tzoneId: options.zoneId,\n\t\t});\n\t\tconst leaseClient =\n\t\t\tdependencies.createLeaseClient?.({\n\t\t\t\tcontrollerUrl: options.controllerUrl,\n\t\t\t}) ?? createLeaseClient({ controllerUrl: options.controllerUrl });\n\t\tconst cachedEntry = scopeCache.get(cacheKey);\n\t\tif (cachedEntry) {\n\t\t\ttry {\n\t\t\t\tawait leaseClient.renewLease(cachedEntry.lease.leaseId);\n\t\t\t\treturn cachedEntry.handle;\n\t\t\t} catch (error) {\n\t\t\t\twriteSandboxBackendLog(\n\t\t\t\t\t`lease renew failed for zone '${options.zoneId}' scope '${params.scopeKey}' lease '${cachedEntry.lease.leaseId}': ${formatUnknownError(error)}`,\n\t\t\t\t);\n\t\t\t\tif (!shouldRefreshCachedLease(error)) {\n\t\t\t\t\tthrow error;\n\t\t\t\t}\n\t\t\t\tscopeCache.delete(cacheKey);\n\t\t\t}\n\t\t}\n\t\t// OpenClaw SDK still names the selected sandbox path `workspaceDir`.\n\t\t// agent-vm's controller calls the same value `workMountDir` because it\n\t\t// selects the host path exposed at the lease response `workdir`.\n\t\tconst runtimeStatus = options.openClawRuntimeStatusProvider?.();\n\t\tif (runtimeStatus && leaseClient.publishOpenClawRuntimeStatus) {\n\t\t\tawait leaseClient.publishOpenClawRuntimeStatus(runtimeStatus);\n\t\t}\n\t\tconst leaseResponse = await leaseClient.requestLease({\n\t\t\tagentId,\n\t\t\tagentWorkspaceDir: params.agentWorkspaceDir,\n\t\t\tprofileId,\n\t\t\tsandbox: snapshotOpenClawGondolinSandboxConfig(params.cfg),\n\t\t\tscopeKey: params.scopeKey,\n\t\t\tsessionKey: params.sessionKey,\n\t\t\tworkMountDir: params.workspaceDir,\n\t\t\tzoneId: options.zoneId,\n\t\t});\n\t\tif (!isToolVmSshLease(leaseResponse)) {\n\t\t\tthrow new TypeError('Controller lease API returned an unexpected response.');\n\t\t}\n\n\t\tconst lease = leaseResponse;\n\t\tconst handle = createSandboxBackendHandle({\n\t\t\tcfg: params.cfg,\n\t\t\tcontrollerUrl: options.controllerUrl,\n\t\t\tcreateFsBridgeBuilder: dependencies.createFsBridgeBuilder,\n\t\t\tlease,\n\t\t\tleaseClient,\n\t\t\trunRemoteShellScript: dependencies.runRemoteShellScript,\n\t\t\tbuildExecSpec: dependencies.buildExecSpec,\n\t\t\tscopeKey: params.scopeKey,\n\t\t\tsessionKey: params.sessionKey,\n\t\t\tzoneId: options.zoneId,\n\t\t});\n\t\tscopeCache.set(cacheKey, { handle, lease });\n\t\treturn handle;\n\t};\n}\n\nfunction createSandboxBackendHandle(options: {\n\treadonly buildExecSpec: CreateBackendDependencies['buildExecSpec'];\n\treadonly cfg: {\n\t\treadonly docker?: {\n\t\t\treadonly env?: Record<string, string>;\n\t\t};\n\t};\n\treadonly controllerUrl: string;\n\treadonly createFsBridgeBuilder?: CreateBackendDependencies['createFsBridgeBuilder'];\n\treadonly lease: CachedScopeEntry['lease'];\n\treadonly leaseClient: LeaseClient;\n\treadonly runRemoteShellScript: CreateBackendDependencies['runRemoteShellScript'];\n\treadonly scopeKey: string;\n\treadonly sessionKey: string;\n\treadonly zoneId: string;\n}): OpenClawSandboxBackendHandle {\n\tconst createActiveUseHandle = async (\n\t\tcorrelation: ToolVmActiveUseCorrelation,\n\t): Promise<ToolVmActiveUseHandle> =>\n\t\tawait createToolVmActiveUseHandle({\n\t\t\tcorrelation,\n\t\t\tendActiveUse: async (useId: string, request: EndToolVmActiveUseRequest): Promise<void> => {\n\t\t\t\tawait options.leaseClient.endActiveUse(options.lease.leaseId, useId, request);\n\t\t\t},\n\t\t\theartbeatActiveUse: async (useId: string): Promise<HeartbeatToolVmActiveUseResponse> =>\n\t\t\t\tawait options.leaseClient.heartbeatActiveUse(options.lease.leaseId, useId),\n\t\t\tisEndErrorTolerable: isCleanupNotFound,\n\t\t\tlogEndFailure: (error: unknown): void => {\n\t\t\t\twriteSandboxBackendLog(\n\t\t\t\t\t`active-use cleanup ignored for zone '${options.zoneId}' lease '${options.lease.leaseId}': ${formatUnknownError(error)}`,\n\t\t\t\t);\n\t\t\t},\n\t\t\tlogHeartbeatFailure: (error: unknown): void => {\n\t\t\t\twriteSandboxBackendLog(\n\t\t\t\t\t`active-use heartbeat failed for zone '${options.zoneId}' lease '${options.lease.leaseId}': ${formatUnknownError(error)}`,\n\t\t\t\t);\n\t\t\t},\n\t\t\tstartActiveUse: async (\n\t\t\t\trequest: StartToolVmActiveUseRequest,\n\t\t\t): Promise<StartToolVmActiveUseResponse> =>\n\t\t\t\tawait options.leaseClient.startActiveUse(options.lease.leaseId, request),\n\t\t});\n\n\tconst runWithActiveUse = async <TResult>(\n\t\tcorrelation: ToolVmActiveUseCorrelation,\n\t\tfn: () => Promise<TResult>,\n\t): Promise<TResult> => {\n\t\tconst activeUseHandle = await createActiveUseHandle(correlation);\n\t\ttry {\n\t\t\tconst result = await fn();\n\t\t\tawait activeUseHandle.dispose('completed');\n\t\t\treturn result;\n\t\t} catch (error) {\n\t\t\tawait activeUseHandle.dispose('failed').catch((cleanupError: unknown) => {\n\t\t\t\twriteSandboxBackendLog(\n\t\t\t\t\t`failed to end active use after operation failure for zone '${options.zoneId}' lease '${options.lease.leaseId}': ${formatUnknownError(cleanupError)}`,\n\t\t\t\t);\n\t\t\t});\n\t\t\tthrow error;\n\t\t}\n\t};\n\n\tconst boundRunRemoteShellScript: OpenClawFsBridgeLeaseContext['runRemoteShellScript'] = async (\n\t\tshellParams,\n\t) =>\n\t\tawait runWithActiveUse(\n\t\t\t{\n\t\t\t\tsessionKey: options.sessionKey,\n\t\t\t\ttoolName: 'fs-bridge',\n\t\t\t},\n\t\t\tasync () =>\n\t\t\t\tawait options.runRemoteShellScript({\n\t\t\t\t\t...(shellParams.allowFailure !== undefined\n\t\t\t\t\t\t? { allowFailure: shellParams.allowFailure }\n\t\t\t\t\t\t: {}),\n\t\t\t\t\tscript: buildShellScriptWithArgs(shellParams.script, shellParams.args),\n\t\t\t\t\t...(shellParams.signal !== undefined ? { signal: shellParams.signal } : {}),\n\t\t\t\t\tssh: options.lease.ssh,\n\t\t\t\t\t...(shellParams.stdin !== undefined ? { stdin: shellParams.stdin } : {}),\n\t\t\t\t}),\n\t\t);\n\n\tconst disposeInnerFinalizeToken = async (token: unknown): Promise<void> => {\n\t\tif (isDisposableFinalizeToken(token)) {\n\t\t\tawait token.dispose();\n\t\t}\n\t};\n\n\tconst endActiveUseFinalizeToken = async (\n\t\ttoken: ActiveUseFinalizeToken,\n\t\toutcome: ToolVmActiveUseOutcome,\n\t): Promise<void> => {\n\t\tlet innerError: unknown;\n\t\ttry {\n\t\t\tawait disposeInnerFinalizeToken(token.innerToken);\n\t\t} catch (error) {\n\t\t\tinnerError = error;\n\t\t}\n\t\tlet activeUseError: unknown;\n\t\ttry {\n\t\t\tawait token.activeUseHandle.dispose(outcome);\n\t\t} catch (error) {\n\t\t\tactiveUseError = error;\n\t\t}\n\t\tif (innerError) {\n\t\t\tthrow innerError;\n\t\t}\n\t\tif (activeUseError) {\n\t\t\tthrow activeUseError;\n\t\t}\n\t};\n\n\tconst createFsBridge = options.createFsBridgeBuilder?.({\n\t\tremoteAgentWorkspaceDir: options.lease.workdir,\n\t\tremoteWorkspaceDir: options.lease.workdir,\n\t\trunRemoteShellScript: boundRunRemoteShellScript,\n\t});\n\n\treturn {\n\t\t...(createFsBridge ? { createFsBridge } : {}),\n\t\t...(options.cfg.docker?.env ? { env: options.cfg.docker.env } : {}),\n\t\tconfigLabel: `${options.controllerUrl} (${options.zoneId})`,\n\t\tconfigLabelKind: 'VM',\n\t\tid: 'gondolin',\n\t\truntimeId: options.lease.leaseId,\n\t\truntimeLabel: options.lease.leaseId,\n\t\tworkdir: options.lease.workdir,\n\t\tbuildExecSpec: async (execParams) => {\n\t\t\tconst activeUseHandle = await createActiveUseHandle({\n\t\t\t\tsessionKey: options.sessionKey,\n\t\t\t\ttoolName: 'shell',\n\t\t\t});\n\t\t\ttry {\n\t\t\t\tconst execSpec = await options.buildExecSpec({\n\t\t\t\t\tcommand: execParams.command,\n\t\t\t\t\tenv: execParams.env,\n\t\t\t\t\tssh: options.lease.ssh,\n\t\t\t\t\tusePty: execParams.usePty,\n\t\t\t\t\tworkdir: execParams.workdir ?? options.lease.workdir,\n\t\t\t\t});\n\t\t\t\treturn {\n\t\t\t\t\t...execSpec,\n\t\t\t\t\tfinalizeToken: {\n\t\t\t\t\t\tactiveUseHandle,\n\t\t\t\t\t\t...(execSpec.finalizeToken !== undefined ? { innerToken: execSpec.finalizeToken } : {}),\n\t\t\t\t\t} satisfies ActiveUseFinalizeToken,\n\t\t\t\t};\n\t\t\t} catch (error) {\n\t\t\t\tawait activeUseHandle.dispose('failed').catch((cleanupError: unknown) => {\n\t\t\t\t\twriteSandboxBackendLog(\n\t\t\t\t\t\t`failed to end active use after buildExecSpec failure for zone '${options.zoneId}' lease '${options.lease.leaseId}': ${formatUnknownError(cleanupError)}`,\n\t\t\t\t\t);\n\t\t\t\t});\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t},\n\t\tfinalizeExec: async (finalizeParams) => {\n\t\t\tif (isActiveUseFinalizeToken(finalizeParams.token)) {\n\t\t\t\tawait endActiveUseFinalizeToken(\n\t\t\t\t\tfinalizeParams.token,\n\t\t\t\t\tactiveUseOutcomeForFinalizeParams(finalizeParams),\n\t\t\t\t);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tawait disposeInnerFinalizeToken(finalizeParams.token);\n\t\t},\n\t\trunShellCommand: async (commandParams) =>\n\t\t\tawait runWithActiveUse(\n\t\t\t\t{\n\t\t\t\t\tsessionKey: options.sessionKey,\n\t\t\t\t\ttoolName: 'runShellCommand',\n\t\t\t\t},\n\t\t\t\tasync () =>\n\t\t\t\t\tawait options.runRemoteShellScript({\n\t\t\t\t\t\tscript: commandParams.script,\n\t\t\t\t\t\tssh: options.lease.ssh,\n\t\t\t\t\t}),\n\t\t\t),\n\t} satisfies OpenClawSandboxBackendHandle;\n}\n","import { ControllerLeaseRequestError, createLeaseClient } from '../controller-lease-client.js';\nimport type { CreateBackendDependencies } from './sandbox-backend-contract.js';\n\nexport function createGondolinSandboxBackendManager(\n\toptions: {\n\t\treadonly controllerUrl: string;\n\t\treadonly zoneId: string;\n\t},\n\tdependencies: CreateBackendDependencies,\n): {\n\tdescribeRuntime: (params: {\n\t\treadonly entry: { readonly containerName: string };\n\t}) => Promise<{ readonly configLabelMatch: boolean; readonly running: boolean }>;\n\tremoveRuntime: (params: { readonly entry: { readonly containerName: string } }) => Promise<void>;\n} {\n\treturn {\n\t\tdescribeRuntime: async (params) => {\n\t\t\tconst leaseClient =\n\t\t\t\tdependencies.createLeaseClient?.({\n\t\t\t\t\tcontrollerUrl: options.controllerUrl,\n\t\t\t\t}) ?? createLeaseClient({ controllerUrl: options.controllerUrl });\n\t\t\ttry {\n\t\t\t\tconst leaseStatus = await leaseClient.peekLease(params.entry.containerName);\n\t\t\t\treturn { configLabelMatch: true, running: leaseStatus !== null };\n\t\t\t} catch (error) {\n\t\t\t\tif (!(error instanceof ControllerLeaseRequestError) || error.status !== 404) {\n\t\t\t\t\tthrow error;\n\t\t\t\t}\n\t\t\t\treturn { configLabelMatch: false, running: false };\n\t\t\t}\n\t\t},\n\t\tremoveRuntime: async (params) => {\n\t\t\tconst leaseClient =\n\t\t\t\tdependencies.createLeaseClient?.({\n\t\t\t\t\tcontrollerUrl: options.controllerUrl,\n\t\t\t\t}) ?? createLeaseClient({ controllerUrl: options.controllerUrl });\n\t\t\tawait leaseClient.releaseLease(params.entry.containerName, { force: true });\n\t\t},\n\t};\n}\n","export interface ResolvedGondolinPluginConfig {\n\treadonly controllerUrl: string;\n\treadonly profileId?: string;\n\treadonly zoneGitToken?: string;\n\treadonly zoneGitTokenEnv?: string;\n\treadonly zoneId: string;\n}\n\nexport function resolveGondolinPluginConfig(\n\tconfig: Record<string, unknown>,\n): ResolvedGondolinPluginConfig {\n\tif (typeof config.controllerUrl !== 'string' || typeof config.zoneId !== 'string') {\n\t\tthrow new Error('Gondolin plugin config requires controllerUrl and zoneId.');\n\t}\n\n\treturn {\n\t\tcontrollerUrl: config.controllerUrl,\n\t\t...(typeof config.profileId === 'string' ? { profileId: config.profileId } : {}),\n\t\t...(typeof config.zoneGitToken === 'string' ? { zoneGitToken: config.zoneGitToken } : {}),\n\t\t...(typeof config.zoneGitTokenEnv === 'string'\n\t\t\t? { zoneGitTokenEnv: config.zoneGitTokenEnv }\n\t\t\t: {}),\n\t\tzoneId: config.zoneId,\n\t};\n}\n","import type { SshHelpers, SshSandboxSession } from './openclaw-sandbox-sdk-contract.js';\nimport type {\n\tCreateBackendDependencies,\n\tOpenClawFsBridgeLeaseContext,\n\tOpenClawSandboxFsBridge,\n} from './sandbox-backend-factory.js';\n\nexport const OPENCLAW_SSH_SESSION_SCRATCH_ROOT = '/work';\n\nexport function createBackendDeps(ssh: SshHelpers): {\n\treadonly buildExecSpec: CreateBackendDependencies['buildExecSpec'];\n\treadonly createFsBridgeBuilder: (\n\t\tleaseContext: OpenClawFsBridgeLeaseContext,\n\t) => (params: { readonly sandbox: unknown }) => OpenClawSandboxFsBridge;\n\treadonly runRemoteShellScript: CreateBackendDependencies['runRemoteShellScript'];\n} {\n\treturn {\n\t\tbuildExecSpec: async ({ command, env, ssh: sshCreds, usePty, workdir }) => {\n\t\t\tconst session = await ssh.createSshSandboxSessionFromSettings({\n\t\t\t\tcommand: 'ssh',\n\t\t\t\tidentityData: sshCreds.identityPem,\n\t\t\t\tstrictHostKeyChecking: false,\n\t\t\t\ttarget: `${sshCreds.user}@${sshCreds.host}:${sshCreds.port}`,\n\t\t\t\tupdateHostKeys: false,\n\t\t\t\tworkspaceRoot: OPENCLAW_SSH_SESSION_SCRATCH_ROOT,\n\t\t\t});\n\t\t\tconst disposeSshSandboxSession = ssh.disposeSshSandboxSession;\n\t\t\treturn {\n\t\t\t\targv: ssh.buildSshSandboxArgv({\n\t\t\t\t\tremoteCommand: ssh.buildExecRemoteCommand({\n\t\t\t\t\t\tcommand,\n\t\t\t\t\t\tenv,\n\t\t\t\t\t\tworkdir,\n\t\t\t\t\t}),\n\t\t\t\t\tsession,\n\t\t\t\t\ttty: usePty,\n\t\t\t\t}),\n\t\t\t\tenv: ssh.sanitizeEnvVars(process.env).allowed,\n\t\t\t\tfinalizeToken: {\n\t\t\t\t\tdispose: async (): Promise<void> => {\n\t\t\t\t\t\tif (disposeSshSandboxSession) {\n\t\t\t\t\t\t\tawait disposeSshSandboxSession(session);\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\tsession,\n\t\t\t\t},\n\t\t\t\tstdinMode: 'pipe-open' as const,\n\t\t\t};\n\t\t},\n\t\tcreateFsBridgeBuilder:\n\t\t\t(leaseContext: OpenClawFsBridgeLeaseContext) =>\n\t\t\t(params: { readonly sandbox: unknown }): OpenClawSandboxFsBridge =>\n\t\t\t\tssh.createRemoteShellSandboxFsBridge({\n\t\t\t\t\tsandbox: params.sandbox,\n\t\t\t\t\truntime: {\n\t\t\t\t\t\tremoteAgentWorkspaceDir: leaseContext.remoteAgentWorkspaceDir,\n\t\t\t\t\t\tremoteWorkspaceDir: leaseContext.remoteWorkspaceDir,\n\t\t\t\t\t\trunRemoteShellScript: leaseContext.runRemoteShellScript,\n\t\t\t\t\t},\n\t\t\t\t}),\n\t\trunRemoteShellScript: async ({ allowFailure, script, signal, ssh: sshCreds, stdin }) => {\n\t\t\tconst session = await ssh.createSshSandboxSessionFromSettings({\n\t\t\t\tcommand: 'ssh',\n\t\t\t\tidentityData: sshCreds.identityPem,\n\t\t\t\tstrictHostKeyChecking: false,\n\t\t\t\ttarget: `${sshCreds.user}@${sshCreds.host}:${sshCreds.port}`,\n\t\t\t\tupdateHostKeys: false,\n\t\t\t\tworkspaceRoot: OPENCLAW_SSH_SESSION_SCRATCH_ROOT,\n\t\t\t});\n\t\t\treturn await ssh.runSshSandboxCommand({\n\t\t\t\t...(allowFailure !== undefined ? { allowFailure } : {}),\n\t\t\t\tremoteCommand: ssh.buildRemoteCommand(['/bin/sh', '-c', script, 'gondolin-sandbox-fs']),\n\t\t\t\tsession,\n\t\t\t\t...(signal !== undefined ? { signal } : {}),\n\t\t\t\t...(stdin !== undefined ? { stdin } : {}),\n\t\t\t});\n\t\t},\n\t};\n}\n\nexport type { SshHelpers, SshSandboxSession };\n","import {\n\teffectiveOpenClawGondolinSandboxValue,\n\tformatOpenClawGondolinRequirementFieldPath,\n\tformatOpenClawGondolinRequirementFindingId,\n\tformatOpenClawGondolinRequirementHint,\n\tOPENCLAW_GONDOLIN_SANDBOX_REQUIREMENTS,\n\ttype OpenClawGondolinAgentConfig,\n} from './openclaw-gondolin-contract.js';\n\ninterface OpenClawRuntimeConfig {\n\treadonly [key: string]: unknown;\n\treadonly agents?: {\n\t\treadonly defaults?: OpenClawGondolinAgentConfig;\n\t\treadonly list?: readonly unknown[];\n\t};\n}\n\nexport interface OpenClawRuntimeRequirementFinding {\n\treadonly hint: string;\n\treadonly id: string;\n\treadonly ok: boolean;\n}\n\nexport interface OpenClawRuntimeStatusReport {\n\treadonly findings: readonly OpenClawRuntimeRequirementFinding[];\n\treadonly pluginId: 'gondolin';\n\treadonly zoneId: string;\n}\n\nfunction isObjectRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction readAgentConfigEntries(config: OpenClawRuntimeConfig): readonly {\n\treadonly config: OpenClawGondolinAgentConfig;\n\treadonly label: string;\n}[] {\n\tconst defaultConfig = config.agents?.defaults ?? {};\n\tconst agentConfigs = (config.agents?.list ?? [])\n\t\t.filter(isObjectRecord)\n\t\t.map((agentConfig, agentIndex) => ({\n\t\t\tconfig: agentConfig,\n\t\t\tlabel:\n\t\t\t\ttypeof agentConfig.id === 'string'\n\t\t\t\t\t? `agent-${agentConfig.id}`\n\t\t\t\t\t: `agent-${String(agentIndex)}`,\n\t\t}));\n\treturn [{ config: defaultConfig, label: 'defaults' }, ...agentConfigs];\n}\n\nfunction effectiveWorkspace(\n\tdefaults: OpenClawGondolinAgentConfig,\n\tagentConfig: OpenClawGondolinAgentConfig,\n): unknown {\n\treturn agentConfig.workspace ?? defaults.workspace;\n}\n\nfunction requirementFinding(options: {\n\treadonly actualValue: unknown;\n\treadonly expectedValue: string;\n\treadonly fieldPath: string;\n\treadonly label: string;\n\treadonly zoneId: string;\n}): OpenClawRuntimeRequirementFinding {\n\tconst ok = options.actualValue === options.expectedValue;\n\treturn {\n\t\tid: formatOpenClawGondolinRequirementFindingId({\n\t\t\tfieldPath: options.fieldPath,\n\t\t\tlabel: options.label,\n\t\t\tzoneId: options.zoneId,\n\t\t}),\n\t\tok,\n\t\thint: formatOpenClawGondolinRequirementHint({\n\t\t\texpectedValue: options.expectedValue,\n\t\t\tfieldPath: options.fieldPath,\n\t\t\tok,\n\t\t}),\n\t};\n}\n\nexport function buildOpenClawRuntimeStatusReport(options: {\n\treadonly config: Record<string, unknown>;\n\treadonly zoneId: string;\n}): OpenClawRuntimeStatusReport {\n\tconst config: OpenClawRuntimeConfig = options.config;\n\tconst defaults = config.agents?.defaults ?? {};\n\treturn {\n\t\tpluginId: 'gondolin',\n\t\tzoneId: options.zoneId,\n\t\tfindings: readAgentConfigEntries(config).flatMap(({ config: agentConfig, label }) => {\n\t\t\tconst workspace = effectiveWorkspace(defaults, agentConfig);\n\t\t\tconst requirementFindings = OPENCLAW_GONDOLIN_SANDBOX_REQUIREMENTS.map((requirement) =>\n\t\t\t\trequirementFinding({\n\t\t\t\t\tactualValue: effectiveOpenClawGondolinSandboxValue(\n\t\t\t\t\t\tdefaults,\n\t\t\t\t\t\tagentConfig,\n\t\t\t\t\t\trequirement.key,\n\t\t\t\t\t),\n\t\t\t\t\texpectedValue: requirement.expectedValue,\n\t\t\t\t\tfieldPath: formatOpenClawGondolinRequirementFieldPath(label, requirement.key),\n\t\t\t\t\tlabel,\n\t\t\t\t\tzoneId: options.zoneId,\n\t\t\t\t}),\n\t\t\t);\n\t\t\tconst workspaceFinding = {\n\t\t\t\tid: `openclaw-tool-vm-workspace-${options.zoneId}-${label}`,\n\t\t\t\tok: workspace !== '/zone',\n\t\t\t\thint:\n\t\t\t\t\tworkspace === '/zone'\n\t\t\t\t\t\t? 'Use /zone/agents/default or per-agent workspaces; keep /zone for shared zone files.'\n\t\t\t\t\t\t: typeof workspace === 'string'\n\t\t\t\t\t\t\t? workspace\n\t\t\t\t\t\t\t: 'agents workspace is unset',\n\t\t\t} satisfies OpenClawRuntimeRequirementFinding;\n\t\t\treturn requirementFindings.concat(workspaceFinding);\n\t\t}),\n\t};\n}\n","export interface SshSandboxSession {\n\treadonly command: string;\n\treadonly configPath: string;\n\treadonly host: string;\n}\n\nexport interface SshHelpers {\n\treadonly buildExecRemoteCommand: (params: {\n\t\treadonly command: string;\n\t\treadonly env: Record<string, string>;\n\t\treadonly workdir?: string;\n\t}) => string;\n\treadonly buildRemoteCommand: (argv: readonly string[]) => string;\n\treadonly buildSshSandboxArgv: (params: {\n\t\treadonly remoteCommand: string;\n\t\treadonly session: SshSandboxSession;\n\t\treadonly tty?: boolean;\n\t}) => string[];\n\treadonly createRemoteShellSandboxFsBridge: (params: {\n\t\treadonly runtime: {\n\t\t\treadonly remoteAgentWorkspaceDir: string;\n\t\t\treadonly remoteWorkspaceDir: string;\n\t\t\treadonly runRemoteShellScript: (shellParams: {\n\t\t\t\treadonly allowFailure?: boolean;\n\t\t\t\treadonly args?: string[];\n\t\t\t\treadonly script: string;\n\t\t\t\treadonly signal?: AbortSignal;\n\t\t\t\treadonly stdin?: Buffer | string;\n\t\t\t}) => Promise<{\n\t\t\t\treadonly code: number;\n\t\t\t\treadonly stderr: Buffer;\n\t\t\t\treadonly stdout: Buffer;\n\t\t\t}>;\n\t\t};\n\t\treadonly sandbox: unknown;\n\t}) => import('./sandbox-backend-factory.js').OpenClawSandboxFsBridge;\n\treadonly createSshSandboxSessionFromSettings: (settings: {\n\t\treadonly command: string;\n\t\treadonly identityData?: string;\n\t\treadonly strictHostKeyChecking: boolean;\n\t\treadonly target: string;\n\t\treadonly updateHostKeys: boolean;\n\t\treadonly workspaceRoot: string;\n\t}) => Promise<SshSandboxSession>;\n\treadonly disposeSshSandboxSession?: (session: SshSandboxSession) => Promise<void>;\n\treadonly runSshSandboxCommand: (params: {\n\t\treadonly allowFailure?: boolean;\n\t\treadonly remoteCommand: string;\n\t\treadonly session: SshSandboxSession;\n\t\treadonly signal?: AbortSignal;\n\t\treadonly stdin?: Buffer | string;\n\t}) => Promise<{\n\t\treadonly code: number;\n\t\treadonly stderr: Buffer;\n\t\treadonly stdout: Buffer;\n\t}>;\n\treadonly sanitizeEnvVars: (env: NodeJS.ProcessEnv) => {\n\t\treadonly allowed: Record<string, string>;\n\t};\n}\n\nexport interface OpenClawToolRegistration {\n\treadonly description: string;\n\treadonly execute: (toolCallId: string, params: unknown) => Promise<OpenClawToolResult>;\n\treadonly name: string;\n\treadonly parameters: Record<string, unknown>;\n}\n\nexport interface OpenClawToolRegistrationOptions {\n\treadonly name?: string;\n\treadonly names?: readonly string[];\n\treadonly optional?: boolean;\n}\n\nexport interface OpenClawToolResult {\n\treadonly content: string;\n\treadonly details?: unknown;\n}\n\nexport interface OpenClawToolRegistrationApi {\n\treadonly registerTool?: (\n\t\ttool: OpenClawToolRegistration,\n\t\toptions?: OpenClawToolRegistrationOptions,\n\t) => void;\n}\n\nexport function assertSdkShape(value: unknown): asserts value is SshHelpers & {\n\tregisterSandboxBackend: (\n\t\tid: string,\n\t\tregistration: {\n\t\t\tfactory: ReturnType<\n\t\t\t\ttypeof import('./sandbox-backend-factory.js').createGondolinSandboxBackendFactory\n\t\t\t>;\n\t\t\tmanager?: ReturnType<\n\t\t\t\ttypeof import('./sandbox-backend-factory.js').createGondolinSandboxBackendManager\n\t\t\t>;\n\t\t},\n\t) => void;\n} {\n\tif (typeof value !== 'object' || value === null) {\n\t\tthrow new TypeError('OpenClaw SDK module is not an object');\n\t}\n\n\tfor (const exportName of [\n\t\t'buildExecRemoteCommand',\n\t\t'buildRemoteCommand',\n\t\t'buildSshSandboxArgv',\n\t\t'createRemoteShellSandboxFsBridge',\n\t\t'createSshSandboxSessionFromSettings',\n\t\t'runSshSandboxCommand',\n\t\t'sanitizeEnvVars',\n\t\t'registerSandboxBackend',\n\t] as const) {\n\t\tif (typeof (value as Record<string, unknown>)[exportName] !== 'function') {\n\t\t\tthrow new TypeError(`OpenClaw SDK missing required export: ${exportName}`);\n\t\t}\n\t}\n}\n","import type { OpenClawToolRegistrationApi } from './openclaw-sandbox-sdk-contract.js';\n\ntype RequiredOpenClawToolRegistrationApi = OpenClawToolRegistrationApi & {\n\treadonly registerTool: NonNullable<OpenClawToolRegistrationApi['registerTool']>;\n};\n\nexport interface RegisterZoneGitToolOptions {\n\treadonly api: RequiredOpenClawToolRegistrationApi;\n\treadonly controllerUrl: string;\n\treadonly fetchImpl?: typeof fetch;\n\treadonly zoneGitToken?: string;\n\treadonly zoneId: string;\n}\n\nconst zoneGitCapabilityHeader = 'x-agent-vm-zone-git-token';\n\nfunction readExpectedHead(input: unknown): string {\n\tif (typeof input !== 'object' || input === null || !('expectedHead' in input)) {\n\t\tthrow new Error('zone_git_push requires expectedHead.');\n\t}\n\tconst expectedHead = input.expectedHead;\n\tif (typeof expectedHead !== 'string' || expectedHead.length === 0) {\n\t\tthrow new Error('zone_git_push requires expectedHead.');\n\t}\n\treturn expectedHead;\n}\n\nfunction buildControllerUrl(controllerUrl: string, zoneId: string): string {\n\treturn `${controllerUrl.replace(/\\/$/u, '')}/zones/${encodeURIComponent(zoneId)}/zone-git/push`;\n}\n\nasync function readResponseText(response: Response): Promise<string> {\n\ttry {\n\t\treturn await response.text();\n\t} catch (error) {\n\t\treturn error instanceof Error ? error.message : String(error);\n\t}\n}\n\nfunction parseJsonPayload(responseText: string): unknown {\n\ttry {\n\t\treturn JSON.parse(responseText);\n\t} catch (error) {\n\t\tthrow new Error(`zone_git_push returned non-JSON response: ${responseText.slice(0, 500)}`, {\n\t\t\tcause: error,\n\t\t});\n\t}\n}\n\nexport function registerZoneGitTool(options: RegisterZoneGitToolOptions): void {\n\toptions.api.registerTool(\n\t\t{\n\t\t\tname: 'zone_git_push',\n\t\t\tdescription:\n\t\t\t\t'Push committed OpenClaw zone workspace changes through the agent-vm controller. Use after git commit; do not run raw git push.',\n\t\t\tparameters: {\n\t\t\t\ttype: 'object',\n\t\t\t\tadditionalProperties: false,\n\t\t\t\tproperties: {\n\t\t\t\t\texpectedHead: { type: 'string' },\n\t\t\t\t},\n\t\t\t\trequired: ['expectedHead'],\n\t\t\t},\n\t\t\texecute: async (_toolCallId: string, input: unknown) => {\n\t\t\t\tconst expectedHead = readExpectedHead(input);\n\t\t\t\tconst response = await (options.fetchImpl ?? fetch)(\n\t\t\t\t\tbuildControllerUrl(options.controllerUrl, options.zoneId),\n\t\t\t\t\t{\n\t\t\t\t\t\tbody: JSON.stringify({ expectedHead }),\n\t\t\t\t\t\theaders: {\n\t\t\t\t\t\t\t'content-type': 'application/json',\n\t\t\t\t\t\t\t...(options.zoneGitToken ? { [zoneGitCapabilityHeader]: options.zoneGitToken } : {}),\n\t\t\t\t\t\t},\n\t\t\t\t\t\tmethod: 'POST',\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t\tconst responseText = await readResponseText(response);\n\t\t\t\tif (!response.ok) {\n\t\t\t\t\tthrow new Error(`zone_git_push failed: ${response.status} ${responseText.slice(0, 500)}`);\n\t\t\t\t}\n\t\t\t\tconst payload = parseJsonPayload(responseText);\n\t\t\t\treturn {\n\t\t\t\t\tcontent: JSON.stringify(payload),\n\t\t\t\t\tdetails: payload,\n\t\t\t\t};\n\t\t\t},\n\t\t},\n\t\t{ name: 'zone_git_push', optional: true },\n\t);\n}\n","import { createLeaseClient } from './controller-lease-client.js';\nimport { resolveGondolinPluginConfig } from './gondolin-plugin-config.js';\nimport {\n\tOPENCLAW_SSH_SESSION_SCRATCH_ROOT,\n\tcreateBackendDeps,\n} from './openclaw-backend-dependencies.js';\nimport { buildOpenClawRuntimeStatusReport } from './openclaw-runtime-status.js';\nimport {\n\tassertSdkShape,\n\ttype OpenClawToolRegistrationApi,\n\ttype SshHelpers,\n\ttype SshSandboxSession,\n} from './openclaw-sandbox-sdk-contract.js';\nimport {\n\tcreateGondolinSandboxBackendFactory,\n\tcreateGondolinSandboxBackendManager,\n} from './sandbox-backend-factory.js';\nimport { registerZoneGitTool } from './zone-git-tool.js';\n\nconst plugin = {\n\tid: 'gondolin',\n\tname: 'Gondolin VM Sandbox',\n\tdescription: 'Sandbox backend powered by Gondolin micro-VMs.',\n\n\tregister(api: {\n\t\treadonly config?: Record<string, unknown>;\n\t\treadonly pluginConfig: Record<string, unknown>;\n\t\treadonly registerTool?: OpenClawToolRegistrationApi['registerTool'];\n\t\treadonly registrationMode: string;\n\t\treadonly runtime?: {\n\t\t\treadonly config?: {\n\t\t\t\treadonly current?: () => Record<string, unknown>;\n\t\t\t};\n\t\t};\n\t}): void {\n\t\tconst registerTool = api.registerTool;\n\t\tif (typeof registerTool !== 'function') {\n\t\t\tif (api.registrationMode === 'full') {\n\t\t\t\tthrow new Error('Gondolin full registration requires OpenClaw registerTool.');\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t\tconst pluginConfig = resolveGondolinPluginConfig(api.pluginConfig);\n\t\tconst zoneGitToken =\n\t\t\tpluginConfig.zoneGitToken ??\n\t\t\t(pluginConfig.zoneGitTokenEnv ? process.env[pluginConfig.zoneGitTokenEnv] : undefined);\n\t\tregisterZoneGitTool({\n\t\t\tapi: { registerTool },\n\t\t\tcontrollerUrl: pluginConfig.controllerUrl,\n\t\t\t...(zoneGitToken ? { zoneGitToken } : {}),\n\t\t\tzoneId: pluginConfig.zoneId,\n\t\t});\n\t\tif (api.registrationMode !== 'full') {\n\t\t\treturn;\n\t\t}\n\t\tconst buildRuntimeStatus = ():\n\t\t\t| ReturnType<typeof buildOpenClawRuntimeStatusReport>\n\t\t\t| undefined => {\n\t\t\tconst runtimeConfig = api.runtime?.config?.current?.() ?? api.config;\n\t\t\treturn runtimeConfig\n\t\t\t\t? buildOpenClawRuntimeStatusReport({\n\t\t\t\t\t\tconfig: runtimeConfig,\n\t\t\t\t\t\tzoneId: pluginConfig.zoneId,\n\t\t\t\t\t})\n\t\t\t\t: undefined;\n\t\t};\n\t\tconst initialRuntimeStatus = buildRuntimeStatus();\n\t\tif (initialRuntimeStatus) {\n\t\t\tconst leaseClient = createLeaseClient({ controllerUrl: pluginConfig.controllerUrl });\n\t\t\tvoid leaseClient\n\t\t\t\t.publishOpenClawRuntimeStatus?.(initialRuntimeStatus)\n\t\t\t\t?.catch((error: unknown) => {\n\t\t\t\t\tconst message = error instanceof Error ? error.message : JSON.stringify(error);\n\t\t\t\t\tprocess.stderr.write(\n\t\t\t\t\t\t`[gondolin] failed to publish OpenClaw runtime status: ${message}\\n`,\n\t\t\t\t\t);\n\t\t\t\t});\n\t\t}\n\n\t\tconst sdkPath = '/opt/openclaw-sdk/sandbox.js';\n\t\tconst sdkPromise = import(sdkPath).then((sdkRaw: Record<string, unknown>) => {\n\t\t\tassertSdkShape(sdkRaw);\n\n\t\t\tconst sshHelpers: SshHelpers = {\n\t\t\t\tbuildExecRemoteCommand: sdkRaw.buildExecRemoteCommand,\n\t\t\t\tbuildRemoteCommand: sdkRaw.buildRemoteCommand,\n\t\t\t\tbuildSshSandboxArgv: sdkRaw.buildSshSandboxArgv,\n\t\t\t\tcreateRemoteShellSandboxFsBridge: sdkRaw.createRemoteShellSandboxFsBridge,\n\t\t\t\tcreateSshSandboxSessionFromSettings: sdkRaw.createSshSandboxSessionFromSettings,\n\t\t\t\t...(typeof sdkRaw.disposeSshSandboxSession === 'function'\n\t\t\t\t\t? {\n\t\t\t\t\t\t\tdisposeSshSandboxSession: sdkRaw.disposeSshSandboxSession as (\n\t\t\t\t\t\t\t\tsession: SshSandboxSession,\n\t\t\t\t\t\t\t) => Promise<void>,\n\t\t\t\t\t\t}\n\t\t\t\t\t: {}),\n\t\t\t\trunSshSandboxCommand: sdkRaw.runSshSandboxCommand,\n\t\t\t\tsanitizeEnvVars: sdkRaw.sanitizeEnvVars,\n\t\t\t};\n\n\t\t\tconst backendDependencies = createBackendDeps(sshHelpers);\n\t\t\tsdkRaw.registerSandboxBackend('gondolin', {\n\t\t\t\tfactory: createGondolinSandboxBackendFactory(\n\t\t\t\t\t{\n\t\t\t\t\t\t...pluginConfig,\n\t\t\t\t\t\topenClawRuntimeStatusProvider: buildRuntimeStatus,\n\t\t\t\t\t},\n\t\t\t\t\tbackendDependencies,\n\t\t\t\t),\n\t\t\t\tmanager: createGondolinSandboxBackendManager(pluginConfig, backendDependencies),\n\t\t\t});\n\t\t});\n\n\t\tsdkPromise.catch((error: unknown) => {\n\t\t\tconst message = error instanceof Error ? error.message : JSON.stringify(error);\n\t\t\tprocess.stderr.write(`[gondolin] failed to load OpenClaw SDK: ${message}\\n`);\n\t\t});\n\t},\n};\n\nexport default plugin;\n\nexport { OPENCLAW_SSH_SESSION_SCRATCH_ROOT, createBackendDeps };\nexport type { SshHelpers };\n","export * from './sandbox-backend-factory.js';\nexport * from './gondolin-plugin-config.js';\nexport * from './controller-lease-client.js';\nexport * from './openclaw-plugin-registration.js';\nexport * from './openclaw-gondolin-contract.js';\nexport { default } from './openclaw-plugin-registration.js';\n\nexport const OPENCLAW_GONDOLIN_PLUGIN_PACKAGE_NAME = '@agent-vm/openclaw-agent-vm-plugin';\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":["formatUnknownError","formatUnknownError"],"sources":["../src/controller-lease-client.ts","../src/openclaw-gondolin-contract.ts","../src/sandbox-backend/openclaw-tool-vm-path-mapping.ts","../src/sandbox-backend/sandbox-shell-script.ts","../src/sandbox-backend/tool-vm-ssh-operation-guard.ts","../src/sandbox-backend/sandbox-backend-handle-factory.ts","../src/sandbox-backend/sandbox-backend-manager.ts","../src/gondolin-plugin-config.ts","../src/openclaw-backend-dependencies.ts","../src/openclaw-runtime-status.ts","../src/openclaw-sandbox-sdk-contract.ts","../src/zone-git-tool.ts","../src/openclaw-plugin-registration.ts","../src/index.ts"],"sourcesContent":["import {\n\tisToolVmLeasePeek,\n\tisToolVmSshLease,\n\ttype ToolVmLeasePeek,\n\ttype ToolVmSshLease,\n} from '@agent-vm/gateway-interface';\nimport type {\n\tEndToolVmActiveUseRequest,\n\tHeartbeatToolVmActiveUseRequest,\n\tHeartbeatToolVmActiveUseResponse,\n\tStartToolVmActiveUseRequest,\n\tStartToolVmActiveUseResponse,\n} from '@agent-vm/gateway-interface';\nimport { z } from 'zod';\n\nexport type JsonValue =\n\t| boolean\n\t| null\n\t| number\n\t| string\n\t| { readonly [key: string]: JsonValue }\n\t| readonly JsonValue[];\n\nexport interface OpenClawRuntimeStatusReport {\n\treadonly findings: readonly {\n\t\treadonly hint: string;\n\t\treadonly id: string;\n\t\treadonly ok: boolean;\n\t}[];\n\treadonly pluginId: 'gondolin';\n\treadonly zoneId: string;\n}\n\nexport interface OpenClawGondolinLeaseSandboxSnapshot {\n\treadonly backend: unknown;\n\treadonly mode: unknown;\n\treadonly scope: unknown;\n\treadonly workspaceAccess: unknown;\n}\n\nexport interface OpenClawGondolinLeaseRequest {\n\treadonly agentId: string;\n\treadonly agentWorkspaceDir: string;\n\treadonly idleTtlMs?: number;\n\treadonly profileId: string;\n\treadonly sessionKey: string;\n\treadonly workMountDir: string;\n\treadonly zoneId: string;\n}\n\nexport interface LeaseClient {\n\t// Cached handles use renewLease; read-only runtime probes use peekLease.\n\tendActiveUse(leaseId: string, useId: string, request: EndToolVmActiveUseRequest): Promise<void>;\n\theartbeatActiveUse(\n\t\tleaseId: string,\n\t\tuseId: string,\n\t\trequest: HeartbeatToolVmActiveUseRequest,\n\t): Promise<HeartbeatToolVmActiveUseResponse>;\n\tpeekLease(leaseId: string): Promise<ToolVmLeasePeek>;\n\tpublishOpenClawRuntimeStatus?(report: OpenClawRuntimeStatusReport): Promise<void>;\n\treleaseLease(leaseId: string, options?: { readonly force?: boolean }): Promise<void>;\n\trenewLease(leaseId: string): Promise<ToolVmSshLease>;\n\trequestLease(request: OpenClawGondolinLeaseRequest): Promise<ToolVmSshLease>;\n\tstartActiveUse(\n\t\tleaseId: string,\n\t\trequest: StartToolVmActiveUseRequest,\n\t): Promise<StartToolVmActiveUseResponse>;\n}\n\nexport type ControllerLeaseRequestErrorKind = 'client-error' | 'server-error';\n\nexport class ControllerLeaseRequestError extends Error {\n\treadonly bodyText: string;\n\treadonly kind: ControllerLeaseRequestErrorKind;\n\treadonly responseBody: JsonValue | undefined;\n\treadonly status: number;\n\n\tconstructor(options: {\n\t\treadonly bodyText: string;\n\t\treadonly context: string;\n\t\treadonly responseBody: JsonValue | undefined;\n\t\treadonly status: number;\n\t}) {\n\t\tconst kind: ControllerLeaseRequestErrorKind =\n\t\t\toptions.status >= 400 && options.status < 500 ? 'client-error' : 'server-error';\n\t\tsuper(\n\t\t\t`${options.context} returned HTTP ${String(options.status)} (${kind})${formatStructuredErrorSuffix(\n\t\t\t\toptions.responseBody,\n\t\t\t)}`,\n\t\t);\n\t\tthis.bodyText = options.bodyText;\n\t\tthis.kind = kind;\n\t\tthis.responseBody = options.responseBody;\n\t\tthis.status = options.status;\n\t}\n}\n\nconst structuredControllerErrorSchema = z.object({\n\tguidance: z.string().trim().min(1).optional(),\n\tmessage: z.string().trim().min(1).optional(),\n});\n\nfunction isJsonObjectRecord(value: unknown): value is { readonly [key: string]: JsonValue } {\n\treturn (\n\t\ttypeof value === 'object' &&\n\t\tvalue !== null &&\n\t\t!Array.isArray(value) &&\n\t\tObject.values(value).every(isJsonValue)\n\t);\n}\n\nfunction isJsonValue(value: unknown): value is JsonValue {\n\tif (\n\t\tvalue === null ||\n\t\ttypeof value === 'string' ||\n\t\ttypeof value === 'boolean' ||\n\t\ttypeof value === 'number'\n\t) {\n\t\treturn true;\n\t}\n\tif (Array.isArray(value)) {\n\t\treturn value.every(isJsonValue);\n\t}\n\treturn isJsonObjectRecord(value);\n}\n\nconst jsonValueSchema = z.custom<JsonValue>(isJsonValue);\n\nfunction objectValue(value: unknown): object | undefined {\n\treturn typeof value === 'object' && value !== null ? value : undefined;\n}\n\nfunction formatStructuredErrorSuffix(responseBody: JsonValue | undefined): string {\n\tconst parsedError = structuredControllerErrorSchema.safeParse(responseBody);\n\tif (!parsedError.success) {\n\t\treturn '';\n\t}\n\tconst { guidance, message } = parsedError.data;\n\tconst parts = [message, guidance ? `Guidance: ${guidance}` : undefined].filter(\n\t\t(part): part is string => part !== undefined,\n\t);\n\treturn parts.length > 0 ? `: ${parts.join(' ')}` : '';\n}\n\nfunction isStartActiveUseResponse(value: unknown): value is StartToolVmActiveUseResponse {\n\tconst record = objectValue(value);\n\treturn (\n\t\trecord !== undefined &&\n\t\ttypeof Reflect.get(record, 'expiresAt') === 'number' &&\n\t\ttypeof Reflect.get(record, 'heartbeatAfterMs') === 'number' &&\n\t\ttypeof Reflect.get(record, 'useId') === 'string'\n\t);\n}\n\nfunction isHeartbeatActiveUseResponse(value: unknown): value is HeartbeatToolVmActiveUseResponse {\n\tconst record = objectValue(value);\n\treturn (\n\t\trecord !== undefined &&\n\t\ttypeof Reflect.get(record, 'expiresAt') === 'number' &&\n\t\ttypeof Reflect.get(record, 'heartbeatAfterMs') === 'number'\n\t);\n}\n\nfunction formatUnknownError(error: unknown): string {\n\treturn error instanceof Error ? error.message : String(error);\n}\n\nfunction writeLeaseClientLog(message: string): void {\n\tprocess.stderr.write(`[openclaw-agent-vm-plugin] ${message}\\n`);\n}\n\nfunction parseJsonBody(bodyText: string, context: string): JsonValue | undefined {\n\ttry {\n\t\tconst parsedJson: unknown = JSON.parse(bodyText);\n\t\tconst parsedBody = jsonValueSchema.safeParse(parsedJson);\n\t\treturn parsedBody.success ? parsedBody.data : undefined;\n\t} catch (error) {\n\t\twriteLeaseClientLog(`${context} returned a non-JSON error body: ${formatUnknownError(error)}`);\n\t\treturn undefined;\n\t}\n}\n\nasync function readErrorBody(\n\tresponse: Response,\n\tcontext: string,\n): Promise<{\n\treadonly bodyText: string;\n\treadonly responseBody: JsonValue | undefined;\n}> {\n\tconst bodyText = await response.text().catch(() => '(unreadable)');\n\treturn {\n\t\tbodyText,\n\t\tresponseBody: bodyText === '(unreadable)' ? undefined : parseJsonBody(bodyText, context),\n\t};\n}\n\nasync function readJsonResponse<TValue>(\n\tresponse: Response,\n\tcontext: string,\n\tisExpectedResponse: (value: unknown) => value is TValue,\n): Promise<TValue> {\n\tif (!response.ok) {\n\t\tconst errorBody = await readErrorBody(response, context);\n\t\tthrow new ControllerLeaseRequestError({\n\t\t\tbodyText: errorBody.bodyText,\n\t\t\tcontext,\n\t\t\tresponseBody: errorBody.responseBody,\n\t\t\tstatus: response.status,\n\t\t});\n\t}\n\tconst payload = await response.json();\n\tif (!isExpectedResponse(payload)) {\n\t\tthrow new TypeError(\n\t\t\t`${context} returned an invalid response: ${JSON.stringify(payload).slice(0, 200)}`,\n\t\t);\n\t}\n\treturn payload;\n}\n\nexport function createLeaseClient(options: {\n\treadonly controllerUrl: string;\n\treadonly fetchImpl?: (input: string | URL | Request, init?: RequestInit) => Promise<Response>;\n}): LeaseClient {\n\tconst fetchImpl = options.fetchImpl ?? fetch;\n\tconst baseUrl = options.controllerUrl.replace(/\\/$/u, '');\n\tconst renewLease = async (leaseId: string): Promise<ToolVmSshLease> => {\n\t\tconst response = await fetchImpl(`${baseUrl}/lease/${encodeURIComponent(leaseId)}/renew`, {\n\t\t\tmethod: 'POST',\n\t\t});\n\t\treturn await readJsonResponse(response, 'Controller lease renew API', isToolVmSshLease);\n\t};\n\n\treturn {\n\t\tendActiveUse: async (\n\t\t\tleaseId: string,\n\t\t\tuseId: string,\n\t\t\trequest: EndToolVmActiveUseRequest,\n\t\t): Promise<void> => {\n\t\t\tconst response = await fetchImpl(\n\t\t\t\t`${baseUrl}/lease/${encodeURIComponent(leaseId)}/uses/${encodeURIComponent(useId)}`,\n\t\t\t\t{\n\t\t\t\t\tbody: JSON.stringify(request),\n\t\t\t\t\theaders: {\n\t\t\t\t\t\t'content-type': 'application/json',\n\t\t\t\t\t},\n\t\t\t\t\tmethod: 'DELETE',\n\t\t\t\t},\n\t\t\t);\n\t\t\tif (!response.ok) {\n\t\t\t\tconst errorBody = await readErrorBody(response, 'Controller active-use end API');\n\t\t\t\tthrow new ControllerLeaseRequestError({\n\t\t\t\t\tbodyText: errorBody.bodyText,\n\t\t\t\t\tcontext: 'Controller active-use end API',\n\t\t\t\t\tresponseBody: errorBody.responseBody,\n\t\t\t\t\tstatus: response.status,\n\t\t\t\t});\n\t\t\t}\n\t\t},\n\t\theartbeatActiveUse: async (\n\t\t\tleaseId: string,\n\t\t\tuseId: string,\n\t\t\trequest: HeartbeatToolVmActiveUseRequest,\n\t\t): Promise<HeartbeatToolVmActiveUseResponse> => {\n\t\t\tconst response = await fetchImpl(\n\t\t\t\t`${baseUrl}/lease/${encodeURIComponent(leaseId)}/uses/${encodeURIComponent(useId)}/heartbeat`,\n\t\t\t\t{\n\t\t\t\t\tbody: JSON.stringify(request),\n\t\t\t\t\theaders: {\n\t\t\t\t\t\t'content-type': 'application/json',\n\t\t\t\t\t},\n\t\t\t\t\tmethod: 'POST',\n\t\t\t\t},\n\t\t\t);\n\t\t\treturn await readJsonResponse(\n\t\t\t\tresponse,\n\t\t\t\t'Controller active-use heartbeat API',\n\t\t\t\tisHeartbeatActiveUseResponse,\n\t\t\t);\n\t\t},\n\t\trenewLease,\n\t\tpeekLease: async (leaseId: string): Promise<ToolVmLeasePeek> => {\n\t\t\tconst response = await fetchImpl(`${baseUrl}/lease/${encodeURIComponent(leaseId)}/peek`);\n\t\t\treturn await readJsonResponse(response, 'Controller lease peek API', isToolVmLeasePeek);\n\t\t},\n\t\tpublishOpenClawRuntimeStatus: async (report): Promise<void> => {\n\t\t\tconst response = await fetchImpl(\n\t\t\t\t`${baseUrl}/zones/${encodeURIComponent(report.zoneId)}/openclaw-runtime-status`,\n\t\t\t\t{\n\t\t\t\t\tbody: JSON.stringify(report),\n\t\t\t\t\theaders: {\n\t\t\t\t\t\t'content-type': 'application/json',\n\t\t\t\t\t},\n\t\t\t\t\tmethod: 'POST',\n\t\t\t\t},\n\t\t\t);\n\t\t\tif (!response.ok) {\n\t\t\t\tconst errorBody = await readErrorBody(response, 'Controller OpenClaw runtime status API');\n\t\t\t\tthrow new ControllerLeaseRequestError({\n\t\t\t\t\tbodyText: errorBody.bodyText,\n\t\t\t\t\tcontext: 'Controller OpenClaw runtime status API',\n\t\t\t\t\tresponseBody: errorBody.responseBody,\n\t\t\t\t\tstatus: response.status,\n\t\t\t\t});\n\t\t\t}\n\t\t},\n\t\treleaseLease: async (\n\t\t\tleaseId: string,\n\t\t\treleaseOptions: { readonly force?: boolean } = {},\n\t\t): Promise<void> => {\n\t\t\tconst releaseUrl = new URL(`${baseUrl}/lease/${encodeURIComponent(leaseId)}`);\n\t\t\tif (releaseOptions.force === true) {\n\t\t\t\treleaseUrl.searchParams.set('force', 'true');\n\t\t\t}\n\t\t\tconst response = await fetchImpl(releaseUrl.toString(), {\n\t\t\t\tmethod: 'DELETE',\n\t\t\t});\n\t\t\tif (!response.ok) {\n\t\t\t\tconst errorBody = await readErrorBody(response, 'Controller lease release API');\n\t\t\t\tthrow new ControllerLeaseRequestError({\n\t\t\t\t\tbodyText: errorBody.bodyText,\n\t\t\t\t\tcontext: 'Controller lease release API',\n\t\t\t\t\tresponseBody: errorBody.responseBody,\n\t\t\t\t\tstatus: response.status,\n\t\t\t\t});\n\t\t\t}\n\t\t},\n\t\trequestLease: async (request): Promise<ToolVmSshLease> => {\n\t\t\tconst response = await fetchImpl(`${baseUrl}/lease`, {\n\t\t\t\tbody: JSON.stringify({\n\t\t\t\t\tagentId: request.agentId,\n\t\t\t\t\tagentWorkspaceDir: request.agentWorkspaceDir,\n\t\t\t\t\t...(request.idleTtlMs !== undefined ? { idleTtlMs: request.idleTtlMs } : {}),\n\t\t\t\t\tprofileId: request.profileId,\n\t\t\t\t\tsessionKey: request.sessionKey,\n\t\t\t\t\tworkMountDir: request.workMountDir,\n\t\t\t\t\tzoneId: request.zoneId,\n\t\t\t\t}),\n\t\t\t\theaders: {\n\t\t\t\t\t'content-type': 'application/json',\n\t\t\t\t},\n\t\t\t\tmethod: 'POST',\n\t\t\t});\n\t\t\treturn await readJsonResponse(response, 'Controller lease API', isToolVmSshLease);\n\t\t},\n\t\tstartActiveUse: async (\n\t\t\tleaseId: string,\n\t\t\trequest: StartToolVmActiveUseRequest,\n\t\t): Promise<StartToolVmActiveUseResponse> => {\n\t\t\tconst response = await fetchImpl(`${baseUrl}/lease/${encodeURIComponent(leaseId)}/uses`, {\n\t\t\t\tbody: JSON.stringify(request),\n\t\t\t\theaders: {\n\t\t\t\t\t'content-type': 'application/json',\n\t\t\t\t},\n\t\t\t\tmethod: 'POST',\n\t\t\t});\n\t\t\treturn await readJsonResponse(\n\t\t\t\tresponse,\n\t\t\t\t'Controller active-use start API',\n\t\t\t\tisStartActiveUseResponse,\n\t\t\t);\n\t\t},\n\t};\n}\n","const agentIdPattern = /^[a-z0-9][a-z0-9_-]{0,63}$/iu;\n\nexport const OPENCLAW_DEFAULT_AGENT_ID = 'main';\n\nexport const OPENCLAW_GONDOLIN_SANDBOX_REQUIREMENTS = [\n\t{ expectedValue: 'gondolin', key: 'backend' },\n\t{ expectedValue: 'all', key: 'mode' },\n\t{ expectedValue: 'agent', key: 'scope' },\n\t{ expectedValue: 'rw', key: 'workspaceAccess' },\n] as const;\n\nexport const OPENCLAW_GONDOLIN_LEASE_SCOPE_GUIDANCE =\n\t'Managed OpenClaw/Gondolin leases are agent-scoped. The plugin derives agentId from sessionKey and does not send OpenClaw scope keys to the controller.';\n\nexport type OpenClawGondolinSandboxRequirement =\n\t(typeof OPENCLAW_GONDOLIN_SANDBOX_REQUIREMENTS)[number];\n\nexport type OpenClawGondolinSandboxRequirementKey = OpenClawGondolinSandboxRequirement['key'];\n\nexport interface OpenClawGondolinSandboxSnapshot {\n\treadonly backend?: unknown;\n\treadonly mode?: unknown;\n\treadonly scope?: unknown;\n\treadonly workspaceAccess?: unknown;\n}\n\nexport interface OpenClawGondolinAgentConfig {\n\treadonly id?: unknown;\n\treadonly sandbox?: OpenClawGondolinSandboxSnapshot;\n\treadonly workspace?: unknown;\n}\n\nexport function isOpenClawAgentId(value: string): boolean {\n\treturn agentIdPattern.test(value.trim());\n}\n\nexport function effectiveOpenClawGondolinSandboxValue(\n\tdefaults: OpenClawGondolinAgentConfig,\n\tagentConfig: OpenClawGondolinAgentConfig,\n\tkey: OpenClawGondolinSandboxRequirementKey,\n): unknown {\n\treturn agentConfig.sandbox?.[key] ?? defaults.sandbox?.[key];\n}\n\nexport function formatOpenClawGondolinRequirementFieldPath(\n\tlabel: string,\n\tkey: OpenClawGondolinSandboxRequirementKey,\n): string {\n\treturn `agents.${label}.sandbox.${key}`;\n}\n\nexport function formatOpenClawGondolinRequirementFindingId(options: {\n\treadonly fieldPath: string;\n\treadonly label: string;\n\treadonly zoneId: string;\n}): string {\n\treturn `openclaw-tool-vm-${options.fieldPath.replace(/[.[\\]]/gu, '-')}-${options.zoneId}-${options.label}`;\n}\n\nexport function formatOpenClawGondolinRequirementHint(options: {\n\treadonly expectedValue: string;\n\treadonly fieldPath: string;\n\treadonly ok: boolean;\n}): string {\n\treturn options.ok\n\t\t? `${options.fieldPath}=${options.expectedValue}`\n\t\t: `Set ${options.fieldPath} to \"${options.expectedValue}\" for OpenClaw Tool VM mediation.`;\n}\n\nexport function normalizeOpenClawAgentId(value: string | undefined | null): string {\n\tconst trimmed = (value ?? '').trim().toLowerCase();\n\treturn isOpenClawAgentId(trimmed) ? trimmed : OPENCLAW_DEFAULT_AGENT_ID;\n}\n\nexport function resolveOpenClawAgentIdFromSessionKey(sessionKey: string): string {\n\tconst parts = sessionKey.trim().split(':');\n\tif (parts[0] !== 'agent' || !parts[1]) {\n\t\treturn OPENCLAW_DEFAULT_AGENT_ID;\n\t}\n\treturn normalizeOpenClawAgentId(parts[1]);\n}\n\nexport function isOpenClawAgentSessionKey(sessionKey: string): boolean {\n\tconst parts = sessionKey.trim().split(':');\n\treturn parts[0] === 'agent' && parts[1] !== undefined && isOpenClawAgentId(parts[1]);\n}\n\nexport function snapshotOpenClawGondolinSandboxConfig(cfg: OpenClawGondolinSandboxSnapshot): {\n\treadonly backend: unknown;\n\treadonly mode: unknown;\n\treadonly scope: unknown;\n\treadonly workspaceAccess: unknown;\n} {\n\treturn {\n\t\tbackend: cfg.backend,\n\t\tmode: cfg.mode,\n\t\tscope: cfg.scope,\n\t\tworkspaceAccess: cfg.workspaceAccess,\n\t};\n}\n\nexport function findOpenClawGondolinSandboxMismatch(\n\tsandbox: OpenClawGondolinSandboxSnapshot,\n): OpenClawGondolinSandboxRequirement | undefined {\n\treturn OPENCLAW_GONDOLIN_SANDBOX_REQUIREMENTS.find(\n\t\t(requirement) => sandbox[requirement.key] !== requirement.expectedValue,\n\t);\n}\n","import {\n\tOPENCLAW_STATE_SANDBOXES_VM_ROOT,\n\tTOOL_VM_SCRATCH_GUEST_ROOT,\n\tTOOL_VM_WORKSPACE_GUEST_ROOT,\n\ttranslateRuntimePath,\n\ttype RuntimePathMapping,\n\ttype RuntimePathTranslation,\n\ttype RuntimePathTranslationError,\n} from '@agent-vm/gateway-interface';\n\nexport type OpenClawToolVmPathIntentKind =\n\t| 'host-workspace-root'\n\t| 'host-workspace-subpath'\n\t| 'openclaw-sandbox-path'\n\t| 'workspace-root'\n\t| 'workspace-subpath'\n\t| 'scratch-root'\n\t| 'scratch-subpath';\n\nexport interface OpenClawToolVmPathIntentResolution {\n\treadonly effectiveGuestCwd: string;\n\treadonly hostEquivalentPath?: string;\n\treadonly kind: OpenClawToolVmPathIntentKind;\n\treadonly leaseWorkMountDir: string;\n}\n\nexport type OpenClawToolVmPathIntentResult =\n\t| {\n\t\t\treadonly ok: true;\n\t\t\treadonly value: OpenClawToolVmPathIntentResolution;\n\t }\n\t| {\n\t\t\treadonly ok: false;\n\t\t\treadonly error: RuntimePathTranslationError;\n\t };\n\nexport class OpenClawToolVmPathIntentError extends Error {\n\treadonly details: RuntimePathTranslationError;\n\n\tconstructor(details: RuntimePathTranslationError) {\n\t\tsuper(`${details.message} ${details.retryGuidance}`);\n\t\tthis.name = 'OpenClawToolVmPathIntentError';\n\t\tthis.details = details;\n\t}\n}\n\nfunction pathContainsParentTraversal(inputPath: string): boolean {\n\treturn inputPath.split(/\\/+/u).includes('..');\n}\n\nfunction normalizedAbsolutePath(inputPath: string): string {\n\tconst rawSegments = inputPath.split('/').filter((segment) => segment !== '' && segment !== '.');\n\treturn `/${rawSegments.join('/')}`;\n}\n\nfunction invalidAgentWorkspaceRootError(agentWorkspaceDir: string): RuntimePathTranslationError {\n\treturn {\n\t\tallowedPathForms: [],\n\t\tcode: 'invalid-runtime-root',\n\t\tinputPath: agentWorkspaceDir,\n\t\tmappingId: 'openclaw-tool-vm',\n\t\tmessage: `OpenClaw agentWorkspaceDir '${agentWorkspaceDir}' must be an absolute non-root path without parent traversal.`,\n\t\tpurpose: 'executionCwd',\n\t\tretryGuidance:\n\t\t\t'Retry with OpenClaw agentWorkspaceDir set to the resolved host RealFS workspace for the requested agent.',\n\t};\n}\n\nfunction validateAgentWorkspaceDir(\n\tagentWorkspaceDir: string,\n): RuntimePathTranslationError | undefined {\n\tif (\n\t\tagentWorkspaceDir.trim() === '' ||\n\t\t!agentWorkspaceDir.startsWith('/') ||\n\t\tnormalizedAbsolutePath(agentWorkspaceDir) === '/' ||\n\t\tpathContainsParentTraversal(agentWorkspaceDir)\n\t) {\n\t\treturn invalidAgentWorkspaceRootError(agentWorkspaceDir);\n\t}\n\treturn undefined;\n}\n\nfunction createOpenClawToolVmPathMapping(options: {\n\treadonly agentWorkspaceDir: string;\n}): RuntimePathMapping {\n\treturn {\n\t\tid: 'openclaw-tool-vm',\n\t\troots: [\n\t\t\t{\n\t\t\t\tid: 'agent-workspace',\n\t\t\t\tguestRoot: TOOL_VM_WORKSPACE_GUEST_ROOT,\n\t\t\t\thostRoot: options.agentWorkspaceDir,\n\t\t\t\tbacking: {\n\t\t\t\t\tkind: 'host-realfs',\n\t\t\t\t\tdurability: 'durable',\n\t\t\t\t\tbackup: 'included',\n\t\t\t\t},\n\t\t\t\tcapabilities: {\n\t\t\t\t\texecutionCwd: true,\n\t\t\t\t\tleaseMount: true,\n\t\t\t\t},\n\t\t\t\trootPathAllowed: true,\n\t\t\t\tguidanceLabel: 'agent workspace',\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: 'tool-vm-scratch',\n\t\t\t\tguestRoot: TOOL_VM_SCRATCH_GUEST_ROOT,\n\t\t\t\tbacking: {\n\t\t\t\t\tkind: 'guest-rootfs-cow',\n\t\t\t\t\tdurability: 'vm-lifetime',\n\t\t\t\t},\n\t\t\t\tcapabilities: {\n\t\t\t\t\texecutionCwd: true,\n\t\t\t\t\tleaseMount: false,\n\t\t\t\t},\n\t\t\t\trootPathAllowed: true,\n\t\t\t\tguidanceLabel: 'Tool VM scratch',\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: 'openclaw-sandboxes',\n\t\t\t\thostRoot: OPENCLAW_STATE_SANDBOXES_VM_ROOT,\n\t\t\t\tbacking: {\n\t\t\t\t\tkind: 'host-realfs',\n\t\t\t\t\tdurability: 'durable',\n\t\t\t\t\tbackup: 'included',\n\t\t\t\t},\n\t\t\t\tcapabilities: {\n\t\t\t\t\texecutionCwd: true,\n\t\t\t\t\tleaseMount: true,\n\t\t\t\t},\n\t\t\t\trootPathAllowed: false,\n\t\t\t\tguidanceLabel: 'OpenClaw sandbox work directory',\n\t\t\t},\n\t\t],\n\t};\n}\n\nfunction resolveOpenClawSandboxPathIntent(translation: RuntimePathTranslation): {\n\treadonly effectiveGuestCwd: string;\n\treadonly leaseWorkMountDir: string;\n} {\n\tconst [sandboxChild, ...guestCwdSegments] = translation.relativePath.split('/');\n\tconst leaseWorkMountDir =\n\t\tsandboxChild === undefined || sandboxChild === ''\n\t\t\t? (translation.hostPath ?? OPENCLAW_STATE_SANDBOXES_VM_ROOT)\n\t\t\t: `${OPENCLAW_STATE_SANDBOXES_VM_ROOT}/${sandboxChild}`;\n\tconst effectiveGuestCwd =\n\t\tguestCwdSegments.length === 0\n\t\t\t? TOOL_VM_WORKSPACE_GUEST_ROOT\n\t\t\t: `${TOOL_VM_WORKSPACE_GUEST_ROOT}/${guestCwdSegments.join('/')}`;\n\treturn {\n\t\teffectiveGuestCwd,\n\t\tleaseWorkMountDir,\n\t};\n}\n\nfunction kindForTranslation(translation: RuntimePathTranslation): OpenClawToolVmPathIntentKind {\n\tconst isRoot = translation.relativePath === '';\n\tif (translation.rootId === 'tool-vm-scratch') {\n\t\treturn isRoot ? 'scratch-root' : 'scratch-subpath';\n\t}\n\tif (translation.rootId === 'openclaw-sandboxes') {\n\t\treturn 'openclaw-sandbox-path';\n\t}\n\tif (translation.inputNamespace === 'host') {\n\t\treturn isRoot ? 'host-workspace-root' : 'host-workspace-subpath';\n\t}\n\treturn isRoot ? 'workspace-root' : 'workspace-subpath';\n}\n\nexport function resolveOpenClawToolVmPathIntent(options: {\n\treadonly agentWorkspaceDir: string;\n\treadonly inputPath: string;\n}): OpenClawToolVmPathIntentResult {\n\tconst agentWorkspaceDirError = validateAgentWorkspaceDir(options.agentWorkspaceDir);\n\tif (agentWorkspaceDirError !== undefined) {\n\t\treturn {\n\t\t\terror: agentWorkspaceDirError,\n\t\t\tok: false,\n\t\t};\n\t}\n\tconst translation = translateRuntimePath({\n\t\tinputPath: options.inputPath,\n\t\tmapping: createOpenClawToolVmPathMapping({\n\t\t\tagentWorkspaceDir: options.agentWorkspaceDir,\n\t\t}),\n\t\tpurpose: 'executionCwd',\n\t});\n\tif (!translation.ok) {\n\t\treturn translation;\n\t}\n\tconst sandboxPathIntent =\n\t\ttranslation.value.rootId === 'openclaw-sandboxes'\n\t\t\t? resolveOpenClawSandboxPathIntent(translation.value)\n\t\t\t: undefined;\n\treturn {\n\t\tok: true,\n\t\tvalue: {\n\t\t\teffectiveGuestCwd:\n\t\t\t\tsandboxPathIntent !== undefined\n\t\t\t\t\t? sandboxPathIntent.effectiveGuestCwd\n\t\t\t\t\t: (translation.value.guestPath ?? TOOL_VM_WORKSPACE_GUEST_ROOT),\n\t\t\t...(translation.value.hostPath !== undefined\n\t\t\t\t? { hostEquivalentPath: translation.value.hostPath }\n\t\t\t\t: {}),\n\t\t\tkind: kindForTranslation(translation.value),\n\t\t\tleaseWorkMountDir:\n\t\t\t\tsandboxPathIntent !== undefined\n\t\t\t\t\t? sandboxPathIntent.leaseWorkMountDir\n\t\t\t\t\t: (translation.value.hostRoot ?? options.agentWorkspaceDir),\n\t\t},\n\t};\n}\n\nexport function assertOpenClawToolVmPathIntent(options: {\n\treadonly agentWorkspaceDir: string;\n\treadonly inputPath: string;\n}): OpenClawToolVmPathIntentResolution {\n\tconst result = resolveOpenClawToolVmPathIntent(options);\n\tif (!result.ok) {\n\t\tthrow new OpenClawToolVmPathIntentError(result.error);\n\t}\n\treturn result.value;\n}\n","export function buildShellScriptWithArgs(script: string, args?: readonly string[]): string {\n\tif (!args || args.length === 0) {\n\t\treturn script;\n\t}\n\n\tconst escapedArgs = args.map((arg) => `'${arg.replace(/'/g, \"'\\\\''\")}'`).join(' ');\n\treturn `set -- ${escapedArgs}; ${script}`;\n}\n","import type {\n\tToolVmActiveUseOperationReport,\n\tToolVmSshFailureKind,\n} from '@agent-vm/gateway-interface';\n\nexport class ToolVmSshOperationStaleError extends Error {\n\toverride readonly cause: unknown;\n\treadonly reason: ToolVmSshFailureKind;\n\n\tconstructor(options: {\n\t\treadonly cause: unknown;\n\t\treadonly message: string;\n\t\treadonly reason: ToolVmSshFailureKind;\n\t}) {\n\t\tsuper(options.message);\n\t\tthis.cause = options.cause;\n\t\tthis.reason = options.reason;\n\t}\n}\n\nexport interface ToolVmSshOperationGuardOptions<TResult> {\n\treadonly clearTimeoutImpl?: typeof clearTimeout | undefined;\n\treadonly now?: (() => number) | undefined;\n\treadonly operation: (signal: AbortSignal) => Promise<TResult>;\n\treadonly operationName: string;\n\treadonly report: (report: ToolVmActiveUseOperationReport) => void;\n\treadonly setTimeoutImpl?: typeof setTimeout | undefined;\n\treadonly timeoutMs: number;\n}\n\nfunction formatUnknownError(error: unknown): string {\n\treturn error instanceof Error ? error.message : String(error);\n}\n\nexport async function runToolVmSshOperationWithGuard<TResult>(\n\toptions: ToolVmSshOperationGuardOptions<TResult>,\n): Promise<TResult> {\n\tconst now = options.now ?? Date.now;\n\tconst setTimeoutImpl = options.setTimeoutImpl ?? setTimeout;\n\tconst clearTimeoutImpl = options.clearTimeoutImpl ?? clearTimeout;\n\tconst abortController = new AbortController();\n\tlet timeoutHandle: ReturnType<typeof setTimeout> | undefined;\n\n\toptions.report({\n\t\tobservedAtMs: now(),\n\t\tphase: 'running',\n\t});\n\n\tconst timeoutPromise = new Promise<never>((_resolve, reject) => {\n\t\ttimeoutHandle = setTimeoutImpl(() => {\n\t\t\tabortController.abort();\n\t\t\treject(\n\t\t\t\tnew ToolVmSshOperationStaleError({\n\t\t\t\t\tcause: undefined,\n\t\t\t\t\tmessage: `${options.operationName} exceeded ${String(options.timeoutMs)}ms.`,\n\t\t\t\t\treason: 'ssh-command-timed-out',\n\t\t\t\t}),\n\t\t\t);\n\t\t}, options.timeoutMs);\n\t});\n\n\ttry {\n\t\tconst result = await Promise.race([options.operation(abortController.signal), timeoutPromise]);\n\t\toptions.report({\n\t\t\tobservedAtMs: now(),\n\t\t\tphase: 'completed',\n\t\t\tssh: { probeSucceeded: true },\n\t\t});\n\t\treturn result;\n\t} catch (error) {\n\t\tconst staleError =\n\t\t\terror instanceof ToolVmSshOperationStaleError\n\t\t\t\t? error\n\t\t\t\t: new ToolVmSshOperationStaleError({\n\t\t\t\t\t\tcause: error,\n\t\t\t\t\t\tmessage: formatUnknownError(error),\n\t\t\t\t\t\treason: 'ssh-command-failed',\n\t\t\t\t\t});\n\t\toptions.report({\n\t\t\tobservedAtMs: now(),\n\t\t\tphase: 'failed',\n\t\t\tssh: {\n\t\t\t\tfailure: {\n\t\t\t\t\tkind: staleError.reason,\n\t\t\t\t\tmessage: staleError.message,\n\t\t\t\t},\n\t\t\t},\n\t\t});\n\t\tthrow staleError;\n\t} finally {\n\t\tif (timeoutHandle !== undefined) {\n\t\t\tclearTimeoutImpl(timeoutHandle);\n\t\t}\n\t}\n}\n","import {\n\tcreateToolVmActiveUseHandle,\n\ttype EndToolVmActiveUseRequest,\n\ttype HeartbeatToolVmActiveUseResponse,\n\ttype StartToolVmActiveUseRequest,\n\ttype StartToolVmActiveUseResponse,\n\ttype ToolVmActiveUseCorrelation,\n\ttype ToolVmActiveUseHandle,\n\ttype ToolVmActiveUseOutcome,\n\ttype ToolVmSshFailureKind,\n\tisToolVmSshLease,\n} from '@agent-vm/gateway-interface';\n\nimport {\n\tControllerLeaseRequestError,\n\tcreateLeaseClient,\n\ttype LeaseClient,\n\ttype OpenClawRuntimeStatusReport,\n} from '../controller-lease-client.js';\nimport {\n\tfindOpenClawGondolinSandboxMismatch,\n\tresolveOpenClawAgentIdFromSessionKey,\n\ttype OpenClawGondolinSandboxSnapshot,\n} from '../openclaw-gondolin-contract.js';\nimport { assertOpenClawToolVmPathIntent } from './openclaw-tool-vm-path-mapping.js';\nimport {\n\ttype CachedAgentLeaseEntry,\n\ttype CreateBackendDependencies,\n\ttype OpenClawFsBridgeLeaseContext,\n\ttype OpenClawSandboxBackendHandle,\n} from './sandbox-backend-contract.js';\nimport { buildShellScriptWithArgs } from './sandbox-shell-script.js';\nimport {\n\trunToolVmSshOperationWithGuard,\n\tToolVmSshOperationStaleError,\n} from './tool-vm-ssh-operation-guard.js';\n\nfunction agentLeaseCacheKey(params: { readonly agentId: string; readonly zoneId: string }): string {\n\treturn [params.zoneId, params.agentId].join('\\0');\n}\n\ntype CachedAgentLeaseCompatibility = Pick<\n\tCachedAgentLeaseEntry,\n\t'agentWorkspaceDir' | 'leaseWorkMountDir' | 'profileId'\n>;\n\nfunction findCachedLeaseCompatibilityMismatch(params: {\n\treadonly cachedEntry: CachedAgentLeaseCompatibility;\n\treadonly requestedEntry: CachedAgentLeaseCompatibility;\n}): string | undefined {\n\tif (params.cachedEntry.agentWorkspaceDir !== params.requestedEntry.agentWorkspaceDir) {\n\t\treturn 'agentWorkspaceDir';\n\t}\n\tif (params.cachedEntry.leaseWorkMountDir !== params.requestedEntry.leaseWorkMountDir) {\n\t\treturn 'leaseWorkMountDir';\n\t}\n\tif (params.cachedEntry.profileId !== params.requestedEntry.profileId) {\n\t\treturn 'profileId';\n\t}\n\treturn undefined;\n}\n\nfunction assertCachedLeaseCompatible(params: {\n\treadonly agentId: string;\n\treadonly cachedEntry: CachedAgentLeaseCompatibility;\n\treadonly requestedEntry: CachedAgentLeaseCompatibility;\n\treadonly zoneId: string;\n}): void {\n\tconst mismatch = findCachedLeaseCompatibilityMismatch(params);\n\tif (mismatch === undefined) {\n\t\treturn;\n\t}\n\tthrow new Error(\n\t\t`Cannot reuse cached Tool VM lease for zone '${params.zoneId}' agent '${params.agentId}': ${mismatch} changed.`,\n\t);\n}\n\nfunction formatControllerLeaseRequestError(error: ControllerLeaseRequestError): string {\n\tconst responseBody =\n\t\terror.responseBody === undefined ? error.bodyText : JSON.stringify(error.responseBody);\n\treturn `${error.message}; response=${responseBody}`;\n}\n\nfunction formatUnknownError(error: unknown): string {\n\tif (error instanceof ControllerLeaseRequestError) {\n\t\treturn formatControllerLeaseRequestError(error);\n\t}\n\treturn error instanceof Error ? error.message : String(error);\n}\n\nfunction writeSandboxBackendLog(message: string): void {\n\tprocess.stderr.write(`[openclaw-agent-vm-plugin] ${message}\\n`);\n}\n\nfunction shouldRefreshCachedLease(error: unknown): boolean {\n\treturn isRefreshableLeaseError(error);\n}\n\nfunction isRefreshableLeaseError(error: unknown): boolean {\n\treturn (\n\t\terror instanceof ControllerLeaseRequestError && (error.status === 404 || error.status === 410)\n\t);\n}\n\nfunction isCleanupNotFound(error: unknown): boolean {\n\treturn error instanceof ControllerLeaseRequestError && error.status === 404;\n}\n\ninterface DisposableFinalizeToken {\n\tdispose(): Promise<void>;\n}\n\ninterface ActiveUseFinalizeToken {\n\treadonly activeUseHandle: ToolVmActiveUseHandle;\n\treadonly innerToken?: unknown;\n}\n\nfunction isDisposableFinalizeToken(value: unknown): value is DisposableFinalizeToken {\n\treturn (\n\t\ttypeof value === 'object' &&\n\t\tvalue !== null &&\n\t\t'dispose' in value &&\n\t\ttypeof Reflect.get(value, 'dispose') === 'function'\n\t);\n}\n\nfunction isActiveUseFinalizeToken(value: unknown): value is ActiveUseFinalizeToken {\n\treturn (\n\t\ttypeof value === 'object' &&\n\t\tvalue !== null &&\n\t\t'activeUseHandle' in value &&\n\t\ttypeof Reflect.get(value, 'activeUseHandle') === 'object'\n\t);\n}\n\nfunction activeUseOutcomeForFinalizeParams(finalizeParams: {\n\treadonly status: 'completed' | 'failed';\n\treadonly timedOut: boolean;\n}): ToolVmActiveUseOutcome {\n\treturn finalizeParams.timedOut\n\t\t? 'timed-out'\n\t\t: finalizeParams.status === 'completed'\n\t\t\t? 'completed'\n\t\t\t: 'failed';\n}\n\nfunction mergedAbortSignal(\n\tfirstSignal: AbortSignal | undefined,\n\tsecondSignal: AbortSignal,\n): AbortSignal {\n\tif (firstSignal === undefined) {\n\t\treturn secondSignal;\n\t}\n\treturn AbortSignal.any([firstSignal, secondSignal]);\n}\n\nfunction mergedAbortSignals(\n\tsignals: readonly (AbortSignal | undefined)[],\n): AbortSignal | undefined {\n\tconst presentSignals = signals.filter((signal): signal is AbortSignal => signal !== undefined);\n\tif (presentSignals.length === 0) {\n\t\treturn undefined;\n\t}\n\tif (presentSignals.length === 1) {\n\t\treturn presentSignals[0];\n\t}\n\treturn AbortSignal.any(presentSignals);\n}\n\nfunction resolveLeaseRequestAgentId(sessionKey: string): string {\n\treturn resolveOpenClawAgentIdFromSessionKey(sessionKey);\n}\n\nfunction assertPluginLeaseContract(params: {\n\treadonly cfg: OpenClawGondolinSandboxSnapshot;\n}): void {\n\tconst mismatch = findOpenClawGondolinSandboxMismatch(params.cfg);\n\tif (mismatch) {\n\t\tthrow new Error(\n\t\t\t`OpenClaw Gondolin sandbox requires ${mismatch.key}=${mismatch.expectedValue}; received ${String(params.cfg[mismatch.key])}.`,\n\t\t);\n\t}\n}\n\nexport function createGondolinSandboxBackendFactory(\n\toptions: {\n\t\treadonly controllerUrl: string;\n\t\treadonly openClawRuntimeStatusProvider?: () => OpenClawRuntimeStatusReport | undefined;\n\t\treadonly profileId?: string;\n\t\treadonly zoneId: string;\n\t},\n\tdependencies: CreateBackendDependencies,\n): (params: {\n\treadonly agentWorkspaceDir: string;\n\treadonly cfg: OpenClawGondolinSandboxSnapshot & {\n\t\treadonly docker?: {\n\t\t\treadonly env?: Record<string, string>;\n\t\t};\n\t};\n\t// OpenClaw SDK boundary input only. Agent-vm leases are keyed by agentId,\n\t// so this value is intentionally not read or forwarded to the controller.\n\treadonly scopeKey: string;\n\treadonly sessionKey: string;\n\treadonly workspaceDir: string;\n}) => Promise<OpenClawSandboxBackendHandle> {\n\tconst agentLeaseCache = new Map<string, CachedAgentLeaseEntry>();\n\tconst inFlightLeaseRequests = new Map<string, Promise<CachedAgentLeaseEntry>>();\n\n\treturn async (params) => {\n\t\tconst profileId = options.profileId ?? 'standard';\n\t\tconst agentId = resolveLeaseRequestAgentId(params.sessionKey);\n\t\tassertPluginLeaseContract({\n\t\t\tcfg: params.cfg,\n\t\t});\n\t\tconst pathIntent = assertOpenClawToolVmPathIntent({\n\t\t\tagentWorkspaceDir: params.agentWorkspaceDir,\n\t\t\tinputPath: params.workspaceDir,\n\t\t});\n\t\tconst cacheKey = agentLeaseCacheKey({\n\t\t\tagentId,\n\t\t\tzoneId: options.zoneId,\n\t\t});\n\t\tconst requestedCacheEntry = {\n\t\t\tagentWorkspaceDir: params.agentWorkspaceDir,\n\t\t\tleaseWorkMountDir: pathIntent.leaseWorkMountDir,\n\t\t\tprofileId,\n\t\t} satisfies CachedAgentLeaseCompatibility;\n\t\tconst leaseClient =\n\t\t\tdependencies.createLeaseClient?.({\n\t\t\t\tcontrollerUrl: options.controllerUrl,\n\t\t\t}) ?? createLeaseClient({ controllerUrl: options.controllerUrl });\n\t\tconst markLeaseStale = async (\n\t\t\tlease: CachedAgentLeaseEntry['lease'],\n\t\t\treason: ToolVmSshFailureKind,\n\t\t\terror: unknown,\n\t\t): Promise<void> => {\n\t\t\tagentLeaseCache.delete(cacheKey);\n\t\t\twriteSandboxBackendLog(\n\t\t\t\t`lease marked stale for zone '${options.zoneId}' agent '${agentId}' lease '${lease.leaseId}' reason '${reason}': ${formatUnknownError(error)}`,\n\t\t\t);\n\t\t\tawait leaseClient\n\t\t\t\t.releaseLease(lease.leaseId, { force: true })\n\t\t\t\t.catch((releaseError: unknown) => {\n\t\t\t\t\twriteSandboxBackendLog(\n\t\t\t\t\t\t`best-effort stale lease release failed for zone '${options.zoneId}' agent '${agentId}' lease '${lease.leaseId}': ${formatUnknownError(releaseError)}`,\n\t\t\t\t\t);\n\t\t\t\t});\n\t\t};\n\t\tconst cachedEntry = agentLeaseCache.get(cacheKey);\n\t\tlet lease: CachedAgentLeaseEntry['lease'] | undefined;\n\t\tif (cachedEntry) {\n\t\t\tassertCachedLeaseCompatible({\n\t\t\t\tagentId,\n\t\t\t\tcachedEntry,\n\t\t\t\trequestedEntry: requestedCacheEntry,\n\t\t\t\tzoneId: options.zoneId,\n\t\t\t});\n\t\t\ttry {\n\t\t\t\tconst renewedLease = await leaseClient.renewLease(cachedEntry.lease.leaseId);\n\t\t\t\tawait runToolVmSshOperationWithGuard({\n\t\t\t\t\toperation: async (signal) =>\n\t\t\t\t\t\tawait dependencies.runRemoteShellScript({\n\t\t\t\t\t\t\tallowFailure: false,\n\t\t\t\t\t\t\tscript: 'true',\n\t\t\t\t\t\t\tsignal,\n\t\t\t\t\t\t\tssh: renewedLease.ssh,\n\t\t\t\t\t\t}),\n\t\t\t\t\toperationName: 'cached-ssh-probe',\n\t\t\t\t\treport: () => {},\n\t\t\t\t\ttimeoutMs: 30_000,\n\t\t\t\t});\n\t\t\t\tlease = renewedLease;\n\t\t\t\tagentLeaseCache.set(cacheKey, { ...requestedCacheEntry, lease });\n\t\t\t} catch (error) {\n\t\t\t\twriteSandboxBackendLog(\n\t\t\t\t\t`lease renew failed for zone '${options.zoneId}' agent '${agentId}' lease '${cachedEntry.lease.leaseId}': ${formatUnknownError(error)}`,\n\t\t\t\t);\n\t\t\t\tif (error instanceof ToolVmSshOperationStaleError) {\n\t\t\t\t\tawait markLeaseStale(cachedEntry.lease, error.reason, error);\n\t\t\t\t} else if (shouldRefreshCachedLease(error)) {\n\t\t\t\t\tagentLeaseCache.delete(cacheKey);\n\t\t\t\t} else {\n\t\t\t\t\tthrow error;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (lease === undefined) {\n\t\t\tconst inFlightLeaseRequest = inFlightLeaseRequests.get(cacheKey);\n\t\t\tif (inFlightLeaseRequest !== undefined) {\n\t\t\t\tconst inFlightEntry = await inFlightLeaseRequest;\n\t\t\t\tassertCachedLeaseCompatible({\n\t\t\t\t\tagentId,\n\t\t\t\t\tcachedEntry: inFlightEntry,\n\t\t\t\t\trequestedEntry: requestedCacheEntry,\n\t\t\t\t\tzoneId: options.zoneId,\n\t\t\t\t});\n\t\t\t\tlease = inFlightEntry.lease;\n\t\t\t} else {\n\t\t\t\t// OpenClaw SDK still names the selected sandbox path `workspaceDir`.\n\t\t\t\t// agent-vm's controller calls the selected host source `workMountDir`.\n\t\t\t\tconst leaseRequestPromise = (async (): Promise<CachedAgentLeaseEntry> => {\n\t\t\t\t\tconst runtimeStatus = options.openClawRuntimeStatusProvider?.();\n\t\t\t\t\tif (runtimeStatus && leaseClient.publishOpenClawRuntimeStatus) {\n\t\t\t\t\t\tawait leaseClient.publishOpenClawRuntimeStatus(runtimeStatus);\n\t\t\t\t\t}\n\t\t\t\t\tconst leaseResponse = await leaseClient.requestLease({\n\t\t\t\t\t\tagentId,\n\t\t\t\t\t\tagentWorkspaceDir: params.agentWorkspaceDir,\n\t\t\t\t\t\tprofileId,\n\t\t\t\t\t\tsessionKey: params.sessionKey,\n\t\t\t\t\t\tworkMountDir: pathIntent.leaseWorkMountDir,\n\t\t\t\t\t\tzoneId: options.zoneId,\n\t\t\t\t\t});\n\t\t\t\t\tif (!isToolVmSshLease(leaseResponse)) {\n\t\t\t\t\t\tthrow new TypeError('Controller lease API returned an unexpected response.');\n\t\t\t\t\t}\n\t\t\t\t\treturn {\n\t\t\t\t\t\t...requestedCacheEntry,\n\t\t\t\t\t\tlease: leaseResponse,\n\t\t\t\t\t};\n\t\t\t\t})();\n\t\t\t\tinFlightLeaseRequests.set(cacheKey, leaseRequestPromise);\n\t\t\t\ttry {\n\t\t\t\t\tconst leaseEntry = await leaseRequestPromise;\n\t\t\t\t\tagentLeaseCache.set(cacheKey, leaseEntry);\n\t\t\t\t\tlease = leaseEntry.lease;\n\t\t\t\t} finally {\n\t\t\t\t\tif (inFlightLeaseRequests.get(cacheKey) === leaseRequestPromise) {\n\t\t\t\t\t\tinFlightLeaseRequests.delete(cacheKey);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tconst handle = createSandboxBackendHandle({\n\t\t\tcfg: params.cfg,\n\t\t\tcontrollerUrl: options.controllerUrl,\n\t\t\tcreateFsBridgeBuilder: dependencies.createFsBridgeBuilder,\n\t\t\teffectiveGuestCwd: pathIntent.effectiveGuestCwd,\n\t\t\tlease,\n\t\t\tleaseClient,\n\t\t\tmarkCachedLeaseStale: async (reason, error) => {\n\t\t\t\tawait markLeaseStale(lease, reason, error);\n\t\t\t},\n\t\t\trunRemoteShellScript: dependencies.runRemoteShellScript,\n\t\t\tbuildExecSpec: dependencies.buildExecSpec,\n\t\t\tsessionKey: params.sessionKey,\n\t\t\tzoneId: options.zoneId,\n\t\t});\n\t\treturn handle;\n\t};\n}\n\nfunction createSandboxBackendHandle(options: {\n\treadonly buildExecSpec: CreateBackendDependencies['buildExecSpec'];\n\treadonly cfg: {\n\t\treadonly docker?: {\n\t\t\treadonly env?: Record<string, string>;\n\t\t};\n\t};\n\treadonly controllerUrl: string;\n\treadonly createFsBridgeBuilder?: CreateBackendDependencies['createFsBridgeBuilder'];\n\treadonly effectiveGuestCwd: string;\n\treadonly lease: CachedAgentLeaseEntry['lease'];\n\treadonly leaseClient: LeaseClient;\n\treadonly markCachedLeaseStale: (reason: ToolVmSshFailureKind, error: unknown) => Promise<void>;\n\treadonly runRemoteShellScript: CreateBackendDependencies['runRemoteShellScript'];\n\treadonly sessionKey: string;\n\treadonly zoneId: string;\n}): OpenClawSandboxBackendHandle {\n\tconst createActiveUseHandle = async (\n\t\tcorrelation: ToolVmActiveUseCorrelation,\n\t): Promise<ToolVmActiveUseHandle> => {\n\t\ttry {\n\t\t\treturn await createToolVmActiveUseHandle({\n\t\t\t\tcorrelation,\n\t\t\t\tendActiveUse: async (useId: string, request: EndToolVmActiveUseRequest): Promise<void> => {\n\t\t\t\t\tawait options.leaseClient.endActiveUse(options.lease.leaseId, useId, request);\n\t\t\t\t},\n\t\t\t\theartbeatActiveUse: async (useId, request): Promise<HeartbeatToolVmActiveUseResponse> =>\n\t\t\t\t\tawait options.leaseClient.heartbeatActiveUse(options.lease.leaseId, useId, request),\n\t\t\t\tisEndErrorTolerable: isCleanupNotFound,\n\t\t\t\tisHeartbeatErrorRefreshable: isRefreshableLeaseError,\n\t\t\t\tlogEndFailure: (error: unknown): void => {\n\t\t\t\t\twriteSandboxBackendLog(\n\t\t\t\t\t\t`active-use cleanup ignored for zone '${options.zoneId}' lease '${options.lease.leaseId}': ${formatUnknownError(error)}`,\n\t\t\t\t\t);\n\t\t\t\t},\n\t\t\t\tlogHeartbeatFailure: (error: unknown): void => {\n\t\t\t\t\twriteSandboxBackendLog(\n\t\t\t\t\t\t`active-use heartbeat failed for zone '${options.zoneId}' lease '${options.lease.leaseId}': ${formatUnknownError(error)}`,\n\t\t\t\t\t);\n\t\t\t\t},\n\t\t\t\tonRefreshableHeartbeatFailure: async (error): Promise<void> => {\n\t\t\t\t\tawait options.markCachedLeaseStale('active-use-refreshable-failure', error);\n\t\t\t\t},\n\t\t\t\tstartActiveUse: async (\n\t\t\t\t\trequest: StartToolVmActiveUseRequest,\n\t\t\t\t): Promise<StartToolVmActiveUseResponse> =>\n\t\t\t\t\tawait options.leaseClient.startActiveUse(options.lease.leaseId, request),\n\t\t\t});\n\t\t} catch (error) {\n\t\t\tif (isRefreshableLeaseError(error)) {\n\t\t\t\tawait options.markCachedLeaseStale('active-use-refreshable-failure', error);\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\t};\n\n\tconst runWithActiveUse = async <TResult>(\n\t\tcorrelation: ToolVmActiveUseCorrelation,\n\t\tfn: (activeUseHandle: ToolVmActiveUseHandle) => Promise<TResult>,\n\t): Promise<TResult> => {\n\t\tconst activeUseHandle = await createActiveUseHandle(correlation);\n\t\ttry {\n\t\t\tconst result = await fn(activeUseHandle);\n\t\t\tawait activeUseHandle.dispose('completed');\n\t\t\treturn result;\n\t\t} catch (error) {\n\t\t\tawait activeUseHandle\n\t\t\t\t.dispose(\n\t\t\t\t\terror instanceof ToolVmSshOperationStaleError && error.reason === 'ssh-command-timed-out'\n\t\t\t\t\t\t? 'timed-out'\n\t\t\t\t\t\t: 'failed',\n\t\t\t\t)\n\t\t\t\t.catch((cleanupError: unknown) => {\n\t\t\t\t\twriteSandboxBackendLog(\n\t\t\t\t\t\t`failed to end active use after operation failure for zone '${options.zoneId}' lease '${options.lease.leaseId}': ${formatUnknownError(cleanupError)}`,\n\t\t\t\t\t);\n\t\t\t\t});\n\t\t\tif (error instanceof ToolVmSshOperationStaleError) {\n\t\t\t\tawait options.markCachedLeaseStale(error.reason, error);\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\t};\n\n\tconst boundRunRemoteShellScript: OpenClawFsBridgeLeaseContext['runRemoteShellScript'] = async (\n\t\tshellParams,\n\t) =>\n\t\tawait runWithActiveUse(\n\t\t\t{\n\t\t\t\tsessionKey: options.sessionKey,\n\t\t\t\ttoolName: 'fs-bridge',\n\t\t\t},\n\t\t\tasync (activeUseHandle) =>\n\t\t\t\tawait runToolVmSshOperationWithGuard({\n\t\t\t\t\toperation: async (signal) => {\n\t\t\t\t\t\tconst operationSignal = mergedAbortSignals([\n\t\t\t\t\t\t\tshellParams.signal,\n\t\t\t\t\t\t\tactiveUseHandle.signal,\n\t\t\t\t\t\t\tsignal,\n\t\t\t\t\t\t]);\n\t\t\t\t\t\treturn await options.runRemoteShellScript({\n\t\t\t\t\t\t\t...(shellParams.allowFailure !== undefined\n\t\t\t\t\t\t\t\t? { allowFailure: shellParams.allowFailure }\n\t\t\t\t\t\t\t\t: {}),\n\t\t\t\t\t\t\tscript: buildShellScriptWithArgs(shellParams.script, shellParams.args),\n\t\t\t\t\t\t\t...(operationSignal === undefined ? {} : { signal: operationSignal }),\n\t\t\t\t\t\t\tssh: options.lease.ssh,\n\t\t\t\t\t\t\t...(shellParams.stdin !== undefined ? { stdin: shellParams.stdin } : {}),\n\t\t\t\t\t\t});\n\t\t\t\t\t},\n\t\t\t\t\toperationName: 'fs-bridge',\n\t\t\t\t\treport: (report) => {\n\t\t\t\t\t\tactiveUseHandle.report(report);\n\t\t\t\t\t},\n\t\t\t\t\ttimeoutMs: 30_000,\n\t\t\t\t}),\n\t\t);\n\n\tconst disposeInnerFinalizeToken = async (token: unknown): Promise<void> => {\n\t\tif (isDisposableFinalizeToken(token)) {\n\t\t\tawait token.dispose();\n\t\t}\n\t};\n\n\tconst endActiveUseFinalizeToken = async (\n\t\ttoken: ActiveUseFinalizeToken,\n\t\toutcome: ToolVmActiveUseOutcome,\n\t): Promise<void> => {\n\t\tlet innerError: unknown;\n\t\ttry {\n\t\t\tawait disposeInnerFinalizeToken(token.innerToken);\n\t\t} catch (error) {\n\t\t\tinnerError = error;\n\t\t}\n\t\tlet activeUseError: unknown;\n\t\ttry {\n\t\t\tawait token.activeUseHandle.dispose(outcome);\n\t\t} catch (error) {\n\t\t\tactiveUseError = error;\n\t\t}\n\t\tif (innerError) {\n\t\t\tthrow innerError;\n\t\t}\n\t\tif (activeUseError) {\n\t\t\tthrow activeUseError;\n\t\t}\n\t};\n\n\tconst createFsBridge = options.createFsBridgeBuilder?.({\n\t\tremoteAgentWorkspaceDir: options.lease.workdir,\n\t\tremoteWorkspaceDir: options.effectiveGuestCwd,\n\t\trunRemoteShellScript: boundRunRemoteShellScript,\n\t});\n\n\treturn {\n\t\t...(createFsBridge ? { createFsBridge } : {}),\n\t\t...(options.cfg.docker?.env ? { env: options.cfg.docker.env } : {}),\n\t\tconfigLabel: `${options.controllerUrl} (${options.zoneId})`,\n\t\tconfigLabelKind: 'VM',\n\t\tid: 'gondolin',\n\t\truntimeId: options.lease.leaseId,\n\t\truntimeLabel: options.lease.leaseId,\n\t\tworkdir: options.effectiveGuestCwd,\n\t\tbuildExecSpec: async (execParams) => {\n\t\t\tconst activeUseHandle = await createActiveUseHandle({\n\t\t\t\tsessionKey: options.sessionKey,\n\t\t\t\ttoolName: 'shell',\n\t\t\t});\n\t\t\ttry {\n\t\t\t\tconst execSpec = await options.buildExecSpec({\n\t\t\t\t\tcommand: execParams.command,\n\t\t\t\t\tenv: execParams.env,\n\t\t\t\t\tssh: options.lease.ssh,\n\t\t\t\t\tusePty: execParams.usePty,\n\t\t\t\t\tworkdir: execParams.workdir ?? options.effectiveGuestCwd,\n\t\t\t\t});\n\t\t\t\treturn {\n\t\t\t\t\t...execSpec,\n\t\t\t\t\tfinalizeToken: {\n\t\t\t\t\t\tactiveUseHandle,\n\t\t\t\t\t\t...(execSpec.finalizeToken !== undefined ? { innerToken: execSpec.finalizeToken } : {}),\n\t\t\t\t\t} satisfies ActiveUseFinalizeToken,\n\t\t\t\t};\n\t\t\t} catch (error) {\n\t\t\t\tawait activeUseHandle.dispose('failed').catch((cleanupError: unknown) => {\n\t\t\t\t\twriteSandboxBackendLog(\n\t\t\t\t\t\t`failed to end active use after buildExecSpec failure for zone '${options.zoneId}' lease '${options.lease.leaseId}': ${formatUnknownError(cleanupError)}`,\n\t\t\t\t\t);\n\t\t\t\t});\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t},\n\t\tfinalizeExec: async (finalizeParams) => {\n\t\t\tif (isActiveUseFinalizeToken(finalizeParams.token)) {\n\t\t\t\tif (finalizeParams.timedOut) {\n\t\t\t\t\tfinalizeParams.token.activeUseHandle.report({\n\t\t\t\t\t\tobservedAtMs: Date.now(),\n\t\t\t\t\t\tphase: 'failed',\n\t\t\t\t\t\tssh: {\n\t\t\t\t\t\t\tfailure: {\n\t\t\t\t\t\t\t\tkind: 'ssh-command-timed-out',\n\t\t\t\t\t\t\t\tmessage: 'exec command timed out.',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tawait endActiveUseFinalizeToken(\n\t\t\t\t\tfinalizeParams.token,\n\t\t\t\t\tactiveUseOutcomeForFinalizeParams(finalizeParams),\n\t\t\t\t);\n\t\t\t\tif (finalizeParams.timedOut) {\n\t\t\t\t\tawait options.markCachedLeaseStale('ssh-command-timed-out', undefined);\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tawait disposeInnerFinalizeToken(finalizeParams.token);\n\t\t},\n\t\trunShellCommand: async (commandParams) =>\n\t\t\tawait runWithActiveUse(\n\t\t\t\t{\n\t\t\t\t\tsessionKey: options.sessionKey,\n\t\t\t\t\ttoolName: 'runShellCommand',\n\t\t\t\t},\n\t\t\t\tasync (activeUseHandle) =>\n\t\t\t\t\tawait runToolVmSshOperationWithGuard({\n\t\t\t\t\t\toperation: async (signal) =>\n\t\t\t\t\t\t\tawait options.runRemoteShellScript({\n\t\t\t\t\t\t\t\tscript: commandParams.script,\n\t\t\t\t\t\t\t\tsignal: mergedAbortSignal(activeUseHandle.signal, signal),\n\t\t\t\t\t\t\t\tssh: options.lease.ssh,\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\toperationName: 'runShellCommand',\n\t\t\t\t\t\treport: (report) => {\n\t\t\t\t\t\t\tactiveUseHandle.report(report);\n\t\t\t\t\t\t},\n\t\t\t\t\t\ttimeoutMs: 30_000,\n\t\t\t\t\t}),\n\t\t\t),\n\t} satisfies OpenClawSandboxBackendHandle;\n}\n","import { ControllerLeaseRequestError, createLeaseClient } from '../controller-lease-client.js';\nimport type { CreateBackendDependencies } from './sandbox-backend-contract.js';\n\nexport function createGondolinSandboxBackendManager(\n\toptions: {\n\t\treadonly controllerUrl: string;\n\t\treadonly zoneId: string;\n\t},\n\tdependencies: CreateBackendDependencies,\n): {\n\tdescribeRuntime: (params: {\n\t\treadonly entry: { readonly containerName: string };\n\t}) => Promise<{ readonly configLabelMatch: boolean; readonly running: boolean }>;\n\tremoveRuntime: (params: { readonly entry: { readonly containerName: string } }) => Promise<void>;\n} {\n\treturn {\n\t\tdescribeRuntime: async (params) => {\n\t\t\tconst leaseClient =\n\t\t\t\tdependencies.createLeaseClient?.({\n\t\t\t\t\tcontrollerUrl: options.controllerUrl,\n\t\t\t\t}) ?? createLeaseClient({ controllerUrl: options.controllerUrl });\n\t\t\ttry {\n\t\t\t\tconst leaseStatus = await leaseClient.peekLease(params.entry.containerName);\n\t\t\t\treturn { configLabelMatch: true, running: leaseStatus !== null };\n\t\t\t} catch (error) {\n\t\t\t\tif (!(error instanceof ControllerLeaseRequestError) || error.status !== 404) {\n\t\t\t\t\tthrow error;\n\t\t\t\t}\n\t\t\t\treturn { configLabelMatch: false, running: false };\n\t\t\t}\n\t\t},\n\t\tremoveRuntime: async (params) => {\n\t\t\tconst leaseClient =\n\t\t\t\tdependencies.createLeaseClient?.({\n\t\t\t\t\tcontrollerUrl: options.controllerUrl,\n\t\t\t\t}) ?? createLeaseClient({ controllerUrl: options.controllerUrl });\n\t\t\tawait leaseClient.releaseLease(params.entry.containerName, { force: true });\n\t\t},\n\t};\n}\n","export interface ResolvedGondolinPluginConfig {\n\treadonly controllerUrl: string;\n\treadonly profileId?: string;\n\treadonly zoneGitToken?: string;\n\treadonly zoneGitTokenEnv?: string;\n\treadonly zoneId: string;\n}\n\nexport function resolveGondolinPluginConfig(\n\tconfig: Record<string, unknown>,\n): ResolvedGondolinPluginConfig {\n\tif (typeof config.controllerUrl !== 'string' || typeof config.zoneId !== 'string') {\n\t\tthrow new Error('Gondolin plugin config requires controllerUrl and zoneId.');\n\t}\n\n\treturn {\n\t\tcontrollerUrl: config.controllerUrl,\n\t\t...(typeof config.profileId === 'string' ? { profileId: config.profileId } : {}),\n\t\t...(typeof config.zoneGitToken === 'string' ? { zoneGitToken: config.zoneGitToken } : {}),\n\t\t...(typeof config.zoneGitTokenEnv === 'string'\n\t\t\t? { zoneGitTokenEnv: config.zoneGitTokenEnv }\n\t\t\t: {}),\n\t\tzoneId: config.zoneId,\n\t};\n}\n","import type { SshHelpers, SshSandboxSession } from './openclaw-sandbox-sdk-contract.js';\nimport type {\n\tCreateBackendDependencies,\n\tOpenClawFsBridgeLeaseContext,\n\tOpenClawSandboxFsBridge,\n} from './sandbox-backend-factory.js';\n\nexport const OPENCLAW_SSH_SESSION_SCRATCH_ROOT = '/work';\n\nexport function createBackendDeps(ssh: SshHelpers): {\n\treadonly buildExecSpec: CreateBackendDependencies['buildExecSpec'];\n\treadonly createFsBridgeBuilder: (\n\t\tleaseContext: OpenClawFsBridgeLeaseContext,\n\t) => (params: { readonly sandbox: unknown }) => OpenClawSandboxFsBridge;\n\treadonly runRemoteShellScript: CreateBackendDependencies['runRemoteShellScript'];\n} {\n\treturn {\n\t\tbuildExecSpec: async ({ command, env, ssh: sshCreds, usePty, workdir }) => {\n\t\t\tconst session = await ssh.createSshSandboxSessionFromSettings({\n\t\t\t\tcommand: 'ssh',\n\t\t\t\tidentityData: sshCreds.identityPem,\n\t\t\t\tstrictHostKeyChecking: false,\n\t\t\t\ttarget: `${sshCreds.user}@${sshCreds.host}:${sshCreds.port}`,\n\t\t\t\tupdateHostKeys: false,\n\t\t\t\tworkspaceRoot: OPENCLAW_SSH_SESSION_SCRATCH_ROOT,\n\t\t\t});\n\t\t\tconst disposeSshSandboxSession = ssh.disposeSshSandboxSession;\n\t\t\treturn {\n\t\t\t\targv: ssh.buildSshSandboxArgv({\n\t\t\t\t\tremoteCommand: ssh.buildExecRemoteCommand({\n\t\t\t\t\t\tcommand,\n\t\t\t\t\t\tenv,\n\t\t\t\t\t\tworkdir,\n\t\t\t\t\t}),\n\t\t\t\t\tsession,\n\t\t\t\t\ttty: usePty,\n\t\t\t\t}),\n\t\t\t\tenv: ssh.sanitizeEnvVars(process.env).allowed,\n\t\t\t\tfinalizeToken: {\n\t\t\t\t\tdispose: async (): Promise<void> => {\n\t\t\t\t\t\tif (disposeSshSandboxSession) {\n\t\t\t\t\t\t\tawait disposeSshSandboxSession(session);\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\tsession,\n\t\t\t\t},\n\t\t\t\tstdinMode: 'pipe-open' as const,\n\t\t\t};\n\t\t},\n\t\tcreateFsBridgeBuilder:\n\t\t\t(leaseContext: OpenClawFsBridgeLeaseContext) =>\n\t\t\t(params: { readonly sandbox: unknown }): OpenClawSandboxFsBridge =>\n\t\t\t\tssh.createRemoteShellSandboxFsBridge({\n\t\t\t\t\tsandbox: params.sandbox,\n\t\t\t\t\truntime: {\n\t\t\t\t\t\tremoteAgentWorkspaceDir: leaseContext.remoteAgentWorkspaceDir,\n\t\t\t\t\t\tremoteWorkspaceDir: leaseContext.remoteWorkspaceDir,\n\t\t\t\t\t\trunRemoteShellScript: leaseContext.runRemoteShellScript,\n\t\t\t\t\t},\n\t\t\t\t}),\n\t\trunRemoteShellScript: async ({ allowFailure, script, signal, ssh: sshCreds, stdin }) => {\n\t\t\tconst session = await ssh.createSshSandboxSessionFromSettings({\n\t\t\t\tcommand: 'ssh',\n\t\t\t\tidentityData: sshCreds.identityPem,\n\t\t\t\tstrictHostKeyChecking: false,\n\t\t\t\ttarget: `${sshCreds.user}@${sshCreds.host}:${sshCreds.port}`,\n\t\t\t\tupdateHostKeys: false,\n\t\t\t\tworkspaceRoot: OPENCLAW_SSH_SESSION_SCRATCH_ROOT,\n\t\t\t});\n\t\t\treturn await ssh.runSshSandboxCommand({\n\t\t\t\t...(allowFailure !== undefined ? { allowFailure } : {}),\n\t\t\t\tremoteCommand: ssh.buildRemoteCommand(['/bin/sh', '-c', script, 'gondolin-sandbox-fs']),\n\t\t\t\tsession,\n\t\t\t\t...(signal !== undefined ? { signal } : {}),\n\t\t\t\t...(stdin !== undefined ? { stdin } : {}),\n\t\t\t});\n\t\t},\n\t};\n}\n\nexport type { SshHelpers, SshSandboxSession };\n","import {\n\teffectiveOpenClawGondolinSandboxValue,\n\tformatOpenClawGondolinRequirementFieldPath,\n\tformatOpenClawGondolinRequirementFindingId,\n\tformatOpenClawGondolinRequirementHint,\n\tOPENCLAW_GONDOLIN_SANDBOX_REQUIREMENTS,\n\ttype OpenClawGondolinAgentConfig,\n} from './openclaw-gondolin-contract.js';\n\ninterface OpenClawRuntimeConfig {\n\treadonly [key: string]: unknown;\n\treadonly agents?: {\n\t\treadonly defaults?: OpenClawGondolinAgentConfig;\n\t\treadonly list?: readonly unknown[];\n\t};\n}\n\nexport interface OpenClawRuntimeRequirementFinding {\n\treadonly hint: string;\n\treadonly id: string;\n\treadonly ok: boolean;\n}\n\nexport interface OpenClawRuntimeStatusReport {\n\treadonly findings: readonly OpenClawRuntimeRequirementFinding[];\n\treadonly pluginId: 'gondolin';\n\treadonly zoneId: string;\n}\n\nfunction isObjectRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction readAgentConfigEntries(config: OpenClawRuntimeConfig): readonly {\n\treadonly config: OpenClawGondolinAgentConfig;\n\treadonly label: string;\n}[] {\n\tconst defaultConfig = config.agents?.defaults ?? {};\n\tconst agentConfigs = (config.agents?.list ?? [])\n\t\t.filter(isObjectRecord)\n\t\t.map((agentConfig, agentIndex) => ({\n\t\t\tconfig: agentConfig,\n\t\t\tlabel:\n\t\t\t\ttypeof agentConfig.id === 'string'\n\t\t\t\t\t? `agent-${agentConfig.id}`\n\t\t\t\t\t: `agent-${String(agentIndex)}`,\n\t\t}));\n\treturn [{ config: defaultConfig, label: 'defaults' }, ...agentConfigs];\n}\n\nfunction effectiveWorkspace(\n\tdefaults: OpenClawGondolinAgentConfig,\n\tagentConfig: OpenClawGondolinAgentConfig,\n): unknown {\n\treturn agentConfig.workspace ?? defaults.workspace;\n}\n\nfunction requirementFinding(options: {\n\treadonly actualValue: unknown;\n\treadonly expectedValue: string;\n\treadonly fieldPath: string;\n\treadonly label: string;\n\treadonly zoneId: string;\n}): OpenClawRuntimeRequirementFinding {\n\tconst ok = options.actualValue === options.expectedValue;\n\treturn {\n\t\tid: formatOpenClawGondolinRequirementFindingId({\n\t\t\tfieldPath: options.fieldPath,\n\t\t\tlabel: options.label,\n\t\t\tzoneId: options.zoneId,\n\t\t}),\n\t\tok,\n\t\thint: formatOpenClawGondolinRequirementHint({\n\t\t\texpectedValue: options.expectedValue,\n\t\t\tfieldPath: options.fieldPath,\n\t\t\tok,\n\t\t}),\n\t};\n}\n\nexport function buildOpenClawRuntimeStatusReport(options: {\n\treadonly config: Record<string, unknown>;\n\treadonly zoneId: string;\n}): OpenClawRuntimeStatusReport {\n\tconst config: OpenClawRuntimeConfig = options.config;\n\tconst defaults = config.agents?.defaults ?? {};\n\treturn {\n\t\tpluginId: 'gondolin',\n\t\tzoneId: options.zoneId,\n\t\tfindings: readAgentConfigEntries(config).flatMap(({ config: agentConfig, label }) => {\n\t\t\tconst workspace = effectiveWorkspace(defaults, agentConfig);\n\t\t\tconst requirementFindings = OPENCLAW_GONDOLIN_SANDBOX_REQUIREMENTS.map((requirement) =>\n\t\t\t\trequirementFinding({\n\t\t\t\t\tactualValue: effectiveOpenClawGondolinSandboxValue(\n\t\t\t\t\t\tdefaults,\n\t\t\t\t\t\tagentConfig,\n\t\t\t\t\t\trequirement.key,\n\t\t\t\t\t),\n\t\t\t\t\texpectedValue: requirement.expectedValue,\n\t\t\t\t\tfieldPath: formatOpenClawGondolinRequirementFieldPath(label, requirement.key),\n\t\t\t\t\tlabel,\n\t\t\t\t\tzoneId: options.zoneId,\n\t\t\t\t}),\n\t\t\t);\n\t\t\tconst workspaceFinding = {\n\t\t\t\tid: `openclaw-tool-vm-workspace-${options.zoneId}-${label}`,\n\t\t\t\tok: workspace !== '/zone',\n\t\t\t\thint:\n\t\t\t\t\tworkspace === '/zone'\n\t\t\t\t\t\t? 'Use /zone/agents/default or per-agent workspaces; keep /zone for shared zone files.'\n\t\t\t\t\t\t: typeof workspace === 'string'\n\t\t\t\t\t\t\t? workspace\n\t\t\t\t\t\t\t: 'agents workspace is unset',\n\t\t\t} satisfies OpenClawRuntimeRequirementFinding;\n\t\t\treturn requirementFindings.concat(workspaceFinding);\n\t\t}),\n\t};\n}\n","export interface SshSandboxSession {\n\treadonly command: string;\n\treadonly configPath: string;\n\treadonly host: string;\n}\n\nexport interface SshHelpers {\n\treadonly buildExecRemoteCommand: (params: {\n\t\treadonly command: string;\n\t\treadonly env: Record<string, string>;\n\t\treadonly workdir?: string;\n\t}) => string;\n\treadonly buildRemoteCommand: (argv: readonly string[]) => string;\n\treadonly buildSshSandboxArgv: (params: {\n\t\treadonly remoteCommand: string;\n\t\treadonly session: SshSandboxSession;\n\t\treadonly tty?: boolean;\n\t}) => string[];\n\treadonly createRemoteShellSandboxFsBridge: (params: {\n\t\treadonly runtime: {\n\t\t\treadonly remoteAgentWorkspaceDir: string;\n\t\t\treadonly remoteWorkspaceDir: string;\n\t\t\treadonly runRemoteShellScript: (shellParams: {\n\t\t\t\treadonly allowFailure?: boolean;\n\t\t\t\treadonly args?: string[];\n\t\t\t\treadonly script: string;\n\t\t\t\treadonly signal?: AbortSignal;\n\t\t\t\treadonly stdin?: Buffer | string;\n\t\t\t}) => Promise<{\n\t\t\t\treadonly code: number;\n\t\t\t\treadonly stderr: Buffer;\n\t\t\t\treadonly stdout: Buffer;\n\t\t\t}>;\n\t\t};\n\t\treadonly sandbox: unknown;\n\t}) => import('./sandbox-backend-factory.js').OpenClawSandboxFsBridge;\n\treadonly createSshSandboxSessionFromSettings: (settings: {\n\t\treadonly command: string;\n\t\treadonly identityData?: string;\n\t\treadonly strictHostKeyChecking: boolean;\n\t\treadonly target: string;\n\t\treadonly updateHostKeys: boolean;\n\t\treadonly workspaceRoot: string;\n\t}) => Promise<SshSandboxSession>;\n\treadonly disposeSshSandboxSession?: (session: SshSandboxSession) => Promise<void>;\n\treadonly runSshSandboxCommand: (params: {\n\t\treadonly allowFailure?: boolean;\n\t\treadonly remoteCommand: string;\n\t\treadonly session: SshSandboxSession;\n\t\treadonly signal?: AbortSignal;\n\t\treadonly stdin?: Buffer | string;\n\t}) => Promise<{\n\t\treadonly code: number;\n\t\treadonly stderr: Buffer;\n\t\treadonly stdout: Buffer;\n\t}>;\n\treadonly sanitizeEnvVars: (env: NodeJS.ProcessEnv) => {\n\t\treadonly allowed: Record<string, string>;\n\t};\n}\n\nexport interface OpenClawToolRegistration {\n\treadonly description: string;\n\treadonly execute: (toolCallId: string, params: unknown) => Promise<OpenClawToolResult>;\n\treadonly name: string;\n\treadonly parameters: Record<string, unknown>;\n}\n\nexport interface OpenClawToolRegistrationOptions {\n\treadonly name?: string;\n\treadonly names?: readonly string[];\n\treadonly optional?: boolean;\n}\n\nexport interface OpenClawToolResult {\n\treadonly content: string;\n\treadonly details?: unknown;\n}\n\nexport interface OpenClawToolRegistrationApi {\n\treadonly registerTool?: (\n\t\ttool: OpenClawToolRegistration,\n\t\toptions?: OpenClawToolRegistrationOptions,\n\t) => void;\n}\n\nexport function assertSdkShape(value: unknown): asserts value is SshHelpers & {\n\tregisterSandboxBackend: (\n\t\tid: string,\n\t\tregistration: {\n\t\t\tfactory: ReturnType<\n\t\t\t\ttypeof import('./sandbox-backend-factory.js').createGondolinSandboxBackendFactory\n\t\t\t>;\n\t\t\tmanager?: ReturnType<\n\t\t\t\ttypeof import('./sandbox-backend-factory.js').createGondolinSandboxBackendManager\n\t\t\t>;\n\t\t},\n\t) => void;\n} {\n\tif (typeof value !== 'object' || value === null) {\n\t\tthrow new TypeError('OpenClaw SDK module is not an object');\n\t}\n\n\tfor (const exportName of [\n\t\t'buildExecRemoteCommand',\n\t\t'buildRemoteCommand',\n\t\t'buildSshSandboxArgv',\n\t\t'createRemoteShellSandboxFsBridge',\n\t\t'createSshSandboxSessionFromSettings',\n\t\t'runSshSandboxCommand',\n\t\t'sanitizeEnvVars',\n\t\t'registerSandboxBackend',\n\t] as const) {\n\t\tif (typeof (value as Record<string, unknown>)[exportName] !== 'function') {\n\t\t\tthrow new TypeError(`OpenClaw SDK missing required export: ${exportName}`);\n\t\t}\n\t}\n}\n","import type { OpenClawToolRegistrationApi } from './openclaw-sandbox-sdk-contract.js';\n\ntype RequiredOpenClawToolRegistrationApi = OpenClawToolRegistrationApi & {\n\treadonly registerTool: NonNullable<OpenClawToolRegistrationApi['registerTool']>;\n};\n\nexport interface RegisterZoneGitToolOptions {\n\treadonly api: RequiredOpenClawToolRegistrationApi;\n\treadonly controllerUrl: string;\n\treadonly fetchImpl?: typeof fetch;\n\treadonly zoneGitToken?: string;\n\treadonly zoneId: string;\n}\n\nconst zoneGitCapabilityHeader = 'x-agent-vm-zone-git-token';\n\nfunction readExpectedHead(input: unknown): string {\n\tif (typeof input !== 'object' || input === null || !('expectedHead' in input)) {\n\t\tthrow new Error('zone_git_push requires expectedHead.');\n\t}\n\tconst expectedHead = input.expectedHead;\n\tif (typeof expectedHead !== 'string' || expectedHead.length === 0) {\n\t\tthrow new Error('zone_git_push requires expectedHead.');\n\t}\n\treturn expectedHead;\n}\n\nfunction buildControllerUrl(controllerUrl: string, zoneId: string): string {\n\treturn `${controllerUrl.replace(/\\/$/u, '')}/zones/${encodeURIComponent(zoneId)}/zone-git/push`;\n}\n\nasync function readResponseText(response: Response): Promise<string> {\n\ttry {\n\t\treturn await response.text();\n\t} catch (error) {\n\t\treturn error instanceof Error ? error.message : String(error);\n\t}\n}\n\nfunction parseJsonPayload(responseText: string): unknown {\n\ttry {\n\t\treturn JSON.parse(responseText);\n\t} catch (error) {\n\t\tthrow new Error(`zone_git_push returned non-JSON response: ${responseText.slice(0, 500)}`, {\n\t\t\tcause: error,\n\t\t});\n\t}\n}\n\nexport function registerZoneGitTool(options: RegisterZoneGitToolOptions): void {\n\toptions.api.registerTool(\n\t\t{\n\t\t\tname: 'zone_git_push',\n\t\t\tdescription:\n\t\t\t\t'Push committed OpenClaw zone workspace changes through the agent-vm controller. Use after git commit; do not run raw git push.',\n\t\t\tparameters: {\n\t\t\t\ttype: 'object',\n\t\t\t\tadditionalProperties: false,\n\t\t\t\tproperties: {\n\t\t\t\t\texpectedHead: { type: 'string' },\n\t\t\t\t},\n\t\t\t\trequired: ['expectedHead'],\n\t\t\t},\n\t\t\texecute: async (_toolCallId: string, input: unknown) => {\n\t\t\t\tconst expectedHead = readExpectedHead(input);\n\t\t\t\tconst response = await (options.fetchImpl ?? fetch)(\n\t\t\t\t\tbuildControllerUrl(options.controllerUrl, options.zoneId),\n\t\t\t\t\t{\n\t\t\t\t\t\tbody: JSON.stringify({ expectedHead }),\n\t\t\t\t\t\theaders: {\n\t\t\t\t\t\t\t'content-type': 'application/json',\n\t\t\t\t\t\t\t...(options.zoneGitToken ? { [zoneGitCapabilityHeader]: options.zoneGitToken } : {}),\n\t\t\t\t\t\t},\n\t\t\t\t\t\tmethod: 'POST',\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t\tconst responseText = await readResponseText(response);\n\t\t\t\tif (!response.ok) {\n\t\t\t\t\tthrow new Error(`zone_git_push failed: ${response.status} ${responseText.slice(0, 500)}`);\n\t\t\t\t}\n\t\t\t\tconst payload = parseJsonPayload(responseText);\n\t\t\t\treturn {\n\t\t\t\t\tcontent: JSON.stringify(payload),\n\t\t\t\t\tdetails: payload,\n\t\t\t\t};\n\t\t\t},\n\t\t},\n\t\t{ name: 'zone_git_push', optional: true },\n\t);\n}\n","/* oxlint-disable eslint/no-await-in-loop -- runtime status publish retries must be sequential */\nimport { createLeaseClient } from './controller-lease-client.js';\nimport { resolveGondolinPluginConfig } from './gondolin-plugin-config.js';\nimport {\n\tOPENCLAW_SSH_SESSION_SCRATCH_ROOT,\n\tcreateBackendDeps,\n} from './openclaw-backend-dependencies.js';\nimport { buildOpenClawRuntimeStatusReport } from './openclaw-runtime-status.js';\nimport {\n\tassertSdkShape,\n\ttype OpenClawToolRegistrationApi,\n\ttype SshHelpers,\n\ttype SshSandboxSession,\n} from './openclaw-sandbox-sdk-contract.js';\nimport {\n\tcreateGondolinSandboxBackendFactory,\n\tcreateGondolinSandboxBackendManager,\n} from './sandbox-backend-factory.js';\nimport { registerZoneGitTool } from './zone-git-tool.js';\n\nconst runtimeStatusPublishMaxAttempts = 30;\nconst runtimeStatusPublishRetryDelayMs = 1_000;\n\nfunction sleep(ms: number): Promise<void> {\n\treturn new Promise((resolve) => {\n\t\tsetTimeout(resolve, ms);\n\t});\n}\n\nasync function publishRuntimeStatusWithRetry(options: {\n\treadonly controllerUrl: string;\n\treadonly report: ReturnType<typeof buildOpenClawRuntimeStatusReport>;\n}): Promise<void> {\n\tconst leaseClient = createLeaseClient({ controllerUrl: options.controllerUrl });\n\tfor (let attemptIndex = 0; attemptIndex < runtimeStatusPublishMaxAttempts; attemptIndex += 1) {\n\t\ttry {\n\t\t\tawait leaseClient.publishOpenClawRuntimeStatus?.(options.report);\n\t\t\treturn;\n\t\t} catch (error: unknown) {\n\t\t\tif (attemptIndex === runtimeStatusPublishMaxAttempts - 1) {\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t\tawait sleep(runtimeStatusPublishRetryDelayMs);\n\t\t}\n\t}\n}\n\nconst plugin = {\n\tid: 'gondolin',\n\tname: 'Gondolin VM Sandbox',\n\tdescription: 'Sandbox backend powered by Gondolin micro-VMs.',\n\n\tregister(api: {\n\t\treadonly config?: Record<string, unknown>;\n\t\treadonly pluginConfig: Record<string, unknown>;\n\t\treadonly registerTool?: OpenClawToolRegistrationApi['registerTool'];\n\t\treadonly registrationMode: string;\n\t\treadonly runtime?: {\n\t\t\treadonly config?: {\n\t\t\t\treadonly current?: () => Record<string, unknown>;\n\t\t\t};\n\t\t};\n\t}): void {\n\t\tconst registerTool = api.registerTool;\n\t\tif (typeof registerTool !== 'function') {\n\t\t\tif (api.registrationMode === 'full') {\n\t\t\t\tthrow new Error('Gondolin full registration requires OpenClaw registerTool.');\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t\tconst pluginConfig = resolveGondolinPluginConfig(api.pluginConfig);\n\t\tconst zoneGitToken =\n\t\t\tpluginConfig.zoneGitToken ??\n\t\t\t(pluginConfig.zoneGitTokenEnv ? process.env[pluginConfig.zoneGitTokenEnv] : undefined);\n\t\tregisterZoneGitTool({\n\t\t\tapi: { registerTool },\n\t\t\tcontrollerUrl: pluginConfig.controllerUrl,\n\t\t\t...(zoneGitToken ? { zoneGitToken } : {}),\n\t\t\tzoneId: pluginConfig.zoneId,\n\t\t});\n\t\tif (api.registrationMode !== 'full') {\n\t\t\treturn;\n\t\t}\n\t\tconst buildRuntimeStatus = ():\n\t\t\t| ReturnType<typeof buildOpenClawRuntimeStatusReport>\n\t\t\t| undefined => {\n\t\t\tconst runtimeConfig = api.runtime?.config?.current?.() ?? api.config;\n\t\t\treturn runtimeConfig\n\t\t\t\t? buildOpenClawRuntimeStatusReport({\n\t\t\t\t\t\tconfig: runtimeConfig,\n\t\t\t\t\t\tzoneId: pluginConfig.zoneId,\n\t\t\t\t\t})\n\t\t\t\t: undefined;\n\t\t};\n\t\tconst initialRuntimeStatus = buildRuntimeStatus();\n\t\tif (initialRuntimeStatus) {\n\t\t\tvoid publishRuntimeStatusWithRetry({\n\t\t\t\tcontrollerUrl: pluginConfig.controllerUrl,\n\t\t\t\treport: initialRuntimeStatus,\n\t\t\t}).catch((error: unknown) => {\n\t\t\t\tconst message = error instanceof Error ? error.message : JSON.stringify(error);\n\t\t\t\tprocess.stderr.write(`[gondolin] failed to publish OpenClaw runtime status: ${message}\\n`);\n\t\t\t});\n\t\t}\n\n\t\tconst sdkPath = '/opt/openclaw-sdk/sandbox.js';\n\t\tconst sdkPromise = import(sdkPath).then((sdkRaw: Record<string, unknown>) => {\n\t\t\tassertSdkShape(sdkRaw);\n\n\t\t\tconst sshHelpers: SshHelpers = {\n\t\t\t\tbuildExecRemoteCommand: sdkRaw.buildExecRemoteCommand,\n\t\t\t\tbuildRemoteCommand: sdkRaw.buildRemoteCommand,\n\t\t\t\tbuildSshSandboxArgv: sdkRaw.buildSshSandboxArgv,\n\t\t\t\tcreateRemoteShellSandboxFsBridge: sdkRaw.createRemoteShellSandboxFsBridge,\n\t\t\t\tcreateSshSandboxSessionFromSettings: sdkRaw.createSshSandboxSessionFromSettings,\n\t\t\t\t...(typeof sdkRaw.disposeSshSandboxSession === 'function'\n\t\t\t\t\t? {\n\t\t\t\t\t\t\tdisposeSshSandboxSession: sdkRaw.disposeSshSandboxSession as (\n\t\t\t\t\t\t\t\tsession: SshSandboxSession,\n\t\t\t\t\t\t\t) => Promise<void>,\n\t\t\t\t\t\t}\n\t\t\t\t\t: {}),\n\t\t\t\trunSshSandboxCommand: sdkRaw.runSshSandboxCommand,\n\t\t\t\tsanitizeEnvVars: sdkRaw.sanitizeEnvVars,\n\t\t\t};\n\n\t\t\tconst backendDependencies = createBackendDeps(sshHelpers);\n\t\t\tsdkRaw.registerSandboxBackend('gondolin', {\n\t\t\t\tfactory: createGondolinSandboxBackendFactory(\n\t\t\t\t\t{\n\t\t\t\t\t\t...pluginConfig,\n\t\t\t\t\t\topenClawRuntimeStatusProvider: buildRuntimeStatus,\n\t\t\t\t\t},\n\t\t\t\t\tbackendDependencies,\n\t\t\t\t),\n\t\t\t\tmanager: createGondolinSandboxBackendManager(pluginConfig, backendDependencies),\n\t\t\t});\n\t\t});\n\n\t\tsdkPromise.catch((error: unknown) => {\n\t\t\tconst message = error instanceof Error ? error.message : JSON.stringify(error);\n\t\t\tprocess.stderr.write(`[gondolin] failed to load OpenClaw SDK: ${message}\\n`);\n\t\t});\n\t},\n};\n\nexport default plugin;\n\nexport { OPENCLAW_SSH_SESSION_SCRATCH_ROOT, createBackendDeps };\nexport type { SshHelpers };\n","export * from './sandbox-backend-factory.js';\nexport * from './gondolin-plugin-config.js';\nexport * from './controller-lease-client.js';\nexport * from './openclaw-plugin-registration.js';\nexport * from './openclaw-gondolin-contract.js';\nexport { buildOpenClawRuntimeStatusReport } from './openclaw-runtime-status.js';\nexport { default } from './openclaw-plugin-registration.js';\n\nexport const OPENCLAW_GONDOLIN_PLUGIN_PACKAGE_NAME = '@agent-vm/openclaw-agent-vm-plugin';\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agent-vm/openclaw-agent-vm-plugin",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.82",
|
|
4
4
|
"description": "OpenClaw sandbox-backend plugin that delegates execution to a Gondolin-managed VM.",
|
|
5
5
|
"homepage": "https://github.com/ShravanSunder/agent-vm#readme",
|
|
6
6
|
"bugs": {
|
|
@@ -30,8 +30,8 @@
|
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
32
|
"zod": "^4.4.3",
|
|
33
|
-
"@agent-vm/
|
|
34
|
-
"@agent-vm/
|
|
33
|
+
"@agent-vm/gondolin-adapter": "0.0.82",
|
|
34
|
+
"@agent-vm/gateway-interface": "0.0.82"
|
|
35
35
|
},
|
|
36
36
|
"scripts": {
|
|
37
37
|
"build": "tsdown && cp openclaw.plugin.json sdk-validate.mjs dist/",
|