@agent-vm/openclaw-gateway 0.0.58 → 0.0.60

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 CHANGED
@@ -1,200 +1,5 @@
1
- //#region ../gateway-interface/dist/index.d.ts
2
- //#region src/gateway-runtime-contract.d.ts
3
- declare const gatewayTypeValues: readonly ["openclaw", "worker"];
4
- type GatewayType = (typeof gatewayTypeValues)[number];
5
- //#endregion
6
- //#region ../gondolin-adapter/dist/index.d.ts
7
-
8
- //#endregion
9
- //#region src/pinned-realfs.d.ts
10
- interface PinnedRealFsRoot {
11
- readonly hostPath: string;
12
- readonly realPath: string;
13
- readonly fd: number;
14
- readonly device: number;
15
- readonly inode: number;
16
- }
17
- //#endregion
18
- //#region src/types.d.ts
19
- interface SecretSpec {
20
- readonly hosts: readonly string[];
21
- readonly value: string;
22
- }
23
- type SecretRef = {
24
- readonly source: '1password';
25
- readonly ref: string;
26
- } | {
27
- readonly source: 'environment';
28
- readonly ref: string;
29
- };
30
- //#endregion
31
- //#region src/secret-resolver.d.ts
1
+ import { GatewayLifecycle } from "@agent-vm/gateway-interface";
32
2
 
33
- interface SecretResolver {
34
- resolve(ref: SecretRef): Promise<string>;
35
- resolveAll(refs: Record<string, SecretRef>): Promise<Record<string, string>>;
36
- }
37
- interface VfsMountSpec {
38
- readonly kind: 'realfs' | 'realfs-readonly' | 'memory' | 'shadow';
39
- readonly hostPath?: string;
40
- readonly pinnedHostRoot?: PinnedRealFsRoot;
41
- readonly shadowConfig?: {
42
- readonly deny: readonly string[];
43
- readonly tmpfs: readonly string[];
44
- };
45
- }
46
- //#endregion
47
- //#region src/gateway-process-spec.d.ts
48
- type GatewayHealthCheck = {
49
- readonly type: 'http';
50
- readonly port: number;
51
- readonly path: string;
52
- } | {
53
- readonly type: 'command';
54
- readonly command: string;
55
- };
56
- /**
57
- * Everything about the process running inside the VM.
58
- * Retained by the running gateway handle for logs, health, restart.
59
- */
60
- interface GatewayProcessSpec {
61
- readonly bootstrapCommand: string;
62
- readonly startCommand: string;
63
- readonly healthCheck: GatewayHealthCheck;
64
- readonly guestListenPort: number;
65
- readonly logPath: string;
66
- }
67
- //#endregion
68
- //#region src/gateway-vm-spec.d.ts
69
- /**
70
- * Everything the controller needs to create the Gondolin VM.
71
- * Lifecycle implementations own the full Gondolin-facing contract.
72
- */
73
- interface GatewayVmSpec {
74
- readonly environment: Record<string, string>;
75
- readonly vfsMounts: Record<string, VfsMountSpec>;
76
- readonly mediatedSecrets: Record<string, SecretSpec>;
77
- readonly tcpHosts: Record<string, string>;
78
- readonly allowedHosts: readonly string[];
79
- readonly rootfsMode: 'readonly' | 'memory' | 'cow';
80
- readonly sessionLabel: string;
81
- }
82
- //#endregion
83
- //#region src/gateway-lifecycle.d.ts
84
- /**
85
- * Describes how to run interactive auth for a gateway type.
86
- * Static property — available without a running VM.
87
- */
88
- interface GatewayAuthConfig {
89
- /**
90
- * Shell command to list available auth providers inside the VM.
91
- * Should output one provider name per line to stdout.
92
- */
93
- readonly listProvidersCommand: string;
94
- /**
95
- * Build the shell command for interactive auth login.
96
- * The CLI passes this as the SSH remote command with -t (TTY).
97
- */
98
- readonly buildLoginCommand: (provider: string, options?: {
99
- readonly deviceCode?: boolean;
100
- readonly setDefault?: boolean;
101
- }) => string;
102
- }
103
- interface GatewayAuthProfilesRef {
104
- readonly source: '1password' | 'environment';
105
- }
106
- interface OnePasswordGatewayAuthProfilesRef extends GatewayAuthProfilesRef {
107
- readonly source: '1password';
108
- readonly ref: string;
109
- }
110
- interface EnvironmentGatewayAuthProfilesRef extends GatewayAuthProfilesRef {
111
- readonly source: 'environment';
112
- readonly envVar: string;
113
- }
114
- type GatewaySshSecretEnvMode = 'always' | 'explicit' | 'never';
115
- interface GatewaySshConfig {
116
- readonly secretEnv: GatewaySshSecretEnvMode;
117
- }
118
- interface GatewayZoneBaseGatewayConfig {
119
- readonly type: GatewayType;
120
- readonly memory: string;
121
- readonly cpus: number;
122
- readonly port: number;
123
- readonly config: string;
124
- readonly stateDir: string;
125
- readonly ssh: GatewaySshConfig;
126
- readonly authProfilesRef?: OnePasswordGatewayAuthProfilesRef | EnvironmentGatewayAuthProfilesRef | undefined;
127
- }
128
- interface OpenClawGatewayZoneGatewayConfig extends GatewayZoneBaseGatewayConfig {
129
- readonly type: 'openclaw';
130
- readonly zoneFilesDir: string;
131
- readonly authProfilesByAgent?: Readonly<Record<string, OnePasswordGatewayAuthProfilesRef | EnvironmentGatewayAuthProfilesRef>>;
132
- }
133
- interface WorkerGatewayZoneGatewayConfig extends GatewayZoneBaseGatewayConfig {
134
- readonly type: 'worker';
135
- }
136
- type GatewayZoneGatewayConfig = OpenClawGatewayZoneGatewayConfig | WorkerGatewayZoneGatewayConfig;
137
- /**
138
- * Zone config as the lifecycle sees it.
139
- * Decoupled from SystemConfig — the controller maps into this shape.
140
- */
141
- interface GatewayZoneConfig {
142
- readonly id: string;
143
- readonly gateway: GatewayZoneGatewayConfig;
144
- readonly runtimeEnvironment?: Readonly<Record<string, string>>;
145
- readonly runtimePluginConfigs?: Readonly<Record<string, Readonly<Record<string, unknown>>>>;
146
- readonly secrets: Record<string, {
147
- readonly source: '1password';
148
- readonly ref: string;
149
- readonly injection: 'env' | 'http-mediation';
150
- readonly hosts?: readonly string[] | undefined;
151
- } | {
152
- readonly source: 'environment';
153
- readonly envVar: string;
154
- readonly injection: 'env' | 'http-mediation';
155
- readonly hosts?: readonly string[] | undefined;
156
- }>;
157
- readonly allowedHosts: readonly string[];
158
- readonly websocketBypass: readonly string[];
159
- readonly defaultToolVmProfile?: string;
160
- }
161
- interface BuildGatewayVmSpecOptions {
162
- readonly controllerPort: number;
163
- readonly gatewayCacheDir: string;
164
- readonly projectNamespace: string;
165
- readonly resolvedSecrets: Record<string, string>;
166
- readonly runtimeDir: string;
167
- readonly tcpPool: {
168
- readonly basePort: number;
169
- readonly size: number;
170
- };
171
- readonly zone: GatewayZoneConfig;
172
- }
173
- interface GatewayLifecycle {
174
- /**
175
- * How to run interactive auth for this gateway type.
176
- * Absent means the gateway type does not support interactive auth.
177
- */
178
- readonly authConfig?: GatewayAuthConfig | undefined;
179
- /**
180
- * Build the full VM spec — everything Gondolin needs to create the VM.
181
- * Pure data assembly — no side effects.
182
- */
183
- buildVmSpec(options: BuildGatewayVmSpecOptions): GatewayVmSpec;
184
- /**
185
- * Build the process spec — everything about startup, health, and logging.
186
- * Pure data assembly — no side effects.
187
- */
188
- buildProcessSpec(zone: GatewayZoneConfig, resolvedSecrets: Record<string, string>): GatewayProcessSpec;
189
- /**
190
- * Optional hook to prepare host-side state before the VM boots.
191
- * Example: writing auth-profiles.json from 1Password.
192
- */
193
- prepareHostState?(zone: GatewayZoneConfig, secretResolver: SecretResolver): Promise<void>;
194
- }
195
- //#endregion
196
- //#region src/split-resolved-gateway-secrets.d.ts
197
- //#endregion
198
3
  //#region src/openclaw-lifecycle.d.ts
