@agent-vm/openclaw-gateway 0.0.96 → 0.0.98
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.map +1 -1
- package/dist/index.js +75 -7
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/openclaw-lifecycle.ts"],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/openclaw-lifecycle.ts"],"mappings":";;;cAyyBa,iBAAA,EAAmB,gBAAA"}
|
package/dist/index.js
CHANGED
|
@@ -18,13 +18,25 @@ const openClawRuntimeSecretsEnvFilePath = "/run/openclaw/secrets.env";
|
|
|
18
18
|
const openClawGatewayTokenEnvFilePath = "/run/openclaw/gateway-token.env";
|
|
19
19
|
const openClawCommandVmPath = "/usr/local/bin/openclaw";
|
|
20
20
|
const openClawGatewayGuestPath = "/pnpm:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin";
|
|
21
|
+
const diagnosticsOtelPluginId = "diagnostics-otel";
|
|
21
22
|
function isObjectRecord(value) {
|
|
22
23
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
23
24
|
}
|
|
25
|
+
function setTcpHost(tcpHosts, key, target) {
|
|
26
|
+
const existingTarget = tcpHosts[key];
|
|
27
|
+
if (existingTarget !== void 0 && existingTarget !== target) throw new Error(`OpenClaw tcpHosts entry '${key}' cannot target both '${existingTarget}' and '${target}'.`);
|
|
28
|
+
tcpHosts[key] = target;
|
|
29
|
+
}
|
|
24
30
|
function buildGatewayTcpHosts(zone, controllerPort, tcpPool) {
|
|
25
|
-
const tcpHosts = {
|
|
26
|
-
|
|
27
|
-
for (
|
|
31
|
+
const tcpHosts = {};
|
|
32
|
+
setTcpHost(tcpHosts, `${controllerVmHost}:18800`, `127.0.0.1:${controllerPort}`);
|
|
33
|
+
for (let slot = 0; slot < tcpPool.size; slot += 1) setTcpHost(tcpHosts, `tool-${slot}.vm.host:22`, `127.0.0.1:${tcpPool.basePort + slot}`);
|
|
34
|
+
for (const websocketHost of zone.websocketBypass) setTcpHost(tcpHosts, websocketHost, websocketHost);
|
|
35
|
+
if (zone.observability?.mode === "collector") {
|
|
36
|
+
const { collector } = zone.observability;
|
|
37
|
+
setTcpHost(tcpHosts, `${collector.host}:${String(collector.grpcPort)}`, `${collector.targetHost}:${String(collector.targetGrpcPort)}`);
|
|
38
|
+
setTcpHost(tcpHosts, `${collector.host}:${String(collector.httpPort)}`, `${collector.targetHost}:${String(collector.targetHttpPort)}`);
|
|
39
|
+
}
|
|
28
40
|
return tcpHosts;
|
|
29
41
|
}
|
|
30
42
|
function buildOpenClawBootstrapCommand(zone, resolvedSecrets) {
|
|
@@ -106,6 +118,7 @@ function assertAllowedOpenClawEnvironmentSecrets(zone, environmentSecrets, logPr
|
|
|
106
118
|
if (zone.gateway.type !== "openclaw") throw new Error(`OpenClaw lifecycle cannot build gateway type '${zone.gateway.type}'.`);
|
|
107
119
|
const allowedRawEnvSecrets = new Set([zone.gateway.controlAuth.secret, ...zone.gateway.rawEnvSecrets ?? []]);
|
|
108
120
|
for (const secretName of Object.keys(environmentSecrets)) {
|
|
121
|
+
if (zone.observability?.mode === "collector" && secretName === "OPENCLAW_DIAGNOSTICS") throw new Error(`[${logPrefix}] OpenClaw observability owns diagnostics configuration; do not inject OPENCLAW_DIAGNOSTICS through gateway raw environment secrets.`);
|
|
109
122
|
if (allowedRawEnvSecrets.has(secretName)) continue;
|
|
110
123
|
throw new Error(`[${logPrefix}] OpenClaw env secret '${secretName}' must be listed in gateway.rawEnvSecrets or use injection 'http-mediation'.`);
|
|
111
124
|
}
|
|
@@ -165,23 +178,36 @@ function buildEffectiveSecretsConfig(parsedBaseConfig) {
|
|
|
165
178
|
function buildEffectiveMcpPortalPluginConfig(_existingPluginConfig, runtimeConfig) {
|
|
166
179
|
return { ...runtimeConfig };
|
|
167
180
|
}
|
|
181
|
+
function appendUniqueStrings(existingValues, additionalValues) {
|
|
182
|
+
const values = [...existingValues];
|
|
183
|
+
for (const value of additionalValues) if (!values.includes(value)) values.push(value);
|
|
184
|
+
return values;
|
|
185
|
+
}
|
|
168
186
|
function buildEffectivePluginsConfig(parsedBaseConfig, runtimePluginConfigs) {
|
|
169
187
|
const existingPluginsConfig = isObjectRecord(parsedBaseConfig.plugins) ? parsedBaseConfig.plugins : {};
|
|
188
|
+
const runtimePluginIds = Object.keys(runtimePluginConfigs ?? {});
|
|
189
|
+
const existingAllowConfig = Array.isArray(existingPluginsConfig.allow) ? existingPluginsConfig.allow.filter((value) => typeof value === "string") : [];
|
|
170
190
|
const existingEntriesConfig = isObjectRecord(existingPluginsConfig.entries) ? existingPluginsConfig.entries : {};
|
|
171
|
-
const runtimeEntriesConfig =
|
|
191
|
+
const runtimeEntriesConfig = {};
|
|
192
|
+
for (const [pluginId, runtimeConfig] of Object.entries(runtimePluginConfigs ?? {})) {
|
|
172
193
|
const existingEntryConfig = isObjectRecord(existingEntriesConfig[pluginId]) ? existingEntriesConfig[pluginId] : {};
|
|
194
|
+
if (pluginId === diagnosticsOtelPluginId) {
|
|
195
|
+
runtimeEntriesConfig[pluginId] = { enabled: true };
|
|
196
|
+
continue;
|
|
197
|
+
}
|
|
173
198
|
const existingPluginConfig = isObjectRecord(existingEntryConfig.config) ? existingEntryConfig.config : {};
|
|
174
199
|
const config = pluginId === "mcp-portal" ? buildEffectiveMcpPortalPluginConfig(existingPluginConfig, runtimeConfig) : {
|
|
175
200
|
...existingPluginConfig,
|
|
176
201
|
...runtimeConfig
|
|
177
202
|
};
|
|
178
|
-
|
|
203
|
+
runtimeEntriesConfig[pluginId] = {
|
|
179
204
|
...existingEntryConfig,
|
|
180
205
|
config
|
|
181
|
-
}
|
|
182
|
-
}
|
|
206
|
+
};
|
|
207
|
+
}
|
|
183
208
|
return {
|
|
184
209
|
...existingPluginsConfig,
|
|
210
|
+
...runtimePluginIds.length > 0 ? { allow: appendUniqueStrings(existingAllowConfig, runtimePluginIds) } : {},
|
|
185
211
|
entries: {
|
|
186
212
|
...existingEntriesConfig,
|
|
187
213
|
...runtimeEntriesConfig
|
|
@@ -205,6 +231,44 @@ function buildEffectiveLoggingConfig(parsedBaseConfig) {
|
|
|
205
231
|
...isObjectRecord(parsedBaseConfig.logging) ? parsedBaseConfig.logging : {}
|
|
206
232
|
};
|
|
207
233
|
}
|
|
234
|
+
function assertObservabilityCompatibleLoggingConfig(parsedBaseConfig) {
|
|
235
|
+
const redactSensitiveValue = (isObjectRecord(parsedBaseConfig.logging) ? parsedBaseConfig.logging : {}).redactSensitive;
|
|
236
|
+
if (isDisabledOpenClawRedactionValue(redactSensitiveValue)) throw new Error("OpenClaw observability requires logging.redactSensitive to stay enabled; remove 'off' or false before enabling telemetry.");
|
|
237
|
+
}
|
|
238
|
+
function isDisabledOpenClawRedactionValue(value) {
|
|
239
|
+
if (value === false || value === 0) return true;
|
|
240
|
+
if (typeof value !== "string") return false;
|
|
241
|
+
return [
|
|
242
|
+
"0",
|
|
243
|
+
"disable",
|
|
244
|
+
"disabled",
|
|
245
|
+
"false",
|
|
246
|
+
"no",
|
|
247
|
+
"off"
|
|
248
|
+
].includes(value.trim().toLowerCase());
|
|
249
|
+
}
|
|
250
|
+
function buildEffectiveDiagnosticsConfig(parsedBaseConfig, zone) {
|
|
251
|
+
if (zone.observability?.mode !== "collector") return;
|
|
252
|
+
const existingDiagnosticsConfig = isObjectRecord(parsedBaseConfig.diagnostics) ? parsedBaseConfig.diagnostics : {};
|
|
253
|
+
const { collector, openclaw } = zone.observability;
|
|
254
|
+
return {
|
|
255
|
+
...existingDiagnosticsConfig,
|
|
256
|
+
enabled: true,
|
|
257
|
+
flags: openclaw.diagnosticsFlags,
|
|
258
|
+
otel: {
|
|
259
|
+
captureContent: { enabled: false },
|
|
260
|
+
enabled: true,
|
|
261
|
+
endpoint: `http://${collector.host}:${String(collector.httpPort)}`,
|
|
262
|
+
flushIntervalMs: openclaw.flushIntervalMs,
|
|
263
|
+
logs: openclaw.logs,
|
|
264
|
+
metrics: openclaw.metrics,
|
|
265
|
+
protocol: "http/protobuf",
|
|
266
|
+
sampleRate: openclaw.sampleRate,
|
|
267
|
+
serviceName: openclaw.serviceName,
|
|
268
|
+
traces: openclaw.traces
|
|
269
|
+
}
|
|
270
|
+
};
|
|
271
|
+
}
|
|
208
272
|
async function writeAuthProfilesIfConfigured(zone, secretResolver) {
|
|
209
273
|
const resolvedAuthProfiles = await resolveAuthProfilesIfConfigured(zone, secretResolver);
|
|
210
274
|
const writeErrors = (await Promise.allSettled(resolvedAuthProfiles.map(async ({ agentId, authProfiles }) => {
|
|
@@ -283,8 +347,10 @@ async function buildEffectiveOpenClawConfigContent(zone) {
|
|
|
283
347
|
const rawBaseConfig = await readFile(zone.gateway.config, "utf8");
|
|
284
348
|
const parsedBaseConfig = JSON.parse(rawBaseConfig);
|
|
285
349
|
if (!isObjectRecord(parsedBaseConfig)) throw new Error(`OpenClaw config at '${zone.gateway.config}' must be a JSON object.`);
|
|
350
|
+
if (zone.observability?.mode === "collector") assertObservabilityCompatibleLoggingConfig(parsedBaseConfig);
|
|
286
351
|
const runtimePluginConfigs = {
|
|
287
352
|
...zone.runtimePluginConfigs,
|
|
353
|
+
...zone.observability?.mode === "collector" ? { [diagnosticsOtelPluginId]: {} } : {},
|
|
288
354
|
gondolin: {
|
|
289
355
|
controllerUrl: `http://${controllerVmHost}:18800`,
|
|
290
356
|
gatewayControlLinkMonitor: {
|
|
@@ -298,9 +364,11 @@ async function buildEffectiveOpenClawConfigContent(zone) {
|
|
|
298
364
|
};
|
|
299
365
|
const config = isObjectRecord(parsedBaseConfig.gateway) ? parsedBaseConfig.gateway : {};
|
|
300
366
|
const existingAuthConfig = isObjectRecord(config.auth) ? config.auth : {};
|
|
367
|
+
const effectiveDiagnosticsConfig = buildEffectiveDiagnosticsConfig(parsedBaseConfig, zone);
|
|
301
368
|
const effectiveConfig = {
|
|
302
369
|
...parsedBaseConfig,
|
|
303
370
|
logging: buildEffectiveLoggingConfig(parsedBaseConfig),
|
|
371
|
+
...effectiveDiagnosticsConfig === void 0 ? {} : { diagnostics: effectiveDiagnosticsConfig },
|
|
304
372
|
gateway: {
|
|
305
373
|
...config,
|
|
306
374
|
auth: {
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["exhaustiveCheck","buildGatewaySessionLabelValue"],"sources":["../src/openclaw-lifecycle.ts"],"sourcesContent":["import { randomUUID } from 'node:crypto';\nimport { chmod, lstat, mkdir, readFile, rm } from 'node:fs/promises';\nimport path from 'node:path';\n\nimport type {\n\tBuildGatewayVmSpecOptions,\n\tGatewayLifecycle,\n\tGatewayProcessSpec,\n\tGatewayZoneConfig,\n\tGatewayVmSpec,\n\tSplitResolvedGatewaySecretsResult,\n} from '@agent-vm/gateway-interface';\nimport {\n\tbuildGatewaySessionLabel as buildGatewaySessionLabelValue,\n\tcomposeNodeOptions,\n\tcontrollerVmHost,\n\tFORCE_IPV4_EGRESS_NODE_OPTIONS,\n\tgatewayVmAllowedHosts,\n\tmergeRuntimeGatewaySecrets,\n\tsplitResolvedGatewaySecrets,\n} from '@agent-vm/gateway-interface';\nimport { writeFileAtomically } from '@agent-vm/gondolin-adapter';\nimport {\n\tredactOnePasswordReferences,\n\ttype SecretRef,\n\ttype SecretResolver,\n} from '@agent-vm/secret-management';\n\nconst effectiveOpenClawConfigFileName = 'effective-openclaw.json';\nconst effectiveOpenClawConfigVmPath = `/home/openclaw/.openclaw/state/${effectiveOpenClawConfigFileName}`;\nconst openClawStateDirVmPath = '/home/openclaw/.openclaw/state';\nconst openClawCacheDirVmPath = '/home/openclaw/.openclaw/cache';\nconst openClawZoneFilesDirVmPath = '/zone';\nconst agentVmLogsDirVmPath = '/agent-vm/logs';\nconst openClawRuntimeLogFileVmPath = `${agentVmLogsDirVmPath}/openclaw-YYYY-MM-DD.log`;\nconst openClawGatewayBootLogFileVmPath = `${agentVmLogsDirVmPath}/gateway-boot-latest.log`;\nconst openClawShellEnvFilePath = '/etc/profile.d/openclaw-env.sh';\nconst openClawRuntimeSecretsEnvFilePath = '/run/openclaw/secrets.env';\nconst openClawGatewayTokenEnvFilePath = '/run/openclaw/gateway-token.env';\nconst openClawCommandVmPath = '/usr/local/bin/openclaw';\nconst openClawGatewayGuestPath =\n\t'/pnpm:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin';\n\ninterface OpenClawSecretRef {\n\treadonly id: string;\n\treadonly provider: string;\n\treadonly source: 'env';\n}\n\nfunction isObjectRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction buildGatewayTcpHosts(\n\tzone: GatewayZoneConfig,\n\tcontrollerPort: number,\n\ttcpPool: { readonly basePort: number; readonly size: number },\n): Record<string, string> {\n\tconst tcpHosts: Record<string, string> = {\n\t\t[`${controllerVmHost}:18800`]: `127.0.0.1:${controllerPort}`,\n\t};\n\n\tfor (let slot = 0; slot < tcpPool.size; slot += 1) {\n\t\ttcpHosts[`tool-${slot}.vm.host:22`] = `127.0.0.1:${tcpPool.basePort + slot}`;\n\t}\n\n\tfor (const websocketHost of zone.websocketBypass) {\n\t\ttcpHosts[websocketHost] = websocketHost;\n\t}\n\n\treturn tcpHosts;\n}\n\nfunction buildOpenClawBootstrapCommand(\n\tzone: GatewayZoneConfig,\n\tresolvedSecrets: Record<string, string>,\n): string {\n\tif (zone.gateway.type !== 'openclaw') {\n\t\tthrow new Error(`OpenClaw lifecycle cannot build gateway type '${zone.gateway.type}'.`);\n\t}\n\tconst { environmentSecrets } = mergeRuntimeGatewaySecrets(\n\t\tsplitAllowedOpenClawGatewaySecrets(zone, resolvedSecrets, 'openclaw-bootstrap-raw-env-secrets'),\n\t\t{\n\t\t\tlogPrefix: 'openclaw-bootstrap-runtime-secrets',\n\t\t\truntimeEnvironment: zone.runtimeEnvironment,\n\t\t\truntimeMediatedSecrets: zone.runtimeMediatedSecrets,\n\t\t},\n\t);\n\tassertAllowedOpenClawEnvironmentSecrets(\n\t\tzone,\n\t\tenvironmentSecrets,\n\t\t'openclaw-bootstrap-runtime-raw-env-secrets',\n\t);\n\tconst environmentLines = [\n\t\t'export OPENCLAW_HOME=/home/openclaw',\n\t\t`export OPENCLAW_CONFIG_PATH=${effectiveOpenClawConfigVmPath}`,\n\t\t`export OPENCLAW_STATE_DIR=${openClawStateDirVmPath}`,\n\t\t'export PNPM_HOME=/pnpm',\n\t\t'export PATH=/pnpm:$PATH',\n\t\t'export TMPDIR=/work/tmp',\n\t\t'export TMP=/work/tmp',\n\t\t'export TEMP=/work/tmp',\n\t\t'export npm_config_cache=/work/cache/npm',\n\t\t'export pnpm_config_store_dir=/work/cache/pnpm/store',\n\t\t'export PIP_CACHE_DIR=/work/cache/pip',\n\t\t'export UV_CACHE_DIR=/work/cache/uv',\n\t\t'export NODE_EXTRA_CA_CERTS=/run/gondolin/ca-certificates.crt',\n\t\t// Prepend each forced IPv4-preference flag only when it is not\n\t\t// already present. The VM env normally carries these flags\n\t\t// already; the profile keeps interactive shells safe without\n\t\t// duplicating the boot-log value.\n\t\t...FORCE_IPV4_EGRESS_NODE_OPTIONS.split(' ').map(\n\t\t\t(nodeOptionFlag) =>\n\t\t\t\t`case \" \\${NODE_OPTIONS:-} \" in *\" ${nodeOptionFlag} \"*) ;; *) export NODE_OPTIONS=\"${nodeOptionFlag}\\${NODE_OPTIONS:+ \\${NODE_OPTIONS}}\";; esac`,\n\t\t),\n\t];\n\tconst secretEnvironmentNames = Object.entries({\n\t\t...environmentSecrets,\n\t\t...zone.runtimeEnvironment,\n\t}).map(([secretName, secretValue]) => {\n\t\tassertShellSafeEnvName(secretName);\n\t\tassertShellProfileSafeSecretValue(secretName, secretValue);\n\t\treturn secretName;\n\t});\n\tconst secretsFileCommand =\n\t\tsecretEnvironmentNames.length === 0\n\t\t\t? `: > ${openClawRuntimeSecretsEnvFilePath} && `\n\t\t\t: `{ ${secretEnvironmentNames.map(runtimeSecretLiteralExportCommand).join('; ')}; } > ${openClawRuntimeSecretsEnvFilePath} && `;\n\tconst gatewayTokenSecretName = zone.gateway.controlAuth.secret;\n\tconst gatewayTokenFileCommand = secretEnvironmentNames.includes(gatewayTokenSecretName)\n\t\t? `{ ${runtimeSecretLiteralExportCommand(gatewayTokenSecretName)}; } > ${openClawGatewayTokenEnvFilePath} && `\n\t\t: `: > ${openClawGatewayTokenEnvFilePath} && `;\n\tconst sshConfigLines = ['Host tool-*.vm.host', ' AddressFamily inet'];\n\tconst sshConfigCommand =\n\t\t`mkdir -p /root/.ssh /home/openclaw/.ssh && ` +\n\t\t`printf '%s\\\\n' ${sshConfigLines.map((line) => shellQuote(line)).join(' ')} > /root/.ssh/config && ` +\n\t\t'cp /root/.ssh/config /home/openclaw/.ssh/config && ' +\n\t\t'chown -R openclaw:openclaw /home/openclaw/.ssh && ' +\n\t\t'chmod 700 /root/.ssh /home/openclaw/.ssh && ' +\n\t\t'chmod 600 /root/.ssh/config /home/openclaw/.ssh/config && ';\n\n\treturn (\n\t\t`mkdir -p /root /etc/profile.d /run/openclaw /work/tmp /work/cache/npm /work/cache/pnpm/store /work/cache/pip /work/cache/uv && chown -R openclaw:openclaw /work && cat > ${openClawShellEnvFilePath} << 'ENVEOF'\\n` +\n\t\tenvironmentLines.join('\\n') +\n\t\t'\\nENVEOF\\n' +\n\t\t`chmod 644 ${openClawShellEnvFilePath} && ` +\n\t\tsecretsFileCommand +\n\t\t`chmod 600 ${openClawRuntimeSecretsEnvFilePath} && ` +\n\t\tgatewayTokenFileCommand +\n\t\t`chmod 600 ${openClawGatewayTokenEnvFilePath} && ` +\n\t\tsshConfigCommand +\n\t\t'touch /root/.bashrc && ' +\n\t\t`grep -qxF 'source ${openClawShellEnvFilePath}' /root/.bashrc || echo 'source ${openClawShellEnvFilePath}' >> /root/.bashrc && ` +\n\t\t'touch /root/.bash_profile && ' +\n\t\t\"grep -qxF 'source /root/.bashrc' /root/.bash_profile || echo 'source /root/.bashrc' >> /root/.bash_profile\"\n\t);\n}\n\nfunction getEffectiveOpenClawConfigHostPath(zone: GatewayZoneConfig): string {\n\treturn path.join(zone.gateway.stateDir, effectiveOpenClawConfigFileName);\n}\n\nasync function assertEffectiveConfigPathWritable(\n\tzone: GatewayZoneConfig,\n\tcontent: string,\n): Promise<void> {\n\tconst effectiveConfigPath = getEffectiveOpenClawConfigHostPath(zone);\n\tconst existingEffectiveConfig = await lstat(effectiveConfigPath).catch((error: unknown) => {\n\t\tif (isObjectRecord(error) && error.code === 'ENOENT') {\n\t\t\treturn undefined;\n\t\t}\n\t\tthrow error;\n\t});\n\tif (existingEffectiveConfig?.isDirectory()) {\n\t\tthrow new Error(`Effective OpenClaw config path '${effectiveConfigPath}' is a directory.`);\n\t}\n\n\tconst preflightPath = path.join(\n\t\tzone.gateway.stateDir,\n\t\t`.agent-vm-effective-openclaw-preflight-${process.pid}-${randomUUID()}.json`,\n\t);\n\ttry {\n\t\tawait writeFileAtomically(preflightPath, content, { mode: 0o600 });\n\t} finally {\n\t\tawait rm(preflightPath, { force: true });\n\t}\n}\n\nfunction shellQuote(value: string): string {\n\treturn `'${value.replace(/'/gu, `'\\\\''`)}'`;\n}\n\nfunction includesShellUnsafeControlByte(value: string): boolean {\n\tfor (const character of value) {\n\t\tconst codePoint = character.codePointAt(0);\n\t\tif (codePoint !== undefined && (codePoint <= 0x1f || codePoint === 0x7f)) {\n\t\t\treturn true;\n\t\t}\n\t}\n\treturn false;\n}\n\nfunction assertShellSafeEnvName(secretName: string): void {\n\tif (!/^[_A-Za-z][_0-9A-Za-z]*$/u.test(secretName)) {\n\t\tthrow new Error(\n\t\t\t`OpenClaw env-injected gateway secret '${secretName}' must be a shell-safe environment variable name.`,\n\t\t);\n\t}\n}\n\nfunction assertShellProfileSafeSecretValue(secretName: string, value: string): void {\n\tif (includesShellUnsafeControlByte(value)) {\n\t\tthrow new Error(\n\t\t\t`OpenClaw env-injected gateway secret '${secretName}' must be a single-line value without control bytes. Use http-mediation for secrets that require structured transport.`,\n\t\t);\n\t}\n}\n\nfunction runtimeSecretLiteralExportCommand(secretName: string): string {\n\tconst runtimeSecretValue = `\"\\${${secretName}?missing runtime secret ${secretName}}\"`;\n\treturn `secret_value=${runtimeSecretValue} && escaped_secret_value=\"$(printf '%s' \"$secret_value\" | sed 's/[\"\\\\\\\\$\\`]/\\\\\\\\&/g')\" && printf 'export ${secretName}=\"%s\"\\\\n' \"$escaped_secret_value\"`;\n}\n\nfunction assertAllowedOpenClawEnvironmentSecrets(\n\tzone: GatewayZoneConfig,\n\tenvironmentSecrets: Readonly<Record<string, string>>,\n\tlogPrefix: string,\n): void {\n\tif (zone.gateway.type !== 'openclaw') {\n\t\tthrow new Error(`OpenClaw lifecycle cannot build gateway type '${zone.gateway.type}'.`);\n\t}\n\tconst allowedRawEnvSecrets = new Set([\n\t\tzone.gateway.controlAuth.secret,\n\t\t...(zone.gateway.rawEnvSecrets ?? []),\n\t]);\n\tfor (const secretName of Object.keys(environmentSecrets)) {\n\t\tif (allowedRawEnvSecrets.has(secretName)) {\n\t\t\tcontinue;\n\t\t}\n\t\tthrow new Error(\n\t\t\t`[${logPrefix}] OpenClaw env secret '${secretName}' must be listed in gateway.rawEnvSecrets or use injection 'http-mediation'.`,\n\t\t);\n\t}\n}\n\nfunction splitAllowedOpenClawGatewaySecrets(\n\tzone: GatewayZoneConfig,\n\tresolvedSecrets: Record<string, string>,\n\tlogPrefix: string,\n): SplitResolvedGatewaySecretsResult {\n\tconst splitSecrets = splitResolvedGatewaySecrets(zone, resolvedSecrets);\n\tassertAllowedOpenClawEnvironmentSecrets(zone, splitSecrets.environmentSecrets, logPrefix);\n\treturn splitSecrets;\n}\n\ntype SourceAwareSecretReference =\n\t| {\n\t\t\treadonly source: 'environment';\n\t\t\treadonly envVar: string;\n\t }\n\t| {\n\t\t\treadonly source: '1password';\n\t\t\treadonly ref: string;\n\t }\n\t| {\n\t\t\treadonly source: 'config';\n\t\t\treadonly value: string;\n\t };\n\nfunction isSourceAwareSecretReference(value: unknown): value is SourceAwareSecretReference {\n\tif (typeof value !== 'object' || value === null) {\n\t\treturn false;\n\t}\n\n\tif (!('source' in value) || typeof value.source !== 'string') {\n\t\treturn false;\n\t}\n\n\tif (value.source === 'environment') {\n\t\treturn 'envVar' in value && typeof value.envVar === 'string';\n\t}\n\n\tif (value.source === '1password') {\n\t\treturn 'ref' in value && typeof value.ref === 'string';\n\t}\n\n\tif (value.source === 'config') {\n\t\treturn 'value' in value && typeof value.value === 'string';\n\t}\n\n\treturn false;\n}\n\nfunction toSecretRef(secret: SourceAwareSecretReference): SecretRef {\n\tswitch (secret.source) {\n\t\tcase 'environment':\n\t\t\treturn {\n\t\t\t\tsource: 'environment',\n\t\t\t\tref: secret.envVar,\n\t\t\t};\n\t\tcase '1password':\n\t\t\treturn {\n\t\t\t\tsource: '1password',\n\t\t\t\tref: secret.ref,\n\t\t\t};\n\t\tcase 'config':\n\t\t\treturn {\n\t\t\t\tsource: 'config',\n\t\t\t\tvalue: secret.value,\n\t\t\t};\n\t\tdefault: {\n\t\t\tconst exhaustiveCheck: never = secret;\n\t\t\tthrow new Error(`Unsupported secret source: ${JSON.stringify(exhaustiveCheck)}`);\n\t\t}\n\t}\n}\n\nfunction describeSecretReference(secret: SourceAwareSecretReference): string {\n\tswitch (secret.source) {\n\t\tcase 'environment':\n\t\t\treturn secret.envVar;\n\t\tcase '1password':\n\t\t\treturn redactOnePasswordReferences(secret.ref);\n\t\tcase 'config':\n\t\t\treturn 'config value';\n\t\tdefault: {\n\t\t\tconst exhaustiveCheck: never = secret;\n\t\t\tthrow new Error(`Unsupported secret source: ${JSON.stringify(exhaustiveCheck)}`);\n\t\t}\n\t}\n}\n\nfunction formatSafeOpenClawErrorMessage(error: unknown): string {\n\treturn redactOnePasswordReferences(error instanceof Error ? error.message : String(error));\n}\n\nfunction buildEffectiveSecretsConfig(\n\tparsedBaseConfig: Record<string, unknown>,\n): Record<string, unknown> {\n\tconst existingSecretsConfig = isObjectRecord(parsedBaseConfig.secrets)\n\t\t? parsedBaseConfig.secrets\n\t\t: {};\n\tconst existingProvidersConfig = isObjectRecord(existingSecretsConfig.providers)\n\t\t? existingSecretsConfig.providers\n\t\t: {};\n\n\treturn {\n\t\t...existingSecretsConfig,\n\t\tproviders: {\n\t\t\t...existingProvidersConfig,\n\t\t\tdefault: {\n\t\t\t\tsource: 'env',\n\t\t\t},\n\t\t},\n\t};\n}\n\nfunction buildEffectiveMcpPortalPluginConfig(\n\t_existingPluginConfig: Record<string, unknown>,\n\truntimeConfig: Readonly<Record<string, unknown>>,\n): Record<string, unknown> {\n\treturn {\n\t\t...runtimeConfig,\n\t};\n}\n\nfunction buildEffectivePluginsConfig(\n\tparsedBaseConfig: Record<string, unknown>,\n\truntimePluginConfigs: Readonly<Record<string, Readonly<Record<string, unknown>>>> | undefined,\n): Record<string, unknown> {\n\tconst existingPluginsConfig = isObjectRecord(parsedBaseConfig.plugins)\n\t\t? parsedBaseConfig.plugins\n\t\t: {};\n\tconst existingEntriesConfig = isObjectRecord(existingPluginsConfig.entries)\n\t\t? existingPluginsConfig.entries\n\t\t: {};\n\tconst runtimeEntriesConfig = Object.fromEntries(\n\t\tObject.entries(runtimePluginConfigs ?? {}).map(([pluginId, runtimeConfig]) => {\n\t\t\tconst existingEntryConfig = isObjectRecord(existingEntriesConfig[pluginId])\n\t\t\t\t? existingEntriesConfig[pluginId]\n\t\t\t\t: {};\n\t\t\tconst existingPluginConfig = isObjectRecord(existingEntryConfig.config)\n\t\t\t\t? existingEntryConfig.config\n\t\t\t\t: {};\n\t\t\tconst config =\n\t\t\t\tpluginId === 'mcp-portal'\n\t\t\t\t\t? buildEffectiveMcpPortalPluginConfig(existingPluginConfig, runtimeConfig)\n\t\t\t\t\t: {\n\t\t\t\t\t\t\t...existingPluginConfig,\n\t\t\t\t\t\t\t...runtimeConfig,\n\t\t\t\t\t\t};\n\t\t\treturn [\n\t\t\t\tpluginId,\n\t\t\t\t{\n\t\t\t\t\t...existingEntryConfig,\n\t\t\t\t\tconfig,\n\t\t\t\t},\n\t\t\t] as const;\n\t\t}),\n\t);\n\n\treturn {\n\t\t...existingPluginsConfig,\n\t\tentries: {\n\t\t\t...existingEntriesConfig,\n\t\t\t...runtimeEntriesConfig,\n\t\t},\n\t};\n}\n\nfunction buildEffectiveMcpConfig(\n\tparsedBaseConfig: Record<string, unknown>,\n\truntimeMcpServers: Readonly<Record<string, unknown>> | undefined,\n): Record<string, unknown> {\n\tconst existingMcpConfig = isObjectRecord(parsedBaseConfig.mcp) ? parsedBaseConfig.mcp : {};\n\tconst existingServersConfig = isObjectRecord(existingMcpConfig.servers)\n\t\t? existingMcpConfig.servers\n\t\t: {};\n\treturn {\n\t\t...existingMcpConfig,\n\t\tservers: {\n\t\t\t...existingServersConfig,\n\t\t\t...runtimeMcpServers,\n\t\t},\n\t};\n}\n\nfunction buildEffectiveLoggingConfig(\n\tparsedBaseConfig: Record<string, unknown>,\n): Record<string, unknown> {\n\tconst existingLoggingConfig = isObjectRecord(parsedBaseConfig.logging)\n\t\t? parsedBaseConfig.logging\n\t\t: {};\n\n\treturn {\n\t\tfile: openClawRuntimeLogFileVmPath,\n\t\t...existingLoggingConfig,\n\t};\n}\n\nasync function writeAuthProfilesIfConfigured(\n\tzone: GatewayZoneConfig,\n\tsecretResolver: SecretResolver,\n): Promise<void> {\n\tconst resolvedAuthProfiles = await resolveAuthProfilesIfConfigured(zone, secretResolver);\n\n\tconst writeResults = await Promise.allSettled(\n\t\tresolvedAuthProfiles.map(async ({ agentId, authProfiles }) => {\n\t\t\tconst authProfilesDirectory = path.join(zone.gateway.stateDir, 'agents', agentId, 'agent');\n\t\t\tawait mkdir(authProfilesDirectory, { recursive: true, mode: 0o700 });\n\t\t\tawait chmod(authProfilesDirectory, 0o700);\n\t\t\tawait writeFileAtomically(\n\t\t\t\tpath.join(authProfilesDirectory, 'auth-profiles.json'),\n\t\t\t\tauthProfiles,\n\t\t\t\t{\n\t\t\t\t\tmode: 0o600,\n\t\t\t\t},\n\t\t\t);\n\t\t}),\n\t);\n\tconst writeErrors = writeResults\n\t\t.filter((result): result is PromiseRejectedResult => result.status === 'rejected')\n\t\t.map((result) =>\n\t\t\tresult.reason instanceof Error ? result.reason : new Error(String(result.reason)),\n\t\t);\n\tif (writeErrors.length > 0) {\n\t\tthrow new AggregateError(\n\t\t\twriteErrors,\n\t\t\t`Failed to write ${String(writeErrors.length)} OpenClaw auth profile file(s) for zone '${zone.id}'.`,\n\t\t);\n\t}\n}\n\nasync function assertAuthProfilePathWritable(\n\tzone: GatewayZoneConfig,\n\tagentId: string,\n): Promise<void> {\n\tconst authProfilesDirectory = path.join(zone.gateway.stateDir, 'agents', agentId, 'agent');\n\tconst authProfilesPath = path.join(authProfilesDirectory, 'auth-profiles.json');\n\tconst existingAuthProfilesPath = await lstat(authProfilesPath).catch((error: unknown) => {\n\t\tif (isObjectRecord(error) && error.code === 'ENOENT') {\n\t\t\treturn undefined;\n\t\t}\n\t\tthrow error;\n\t});\n\tif (existingAuthProfilesPath?.isDirectory()) {\n\t\tthrow new Error(`OpenClaw auth profiles path '${authProfilesPath}' is a directory.`);\n\t}\n\n\tconst preflightPath = path.join(\n\t\tauthProfilesDirectory,\n\t\t`.agent-vm-auth-profiles-preflight-${process.pid}-${randomUUID()}.json`,\n\t);\n\ttry {\n\t\tawait mkdir(authProfilesDirectory, { recursive: true, mode: 0o700 });\n\t\tawait chmod(authProfilesDirectory, 0o700);\n\t\tawait writeFileAtomically(preflightPath, '{}\\n', { mode: 0o600 });\n\t} finally {\n\t\tawait rm(preflightPath, { force: true });\n\t}\n}\n\nasync function preflightAuthProfilesIfConfigured(\n\tzone: GatewayZoneConfig,\n\tsecretResolver: SecretResolver,\n): Promise<void> {\n\tconst resolvedAuthProfiles = await resolveAuthProfilesIfConfigured(zone, secretResolver);\n\tconst writeResults = await Promise.allSettled(\n\t\tresolvedAuthProfiles.map(async ({ agentId }) => {\n\t\t\tawait assertAuthProfilePathWritable(zone, agentId);\n\t\t}),\n\t);\n\tconst writeErrors = writeResults\n\t\t.filter((result): result is PromiseRejectedResult => result.status === 'rejected')\n\t\t.map((result) =>\n\t\t\tresult.reason instanceof Error ? result.reason : new Error(String(result.reason)),\n\t\t);\n\tif (writeErrors.length > 0) {\n\t\tthrow new AggregateError(\n\t\t\twriteErrors,\n\t\t\t`Failed to preflight ${String(writeErrors.length)} OpenClaw auth profile file write(s) for zone '${zone.id}'.`,\n\t\t);\n\t}\n}\n\nasync function resolveAuthProfilesIfConfigured(\n\tzone: GatewayZoneConfig,\n\tsecretResolver: SecretResolver,\n): Promise<readonly { readonly agentId: string; readonly authProfiles: string }[]> {\n\tconst authProfilesByAgent = {\n\t\t...(zone.gateway.authProfilesRef ? { main: zone.gateway.authProfilesRef } : {}),\n\t\t...(zone.gateway.type === 'openclaw' ? (zone.gateway.authProfilesByAgent ?? {}) : {}),\n\t};\n\n\tconst resolveResults = await Promise.allSettled(\n\t\tObject.entries(authProfilesByAgent).map(async ([agentId, authProfilesSecretCandidate]) => {\n\t\t\tif (!isSourceAwareSecretReference(authProfilesSecretCandidate)) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Zone '${zone.id}' has an invalid auth profile shape for agent '${agentId}'.`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst authProfilesSecret = authProfilesSecretCandidate;\n\n\t\t\ttry {\n\t\t\t\tconst authProfiles = await secretResolver.resolve(toSecretRef(authProfilesSecret));\n\t\t\t\treturn { agentId, authProfiles };\n\t\t\t} catch (error) {\n\t\t\t\tconst message = formatSafeOpenClawErrorMessage(error);\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Failed to resolve OpenClaw auth profiles for zone '${zone.id}' agent '${agentId}' from '${describeSecretReference(authProfilesSecret)}': ${message}`,\n\t\t\t\t\t{ cause: error },\n\t\t\t\t);\n\t\t\t}\n\t\t}),\n\t);\n\tconst resolveErrors = resolveResults\n\t\t.filter((result): result is PromiseRejectedResult => result.status === 'rejected')\n\t\t.map((result) =>\n\t\t\tresult.reason instanceof Error ? result.reason : new Error(String(result.reason)),\n\t\t);\n\tif (resolveErrors.length > 0) {\n\t\tthrow new AggregateError(\n\t\t\tresolveErrors,\n\t\t\t`Failed to resolve ${String(resolveErrors.length)} OpenClaw auth profile secret(s) for zone '${zone.id}'.`,\n\t\t);\n\t}\n\treturn resolveResults\n\t\t.filter(\n\t\t\t(\n\t\t\t\tresult,\n\t\t\t): result is PromiseFulfilledResult<{\n\t\t\t\treadonly agentId: string;\n\t\t\t\treadonly authProfiles: string;\n\t\t\t}> => result.status === 'fulfilled',\n\t\t)\n\t\t.map((result) => result.value);\n}\n\nasync function buildEffectiveOpenClawConfigContent(zone: GatewayZoneConfig): Promise<string> {\n\tif (zone.gateway.type !== 'openclaw') {\n\t\tthrow new Error(`OpenClaw lifecycle cannot build gateway type '${zone.gateway.type}'.`);\n\t}\n\tconst gatewayTokenSecretName = zone.gateway.controlAuth.secret;\n\tconst gatewayTokenSecret = zone.secrets[gatewayTokenSecretName];\n\tif (!gatewayTokenSecret) {\n\t\tthrow new Error(\n\t\t\t`Zone '${zone.id}' secret '${gatewayTokenSecretName}' is missing. Add an explicit 1Password or environment reference for the gateway token.`,\n\t\t);\n\t}\n\tif (!isSourceAwareSecretReference(gatewayTokenSecret)) {\n\t\tthrow new Error(`Zone '${zone.id}' secret '${gatewayTokenSecretName}' has an invalid shape.`);\n\t}\n\n\ttry {\n\t\tif (gatewayTokenSecret.source === '1password' && !gatewayTokenSecret.ref) {\n\t\t\tthrow new Error(\n\t\t\t\t`Zone '${zone.id}' secret '${gatewayTokenSecretName}' is missing 'ref'. Add an explicit 1Password reference for the gateway token.`,\n\t\t\t);\n\t\t}\n\t\tif (gatewayTokenSecret.source === 'environment' && !gatewayTokenSecret.envVar) {\n\t\t\tthrow new Error(\n\t\t\t\t`Zone '${zone.id}' secret '${gatewayTokenSecretName}' is missing 'envVar'. Add an explicit environment variable name.`,\n\t\t\t);\n\t\t}\n\t\tconst openClawGatewayTokenSecretRef: OpenClawSecretRef = {\n\t\t\tid: gatewayTokenSecretName,\n\t\t\tprovider: 'default',\n\t\t\tsource: 'env',\n\t\t};\n\t\tconst rawBaseConfig = await readFile(zone.gateway.config, 'utf8');\n\t\tconst parsedBaseConfig: unknown = JSON.parse(rawBaseConfig);\n\t\tif (!isObjectRecord(parsedBaseConfig)) {\n\t\t\tthrow new Error(`OpenClaw config at '${zone.gateway.config}' must be a JSON object.`);\n\t\t}\n\t\tconst runtimePluginConfigs = {\n\t\t\t...zone.runtimePluginConfigs,\n\t\t\tgondolin: {\n\t\t\t\tcontrollerUrl: `http://${controllerVmHost}:18800`,\n\t\t\t\tgatewayControlLinkMonitor: {\n\t\t\t\t\tbaseIntervalMs: 10_000,\n\t\t\t\t\tenabled: true,\n\t\t\t\t\tmaxIntervalMs: 120_000,\n\t\t\t\t},\n\t\t\t\tzoneId: zone.id,\n\t\t\t\t...(isObjectRecord(zone.runtimePluginConfigs?.gondolin)\n\t\t\t\t\t? zone.runtimePluginConfigs.gondolin\n\t\t\t\t\t: {}),\n\t\t\t},\n\t\t};\n\t\tconst config = isObjectRecord(parsedBaseConfig.gateway) ? parsedBaseConfig.gateway : {};\n\t\tconst existingAuthConfig = isObjectRecord(config.auth) ? config.auth : {};\n\t\tconst effectiveConfig = {\n\t\t\t...parsedBaseConfig,\n\t\t\tlogging: buildEffectiveLoggingConfig(parsedBaseConfig),\n\t\t\tgateway: {\n\t\t\t\t...config,\n\t\t\t\tauth: {\n\t\t\t\t\t...existingAuthConfig,\n\t\t\t\t\tmode: 'token',\n\t\t\t\t\ttoken: openClawGatewayTokenSecretRef,\n\t\t\t\t},\n\t\t\t},\n\t\t\tmeta: {\n\t\t\t\t...(isObjectRecord(parsedBaseConfig.meta) ? parsedBaseConfig.meta : {}),\n\t\t\t\tlastTouchedAt: new Date().toISOString(),\n\t\t\t\tlastTouchedVersion: 'agent-vm',\n\t\t\t},\n\t\t\tmcp: buildEffectiveMcpConfig(parsedBaseConfig, zone.runtimeMcpServers),\n\t\t\tplugins: buildEffectivePluginsConfig(parsedBaseConfig, runtimePluginConfigs),\n\t\t\tsecrets: buildEffectiveSecretsConfig(parsedBaseConfig),\n\t\t};\n\t\treturn `${JSON.stringify(effectiveConfig, null, 2)}\\n`;\n\t} catch (error) {\n\t\tconst message = formatSafeOpenClawErrorMessage(error);\n\t\tthrow new Error(\n\t\t\t`Failed to build effective OpenClaw config for zone '${zone.id}' from '${zone.gateway.config}' using secret '${describeSecretReference(gatewayTokenSecret)}': ${message}`,\n\t\t\t{ cause: error },\n\t\t);\n\t}\n}\n\nasync function writeEffectiveOpenClawConfig(zone: GatewayZoneConfig): Promise<void> {\n\tconst content = await buildEffectiveOpenClawConfigContent(zone);\n\ttry {\n\t\tconst effectiveConfigPath = getEffectiveOpenClawConfigHostPath(zone);\n\t\tawait mkdir(zone.gateway.stateDir, { recursive: true, mode: 0o700 });\n\t\tawait chmod(zone.gateway.stateDir, 0o700);\n\t\tawait writeFileAtomically(effectiveConfigPath, content, { mode: 0o600 });\n\t} catch (error) {\n\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\tthrow new Error(`Failed to write effective OpenClaw config for zone '${zone.id}': ${message}`, {\n\t\t\tcause: error,\n\t\t});\n\t}\n}\n\nasync function preflightEffectiveOpenClawConfig(zone: GatewayZoneConfig): Promise<void> {\n\tconst content = await buildEffectiveOpenClawConfigContent(zone);\n\ttry {\n\t\tawait mkdir(zone.gateway.stateDir, { recursive: true, mode: 0o700 });\n\t\tawait chmod(zone.gateway.stateDir, 0o700);\n\t\tawait assertEffectiveConfigPathWritable(zone, content);\n\t} catch (error) {\n\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\tthrow new Error(\n\t\t\t`Failed to preflight effective OpenClaw config for zone '${zone.id}': ${message}`,\n\t\t\t{ cause: error },\n\t\t);\n\t}\n}\n\nexport const openclawLifecycle: GatewayLifecycle = {\n\tauthConfig: {\n\t\tlistProvidersCommand: 'openclaw models auth list --format plain 2>/dev/null || echo \"\"',\n\t\tbuildLoginCommand: (\n\t\t\tprovider: string,\n\t\t\toptions: {\n\t\t\t\treadonly agentId?: string;\n\t\t\t\treadonly deviceCode?: boolean;\n\t\t\t\treadonly setDefault?: boolean;\n\t\t\t} = {},\n\t\t): string =>\n\t\t\t[\n\t\t\t\t'openclaw models auth',\n\t\t\t\t...(options.agentId ? [`--agent ${shellQuote(options.agentId)}`] : []),\n\t\t\t\t`login --provider ${shellQuote(provider)}`,\n\t\t\t\t...(options.deviceCode === true ? ['--device-code'] : []),\n\t\t\t\t...(options.setDefault === true ? ['--set-default'] : []),\n\t\t\t].join(' '),\n\t},\n\n\tbuildVmSpec({\n\t\tcontrollerPort,\n\t\tgatewayCacheDir,\n\t\tprojectNamespace,\n\t\tresolvedSecrets,\n\t\truntimeDir,\n\t\ttcpPool,\n\t\tzone,\n\t}: BuildGatewayVmSpecOptions): GatewayVmSpec {\n\t\tif (zone.gateway.type !== 'openclaw') {\n\t\t\tthrow new Error(`OpenClaw lifecycle cannot build gateway type '${zone.gateway.type}'.`);\n\t\t}\n\t\tconst configDirectory = path.dirname(path.resolve(zone.gateway.config));\n\t\tconst { environmentSecrets, mediatedSecrets } = mergeRuntimeGatewaySecrets(\n\t\t\tsplitAllowedOpenClawGatewaySecrets(zone, resolvedSecrets, 'openclaw-vm-raw-env-secrets'),\n\t\t\t{\n\t\t\t\tlogPrefix: 'openclaw-vm-runtime-secrets',\n\t\t\t\truntimeEnvironment: zone.runtimeEnvironment,\n\t\t\t\truntimeMediatedSecrets: zone.runtimeMediatedSecrets,\n\t\t\t},\n\t\t);\n\t\tassertAllowedOpenClawEnvironmentSecrets(\n\t\t\tzone,\n\t\t\tenvironmentSecrets,\n\t\t\t'openclaw-vm-runtime-raw-env-secrets',\n\t\t);\n\n\t\treturn {\n\t\t\tallowedHosts: gatewayVmAllowedHosts(zone.egressHosts),\n\t\t\tenvironment: {\n\t\t\t\tHOME: '/home/openclaw',\n\t\t\t\tNODE_EXTRA_CA_CERTS: '/run/gondolin/ca-certificates.crt',\n\t\t\t\tOPENCLAW_CONFIG_PATH: effectiveOpenClawConfigVmPath,\n\t\t\t\tOPENCLAW_HOME: '/home/openclaw',\n\t\t\t\tOPENCLAW_STATE_DIR: openClawStateDirVmPath,\n\t\t\t\tPATH: openClawGatewayGuestPath,\n\t\t\t\tPIP_CACHE_DIR: '/work/cache/pip',\n\t\t\t\tPNPM_HOME: '/pnpm',\n\t\t\t\tTEMP: '/work/tmp',\n\t\t\t\tTMP: '/work/tmp',\n\t\t\t\tTMPDIR: '/work/tmp',\n\t\t\t\tUV_CACHE_DIR: '/work/cache/uv',\n\t\t\t\tnpm_config_cache: '/work/cache/npm',\n\t\t\t\tpnpm_config_store_dir: '/work/cache/pnpm/store',\n\t\t\t\t...environmentSecrets,\n\t\t\t\t// NODE_OPTIONS goes AFTER the spread so a user-supplied\n\t\t\t\t// NODE_OPTIONS in environmentSecrets cannot drop the\n\t\t\t\t// forced IPv4-preference flags. composeNodeOptions\n\t\t\t\t// preserves the user value as additional flags.\n\t\t\t\tNODE_OPTIONS: composeNodeOptions(environmentSecrets.NODE_OPTIONS),\n\t\t\t},\n\t\t\tmediatedSecrets: {\n\t\t\t\t...mediatedSecrets,\n\t\t\t},\n\t\t\trootfsMode: 'cow',\n\t\t\t...(zone.gateway.runtimeRootfsSize\n\t\t\t\t? { runtimeRootfsSize: zone.gateway.runtimeRootfsSize }\n\t\t\t\t: {}),\n\t\t\tsessionLabel: buildGatewaySessionLabelValue(projectNamespace, zone.id),\n\t\t\ttcpHosts: buildGatewayTcpHosts(zone, controllerPort, tcpPool),\n\t\t\tvfsMounts: {\n\t\t\t\t'/home/openclaw/.openclaw/config': {\n\t\t\t\t\thostPath: configDirectory,\n\t\t\t\t\tkind: 'realfs',\n\t\t\t\t},\n\t\t\t\t[openClawCacheDirVmPath]: {\n\t\t\t\t\thostPath: gatewayCacheDir,\n\t\t\t\t\tkind: 'realfs',\n\t\t\t\t},\n\t\t\t\t'/home/openclaw/.openclaw/state': {\n\t\t\t\t\thostPath: zone.gateway.stateDir,\n\t\t\t\t\tkind: 'realfs',\n\t\t\t\t},\n\t\t\t\t[openClawZoneFilesDirVmPath]: {\n\t\t\t\t\thostPath: zone.gateway.zoneFilesDir,\n\t\t\t\t\tkind: 'realfs',\n\t\t\t\t},\n\t\t\t\t[agentVmLogsDirVmPath]: {\n\t\t\t\t\thostPath: path.join(runtimeDir, 'zones', zone.id, 'logs'),\n\t\t\t\t\tkind: 'realfs',\n\t\t\t\t},\n\t\t\t},\n\t\t};\n\t},\n\n\tbuildProcessSpec(\n\t\tzone: GatewayZoneConfig,\n\t\tresolvedSecrets: Record<string, string>,\n\t): GatewayProcessSpec {\n\t\treturn {\n\t\t\tbootstrapCommand: buildOpenClawBootstrapCommand(zone, resolvedSecrets),\n\t\t\t// printf NODE_OPTIONS into the boot log so an env-loss regression\n\t\t\t// (e.g. a future secrets.env or merge change that drops the\n\t\t\t// FORCE_IPV4_EGRESS_NODE_OPTIONS flags) is visible in the log\n\t\t\t// stream without SSHing into the VM. See\n\t\t\t// FORCE_IPV4_EGRESS_NODE_OPTIONS in @agent-vm/gateway-interface.\n\t\t\tstartCommand: `set -a && . ${openClawRuntimeSecretsEnvFilePath} && set +a && { printf 'gateway-boot: NODE_OPTIONS=%s\\\\n' \"$NODE_OPTIONS\" > ${openClawGatewayBootLogFileVmPath}; } && cd /home/openclaw && nohup ${openClawCommandVmPath} gateway --port 18789 >> ${openClawGatewayBootLogFileVmPath} 2>&1 &`,\n\t\t\thealthCheck: {\n\t\t\t\ttype: 'http',\n\t\t\t\tport: 18789,\n\t\t\t\tpath: '/readyz',\n\t\t\t},\n\t\t\tserviceHealthCheck: {\n\t\t\t\ttype: 'http',\n\t\t\t\tport: 18789,\n\t\t\t\tpath: '/health',\n\t\t\t},\n\t\t\tguestListenPort: 18789,\n\t\t\tlogPath: openClawGatewayBootLogFileVmPath,\n\t\t};\n\t},\n\n\tasync prepareHostState(zone: GatewayZoneConfig, secretResolver: SecretResolver): Promise<void> {\n\t\tawait writeEffectiveOpenClawConfig(zone);\n\t\tawait writeAuthProfilesIfConfigured(zone, secretResolver);\n\t},\n\n\tasync preflightHostState(zone: GatewayZoneConfig, secretResolver: SecretResolver): Promise<void> {\n\t\tawait preflightEffectiveOpenClawConfig(zone);\n\t\tawait preflightAuthProfilesIfConfigured(zone, secretResolver);\n\t},\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":["exhaustiveCheck","buildGatewaySessionLabelValue"],"sources":["../src/openclaw-lifecycle.ts"],"sourcesContent":["import { randomUUID } from 'node:crypto';\nimport { chmod, lstat, mkdir, readFile, rm } from 'node:fs/promises';\nimport path from 'node:path';\n\nimport type {\n\tBuildGatewayVmSpecOptions,\n\tGatewayLifecycle,\n\tGatewayProcessSpec,\n\tGatewayZoneConfig,\n\tGatewayVmSpec,\n\tSplitResolvedGatewaySecretsResult,\n} from '@agent-vm/gateway-interface';\nimport {\n\tbuildGatewaySessionLabel as buildGatewaySessionLabelValue,\n\tcomposeNodeOptions,\n\tcontrollerVmHost,\n\tFORCE_IPV4_EGRESS_NODE_OPTIONS,\n\tgatewayVmAllowedHosts,\n\tmergeRuntimeGatewaySecrets,\n\tsplitResolvedGatewaySecrets,\n} from '@agent-vm/gateway-interface';\nimport { writeFileAtomically } from '@agent-vm/gondolin-adapter';\nimport {\n\tredactOnePasswordReferences,\n\ttype SecretRef,\n\ttype SecretResolver,\n} from '@agent-vm/secret-management';\n\nconst effectiveOpenClawConfigFileName = 'effective-openclaw.json';\nconst effectiveOpenClawConfigVmPath = `/home/openclaw/.openclaw/state/${effectiveOpenClawConfigFileName}`;\nconst openClawStateDirVmPath = '/home/openclaw/.openclaw/state';\nconst openClawCacheDirVmPath = '/home/openclaw/.openclaw/cache';\nconst openClawZoneFilesDirVmPath = '/zone';\nconst agentVmLogsDirVmPath = '/agent-vm/logs';\nconst openClawRuntimeLogFileVmPath = `${agentVmLogsDirVmPath}/openclaw-YYYY-MM-DD.log`;\nconst openClawGatewayBootLogFileVmPath = `${agentVmLogsDirVmPath}/gateway-boot-latest.log`;\nconst openClawShellEnvFilePath = '/etc/profile.d/openclaw-env.sh';\nconst openClawRuntimeSecretsEnvFilePath = '/run/openclaw/secrets.env';\nconst openClawGatewayTokenEnvFilePath = '/run/openclaw/gateway-token.env';\nconst openClawCommandVmPath = '/usr/local/bin/openclaw';\nconst openClawGatewayGuestPath =\n\t'/pnpm:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin';\nconst diagnosticsOtelPluginId = 'diagnostics-otel';\n\ninterface OpenClawSecretRef {\n\treadonly id: string;\n\treadonly provider: string;\n\treadonly source: 'env';\n}\n\nfunction isObjectRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction setTcpHost(tcpHosts: Record<string, string>, key: string, target: string): void {\n\tconst existingTarget = tcpHosts[key];\n\tif (existingTarget !== undefined && existingTarget !== target) {\n\t\tthrow new Error(\n\t\t\t`OpenClaw tcpHosts entry '${key}' cannot target both '${existingTarget}' and '${target}'.`,\n\t\t);\n\t}\n\ttcpHosts[key] = target;\n}\n\nfunction buildGatewayTcpHosts(\n\tzone: GatewayZoneConfig,\n\tcontrollerPort: number,\n\ttcpPool: { readonly basePort: number; readonly size: number },\n): Record<string, string> {\n\tconst tcpHosts: Record<string, string> = {};\n\tsetTcpHost(tcpHosts, `${controllerVmHost}:18800`, `127.0.0.1:${controllerPort}`);\n\n\tfor (let slot = 0; slot < tcpPool.size; slot += 1) {\n\t\tsetTcpHost(tcpHosts, `tool-${slot}.vm.host:22`, `127.0.0.1:${tcpPool.basePort + slot}`);\n\t}\n\n\tfor (const websocketHost of zone.websocketBypass) {\n\t\tsetTcpHost(tcpHosts, websocketHost, websocketHost);\n\t}\n\n\tif (zone.observability?.mode === 'collector') {\n\t\tconst { collector } = zone.observability;\n\t\tsetTcpHost(\n\t\t\ttcpHosts,\n\t\t\t`${collector.host}:${String(collector.grpcPort)}`,\n\t\t\t`${collector.targetHost}:${String(collector.targetGrpcPort)}`,\n\t\t);\n\t\tsetTcpHost(\n\t\t\ttcpHosts,\n\t\t\t`${collector.host}:${String(collector.httpPort)}`,\n\t\t\t`${collector.targetHost}:${String(collector.targetHttpPort)}`,\n\t\t);\n\t}\n\n\treturn tcpHosts;\n}\n\nfunction buildOpenClawBootstrapCommand(\n\tzone: GatewayZoneConfig,\n\tresolvedSecrets: Record<string, string>,\n): string {\n\tif (zone.gateway.type !== 'openclaw') {\n\t\tthrow new Error(`OpenClaw lifecycle cannot build gateway type '${zone.gateway.type}'.`);\n\t}\n\tconst { environmentSecrets } = mergeRuntimeGatewaySecrets(\n\t\tsplitAllowedOpenClawGatewaySecrets(zone, resolvedSecrets, 'openclaw-bootstrap-raw-env-secrets'),\n\t\t{\n\t\t\tlogPrefix: 'openclaw-bootstrap-runtime-secrets',\n\t\t\truntimeEnvironment: zone.runtimeEnvironment,\n\t\t\truntimeMediatedSecrets: zone.runtimeMediatedSecrets,\n\t\t},\n\t);\n\tassertAllowedOpenClawEnvironmentSecrets(\n\t\tzone,\n\t\tenvironmentSecrets,\n\t\t'openclaw-bootstrap-runtime-raw-env-secrets',\n\t);\n\tconst environmentLines = [\n\t\t'export OPENCLAW_HOME=/home/openclaw',\n\t\t`export OPENCLAW_CONFIG_PATH=${effectiveOpenClawConfigVmPath}`,\n\t\t`export OPENCLAW_STATE_DIR=${openClawStateDirVmPath}`,\n\t\t'export PNPM_HOME=/pnpm',\n\t\t'export PATH=/pnpm:$PATH',\n\t\t'export TMPDIR=/work/tmp',\n\t\t'export TMP=/work/tmp',\n\t\t'export TEMP=/work/tmp',\n\t\t'export npm_config_cache=/work/cache/npm',\n\t\t'export pnpm_config_store_dir=/work/cache/pnpm/store',\n\t\t'export PIP_CACHE_DIR=/work/cache/pip',\n\t\t'export UV_CACHE_DIR=/work/cache/uv',\n\t\t'export NODE_EXTRA_CA_CERTS=/run/gondolin/ca-certificates.crt',\n\t\t// Prepend each forced IPv4-preference flag only when it is not\n\t\t// already present. The VM env normally carries these flags\n\t\t// already; the profile keeps interactive shells safe without\n\t\t// duplicating the boot-log value.\n\t\t...FORCE_IPV4_EGRESS_NODE_OPTIONS.split(' ').map(\n\t\t\t(nodeOptionFlag) =>\n\t\t\t\t`case \" \\${NODE_OPTIONS:-} \" in *\" ${nodeOptionFlag} \"*) ;; *) export NODE_OPTIONS=\"${nodeOptionFlag}\\${NODE_OPTIONS:+ \\${NODE_OPTIONS}}\";; esac`,\n\t\t),\n\t];\n\tconst secretEnvironmentNames = Object.entries({\n\t\t...environmentSecrets,\n\t\t...zone.runtimeEnvironment,\n\t}).map(([secretName, secretValue]) => {\n\t\tassertShellSafeEnvName(secretName);\n\t\tassertShellProfileSafeSecretValue(secretName, secretValue);\n\t\treturn secretName;\n\t});\n\tconst secretsFileCommand =\n\t\tsecretEnvironmentNames.length === 0\n\t\t\t? `: > ${openClawRuntimeSecretsEnvFilePath} && `\n\t\t\t: `{ ${secretEnvironmentNames.map(runtimeSecretLiteralExportCommand).join('; ')}; } > ${openClawRuntimeSecretsEnvFilePath} && `;\n\tconst gatewayTokenSecretName = zone.gateway.controlAuth.secret;\n\tconst gatewayTokenFileCommand = secretEnvironmentNames.includes(gatewayTokenSecretName)\n\t\t? `{ ${runtimeSecretLiteralExportCommand(gatewayTokenSecretName)}; } > ${openClawGatewayTokenEnvFilePath} && `\n\t\t: `: > ${openClawGatewayTokenEnvFilePath} && `;\n\tconst sshConfigLines = ['Host tool-*.vm.host', ' AddressFamily inet'];\n\tconst sshConfigCommand =\n\t\t`mkdir -p /root/.ssh /home/openclaw/.ssh && ` +\n\t\t`printf '%s\\\\n' ${sshConfigLines.map((line) => shellQuote(line)).join(' ')} > /root/.ssh/config && ` +\n\t\t'cp /root/.ssh/config /home/openclaw/.ssh/config && ' +\n\t\t'chown -R openclaw:openclaw /home/openclaw/.ssh && ' +\n\t\t'chmod 700 /root/.ssh /home/openclaw/.ssh && ' +\n\t\t'chmod 600 /root/.ssh/config /home/openclaw/.ssh/config && ';\n\n\treturn (\n\t\t`mkdir -p /root /etc/profile.d /run/openclaw /work/tmp /work/cache/npm /work/cache/pnpm/store /work/cache/pip /work/cache/uv && chown -R openclaw:openclaw /work && cat > ${openClawShellEnvFilePath} << 'ENVEOF'\\n` +\n\t\tenvironmentLines.join('\\n') +\n\t\t'\\nENVEOF\\n' +\n\t\t`chmod 644 ${openClawShellEnvFilePath} && ` +\n\t\tsecretsFileCommand +\n\t\t`chmod 600 ${openClawRuntimeSecretsEnvFilePath} && ` +\n\t\tgatewayTokenFileCommand +\n\t\t`chmod 600 ${openClawGatewayTokenEnvFilePath} && ` +\n\t\tsshConfigCommand +\n\t\t'touch /root/.bashrc && ' +\n\t\t`grep -qxF 'source ${openClawShellEnvFilePath}' /root/.bashrc || echo 'source ${openClawShellEnvFilePath}' >> /root/.bashrc && ` +\n\t\t'touch /root/.bash_profile && ' +\n\t\t\"grep -qxF 'source /root/.bashrc' /root/.bash_profile || echo 'source /root/.bashrc' >> /root/.bash_profile\"\n\t);\n}\n\nfunction getEffectiveOpenClawConfigHostPath(zone: GatewayZoneConfig): string {\n\treturn path.join(zone.gateway.stateDir, effectiveOpenClawConfigFileName);\n}\n\nasync function assertEffectiveConfigPathWritable(\n\tzone: GatewayZoneConfig,\n\tcontent: string,\n): Promise<void> {\n\tconst effectiveConfigPath = getEffectiveOpenClawConfigHostPath(zone);\n\tconst existingEffectiveConfig = await lstat(effectiveConfigPath).catch((error: unknown) => {\n\t\tif (isObjectRecord(error) && error.code === 'ENOENT') {\n\t\t\treturn undefined;\n\t\t}\n\t\tthrow error;\n\t});\n\tif (existingEffectiveConfig?.isDirectory()) {\n\t\tthrow new Error(`Effective OpenClaw config path '${effectiveConfigPath}' is a directory.`);\n\t}\n\n\tconst preflightPath = path.join(\n\t\tzone.gateway.stateDir,\n\t\t`.agent-vm-effective-openclaw-preflight-${process.pid}-${randomUUID()}.json`,\n\t);\n\ttry {\n\t\tawait writeFileAtomically(preflightPath, content, { mode: 0o600 });\n\t} finally {\n\t\tawait rm(preflightPath, { force: true });\n\t}\n}\n\nfunction shellQuote(value: string): string {\n\treturn `'${value.replace(/'/gu, `'\\\\''`)}'`;\n}\n\nfunction includesShellUnsafeControlByte(value: string): boolean {\n\tfor (const character of value) {\n\t\tconst codePoint = character.codePointAt(0);\n\t\tif (codePoint !== undefined && (codePoint <= 0x1f || codePoint === 0x7f)) {\n\t\t\treturn true;\n\t\t}\n\t}\n\treturn false;\n}\n\nfunction assertShellSafeEnvName(secretName: string): void {\n\tif (!/^[_A-Za-z][_0-9A-Za-z]*$/u.test(secretName)) {\n\t\tthrow new Error(\n\t\t\t`OpenClaw env-injected gateway secret '${secretName}' must be a shell-safe environment variable name.`,\n\t\t);\n\t}\n}\n\nfunction assertShellProfileSafeSecretValue(secretName: string, value: string): void {\n\tif (includesShellUnsafeControlByte(value)) {\n\t\tthrow new Error(\n\t\t\t`OpenClaw env-injected gateway secret '${secretName}' must be a single-line value without control bytes. Use http-mediation for secrets that require structured transport.`,\n\t\t);\n\t}\n}\n\nfunction runtimeSecretLiteralExportCommand(secretName: string): string {\n\tconst runtimeSecretValue = `\"\\${${secretName}?missing runtime secret ${secretName}}\"`;\n\treturn `secret_value=${runtimeSecretValue} && escaped_secret_value=\"$(printf '%s' \"$secret_value\" | sed 's/[\"\\\\\\\\$\\`]/\\\\\\\\&/g')\" && printf 'export ${secretName}=\"%s\"\\\\n' \"$escaped_secret_value\"`;\n}\n\nfunction assertAllowedOpenClawEnvironmentSecrets(\n\tzone: GatewayZoneConfig,\n\tenvironmentSecrets: Readonly<Record<string, string>>,\n\tlogPrefix: string,\n): void {\n\tif (zone.gateway.type !== 'openclaw') {\n\t\tthrow new Error(`OpenClaw lifecycle cannot build gateway type '${zone.gateway.type}'.`);\n\t}\n\tconst allowedRawEnvSecrets = new Set([\n\t\tzone.gateway.controlAuth.secret,\n\t\t...(zone.gateway.rawEnvSecrets ?? []),\n\t]);\n\tfor (const secretName of Object.keys(environmentSecrets)) {\n\t\tif (zone.observability?.mode === 'collector' && secretName === 'OPENCLAW_DIAGNOSTICS') {\n\t\t\tthrow new Error(\n\t\t\t\t`[${logPrefix}] OpenClaw observability owns diagnostics configuration; do not inject OPENCLAW_DIAGNOSTICS through gateway raw environment secrets.`,\n\t\t\t);\n\t\t}\n\t\tif (allowedRawEnvSecrets.has(secretName)) {\n\t\t\tcontinue;\n\t\t}\n\t\tthrow new Error(\n\t\t\t`[${logPrefix}] OpenClaw env secret '${secretName}' must be listed in gateway.rawEnvSecrets or use injection 'http-mediation'.`,\n\t\t);\n\t}\n}\n\nfunction splitAllowedOpenClawGatewaySecrets(\n\tzone: GatewayZoneConfig,\n\tresolvedSecrets: Record<string, string>,\n\tlogPrefix: string,\n): SplitResolvedGatewaySecretsResult {\n\tconst splitSecrets = splitResolvedGatewaySecrets(zone, resolvedSecrets);\n\tassertAllowedOpenClawEnvironmentSecrets(zone, splitSecrets.environmentSecrets, logPrefix);\n\treturn splitSecrets;\n}\n\ntype SourceAwareSecretReference =\n\t| {\n\t\t\treadonly source: 'environment';\n\t\t\treadonly envVar: string;\n\t }\n\t| {\n\t\t\treadonly source: '1password';\n\t\t\treadonly ref: string;\n\t }\n\t| {\n\t\t\treadonly source: 'config';\n\t\t\treadonly value: string;\n\t };\n\nfunction isSourceAwareSecretReference(value: unknown): value is SourceAwareSecretReference {\n\tif (typeof value !== 'object' || value === null) {\n\t\treturn false;\n\t}\n\n\tif (!('source' in value) || typeof value.source !== 'string') {\n\t\treturn false;\n\t}\n\n\tif (value.source === 'environment') {\n\t\treturn 'envVar' in value && typeof value.envVar === 'string';\n\t}\n\n\tif (value.source === '1password') {\n\t\treturn 'ref' in value && typeof value.ref === 'string';\n\t}\n\n\tif (value.source === 'config') {\n\t\treturn 'value' in value && typeof value.value === 'string';\n\t}\n\n\treturn false;\n}\n\nfunction toSecretRef(secret: SourceAwareSecretReference): SecretRef {\n\tswitch (secret.source) {\n\t\tcase 'environment':\n\t\t\treturn {\n\t\t\t\tsource: 'environment',\n\t\t\t\tref: secret.envVar,\n\t\t\t};\n\t\tcase '1password':\n\t\t\treturn {\n\t\t\t\tsource: '1password',\n\t\t\t\tref: secret.ref,\n\t\t\t};\n\t\tcase 'config':\n\t\t\treturn {\n\t\t\t\tsource: 'config',\n\t\t\t\tvalue: secret.value,\n\t\t\t};\n\t\tdefault: {\n\t\t\tconst exhaustiveCheck: never = secret;\n\t\t\tthrow new Error(`Unsupported secret source: ${JSON.stringify(exhaustiveCheck)}`);\n\t\t}\n\t}\n}\n\nfunction describeSecretReference(secret: SourceAwareSecretReference): string {\n\tswitch (secret.source) {\n\t\tcase 'environment':\n\t\t\treturn secret.envVar;\n\t\tcase '1password':\n\t\t\treturn redactOnePasswordReferences(secret.ref);\n\t\tcase 'config':\n\t\t\treturn 'config value';\n\t\tdefault: {\n\t\t\tconst exhaustiveCheck: never = secret;\n\t\t\tthrow new Error(`Unsupported secret source: ${JSON.stringify(exhaustiveCheck)}`);\n\t\t}\n\t}\n}\n\nfunction formatSafeOpenClawErrorMessage(error: unknown): string {\n\treturn redactOnePasswordReferences(error instanceof Error ? error.message : String(error));\n}\n\nfunction buildEffectiveSecretsConfig(\n\tparsedBaseConfig: Record<string, unknown>,\n): Record<string, unknown> {\n\tconst existingSecretsConfig = isObjectRecord(parsedBaseConfig.secrets)\n\t\t? parsedBaseConfig.secrets\n\t\t: {};\n\tconst existingProvidersConfig = isObjectRecord(existingSecretsConfig.providers)\n\t\t? existingSecretsConfig.providers\n\t\t: {};\n\n\treturn {\n\t\t...existingSecretsConfig,\n\t\tproviders: {\n\t\t\t...existingProvidersConfig,\n\t\t\tdefault: {\n\t\t\t\tsource: 'env',\n\t\t\t},\n\t\t},\n\t};\n}\n\nfunction buildEffectiveMcpPortalPluginConfig(\n\t_existingPluginConfig: Record<string, unknown>,\n\truntimeConfig: Readonly<Record<string, unknown>>,\n): Record<string, unknown> {\n\treturn {\n\t\t...runtimeConfig,\n\t};\n}\n\nfunction appendUniqueStrings(\n\texistingValues: readonly string[],\n\tadditionalValues: readonly string[],\n): readonly string[] {\n\tconst values = [...existingValues];\n\tfor (const value of additionalValues) {\n\t\tif (!values.includes(value)) {\n\t\t\tvalues.push(value);\n\t\t}\n\t}\n\treturn values;\n}\n\nfunction buildEffectivePluginsConfig(\n\tparsedBaseConfig: Record<string, unknown>,\n\truntimePluginConfigs: Readonly<Record<string, Readonly<Record<string, unknown>>>> | undefined,\n): Record<string, unknown> {\n\tconst existingPluginsConfig = isObjectRecord(parsedBaseConfig.plugins)\n\t\t? parsedBaseConfig.plugins\n\t\t: {};\n\tconst runtimePluginIds = Object.keys(runtimePluginConfigs ?? {});\n\tconst existingAllowConfig = Array.isArray(existingPluginsConfig.allow)\n\t\t? existingPluginsConfig.allow.filter((value): value is string => typeof value === 'string')\n\t\t: [];\n\tconst existingEntriesConfig = isObjectRecord(existingPluginsConfig.entries)\n\t\t? existingPluginsConfig.entries\n\t\t: {};\n\tconst runtimeEntriesConfig: Record<string, unknown> = {};\n\tfor (const [pluginId, runtimeConfig] of Object.entries(runtimePluginConfigs ?? {})) {\n\t\tconst existingEntryConfig = isObjectRecord(existingEntriesConfig[pluginId])\n\t\t\t? existingEntriesConfig[pluginId]\n\t\t\t: {};\n\t\tif (pluginId === diagnosticsOtelPluginId) {\n\t\t\truntimeEntriesConfig[pluginId] = {\n\t\t\t\tenabled: true,\n\t\t\t};\n\t\t\tcontinue;\n\t\t}\n\t\tconst existingPluginConfig = isObjectRecord(existingEntryConfig.config)\n\t\t\t? existingEntryConfig.config\n\t\t\t: {};\n\t\tconst config =\n\t\t\tpluginId === 'mcp-portal'\n\t\t\t\t? buildEffectiveMcpPortalPluginConfig(existingPluginConfig, runtimeConfig)\n\t\t\t\t: {\n\t\t\t\t\t\t...existingPluginConfig,\n\t\t\t\t\t\t...runtimeConfig,\n\t\t\t\t\t};\n\t\truntimeEntriesConfig[pluginId] = {\n\t\t\t...existingEntryConfig,\n\t\t\tconfig,\n\t\t};\n\t}\n\n\treturn {\n\t\t...existingPluginsConfig,\n\t\t...(runtimePluginIds.length > 0\n\t\t\t? { allow: appendUniqueStrings(existingAllowConfig, runtimePluginIds) }\n\t\t\t: {}),\n\t\tentries: {\n\t\t\t...existingEntriesConfig,\n\t\t\t...runtimeEntriesConfig,\n\t\t},\n\t};\n}\n\nfunction buildEffectiveMcpConfig(\n\tparsedBaseConfig: Record<string, unknown>,\n\truntimeMcpServers: Readonly<Record<string, unknown>> | undefined,\n): Record<string, unknown> {\n\tconst existingMcpConfig = isObjectRecord(parsedBaseConfig.mcp) ? parsedBaseConfig.mcp : {};\n\tconst existingServersConfig = isObjectRecord(existingMcpConfig.servers)\n\t\t? existingMcpConfig.servers\n\t\t: {};\n\treturn {\n\t\t...existingMcpConfig,\n\t\tservers: {\n\t\t\t...existingServersConfig,\n\t\t\t...runtimeMcpServers,\n\t\t},\n\t};\n}\n\nfunction buildEffectiveLoggingConfig(\n\tparsedBaseConfig: Record<string, unknown>,\n): Record<string, unknown> {\n\tconst existingLoggingConfig = isObjectRecord(parsedBaseConfig.logging)\n\t\t? parsedBaseConfig.logging\n\t\t: {};\n\n\treturn {\n\t\tfile: openClawRuntimeLogFileVmPath,\n\t\t...existingLoggingConfig,\n\t};\n}\n\nfunction assertObservabilityCompatibleLoggingConfig(\n\tparsedBaseConfig: Record<string, unknown>,\n): void {\n\tconst existingLoggingConfig = isObjectRecord(parsedBaseConfig.logging)\n\t\t? parsedBaseConfig.logging\n\t\t: {};\n\tconst redactSensitiveValue = existingLoggingConfig.redactSensitive;\n\tif (isDisabledOpenClawRedactionValue(redactSensitiveValue)) {\n\t\tthrow new Error(\n\t\t\t\"OpenClaw observability requires logging.redactSensitive to stay enabled; remove 'off' or false before enabling telemetry.\",\n\t\t);\n\t}\n}\n\nfunction isDisabledOpenClawRedactionValue(value: unknown): boolean {\n\tif (value === false || value === 0) {\n\t\treturn true;\n\t}\n\tif (typeof value !== 'string') {\n\t\treturn false;\n\t}\n\treturn ['0', 'disable', 'disabled', 'false', 'no', 'off'].includes(value.trim().toLowerCase());\n}\n\nfunction buildEffectiveDiagnosticsConfig(\n\tparsedBaseConfig: Record<string, unknown>,\n\tzone: GatewayZoneConfig,\n): Record<string, unknown> | undefined {\n\tif (zone.observability?.mode !== 'collector') {\n\t\treturn undefined;\n\t}\n\n\tconst existingDiagnosticsConfig = isObjectRecord(parsedBaseConfig.diagnostics)\n\t\t? parsedBaseConfig.diagnostics\n\t\t: {};\n\tconst { collector, openclaw } = zone.observability;\n\treturn {\n\t\t...existingDiagnosticsConfig,\n\t\tenabled: true,\n\t\tflags: openclaw.diagnosticsFlags,\n\t\totel: {\n\t\t\tcaptureContent: { enabled: false },\n\t\t\tenabled: true,\n\t\t\tendpoint: `http://${collector.host}:${String(collector.httpPort)}`,\n\t\t\tflushIntervalMs: openclaw.flushIntervalMs,\n\t\t\tlogs: openclaw.logs,\n\t\t\tmetrics: openclaw.metrics,\n\t\t\tprotocol: 'http/protobuf',\n\t\t\tsampleRate: openclaw.sampleRate,\n\t\t\tserviceName: openclaw.serviceName,\n\t\t\ttraces: openclaw.traces,\n\t\t},\n\t};\n}\n\nasync function writeAuthProfilesIfConfigured(\n\tzone: GatewayZoneConfig,\n\tsecretResolver: SecretResolver,\n): Promise<void> {\n\tconst resolvedAuthProfiles = await resolveAuthProfilesIfConfigured(zone, secretResolver);\n\n\tconst writeResults = await Promise.allSettled(\n\t\tresolvedAuthProfiles.map(async ({ agentId, authProfiles }) => {\n\t\t\tconst authProfilesDirectory = path.join(zone.gateway.stateDir, 'agents', agentId, 'agent');\n\t\t\tawait mkdir(authProfilesDirectory, { recursive: true, mode: 0o700 });\n\t\t\tawait chmod(authProfilesDirectory, 0o700);\n\t\t\tawait writeFileAtomically(\n\t\t\t\tpath.join(authProfilesDirectory, 'auth-profiles.json'),\n\t\t\t\tauthProfiles,\n\t\t\t\t{\n\t\t\t\t\tmode: 0o600,\n\t\t\t\t},\n\t\t\t);\n\t\t}),\n\t);\n\tconst writeErrors = writeResults\n\t\t.filter((result): result is PromiseRejectedResult => result.status === 'rejected')\n\t\t.map((result) =>\n\t\t\tresult.reason instanceof Error ? result.reason : new Error(String(result.reason)),\n\t\t);\n\tif (writeErrors.length > 0) {\n\t\tthrow new AggregateError(\n\t\t\twriteErrors,\n\t\t\t`Failed to write ${String(writeErrors.length)} OpenClaw auth profile file(s) for zone '${zone.id}'.`,\n\t\t);\n\t}\n}\n\nasync function assertAuthProfilePathWritable(\n\tzone: GatewayZoneConfig,\n\tagentId: string,\n): Promise<void> {\n\tconst authProfilesDirectory = path.join(zone.gateway.stateDir, 'agents', agentId, 'agent');\n\tconst authProfilesPath = path.join(authProfilesDirectory, 'auth-profiles.json');\n\tconst existingAuthProfilesPath = await lstat(authProfilesPath).catch((error: unknown) => {\n\t\tif (isObjectRecord(error) && error.code === 'ENOENT') {\n\t\t\treturn undefined;\n\t\t}\n\t\tthrow error;\n\t});\n\tif (existingAuthProfilesPath?.isDirectory()) {\n\t\tthrow new Error(`OpenClaw auth profiles path '${authProfilesPath}' is a directory.`);\n\t}\n\n\tconst preflightPath = path.join(\n\t\tauthProfilesDirectory,\n\t\t`.agent-vm-auth-profiles-preflight-${process.pid}-${randomUUID()}.json`,\n\t);\n\ttry {\n\t\tawait mkdir(authProfilesDirectory, { recursive: true, mode: 0o700 });\n\t\tawait chmod(authProfilesDirectory, 0o700);\n\t\tawait writeFileAtomically(preflightPath, '{}\\n', { mode: 0o600 });\n\t} finally {\n\t\tawait rm(preflightPath, { force: true });\n\t}\n}\n\nasync function preflightAuthProfilesIfConfigured(\n\tzone: GatewayZoneConfig,\n\tsecretResolver: SecretResolver,\n): Promise<void> {\n\tconst resolvedAuthProfiles = await resolveAuthProfilesIfConfigured(zone, secretResolver);\n\tconst writeResults = await Promise.allSettled(\n\t\tresolvedAuthProfiles.map(async ({ agentId }) => {\n\t\t\tawait assertAuthProfilePathWritable(zone, agentId);\n\t\t}),\n\t);\n\tconst writeErrors = writeResults\n\t\t.filter((result): result is PromiseRejectedResult => result.status === 'rejected')\n\t\t.map((result) =>\n\t\t\tresult.reason instanceof Error ? result.reason : new Error(String(result.reason)),\n\t\t);\n\tif (writeErrors.length > 0) {\n\t\tthrow new AggregateError(\n\t\t\twriteErrors,\n\t\t\t`Failed to preflight ${String(writeErrors.length)} OpenClaw auth profile file write(s) for zone '${zone.id}'.`,\n\t\t);\n\t}\n}\n\nasync function resolveAuthProfilesIfConfigured(\n\tzone: GatewayZoneConfig,\n\tsecretResolver: SecretResolver,\n): Promise<readonly { readonly agentId: string; readonly authProfiles: string }[]> {\n\tconst authProfilesByAgent = {\n\t\t...(zone.gateway.authProfilesRef ? { main: zone.gateway.authProfilesRef } : {}),\n\t\t...(zone.gateway.type === 'openclaw' ? (zone.gateway.authProfilesByAgent ?? {}) : {}),\n\t};\n\n\tconst resolveResults = await Promise.allSettled(\n\t\tObject.entries(authProfilesByAgent).map(async ([agentId, authProfilesSecretCandidate]) => {\n\t\t\tif (!isSourceAwareSecretReference(authProfilesSecretCandidate)) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Zone '${zone.id}' has an invalid auth profile shape for agent '${agentId}'.`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst authProfilesSecret = authProfilesSecretCandidate;\n\n\t\t\ttry {\n\t\t\t\tconst authProfiles = await secretResolver.resolve(toSecretRef(authProfilesSecret));\n\t\t\t\treturn { agentId, authProfiles };\n\t\t\t} catch (error) {\n\t\t\t\tconst message = formatSafeOpenClawErrorMessage(error);\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Failed to resolve OpenClaw auth profiles for zone '${zone.id}' agent '${agentId}' from '${describeSecretReference(authProfilesSecret)}': ${message}`,\n\t\t\t\t\t{ cause: error },\n\t\t\t\t);\n\t\t\t}\n\t\t}),\n\t);\n\tconst resolveErrors = resolveResults\n\t\t.filter((result): result is PromiseRejectedResult => result.status === 'rejected')\n\t\t.map((result) =>\n\t\t\tresult.reason instanceof Error ? result.reason : new Error(String(result.reason)),\n\t\t);\n\tif (resolveErrors.length > 0) {\n\t\tthrow new AggregateError(\n\t\t\tresolveErrors,\n\t\t\t`Failed to resolve ${String(resolveErrors.length)} OpenClaw auth profile secret(s) for zone '${zone.id}'.`,\n\t\t);\n\t}\n\treturn resolveResults\n\t\t.filter(\n\t\t\t(\n\t\t\t\tresult,\n\t\t\t): result is PromiseFulfilledResult<{\n\t\t\t\treadonly agentId: string;\n\t\t\t\treadonly authProfiles: string;\n\t\t\t}> => result.status === 'fulfilled',\n\t\t)\n\t\t.map((result) => result.value);\n}\n\nasync function buildEffectiveOpenClawConfigContent(zone: GatewayZoneConfig): Promise<string> {\n\tif (zone.gateway.type !== 'openclaw') {\n\t\tthrow new Error(`OpenClaw lifecycle cannot build gateway type '${zone.gateway.type}'.`);\n\t}\n\tconst gatewayTokenSecretName = zone.gateway.controlAuth.secret;\n\tconst gatewayTokenSecret = zone.secrets[gatewayTokenSecretName];\n\tif (!gatewayTokenSecret) {\n\t\tthrow new Error(\n\t\t\t`Zone '${zone.id}' secret '${gatewayTokenSecretName}' is missing. Add an explicit 1Password or environment reference for the gateway token.`,\n\t\t);\n\t}\n\tif (!isSourceAwareSecretReference(gatewayTokenSecret)) {\n\t\tthrow new Error(`Zone '${zone.id}' secret '${gatewayTokenSecretName}' has an invalid shape.`);\n\t}\n\n\ttry {\n\t\tif (gatewayTokenSecret.source === '1password' && !gatewayTokenSecret.ref) {\n\t\t\tthrow new Error(\n\t\t\t\t`Zone '${zone.id}' secret '${gatewayTokenSecretName}' is missing 'ref'. Add an explicit 1Password reference for the gateway token.`,\n\t\t\t);\n\t\t}\n\t\tif (gatewayTokenSecret.source === 'environment' && !gatewayTokenSecret.envVar) {\n\t\t\tthrow new Error(\n\t\t\t\t`Zone '${zone.id}' secret '${gatewayTokenSecretName}' is missing 'envVar'. Add an explicit environment variable name.`,\n\t\t\t);\n\t\t}\n\t\tconst openClawGatewayTokenSecretRef: OpenClawSecretRef = {\n\t\t\tid: gatewayTokenSecretName,\n\t\t\tprovider: 'default',\n\t\t\tsource: 'env',\n\t\t};\n\t\tconst rawBaseConfig = await readFile(zone.gateway.config, 'utf8');\n\t\tconst parsedBaseConfig: unknown = JSON.parse(rawBaseConfig);\n\t\tif (!isObjectRecord(parsedBaseConfig)) {\n\t\t\tthrow new Error(`OpenClaw config at '${zone.gateway.config}' must be a JSON object.`);\n\t\t}\n\t\tif (zone.observability?.mode === 'collector') {\n\t\t\tassertObservabilityCompatibleLoggingConfig(parsedBaseConfig);\n\t\t}\n\t\tconst runtimePluginConfigs = {\n\t\t\t...zone.runtimePluginConfigs,\n\t\t\t...(zone.observability?.mode === 'collector'\n\t\t\t\t? {\n\t\t\t\t\t\t[diagnosticsOtelPluginId]: {},\n\t\t\t\t\t}\n\t\t\t\t: {}),\n\t\t\tgondolin: {\n\t\t\t\tcontrollerUrl: `http://${controllerVmHost}:18800`,\n\t\t\t\tgatewayControlLinkMonitor: {\n\t\t\t\t\tbaseIntervalMs: 10_000,\n\t\t\t\t\tenabled: true,\n\t\t\t\t\tmaxIntervalMs: 120_000,\n\t\t\t\t},\n\t\t\t\tzoneId: zone.id,\n\t\t\t\t...(isObjectRecord(zone.runtimePluginConfigs?.gondolin)\n\t\t\t\t\t? zone.runtimePluginConfigs.gondolin\n\t\t\t\t\t: {}),\n\t\t\t},\n\t\t};\n\t\tconst config = isObjectRecord(parsedBaseConfig.gateway) ? parsedBaseConfig.gateway : {};\n\t\tconst existingAuthConfig = isObjectRecord(config.auth) ? config.auth : {};\n\t\tconst effectiveDiagnosticsConfig = buildEffectiveDiagnosticsConfig(parsedBaseConfig, zone);\n\t\tconst effectiveConfig = {\n\t\t\t...parsedBaseConfig,\n\t\t\tlogging: buildEffectiveLoggingConfig(parsedBaseConfig),\n\t\t\t...(effectiveDiagnosticsConfig === undefined\n\t\t\t\t? {}\n\t\t\t\t: { diagnostics: effectiveDiagnosticsConfig }),\n\t\t\tgateway: {\n\t\t\t\t...config,\n\t\t\t\tauth: {\n\t\t\t\t\t...existingAuthConfig,\n\t\t\t\t\tmode: 'token',\n\t\t\t\t\ttoken: openClawGatewayTokenSecretRef,\n\t\t\t\t},\n\t\t\t},\n\t\t\tmeta: {\n\t\t\t\t...(isObjectRecord(parsedBaseConfig.meta) ? parsedBaseConfig.meta : {}),\n\t\t\t\tlastTouchedAt: new Date().toISOString(),\n\t\t\t\tlastTouchedVersion: 'agent-vm',\n\t\t\t},\n\t\t\tmcp: buildEffectiveMcpConfig(parsedBaseConfig, zone.runtimeMcpServers),\n\t\t\tplugins: buildEffectivePluginsConfig(parsedBaseConfig, runtimePluginConfigs),\n\t\t\tsecrets: buildEffectiveSecretsConfig(parsedBaseConfig),\n\t\t};\n\t\treturn `${JSON.stringify(effectiveConfig, null, 2)}\\n`;\n\t} catch (error) {\n\t\tconst message = formatSafeOpenClawErrorMessage(error);\n\t\tthrow new Error(\n\t\t\t`Failed to build effective OpenClaw config for zone '${zone.id}' from '${zone.gateway.config}' using secret '${describeSecretReference(gatewayTokenSecret)}': ${message}`,\n\t\t\t{ cause: error },\n\t\t);\n\t}\n}\n\nasync function writeEffectiveOpenClawConfig(zone: GatewayZoneConfig): Promise<void> {\n\tconst content = await buildEffectiveOpenClawConfigContent(zone);\n\ttry {\n\t\tconst effectiveConfigPath = getEffectiveOpenClawConfigHostPath(zone);\n\t\tawait mkdir(zone.gateway.stateDir, { recursive: true, mode: 0o700 });\n\t\tawait chmod(zone.gateway.stateDir, 0o700);\n\t\tawait writeFileAtomically(effectiveConfigPath, content, { mode: 0o600 });\n\t} catch (error) {\n\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\tthrow new Error(`Failed to write effective OpenClaw config for zone '${zone.id}': ${message}`, {\n\t\t\tcause: error,\n\t\t});\n\t}\n}\n\nasync function preflightEffectiveOpenClawConfig(zone: GatewayZoneConfig): Promise<void> {\n\tconst content = await buildEffectiveOpenClawConfigContent(zone);\n\ttry {\n\t\tawait mkdir(zone.gateway.stateDir, { recursive: true, mode: 0o700 });\n\t\tawait chmod(zone.gateway.stateDir, 0o700);\n\t\tawait assertEffectiveConfigPathWritable(zone, content);\n\t} catch (error) {\n\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\tthrow new Error(\n\t\t\t`Failed to preflight effective OpenClaw config for zone '${zone.id}': ${message}`,\n\t\t\t{ cause: error },\n\t\t);\n\t}\n}\n\nexport const openclawLifecycle: GatewayLifecycle = {\n\tauthConfig: {\n\t\tlistProvidersCommand: 'openclaw models auth list --format plain 2>/dev/null || echo \"\"',\n\t\tbuildLoginCommand: (\n\t\t\tprovider: string,\n\t\t\toptions: {\n\t\t\t\treadonly agentId?: string;\n\t\t\t\treadonly deviceCode?: boolean;\n\t\t\t\treadonly setDefault?: boolean;\n\t\t\t} = {},\n\t\t): string =>\n\t\t\t[\n\t\t\t\t'openclaw models auth',\n\t\t\t\t...(options.agentId ? [`--agent ${shellQuote(options.agentId)}`] : []),\n\t\t\t\t`login --provider ${shellQuote(provider)}`,\n\t\t\t\t...(options.deviceCode === true ? ['--device-code'] : []),\n\t\t\t\t...(options.setDefault === true ? ['--set-default'] : []),\n\t\t\t].join(' '),\n\t},\n\n\tbuildVmSpec({\n\t\tcontrollerPort,\n\t\tgatewayCacheDir,\n\t\tprojectNamespace,\n\t\tresolvedSecrets,\n\t\truntimeDir,\n\t\ttcpPool,\n\t\tzone,\n\t}: BuildGatewayVmSpecOptions): GatewayVmSpec {\n\t\tif (zone.gateway.type !== 'openclaw') {\n\t\t\tthrow new Error(`OpenClaw lifecycle cannot build gateway type '${zone.gateway.type}'.`);\n\t\t}\n\t\tconst configDirectory = path.dirname(path.resolve(zone.gateway.config));\n\t\tconst { environmentSecrets, mediatedSecrets } = mergeRuntimeGatewaySecrets(\n\t\t\tsplitAllowedOpenClawGatewaySecrets(zone, resolvedSecrets, 'openclaw-vm-raw-env-secrets'),\n\t\t\t{\n\t\t\t\tlogPrefix: 'openclaw-vm-runtime-secrets',\n\t\t\t\truntimeEnvironment: zone.runtimeEnvironment,\n\t\t\t\truntimeMediatedSecrets: zone.runtimeMediatedSecrets,\n\t\t\t},\n\t\t);\n\t\tassertAllowedOpenClawEnvironmentSecrets(\n\t\t\tzone,\n\t\t\tenvironmentSecrets,\n\t\t\t'openclaw-vm-runtime-raw-env-secrets',\n\t\t);\n\n\t\treturn {\n\t\t\tallowedHosts: gatewayVmAllowedHosts(zone.egressHosts),\n\t\t\tenvironment: {\n\t\t\t\tHOME: '/home/openclaw',\n\t\t\t\tNODE_EXTRA_CA_CERTS: '/run/gondolin/ca-certificates.crt',\n\t\t\t\tOPENCLAW_CONFIG_PATH: effectiveOpenClawConfigVmPath,\n\t\t\t\tOPENCLAW_HOME: '/home/openclaw',\n\t\t\t\tOPENCLAW_STATE_DIR: openClawStateDirVmPath,\n\t\t\t\tPATH: openClawGatewayGuestPath,\n\t\t\t\tPIP_CACHE_DIR: '/work/cache/pip',\n\t\t\t\tPNPM_HOME: '/pnpm',\n\t\t\t\tTEMP: '/work/tmp',\n\t\t\t\tTMP: '/work/tmp',\n\t\t\t\tTMPDIR: '/work/tmp',\n\t\t\t\tUV_CACHE_DIR: '/work/cache/uv',\n\t\t\t\tnpm_config_cache: '/work/cache/npm',\n\t\t\t\tpnpm_config_store_dir: '/work/cache/pnpm/store',\n\t\t\t\t...environmentSecrets,\n\t\t\t\t// NODE_OPTIONS goes AFTER the spread so a user-supplied\n\t\t\t\t// NODE_OPTIONS in environmentSecrets cannot drop the\n\t\t\t\t// forced IPv4-preference flags. composeNodeOptions\n\t\t\t\t// preserves the user value as additional flags.\n\t\t\t\tNODE_OPTIONS: composeNodeOptions(environmentSecrets.NODE_OPTIONS),\n\t\t\t},\n\t\t\tmediatedSecrets: {\n\t\t\t\t...mediatedSecrets,\n\t\t\t},\n\t\t\trootfsMode: 'cow',\n\t\t\t...(zone.gateway.runtimeRootfsSize\n\t\t\t\t? { runtimeRootfsSize: zone.gateway.runtimeRootfsSize }\n\t\t\t\t: {}),\n\t\t\tsessionLabel: buildGatewaySessionLabelValue(projectNamespace, zone.id),\n\t\t\ttcpHosts: buildGatewayTcpHosts(zone, controllerPort, tcpPool),\n\t\t\tvfsMounts: {\n\t\t\t\t'/home/openclaw/.openclaw/config': {\n\t\t\t\t\thostPath: configDirectory,\n\t\t\t\t\tkind: 'realfs',\n\t\t\t\t},\n\t\t\t\t[openClawCacheDirVmPath]: {\n\t\t\t\t\thostPath: gatewayCacheDir,\n\t\t\t\t\tkind: 'realfs',\n\t\t\t\t},\n\t\t\t\t'/home/openclaw/.openclaw/state': {\n\t\t\t\t\thostPath: zone.gateway.stateDir,\n\t\t\t\t\tkind: 'realfs',\n\t\t\t\t},\n\t\t\t\t[openClawZoneFilesDirVmPath]: {\n\t\t\t\t\thostPath: zone.gateway.zoneFilesDir,\n\t\t\t\t\tkind: 'realfs',\n\t\t\t\t},\n\t\t\t\t[agentVmLogsDirVmPath]: {\n\t\t\t\t\thostPath: path.join(runtimeDir, 'zones', zone.id, 'logs'),\n\t\t\t\t\tkind: 'realfs',\n\t\t\t\t},\n\t\t\t},\n\t\t};\n\t},\n\n\tbuildProcessSpec(\n\t\tzone: GatewayZoneConfig,\n\t\tresolvedSecrets: Record<string, string>,\n\t): GatewayProcessSpec {\n\t\treturn {\n\t\t\tbootstrapCommand: buildOpenClawBootstrapCommand(zone, resolvedSecrets),\n\t\t\t// printf NODE_OPTIONS into the boot log so an env-loss regression\n\t\t\t// (e.g. a future secrets.env or merge change that drops the\n\t\t\t// FORCE_IPV4_EGRESS_NODE_OPTIONS flags) is visible in the log\n\t\t\t// stream without SSHing into the VM. See\n\t\t\t// FORCE_IPV4_EGRESS_NODE_OPTIONS in @agent-vm/gateway-interface.\n\t\t\tstartCommand: `set -a && . ${openClawRuntimeSecretsEnvFilePath} && set +a && { printf 'gateway-boot: NODE_OPTIONS=%s\\\\n' \"$NODE_OPTIONS\" > ${openClawGatewayBootLogFileVmPath}; } && cd /home/openclaw && nohup ${openClawCommandVmPath} gateway --port 18789 >> ${openClawGatewayBootLogFileVmPath} 2>&1 &`,\n\t\t\thealthCheck: {\n\t\t\t\ttype: 'http',\n\t\t\t\tport: 18789,\n\t\t\t\tpath: '/readyz',\n\t\t\t},\n\t\t\tserviceHealthCheck: {\n\t\t\t\ttype: 'http',\n\t\t\t\tport: 18789,\n\t\t\t\tpath: '/health',\n\t\t\t},\n\t\t\tguestListenPort: 18789,\n\t\t\tlogPath: openClawGatewayBootLogFileVmPath,\n\t\t};\n\t},\n\n\tasync prepareHostState(zone: GatewayZoneConfig, secretResolver: SecretResolver): Promise<void> {\n\t\tawait writeEffectiveOpenClawConfig(zone);\n\t\tawait writeAuthProfilesIfConfigured(zone, secretResolver);\n\t},\n\n\tasync preflightHostState(zone: GatewayZoneConfig, secretResolver: SecretResolver): Promise<void> {\n\t\tawait preflightEffectiveOpenClawConfig(zone);\n\t\tawait preflightAuthProfilesIfConfigured(zone, secretResolver);\n\t},\n};\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agent-vm/openclaw-gateway",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.98",
|
|
4
4
|
"description": "OpenClaw gateway lifecycle running inside a Gondolin VM.",
|
|
5
5
|
"homepage": "https://github.com/ShravanSunder/agent-vm#readme",
|
|
6
6
|
"bugs": {
|
|
@@ -29,9 +29,9 @@
|
|
|
29
29
|
"access": "public"
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"@agent-vm/
|
|
33
|
-
"@agent-vm/
|
|
34
|
-
"@agent-vm/secret-management": "0.0.
|
|
32
|
+
"@agent-vm/gateway-interface": "0.0.98",
|
|
33
|
+
"@agent-vm/gondolin-adapter": "0.0.98",
|
|
34
|
+
"@agent-vm/secret-management": "0.0.98"
|
|
35
35
|
},
|
|
36
36
|
"scripts": {
|
|
37
37
|
"build": "tsdown",
|