@poncho-ai/messaging 0.2.8 → 0.3.0

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,18 @@
1
+ import { timingSafeEqual } from "node:crypto";
2
+
3
+ /**
4
+ * Verify the Telegram webhook secret token.
5
+ *
6
+ * When registering the webhook via `setWebhook`, a `secret_token` can be
7
+ * provided. Telegram then sends it in the `X-Telegram-Bot-Api-Secret-Token`
8
+ * header on every update. This function compares the expected and received
9
+ * values using timing-safe equality.
10
+ */
11
+ export const verifyTelegramSecret = (
12
+ expected: string,
13
+ received: string | undefined,
14
+ ): boolean => {
15
+ if (!received) return false;
16
+ if (expected.length !== received.length) return false;
17
+ return timingSafeEqual(Buffer.from(expected), Buffer.from(received));
18
+ };
package/src/bridge.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import { createHash } from "node:crypto";
1
2
  import type {
2
3
  AgentBridgeOptions,
3
4
  IncomingMessage,
@@ -7,13 +8,24 @@ import type {
7
8
  } from "./types.js";
8
9
 
9
10
  /**
10
- * Derive a stable conversation ID from a platform thread reference.
11
- * Format: `<platform>:<channelId>:<threadId>`
11
+ * Derive a deterministic UUID from a platform thread reference.
12
+ * SHA-256 hashes the composite key and formats 16 bytes as a UUID v4-shaped
13
+ * string, ensuring a valid UUID that's stable across requests for the same thread.
12
14
  */
13
15
  const conversationIdFromThread = (
14
16
  platform: string,
15
17
  ref: ThreadRef,
16
- ): string => `${platform}:${ref.channelId}:${ref.platformThreadId}`;
18
+ ): string => {
19
+ const key = `${platform}:${ref.channelId}:${ref.platformThreadId}`;
20
+ const hex = createHash("sha256").update(key).digest("hex").slice(0, 32);
21
+ return [
22
+ hex.slice(0, 8),
23
+ hex.slice(8, 12),
24
+ `4${hex.slice(13, 16)}`,
25
+ ((parseInt(hex.slice(16, 18), 16) & 0x3f) | 0x80).toString(16).padStart(2, "0") + hex.slice(18, 20),
26
+ hex.slice(20, 32),
27
+ ].join("-");
28
+ };
17
29
 
18
30
  export class AgentBridge {
19
31
  private readonly adapter: MessagingAdapter;
@@ -53,9 +65,11 @@ export class AgentBridge {
53
65
  message.threadRef,
54
66
  );
55
67
 
56
- const titleParts = [message.sender.id];
68
+ const platformTag = `[${message.platform.charAt(0).toUpperCase()}${message.platform.slice(1)}]`;
69
+ const senderLabel = message.sender.name || message.sender.id;
70
+ const titleParts = [platformTag, senderLabel];
57
71
  if (message.subject) titleParts.push(message.subject);
58
- const title = titleParts.join(" ") || `${message.platform} thread`;
72
+ const title = titleParts.join(" ") || `${message.platform} thread`;
59
73
 
60
74
  const conversation = await this.runner.getOrCreateConversation(
61
75
  conversationId,
package/src/index.ts CHANGED
@@ -15,6 +15,8 @@ export { SlackAdapter } from "./adapters/slack/index.js";
15
15
  export type { SlackAdapterOptions } from "./adapters/slack/index.js";
16
16
  export { ResendAdapter } from "./adapters/resend/index.js";
17
17
  export type { ResendAdapterOptions } from "./adapters/resend/index.js";
18
+ export { TelegramAdapter } from "./adapters/telegram/index.js";
19
+ export type { TelegramAdapterOptions } from "./adapters/telegram/index.js";
18
20
 
19
21
  export {
20
22
  buildReplyHeaders,