@openclaw/crabline 0.1.11 → 0.1.13

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 (214) hide show
  1. package/README.md +137 -23
  2. package/dist/src/bin/crabline.js +3 -1
  3. package/dist/src/bin/crabline.js.map +1 -1
  4. package/dist/src/cli/program.d.ts +5 -1
  5. package/dist/src/cli/program.js +281 -52
  6. package/dist/src/cli/program.js.map +1 -1
  7. package/dist/src/config/load.js +39 -3
  8. package/dist/src/config/load.js.map +1 -1
  9. package/dist/src/config/schema.d.ts +20 -0
  10. package/dist/src/config/schema.js +163 -35
  11. package/dist/src/config/schema.js.map +1 -1
  12. package/dist/src/core/errors.d.ts +1 -0
  13. package/dist/src/core/errors.js +6 -3
  14. package/dist/src/core/errors.js.map +1 -1
  15. package/dist/src/core/http-path.d.ts +1 -0
  16. package/dist/src/core/http-path.js +14 -0
  17. package/dist/src/core/http-path.js.map +1 -0
  18. package/dist/src/core/matcher.d.ts +3 -1
  19. package/dist/src/core/matcher.js +58 -2
  20. package/dist/src/core/matcher.js.map +1 -1
  21. package/dist/src/core/nonces.d.ts +2 -0
  22. package/dist/src/core/nonces.js +11 -1
  23. package/dist/src/core/nonces.js.map +1 -1
  24. package/dist/src/core/reporters.d.ts +5 -0
  25. package/dist/src/core/reporters.js +26 -2
  26. package/dist/src/core/reporters.js.map +1 -1
  27. package/dist/src/core/run.d.ts +3 -1
  28. package/dist/src/core/run.js +178 -66
  29. package/dist/src/core/run.js.map +1 -1
  30. package/dist/src/index.d.ts +12 -10
  31. package/dist/src/index.js +6 -5
  32. package/dist/src/index.js.map +1 -1
  33. package/dist/src/matrix-ids.d.ts +5 -0
  34. package/dist/src/matrix-ids.js +83 -0
  35. package/dist/src/matrix-ids.js.map +1 -0
  36. package/dist/src/openclaw/artifact-generation.d.ts +7 -6
  37. package/dist/src/openclaw/artifact-generation.js +385 -41
  38. package/dist/src/openclaw/artifact-generation.js.map +1 -1
  39. package/dist/src/openclaw/bridges/discord.d.ts +1 -0
  40. package/dist/src/openclaw/bridges/discord.js +149 -0
  41. package/dist/src/openclaw/bridges/discord.js.map +1 -0
  42. package/dist/src/openclaw/bridges/matrix.js +22 -5
  43. package/dist/src/openclaw/bridges/matrix.js.map +1 -1
  44. package/dist/src/openclaw/bridges/mattermost.js +14 -9
  45. package/dist/src/openclaw/bridges/mattermost.js.map +1 -1
  46. package/dist/src/openclaw/bridges/probe-response.d.ts +1 -0
  47. package/dist/src/openclaw/bridges/probe-response.js +5 -0
  48. package/dist/src/openclaw/bridges/probe-response.js.map +1 -0
  49. package/dist/src/openclaw/bridges/signal.js +16 -7
  50. package/dist/src/openclaw/bridges/signal.js.map +1 -1
  51. package/dist/src/openclaw/bridges/slack.js +117 -24
  52. package/dist/src/openclaw/bridges/slack.js.map +1 -1
  53. package/dist/src/openclaw/bridges/telegram.js +46 -20
  54. package/dist/src/openclaw/bridges/telegram.js.map +1 -1
  55. package/dist/src/openclaw/bridges/whatsapp.js +33 -17
  56. package/dist/src/openclaw/bridges/whatsapp.js.map +1 -1
  57. package/dist/src/openclaw/bridges/zalo.js +9 -4
  58. package/dist/src/openclaw/bridges/zalo.js.map +1 -1
  59. package/dist/src/openclaw/outbound-contract.js +3 -0
  60. package/dist/src/openclaw/outbound-contract.js.map +1 -1
  61. package/dist/src/openclaw/private-file.d.ts +38 -3
  62. package/dist/src/openclaw/private-file.js +2008 -87
  63. package/dist/src/openclaw/private-file.js.map +1 -1
  64. package/dist/src/openclaw/{smoke-lock.d.ts → provider-readiness-lock.d.ts} +14 -5
  65. package/dist/src/openclaw/provider-readiness-lock.js +1320 -0
  66. package/dist/src/openclaw/provider-readiness-lock.js.map +1 -0
  67. package/dist/src/openclaw/shared.d.ts +10 -17
  68. package/dist/src/openclaw/shared.js +53 -19
  69. package/dist/src/openclaw/shared.js.map +1 -1
  70. package/dist/src/openclaw.d.ts +3 -5
  71. package/dist/src/openclaw.js +245 -60
  72. package/dist/src/openclaw.js.map +1 -1
  73. package/dist/src/platform/process-owned-lock.d.ts +11 -0
  74. package/dist/src/platform/process-owned-lock.js +1698 -0
  75. package/dist/src/platform/process-owned-lock.js.map +1 -0
  76. package/dist/src/platform/recorder-directory.d.ts +1 -0
  77. package/dist/src/platform/recorder-directory.js +14 -0
  78. package/dist/src/platform/recorder-directory.js.map +1 -0
  79. package/dist/src/platform/windows-acl.d.ts +18 -0
  80. package/dist/src/platform/windows-acl.js +1367 -0
  81. package/dist/src/platform/windows-acl.js.map +1 -0
  82. package/dist/src/platform/windows-lock-root.d.ts +13 -0
  83. package/dist/src/platform/windows-lock-root.js +98 -0
  84. package/dist/src/platform/windows-lock-root.js.map +1 -0
  85. package/dist/src/providers/builtin/discord.d.ts +4 -0
  86. package/dist/src/providers/builtin/discord.js +52 -9
  87. package/dist/src/providers/builtin/discord.js.map +1 -1
  88. package/dist/src/providers/builtin/external-webhook-auth.d.ts +1 -0
  89. package/dist/src/providers/builtin/external-webhook-auth.js +38 -1
  90. package/dist/src/providers/builtin/external-webhook-auth.js.map +1 -1
  91. package/dist/src/providers/builtin/feishu.d.ts +1 -0
  92. package/dist/src/providers/builtin/feishu.js +96 -26
  93. package/dist/src/providers/builtin/feishu.js.map +1 -1
  94. package/dist/src/providers/builtin/googlechat.d.ts +1 -0
  95. package/dist/src/providers/builtin/googlechat.js +95 -26
  96. package/dist/src/providers/builtin/googlechat.js.map +1 -1
  97. package/dist/src/providers/builtin/imessage.js +60 -17
  98. package/dist/src/providers/builtin/imessage.js.map +1 -1
  99. package/dist/src/providers/builtin/loopback.js +88 -35
  100. package/dist/src/providers/builtin/loopback.js.map +1 -1
  101. package/dist/src/providers/builtin/matrix.d.ts +2 -2
  102. package/dist/src/providers/builtin/matrix.js +78 -21
  103. package/dist/src/providers/builtin/matrix.js.map +1 -1
  104. package/dist/src/providers/builtin/mattermost.d.ts +11 -7
  105. package/dist/src/providers/builtin/mattermost.js +138 -24
  106. package/dist/src/providers/builtin/mattermost.js.map +1 -1
  107. package/dist/src/providers/builtin/msteams.d.ts +1 -0
  108. package/dist/src/providers/builtin/msteams.js +118 -38
  109. package/dist/src/providers/builtin/msteams.js.map +1 -1
  110. package/dist/src/providers/builtin/native-local-mock.js +4 -4
  111. package/dist/src/providers/builtin/native-local-mock.js.map +1 -1
  112. package/dist/src/providers/builtin/script.js +1057 -146
  113. package/dist/src/providers/builtin/script.js.map +1 -1
  114. package/dist/src/providers/builtin/slack.d.ts +8 -1
  115. package/dist/src/providers/builtin/slack.js +327 -24
  116. package/dist/src/providers/builtin/slack.js.map +1 -1
  117. package/dist/src/providers/builtin/telegram.d.ts +1 -1
  118. package/dist/src/providers/builtin/telegram.js +55 -14
  119. package/dist/src/providers/builtin/telegram.js.map +1 -1
  120. package/dist/src/providers/builtin/whatsapp.d.ts +4 -3
  121. package/dist/src/providers/builtin/whatsapp.js +157 -29
  122. package/dist/src/providers/builtin/whatsapp.js.map +1 -1
  123. package/dist/src/providers/builtin/zalo.d.ts +5 -2
  124. package/dist/src/providers/builtin/zalo.js +31 -7
  125. package/dist/src/providers/builtin/zalo.js.map +1 -1
  126. package/dist/src/providers/catalog.d.ts +1 -1
  127. package/dist/src/providers/catalog.js +1 -1
  128. package/dist/src/providers/catalog.js.map +1 -1
  129. package/dist/src/providers/local-mock.d.ts +4 -0
  130. package/dist/src/providers/local-mock.js +162 -35
  131. package/dist/src/providers/local-mock.js.map +1 -1
  132. package/dist/src/providers/native-ids.d.ts +2 -0
  133. package/dist/src/providers/native-ids.js +3 -0
  134. package/dist/src/providers/native-ids.js.map +1 -1
  135. package/dist/src/providers/recorder.d.ts +14 -3
  136. package/dist/src/providers/recorder.js +521 -41
  137. package/dist/src/providers/recorder.js.map +1 -1
  138. package/dist/src/providers/registry.d.ts +1 -0
  139. package/dist/src/providers/registry.js +65 -20
  140. package/dist/src/providers/registry.js.map +1 -1
  141. package/dist/src/providers/signed-jwt.d.ts +6 -1
  142. package/dist/src/providers/signed-jwt.js +241 -50
  143. package/dist/src/providers/signed-jwt.js.map +1 -1
  144. package/dist/src/providers/slack-ids.d.ts +1 -0
  145. package/dist/src/providers/slack-ids.js +5 -0
  146. package/dist/src/providers/slack-ids.js.map +1 -1
  147. package/dist/src/providers/target-normalizers.d.ts +9 -1
  148. package/dist/src/providers/target-normalizers.js +177 -58
  149. package/dist/src/providers/target-normalizers.js.map +1 -1
  150. package/dist/src/providers/webhook-server.d.ts +3 -0
  151. package/dist/src/providers/webhook-server.js +268 -47
  152. package/dist/src/providers/webhook-server.js.map +1 -1
  153. package/dist/src/servers/discord.d.ts +40 -0
  154. package/dist/src/servers/discord.js +842 -0
  155. package/dist/src/servers/discord.js.map +1 -0
  156. package/dist/src/servers/http.d.ts +14 -2
  157. package/dist/src/servers/http.js +229 -58
  158. package/dist/src/servers/http.js.map +1 -1
  159. package/dist/src/servers/index.d.ts +10 -4
  160. package/dist/src/servers/index.js +4 -0
  161. package/dist/src/servers/index.js.map +1 -1
  162. package/dist/src/servers/matrix.d.ts +3 -0
  163. package/dist/src/servers/matrix.js +268 -110
  164. package/dist/src/servers/matrix.js.map +1 -1
  165. package/dist/src/servers/mattermost.d.ts +5 -0
  166. package/dist/src/servers/mattermost.js +389 -91
  167. package/dist/src/servers/mattermost.js.map +1 -1
  168. package/dist/src/servers/recorder.d.ts +11 -0
  169. package/dist/src/servers/recorder.js +1072 -69
  170. package/dist/src/servers/recorder.js.map +1 -1
  171. package/dist/src/servers/signal.d.ts +1 -0
  172. package/dist/src/servers/signal.js +279 -44
  173. package/dist/src/servers/signal.js.map +1 -1
  174. package/dist/src/servers/slack.d.ts +15 -0
  175. package/dist/src/servers/slack.js +270 -54
  176. package/dist/src/servers/slack.js.map +1 -1
  177. package/dist/src/servers/telegram-identity.d.ts +6 -0
  178. package/dist/src/servers/telegram-identity.js +27 -0
  179. package/dist/src/servers/telegram-identity.js.map +1 -0
  180. package/dist/src/servers/telegram.d.ts +17 -6
  181. package/dist/src/servers/telegram.js +1218 -107
  182. package/dist/src/servers/telegram.js.map +1 -1
  183. package/dist/src/servers/webhook-target.d.ts +12 -4
  184. package/dist/src/servers/webhook-target.js +226 -28
  185. package/dist/src/servers/webhook-target.js.map +1 -1
  186. package/dist/src/servers/whatsapp-baileys-websocket.d.ts +60 -1
  187. package/dist/src/servers/whatsapp-baileys-websocket.js +782 -112
  188. package/dist/src/servers/whatsapp-baileys-websocket.js.map +1 -1
  189. package/dist/src/servers/whatsapp-jid.d.ts +1 -0
  190. package/dist/src/servers/whatsapp-jid.js +9 -5
  191. package/dist/src/servers/whatsapp-jid.js.map +1 -1
  192. package/dist/src/servers/whatsapp-wire/binary-node.d.ts +1 -0
  193. package/dist/src/servers/whatsapp-wire/binary-node.js +37 -13
  194. package/dist/src/servers/whatsapp-wire/binary-node.js.map +1 -1
  195. package/dist/src/servers/whatsapp-wire/crypto.d.ts +3 -0
  196. package/dist/src/servers/whatsapp-wire/crypto.js +23 -8
  197. package/dist/src/servers/whatsapp-wire/crypto.js.map +1 -1
  198. package/dist/src/servers/whatsapp-wire/handshake.d.ts +9 -3
  199. package/dist/src/servers/whatsapp-wire/handshake.js +173 -12
  200. package/dist/src/servers/whatsapp-wire/handshake.js.map +1 -1
  201. package/dist/src/servers/whatsapp-wire/signal.js +3 -3
  202. package/dist/src/servers/whatsapp-wire/signal.js.map +1 -1
  203. package/dist/src/servers/whatsapp.d.ts +7 -1
  204. package/dist/src/servers/whatsapp.js +149 -25
  205. package/dist/src/servers/whatsapp.js.map +1 -1
  206. package/dist/src/servers/zalo.d.ts +1 -0
  207. package/dist/src/servers/zalo.js +193 -82
  208. package/dist/src/servers/zalo.js.map +1 -1
  209. package/docs/channel-setup.md +251 -64
  210. package/fixtures/examples/crabline.example.yaml +3 -2
  211. package/package.json +18 -10
  212. package/dist/src/openclaw/smoke-lock.js +0 -1004
  213. package/dist/src/openclaw/smoke-lock.js.map +0 -1
  214. package/fixtures/examples/openclaw-bridge.yaml +0 -125
