@openclaw/crabline 0.1.9 → 0.1.10

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 (189) hide show
  1. package/README.md +47 -22
  2. package/assets/crabline-banner.svg +20 -0
  3. package/dist/src/bin/crabline.js.map +1 -1
  4. package/dist/src/cli/program.d.ts +25 -1
  5. package/dist/src/cli/program.js +579 -82
  6. package/dist/src/cli/program.js.map +1 -1
  7. package/dist/src/config/load.js +59 -6
  8. package/dist/src/config/load.js.map +1 -1
  9. package/dist/src/config/schema.d.ts +116 -92
  10. package/dist/src/config/schema.js +179 -73
  11. package/dist/src/config/schema.js.map +1 -1
  12. package/dist/src/core/errors.js +9 -2
  13. package/dist/src/core/errors.js.map +1 -1
  14. package/dist/src/core/exit-codes.js.map +1 -1
  15. package/dist/src/core/matcher.js +7 -6
  16. package/dist/src/core/matcher.js.map +1 -1
  17. package/dist/src/core/message-template.js.map +1 -1
  18. package/dist/src/core/nonces.d.ts +1 -0
  19. package/dist/src/core/nonces.js +4 -2
  20. package/dist/src/core/nonces.js.map +1 -1
  21. package/dist/src/core/reporters.d.ts +1 -0
  22. package/dist/src/core/reporters.js +42 -4
  23. package/dist/src/core/reporters.js.map +1 -1
  24. package/dist/src/core/run.d.ts +3 -0
  25. package/dist/src/core/run.js +415 -107
  26. package/dist/src/core/run.js.map +1 -1
  27. package/dist/src/core/safe-regex.d.ts +3 -0
  28. package/dist/src/core/safe-regex.js +21 -0
  29. package/dist/src/core/safe-regex.js.map +1 -0
  30. package/dist/src/index.d.ts +2 -2
  31. package/dist/src/index.js +1 -1
  32. package/dist/src/index.js.map +1 -1
  33. package/dist/src/openclaw/artifact-generation.d.ts +38 -0
  34. package/dist/src/openclaw/artifact-generation.js +314 -0
  35. package/dist/src/openclaw/artifact-generation.js.map +1 -0
  36. package/dist/src/openclaw/bridges/matrix.js +97 -12
  37. package/dist/src/openclaw/bridges/matrix.js.map +1 -1
  38. package/dist/src/openclaw/bridges/mattermost.js +32 -10
  39. package/dist/src/openclaw/bridges/mattermost.js.map +1 -1
  40. package/dist/src/openclaw/bridges/signal.js +55 -18
  41. package/dist/src/openclaw/bridges/signal.js.map +1 -1
  42. package/dist/src/openclaw/bridges/slack.js +85 -7
  43. package/dist/src/openclaw/bridges/slack.js.map +1 -1
  44. package/dist/src/openclaw/bridges/telegram.js +124 -30
  45. package/dist/src/openclaw/bridges/telegram.js.map +1 -1
  46. package/dist/src/openclaw/bridges/whatsapp.js +78 -17
  47. package/dist/src/openclaw/bridges/whatsapp.js.map +1 -1
  48. package/dist/src/openclaw/bridges/zalo.js +14 -5
  49. package/dist/src/openclaw/bridges/zalo.js.map +1 -1
  50. package/dist/src/openclaw/outbound-contract.d.ts +5 -0
  51. package/dist/src/openclaw/outbound-contract.js +40 -0
  52. package/dist/src/openclaw/outbound-contract.js.map +1 -0
  53. package/dist/src/openclaw/private-file.d.ts +26 -0
  54. package/dist/src/openclaw/private-file.js +411 -0
  55. package/dist/src/openclaw/private-file.js.map +1 -0
  56. package/dist/src/openclaw/shared.d.ts +21 -2
  57. package/dist/src/openclaw/shared.js +115 -18
  58. package/dist/src/openclaw/shared.js.map +1 -1
  59. package/dist/src/openclaw/smoke-lock.d.ts +63 -0
  60. package/dist/src/openclaw/smoke-lock.js +949 -0
  61. package/dist/src/openclaw/smoke-lock.js.map +1 -0
  62. package/dist/src/openclaw.d.ts +16 -8
  63. package/dist/src/openclaw.js +194 -52
  64. package/dist/src/openclaw.js.map +1 -1
  65. package/dist/src/providers/builtin/discord.d.ts +10 -1
  66. package/dist/src/providers/builtin/discord.js +144 -18
  67. package/dist/src/providers/builtin/discord.js.map +1 -1
  68. package/dist/src/providers/builtin/external-webhook-auth.d.ts +11 -0
  69. package/dist/src/providers/builtin/external-webhook-auth.js +10 -0
  70. package/dist/src/providers/builtin/external-webhook-auth.js.map +1 -0
  71. package/dist/src/providers/builtin/feishu.d.ts +19 -2
  72. package/dist/src/providers/builtin/feishu.js +307 -25
  73. package/dist/src/providers/builtin/feishu.js.map +1 -1
  74. package/dist/src/providers/builtin/googlechat.d.ts +20 -1
  75. package/dist/src/providers/builtin/googlechat.js +178 -19
  76. package/dist/src/providers/builtin/googlechat.js.map +1 -1
  77. package/dist/src/providers/builtin/imessage.d.ts +4 -0
  78. package/dist/src/providers/builtin/imessage.js +26 -11
  79. package/dist/src/providers/builtin/imessage.js.map +1 -1
  80. package/dist/src/providers/builtin/loopback.js +92 -30
  81. package/dist/src/providers/builtin/loopback.js.map +1 -1
  82. package/dist/src/providers/builtin/matrix.d.ts +11 -1
  83. package/dist/src/providers/builtin/matrix.js +53 -29
  84. package/dist/src/providers/builtin/matrix.js.map +1 -1
  85. package/dist/src/providers/builtin/mattermost.d.ts +10 -0
  86. package/dist/src/providers/builtin/mattermost.js +38 -15
  87. package/dist/src/providers/builtin/mattermost.js.map +1 -1
  88. package/dist/src/providers/builtin/msteams.d.ts +17 -1
  89. package/dist/src/providers/builtin/msteams.js +113 -14
  90. package/dist/src/providers/builtin/msteams.js.map +1 -1
  91. package/dist/src/providers/builtin/native-local-mock.d.ts +2 -9
  92. package/dist/src/providers/builtin/native-local-mock.js +12 -35
  93. package/dist/src/providers/builtin/native-local-mock.js.map +1 -1
  94. package/dist/src/providers/builtin/script.d.ts +11 -15
  95. package/dist/src/providers/builtin/script.js +566 -104
  96. package/dist/src/providers/builtin/script.js.map +1 -1
  97. package/dist/src/providers/builtin/slack.d.ts +6 -0
  98. package/dist/src/providers/builtin/slack.js +99 -40
  99. package/dist/src/providers/builtin/slack.js.map +1 -1
  100. package/dist/src/providers/builtin/telegram.d.ts +6 -0
  101. package/dist/src/providers/builtin/telegram.js +64 -43
  102. package/dist/src/providers/builtin/telegram.js.map +1 -1
  103. package/dist/src/providers/builtin/whatsapp.d.ts +28 -8
  104. package/dist/src/providers/builtin/whatsapp.js +567 -30
  105. package/dist/src/providers/builtin/whatsapp.js.map +1 -1
  106. package/dist/src/providers/builtin/zalo.js +30 -19
  107. package/dist/src/providers/builtin/zalo.js.map +1 -1
  108. package/dist/src/providers/catalog.d.ts +3 -3
  109. package/dist/src/providers/catalog.js +3 -3
  110. package/dist/src/providers/catalog.js.map +1 -1
  111. package/dist/src/providers/local-mock.d.ts +11 -2
  112. package/dist/src/providers/local-mock.js +322 -96
  113. package/dist/src/providers/local-mock.js.map +1 -1
  114. package/dist/src/providers/native-ids.d.ts +1 -0
  115. package/dist/src/providers/native-ids.js +6 -1
  116. package/dist/src/providers/native-ids.js.map +1 -1
  117. package/dist/src/providers/recorder.d.ts +30 -2
  118. package/dist/src/providers/recorder.js +539 -70
  119. package/dist/src/providers/recorder.js.map +1 -1
  120. package/dist/src/providers/registry.d.ts +25 -1
  121. package/dist/src/providers/registry.js +280 -40
  122. package/dist/src/providers/registry.js.map +1 -1
  123. package/dist/src/providers/signed-jwt.d.ts +29 -0
  124. package/dist/src/providers/signed-jwt.js +202 -0
  125. package/dist/src/providers/signed-jwt.js.map +1 -0
  126. package/dist/src/providers/slack-ids.js.map +1 -1
  127. package/dist/src/providers/target-normalizers.d.ts +26 -0
  128. package/dist/src/providers/target-normalizers.js +276 -0
  129. package/dist/src/providers/target-normalizers.js.map +1 -0
  130. package/dist/src/providers/types.d.ts +5 -0
  131. package/dist/src/providers/types.js.map +1 -1
  132. package/dist/src/providers/webhook-server.d.ts +2 -0
  133. package/dist/src/providers/webhook-server.js +72 -25
  134. package/dist/src/providers/webhook-server.js.map +1 -1
  135. package/dist/src/servers/http.d.ts +23 -3
  136. package/dist/src/servers/http.js +213 -20
  137. package/dist/src/servers/http.js.map +1 -1
  138. package/dist/src/servers/index.js +20 -21
  139. package/dist/src/servers/index.js.map +1 -1
  140. package/dist/src/servers/matrix.js +465 -51
  141. package/dist/src/servers/matrix.js.map +1 -1
  142. package/dist/src/servers/mattermost.d.ts +5 -0
  143. package/dist/src/servers/mattermost.js +306 -58
  144. package/dist/src/servers/mattermost.js.map +1 -1
  145. package/dist/src/servers/pending-events.d.ts +2 -0
  146. package/dist/src/servers/pending-events.js +11 -0
  147. package/dist/src/servers/pending-events.js.map +1 -0
  148. package/dist/src/servers/recorder.d.ts +5 -0
  149. package/dist/src/servers/recorder.js +46 -3
  150. package/dist/src/servers/recorder.js.map +1 -1
  151. package/dist/src/servers/signal.d.ts +2 -0
  152. package/dist/src/servers/signal.js +444 -56
  153. package/dist/src/servers/signal.js.map +1 -1
  154. package/dist/src/servers/slack.d.ts +5 -0
  155. package/dist/src/servers/slack.js +515 -49
  156. package/dist/src/servers/slack.js.map +1 -1
  157. package/dist/src/servers/telegram.d.ts +111 -0
  158. package/dist/src/servers/telegram.js +811 -152
  159. package/dist/src/servers/telegram.js.map +1 -1
  160. package/dist/src/servers/webhook-target.d.ts +40 -0
  161. package/dist/src/servers/webhook-target.js +349 -0
  162. package/dist/src/servers/webhook-target.js.map +1 -0
  163. package/dist/src/servers/websocket.d.ts +2 -0
  164. package/dist/src/servers/websocket.js +29 -0
  165. package/dist/src/servers/websocket.js.map +1 -0
  166. package/dist/src/servers/whatsapp-baileys-websocket.d.ts +65 -1
  167. package/dist/src/servers/whatsapp-baileys-websocket.js +723 -99
  168. package/dist/src/servers/whatsapp-baileys-websocket.js.map +1 -1
  169. package/dist/src/servers/whatsapp-jid.d.ts +5 -0
  170. package/dist/src/servers/whatsapp-jid.js +32 -0
  171. package/dist/src/servers/whatsapp-jid.js.map +1 -0
  172. package/dist/src/servers/whatsapp-wire/binary-node.d.ts +5 -0
  173. package/dist/src/servers/whatsapp-wire/binary-node.js +87 -20
  174. package/dist/src/servers/whatsapp-wire/binary-node.js.map +1 -1
  175. package/dist/src/servers/whatsapp-wire/crypto.d.ts +6 -1
  176. package/dist/src/servers/whatsapp-wire/crypto.js +99 -45
  177. package/dist/src/servers/whatsapp-wire/crypto.js.map +1 -1
  178. package/dist/src/servers/whatsapp-wire/handshake.js +39 -4
  179. package/dist/src/servers/whatsapp-wire/handshake.js.map +1 -1
  180. package/dist/src/servers/whatsapp-wire/signal.js.map +1 -1
  181. package/dist/src/servers/whatsapp.d.ts +12 -7
  182. package/dist/src/servers/whatsapp.js +269 -107
  183. package/dist/src/servers/whatsapp.js.map +1 -1
  184. package/dist/src/servers/zalo.d.ts +14 -0
  185. package/dist/src/servers/zalo.js +521 -88
  186. package/dist/src/servers/zalo.js.map +1 -1
  187. package/docs/channel-setup.md +197 -19
  188. package/fixtures/examples/crabline.example.yaml +10 -0
  189. package/package.json +20 -15
