openclaw-ringcentral 2026.1.29-beta1
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 +21 -0
- package/README.md +186 -0
- package/index.ts +18 -0
- package/openclaw.plugin.json +200 -0
- package/package.json +72 -0
- package/src/accounts.test.ts +311 -0
- package/src/accounts.ts +167 -0
- package/src/api.ts +241 -0
- package/src/auth.ts +92 -0
- package/src/channel.ts +545 -0
- package/src/config-schema.ts +78 -0
- package/src/markdown.test.ts +168 -0
- package/src/markdown.ts +158 -0
- package/src/monitor.test.ts +47 -0
- package/src/monitor.ts +742 -0
- package/src/openclaw.d.ts +68 -0
- package/src/runtime.ts +14 -0
- package/src/targets.test.ts +118 -0
- package/src/targets.ts +70 -0
- package/src/types.ts +174 -0
|
@@ -0,0 +1,311 @@
|
|
|
1
|
+
import { describe, expect, it, beforeEach, afterEach, vi } from "vitest";
|
|
2
|
+
import type { OpenClawConfig } from "openclaw/plugin-sdk";
|
|
3
|
+
import {
|
|
4
|
+
listRingCentralAccountIds,
|
|
5
|
+
resolveDefaultRingCentralAccountId,
|
|
6
|
+
resolveRingCentralAccount,
|
|
7
|
+
listEnabledRingCentralAccounts,
|
|
8
|
+
} from "./accounts.js";
|
|
9
|
+
|
|
10
|
+
describe("listRingCentralAccountIds", () => {
|
|
11
|
+
it("returns default account when no accounts configured", () => {
|
|
12
|
+
const cfg = { channels: {} } as OpenClawConfig;
|
|
13
|
+
expect(listRingCentralAccountIds(cfg)).toEqual(["default"]);
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
it("returns default account when ringcentral channel not configured", () => {
|
|
17
|
+
const cfg = { channels: { telegram: { enabled: true } } } as OpenClawConfig;
|
|
18
|
+
expect(listRingCentralAccountIds(cfg)).toEqual(["default"]);
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
it("returns configured account IDs sorted alphabetically", () => {
|
|
22
|
+
const cfg = {
|
|
23
|
+
channels: {
|
|
24
|
+
ringcentral: {
|
|
25
|
+
accounts: {
|
|
26
|
+
work: { enabled: true },
|
|
27
|
+
personal: { enabled: true },
|
|
28
|
+
},
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
} as OpenClawConfig;
|
|
32
|
+
expect(listRingCentralAccountIds(cfg)).toEqual(["personal", "work"]);
|
|
33
|
+
});
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
describe("resolveDefaultRingCentralAccountId", () => {
|
|
37
|
+
it("returns explicitly set default account", () => {
|
|
38
|
+
const cfg = {
|
|
39
|
+
channels: {
|
|
40
|
+
ringcentral: {
|
|
41
|
+
defaultAccount: "work",
|
|
42
|
+
accounts: {
|
|
43
|
+
work: {},
|
|
44
|
+
personal: {},
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
} as OpenClawConfig;
|
|
49
|
+
expect(resolveDefaultRingCentralAccountId(cfg)).toBe("work");
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
it("returns default if included in accounts", () => {
|
|
53
|
+
const cfg = {
|
|
54
|
+
channels: {
|
|
55
|
+
ringcentral: {
|
|
56
|
+
accounts: {
|
|
57
|
+
default: {},
|
|
58
|
+
other: {},
|
|
59
|
+
},
|
|
60
|
+
},
|
|
61
|
+
},
|
|
62
|
+
} as OpenClawConfig;
|
|
63
|
+
expect(resolveDefaultRingCentralAccountId(cfg)).toBe("default");
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
it("returns first account ID when no default specified", () => {
|
|
67
|
+
const cfg = {
|
|
68
|
+
channels: {
|
|
69
|
+
ringcentral: {
|
|
70
|
+
accounts: {
|
|
71
|
+
zebra: {},
|
|
72
|
+
alpha: {},
|
|
73
|
+
},
|
|
74
|
+
},
|
|
75
|
+
},
|
|
76
|
+
} as OpenClawConfig;
|
|
77
|
+
expect(resolveDefaultRingCentralAccountId(cfg)).toBe("alpha");
|
|
78
|
+
});
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
describe("resolveRingCentralAccount", () => {
|
|
82
|
+
const originalEnv = process.env;
|
|
83
|
+
|
|
84
|
+
beforeEach(() => {
|
|
85
|
+
vi.resetModules();
|
|
86
|
+
process.env = { ...originalEnv };
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
afterEach(() => {
|
|
90
|
+
process.env = originalEnv;
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
it("resolves account from config credentials", () => {
|
|
94
|
+
const cfg = {
|
|
95
|
+
channels: {
|
|
96
|
+
ringcentral: {
|
|
97
|
+
enabled: true,
|
|
98
|
+
credentials: {
|
|
99
|
+
clientId: "test-client-id",
|
|
100
|
+
clientSecret: "test-client-secret",
|
|
101
|
+
jwt: "test-jwt",
|
|
102
|
+
server: "https://platform.devtest.ringcentral.com",
|
|
103
|
+
},
|
|
104
|
+
},
|
|
105
|
+
},
|
|
106
|
+
} as OpenClawConfig;
|
|
107
|
+
|
|
108
|
+
const account = resolveRingCentralAccount({ cfg });
|
|
109
|
+
|
|
110
|
+
expect(account.accountId).toBe("default");
|
|
111
|
+
expect(account.enabled).toBe(true);
|
|
112
|
+
expect(account.credentialSource).toBe("config");
|
|
113
|
+
expect(account.clientId).toBe("test-client-id");
|
|
114
|
+
expect(account.clientSecret).toBe("test-client-secret");
|
|
115
|
+
expect(account.jwt).toBe("test-jwt");
|
|
116
|
+
expect(account.server).toBe("https://platform.devtest.ringcentral.com");
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
it("resolves account from environment variables", () => {
|
|
120
|
+
process.env.RINGCENTRAL_CLIENT_ID = "env-client-id";
|
|
121
|
+
process.env.RINGCENTRAL_CLIENT_SECRET = "env-client-secret";
|
|
122
|
+
process.env.RINGCENTRAL_JWT = "env-jwt";
|
|
123
|
+
process.env.RINGCENTRAL_SERVER = "https://platform.devtest.ringcentral.com";
|
|
124
|
+
|
|
125
|
+
const cfg = {
|
|
126
|
+
channels: {
|
|
127
|
+
ringcentral: {
|
|
128
|
+
enabled: true,
|
|
129
|
+
},
|
|
130
|
+
},
|
|
131
|
+
} as OpenClawConfig;
|
|
132
|
+
|
|
133
|
+
const account = resolveRingCentralAccount({ cfg });
|
|
134
|
+
|
|
135
|
+
expect(account.credentialSource).toBe("env");
|
|
136
|
+
expect(account.clientId).toBe("env-client-id");
|
|
137
|
+
expect(account.clientSecret).toBe("env-client-secret");
|
|
138
|
+
expect(account.jwt).toBe("env-jwt");
|
|
139
|
+
expect(account.server).toBe("https://platform.devtest.ringcentral.com");
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
it("returns none source when no credentials configured", () => {
|
|
143
|
+
const cfg = {
|
|
144
|
+
channels: {
|
|
145
|
+
ringcentral: {
|
|
146
|
+
enabled: true,
|
|
147
|
+
},
|
|
148
|
+
},
|
|
149
|
+
} as OpenClawConfig;
|
|
150
|
+
|
|
151
|
+
const account = resolveRingCentralAccount({ cfg });
|
|
152
|
+
|
|
153
|
+
expect(account.credentialSource).toBe("none");
|
|
154
|
+
expect(account.clientId).toBeUndefined();
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
it("uses default server when not specified", () => {
|
|
158
|
+
const cfg = {
|
|
159
|
+
channels: {
|
|
160
|
+
ringcentral: {
|
|
161
|
+
enabled: true,
|
|
162
|
+
credentials: {
|
|
163
|
+
clientId: "test-client-id",
|
|
164
|
+
clientSecret: "test-client-secret",
|
|
165
|
+
jwt: "test-jwt",
|
|
166
|
+
},
|
|
167
|
+
},
|
|
168
|
+
},
|
|
169
|
+
} as OpenClawConfig;
|
|
170
|
+
|
|
171
|
+
const account = resolveRingCentralAccount({ cfg });
|
|
172
|
+
|
|
173
|
+
expect(account.server).toBe("https://platform.ringcentral.com");
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
it("resolves specific account from accounts map", () => {
|
|
177
|
+
const cfg = {
|
|
178
|
+
channels: {
|
|
179
|
+
ringcentral: {
|
|
180
|
+
enabled: true,
|
|
181
|
+
accounts: {
|
|
182
|
+
work: {
|
|
183
|
+
credentials: {
|
|
184
|
+
clientId: "work-client-id",
|
|
185
|
+
clientSecret: "work-client-secret",
|
|
186
|
+
jwt: "work-jwt",
|
|
187
|
+
},
|
|
188
|
+
name: "Work Account",
|
|
189
|
+
},
|
|
190
|
+
},
|
|
191
|
+
},
|
|
192
|
+
},
|
|
193
|
+
} as OpenClawConfig;
|
|
194
|
+
|
|
195
|
+
const account = resolveRingCentralAccount({ cfg, accountId: "work" });
|
|
196
|
+
|
|
197
|
+
expect(account.accountId).toBe("work");
|
|
198
|
+
expect(account.name).toBe("Work Account");
|
|
199
|
+
expect(account.clientId).toBe("work-client-id");
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
it("merges base config with account config", () => {
|
|
203
|
+
const cfg = {
|
|
204
|
+
channels: {
|
|
205
|
+
ringcentral: {
|
|
206
|
+
enabled: true,
|
|
207
|
+
credentials: {
|
|
208
|
+
server: "https://base.server.com",
|
|
209
|
+
},
|
|
210
|
+
accounts: {
|
|
211
|
+
work: {
|
|
212
|
+
credentials: {
|
|
213
|
+
clientId: "work-client-id",
|
|
214
|
+
clientSecret: "work-client-secret",
|
|
215
|
+
jwt: "work-jwt",
|
|
216
|
+
},
|
|
217
|
+
},
|
|
218
|
+
},
|
|
219
|
+
},
|
|
220
|
+
},
|
|
221
|
+
} as OpenClawConfig;
|
|
222
|
+
|
|
223
|
+
const account = resolveRingCentralAccount({ cfg, accountId: "work" });
|
|
224
|
+
|
|
225
|
+
expect(account.server).toBe("https://base.server.com");
|
|
226
|
+
});
|
|
227
|
+
|
|
228
|
+
it("account config overrides base config", () => {
|
|
229
|
+
const cfg = {
|
|
230
|
+
channels: {
|
|
231
|
+
ringcentral: {
|
|
232
|
+
enabled: true,
|
|
233
|
+
credentials: {
|
|
234
|
+
server: "https://base.server.com",
|
|
235
|
+
},
|
|
236
|
+
accounts: {
|
|
237
|
+
work: {
|
|
238
|
+
credentials: {
|
|
239
|
+
clientId: "work-client-id",
|
|
240
|
+
clientSecret: "work-client-secret",
|
|
241
|
+
jwt: "work-jwt",
|
|
242
|
+
server: "https://work.server.com",
|
|
243
|
+
},
|
|
244
|
+
},
|
|
245
|
+
},
|
|
246
|
+
},
|
|
247
|
+
},
|
|
248
|
+
} as OpenClawConfig;
|
|
249
|
+
|
|
250
|
+
const account = resolveRingCentralAccount({ cfg, accountId: "work" });
|
|
251
|
+
|
|
252
|
+
expect(account.server).toBe("https://work.server.com");
|
|
253
|
+
});
|
|
254
|
+
});
|
|
255
|
+
|
|
256
|
+
describe("listEnabledRingCentralAccounts", () => {
|
|
257
|
+
it("returns only enabled accounts", () => {
|
|
258
|
+
const cfg = {
|
|
259
|
+
channels: {
|
|
260
|
+
ringcentral: {
|
|
261
|
+
enabled: true,
|
|
262
|
+
credentials: {
|
|
263
|
+
clientId: "base-id",
|
|
264
|
+
clientSecret: "base-secret",
|
|
265
|
+
jwt: "base-jwt",
|
|
266
|
+
},
|
|
267
|
+
accounts: {
|
|
268
|
+
enabled1: {
|
|
269
|
+
enabled: true,
|
|
270
|
+
credentials: {
|
|
271
|
+
clientId: "e1-id",
|
|
272
|
+
clientSecret: "e1-secret",
|
|
273
|
+
jwt: "e1-jwt",
|
|
274
|
+
},
|
|
275
|
+
},
|
|
276
|
+
disabled1: {
|
|
277
|
+
enabled: false,
|
|
278
|
+
credentials: {
|
|
279
|
+
clientId: "d1-id",
|
|
280
|
+
clientSecret: "d1-secret",
|
|
281
|
+
jwt: "d1-jwt",
|
|
282
|
+
},
|
|
283
|
+
},
|
|
284
|
+
},
|
|
285
|
+
},
|
|
286
|
+
},
|
|
287
|
+
} as OpenClawConfig;
|
|
288
|
+
|
|
289
|
+
const accounts = listEnabledRingCentralAccounts(cfg);
|
|
290
|
+
|
|
291
|
+
expect(accounts.map((a) => a.accountId)).toContain("enabled1");
|
|
292
|
+
expect(accounts.map((a) => a.accountId)).not.toContain("disabled1");
|
|
293
|
+
});
|
|
294
|
+
|
|
295
|
+
it("returns empty array when channel is disabled", () => {
|
|
296
|
+
const cfg = {
|
|
297
|
+
channels: {
|
|
298
|
+
ringcentral: {
|
|
299
|
+
enabled: false,
|
|
300
|
+
accounts: {
|
|
301
|
+
work: { enabled: true },
|
|
302
|
+
},
|
|
303
|
+
},
|
|
304
|
+
},
|
|
305
|
+
} as OpenClawConfig;
|
|
306
|
+
|
|
307
|
+
const accounts = listEnabledRingCentralAccounts(cfg);
|
|
308
|
+
|
|
309
|
+
expect(accounts).toEqual([]);
|
|
310
|
+
});
|
|
311
|
+
});
|
package/src/accounts.ts
ADDED
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
import type { OpenClawConfig } from "openclaw/plugin-sdk";
|
|
2
|
+
import { DEFAULT_ACCOUNT_ID, normalizeAccountId } from "openclaw/plugin-sdk";
|
|
3
|
+
|
|
4
|
+
import type { RingCentralAccountConfig, RingCentralConfig } from "./types.js";
|
|
5
|
+
|
|
6
|
+
export type RingCentralCredentialSource = "config" | "env" | "none";
|
|
7
|
+
|
|
8
|
+
export type ResolvedRingCentralAccount = {
|
|
9
|
+
accountId: string;
|
|
10
|
+
name?: string;
|
|
11
|
+
enabled: boolean;
|
|
12
|
+
config: RingCentralAccountConfig;
|
|
13
|
+
credentialSource: RingCentralCredentialSource;
|
|
14
|
+
clientId?: string;
|
|
15
|
+
clientSecret?: string;
|
|
16
|
+
jwt?: string;
|
|
17
|
+
server: string;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
const ENV_CLIENT_ID = "RINGCENTRAL_CLIENT_ID";
|
|
21
|
+
const ENV_CLIENT_SECRET = "RINGCENTRAL_CLIENT_SECRET";
|
|
22
|
+
const ENV_JWT = "RINGCENTRAL_JWT";
|
|
23
|
+
const ENV_SERVER = "RINGCENTRAL_SERVER";
|
|
24
|
+
|
|
25
|
+
const DEFAULT_SERVER = "https://platform.ringcentral.com";
|
|
26
|
+
|
|
27
|
+
function listConfiguredAccountIds(cfg: OpenClawConfig): string[] {
|
|
28
|
+
const accounts = (cfg.channels?.ringcentral as RingCentralConfig | undefined)?.accounts;
|
|
29
|
+
if (!accounts || typeof accounts !== "object") return [];
|
|
30
|
+
return Object.keys(accounts).filter(Boolean);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export function listRingCentralAccountIds(cfg: OpenClawConfig): string[] {
|
|
34
|
+
const ids = listConfiguredAccountIds(cfg);
|
|
35
|
+
if (ids.length === 0) return [DEFAULT_ACCOUNT_ID];
|
|
36
|
+
return ids.sort((a, b) => a.localeCompare(b));
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export function resolveDefaultRingCentralAccountId(cfg: OpenClawConfig): string {
|
|
40
|
+
const channel = cfg.channels?.ringcentral as RingCentralConfig | undefined;
|
|
41
|
+
if (channel?.defaultAccount?.trim()) return channel.defaultAccount.trim();
|
|
42
|
+
const ids = listRingCentralAccountIds(cfg);
|
|
43
|
+
if (ids.includes(DEFAULT_ACCOUNT_ID)) return DEFAULT_ACCOUNT_ID;
|
|
44
|
+
return ids[0] ?? DEFAULT_ACCOUNT_ID;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function resolveAccountConfig(
|
|
48
|
+
cfg: OpenClawConfig,
|
|
49
|
+
accountId: string,
|
|
50
|
+
): RingCentralAccountConfig | undefined {
|
|
51
|
+
const accounts = (cfg.channels?.ringcentral as RingCentralConfig | undefined)?.accounts;
|
|
52
|
+
if (!accounts || typeof accounts !== "object") return undefined;
|
|
53
|
+
return accounts[accountId] as RingCentralAccountConfig | undefined;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function mergeRingCentralAccountConfig(
|
|
57
|
+
cfg: OpenClawConfig,
|
|
58
|
+
accountId: string,
|
|
59
|
+
): RingCentralAccountConfig {
|
|
60
|
+
const raw = (cfg.channels?.ringcentral ?? {}) as RingCentralConfig;
|
|
61
|
+
const { accounts: _ignored, defaultAccount: _ignored2, ...base } = raw;
|
|
62
|
+
const account = resolveAccountConfig(cfg, accountId) ?? {};
|
|
63
|
+
return {
|
|
64
|
+
...base,
|
|
65
|
+
...account,
|
|
66
|
+
credentials: { ...base.credentials, ...account.credentials },
|
|
67
|
+
} as RingCentralAccountConfig;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function resolveCredentialsFromConfig(params: {
|
|
71
|
+
accountId: string;
|
|
72
|
+
account: RingCentralAccountConfig;
|
|
73
|
+
}): {
|
|
74
|
+
clientId?: string;
|
|
75
|
+
clientSecret?: string;
|
|
76
|
+
jwt?: string;
|
|
77
|
+
server: string;
|
|
78
|
+
source: RingCentralCredentialSource;
|
|
79
|
+
} {
|
|
80
|
+
const { account, accountId } = params;
|
|
81
|
+
|
|
82
|
+
const creds = account.credentials;
|
|
83
|
+
const configClientId = creds?.clientId?.trim();
|
|
84
|
+
const configClientSecret = creds?.clientSecret?.trim();
|
|
85
|
+
const configJwt = creds?.jwt?.trim();
|
|
86
|
+
const configServer = creds?.server?.trim() || DEFAULT_SERVER;
|
|
87
|
+
|
|
88
|
+
// 1. Check inline config first
|
|
89
|
+
if (configClientId && configClientSecret && configJwt) {
|
|
90
|
+
return {
|
|
91
|
+
clientId: configClientId,
|
|
92
|
+
clientSecret: configClientSecret,
|
|
93
|
+
jwt: configJwt,
|
|
94
|
+
server: configServer,
|
|
95
|
+
source: "config",
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// 2. Check environment variables (default account only)
|
|
100
|
+
if (accountId === DEFAULT_ACCOUNT_ID) {
|
|
101
|
+
const envClientId = process.env[ENV_CLIENT_ID]?.trim();
|
|
102
|
+
const envClientSecret = process.env[ENV_CLIENT_SECRET]?.trim();
|
|
103
|
+
const envJwt = process.env[ENV_JWT]?.trim();
|
|
104
|
+
const envServer = process.env[ENV_SERVER]?.trim() || DEFAULT_SERVER;
|
|
105
|
+
|
|
106
|
+
if (envClientId && envClientSecret && envJwt) {
|
|
107
|
+
return {
|
|
108
|
+
clientId: envClientId,
|
|
109
|
+
clientSecret: envClientSecret,
|
|
110
|
+
jwt: envJwt,
|
|
111
|
+
server: envServer,
|
|
112
|
+
source: "env",
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// 3. Allow partial config + env fallback
|
|
117
|
+
const finalClientId = configClientId || envClientId;
|
|
118
|
+
const finalClientSecret = configClientSecret || envClientSecret;
|
|
119
|
+
const finalJwt = configJwt || envJwt;
|
|
120
|
+
const finalServer = configServer !== DEFAULT_SERVER ? configServer : envServer;
|
|
121
|
+
|
|
122
|
+
if (finalClientId && finalClientSecret && finalJwt) {
|
|
123
|
+
const source: RingCentralCredentialSource =
|
|
124
|
+
configClientId || configClientSecret || configJwt ? "config" : "env";
|
|
125
|
+
return {
|
|
126
|
+
clientId: finalClientId,
|
|
127
|
+
clientSecret: finalClientSecret,
|
|
128
|
+
jwt: finalJwt,
|
|
129
|
+
server: finalServer,
|
|
130
|
+
source,
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
return { server: configServer, source: "none" };
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
export function resolveRingCentralAccount(params: {
|
|
139
|
+
cfg: OpenClawConfig;
|
|
140
|
+
accountId?: string | null;
|
|
141
|
+
}): ResolvedRingCentralAccount {
|
|
142
|
+
const accountId = normalizeAccountId(params.accountId);
|
|
143
|
+
const baseEnabled =
|
|
144
|
+
(params.cfg.channels?.ringcentral as RingCentralConfig | undefined)?.enabled !== false;
|
|
145
|
+
const merged = mergeRingCentralAccountConfig(params.cfg, accountId);
|
|
146
|
+
const accountEnabled = merged.enabled !== false;
|
|
147
|
+
const enabled = baseEnabled && accountEnabled;
|
|
148
|
+
const credentials = resolveCredentialsFromConfig({ accountId, account: merged });
|
|
149
|
+
|
|
150
|
+
return {
|
|
151
|
+
accountId,
|
|
152
|
+
name: merged.name?.trim() || undefined,
|
|
153
|
+
enabled,
|
|
154
|
+
config: merged,
|
|
155
|
+
credentialSource: credentials.source,
|
|
156
|
+
clientId: credentials.clientId,
|
|
157
|
+
clientSecret: credentials.clientSecret,
|
|
158
|
+
jwt: credentials.jwt,
|
|
159
|
+
server: credentials.server,
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
export function listEnabledRingCentralAccounts(cfg: OpenClawConfig): ResolvedRingCentralAccount[] {
|
|
164
|
+
return listRingCentralAccountIds(cfg)
|
|
165
|
+
.map((accountId) => resolveRingCentralAccount({ cfg, accountId }))
|
|
166
|
+
.filter((account) => account.enabled);
|
|
167
|
+
}
|