@jimiford/webex 0.1.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.
@@ -0,0 +1,410 @@
1
+ "use strict";
2
+ /**
3
+ * OpenClaw Channel Plugin for Webex
4
+ *
5
+ * Implements the ChannelPlugin interface for OpenClaw's plugin system.
6
+ */
7
+ Object.defineProperty(exports, "__esModule", { value: true });
8
+ exports.webexPlugin = void 0;
9
+ const send_1 = require("./send");
10
+ const webhook_1 = require("./webhook");
11
+ const DEFAULT_ACCOUNT_ID = "default";
12
+ function listWebexAccountIds(cfg) {
13
+ const section = cfg.channels?.webex;
14
+ if (!section)
15
+ return [];
16
+ const ids = [];
17
+ // Check for top-level config (default account)
18
+ if (section.token) {
19
+ ids.push(DEFAULT_ACCOUNT_ID);
20
+ }
21
+ // Check for named accounts
22
+ if (section.accounts) {
23
+ for (const id of Object.keys(section.accounts)) {
24
+ if (id !== DEFAULT_ACCOUNT_ID) {
25
+ ids.push(id);
26
+ }
27
+ }
28
+ }
29
+ return ids;
30
+ }
31
+ function resolveWebexAccount(opts) {
32
+ const { cfg, accountId = DEFAULT_ACCOUNT_ID } = opts;
33
+ const section = cfg.channels?.webex;
34
+ if (!section) {
35
+ return {
36
+ accountId,
37
+ enabled: false,
38
+ configured: false,
39
+ config: {},
40
+ };
41
+ }
42
+ // Check for named account first
43
+ const namedAccount = section.accounts?.[accountId];
44
+ if (namedAccount) {
45
+ const token = namedAccount.token ?? section.token;
46
+ const webhookUrl = namedAccount.webhookUrl ?? section.webhookUrl;
47
+ return {
48
+ accountId,
49
+ name: namedAccount.name,
50
+ enabled: namedAccount.enabled !== false,
51
+ configured: Boolean(token && webhookUrl),
52
+ token,
53
+ webhookUrl,
54
+ config: {
55
+ token: token ?? "",
56
+ webhookUrl: webhookUrl ?? "",
57
+ webhookSecret: namedAccount.webhookSecret ?? section.webhookSecret,
58
+ dmPolicy: namedAccount.dmPolicy ?? section.dmPolicy ?? "allow",
59
+ allowFrom: namedAccount.allowFrom ?? section.allowFrom,
60
+ apiBaseUrl: namedAccount.apiBaseUrl ?? section.apiBaseUrl,
61
+ maxRetries: namedAccount.maxRetries ?? section.maxRetries,
62
+ retryDelayMs: namedAccount.retryDelayMs ?? section.retryDelayMs,
63
+ },
64
+ };
65
+ }
66
+ // Fall back to top-level config (default account)
67
+ if (accountId === DEFAULT_ACCOUNT_ID) {
68
+ return {
69
+ accountId,
70
+ name: section.name,
71
+ enabled: section.enabled !== false,
72
+ configured: Boolean(section.token && section.webhookUrl),
73
+ token: section.token,
74
+ webhookUrl: section.webhookUrl,
75
+ config: {
76
+ token: section.token ?? "",
77
+ webhookUrl: section.webhookUrl ?? "",
78
+ webhookSecret: section.webhookSecret,
79
+ dmPolicy: section.dmPolicy ?? "allow",
80
+ allowFrom: section.allowFrom,
81
+ apiBaseUrl: section.apiBaseUrl,
82
+ maxRetries: section.maxRetries,
83
+ retryDelayMs: section.retryDelayMs,
84
+ },
85
+ };
86
+ }
87
+ // Account not found
88
+ return {
89
+ accountId,
90
+ enabled: false,
91
+ configured: false,
92
+ config: {},
93
+ };
94
+ }
95
+ const meta = {
96
+ id: "webex",
97
+ label: "Webex",
98
+ selectionLabel: "Cisco Webex",
99
+ docsPath: "/channels/webex",
100
+ docsLabel: "webex",
101
+ blurb: "Cisco Webex messaging via bot webhooks.",
102
+ order: 75,
103
+ aliases: ["cisco-webex"],
104
+ };
105
+ exports.webexPlugin = {
106
+ id: "webex",
107
+ meta,
108
+ capabilities: {
109
+ chatTypes: ["direct", "group"],
110
+ threads: true,
111
+ media: true,
112
+ },
113
+ reload: { configPrefixes: ["channels.webex"] },
114
+ config: {
115
+ listAccountIds: (cfg) => listWebexAccountIds(cfg),
116
+ resolveAccount: (cfg, accountId) => resolveWebexAccount({ cfg: cfg, accountId }),
117
+ defaultAccountId: () => DEFAULT_ACCOUNT_ID,
118
+ setAccountEnabled: ({ cfg, accountId, enabled }) => {
119
+ const config = cfg;
120
+ const section = config.channels?.webex ?? {};
121
+ if (accountId === DEFAULT_ACCOUNT_ID) {
122
+ return {
123
+ ...config,
124
+ channels: {
125
+ ...config.channels,
126
+ webex: {
127
+ ...section,
128
+ enabled,
129
+ },
130
+ },
131
+ };
132
+ }
133
+ return {
134
+ ...config,
135
+ channels: {
136
+ ...config.channels,
137
+ webex: {
138
+ ...section,
139
+ accounts: {
140
+ ...section.accounts,
141
+ [accountId]: {
142
+ ...section.accounts?.[accountId],
143
+ enabled,
144
+ },
145
+ },
146
+ },
147
+ },
148
+ };
149
+ },
150
+ deleteAccount: ({ cfg, accountId }) => {
151
+ const config = cfg;
152
+ const section = config.channels?.webex ?? {};
153
+ if (accountId === DEFAULT_ACCOUNT_ID) {
154
+ const { token, webhookUrl, webhookSecret, dmPolicy, allowFrom, ...rest } = section;
155
+ return {
156
+ ...config,
157
+ channels: {
158
+ ...config.channels,
159
+ webex: rest,
160
+ },
161
+ };
162
+ }
163
+ const accounts = { ...section.accounts };
164
+ delete accounts[accountId];
165
+ return {
166
+ ...config,
167
+ channels: {
168
+ ...config.channels,
169
+ webex: {
170
+ ...section,
171
+ accounts,
172
+ },
173
+ },
174
+ };
175
+ },
176
+ isConfigured: (account) => account.configured,
177
+ describeAccount: (account) => ({
178
+ accountId: account.accountId,
179
+ name: account.name,
180
+ enabled: account.enabled,
181
+ configured: account.configured,
182
+ baseUrl: account.config.apiBaseUrl ?? "https://webexapis.com/v1",
183
+ }),
184
+ resolveAllowFrom: ({ cfg }) => (cfg.channels?.webex?.allowFrom ?? []).map(String),
185
+ formatAllowFrom: ({ allowFrom }) => allowFrom.map((entry) => entry.trim().toLowerCase()),
186
+ },
187
+ security: {
188
+ resolveDmPolicy: ({ account }) => {
189
+ const policy = account.config.dmPolicy ?? "allow";
190
+ // Map "allowlisted" to "allowlist" for OpenClaw compatibility
191
+ const normalizedPolicy = policy === "allowlisted" ? "allowlist" : policy;
192
+ return {
193
+ policy: normalizedPolicy,
194
+ allowFrom: account.config.allowFrom ?? [],
195
+ policyPath: "channels.webex.dmPolicy",
196
+ allowFromPath: "channels.webex.allowFrom",
197
+ approveHint: "Add user ID or email to channels.webex.allowFrom",
198
+ normalizeEntry: (raw) => raw.trim().toLowerCase(),
199
+ };
200
+ },
201
+ },
202
+ threading: {
203
+ resolveReplyToMode: () => "off",
204
+ buildToolContext: ({ context, hasRepliedRef }) => ({
205
+ currentChannelId: context.To?.trim() || undefined,
206
+ currentThreadTs: context.MessageThreadId != null
207
+ ? String(context.MessageThreadId)
208
+ : context.ReplyToId,
209
+ hasRepliedRef,
210
+ }),
211
+ },
212
+ messaging: {
213
+ normalizeTarget: (raw) => {
214
+ let normalized = raw.trim();
215
+ if (!normalized)
216
+ return undefined;
217
+ if (normalized.toLowerCase().startsWith("webex:")) {
218
+ normalized = normalized.slice("webex:".length).trim();
219
+ }
220
+ return normalized || undefined;
221
+ },
222
+ targetResolver: {
223
+ looksLikeId: (raw) => {
224
+ const trimmed = raw.trim();
225
+ if (!trimmed)
226
+ return false;
227
+ // Webex IDs are base64-encoded and start with a specific prefix
228
+ if (trimmed.startsWith("Y2lzY29zcGFyazovL3"))
229
+ return true;
230
+ // Also accept emails
231
+ return trimmed.includes("@");
232
+ },
233
+ hint: "<roomId|personId|email>",
234
+ },
235
+ },
236
+ outbound: {
237
+ deliveryMode: "direct",
238
+ textChunkLimit: 7000, // Webex has a 7439 byte limit
239
+ sendText: async ({ to, text, account, replyToId }) => {
240
+ const sender = new send_1.WebexSender(account.config);
241
+ const result = await sender.send({
242
+ to,
243
+ content: { text },
244
+ parentId: replyToId,
245
+ });
246
+ return {
247
+ channel: "webex",
248
+ messageId: result.id,
249
+ roomId: result.roomId,
250
+ };
251
+ },
252
+ sendMedia: async ({ to, text, mediaUrl, account, replyToId }) => {
253
+ const sender = new send_1.WebexSender(account.config);
254
+ const result = await sender.send({
255
+ to,
256
+ content: {
257
+ text,
258
+ files: mediaUrl ? [mediaUrl] : undefined,
259
+ },
260
+ parentId: replyToId,
261
+ });
262
+ return {
263
+ channel: "webex",
264
+ messageId: result.id,
265
+ roomId: result.roomId,
266
+ };
267
+ },
268
+ },
269
+ status: {
270
+ defaultRuntime: {
271
+ accountId: DEFAULT_ACCOUNT_ID,
272
+ running: false,
273
+ lastStartAt: null,
274
+ lastStopAt: null,
275
+ lastError: null,
276
+ },
277
+ collectStatusIssues: (accounts) => accounts.flatMap((account) => {
278
+ const lastError = typeof account.lastError === "string" ? account.lastError.trim() : "";
279
+ if (!lastError)
280
+ return [];
281
+ return [
282
+ {
283
+ channel: "webex",
284
+ accountId: account.accountId,
285
+ kind: "runtime",
286
+ message: `Channel error: ${lastError}`,
287
+ },
288
+ ];
289
+ }),
290
+ buildChannelSummary: ({ snapshot }) => ({
291
+ configured: (snapshot.configured ?? false),
292
+ baseUrl: (snapshot.baseUrl ?? null),
293
+ running: (snapshot.running ?? false),
294
+ lastStartAt: (snapshot.lastStartAt ?? null),
295
+ lastStopAt: (snapshot.lastStopAt ?? null),
296
+ lastError: (snapshot.lastError ?? null),
297
+ }),
298
+ probeAccount: async ({ account, timeoutMs }) => {
299
+ if (!account.configured) {
300
+ return {
301
+ ok: false,
302
+ error: "Account not configured",
303
+ elapsedMs: 0,
304
+ };
305
+ }
306
+ const start = Date.now();
307
+ try {
308
+ const response = await fetch(`${account.config.apiBaseUrl ?? "https://webexapis.com/v1"}/people/me`, {
309
+ method: "GET",
310
+ headers: {
311
+ Authorization: `Bearer ${account.config.token}`,
312
+ "Content-Type": "application/json",
313
+ },
314
+ signal: timeoutMs ? AbortSignal.timeout(timeoutMs) : undefined,
315
+ });
316
+ const elapsedMs = Date.now() - start;
317
+ if (!response.ok) {
318
+ return {
319
+ ok: false,
320
+ error: `HTTP ${response.status}: ${response.statusText}`,
321
+ elapsedMs,
322
+ };
323
+ }
324
+ return { ok: true, elapsedMs };
325
+ }
326
+ catch (err) {
327
+ return {
328
+ ok: false,
329
+ error: err instanceof Error ? err.message : String(err),
330
+ elapsedMs: Date.now() - start,
331
+ };
332
+ }
333
+ },
334
+ buildAccountSnapshot: ({ account, runtime, probe }) => ({
335
+ accountId: account.accountId,
336
+ name: account.name,
337
+ enabled: account.enabled,
338
+ configured: account.configured,
339
+ baseUrl: account.config.apiBaseUrl ?? "https://webexapis.com/v1",
340
+ running: runtime?.running ?? false,
341
+ lastStartAt: runtime?.lastStartAt ?? null,
342
+ lastStopAt: runtime?.lastStopAt ?? null,
343
+ lastError: runtime?.lastError ?? null,
344
+ probe,
345
+ lastProbeAt: runtime?.lastProbeAt ?? null,
346
+ }),
347
+ },
348
+ gateway: {
349
+ startAccount: async (ctx) => {
350
+ const { account, runtime, log, setStatus } = ctx;
351
+ setStatus({
352
+ accountId: account.accountId,
353
+ baseUrl: account.config.apiBaseUrl ?? "https://webexapis.com/v1",
354
+ });
355
+ log?.info?.(`[${account.accountId}] starting Webex provider (webhook mode)`);
356
+ // Initialize webhook handler
357
+ const webhookHandler = new webhook_1.WebexWebhookHandler(account.config);
358
+ await webhookHandler.initialize();
359
+ // Register webhooks with Webex
360
+ try {
361
+ await webhookHandler.registerWebhooks();
362
+ log?.info?.(`[${account.accountId}] webhooks registered`);
363
+ }
364
+ catch (err) {
365
+ log?.warn?.(`[${account.accountId}] failed to register webhooks: ${err instanceof Error ? err.message : err}`);
366
+ }
367
+ // Register HTTP handler for incoming webhooks
368
+ const webhookPath = `/webhooks/webex/${account.accountId}`;
369
+ runtime.http.registerHandler({
370
+ method: "POST",
371
+ path: webhookPath,
372
+ handler: async (req) => {
373
+ try {
374
+ const signature = req.headers["x-spark-signature"];
375
+ const payload = req.body;
376
+ const envelope = await webhookHandler.handleWebhook(payload, signature);
377
+ if (envelope) {
378
+ // Forward to OpenClaw's message pipeline
379
+ await runtime.messaging.handleInbound({
380
+ channel: "webex",
381
+ accountId: account.accountId,
382
+ senderId: envelope.author.id,
383
+ senderEmail: envelope.author.email,
384
+ conversationId: envelope.conversationId,
385
+ messageId: envelope.id,
386
+ text: envelope.content.text ?? "",
387
+ roomType: envelope.metadata.roomType,
388
+ threadId: envelope.metadata.parentId,
389
+ timestamp: new Date(envelope.metadata.timestamp),
390
+ raw: envelope.metadata.raw,
391
+ });
392
+ }
393
+ return { status: 200, body: { ok: true } };
394
+ }
395
+ catch (err) {
396
+ log?.error?.(`[${account.accountId}] webhook error: ${err instanceof Error ? err.message : err}`);
397
+ return { status: 500, body: { error: "Internal error" } };
398
+ }
399
+ },
400
+ });
401
+ log?.info?.(`[${account.accountId}] HTTP webhook handler registered at ${webhookPath}`);
402
+ // Return cleanup function
403
+ return async () => {
404
+ log?.info?.(`[${account.accountId}] stopping Webex provider`);
405
+ runtime.http.unregisterHandler(webhookPath);
406
+ };
407
+ },
408
+ },
409
+ };
410
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2hhbm5lbC1wbHVnaW4uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvY2hhbm5lbC1wbHVnaW4udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBOzs7O0dBSUc7OztBQVFILGlDQUFxQztBQUNyQyx1Q0FBZ0Q7QUFtRGhELE1BQU0sa0JBQWtCLEdBQUcsU0FBUyxDQUFDO0FBRXJDLFNBQVMsbUJBQW1CLENBQUMsR0FBZTtJQUMxQyxNQUFNLE9BQU8sR0FBRyxHQUFHLENBQUMsUUFBUSxFQUFFLEtBQUssQ0FBQztJQUNwQyxJQUFJLENBQUMsT0FBTztRQUFFLE9BQU8sRUFBRSxDQUFDO0lBRXhCLE1BQU0sR0FBRyxHQUFhLEVBQUUsQ0FBQztJQUV6QiwrQ0FBK0M7SUFDL0MsSUFBSSxPQUFPLENBQUMsS0FBSyxFQUFFLENBQUM7UUFDbEIsR0FBRyxDQUFDLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDO0lBQy9CLENBQUM7SUFFRCwyQkFBMkI7SUFDM0IsSUFBSSxPQUFPLENBQUMsUUFBUSxFQUFFLENBQUM7UUFDckIsS0FBSyxNQUFNLEVBQUUsSUFBSSxNQUFNLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsRUFBRSxDQUFDO1lBQy9DLElBQUksRUFBRSxLQUFLLGtCQUFrQixFQUFFLENBQUM7Z0JBQzlCLEdBQUcsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUM7WUFDZixDQUFDO1FBQ0gsQ0FBQztJQUNILENBQUM7SUFFRCxPQUFPLEdBQUcsQ0FBQztBQUNiLENBQUM7QUFFRCxTQUFTLG1CQUFtQixDQUFDLElBRzVCO0lBQ0MsTUFBTSxFQUFFLEdBQUcsRUFBRSxTQUFTLEdBQUcsa0JBQWtCLEVBQUUsR0FBRyxJQUFJLENBQUM7SUFDckQsTUFBTSxPQUFPLEdBQUcsR0FBRyxDQUFDLFFBQVEsRUFBRSxLQUFLLENBQUM7SUFFcEMsSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFDO1FBQ2IsT0FBTztZQUNMLFNB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QixHQUFHLFlBQVksS0FBSyxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxHQUFHLEVBQUUsQ0FDcEYsQ0FBQzt3QkFDRixPQUFPLEVBQUUsTUFBTSxFQUFFLEdBQUcsRUFBRSxJQUFJLEVBQUUsRUFBRSxLQUFLLEVBQUUsZ0JBQWdCLEVBQUUsRUFBRSxDQUFDO29CQUM1RCxDQUFDO2dCQUNILENBQUM7YUFDRixDQUFDLENBQUM7WUFFSCxHQUFHLEVBQUUsSUFBSSxFQUFFLENBQ1QsSUFBSSxPQUFPLENBQUMsU0FBUyx3Q0FBd0MsV0FBVyxFQUFFLENBQzNFLENBQUM7WUFFRiwwQkFBMEI7WUFDMUIsT0FBTyxLQUFLLElBQUksRUFBRTtnQkFDaEIsR0FBRyxFQUFFLElBQUksRUFBRSxDQUFDLElBQUksT0FBTyxDQUFDLFNBQVMsMkJBQTJCLENBQUMsQ0FBQztnQkFDOUQsT0FBTyxDQUFDLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxXQUFXLENBQUMsQ0FBQztZQUM5QyxDQUFDLENBQUM7UUFDSixDQUFDO0tBQ0Y7Q0FDRixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBPcGVuQ2xhdyBDaGFubmVsIFBsdWdpbiBmb3IgV2ViZXhcbiAqXG4gKiBJbXBsZW1lbnRzIHRoZSBDaGFubmVsUGx1Z2luIGludGVyZmFjZSBmb3IgT3BlbkNsYXcncyBwbHVnaW4gc3lzdGVtLlxuICovXG5cbmltcG9ydCB0eXBlIHtcbiAgQ2hhbm5lbFBsdWdpbixcbiAgUGx1Z2luUnVudGltZSxcbiAgSHR0cFJlcXVlc3QsXG59IGZyb20gXCJvcGVuY2xhdy9wbHVnaW4tc2RrXCI7XG5cbmltcG9ydCB7IFdlYmV4U2VuZGVyIH0gZnJvbSBcIi4vc2VuZFwiO1xuaW1wb3J0IHsgV2ViZXhXZWJob29rSGFuZGxlciB9IGZyb20gXCIuL3dlYmhvb2tcIjtcbmltcG9ydCB0eXBlIHsgV2ViZXhDaGFubmVsQ29uZmlnLCBXZWJleFdlYmhvb2tQYXlsb2FkIH0gZnJvbSBcIi4vdHlwZXNcIjtcblxuLyoqIFJlc29sdmVkIGFjY291bnQgY29uZmlndXJhdGlvbiAqL1xuZXhwb3J0IGludGVyZmFjZSBSZXNvbHZlZFdlYmV4QWNjb3VudCB7XG4gIGFjY291bnRJZDogc3RyaW5nO1xuICBuYW1lPzogc3RyaW5nO1xuICBlbmFibGVkOiBib29sZWFuO1xuICBjb25maWd1cmVkOiBib29sZWFuO1xuICBjb25maWc6IFdlYmV4Q2hhbm5lbENvbmZpZztcbiAgdG9rZW4/OiBzdHJpbmc7XG4gIHdlYmhvb2tVcmw/OiBzdHJpbmc7XG59XG5cbi8qKiBDb3JlIGNvbmZpZyB0eXBlIGZvciBhY2Nlc3NpbmcgY2hhbm5lbHMud2ViZXggKi9cbmludGVyZmFjZSBDb3JlQ29uZmlnIHtcbiAgY2hhbm5lbHM/OiB7XG4gICAgd2ViZXg/OiBXZWJleENoYW5uZWxTZWN0aW9uO1xuICAgIGRlZmF1bHRzPzoge1xuICAgICAgZ3JvdXBQb2xpY3k/OiBzdHJpbmc7XG4gICAgfTtcbiAgfTtcbn1cblxuaW50ZXJmYWNlIFdlYmV4Q2hhbm5lbFNlY3Rpb24ge1xuICBlbmFibGVkPzogYm9vbGVhbjtcbiAgbmFtZT86IHN0cmluZztcbiAgdG9rZW4/OiBzdHJpbmc7XG4gIHdlYmhvb2tVcmw/OiBzdHJpbmc7XG4gIHdlYmhvb2tTZWNyZXQ/OiBzdHJpbmc7XG4gIGRtUG9saWN5PzogXCJhbGxvd1wiIHwgXCJkZW55XCIgfCBcImFsbG93bGlzdGVkXCIgfCBcInBhaXJpbmdcIjtcbiAgYWxsb3dGcm9tPzogc3RyaW5nW107XG4gIGFwaUJhc2VVcmw/OiBzdHJpbmc7XG4gIG1heFJldHJpZXM/OiBudW1iZXI7XG4gIHJldHJ5RGVsYXlNcz86IG51bWJlcjtcbiAgYWNjb3VudHM/OiBSZWNvcmQ8c3RyaW5nLCBXZWJleEFjY291bnRDb25maWc+O1xufVxuXG5pbnRlcmZhY2UgV2ViZXhBY2NvdW50Q29uZmlnIHtcbiAgZW5hYmxlZD86IGJvb2xlYW47XG4gIG5hbWU/OiBzdHJpbmc7XG4gIHRva2VuPzogc3RyaW5nO1xuICB3ZWJob29rVXJsPzogc3RyaW5nO1xuICB3ZWJob29rU2VjcmV0Pzogc3RyaW5nO1xuICBkbVBvbGljeT86IFwiYWxsb3dcIiB8IFwiZGVueVwiIHwgXCJhbGxvd2xpc3RlZFwiIHwgXCJwYWlyaW5nXCI7XG4gIGFsbG93RnJvbT86IHN0cmluZ1tdO1xuICBhcGlCYXNlVXJsPzogc3RyaW5nO1xuICBtYXhSZXRyaWVzPzogbnVtYmVyO1xuICByZXRyeURlbGF5TXM/OiBudW1iZXI7XG59XG5cbmNvbnN0IERFRkFVTFRfQUNDT1VOVF9JRCA9IFwiZGVmYXVsdFwiO1xuXG5mdW5jdGlvbiBsaXN0V2ViZXhBY2NvdW50SWRzKGNmZzogQ29yZUNvbmZpZyk6IHN0cmluZ1tdIHtcbiAgY29uc3Qgc2VjdGlvbiA9IGNmZy5jaGFubmVscz8ud2ViZXg7XG4gIGlmICghc2VjdGlvbikgcmV0dXJuIFtdO1xuXG4gIGNvbnN0IGlkczogc3RyaW5nW10gPSBbXTtcblxuICAvLyBDaGVjayBmb3IgdG9wLWxldmVsIGNvbmZpZyAoZGVmYXVsdCBhY2NvdW50KVxuICBpZiAoc2VjdGlvbi50b2tlbikge1xuICAgIGlkcy5wdXNoKERFRkFVTFRfQUNDT1VOVF9JRCk7XG4gIH1cblxuICAvLyBDaGVjayBmb3IgbmFtZWQgYWNjb3VudHNcbiAgaWYgKHNlY3Rpb24uYWNjb3VudHMpIHtcbiAgICBmb3IgKGNvbnN0IGlkIG9mIE9iamVjdC5rZXlzKHNlY3Rpb24uYWNjb3VudHMpKSB7XG4gICAgICBpZiAoaWQgIT09IERFRkFVTFRfQUNDT1VOVF9JRCkge1xuICAgICAgICBpZHMucHVzaChpZCk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGlkcztcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZVdlYmV4QWNjb3VudChvcHRzOiB7XG4gIGNmZzogQ29yZUNvbmZpZztcbiAgYWNjb3VudElkPzogc3RyaW5nO1xufSk6IFJlc29sdmVkV2ViZXhBY2NvdW50IHtcbiAgY29uc3QgeyBjZmcsIGFjY291bnRJZCA9IERFRkFVTFRfQUNDT1VOVF9JRCB9ID0gb3B0cztcbiAgY29uc3Qgc2VjdGlvbiA9IGNmZy5jaGFubmVscz8ud2ViZXg7XG5cbiAgaWYgKCFzZWN0aW9uKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIGFjY291bnRJZCxcbiAgICAgIGVuYWJsZWQ6IGZhbHNlLFxuICAgICAgY29uZmlndXJlZDogZmFsc2UsXG4gICAgICBjb25maWc6IHt9IGFzIFdlYmV4Q2hhbm5lbENvbmZpZyxcbiAgICB9O1xuICB9XG5cbiAgLy8gQ2hlY2sgZm9yIG5hbWVkIGFjY291bnQgZmlyc3RcbiAgY29uc3QgbmFtZWRBY2NvdW50ID0gc2VjdGlvbi5hY2NvdW50cz8uW2FjY291bnRJZF07XG5cbiAgaWYgKG5hbWVkQWNjb3VudCkge1xuICAgIGNvbnN0IHRva2VuID0gbmFtZWRBY2NvdW50LnRva2VuID8/IHNlY3Rpb24udG9rZW47XG4gICAgY29uc3Qgd2ViaG9va1VybCA9IG5hbWVkQWNjb3VudC53ZWJob29rVXJsID8/IHNlY3Rpb24ud2ViaG9va1VybDtcblxuICAgIHJldHVybiB7XG4gICAgICBhY2NvdW50SWQsXG4gICAgICBuYW1lOiBuYW1lZEFjY291bnQubmFtZSxcbiAgICAgIGVuYWJsZWQ6IG5hbWVkQWNjb3VudC5lbmFibGVkICE9PSBmYWxzZSxcbiAgICAgIGNvbmZpZ3VyZWQ6IEJvb2xlYW4odG9rZW4gJiYgd2ViaG9va1VybCksXG4gICAgICB0b2tlbixcbiAgICAgIHdlYmhvb2tVcmwsXG4gICAgICBjb25maWc6IHtcbiAgICAgICAgdG9rZW46IHRva2VuID8/IFwiXCIsXG4gICAgICAgIHdlYmhvb2tVcmw6IHdlYmhvb2tVcmwgPz8gXCJcIixcbiAgICAgICAgd2ViaG9va1NlY3JldDogbmFtZWRBY2NvdW50LndlYmhvb2tTZWNyZXQgPz8gc2VjdGlvbi53ZWJob29rU2VjcmV0LFxuICAgICAgICBkbVBvbGljeTogbmFtZWRBY2NvdW50LmRtUG9saWN5ID8/IHNlY3Rpb24uZG1Qb2xpY3kgPz8gXCJhbGxvd1wiLFxuICAgICAgICBhbGxvd0Zyb206IG5hbWVkQWNjb3VudC5hbGxvd0Zyb20gPz8gc2VjdGlvbi5hbGxvd0Zyb20sXG4gICAgICAgIGFwaUJhc2VVcmw6IG5hbWVkQWNjb3VudC5hcGlCYXNlVXJsID8/IHNlY3Rpb24uYXBpQmFzZVVybCxcbiAgICAgICAgbWF4UmV0cmllczogbmFtZWRBY2NvdW50Lm1heFJldHJpZXMgPz8gc2VjdGlvbi5tYXhSZXRyaWVzLFxuICAgICAgICByZXRyeURlbGF5TXM6IG5hbWVkQWNjb3VudC5yZXRyeURlbGF5TXMgPz8gc2VjdGlvbi5yZXRyeURlbGF5TXMsXG4gICAgICB9LFxuICAgIH07XG4gIH1cblxuICAvLyBGYWxsIGJhY2sgdG8gdG9wLWxldmVsIGNvbmZpZyAoZGVmYXVsdCBhY2NvdW50KVxuICBpZiAoYWNjb3VudElkID09PSBERUZBVUxUX0FDQ09VTlRfSUQpIHtcbiAgICByZXR1cm4ge1xuICAgICAgYWNjb3VudElkLFxuICAgICAgbmFtZTogc2VjdGlvbi5uYW1lLFxuICAgICAgZW5hYmxlZDogc2VjdGlvbi5lbmFibGVkICE9PSBmYWxzZSxcbiAgICAgIGNvbmZpZ3VyZWQ6IEJvb2xlYW4oc2VjdGlvbi50b2tlbiAmJiBzZWN0aW9uLndlYmhvb2tVcmwpLFxuICAgICAgdG9rZW46IHNlY3Rpb24udG9rZW4sXG4gICAgICB3ZWJob29rVXJsOiBzZWN0aW9uLndlYmhvb2tVcmwsXG4gICAgICBjb25maWc6IHtcbiAgICAgICAgdG9rZW46IHNlY3Rpb24udG9rZW4gPz8gXCJcIixcbiAgICAgICAgd2ViaG9va1VybDogc2VjdGlvbi53ZWJob29rVXJsID8/IFwiXCIsXG4gICAgICAgIHdlYmhvb2tTZWNyZXQ6IHNlY3Rpb24ud2ViaG9va1NlY3JldCxcbiAgICAgICAgZG1Qb2xpY3k6IHNlY3Rpb24uZG1Qb2xpY3kgPz8gXCJhbGxvd1wiLFxuICAgICAgICBhbGxvd0Zyb206IHNlY3Rpb24uYWxsb3dGcm9tLFxuICAgICAgICBhcGlCYXNlVXJsOiBzZWN0aW9uLmFwaUJhc2VVcmwsXG4gICAgICAgIG1heFJldHJpZXM6IHNlY3Rpb24ubWF4UmV0cmllcyxcbiAgICAgICAgcmV0cnlEZWxheU1zOiBzZWN0aW9uLnJldHJ5RGVsYXlNcyxcbiAgICAgIH0sXG4gICAgfTtcbiAgfVxuXG4gIC8vIEFjY291bnQgbm90IGZvdW5kXG4gIHJldHVybiB7XG4gICAgYWNjb3VudElkLFxuICAgIGVuYWJsZWQ6IGZhbHNlLFxuICAgIGNvbmZpZ3VyZWQ6IGZhbHNlLFxuICAgIGNvbmZpZzoge30gYXMgV2ViZXhDaGFubmVsQ29uZmlnLFxuICB9O1xufVxuXG5jb25zdCBtZXRhID0ge1xuICBpZDogXCJ3ZWJleFwiLFxuICBsYWJlbDogXCJXZWJleFwiLFxuICBzZWxlY3Rpb25MYWJlbDogXCJDaXNjbyBXZWJleFwiLFxuICBkb2NzUGF0aDogXCIvY2hhbm5lbHMvd2ViZXhcIixcbiAgZG9jc0xhYmVsOiBcIndlYmV4XCIsXG4gIGJsdXJiOiBcIkNpc2NvIFdlYmV4IG1lc3NhZ2luZyB2aWEgYm90IHdlYmhvb2tzLlwiLFxuICBvcmRlcjogNzUsXG4gIGFsaWFzZXM6IFtcImNpc2NvLXdlYmV4XCJdLFxufTtcblxuZXhwb3J0IGNvbnN0IHdlYmV4UGx1Z2luOiBDaGFubmVsUGx1Z2luPFJlc29sdmVkV2ViZXhBY2NvdW50PiA9IHtcbiAgaWQ6IFwid2ViZXhcIixcbiAgbWV0YSxcblxuICBjYXBhYmlsaXRpZXM6IHtcbiAgICBjaGF0VHlwZXM6IFtcImRpcmVjdFwiLCBcImdyb3VwXCJdLFxuICAgIHRocmVhZHM6IHRydWUsXG4gICAgbWVkaWE6IHRydWUsXG4gIH0sXG5cbiAgcmVsb2FkOiB7IGNvbmZpZ1ByZWZpeGVzOiBbXCJjaGFubmVscy53ZWJleFwiXSB9LFxuXG4gIGNvbmZpZzoge1xuICAgIGxpc3RBY2NvdW50SWRzOiAoY2ZnKSA9PiBsaXN0V2ViZXhBY2NvdW50SWRzKGNmZyBhcyBDb3JlQ29uZmlnKSxcblxuICAgIHJlc29sdmVBY2NvdW50OiAoY2ZnLCBhY2NvdW50SWQpID0+XG4gICAgICByZXNvbHZlV2ViZXhBY2NvdW50KHsgY2ZnOiBjZmcgYXMgQ29yZUNvbmZpZywgYWNjb3VudElkIH0pLFxuXG4gICAgZGVmYXVsdEFjY291bnRJZDogKCkgPT4gREVGQVVMVF9BQ0NPVU5UX0lELFxuXG4gICAgc2V0QWNjb3VudEVuYWJsZWQ6ICh7IGNmZywgYWNjb3VudElkLCBlbmFibGVkIH0pID0+IHtcbiAgICAgIGNvbnN0IGNvbmZpZyA9IGNmZyBhcyBDb3JlQ29uZmlnO1xuICAgICAgY29uc3Qgc2VjdGlvbiA9IGNvbmZpZy5jaGFubmVscz8ud2ViZXggPz8ge307XG5cbiAgICAgIGlmIChhY2NvdW50SWQgPT09IERFRkFVTFRfQUNDT1VOVF9JRCkge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIC4uLmNvbmZpZyxcbiAgICAgICAgICBjaGFubmVsczoge1xuICAgICAgICAgICAgLi4uY29uZmlnLmNoYW5uZWxzLFxuICAgICAgICAgICAgd2ViZXg6IHtcbiAgICAgICAgICAgICAgLi4uc2VjdGlvbixcbiAgICAgICAgICAgICAgZW5hYmxlZCxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgfSxcbiAgICAgICAgfTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHtcbiAgICAgICAgLi4uY29uZmlnLFxuICAgICAgICBjaGFubmVsczoge1xuICAgICAgICAgIC4uLmNvbmZpZy5jaGFubmVscyxcbiAgICAgICAgICB3ZWJleDoge1xuICAgICAgICAgICAgLi4uc2VjdGlvbixcbiAgICAgICAgICAgIGFjY291bnRzOiB7XG4gICAgICAgICAgICAgIC4uLnNlY3Rpb24uYWNjb3VudHMsXG4gICAgICAgICAgICAgIFthY2NvdW50SWRdOiB7XG4gICAgICAgICAgICAgICAgLi4uc2VjdGlvbi5hY2NvdW50cz8uW2FjY291bnRJZF0sXG4gICAgICAgICAgICAgICAgZW5hYmxlZCxcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgfSxcbiAgICAgICAgfSxcbiAgICAgIH07XG4gICAgfSxcblxuICAgIGRlbGV0ZUFjY291bnQ6ICh7IGNmZywgYWNjb3VudElkIH0pID0+IHtcbiAgICAgIGNvbnN0IGNvbmZpZyA9IGNmZyBhcyBDb3JlQ29uZmlnO1xuICAgICAgY29uc3Qgc2VjdGlvbiA9IGNvbmZpZy5jaGFubmVscz8ud2ViZXggPz8ge307XG5cbiAgICAgIGlmIChhY2NvdW50SWQgPT09IERFRkFVTFRfQUNDT1VOVF9JRCkge1xuICAgICAgICBjb25zdCB7IHRva2VuLCB3ZWJob29rVXJsLCB3ZWJob29rU2VjcmV0LCBkbVBvbGljeSwgYWxsb3dGcm9tLCAuLi5yZXN0IH0gPSBzZWN0aW9uO1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIC4uLmNvbmZpZyxcbiAgICAgICAgICBjaGFubmVsczoge1xuICAgICAgICAgICAgLi4uY29uZmlnLmNoYW5uZWxzLFxuICAgICAgICAgICAgd2ViZXg6IHJlc3QsXG4gICAgICAgICAgfSxcbiAgICAgICAgfTtcbiAgICAgIH1cblxuICAgICAgY29uc3QgYWNjb3VudHMgPSB7IC4uLnNlY3Rpb24uYWNjb3VudHMgfTtcbiAgICAgIGRlbGV0ZSBhY2NvdW50c1thY2NvdW50SWRdO1xuXG4gICAgICByZXR1cm4ge1xuICAgICAgICAuLi5jb25maWcsXG4gICAgICAgIGNoYW5uZWxzOiB7XG4gICAgICAgICAgLi4uY29uZmlnLmNoYW5uZWxzLFxuICAgICAgICAgIHdlYmV4OiB7XG4gICAgICAgICAgICAuLi5zZWN0aW9uLFxuICAgICAgICAgICAgYWNjb3VudHMsXG4gICAgICAgICAgfSxcbiAgICAgICAgfSxcbiAgICAgIH07XG4gICAgfSxcblxuICAgIGlzQ29uZmlndXJlZDogKGFjY291bnQpID0+IGFjY291bnQuY29uZmlndXJlZCxcblxuICAgIGRlc2NyaWJlQWNjb3VudDogKGFjY291bnQpID0+ICh7XG4gICAgICBhY2NvdW50SWQ6IGFjY291bnQuYWNjb3VudElkLFxuICAgICAgbmFtZTogYWNjb3VudC5uYW1lLFxuICAgICAgZW5hYmxlZDogYWNjb3VudC5lbmFibGVkLFxuICAgICAgY29uZmlndXJlZDogYWNjb3VudC5jb25maWd1cmVkLFxuICAgICAgYmFzZVVybDogYWNjb3VudC5jb25maWcuYXBpQmFzZVVybCA/PyBcImh0dHBzOi8vd2ViZXhhcGlzLmNvbS92MVwiLFxuICAgIH0pLFxuXG4gICAgcmVzb2x2ZUFsbG93RnJvbTogKHsgY2ZnIH0pID0+XG4gICAgICAoKGNmZyBhcyBDb3JlQ29uZmlnKS5jaGFubmVscz8ud2ViZXg/LmFsbG93RnJvbSA/PyBbXSkubWFwKFN0cmluZyksXG5cbiAgICBmb3JtYXRBbGxvd0Zyb206ICh7IGFsbG93RnJvbSB9KSA9PlxuICAgICAgYWxsb3dGcm9tLm1hcCgoZW50cnkpID0+IGVudHJ5LnRyaW0oKS50b0xvd2VyQ2FzZSgpKSxcbiAgfSxcblxuICBzZWN1cml0eToge1xuICAgIHJlc29sdmVEbVBvbGljeTogKHsgYWNjb3VudCB9KSA9PiB7XG4gICAgICBjb25zdCBwb2xpY3kgPSBhY2NvdW50LmNvbmZpZy5kbVBvbGljeSA/PyBcImFsbG93XCI7XG4gICAgICAvLyBNYXAgXCJhbGxvd2xpc3RlZFwiIHRvIFwiYWxsb3dsaXN0XCIgZm9yIE9wZW5DbGF3IGNvbXBhdGliaWxpdHlcbiAgICAgIGNvbnN0IG5vcm1hbGl6ZWRQb2xpY3kgPSBwb2xpY3kgPT09IFwiYWxsb3dsaXN0ZWRcIiA/IFwiYWxsb3dsaXN0XCIgOiBwb2xpY3k7XG5cbiAgICAgIHJldHVybiB7XG4gICAgICAgIHBvbGljeTogbm9ybWFsaXplZFBvbGljeSBhcyBcImFsbG93XCIgfCBcImRlbnlcIiB8IFwiYWxsb3dsaXN0XCIgfCBcInBhaXJpbmdcIixcbiAgICAgICAgYWxsb3dGcm9tOiBhY2NvdW50LmNvbmZpZy5hbGxvd0Zyb20gPz8gW10sXG4gICAgICAgIHBvbGljeVBhdGg6IFwiY2hhbm5lbHMud2ViZXguZG1Qb2xpY3lcIixcbiAgICAgICAgYWxsb3dGcm9tUGF0aDogXCJjaGFubmVscy53ZWJleC5hbGxvd0Zyb21cIixcbiAgICAgICAgYXBwcm92ZUhpbnQ6IFwiQWRkIHVzZXIgSUQgb3IgZW1haWwgdG8gY2hhbm5lbHMud2ViZXguYWxsb3dGcm9tXCIsXG4gICAgICAgIG5vcm1hbGl6ZUVudHJ5OiAocmF3KSA9PiByYXcudHJpbSgpLnRvTG93ZXJDYXNlKCksXG4gICAgICB9O1xuICAgIH0sXG4gIH0sXG5cbiAgdGhyZWFkaW5nOiB7XG4gICAgcmVzb2x2ZVJlcGx5VG9Nb2RlOiAoKSA9PiBcIm9mZlwiLFxuICAgIGJ1aWxkVG9vbENvbnRleHQ6ICh7IGNvbnRleHQsIGhhc1JlcGxpZWRSZWYgfSkgPT4gKHtcbiAgICAgIGN1cnJlbnRDaGFubmVsSWQ6IGNvbnRleHQuVG8/LnRyaW0oKSB8fCB1bmRlZmluZWQsXG4gICAgICBjdXJyZW50VGhyZWFkVHM6IGNvbnRleHQuTWVzc2FnZVRocmVhZElkICE9IG51bGxcbiAgICAgICAgPyBTdHJpbmcoY29udGV4dC5NZXNzYWdlVGhyZWFkSWQpXG4gICAgICAgIDogY29udGV4dC5SZXBseVRvSWQsXG4gICAgICBoYXNSZXBsaWVkUmVmLFxuICAgIH0pLFxuICB9LFxuXG4gIG1lc3NhZ2luZzoge1xuICAgIG5vcm1hbGl6ZVRhcmdldDogKHJhdzogc3RyaW5nKSA9PiB7XG4gICAgICBsZXQgbm9ybWFsaXplZCA9IHJhdy50cmltKCk7XG4gICAgICBpZiAoIW5vcm1hbGl6ZWQpIHJldHVybiB1bmRlZmluZWQ7XG4gICAgICBpZiAobm9ybWFsaXplZC50b0xvd2VyQ2FzZSgpLnN0YXJ0c1dpdGgoXCJ3ZWJleDpcIikpIHtcbiAgICAgICAgbm9ybWFsaXplZCA9IG5vcm1hbGl6ZWQuc2xpY2UoXCJ3ZWJleDpcIi5sZW5ndGgpLnRyaW0oKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBub3JtYWxpemVkIHx8IHVuZGVmaW5lZDtcbiAgICB9LFxuICAgIHRhcmdldFJlc29sdmVyOiB7XG4gICAgICBsb29rc0xpa2VJZDogKHJhdykgPT4ge1xuICAgICAgICBjb25zdCB0cmltbWVkID0gcmF3LnRyaW0oKTtcbiAgICAgICAgaWYgKCF0cmltbWVkKSByZXR1cm4gZmFsc2U7XG4gICAgICAgIC8vIFdlYmV4IElEcyBhcmUgYmFzZTY0LWVuY29kZWQgYW5kIHN0YXJ0IHdpdGggYSBzcGVjaWZpYyBwcmVmaXhcbiAgICAgICAgaWYgKHRyaW1tZWQuc3RhcnRzV2l0aChcIlkybHpZMjl6Y0dGeWF6b3ZMM1wiKSkgcmV0dXJuIHRydWU7XG4gICAgICAgIC8vIEFsc28gYWNjZXB0IGVtYWlsc1xuICAgICAgICByZXR1cm4gdHJpbW1lZC5pbmNsdWRlcyhcIkBcIik7XG4gICAgICB9LFxuICAgICAgaGludDogXCI8cm9vbUlkfHBlcnNvbklkfGVtYWlsPlwiLFxuICAgIH0sXG4gIH0sXG5cbiAgb3V0Ym91bmQ6IHtcbiAgICBkZWxpdmVyeU1vZGU6IFwiZGlyZWN0XCIsXG4gICAgdGV4dENodW5rTGltaXQ6IDcwMDAsIC8vIFdlYmV4IGhhcyBhIDc0MzkgYnl0ZSBsaW1pdFxuXG4gICAgc2VuZFRleHQ6IGFzeW5jICh7IHRvLCB0ZXh0LCBhY2NvdW50LCByZXBseVRvSWQgfSkgPT4ge1xuICAgICAgY29uc3Qgc2VuZGVyID0gbmV3IFdlYmV4U2VuZGVyKGFjY291bnQuY29uZmlnKTtcblxuICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgc2VuZGVyLnNlbmQoe1xuICAgICAgICB0byxcbiAgICAgICAgY29udGVudDogeyB0ZXh0IH0sXG4gICAgICAgIHBhcmVudElkOiByZXBseVRvSWQsXG4gICAgICB9KTtcblxuICAgICAgcmV0dXJuIHtcbiAgICAgICAgY2hhbm5lbDogXCJ3ZWJleFwiLFxuICAgICAgICBtZXNzYWdlSWQ6IHJlc3VsdC5pZCxcbiAgICAgICAgcm9vbUlkOiByZXN1bHQucm9vbUlkLFxuICAgICAgfTtcbiAgICB9LFxuXG4gICAgc2VuZE1lZGlhOiBhc3luYyAoeyB0bywgdGV4dCwgbWVkaWFVcmwsIGFjY291bnQsIHJlcGx5VG9JZCB9KSA9PiB7XG4gICAgICBjb25zdCBzZW5kZXIgPSBuZXcgV2ViZXhTZW5kZXIoYWNjb3VudC5jb25maWcpO1xuXG4gICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBzZW5kZXIuc2VuZCh7XG4gICAgICAgIHRvLFxuICAgICAgICBjb250ZW50OiB7XG4gICAgICAgICAgdGV4dCxcbiAgICAgICAgICBmaWxlczogbWVkaWFVcmwgPyBbbWVkaWFVcmxdIDogdW5kZWZpbmVkLFxuICAgICAgICB9LFxuICAgICAgICBwYXJlbnRJZDogcmVwbHlUb0lkLFxuICAgICAgfSk7XG5cbiAgICAgIHJldHVybiB7XG4gICAgICAgIGNoYW5uZWw6IFwid2ViZXhcIixcbiAgICAgICAgbWVzc2FnZUlkOiByZXN1bHQuaWQsXG4gICAgICAgIHJvb21JZDogcmVzdWx0LnJvb21JZCxcbiAgICAgIH07XG4gICAgfSxcbiAgfSxcblxuICBzdGF0dXM6IHtcbiAgICBkZWZhdWx0UnVudGltZToge1xuICAgICAgYWNjb3VudElkOiBERUZBVUxUX0FDQ09VTlRfSUQsXG4gICAgICBydW5uaW5nOiBmYWxzZSxcbiAgICAgIGxhc3RTdGFydEF0OiBudWxsLFxuICAgICAgbGFzdFN0b3BBdDogbnVsbCxcbiAgICAgIGxhc3RFcnJvcjogbnVsbCxcbiAgICB9LFxuXG4gICAgY29sbGVjdFN0YXR1c0lzc3VlczogKGFjY291bnRzKSA9PlxuICAgICAgYWNjb3VudHMuZmxhdE1hcCgoYWNjb3VudCkgPT4ge1xuICAgICAgICBjb25zdCBsYXN0RXJyb3IgPSB0eXBlb2YgYWNjb3VudC5sYXN0RXJyb3IgPT09IFwic3RyaW5nXCIgPyBhY2NvdW50Lmxhc3RFcnJvci50cmltKCkgOiBcIlwiO1xuICAgICAgICBpZiAoIWxhc3RFcnJvcikgcmV0dXJuIFtdO1xuICAgICAgICByZXR1cm4gW1xuICAgICAgICAgIHtcbiAgICAgICAgICAgIGNoYW5uZWw6IFwid2ViZXhcIixcbiAgICAgICAgICAgIGFjY291bnRJZDogYWNjb3VudC5hY2NvdW50SWQsXG4gICAgICAgICAgICBraW5kOiBcInJ1bnRpbWVcIiBhcyBjb25zdCxcbiAgICAgICAgICAgIG1lc3NhZ2U6IGBDaGFubmVsIGVycm9yOiAke2xhc3RFcnJvcn1gLFxuICAgICAgICAgIH0sXG4gICAgICAgIF07XG4gICAgICB9KSxcblxuICAgIGJ1aWxkQ2hhbm5lbFN1bW1hcnk6ICh7IHNuYXBzaG90IH0pID0+ICh7XG4gICAgICBjb25maWd1cmVkOiAoc25hcHNob3QuY29uZmlndXJlZCA/PyBmYWxzZSkgYXMgYm9vbGVhbixcbiAgICAgIGJhc2VVcmw6IChzbmFwc2hvdC5iYXNlVXJsID8/IG51bGwpIGFzIHN0cmluZyB8IG51bGwsXG4gICAgICBydW5uaW5nOiAoc25hcHNob3QucnVubmluZyA/PyBmYWxzZSkgYXMgYm9vbGVhbixcbiAgICAgIGxhc3RTdGFydEF0OiAoc25hcHNob3QubGFzdFN0YXJ0QXQgPz8gbnVsbCkgYXMgRGF0ZSB8IG51bGwsXG4gICAgICBsYXN0U3RvcEF0OiAoc25hcHNob3QubGFzdFN0b3BBdCA/PyBudWxsKSBhcyBEYXRlIHwgbnVsbCxcbiAgICAgIGxhc3RFcnJvcjogKHNuYXBzaG90Lmxhc3RFcnJvciA/PyBudWxsKSBhcyBzdHJpbmcgfCBudWxsLFxuICAgIH0pLFxuXG4gICAgcHJvYmVBY2NvdW50OiBhc3luYyAoeyBhY2NvdW50LCB0aW1lb3V0TXMgfSkgPT4ge1xuICAgICAgaWYgKCFhY2NvdW50LmNvbmZpZ3VyZWQpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICBvazogZmFsc2UsXG4gICAgICAgICAgZXJyb3I6IFwiQWNjb3VudCBub3QgY29uZmlndXJlZFwiLFxuICAgICAgICAgIGVsYXBzZWRNczogMCxcbiAgICAgICAgfTtcbiAgICAgIH1cblxuICAgICAgY29uc3Qgc3RhcnQgPSBEYXRlLm5vdygpO1xuICAgICAgdHJ5IHtcbiAgICAgICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCBmZXRjaChcbiAgICAgICAgICBgJHthY2NvdW50LmNvbmZpZy5hcGlCYXNlVXJsID8/IFwiaHR0cHM6Ly93ZWJleGFwaXMuY29tL3YxXCJ9L3Blb3BsZS9tZWAsXG4gICAgICAgICAge1xuICAgICAgICAgICAgbWV0aG9kOiBcIkdFVFwiLFxuICAgICAgICAgICAgaGVhZGVyczoge1xuICAgICAgICAgICAgICBBdXRob3JpemF0aW9uOiBgQmVhcmVyICR7YWNjb3VudC5jb25maWcudG9rZW59YCxcbiAgICAgICAgICAgICAgXCJDb250ZW50LVR5cGVcIjogXCJhcHBsaWNhdGlvbi9qc29uXCIsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgc2lnbmFsOiB0aW1lb3V0TXMgPyBBYm9ydFNpZ25hbC50aW1lb3V0KHRpbWVvdXRNcykgOiB1bmRlZmluZWQsXG4gICAgICAgICAgfVxuICAgICAgICApO1xuXG4gICAgICAgIGNvbnN0IGVsYXBzZWRNcyA9IERhdGUubm93KCkgLSBzdGFydDtcblxuICAgICAgICBpZiAoIXJlc3BvbnNlLm9rKSB7XG4gICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIG9rOiBmYWxzZSxcbiAgICAgICAgICAgIGVycm9yOiBgSFRUUCAke3Jlc3BvbnNlLnN0YXR1c306ICR7cmVzcG9uc2Uuc3RhdHVzVGV4dH1gLFxuICAgICAgICAgICAgZWxhcHNlZE1zLFxuICAgICAgICAgIH07XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4geyBvazogdHJ1ZSwgZWxhcHNlZE1zIH07XG4gICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICBvazogZmFsc2UsXG4gICAgICAgICAgZXJyb3I6IGVyciBpbnN0YW5jZW9mIEVycm9yID8gZXJyLm1lc3NhZ2UgOiBTdHJpbmcoZXJyKSxcbiAgICAgICAgICBlbGFwc2VkTXM6IERhdGUubm93KCkgLSBzdGFydCxcbiAgICAgICAgfTtcbiAgICAgIH1cbiAgICB9LFxuXG4gICAgYnVpbGRBY2NvdW50U25hcHNob3Q6ICh7IGFjY291bnQsIHJ1bnRpbWUsIHByb2JlIH0pID0+ICh7XG4gICAgICBhY2NvdW50SWQ6IGFjY291bnQuYWNjb3VudElkLFxuICAgICAgbmFtZTogYWNjb3VudC5uYW1lLFxuICAgICAgZW5hYmxlZDogYWNjb3VudC5lbmFibGVkLFxuICAgICAgY29uZmlndXJlZDogYWNjb3VudC5jb25maWd1cmVkLFxuICAgICAgYmFzZVVybDogYWNjb3VudC5jb25maWcuYXBpQmFzZVVybCA/PyBcImh0dHBzOi8vd2ViZXhhcGlzLmNvbS92MVwiLFxuICAgICAgcnVubmluZzogcnVudGltZT8ucnVubmluZyA/PyBmYWxzZSxcbiAgICAgIGxhc3RTdGFydEF0OiBydW50aW1lPy5sYXN0U3RhcnRBdCA/PyBudWxsLFxuICAgICAgbGFzdFN0b3BBdDogcnVudGltZT8ubGFzdFN0b3BBdCA/PyBudWxsLFxuICAgICAgbGFzdEVycm9yOiBydW50aW1lPy5sYXN0RXJyb3IgPz8gbnVsbCxcbiAgICAgIHByb2JlLFxuICAgICAgbGFzdFByb2JlQXQ6IHJ1bnRpbWU/Lmxhc3RQcm9iZUF0ID8/IG51bGwsXG4gICAgfSksXG4gIH0sXG5cbiAgZ2F0ZXdheToge1xuICAgIHN0YXJ0QWNjb3VudDogYXN5bmMgKGN0eCkgPT4ge1xuICAgICAgY29uc3QgeyBhY2NvdW50LCBydW50aW1lLCBsb2csIHNldFN0YXR1cyB9ID0gY3R4O1xuXG4gICAgICBzZXRTdGF0dXMoe1xuICAgICAgICBhY2NvdW50SWQ6IGFjY291bnQuYWNjb3VudElkLFxuICAgICAgICBiYXNlVXJsOiBhY2NvdW50LmNvbmZpZy5hcGlCYXNlVXJsID8/IFwiaHR0cHM6Ly93ZWJleGFwaXMuY29tL3YxXCIsXG4gICAgICB9KTtcblxuICAgICAgbG9nPy5pbmZvPy4oXG4gICAgICAgIGBbJHthY2NvdW50LmFjY291bnRJZH1dIHN0YXJ0aW5nIFdlYmV4IHByb3ZpZGVyICh3ZWJob29rIG1vZGUpYFxuICAgICAgKTtcblxuICAgICAgLy8gSW5pdGlhbGl6ZSB3ZWJob29rIGhhbmRsZXJcbiAgICAgIGNvbnN0IHdlYmhvb2tIYW5kbGVyID0gbmV3IFdlYmV4V2ViaG9va0hhbmRsZXIoYWNjb3VudC5jb25maWcpO1xuICAgICAgYXdhaXQgd2ViaG9va0hhbmRsZXIuaW5pdGlhbGl6ZSgpO1xuXG4gICAgICAvLyBSZWdpc3RlciB3ZWJob29rcyB3aXRoIFdlYmV4XG4gICAgICB0cnkge1xuICAgICAgICBhd2FpdCB3ZWJob29rSGFuZGxlci5yZWdpc3RlcldlYmhvb2tzKCk7XG4gICAgICAgIGxvZz8uaW5mbz8uKGBbJHthY2NvdW50LmFjY291bnRJZH1dIHdlYmhvb2tzIHJlZ2lzdGVyZWRgKTtcbiAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICBsb2c/Lndhcm4/LihcbiAgICAgICAgICBgWyR7YWNjb3VudC5hY2NvdW50SWR9XSBmYWlsZWQgdG8gcmVnaXN0ZXIgd2ViaG9va3M6ICR7ZXJyIGluc3RhbmNlb2YgRXJyb3IgPyBlcnIubWVzc2FnZSA6IGVycn1gXG4gICAgICAgICk7XG4gICAgICB9XG5cbiAgICAgIC8vIFJlZ2lzdGVyIEhUVFAgaGFuZGxlciBmb3IgaW5jb21pbmcgd2ViaG9va3NcbiAgICAgIGNvbnN0IHdlYmhvb2tQYXRoID0gYC93ZWJob29rcy93ZWJleC8ke2FjY291bnQuYWNjb3VudElkfWA7XG5cbiAgICAgIHJ1bnRpbWUuaHR0cC5yZWdpc3RlckhhbmRsZXIoe1xuICAgICAgICBtZXRob2Q6IFwiUE9TVFwiLFxuICAgICAgICBwYXRoOiB3ZWJob29rUGF0aCxcbiAgICAgICAgaGFuZGxlcjogYXN5bmMgKHJlcSkgPT4ge1xuICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICBjb25zdCBzaWduYXR1cmUgPSByZXEuaGVhZGVyc1tcIngtc3Bhcmstc2lnbmF0dXJlXCJdIGFzIHN0cmluZyB8IHVuZGVmaW5lZDtcbiAgICAgICAgICAgIGNvbnN0IHBheWxvYWQgPSByZXEuYm9keSBhcyBXZWJleFdlYmhvb2tQYXlsb2FkO1xuXG4gICAgICAgICAgICBjb25zdCBlbnZlbG9wZSA9IGF3YWl0IHdlYmhvb2tIYW5kbGVyLmhhbmRsZVdlYmhvb2socGF5bG9hZCwgc2lnbmF0dXJlKTtcblxuICAgICAgICAgICAgaWYgKGVudmVsb3BlKSB7XG4gICAgICAgICAgICAgIC8vIEZvcndhcmQgdG8gT3BlbkNsYXcncyBtZXNzYWdlIHBpcGVsaW5lXG4gICAgICAgICAgICAgIGF3YWl0IHJ1bnRpbWUubWVzc2FnaW5nLmhhbmRsZUluYm91bmQoe1xuICAgICAgICAgICAgICAgIGNoYW5uZWw6IFwid2ViZXhcIixcbiAgICAgICAgICAgICAgICBhY2NvdW50SWQ6IGFjY291bnQuYWNjb3VudElkLFxuICAgICAgICAgICAgICAgIHNlbmRlcklkOiBlbnZlbG9wZS5hdXRob3IuaWQsXG4gICAgICAgICAgICAgICAgc2VuZGVyRW1haWw6IGVudmVsb3BlLmF1dGhvci5lbWFpbCxcbiAgICAgICAgICAgICAgICBjb252ZXJzYXRpb25JZDogZW52ZWxvcGUuY29udmVyc2F0aW9uSWQsXG4gICAgICAgICAgICAgICAgbWVzc2FnZUlkOiBlbnZlbG9wZS5pZCxcbiAgICAgICAgICAgICAgICB0ZXh0OiBlbnZlbG9wZS5jb250ZW50LnRleHQgPz8gXCJcIixcbiAgICAgICAgICAgICAgICByb29tVHlwZTogZW52ZWxvcGUubWV0YWRhdGEucm9vbVR5cGUsXG4gICAgICAgICAgICAgICAgdGhyZWFkSWQ6IGVudmVsb3BlLm1ldGFkYXRhLnBhcmVudElkLFxuICAgICAgICAgICAgICAgIHRpbWVzdGFtcDogbmV3IERhdGUoZW52ZWxvcGUubWV0YWRhdGEudGltZXN0YW1wKSxcbiAgICAgICAgICAgICAgICByYXc6IGVudmVsb3BlLm1ldGFkYXRhLnJhdyxcbiAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHJldHVybiB7IHN0YXR1czogMjAwLCBib2R5OiB7IG9rOiB0cnVlIH0gfTtcbiAgICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICAgIGxvZz8uZXJyb3I/LihcbiAgICAgICAgICAgICAgYFske2FjY291bnQuYWNjb3VudElkfV0gd2ViaG9vayBlcnJvcjogJHtlcnIgaW5zdGFuY2VvZiBFcnJvciA/IGVyci5tZXNzYWdlIDogZXJyfWBcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICByZXR1cm4geyBzdGF0dXM6IDUwMCwgYm9keTogeyBlcnJvcjogXCJJbnRlcm5hbCBlcnJvclwiIH0gfTtcbiAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICB9KTtcblxuICAgICAgbG9nPy5pbmZvPy4oXG4gICAgICAgIGBbJHthY2NvdW50LmFjY291bnRJZH1dIEhUVFAgd2ViaG9vayBoYW5kbGVyIHJlZ2lzdGVyZWQgYXQgJHt3ZWJob29rUGF0aH1gXG4gICAgICApO1xuXG4gICAgICAvLyBSZXR1cm4gY2xlYW51cCBmdW5jdGlvblxuICAgICAgcmV0dXJuIGFzeW5jICgpID0+IHtcbiAgICAgICAgbG9nPy5pbmZvPy4oYFske2FjY291bnQuYWNjb3VudElkfV0gc3RvcHBpbmcgV2ViZXggcHJvdmlkZXJgKTtcbiAgICAgICAgcnVudGltZS5odHRwLnVucmVnaXN0ZXJIYW5kbGVyKHdlYmhvb2tQYXRoKTtcbiAgICAgIH07XG4gICAgfSxcbiAgfSxcbn07XG4iXX0=
@@ -0,0 +1,98 @@
1
+ /**
2
+ * Webex Channel - Main Channel Logic
3
+ */
4
+ import type { WebexChannelConfig, WebexChannelPlugin, WebexMessage, WebexWebhook, WebexWebhookPayload, OpenClawEnvelope, OpenClawOutboundMessage, WebhookHandler } from './types';
5
+ import { WebexSender } from './send';
6
+ import { WebexWebhookHandler } from './webhook';
7
+ /**
8
+ * WebexChannel implements the OpenClaw channel plugin interface for Cisco Webex
9
+ */
10
+ export declare class WebexChannel implements WebexChannelPlugin {
11
+ readonly name = "webex";
12
+ readonly version = "1.0.0";
13
+ private config;
14
+ private sender;
15
+ private webhookHandler;
16
+ private messageHandlers;
17
+ private initialized;
18
+ /**
19
+ * Initialize the channel with configuration
20
+ */
21
+ initialize(config: WebexChannelConfig): Promise<void>;
22
+ /**
23
+ * Validate configuration
24
+ */
25
+ private validateConfig;
26
+ /**
27
+ * Ensure the channel is initialized
28
+ */
29
+ private ensureInitialized;
30
+ /**
31
+ * Send a message
32
+ */
33
+ send(message: OpenClawOutboundMessage): Promise<WebexMessage>;
34
+ /**
35
+ * Send a simple text message to a room
36
+ */
37
+ sendText(roomId: string, text: string): Promise<WebexMessage>;
38
+ /**
39
+ * Send a markdown message to a room
40
+ */
41
+ sendMarkdown(roomId: string, markdown: string): Promise<WebexMessage>;
42
+ /**
43
+ * Send a direct message to a person
44
+ */
45
+ sendDirect(personIdOrEmail: string, text: string): Promise<WebexMessage>;
46
+ /**
47
+ * Reply to a message in a thread
48
+ */
49
+ reply(roomId: string, parentId: string, text: string): Promise<WebexMessage>;
50
+ /**
51
+ * Handle incoming webhook
52
+ */
53
+ handleWebhook(payload: WebexWebhookPayload, signature?: string): Promise<OpenClawEnvelope | null>;
54
+ /**
55
+ * Register a message handler
56
+ */
57
+ onMessage(handler: WebhookHandler): void;
58
+ /**
59
+ * Remove a message handler
60
+ */
61
+ offMessage(handler: WebhookHandler): void;
62
+ /**
63
+ * Notify all registered handlers of a new message
64
+ */
65
+ private notifyHandlers;
66
+ /**
67
+ * Register webhooks with Webex
68
+ */
69
+ registerWebhooks(): Promise<WebexWebhook[]>;
70
+ /**
71
+ * Get the sender instance for advanced operations
72
+ */
73
+ getSender(): WebexSender;
74
+ /**
75
+ * Get the webhook handler instance for advanced operations
76
+ */
77
+ getWebhookHandler(): WebexWebhookHandler;
78
+ /**
79
+ * Get the current configuration
80
+ */
81
+ getConfig(): WebexChannelConfig | null;
82
+ /**
83
+ * Check if the channel is initialized
84
+ */
85
+ isInitialized(): boolean;
86
+ /**
87
+ * Cleanup and shutdown
88
+ */
89
+ shutdown(): Promise<void>;
90
+ }
91
+ /**
92
+ * Create a new Webex channel instance
93
+ */
94
+ export declare function createWebexChannel(): WebexChannel;
95
+ /**
96
+ * Create and initialize a Webex channel with config
97
+ */
98
+ export declare function createAndInitialize(config: WebexChannelConfig): Promise<WebexChannel>;