@@ -1 +1 @@
1
- {"version":3,"file":"loopback.js","sourceRoot":"","sources":["../../../../src/providers/builtin/loopback.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"loopback.js","sourceRoot":"","sources":["../../../../src/providers/builtin/loopback.ts"],"names":[],"mappings":"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","sourcesContent":["import { randomUUID } from \"node:crypto\";\nimport path from \"node:path\";\nimport { CrablineError } from \"../../core/errors.js\";\nimport type { ProviderConfig } from \"../../config/schema.js\";\nimport { LocalMockProviderAdapter } from \"../local-mock.js\";\nimport { getBuiltinTargetCodec } from \"../target-normalizers.js\";\nimport type { LoopbackMessage, LoopbackRawMessage, ProviderAdapter } from \"../types.js\";\n\ntype ThreadAddress = {\n channelId?: string | undefined;\n id: string;\n threadId?: string | undefined;\n};\n\ntype PostableMessage =\n | string\n | { card: unknown; fallbackText?: string }\n | { markdown: string }\n | { raw: string };\n\ntype StoredLoopbackMessage = {\n message: LoopbackMessage;\n sequence: number;\n};\n\nfunction createMessageId(): string {\n return `loopback-mock-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;\n}\n\nfunction cloneRawMessage(raw: LoopbackRawMessage): LoopbackRawMessage {\n return { ...raw };\n}\n\nfunction cloneMessage(message: LoopbackMessage): LoopbackMessage {\n return {\n ...message,\n author: { ...message.author },\n metadata: {\n dateSent: new Date(message.metadata.dateSent),\n edited: message.metadata.edited,\n ...(message.metadata.editedAt ? { editedAt: new Date(message.metadata.editedAt) } : {}),\n },\n raw: cloneRawMessage(message.raw),\n };\n}\n\nfunction toPostableText(message: PostableMessage): string {\n if (typeof message === \"string\") {\n return message;\n }\n if (\"raw\" in message) {\n return message.raw;\n }\n if (\"markdown\" in message) {\n return message.markdown;\n }\n return message.fallbackText ?? \"[card]\";\n}\n\nexport class LoopbackChatAdapter {\n readonly name = \"loopback\";\n readonly persistMessageHistory = true;\n readonly userName;\n\n readonly #messages = new Map<string, StoredLoopbackMessage[]>();\n readonly #nextSequence = new Map<string, number>();\n\n constructor(userName: string) {\n this.userName = userName;\n }\n\n addReaction(): Promise<void> {\n return Promise.resolve();\n }\n\n channelIdFromThreadId(threadId: string): string {\n const [address = threadId] = threadId.split(\"::\");\n if (!address.startsWith(\"loopback+v2:\")) {\n return address;\n }\n return this.decodeThreadId(threadId).channelId ?? address;\n }\n\n decodeThreadId(threadId: string): ThreadAddress {\n const [address = threadId, rawThreadId] = threadId.split(\"::\");\n const [platform, rawChannelOrId, rawId] = address.split(\":\");\n if (platform !== \"loopback+v2\" || !rawChannelOrId) {\n const [, channelId = address, id = address] = address.split(\":\");\n const decoded: ThreadAddress = { id };\n if (channelId) {\n decoded.channelId = channelId;\n }\n if (rawThreadId) {\n decoded.threadId = rawThreadId;\n }\n return decoded;\n }\n\n const decoded: ThreadAddress = {\n id: decodeURIComponent(rawId ?? rawChannelOrId),\n };\n if (rawId) {\n decoded.channelId = decodeURIComponent(rawChannelOrId);\n }\n if (rawThreadId) {\n decoded.threadId = decodeURIComponent(rawThreadId);\n }\n return decoded;\n }\n\n deleteMessage(threadId: string, messageId: string): Promise<void> {\n const messages = this.#messages.get(threadId) ?? [];\n this.#messages.set(\n threadId,\n messages.filter((entry) => entry.message.id !== messageId),\n );\n return Promise.resolve();\n }\n\n editMessage(\n threadId: string,\n messageId: string,\n message: PostableMessage,\n ): Promise<{ id: string; raw: LoopbackRawMessage; threadId: string }> {\n const messages = this.#messages.get(threadId) ?? [];\n const stored = messages.find((entry) => entry.message.id === messageId);\n if (!stored) {\n throw new CrablineError(`Loopback message not found: ${messageId}`, { kind: \"inbound\" });\n }\n\n const existing = stored.message;\n const text = toPostableText(message);\n existing.text = text;\n existing.formatted = text;\n existing.metadata.edited = true;\n existing.metadata.editedAt = new Date();\n existing.raw.text = text;\n return Promise.resolve({ id: existing.id, raw: cloneRawMessage(existing.raw), threadId });\n }\n\n encodeThreadId(platformData: ThreadAddress): string {\n const address = platformData.channelId\n ? `loopback+v2:${encodeURIComponent(platformData.channelId)}:${encodeURIComponent(platformData.id)}`\n : `loopback+v2:${encodeURIComponent(platformData.id)}`;\n return platformData.threadId\n ? `${address}::${encodeURIComponent(platformData.threadId)}`\n : address;\n }\n\n fetchMessages(\n threadId: string,\n options?: { cursor?: string; limit?: number },\n ): Promise<{ messages: LoopbackMessage[]; nextCursor?: string }> {\n const storedMessages = [...(this.#messages.get(threadId) ?? [])];\n if (\n options?.limit !== undefined &&\n (!Number.isSafeInteger(options.limit) || options.limit <= 0)\n ) {\n throw new CrablineError(\"Loopback message limit must be a positive safe integer.\", {\n kind: \"config\",\n });\n }\n const limit = options?.limit ?? storedMessages.length;\n let cursor: number | undefined;\n if (options?.cursor) {\n if (!/^[1-9]\\d*$/u.test(options.cursor)) {\n throw new CrablineError(\"Loopback message cursor must be a positive safe integer.\", {\n kind: \"config\",\n });\n }\n cursor = Number(options.cursor);\n if (!Number.isSafeInteger(cursor) || cursor > (this.#nextSequence.get(threadId) ?? 0)) {\n throw new CrablineError(\n \"Loopback message cursor must be a positive safe integer within message history.\",\n { kind: \"config\" },\n );\n }\n }\n\n const eligibleMessages =\n cursor === undefined\n ? storedMessages\n : storedMessages.filter((entry) => entry.sequence < cursor);\n const page = eligibleMessages.slice(-limit);\n const result: { messages: LoopbackMessage[]; nextCursor?: string } = {\n messages: page.map((entry) => cloneMessage(entry.message)),\n };\n if (eligibleMessages.length > page.length && page[0]) {\n result.nextCursor = String(page[0].sequence);\n }\n return Promise.resolve(result);\n }\n\n fetchThread(threadId: string) {\n return Promise.resolve({\n channelId: this.channelIdFromThreadId(threadId),\n id: threadId,\n isDM: true,\n metadata: {},\n });\n }\n\n handleWebhook(_request?: Request): Promise<Response> {\n return Promise.resolve(\n new Response(\"loopback adapter has no webhook surface\", { status: 501 }),\n );\n }\n\n isDM(): boolean {\n return true;\n }\n\n parseMessage(raw: LoopbackRawMessage): LoopbackMessage {\n return {\n author: {\n isMe: raw.author === \"assistant\",\n userName: raw.author === \"assistant\" ? this.userName : \"loopback\",\n },\n formatted: raw.text,\n id: raw.id,\n metadata: {\n dateSent: new Date(raw.timestamp),\n edited: false,\n },\n raw: cloneRawMessage(raw),\n text: raw.text,\n threadId: raw.threadId,\n };\n }\n\n postMessage(\n threadId: string,\n message: PostableMessage,\n ): Promise<{ id: string; raw: LoopbackRawMessage; threadId: string }> {\n const text = toPostableText(message);\n const raw = {\n author: \"assistant\",\n id: createMessageId(),\n text,\n threadId,\n timestamp: new Date().toISOString(),\n } satisfies LoopbackRawMessage;\n const parsed = this.parseMessage(raw);\n this.#append(threadId, parsed);\n return Promise.resolve({ id: raw.id, raw: cloneRawMessage(raw), threadId });\n }\n\n removeReaction(): Promise<void> {\n return Promise.resolve();\n }\n\n renderFormatted(content: string): string {\n return content;\n }\n\n startTyping(): Promise<void> {\n return Promise.resolve();\n }\n\n ingestUserMessage(threadId: string, text: string): LoopbackMessage {\n const raw = {\n author: \"user\",\n id: createMessageId(),\n text,\n threadId,\n timestamp: new Date().toISOString(),\n } satisfies LoopbackRawMessage;\n const parsed = this.parseMessage(raw);\n this.#append(threadId, parsed);\n return cloneMessage(parsed);\n }\n\n listSince(threadId: string, since: string): LoopbackMessage[] {\n const sinceTime = new Date(since).getTime();\n return (this.#messages.get(threadId) ?? [])\n .map((entry) => entry.message)\n .filter((message) => message.metadata.dateSent.getTime() >= sinceTime)\n .map(cloneMessage);\n }\n\n #append(threadId: string, message: LoopbackMessage): void {\n const bucket = this.#messages.get(threadId) ?? [];\n const sequence = (this.#nextSequence.get(threadId) ?? 0) + 1;\n bucket.push({ message: cloneMessage(message), sequence });\n this.#messages.set(threadId, bucket);\n this.#nextSequence.set(threadId, sequence);\n }\n}\n\nexport class LoopbackProviderAdapter extends LocalMockProviderAdapter implements ProviderAdapter {\n constructor(id: string, config: ProviderConfig, _userName: string) {\n super({\n codec: getBuiltinTargetCodec(\"loopback\"),\n config,\n id,\n options: {\n defaultWebhook: { host: \"127.0.0.1\", path: \"/loopback/webhook\", port: 0 },\n endpointLabel: \"webhook endpoint\",\n platform: \"loopback\",\n recorderPath: path.resolve(\".crabline\", \"recorders\", `${id}-${randomUUID()}.jsonl`),\n },\n });\n }\n}\n"]}
@@ -17,5 +17,15 @@ export declare function resolveMatrixAdapterConfig(config: ProviderConfig, userN
17
17
  recoveryKey: string | undefined;
18
18
  };
