@andreprado/agentkit 0.1.0 → 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.
- package/package.json +1 -1
- package/src/runtime/channels/discord.ts +14 -6
- package/src/runtime/channels/generic-webhook.ts +21 -313
- package/src/runtime/channels/net-guard.ts +480 -0
- package/src/runtime/channels/provider-fetch.ts +54 -0
- package/src/runtime/channels/slack.ts +9 -3
- package/src/runtime/channels/telegram.ts +43 -10
- package/src/runtime/channels/whatsapp-evolution.ts +33 -60
- package/src/runtime/channels/whatsapp-uazapi.ts +33 -164
- package/src/runtime/channels/whatsapp-zapster.ts +35 -7
- package/src/runtime/config.ts +23 -0
- package/src/runtime/knowledge/embeddings.ts +45 -7
- package/src/runtime/knowledge/ingest.ts +69 -6
- package/src/runtime/knowledge/vector.ts +30 -30
package/package.json
CHANGED
|
@@ -8,6 +8,10 @@ import type {
|
|
|
8
8
|
WebhookVerificationResult,
|
|
9
9
|
} from "../channels";
|
|
10
10
|
import { AgentKitError } from "../errors";
|
|
11
|
+
import {
|
|
12
|
+
CHANNEL_SEND_TIMEOUT_MS,
|
|
13
|
+
classifySendRequestError,
|
|
14
|
+
} from "./provider-fetch";
|
|
11
15
|
|
|
12
16
|
const DISCORD_INTERACTION_PING = 1;
|
|
13
17
|
const DISCORD_INTERACTION_APPLICATION_COMMAND = 2;
|
|
@@ -331,16 +335,18 @@ export async function sendDiscordMessage(
|
|
|
331
335
|
|
|
332
336
|
try {
|
|
333
337
|
response = await fetcher(actualRequest.url, {
|
|
338
|
+
signal: AbortSignal.timeout(CHANNEL_SEND_TIMEOUT_MS),
|
|
334
339
|
method: actualRequest.method,
|
|
335
340
|
headers: actualRequest.headers,
|
|
336
341
|
body: JSON.stringify(actualRequest.body),
|
|
337
342
|
});
|
|
338
343
|
} catch (error) {
|
|
344
|
+
const failure = classifySendRequestError(error);
|
|
339
345
|
return {
|
|
340
346
|
ok: false,
|
|
341
|
-
retryable:
|
|
342
|
-
code:
|
|
343
|
-
message: `Discord bot message request
|
|
347
|
+
retryable: failure.retryable,
|
|
348
|
+
code: failure.code,
|
|
349
|
+
message: `Discord bot message request ${failure.reason}: ${redactDiscordToken(
|
|
344
350
|
error instanceof Error ? error.message : String(error),
|
|
345
351
|
input.secrets.DISCORD_BOT_TOKEN,
|
|
346
352
|
)}`,
|
|
@@ -457,6 +463,7 @@ export async function sendDiscordInteractionFollowup(
|
|
|
457
463
|
|
|
458
464
|
try {
|
|
459
465
|
response = await fetcher(actualRequest.url, {
|
|
466
|
+
signal: AbortSignal.timeout(CHANNEL_SEND_TIMEOUT_MS),
|
|
460
467
|
method: actualRequest.method,
|
|
461
468
|
headers: {
|
|
462
469
|
"Content-Type": "application/json",
|
|
@@ -464,11 +471,12 @@ export async function sendDiscordInteractionFollowup(
|
|
|
464
471
|
body: JSON.stringify(actualRequest.body),
|
|
465
472
|
});
|
|
466
473
|
} catch (error) {
|
|
474
|
+
const failure = classifySendRequestError(error);
|
|
467
475
|
return {
|
|
468
476
|
ok: false,
|
|
469
|
-
retryable:
|
|
470
|
-
code:
|
|
471
|
-
message: `Discord follow-up request
|
|
477
|
+
retryable: failure.retryable,
|
|
478
|
+
code: failure.code,
|
|
479
|
+
message: `Discord follow-up request ${failure.reason}: ${redactDiscordToken(
|
|
472
480
|
error instanceof Error ? error.message : String(error),
|
|
473
481
|
replyTarget.interactionToken,
|
|
474
482
|
)}`,
|
|
@@ -1,16 +1,21 @@
|
|
|
1
1
|
import { createHash, createHmac, randomUUID, timingSafeEqual } from "node:crypto";
|
|
2
|
-
import { lookup as dnsLookup } from "node:dns/promises";
|
|
3
|
-
import { request as httpsRequest } from "node:https";
|
|
4
|
-
import type { LookupFunction } from "node:net";
|
|
5
|
-
import { Readable } from "node:stream";
|
|
6
2
|
|
|
7
3
|
import type { GenericWebhookOutputChannelConfig } from "../../index";
|
|
8
4
|
import type { ChannelAdapter, ChannelSendInput, ChannelSendResult, RawWebhookEvent } from "../channels";
|
|
9
5
|
import { AgentKitError } from "../errors";
|
|
6
|
+
import {
|
|
7
|
+
isBlockedOutboundHost,
|
|
8
|
+
pinnedHttpsFetch,
|
|
9
|
+
resolveOutboundAddresses,
|
|
10
|
+
resolvePublicOutboundUrl,
|
|
11
|
+
type OutboundResolver,
|
|
12
|
+
type ResolvedOutboundUrl,
|
|
13
|
+
} from "./net-guard";
|
|
10
14
|
|
|
11
15
|
const DEFAULT_SECRET_NAME = "AGENTKIT_WEBHOOK_SECRET";
|
|
12
16
|
const DEFAULT_OUTPUT_HMAC_HEADER = "X-AgentKit-Webhook-Signature";
|
|
13
17
|
const MAX_OUTPUT_RESPONSE_BYTES = 64_000;
|
|
18
|
+
const GENERIC_WEBHOOK_OUTPUT_URL_LABEL = "Generic webhook output URL";
|
|
14
19
|
|
|
15
20
|
export const genericWebhookChannelAdapter: ChannelAdapter = {
|
|
16
21
|
type: "webhook",
|
|
@@ -152,12 +157,7 @@ type GenericWebhookOutputRequest = {
|
|
|
152
157
|
};
|
|
153
158
|
|
|
154
159
|
type GenericWebhookOutputFetch = (input: string | URL | Request, init?: RequestInit) => Promise<Response>;
|
|
155
|
-
type GenericWebhookOutputResolver =
|
|
156
|
-
type GenericWebhookOutputResolvedUrl = {
|
|
157
|
-
href: string;
|
|
158
|
-
address: string;
|
|
159
|
-
family: 4 | 6;
|
|
160
|
-
};
|
|
160
|
+
type GenericWebhookOutputResolver = OutboundResolver;
|
|
161
161
|
type GenericWebhookOutputRequestInit = {
|
|
162
162
|
method: "POST";
|
|
163
163
|
headers: Record<string, string>;
|
|
@@ -218,10 +218,12 @@ export async function sendGenericWebhookOutputMessage(
|
|
|
218
218
|
input: ChannelSendInput,
|
|
219
219
|
channel: GenericWebhookOutputChannelConfig,
|
|
220
220
|
fetcher?: GenericWebhookOutputFetch,
|
|
221
|
-
resolver: GenericWebhookOutputResolver =
|
|
221
|
+
resolver: GenericWebhookOutputResolver = resolveOutboundAddresses,
|
|
222
222
|
): Promise<ChannelSendResult> {
|
|
223
223
|
let request: GenericWebhookOutputRequest;
|
|
224
|
-
let resolvedUrl:
|
|
224
|
+
let resolvedUrl: ResolvedOutboundUrl;
|
|
225
|
+
// Started before DNS resolution so a stalled resolver counts against the deadline.
|
|
226
|
+
const signal = AbortSignal.timeout(15_000);
|
|
225
227
|
|
|
226
228
|
try {
|
|
227
229
|
request = buildGenericWebhookOutputRequest(input, channel);
|
|
@@ -235,7 +237,7 @@ export async function sendGenericWebhookOutputMessage(
|
|
|
235
237
|
};
|
|
236
238
|
}
|
|
237
239
|
|
|
238
|
-
resolvedUrl = await validateGenericWebhookOutputResolvedUrl(request.url, resolver);
|
|
240
|
+
resolvedUrl = await validateGenericWebhookOutputResolvedUrl(request.url, resolver, signal);
|
|
239
241
|
} catch (error) {
|
|
240
242
|
return genericWebhookOutputFailureFromError(error);
|
|
241
243
|
}
|
|
@@ -246,13 +248,13 @@ export async function sendGenericWebhookOutputMessage(
|
|
|
246
248
|
headers: request.headers,
|
|
247
249
|
body: JSON.stringify(request.body),
|
|
248
250
|
redirect: "manual",
|
|
249
|
-
signal
|
|
251
|
+
signal,
|
|
250
252
|
};
|
|
251
253
|
|
|
252
254
|
try {
|
|
253
255
|
response = fetcher
|
|
254
256
|
? await fetcher(resolvedUrl.href, requestInit)
|
|
255
|
-
: await
|
|
257
|
+
: await pinnedHttpsFetch(resolvedUrl, requestInit, GENERIC_WEBHOOK_OUTPUT_URL_LABEL);
|
|
256
258
|
} catch (error) {
|
|
257
259
|
if (error instanceof AgentKitError) {
|
|
258
260
|
return {
|
|
@@ -411,7 +413,7 @@ function validateGenericWebhookOutputUrl(rawUrl: string): string {
|
|
|
411
413
|
throw new AgentKitError("channel_payload_invalid", "Generic webhook output URL must not include credentials.");
|
|
412
414
|
}
|
|
413
415
|
|
|
414
|
-
if (
|
|
416
|
+
if (isBlockedOutboundHost(url.hostname)) {
|
|
415
417
|
throw new AgentKitError("channel_payload_invalid", "Generic webhook output URL host is not allowed.");
|
|
416
418
|
}
|
|
417
419
|
|
|
@@ -421,317 +423,23 @@ function validateGenericWebhookOutputUrl(rawUrl: string): string {
|
|
|
421
423
|
async function validateGenericWebhookOutputResolvedUrl(
|
|
422
424
|
rawUrl: string,
|
|
423
425
|
resolver: GenericWebhookOutputResolver,
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
let addresses: string[];
|
|
428
|
-
|
|
429
|
-
try {
|
|
430
|
-
addresses = await resolver(url.hostname);
|
|
431
|
-
} catch (error) {
|
|
432
|
-
throw new AgentKitError(
|
|
433
|
-
"channel_provider_unavailable",
|
|
434
|
-
`Generic webhook output URL host could not be resolved: ${error instanceof Error ? error.message : String(error)}`,
|
|
435
|
-
);
|
|
436
|
-
}
|
|
437
|
-
|
|
438
|
-
if (addresses.length === 0) {
|
|
439
|
-
throw new AgentKitError("channel_provider_unavailable", "Generic webhook output URL host did not resolve.");
|
|
440
|
-
}
|
|
441
|
-
|
|
442
|
-
for (const address of addresses) {
|
|
443
|
-
if (isBlockedGenericWebhookOutputHost(address)) {
|
|
444
|
-
throw new AgentKitError("channel_payload_invalid", "Generic webhook output URL host resolved to a blocked address.");
|
|
445
|
-
}
|
|
446
|
-
}
|
|
447
|
-
|
|
448
|
-
const address = normalizeGenericWebhookOutputHost(addresses[0]);
|
|
449
|
-
|
|
450
|
-
return {
|
|
451
|
-
href,
|
|
452
|
-
address,
|
|
453
|
-
family: parseIpv4Octets(address) ? 4 : 6,
|
|
454
|
-
};
|
|
455
|
-
}
|
|
456
|
-
|
|
457
|
-
function fetchGenericWebhookOutputResponse(
|
|
458
|
-
resolvedUrl: GenericWebhookOutputResolvedUrl,
|
|
459
|
-
init: GenericWebhookOutputRequestInit,
|
|
460
|
-
): Promise<Response> {
|
|
461
|
-
const url = new URL(resolvedUrl.href);
|
|
462
|
-
const lookup: LookupFunction = (_hostname, _options, callback) => {
|
|
463
|
-
callback(null, resolvedUrl.address, resolvedUrl.family);
|
|
464
|
-
};
|
|
465
|
-
|
|
466
|
-
return new Promise((resolve, reject) => {
|
|
467
|
-
const request = httpsRequest(
|
|
468
|
-
url,
|
|
469
|
-
{
|
|
470
|
-
method: init.method,
|
|
471
|
-
headers: init.headers,
|
|
472
|
-
lookup,
|
|
473
|
-
signal: init.signal,
|
|
474
|
-
},
|
|
475
|
-
(response) => {
|
|
476
|
-
try {
|
|
477
|
-
assertAllowedGenericWebhookOutputRemoteAddress(response.socket.remoteAddress);
|
|
478
|
-
} catch (error) {
|
|
479
|
-
response.destroy(error instanceof Error ? error : new Error(String(error)));
|
|
480
|
-
reject(error);
|
|
481
|
-
return;
|
|
482
|
-
}
|
|
483
|
-
|
|
484
|
-
resolve(
|
|
485
|
-
new Response(Readable.toWeb(response) as unknown as ReadableStream<Uint8Array>, {
|
|
486
|
-
status: response.statusCode ?? 502,
|
|
487
|
-
headers: headersFromIncomingMessage(response.headers),
|
|
488
|
-
}),
|
|
489
|
-
);
|
|
490
|
-
},
|
|
491
|
-
);
|
|
492
|
-
|
|
493
|
-
request.on("socket", (socket) => {
|
|
494
|
-
const validateSocket = () => {
|
|
495
|
-
try {
|
|
496
|
-
assertAllowedGenericWebhookOutputRemoteAddress(socket.remoteAddress);
|
|
497
|
-
} catch (error) {
|
|
498
|
-
request.destroy(error instanceof Error ? error : new Error(String(error)));
|
|
499
|
-
}
|
|
500
|
-
};
|
|
501
|
-
|
|
502
|
-
socket.once("connect", validateSocket);
|
|
503
|
-
socket.once("secureConnect", validateSocket);
|
|
504
|
-
});
|
|
505
|
-
request.once("error", reject);
|
|
506
|
-
request.end(init.body);
|
|
507
|
-
});
|
|
508
|
-
}
|
|
509
|
-
|
|
510
|
-
function assertAllowedGenericWebhookOutputRemoteAddress(address: string | undefined): void {
|
|
511
|
-
if (!address || isBlockedGenericWebhookOutputHost(address)) {
|
|
512
|
-
throw new AgentKitError("channel_payload_invalid", "Generic webhook output URL connected to a blocked address.");
|
|
513
|
-
}
|
|
514
|
-
}
|
|
515
|
-
|
|
516
|
-
function headersFromIncomingMessage(headers: Record<string, string | string[] | number | undefined>): Headers {
|
|
517
|
-
const result = new Headers();
|
|
518
|
-
|
|
519
|
-
for (const [key, value] of Object.entries(headers)) {
|
|
520
|
-
if (Array.isArray(value)) {
|
|
521
|
-
for (const item of value) {
|
|
522
|
-
result.append(key, item);
|
|
523
|
-
}
|
|
524
|
-
continue;
|
|
525
|
-
}
|
|
526
|
-
|
|
527
|
-
if (value !== undefined) {
|
|
528
|
-
result.set(key, String(value));
|
|
529
|
-
}
|
|
530
|
-
}
|
|
531
|
-
|
|
532
|
-
return result;
|
|
533
|
-
}
|
|
534
|
-
|
|
535
|
-
async function resolveGenericWebhookOutputAddresses(hostname: string): Promise<string[]> {
|
|
536
|
-
const host = normalizeGenericWebhookOutputHost(hostname);
|
|
537
|
-
|
|
538
|
-
if (parseIpv4Octets(host) || parseIpv6Segments(host)) {
|
|
539
|
-
return [host];
|
|
540
|
-
}
|
|
541
|
-
|
|
542
|
-
const records = await dnsLookup(host, {
|
|
543
|
-
all: true,
|
|
544
|
-
verbatim: true,
|
|
545
|
-
});
|
|
546
|
-
|
|
547
|
-
return records.map((record) => record.address);
|
|
548
|
-
}
|
|
549
|
-
|
|
550
|
-
function isBlockedGenericWebhookOutputHost(hostname: string): boolean {
|
|
551
|
-
const host = normalizeGenericWebhookOutputHost(hostname);
|
|
552
|
-
|
|
553
|
-
if (
|
|
554
|
-
host === "localhost" ||
|
|
555
|
-
host.endsWith(".localhost") ||
|
|
556
|
-
host === "metadata.google.internal"
|
|
557
|
-
) {
|
|
558
|
-
return true;
|
|
559
|
-
}
|
|
560
|
-
|
|
561
|
-
const ipv4 = parseIpv4Octets(host);
|
|
562
|
-
|
|
563
|
-
if (ipv4) {
|
|
564
|
-
return isBlockedIpv4Octets(ipv4);
|
|
565
|
-
}
|
|
566
|
-
|
|
567
|
-
const ipv6 = parseIpv6Segments(host);
|
|
568
|
-
|
|
569
|
-
if (ipv6) {
|
|
570
|
-
return isBlockedIpv6Segments(ipv6);
|
|
571
|
-
}
|
|
572
|
-
|
|
573
|
-
return false;
|
|
574
|
-
}
|
|
575
|
-
|
|
576
|
-
function normalizeGenericWebhookOutputHost(hostname: string): string {
|
|
577
|
-
return hostname.toLowerCase().replace(/^\[/, "").replace(/\]$/, "").replace(/\.$/, "");
|
|
578
|
-
}
|
|
579
|
-
|
|
580
|
-
function parseIpv4Octets(host: string): number[] | undefined {
|
|
581
|
-
const parts = host.split(".");
|
|
582
|
-
|
|
583
|
-
if (parts.length !== 4) {
|
|
584
|
-
return undefined;
|
|
585
|
-
}
|
|
586
|
-
|
|
587
|
-
const octets = parts.map((part) => Number(part));
|
|
588
|
-
|
|
589
|
-
if (octets.some((part) => !Number.isInteger(part) || part < 0 || part > 255)) {
|
|
590
|
-
return undefined;
|
|
591
|
-
}
|
|
592
|
-
|
|
593
|
-
return octets;
|
|
426
|
+
signal: AbortSignal,
|
|
427
|
+
): Promise<ResolvedOutboundUrl> {
|
|
428
|
+
return resolvePublicOutboundUrl(validateGenericWebhookOutputUrl(rawUrl), GENERIC_WEBHOOK_OUTPUT_URL_LABEL, resolver, signal);
|
|
594
429
|
}
|
|
595
430
|
|
|
596
|
-
function isBlockedIpv4Octets(parts: number[]): boolean {
|
|
597
|
-
const [a, b] = parts;
|
|
598
431
|
|
|
599
|
-
return (
|
|
600
|
-
a === 0 ||
|
|
601
|
-
a === 10 ||
|
|
602
|
-
a === 127 ||
|
|
603
|
-
(a === 100 && b >= 64 && b <= 127) ||
|
|
604
|
-
(a === 169 && b === 254) ||
|
|
605
|
-
(a === 172 && b >= 16 && b <= 31) ||
|
|
606
|
-
(a === 192 && b === 168) ||
|
|
607
|
-
(a === 198 && (b === 18 || b === 19)) ||
|
|
608
|
-
a >= 224
|
|
609
|
-
);
|
|
610
|
-
}
|
|
611
432
|
|
|
612
|
-
function parseIpv6Segments(host: string): number[] | undefined {
|
|
613
|
-
if (!host.includes(":")) {
|
|
614
|
-
return undefined;
|
|
615
|
-
}
|
|
616
433
|
|
|
617
|
-
if (host === "::") {
|
|
618
|
-
return new Array(8).fill(0);
|
|
619
|
-
}
|
|
620
434
|
|
|
621
|
-
const [leftRaw, rightRaw, extra] = host.split("::");
|
|
622
435
|
|
|
623
|
-
if (extra !== undefined) {
|
|
624
|
-
return undefined;
|
|
625
|
-
}
|
|
626
436
|
|
|
627
|
-
const left = parseIpv6SegmentSide(leftRaw ?? "");
|
|
628
|
-
const right = parseIpv6SegmentSide(rightRaw ?? "");
|
|
629
437
|
|
|
630
|
-
if (!left || !right) {
|
|
631
|
-
return undefined;
|
|
632
|
-
}
|
|
633
438
|
|
|
634
|
-
if (rightRaw === undefined) {
|
|
635
|
-
return left.length === 8 ? left : undefined;
|
|
636
|
-
}
|
|
637
|
-
|
|
638
|
-
const missing = 8 - left.length - right.length;
|
|
639
|
-
|
|
640
|
-
if (missing < 1) {
|
|
641
|
-
return undefined;
|
|
642
|
-
}
|
|
643
|
-
|
|
644
|
-
return [...left, ...new Array(missing).fill(0), ...right];
|
|
645
|
-
}
|
|
646
439
|
|
|
647
|
-
function parseIpv6SegmentSide(value: string): number[] | undefined {
|
|
648
|
-
if (!value) {
|
|
649
|
-
return [];
|
|
650
|
-
}
|
|
651
440
|
|
|
652
|
-
const segments: number[] = [];
|
|
653
441
|
|
|
654
|
-
const parts = value.split(":");
|
|
655
|
-
|
|
656
|
-
for (const [index, part] of parts.entries()) {
|
|
657
|
-
if (part.includes(".")) {
|
|
658
|
-
if (index !== parts.length - 1) {
|
|
659
|
-
return undefined;
|
|
660
|
-
}
|
|
661
|
-
|
|
662
|
-
const octets = parseIpv4Octets(part);
|
|
663
|
-
|
|
664
|
-
if (!octets) {
|
|
665
|
-
return undefined;
|
|
666
|
-
}
|
|
667
|
-
|
|
668
|
-
segments.push((octets[0] << 8) | octets[1], (octets[2] << 8) | octets[3]);
|
|
669
|
-
continue;
|
|
670
|
-
}
|
|
671
442
|
|
|
672
|
-
if (!/^[0-9a-f]{1,4}$/i.test(part)) {
|
|
673
|
-
return undefined;
|
|
674
|
-
}
|
|
675
|
-
|
|
676
|
-
segments.push(parseInt(part, 16));
|
|
677
|
-
}
|
|
678
|
-
|
|
679
|
-
return segments;
|
|
680
|
-
}
|
|
681
|
-
|
|
682
|
-
function isBlockedIpv6Segments(parts: number[]): boolean {
|
|
683
|
-
if (parts.length !== 8) {
|
|
684
|
-
return true;
|
|
685
|
-
}
|
|
686
|
-
|
|
687
|
-
const embeddedIpv4 = ipv4OctetsFromIpv6Segments(parts);
|
|
688
|
-
|
|
689
|
-
if (embeddedIpv4) {
|
|
690
|
-
return isBlockedIpv4Octets(embeddedIpv4);
|
|
691
|
-
}
|
|
692
|
-
|
|
693
|
-
const isAllZero = parts.every((part) => part === 0);
|
|
694
|
-
|
|
695
|
-
if (isAllZero || (parts.slice(0, 7).every((part) => part === 0) && parts[7] === 1)) {
|
|
696
|
-
return true;
|
|
697
|
-
}
|
|
698
|
-
|
|
699
|
-
const first = parts[0];
|
|
700
|
-
|
|
701
|
-
return (
|
|
702
|
-
(first & 0xfe00) === 0xfc00 ||
|
|
703
|
-
(first & 0xffc0) === 0xfe80 ||
|
|
704
|
-
(first & 0xff00) === 0xff00
|
|
705
|
-
);
|
|
706
|
-
}
|
|
707
|
-
|
|
708
|
-
function ipv4OctetsFromIpv6Segments(parts: number[]): number[] | undefined {
|
|
709
|
-
const trailingIpv4 = [
|
|
710
|
-
(parts[6] >> 8) & 0xff,
|
|
711
|
-
parts[6] & 0xff,
|
|
712
|
-
(parts[7] >> 8) & 0xff,
|
|
713
|
-
parts[7] & 0xff,
|
|
714
|
-
];
|
|
715
|
-
|
|
716
|
-
if (parts.slice(0, 5).every((part) => part === 0) && (parts[5] === 0xffff || parts[5] === 0)) {
|
|
717
|
-
return trailingIpv4;
|
|
718
|
-
}
|
|
719
|
-
|
|
720
|
-
if (parts[0] === 0x64 && parts[1] === 0xff9b && parts.slice(2, 6).every((part) => part === 0)) {
|
|
721
|
-
return trailingIpv4;
|
|
722
|
-
}
|
|
723
|
-
|
|
724
|
-
if (parts[0] === 0x2002) {
|
|
725
|
-
return [
|
|
726
|
-
(parts[1] >> 8) & 0xff,
|
|
727
|
-
parts[1] & 0xff,
|
|
728
|
-
(parts[2] >> 8) & 0xff,
|
|
729
|
-
parts[2] & 0xff,
|
|
730
|
-
];
|
|
731
|
-
}
|
|
732
|
-
|
|
733
|
-
return undefined;
|
|
734
|
-
}
|
|
735
443
|
|
|
736
444
|
function redactedGenericWebhookOutputRequest(request: GenericWebhookOutputRequest): Record<string, unknown> {
|
|
737
445
|
return {
|