clawrelay 0.3.4 → 0.3.6
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/README.md +3 -7
- package/package.json +1 -1
- package/src/channel.ts +0 -1
- package/src/gateway-handler.ts +0 -1
- package/src/index.ts +1 -1
- package/src/onboarding.ts +6 -78
- package/src/types.ts +0 -1
package/README.md
CHANGED
|
@@ -45,11 +45,7 @@ Add to `~/.openclaw/openclaw.json`:
|
|
|
45
45
|
{
|
|
46
46
|
"channels": {
|
|
47
47
|
"relay": {
|
|
48
|
-
"
|
|
49
|
-
"default": {
|
|
50
|
-
"authToken": "optional-per-account-token"
|
|
51
|
-
}
|
|
52
|
-
}
|
|
48
|
+
"enabled": true
|
|
53
49
|
}
|
|
54
50
|
},
|
|
55
51
|
"plugins": {
|
|
@@ -61,7 +57,7 @@ Add to `~/.openclaw/openclaw.json`:
|
|
|
61
57
|
}
|
|
62
58
|
```
|
|
63
59
|
|
|
64
|
-
|
|
60
|
+
Authentication is handled by the gateway's own auth token (`gateway.auth.token`).
|
|
65
61
|
|
|
66
62
|
## Verify installation
|
|
67
63
|
|
|
@@ -86,7 +82,7 @@ openclaw plugins doctor
|
|
|
86
82
|
| `src/channel.ts` | Channel definition, config resolution, onboarding |
|
|
87
83
|
| `src/gateway-handler.ts` | `relay.inbound` gateway method handler |
|
|
88
84
|
| `src/health-handler.ts` | HTTP health route handler |
|
|
89
|
-
| `src/onboarding.ts` | Setup wizard (
|
|
85
|
+
| `src/onboarding.ts` | Setup wizard (enable channel, sprite gateway service) |
|
|
90
86
|
| `src/runtime.ts` | OpenClaw runtime accessor |
|
|
91
87
|
| `src/types.ts` | Protocol and config types |
|
|
92
88
|
|
package/package.json
CHANGED
package/src/channel.ts
CHANGED
package/src/gateway-handler.ts
CHANGED
package/src/index.ts
CHANGED
|
@@ -37,7 +37,7 @@ const plugin = {
|
|
|
37
37
|
api.registerGatewayMethod('relay.inbound', relayInboundHandler);
|
|
38
38
|
|
|
39
39
|
// Register HTTP health route on the gateway's HTTP server
|
|
40
|
-
api.registerHttpRoute({ path: '/relay/health', handler: relayHealthHandler });
|
|
40
|
+
api.registerHttpRoute({ path: '/relay/health', auth: 'plugin', handler: relayHealthHandler });
|
|
41
41
|
|
|
42
42
|
logger.info('[clawrelay] Relay channel plugin registered (gateway method + HTTP health)');
|
|
43
43
|
},
|
package/src/onboarding.ts
CHANGED
|
@@ -8,7 +8,6 @@ import {
|
|
|
8
8
|
normalizeAccountId,
|
|
9
9
|
promptAccountId,
|
|
10
10
|
} from "openclaw/plugin-sdk";
|
|
11
|
-
import crypto from "node:crypto";
|
|
12
11
|
import { execSync } from "node:child_process";
|
|
13
12
|
import path from "node:path";
|
|
14
13
|
|
|
@@ -107,16 +106,9 @@ async function ensureSpriteGatewayService(
|
|
|
107
106
|
}
|
|
108
107
|
}
|
|
109
108
|
|
|
110
|
-
function generateAuthToken(): string {
|
|
111
|
-
const bytes = crypto.randomBytes(24);
|
|
112
|
-
return `crly_${bytes.toString("base64url")}`;
|
|
113
|
-
}
|
|
114
|
-
|
|
115
109
|
function setRelayAccountConfig(
|
|
116
110
|
cfg: OpenClawConfig,
|
|
117
111
|
accountId: string,
|
|
118
|
-
defaultPatch: Record<string, unknown>,
|
|
119
|
-
accountPatch: Record<string, unknown> = defaultPatch,
|
|
120
112
|
): OpenClawConfig {
|
|
121
113
|
if (accountId === DEFAULT_ACCOUNT_ID) {
|
|
122
114
|
return {
|
|
@@ -126,7 +118,6 @@ function setRelayAccountConfig(
|
|
|
126
118
|
relay: {
|
|
127
119
|
...cfg.channels?.relay,
|
|
128
120
|
enabled: true,
|
|
129
|
-
...defaultPatch,
|
|
130
121
|
},
|
|
131
122
|
},
|
|
132
123
|
} as OpenClawConfig;
|
|
@@ -143,7 +134,6 @@ function setRelayAccountConfig(
|
|
|
143
134
|
[accountId]: {
|
|
144
135
|
...cfg.channels?.relay?.accounts?.[accountId],
|
|
145
136
|
enabled: cfg.channels?.relay?.accounts?.[accountId]?.enabled ?? true,
|
|
146
|
-
...accountPatch,
|
|
147
137
|
},
|
|
148
138
|
},
|
|
149
139
|
},
|
|
@@ -161,31 +151,12 @@ function resolveDefaultRelayAccountId(cfg: OpenClawConfig): string {
|
|
|
161
151
|
return ids[0] ?? DEFAULT_ACCOUNT_ID;
|
|
162
152
|
}
|
|
163
153
|
|
|
164
|
-
function getExistingToken(cfg: OpenClawConfig, accountId: string): string | undefined {
|
|
165
|
-
const relay = (cfg.channels as any)?.relay;
|
|
166
|
-
if (accountId === DEFAULT_ACCOUNT_ID) {
|
|
167
|
-
return relay?.authToken;
|
|
168
|
-
}
|
|
169
|
-
return relay?.accounts?.[accountId]?.authToken;
|
|
170
|
-
}
|
|
171
|
-
|
|
172
154
|
export const relayOnboardingAdapter: ChannelOnboardingAdapter = {
|
|
173
155
|
channel,
|
|
174
156
|
|
|
175
157
|
getStatus: async ({ cfg }) => {
|
|
176
|
-
const ids = listRelayAccountIds(cfg);
|
|
177
158
|
const relay = (cfg.channels as any)?.relay;
|
|
178
|
-
|
|
179
|
-
// Check default account (top-level authToken) or any named account
|
|
180
|
-
let configured = Boolean(relay?.authToken);
|
|
181
|
-
if (!configured) {
|
|
182
|
-
for (const id of ids) {
|
|
183
|
-
if (relay?.accounts?.[id]?.authToken) {
|
|
184
|
-
configured = true;
|
|
185
|
-
break;
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
}
|
|
159
|
+
const configured = relay?.enabled === true;
|
|
189
160
|
|
|
190
161
|
return {
|
|
191
162
|
channel,
|
|
@@ -209,11 +180,11 @@ export const relayOnboardingAdapter: ChannelOnboardingAdapter = {
|
|
|
209
180
|
await prompter.note(
|
|
210
181
|
[
|
|
211
182
|
"ClawRelay bridges Discord/Telegram to OpenClaw via a",
|
|
212
|
-
"lightweight always-on relay service. This wizard
|
|
213
|
-
"the channel plugin
|
|
183
|
+
"lightweight always-on relay service. This wizard enables",
|
|
184
|
+
"the channel plugin and configures the gateway service.",
|
|
214
185
|
"",
|
|
215
186
|
"The relay service connects to the OpenClaw gateway via WS",
|
|
216
|
-
"and
|
|
187
|
+
"and authenticates using the gateway auth token.",
|
|
217
188
|
"",
|
|
218
189
|
"You'll deploy the relay service separately afterwards.",
|
|
219
190
|
].join("\n"),
|
|
@@ -238,60 +209,17 @@ export const relayOnboardingAdapter: ChannelOnboardingAdapter = {
|
|
|
238
209
|
});
|
|
239
210
|
}
|
|
240
211
|
|
|
241
|
-
let next = cfg;
|
|
242
|
-
|
|
243
|
-
// --- Auth Token (optional per-account verification token) ---
|
|
244
|
-
const existingToken = getExistingToken(next, accountId);
|
|
245
|
-
let authToken: string;
|
|
246
|
-
|
|
247
|
-
if (existingToken) {
|
|
248
|
-
const keepToken = await prompter.confirm({
|
|
249
|
-
message: `Auth token already set (${existingToken.slice(0, 12)}...). Keep it?`,
|
|
250
|
-
initialValue: true,
|
|
251
|
-
});
|
|
252
|
-
if (keepToken) {
|
|
253
|
-
authToken = existingToken;
|
|
254
|
-
} else {
|
|
255
|
-
authToken = await promptAuthToken(prompter);
|
|
256
|
-
}
|
|
257
|
-
} else {
|
|
258
|
-
authToken = await promptAuthToken(prompter);
|
|
259
|
-
}
|
|
260
|
-
|
|
261
212
|
// --- Write config ---
|
|
262
|
-
next = setRelayAccountConfig(
|
|
263
|
-
authToken,
|
|
264
|
-
});
|
|
213
|
+
const next = setRelayAccountConfig(cfg, accountId);
|
|
265
214
|
|
|
266
215
|
// --- Sprite gateway service ---
|
|
267
216
|
await ensureSpriteGatewayService(next, prompter);
|
|
268
217
|
|
|
269
218
|
await prompter.note(
|
|
270
|
-
|
|
219
|
+
"Relay channel enabled. Select Finished below, then deploy the relay service.",
|
|
271
220
|
"Relay",
|
|
272
221
|
);
|
|
273
222
|
|
|
274
223
|
return { cfg: next, accountId };
|
|
275
224
|
},
|
|
276
225
|
};
|
|
277
|
-
|
|
278
|
-
async function promptAuthToken(prompter: WizardPrompter): Promise<string> {
|
|
279
|
-
const generated = generateAuthToken();
|
|
280
|
-
const useGenerated = await prompter.confirm({
|
|
281
|
-
message: `Use auto-generated token? (${generated})`,
|
|
282
|
-
initialValue: true,
|
|
283
|
-
});
|
|
284
|
-
|
|
285
|
-
if (useGenerated) {
|
|
286
|
-
return generated;
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
const custom = await prompter.text({
|
|
290
|
-
message: "Enter your auth token",
|
|
291
|
-
validate: (value) =>
|
|
292
|
-
String(value ?? "").trim().length >= 8
|
|
293
|
-
? undefined
|
|
294
|
-
: "Token must be at least 8 characters",
|
|
295
|
-
});
|
|
296
|
-
return String(custom).trim();
|
|
297
|
-
}
|