199
4
  declare const openclawLifecycle: GatewayLifecycle;
200
5
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","names":["gatewayTypeValues","GatewayType","buildGatewaySessionLabel","buildToolSessionLabel","PinnedRealFsRoot","SecretSpec","SecretRef","SecretResolver","Promise","Record","VfsMountSpec","GatewayHealthCheck","GatewayProcessSpec","GatewayVmSpec","GatewayAuthConfig","GatewayAuthProfilesRef","OnePasswordGatewayAuthProfilesRef","EnvironmentGatewayAuthProfilesRef","GatewaySshSecretEnvMode","GatewaySshConfig","GatewayZoneBaseGatewayConfig","OpenClawGatewayZoneGatewayConfig","Readonly","WorkerGatewayZoneGatewayConfig","GatewayZoneGatewayConfig","GatewayZoneConfig","BuildGatewayVmSpecOptions","GatewayLifecycle","SplitResolvedGatewaySecretsResult","splitResolvedGatewaySecrets"],"sources":["../../gateway-interface/dist/index.d.ts","../src/openclaw-lifecycle.ts"],"sourcesContent":["//#region src/gateway-runtime-contract.d.ts\ndeclare const gatewayTypeValues: readonly [\"openclaw\", \"worker\"];\ntype GatewayType = (typeof gatewayTypeValues)[number];\ndeclare function buildGatewaySessionLabel(projectNamespace: string, zoneId: string): string;\ndeclare function buildToolSessionLabel(projectNamespace: string, zoneId: string, tcpSlot: number): string;\n//#endregion\n//#region ../gondolin-adapter/dist/index.d.ts\n\n//#endregion\n//#region src/pinned-realfs.d.ts\ninterface PinnedRealFsRoot {\n readonly hostPath: string;\n readonly realPath: string;\n readonly fd: number;\n readonly device: number;\n readonly inode: number;\n}\n//#endregion\n//#region src/types.d.ts\ninterface SecretSpec {\n readonly hosts: readonly string[];\n readonly value: string;\n}\ntype SecretRef = {\n readonly source: '1password';\n readonly ref: string;\n} | {\n readonly source: 'environment';\n readonly ref: string;\n};\n//#endregion\n//#region src/secret-resolver.d.ts\n\ninterface SecretResolver {\n resolve(ref: SecretRef): Promise<string>;\n resolveAll(refs: Record<string, SecretRef>): Promise<Record<string, string>>;\n}\ninterface VfsMountSpec {\n readonly kind: 'realfs' | 'realfs-readonly' | 'memory' | 'shadow';\n readonly hostPath?: string;\n readonly pinnedHostRoot?: PinnedRealFsRoot;\n readonly shadowConfig?: {\n readonly deny: readonly string[];\n readonly tmpfs: readonly string[];\n };\n}\n//#endregion\n//#region src/gateway-process-spec.d.ts\ntype GatewayHealthCheck = {\n readonly type: 'http';\n readonly port: number;\n readonly path: string;\n} | {\n readonly type: 'command';\n readonly command: string;\n};\n/**\n * Everything about the process running inside the VM.\n * Retained by the running gateway handle for logs, health, restart.\n */\ninterface GatewayProcessSpec {\n readonly bootstrapCommand: string;\n readonly startCommand: string;\n readonly healthCheck: GatewayHealthCheck;\n readonly guestListenPort: number;\n readonly logPath: string;\n}\n//#endregion\n//#region src/gateway-vm-spec.d.ts\n/**\n * Everything the controller needs to create the Gondolin VM.\n * Lifecycle implementations own the full Gondolin-facing contract.\n */\ninterface GatewayVmSpec {\n readonly environment: Record<string, string>;\n readonly vfsMounts: Record<string, VfsMountSpec>;\n readonly mediatedSecrets: Record<string, SecretSpec>;\n readonly tcpHosts: Record<string, string>;\n readonly allowedHosts: readonly string[];\n readonly rootfsMode: 'readonly' | 'memory' | 'cow';\n readonly sessionLabel: string;\n}\n//#endregion\n//#region src/gateway-lifecycle.d.ts\n/**\n * Describes how to run interactive auth for a gateway type.\n * Static property — available without a running VM.\n */\ninterface GatewayAuthConfig {\n /**\n * Shell command to list available auth providers inside the VM.\n * Should output one provider name per line to stdout.\n */\n readonly listProvidersCommand: string;\n /**\n * Build the shell command for interactive auth login.\n * The CLI passes this as the SSH remote command with -t (TTY).\n */\n readonly buildLoginCommand: (provider: string, options?: {\n readonly deviceCode?: boolean;\n readonly setDefault?: boolean;\n }) => string;\n}\ninterface GatewayAuthProfilesRef {\n readonly source: '1password' | 'environment';\n}\ninterface OnePasswordGatewayAuthProfilesRef extends GatewayAuthProfilesRef {\n readonly source: '1password';\n readonly ref: string;\n}\ninterface EnvironmentGatewayAuthProfilesRef extends GatewayAuthProfilesRef {\n readonly source: 'environment';\n readonly envVar: string;\n}\ntype GatewaySshSecretEnvMode = 'always' | 'explicit' | 'never';\ninterface GatewaySshConfig {\n readonly secretEnv: GatewaySshSecretEnvMode;\n}\ninterface GatewayZoneBaseGatewayConfig {\n readonly type: GatewayType;\n readonly memory: string;\n readonly cpus: number;\n readonly port: number;\n readonly config: string;\n readonly stateDir: string;\n readonly ssh: GatewaySshConfig;\n readonly authProfilesRef?: OnePasswordGatewayAuthProfilesRef | EnvironmentGatewayAuthProfilesRef | undefined;\n}\ninterface OpenClawGatewayZoneGatewayConfig extends GatewayZoneBaseGatewayConfig {\n readonly type: 'openclaw';\n readonly zoneFilesDir: string;\n readonly authProfilesByAgent?: Readonly<Record<string, OnePasswordGatewayAuthProfilesRef | EnvironmentGatewayAuthProfilesRef>>;\n}\ninterface WorkerGatewayZoneGatewayConfig extends GatewayZoneBaseGatewayConfig {\n readonly type: 'worker';\n}\ntype GatewayZoneGatewayConfig = OpenClawGatewayZoneGatewayConfig | WorkerGatewayZoneGatewayConfig;\n/**\n * Zone config as the lifecycle sees it.\n * Decoupled from SystemConfig — the controller maps into this shape.\n */\ninterface GatewayZoneConfig {\n readonly id: string;\n readonly gateway: GatewayZoneGatewayConfig;\n readonly runtimeEnvironment?: Readonly<Record<string, string>>;\n readonly runtimePluginConfigs?: Readonly<Record<string, Readonly<Record<string, unknown>>>>;\n readonly secrets: Record<string, {\n readonly source: '1password';\n readonly ref: string;\n readonly injection: 'env' | 'http-mediation';\n readonly hosts?: readonly string[] | undefined;\n } | {\n readonly source: 'environment';\n readonly envVar: string;\n readonly injection: 'env' | 'http-mediation';\n readonly hosts?: readonly string[] | undefined;\n }>;\n readonly allowedHosts: readonly string[];\n readonly websocketBypass: readonly string[];\n readonly defaultToolVmProfile?: string;\n}\ninterface BuildGatewayVmSpecOptions {\n readonly controllerPort: number;\n readonly gatewayCacheDir: string;\n readonly projectNamespace: string;\n readonly resolvedSecrets: Record<string, string>;\n readonly runtimeDir: string;\n readonly tcpPool: {\n readonly basePort: number;\n readonly size: number;\n };\n readonly zone: GatewayZoneConfig;\n}\ninterface GatewayLifecycle {\n /**\n * How to run interactive auth for this gateway type.\n * Absent means the gateway type does not support interactive auth.\n */\n readonly authConfig?: GatewayAuthConfig | undefined;\n /**\n * Build the full VM spec — everything Gondolin needs to create the VM.\n * Pure data assembly — no side effects.\n */\n buildVmSpec(options: BuildGatewayVmSpecOptions): GatewayVmSpec;\n /**\n * Build the process spec — everything about startup, health, and logging.\n * Pure data assembly — no side effects.\n */\n buildProcessSpec(zone: GatewayZoneConfig, resolvedSecrets: Record<string, string>): GatewayProcessSpec;\n /**\n * Optional hook to prepare host-side state before the VM boots.\n * Example: writing auth-profiles.json from 1Password.\n */\n prepareHostState?(zone: GatewayZoneConfig, secretResolver: SecretResolver): Promise<void>;\n}\n//#endregion\n//#region src/split-resolved-gateway-secrets.d.ts\ninterface SplitResolvedGatewaySecretsResult {\n readonly environmentSecrets: Record<string, string>;\n readonly mediatedSecrets: Record<string, SecretSpec>;\n}\ndeclare function splitResolvedGatewaySecrets(zone: GatewayZoneConfig, resolvedSecrets: Record<string, string>): SplitResolvedGatewaySecretsResult;\n//#endregion\nexport { type BuildGatewayVmSpecOptions, type GatewayAuthConfig, type GatewayHealthCheck, type GatewayLifecycle, type GatewayProcessSpec, type GatewayType, type GatewayVmSpec, type GatewayZoneConfig, type SplitResolvedGatewaySecretsResult, buildGatewaySessionLabel, buildToolSessionLabel, gatewayTypeValues, splitResolvedGatewaySecrets };\n//# sourceMappingURL=index.d.ts.map"],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../src/openclaw-lifecycle.ts"],"mappings":";;;cA8aa,iBAAA,EAAmB,gBAAA"}
package/dist/index.js CHANGED
@@ -1,8 +1,7 @@
1
1
  import { chmod, mkdir, readFile } from "node:fs/promises";
