@agent-vm/openclaw-agent-vm-plugin 0.0.71 → 0.0.73
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 +27 -47
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +127 -101
- package/dist/index.js.map +1 -1
- package/package.json +3 -2
package/dist/index.d.ts
CHANGED
|
@@ -1,31 +1,6 @@
|
|
|
1
|
+
import { EndToolVmActiveUseRequest, HeartbeatToolVmActiveUseResponse, StartToolVmActiveUseRequest, StartToolVmActiveUseResponse, ToolVmLeasePeek, ToolVmSshLease } from "@agent-vm/gateway-interface";
|
|
2
|
+
|
|
1
3
|
//#region src/controller-lease-client.d.ts
|
|
2
|
-
interface GondolinLeaseResponse {
|
|
3
|
-
readonly idleTtlMs?: number;
|
|
4
|
-
readonly leaseId: string;
|
|
5
|
-
readonly ssh: {
|
|
6
|
-
readonly host: string;
|
|
7
|
-
readonly identityPem: string;
|
|
8
|
-
readonly knownHostsLine: string;
|
|
9
|
-
readonly port: number;
|
|
10
|
-
readonly user: string;
|
|
11
|
-
};
|
|
12
|
-
readonly tcpSlot: number;
|
|
13
|
-
readonly workdir: string;
|
|
14
|
-
}
|
|
15
|
-
interface LeasePeekResponse {
|
|
16
|
-
readonly createdAt: number;
|
|
17
|
-
readonly lastUsedAt: number;
|
|
18
|
-
readonly leaseId: string;
|
|
19
|
-
readonly profileId: string;
|
|
20
|
-
readonly scopeKey: string;
|
|
21
|
-
readonly ssh: {
|
|
22
|
-
readonly host: string;
|
|
23
|
-
readonly port: number;
|
|
24
|
-
readonly user: string;
|
|
25
|
-
};
|
|
26
|
-
readonly tcpSlot: number;
|
|
27
|
-
readonly zoneId: string;
|
|
28
|
-
}
|
|
29
4
|
interface OpenClawRuntimeStatusReport {
|
|
30
5
|
readonly findings: readonly {
|
|
31
6
|
readonly hint: string;
|
|
@@ -36,17 +11,22 @@ interface OpenClawRuntimeStatusReport {
|
|
|
36
11
|
readonly zoneId: string;
|
|
37
12
|
}
|
|
38
13
|
interface LeaseClient {
|
|
39
|
-
|
|
40
|
-
|
|
14
|
+
endActiveUse(leaseId: string, useId: string, request: EndToolVmActiveUseRequest): Promise<void>;
|
|
15
|
+
heartbeatActiveUse(leaseId: string, useId: string): Promise<HeartbeatToolVmActiveUseResponse>;
|
|
16
|
+
peekLease(leaseId: string): Promise<ToolVmLeasePeek>;
|
|
41
17
|
publishOpenClawRuntimeStatus?(report: OpenClawRuntimeStatusReport): Promise<void>;
|
|
42
|
-
releaseLease(leaseId: string
|
|
18
|
+
releaseLease(leaseId: string, options?: {
|
|
19
|
+
readonly force?: boolean;
|
|
20
|
+
}): Promise<void>;
|
|
21
|
+
renewLease(leaseId: string): Promise<ToolVmSshLease>;
|
|
43
22
|
requestLease(request: {
|
|
44
23
|
readonly agentWorkspaceDir: string;
|
|
45
24
|
readonly profileId: string;
|
|
46
25
|
readonly scopeKey: string;
|
|
47
26
|
readonly workMountDir: string;
|
|
48
27
|
readonly zoneId: string;
|
|
49
|
-
}): Promise<
|
|
28
|
+
}): Promise<ToolVmSshLease>;
|
|
29
|
+
startActiveUse(leaseId: string, request: StartToolVmActiveUseRequest): Promise<StartToolVmActiveUseResponse>;
|
|
50
30
|
}
|
|
51
31
|
type ControllerLeaseRequestErrorKind = 'client-error' | 'server-error';
|
|
52
32
|
declare class ControllerLeaseRequestError extends Error {
|
|
@@ -67,7 +47,7 @@ declare function createLeaseClient(options: {
|
|
|
67
47
|
}): LeaseClient;
|
|
68
48
|
//#endregion
|
|
69
49
|
//#region src/sandbox-backend/sandbox-backend-contract.d.ts
|
|
70
|
-
interface
|
|
50
|
+
interface OpenClawFsBridgeLeaseContext {
|
|
71
51
|
readonly remoteAgentWorkspaceDir: string;
|
|
72
52
|
readonly remoteWorkspaceDir: string;
|
|
73
53
|
readonly runRemoteShellScript: (params: {
|
|
@@ -82,7 +62,7 @@ interface FsBridgeLeaseContext {
|
|
|
82
62
|
readonly stdout: Buffer;
|
|
83
63
|
}>;
|
|
84
64
|
}
|
|
85
|
-
interface
|
|
65
|
+
interface OpenClawSandboxFsBridge {
|
|
86
66
|
mkdirp(params: {
|
|
87
67
|
readonly cwd?: string;
|
|
88
68
|
readonly filePath: string;
|
|
@@ -135,7 +115,7 @@ interface CreateBackendDependencies {
|
|
|
135
115
|
readonly buildExecSpec: (params: {
|
|
136
116
|
readonly command: string;
|
|
137
117
|
readonly env: Record<string, string>;
|
|
138
|
-
readonly ssh:
|
|
118
|
+
readonly ssh: ToolVmSshLease['ssh'];
|
|
139
119
|
readonly usePty: boolean;
|
|
140
120
|
readonly workdir: string;
|
|
141
121
|
}) => Promise<{
|
|
@@ -144,9 +124,9 @@ interface CreateBackendDependencies {
|
|
|
144
124
|
readonly finalizeToken?: unknown;
|
|
145
125
|
readonly stdinMode: 'pipe-open' | 'pipe-closed';
|
|
146
126
|
}>;
|
|
147
|
-
readonly createFsBridgeBuilder?: (leaseContext:
|
|
127
|
+
readonly createFsBridgeBuilder?: (leaseContext: OpenClawFsBridgeLeaseContext) => (params: {
|
|
148
128
|
readonly sandbox: unknown;
|
|
149
|
-
}) =>
|
|
129
|
+
}) => OpenClawSandboxFsBridge;
|
|
150
130
|
readonly createLeaseClient?: (options: {
|
|
151
131
|
readonly controllerUrl: string;
|
|
152
132
|
}) => LeaseClient;
|
|
@@ -154,7 +134,7 @@ interface CreateBackendDependencies {
|
|
|
154
134
|
readonly allowFailure?: boolean;
|
|
155
135
|
readonly script: string;
|
|
156
136
|
readonly signal?: AbortSignal;
|
|
157
|
-
readonly ssh:
|
|
137
|
+
readonly ssh: ToolVmSshLease['ssh'];
|
|
158
138
|
readonly stdin?: Buffer | string;
|
|
159
139
|
}) => Promise<{
|
|
160
140
|
readonly code: number;
|
|
@@ -162,13 +142,13 @@ interface CreateBackendDependencies {
|
|
|
162
142
|
readonly stdout: Buffer;
|
|
163
143
|
}>;
|
|
164
144
|
}
|
|
165
|
-
interface
|
|
145
|
+
interface OpenClawSandboxBackendHandle {
|
|
166
146
|
readonly configLabel?: string;
|
|
167
147
|
readonly configLabelKind?: string;
|
|
168
|
-
createFsBridge?: (params: {
|
|
148
|
+
readonly createFsBridge?: (params: {
|
|
169
149
|
readonly sandbox: unknown;
|
|
170
|
-
}) =>
|
|
171
|
-
env?: Record<string, string>;
|
|
150
|
+
}) => OpenClawSandboxFsBridge;
|
|
151
|
+
readonly env?: Record<string, string>;
|
|
172
152
|
readonly id: string;
|
|
173
153
|
readonly runtimeId: string;
|
|
174
154
|
readonly runtimeLabel: string;
|
|
@@ -184,7 +164,7 @@ interface GondolinSandboxBackendHandle {
|
|
|
184
164
|
readonly finalizeToken?: unknown;
|
|
185
165
|
readonly stdinMode: 'pipe-open' | 'pipe-closed';
|
|
186
166
|
}>;
|
|
187
|
-
finalizeExec?: (params: {
|
|
167
|
+
readonly finalizeExec?: (params: {
|
|
188
168
|
readonly exitCode: number | null;
|
|
189
169
|
readonly status: 'completed' | 'failed';
|
|
190
170
|
readonly timedOut: boolean;
|
|
@@ -215,7 +195,7 @@ declare function createGondolinSandboxBackendFactory(options: {
|
|
|
215
195
|
readonly scopeKey: string;
|
|
216
196
|
readonly sessionKey: string;
|
|
217
197
|
readonly workspaceDir: string;
|
|
218
|
-
}) => Promise<
|
|
198
|
+
}) => Promise<OpenClawSandboxBackendHandle>;
|
|
219
199
|
//#endregion
|
|
220
200
|
//#region src/sandbox-backend/sandbox-backend-manager.d.ts
|
|
221
201
|
declare function createGondolinSandboxBackendManager(options: {
|
|
@@ -282,7 +262,7 @@ interface SshHelpers {
|
|
|
282
262
|
}>;
|
|
283
263
|
};
|
|
284
264
|
readonly sandbox: unknown;
|
|
285
|
-
}) =>
|
|
265
|
+
}) => OpenClawSandboxFsBridge;
|
|
286
266
|
readonly createSshSandboxSessionFromSettings: (settings: {
|
|
287
267
|
readonly command: string;
|
|
288
268
|
readonly identityData?: string;
|
|
@@ -329,9 +309,9 @@ interface OpenClawToolRegistrationApi {
|
|
|
329
309
|
//#region src/openclaw-backend-dependencies.d.ts
|
|
330
310
|
declare function createBackendDeps(ssh: SshHelpers): {
|
|
331
311
|
readonly buildExecSpec: CreateBackendDependencies['buildExecSpec'];
|
|
332
|
-
readonly createFsBridgeBuilder: (leaseContext:
|
|
312
|
+
readonly createFsBridgeBuilder: (leaseContext: OpenClawFsBridgeLeaseContext) => (params: {
|
|
333
313
|
readonly sandbox: unknown;
|
|
334
|
-
}) =>
|
|
314
|
+
}) => OpenClawSandboxFsBridge;
|
|
335
315
|
readonly runRemoteShellScript: CreateBackendDependencies['runRemoteShellScript'];
|
|
336
316
|
};
|
|
337
317
|
//#endregion
|
|
@@ -356,5 +336,5 @@ declare const plugin: {
|
|
|
356
336
|
//#region src/index.d.ts
|
|
357
337
|
declare const OPENCLAW_GONDOLIN_PLUGIN_PACKAGE_NAME = "@agent-vm/openclaw-agent-vm-plugin";
|
|
358
338
|
//#endregion
|
|
359
|
-
export { ControllerLeaseRequestError, ControllerLeaseRequestErrorKind, CreateBackendDependencies,
|
|
339
|
+
export { ControllerLeaseRequestError, ControllerLeaseRequestErrorKind, type CreateBackendDependencies, LeaseClient, OPENCLAW_GONDOLIN_PLUGIN_PACKAGE_NAME, type OpenClawFsBridgeLeaseContext, OpenClawRuntimeStatusReport, type OpenClawSandboxBackendHandle, type OpenClawSandboxFsBridge, ResolvedGondolinPluginConfig, type SshHelpers, createBackendDeps, createGondolinSandboxBackendFactory, createGondolinSandboxBackendManager, createLeaseClient, plugin as default, resolveGondolinPluginConfig };
|
|
360
340
|
//# 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/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/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":"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"}
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { createToolVmActiveUseHandle, isToolVmLeasePeek, isToolVmSshLease } from "@agent-vm/gateway-interface";
|
|
1
2
|
//#region src/controller-lease-client.ts
|
|
2
3
|
var ControllerLeaseRequestError = class extends Error {
|
|
3
4
|
bodyText;
|
|
@@ -16,21 +17,13 @@ var ControllerLeaseRequestError = class extends Error {
|
|
|
16
17
|
function objectValue(value) {
|
|
17
18
|
return typeof value === "object" && value !== null ? value : void 0;
|
|
18
19
|
}
|
|
19
|
-
function
|
|
20
|
+
function isStartActiveUseResponse(value) {
|
|
20
21
|
const record = objectValue(value);
|
|
21
|
-
return record !== void 0 && typeof Reflect.get(record, "
|
|
22
|
+
return record !== void 0 && typeof Reflect.get(record, "expiresAt") === "number" && typeof Reflect.get(record, "heartbeatAfterMs") === "number" && typeof Reflect.get(record, "useId") === "string";
|
|
22
23
|
}
|
|
23
|
-
function
|
|
24
|
+
function isHeartbeatActiveUseResponse(value) {
|
|
24
25
|
const record = objectValue(value);
|
|
25
|
-
return record !== void 0 && typeof Reflect.get(record, "
|
|
26
|
-
}
|
|
27
|
-
function isGondolinLeaseResponse$1(value) {
|
|
28
|
-
const record = objectValue(value);
|
|
29
|
-
return record !== void 0 && (Reflect.get(record, "idleTtlMs") === void 0 || typeof Reflect.get(record, "idleTtlMs") === "number") && typeof Reflect.get(record, "leaseId") === "string" && isSshResponse(Reflect.get(record, "ssh")) && typeof Reflect.get(record, "tcpSlot") === "number" && typeof Reflect.get(record, "workdir") === "string";
|
|
30
|
-
}
|
|
31
|
-
function isLeasePeekResponse(value) {
|
|
32
|
-
const record = objectValue(value);
|
|
33
|
-
return record !== void 0 && typeof Reflect.get(record, "createdAt") === "number" && typeof Reflect.get(record, "lastUsedAt") === "number" && typeof Reflect.get(record, "leaseId") === "string" && typeof Reflect.get(record, "profileId") === "string" && typeof Reflect.get(record, "scopeKey") === "string" && isLeasePeekSshResponse(Reflect.get(record, "ssh")) && typeof Reflect.get(record, "tcpSlot") === "number" && typeof Reflect.get(record, "zoneId") === "string";
|
|
26
|
+
return record !== void 0 && typeof Reflect.get(record, "expiresAt") === "number" && typeof Reflect.get(record, "heartbeatAfterMs") === "number";
|
|
34
27
|
}
|
|
35
28
|
function formatUnknownError$1(error) {
|
|
36
29
|
return error instanceof Error ? error.message : String(error);
|
|
@@ -70,12 +63,32 @@ async function readJsonResponse(response, context, isExpectedResponse) {
|
|
|
70
63
|
function createLeaseClient(options) {
|
|
71
64
|
const fetchImpl = options.fetchImpl ?? fetch;
|
|
72
65
|
const baseUrl = options.controllerUrl.replace(/\/$/u, "");
|
|
66
|
+
const renewLease = async (leaseId) => {
|
|
67
|
+
return await readJsonResponse(await fetchImpl(`${baseUrl}/lease/${encodeURIComponent(leaseId)}/renew`, { method: "POST" }), "Controller lease renew API", isToolVmSshLease);
|
|
68
|
+
};
|
|
73
69
|
return {
|
|
74
|
-
|
|
75
|
-
|
|
70
|
+
endActiveUse: async (leaseId, useId, request) => {
|
|
71
|
+
const response = await fetchImpl(`${baseUrl}/lease/${encodeURIComponent(leaseId)}/uses/${encodeURIComponent(useId)}`, {
|
|
72
|
+
body: JSON.stringify(request),
|
|
73
|
+
headers: { "content-type": "application/json" },
|
|
74
|
+
method: "DELETE"
|
|
75
|
+
});
|
|
76
|
+
if (!response.ok) {
|
|
77
|
+
const errorBody = await readErrorBody(response, "Controller active-use end API");
|
|
78
|
+
throw new ControllerLeaseRequestError({
|
|
79
|
+
bodyText: errorBody.bodyText,
|
|
80
|
+
context: "Controller active-use end API",
|
|
81
|
+
responseBody: errorBody.responseBody,
|
|
82
|
+
status: response.status
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
},
|
|
86
|
+
heartbeatActiveUse: async (leaseId, useId) => {
|
|
87
|
+
return await readJsonResponse(await fetchImpl(`${baseUrl}/lease/${encodeURIComponent(leaseId)}/uses/${encodeURIComponent(useId)}/heartbeat`, { method: "POST" }), "Controller active-use heartbeat API", isHeartbeatActiveUseResponse);
|
|
76
88
|
},
|
|
89
|
+
renewLease,
|
|
77
90
|
peekLease: async (leaseId) => {
|
|
78
|
-
return await readJsonResponse(await fetchImpl(`${baseUrl}/lease/${leaseId}/peek`), "Controller lease peek API",
|
|
91
|
+
return await readJsonResponse(await fetchImpl(`${baseUrl}/lease/${encodeURIComponent(leaseId)}/peek`), "Controller lease peek API", isToolVmLeasePeek);
|
|
79
92
|
},
|
|
80
93
|
publishOpenClawRuntimeStatus: async (report) => {
|
|
81
94
|
const response = await fetchImpl(`${baseUrl}/zones/${encodeURIComponent(report.zoneId)}/openclaw-runtime-status`, {
|
|
@@ -93,8 +106,10 @@ function createLeaseClient(options) {
|
|
|
93
106
|
});
|
|
94
107
|
}
|
|
95
108
|
},
|
|
96
|
-
releaseLease: async (leaseId) => {
|
|
97
|
-
const
|
|
109
|
+
releaseLease: async (leaseId, releaseOptions = {}) => {
|
|
110
|
+
const releaseUrl = new URL(`${baseUrl}/lease/${encodeURIComponent(leaseId)}`);
|
|
111
|
+
if (releaseOptions.force === true) releaseUrl.searchParams.set("force", "true");
|
|
112
|
+
const response = await fetchImpl(releaseUrl.toString(), { method: "DELETE" });
|
|
98
113
|
if (!response.ok) {
|
|
99
114
|
const errorBody = await readErrorBody(response, "Controller lease release API");
|
|
100
115
|
throw new ControllerLeaseRequestError({
|
|
@@ -116,16 +131,18 @@ function createLeaseClient(options) {
|
|
|
116
131
|
}),
|
|
117
132
|
headers: { "content-type": "application/json" },
|
|
118
133
|
method: "POST"
|
|
119
|
-
}), "Controller lease API",
|
|
134
|
+
}), "Controller lease API", isToolVmSshLease);
|
|
135
|
+
},
|
|
136
|
+
startActiveUse: async (leaseId, request) => {
|
|
137
|
+
return await readJsonResponse(await fetchImpl(`${baseUrl}/lease/${encodeURIComponent(leaseId)}/uses`, {
|
|
138
|
+
body: JSON.stringify(request),
|
|
139
|
+
headers: { "content-type": "application/json" },
|
|
140
|
+
method: "POST"
|
|
141
|
+
}), "Controller active-use start API", isStartActiveUseResponse);
|
|
120
142
|
}
|
|
121
143
|
};
|
|
122
144
|
}
|
|
123
145
|
//#endregion
|
|
124
|
-
//#region src/sandbox-backend/sandbox-backend-contract.ts
|
|
125
|
-
function isGondolinLeaseResponse(value) {
|
|
126
|
-
return typeof value === "object" && value !== null && typeof value.leaseId === "string" && typeof value.tcpSlot === "number" && typeof value.workdir === "string" && typeof value.ssh === "object" && value.ssh !== null;
|
|
127
|
-
}
|
|
128
|
-
//#endregion
|
|
129
146
|
//#region src/sandbox-backend/sandbox-shell-script.ts
|
|
130
147
|
function buildShellScriptWithArgs(script, args) {
|
|
131
148
|
if (!args || args.length === 0) return script;
|
|
@@ -151,14 +168,17 @@ function writeSandboxBackendLog(message) {
|
|
|
151
168
|
function shouldRefreshCachedLease(error) {
|
|
152
169
|
return error instanceof ControllerLeaseRequestError && error.status === 404;
|
|
153
170
|
}
|
|
154
|
-
function
|
|
155
|
-
return
|
|
171
|
+
function isCleanupNotFound(error) {
|
|
172
|
+
return error instanceof ControllerLeaseRequestError && error.status === 404;
|
|
173
|
+
}
|
|
174
|
+
function isDisposableFinalizeToken(value) {
|
|
175
|
+
return typeof value === "object" && value !== null && "dispose" in value && typeof Reflect.get(value, "dispose") === "function";
|
|
156
176
|
}
|
|
157
|
-
function
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
return
|
|
177
|
+
function isActiveUseFinalizeToken(value) {
|
|
178
|
+
return typeof value === "object" && value !== null && "activeUseHandle" in value && typeof Reflect.get(value, "activeUseHandle") === "object";
|
|
179
|
+
}
|
|
180
|
+
function activeUseOutcomeForFinalizeParams(finalizeParams) {
|
|
181
|
+
return finalizeParams.timedOut ? "timed-out" : finalizeParams.status === "completed" ? "completed" : "failed";
|
|
162
182
|
}
|
|
163
183
|
function createGondolinSandboxBackendFactory(options, dependencies) {
|
|
164
184
|
const scopeCache = /* @__PURE__ */ new Map();
|
|
@@ -174,10 +194,10 @@ function createGondolinSandboxBackendFactory(options, dependencies) {
|
|
|
174
194
|
const leaseClient = dependencies.createLeaseClient?.({ controllerUrl: options.controllerUrl }) ?? createLeaseClient({ controllerUrl: options.controllerUrl });
|
|
175
195
|
const cachedEntry = scopeCache.get(cacheKey);
|
|
176
196
|
if (cachedEntry) try {
|
|
177
|
-
await leaseClient.
|
|
197
|
+
await leaseClient.renewLease(cachedEntry.lease.leaseId);
|
|
178
198
|
return cachedEntry.handle;
|
|
179
199
|
} catch (error) {
|
|
180
|
-
writeSandboxBackendLog(`lease
|
|
200
|
+
writeSandboxBackendLog(`lease renew failed for zone '${options.zoneId}' scope '${params.scopeKey}' lease '${cachedEntry.lease.leaseId}': ${formatUnknownError(error)}`);
|
|
181
201
|
if (!shouldRefreshCachedLease(error)) throw error;
|
|
182
202
|
scopeCache.delete(cacheKey);
|
|
183
203
|
}
|
|
@@ -190,27 +210,18 @@ function createGondolinSandboxBackendFactory(options, dependencies) {
|
|
|
190
210
|
workMountDir: params.workspaceDir,
|
|
191
211
|
zoneId: options.zoneId
|
|
192
212
|
});
|
|
193
|
-
if (!
|
|
213
|
+
if (!isToolVmSshLease(leaseResponse)) throw new TypeError("Controller lease API returned an unexpected response.");
|
|
194
214
|
const lease = leaseResponse;
|
|
195
215
|
const handle = createSandboxBackendHandle({
|
|
196
216
|
cfg: params.cfg,
|
|
197
217
|
controllerUrl: options.controllerUrl,
|
|
198
218
|
createFsBridgeBuilder: dependencies.createFsBridgeBuilder,
|
|
199
|
-
keepLeaseAlive: async (operation) => {
|
|
200
|
-
try {
|
|
201
|
-
await leaseClient.keepLeaseAlive(lease.leaseId);
|
|
202
|
-
} catch (error) {
|
|
203
|
-
writeSandboxBackendLog(`lease command keepalive failed during ${operation} for zone '${options.zoneId}' scope '${params.scopeKey}' lease '${lease.leaseId}': ${formatUnknownError(error)}`);
|
|
204
|
-
if (shouldRefreshCachedLease(error)) {
|
|
205
|
-
if (scopeCache.get(cacheKey)?.lease.leaseId === lease.leaseId) scopeCache.delete(cacheKey);
|
|
206
|
-
}
|
|
207
|
-
throw error;
|
|
208
|
-
}
|
|
209
|
-
},
|
|
210
219
|
lease,
|
|
220
|
+
leaseClient,
|
|
211
221
|
runRemoteShellScript: dependencies.runRemoteShellScript,
|
|
212
222
|
buildExecSpec: dependencies.buildExecSpec,
|
|
213
223
|
scopeKey: params.scopeKey,
|
|
224
|
+
sessionKey: params.sessionKey,
|
|
214
225
|
zoneId: options.zoneId
|
|
215
226
|
});
|
|
216
227
|
scopeCache.set(cacheKey, {
|
|
@@ -221,45 +232,63 @@ function createGondolinSandboxBackendFactory(options, dependencies) {
|
|
|
221
232
|
};
|
|
222
233
|
}
|
|
223
234
|
function createSandboxBackendHandle(options) {
|
|
224
|
-
const
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
options.
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
}
|
|
242
|
-
async function runWithLeaseRenewal(operation, runOperation) {
|
|
243
|
-
await options.keepLeaseAlive(`${operation} start`);
|
|
244
|
-
const renewalTimer = beginLeaseRenewalTimer(operation);
|
|
235
|
+
const createActiveUseHandle = async (correlation) => await createToolVmActiveUseHandle({
|
|
236
|
+
correlation,
|
|
237
|
+
endActiveUse: async (useId, request) => {
|
|
238
|
+
await options.leaseClient.endActiveUse(options.lease.leaseId, useId, request);
|
|
239
|
+
},
|
|
240
|
+
heartbeatActiveUse: async (useId) => await options.leaseClient.heartbeatActiveUse(options.lease.leaseId, useId),
|
|
241
|
+
isEndErrorTolerable: isCleanupNotFound,
|
|
242
|
+
logEndFailure: (error) => {
|
|
243
|
+
writeSandboxBackendLog(`active-use cleanup ignored for zone '${options.zoneId}' lease '${options.lease.leaseId}': ${formatUnknownError(error)}`);
|
|
244
|
+
},
|
|
245
|
+
logHeartbeatFailure: (error) => {
|
|
246
|
+
writeSandboxBackendLog(`active-use heartbeat failed for zone '${options.zoneId}' lease '${options.lease.leaseId}': ${formatUnknownError(error)}`);
|
|
247
|
+
},
|
|
248
|
+
startActiveUse: async (request) => await options.leaseClient.startActiveUse(options.lease.leaseId, request)
|
|
249
|
+
});
|
|
250
|
+
const runWithActiveUse = async (correlation, fn) => {
|
|
251
|
+
const activeUseHandle = await createActiveUseHandle(correlation);
|
|
245
252
|
try {
|
|
246
|
-
const result = await
|
|
247
|
-
|
|
248
|
-
await renewLeaseAfterOperation(`${operation} end`, { hadPrimaryError: false });
|
|
253
|
+
const result = await fn();
|
|
254
|
+
await activeUseHandle.dispose("completed");
|
|
249
255
|
return result;
|
|
250
256
|
} catch (error) {
|
|
251
|
-
|
|
252
|
-
|
|
257
|
+
await activeUseHandle.dispose("failed").catch((cleanupError) => {
|
|
258
|
+
writeSandboxBackendLog(`failed to end active use after operation failure for zone '${options.zoneId}' lease '${options.lease.leaseId}': ${formatUnknownError(cleanupError)}`);
|
|
259
|
+
});
|
|
253
260
|
throw error;
|
|
254
261
|
}
|
|
255
|
-
}
|
|
256
|
-
const boundRunRemoteShellScript = async (shellParams) => await
|
|
262
|
+
};
|
|
263
|
+
const boundRunRemoteShellScript = async (shellParams) => await runWithActiveUse({
|
|
264
|
+
sessionKey: options.sessionKey,
|
|
265
|
+
toolName: "fs-bridge"
|
|
266
|
+
}, async () => await options.runRemoteShellScript({
|
|
257
267
|
...shellParams.allowFailure !== void 0 ? { allowFailure: shellParams.allowFailure } : {},
|
|
258
268
|
script: buildShellScriptWithArgs(shellParams.script, shellParams.args),
|
|
259
269
|
...shellParams.signal !== void 0 ? { signal: shellParams.signal } : {},
|
|
260
270
|
ssh: options.lease.ssh,
|
|
261
271
|
...shellParams.stdin !== void 0 ? { stdin: shellParams.stdin } : {}
|
|
262
272
|
}));
|
|
273
|
+
const disposeInnerFinalizeToken = async (token) => {
|
|
274
|
+
if (isDisposableFinalizeToken(token)) await token.dispose();
|
|
275
|
+
};
|
|
276
|
+
const endActiveUseFinalizeToken = async (token, outcome) => {
|
|
277
|
+
let innerError;
|
|
278
|
+
try {
|
|
279
|
+
await disposeInnerFinalizeToken(token.innerToken);
|
|
280
|
+
} catch (error) {
|
|
281
|
+
innerError = error;
|
|
282
|
+
}
|
|
283
|
+
let activeUseError;
|
|
284
|
+
try {
|
|
285
|
+
await token.activeUseHandle.dispose(outcome);
|
|
286
|
+
} catch (error) {
|
|
287
|
+
activeUseError = error;
|
|
288
|
+
}
|
|
289
|
+
if (innerError) throw innerError;
|
|
290
|
+
if (activeUseError) throw activeUseError;
|
|
291
|
+
};
|
|
263
292
|
const createFsBridge = options.createFsBridgeBuilder?.({
|
|
264
293
|
remoteAgentWorkspaceDir: options.lease.workdir,
|
|
265
294
|
remoteWorkspaceDir: options.lease.workdir,
|
|
@@ -275,47 +304,43 @@ function createSandboxBackendHandle(options) {
|
|
|
275
304
|
runtimeLabel: options.lease.leaseId,
|
|
276
305
|
workdir: options.lease.workdir,
|
|
277
306
|
buildExecSpec: async (execParams) => {
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
307
|
+
const activeUseHandle = await createActiveUseHandle({
|
|
308
|
+
sessionKey: options.sessionKey,
|
|
309
|
+
toolName: "shell"
|
|
310
|
+
});
|
|
281
311
|
try {
|
|
282
|
-
execSpec = await options.buildExecSpec({
|
|
312
|
+
const execSpec = await options.buildExecSpec({
|
|
283
313
|
command: execParams.command,
|
|
284
314
|
env: execParams.env,
|
|
285
315
|
ssh: options.lease.ssh,
|
|
286
316
|
usePty: execParams.usePty,
|
|
287
317
|
workdir: execParams.workdir ?? options.lease.workdir
|
|
288
318
|
});
|
|
319
|
+
return {
|
|
320
|
+
...execSpec,
|
|
321
|
+
finalizeToken: {
|
|
322
|
+
activeUseHandle,
|
|
323
|
+
...execSpec.finalizeToken !== void 0 ? { innerToken: execSpec.finalizeToken } : {}
|
|
324
|
+
}
|
|
325
|
+
};
|
|
289
326
|
} catch (error) {
|
|
290
|
-
|
|
327
|
+
await activeUseHandle.dispose("failed").catch((cleanupError) => {
|
|
328
|
+
writeSandboxBackendLog(`failed to end active use after buildExecSpec failure for zone '${options.zoneId}' lease '${options.lease.leaseId}': ${formatUnknownError(cleanupError)}`);
|
|
329
|
+
});
|
|
291
330
|
throw error;
|
|
292
331
|
}
|
|
293
|
-
return {
|
|
294
|
-
...execSpec,
|
|
295
|
-
finalizeToken: {
|
|
296
|
-
innerToken: execSpec.finalizeToken,
|
|
297
|
-
leaseRenewalTimer: execRenewalTimer
|
|
298
|
-
}
|
|
299
|
-
};
|
|
300
332
|
},
|
|
301
333
|
finalizeExec: async (finalizeParams) => {
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
let hadPrimaryError = false;
|
|
306
|
-
let primaryError;
|
|
307
|
-
try {
|
|
308
|
-
if (hasDisposeFunction(innerToken)) await innerToken.dispose();
|
|
309
|
-
} catch (error) {
|
|
310
|
-
hadPrimaryError = true;
|
|
311
|
-
primaryError = error;
|
|
312
|
-
} finally {
|
|
313
|
-
await leaseRenewalTimer?.dispose();
|
|
334
|
+
if (isActiveUseFinalizeToken(finalizeParams.token)) {
|
|
335
|
+
await endActiveUseFinalizeToken(finalizeParams.token, activeUseOutcomeForFinalizeParams(finalizeParams));
|
|
336
|
+
return;
|
|
314
337
|
}
|
|
315
|
-
await
|
|
316
|
-
if (hadPrimaryError) throw primaryError;
|
|
338
|
+
await disposeInnerFinalizeToken(finalizeParams.token);
|
|
317
339
|
},
|
|
318
|
-
runShellCommand: async (commandParams) => await
|
|
340
|
+
runShellCommand: async (commandParams) => await runWithActiveUse({
|
|
341
|
+
sessionKey: options.sessionKey,
|
|
342
|
+
toolName: "runShellCommand"
|
|
343
|
+
}, async () => await options.runRemoteShellScript({
|
|
319
344
|
script: commandParams.script,
|
|
320
345
|
ssh: options.lease.ssh
|
|
321
346
|
}))
|
|
@@ -332,7 +357,8 @@ function createGondolinSandboxBackendManager(options, dependencies) {
|
|
|
332
357
|
configLabelMatch: true,
|
|
333
358
|
running: await leaseClient.peekLease(params.entry.containerName) !== null
|
|
334
359
|
};
|
|
335
|
-
} catch {
|
|
360
|
+
} catch (error) {
|
|
361
|
+
if (!(error instanceof ControllerLeaseRequestError) || error.status !== 404) throw error;
|
|
336
362
|
return {
|
|
337
363
|
configLabelMatch: false,
|
|
338
364
|
running: false
|
|
@@ -340,7 +366,7 @@ function createGondolinSandboxBackendManager(options, dependencies) {
|
|
|
340
366
|
}
|
|
341
367
|
},
|
|
342
368
|
removeRuntime: async (params) => {
|
|
343
|
-
await (dependencies.createLeaseClient?.({ controllerUrl: options.controllerUrl }) ?? createLeaseClient({ controllerUrl: options.controllerUrl })).releaseLease(params.entry.containerName);
|
|
369
|
+
await (dependencies.createLeaseClient?.({ controllerUrl: options.controllerUrl }) ?? createLeaseClient({ controllerUrl: options.controllerUrl })).releaseLease(params.entry.containerName, { force: true });
|
|
344
370
|
}
|
|
345
371
|
};
|
|
346
372
|
}
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["isGondolinLeaseResponse","formatUnknownError"],"sources":["../src/controller-lease-client.ts","../src/sandbox-backend/sandbox-backend-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":["export interface GondolinLeaseResponse {\n\treadonly idleTtlMs?: number;\n\treadonly leaseId: string;\n\treadonly ssh: {\n\t\treadonly host: string;\n\t\treadonly identityPem: string;\n\t\treadonly knownHostsLine: string;\n\t\treadonly port: number;\n\t\treadonly user: string;\n\t};\n\treadonly tcpSlot: number;\n\treadonly workdir: string;\n}\n\nexport interface LeasePeekResponse {\n\treadonly createdAt: number;\n\treadonly lastUsedAt: number;\n\treadonly leaseId: string;\n\treadonly profileId: string;\n\treadonly scopeKey: string;\n\treadonly ssh: {\n\t\treadonly host: string;\n\t\treadonly port: number;\n\t\treadonly user: string;\n\t};\n\treadonly tcpSlot: number;\n\treadonly zoneId: string;\n}\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 LeaseClient {\n\t// Cached handles use keepalive; read-only runtime probes use peekLease.\n\tkeepLeaseAlive(leaseId: string): Promise<GondolinLeaseResponse>;\n\tpeekLease(leaseId: string): Promise<LeasePeekResponse>;\n\tpublishOpenClawRuntimeStatus?(report: OpenClawRuntimeStatusReport): Promise<void>;\n\treleaseLease(leaseId: string): Promise<void>;\n\trequestLease(request: {\n\t\treadonly agentWorkspaceDir: string;\n\t\treadonly profileId: string;\n\t\treadonly scopeKey: string;\n\t\treadonly workMountDir: string;\n\t\treadonly zoneId: string;\n\t}): Promise<GondolinLeaseResponse>;\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: unknown;\n\treadonly status: number;\n\n\tconstructor(options: {\n\t\treadonly bodyText: string;\n\t\treadonly context: string;\n\t\treadonly responseBody: unknown;\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(`${options.context} returned HTTP ${String(options.status)} (${kind})`);\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\nfunction objectValue(value: unknown): object | undefined {\n\treturn typeof value === 'object' && value !== null ? value : undefined;\n}\n\nfunction isSshResponse(value: unknown): value is GondolinLeaseResponse['ssh'] {\n\tconst record = objectValue(value);\n\treturn (\n\t\trecord !== undefined &&\n\t\ttypeof Reflect.get(record, 'host') === 'string' &&\n\t\ttypeof Reflect.get(record, 'identityPem') === 'string' &&\n\t\ttypeof Reflect.get(record, 'knownHostsLine') === 'string' &&\n\t\ttypeof Reflect.get(record, 'port') === 'number' &&\n\t\ttypeof Reflect.get(record, 'user') === 'string'\n\t);\n}\n\nfunction isLeasePeekSshResponse(value: unknown): value is LeasePeekResponse['ssh'] {\n\tconst record = objectValue(value);\n\treturn (\n\t\trecord !== undefined &&\n\t\ttypeof Reflect.get(record, 'host') === 'string' &&\n\t\ttypeof Reflect.get(record, 'port') === 'number' &&\n\t\ttypeof Reflect.get(record, 'user') === 'string'\n\t);\n}\n\nfunction isGondolinLeaseResponse(value: unknown): value is GondolinLeaseResponse {\n\tconst record = objectValue(value);\n\treturn (\n\t\trecord !== undefined &&\n\t\t(Reflect.get(record, 'idleTtlMs') === undefined ||\n\t\t\ttypeof Reflect.get(record, 'idleTtlMs') === 'number') &&\n\t\ttypeof Reflect.get(record, 'leaseId') === 'string' &&\n\t\tisSshResponse(Reflect.get(record, 'ssh')) &&\n\t\ttypeof Reflect.get(record, 'tcpSlot') === 'number' &&\n\t\ttypeof Reflect.get(record, 'workdir') === 'string'\n\t);\n}\n\nfunction isLeasePeekResponse(value: unknown): value is LeasePeekResponse {\n\tconst record = objectValue(value);\n\treturn (\n\t\trecord !== undefined &&\n\t\ttypeof Reflect.get(record, 'createdAt') === 'number' &&\n\t\ttypeof Reflect.get(record, 'lastUsedAt') === 'number' &&\n\t\ttypeof Reflect.get(record, 'leaseId') === 'string' &&\n\t\ttypeof Reflect.get(record, 'profileId') === 'string' &&\n\t\ttypeof Reflect.get(record, 'scopeKey') === 'string' &&\n\t\tisLeasePeekSshResponse(Reflect.get(record, 'ssh')) &&\n\t\ttypeof Reflect.get(record, 'tcpSlot') === 'number' &&\n\t\ttypeof Reflect.get(record, 'zoneId') === 'string'\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): unknown {\n\ttry {\n\t\treturn JSON.parse(bodyText);\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: unknown;\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\n\treturn {\n\t\tkeepLeaseAlive: async (leaseId: string): Promise<GondolinLeaseResponse> => {\n\t\t\tconst response = await fetchImpl(`${baseUrl}/lease/${leaseId}`);\n\t\t\treturn await readJsonResponse(\n\t\t\t\tresponse,\n\t\t\t\t'Controller lease keepalive API',\n\t\t\t\tisGondolinLeaseResponse,\n\t\t\t);\n\t\t},\n\t\tpeekLease: async (leaseId: string): Promise<LeasePeekResponse> => {\n\t\t\tconst response = await fetchImpl(`${baseUrl}/lease/${leaseId}/peek`);\n\t\t\treturn await readJsonResponse(response, 'Controller lease peek API', isLeasePeekResponse);\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 (leaseId: string): Promise<void> => {\n\t\t\tconst response = await fetchImpl(`${baseUrl}/lease/${leaseId}`, {\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<GondolinLeaseResponse> => {\n\t\t\tconst response = await fetchImpl(`${baseUrl}/lease`, {\n\t\t\t\tbody: JSON.stringify({\n\t\t\t\t\tagentWorkspaceDir: request.agentWorkspaceDir,\n\t\t\t\t\tprofileId: request.profileId,\n\t\t\t\t\tscopeKey: request.scopeKey,\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', isGondolinLeaseResponse);\n\t\t},\n\t};\n}\n","import type { GondolinLeaseResponse, LeaseClient } from '../controller-lease-client.js';\n\nexport function isGondolinLeaseResponse(value: unknown): value is GondolinLeaseResponse {\n\treturn (\n\t\ttypeof value === 'object' &&\n\t\tvalue !== null &&\n\t\ttypeof (value as { leaseId?: unknown }).leaseId === 'string' &&\n\t\ttypeof (value as { tcpSlot?: unknown }).tcpSlot === 'number' &&\n\t\ttypeof (value as { workdir?: unknown }).workdir === 'string' &&\n\t\ttypeof (value as { ssh?: unknown }).ssh === 'object' &&\n\t\t(value as { ssh?: unknown }).ssh !== null\n\t);\n}\n\nexport interface FsBridgeLeaseContext {\n\treadonly remoteAgentWorkspaceDir: string;\n\treadonly remoteWorkspaceDir: string;\n\treadonly runRemoteShellScript: (params: {\n\t\treadonly allowFailure?: boolean;\n\t\treadonly args?: string[];\n\t\treadonly script: string;\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}\n\nexport interface GondolinFsBridge {\n\tmkdirp(params: {\n\t\treadonly cwd?: string;\n\t\treadonly filePath: string;\n\t\treadonly signal?: AbortSignal;\n\t}): Promise<void>;\n\treadFile(params: {\n\t\treadonly cwd?: string;\n\t\treadonly filePath: string;\n\t\treadonly signal?: AbortSignal;\n\t}): Promise<Buffer>;\n\tremove(params: {\n\t\treadonly cwd?: string;\n\t\treadonly filePath: string;\n\t\treadonly force?: boolean;\n\t\treadonly recursive?: boolean;\n\t\treadonly signal?: AbortSignal;\n\t}): Promise<void>;\n\trename(params: {\n\t\treadonly cwd?: string;\n\t\treadonly from: string;\n\t\treadonly signal?: AbortSignal;\n\t\treadonly to: string;\n\t}): Promise<void>;\n\tresolvePath(params: { readonly cwd?: string; readonly filePath: string }): {\n\t\treadonly containerPath: string;\n\t\treadonly relativePath: string;\n\t};\n\tstat(params: {\n\t\treadonly cwd?: string;\n\t\treadonly filePath: string;\n\t\treadonly signal?: AbortSignal;\n\t}): Promise<{\n\t\treadonly mtimeMs: number;\n\t\treadonly size: number;\n\t\treadonly type: 'directory' | 'file' | 'other';\n\t} | null>;\n\twriteFile(params: {\n\t\treadonly cwd?: string;\n\t\treadonly data: Buffer | string;\n\t\treadonly encoding?: BufferEncoding;\n\t\treadonly filePath: string;\n\t\treadonly mkdir?: boolean;\n\t\treadonly signal?: AbortSignal;\n\t}): Promise<void>;\n}\n\nexport interface CreateBackendDependencies {\n\treadonly buildExecSpec: (params: {\n\t\treadonly command: string;\n\t\treadonly env: Record<string, string>;\n\t\treadonly ssh: GondolinLeaseResponse['ssh'];\n\t\treadonly usePty: boolean;\n\t\treadonly workdir: string;\n\t}) => Promise<{\n\t\treadonly argv: string[];\n\t\treadonly env: Record<string, string>;\n\t\treadonly finalizeToken?: unknown;\n\t\treadonly stdinMode: 'pipe-open' | 'pipe-closed';\n\t}>;\n\treadonly createFsBridgeBuilder?: (\n\t\tleaseContext: FsBridgeLeaseContext,\n\t) => (params: { readonly sandbox: unknown }) => GondolinFsBridge;\n\treadonly createLeaseClient?: (options: { readonly controllerUrl: string }) => LeaseClient;\n\treadonly runRemoteShellScript: (params: {\n\t\treadonly allowFailure?: boolean;\n\t\treadonly script: string;\n\t\treadonly signal?: AbortSignal;\n\t\treadonly ssh: GondolinLeaseResponse['ssh'];\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}\n\nexport interface GondolinSandboxBackendHandle {\n\treadonly configLabel?: string;\n\treadonly configLabelKind?: string;\n\tcreateFsBridge?: (params: { readonly sandbox: unknown }) => GondolinFsBridge;\n\tenv?: Record<string, string>;\n\treadonly id: string;\n\treadonly runtimeId: string;\n\treadonly runtimeLabel: string;\n\treadonly workdir: string;\n\tbuildExecSpec(params: {\n\t\treadonly command: string;\n\t\treadonly env: Record<string, string>;\n\t\treadonly usePty: boolean;\n\t\treadonly workdir?: string;\n\t}): Promise<{\n\t\treadonly argv: string[];\n\t\treadonly env: Record<string, string>;\n\t\treadonly finalizeToken?: unknown;\n\t\treadonly stdinMode: 'pipe-open' | 'pipe-closed';\n\t}>;\n\tfinalizeExec?: (params: {\n\t\treadonly exitCode: number | null;\n\t\treadonly status: 'completed' | 'failed';\n\t\treadonly timedOut: boolean;\n\t\treadonly token?: unknown;\n\t}) => Promise<void>;\n\trunShellCommand(params: { readonly script: string }): Promise<{\n\t\treadonly code: number;\n\t\treadonly stderr: Buffer;\n\t\treadonly stdout: Buffer;\n\t}>;\n}\n\nexport interface CachedScopeEntry {\n\treadonly handle: GondolinSandboxBackendHandle;\n\treadonly lease: GondolinLeaseResponse;\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\tControllerLeaseRequestError,\n\tcreateLeaseClient,\n\ttype GondolinLeaseResponse,\n\ttype OpenClawRuntimeStatusReport,\n} from '../controller-lease-client.js';\nimport {\n\ttype CachedScopeEntry,\n\ttype CreateBackendDependencies,\n\ttype FsBridgeLeaseContext,\n\ttype GondolinSandboxBackendHandle,\n\tisGondolinLeaseResponse,\n} from './sandbox-backend-contract.js';\nimport { buildShellScriptWithArgs } from './sandbox-shell-script.js';\n\nfunction scopeCacheKey(params: {\n\treadonly agentWorkspaceDir: string;\n\treadonly profileId: string;\n\treadonly scopeKey: string;\n\treadonly workspaceDir: string;\n\treadonly zoneId: string;\n}): string {\n\treturn [\n\t\tparams.zoneId,\n\t\tparams.scopeKey,\n\t\tparams.profileId,\n\t\tparams.agentWorkspaceDir,\n\t\tparams.workspaceDir,\n\t].join('\\0');\n}\n\nfunction formatUnknownError(error: unknown): string {\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 hasDisposeFunction(\n\tvalue: unknown,\n): value is { readonly dispose: () => void | Promise<void> } {\n\treturn (\n\t\ttypeof value === 'object' &&\n\t\tvalue !== null &&\n\t\t'dispose' in value &&\n\t\ttypeof value.dispose === 'function'\n\t);\n}\n\nfunction renewalIntervalMsForLease(lease: GondolinLeaseResponse): number {\n\tconst fallbackRenewalIntervalMs = 60_000;\n\tconst minimumRenewalIntervalMs = 1_000;\n\tif (lease.idleTtlMs === undefined) {\n\t\treturn fallbackRenewalIntervalMs;\n\t}\n\treturn Math.max(\n\t\tminimumRenewalIntervalMs,\n\t\tMath.min(fallbackRenewalIntervalMs, Math.floor(lease.idleTtlMs / 3)),\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: {\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<GondolinSandboxBackendHandle> {\n\tconst scopeCache = new Map<string, CachedScopeEntry>();\n\n\treturn async (params) => {\n\t\tconst profileId = options.profileId ?? 'standard';\n\t\tconst cacheKey = scopeCacheKey({\n\t\t\tagentWorkspaceDir: params.agentWorkspaceDir,\n\t\t\tprofileId,\n\t\t\tscopeKey: params.scopeKey,\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.keepLeaseAlive(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 keepalive 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// backs the Tool VM /work mount.\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\tagentWorkspaceDir: params.agentWorkspaceDir,\n\t\t\tprofileId,\n\t\t\tscopeKey: params.scopeKey,\n\t\t\tworkMountDir: params.workspaceDir,\n\t\t\tzoneId: options.zoneId,\n\t\t});\n\t\tif (!isGondolinLeaseResponse(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\tkeepLeaseAlive: async (operation) => {\n\t\t\t\ttry {\n\t\t\t\t\tawait leaseClient.keepLeaseAlive(lease.leaseId);\n\t\t\t\t} catch (error) {\n\t\t\t\t\twriteSandboxBackendLog(\n\t\t\t\t\t\t`lease command keepalive failed during ${operation} for zone '${options.zoneId}' scope '${params.scopeKey}' lease '${lease.leaseId}': ${formatUnknownError(error)}`,\n\t\t\t\t\t);\n\t\t\t\t\tif (shouldRefreshCachedLease(error)) {\n\t\t\t\t\t\tconst cachedEntryForLease = scopeCache.get(cacheKey);\n\t\t\t\t\t\tif (cachedEntryForLease?.lease.leaseId === lease.leaseId) {\n\t\t\t\t\t\t\tscopeCache.delete(cacheKey);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tthrow error;\n\t\t\t\t}\n\t\t\t},\n\t\t\tlease,\n\t\t\trunRemoteShellScript: dependencies.runRemoteShellScript,\n\t\t\tbuildExecSpec: dependencies.buildExecSpec,\n\t\t\tscopeKey: params.scopeKey,\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 keepLeaseAlive: (operation: string) => Promise<void>;\n\treadonly lease: GondolinLeaseResponse;\n\treadonly runRemoteShellScript: CreateBackendDependencies['runRemoteShellScript'];\n\treadonly scopeKey: string;\n\treadonly zoneId: string;\n}): GondolinSandboxBackendHandle {\n\tconst renewalIntervalMs = renewalIntervalMsForLease(options.lease);\n\n\tfunction beginLeaseRenewalTimer(operation: string): { readonly dispose: () => void } {\n\t\tconst interval = setInterval(() => {\n\t\t\tvoid options.keepLeaseAlive(`${operation} active`).catch((error: unknown) => {\n\t\t\t\twriteSandboxBackendLog(\n\t\t\t\t\t`lease command keepalive failed while ${operation} was active for zone '${options.zoneId}' scope '${options.scopeKey}' lease '${options.lease.leaseId}': ${formatUnknownError(error)}`,\n\t\t\t\t);\n\t\t\t});\n\t\t}, renewalIntervalMs);\n\t\tif ('unref' in interval && typeof interval.unref === 'function') {\n\t\t\tinterval.unref();\n\t\t}\n\t\treturn {\n\t\t\tdispose: () => clearInterval(interval),\n\t\t};\n\t}\n\n\tasync function renewLeaseAfterOperation(\n\t\toperation: string,\n\t\toptionsForRenewal: { readonly hadPrimaryError: boolean },\n\t): Promise<void> {\n\t\ttry {\n\t\t\tawait options.keepLeaseAlive(operation);\n\t\t} catch (error) {\n\t\t\tif (!optionsForRenewal.hadPrimaryError) {\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t\twriteSandboxBackendLog(\n\t\t\t\t`lease command keepalive failed after ${operation} for zone '${options.zoneId}' scope '${options.scopeKey}' lease '${options.lease.leaseId}': ${formatUnknownError(error)}`,\n\t\t\t);\n\t\t}\n\t}\n\n\tasync function runWithLeaseRenewal<TValue>(\n\t\toperation: string,\n\t\trunOperation: () => Promise<TValue>,\n\t): Promise<TValue> {\n\t\tawait options.keepLeaseAlive(`${operation} start`);\n\t\tconst renewalTimer = beginLeaseRenewalTimer(operation);\n\t\ttry {\n\t\t\tconst result = await runOperation();\n\t\t\trenewalTimer.dispose();\n\t\t\tawait renewLeaseAfterOperation(`${operation} end`, { hadPrimaryError: false });\n\t\t\treturn result;\n\t\t} catch (error) {\n\t\t\trenewalTimer.dispose();\n\t\t\tawait renewLeaseAfterOperation(`${operation} end`, { hadPrimaryError: true });\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tconst boundRunRemoteShellScript: FsBridgeLeaseContext['runRemoteShellScript'] = async (\n\t\tshellParams,\n\t) =>\n\t\tawait runWithLeaseRenewal(\n\t\t\t'fs bridge shell command',\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 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\tawait options.keepLeaseAlive('exec spec build start');\n\t\t\tconst execRenewalTimer = beginLeaseRenewalTimer('exec command');\n\t\t\tlet execSpec: Awaited<ReturnType<CreateBackendDependencies['buildExecSpec']>>;\n\t\t\ttry {\n\t\t\t\texecSpec = 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} catch (error) {\n\t\t\t\texecRenewalTimer.dispose();\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t\treturn {\n\t\t\t\t...execSpec,\n\t\t\t\tfinalizeToken: {\n\t\t\t\t\tinnerToken: execSpec.finalizeToken,\n\t\t\t\t\tleaseRenewalTimer: execRenewalTimer,\n\t\t\t\t},\n\t\t\t};\n\t\t},\n\t\tfinalizeExec: async (finalizeParams) => {\n\t\t\tconst token = finalizeParams.token;\n\t\t\tconst leaseRenewalTimer =\n\t\t\t\ttypeof token === 'object' &&\n\t\t\t\ttoken !== null &&\n\t\t\t\t'leaseRenewalTimer' in token &&\n\t\t\t\thasDisposeFunction(token.leaseRenewalTimer)\n\t\t\t\t\t? token.leaseRenewalTimer\n\t\t\t\t\t: undefined;\n\t\t\tconst innerToken =\n\t\t\t\ttypeof token === 'object' && token !== null && 'innerToken' in token\n\t\t\t\t\t? token.innerToken\n\t\t\t\t\t: token;\n\t\t\tlet hadPrimaryError = false;\n\t\t\tlet primaryError: unknown;\n\t\t\ttry {\n\t\t\t\tif (hasDisposeFunction(innerToken)) {\n\t\t\t\t\tawait innerToken.dispose();\n\t\t\t\t}\n\t\t\t} catch (error) {\n\t\t\t\thadPrimaryError = true;\n\t\t\t\tprimaryError = error;\n\t\t\t} finally {\n\t\t\t\tawait leaseRenewalTimer?.dispose();\n\t\t\t}\n\t\t\tawait renewLeaseAfterOperation('exec finalize', {\n\t\t\t\thadPrimaryError,\n\t\t\t});\n\t\t\tif (hadPrimaryError) {\n\t\t\t\tthrow primaryError;\n\t\t\t}\n\t\t},\n\t\trunShellCommand: async (commandParams) =>\n\t\t\tawait runWithLeaseRenewal(\n\t\t\t\t'shell command',\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 GondolinSandboxBackendHandle;\n}\n","import { 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 {\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);\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\tFsBridgeLeaseContext,\n\tGondolinFsBridge,\n} from './sandbox-backend-factory.js';\n\nexport function createBackendDeps(ssh: SshHelpers): {\n\treadonly buildExecSpec: CreateBackendDependencies['buildExecSpec'];\n\treadonly createFsBridgeBuilder: (\n\t\tleaseContext: FsBridgeLeaseContext,\n\t) => (params: { readonly sandbox: unknown }) => GondolinFsBridge;\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: workdir,\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: FsBridgeLeaseContext) =>\n\t\t\t(params: { readonly sandbox: unknown }): GondolinFsBridge =>\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: '/work',\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","interface OpenClawAgentConfig {\n\treadonly [key: string]: unknown;\n\treadonly id?: unknown;\n\treadonly sandbox?: {\n\t\treadonly [key: string]: unknown;\n\t\treadonly backend?: unknown;\n\t\treadonly mode?: unknown;\n\t\treadonly scope?: unknown;\n\t\treadonly workspaceAccess?: unknown;\n\t};\n\treadonly workspace?: unknown;\n}\n\ninterface OpenClawRuntimeConfig {\n\treadonly [key: string]: unknown;\n\treadonly agents?: {\n\t\treadonly defaults?: OpenClawAgentConfig;\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: OpenClawAgentConfig;\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 effectiveSandboxValue(\n\tdefaults: OpenClawAgentConfig,\n\tagentConfig: OpenClawAgentConfig,\n\tkey: 'backend' | 'mode' | 'scope' | 'workspaceAccess',\n): unknown {\n\treturn agentConfig.sandbox?.[key] ?? defaults.sandbox?.[key];\n}\n\nfunction effectiveWorkspace(\n\tdefaults: OpenClawAgentConfig,\n\tagentConfig: OpenClawAgentConfig,\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: `openclaw-tool-vm-${options.fieldPath.replace(/[.[\\]]/gu, '-')}-${options.zoneId}-${options.label}`,\n\t\tok,\n\t\thint: ok\n\t\t\t? `${options.fieldPath}=${options.expectedValue}`\n\t\t\t: `Set ${options.fieldPath} to \"${options.expectedValue}\" for OpenClaw Tool VM mediation.`,\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\treturn [\n\t\t\t\trequirementFinding({\n\t\t\t\t\tactualValue: effectiveSandboxValue(defaults, agentConfig, 'backend'),\n\t\t\t\t\texpectedValue: 'gondolin',\n\t\t\t\t\tfieldPath: `agents.${label}.sandbox.backend`,\n\t\t\t\t\tlabel,\n\t\t\t\t\tzoneId: options.zoneId,\n\t\t\t\t}),\n\t\t\t\trequirementFinding({\n\t\t\t\t\tactualValue: effectiveSandboxValue(defaults, agentConfig, 'mode'),\n\t\t\t\t\texpectedValue: 'all',\n\t\t\t\t\tfieldPath: `agents.${label}.sandbox.mode`,\n\t\t\t\t\tlabel,\n\t\t\t\t\tzoneId: options.zoneId,\n\t\t\t\t}),\n\t\t\t\trequirementFinding({\n\t\t\t\t\tactualValue: effectiveSandboxValue(defaults, agentConfig, 'scope'),\n\t\t\t\t\texpectedValue: 'agent',\n\t\t\t\t\tfieldPath: `agents.${label}.sandbox.scope`,\n\t\t\t\t\tlabel,\n\t\t\t\t\tzoneId: options.zoneId,\n\t\t\t\t}),\n\t\t\t\trequirementFinding({\n\t\t\t\t\tactualValue: effectiveSandboxValue(defaults, agentConfig, 'workspaceAccess'),\n\t\t\t\t\texpectedValue: 'rw',\n\t\t\t\t\tfieldPath: `agents.${label}.sandbox.workspaceAccess`,\n\t\t\t\t\tlabel,\n\t\t\t\t\tzoneId: options.zoneId,\n\t\t\t\t}),\n\t\t\t\t{\n\t\t\t\t\tid: `openclaw-tool-vm-workspace-${options.zoneId}-${label}`,\n\t\t\t\t\tok: workspace !== '/zone',\n\t\t\t\t\thint:\n\t\t\t\t\t\tworkspace === '/zone'\n\t\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\t: typeof workspace === 'string'\n\t\t\t\t\t\t\t\t? workspace\n\t\t\t\t\t\t\t\t: 'agents workspace is unset',\n\t\t\t\t},\n\t\t\t] as const satisfies readonly OpenClawRuntimeRequirementFinding[];\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').GondolinFsBridge;\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 { createBackendDeps } 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 { 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 { 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"],"sources":["../src/controller-lease-client.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';\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 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: {\n\t\treadonly agentWorkspaceDir: string;\n\t\treadonly profileId: string;\n\t\treadonly scopeKey: string;\n\t\treadonly workMountDir: string;\n\t\treadonly zoneId: string;\n\t}): 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: unknown;\n\treadonly status: number;\n\n\tconstructor(options: {\n\t\treadonly bodyText: string;\n\t\treadonly context: string;\n\t\treadonly responseBody: unknown;\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(`${options.context} returned HTTP ${String(options.status)} (${kind})`);\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\nfunction objectValue(value: unknown): object | undefined {\n\treturn typeof value === 'object' && value !== null ? value : undefined;\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): unknown {\n\ttry {\n\t\treturn JSON.parse(bodyText);\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: unknown;\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\tagentWorkspaceDir: request.agentWorkspaceDir,\n\t\t\t\t\tprofileId: request.profileId,\n\t\t\t\t\tscopeKey: request.scopeKey,\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","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\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 scopeCacheKey(params: {\n\treadonly agentWorkspaceDir: string;\n\treadonly profileId: string;\n\treadonly scopeKey: string;\n\treadonly workspaceDir: string;\n\treadonly zoneId: string;\n}): string {\n\treturn [\n\t\tparams.zoneId,\n\t\tparams.scopeKey,\n\t\tparams.profileId,\n\t\tparams.agentWorkspaceDir,\n\t\tparams.workspaceDir,\n\t].join('\\0');\n}\n\nfunction formatUnknownError(error: unknown): string {\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\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: {\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 cacheKey = scopeCacheKey({\n\t\t\tagentWorkspaceDir: params.agentWorkspaceDir,\n\t\t\tprofileId,\n\t\t\tscopeKey: params.scopeKey,\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// backs the Tool VM /work mount.\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\tagentWorkspaceDir: params.agentWorkspaceDir,\n\t\t\tprofileId,\n\t\t\tscopeKey: params.scopeKey,\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 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: workdir,\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: '/work',\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","interface OpenClawAgentConfig {\n\treadonly [key: string]: unknown;\n\treadonly id?: unknown;\n\treadonly sandbox?: {\n\t\treadonly [key: string]: unknown;\n\t\treadonly backend?: unknown;\n\t\treadonly mode?: unknown;\n\t\treadonly scope?: unknown;\n\t\treadonly workspaceAccess?: unknown;\n\t};\n\treadonly workspace?: unknown;\n}\n\ninterface OpenClawRuntimeConfig {\n\treadonly [key: string]: unknown;\n\treadonly agents?: {\n\t\treadonly defaults?: OpenClawAgentConfig;\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: OpenClawAgentConfig;\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 effectiveSandboxValue(\n\tdefaults: OpenClawAgentConfig,\n\tagentConfig: OpenClawAgentConfig,\n\tkey: 'backend' | 'mode' | 'scope' | 'workspaceAccess',\n): unknown {\n\treturn agentConfig.sandbox?.[key] ?? defaults.sandbox?.[key];\n}\n\nfunction effectiveWorkspace(\n\tdefaults: OpenClawAgentConfig,\n\tagentConfig: OpenClawAgentConfig,\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: `openclaw-tool-vm-${options.fieldPath.replace(/[.[\\]]/gu, '-')}-${options.zoneId}-${options.label}`,\n\t\tok,\n\t\thint: ok\n\t\t\t? `${options.fieldPath}=${options.expectedValue}`\n\t\t\t: `Set ${options.fieldPath} to \"${options.expectedValue}\" for OpenClaw Tool VM mediation.`,\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\treturn [\n\t\t\t\trequirementFinding({\n\t\t\t\t\tactualValue: effectiveSandboxValue(defaults, agentConfig, 'backend'),\n\t\t\t\t\texpectedValue: 'gondolin',\n\t\t\t\t\tfieldPath: `agents.${label}.sandbox.backend`,\n\t\t\t\t\tlabel,\n\t\t\t\t\tzoneId: options.zoneId,\n\t\t\t\t}),\n\t\t\t\trequirementFinding({\n\t\t\t\t\tactualValue: effectiveSandboxValue(defaults, agentConfig, 'mode'),\n\t\t\t\t\texpectedValue: 'all',\n\t\t\t\t\tfieldPath: `agents.${label}.sandbox.mode`,\n\t\t\t\t\tlabel,\n\t\t\t\t\tzoneId: options.zoneId,\n\t\t\t\t}),\n\t\t\t\trequirementFinding({\n\t\t\t\t\tactualValue: effectiveSandboxValue(defaults, agentConfig, 'scope'),\n\t\t\t\t\texpectedValue: 'agent',\n\t\t\t\t\tfieldPath: `agents.${label}.sandbox.scope`,\n\t\t\t\t\tlabel,\n\t\t\t\t\tzoneId: options.zoneId,\n\t\t\t\t}),\n\t\t\t\trequirementFinding({\n\t\t\t\t\tactualValue: effectiveSandboxValue(defaults, agentConfig, 'workspaceAccess'),\n\t\t\t\t\texpectedValue: 'rw',\n\t\t\t\t\tfieldPath: `agents.${label}.sandbox.workspaceAccess`,\n\t\t\t\t\tlabel,\n\t\t\t\t\tzoneId: options.zoneId,\n\t\t\t\t}),\n\t\t\t\t{\n\t\t\t\t\tid: `openclaw-tool-vm-workspace-${options.zoneId}-${label}`,\n\t\t\t\t\tok: workspace !== '/zone',\n\t\t\t\t\thint:\n\t\t\t\t\t\tworkspace === '/zone'\n\t\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\t: typeof workspace === 'string'\n\t\t\t\t\t\t\t\t? workspace\n\t\t\t\t\t\t\t\t: 'agents workspace is unset',\n\t\t\t\t},\n\t\t\t] as const satisfies readonly OpenClawRuntimeRequirementFinding[];\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 { createBackendDeps } 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 { 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 { 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.73",
|
|
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": {
|
|
@@ -29,7 +29,8 @@
|
|
|
29
29
|
"access": "public"
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"@agent-vm/
|
|
32
|
+
"@agent-vm/gateway-interface": "0.0.73",
|
|
33
|
+
"@agent-vm/gondolin-adapter": "0.0.73"
|
|
33
34
|
},
|
|
34
35
|
"scripts": {
|
|
35
36
|
"build": "tsdown && cp openclaw.plugin.json sdk-validate.mjs dist/",
|