@relaymessenger/chat-sdk-adapter 0.2.1 → 0.3.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.
Files changed (69) hide show
  1. package/LICENSE +3 -3
  2. package/README.md +218 -98
  3. package/dist/adapter.d.ts +156 -0
  4. package/dist/adapter.d.ts.map +1 -0
  5. package/dist/adapter.js +723 -0
  6. package/dist/adapter.js.map +1 -0
  7. package/dist/client.d.ts +84 -0
  8. package/dist/client.d.ts.map +1 -0
  9. package/dist/client.js +266 -0
  10. package/dist/client.js.map +1 -0
  11. package/dist/content.d.ts +11 -0
  12. package/dist/content.d.ts.map +1 -0
  13. package/dist/content.js +172 -0
  14. package/dist/content.js.map +1 -0
  15. package/dist/credentials.d.ts +13 -0
  16. package/dist/credentials.d.ts.map +1 -0
  17. package/dist/credentials.js +28 -0
  18. package/dist/credentials.js.map +1 -0
  19. package/dist/index.d.ts +17 -0
  20. package/dist/index.d.ts.map +1 -0
  21. package/dist/index.js +10 -0
  22. package/dist/index.js.map +1 -0
  23. package/dist/reactions.d.ts +15 -0
  24. package/dist/reactions.d.ts.map +1 -0
  25. package/dist/reactions.js +58 -0
  26. package/dist/reactions.js.map +1 -0
  27. package/dist/signature.d.ts +22 -0
  28. package/dist/signature.d.ts.map +1 -0
  29. package/dist/signature.js +98 -0
  30. package/dist/signature.js.map +1 -0
  31. package/dist/thread-id.d.ts +8 -0
  32. package/dist/thread-id.d.ts.map +1 -0
  33. package/dist/thread-id.js +27 -0
  34. package/dist/thread-id.js.map +1 -0
  35. package/dist/turn.d.ts +16 -0
  36. package/dist/turn.d.ts.map +1 -0
  37. package/dist/turn.js +22 -0
  38. package/dist/turn.js.map +1 -0
  39. package/dist/types.d.ts +193 -0
  40. package/dist/types.d.ts.map +1 -0
  41. package/dist/types.js +27 -0
  42. package/dist/types.js.map +1 -0
  43. package/dist/webhook.d.ts +9 -0
  44. package/dist/webhook.d.ts.map +1 -0
  45. package/dist/webhook.js +115 -0
  46. package/dist/webhook.js.map +1 -0
  47. package/package.json +52 -32
  48. package/dist/src/adapter.d.ts +0 -125
  49. package/dist/src/adapter.js +0 -724
  50. package/dist/src/chunk.d.ts +0 -25
  51. package/dist/src/chunk.js +0 -108
  52. package/dist/src/client.d.ts +0 -112
  53. package/dist/src/client.js +0 -180
  54. package/dist/src/format.d.ts +0 -43
  55. package/dist/src/format.js +0 -266
  56. package/dist/src/idempotency.d.ts +0 -50
  57. package/dist/src/idempotency.js +0 -75
  58. package/dist/src/index.d.ts +0 -14
  59. package/dist/src/index.js +0 -8
  60. package/dist/src/reactions.d.ts +0 -12
  61. package/dist/src/reactions.js +0 -98
  62. package/dist/src/signature.d.ts +0 -46
  63. package/dist/src/signature.js +0 -95
  64. package/dist/src/threadId.d.ts +0 -12
  65. package/dist/src/threadId.js +0 -28
  66. package/dist/src/turn.d.ts +0 -38
  67. package/dist/src/turn.js +0 -15
  68. package/dist/src/types.d.ts +0 -177
  69. package/dist/src/types.js +0 -7
