agent-relay 3.1.7 → 3.1.9
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/package.json +8 -8
- package/packages/acp-bridge/package.json +2 -2
- package/packages/config/package.json +1 -1
- package/packages/hooks/package.json +4 -4
- package/packages/memory/package.json +2 -2
- package/packages/openclaw/dist/__tests__/ws-client.test.js +69 -0
- package/packages/openclaw/dist/__tests__/ws-client.test.js.map +1 -1
- package/packages/openclaw/dist/cli.js +8 -1
- package/packages/openclaw/dist/cli.js.map +1 -1
- package/packages/openclaw/dist/config.d.ts +6 -2
- package/packages/openclaw/dist/config.d.ts.map +1 -1
- package/packages/openclaw/dist/config.js +95 -7
- package/packages/openclaw/dist/config.js.map +1 -1
- package/packages/openclaw/dist/gateway.d.ts +8 -0
- package/packages/openclaw/dist/gateway.d.ts.map +1 -1
- package/packages/openclaw/dist/gateway.js +269 -34
- package/packages/openclaw/dist/gateway.js.map +1 -1
- package/packages/openclaw/dist/setup.d.ts.map +1 -1
- package/packages/openclaw/dist/setup.js +117 -15
- package/packages/openclaw/dist/setup.js.map +1 -1
- package/packages/openclaw/package.json +2 -2
- package/packages/openclaw/skill/SKILL.md +103 -0
- package/packages/openclaw/src/__tests__/ws-client.test.ts +72 -0
- package/packages/openclaw/src/cli.ts +7 -1
- package/packages/openclaw/src/config.ts +94 -8
- package/packages/openclaw/src/gateway.ts +328 -36
- package/packages/openclaw/src/setup.ts +120 -13
- package/packages/policy/package.json +2 -2
- package/packages/sdk/package.json +2 -2
- 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
|
@@ -5,6 +5,7 @@ import { existsSync } from 'node:fs';
|
|
|
5
5
|
import { hostname } from 'node:os';
|
|
6
6
|
import { fileURLToPath } from 'node:url';
|
|
7
7
|
import { spawn as spawnProcess, execFileSync } from 'node:child_process';
|
|
8
|
+
import { randomBytes } from 'node:crypto';
|
|
8
9
|
|
|
9
10
|
import { RelayCast } from '@relaycast/sdk';
|
|
10
11
|
|
|
@@ -25,6 +26,30 @@ function extractNestedValue(obj: unknown, path: string): unknown {
|
|
|
25
26
|
return current;
|
|
26
27
|
}
|
|
27
28
|
|
|
29
|
+
/**
|
|
30
|
+
* Set a deeply nested value in an object by dot-separated path, creating
|
|
31
|
+
* intermediate objects as needed.
|
|
32
|
+
*/
|
|
33
|
+
const DANGEROUS_KEYS = new Set(['__proto__', 'prototype', 'constructor']);
|
|
34
|
+
|
|
35
|
+
function setNestedValue(obj: Record<string, unknown>, path: string, value: unknown): void {
|
|
36
|
+
const keys = path.split('.');
|
|
37
|
+
for (const key of keys) {
|
|
38
|
+
if (DANGEROUS_KEYS.has(key)) {
|
|
39
|
+
throw new Error(`Refusing to set dangerous key "${key}" in path "${path}"`);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
let current: Record<string, unknown> = obj;
|
|
43
|
+
for (let i = 0; i < keys.length - 1; i++) {
|
|
44
|
+
const key = keys[i];
|
|
45
|
+
if (current[key] == null || typeof current[key] !== 'object') {
|
|
46
|
+
current[key] = {};
|
|
47
|
+
}
|
|
48
|
+
current = current[key] as Record<string, unknown>;
|
|
49
|
+
}
|
|
50
|
+
current[keys[keys.length - 1]] = value;
|
|
51
|
+
}
|
|
52
|
+
|
|
28
53
|
/**
|
|
29
54
|
* Resolve how to invoke mcporter. Prefers a global binary, falls back to npx.
|
|
30
55
|
*/
|
|
@@ -98,14 +123,18 @@ export async function setup(options: SetupOptions): Promise<SetupResult> {
|
|
|
98
123
|
const baseUrl = options.baseUrl ?? 'https://api.relaycast.dev';
|
|
99
124
|
const channels = options.channels ?? ['general'];
|
|
100
125
|
|
|
126
|
+
// CLI name for restart reminder messages (based on detected variant)
|
|
127
|
+
const cliName = detection.variant === 'clawdbot' ? 'clawdbot' : 'openclaw';
|
|
128
|
+
const serviceName = detection.variant === 'clawdbot' ? 'clawdbot' : 'openclaw';
|
|
129
|
+
|
|
101
130
|
if (!detection.installed) {
|
|
102
131
|
// Auto-create ~/.openclaw/ if OpenClaw binary is available but the config dir
|
|
103
132
|
// doesn't exist yet (common in Docker images before onboarding).
|
|
104
133
|
try {
|
|
105
134
|
await mkdir(detection.homeDir, { recursive: true });
|
|
106
135
|
await mkdir(join(detection.homeDir, 'workspace'), { recursive: true });
|
|
107
|
-
// Write a minimal
|
|
108
|
-
const configPath = join(detection.homeDir,
|
|
136
|
+
// Write a minimal config file so MCP servers can be registered
|
|
137
|
+
const configPath = join(detection.homeDir, detection.configFilename);
|
|
109
138
|
if (!existsSync(configPath)) {
|
|
110
139
|
await writeFile(configPath, JSON.stringify({ mcpServers: {} }, null, 2) + '\n', 'utf-8');
|
|
111
140
|
}
|
|
@@ -126,14 +155,48 @@ export async function setup(options: SetupOptions): Promise<SetupResult> {
|
|
|
126
155
|
|
|
127
156
|
// Enable the OpenResponses HTTP API so the inbound gateway can inject
|
|
128
157
|
// messages via POST /v1/responses on the local OpenClaw gateway.
|
|
129
|
-
|
|
130
|
-
|
|
158
|
+
// Try CLI names in order: openclaw, clawdbot, clawdbot-cli.sh.
|
|
159
|
+
// If all CLI calls fail, mutate the config JSON directly.
|
|
160
|
+
let configMutated = false;
|
|
161
|
+
{
|
|
162
|
+
const httpEndpointArgs = [
|
|
131
163
|
'config', 'set',
|
|
132
164
|
'gateway.http.endpoints.responses.enabled', 'true',
|
|
133
|
-
]
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
165
|
+
];
|
|
166
|
+
const cliCandidates = ['openclaw', 'clawdbot', 'clawdbot-cli.sh'];
|
|
167
|
+
let cliSuccess = false;
|
|
168
|
+
|
|
169
|
+
for (const cli of cliCandidates) {
|
|
170
|
+
try {
|
|
171
|
+
execFileSync(cli, httpEndpointArgs, { stdio: 'pipe' });
|
|
172
|
+
cliSuccess = true;
|
|
173
|
+
break;
|
|
174
|
+
} catch {
|
|
175
|
+
// Try next candidate
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
if (!cliSuccess) {
|
|
180
|
+
// Fall back to direct JSON config file mutation
|
|
181
|
+
if (detection.configFile) {
|
|
182
|
+
try {
|
|
183
|
+
const raw = await readFile(detection.configFile, 'utf-8');
|
|
184
|
+
const cfg = JSON.parse(raw) as Record<string, unknown>;
|
|
185
|
+
setNestedValue(cfg, 'gateway.http.endpoints.responses.enabled', true);
|
|
186
|
+
await writeFile(detection.configFile, JSON.stringify(cfg, null, 2) + '\n', 'utf-8');
|
|
187
|
+
// Reload config in detection
|
|
188
|
+
detection.config = cfg;
|
|
189
|
+
configMutated = true;
|
|
190
|
+
console.log('[setup] Enabled gateway.http.endpoints.responses.enabled via config file.');
|
|
191
|
+
} catch (writeErr) {
|
|
192
|
+
console.warn('Could not enable OpenResponses API (non-fatal). Enable manually:');
|
|
193
|
+
console.warn(` ${cliName} config set gateway.http.endpoints.responses.enabled true`);
|
|
194
|
+
}
|
|
195
|
+
} else {
|
|
196
|
+
console.warn('Could not enable OpenResponses API (non-fatal). Enable manually:');
|
|
197
|
+
console.warn(` ${cliName} config set gateway.http.endpoints.responses.enabled true`);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
137
200
|
}
|
|
138
201
|
|
|
139
202
|
// Resolve API key: use provided key or create a new workspace
|
|
@@ -220,19 +283,63 @@ export async function setup(options: SetupOptions): Promise<SetupResult> {
|
|
|
220
283
|
);
|
|
221
284
|
}
|
|
222
285
|
|
|
223
|
-
// Extract gateway auth from
|
|
224
|
-
|
|
286
|
+
// Extract gateway auth from config (if available). Auto-generate if missing.
|
|
287
|
+
let openclawGatewayToken: string | undefined =
|
|
225
288
|
process.env.OPENCLAW_GATEWAY_TOKEN ??
|
|
226
289
|
(extractNestedValue(detection.config, 'gateway.auth.token') as string | undefined);
|
|
290
|
+
|
|
227
291
|
const openclawGatewayPortRaw =
|
|
228
292
|
process.env.OPENCLAW_GATEWAY_PORT ??
|
|
229
293
|
(extractNestedValue(detection.config, 'gateway.port') as number | string | undefined);
|
|
230
294
|
const openclawGatewayPort = openclawGatewayPortRaw ? Number(openclawGatewayPortRaw) : undefined;
|
|
231
295
|
|
|
232
296
|
if (!openclawGatewayToken) {
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
297
|
+
// Generate a random token and persist it to the config file
|
|
298
|
+
const generated = randomBytes(16).toString('hex');
|
|
299
|
+
openclawGatewayToken = generated;
|
|
300
|
+
console.log('[setup] No gateway token found — generating one and writing to config file.');
|
|
301
|
+
|
|
302
|
+
if (detection.configFile) {
|
|
303
|
+
try {
|
|
304
|
+
const raw = await readFile(detection.configFile, 'utf-8');
|
|
305
|
+
const cfg = JSON.parse(raw) as Record<string, unknown>;
|
|
306
|
+
setNestedValue(cfg, 'gateway.auth.token', generated);
|
|
307
|
+
await writeFile(detection.configFile, JSON.stringify(cfg, null, 2) + '\n', 'utf-8');
|
|
308
|
+
detection.config = cfg;
|
|
309
|
+
configMutated = true;
|
|
310
|
+
} catch (writeErr) {
|
|
311
|
+
console.warn(`[setup] Could not write generated token to config file: ${writeErr instanceof Error ? writeErr.message : String(writeErr)}`);
|
|
312
|
+
}
|
|
313
|
+
} else {
|
|
314
|
+
console.warn('[setup] No config file available to persist generated token. Set manually:');
|
|
315
|
+
console.warn(`[setup] export OPENCLAW_GATEWAY_TOKEN=${generated}`);
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
// Print restart reminder if any config mutations were made
|
|
320
|
+
if (configMutated) {
|
|
321
|
+
console.log('');
|
|
322
|
+
console.log('Config changes detected. Restart the gateway to apply:');
|
|
323
|
+
console.log(` systemctl restart ${serviceName}`);
|
|
324
|
+
if (serviceName !== 'openclaw') {
|
|
325
|
+
console.log(` # or: systemctl restart openclaw`);
|
|
326
|
+
}
|
|
327
|
+
console.log(` # or restart manually if not using systemd`);
|
|
328
|
+
console.log('');
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
// Exec policy preflight warning — warn when security is missing OR not 'full'
|
|
332
|
+
{
|
|
333
|
+
const execSecurity = extractNestedValue(detection.config, 'tools.exec.security') as string | undefined;
|
|
334
|
+
if (execSecurity !== 'full') {
|
|
335
|
+
console.warn('');
|
|
336
|
+
console.warn('Warning: Execution policies may be locked down. If the agent can only chat:');
|
|
337
|
+
console.warn(` ${cliName} config set tools.exec.host gateway`);
|
|
338
|
+
console.warn(` ${cliName} config set tools.exec.ask off`);
|
|
339
|
+
console.warn(` ${cliName} config set tools.exec.security full`);
|
|
340
|
+
console.warn(` systemctl restart ${serviceName}`);
|
|
341
|
+
console.warn('');
|
|
342
|
+
}
|
|
236
343
|
}
|
|
237
344
|
|
|
238
345
|
// Save gateway config (.env)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agent-relay/policy",
|
|
3
|
-
"version": "3.1.
|
|
3
|
+
"version": "3.1.9",
|
|
4
4
|
"description": "Agent policy management with multi-level fallback (repo, local PRPM, cloud workspace)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
"test:watch": "vitest"
|
|
23
23
|
},
|
|
24
24
|
"dependencies": {
|
|
25
|
-
"@agent-relay/config": "3.1.
|
|
25
|
+
"@agent-relay/config": "3.1.9"
|
|
26
26
|
},
|
|
27
27
|
"devDependencies": {
|
|
28
28
|
"@types/node": "^22.19.3",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agent-relay/sdk",
|
|
3
|
-
"version": "3.1.
|
|
3
|
+
"version": "3.1.9",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -81,7 +81,7 @@
|
|
|
81
81
|
"typescript": "^5.7.3"
|
|
82
82
|
},
|
|
83
83
|
"dependencies": {
|
|
84
|
-
"@agent-relay/config": "3.1.
|
|
84
|
+
"@agent-relay/config": "3.1.9",
|
|
85
85
|
"@relaycast/sdk": "^0.4.0",
|
|
86
86
|
"yaml": "^2.7.0"
|
|
87
87
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agent-relay/trajectory",
|
|
3
|
-
"version": "3.1.
|
|
3
|
+
"version": "3.1.9",
|
|
4
4
|
"description": "Trajectory integration utilities (trail/PDERO) for Relay",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
"test:watch": "vitest"
|
|
23
23
|
},
|
|
24
24
|
"dependencies": {
|
|
25
|
-
"@agent-relay/config": "3.1.
|
|
25
|
+
"@agent-relay/config": "3.1.9"
|
|
26
26
|
},
|
|
27
27
|
"devDependencies": {
|
|
28
28
|
"@types/node": "^22.19.3",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agent-relay/user-directory",
|
|
3
|
-
"version": "3.1.
|
|
3
|
+
"version": "3.1.9",
|
|
4
4
|
"description": "User directory service for agent-relay (per-user credential storage)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
"test:watch": "vitest"
|
|
23
23
|
},
|
|
24
24
|
"dependencies": {
|
|
25
|
-
"@agent-relay/utils": "3.1.
|
|
25
|
+
"@agent-relay/utils": "3.1.9"
|
|
26
26
|
},
|
|
27
27
|
"devDependencies": {
|
|
28
28
|
"@types/node": "^22.19.3",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agent-relay/utils",
|
|
3
|
-
"version": "3.1.
|
|
3
|
+
"version": "3.1.9",
|
|
4
4
|
"description": "Shared utilities for agent-relay: logging, name generation, command resolution, update checking",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/cjs/index.js",
|
|
@@ -112,7 +112,7 @@
|
|
|
112
112
|
"vitest": "^3.2.4"
|
|
113
113
|
},
|
|
114
114
|
"dependencies": {
|
|
115
|
-
"@agent-relay/config": "3.1.
|
|
115
|
+
"@agent-relay/config": "3.1.9",
|
|
116
116
|
"compare-versions": "^6.1.1"
|
|
117
117
|
},
|
|
118
118
|
"publishConfig": {
|