19
19
  export declare class MatrixProviderAdapter extends LocalMockProviderAdapter implements ProviderAdapter {
20
- constructor(id: string, config: ProviderConfig, _userName: string, _runtime?: unknown);
20
+ constructor(id: string, config: ProviderConfig, userName: string, _runtime?: unknown);
21
21
  }
22
+ export declare function matchesMatrixThread(candidateThreadId: string, expectedThreadId: string | undefined, target: {
23
+ channelId?: string | undefined;
24
+ }): boolean;
25
+ export declare function normalizeMatrixWebhookPayload(payload: unknown, botUserId?: string): {
26
+ author?: "assistant" | "system" | "user" | undefined;
27
+ authorIsBot?: boolean;
28
+ id?: string | undefined;
29
+ raw: {};
30
+ text?: string | undefined;
31
+ };
@@ -1,23 +1,15 @@
1
1
  import path from "node:path";
2
2
  import { CrablineError } from "../../core/errors.js";
3
3
  import { LocalMockProviderAdapter } from "../local-mock.js";
4
- import { authorFromBotFlag, createNativeTargetCodec, genericMockPayloadWithNativeThread, isRecord, optionalRecord, optionalString, requireNativeInboundId, } from "./native-local-mock.js";
5
- const MATRIX_ROOM_ID_RULE = {
6
- example: "!abcdef:matrix.org",
7
- name: "Matrix room id",
8
- pattern: /^![^:\s]+:[^\s]+$/u,
9
- };
10
- const MATRIX_EVENT_ID_RULE = {
11
- example: "$eventid:matrix.org",
12
- name: "Matrix event id",
13
- pattern: /^\$[^\s]+(?::[^\s]+)?$/u,
14
- };
4
+ import { getBuiltinTargetCodec, MATRIX_EVENT_ID_RULE, MATRIX_ROOM_ID_RULE, } from "../target-normalizers.js";
5
+ import { authorFromBotFlag, genericMockPayloadWithNativeThread, isRecord, optionalRecord, optionalString, requireNativeInboundId, } from "./native-local-mock.js";
6
+ import { requireExternalWebhookAuthentication } from "./external-webhook-auth.js";
15
7
  export function resolveMatrixAdapterConfig(config, userName, env = process.env) {
16
8
  return {
17
9
  auth: config.matrix?.auth ?? {
18
10
  accessToken: env.MATRIX_ACCESS_TOKEN ?? "local-mock-matrix-token",
19
11
  type: "accessToken",
20
- userID: `@${userName}:matrix.local`,
12
+ userID: env.MATRIX_USER_ID?.trim() || `@${userName}:matrix.local`,
21
13
  },
22
14
  baseURL: config.matrix?.baseURL ?? env.MATRIX_BASE_URL ?? "http://matrix.local",
23
15
  commandPrefix: config.matrix?.commandPrefix,
@@ -25,20 +17,24 @@ export function resolveMatrixAdapterConfig(config, userName, env = process.env)
25
17
  };
26
18
  }