2
2
  import path from "node:path";
3
- import { buildGatewaySessionLabel, splitResolvedGatewaySecrets } from "@agent-vm/gateway-interface";
3
+ import { buildGatewaySessionLabel, controllerVmHost, gatewayVmAllowedHosts, splitResolvedGatewaySecrets } from "@agent-vm/gateway-interface";
4
4
  import { writeFileAtomically } from "@agent-vm/gondolin-adapter";
5
-
6
5
  //#region src/openclaw-lifecycle.ts
7
6
  const effectiveOpenClawConfigFileName = "effective-openclaw.json";
8
7
  const effectiveOpenClawConfigVmPath = `/home/openclaw/.openclaw/state/${effectiveOpenClawConfigFileName}`;
@@ -23,7 +22,7 @@ function isObjectRecord(value) {
23
22
  return typeof value === "object" && value !== null && !Array.isArray(value);
24
23
  }
25
24
  function buildGatewayTcpHosts(zone, controllerPort, tcpPool) {
26
- const tcpHosts = { "controller.vm.host:18800": `127.0.0.1:${controllerPort}` };
25
+ const tcpHosts = { [`${controllerVmHost}:18800`]: `127.0.0.1:${controllerPort}` };
27
26
  for (let slot = 0; slot < tcpPool.size; slot += 1) tcpHosts[`tool-${slot}.vm.host:22`] = `127.0.0.1:${tcpPool.basePort + slot}`;
28
27
  for (const websocketHost of zone.websocketBypass) tcpHosts[websocketHost] = websocketHost;
29
28
  return tcpHosts;
@@ -43,17 +42,18 @@ function buildOpenClawBootstrapCommand(zone, resolvedSecrets) {
43
42
  "export pnpm_config_store_dir=/work/cache/pnpm/store",
44
43
  "export PIP_CACHE_DIR=/work/cache/pip",
45
44
  "export UV_CACHE_DIR=/work/cache/uv",
46
- "export NODE_EXTRA_CA_CERTS=/run/gondolin/ca-certificates.crt"
45
+ "export NODE_EXTRA_CA_CERTS=/run/gondolin/ca-certificates.crt",
46
+ "export NODE_OPTIONS=--dns-result-order=ipv4first"
47
47
  ];
48
48
  const secretEnvironmentLines = Object.entries({
49
49
  ...environmentSecrets,
50
50
  ...zone.runtimeEnvironment
51
- }).map(([secretName, secretValue]) => `export ${secretName}=${shellQuote(secretValue)}`);
51
+ }).map(([secretName, secretValue]) => `export ${secretName}=${shellQuoteEnvSecretValue(secretName, secretValue)}`);
52
+ const secretsFileCommand = secretEnvironmentLines.length === 0 ? `: > ${openClawRuntimeSecretsEnvFilePath} && ` : `printf '%s\\n' ${secretEnvironmentLines.map((line) => shellQuote(line)).join(" ")} > ${openClawRuntimeSecretsEnvFilePath} && `;
53
+ const sshConfigCommand = `mkdir -p /root/.ssh /home/openclaw/.ssh && printf '%s\\n' ${["Host tool-*.vm.host", " AddressFamily inet"].map((line) => shellQuote(line)).join(" ")} > /root/.ssh/config && cp /root/.ssh/config /home/openclaw/.ssh/config && chown -R openclaw:openclaw /home/openclaw/.ssh && chmod 700 /root/.ssh /home/openclaw/.ssh && chmod 600 /root/.ssh/config /home/openclaw/.ssh/config && `;
52
54
  return `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` + environmentLines.join("\n") + `
53
55
  ENVEOF
54
- chmod 644 ${openClawShellEnvFilePath} && cat > ${openClawRuntimeSecretsEnvFilePath} << 'ENVEOF'\n` + secretEnvironmentLines.join("\n") + `
55
- ENVEOF
56
- chmod 600 ${openClawRuntimeSecretsEnvFilePath} && touch /root/.bashrc && grep -qxF 'source ${openClawShellEnvFilePath}' /root/.bashrc || echo 'source ${openClawShellEnvFilePath}' >> /root/.bashrc && touch /root/.bash_profile && grep -qxF 'source /root/.bashrc' /root/.bash_profile || echo 'source /root/.bashrc' >> /root/.bash_profile`;
56
+ chmod 644 ${openClawShellEnvFilePath} && ` + secretsFileCommand + `chmod 600 ${openClawRuntimeSecretsEnvFilePath} && ` + sshConfigCommand + `touch /root/.bashrc && grep -qxF 'source ${openClawShellEnvFilePath}' /root/.bashrc || echo 'source ${openClawShellEnvFilePath}' >> /root/.bashrc && touch /root/.bash_profile && grep -qxF 'source /root/.bashrc' /root/.bash_profile || echo 'source /root/.bashrc' >> /root/.bash_profile`;
57
57
  }
58
58
  function getEffectiveOpenClawConfigHostPath(zone) {
59
59
  return path.join(zone.gateway.stateDir, effectiveOpenClawConfigFileName);
@@ -61,6 +61,17 @@ function getEffectiveOpenClawConfigHostPath(zone) {
61
61
  function shellQuote(value) {
62
62
  return `'${value.replace(/'/gu, `'\\''`)}'`;