@@ -1,12 +1,11 @@
1
1
  import { createHash } from "node:crypto";
2
2
  import { createAdminInboundRequest, createOpenClawCrablineProviderBridge, DEFAULT_ACCOUNT_ID, isRecord, qaTargetForInbound, readNonBlankString, readString, } from "../shared.js";
3
- const TELEGRAM_SYMBOLIC_DIRECT_ID_BASE = 1n << 51n;
4
- const TELEGRAM_SYMBOLIC_DIRECT_ID_MASK = TELEGRAM_SYMBOLIC_DIRECT_ID_BASE - 1n;
5
- const TELEGRAM_SYMBOLIC_GROUP_ID_BASE = 1000000000000n;
6
- const TELEGRAM_SYMBOLIC_GROUP_ID_RANGE = 10000000000n;
3
+ import { canonicalizeTelegramUsername, TELEGRAM_BOT_USERNAME_PATTERN, TELEGRAM_CHAT_USERNAME_PATTERN, TELEGRAM_NATIVE_CHAT_ID_MAX, telegramUsernameChatId, } from "../../servers/telegram-identity.js";
4
+ import { throwProbeHttpError } from "./probe-response.js";
5
+ const TELEGRAM_SYMBOLIC_ID_BASE = TELEGRAM_NATIVE_CHAT_ID_MAX + 1n;
6
+ const TELEGRAM_SYMBOLIC_ID_RANGE = 1n << 50n;
7
7
  const TELEGRAM_OUTBOUND_METHOD_RE = /\/(sendAnimation|sendAudio|sendDocument|sendMessage|sendPhoto|sendVideo)$/iu;
8
- const TELEGRAM_USERNAME_RE = /^@[A-Za-z][A-Za-z0-9_]{3,31}$/u;
9
- function normalizeTelegramChatId(kind, id) {
8
+ function normalizeTelegramChatId(kind, id, options) {
10
9
  const value = id.trim();
11
10
  if (!value) {
12
11
  throw new Error("Telegram target is required.");
@@ -20,19 +19,32 @@ function normalizeTelegramChatId(kind, id) {
20
19
  numericId > BigInt(Number.MAX_SAFE_INTEGER)) {
21
20
  throw new Error("Telegram numeric target must be a safe integer.");
22
21
  }
22
+ if (numericId < -TELEGRAM_NATIVE_CHAT_ID_MAX || numericId > TELEGRAM_NATIVE_CHAT_ID_MAX) {
23
+ throw new Error("Telegram native numeric targets must fit within 52 significant bits.");
24
+ }
23
25
  return numericId.toString();
24
26
  }
25
- if (kind === "group" && TELEGRAM_USERNAME_RE.test(value)) {
26
- return value;
27
- }
28
27
  if (value.startsWith("@")) {
29
- throw new Error("Telegram usernames must contain 4-32 letters, digits, or underscores.");
28
+ const username = canonicalizeTelegramUsername(value);
29
+ if (!username) {
30
+ throw new Error("Telegram usernames must contain 4-32 letters, digits, or underscores.");
31
+ }
32
+ if (kind === "group" && options.preserveGroupUsername) {
33
+ return username;
34
+ }
35
+ if (kind === "group") {
36
+ return String(telegramUsernameChatId(username));
37
+ }
38
+ return syntheticTelegramChatId(kind, username);
30
39
  }
40
+ return syntheticTelegramChatId(kind, value);
41
+ }
42
+ function syntheticTelegramChatId(kind, value) {
31
43
  const hash = createHash("sha256").update(`${kind}:${value}`).digest().readBigUInt64BE();
32
44
  if (kind === "group") {
33
- return String(-(TELEGRAM_SYMBOLIC_GROUP_ID_BASE + (hash % TELEGRAM_SYMBOLIC_GROUP_ID_RANGE)));
45
+ return String(-(TELEGRAM_SYMBOLIC_ID_BASE + (hash % TELEGRAM_SYMBOLIC_ID_RANGE)));
34
46
  }
35
- return String(TELEGRAM_SYMBOLIC_DIRECT_ID_BASE + (hash & TELEGRAM_SYMBOLIC_DIRECT_ID_MASK));
47
+ return String(TELEGRAM_SYMBOLIC_ID_BASE + (hash % TELEGRAM_SYMBOLIC_ID_RANGE));
36
48
  }
37
49
  function telegramTargetKey(chatId, threadId) {
38
50
  return threadId === undefined ? chatId : `${chatId}:topic:${threadId}`;
@@ -51,7 +63,8 @@ function canonicalTelegramRecorderChatId(value) {
51
63
  }
52
64
  return numericId.toString();
53
65
  }
54
- return TELEGRAM_USERNAME_RE.test(chatId) ? chatId : undefined;
66
+ const usernameChatId = telegramUsernameChatId(chatId);
67
+ return usernameChatId === undefined ? undefined : String(usernameChatId);
55
68
  }