@@ -0,0 +1,28 @@
1
+ import { AuthenticationError, ValidationError, } from "@chat-adapter/shared";
2
+ export function relayEnv(name) {
3
+ if (typeof process === "undefined")
4
+ return undefined;
5
+ return process.env[name];
6
+ }
7
+ export async function resolveRelayCredential(credential, label) {
8
+ let value;
9
+ try {
10
+ value =
11
+ typeof credential === "function"
12
+ ? await credential()
13
+ : credential;
14
+ }
15
+ catch (error) {
16
+ throw new AuthenticationError("relay", `${label} resolver failed${error instanceof Error ? `: ${error.message}` : ""}`);
17
+ }
18
+ if (!value?.trim()) {
19
+ throw new AuthenticationError("relay", `${label} is required and its resolver must return a non-empty string`);
20
+ }
21
+ return value;
22
+ }
23
+ export function validateStaticCredential(credential, label) {
24
+ if (typeof credential === "string" && !credential.trim()) {
25
+ throw new ValidationError("relay", `${label} must not be empty`);
26
+ }
27
+ }
28
+ //# sourceMappingURL=credentials.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"credentials.js","sourceRoot":"","sources":["../src/credentials.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,mBAAmB,EACnB,eAAe,GAChB,MAAM,sBAAsB,CAAC;AAe9B,MAAM,UAAU,QAAQ,CAAC,IAAY;IACnC,IAAI,OAAO,OAAO,KAAK,WAAW;QAAE,OAAO,SAAS,CAAC;IACrD,OAAO,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;AAC3B,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAC1C,UAAuC,EACvC,KAAa;IAEb,IAAI,KAAyB,CAAC;IAC9B,IAAI,CAAC;QACH,KAAK;YACH,OAAO,UAAU,KAAK,UAAU;gBAC9B,CAAC,CAAC,MAAM,UAAU,EAAE;gBACpB,CAAC,CAAC,UAAU,CAAC;IACnB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,mBAAmB,CAC3B,OAAO,EACP,GAAG,KAAK,mBACN,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAClD,EAAE,CACH,CAAC;IACJ,CAAC;IACD,IAAI,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE,CAAC;QACnB,MAAM,IAAI,mBAAmB,CAC3B,OAAO,EACP,GAAG,KAAK,8DAA8D,CACvE,CAAC;IACJ,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,UAAU,wBAAwB,CACtC,UAAuC,EACvC,KAAa;IAEb,IAAI,OAAO,UAAU,KAAK,QAAQ,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE,EAAE,CAAC;QACzD,MAAM,IAAI,eAAe,CAAC,OAAO,EAAE,GAAG,KAAK,oBAAoB,CAAC,CAAC;IACnE,CAAC;AACH,CAAC"}
@@ -0,0 +1,17 @@
1
+ export { createRelayAdapter, RELAY_ADAPTER_NAME, RelayAdapter, } from "./adapter.js";
2
+ export type { RelayAdapterOptions } from "./adapter.js";
3
+ export type { RelayIdempotencyKeyContext, RelayIdempotencyKeyResolver, } from "./adapter.js";
4
+ export { RELAY_DEFAULT_BASE_URL, RelayApiError, RelayClient, } from "./client.js";
5
+ export type { RelayClientOptions, RelayUploadOptions, } from "./client.js";
6
+ export { relayEnv, resolveRelayCredential, validateStaticCredential, } from "./credentials.js";
7
+ export type { RelayCredential, RelayCredentialResolver, } from "./credentials.js";
8
+ export { RELAY_MAX_ATTACHMENT_BYTES, RELAY_MAX_MESSAGE_PARTS, RELAY_MAX_TEXT_PART_LENGTH, } from "./content.js";
9
+ export { fromRelayReaction, toRelayReaction, } from "./reactions.js";
10
+ export type { RelayReactionInput } from "./reactions.js";
11
+ export { decodeWebhookSecret, verifyWebhookSignature, WebhookSecretError, WebhookVerificationError, } from "./signature.js";
12
+ export type { VerifyWebhookSignatureOptions } from "./signature.js";
13
+ export { assertRelayUuid, decodeRelayThreadId, encodeRelayThreadId, isRelayUuid, relayChannelIdFromThreadId, RELAY_THREAD_PREFIX, } from "./thread-id.js";
14
+ export { inboundIdempotencyKey } from "./turn.js";
15
+ export { RELAY_API_VERSION, RELAY_WEBHOOK_EVENT_TYPES, RELAY_WEBHOOK_VERSION, } from "./types.js";
16
+ export type * from "./types.js";
17
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kBAAkB,EAClB,kBAAkB,EAClB,YAAY,GACb,MAAM,cAAc,CAAC;AACtB,YAAY,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AACxD,YAAY,EACV,0BAA0B,EAC1B,2BAA2B,GAC5B,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,sBAAsB,EACtB,aAAa,EACb,WAAW,GACZ,MAAM,aAAa,CAAC;AACrB,YAAY,EACV,kBAAkB,EAClB,kBAAkB,GACnB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,QAAQ,EACR,sBAAsB,EACtB,wBAAwB,GACzB,MAAM,kBAAkB,CAAC;AAC1B,YAAY,EACV,eAAe,EACf,uBAAuB,GACxB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACL,0BAA0B,EAC1B,uBAAuB,EACvB,0BAA0B,GAC3B,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,iBAAiB,EACjB,eAAe,GAChB,MAAM,gBAAgB,CAAC;AACxB,YAAY,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACzD,OAAO,EACL,mBAAmB,EACnB,sBAAsB,EACtB,kBAAkB,EAClB,wBAAwB,GACzB,MAAM,gBAAgB,CAAC;AACxB,YAAY,EAAE,6BAA6B,EAAE,MAAM,gBAAgB,CAAC;AACpE,OAAO,EACL,eAAe,EACf,mBAAmB,EACnB,mBAAmB,EACnB,WAAW,EACX,0BAA0B,EAC1B,mBAAmB,GACpB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,qBAAqB,EAAE,MAAM,WAAW,CAAC;AAClD,OAAO,EACL,iBAAiB,EACjB,yBAAyB,EACzB,qBAAqB,GACtB,MAAM,YAAY,CAAC;AACpB,mBAAmB,YAAY,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,10 @@
1
+ export { createRelayAdapter, RELAY_ADAPTER_NAME, RelayAdapter, } from "./adapter.js";
2
+ export { RELAY_DEFAULT_BASE_URL, RelayApiError, RelayClient, } from "./client.js";
3
+ export { relayEnv, resolveRelayCredential, validateStaticCredential, } from "./credentials.js";
4
+ export { RELAY_MAX_ATTACHMENT_BYTES, RELAY_MAX_MESSAGE_PARTS, RELAY_MAX_TEXT_PART_LENGTH, } from "./content.js";
5
+ export { fromRelayReaction, toRelayReaction, } from "./reactions.js";
6
+ export { decodeWebhookSecret, verifyWebhookSignature, WebhookSecretError, WebhookVerificationError, } from "./signature.js";
7
+ export { assertRelayUuid, decodeRelayThreadId, encodeRelayThreadId, isRelayUuid, relayChannelIdFromThreadId, RELAY_THREAD_PREFIX, } from "./thread-id.js";
8
+ export { inboundIdempotencyKey } from "./turn.js";
9
+ export { RELAY_API_VERSION, RELAY_WEBHOOK_EVENT_TYPES, RELAY_WEBHOOK_VERSION, } from "./types.js";
10
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kBAAkB,EAClB,kBAAkB,EAClB,YAAY,GACb,MAAM,cAAc,CAAC;AAMtB,OAAO,EACL,sBAAsB,EACtB,aAAa,EACb,WAAW,GACZ,MAAM,aAAa,CAAC;AAKrB,OAAO,EACL,QAAQ,EACR,sBAAsB,EACtB,wBAAwB,GACzB,MAAM,kBAAkB,CAAC;AAK1B,OAAO,EACL,0BAA0B,EAC1B,uBAAuB,EACvB,0BAA0B,GAC3B,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,iBAAiB,EACjB,eAAe,GAChB,MAAM,gBAAgB,CAAC;AAExB,OAAO,EACL,mBAAmB,EACnB,sBAAsB,EACtB,kBAAkB,EAClB,wBAAwB,GACzB,MAAM,gBAAgB,CAAC;AAExB,OAAO,EACL,eAAe,EACf,mBAAmB,EACnB,mBAAmB,EACnB,WAAW,EACX,0BAA0B,EAC1B,mBAAmB,GACpB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,qBAAqB,EAAE,MAAM,WAAW,CAAC;AAClD,OAAO,EACL,iBAAiB,EACjB,yBAAyB,EACzB,qBAAqB,GACtB,MAAM,YAAY,CAAC"}
@@ -0,0 +1,15 @@
1
+ import { type EmojiValue } from "chat";
2
+ import type { RelayReactionType } from "./types.js";
3
+ export interface RelayReactionInput {
4
+ customEmoji?: string;
5
+ type: RelayReactionType;
6
+ }
7
+ export declare function toRelayReaction(input: EmojiValue | string): RelayReactionInput;
8
+ export declare function fromRelayReaction(input: {
9
+ customEmoji?: string | null;
10
+ type: RelayReactionType;
11
+ }): {
12
+ emoji: EmojiValue;
13
+ rawEmoji: string;
14
+ };
15
+ //# sourceMappingURL=reactions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reactions.d.ts","sourceRoot":"","sources":["../src/reactions.ts"],"names":[],"mappings":"AACA,OAAO,EAGL,KAAK,UAAU,EAChB,MAAM,MAAM,CAAC;AACd,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAEpD,MAAM,WAAW,kBAAkB;IACjC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,iBAAiB,CAAC;CACzB;AAoCD,wBAAgB,eAAe,CAC7B,KAAK,EAAE,UAAU,GAAG,MAAM,GACzB,kBAAkB,CAkBpB;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE;IACvC,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,IAAI,EAAE,iBAAiB,CAAC;CACzB,GAAG;IAAE,KAAK,EAAE,UAAU,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAkB1C"}
@@ -0,0 +1,58 @@
1
+ import { ValidationError } from "@chat-adapter/shared";
2
+ import { defaultEmojiResolver, getEmoji, } from "chat";
3
+ const STANDARD_BY_NAME = {
4
+ exclamation: "emphasize",
5
+ heart: "love",
6
+ laugh: "laugh",
7
+ question: "question",
8
+ thumbs_down: "dislike",
9
+ thumbs_up: "like",
10
+ };
11
+ const NAME_BY_STANDARD = {
12
+ dislike: "thumbs_down",
13
+ emphasize: "exclamation",
14
+ laugh: "laugh",
15
+ like: "thumbs_up",
16
+ love: "heart",
17
+ question: "question",
18
+ };
19
+ function normalizeName(input) {
20
+ const placeholder = /^\{\{emoji:([^}]+)\}\}$/.exec(input.trim());
21
+ const shortcode = /^:([^:]+):$/.exec(input.trim());
22
+ return (placeholder?.[1] ?? shortcode?.[1] ?? input.trim()).toLowerCase();
23
+ }
24
+ function looksLikeUnicodeEmoji(value) {
25
+ return (/\p{Extended_Pictographic}/u.test(value) ||
26
+ /\p{Regional_Indicator}{2}/u.test(value));
27
+ }
28
+ export function toRelayReaction(input) {
29
+ const raw = typeof input === "string" ? input.trim() : input.name;
30
+ const normalized = normalizeName(raw);
31
+ const standard = STANDARD_BY_NAME[normalized];
32
+ if (standard)
33
+ return { type: standard };
34
+ const literal = looksLikeUnicodeEmoji(raw)
35
+ ? raw
36
+ : defaultEmojiResolver.toGChat(normalized);
37
+ if (!looksLikeUnicodeEmoji(literal)) {
38
+ throw new ValidationError("relay", `Relay custom reactions require a Unicode emoji; received ${JSON.stringify(raw)}`);
39
+ }
40
+ return { customEmoji: literal, type: "custom" };
41
+ }
42
+ export function fromRelayReaction(input) {
43
+ if (input.type === "custom") {
44
+ if (!input.customEmoji) {
45
+ throw new ValidationError("relay", "A custom Relay reaction event is missing custom_emoji");
46
+ }
47
+ return {
48
+ emoji: defaultEmojiResolver.fromGChat(input.customEmoji),
49
+ rawEmoji: input.customEmoji,
50
+ };
51
+ }
52
+ const name = NAME_BY_STANDARD[input.type];
53
+ return {
54
+ emoji: getEmoji(name),
55
+ rawEmoji: defaultEmojiResolver.toGChat(name),
56
+ };
57
+ }
58
+ //# sourceMappingURL=reactions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reactions.js","sourceRoot":"","sources":["../src/reactions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EACL,oBAAoB,EACpB,QAAQ,GAET,MAAM,MAAM,CAAC;AAQd,MAAM,gBAAgB,GAAsC;IAC1D,WAAW,EAAE,WAAW;IACxB,KAAK,EAAE,MAAM;IACb,KAAK,EAAE,OAAO;IACd,QAAQ,EAAE,UAAU;IACpB,WAAW,EAAE,SAAS;IACtB,SAAS,EAAE,MAAM;CAClB,CAAC;AAEF,MAAM,gBAAgB,GAGlB;IACF,OAAO,EAAE,aAAa;IACtB,SAAS,EAAE,aAAa;IACxB,KAAK,EAAE,OAAO;IACd,IAAI,EAAE,WAAW;IACjB,IAAI,EAAE,OAAO;IACb,QAAQ,EAAE,UAAU;CACrB,CAAC;AAEF,SAAS,aAAa,CAAC,KAAa;IAClC,MAAM,WAAW,GAAG,yBAAyB,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;IACjE,MAAM,SAAS,GAAG,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;IACnD,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,IAAI,SAAS,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC;AAC5E,CAAC;AAED,SAAS,qBAAqB,CAAC,KAAa;IAC1C,OAAO,CACL,4BAA4B,CAAC,IAAI,CAAC,KAAK,CAAC;QACxC,4BAA4B,CAAC,IAAI,CAAC,KAAK,CAAC,CACzC,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,eAAe,CAC7B,KAA0B;IAE1B,MAAM,GAAG,GAAG,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC;IAClE,MAAM,UAAU,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC;IACtC,MAAM,QAAQ,GAAG,gBAAgB,CAAC,UAAU,CAAC,CAAC;IAC9C,IAAI,QAAQ;QAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;IAExC,MAAM,OAAO,GAAG,qBAAqB,CAAC,GAAG,CAAC;QACxC,CAAC,CAAC,GAAG;QACL,CAAC,CAAC,oBAAoB,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IAC7C,IAAI,CAAC,qBAAqB,CAAC,OAAO,CAAC,EAAE,CAAC;QACpC,MAAM,IAAI,eAAe,CACvB,OAAO,EACP,4DAA4D,IAAI,CAAC,SAAS,CACxE,GAAG,CACJ,EAAE,CACJ,CAAC;IACJ,CAAC;IACD,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;AAClD,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,KAGjC;IACC,IAAI,KAAK,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;QAC5B,IAAI,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC;YACvB,MAAM,IAAI,eAAe,CACvB,OAAO,EACP,uDAAuD,CACxD,CAAC;QACJ,CAAC;QACD,OAAO;YACL,KAAK,EAAE,oBAAoB,CAAC,SAAS,CAAC,KAAK,CAAC,WAAW,CAAC;YACxD,QAAQ,EAAE,KAAK,CAAC,WAAW;SAC5B,CAAC;IACJ,CAAC;IACD,MAAM,IAAI,GAAG,gBAAgB,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC1C,OAAO;QACL,KAAK,EAAE,QAAQ,CAAC,IAAI,CAAC;QACrB,QAAQ,EAAE,oBAAoB,CAAC,OAAO,CAAC,IAAI,CAAC;KAC7C,CAAC;AACJ,CAAC"}
@@ -0,0 +1,22 @@
1
+ import type { RelayCredential } from "./credentials.js";
2
+ export interface VerifyWebhookSignatureOptions {
3
+ nowSeconds?: number;
4
+ toleranceSeconds?: number;
5
+ }
6
+ export declare class WebhookSecretError extends Error {
7
+ constructor(message: string);
8
+ }
9
+ export declare class WebhookVerificationError extends Error {
10
+ constructor(message: string);
11
+ }
12
+ export declare function decodeWebhookSecret(secret: string): Uint8Array<ArrayBuffer>;
13
+ /**
14
+ * Verify Relay's current Standard Webhooks v1 signature over the exact body.
15
+ */
16
+ export declare function verifyWebhookSignature(input: {
17
+ headers: Pick<Headers, "get">;
18
+ payload: string;
19
+ secret: RelayCredential;
20
+ options?: VerifyWebhookSignatureOptions;
21
+ }): Promise<void>;
22
+ //# sourceMappingURL=signature.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"signature.d.ts","sourceRoot":"","sources":["../src/signature.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAGxD,MAAM,WAAW,6BAA6B;IAC5C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,qBAAa,kBAAmB,SAAQ,KAAK;IAC3C,YAAY,OAAO,EAAE,MAAM,EAG1B;CACF;AAED,qBAAa,wBAAyB,SAAQ,KAAK;IACjD,YAAY,OAAO,EAAE,MAAM,EAG1B;CACF;AA0BD,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,MAAM,GACb,UAAU,CAAC,WAAW,CAAC,CAWzB;AAWD;;GAEG;AACH,wBAAsB,sBAAsB,CAAC,KAAK,EAAE;IAClD,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,eAAe,CAAC;IACxB,OAAO,CAAC,EAAE,6BAA6B,CAAC;CACzC,GAAG,OAAO,CAAC,IAAI,CAAC,CA+DhB"}
@@ -0,0 +1,98 @@
1
+ import { resolveRelayCredential } from "./credentials.js";
2
+ export class WebhookSecretError extends Error {
3
+ constructor(message) {
4
+ super(message);
5
+ this.name = "WebhookSecretError";
6
+ }
7
+ }
8
+ export class WebhookVerificationError extends Error {
9
+ constructor(message) {
10
+ super(message);
11
+ this.name = "WebhookVerificationError";
12
+ }
13
+ }
14
+ const DEFAULT_TOLERANCE_SECONDS = 5 * 60;
15
+ function decodeBase64(value) {
16
+ const normalized = value.trim();
17
+ if (!normalized ||
18
+ normalized.length % 4 === 1 ||
19
+ !/^[A-Za-z0-9+/]*={0,2}$/.test(normalized)) {
20
+ throw new WebhookSecretError("value is not valid base64");
21
+ }
22
+ try {
23
+ const binary = atob(normalized);
24
+ if (!binary)
25
+ throw new Error("empty");
26
+ const bytes = new Uint8Array(binary.length);
27
+ for (let index = 0; index < binary.length; index += 1) {
28
+ bytes[index] = binary.charCodeAt(index);
29
+ }
30
+ return bytes;
31
+ }
32
+ catch {
33
+ throw new WebhookSecretError("value is not valid base64");
34
+ }
35
+ }
36
+ export function decodeWebhookSecret(secret) {
37
+ const encoded = secret.startsWith("whsec_")
38
+ ? secret.slice("whsec_".length)
39
+ : secret;
40
+ try {
41
+ return decodeBase64(encoded);
42
+ }
43
+ catch {
44
+ throw new WebhookSecretError("Relay webhookSecret must be the base64 whsec_ value Relay issued");
45
+ }
46
+ }
47
+ function constantTimeEqual(left, right) {
48
+ if (left.length !== right.length)
49
+ return false;
50
+ let difference = 0;
51
+ for (let index = 0; index < left.length; index += 1) {
52
+ difference |= left[index] ^ right[index];
53
+ }
54
+ return difference === 0;
55
+ }
56
+ /**
57
+ * Verify Relay's current Standard Webhooks v1 signature over the exact body.
58
+ */
59
+ export async function verifyWebhookSignature(input) {
60
+ const id = input.headers.get("webhook-id");
61
+ const timestamp = input.headers.get("webhook-timestamp");
62
+ const signatures = input.headers.get("webhook-signature");
63
+ if (!id || !timestamp || !signatures) {
64
+ throw new WebhookVerificationError("missing Standard Webhooks signature headers");
65
+ }
66
+ const parsedTimestamp = Number(timestamp);
67
+ if (!Number.isSafeInteger(parsedTimestamp) ||
68
+ parsedTimestamp < 0) {
69
+ throw new WebhookVerificationError("invalid webhook-timestamp");
70
+ }
71
+ const now = input.options?.nowSeconds ?? Math.floor(Date.now() / 1_000);
72
+ const tolerance = input.options?.toleranceSeconds ?? DEFAULT_TOLERANCE_SECONDS;
73
+ if (!Number.isFinite(tolerance) ||
74
+ tolerance < 0 ||
75
+ Math.abs(now - parsedTimestamp) > tolerance) {
76
+ throw new WebhookVerificationError("webhook-timestamp outside tolerance");
77
+ }
78
+ const secret = await resolveRelayCredential(input.secret, "Relay webhook signing secret");
79
+ const key = await crypto.subtle.importKey("raw", decodeWebhookSecret(secret), { hash: "SHA-256", name: "HMAC" }, false, ["sign"]);
80
+ const content = `${id}.${timestamp}.${input.payload}`;
81
+ const expected = new Uint8Array(await crypto.subtle.sign("HMAC", key, new TextEncoder().encode(content)));
82
+ for (const candidate of signatures.split(/\s+/)) {
83
+ const [version, encoded] = candidate.split(",", 2);
84
+ if (version !== "v1" || !encoded)
85
+ continue;
86
+ let provided;
87
+ try {
88
+ provided = decodeBase64(encoded);
89
+ }
90
+ catch {
91
+ continue;
92
+ }
93
+ if (constantTimeEqual(expected, provided))
94
+ return;
95
+ }
96
+ throw new WebhookVerificationError("no matching v1 signature");
97
+ }
98
+ //# sourceMappingURL=signature.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"signature.js","sourceRoot":"","sources":["../src/signature.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ import type { RelayThreadId } from "./types.js";
2
+ export declare const RELAY_THREAD_PREFIX = "relay:";
3
+ export declare function isRelayUuid(value: string): boolean;
4
+ export declare function assertRelayUuid(value: string, label: string): void;
5
+ export declare function encodeRelayThreadId(data: RelayThreadId): string;
6
+ export declare function decodeRelayThreadId(threadId: string): RelayThreadId;
7
+ export declare function relayChannelIdFromThreadId(threadId: string): string;
8
+ //# sourceMappingURL=thread-id.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"thread-id.d.ts","sourceRoot":"","sources":["../src/thread-id.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEhD,eAAO,MAAM,mBAAmB,WAAW,CAAC;AAK5C,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAElD;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAOlE;AAED,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,aAAa,GAAG,MAAM,CAG/D;AAED,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,aAAa,CAUnE;AAED,wBAAgB,0BAA0B,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAEnE"}
@@ -0,0 +1,27 @@
1
+ import { ValidationError } from "@chat-adapter/shared";
2
+ export const RELAY_THREAD_PREFIX = "relay:";
3
+ const UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
4
+ export function isRelayUuid(value) {
5
+ return UUID.test(value);
6
+ }
7
+ export function assertRelayUuid(value, label) {
8
+ if (!isRelayUuid(value)) {
9
+ throw new ValidationError("relay", `${label} must be a Relay UUID; received ${JSON.stringify(value)}`);
10
+ }
11
+ }
12
+ export function encodeRelayThreadId(data) {
13
+ assertRelayUuid(data.chatId, "chatId");
14
+ return `${RELAY_THREAD_PREFIX}${data.chatId}`;
15
+ }
16
+ export function decodeRelayThreadId(threadId) {
17
+ if (!threadId.startsWith(RELAY_THREAD_PREFIX)) {
18
+ throw new ValidationError("relay", `not a Relay thread ID: ${JSON.stringify(threadId)}`);
19
+ }
20
+ const chatId = threadId.slice(RELAY_THREAD_PREFIX.length);
21
+ assertRelayUuid(chatId, "Relay thread chat ID");
22
+ return { chatId };
23
+ }
24
+ export function relayChannelIdFromThreadId(threadId) {
25
+ return encodeRelayThreadId(decodeRelayThreadId(threadId));
26
+ }
27
+ //# sourceMappingURL=thread-id.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"thread-id.js","sourceRoot":"","sources":["../src/thread-id.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAGvD,MAAM,CAAC,MAAM,mBAAmB,GAAG,QAAQ,CAAC;AAE5C,MAAM,IAAI,GACR,iEAAiE,CAAC;AAEpE,MAAM,UAAU,WAAW,CAAC,KAAa;IACvC,OAAO,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AAC1B,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,KAAa,EAAE,KAAa;IAC1D,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,EAAE,CAAC;QACxB,MAAM,IAAI,eAAe,CACvB,OAAO,EACP,GAAG,KAAK,mCAAmC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CACnE,CAAC;IACJ,CAAC;AACH,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,IAAmB;IACrD,eAAe,CAAC,IAAI,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IACvC,OAAO,GAAG,mBAAmB,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC;AAChD,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,QAAgB;IAClD,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,mBAAmB,CAAC,EAAE,CAAC;QAC9C,MAAM,IAAI,eAAe,CACvB,OAAO,EACP,0BAA0B,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,EAAE,CACrD,CAAC;IACJ,CAAC;IACD,MAAM,MAAM,GAAG,QAAQ,CAAC,KAAK,CAAC,mBAAmB,CAAC,MAAM,CAAC,CAAC;IAC1D,eAAe,CAAC,MAAM,EAAE,sBAAsB,CAAC,CAAC;IAChD,OAAO,EAAE,MAAM,EAAE,CAAC;AACpB,CAAC;AAED,MAAM,UAAU,0BAA0B,CAAC,QAAgB;IACzD,OAAO,mBAAmB,CAAC,mBAAmB,CAAC,QAAQ,CAAC,CAAC,CAAC;AAC5D,CAAC"}
package/dist/turn.d.ts ADDED
@@ -0,0 +1,16 @@
1
+ export interface RelayTurn {
2
+ readonly eventId: string;
3
+ sent: number;
4
+ tail: Promise<void>;
5
+ }
6
+ /**
7
+ * Request-local transport context. It is never persisted and owns no delivery
8
+ * record; it only makes Relay's Idempotency-Key stable for a redelivered event.
9
+ */
10
+ export declare class RelayTurnContext {
11
+ private readonly storage;
12
+ run<T>(eventId: string, callback: () => T): T;
13
+ active(): RelayTurn | undefined;
14
+ }
15
+ export declare function inboundIdempotencyKey(eventId: string, ordinal: number): string;
16
+ //# sourceMappingURL=turn.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"turn.d.ts","sourceRoot":"","sources":["../src/turn.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;CACrB;AAED;;;GAGG;AACH,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAsC;IAE9D,GAAG,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,CAAC,GAAG,CAAC,CAS5C;IAED,MAAM,IAAI,SAAS,GAAG,SAAS,CAE9B;CACF;AAED,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,GACd,MAAM,CAER"}
package/dist/turn.js ADDED
@@ -0,0 +1,22 @@
1
+ import { AsyncLocalStorage } from "node:async_hooks";
2
+ /**
3
+ * Request-local transport context. It is never persisted and owns no delivery
4
+ * record; it only makes Relay's Idempotency-Key stable for a redelivered event.
5
+ */
6
+ export class RelayTurnContext {
7
+ storage = new AsyncLocalStorage();
8
+ run(eventId, callback) {
9
+ return this.storage.run({
10
+ eventId,
11
+ sent: 0,
12
+ tail: Promise.resolve(),
13
+ }, callback);
14
+ }
15
+ active() {
16
+ return this.storage.getStore();
17
+ }
18
+ }
19
+ export function inboundIdempotencyKey(eventId, ordinal) {
20
+ return `relay-chat-sdk:${eventId}:${ordinal}`;
21
+ }
22
+ //# sourceMappingURL=turn.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"turn.js","sourceRoot":"","sources":["../src/turn.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAQrD;;;GAGG;AACH,MAAM,OAAO,gBAAgB;IACV,OAAO,GAAG,IAAI,iBAAiB,EAAa,CAAC;IAE9D,GAAG,CAAI,OAAe,EAAE,QAAiB;QACvC,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CACrB;YACE,OAAO;YACP,IAAI,EAAE,CAAC;YACP,IAAI,EAAE,OAAO,CAAC,OAAO,EAAE;SACxB,EACD,QAAQ,CACT,CAAC;IACJ,CAAC;IAED,MAAM;QACJ,OAAO,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC;IACjC,CAAC;CACF;AAED,MAAM,UAAU,qBAAqB,CACnC,OAAe,EACf,OAAe;IAEf,OAAO,kBAAkB,OAAO,IAAI,OAAO,EAAE,CAAC;AAChD,CAAC"}
@@ -0,0 +1,193 @@
1
+ /**
2
+ * Relay v1 wire types used by this adapter.
3
+ *
4
+ * Contract source:
5
+ * Relay Server 9b4d5bb32cc749c6fd271969948c385300d404d6
6
+ * OpenAPI f62f431fc0daa48500926bf87753f81c3fdda25ab463b130ca97f2896367e0a5
7
+ */
8
+ export declare const RELAY_API_VERSION: "v1";
9
+ export declare const RELAY_WEBHOOK_VERSION: "2026-08-30";
10
+ export declare const RELAY_WEBHOOK_EVENT_TYPES: readonly ["message.sent", "message.received", "message.read", "message.delivered", "reaction.added", "reaction.removed", "participant.added", "participant.removed", "chat.created", "chat.group_name_updated", "chat.group_icon_updated", "chat.typing_indicator.started", "chat.typing_indicator.stopped", "contact.added", "contact.removed"];
11
+ export type RelayWebhookEventType = (typeof RELAY_WEBHOOK_EVENT_TYPES)[number];
12
+ export interface RelayWebhookEnvelope<TData = Record<string, unknown>> {
13
+ agent_id: string;
14
+ api_version: typeof RELAY_API_VERSION;
15
+ created_at: string;
16
+ data: TData;
17
+ event_id: string;
18
+ event_type: RelayWebhookEventType;
19
+ trace_id: string;
20
+ webhook_version: typeof RELAY_WEBHOOK_VERSION;
21
+ }
22
+ export interface RelayChatHandle {
23
+ avatar_url: string | null;
24
+ display_name: string | null;
25
+ handle: string;
26
+ id: string;
27
+ is_me?: boolean | null;
28
+ joined_at: string;
29
+ kind: "user" | "agent";
30
+ left_at?: string | null;
31
+ status?: "active" | "left" | "removed" | null;
32
+ tagline: string | null;
33
+ verified: boolean;
34
+ }
35
+ export type RelayReactionType = "love" | "like" | "dislike" | "laugh" | "emphasize" | "question" | "custom";
36
+ export interface RelayReaction {
37
+ custom_emoji?: string | null;
38
+ handle: RelayChatHandle;
39
+ is_me: boolean;
40
+ type: RelayReactionType;
41
+ }
42
+ export interface RelayTextPart {
43
+ mention?: string | null;
44
+ mention_range?: [number, number] | null;
45
+ type: "text";
46
+ value: string;
47
+ }
48
+ export interface RelayMediaPart {
49
+ attachment_id?: string;
50
+ type: "media";
51
+ url?: string;
52
+ }
53
+ export interface RelayLinkPart {
54
+ type: "link";
55
+ value: string;
56
+ }
57
+ export type RelayOutgoingPart = RelayTextPart | RelayMediaPart | RelayLinkPart;
58
+ export interface RelayTextPartResponse extends RelayTextPart {
59
+ reactions?: RelayReaction[] | null;
60
+ }
61
+ export interface RelayMediaPartResponse {
62
+ duration_ms?: number | null;
63
+ filename: string;
64
+ height?: number | null;
65
+ id: string;
66
+ mime_type: string;
67
+ reactions?: RelayReaction[] | null;
68
+ size_bytes: number;
69
+ type: "media";
70
+ url: string;
71
+ width?: number | null;
72
+ }
73
+ export interface RelayLinkPartResponse extends RelayLinkPart {
74
+ reactions?: RelayReaction[] | null;
75
+ }
76
+ export interface RelaySystemPartResponse {
77
+ reactions?: RelayReaction[] | null;
78
+ type: "system";
79
+ value: string;
80
+ }
81
+ export type RelayMessagePartResponse = RelayTextPartResponse | RelayMediaPartResponse | RelayLinkPartResponse | RelaySystemPartResponse;
82
+ export interface RelayReplyTo {
83
+ message_id: string;
84
+ part_index?: number;
85
+ }
86
+ export interface RelayMessage {
87
+ chat_id: string;
88
+ created_at: string;
89
+ delivered_at?: string | null;
90
+ delivery_status: "sent" | "delivered" | "read";
91
+ from?: string | null;
92
+ from_handle?: RelayChatHandle | null;
93
+ id: string;
94
+ is_from_me: boolean;
95
+ is_system_message: boolean;
96
+ parts?: RelayMessagePartResponse[] | null;
97
+ read_at?: string | null;
98
+ reply_to?: RelayReplyTo | null;
99
+ sent_at?: string | null;
100
+ system_event?: Record<string, unknown> | null;
101
+ updated_at: string;
102
+ }
103
+ export interface RelayWebhookMessageEvent {
104
+ chat: {
105
+ id: string;
106
+ is_group?: boolean | null;
107
+ owner_handle?: RelayChatHandle | null;
108
+ };
109
+ delivered_at?: string | null;
110
+ direction: "inbound" | "outbound";
111
+ id: string;
112
+ idempotency_key?: string | null;
113
+ parts: Array<RelayTextPartResponse | RelayMediaPartResponse | RelayLinkPartResponse>;
114
+ read_at?: string | null;
115
+ reply_to?: RelayReplyTo | null;
116
+ sender_handle: RelayChatHandle;
117
+ sent_at?: string | null;
118
+ }
119
+ export interface RelaySentMessage {
120
+ created_at: string;
121
+ delivered_at?: string | null;
122
+ delivery_status: "sent" | "delivered" | "read";
123
+ from_handle?: RelayChatHandle | null;
124
+ id: string;
125
+ parts: Array<RelayTextPartResponse | RelayMediaPartResponse | RelayLinkPartResponse>;
126
+ reply_to?: RelayReplyTo | null;
127
+ sent_at: string | null;
128
+ }
129
+ export interface RelaySendMessageResponse {
130
+ chat_id: string;
131
+ message: RelaySentMessage;
132
+ }
133
+ export interface RelayGetMessagesResult {
134
+ messages: RelayMessage[];
135
+ next_cursor?: string | null;
136
+ }
137
+ export interface RelayChat {
138
+ created_at: string;
139
+ display_name: string | null;
140
+ group_chat_icon?: string | null;
141
+ handles: RelayChatHandle[];
142
+ id: string;
143
+ is_group: boolean;
144
+ updated_at: string;
145
+ }
146
+ export interface RelayReactionEvent {
147
+ chat_id: string;
148
+ custom_emoji?: string | null;
149
+ from_handle: RelayChatHandle;
150
+ is_from_me: boolean;
151
+ message_id: string;
152
+ part_index: number;
153
+ reacted_at: string;
154
+ reaction_type: RelayReactionType;
155
+ }
156
+ /**
157
+ * `GET /v1/attachments/{attachmentId}` metadata. `download_url` is optional in
158
+ * the locked v1 contract, so a caller must handle its absence.
159
+ */
160
+ export interface RelayAttachment {
161
+ content_type: string;
162
+ created_at: string;
163
+ download_url?: string;
164
+ duration_ms?: number | null;
165
+ filename: string;
166
+ height?: number | null;
167
+ id: string;
168
+ size_bytes: number;
169
+ status: "pending" | "complete" | "failed";
170
+ width?: number | null;
171
+ }
172
+ export interface RelayAttachmentAllocation {
173
+ attachment_id: string;
174
+ download_url: string;
175
+ expires_at: string;
176
+ http_method: "PUT";
177
+ required_headers: Record<string, string>;
178
+ upload_url: string;
179
+ }
180
+ export interface RelayRawMessage {
181
+ chatId: string;
182
+ createdAt?: string;
183
+ eventId?: string;
184
+ eventType?: RelayWebhookEventType;
185
+ message: RelayMessage | RelaySentMessage | RelayWebhookMessageEvent | null;
186
+ /** Synthetic Chat SDK result for an intentionally empty no-op post. */
187
+ noop?: true;
188
+ }
189
+ /** Platform data encoded by `relay:<chat UUID>`. */
190
+ export interface RelayThreadId {
191
+ chatId: string;
192
+ }
193
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,eAAO,MAAM,iBAAiB,EAAG,IAAa,CAAC;AAC/C,eAAO,MAAM,qBAAqB,EAAG,YAAqB,CAAC;AAE3D,eAAO,MAAM,yBAAyB,YACpC,cAAc,EACd,kBAAkB,EAClB,cAAc,EACd,mBAAmB,EACnB,gBAAgB,EAChB,kBAAkB,EAClB,mBAAmB,EACnB,qBAAqB,EACrB,cAAc,EACd,yBAAyB,EACzB,yBAAyB,EACzB,+BAA+B,EAC/B,+BAA+B,EAC/B,eAAe,EACf,iBAAiB,CACT,CAAC;AAEX,MAAM,MAAM,qBAAqB,GAC/B,CAAC,OAAO,yBAAyB,CAAC,CAAC,MAAM,CAAC,CAAC;AAE7C,MAAM,WAAW,oBAAoB,CAAC,KAAK,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IACnE,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,OAAO,iBAAiB,CAAC;IACtC,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,KAAK,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,qBAAqB,CAAC;IAClC,QAAQ,EAAE,MAAM,CAAC;IACjB,eAAe,EAAE,OAAO,qBAAqB,CAAC;CAC/C;AAED,MAAM,WAAW,eAAe;IAC9B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;IACvB,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,MAAM,CAAC,EAAE,QAAQ,GAAG,MAAM,GAAG,SAAS,GAAG,IAAI,CAAC;IAC9C,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,MAAM,iBAAiB,GACzB,MAAM,GACN,MAAM,GACN,SAAS,GACT,OAAO,GACP,WAAW,GACX,UAAU,GACV,QAAQ,CAAC;AAEb,MAAM,WAAW,aAAa;IAC5B,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,MAAM,EAAE,eAAe,CAAC;IACxB,KAAK,EAAE,OAAO,CAAC;IACf,IAAI,EAAE,iBAAiB,CAAC;CACzB;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,aAAa,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,CAAC;IACxC,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,cAAc;IAC7B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,IAAI,EAAE,OAAO,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,MAAM,iBAAiB,GACzB,aAAa,GACb,cAAc,GACd,aAAa,CAAC;AAElB,MAAM,WAAW,qBAAsB,SAAQ,aAAa;IAC1D,SAAS,CAAC,EAAE,aAAa,EAAE,GAAG,IAAI,CAAC;CACpC;AAED,MAAM,WAAW,sBAAsB;IACrC,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,aAAa,EAAE,GAAG,IAAI,CAAC;IACnC,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,OAAO,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB;AAED,MAAM,WAAW,qBAAsB,SAAQ,aAAa;IAC1D,SAAS,CAAC,EAAE,aAAa,EAAE,GAAG,IAAI,CAAC;CACpC;AAED,MAAM,WAAW,uBAAuB;IACtC,SAAS,CAAC,EAAE,aAAa,EAAE,GAAG,IAAI,CAAC;IACnC,IAAI,EAAE,QAAQ,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,MAAM,wBAAwB,GAChC,qBAAqB,GACrB,sBAAsB,GACtB,qBAAqB,GACrB,uBAAuB,CAAC;AAE5B,MAAM,WAAW,YAAY;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,eAAe,EAAE,MAAM,GAAG,WAAW,GAAG,MAAM,CAAC;IAC/C,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,WAAW,CAAC,EAAE,eAAe,GAAG,IAAI,CAAC;IACrC,EAAE,EAAE,MAAM,CAAC;IACX,UAAU,EAAE,OAAO,CAAC;IACpB,iBAAiB,EAAE,OAAO,CAAC;IAC3B,KAAK,CAAC,EAAE,wBAAwB,EAAE,GAAG,IAAI,CAAC;IAC1C,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,QAAQ,CAAC,EAAE,YAAY,GAAG,IAAI,CAAC;IAC/B,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAC9C,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,wBAAwB;IACvC,IAAI,EAAE;QACJ,EAAE,EAAE,MAAM,CAAC;QACX,QAAQ,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;QAC1B,YAAY,CAAC,EAAE,eAAe,GAAG,IAAI,CAAC;KACvC,CAAC;IACF,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,SAAS,EAAE,SAAS,GAAG,UAAU,CAAC;IAClC,EAAE,EAAE,MAAM,CAAC;IACX,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,KAAK,EAAE,KAAK,CACV,qBAAqB,GAAG,sBAAsB,GAAG,qBAAqB,CACvE,CAAC;IACF,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,QAAQ,CAAC,EAAE,YAAY,GAAG,IAAI,CAAC;IAC/B,aAAa,EAAE,eAAe,CAAC;IAC/B,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB;AAED,MAAM,WAAW,gBAAgB;IAC/B,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,eAAe,EAAE,MAAM,GAAG,WAAW,GAAG,MAAM,CAAC;IAC/C,WAAW,CAAC,EAAE,eAAe,GAAG,IAAI,CAAC;IACrC,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,KAAK,CACV,qBAAqB,GAAG,sBAAsB,GAAG,qBAAqB,CACvE,CAAC;IACF,QAAQ,CAAC,EAAE,YAAY,GAAG,IAAI,CAAC;IAC/B,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CACxB;AAED,MAAM,WAAW,wBAAwB;IACvC,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,gBAAgB,CAAC;CAC3B;AAED,MAAM,WAAW,sBAAsB;IACrC,QAAQ,EAAE,YAAY,EAAE,CAAC;IACzB,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7B;AAED,MAAM,WAAW,SAAS;IACxB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,OAAO,EAAE,eAAe,EAAE,CAAC;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,OAAO,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,WAAW,EAAE,eAAe,CAAC;IAC7B,UAAU,EAAE,OAAO,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,iBAAiB,CAAC;CAClC;AAED;;;GAGG;AACH,MAAM,WAAW,eAAe;IAC9B,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,SAAS,GAAG,UAAU,GAAG,QAAQ,CAAC;IAC1C,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB;AAED,MAAM,WAAW,yBAAyB;IACxC,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,KAAK,CAAC;IACnB,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACzC,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,qBAAqB,CAAC;IAClC,OAAO,EACH,YAAY,GACZ,gBAAgB,GAChB,wBAAwB,GACxB,IAAI,CAAC;IACT,uEAAuE;IACvE,IAAI,CAAC,EAAE,IAAI,CAAC;CACb;AAED,oDAAoD;AACpD,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAC;CAChB"}
package/dist/types.js ADDED
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Relay v1 wire types used by this adapter.
3
+ *
4
+ * Contract source:
5
+ * Relay Server 9b4d5bb32cc749c6fd271969948c385300d404d6
6
+ * OpenAPI f62f431fc0daa48500926bf87753f81c3fdda25ab463b130ca97f2896367e0a5
7
+ */
8
+ export const RELAY_API_VERSION = "v1";
9
+ export const RELAY_WEBHOOK_VERSION = "2026-08-30";
10
+ export const RELAY_WEBHOOK_EVENT_TYPES = [
11
+ "message.sent",
12
+ "message.received",
13
+ "message.read",
14
+ "message.delivered",
15
+ "reaction.added",
16
+ "reaction.removed",
17
+ "participant.added",
18
+ "participant.removed",
19
+ "chat.created",
20
+ "chat.group_name_updated",
21
+ "chat.group_icon_updated",
22
+ "chat.typing_indicator.started",
23
+ "chat.typing_indicator.stopped",
24
+ "contact.added",
25
+ "contact.removed",
26
+ ];
27
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,MAAM,CAAC,MAAM,iBAAiB,GAAG,IAAa,CAAC;AAC/C,MAAM,CAAC,MAAM,qBAAqB,GAAG,YAAqB,CAAC;AAE3D,MAAM,CAAC,MAAM,yBAAyB,GAAG;IACvC,cAAc;IACd,kBAAkB;IAClB,cAAc;IACd,mBAAmB;IACnB,gBAAgB;IAChB,kBAAkB;IAClB,mBAAmB;IACnB,qBAAqB;IACrB,cAAc;IACd,yBAAyB;IACzB,yBAAyB;IACzB,+BAA+B;IAC/B,+BAA+B;IAC/B,eAAe;IACf,iBAAiB;CACT,CAAC"}
@@ -0,0 +1,9 @@
1
+ import type { RelayReactionEvent, RelayWebhookEnvelope, RelayWebhookEventType, RelayWebhookMessageEvent } from "./types.js";
2
+ export declare const MAX_WEBHOOK_BODY_BYTES: number;
3
+ export declare function parseWebhookEnvelope(value: unknown): RelayWebhookEnvelope;
4
+ export declare function parseWebhookMessageEvent(data: Record<string, unknown>): RelayWebhookMessageEvent;
5
+ export declare function parseReactionEvent(data: Record<string, unknown>): RelayReactionEvent;
6
+ export declare function assertExhaustiveEvent(eventType: never): never;
7
+ export declare function readWebhookBody(request: Request): Promise<string>;
8
+ export declare function isMessageEventType(value: RelayWebhookEventType): value is "message.sent" | "message.received" | "message.read" | "message.delivered";
9
+ //# sourceMappingURL=webhook.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"webhook.d.ts","sourceRoot":"","sources":["../src/webhook.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,kBAAkB,EAClB,oBAAoB,EACpB,qBAAqB,EACrB,wBAAwB,EACzB,MAAM,YAAY,CAAC;AAYpB,eAAO,MAAM,sBAAsB,QAAgB,CAAC;AAiBpD,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,OAAO,GACb,oBAAoB,CA2BtB;AAYD,wBAAgB,wBAAwB,CACtC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC5B,wBAAwB,CAkB1B;AAED,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC5B,kBAAkB,CA4BpB;AAED,wBAAgB,qBAAqB,CACnC,SAAS,EAAE,KAAK,GACf,KAAK,CAEP;AAED,wBAAsB,eAAe,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAsBvE;AAED,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,qBAAqB,GAC3B,KAAK,IACJ,cAAc,GACd,kBAAkB,GAClB,cAAc,GACd,mBAAmB,CAEtB"}