63
63
  }
64
+ function includesShellUnsafeControlByte(value) {
65
+ for (const character of value) {
66
+ const codePoint = character.codePointAt(0);
67
+ if (codePoint !== void 0 && (codePoint <= 31 || codePoint === 127)) return true;
68
+ }
69
+ return false;
70
+ }
71
+ function shellQuoteEnvSecretValue(secretName, value) {
72
+ if (includesShellUnsafeControlByte(value)) throw new Error(`OpenClaw env-injected gateway secret '${secretName}' must be a single-line value without control bytes. Use http-mediation for secrets that require structured transport.`);
73
+ return shellQuote(value);
74
+ }
64
75
  function isSourceAwareSecretReference(value) {
65
76
  if (typeof value !== "object" || value === null) return false;
66
77
  if (!("source" in value) || typeof value.source !== "string") return false;
@@ -91,18 +102,25 @@ function buildEffectiveSecretsConfig(parsedBaseConfig) {
91
102
  }
92
103
  };
93
104
  }
105
+ function buildEffectiveMcpPortalPluginConfig(existingPluginConfig, runtimeConfig) {
106
+ return {
107
+ ...typeof existingPluginConfig.binPath === "string" ? { binPath: existingPluginConfig.binPath } : {},
108
+ ...runtimeConfig
109
+ };
110
+ }
94
111
  function buildEffectivePluginsConfig(parsedBaseConfig, runtimePluginConfigs) {
95
112
  const existingPluginsConfig = isObjectRecord(parsedBaseConfig.plugins) ? parsedBaseConfig.plugins : {};
96
113
  const existingEntriesConfig = isObjectRecord(existingPluginsConfig.entries) ? existingPluginsConfig.entries : {};
97
114
  const runtimeEntriesConfig = Object.fromEntries(Object.entries(runtimePluginConfigs ?? {}).map(([pluginId, runtimeConfig]) => {
98
115
  const existingEntryConfig = isObjectRecord(existingEntriesConfig[pluginId]) ? existingEntriesConfig[pluginId] : {};
99
116
  const existingPluginConfig = isObjectRecord(existingEntryConfig.config) ? existingEntryConfig.config : {};
117
+ const config = pluginId === "mcp-portal" ? buildEffectiveMcpPortalPluginConfig(existingPluginConfig, runtimeConfig) : {
118
+ ...existingPluginConfig,
119
+ ...runtimeConfig
120
+ };
100
121
  return [pluginId, {
101
122
  ...existingEntryConfig,
102
- config: {
103
- ...existingPluginConfig,
104
- ...runtimeConfig
105
- }
123
+ config
106
124
  }];
107
125
  }));
108
126
  return {
@@ -113,6 +131,17 @@ function buildEffectivePluginsConfig(parsedBaseConfig, runtimePluginConfigs) {
113
131
  }
114
132
  };
115
133
  }