56
69
  function telegramBotCommandEntity(text, commandName) {
57
70
  if (!/^[a-z0-9_]{1,32}$/u.test(commandName)) {
@@ -89,9 +102,10 @@ export const TELEGRAM_OPENCLAW_CRABLINE_PROVIDER_BRIDGE = createOpenClawCrabline
89
102
  createAdapter(telegram) {
90
103
  return {
91
104
  async probe(signal) {
105
+ const configuredBotId = /^([1-9]\d*):/u.exec(telegram.botToken)?.[1];
92
106
  const response = await fetch(`${telegram.endpoints.apiRoot}/bot${telegram.botToken}/getMe`, signal ? { signal } : {});
93
107
  if (!response.ok) {
94
- throw new Error(`Crabline Telegram getMe probe failed with HTTP ${response.status}.`);
108
+ await throwProbeHttpError(response, `Crabline Telegram getMe probe failed with HTTP ${response.status}.`);
95
109
  }
96
110
  const payload = await response.json();
97
111
  if (!isRecord(payload) || payload.ok !== true) {
@@ -105,11 +119,12 @@ export const TELEGRAM_OPENCLAW_CRABLINE_PROVIDER_BRIDGE = createOpenClawCrabline
105
119
  typeof result.id !== "number" ||
106
120
  !Number.isSafeInteger(result.id) ||
107
121
  result.id <= 0 ||
122
+ configuredBotId !== String(result.id) ||
108
123
  result.is_bot !== true ||
109
124
  !readNonBlankString(result.first_name) ||
110
125
  (result.username !== undefined &&
111
126
  (typeof result.username !== "string" ||
112
- !TELEGRAM_USERNAME_RE.test(`@${result.username}`)))) {
127
+ !TELEGRAM_BOT_USERNAME_PATTERN.test(`@${result.username}`)))) {
113
128
  throw new Error("Crabline Telegram getMe probe failed: invalid response.");
114
129
  }
115
130
  return payload;
@@ -118,7 +133,7 @@ export const TELEGRAM_OPENCLAW_CRABLINE_PROVIDER_BRIDGE = createOpenClawCrabline
118
133
  return {
119
134
  accountId: DEFAULT_ACCOUNT_ID,
120
135
  channel: "telegram",
121
- createChannelDriverSmokeEnv: (env) => ({
136
+ createProviderReadinessEnv: (env) => ({
122
137
  ...env,
123
138
  TELEGRAM_BOT_TOKEN: telegram.botToken,
124
139
  }),
@@ -166,10 +181,13 @@ export const TELEGRAM_OPENCLAW_CRABLINE_PROVIDER_BRIDGE = createOpenClawCrabline
166
181
  },
167
182
  createAgentDelivery(parsed) {
168
183
  const kind = parsed.native &&
169
- (/^-\d+$/u.test(parsed.id.trim()) || TELEGRAM_USERNAME_RE.test(parsed.id.trim()))
184
+ (/^-\d+$/u.test(parsed.id.trim()) ||
185
+ TELEGRAM_CHAT_USERNAME_PATTERN.test(parsed.id.trim()))
170
186
  ? "group"
171
187
  : parsed.kind;
172
- const chatId = normalizeTelegramChatId(kind, parsed.id);
188
+ const chatId = normalizeTelegramChatId(kind, parsed.id, {
189
+ preserveGroupUsername: true,
190
+ });
173
191
  const threadId = parseTelegramThreadTargetId(parsed.threadId);
174
192
  const to = telegramTargetKey(chatId, threadId);
175
193
  return {
@@ -181,13 +199,21 @@ export const TELEGRAM_OPENCLAW_CRABLINE_PROVIDER_BRIDGE = createOpenClawCrabline
181
199
  },
182
200
  createInbound(input) {
183
201
  const kind = input.conversation.kind === "direct" ? "direct" : "group";
184
- const chatId = normalizeTelegramChatId(kind, input.conversation.id);
202
+ const chatId = normalizeTelegramChatId(kind, input.conversation.id, {
203
+ preserveGroupUsername: false,
204
+ });
205
+ const senderId = normalizeTelegramChatId("direct", input.senderId, {
206
+ preserveGroupUsername: false,
207
+ });
208
+ if (kind === "direct" && chatId !== senderId) {
209
+ throw new Error("Telegram direct conversation and sender must normalize to the same identity.");
210
+ }
185
211
  const threadId = parseTelegramThreadTargetId(input.threadId);
186
212
  return {
187
213
  ...createAdminInboundRequest(telegram),
188
214
  providerBody: {
189
215
  chatId,
190
- fromId: Number(normalizeTelegramChatId("direct", input.senderId)),
216
+ fromId: Number(senderId),
191
217
  fromName: input.senderName ?? input.senderId,
192
218
  ...(threadId !== undefined ? { messageThreadId: threadId } : {}),
193
219
  ...(input.nativeCommand
@@ -1 +1 @@
1
- {"version":3,"file":"telegram.js","sourceRoot":"","sources":["../../../../src/openclaw/bridges/telegram.ts"],"names":[],"mappings":"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","sourcesContent":["import { createHash } from \"node:crypto\";\nimport {\n createAdminInboundRequest,\n createOpenClawCrablineProviderBridge,\n DEFAULT_ACCOUNT_ID,\n isRecord,\n qaTargetForInbound,\n readNonBlankString,\n readString,\n} from \"../shared.js\";\n\nconst TELEGRAM_SYMBOLIC_DIRECT_ID_BASE = 1n << 51n;\nconst TELEGRAM_SYMBOLIC_DIRECT_ID_MASK = TELEGRAM_SYMBOLIC_DIRECT_ID_BASE - 1n;\nconst TELEGRAM_SYMBOLIC_GROUP_ID_BASE = 1_000_000_000_000n;\nconst TELEGRAM_SYMBOLIC_GROUP_ID_RANGE = 10_000_000_000n;\nconst TELEGRAM_OUTBOUND_METHOD_RE =\n /\\/(sendAnimation|sendAudio|sendDocument|sendMessage|sendPhoto|sendVideo)$/iu;\nconst TELEGRAM_USERNAME_RE = /^@[A-Za-z][A-Za-z0-9_]{3,31}$/u;\n\nfunction normalizeTelegramChatId(kind: \"direct\" | \"group\", id: string): string {\n const value = id.trim();\n if (!value) {\n throw new Error(\"Telegram target is required.\");\n }\n if (/^-?\\d+$/u.test(value)) {\n const numericId = BigInt(value);\n if (numericId === 0n || (kind === \"direct\" ? numericId < 0n : numericId > 0n)) {\n throw new Error(\"Telegram numeric target sign does not match the declared target kind.\");\n }\n if (\n numericId < BigInt(Number.MIN_SAFE_INTEGER) ||\n numericId > BigInt(Number.MAX_SAFE_INTEGER)\n ) {\n throw new Error(\"Telegram numeric target must be a safe integer.\");\n }\n return numericId.toString();\n }\n if (kind === \"group\" && TELEGRAM_USERNAME_RE.test(value)) {\n return value;\n }\n if (value.startsWith(\"@\")) {\n throw new Error(\"Telegram usernames must contain 4-32 letters, digits, or underscores.\");\n }\n const hash = createHash(\"sha256\").update(`${kind}:${value}`).digest().readBigUInt64BE();\n if (kind === \"group\") {\n return String(-(TELEGRAM_SYMBOLIC_GROUP_ID_BASE + (hash % TELEGRAM_SYMBOLIC_GROUP_ID_RANGE)));\n }\n return String(TELEGRAM_SYMBOLIC_DIRECT_ID_BASE + (hash & TELEGRAM_SYMBOLIC_DIRECT_ID_MASK));\n}\n\nfunction telegramTargetKey(chatId: string, threadId?: number) {\n return threadId === undefined ? chatId : `${chatId}:topic:${threadId}`;\n}\n\nfunction canonicalTelegramRecorderChatId(value: unknown): string | undefined {\n const chatId = readString(value);\n if (!chatId) {\n return undefined;\n }\n if (/^-?\\d+$/u.test(chatId)) {\n const numericId = BigInt(chatId);\n if (\n numericId === 0n ||\n numericId < BigInt(Number.MIN_SAFE_INTEGER) ||\n numericId > BigInt(Number.MAX_SAFE_INTEGER)\n ) {\n return undefined;\n }\n return numericId.toString();\n }\n return TELEGRAM_USERNAME_RE.test(chatId) ? chatId : undefined;\n}\n\nfunction telegramBotCommandEntity(text: string, commandName: string) {\n if (!/^[a-z0-9_]{1,32}$/u.test(commandName)) {\n throw new Error(\n \"Telegram native command names must contain 1-32 lowercase letters, digits, or underscores.\",\n );\n }\n const commandPrefix = `/${commandName}`;\n const token = text.match(/^\\S+/u)?.[0];\n if (\n !token ||\n (token.toLowerCase() !== commandPrefix &&\n !new RegExp(`^/${commandName}@[A-Za-z][A-Za-z0-9_]{4,31}$`, \"iu\").test(token))\n ) {\n throw new Error(`Telegram native command text must start with ${commandPrefix}.`);\n }\n return {\n length: token.length,\n offset: 0,\n type: \"bot_command\",\n } as const;\n}\n\nfunction parseTelegramThreadTargetId(value: unknown): number | undefined {\n if (value === undefined) {\n return undefined;\n }\n const trimmed = readString(value);\n if (!trimmed || !/^[1-9]\\d*$/u.test(trimmed)) {\n throw new Error(\"Telegram thread target must be a safe positive integer.\");\n }\n const threadId = Number(trimmed);\n if (!Number.isSafeInteger(threadId)) {\n throw new Error(\"Telegram thread target must be a safe positive integer.\");\n }\n return threadId;\n}\n\nexport const TELEGRAM_OPENCLAW_CRABLINE_PROVIDER_BRIDGE = createOpenClawCrablineProviderBridge({\n provider: \"telegram\",\n createAdapter(telegram) {\n return {\n async probe(signal) {\n const response = await fetch(\n `${telegram.endpoints.apiRoot}/bot${telegram.botToken}/getMe`,\n signal ? { signal } : {},\n );\n if (!response.ok) {\n throw new Error(`Crabline Telegram getMe probe failed with HTTP ${response.status}.`);\n }\n const payload: unknown = await response.json();\n if (!isRecord(payload) || payload.ok !== true) {\n const errorCode = readString(isRecord(payload) ? payload.error_code : undefined);\n const description = readNonBlankString(\n isRecord(payload) ? payload.description : undefined,\n );\n const detail = description ?? (errorCode ? `error ${errorCode}` : \"invalid response\");\n throw new Error(`Crabline Telegram getMe probe failed: ${detail}.`);\n }\n const result = payload.result;\n if (\n !isRecord(result) ||\n typeof result.id !== \"number\" ||\n !Number.isSafeInteger(result.id) ||\n result.id <= 0 ||\n result.is_bot !== true ||\n !readNonBlankString(result.first_name) ||\n (result.username !== undefined &&\n (typeof result.username !== \"string\" ||\n !TELEGRAM_USERNAME_RE.test(`@${result.username}`)))\n ) {\n throw new Error(\"Crabline Telegram getMe probe failed: invalid response.\");\n }\n return payload;\n },\n createBinding() {\n return {\n accountId: DEFAULT_ACCOUNT_ID,\n channel: \"telegram\",\n createChannelDriverSmokeEnv: (env) => ({\n ...env,\n TELEGRAM_BOT_TOKEN: telegram.botToken,\n }),\n createGatewayConfig: (openclawConfig = {}) => {\n const channels = isRecord(openclawConfig.channels) ? openclawConfig.channels : {};\n const telegramConfig = isRecord(channels.telegram) ? channels.telegram : {};\n const groups = isRecord(telegramConfig.groups) ? telegramConfig.groups : {};\n const defaultGroup = isRecord(groups[\"*\"]) ? groups[\"*\"] : {};\n const messages = isRecord(openclawConfig.messages) ? openclawConfig.messages : {};\n const groupChat = isRecord(messages.groupChat) ? messages.groupChat : {};\n\n return {\n ...openclawConfig,\n channels: {\n ...channels,\n telegram: {\n ...telegramConfig,\n enabled: true,\n botToken: telegram.botToken,\n apiRoot: telegram.endpoints.apiRoot,\n dmPolicy: \"open\",\n groupPolicy: \"open\",\n allowFrom: [\"*\"],\n groupAllowFrom: [\"*\"],\n groups: {\n ...groups,\n \"*\": {\n ...defaultGroup,\n requireMention: false,\n },\n },\n },\n },\n messages: {\n ...messages,\n groupChat: {\n ...groupChat,\n mentionPatterns: [\"\\\\b@?openclaw\\\\b\"],\n visibleReplies: \"automatic\",\n },\n },\n };\n },\n requiredPluginIds: [\"telegram\"],\n };\n },\n createAgentDelivery(parsed) {\n const kind =\n parsed.native &&\n (/^-\\d+$/u.test(parsed.id.trim()) || TELEGRAM_USERNAME_RE.test(parsed.id.trim()))\n ? \"group\"\n : parsed.kind;\n const chatId = normalizeTelegramChatId(kind, parsed.id);\n const threadId = parseTelegramThreadTargetId(parsed.threadId);\n const to = telegramTargetKey(chatId, threadId);\n return {\n channel: \"telegram\",\n to,\n replyChannel: \"telegram\",\n replyTo: to,\n };\n },\n createInbound(input) {\n const kind = input.conversation.kind === \"direct\" ? \"direct\" : \"group\";\n const chatId = normalizeTelegramChatId(kind, input.conversation.id);\n const threadId = parseTelegramThreadTargetId(input.threadId);\n return {\n ...createAdminInboundRequest(telegram),\n providerBody: {\n chatId,\n fromId: Number(normalizeTelegramChatId(\"direct\", input.senderId)),\n fromName: input.senderName ?? input.senderId,\n ...(threadId !== undefined ? { messageThreadId: threadId } : {}),\n ...(input.nativeCommand\n ? {\n entities: [telegramBotCommandEntity(input.text, input.nativeCommand.name)],\n }\n : {}),\n text: input.text,\n },\n providerTargetKey: telegramTargetKey(chatId, threadId),\n qaTarget: qaTargetForInbound(input),\n stateConversation: {\n id: chatId,\n kind: kind === \"group\" ? \"group\" : \"direct\",\n },\n ...(threadId !== undefined ? { threadId: String(threadId) } : {}),\n };\n },\n createOutboundFromRecorderEvent({ event, targetByProviderTarget }) {\n if (!isRecord(event) || event.type !== \"api\" || typeof event.path !== \"string\") {\n return null;\n }\n const method = TELEGRAM_OUTBOUND_METHOD_RE.exec(event.path)?.[1]?.toLowerCase();\n if (!method || !isRecord(event.body)) {\n return null;\n }\n const chatId = canonicalTelegramRecorderChatId(event.body.chat_id);\n const text =\n method === \"sendmessage\"\n ? readNonBlankString(event.body.text)\n : readNonBlankString(event.body.caption);\n if (!chatId || !text) {\n return null;\n }\n let threadId: number | undefined;\n try {\n threadId = parseTelegramThreadTargetId(event.body.message_thread_id);\n } catch {\n return null;\n }\n const providerTargetKey = telegramTargetKey(chatId, threadId);\n return {\n accountId: DEFAULT_ACCOUNT_ID,\n senderId: \"openclaw\",\n senderName: \"OpenClaw QA\",\n text,\n to:\n targetByProviderTarget.get(providerTargetKey) ??\n (threadId === undefined ? chatId : providerTargetKey),\n };\n },\n };\n },\n});\n"]}
1
+ {"version":3,"file":"telegram.js","sourceRoot":"","sources":["../../../../src/openclaw/bridges/telegram.ts"],"names":[],"mappings":"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","sourcesContent":["import { createHash } from \"node:crypto\";\nimport {\n createAdminInboundRequest,\n createOpenClawCrablineProviderBridge,\n DEFAULT_ACCOUNT_ID,\n isRecord,\n qaTargetForInbound,\n readNonBlankString,\n readString,\n} from \"../shared.js\";\nimport {\n canonicalizeTelegramUsername,\n TELEGRAM_BOT_USERNAME_PATTERN,\n TELEGRAM_CHAT_USERNAME_PATTERN,\n TELEGRAM_NATIVE_CHAT_ID_MAX,\n telegramUsernameChatId,\n} from \"../../servers/telegram-identity.js\";\nimport { throwProbeHttpError } from \"./probe-response.js\";\n\nconst TELEGRAM_SYMBOLIC_ID_BASE = TELEGRAM_NATIVE_CHAT_ID_MAX + 1n;\nconst TELEGRAM_SYMBOLIC_ID_RANGE = 1n << 50n;\nconst TELEGRAM_OUTBOUND_METHOD_RE =\n /\\/(sendAnimation|sendAudio|sendDocument|sendMessage|sendPhoto|sendVideo)$/iu;\nfunction normalizeTelegramChatId(\n kind: \"direct\" | \"group\",\n id: string,\n options: { preserveGroupUsername: boolean },\n): string {\n const value = id.trim();\n if (!value) {\n throw new Error(\"Telegram target is required.\");\n }\n if (/^-?\\d+$/u.test(value)) {\n const numericId = BigInt(value);\n if (numericId === 0n || (kind === \"direct\" ? numericId < 0n : numericId > 0n)) {\n throw new Error(\"Telegram numeric target sign does not match the declared target kind.\");\n }\n if (\n numericId < BigInt(Number.MIN_SAFE_INTEGER) ||\n numericId > BigInt(Number.MAX_SAFE_INTEGER)\n ) {\n throw new Error(\"Telegram numeric target must be a safe integer.\");\n }\n if (numericId < -TELEGRAM_NATIVE_CHAT_ID_MAX || numericId > TELEGRAM_NATIVE_CHAT_ID_MAX) {\n throw new Error(\"Telegram native numeric targets must fit within 52 significant bits.\");\n }\n return numericId.toString();\n }\n if (value.startsWith(\"@\")) {\n const username = canonicalizeTelegramUsername(value);\n if (!username) {\n throw new Error(\"Telegram usernames must contain 4-32 letters, digits, or underscores.\");\n }\n if (kind === \"group\" && options.preserveGroupUsername) {\n return username;\n }\n if (kind === \"group\") {\n return String(telegramUsernameChatId(username));\n }\n return syntheticTelegramChatId(kind, username);\n }\n return syntheticTelegramChatId(kind, value);\n}\n\nfunction syntheticTelegramChatId(kind: \"direct\" | \"group\", value: string): string {\n const hash = createHash(\"sha256\").update(`${kind}:${value}`).digest().readBigUInt64BE();\n if (kind === \"group\") {\n return String(-(TELEGRAM_SYMBOLIC_ID_BASE + (hash % TELEGRAM_SYMBOLIC_ID_RANGE)));\n }\n return String(TELEGRAM_SYMBOLIC_ID_BASE + (hash % TELEGRAM_SYMBOLIC_ID_RANGE));\n}\n\nfunction telegramTargetKey(chatId: string, threadId?: number) {\n return threadId === undefined ? chatId : `${chatId}:topic:${threadId}`;\n}\n\nfunction canonicalTelegramRecorderChatId(value: unknown): string | undefined {\n const chatId = readString(value);\n if (!chatId) {\n return undefined;\n }\n if (/^-?\\d+$/u.test(chatId)) {\n const numericId = BigInt(chatId);\n if (\n numericId === 0n ||\n numericId < BigInt(Number.MIN_SAFE_INTEGER) ||\n numericId > BigInt(Number.MAX_SAFE_INTEGER)\n ) {\n return undefined;\n }\n return numericId.toString();\n }\n const usernameChatId = telegramUsernameChatId(chatId);\n return usernameChatId === undefined ? undefined : String(usernameChatId);\n}\n\nfunction telegramBotCommandEntity(text: string, commandName: string) {\n if (!/^[a-z0-9_]{1,32}$/u.test(commandName)) {\n throw new Error(\n \"Telegram native command names must contain 1-32 lowercase letters, digits, or underscores.\",\n );\n }\n const commandPrefix = `/${commandName}`;\n const token = text.match(/^\\S+/u)?.[0];\n if (\n !token ||\n (token.toLowerCase() !== commandPrefix &&\n !new RegExp(`^/${commandName}@[A-Za-z][A-Za-z0-9_]{4,31}$`, \"iu\").test(token))\n ) {\n throw new Error(`Telegram native command text must start with ${commandPrefix}.`);\n }\n return {\n length: token.length,\n offset: 0,\n type: \"bot_command\",\n } as const;\n}\n\nfunction parseTelegramThreadTargetId(value: unknown): number | undefined {\n if (value === undefined) {\n return undefined;\n }\n const trimmed = readString(value);\n if (!trimmed || !/^[1-9]\\d*$/u.test(trimmed)) {\n throw new Error(\"Telegram thread target must be a safe positive integer.\");\n }\n const threadId = Number(trimmed);\n if (!Number.isSafeInteger(threadId)) {\n throw new Error(\"Telegram thread target must be a safe positive integer.\");\n }\n return threadId;\n}\n\nexport const TELEGRAM_OPENCLAW_CRABLINE_PROVIDER_BRIDGE = createOpenClawCrablineProviderBridge({\n provider: \"telegram\",\n createAdapter(telegram) {\n return {\n async probe(signal) {\n const configuredBotId = /^([1-9]\\d*):/u.exec(telegram.botToken)?.[1];\n const response = await fetch(\n `${telegram.endpoints.apiRoot}/bot${telegram.botToken}/getMe`,\n signal ? { signal } : {},\n );\n if (!response.ok) {\n await throwProbeHttpError(\n response,\n `Crabline Telegram getMe probe failed with HTTP ${response.status}.`,\n );\n }\n const payload: unknown = await response.json();\n if (!isRecord(payload) || payload.ok !== true) {\n const errorCode = readString(isRecord(payload) ? payload.error_code : undefined);\n const description = readNonBlankString(\n isRecord(payload) ? payload.description : undefined,\n );\n const detail = description ?? (errorCode ? `error ${errorCode}` : \"invalid response\");\n throw new Error(`Crabline Telegram getMe probe failed: ${detail}.`);\n }\n const result = payload.result;\n if (\n !isRecord(result) ||\n typeof result.id !== \"number\" ||\n !Number.isSafeInteger(result.id) ||\n result.id <= 0 ||\n configuredBotId !== String(result.id) ||\n result.is_bot !== true ||\n !readNonBlankString(result.first_name) ||\n (result.username !== undefined &&\n (typeof result.username !== \"string\" ||\n !TELEGRAM_BOT_USERNAME_PATTERN.test(`@${result.username}`)))\n ) {\n throw new Error(\"Crabline Telegram getMe probe failed: invalid response.\");\n }\n return payload;\n },\n createBinding() {\n return {\n accountId: DEFAULT_ACCOUNT_ID,\n channel: \"telegram\",\n createProviderReadinessEnv: (env) => ({\n ...env,\n TELEGRAM_BOT_TOKEN: telegram.botToken,\n }),\n createGatewayConfig: (openclawConfig = {}) => {\n const channels = isRecord(openclawConfig.channels) ? openclawConfig.channels : {};\n const telegramConfig = isRecord(channels.telegram) ? channels.telegram : {};\n const groups = isRecord(telegramConfig.groups) ? telegramConfig.groups : {};\n const defaultGroup = isRecord(groups[\"*\"]) ? groups[\"*\"] : {};\n const messages = isRecord(openclawConfig.messages) ? openclawConfig.messages : {};\n const groupChat = isRecord(messages.groupChat) ? messages.groupChat : {};\n\n return {\n ...openclawConfig,\n channels: {\n ...channels,\n telegram: {\n ...telegramConfig,\n enabled: true,\n botToken: telegram.botToken,\n apiRoot: telegram.endpoints.apiRoot,\n dmPolicy: \"open\",\n groupPolicy: \"open\",\n allowFrom: [\"*\"],\n groupAllowFrom: [\"*\"],\n groups: {\n ...groups,\n \"*\": {\n ...defaultGroup,\n requireMention: false,\n },\n },\n },\n },\n messages: {\n ...messages,\n groupChat: {\n ...groupChat,\n mentionPatterns: [\"\\\\b@?openclaw\\\\b\"],\n visibleReplies: \"automatic\",\n },\n },\n };\n },\n requiredPluginIds: [\"telegram\"],\n };\n },\n createAgentDelivery(parsed) {\n const kind =\n parsed.native &&\n (/^-\\d+$/u.test(parsed.id.trim()) ||\n TELEGRAM_CHAT_USERNAME_PATTERN.test(parsed.id.trim()))\n ? \"group\"\n : parsed.kind;\n const chatId = normalizeTelegramChatId(kind, parsed.id, {\n preserveGroupUsername: true,\n });\n const threadId = parseTelegramThreadTargetId(parsed.threadId);\n const to = telegramTargetKey(chatId, threadId);\n return {\n channel: \"telegram\",\n to,\n replyChannel: \"telegram\",\n replyTo: to,\n };\n },\n createInbound(input) {\n const kind = input.conversation.kind === \"direct\" ? \"direct\" : \"group\";\n const chatId = normalizeTelegramChatId(kind, input.conversation.id, {\n preserveGroupUsername: false,\n });\n const senderId = normalizeTelegramChatId(\"direct\", input.senderId, {\n preserveGroupUsername: false,\n });\n if (kind === \"direct\" && chatId !== senderId) {\n throw new Error(\n \"Telegram direct conversation and sender must normalize to the same identity.\",\n );\n }\n const threadId = parseTelegramThreadTargetId(input.threadId);\n return {\n ...createAdminInboundRequest(telegram),\n providerBody: {\n chatId,\n fromId: Number(senderId),\n fromName: input.senderName ?? input.senderId,\n ...(threadId !== undefined ? { messageThreadId: threadId } : {}),\n ...(input.nativeCommand\n ? {\n entities: [telegramBotCommandEntity(input.text, input.nativeCommand.name)],\n }\n : {}),\n text: input.text,\n },\n providerTargetKey: telegramTargetKey(chatId, threadId),\n qaTarget: qaTargetForInbound(input),\n stateConversation: {\n id: chatId,\n kind: kind === \"group\" ? \"group\" : \"direct\",\n },\n ...(threadId !== undefined ? { threadId: String(threadId) } : {}),\n };\n },\n createOutboundFromRecorderEvent({ event, targetByProviderTarget }) {\n if (!isRecord(event) || event.type !== \"api\" || typeof event.path !== \"string\") {\n return null;\n }\n const method = TELEGRAM_OUTBOUND_METHOD_RE.exec(event.path)?.[1]?.toLowerCase();\n if (!method || !isRecord(event.body)) {\n return null;\n }\n const chatId = canonicalTelegramRecorderChatId(event.body.chat_id);\n const text =\n method === \"sendmessage\"\n ? readNonBlankString(event.body.text)\n : readNonBlankString(event.body.caption);\n if (!chatId || !text) {\n return null;\n }\n let threadId: number | undefined;\n try {\n threadId = parseTelegramThreadTargetId(event.body.message_thread_id);\n } catch {\n return null;\n }\n const providerTargetKey = telegramTargetKey(chatId, threadId);\n return {\n accountId: DEFAULT_ACCOUNT_ID,\n senderId: \"openclaw\",\n senderName: \"OpenClaw QA\",\n text,\n to:\n targetByProviderTarget.get(providerTargetKey) ??\n (threadId === undefined ? chatId : providerTargetKey),\n };\n },\n };\n },\n});\n"]}
@@ -1,5 +1,6 @@
1
1
  import { createAdminInboundRequest, createOpenClawCrablineProviderBridge, DEFAULT_ACCOUNT_ID, isRecord, qaTargetForInbound, readNonBlankString, readString, } from "../shared.js";
2
- import { canonicalizeWhatsAppChatJid, canonicalizeWhatsAppUserCorrelationJid, canonicalizeWhatsAppUserJid, } from "../../servers/whatsapp-jid.js";
2
+ import { canonicalizeWhatsAppChatCorrelationJid, canonicalizeWhatsAppChatJid, canonicalizeWhatsAppUserCorrelationJid, canonicalizeWhatsAppUserJid, } from "../../servers/whatsapp-jid.js";
3
+ import { throwProbeHttpError } from "./probe-response.js";
3
4
  function requireWhatsAppJid(value, label, userOnly = false) {
4
5
  const canonical = userOnly
5
6
  ? canonicalizeWhatsAppUserJid(value)
@@ -37,7 +38,7 @@ export const WHATSAPP_OPENCLAW_CRABLINE_PROVIDER_BRIDGE = createOpenClawCrabline
37
38
  ...(signal ? { signal } : {}),
38
39
  });
39
40
  if (!response.ok) {
40
- throw new Error(`Crabline WhatsApp probe failed with HTTP ${response.status}.`);
41
+ await throwProbeHttpError(response, `Crabline WhatsApp probe failed with HTTP ${response.status}.`);
41
42
  }
42
43
  const payload = await response.json();
43
44
  if (!isRecord(payload) || readString(payload.id) !== whatsapp.phoneNumberId) {
@@ -49,7 +50,7 @@ export const WHATSAPP_OPENCLAW_CRABLINE_PROVIDER_BRIDGE = createOpenClawCrabline
49
50
  return {
50
51
  accountId: DEFAULT_ACCOUNT_ID,
51
52
  channel: "whatsapp",
52
- createChannelDriverSmokeEnv: (env) => ({
53
+ createProviderReadinessEnv: (env) => ({
53
54
  ...env,
54
55
  CRABLINE_WHATSAPP_ADMIN_TOKEN: whatsapp.adminToken,
55
56
  CRABLINE_WHATSAPP_RECORDER_PATH: whatsapp.recorderPath,
@@ -90,11 +91,12 @@ export const WHATSAPP_OPENCLAW_CRABLINE_PROVIDER_BRIDGE = createOpenClawCrabline
90
91
  if (parsed.threadId !== undefined) {
91
92
  throw new Error("WhatsApp does not support thread targets.");
92
93
  }
93
- const to = requireWhatsAppJid(parsed.id, "WhatsApp target");
94
- requireWhatsAppTargetKind(parsed, to);
95
- if (to.endsWith("@g.us")) {
94
+ const nativeTo = requireWhatsAppJid(parsed.id, "WhatsApp target");
95
+ requireWhatsAppTargetKind(parsed, nativeTo);
96
+ if (nativeTo.endsWith("@g.us")) {
96
97
  throw new Error("WhatsApp Crabline WebSocket outbound supports direct targets only.");
97
98
  }
99
+ const to = canonicalizeWhatsAppUserCorrelationJid(nativeTo);
98
100
  return {
99
101
  channel: "whatsapp",
100
102
  to,
@@ -106,25 +108,31 @@ export const WHATSAPP_OPENCLAW_CRABLINE_PROVIDER_BRIDGE = createOpenClawCrabline
106
108
  if (input.threadId !== undefined) {
107
109
  throw new Error("WhatsApp does not support thread targets.");
108
110
  }
109
- const chatJid = requireWhatsAppJid(input.conversation.id, "WhatsApp conversation");
110
- requireWhatsAppConversationKind(input.conversation.kind, chatJid);
111
- const senderJid = requireWhatsAppJid(input.senderId, "WhatsApp sender", true);
111
+ const nativeChatJid = requireWhatsAppJid(input.conversation.id, "WhatsApp conversation");
112
+ requireWhatsAppConversationKind(input.conversation.kind, nativeChatJid);
113
+ const nativeSenderJid = requireWhatsAppJid(input.senderId, "WhatsApp sender", true);
114
+ const providerTargetKey = canonicalizeWhatsAppChatCorrelationJid(nativeChatJid);
115
+ if (input.conversation.kind === "direct" &&
116
+ canonicalizeWhatsAppUserCorrelationJid(nativeChatJid) !==
117
+ canonicalizeWhatsAppUserCorrelationJid(nativeSenderJid)) {
118
+ throw new Error("WhatsApp direct conversation and sender must identify the same recipient.");
119
+ }
112
120
  return {
113
121
  ...createAdminInboundRequest(whatsapp),
114
122
  providerBody: {
115
- chatJid,
116
- senderJid,
123
+ chatJid: nativeChatJid,
124
+ senderJid: nativeSenderJid,
117
125
  ...(input.senderName ? { pushName: input.senderName } : {}),
118
126
  text: input.text,
119
127
  },
120
- providerTargetKey: chatJid,
128
+ providerTargetKey,
121
129
  qaTarget: qaTargetForInbound({
122
130
  ...input,
123
- conversation: { ...input.conversation, id: chatJid },
131
+ conversation: { ...input.conversation, id: providerTargetKey },
124
132
  }),
125
133
  stateConversation: {
126
- id: chatJid,
127
- kind: chatJid.endsWith("@g.us") ? "group" : "direct",
134
+ id: nativeChatJid,
135
+ kind: nativeChatJid.endsWith("@g.us") ? "group" : "direct",
128
136
  },
129
137
  };
130
138
  },
@@ -141,7 +149,15 @@ export const WHATSAPP_OPENCLAW_CRABLINE_PROVIDER_BRIDGE = createOpenClawCrabline
141
149
  const baileysKey = isRecord(event.body.key) ? event.body.key : undefined;
142
150
  const baileysMessage = isRecord(event.body.message) ? event.body.message : undefined;
143
151
  const isBaileysSend = event.method === "WEBSOCKET" && event.path === "/ws/chat";
144
- if (!isBaileysSend && event.path !== messagesPath) {
152
+ const messagingProduct = readString(event.body.messaging_product);
153
+ const messageType = readString(event.body.type);
154
+ const isCloudTextSend = event.method === "POST" &&
155
+ event.path === messagesPath &&
156
+ (!("messaging_product" in event.body) || messagingProduct === "whatsapp") &&
157
+ (!("type" in event.body) || messageType === "text") &&
158
+ !("status" in event.body) &&
159
+ !("message_id" in event.body);
160
+ if (!isBaileysSend && !isCloudTextSend) {
145
161
  return null;
146
162
  }
147
163
  const to = isBaileysSend ? readString(baileysKey?.remoteJid) : readString(event.body.to);
@@ -155,7 +171,7 @@ export const WHATSAPP_OPENCLAW_CRABLINE_PROVIDER_BRIDGE = createOpenClawCrabline
155
171
  return null;
156
172
  }
157
173
  const providerTarget = isBaileysSend
158
- ? canonicalizeWhatsAppUserCorrelationJid(to)
174
+ ? canonicalizeWhatsAppChatCorrelationJid(to)
159
175
  : (canonicalizeWhatsAppChatJid(to) ??
160
176
  (/^\d{7,15}$/u.test(to) ? `${to}@s.whatsapp.net` : to));
161
177
  if (!providerTarget) {
@@ -1 +1 @@
1
- {"version":3,"file":"whatsapp.js","sourceRoot":"","sources":["../../../../src/openclaw/bridges/whatsapp.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n createAdminInboundRequest,\n createOpenClawCrablineProviderBridge,\n DEFAULT_ACCOUNT_ID,\n isRecord,\n qaTargetForInbound,\n readNonBlankString,\n readString,\n} from \"../shared.js\";\nimport {\n canonicalizeWhatsAppChatJid,\n canonicalizeWhatsAppUserCorrelationJid,\n canonicalizeWhatsAppUserJid,\n} from \"../../servers/whatsapp-jid.js\";\n\nfunction requireWhatsAppJid(value: string, label: string, userOnly = false): string {\n const canonical = userOnly\n ? canonicalizeWhatsAppUserJid(value)\n : canonicalizeWhatsAppChatJid(value);\n if (!canonical) {\n throw new Error(`${label} must be a native WhatsApp JID.`);\n }\n return canonical;\n}\n\nfunction requireWhatsAppTargetKind(\n parsed: { kind: \"direct\" | \"group\"; native: boolean },\n targetId: string,\n): void {\n if (parsed.native) {\n return;\n }\n const nativeKind = targetId.endsWith(\"@g.us\") ? \"group\" : \"direct\";\n if (parsed.kind !== nativeKind) {\n throw new Error(\"WhatsApp target kind does not match the native JID.\");\n }\n}\n\nfunction requireWhatsAppConversationKind(kind: \"direct\" | \"group\", targetId: string): void {\n const nativeKind = targetId.endsWith(\"@g.us\") ? \"group\" : \"direct\";\n if (kind !== nativeKind) {\n throw new Error(\"WhatsApp inbound conversation kind does not match the native JID.\");\n }\n}\n\nexport const WHATSAPP_OPENCLAW_CRABLINE_PROVIDER_BRIDGE = createOpenClawCrablineProviderBridge({\n provider: \"whatsapp\",\n createAdapter(whatsapp) {\n const messagesPath = new URL(whatsapp.endpoints.messagesUrl).pathname;\n return {\n async probe(signal) {\n const response = await fetch(whatsapp.endpoints.phoneNumberUrl, {\n headers: {\n authorization: `Bearer ${whatsapp.accessToken}`,\n },\n ...(signal ? { signal } : {}),\n });\n if (!response.ok) {\n throw new Error(`Crabline WhatsApp probe failed with HTTP ${response.status}.`);\n }\n const payload: unknown = await response.json();\n if (!isRecord(payload) || readString(payload.id) !== whatsapp.phoneNumberId) {\n throw new Error(\"Crabline WhatsApp probe returned an unexpected phone number.\");\n }\n return payload;\n },\n createBinding() {\n return {\n accountId: DEFAULT_ACCOUNT_ID,\n channel: \"whatsapp\",\n createChannelDriverSmokeEnv: (env) => ({\n ...env,\n CRABLINE_WHATSAPP_ADMIN_TOKEN: whatsapp.adminToken,\n CRABLINE_WHATSAPP_RECORDER_PATH: whatsapp.recorderPath,\n CRABLINE_WHATSAPP_SELF_JID: whatsapp.selfJid,\n OPENCLAW_WHATSAPP_WEB_SOCKET_URL: whatsapp.endpoints.baileysWebSocketUrl,\n }),\n createGatewayConfig: (openclawConfig = {}) => {\n const channels = isRecord(openclawConfig.channels) ? openclawConfig.channels : {};\n const whatsappConfig = isRecord(channels.whatsapp) ? channels.whatsapp : {};\n const groups = isRecord(whatsappConfig.groups) ? whatsappConfig.groups : {};\n const defaultGroup = isRecord(groups[\"*\"]) ? groups[\"*\"] : {};\n\n return {\n ...openclawConfig,\n channels: {\n ...channels,\n whatsapp: {\n ...whatsappConfig,\n enabled: true,\n dmPolicy: \"open\",\n groupPolicy: \"open\",\n allowFrom: [\"*\"],\n groupAllowFrom: [\"*\"],\n groups: {\n ...groups,\n \"*\": {\n ...defaultGroup,\n requireMention: false,\n },\n },\n },\n },\n };\n },\n requiredPluginIds: [\"whatsapp\"],\n };\n },\n createAgentDelivery(parsed) {\n if (parsed.threadId !== undefined) {\n throw new Error(\"WhatsApp does not support thread targets.\");\n }\n const to = requireWhatsAppJid(parsed.id, \"WhatsApp target\");\n requireWhatsAppTargetKind(parsed, to);\n if (to.endsWith(\"@g.us\")) {\n throw new Error(\"WhatsApp Crabline WebSocket outbound supports direct targets only.\");\n }\n return {\n channel: \"whatsapp\",\n to,\n replyChannel: \"whatsapp\",\n replyTo: to,\n };\n },\n createInbound(input) {\n if (input.threadId !== undefined) {\n throw new Error(\"WhatsApp does not support thread targets.\");\n }\n const chatJid = requireWhatsAppJid(input.conversation.id, \"WhatsApp conversation\");\n requireWhatsAppConversationKind(input.conversation.kind, chatJid);\n const senderJid = requireWhatsAppJid(input.senderId, \"WhatsApp sender\", true);\n return {\n ...createAdminInboundRequest(whatsapp),\n providerBody: {\n chatJid,\n senderJid,\n ...(input.senderName ? { pushName: input.senderName } : {}),\n text: input.text,\n },\n providerTargetKey: chatJid,\n qaTarget: qaTargetForInbound({\n ...input,\n conversation: { ...input.conversation, id: chatJid },\n }),\n stateConversation: {\n id: chatJid,\n kind: chatJid.endsWith(\"@g.us\") ? \"group\" : \"direct\",\n },\n };\n },\n createOutboundFromRecorderEvent({ event, targetByProviderTarget }) {\n if (\n !isRecord(event) ||\n event.type !== \"api\" ||\n event.accepted !== true ||\n typeof event.path !== \"string\"\n ) {\n return null;\n }\n if (!isRecord(event.body)) {\n return null;\n }\n const baileysKey = isRecord(event.body.key) ? event.body.key : undefined;\n const baileysMessage = isRecord(event.body.message) ? event.body.message : undefined;\n const isBaileysSend = event.method === \"WEBSOCKET\" && event.path === \"/ws/chat\";\n if (!isBaileysSend && event.path !== messagesPath) {\n return null;\n }\n const to = isBaileysSend ? readString(baileysKey?.remoteJid) : readString(event.body.to);\n const textPayload = event.body.text;\n const text = isBaileysSend\n ? readNonBlankString(baileysMessage?.conversation)\n : isRecord(textPayload)\n ? readNonBlankString(textPayload.body)\n : undefined;\n if (!to || !text) {\n return null;\n }\n const providerTarget = isBaileysSend\n ? canonicalizeWhatsAppUserCorrelationJid(to)\n : (canonicalizeWhatsAppChatJid(to) ??\n (/^\\d{7,15}$/u.test(to) ? `${to}@s.whatsapp.net` : to));\n if (!providerTarget) {\n return null;\n }\n return {\n accountId: DEFAULT_ACCOUNT_ID,\n senderId: \"openclaw\",\n senderName: \"OpenClaw QA\",\n text,\n to: targetByProviderTarget.get(providerTarget) ?? providerTarget,\n };\n },\n };\n },\n});\n"]}
1
+ {"version":3,"file":"whatsapp.js","sourceRoot":"","sources":["../../../../src/openclaw/bridges/whatsapp.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n createAdminInboundRequest,\n createOpenClawCrablineProviderBridge,\n DEFAULT_ACCOUNT_ID,\n isRecord,\n qaTargetForInbound,\n readNonBlankString,\n readString,\n} from \"../shared.js\";\nimport {\n canonicalizeWhatsAppChatCorrelationJid,\n canonicalizeWhatsAppChatJid,\n canonicalizeWhatsAppUserCorrelationJid,\n canonicalizeWhatsAppUserJid,\n} from \"../../servers/whatsapp-jid.js\";\nimport { throwProbeHttpError } from \"./probe-response.js\";\n\nfunction requireWhatsAppJid(value: string, label: string, userOnly = false): string {\n const canonical = userOnly\n ? canonicalizeWhatsAppUserJid(value)\n : canonicalizeWhatsAppChatJid(value);\n if (!canonical) {\n throw new Error(`${label} must be a native WhatsApp JID.`);\n }\n return canonical;\n}\n\nfunction requireWhatsAppTargetKind(\n parsed: { kind: \"direct\" | \"group\"; native: boolean },\n targetId: string,\n): void {\n if (parsed.native) {\n return;\n }\n const nativeKind = targetId.endsWith(\"@g.us\") ? \"group\" : \"direct\";\n if (parsed.kind !== nativeKind) {\n throw new Error(\"WhatsApp target kind does not match the native JID.\");\n }\n}\n\nfunction requireWhatsAppConversationKind(kind: \"direct\" | \"group\", targetId: string): void {\n const nativeKind = targetId.endsWith(\"@g.us\") ? \"group\" : \"direct\";\n if (kind !== nativeKind) {\n throw new Error(\"WhatsApp inbound conversation kind does not match the native JID.\");\n }\n}\n\nexport const WHATSAPP_OPENCLAW_CRABLINE_PROVIDER_BRIDGE = createOpenClawCrablineProviderBridge({\n provider: \"whatsapp\",\n createAdapter(whatsapp) {\n const messagesPath = new URL(whatsapp.endpoints.messagesUrl).pathname;\n return {\n async probe(signal) {\n const response = await fetch(whatsapp.endpoints.phoneNumberUrl, {\n headers: {\n authorization: `Bearer ${whatsapp.accessToken}`,\n },\n ...(signal ? { signal } : {}),\n });\n if (!response.ok) {\n await throwProbeHttpError(\n response,\n `Crabline WhatsApp probe failed with HTTP ${response.status}.`,\n );\n }\n const payload: unknown = await response.json();\n if (!isRecord(payload) || readString(payload.id) !== whatsapp.phoneNumberId) {\n throw new Error(\"Crabline WhatsApp probe returned an unexpected phone number.\");\n }\n return payload;\n },\n createBinding() {\n return {\n accountId: DEFAULT_ACCOUNT_ID,\n channel: \"whatsapp\",\n createProviderReadinessEnv: (env) => ({\n ...env,\n CRABLINE_WHATSAPP_ADMIN_TOKEN: whatsapp.adminToken,\n CRABLINE_WHATSAPP_RECORDER_PATH: whatsapp.recorderPath,\n CRABLINE_WHATSAPP_SELF_JID: whatsapp.selfJid,\n OPENCLAW_WHATSAPP_WEB_SOCKET_URL: whatsapp.endpoints.baileysWebSocketUrl,\n }),\n createGatewayConfig: (openclawConfig = {}) => {\n const channels = isRecord(openclawConfig.channels) ? openclawConfig.channels : {};\n const whatsappConfig = isRecord(channels.whatsapp) ? channels.whatsapp : {};\n const groups = isRecord(whatsappConfig.groups) ? whatsappConfig.groups : {};\n const defaultGroup = isRecord(groups[\"*\"]) ? groups[\"*\"] : {};\n\n return {\n ...openclawConfig,\n channels: {\n ...channels,\n whatsapp: {\n ...whatsappConfig,\n enabled: true,\n dmPolicy: \"open\",\n groupPolicy: \"open\",\n allowFrom: [\"*\"],\n groupAllowFrom: [\"*\"],\n groups: {\n ...groups,\n \"*\": {\n ...defaultGroup,\n requireMention: false,\n },\n },\n },\n },\n };\n },\n requiredPluginIds: [\"whatsapp\"],\n };\n },\n createAgentDelivery(parsed) {\n if (parsed.threadId !== undefined) {\n throw new Error(\"WhatsApp does not support thread targets.\");\n }\n const nativeTo = requireWhatsAppJid(parsed.id, \"WhatsApp target\");\n requireWhatsAppTargetKind(parsed, nativeTo);\n if (nativeTo.endsWith(\"@g.us\")) {\n throw new Error(\"WhatsApp Crabline WebSocket outbound supports direct targets only.\");\n }\n const to = canonicalizeWhatsAppUserCorrelationJid(nativeTo)!;\n return {\n channel: \"whatsapp\",\n to,\n replyChannel: \"whatsapp\",\n replyTo: to,\n };\n },\n createInbound(input) {\n if (input.threadId !== undefined) {\n throw new Error(\"WhatsApp does not support thread targets.\");\n }\n const nativeChatJid = requireWhatsAppJid(input.conversation.id, \"WhatsApp conversation\");\n requireWhatsAppConversationKind(input.conversation.kind, nativeChatJid);\n const nativeSenderJid = requireWhatsAppJid(input.senderId, \"WhatsApp sender\", true);\n const providerTargetKey = canonicalizeWhatsAppChatCorrelationJid(nativeChatJid)!;\n if (\n input.conversation.kind === \"direct\" &&\n canonicalizeWhatsAppUserCorrelationJid(nativeChatJid) !==\n canonicalizeWhatsAppUserCorrelationJid(nativeSenderJid)\n ) {\n throw new Error(\n \"WhatsApp direct conversation and sender must identify the same recipient.\",\n );\n }\n return {\n ...createAdminInboundRequest(whatsapp),\n providerBody: {\n chatJid: nativeChatJid,\n senderJid: nativeSenderJid,\n ...(input.senderName ? { pushName: input.senderName } : {}),\n text: input.text,\n },\n providerTargetKey,\n qaTarget: qaTargetForInbound({\n ...input,\n conversation: { ...input.conversation, id: providerTargetKey },\n }),\n stateConversation: {\n id: nativeChatJid,\n kind: nativeChatJid.endsWith(\"@g.us\") ? \"group\" : \"direct\",\n },\n };\n },\n createOutboundFromRecorderEvent({ event, targetByProviderTarget }) {\n if (\n !isRecord(event) ||\n event.type !== \"api\" ||\n event.accepted !== true ||\n typeof event.path !== \"string\"\n ) {\n return null;\n }\n if (!isRecord(event.body)) {\n return null;\n }\n const baileysKey = isRecord(event.body.key) ? event.body.key : undefined;\n const baileysMessage = isRecord(event.body.message) ? event.body.message : undefined;\n const isBaileysSend = event.method === \"WEBSOCKET\" && event.path === \"/ws/chat\";\n const messagingProduct = readString(event.body.messaging_product);\n const messageType = readString(event.body.type);\n const isCloudTextSend =\n event.method === \"POST\" &&\n event.path === messagesPath &&\n (!(\"messaging_product\" in event.body) || messagingProduct === \"whatsapp\") &&\n (!(\"type\" in event.body) || messageType === \"text\") &&\n !(\"status\" in event.body) &&\n !(\"message_id\" in event.body);\n if (!isBaileysSend && !isCloudTextSend) {\n return null;\n }\n const to = isBaileysSend ? readString(baileysKey?.remoteJid) : readString(event.body.to);\n const textPayload = event.body.text;\n const text = isBaileysSend\n ? readNonBlankString(baileysMessage?.conversation)\n : isRecord(textPayload)\n ? readNonBlankString(textPayload.body)\n : undefined;\n if (!to || !text) {\n return null;\n }\n const providerTarget = isBaileysSend\n ? canonicalizeWhatsAppChatCorrelationJid(to)\n : (canonicalizeWhatsAppChatJid(to) ??\n (/^\\d{7,15}$/u.test(to) ? `${to}@s.whatsapp.net` : to));\n if (!providerTarget) {\n return null;\n }\n return {\n accountId: DEFAULT_ACCOUNT_ID,\n senderId: \"openclaw\",\n senderName: \"OpenClaw QA\",\n text,\n to: targetByProviderTarget.get(providerTarget) ?? providerTarget,\n };\n },\n };\n },\n});\n"]}
@@ -1,9 +1,14 @@
1
+ import { ZALO_ID_RULE, ZALO_UNSUPPORTED_THREAD_TARGET_ERROR, } from "../../providers/target-normalizers.js";
1
2
  import { createAdminInboundRequest, createOpenClawCrablineProviderBridge, DEFAULT_ACCOUNT_ID, isRecord, qaTargetForInbound, readNonBlankString, readString, } from "../shared.js";
3
+ import { throwProbeHttpError } from "./probe-response.js";
2
4
  function nativeId(value) {
3
5
  const id = value.trim();
4
6
  if (!id) {
5
7
  throw new Error("Zalo target is required.");
6
8
  }
9
+ if (!ZALO_ID_RULE.pattern.test(id)) {
10
+ throw new Error("Zalo target must be a native Zalo string id without whitespace.");
11
+ }
7
12
  return id;
8
13
  }
9
14
  export const ZALO_OPENCLAW_CRABLINE_PROVIDER_BRIDGE = createOpenClawCrablineProviderBridge({
@@ -16,7 +21,7 @@ export const ZALO_OPENCLAW_CRABLINE_PROVIDER_BRIDGE = createOpenClawCrablineProv
16
21
  ...(signal ? { signal } : {}),
17
22
  });
18
23
  if (!response.ok) {
19
- throw new Error(`Crabline Zalo getMe probe failed with HTTP ${response.status}.`);
24
+ await throwProbeHttpError(response, `Crabline Zalo getMe probe failed with HTTP ${response.status}.`);
20
25
  }
21
26
  const result = await response.json();
22
27
  const bot = isRecord(result) && isRecord(result.result) ? result.result : undefined;
@@ -32,7 +37,7 @@ export const ZALO_OPENCLAW_CRABLINE_PROVIDER_BRIDGE = createOpenClawCrablineProv
32
37
  return {
33
38
  accountId: DEFAULT_ACCOUNT_ID,
34
39
  channel: "zalo",
35
- createChannelDriverSmokeEnv: (env) => ({ ...env, ...zalo.env }),
40
+ createProviderReadinessEnv: (env) => ({ ...env, ...zalo.env }),
36
41
  createGatewayConfig: (openclawConfig = {}) => {
37
42
  const channels = isRecord(openclawConfig.channels) ? openclawConfig.channels : {};
38
43
  const zaloConfig = isRecord(channels.zalo) ? channels.zalo : {};
@@ -57,14 +62,14 @@ export const ZALO_OPENCLAW_CRABLINE_PROVIDER_BRIDGE = createOpenClawCrablineProv
57
62
  },
58
63
  createAgentDelivery(parsed) {
59
64
  if (parsed.threadId) {
60
- throw new Error("Zalo does not support thread targets.");
65
+ throw new Error(ZALO_UNSUPPORTED_THREAD_TARGET_ERROR);
61
66
  }
62
67
  const to = nativeId(parsed.id);
63
68
  return { channel: "zalo", replyChannel: "zalo", replyTo: to, to };
64
69
  },
65
70
  createInbound(input) {
66
71
  if (input.threadId) {
67
- throw new Error("Zalo does not support thread targets.");
72
+ throw new Error(ZALO_UNSUPPORTED_THREAD_TARGET_ERROR);
68
73
  }
69
74
  const kind = input.conversation.kind === "direct" ? "direct" : "group";
70
75
  const chatId = nativeId(input.conversation.id);
@@ -1 +1 @@
1
- {"version":3,"file":"zalo.js","sourceRoot":"","sources":["../../../../src/openclaw/bridges/zalo.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n createAdminInboundRequest,\n createOpenClawCrablineProviderBridge,\n DEFAULT_ACCOUNT_ID,\n isRecord,\n qaTargetForInbound,\n readNonBlankString,\n readString,\n} from \"../shared.js\";\n\nfunction nativeId(value: string): string {\n const id = value.trim();\n if (!id) {\n throw new Error(\"Zalo target is required.\");\n }\n return id;\n}\n\nexport const ZALO_OPENCLAW_CRABLINE_PROVIDER_BRIDGE = createOpenClawCrablineProviderBridge({\n provider: \"zalo\",\n createAdapter(zalo) {\n return {\n async probe(signal) {\n const response = await fetch(`${zalo.endpoints.apiRoot}/bot${zalo.botToken}/getMe`, {\n method: \"POST\",\n ...(signal ? { signal } : {}),\n });\n if (!response.ok) {\n throw new Error(`Crabline Zalo getMe probe failed with HTTP ${response.status}.`);\n }\n const result = await response.json();\n const bot = isRecord(result) && isRecord(result.result) ? result.result : undefined;\n if (!isRecord(result) || result.ok !== true || readNonBlankString(bot?.id) !== zalo.botId) {\n const detail =\n (isRecord(result) ? readNonBlankString(result.description) : undefined) ??\n (isRecord(result) ? readNonBlankString(result.error) : undefined) ??\n \"invalid response\";\n throw new Error(`Crabline Zalo getMe probe failed: ${detail}.`);\n }\n return result;\n },\n createBinding() {\n return {\n accountId: DEFAULT_ACCOUNT_ID,\n channel: \"zalo\",\n createChannelDriverSmokeEnv: (env) => ({ ...env, ...zalo.env }),\n createGatewayConfig: (openclawConfig = {}) => {\n const channels = isRecord(openclawConfig.channels) ? openclawConfig.channels : {};\n const zaloConfig = isRecord(channels.zalo) ? channels.zalo : {};\n return {\n ...openclawConfig,\n channels: {\n ...channels,\n zalo: {\n ...zaloConfig,\n allowFrom: [\"*\"],\n botToken: zalo.botToken,\n dmPolicy: \"open\",\n enabled: true,\n groupAllowFrom: [\"*\"],\n groupPolicy: \"open\",\n },\n },\n };\n },\n requiredPluginIds: [\"zalo\"],\n };\n },\n createAgentDelivery(parsed) {\n if (parsed.threadId) {\n throw new Error(\"Zalo does not support thread targets.\");\n }\n const to = nativeId(parsed.id);\n return { channel: \"zalo\", replyChannel: \"zalo\", replyTo: to, to };\n },\n createInbound(input) {\n if (input.threadId) {\n throw new Error(\"Zalo does not support thread targets.\");\n }\n const kind = input.conversation.kind === \"direct\" ? \"direct\" : \"group\";\n const chatId = nativeId(input.conversation.id);\n return {\n ...createAdminInboundRequest(zalo),\n providerBody: {\n chatId,\n chatType: kind === \"direct\" ? \"PRIVATE\" : \"GROUP\",\n senderId: nativeId(input.senderId),\n ...(input.senderName ? { senderName: input.senderName } : {}),\n text: input.text,\n },\n providerTargetKey: chatId,\n qaTarget: qaTargetForInbound(input),\n stateConversation: { id: chatId, kind },\n };\n },\n createOutboundFromRecorderEvent({ event, targetByProviderTarget }) {\n if (\n !isRecord(event) ||\n event.type !== \"api\" ||\n (event.method !== \"GET\" && event.method !== \"POST\") ||\n !isRecord(event.body) ||\n (event.path !== \"/bot<redacted>/sendMessage\" && event.path !== \"/bot<redacted>/sendPhoto\")\n ) {\n return null;\n }\n const chatId = readString(event.body.chat_id);\n const text =\n event.path === \"/bot<redacted>/sendMessage\"\n ? readNonBlankString(event.body.text)\n : readNonBlankString(event.body.caption);\n if (!chatId || !text) {\n return null;\n }\n return {\n accountId: DEFAULT_ACCOUNT_ID,\n senderId: zalo.botId,\n senderName: \"OpenClaw QA\",\n text,\n to: targetByProviderTarget.get(chatId) ?? chatId,\n };\n },\n };\n },\n});\n"]}
1
+ {"version":3,"file":"zalo.js","sourceRoot":"","sources":["../../../../src/openclaw/bridges/zalo.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n ZALO_ID_RULE,\n ZALO_UNSUPPORTED_THREAD_TARGET_ERROR,\n} from \"../../providers/target-normalizers.js\";\nimport {\n createAdminInboundRequest,\n createOpenClawCrablineProviderBridge,\n DEFAULT_ACCOUNT_ID,\n isRecord,\n qaTargetForInbound,\n readNonBlankString,\n readString,\n} from \"../shared.js\";\nimport { throwProbeHttpError } from \"./probe-response.js\";\n\nfunction nativeId(value: string): string {\n const id = value.trim();\n if (!id) {\n throw new Error(\"Zalo target is required.\");\n }\n if (!ZALO_ID_RULE.pattern.test(id)) {\n throw new Error(\"Zalo target must be a native Zalo string id without whitespace.\");\n }\n return id;\n}\n\nexport const ZALO_OPENCLAW_CRABLINE_PROVIDER_BRIDGE = createOpenClawCrablineProviderBridge({\n provider: \"zalo\",\n createAdapter(zalo) {\n return {\n async probe(signal) {\n const response = await fetch(`${zalo.endpoints.apiRoot}/bot${zalo.botToken}/getMe`, {\n method: \"POST\",\n ...(signal ? { signal } : {}),\n });\n if (!response.ok) {\n await throwProbeHttpError(\n response,\n `Crabline Zalo getMe probe failed with HTTP ${response.status}.`,\n );\n }\n const result = await response.json();\n const bot = isRecord(result) && isRecord(result.result) ? result.result : undefined;\n if (!isRecord(result) || result.ok !== true || readNonBlankString(bot?.id) !== zalo.botId) {\n const detail =\n (isRecord(result) ? readNonBlankString(result.description) : undefined) ??\n (isRecord(result) ? readNonBlankString(result.error) : undefined) ??\n \"invalid response\";\n throw new Error(`Crabline Zalo getMe probe failed: ${detail}.`);\n }\n return result;\n },\n createBinding() {\n return {\n accountId: DEFAULT_ACCOUNT_ID,\n channel: \"zalo\",\n createProviderReadinessEnv: (env) => ({ ...env, ...zalo.env }),\n createGatewayConfig: (openclawConfig = {}) => {\n const channels = isRecord(openclawConfig.channels) ? openclawConfig.channels : {};\n const zaloConfig = isRecord(channels.zalo) ? channels.zalo : {};\n return {\n ...openclawConfig,\n channels: {\n ...channels,\n zalo: {\n ...zaloConfig,\n allowFrom: [\"*\"],\n botToken: zalo.botToken,\n dmPolicy: \"open\",\n enabled: true,\n groupAllowFrom: [\"*\"],\n groupPolicy: \"open\",\n },\n },\n };\n },\n requiredPluginIds: [\"zalo\"],\n };\n },\n createAgentDelivery(parsed) {\n if (parsed.threadId) {\n throw new Error(ZALO_UNSUPPORTED_THREAD_TARGET_ERROR);\n }\n const to = nativeId(parsed.id);\n return { channel: \"zalo\", replyChannel: \"zalo\", replyTo: to, to };\n },\n createInbound(input) {\n if (input.threadId) {\n throw new Error(ZALO_UNSUPPORTED_THREAD_TARGET_ERROR);\n }\n const kind = input.conversation.kind === \"direct\" ? \"direct\" : \"group\";\n const chatId = nativeId(input.conversation.id);\n return {\n ...createAdminInboundRequest(zalo),\n providerBody: {\n chatId,\n chatType: kind === \"direct\" ? \"PRIVATE\" : \"GROUP\",\n senderId: nativeId(input.senderId),\n ...(input.senderName ? { senderName: input.senderName } : {}),\n text: input.text,\n },\n providerTargetKey: chatId,\n qaTarget: qaTargetForInbound(input),\n stateConversation: { id: chatId, kind },\n };\n },\n createOutboundFromRecorderEvent({ event, targetByProviderTarget }) {\n if (\n !isRecord(event) ||\n event.type !== \"api\" ||\n (event.method !== \"GET\" && event.method !== \"POST\") ||\n !isRecord(event.body) ||\n (event.path !== \"/bot<redacted>/sendMessage\" && event.path !== \"/bot<redacted>/sendPhoto\")\n ) {\n return null;\n }\n const chatId = readString(event.body.chat_id);\n const text =\n event.path === \"/bot<redacted>/sendMessage\"\n ? readNonBlankString(event.body.text)\n : readNonBlankString(event.body.caption);\n if (!chatId || !text) {\n return null;\n }\n return {\n accountId: DEFAULT_ACCOUNT_ID,\n senderId: zalo.botId,\n senderName: \"OpenClaw QA\",\n text,\n to: targetByProviderTarget.get(chatId) ?? chatId,\n };\n },\n };\n },\n});\n"]}
@@ -3,6 +3,7 @@ import { isRecord, readNonBlankString } from "./shared.js";
3
3
  const MATRIX_SEND_PATH_RE = /^\/_matrix\/client\/(?:v3|r0)\/rooms\/[^/]+\/send\/m\.room\.message\/[^/]+$/u;
4
4
  const TELEGRAM_SEND_PATH_RE = /^\/bot<redacted>\/(?:sendAnimation|sendAudio|sendDocument|sendMessage|sendPhoto|sendVideo)$/iu;
5
5
  const ZALO_SEND_PATH_RE = /^\/bot<redacted>\/(?:sendMessage|sendPhoto)$/u;
6
+ const DISCORD_SEND_PATH_RE = /^\/api\/v10\/channels\/\d{17,20}\/messages$/u;
6
7
  export function isAcceptedOpenClawCrablineOutbound(params) {
7
8
  if (!isRecord(params.event) || params.event.type !== "api" || params.event.accepted !== true) {
8
9
  return false;
@@ -13,6 +14,8 @@ export function isAcceptedOpenClawCrablineOutbound(params) {
13
14
  return false;
14
15
  }
15
16
  switch (params.manifest.provider) {
17
+ case "discord":
18
+ return method === "POST" && DISCORD_SEND_PATH_RE.test(requestPath);
16
19
  case "mattermost":
17
20
  return method === "POST" && requestPath === "/api/v4/posts";
18
21
  case "matrix":
@@ -1 +1 @@
1
- {"version":3,"file":"outbound-contract.js","sourceRoot":"","sources":["../../../src/openclaw/outbound-contract.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,sCAAsC,EAAE,MAAM,4BAA4B,CAAC;AACpF,OAAO,EAAE,QAAQ,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAE3D,MAAM,mBAAmB,GACvB,8EAA8E,CAAC;AACjF,MAAM,qBAAqB,GACzB,+FAA+F,CAAC;AAClG,MAAM,iBAAiB,GAAG,+CAA+C,CAAC;AAE1E,MAAM,UAAU,kCAAkC,CAAC,MAGlD;IACC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,MAAM,CAAC,KAAK,CAAC,IAAI,KAAK,KAAK,IAAI,MAAM,CAAC,KAAK,CAAC,QAAQ,KAAK,IAAI,EAAE,CAAC;QAC7F,OAAO,KAAK,CAAC;IACf,CAAC;IACD,MAAM,MAAM,GAAG,kBAAkB,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IACvD,MAAM,WAAW,GAAG,kBAAkB,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC1D,IAAI,CAAC,MAAM,IAAI,CAAC,WAAW,EAAE,CAAC;QAC5B,OAAO,KAAK,CAAC;IACf,CAAC;IAED,QAAQ,MAAM,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC;QACjC,KAAK,YAAY;YACf,OAAO,MAAM,KAAK,MAAM,IAAI,WAAW,KAAK,eAAe,CAAC;QAC9D,KAAK,QAAQ;YACX,OAAO,MAAM,KAAK,KAAK,IAAI,mBAAmB,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QACnE,KAAK,QAAQ;YACX,OAAO,MAAM,KAAK,MAAM,IAAI,WAAW,KAAK,aAAa,CAAC;QAC5D,KAAK,OAAO;YACV,OAAO,MAAM,KAAK,MAAM,IAAI,WAAW,KAAK,uBAAuB,CAAC;QACtE,KAAK,UAAU;YACb,OAAO,CAAC,MAAM,KAAK,KAAK,IAAI,MAAM,KAAK,MAAM,CAAC,IAAI,qBAAqB,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QAC5F,KAAK,UAAU,EAAE,CAAC;YAChB,MAAM,YAAY,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC,QAAQ,CAAC;YAC7E,MAAM,IAAI,GAAG,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC;YACzE,MAAM,GAAG,GAAG,QAAQ,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC;YACvD,MAAM,qBAAqB,GAAG,sCAAsC,CAClE,kBAAkB,CAAC,GAAG,EAAE,SAAS,CAAC,IAAI,EAAE,CACzC,CAAC;YACF,OAAO,CACL,CAAC,MAAM,KAAK,MAAM,IAAI,WAAW,KAAK,YAAY,CAAC;gBACnD,CAAC,MAAM,KAAK,WAAW;oBACrB,WAAW,KAAK,UAAU;oBAC1B,qBAAqB,KAAK,SAAS,CAAC,CACvC,CAAC;QACJ,CAAC;QACD,KAAK,MAAM;YACT,OAAO,CAAC,MAAM,KAAK,KAAK,IAAI,MAAM,KAAK,MAAM,CAAC,IAAI,iBAAiB,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IAC1F,CAAC;AACH,CAAC","sourcesContent":["import type { CrablineServerManifest } from \"../servers/index.js\";\nimport { canonicalizeWhatsAppUserCorrelationJid } from \"../servers/whatsapp-jid.js\";\nimport { isRecord, readNonBlankString } from \"./shared.js\";\n\nconst MATRIX_SEND_PATH_RE =\n /^\\/_matrix\\/client\\/(?:v3|r0)\\/rooms\\/[^/]+\\/send\\/m\\.room\\.message\\/[^/]+$/u;\nconst TELEGRAM_SEND_PATH_RE =\n /^\\/bot<redacted>\\/(?:sendAnimation|sendAudio|sendDocument|sendMessage|sendPhoto|sendVideo)$/iu;\nconst ZALO_SEND_PATH_RE = /^\\/bot<redacted>\\/(?:sendMessage|sendPhoto)$/u;\n\nexport function isAcceptedOpenClawCrablineOutbound(params: {\n event: unknown;\n manifest: CrablineServerManifest;\n}): boolean {\n if (!isRecord(params.event) || params.event.type !== \"api\" || params.event.accepted !== true) {\n return false;\n }\n const method = readNonBlankString(params.event.method);\n const requestPath = readNonBlankString(params.event.path);\n if (!method || !requestPath) {\n return false;\n }\n\n switch (params.manifest.provider) {\n case \"mattermost\":\n return method === \"POST\" && requestPath === \"/api/v4/posts\";\n case \"matrix\":\n return method === \"PUT\" && MATRIX_SEND_PATH_RE.test(requestPath);\n case \"signal\":\n return method === \"POST\" && requestPath === \"/api/v1/rpc\";\n case \"slack\":\n return method === \"POST\" && requestPath === \"/api/chat.postMessage\";\n case \"telegram\":\n return (method === \"GET\" || method === \"POST\") && TELEGRAM_SEND_PATH_RE.test(requestPath);\n case \"whatsapp\": {\n const messagesPath = new URL(params.manifest.endpoints.messagesUrl).pathname;\n const body = isRecord(params.event.body) ? params.event.body : undefined;\n const key = isRecord(body?.key) ? body.key : undefined;\n const directWebSocketTarget = canonicalizeWhatsAppUserCorrelationJid(\n readNonBlankString(key?.remoteJid) ?? \"\",\n );\n return (\n (method === \"POST\" && requestPath === messagesPath) ||\n (method === \"WEBSOCKET\" &&\n requestPath === \"/ws/chat\" &&\n directWebSocketTarget !== undefined)\n );\n }\n case \"zalo\":\n return (method === \"GET\" || method === \"POST\") && ZALO_SEND_PATH_RE.test(requestPath);\n }\n}\n"]}
1
+ {"version":3,"file":"outbound-contract.js","sourceRoot":"","sources":["../../../src/openclaw/outbound-contract.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,sCAAsC,EAAE,MAAM,4BAA4B,CAAC;AACpF,OAAO,EAAE,QAAQ,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAE3D,MAAM,mBAAmB,GACvB,8EAA8E,CAAC;AACjF,MAAM,qBAAqB,GACzB,+FAA+F,CAAC;AAClG,MAAM,iBAAiB,GAAG,+CAA+C,CAAC;AAC1E,MAAM,oBAAoB,GAAG,8CAA8C,CAAC;AAE5E,MAAM,UAAU,kCAAkC,CAAC,MAGlD;IACC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,MAAM,CAAC,KAAK,CAAC,IAAI,KAAK,KAAK,IAAI,MAAM,CAAC,KAAK,CAAC,QAAQ,KAAK,IAAI,EAAE,CAAC;QAC7F,OAAO,KAAK,CAAC;IACf,CAAC;IACD,MAAM,MAAM,GAAG,kBAAkB,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IACvD,MAAM,WAAW,GAAG,kBAAkB,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC1D,IAAI,CAAC,MAAM,IAAI,CAAC,WAAW,EAAE,CAAC;QAC5B,OAAO,KAAK,CAAC;IACf,CAAC;IAED,QAAQ,MAAM,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC;QACjC,KAAK,SAAS;YACZ,OAAO,MAAM,KAAK,MAAM,IAAI,oBAAoB,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QACrE,KAAK,YAAY;YACf,OAAO,MAAM,KAAK,MAAM,IAAI,WAAW,KAAK,eAAe,CAAC;QAC9D,KAAK,QAAQ;YACX,OAAO,MAAM,KAAK,KAAK,IAAI,mBAAmB,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QACnE,KAAK,QAAQ;YACX,OAAO,MAAM,KAAK,MAAM,IAAI,WAAW,KAAK,aAAa,CAAC;QAC5D,KAAK,OAAO;YACV,OAAO,MAAM,KAAK,MAAM,IAAI,WAAW,KAAK,uBAAuB,CAAC;QACtE,KAAK,UAAU;YACb,OAAO,CAAC,MAAM,KAAK,KAAK,IAAI,MAAM,KAAK,MAAM,CAAC,IAAI,qBAAqB,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QAC5F,KAAK,UAAU,EAAE,CAAC;YAChB,MAAM,YAAY,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC,QAAQ,CAAC;YAC7E,MAAM,IAAI,GAAG,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC;YACzE,MAAM,GAAG,GAAG,QAAQ,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC;YACvD,MAAM,qBAAqB,GAAG,sCAAsC,CAClE,kBAAkB,CAAC,GAAG,EAAE,SAAS,CAAC,IAAI,EAAE,CACzC,CAAC;YACF,OAAO,CACL,CAAC,MAAM,KAAK,MAAM,IAAI,WAAW,KAAK,YAAY,CAAC;gBACnD,CAAC,MAAM,KAAK,WAAW;oBACrB,WAAW,KAAK,UAAU;oBAC1B,qBAAqB,KAAK,SAAS,CAAC,CACvC,CAAC;QACJ,CAAC;QACD,KAAK,MAAM;YACT,OAAO,CAAC,MAAM,KAAK,KAAK,IAAI,MAAM,KAAK,MAAM,CAAC,IAAI,iBAAiB,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IAC1F,CAAC;AACH,CAAC","sourcesContent":["import type { CrablineServerManifest } from \"../servers/index.js\";\nimport { canonicalizeWhatsAppUserCorrelationJid } from \"../servers/whatsapp-jid.js\";\nimport { isRecord, readNonBlankString } from \"./shared.js\";\n\nconst MATRIX_SEND_PATH_RE =\n /^\\/_matrix\\/client\\/(?:v3|r0)\\/rooms\\/[^/]+\\/send\\/m\\.room\\.message\\/[^/]+$/u;\nconst TELEGRAM_SEND_PATH_RE =\n /^\\/bot<redacted>\\/(?:sendAnimation|sendAudio|sendDocument|sendMessage|sendPhoto|sendVideo)$/iu;\nconst ZALO_SEND_PATH_RE = /^\\/bot<redacted>\\/(?:sendMessage|sendPhoto)$/u;\nconst DISCORD_SEND_PATH_RE = /^\\/api\\/v10\\/channels\\/\\d{17,20}\\/messages$/u;\n\nexport function isAcceptedOpenClawCrablineOutbound(params: {\n event: unknown;\n manifest: CrablineServerManifest;\n}): boolean {\n if (!isRecord(params.event) || params.event.type !== \"api\" || params.event.accepted !== true) {\n return false;\n }\n const method = readNonBlankString(params.event.method);\n const requestPath = readNonBlankString(params.event.path);\n if (!method || !requestPath) {\n return false;\n }\n\n switch (params.manifest.provider) {\n case \"discord\":\n return method === \"POST\" && DISCORD_SEND_PATH_RE.test(requestPath);\n case \"mattermost\":\n return method === \"POST\" && requestPath === \"/api/v4/posts\";\n case \"matrix\":\n return method === \"PUT\" && MATRIX_SEND_PATH_RE.test(requestPath);\n case \"signal\":\n return method === \"POST\" && requestPath === \"/api/v1/rpc\";\n case \"slack\":\n return method === \"POST\" && requestPath === \"/api/chat.postMessage\";\n case \"telegram\":\n return (method === \"GET\" || method === \"POST\") && TELEGRAM_SEND_PATH_RE.test(requestPath);\n case \"whatsapp\": {\n const messagesPath = new URL(params.manifest.endpoints.messagesUrl).pathname;\n const body = isRecord(params.event.body) ? params.event.body : undefined;\n const key = isRecord(body?.key) ? body.key : undefined;\n const directWebSocketTarget = canonicalizeWhatsAppUserCorrelationJid(\n readNonBlankString(key?.remoteJid) ?? \"\",\n );\n return (\n (method === \"POST\" && requestPath === messagesPath) ||\n (method === \"WEBSOCKET\" &&\n requestPath === \"/ws/chat\" &&\n directWebSocketTarget !== undefined)\n );\n }\n case \"zalo\":\n return (method === \"GET\" || method === \"POST\") && ZALO_SEND_PATH_RE.test(requestPath);\n }\n}\n"]}