@relaymessenger/openclaw-plugin 0.3.4 → 0.4.0-staging.1
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/LICENSE +1 -1
- package/README.md +162 -123
- package/contracts/relay-sdk-0.3.0-staging.5.registry.json +69 -0
- package/contracts/relay-v1.lock.json +77 -0
- package/dist/index.js +2 -2
- package/dist/setup-entry.js +1 -2
- package/dist/src/accounts.js +63 -34
- package/dist/src/channel.js +144 -533
- package/dist/src/dispatch.js +257 -0
- package/dist/src/full-sync.js +24 -0
- package/dist/src/gateway.js +171 -0
- package/dist/src/inbound.js +54 -85
- package/dist/src/ingress.js +64 -0
- package/dist/src/outbound.js +48 -111
- package/dist/src/runtime.js +2 -3
- package/dist/src/state.js +492 -0
- package/dist/src/types.js +1 -3
- package/index.ts +1 -2
- package/openclaw.plugin.json +15 -18
- package/package.json +114 -40
- package/setup-entry.ts +0 -2
- package/src/accounts.ts +95 -51
- package/src/channel.ts +271 -646
- package/src/dispatch.ts +324 -0
- package/src/full-sync.ts +47 -0
- package/src/gateway.ts +216 -0
- package/src/inbound.ts +71 -122
- package/src/ingress.ts +123 -0
- package/src/outbound.ts +70 -149
- package/src/runtime.ts +4 -4
- package/src/state.ts +609 -0
- package/src/types.ts +51 -162
- package/dist/src/account-lock.js +0 -91
- package/dist/src/client.js +0 -13
- package/dist/src/cursor-store.js +0 -136
- package/dist/src/inbound-dedupe.js +0 -175
- package/dist/src/invocations.js +0 -47
- package/dist/src/lifecycle.js +0 -35
- package/dist/src/poll-loop.js +0 -137
- package/dist/src/responding.js +0 -36
- package/dist/src/security.js +0 -26
- package/dist/src/state-files.js +0 -243
- package/dist/src/vendor/relay-sdk/client.js +0 -163
- package/dist/src/vendor/relay-sdk/errors.js +0 -45
- package/dist/src/vendor/relay-sdk/types.js +0 -2
- package/dist/src/vendor/relay-sdk/url.js +0 -39
- package/src/account-lock.ts +0 -108
- package/src/client.ts +0 -51
- package/src/cursor-store.ts +0 -186
- package/src/inbound-dedupe.ts +0 -241
- package/src/invocations.ts +0 -58
- package/src/lifecycle.ts +0 -42
- package/src/poll-loop.ts +0 -173
- package/src/responding.ts +0 -52
- package/src/security.ts +0 -36
- package/src/state-files.ts +0 -298
- package/src/vendor/relay-sdk/README.md +0 -28
- package/src/vendor/relay-sdk/client.ts +0 -293
- package/src/vendor/relay-sdk/errors.ts +0 -61
- package/src/vendor/relay-sdk/types.ts +0 -82
- package/src/vendor/relay-sdk/url.ts +0 -43
package/index.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
// Relay channel plugin entrypoint registers the OpenClaw integration.
|
|
2
1
|
import { defineChannelPluginEntry } from "openclaw/plugin-sdk/channel-core";
|
|
3
2
|
import { relayChannelPlugin } from "./src/channel.js";
|
|
4
3
|
import { setRelayRuntime } from "./src/runtime.js";
|
|
@@ -6,7 +5,7 @@ import { setRelayRuntime } from "./src/runtime.js";
|
|
|
6
5
|
export default defineChannelPluginEntry({
|
|
7
6
|
id: "relay",
|
|
8
7
|
name: "Relay",
|
|
9
|
-
description: "Relay channel plugin
|
|
8
|
+
description: "Native Relay channel plugin for OpenClaw.",
|
|
10
9
|
plugin: relayChannelPlugin,
|
|
11
10
|
setRuntime: setRelayRuntime,
|
|
12
11
|
});
|
package/openclaw.plugin.json
CHANGED
|
@@ -1,22 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"id": "relay",
|
|
3
3
|
"name": "Relay",
|
|
4
|
-
"description": "Relay channel plugin
|
|
4
|
+
"description": "Native Relay channel plugin for OpenClaw.",
|
|
5
5
|
"activation": {
|
|
6
6
|
"onStartup": false
|
|
7
7
|
},
|
|
8
8
|
"channels": [
|
|
9
9
|
"relay"
|
|
10
10
|
],
|
|
11
|
-
"configSchema": {
|
|
12
|
-
"type": "object",
|
|
13
|
-
"additionalProperties": false,
|
|
14
|
-
"properties": {}
|
|
15
|
-
},
|
|
16
11
|
"channelConfigs": {
|
|
17
12
|
"relay": {
|
|
18
13
|
"label": "Relay",
|
|
19
|
-
"description": "
|
|
14
|
+
"description": "Connect one or more Relay Contacts to OpenClaw.",
|
|
20
15
|
"schema": {
|
|
21
16
|
"type": "object",
|
|
22
17
|
"additionalProperties": false,
|
|
@@ -42,11 +37,6 @@
|
|
|
42
37
|
"type": "string"
|
|
43
38
|
}
|
|
44
39
|
},
|
|
45
|
-
"pollTimeoutSeconds": {
|
|
46
|
-
"type": "number",
|
|
47
|
-
"minimum": 1,
|
|
48
|
-
"maximum": 30
|
|
49
|
-
},
|
|
50
40
|
"defaultAccount": {
|
|
51
41
|
"type": "string"
|
|
52
42
|
},
|
|
@@ -76,11 +66,6 @@
|
|
|
76
66
|
"items": {
|
|
77
67
|
"type": "string"
|
|
78
68
|
}
|
|
79
|
-
},
|
|
80
|
-
"pollTimeoutSeconds": {
|
|
81
|
-
"type": "number",
|
|
82
|
-
"minimum": 1,
|
|
83
|
-
"maximum": 30
|
|
84
69
|
}
|
|
85
70
|
}
|
|
86
71
|
}
|
|
@@ -92,10 +77,22 @@
|
|
|
92
77
|
"label": "Agent Token",
|
|
93
78
|
"sensitive": true
|
|
94
79
|
},
|
|
80
|
+
"tokenFile": {
|
|
81
|
+
"label": "Agent Token file",
|
|
82
|
+
"sensitive": true
|
|
83
|
+
},
|
|
95
84
|
"baseUrl": {
|
|
96
|
-
"label": "Relay API
|
|
85
|
+
"label": "Relay API origin"
|
|
86
|
+
},
|
|
87
|
+
"allowFrom": {
|
|
88
|
+
"label": "Allowed Contact IDs or Handles"
|
|
97
89
|
}
|
|
98
90
|
}
|
|
99
91
|
}
|
|
92
|
+
},
|
|
93
|
+
"configSchema": {
|
|
94
|
+
"type": "object",
|
|
95
|
+
"additionalProperties": false,
|
|
96
|
+
"properties": {}
|
|
100
97
|
}
|
|
101
98
|
}
|
package/package.json
CHANGED
|
@@ -1,72 +1,80 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@relaymessenger/openclaw-plugin",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Relay channel plugin for OpenClaw
|
|
3
|
+
"version": "0.4.0-staging.1",
|
|
4
|
+
"description": "Native Relay channel plugin for OpenClaw",
|
|
5
5
|
"license": "MIT",
|
|
6
|
-
"
|
|
7
|
-
"access": "public"
|
|
8
|
-
},
|
|
9
|
-
"keywords": [
|
|
10
|
-
"openclaw",
|
|
11
|
-
"relay",
|
|
12
|
-
"messaging",
|
|
13
|
-
"agent"
|
|
14
|
-
],
|
|
6
|
+
"type": "module",
|
|
15
7
|
"engines": {
|
|
16
|
-
"node": ">=22.22.3
|
|
8
|
+
"node": ">=22.22.3"
|
|
17
9
|
},
|
|
18
|
-
"
|
|
19
|
-
"
|
|
20
|
-
"
|
|
21
|
-
"directory": "integrations/openclaw"
|
|
10
|
+
"exports": {
|
|
11
|
+
".": "./dist/index.js",
|
|
12
|
+
"./setup": "./dist/setup-entry.js"
|
|
22
13
|
},
|
|
23
|
-
"type": "module",
|
|
24
14
|
"files": [
|
|
15
|
+
"LICENSE",
|
|
25
16
|
"README.md",
|
|
17
|
+
"contracts/relay-v1.lock.json",
|
|
18
|
+
"contracts/relay-sdk-0.3.0-staging.5.registry.json",
|
|
19
|
+
"openclaw.plugin.json",
|
|
26
20
|
"index.ts",
|
|
27
21
|
"setup-entry.ts",
|
|
28
|
-
"openclaw.plugin.json",
|
|
29
22
|
"src/**/*.ts",
|
|
30
23
|
"!src/**/*.test.ts",
|
|
31
|
-
"dist/**/*.js"
|
|
24
|
+
"dist/**/*.js",
|
|
25
|
+
"dist/**/*.d.ts"
|
|
32
26
|
],
|
|
33
27
|
"scripts": {
|
|
34
|
-
"
|
|
35
|
-
"
|
|
28
|
+
"clean": "node -e \"require('node:fs').rmSync('dist',{recursive:true,force:true})\"",
|
|
29
|
+
"build": "npm run clean && tsc -p tsconfig.build.json",
|
|
30
|
+
"check": "tsc -p tsconfig.json --noEmit",
|
|
36
31
|
"test": "vitest run",
|
|
32
|
+
"validate": "npm run check && npm run build && npm test && npm run contract:verify && npm run contract:test",
|
|
33
|
+
"release:validate": "node scripts/release-validate.mjs",
|
|
34
|
+
"contract:verify": "node scripts/verify-contract-provenance.mjs",
|
|
35
|
+
"contract:test": "node --test test/*.test.mjs",
|
|
37
36
|
"pack:smoke": "node scripts/pack-smoke.mjs",
|
|
38
37
|
"gateway:harness": "node scripts/gateway-harness.mjs",
|
|
39
38
|
"prepack": "npm run build"
|
|
40
39
|
},
|
|
41
40
|
"dependencies": {
|
|
42
|
-
"@
|
|
41
|
+
"@relaymessenger/sdk": "0.3.0-staging.5"
|
|
43
42
|
},
|
|
44
43
|
"devDependencies": {
|
|
45
|
-
"@types/node": "^26.
|
|
46
|
-
"openclaw": "2026.
|
|
44
|
+
"@types/node": "^26.0.0",
|
|
45
|
+
"openclaw": "2026.8.1",
|
|
47
46
|
"typescript": "^7.0.2",
|
|
48
47
|
"vitest": "^4.1.10"
|
|
49
48
|
},
|
|
50
49
|
"peerDependencies": {
|
|
51
|
-
"openclaw": ">=2026.
|
|
50
|
+
"openclaw": ">=2026.8.1 <2026.9.0"
|
|
52
51
|
},
|
|
53
52
|
"peerDependenciesMeta": {
|
|
54
53
|
"openclaw": {
|
|
55
54
|
"optional": true
|
|
56
55
|
}
|
|
57
56
|
},
|
|
57
|
+
"publishConfig": {
|
|
58
|
+
"access": "public",
|
|
59
|
+
"tag": "staging",
|
|
60
|
+
"provenance": true
|
|
61
|
+
},
|
|
62
|
+
"repository": {
|
|
63
|
+
"type": "git",
|
|
64
|
+
"url": "git+https://github.com/RelayMessenger/Relay-SDK.git",
|
|
65
|
+
"directory": "packages/openclaw"
|
|
66
|
+
},
|
|
67
|
+
"homepage": "https://docs.relayapp.im/integrations/openclaw",
|
|
68
|
+
"bugs": {
|
|
69
|
+
"url": "https://github.com/RelayMessenger/Relay-SDK/issues"
|
|
70
|
+
},
|
|
71
|
+
"keywords": [
|
|
72
|
+
"openclaw",
|
|
73
|
+
"relay",
|
|
74
|
+
"messaging",
|
|
75
|
+
"channel"
|
|
76
|
+
],
|
|
58
77
|
"openclaw": {
|
|
59
|
-
"compat": {
|
|
60
|
-
"pluginApi": ">=2026.7.1-2"
|
|
61
|
-
},
|
|
62
|
-
"install": {
|
|
63
|
-
"localPath": ".",
|
|
64
|
-
"defaultChoice": "local",
|
|
65
|
-
"minHostVersion": ">=2026.7.1-2"
|
|
66
|
-
},
|
|
67
|
-
"build": {
|
|
68
|
-
"openclawVersion": "2026.7.2-beta.7"
|
|
69
|
-
},
|
|
70
78
|
"extensions": [
|
|
71
79
|
"./index.ts"
|
|
72
80
|
],
|
|
@@ -86,12 +94,78 @@
|
|
|
86
94
|
},
|
|
87
95
|
"label": "Relay",
|
|
88
96
|
"selectionLabel": "Relay",
|
|
89
|
-
"detailLabel": "Relay",
|
|
97
|
+
"detailLabel": "Relay Messenger",
|
|
90
98
|
"docsPath": "https://docs.relayapp.im/integrations/openclaw",
|
|
91
|
-
"docsLabel": "
|
|
92
|
-
"blurb": "
|
|
99
|
+
"docsLabel": "Relay OpenClaw",
|
|
100
|
+
"blurb": "Message your OpenClaw through Relay.",
|
|
93
101
|
"systemImage": "message",
|
|
94
|
-
"markdownCapable": false
|
|
102
|
+
"markdownCapable": false,
|
|
103
|
+
"order": 70,
|
|
104
|
+
"commands": {
|
|
105
|
+
"nativeCommandsAutoEnabled": false,
|
|
106
|
+
"nativeSkillsAutoEnabled": false
|
|
107
|
+
},
|
|
108
|
+
"setup": {
|
|
109
|
+
"fields": [
|
|
110
|
+
{
|
|
111
|
+
"key": "token",
|
|
112
|
+
"kind": "string",
|
|
113
|
+
"sensitive": true,
|
|
114
|
+
"cli": {
|
|
115
|
+
"flags": "--token <token>",
|
|
116
|
+
"description": "Relay Agent Token"
|
|
117
|
+
}
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
"key": "tokenFile",
|
|
121
|
+
"kind": "string",
|
|
122
|
+
"sensitive": true,
|
|
123
|
+
"cli": {
|
|
124
|
+
"flags": "--token-file <path>",
|
|
125
|
+
"description": "File containing a Relay Agent Token"
|
|
126
|
+
}
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
"key": "baseUrl",
|
|
130
|
+
"kind": "string",
|
|
131
|
+
"cli": {
|
|
132
|
+
"flags": "--base-url <url>",
|
|
133
|
+
"description": "Relay API origin"
|
|
134
|
+
}
|
|
135
|
+
},
|
|
136
|
+
{
|
|
137
|
+
"key": "allowFrom",
|
|
138
|
+
"kind": "string-list",
|
|
139
|
+
"cli": {
|
|
140
|
+
"flags": "--allow-from <contacts>",
|
|
141
|
+
"description": "Allowed Relay Contact IDs or Handles"
|
|
142
|
+
}
|
|
143
|
+
},
|
|
144
|
+
{
|
|
145
|
+
"key": "useEnv",
|
|
146
|
+
"kind": "boolean",
|
|
147
|
+
"cli": {
|
|
148
|
+
"flags": "--use-env",
|
|
149
|
+
"description": "Use RELAY_AGENT_TOKEN"
|
|
150
|
+
},
|
|
151
|
+
"envVars": [
|
|
152
|
+
"RELAY_AGENT_TOKEN"
|
|
153
|
+
]
|
|
154
|
+
}
|
|
155
|
+
]
|
|
156
|
+
}
|
|
157
|
+
},
|
|
158
|
+
"install": {
|
|
159
|
+
"npmSpec": "@relaymessenger/openclaw-plugin",
|
|
160
|
+
"defaultChoice": "npm",
|
|
161
|
+
"minHostVersion": ">=2026.8.1",
|
|
162
|
+
"allowInvalidConfigRecovery": true
|
|
163
|
+
},
|
|
164
|
+
"compat": {
|
|
165
|
+
"pluginApi": ">=2026.8.1 <2026.9.0"
|
|
166
|
+
},
|
|
167
|
+
"build": {
|
|
168
|
+
"openclawVersion": "2026.8.1"
|
|
95
169
|
}
|
|
96
170
|
}
|
|
97
171
|
}
|
package/setup-entry.ts
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
// Lightweight setup entry: loaded instead of the full entry while the channel
|
|
2
|
-
// is disabled/unconfigured, so status/config surfaces avoid runtime imports.
|
|
3
1
|
import { defineSetupPluginEntry } from "openclaw/plugin-sdk/channel-core";
|
|
4
2
|
import { relayChannelPlugin } from "./src/channel.js";
|
|
5
3
|
|
package/src/accounts.ts
CHANGED
|
@@ -1,98 +1,142 @@
|
|
|
1
|
-
// Multi-account resolution: channels.relay.accounts.<id> with a
|
|
2
|
-
// default-account fallback, so one OpenClaw can back several Relay contacts
|
|
3
|
-
// (one Agent Token each). Env vars cover the single-account quickstart.
|
|
4
1
|
import {
|
|
5
2
|
createAccountListHelpers,
|
|
6
3
|
resolveMergedAccountConfig,
|
|
7
4
|
} from "openclaw/plugin-sdk/account-helpers";
|
|
8
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
DEFAULT_ACCOUNT_ID,
|
|
7
|
+
normalizeAccountId,
|
|
8
|
+
} from "openclaw/plugin-sdk/account-id";
|
|
9
9
|
import { tryReadSecretFileSync } from "openclaw/plugin-sdk/channel-core";
|
|
10
|
-
import {
|
|
11
|
-
|
|
10
|
+
import type {
|
|
11
|
+
RelayAccountConfig,
|
|
12
|
+
RelayCoreConfig,
|
|
13
|
+
ResolvedRelayAccount,
|
|
14
|
+
} from "./types.js";
|
|
12
15
|
|
|
13
16
|
export const RELAY_TOKEN_ENV_VAR = "RELAY_AGENT_TOKEN";
|
|
14
17
|
export const RELAY_BASE_URL_ENV_VAR = "RELAY_BASE_URL";
|
|
18
|
+
export const DEFAULT_RELAY_BASE_URL = "https://api.relayapp.im";
|
|
15
19
|
|
|
16
|
-
const
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
20
|
+
const { listAccountIds, resolveDefaultAccountId } = createAccountListHelpers(
|
|
21
|
+
"relay",
|
|
22
|
+
{
|
|
23
|
+
normalizeAccountId,
|
|
24
|
+
implicitDefaultAccount: {
|
|
25
|
+
channelKeys: ["token", "tokenFile"],
|
|
26
|
+
envVars: [RELAY_TOKEN_ENV_VAR],
|
|
27
|
+
},
|
|
23
28
|
},
|
|
24
|
-
|
|
29
|
+
);
|
|
25
30
|
|
|
26
31
|
export {
|
|
32
|
+
DEFAULT_ACCOUNT_ID,
|
|
27
33
|
listAccountIds as listRelayAccountIds,
|
|
28
34
|
resolveDefaultAccountId as resolveDefaultRelayAccountId,
|
|
29
|
-
DEFAULT_ACCOUNT_ID,
|
|
30
35
|
};
|
|
31
36
|
|
|
32
|
-
function
|
|
37
|
+
function mergedAccountConfig(
|
|
33
38
|
cfg: RelayCoreConfig,
|
|
34
39
|
accountId: string,
|
|
35
40
|
): RelayAccountConfig {
|
|
36
41
|
return resolveMergedAccountConfig<RelayAccountConfig>({
|
|
37
|
-
channelConfig: cfg.channels?.relay
|
|
42
|
+
channelConfig: cfg.channels?.relay,
|
|
38
43
|
accounts: cfg.channels?.relay?.accounts,
|
|
39
44
|
accountId,
|
|
40
|
-
|
|
45
|
+
// A channel-level token or tokenFile belongs only to the implicit/default
|
|
46
|
+
// account. Named accounts may inherit non-credential defaults, but must
|
|
47
|
+
// opt into their own credential source.
|
|
48
|
+
omitKeys:
|
|
49
|
+
accountId === DEFAULT_ACCOUNT_ID
|
|
50
|
+
? ["defaultAccount"]
|
|
51
|
+
: ["defaultAccount", "token", "tokenFile"],
|
|
41
52
|
normalizeAccountId,
|
|
42
53
|
});
|
|
43
54
|
}
|
|
44
55
|
|
|
45
56
|
function resolveToken(params: {
|
|
46
|
-
|
|
57
|
+
config: RelayAccountConfig;
|
|
47
58
|
accountId: string;
|
|
48
59
|
env: NodeJS.ProcessEnv;
|
|
49
60
|
}): string {
|
|
50
|
-
const
|
|
51
|
-
if (
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
? tryReadSecretFileSync(params.merged.tokenFile, "relay tokenFile")?.trim()
|
|
61
|
+
const inline = params.config.token?.trim();
|
|
62
|
+
if (inline) return inline;
|
|
63
|
+
|
|
64
|
+
const fromFile = params.config.tokenFile
|
|
65
|
+
? tryReadSecretFileSync(params.config.tokenFile, "relay tokenFile")?.trim()
|
|
56
66
|
: undefined;
|
|
57
|
-
if (fromFile)
|
|
58
|
-
|
|
67
|
+
if (fromFile) return fromFile;
|
|
68
|
+
|
|
69
|
+
return params.accountId === DEFAULT_ACCOUNT_ID
|
|
70
|
+
? (params.env[RELAY_TOKEN_ENV_VAR]?.trim() ?? "")
|
|
71
|
+
: "";
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function isLoopbackHostname(hostname: string): boolean {
|
|
75
|
+
return (
|
|
76
|
+
hostname === "localhost" ||
|
|
77
|
+
hostname === "127.0.0.1" ||
|
|
78
|
+
hostname === "::1" ||
|
|
79
|
+
hostname.endsWith(".localhost")
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export function normalizeRelayBaseUrl(
|
|
84
|
+
value: string | undefined,
|
|
85
|
+
): string {
|
|
86
|
+
let parsed: URL;
|
|
87
|
+
try {
|
|
88
|
+
parsed = new URL(value?.trim() || DEFAULT_RELAY_BASE_URL);
|
|
89
|
+
} catch {
|
|
90
|
+
throw new Error("relay: baseUrl must be an absolute Relay API origin");
|
|
91
|
+
}
|
|
92
|
+
if (parsed.username || parsed.password || parsed.search || parsed.hash) {
|
|
93
|
+
throw new Error("relay: baseUrl must not contain credentials, query, or fragment");
|
|
59
94
|
}
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
if (params.accountId === DEFAULT_ACCOUNT_ID) {
|
|
63
|
-
return params.env[RELAY_TOKEN_ENV_VAR]?.trim() ?? "";
|
|
95
|
+
if (parsed.pathname !== "/" && parsed.pathname !== "") {
|
|
96
|
+
throw new Error("relay: baseUrl must be an origin without a path");
|
|
64
97
|
}
|
|
65
|
-
|
|
98
|
+
if (
|
|
99
|
+
parsed.protocol !== "https:" &&
|
|
100
|
+
!(parsed.protocol === "http:" && isLoopbackHostname(parsed.hostname))
|
|
101
|
+
) {
|
|
102
|
+
throw new Error("relay: baseUrl must use HTTPS (HTTP is allowed only for loopback tests)");
|
|
103
|
+
}
|
|
104
|
+
return parsed.origin;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
function normalizeAllowFrom(values: string[] | undefined): string[] {
|
|
108
|
+
return [
|
|
109
|
+
...new Set(
|
|
110
|
+
(values ?? [])
|
|
111
|
+
.map((value) => value.trim())
|
|
112
|
+
.filter((value) => value.length > 0),
|
|
113
|
+
),
|
|
114
|
+
];
|
|
66
115
|
}
|
|
67
116
|
|
|
68
117
|
export function resolveRelayAccount(params: {
|
|
69
118
|
cfg: RelayCoreConfig;
|
|
70
|
-
accountId?: string | null;
|
|
119
|
+
accountId?: string | null | undefined;
|
|
71
120
|
env?: NodeJS.ProcessEnv;
|
|
72
121
|
}): ResolvedRelayAccount {
|
|
73
122
|
const env = params.env ?? process.env;
|
|
74
123
|
const accountId = normalizeAccountId(params.accountId);
|
|
75
|
-
const
|
|
124
|
+
const config = mergedAccountConfig(params.cfg, accountId);
|
|
76
125
|
const baseEnabled = params.cfg.channels?.relay?.enabled !== false;
|
|
77
|
-
const
|
|
78
|
-
const
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
);
|
|
84
|
-
const pollTimeoutSeconds = Math.min(
|
|
85
|
-
Math.max(merged.pollTimeoutSeconds ?? DEFAULT_POLL_TIMEOUT_SECONDS, 1),
|
|
86
|
-
30,
|
|
87
|
-
);
|
|
126
|
+
const token = resolveToken({ config, accountId, env });
|
|
127
|
+
const configuredBaseUrl =
|
|
128
|
+
config.baseUrl?.trim() ||
|
|
129
|
+
(accountId === DEFAULT_ACCOUNT_ID
|
|
130
|
+
? env[RELAY_BASE_URL_ENV_VAR]?.trim()
|
|
131
|
+
: undefined);
|
|
88
132
|
return {
|
|
89
133
|
accountId,
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
134
|
+
...(config.name?.trim() ? { name: config.name.trim() } : {}),
|
|
135
|
+
enabled: baseEnabled && config.enabled !== false,
|
|
136
|
+
configured: token.length > 0,
|
|
93
137
|
token,
|
|
94
|
-
baseUrl,
|
|
95
|
-
|
|
96
|
-
config
|
|
138
|
+
baseUrl: normalizeRelayBaseUrl(configuredBaseUrl),
|
|
139
|
+
allowFrom: normalizeAllowFrom(config.allowFrom),
|
|
140
|
+
config,
|
|
97
141
|
};
|
|
98
142
|
}
|