134
+ function buildEffectiveMcpConfig(parsedBaseConfig, runtimeMcpServers) {
135
+ const existingMcpConfig = isObjectRecord(parsedBaseConfig.mcp) ? parsedBaseConfig.mcp : {};
136
+ const existingServersConfig = isObjectRecord(existingMcpConfig.servers) ? existingMcpConfig.servers : {};
137
+ return {
138
+ ...existingMcpConfig,
139
+ servers: {
140
+ ...existingServersConfig,
141
+ ...runtimeMcpServers
142
+ }
143
+ };
144
+ }
116
145
  function buildEffectiveLoggingConfig(parsedBaseConfig) {
117
146
  return {
118
147
  file: openClawRuntimeLogFileVmPath,
@@ -153,6 +182,10 @@ async function writeEffectiveOpenClawConfig(zone) {
153
182
  const rawBaseConfig = await readFile(zone.gateway.config, "utf8");
154
183
  const parsedBaseConfig = JSON.parse(rawBaseConfig);
155
184
  if (!isObjectRecord(parsedBaseConfig)) throw new Error(`OpenClaw config at '${zone.gateway.config}' must be a JSON object.`);
185
+ const runtimePluginConfigs = {
186
+ ...zone.mcp === void 0 ? {} : { "mcp-portal": { configDir: "/home/openclaw/.openclaw/config" } },
187
+ ...zone.runtimePluginConfigs
188
+ };
156
189
  const config = isObjectRecord(parsedBaseConfig.gateway) ? parsedBaseConfig.gateway : {};
157
190
  const existingAuthConfig = isObjectRecord(config.auth) ? config.auth : {};
158
191
  const effectiveConfig = {
@@ -171,7 +204,8 @@ async function writeEffectiveOpenClawConfig(zone) {
171
204
  lastTouchedAt: (/* @__PURE__ */ new Date()).toISOString(),
172
205
  lastTouchedVersion: "agent-vm"
173
206
  },
174
- plugins: buildEffectivePluginsConfig(parsedBaseConfig, zone.runtimePluginConfigs),
207
+ mcp: buildEffectiveMcpConfig(parsedBaseConfig, zone.runtimeMcpServers),
208
+ plugins: buildEffectivePluginsConfig(parsedBaseConfig, runtimePluginConfigs),
175
209
  secrets: buildEffectiveSecretsConfig(parsedBaseConfig)
176
210
  };
177
211
  const effectiveConfigPath = getEffectiveOpenClawConfigHostPath(zone);
@@ -200,10 +234,11 @@ const openclawLifecycle = {
200
234
  const configDirectory = path.dirname(path.resolve(zone.gateway.config));
201
235
  const { environmentSecrets, mediatedSecrets } = splitResolvedGatewaySecrets(zone, resolvedSecrets);
202
236
  return {
203
- allowedHosts: [...zone.allowedHosts],
237
+ allowedHosts: gatewayVmAllowedHosts(zone.egressHosts),
204
238
  environment: {
205
239
  HOME: "/home/openclaw",
206
240
  NODE_EXTRA_CA_CERTS: "/run/gondolin/ca-certificates.crt",
241
+ NODE_OPTIONS: "--dns-result-order=ipv4first",
207
242
  OPENCLAW_CONFIG_PATH: effectiveOpenClawConfigVmPath,
208
243
  OPENCLAW_HOME: "/home/openclaw",
209
244
  OPENCLAW_STATE_DIR: openClawStateDirVmPath,
@@ -265,7 +300,7 @@ const openclawLifecycle = {
265
300
  await writeAuthProfilesIfConfigured(zone, secretResolver);
266
301
  }
267
302
  };
268
-
269
303
  //#endregion
270
304
  export { openclawLifecycle };
305
+
271
306
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["openClawGatewayTokenSecretRef: OpenClawSecretRef","tcpHosts: Record<string, string>","parsedBaseConfig: unknown","openclawLifecycle: GatewayLifecycle","buildGatewaySessionLabelValue"],"sources":["../src/openclaw-lifecycle.ts"],"sourcesContent":["import { chmod, mkdir, readFile } from 'node:fs/promises';\nimport path from 'node:path';\n\nimport type {\n\tBuildGatewayVmSpecOptions,\n\tGatewayLifecycle,\n\tGatewayProcessSpec,\n\tGatewayZoneConfig,\n\tGatewayVmSpec,\n} from '@agent-vm/gateway-interface';\nimport {\n\tbuildGatewaySessionLabel as buildGatewaySessionLabelValue,\n\tsplitResolvedGatewaySecrets,\n} from '@agent-vm/gateway-interface';\nimport {\n\ttype SecretRef,\n\ttype SecretResolver,\n\twriteFileAtomically,\n} from '@agent-vm/gondolin-adapter';\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 openClawGatewayTokenEnvVar = 'OPENCLAW_GATEWAY_TOKEN';\n\ninterface OpenClawSecretRef {\n\treadonly id: string;\n\treadonly provider: string;\n\treadonly source: 'env';\n}\n\nconst openClawGatewayTokenSecretRef: OpenClawSecretRef = {\n\tid: openClawGatewayTokenEnvVar,\n\tprovider: 'default',\n\tsource: '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'controller.vm.host: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\tconst { environmentSecrets } = splitResolvedGatewaySecrets(zone, resolvedSecrets);\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];\n\tconst secretEnvironmentLines = Object.entries({\n\t\t...environmentSecrets,\n\t\t...zone.runtimeEnvironment,\n\t}).map(([secretName, secretValue]) => `export ${secretName}=${shellQuote(secretValue)}`);\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\t`cat > ${openClawRuntimeSecretsEnvFilePath} << 'ENVEOF'\\n` +\n\t\tsecretEnvironmentLines.join('\\n') +\n\t\t'\\nENVEOF\\n' +\n\t\t`chmod 600 ${openClawRuntimeSecretsEnvFilePath} && ` +\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\nfunction shellQuote(value: string): string {\n\treturn `'${value.replace(/'/gu, `'\\\\''`)}'`;\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\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\treturn false;\n}\n\nfunction toSecretRef(secret: SourceAwareSecretReference): SecretRef {\n\treturn secret.source === 'environment'\n\t\t? {\n\t\t\t\tsource: 'environment',\n\t\t\t\tref: secret.envVar,\n\t\t\t}\n\t\t: {\n\t\t\t\tsource: '1password',\n\t\t\t\tref: secret.ref,\n\t\t\t};\n}\n\nfunction describeSecretReference(secret: SourceAwareSecretReference): string {\n\treturn secret.source === 'environment' ? secret.envVar : secret.ref;\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 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\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\t\t...existingPluginConfig,\n\t\t\t\t\t\t...runtimeConfig,\n\t\t\t\t\t},\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 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 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 writeResults = 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 authProfilesDirectory = path.join(zone.gateway.stateDir, 'agents', agentId, 'agent');\n\t\t\t\tawait mkdir(authProfilesDirectory, { recursive: true, mode: 0o700 });\n\t\t\t\tawait chmod(authProfilesDirectory, 0o700);\n\t\t\t\tconst authProfiles = await secretResolver.resolve(toSecretRef(authProfilesSecret));\n\t\t\t\tawait writeFileAtomically(\n\t\t\t\t\tpath.join(authProfilesDirectory, 'auth-profiles.json'),\n\t\t\t\t\tauthProfiles,\n\t\t\t\t\t{ mode: 0o600 },\n\t\t\t\t);\n\t\t\t} catch (error) {\n\t\t\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Failed to write 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 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 writeEffectiveOpenClawConfig(zone: GatewayZoneConfig): Promise<void> {\n\tconst gatewayTokenSecret = zone.secrets.OPENCLAW_GATEWAY_TOKEN;\n\tif (!gatewayTokenSecret) {\n\t\tthrow new Error(\n\t\t\t`Zone '${zone.id}' secret 'OPENCLAW_GATEWAY_TOKEN' is missing. Add an explicit 1Password or environment reference such as 'op://agent-vm/${zone.id}-gateway-auth/password'.`,\n\t\t);\n\t}\n\tif (!isSourceAwareSecretReference(gatewayTokenSecret)) {\n\t\tthrow new Error(`Zone '${zone.id}' secret 'OPENCLAW_GATEWAY_TOKEN' 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 'OPENCLAW_GATEWAY_TOKEN' is missing 'ref'. Add an explicit 1Password reference such as 'op://agent-vm/${zone.id}-gateway-auth/password'.`,\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 'OPENCLAW_GATEWAY_TOKEN' is missing 'envVar'. Add an explicit environment variable name.`,\n\t\t\t);\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 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\tplugins: buildEffectivePluginsConfig(parsedBaseConfig, zone.runtimePluginConfigs),\n\t\t\tsecrets: buildEffectiveSecretsConfig(parsedBaseConfig),\n\t\t};\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(\n\t\t\teffectiveConfigPath,\n\t\t\t`${JSON.stringify(effectiveConfig, null, 2)}\\n`,\n\t\t\t{ mode: 0o600 },\n\t\t);\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 write 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\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: { readonly deviceCode?: boolean; readonly setDefault?: boolean } = {},\n\t\t): string =>\n\t\t\t[\n\t\t\t\t`openclaw models auth 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 } = splitResolvedGatewaySecrets(\n\t\t\tzone,\n\t\t\tresolvedSecrets,\n\t\t);\n\n\t\treturn {\n\t\t\tallowedHosts: [...zone.allowedHosts],\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: `/pnpm:${process.env.PATH ?? ''}`,\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...zone.runtimeEnvironment,\n\t\t\t},\n\t\t\tmediatedSecrets,\n\t\t\trootfsMode: 'cow',\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\tstartCommand: `set -a && . ${openClawRuntimeSecretsEnvFilePath} && set +a && cd /home/openclaw && nohup openclaw 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\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"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":["buildGatewaySessionLabelValue"],"sources":["../src/openclaw-lifecycle.ts"],"sourcesContent":["import { chmod, mkdir, readFile } from 'node:fs/promises';\nimport path from 'node:path';\n\nimport type {\n\tBuildGatewayVmSpecOptions,\n\tGatewayLifecycle,\n\tGatewayProcessSpec,\n\tGatewayZoneConfig,\n\tGatewayVmSpec,\n} from '@agent-vm/gateway-interface';\nimport {\n\tbuildGatewaySessionLabel as buildGatewaySessionLabelValue,\n\tcontrollerVmHost,\n\tgatewayVmAllowedHosts,\n\tsplitResolvedGatewaySecrets,\n} from '@agent-vm/gateway-interface';\nimport {\n\ttype SecretRef,\n\ttype SecretResolver,\n\twriteFileAtomically,\n} from '@agent-vm/gondolin-adapter';\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 openClawGatewayTokenEnvVar = 'OPENCLAW_GATEWAY_TOKEN';\n\ninterface OpenClawSecretRef {\n\treadonly id: string;\n\treadonly provider: string;\n\treadonly source: 'env';\n}\n\nconst openClawGatewayTokenSecretRef: OpenClawSecretRef = {\n\tid: openClawGatewayTokenEnvVar,\n\tprovider: 'default',\n\tsource: '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\tconst { environmentSecrets } = splitResolvedGatewaySecrets(zone, resolvedSecrets);\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'export NODE_OPTIONS=--dns-result-order=ipv4first',\n\t];\n\tconst secretEnvironmentLines = Object.entries({\n\t\t...environmentSecrets,\n\t\t...zone.runtimeEnvironment,\n\t}).map(\n\t\t([secretName, secretValue]) =>\n\t\t\t`export ${secretName}=${shellQuoteEnvSecretValue(secretName, secretValue)}`,\n\t);\n\tconst secretsFileCommand =\n\t\tsecretEnvironmentLines.length === 0\n\t\t\t? `: > ${openClawRuntimeSecretsEnvFilePath} && `\n\t\t\t: `printf '%s\\\\n' ${secretEnvironmentLines.map((line) => shellQuote(line)).join(' ')} > ${openClawRuntimeSecretsEnvFilePath} && `;\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\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\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 shellQuoteEnvSecretValue(secretName: string, value: string): string {\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\treturn shellQuote(value);\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\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\treturn false;\n}\n\nfunction toSecretRef(secret: SourceAwareSecretReference): SecretRef {\n\treturn secret.source === 'environment'\n\t\t? {\n\t\t\t\tsource: 'environment',\n\t\t\t\tref: secret.envVar,\n\t\t\t}\n\t\t: {\n\t\t\t\tsource: '1password',\n\t\t\t\tref: secret.ref,\n\t\t\t};\n}\n\nfunction describeSecretReference(secret: SourceAwareSecretReference): string {\n\treturn secret.source === 'environment' ? secret.envVar : secret.ref;\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\texistingPluginConfig: Record<string, unknown>,\n\truntimeConfig: Readonly<Record<string, unknown>>,\n): Record<string, unknown> {\n\tconst preservedConfig =\n\t\ttypeof existingPluginConfig.binPath === 'string'\n\t\t\t? { binPath: existingPluginConfig.binPath }\n\t\t\t: {};\n\treturn {\n\t\t...preservedConfig,\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 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 writeResults = 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 authProfilesDirectory = path.join(zone.gateway.stateDir, 'agents', agentId, 'agent');\n\t\t\t\tawait mkdir(authProfilesDirectory, { recursive: true, mode: 0o700 });\n\t\t\t\tawait chmod(authProfilesDirectory, 0o700);\n\t\t\t\tconst authProfiles = await secretResolver.resolve(toSecretRef(authProfilesSecret));\n\t\t\t\tawait writeFileAtomically(\n\t\t\t\t\tpath.join(authProfilesDirectory, 'auth-profiles.json'),\n\t\t\t\t\tauthProfiles,\n\t\t\t\t\t{ mode: 0o600 },\n\t\t\t\t);\n\t\t\t} catch (error) {\n\t\t\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Failed to write 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 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 writeEffectiveOpenClawConfig(zone: GatewayZoneConfig): Promise<void> {\n\tconst gatewayTokenSecret = zone.secrets.OPENCLAW_GATEWAY_TOKEN;\n\tif (!gatewayTokenSecret) {\n\t\tthrow new Error(\n\t\t\t`Zone '${zone.id}' secret 'OPENCLAW_GATEWAY_TOKEN' is missing. Add an explicit 1Password or environment reference such as 'op://agent-vm/${zone.id}-gateway-auth/password'.`,\n\t\t);\n\t}\n\tif (!isSourceAwareSecretReference(gatewayTokenSecret)) {\n\t\tthrow new Error(`Zone '${zone.id}' secret 'OPENCLAW_GATEWAY_TOKEN' 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 'OPENCLAW_GATEWAY_TOKEN' is missing 'ref'. Add an explicit 1Password reference such as 'op://agent-vm/${zone.id}-gateway-auth/password'.`,\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 'OPENCLAW_GATEWAY_TOKEN' is missing 'envVar'. Add an explicit environment variable name.`,\n\t\t\t);\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.mcp === undefined\n\t\t\t\t? {}\n\t\t\t\t: { 'mcp-portal': { configDir: '/home/openclaw/.openclaw/config' } }),\n\t\t\t...zone.runtimePluginConfigs,\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\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(\n\t\t\teffectiveConfigPath,\n\t\t\t`${JSON.stringify(effectiveConfig, null, 2)}\\n`,\n\t\t\t{ mode: 0o600 },\n\t\t);\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 write 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\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: { readonly deviceCode?: boolean; readonly setDefault?: boolean } = {},\n\t\t): string =>\n\t\t\t[\n\t\t\t\t`openclaw models auth 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 } = splitResolvedGatewaySecrets(\n\t\t\tzone,\n\t\t\tresolvedSecrets,\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\tNODE_OPTIONS: '--dns-result-order=ipv4first',\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: `/pnpm:${process.env.PATH ?? ''}`,\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...zone.runtimeEnvironment,\n\t\t\t},\n\t\t\tmediatedSecrets,\n\t\t\trootfsMode: 'cow',\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\tstartCommand: `set -a && . ${openClawRuntimeSecretsEnvFilePath} && set +a && cd /home/openclaw && nohup openclaw 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\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"],"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.58",
3
+ "version": "0.0.60",
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,8 +29,8 @@
29
29
  "access": "public"
30
30
  },
31
31
  "dependencies": {
32
- "@agent-vm/gateway-interface": "0.0.58",
33
- "@agent-vm/gondolin-adapter": "0.0.58"
32
+ "@agent-vm/gondolin-adapter": "0.0.60",
33
+ "@agent-vm/gateway-interface": "0.0.60"
34
34
  },
35
35
  "scripts": {
36
36
  "build": "tsdown",