27
19
  export class MatrixProviderAdapter extends LocalMockProviderAdapter {
28
- constructor(id, config, _userName, _runtime) {
20
+ constructor(id, config, userName, _runtime) {
21
+ const resolvedConfig = resolveMatrixAdapterConfig(config, userName);
22
+ const botUserId = resolvedConfig.auth.userID;
23
+ requireExternalWebhookAuthentication({
24
+ authenticated: false,
25
+ provider: "Matrix",
26
+ requirement: "a provider-native authenticated ingress mode, which this adapter does not support",
27
+ webhook: config.matrix?.webhook,
28
+ });
29
29
  super({
30
- codec: createNativeTargetCodec({
31
- channel: MATRIX_ROOM_ID_RULE,
32
- channelLabel: "Matrix room_id",
33
- thread: MATRIX_EVENT_ID_RULE,
34
- threadLabel: "Matrix event_id",
35
- }),
30
+ codec: getBuiltinTargetCodec("matrix"),
36
31
  config,
37
32
  id,
38
33
  options: {
39
34
  defaultWebhook: { host: "127.0.0.1", path: "/matrix/webhook", port: 8797 },
40
35
  endpointLabel: "webhook endpoint",
41
- normalizeWebhookPayload: normalizeMatrixWebhookPayload,
36
+ matchesThread: matchesMatrixThread,
37
+ normalizeWebhookPayload: (payload) => normalizeMatrixWebhookPayload(payload, botUserId),
42
38
  platform: "matrix",
43
39
  publicUrl: config.matrix?.webhook.publicUrl,
44
40
  recorderPath: config.matrix?.recorder.path
@@ -49,7 +45,22 @@ export class MatrixProviderAdapter extends LocalMockProviderAdapter {
49
45
  });
50
46
  }
51
47
  }
52
- function normalizeMatrixWebhookPayload(payload) {
48
+ function matrixThreadKey(roomId, threadId) {
49
+ return `${roomId}:thread:${threadId}`;
50
+ }
51
+ export function matchesMatrixThread(candidateThreadId, expectedThreadId, target) {
52
+ if (!expectedThreadId) {
53
+ return true;
54
+ }
55
+ const scopedExpected = target.channelId && MATRIX_EVENT_ID_RULE.pattern.test(expectedThreadId)
56
+ ? matrixThreadKey(target.channelId, expectedThreadId)
57
+ : expectedThreadId;
58
+ return (candidateThreadId === expectedThreadId ||
59
+ candidateThreadId === scopedExpected ||
60
+ (MATRIX_ROOM_ID_RULE.pattern.test(scopedExpected) &&
61
+ candidateThreadId.startsWith(`${scopedExpected}:thread:`)));
62
+ }
63
+ export function normalizeMatrixWebhookPayload(payload, botUserId) {
53
64
  if (!isRecord(payload)) {
54
65
  throw new CrablineError("Matrix webhook payload must be an object", { kind: "inbound" });
55
66
  }
@@ -63,21 +74,34 @@ function normalizeMatrixWebhookPayload(payload) {
63
74
  const content = optionalRecord(payload, "content");
64
75
  const roomId = optionalString(payload, "room_id");
65
76
  const eventId = optionalString(payload, "event_id");
77
+ const eventType = optionalString(payload, "type");
78
+ const senderId = optionalString(payload, "sender");
66
79
  const text = content ? optionalString(content, "body") : undefined;
67
- if (!roomId || !text) {
68
- throw new CrablineError("Matrix event payload requires room_id and content.body", {
80
+ if (eventType !== "m.room.message") {
81
+ throw new CrablineError("Matrix event payload requires type=m.room.message", {
82
+ kind: "inbound",
83
+ });
84
+ }
85
+ if (!roomId || !eventId || !text) {
86
+ throw new CrablineError("Matrix event payload requires room_id, event_id, and content.body", {
87
+ kind: "inbound",
88
+ });
89
+ }
90
+ const relation = content ? optionalRecord(content, "m.relates_to") : undefined;
91
+ const isThread = relation && optionalString(relation, "rel_type") === "m.thread";
92
+ const threadRootId = isThread ? optionalString(relation, "event_id") : undefined;
93
+ if (isThread && !threadRootId) {
94
+ throw new CrablineError("Matrix m.thread relation requires event_id", {
69
95
  kind: "inbound",
70
96
  });
71
97
  }
72
98
  return {
73
- author: authorFromBotFlag(false),
74
- ...(eventId
75
- ? { id: requireNativeInboundId(eventId, MATRIX_EVENT_ID_RULE, "Matrix event_id") }
76
- : {}),
99
+ author: authorFromBotFlag(senderId !== undefined && senderId === botUserId),
100
+ id: requireNativeInboundId(eventId, MATRIX_EVENT_ID_RULE, "Matrix event_id"),
77
101
  raw: payload,
78
102
  text,
79
- threadId: eventId
80
- ? requireNativeInboundId(eventId, MATRIX_EVENT_ID_RULE, "Matrix event_id")
103
+ threadId: threadRootId
104
+ ? matrixThreadKey(requireNativeInboundId(roomId, MATRIX_ROOM_ID_RULE, "Matrix room_id"), requireNativeInboundId(threadRootId, MATRIX_EVENT_ID_RULE, "Matrix thread root event_id"))
81
105
  : requireNativeInboundId(roomId, MATRIX_ROOM_ID_RULE, "Matrix room_id"),
82
106
  };
83
107
  }
@@ -1 +1 @@
1
- {"version":3,"file":"matrix.js","sourceRoot":"","sources":["../../../../src/providers/builtin/matrix.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"matrix.js","sourceRoot":"","sources":["../../../../src/providers/builtin/matrix.ts"],"names":[],"mappings":"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","sourcesContent":["import path from \"node:path\";\nimport { CrablineError } from \"../../core/errors.js\";\nimport type { ProviderConfig } from \"../../config/schema.js\";\nimport { LocalMockProviderAdapter } from \"../local-mock.js\";\nimport type { ProviderAdapter } from \"../types.js\";\nimport {\n getBuiltinTargetCodec,\n MATRIX_EVENT_ID_RULE,\n MATRIX_ROOM_ID_RULE,\n} from \"../target-normalizers.js\";\nimport {\n authorFromBotFlag,\n genericMockPayloadWithNativeThread,\n isRecord,\n optionalRecord,\n optionalString,\n requireNativeInboundId,\n} from \"./native-local-mock.js\";\nimport { requireExternalWebhookAuthentication } from \"./external-webhook-auth.js\";\n\nexport function resolveMatrixAdapterConfig(\n config: ProviderConfig,\n userName: string,\n env: NodeJS.ProcessEnv = process.env,\n) {\n return {\n auth: config.matrix?.auth ?? {\n accessToken: env.MATRIX_ACCESS_TOKEN ?? \"local-mock-matrix-token\",\n type: \"accessToken\" as const,\n userID: env.MATRIX_USER_ID?.trim() || `@${userName}:matrix.local`,\n },\n baseURL: config.matrix?.baseURL ?? env.MATRIX_BASE_URL ?? \"http://matrix.local\",\n commandPrefix: config.matrix?.commandPrefix,\n recoveryKey: config.matrix?.recoveryKey ?? env.MATRIX_RECOVERY_KEY,\n };\n}\n\nexport class MatrixProviderAdapter extends LocalMockProviderAdapter implements ProviderAdapter {\n constructor(id: string, config: ProviderConfig, userName: string, _runtime?: unknown) {\n const resolvedConfig = resolveMatrixAdapterConfig(config, userName);\n const botUserId = resolvedConfig.auth.userID;\n requireExternalWebhookAuthentication({\n authenticated: false,\n provider: \"Matrix\",\n requirement:\n \"a provider-native authenticated ingress mode, which this adapter does not support\",\n webhook: config.matrix?.webhook,\n });\n super({\n codec: getBuiltinTargetCodec(\"matrix\"),\n config,\n id,\n options: {\n defaultWebhook: { host: \"127.0.0.1\", path: \"/matrix/webhook\", port: 8797 },\n endpointLabel: \"webhook endpoint\",\n matchesThread: matchesMatrixThread,\n normalizeWebhookPayload: (payload) => normalizeMatrixWebhookPayload(payload, botUserId),\n platform: \"matrix\",\n publicUrl: config.matrix?.webhook.publicUrl,\n recorderPath: config.matrix?.recorder.path\n ? path.resolve(config.matrix.recorder.path)\n : undefined,\n webhook: config.matrix?.webhook,\n },\n });\n }\n}\n\nfunction matrixThreadKey(roomId: string, threadId: string): string {\n return `${roomId}:thread:${threadId}`;\n}\n\nexport function matchesMatrixThread(\n candidateThreadId: string,\n expectedThreadId: string | undefined,\n target: { channelId?: string | undefined },\n): boolean {\n if (!expectedThreadId) {\n return true;\n }\n const scopedExpected =\n target.channelId && MATRIX_EVENT_ID_RULE.pattern.test(expectedThreadId)\n ? matrixThreadKey(target.channelId, expectedThreadId)\n : expectedThreadId;\n return (\n candidateThreadId === expectedThreadId ||\n candidateThreadId === scopedExpected ||\n (MATRIX_ROOM_ID_RULE.pattern.test(scopedExpected) &&\n candidateThreadId.startsWith(`${scopedExpected}:thread:`))\n );\n}\n\nexport function normalizeMatrixWebhookPayload(payload: unknown, botUserId?: string) {\n if (!isRecord(payload)) {\n throw new CrablineError(\"Matrix webhook payload must be an object\", { kind: \"inbound\" });\n }\n\n if (optionalRecord(payload, \"message\")) {\n return genericMockPayloadWithNativeThread({\n channelRule: MATRIX_ROOM_ID_RULE,\n payload,\n threadRule: MATRIX_EVENT_ID_RULE,\n });\n }\n\n const content = optionalRecord(payload, \"content\");\n const roomId = optionalString(payload, \"room_id\");\n const eventId = optionalString(payload, \"event_id\");\n const eventType = optionalString(payload, \"type\");\n const senderId = optionalString(payload, \"sender\");\n const text = content ? optionalString(content, \"body\") : undefined;\n if (eventType !== \"m.room.message\") {\n throw new CrablineError(\"Matrix event payload requires type=m.room.message\", {\n kind: \"inbound\",\n });\n }\n if (!roomId || !eventId || !text) {\n throw new CrablineError(\"Matrix event payload requires room_id, event_id, and content.body\", {\n kind: \"inbound\",\n });\n }\n\n const relation = content ? optionalRecord(content, \"m.relates_to\") : undefined;\n const isThread = relation && optionalString(relation, \"rel_type\") === \"m.thread\";\n const threadRootId = isThread ? optionalString(relation, \"event_id\") : undefined;\n if (isThread && !threadRootId) {\n throw new CrablineError(\"Matrix m.thread relation requires event_id\", {\n kind: \"inbound\",\n });\n }\n\n return {\n author: authorFromBotFlag(senderId !== undefined && senderId === botUserId),\n id: requireNativeInboundId(eventId, MATRIX_EVENT_ID_RULE, \"Matrix event_id\"),\n raw: payload,\n text,\n threadId: threadRootId\n ? matrixThreadKey(\n requireNativeInboundId(roomId, MATRIX_ROOM_ID_RULE, \"Matrix room_id\"),\n requireNativeInboundId(threadRootId, MATRIX_EVENT_ID_RULE, \"Matrix thread root event_id\"),\n )\n : requireNativeInboundId(roomId, MATRIX_ROOM_ID_RULE, \"Matrix room_id\"),\n };\n}\n"]}
@@ -9,3 +9,13 @@ export declare function resolveMattermostAdapterConfig(config: ProviderConfig, e
9
9
  export declare class MattermostProviderAdapter extends LocalMockProviderAdapter implements ProviderAdapter {
10
10
  constructor(id: string, config: ProviderConfig, _userName: string, _runtime?: unknown);
11
11
  }
12
+ export declare function matchesMattermostThread(candidateThreadId: string, expectedThreadId: string | undefined, target: {
13
+ channelId?: string | undefined;
14
+ }): boolean;
15
+ export declare function normalizeMattermostWebhookPayload(payload: unknown): {
16
+ author?: "assistant" | "system" | "user" | undefined;
17
+ authorIsBot?: boolean;
18
+ id?: string | undefined;
19
+ raw: {};
20
+ text?: string | undefined;
21
+ };
@@ -1,12 +1,9 @@
1
1
  import path from "node:path";
2
2
  import { CrablineError } from "../../core/errors.js";
3
3
  import { LocalMockProviderAdapter } from "../local-mock.js";
4
- import { authorFromBotFlag, createNativeTargetCodec, genericMockPayloadWithNativeThread, isRecord, optionalRecord, optionalString, requireNativeInboundId, } from "./native-local-mock.js";
5
- const MATTERMOST_ID_RULE = {
6
- example: "abcdefghijklmnopqrstuvwx12",
7
- name: "Mattermost id",
8
- pattern: /^[a-z0-9]{26}$/u,
9
- };
4
+ import { getBuiltinTargetCodec, MATTERMOST_ID_RULE } from "../target-normalizers.js";
5
+ import { authorFromBotFlag, genericMockPayloadWithNativeThread, isRecord, optionalRecord, optionalString, requireNativeInboundId, } from "./native-local-mock.js";
6
+ import { requireExternalWebhookAuthentication } from "./external-webhook-auth.js";
10
7
  export function resolveMattermostAdapterConfig(config, env = process.env) {
11
8
  return {
12
9
  baseUrl: config.mattermost?.baseUrl ?? env.MATTERMOST_BASE_URL ?? "http://mattermost.local",
@@ -16,16 +13,20 @@ export function resolveMattermostAdapterConfig(config, env = process.env) {
16
13
  }
17
14
  export class MattermostProviderAdapter extends LocalMockProviderAdapter {
18
15
  constructor(id, config, _userName, _runtime) {
16
+ requireExternalWebhookAuthentication({
17
+ authenticated: false,
18
+ provider: "Mattermost",
19
+ requirement: "a provider-native authenticated ingress mode, which this adapter does not support",
20
+ webhook: config.mattermost?.webhook,
21
+ });
19
22
  super({
20
- codec: createNativeTargetCodec({
21
- channel: MATTERMOST_ID_RULE,
22
- channelLabel: "Mattermost channel_id",
23
- }),
23
+ codec: getBuiltinTargetCodec("mattermost"),
24
24
  config,
25
25
  id,
26
26
  options: {
27
27
  defaultWebhook: { host: "127.0.0.1", path: "/mattermost/webhook", port: 8793 },
28
28
  endpointLabel: "webhook endpoint",
29
+ matchesThread: matchesMattermostThread,
29
30
  normalizeWebhookPayload: normalizeMattermostWebhookPayload,
30
31
  platform: "mattermost",
31
32
  publicUrl: config.mattermost?.webhook.publicUrl,
@@ -37,7 +38,24 @@ export class MattermostProviderAdapter extends LocalMockProviderAdapter {
37
38
  });
38
39
  }
39
40
  }
40
- function normalizeMattermostWebhookPayload(payload) {
41
+ function mattermostThreadKey(channelId, rootId) {
42
+ return `${channelId}:thread:${rootId}`;
43
+ }
44
+ export function matchesMattermostThread(candidateThreadId, expectedThreadId, target) {
45
+ if (!expectedThreadId) {
46
+ return true;
47
+ }
48
+ const scopedExpected = target.channelId &&
49
+ MATTERMOST_ID_RULE.pattern.test(expectedThreadId) &&
50
+ expectedThreadId !== target.channelId
51
+ ? mattermostThreadKey(target.channelId, expectedThreadId)
52
+ : expectedThreadId;
53
+ return (candidateThreadId === expectedThreadId ||
54
+ candidateThreadId === scopedExpected ||
55
+ (MATTERMOST_ID_RULE.pattern.test(scopedExpected) &&
56
+ candidateThreadId.startsWith(`${scopedExpected}:thread:`)));
57
+ }
58
+ export function normalizeMattermostWebhookPayload(payload) {
41
59
  if (!isRecord(payload)) {
42
60
  throw new CrablineError("Mattermost webhook payload must be an object", { kind: "inbound" });
43
61
  }
@@ -49,19 +67,24 @@ function normalizeMattermostWebhookPayload(payload) {
49
67
  });
50
68
  }
51
69
  const channelId = optionalString(payload, "channel_id");
52
- const threadId = optionalString(payload, "root_id") ?? channelId;
70
+ const postId = optionalString(payload, "post_id");
71
+ const rootId = optionalString(payload, "root_id");
53
72
  const text = optionalString(payload, "text");
54
- if (!channelId || !threadId || !text) {
73
+ if (!channelId || !text) {
55
74
  throw new CrablineError("Mattermost webhook payload requires channel_id and text", {
56
75
  kind: "inbound",
57
76
  });
58
77
  }
59
78
  return {
60
79
  author: authorFromBotFlag(false),
61
- ...(optionalString(payload, "post_id") ? { id: optionalString(payload, "post_id") } : {}),
80
+ ...(postId
81
+ ? { id: requireNativeInboundId(postId, MATTERMOST_ID_RULE, "Mattermost post_id") }
82
+ : {}),
62
83
  raw: payload,
63
84
  text,
64
- threadId: requireNativeInboundId(threadId, MATTERMOST_ID_RULE, "Mattermost root_id"),
85
+ threadId: rootId
86
+ ? mattermostThreadKey(requireNativeInboundId(channelId, MATTERMOST_ID_RULE, "Mattermost channel_id"), requireNativeInboundId(rootId, MATTERMOST_ID_RULE, "Mattermost root_id"))
87
+ : requireNativeInboundId(channelId, MATTERMOST_ID_RULE, "Mattermost channel_id"),
65
88
  };
66
89
  }
67
90
  //# sourceMappingURL=mattermost.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"mattermost.js","sourceRoot":"","sources":["../../../../src/providers/builtin/mattermost.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"mattermost.js","sourceRoot":"","sources":["../../../../src/providers/builtin/mattermost.ts"],"names":[],"mappings":"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","sourcesContent":["import path from \"node:path\";\nimport { CrablineError } from \"../../core/errors.js\";\nimport type { ProviderConfig } from \"../../config/schema.js\";\nimport { LocalMockProviderAdapter } from \"../local-mock.js\";\nimport type { ProviderAdapter } from \"../types.js\";\nimport { getBuiltinTargetCodec, MATTERMOST_ID_RULE } from \"../target-normalizers.js\";\nimport {\n authorFromBotFlag,\n genericMockPayloadWithNativeThread,\n isRecord,\n optionalRecord,\n optionalString,\n requireNativeInboundId,\n} from \"./native-local-mock.js\";\nimport { requireExternalWebhookAuthentication } from \"./external-webhook-auth.js\";\n\nexport function resolveMattermostAdapterConfig(\n config: ProviderConfig,\n env: NodeJS.ProcessEnv = process.env,\n) {\n return {\n baseUrl: config.mattermost?.baseUrl ?? env.MATTERMOST_BASE_URL ?? \"http://mattermost.local\",\n botToken: config.mattermost?.botToken ?? env.MATTERMOST_BOT_TOKEN ?? \"local-mock-token\",\n userName: config.mattermost?.userName,\n };\n}\n\nexport class MattermostProviderAdapter extends LocalMockProviderAdapter implements ProviderAdapter {\n constructor(id: string, config: ProviderConfig, _userName: string, _runtime?: unknown) {\n requireExternalWebhookAuthentication({\n authenticated: false,\n provider: \"Mattermost\",\n requirement:\n \"a provider-native authenticated ingress mode, which this adapter does not support\",\n webhook: config.mattermost?.webhook,\n });\n super({\n codec: getBuiltinTargetCodec(\"mattermost\"),\n config,\n id,\n options: {\n defaultWebhook: { host: \"127.0.0.1\", path: \"/mattermost/webhook\", port: 8793 },\n endpointLabel: \"webhook endpoint\",\n matchesThread: matchesMattermostThread,\n normalizeWebhookPayload: normalizeMattermostWebhookPayload,\n platform: \"mattermost\",\n publicUrl: config.mattermost?.webhook.publicUrl,\n recorderPath: config.mattermost?.recorder.path\n ? path.resolve(config.mattermost.recorder.path)\n : undefined,\n webhook: config.mattermost?.webhook,\n },\n });\n }\n}\n\nfunction mattermostThreadKey(channelId: string, rootId: string): string {\n return `${channelId}:thread:${rootId}`;\n}\n\nexport function matchesMattermostThread(\n candidateThreadId: string,\n expectedThreadId: string | undefined,\n target: { channelId?: string | undefined },\n): boolean {\n if (!expectedThreadId) {\n return true;\n }\n const scopedExpected =\n target.channelId &&\n MATTERMOST_ID_RULE.pattern.test(expectedThreadId) &&\n expectedThreadId !== target.channelId\n ? mattermostThreadKey(target.channelId, expectedThreadId)\n : expectedThreadId;\n return (\n candidateThreadId === expectedThreadId ||\n candidateThreadId === scopedExpected ||\n (MATTERMOST_ID_RULE.pattern.test(scopedExpected) &&\n candidateThreadId.startsWith(`${scopedExpected}:thread:`))\n );\n}\n\nexport function normalizeMattermostWebhookPayload(payload: unknown) {\n if (!isRecord(payload)) {\n throw new CrablineError(\"Mattermost webhook payload must be an object\", { kind: \"inbound\" });\n }\n\n if (optionalRecord(payload, \"message\")) {\n return genericMockPayloadWithNativeThread({\n channelRule: MATTERMOST_ID_RULE,\n payload,\n threadRule: MATTERMOST_ID_RULE,\n });\n }\n\n const channelId = optionalString(payload, \"channel_id\");\n const postId = optionalString(payload, \"post_id\");\n const rootId = optionalString(payload, \"root_id\");\n const text = optionalString(payload, \"text\");\n if (!channelId || !text) {\n throw new CrablineError(\"Mattermost webhook payload requires channel_id and text\", {\n kind: \"inbound\",\n });\n }\n\n return {\n author: authorFromBotFlag(false),\n ...(postId\n ? { id: requireNativeInboundId(postId, MATTERMOST_ID_RULE, \"Mattermost post_id\") }\n : {}),\n raw: payload,\n text,\n threadId: rootId\n ? mattermostThreadKey(\n requireNativeInboundId(channelId, MATTERMOST_ID_RULE, \"Mattermost channel_id\"),\n requireNativeInboundId(rootId, MATTERMOST_ID_RULE, \"Mattermost root_id\"),\n )\n : requireNativeInboundId(channelId, MATTERMOST_ID_RULE, \"Mattermost channel_id\"),\n };\n}\n"]}
@@ -8,6 +8,22 @@ export declare function resolveMsTeamsAdapterConfig(config: ProviderConfig, env?
8
8
  appType: "MultiTenant" | "SingleTenant" | undefined;
9
9
  userName: string | undefined;
10
10
  };
11
+ type MsTeamsAuthRuntime = {
12
+ env?: NodeJS.ProcessEnv | undefined;
13
+ fetch?: typeof fetch | undefined;
14
+ keyFetchTimeoutMs?: number | undefined;
15
+ now?: (() => number) | undefined;
16
+ unknownKeyCooldownMs?: number | undefined;
17
+ };
18
+ export declare function createMsTeamsWebhookAuthenticator(config: ProviderConfig, runtime?: MsTeamsAuthRuntime): ((request: Request, rawBody: string) => Promise<Response | undefined>) | undefined;
11
19
  export declare class MsTeamsProviderAdapter extends LocalMockProviderAdapter implements ProviderAdapter {
12
- constructor(id: string, config: ProviderConfig, _userName: string, _runtime?: unknown);
20
+ constructor(id: string, config: ProviderConfig, _userName: string, runtime?: unknown);
13
21
  }
22
+ export declare function normalizeMsTeamsWebhookPayload(payload: unknown): {
23
+ author?: "assistant" | "system" | "user" | undefined;
24
+ authorIsBot?: boolean;
25
+ id?: string | undefined;
26
+ raw: {};
27
+ text?: string | undefined;
28
+ };
29
+ export {};
@@ -1,12 +1,11 @@
1
+ import { createPublicKey } from "node:crypto";
1
2
  import path from "node:path";
2
3
  import { CrablineError } from "../../core/errors.js";
3
4
  import { LocalMockProviderAdapter } from "../local-mock.js";
4
- import { authorFromBotFlag, createNativeTargetCodec, genericMockPayloadWithNativeThread, isRecord, optionalRecord, optionalString, requireNativeInboundId, } from "./native-local-mock.js";
5
- const MSTEAMS_CONVERSATION_ID_RULE = {
6
- example: "19:meeting_abc@thread.v2",
7
- name: "Microsoft Teams conversation id",
8
- pattern: /^19:[^@]+@thread\.[A-Za-z0-9.]+$/u,
9
- };
5
+ import { createCachedJwtKeyResolver, readBearerToken, resolveHttpCacheExpiry, verifySignedJwt, } from "../signed-jwt.js";
6
+ import { getBuiltinTargetCodec, MSTEAMS_CONVERSATION_ID_RULE } from "../target-normalizers.js";
7
+ import { authorFromBotFlag, genericMockPayloadWithNativeThread, isRecord, optionalRecord, optionalString, requireNativeInboundId, } from "./native-local-mock.js";
8
+ import { requireExternalWebhookAuthentication } from "./external-webhook-auth.js";
10
9
  export function resolveMsTeamsAdapterConfig(config, env = process.env) {
11
10
  return {
12
11
  appId: config.msteams?.appId ?? env.TEAMS_APP_ID ?? "local-mock-teams-app",
@@ -16,16 +15,101 @@ export function resolveMsTeamsAdapterConfig(config, env = process.env) {
16
15
  userName: config.msteams?.userName,
17
16
  };
18
17
  }
18
+ const BOT_CONNECTOR_ISSUER = "https://api.botframework.com";
19
+ const BOT_CONNECTOR_OPENID_URL = "https://login.botframework.com/v1/.well-known/openidconfiguration";
20
+ export function createMsTeamsWebhookAuthenticator(config, runtime = {}) {
21
+ const appId = config.msteams?.appId ?? (runtime.env ?? process.env).TEAMS_APP_ID;
22
+ if (!appId) {
23
+ return undefined;
24
+ }
25
+ const fetchImpl = runtime.fetch ?? fetch;
26
+ const resolveSigningKey = createCachedJwtKeyResolver({
27
+ async fetchKeys(signal) {
28
+ const fetchedAt = runtime.now?.() ?? Date.now();
29
+ const metadataResponse = await fetchImpl(BOT_CONNECTOR_OPENID_URL, { signal });
30
+ if (!metadataResponse.ok) {
31
+ throw new Error(`Bot Connector metadata fetch failed with HTTP ${metadataResponse.status}.`);
32
+ }
33
+ const metadataExpiry = resolveHttpCacheExpiry(metadataResponse, fetchedAt);
34
+ const metadata = (await metadataResponse.json());
35
+ if (typeof metadata.jwks_uri !== "string") {
36
+ throw new Error("Bot Connector metadata omitted jwks_uri.");
37
+ }
38
+ const keysResponse = await fetchImpl(metadata.jwks_uri, { signal });
39
+ if (!keysResponse.ok) {
40
+ throw new Error(`Bot Connector key fetch failed with HTTP ${keysResponse.status}.`);
41
+ }
42
+ const keyExpiry = resolveHttpCacheExpiry(keysResponse, fetchedAt);
43
+ const keys = (await keysResponse.json());
44
+ if (!Array.isArray(keys.keys)) {
45
+ throw new Error("Bot Connector key response omitted keys.");
46
+ }
47
+ return {
48
+ expiresAt: Math.min(metadataExpiry, keyExpiry),
49
+ values: keys.keys,
50
+ };
51
+ },
52
+ keyId: (value) => value.kid,
53
+ now: runtime.now,
54
+ refreshCooldownMs: runtime.unknownKeyCooldownMs,
55
+ timeoutMs: runtime.keyFetchTimeoutMs,
56
+ unknownKeyMessage: "Bot Connector JWT signing key is unknown.",
57
+ });
58
+ return async (request, rawBody) => {
59
+ const token = readBearerToken(request);
60
+ if (!token) {
61
+ return new Response("unauthorized", {
62
+ headers: { "www-authenticate": "Bearer" },
63
+ status: 401,
64
+ });
65
+ }
66
+ try {
67
+ const payload = JSON.parse(rawBody);
68
+ if (!isRecord(payload)) {
69
+ throw new Error("Bot Connector activity must be an object.");
70
+ }
71
+ const channelId = optionalString(payload, "channelId");
72
+ const serviceUrl = optionalString(payload, "serviceUrl");
73
+ if (channelId !== "msteams" || !serviceUrl) {
74
+ throw new Error("Bot Connector activity requires channelId=msteams and serviceUrl.");
75
+ }
76
+ const claims = await verifySignedJwt({
77
+ audience: appId,
78
+ issuers: [BOT_CONNECTOR_ISSUER],
79
+ now: runtime.now,
80
+ async resolveKey(header) {
81
+ const key = await resolveSigningKey(header);
82
+ if (key.endorsements && !key.endorsements.includes(channelId)) {
83
+ throw new Error("Bot Connector JWT key does not endorse the activity channel.");
84
+ }
85
+ return createPublicKey({ format: "jwk", key });
86
+ },
87
+ token,
88
+ });
89
+ if (claims.serviceurl !== serviceUrl) {
90
+ throw new Error("Bot Connector serviceurl claim does not match the activity.");
91
+ }
92
+ return undefined;
93
+ }
94
+ catch {
95
+ return new Response("unauthorized", {
96
+ headers: { "www-authenticate": "Bearer" },
97
+ status: 401,
98
+ });
99
+ }
100
+ };
101
+ }
19
102
  export class MsTeamsProviderAdapter extends LocalMockProviderAdapter {
20
- constructor(id, config, _userName, _runtime) {
103
+ constructor(id, config, _userName, runtime) {
104
+ const authRuntime = runtime ?? {};
105
+ requireExternalMsTeamsWebhookAuthentication(config, authRuntime.env ?? process.env);
106
+ const authenticateWebhookRequest = createMsTeamsWebhookAuthenticator(config, authRuntime);
21
107
  super({
22
- codec: createNativeTargetCodec({
23
- channel: MSTEAMS_CONVERSATION_ID_RULE,
24
- channelLabel: "Microsoft Teams conversation.id",
25
- }),
108
+ codec: getBuiltinTargetCodec("msteams"),
26
109
  config,
27
110
  id,
28
111
  options: {
112
+ ...(authenticateWebhookRequest ? { authenticateWebhookRequest } : {}),
29
113
  defaultWebhook: { host: "127.0.0.1", path: "/msteams/webhook", port: 8791 },
30
114
  endpointLabel: "webhook endpoint",
31
115
  normalizeWebhookPayload: normalizeMsTeamsWebhookPayload,
@@ -39,7 +123,16 @@ export class MsTeamsProviderAdapter extends LocalMockProviderAdapter {
39
123
  });
40
124
  }
41
125
  }
42
- function normalizeMsTeamsWebhookPayload(payload) {
126
+ function requireExternalMsTeamsWebhookAuthentication(config, env) {
127
+ const appId = config.msteams?.appId ?? env.TEAMS_APP_ID;
128
+ requireExternalWebhookAuthentication({
129
+ authenticated: Boolean(appId),
130
+ provider: "Microsoft Teams",
131
+ requirement: "msteams.appId or TEAMS_APP_ID",
132
+ webhook: config.msteams?.webhook,
133
+ });
134
+ }
135
+ export function normalizeMsTeamsWebhookPayload(payload) {
43
136
  if (!isRecord(payload)) {
44
137
  throw new CrablineError("Microsoft Teams webhook payload must be an object", {
45
138
  kind: "inbound",
@@ -52,12 +145,18 @@ function normalizeMsTeamsWebhookPayload(payload) {
52
145
  threadRule: MSTEAMS_CONVERSATION_ID_RULE,
53
146
  });
54
147
  }
148
+ if (optionalString(payload, "type") !== "message") {
149
+ throw new CrablineError("Microsoft Teams activity payload requires type=message", {
150
+ kind: "inbound",
151
+ });
152
+ }
55
153
  const conversation = optionalRecord(payload, "conversation");
56
154
  const from = optionalRecord(payload, "from");
155
+ const channelId = optionalString(payload, "channelId");
57
156
  const conversationId = conversation ? optionalString(conversation, "id") : undefined;
58
157
  const text = optionalString(payload, "text");
59
- if (!conversationId || !text) {
60
- throw new CrablineError("Microsoft Teams activity payload requires conversation.id and text", {
158
+ if (channelId !== "msteams" || !conversationId || !text) {
159
+ throw new CrablineError("Microsoft Teams activity payload requires channelId=msteams, conversation.id, and text", {
61
160
  kind: "inbound",
62
161
  });
63
162
  }
@@ -1 +1 @@
1
- {"version":3,"file":"msteams.js","sourceRoot":"","sources":["../../../../src/providers/builtin/msteams.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"msteams.js","sourceRoot":"","sources":["../../../../src/providers/builtin/msteams.ts"],"names":[],"mappings":"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","sourcesContent":["import { createPublicKey, type JsonWebKey } from \"node:crypto\";\nimport path from \"node:path\";\nimport { CrablineError } from \"../../core/errors.js\";\nimport type { ProviderConfig } from \"../../config/schema.js\";\nimport { LocalMockProviderAdapter } from \"../local-mock.js\";\nimport type { ProviderAdapter } from \"../types.js\";\nimport {\n createCachedJwtKeyResolver,\n readBearerToken,\n resolveHttpCacheExpiry,\n verifySignedJwt,\n} from \"../signed-jwt.js\";\nimport { getBuiltinTargetCodec, MSTEAMS_CONVERSATION_ID_RULE } from \"../target-normalizers.js\";\nimport {\n authorFromBotFlag,\n genericMockPayloadWithNativeThread,\n isRecord,\n optionalRecord,\n optionalString,\n requireNativeInboundId,\n} from \"./native-local-mock.js\";\nimport { requireExternalWebhookAuthentication } from \"./external-webhook-auth.js\";\n\nexport function resolveMsTeamsAdapterConfig(\n config: ProviderConfig,\n env: NodeJS.ProcessEnv = process.env,\n) {\n return {\n appId: config.msteams?.appId ?? env.TEAMS_APP_ID ?? \"local-mock-teams-app\",\n appPassword: config.msteams?.appPassword ?? env.TEAMS_APP_PASSWORD ?? \"local-mock-secret\",\n appTenantId: config.msteams?.appTenantId,\n appType: config.msteams?.appType,\n userName: config.msteams?.userName,\n };\n}\n\nconst BOT_CONNECTOR_ISSUER = \"https://api.botframework.com\";\nconst BOT_CONNECTOR_OPENID_URL =\n \"https://login.botframework.com/v1/.well-known/openidconfiguration\";\n\ntype MsTeamsAuthRuntime = {\n env?: NodeJS.ProcessEnv | undefined;\n fetch?: typeof fetch | undefined;\n keyFetchTimeoutMs?: number | undefined;\n now?: (() => number) | undefined;\n unknownKeyCooldownMs?: number | undefined;\n};\n\ntype BotConnectorKey = JsonWebKey & {\n endorsements?: string[] | undefined;\n kid?: string | undefined;\n};\n\nexport function createMsTeamsWebhookAuthenticator(\n config: ProviderConfig,\n runtime: MsTeamsAuthRuntime = {},\n) {\n const appId = config.msteams?.appId ?? (runtime.env ?? process.env).TEAMS_APP_ID;\n if (!appId) {\n return undefined;\n }\n const fetchImpl = runtime.fetch ?? fetch;\n const resolveSigningKey = createCachedJwtKeyResolver<BotConnectorKey>({\n async fetchKeys(signal) {\n const fetchedAt = runtime.now?.() ?? Date.now();\n const metadataResponse = await fetchImpl(BOT_CONNECTOR_OPENID_URL, { signal });\n if (!metadataResponse.ok) {\n throw new Error(\n `Bot Connector metadata fetch failed with HTTP ${metadataResponse.status}.`,\n );\n }\n const metadataExpiry = resolveHttpCacheExpiry(metadataResponse, fetchedAt);\n const metadata = (await metadataResponse.json()) as { jwks_uri?: unknown };\n if (typeof metadata.jwks_uri !== \"string\") {\n throw new Error(\"Bot Connector metadata omitted jwks_uri.\");\n }\n const keysResponse = await fetchImpl(metadata.jwks_uri, { signal });\n if (!keysResponse.ok) {\n throw new Error(`Bot Connector key fetch failed with HTTP ${keysResponse.status}.`);\n }\n const keyExpiry = resolveHttpCacheExpiry(keysResponse, fetchedAt);\n const keys = (await keysResponse.json()) as { keys?: unknown };\n if (!Array.isArray(keys.keys)) {\n throw new Error(\"Bot Connector key response omitted keys.\");\n }\n return {\n expiresAt: Math.min(metadataExpiry, keyExpiry),\n values: keys.keys as BotConnectorKey[],\n };\n },\n keyId: (value) => value.kid,\n now: runtime.now,\n refreshCooldownMs: runtime.unknownKeyCooldownMs,\n timeoutMs: runtime.keyFetchTimeoutMs,\n unknownKeyMessage: \"Bot Connector JWT signing key is unknown.\",\n });\n return async (request: Request, rawBody: string): Promise<Response | undefined> => {\n const token = readBearerToken(request);\n if (!token) {\n return new Response(\"unauthorized\", {\n headers: { \"www-authenticate\": \"Bearer\" },\n status: 401,\n });\n }\n try {\n const payload: unknown = JSON.parse(rawBody);\n if (!isRecord(payload)) {\n throw new Error(\"Bot Connector activity must be an object.\");\n }\n const channelId = optionalString(payload, \"channelId\");\n const serviceUrl = optionalString(payload, \"serviceUrl\");\n if (channelId !== \"msteams\" || !serviceUrl) {\n throw new Error(\"Bot Connector activity requires channelId=msteams and serviceUrl.\");\n }\n const claims = await verifySignedJwt({\n audience: appId,\n issuers: [BOT_CONNECTOR_ISSUER],\n now: runtime.now,\n async resolveKey(header) {\n const key = await resolveSigningKey(header);\n if (key.endorsements && !key.endorsements.includes(channelId)) {\n throw new Error(\"Bot Connector JWT key does not endorse the activity channel.\");\n }\n return createPublicKey({ format: \"jwk\", key });\n },\n token,\n });\n if (claims.serviceurl !== serviceUrl) {\n throw new Error(\"Bot Connector serviceurl claim does not match the activity.\");\n }\n return undefined;\n } catch {\n return new Response(\"unauthorized\", {\n headers: { \"www-authenticate\": \"Bearer\" },\n status: 401,\n });\n }\n };\n}\n\nexport class MsTeamsProviderAdapter extends LocalMockProviderAdapter implements ProviderAdapter {\n constructor(id: string, config: ProviderConfig, _userName: string, runtime?: unknown) {\n const authRuntime = (runtime as MsTeamsAuthRuntime | undefined) ?? {};\n requireExternalMsTeamsWebhookAuthentication(config, authRuntime.env ?? process.env);\n const authenticateWebhookRequest = createMsTeamsWebhookAuthenticator(config, authRuntime);\n super({\n codec: getBuiltinTargetCodec(\"msteams\"),\n config,\n id,\n options: {\n ...(authenticateWebhookRequest ? { authenticateWebhookRequest } : {}),\n defaultWebhook: { host: \"127.0.0.1\", path: \"/msteams/webhook\", port: 8791 },\n endpointLabel: \"webhook endpoint\",\n normalizeWebhookPayload: normalizeMsTeamsWebhookPayload,\n platform: \"msteams\",\n publicUrl: config.msteams?.webhook.publicUrl,\n recorderPath: config.msteams?.recorder.path\n ? path.resolve(config.msteams.recorder.path)\n : undefined,\n webhook: config.msteams?.webhook,\n },\n });\n }\n}\n\nfunction requireExternalMsTeamsWebhookAuthentication(\n config: ProviderConfig,\n env: NodeJS.ProcessEnv,\n): void {\n const appId = config.msteams?.appId ?? env.TEAMS_APP_ID;\n requireExternalWebhookAuthentication({\n authenticated: Boolean(appId),\n provider: \"Microsoft Teams\",\n requirement: \"msteams.appId or TEAMS_APP_ID\",\n webhook: config.msteams?.webhook,\n });\n}\n\nexport function normalizeMsTeamsWebhookPayload(payload: unknown) {\n if (!isRecord(payload)) {\n throw new CrablineError(\"Microsoft Teams webhook payload must be an object\", {\n kind: \"inbound\",\n });\n }\n\n if (optionalRecord(payload, \"message\")) {\n return genericMockPayloadWithNativeThread({\n channelRule: MSTEAMS_CONVERSATION_ID_RULE,\n payload,\n threadRule: MSTEAMS_CONVERSATION_ID_RULE,\n });\n }\n\n if (optionalString(payload, \"type\") !== \"message\") {\n throw new CrablineError(\"Microsoft Teams activity payload requires type=message\", {\n kind: \"inbound\",\n });\n }\n const conversation = optionalRecord(payload, \"conversation\");\n const from = optionalRecord(payload, \"from\");\n const channelId = optionalString(payload, \"channelId\");\n const conversationId = conversation ? optionalString(conversation, \"id\") : undefined;\n const text = optionalString(payload, \"text\");\n if (channelId !== \"msteams\" || !conversationId || !text) {\n throw new CrablineError(\n \"Microsoft Teams activity payload requires channelId=msteams, conversation.id, and text\",\n {\n kind: \"inbound\",\n },\n );\n }\n\n return {\n author: authorFromBotFlag(optionalString(from ?? {}, \"role\") === \"bot\"),\n ...(optionalString(payload, \"id\") ? { id: optionalString(payload, \"id\") } : {}),\n raw: payload,\n text,\n threadId: requireNativeInboundId(\n conversationId,\n MSTEAMS_CONVERSATION_ID_RULE,\n \"Microsoft Teams conversation.id\",\n ),\n };\n}\n"]}