agent-relay 3.1.10 → 3.1.12
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/bin/agent-relay-broker-darwin-arm64 +0 -0
- package/bin/agent-relay-broker-darwin-x64 +0 -0
- package/bin/agent-relay-broker-linux-arm64 +0 -0
- package/bin/agent-relay-broker-linux-x64 +0 -0
- package/dist/index.cjs +2 -2
- package/dist/src/cli/bootstrap.d.ts.map +1 -1
- package/dist/src/cli/bootstrap.js +2 -0
- package/dist/src/cli/bootstrap.js.map +1 -1
- package/dist/src/cli/commands/connect.d.ts +3 -0
- package/dist/src/cli/commands/connect.d.ts.map +1 -0
- package/dist/src/cli/commands/connect.js +18 -0
- package/dist/src/cli/commands/connect.js.map +1 -0
- package/dist/src/cli/lib/auth-ssh.d.ts.map +1 -1
- package/dist/src/cli/lib/auth-ssh.js +22 -270
- package/dist/src/cli/lib/auth-ssh.js.map +1 -1
- package/dist/src/cli/lib/broker-lifecycle.d.ts.map +1 -1
- package/dist/src/cli/lib/broker-lifecycle.js +33 -0
- package/dist/src/cli/lib/broker-lifecycle.js.map +1 -1
- package/dist/src/cli/lib/connect-daytona.d.ts +15 -0
- package/dist/src/cli/lib/connect-daytona.d.ts.map +1 -0
- package/dist/src/cli/lib/connect-daytona.js +217 -0
- package/dist/src/cli/lib/connect-daytona.js.map +1 -0
- package/dist/src/cli/lib/ssh-interactive.d.ts +41 -0
- package/dist/src/cli/lib/ssh-interactive.d.ts.map +1 -0
- package/dist/src/cli/lib/ssh-interactive.js +320 -0
- package/dist/src/cli/lib/ssh-interactive.js.map +1 -0
- package/install.sh +2 -1
- package/package.json +13 -10
- package/packages/acp-bridge/package.json +2 -2
- package/packages/config/dist/cli-auth-config.d.ts +2 -0
- package/packages/config/dist/cli-auth-config.d.ts.map +1 -1
- package/packages/config/dist/cli-auth-config.js +1 -0
- package/packages/config/dist/cli-auth-config.js.map +1 -1
- package/packages/config/package.json +1 -1
- package/packages/config/src/cli-auth-config.ts +3 -0
- package/packages/hooks/package.json +4 -4
- package/packages/memory/package.json +2 -2
- package/packages/openclaw/dist/__tests__/gateway-control.test.js +13 -13
- package/packages/openclaw/dist/__tests__/gateway-control.test.js.map +1 -1
- package/packages/openclaw/dist/__tests__/gateway-poll-fallback.test.d.ts +2 -0
- package/packages/openclaw/dist/__tests__/gateway-poll-fallback.test.d.ts.map +1 -0
- package/packages/openclaw/dist/__tests__/gateway-poll-fallback.test.js +369 -0
- package/packages/openclaw/dist/__tests__/gateway-poll-fallback.test.js.map +1 -0
- package/packages/openclaw/dist/__tests__/gateway-threads.test.js +57 -16
- package/packages/openclaw/dist/__tests__/gateway-threads.test.js.map +1 -1
- package/packages/openclaw/dist/__tests__/ws-client.test.js +2 -0
- package/packages/openclaw/dist/__tests__/ws-client.test.js.map +1 -1
- package/packages/openclaw/dist/config.d.ts +2 -0
- package/packages/openclaw/dist/config.d.ts.map +1 -1
- package/packages/openclaw/dist/config.js +99 -12
- package/packages/openclaw/dist/config.js.map +1 -1
- package/packages/openclaw/dist/gateway.d.ts +56 -2
- package/packages/openclaw/dist/gateway.d.ts.map +1 -1
- package/packages/openclaw/dist/gateway.js +819 -127
- package/packages/openclaw/dist/gateway.js.map +1 -1
- package/packages/openclaw/dist/runtime/openclaw-config.d.ts +2 -0
- package/packages/openclaw/dist/runtime/openclaw-config.d.ts.map +1 -1
- package/packages/openclaw/dist/runtime/openclaw-config.js +1 -1
- package/packages/openclaw/dist/runtime/openclaw-config.js.map +1 -1
- package/packages/openclaw/dist/runtime/setup.d.ts +0 -2
- package/packages/openclaw/dist/runtime/setup.d.ts.map +1 -1
- package/packages/openclaw/dist/runtime/setup.js +53 -8
- package/packages/openclaw/dist/runtime/setup.js.map +1 -1
- package/packages/openclaw/dist/types.d.ts +28 -0
- package/packages/openclaw/dist/types.d.ts.map +1 -1
- package/packages/openclaw/package.json +2 -2
- package/packages/openclaw/skill/SKILL.md +150 -44
- package/packages/openclaw/src/__tests__/gateway-control.test.ts +14 -14
- package/packages/openclaw/src/__tests__/gateway-poll-fallback.test.ts +467 -0
- package/packages/openclaw/src/__tests__/gateway-threads.test.ts +73 -23
- package/packages/openclaw/src/__tests__/ws-client.test.ts +71 -51
- package/packages/openclaw/src/config.ts +121 -12
- package/packages/openclaw/src/gateway.ts +1155 -252
- package/packages/openclaw/src/runtime/openclaw-config.ts +3 -1
- package/packages/openclaw/src/runtime/setup.ts +57 -16
- package/packages/openclaw/src/types.ts +31 -0
- package/packages/openclaw/test/vitest.setup.ts +1 -0
- package/packages/policy/package.json +2 -2
- package/packages/sdk/dist/__tests__/unit.test.js +131 -129
- package/packages/sdk/dist/__tests__/unit.test.js.map +1 -1
- package/packages/sdk/dist/relay.js +1 -1
- package/packages/sdk/dist/workflows/runner.d.ts.map +1 -1
- package/packages/sdk/dist/workflows/runner.js +5 -3
- package/packages/sdk/dist/workflows/runner.js.map +1 -1
- package/packages/sdk/package.json +2 -2
- package/packages/sdk/src/__tests__/unit.test.ts +142 -157
- package/packages/sdk/src/relay.ts +1 -1
- package/packages/sdk/src/workflows/runner.ts +12 -9
- package/packages/sdk-py/pyproject.toml +1 -1
- package/packages/telemetry/package.json +1 -1
- package/packages/trajectory/package.json +2 -2
- package/packages/user-directory/package.json +2 -2
- package/packages/utils/package.json +2 -2
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { describe, it, expect, vi,
|
|
1
|
+
import { describe, it, expect, vi, afterEach } from 'vitest';
|
|
2
2
|
import { WebSocketServer, type WebSocket as WsType } from 'ws';
|
|
3
3
|
|
|
4
4
|
// Mock spawn/manager and relaycast SDK to prevent side-effects from gateway.ts module load
|
|
@@ -42,6 +42,8 @@ vi.mock('node:fs/promises', () => ({
|
|
|
42
42
|
readFile: vi.fn().mockResolvedValue('{"spawns":[]}'),
|
|
43
43
|
writeFile: vi.fn().mockResolvedValue(undefined),
|
|
44
44
|
mkdir: vi.fn().mockResolvedValue(undefined),
|
|
45
|
+
rename: vi.fn().mockResolvedValue(undefined),
|
|
46
|
+
chmod: vi.fn().mockResolvedValue(undefined),
|
|
45
47
|
}));
|
|
46
48
|
|
|
47
49
|
vi.mock('node:fs', () => ({
|
|
@@ -114,12 +116,14 @@ class MockOpenClawServer {
|
|
|
114
116
|
if (this.acceptAuth) {
|
|
115
117
|
ws.send(JSON.stringify({ type: 'res', id: 'connect-1', ok: true }));
|
|
116
118
|
} else {
|
|
117
|
-
ws.send(
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
119
|
+
ws.send(
|
|
120
|
+
JSON.stringify({
|
|
121
|
+
type: 'res',
|
|
122
|
+
id: 'connect-1',
|
|
123
|
+
ok: false,
|
|
124
|
+
error: { code: 'auth_failed', message: 'Invalid token' },
|
|
125
|
+
})
|
|
126
|
+
);
|
|
123
127
|
}
|
|
124
128
|
return;
|
|
125
129
|
}
|
|
@@ -128,19 +132,23 @@ class MockOpenClawServer {
|
|
|
128
132
|
if (msg.method === 'chat.send') {
|
|
129
133
|
const respond = () => {
|
|
130
134
|
if (this.chatOk) {
|
|
131
|
-
ws.send(
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
135
|
+
ws.send(
|
|
136
|
+
JSON.stringify({
|
|
137
|
+
type: 'res',
|
|
138
|
+
id: msg.id,
|
|
139
|
+
ok: true,
|
|
140
|
+
payload: { runId: 'run-1', status: 'accepted' },
|
|
141
|
+
})
|
|
142
|
+
);
|
|
137
143
|
} else {
|
|
138
|
-
ws.send(
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
+
ws.send(
|
|
145
|
+
JSON.stringify({
|
|
146
|
+
type: 'res',
|
|
147
|
+
id: msg.id,
|
|
148
|
+
ok: false,
|
|
149
|
+
error: { code: 'rate_limited', message: 'Too many requests' },
|
|
150
|
+
})
|
|
151
|
+
);
|
|
144
152
|
}
|
|
145
153
|
};
|
|
146
154
|
|
|
@@ -308,11 +316,13 @@ describe('OpenClawGatewayClient', () => {
|
|
|
308
316
|
origWss.removeAllListeners('connection');
|
|
309
317
|
origWss.on('connection', (ws) => {
|
|
310
318
|
// Send challenge
|
|
311
|
-
ws.send(
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
319
|
+
ws.send(
|
|
320
|
+
JSON.stringify({
|
|
321
|
+
type: 'event',
|
|
322
|
+
event: 'connect.challenge',
|
|
323
|
+
payload: { nonce: 'nonce-1', ts: Date.now() },
|
|
324
|
+
})
|
|
325
|
+
);
|
|
316
326
|
ws.on('message', (data) => {
|
|
317
327
|
const msg = JSON.parse(data.toString()) as Record<string, unknown>;
|
|
318
328
|
if (msg.method === 'connect') {
|
|
@@ -354,11 +364,13 @@ describe('OpenClawGatewayClient', () => {
|
|
|
354
364
|
origWss.on('connection', (ws) => {
|
|
355
365
|
// Send garbage first, then a proper challenge
|
|
356
366
|
ws.send('not json at all');
|
|
357
|
-
ws.send(
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
367
|
+
ws.send(
|
|
368
|
+
JSON.stringify({
|
|
369
|
+
type: 'event',
|
|
370
|
+
event: 'connect.challenge',
|
|
371
|
+
payload: { nonce: 'nonce-2', ts: Date.now() },
|
|
372
|
+
})
|
|
373
|
+
);
|
|
362
374
|
ws.on('message', (data) => {
|
|
363
375
|
const msg = JSON.parse(data.toString()) as Record<string, unknown>;
|
|
364
376
|
if (msg.method === 'connect') {
|
|
@@ -380,22 +392,26 @@ describe('OpenClawGatewayClient', () => {
|
|
|
380
392
|
origWss.on('connection', (ws) => {
|
|
381
393
|
connectAttempts++;
|
|
382
394
|
// Send challenge
|
|
383
|
-
ws.send(
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
395
|
+
ws.send(
|
|
396
|
+
JSON.stringify({
|
|
397
|
+
type: 'event',
|
|
398
|
+
event: 'connect.challenge',
|
|
399
|
+
payload: { nonce: `nonce-fallback-${connectAttempts}`, ts: Date.now() },
|
|
400
|
+
})
|
|
401
|
+
);
|
|
388
402
|
ws.on('message', (data) => {
|
|
389
403
|
const msg = JSON.parse(data.toString()) as Record<string, unknown>;
|
|
390
404
|
if (msg.method === 'connect') {
|
|
391
405
|
if (connectAttempts === 1) {
|
|
392
406
|
// First attempt: reject with signature invalid
|
|
393
|
-
ws.send(
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
407
|
+
ws.send(
|
|
408
|
+
JSON.stringify({
|
|
409
|
+
type: 'res',
|
|
410
|
+
id: 'connect-1',
|
|
411
|
+
ok: false,
|
|
412
|
+
error: { code: 'auth_failed', message: 'device signature invalid' },
|
|
413
|
+
})
|
|
414
|
+
);
|
|
399
415
|
} else {
|
|
400
416
|
// Second attempt (fallback): accept
|
|
401
417
|
ws.send(JSON.stringify({ type: 'res', id: 'connect-1', ok: true }));
|
|
@@ -418,21 +434,25 @@ describe('OpenClawGatewayClient', () => {
|
|
|
418
434
|
origWss.removeAllListeners('connection');
|
|
419
435
|
origWss.on('connection', (ws) => {
|
|
420
436
|
connectAttempts++;
|
|
421
|
-
ws.send(
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
437
|
+
ws.send(
|
|
438
|
+
JSON.stringify({
|
|
439
|
+
type: 'event',
|
|
440
|
+
event: 'connect.challenge',
|
|
441
|
+
payload: { nonce: `nonce-nofallback-${connectAttempts}`, ts: Date.now() },
|
|
442
|
+
})
|
|
443
|
+
);
|
|
426
444
|
ws.on('message', (data) => {
|
|
427
445
|
const msg = JSON.parse(data.toString()) as Record<string, unknown>;
|
|
428
446
|
if (msg.method === 'connect') {
|
|
429
447
|
// Always reject with signature invalid
|
|
430
|
-
ws.send(
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
448
|
+
ws.send(
|
|
449
|
+
JSON.stringify({
|
|
450
|
+
type: 'res',
|
|
451
|
+
id: 'connect-1',
|
|
452
|
+
ok: false,
|
|
453
|
+
error: { code: 'auth_failed', message: 'device signature invalid' },
|
|
454
|
+
})
|
|
455
|
+
);
|
|
436
456
|
}
|
|
437
457
|
});
|
|
438
458
|
});
|
|
@@ -5,6 +5,28 @@ import { existsSync, readFileSync } from 'node:fs';
|
|
|
5
5
|
|
|
6
6
|
import type { GatewayConfig } from './types.js';
|
|
7
7
|
|
|
8
|
+
function envValue(vars: Record<string, string>, key: string): string | undefined {
|
|
9
|
+
const processValue = process.env[key]?.trim();
|
|
10
|
+
if (processValue) return processValue;
|
|
11
|
+
const fileValue = vars[key]?.trim();
|
|
12
|
+
return fileValue ? fileValue : undefined;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function parseBooleanEnv(vars: Record<string, string>, key: string): boolean | undefined {
|
|
16
|
+
const value = envValue(vars, key);
|
|
17
|
+
if (!value) return undefined;
|
|
18
|
+
if (['1', 'true', 'yes', 'on'].includes(value.toLowerCase())) return true;
|
|
19
|
+
if (['0', 'false', 'no', 'off'].includes(value.toLowerCase())) return false;
|
|
20
|
+
return undefined;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function parseNumberEnv(vars: Record<string, string>, key: string): number | undefined {
|
|
24
|
+
const value = envValue(vars, key);
|
|
25
|
+
if (!value) return undefined;
|
|
26
|
+
const parsed = Number(value);
|
|
27
|
+
return Number.isFinite(parsed) ? parsed : undefined;
|
|
28
|
+
}
|
|
29
|
+
|
|
8
30
|
export interface OpenClawDetection {
|
|
9
31
|
/** Whether OpenClaw is installed. */
|
|
10
32
|
installed: boolean;
|
|
@@ -61,6 +83,15 @@ export function openclawHome(): string {
|
|
|
61
83
|
return openclawHomePath;
|
|
62
84
|
}
|
|
63
85
|
|
|
86
|
+
/** Return the config filename for the resolved OpenClaw home (clawdbot.json or openclaw.json). */
|
|
87
|
+
export function openclawConfigFilename(home?: string): string {
|
|
88
|
+
const dir = home ?? openclawHome();
|
|
89
|
+
if (hasValidConfig(dir, 'clawdbot.json')) return 'clawdbot.json';
|
|
90
|
+
if (hasValidConfig(dir, 'openclaw.json')) return 'openclaw.json';
|
|
91
|
+
// No existing config — infer from directory name
|
|
92
|
+
return dir.endsWith('.clawdbot') ? 'clawdbot.json' : 'openclaw.json';
|
|
93
|
+
}
|
|
94
|
+
|
|
64
95
|
/**
|
|
65
96
|
* Detect whether OpenClaw is installed and return paths/config.
|
|
66
97
|
*/
|
|
@@ -138,6 +169,7 @@ export async function detectOpenClaw(): Promise<OpenClawDetection> {
|
|
|
138
169
|
* Load the gateway config from ~/.openclaw/workspace/relaycast/.env.
|
|
139
170
|
* Returns null if the file doesn't exist or can't be parsed.
|
|
140
171
|
*/
|
|
172
|
+
// eslint-disable-next-line complexity
|
|
141
173
|
export async function loadGatewayConfig(): Promise<GatewayConfig | null> {
|
|
142
174
|
const detection = await detectOpenClaw();
|
|
143
175
|
const envPath = join(detection.workspaceDir, 'relaycast', '.env');
|
|
@@ -163,25 +195,69 @@ export async function loadGatewayConfig(): Promise<GatewayConfig | null> {
|
|
|
163
195
|
vars[trimmed.slice(0, eqIdx)] = value;
|
|
164
196
|
}
|
|
165
197
|
|
|
166
|
-
const apiKey = vars
|
|
167
|
-
const clawName = vars
|
|
198
|
+
const apiKey = envValue(vars, 'RELAY_API_KEY');
|
|
199
|
+
const clawName = envValue(vars, 'RELAY_CLAW_NAME');
|
|
200
|
+
const relayChannels = envValue(vars, 'RELAY_CHANNELS');
|
|
168
201
|
|
|
169
202
|
if (!apiKey || !clawName) {
|
|
170
203
|
return null;
|
|
171
204
|
}
|
|
172
205
|
|
|
173
|
-
const
|
|
174
|
-
const
|
|
206
|
+
const port = parseNumberEnv(vars, 'OPENCLAW_GATEWAY_PORT');
|
|
207
|
+
const pollFallbackEnabled = parseBooleanEnv(vars, 'RELAY_TRANSPORT_POLL_FALLBACK_ENABLED');
|
|
208
|
+
const pollFallbackProbeWsEnabled = parseBooleanEnv(
|
|
209
|
+
vars,
|
|
210
|
+
'RELAY_TRANSPORT_POLL_FALLBACK_PROBE_WS_ENABLED'
|
|
211
|
+
);
|
|
212
|
+
const pollFallbackWsFailureThreshold = parseNumberEnv(
|
|
213
|
+
vars,
|
|
214
|
+
'RELAY_TRANSPORT_POLL_FALLBACK_WS_FAILURE_THRESHOLD'
|
|
215
|
+
);
|
|
216
|
+
const pollFallbackTimeoutSeconds = parseNumberEnv(vars, 'RELAY_TRANSPORT_POLL_FALLBACK_TIMEOUT_SECONDS');
|
|
217
|
+
const pollFallbackLimit = parseNumberEnv(vars, 'RELAY_TRANSPORT_POLL_FALLBACK_LIMIT');
|
|
218
|
+
const pollFallbackProbeWsIntervalMs = parseNumberEnv(
|
|
219
|
+
vars,
|
|
220
|
+
'RELAY_TRANSPORT_POLL_FALLBACK_PROBE_WS_INTERVAL_MS'
|
|
221
|
+
);
|
|
222
|
+
const pollFallbackProbeWsStableGraceMs = parseNumberEnv(
|
|
223
|
+
vars,
|
|
224
|
+
'RELAY_TRANSPORT_POLL_FALLBACK_PROBE_WS_STABLE_GRACE_MS'
|
|
225
|
+
);
|
|
226
|
+
const pollFallbackInitialCursor = envValue(vars, 'RELAY_TRANSPORT_POLL_FALLBACK_INITIAL_CURSOR');
|
|
227
|
+
|
|
228
|
+
const transport =
|
|
229
|
+
pollFallbackEnabled !== undefined ||
|
|
230
|
+
pollFallbackProbeWsEnabled !== undefined ||
|
|
231
|
+
pollFallbackWsFailureThreshold !== undefined ||
|
|
232
|
+
pollFallbackTimeoutSeconds !== undefined ||
|
|
233
|
+
pollFallbackLimit !== undefined ||
|
|
234
|
+
pollFallbackProbeWsIntervalMs !== undefined ||
|
|
235
|
+
pollFallbackProbeWsStableGraceMs !== undefined ||
|
|
236
|
+
pollFallbackInitialCursor !== undefined
|
|
237
|
+
? {
|
|
238
|
+
pollFallback: {
|
|
239
|
+
enabled: pollFallbackEnabled,
|
|
240
|
+
wsFailureThreshold: pollFallbackWsFailureThreshold,
|
|
241
|
+
timeoutSeconds: pollFallbackTimeoutSeconds,
|
|
242
|
+
limit: pollFallbackLimit,
|
|
243
|
+
initialCursor: pollFallbackInitialCursor,
|
|
244
|
+
probeWs: {
|
|
245
|
+
enabled: pollFallbackProbeWsEnabled,
|
|
246
|
+
intervalMs: pollFallbackProbeWsIntervalMs,
|
|
247
|
+
stableGraceMs: pollFallbackProbeWsStableGraceMs,
|
|
248
|
+
},
|
|
249
|
+
},
|
|
250
|
+
}
|
|
251
|
+
: undefined;
|
|
175
252
|
|
|
176
253
|
return {
|
|
177
254
|
apiKey,
|
|
178
255
|
clawName,
|
|
179
|
-
baseUrl: vars
|
|
180
|
-
channels:
|
|
181
|
-
|
|
182
|
-
: ['general'],
|
|
183
|
-
openclawGatewayToken: vars['OPENCLAW_GATEWAY_TOKEN'] || process.env.OPENCLAW_GATEWAY_TOKEN,
|
|
256
|
+
baseUrl: envValue(vars, 'RELAY_BASE_URL') || 'https://api.relaycast.dev',
|
|
257
|
+
channels: relayChannels ? relayChannels.split(',').map((c) => c.trim()) : ['general'],
|
|
258
|
+
openclawGatewayToken: envValue(vars, 'OPENCLAW_GATEWAY_TOKEN'),
|
|
184
259
|
openclawGatewayPort: Number.isFinite(port) ? port : undefined,
|
|
260
|
+
transport,
|
|
185
261
|
};
|
|
186
262
|
} catch {
|
|
187
263
|
return null;
|
|
@@ -207,14 +283,47 @@ export async function saveGatewayConfig(config: GatewayConfig): Promise<void> {
|
|
|
207
283
|
|
|
208
284
|
if (config.openclawGatewayToken) {
|
|
209
285
|
lines.push(`OPENCLAW_GATEWAY_TOKEN=${config.openclawGatewayToken}`);
|
|
210
|
-
const masked =
|
|
211
|
-
? config.openclawGatewayToken.slice(0, 8) + '...'
|
|
212
|
-
: '***';
|
|
286
|
+
const masked =
|
|
287
|
+
config.openclawGatewayToken.length > 12 ? config.openclawGatewayToken.slice(0, 8) + '...' : '***';
|
|
213
288
|
console.log(`[config] Persisting OPENCLAW_GATEWAY_TOKEN (${masked})`);
|
|
214
289
|
}
|
|
215
290
|
if (config.openclawGatewayPort) {
|
|
216
291
|
lines.push(`OPENCLAW_GATEWAY_PORT=${config.openclawGatewayPort}`);
|
|
217
292
|
}
|
|
293
|
+
if (config.transport?.pollFallback?.enabled !== undefined) {
|
|
294
|
+
lines.push(`RELAY_TRANSPORT_POLL_FALLBACK_ENABLED=${config.transport.pollFallback.enabled}`);
|
|
295
|
+
}
|
|
296
|
+
if (config.transport?.pollFallback?.wsFailureThreshold !== undefined) {
|
|
297
|
+
lines.push(
|
|
298
|
+
`RELAY_TRANSPORT_POLL_FALLBACK_WS_FAILURE_THRESHOLD=${config.transport.pollFallback.wsFailureThreshold}`
|
|
299
|
+
);
|
|
300
|
+
}
|
|
301
|
+
if (config.transport?.pollFallback?.timeoutSeconds !== undefined) {
|
|
302
|
+
lines.push(
|
|
303
|
+
`RELAY_TRANSPORT_POLL_FALLBACK_TIMEOUT_SECONDS=${config.transport.pollFallback.timeoutSeconds}`
|
|
304
|
+
);
|
|
305
|
+
}
|
|
306
|
+
if (config.transport?.pollFallback?.limit !== undefined) {
|
|
307
|
+
lines.push(`RELAY_TRANSPORT_POLL_FALLBACK_LIMIT=${config.transport.pollFallback.limit}`);
|
|
308
|
+
}
|
|
309
|
+
if (config.transport?.pollFallback?.initialCursor) {
|
|
310
|
+
lines.push(`RELAY_TRANSPORT_POLL_FALLBACK_INITIAL_CURSOR=${config.transport.pollFallback.initialCursor}`);
|
|
311
|
+
}
|
|
312
|
+
if (config.transport?.pollFallback?.probeWs?.enabled !== undefined) {
|
|
313
|
+
lines.push(
|
|
314
|
+
`RELAY_TRANSPORT_POLL_FALLBACK_PROBE_WS_ENABLED=${config.transport.pollFallback.probeWs.enabled}`
|
|
315
|
+
);
|
|
316
|
+
}
|
|
317
|
+
if (config.transport?.pollFallback?.probeWs?.intervalMs !== undefined) {
|
|
318
|
+
lines.push(
|
|
319
|
+
`RELAY_TRANSPORT_POLL_FALLBACK_PROBE_WS_INTERVAL_MS=${config.transport.pollFallback.probeWs.intervalMs}`
|
|
320
|
+
);
|
|
321
|
+
}
|
|
322
|
+
if (config.transport?.pollFallback?.probeWs?.stableGraceMs !== undefined) {
|
|
323
|
+
lines.push(
|
|
324
|
+
`RELAY_TRANSPORT_POLL_FALLBACK_PROBE_WS_STABLE_GRACE_MS=${config.transport.pollFallback.probeWs.stableGraceMs}`
|
|
325
|
+
);
|
|
326
|
+
}
|
|
218
327
|
|
|
219
328
|
lines.push('');
|
|
220
329
|
const env = lines.join('\n');
|