@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.
- package/README.md +47 -22
- package/assets/crabline-banner.svg +20 -0
- package/dist/src/bin/crabline.js.map +1 -1
- package/dist/src/cli/program.d.ts +25 -1
- package/dist/src/cli/program.js +579 -82
- package/dist/src/cli/program.js.map +1 -1
- package/dist/src/config/load.js +59 -6
- package/dist/src/config/load.js.map +1 -1
- package/dist/src/config/schema.d.ts +116 -92
- package/dist/src/config/schema.js +179 -73
- package/dist/src/config/schema.js.map +1 -1
- package/dist/src/core/errors.js +9 -2
- package/dist/src/core/errors.js.map +1 -1
- package/dist/src/core/exit-codes.js.map +1 -1
- package/dist/src/core/matcher.js +7 -6
- package/dist/src/core/matcher.js.map +1 -1
- package/dist/src/core/message-template.js.map +1 -1
- package/dist/src/core/nonces.d.ts +1 -0
- package/dist/src/core/nonces.js +4 -2
- package/dist/src/core/nonces.js.map +1 -1
- package/dist/src/core/reporters.d.ts +1 -0
- package/dist/src/core/reporters.js +42 -4
- package/dist/src/core/reporters.js.map +1 -1
- package/dist/src/core/run.d.ts +3 -0
- package/dist/src/core/run.js +415 -107
- package/dist/src/core/run.js.map +1 -1
- package/dist/src/core/safe-regex.d.ts +3 -0
- package/dist/src/core/safe-regex.js +21 -0
- package/dist/src/core/safe-regex.js.map +1 -0
- package/dist/src/index.d.ts +2 -2
- package/dist/src/index.js +1 -1
- package/dist/src/index.js.map +1 -1
- package/dist/src/openclaw/artifact-generation.d.ts +38 -0
- package/dist/src/openclaw/artifact-generation.js +314 -0
- package/dist/src/openclaw/artifact-generation.js.map +1 -0
- package/dist/src/openclaw/bridges/matrix.js +97 -12
- package/dist/src/openclaw/bridges/matrix.js.map +1 -1
- package/dist/src/openclaw/bridges/mattermost.js +32 -10
- package/dist/src/openclaw/bridges/mattermost.js.map +1 -1
- package/dist/src/openclaw/bridges/signal.js +55 -18
- package/dist/src/openclaw/bridges/signal.js.map +1 -1
- package/dist/src/openclaw/bridges/slack.js +85 -7
- package/dist/src/openclaw/bridges/slack.js.map +1 -1
- package/dist/src/openclaw/bridges/telegram.js +124 -30
- package/dist/src/openclaw/bridges/telegram.js.map +1 -1
- package/dist/src/openclaw/bridges/whatsapp.js +78 -17
- package/dist/src/openclaw/bridges/whatsapp.js.map +1 -1
- package/dist/src/openclaw/bridges/zalo.js +14 -5
- package/dist/src/openclaw/bridges/zalo.js.map +1 -1
- package/dist/src/openclaw/outbound-contract.d.ts +5 -0
- package/dist/src/openclaw/outbound-contract.js +40 -0
- package/dist/src/openclaw/outbound-contract.js.map +1 -0
- package/dist/src/openclaw/private-file.d.ts +26 -0
- package/dist/src/openclaw/private-file.js +411 -0
- package/dist/src/openclaw/private-file.js.map +1 -0
- package/dist/src/openclaw/shared.d.ts +21 -2
- package/dist/src/openclaw/shared.js +115 -18
- package/dist/src/openclaw/shared.js.map +1 -1
- package/dist/src/openclaw/smoke-lock.d.ts +63 -0
- package/dist/src/openclaw/smoke-lock.js +949 -0
- package/dist/src/openclaw/smoke-lock.js.map +1 -0
- package/dist/src/openclaw.d.ts +16 -8
- package/dist/src/openclaw.js +194 -52
- package/dist/src/openclaw.js.map +1 -1
- package/dist/src/providers/builtin/discord.d.ts +10 -1
- package/dist/src/providers/builtin/discord.js +144 -18
- package/dist/src/providers/builtin/discord.js.map +1 -1
- package/dist/src/providers/builtin/external-webhook-auth.d.ts +11 -0
- package/dist/src/providers/builtin/external-webhook-auth.js +10 -0
- package/dist/src/providers/builtin/external-webhook-auth.js.map +1 -0
- package/dist/src/providers/builtin/feishu.d.ts +19 -2
- package/dist/src/providers/builtin/feishu.js +307 -25
- package/dist/src/providers/builtin/feishu.js.map +1 -1
- package/dist/src/providers/builtin/googlechat.d.ts +20 -1
- package/dist/src/providers/builtin/googlechat.js +178 -19
- package/dist/src/providers/builtin/googlechat.js.map +1 -1
- package/dist/src/providers/builtin/imessage.d.ts +4 -0
- package/dist/src/providers/builtin/imessage.js +26 -11
- package/dist/src/providers/builtin/imessage.js.map +1 -1
- package/dist/src/providers/builtin/loopback.js +92 -30
- package/dist/src/providers/builtin/loopback.js.map +1 -1
- package/dist/src/providers/builtin/matrix.d.ts +11 -1
- package/dist/src/providers/builtin/matrix.js +53 -29
- package/dist/src/providers/builtin/matrix.js.map +1 -1
- package/dist/src/providers/builtin/mattermost.d.ts +10 -0
- package/dist/src/providers/builtin/mattermost.js +38 -15
- package/dist/src/providers/builtin/mattermost.js.map +1 -1
- package/dist/src/providers/builtin/msteams.d.ts +17 -1
- package/dist/src/providers/builtin/msteams.js +113 -14
- package/dist/src/providers/builtin/msteams.js.map +1 -1
- package/dist/src/providers/builtin/native-local-mock.d.ts +2 -9
- package/dist/src/providers/builtin/native-local-mock.js +12 -35
- package/dist/src/providers/builtin/native-local-mock.js.map +1 -1
- package/dist/src/providers/builtin/script.d.ts +11 -15
- package/dist/src/providers/builtin/script.js +566 -104
- package/dist/src/providers/builtin/script.js.map +1 -1
- package/dist/src/providers/builtin/slack.d.ts +6 -0
- package/dist/src/providers/builtin/slack.js +99 -40
- package/dist/src/providers/builtin/slack.js.map +1 -1
- package/dist/src/providers/builtin/telegram.d.ts +6 -0
- package/dist/src/providers/builtin/telegram.js +64 -43
- package/dist/src/providers/builtin/telegram.js.map +1 -1
- package/dist/src/providers/builtin/whatsapp.d.ts +28 -8
- package/dist/src/providers/builtin/whatsapp.js +567 -30
- package/dist/src/providers/builtin/whatsapp.js.map +1 -1
- package/dist/src/providers/builtin/zalo.js +30 -19
- package/dist/src/providers/builtin/zalo.js.map +1 -1
- package/dist/src/providers/catalog.d.ts +3 -3
- package/dist/src/providers/catalog.js +3 -3
- package/dist/src/providers/catalog.js.map +1 -1
- package/dist/src/providers/local-mock.d.ts +11 -2
- package/dist/src/providers/local-mock.js +322 -96
- package/dist/src/providers/local-mock.js.map +1 -1
- package/dist/src/providers/native-ids.d.ts +1 -0
- package/dist/src/providers/native-ids.js +6 -1
- package/dist/src/providers/native-ids.js.map +1 -1
- package/dist/src/providers/recorder.d.ts +30 -2
- package/dist/src/providers/recorder.js +539 -70
- package/dist/src/providers/recorder.js.map +1 -1
- package/dist/src/providers/registry.d.ts +25 -1
- package/dist/src/providers/registry.js +280 -40
- package/dist/src/providers/registry.js.map +1 -1
- package/dist/src/providers/signed-jwt.d.ts +29 -0
- package/dist/src/providers/signed-jwt.js +202 -0
- package/dist/src/providers/signed-jwt.js.map +1 -0
- package/dist/src/providers/slack-ids.js.map +1 -1
- package/dist/src/providers/target-normalizers.d.ts +26 -0
- package/dist/src/providers/target-normalizers.js +276 -0
- package/dist/src/providers/target-normalizers.js.map +1 -0
- package/dist/src/providers/types.d.ts +5 -0
- package/dist/src/providers/types.js.map +1 -1
- package/dist/src/providers/webhook-server.d.ts +2 -0
- package/dist/src/providers/webhook-server.js +72 -25
- package/dist/src/providers/webhook-server.js.map +1 -1
- package/dist/src/servers/http.d.ts +23 -3
- package/dist/src/servers/http.js +213 -20
- package/dist/src/servers/http.js.map +1 -1
- package/dist/src/servers/index.js +20 -21
- package/dist/src/servers/index.js.map +1 -1
- package/dist/src/servers/matrix.js +465 -51
- package/dist/src/servers/matrix.js.map +1 -1
- package/dist/src/servers/mattermost.d.ts +5 -0
- package/dist/src/servers/mattermost.js +306 -58
- package/dist/src/servers/mattermost.js.map +1 -1
- package/dist/src/servers/pending-events.d.ts +2 -0
- package/dist/src/servers/pending-events.js +11 -0
- package/dist/src/servers/pending-events.js.map +1 -0
- package/dist/src/servers/recorder.d.ts +5 -0
- package/dist/src/servers/recorder.js +46 -3
- package/dist/src/servers/recorder.js.map +1 -1
- package/dist/src/servers/signal.d.ts +2 -0
- package/dist/src/servers/signal.js +444 -56
- package/dist/src/servers/signal.js.map +1 -1
- package/dist/src/servers/slack.d.ts +5 -0
- package/dist/src/servers/slack.js +515 -49
- package/dist/src/servers/slack.js.map +1 -1
- package/dist/src/servers/telegram.d.ts +111 -0
- package/dist/src/servers/telegram.js +811 -152
- package/dist/src/servers/telegram.js.map +1 -1
- package/dist/src/servers/webhook-target.d.ts +40 -0
- package/dist/src/servers/webhook-target.js +349 -0
- package/dist/src/servers/webhook-target.js.map +1 -0
- package/dist/src/servers/websocket.d.ts +2 -0
- package/dist/src/servers/websocket.js +29 -0
- package/dist/src/servers/websocket.js.map +1 -0
- package/dist/src/servers/whatsapp-baileys-websocket.d.ts +65 -1
- package/dist/src/servers/whatsapp-baileys-websocket.js +723 -99
- package/dist/src/servers/whatsapp-baileys-websocket.js.map +1 -1
- package/dist/src/servers/whatsapp-jid.d.ts +5 -0
- package/dist/src/servers/whatsapp-jid.js +32 -0
- package/dist/src/servers/whatsapp-jid.js.map +1 -0
- package/dist/src/servers/whatsapp-wire/binary-node.d.ts +5 -0
- package/dist/src/servers/whatsapp-wire/binary-node.js +87 -20
- package/dist/src/servers/whatsapp-wire/binary-node.js.map +1 -1
- package/dist/src/servers/whatsapp-wire/crypto.d.ts +6 -1
- package/dist/src/servers/whatsapp-wire/crypto.js +99 -45
- package/dist/src/servers/whatsapp-wire/crypto.js.map +1 -1
- package/dist/src/servers/whatsapp-wire/handshake.js +39 -4
- package/dist/src/servers/whatsapp-wire/handshake.js.map +1 -1
- package/dist/src/servers/whatsapp-wire/signal.js.map +1 -1
- package/dist/src/servers/whatsapp.d.ts +12 -7
- package/dist/src/servers/whatsapp.js +269 -107
- package/dist/src/servers/whatsapp.js.map +1 -1
- package/dist/src/servers/zalo.d.ts +14 -0
- package/dist/src/servers/zalo.js +521 -88
- package/dist/src/servers/zalo.js.map +1 -1
- package/docs/channel-setup.md +197 -19
- package/fixtures/examples/crabline.example.yaml +10 -0
- 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,
|
|
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 {
|
|
5
|
-
|
|
6
|
-
|
|
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,
|
|
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:
|
|
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
|
-
|
|
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
|
|
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 (
|
|
68
|
-
throw new CrablineError("Matrix event payload requires
|
|
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(
|
|
74
|
-
|
|
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:
|
|
80
|
-
? requireNativeInboundId(
|
|
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":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAErD,OAAO,EAAE,wBAAwB,EAAE,MAAM,kBAAkB,CAAC;AAE5D,OAAO,EACL,iBAAiB,EACjB,
|
|
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 {
|
|
5
|
-
|
|
6
|
-
|
|
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:
|
|
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
|
|
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
|
|
70
|
+
const postId = optionalString(payload, "post_id");
|
|
71
|
+
const rootId = optionalString(payload, "root_id");
|
|
53
72
|
const text = optionalString(payload, "text");
|
|
54
|
-
if (!channelId || !
|
|
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
|
-
...(
|
|
80
|
+
...(postId
|
|
81
|
+
? { id: requireNativeInboundId(postId, MATTERMOST_ID_RULE, "Mattermost post_id") }
|
|
82
|
+
: {}),
|
|
62
83
|
raw: payload,
|
|
63
84
|
text,
|
|
64
|
-
threadId:
|
|
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":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAErD,OAAO,EAAE,wBAAwB,EAAE,MAAM,kBAAkB,CAAC;AAE5D,OAAO,EACL,iBAAiB,EACjB,
|
|
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,
|
|
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 {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
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,
|
|
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:
|
|
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
|
|
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"]}
|