@openclaw/crabline 0.1.11 → 0.1.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +137 -23
- package/dist/src/bin/crabline.js +3 -1
- package/dist/src/bin/crabline.js.map +1 -1
- package/dist/src/cli/program.d.ts +5 -1
- package/dist/src/cli/program.js +281 -52
- package/dist/src/cli/program.js.map +1 -1
- package/dist/src/config/load.js +39 -3
- package/dist/src/config/load.js.map +1 -1
- package/dist/src/config/schema.d.ts +20 -0
- package/dist/src/config/schema.js +163 -35
- package/dist/src/config/schema.js.map +1 -1
- package/dist/src/core/errors.d.ts +1 -0
- package/dist/src/core/errors.js +6 -3
- package/dist/src/core/errors.js.map +1 -1
- package/dist/src/core/http-path.d.ts +1 -0
- package/dist/src/core/http-path.js +14 -0
- package/dist/src/core/http-path.js.map +1 -0
- package/dist/src/core/matcher.d.ts +3 -1
- package/dist/src/core/matcher.js +58 -2
- package/dist/src/core/matcher.js.map +1 -1
- package/dist/src/core/nonces.d.ts +2 -0
- package/dist/src/core/nonces.js +11 -1
- package/dist/src/core/nonces.js.map +1 -1
- package/dist/src/core/reporters.d.ts +5 -0
- package/dist/src/core/reporters.js +26 -2
- package/dist/src/core/reporters.js.map +1 -1
- package/dist/src/core/run.d.ts +3 -1
- package/dist/src/core/run.js +178 -66
- package/dist/src/core/run.js.map +1 -1
- package/dist/src/index.d.ts +12 -10
- package/dist/src/index.js +6 -5
- package/dist/src/index.js.map +1 -1
- package/dist/src/matrix-ids.d.ts +5 -0
- package/dist/src/matrix-ids.js +83 -0
- package/dist/src/matrix-ids.js.map +1 -0
- package/dist/src/openclaw/artifact-generation.d.ts +7 -6
- package/dist/src/openclaw/artifact-generation.js +385 -41
- package/dist/src/openclaw/artifact-generation.js.map +1 -1
- package/dist/src/openclaw/bridges/discord.d.ts +1 -0
- package/dist/src/openclaw/bridges/discord.js +149 -0
- package/dist/src/openclaw/bridges/discord.js.map +1 -0
- package/dist/src/openclaw/bridges/matrix.js +22 -5
- package/dist/src/openclaw/bridges/matrix.js.map +1 -1
- package/dist/src/openclaw/bridges/mattermost.js +14 -9
- package/dist/src/openclaw/bridges/mattermost.js.map +1 -1
- package/dist/src/openclaw/bridges/probe-response.d.ts +1 -0
- package/dist/src/openclaw/bridges/probe-response.js +5 -0
- package/dist/src/openclaw/bridges/probe-response.js.map +1 -0
- package/dist/src/openclaw/bridges/signal.js +16 -7
- package/dist/src/openclaw/bridges/signal.js.map +1 -1
- package/dist/src/openclaw/bridges/slack.js +117 -24
- package/dist/src/openclaw/bridges/slack.js.map +1 -1
- package/dist/src/openclaw/bridges/telegram.js +46 -20
- package/dist/src/openclaw/bridges/telegram.js.map +1 -1
- package/dist/src/openclaw/bridges/whatsapp.js +33 -17
- package/dist/src/openclaw/bridges/whatsapp.js.map +1 -1
- package/dist/src/openclaw/bridges/zalo.js +9 -4
- package/dist/src/openclaw/bridges/zalo.js.map +1 -1
- package/dist/src/openclaw/outbound-contract.js +3 -0
- package/dist/src/openclaw/outbound-contract.js.map +1 -1
- package/dist/src/openclaw/private-file.d.ts +38 -3
- package/dist/src/openclaw/private-file.js +2008 -87
- package/dist/src/openclaw/private-file.js.map +1 -1
- package/dist/src/openclaw/{smoke-lock.d.ts → provider-readiness-lock.d.ts} +14 -5
- package/dist/src/openclaw/provider-readiness-lock.js +1320 -0
- package/dist/src/openclaw/provider-readiness-lock.js.map +1 -0
- package/dist/src/openclaw/shared.d.ts +10 -17
- package/dist/src/openclaw/shared.js +53 -19
- package/dist/src/openclaw/shared.js.map +1 -1
- package/dist/src/openclaw.d.ts +3 -5
- package/dist/src/openclaw.js +245 -60
- package/dist/src/openclaw.js.map +1 -1
- package/dist/src/platform/process-owned-lock.d.ts +11 -0
- package/dist/src/platform/process-owned-lock.js +1698 -0
- package/dist/src/platform/process-owned-lock.js.map +1 -0
- package/dist/src/platform/recorder-directory.d.ts +1 -0
- package/dist/src/platform/recorder-directory.js +14 -0
- package/dist/src/platform/recorder-directory.js.map +1 -0
- package/dist/src/platform/windows-acl.d.ts +18 -0
- package/dist/src/platform/windows-acl.js +1367 -0
- package/dist/src/platform/windows-acl.js.map +1 -0
- package/dist/src/platform/windows-lock-root.d.ts +13 -0
- package/dist/src/platform/windows-lock-root.js +98 -0
- package/dist/src/platform/windows-lock-root.js.map +1 -0
- package/dist/src/providers/builtin/discord.d.ts +4 -0
- package/dist/src/providers/builtin/discord.js +52 -9
- package/dist/src/providers/builtin/discord.js.map +1 -1
- package/dist/src/providers/builtin/external-webhook-auth.d.ts +1 -0
- package/dist/src/providers/builtin/external-webhook-auth.js +38 -1
- package/dist/src/providers/builtin/external-webhook-auth.js.map +1 -1
- package/dist/src/providers/builtin/feishu.d.ts +1 -0
- package/dist/src/providers/builtin/feishu.js +96 -26
- package/dist/src/providers/builtin/feishu.js.map +1 -1
- package/dist/src/providers/builtin/googlechat.d.ts +1 -0
- package/dist/src/providers/builtin/googlechat.js +95 -26
- package/dist/src/providers/builtin/googlechat.js.map +1 -1
- package/dist/src/providers/builtin/imessage.js +60 -17
- package/dist/src/providers/builtin/imessage.js.map +1 -1
- package/dist/src/providers/builtin/loopback.js +88 -35
- package/dist/src/providers/builtin/loopback.js.map +1 -1
- package/dist/src/providers/builtin/matrix.d.ts +2 -2
- package/dist/src/providers/builtin/matrix.js +78 -21
- package/dist/src/providers/builtin/matrix.js.map +1 -1
- package/dist/src/providers/builtin/mattermost.d.ts +11 -7
- package/dist/src/providers/builtin/mattermost.js +138 -24
- package/dist/src/providers/builtin/mattermost.js.map +1 -1
- package/dist/src/providers/builtin/msteams.d.ts +1 -0
- package/dist/src/providers/builtin/msteams.js +118 -38
- package/dist/src/providers/builtin/msteams.js.map +1 -1
- package/dist/src/providers/builtin/native-local-mock.js +4 -4
- package/dist/src/providers/builtin/native-local-mock.js.map +1 -1
- package/dist/src/providers/builtin/script.js +1057 -146
- package/dist/src/providers/builtin/script.js.map +1 -1
- package/dist/src/providers/builtin/slack.d.ts +8 -1
- package/dist/src/providers/builtin/slack.js +327 -24
- package/dist/src/providers/builtin/slack.js.map +1 -1
- package/dist/src/providers/builtin/telegram.d.ts +1 -1
- package/dist/src/providers/builtin/telegram.js +55 -14
- package/dist/src/providers/builtin/telegram.js.map +1 -1
- package/dist/src/providers/builtin/whatsapp.d.ts +4 -3
- package/dist/src/providers/builtin/whatsapp.js +157 -29
- package/dist/src/providers/builtin/whatsapp.js.map +1 -1
- package/dist/src/providers/builtin/zalo.d.ts +5 -2
- package/dist/src/providers/builtin/zalo.js +31 -7
- package/dist/src/providers/builtin/zalo.js.map +1 -1
- package/dist/src/providers/catalog.d.ts +1 -1
- package/dist/src/providers/catalog.js +1 -1
- package/dist/src/providers/catalog.js.map +1 -1
- package/dist/src/providers/local-mock.d.ts +4 -0
- package/dist/src/providers/local-mock.js +162 -35
- package/dist/src/providers/local-mock.js.map +1 -1
- package/dist/src/providers/native-ids.d.ts +2 -0
- package/dist/src/providers/native-ids.js +3 -0
- package/dist/src/providers/native-ids.js.map +1 -1
- package/dist/src/providers/recorder.d.ts +14 -3
- package/dist/src/providers/recorder.js +521 -41
- package/dist/src/providers/recorder.js.map +1 -1
- package/dist/src/providers/registry.d.ts +1 -0
- package/dist/src/providers/registry.js +65 -20
- package/dist/src/providers/registry.js.map +1 -1
- package/dist/src/providers/signed-jwt.d.ts +6 -1
- package/dist/src/providers/signed-jwt.js +241 -50
- package/dist/src/providers/signed-jwt.js.map +1 -1
- package/dist/src/providers/slack-ids.d.ts +1 -0
- package/dist/src/providers/slack-ids.js +5 -0
- package/dist/src/providers/slack-ids.js.map +1 -1
- package/dist/src/providers/target-normalizers.d.ts +9 -1
- package/dist/src/providers/target-normalizers.js +177 -58
- package/dist/src/providers/target-normalizers.js.map +1 -1
- package/dist/src/providers/webhook-server.d.ts +3 -0
- package/dist/src/providers/webhook-server.js +268 -47
- package/dist/src/providers/webhook-server.js.map +1 -1
- package/dist/src/servers/discord.d.ts +40 -0
- package/dist/src/servers/discord.js +842 -0
- package/dist/src/servers/discord.js.map +1 -0
- package/dist/src/servers/http.d.ts +14 -2
- package/dist/src/servers/http.js +229 -58
- package/dist/src/servers/http.js.map +1 -1
- package/dist/src/servers/index.d.ts +10 -4
- package/dist/src/servers/index.js +4 -0
- package/dist/src/servers/index.js.map +1 -1
- package/dist/src/servers/matrix.d.ts +3 -0
- package/dist/src/servers/matrix.js +268 -110
- package/dist/src/servers/matrix.js.map +1 -1
- package/dist/src/servers/mattermost.d.ts +5 -0
- package/dist/src/servers/mattermost.js +389 -91
- package/dist/src/servers/mattermost.js.map +1 -1
- package/dist/src/servers/recorder.d.ts +11 -0
- package/dist/src/servers/recorder.js +1072 -69
- package/dist/src/servers/recorder.js.map +1 -1
- package/dist/src/servers/signal.d.ts +1 -0
- package/dist/src/servers/signal.js +279 -44
- package/dist/src/servers/signal.js.map +1 -1
- package/dist/src/servers/slack.d.ts +15 -0
- package/dist/src/servers/slack.js +270 -54
- package/dist/src/servers/slack.js.map +1 -1
- package/dist/src/servers/telegram-identity.d.ts +6 -0
- package/dist/src/servers/telegram-identity.js +27 -0
- package/dist/src/servers/telegram-identity.js.map +1 -0
- package/dist/src/servers/telegram.d.ts +17 -6
- package/dist/src/servers/telegram.js +1218 -107
- package/dist/src/servers/telegram.js.map +1 -1
- package/dist/src/servers/webhook-target.d.ts +12 -4
- package/dist/src/servers/webhook-target.js +226 -28
- package/dist/src/servers/webhook-target.js.map +1 -1
- package/dist/src/servers/whatsapp-baileys-websocket.d.ts +60 -1
- package/dist/src/servers/whatsapp-baileys-websocket.js +782 -112
- package/dist/src/servers/whatsapp-baileys-websocket.js.map +1 -1
- package/dist/src/servers/whatsapp-jid.d.ts +1 -0
- package/dist/src/servers/whatsapp-jid.js +9 -5
- package/dist/src/servers/whatsapp-jid.js.map +1 -1
- package/dist/src/servers/whatsapp-wire/binary-node.d.ts +1 -0
- package/dist/src/servers/whatsapp-wire/binary-node.js +37 -13
- package/dist/src/servers/whatsapp-wire/binary-node.js.map +1 -1
- package/dist/src/servers/whatsapp-wire/crypto.d.ts +3 -0
- package/dist/src/servers/whatsapp-wire/crypto.js +23 -8
- package/dist/src/servers/whatsapp-wire/crypto.js.map +1 -1
- package/dist/src/servers/whatsapp-wire/handshake.d.ts +9 -3
- package/dist/src/servers/whatsapp-wire/handshake.js +173 -12
- package/dist/src/servers/whatsapp-wire/handshake.js.map +1 -1
- package/dist/src/servers/whatsapp-wire/signal.js +3 -3
- package/dist/src/servers/whatsapp-wire/signal.js.map +1 -1
- package/dist/src/servers/whatsapp.d.ts +7 -1
- package/dist/src/servers/whatsapp.js +149 -25
- package/dist/src/servers/whatsapp.js.map +1 -1
- package/dist/src/servers/zalo.d.ts +1 -0
- package/dist/src/servers/zalo.js +193 -82
- package/dist/src/servers/zalo.js.map +1 -1
- package/docs/channel-setup.md +251 -64
- package/fixtures/examples/crabline.example.yaml +3 -2
- package/package.json +18 -10
- package/dist/src/openclaw/smoke-lock.js +0 -1004
- package/dist/src/openclaw/smoke-lock.js.map +0 -1
- package/fixtures/examples/openclaw-bridge.yaml +0 -125
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"whatsapp.js","sourceRoot":"","sources":["../../../../src/providers/builtin/whatsapp.ts"],"names":[],"mappings":"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","sourcesContent":["import { createHmac, timingSafeEqual } from \"node:crypto\";\nimport path from \"node:path\";\nimport { CrablineError, ensureErrorMessage } from \"../../core/errors.js\";\nimport { matchesInbound } from \"../../core/matcher.js\";\nimport type { ProviderConfig } from \"../../config/schema.js\";\nimport { LocalMockProviderAdapter, type LocalMockWebhookConfig } from \"../local-mock.js\";\nimport {\n appendRecordedInboundBatch,\n cloneRecordedInboundCursor,\n createRecordedInboundCursor,\n waitForRecordedInbound,\n watchRecordedInbound,\n type RecordedInboundCursor,\n type RecordedInboundEnvelope,\n} from \"../recorder.js\";\nimport type {\n InboundEnvelope,\n ProbeResult,\n ProviderAdapter,\n ProviderContext,\n SendContext,\n SendResult,\n WaitContext,\n WatchContext,\n} from \"../types.js\";\nimport { getBuiltinTargetCodec, WHATSAPP_WA_ID_RULE } from \"../target-normalizers.js\";\nimport { startWebhookServer, type StartedWebhookServer } from \"../webhook-server.js\";\nimport {\n authorFromBotFlag,\n genericMockPayloadWithNativeThread,\n isRecord,\n normalizeAuthor,\n optionalRecord,\n optionalString,\n requireNativeInboundId,\n} from \"./native-local-mock.js\";\n\ntype NormalizedWhatsAppWebhookMessage = {\n author?: \"assistant\" | \"system\" | \"user\";\n authorIsBot?: boolean;\n id?: string;\n message?: {\n author?: \"assistant\" | \"system\" | \"user\";\n authorIsBot?: boolean;\n id?: string;\n raw?: unknown;\n sentAt?: string;\n text?: string;\n threadId?: string;\n };\n raw?: unknown;\n sentAt?: string;\n text?: string;\n threadId?: string;\n};\n\nconst DEFAULT_WHATSAPP_WEBHOOK = {\n host: \"127.0.0.1\",\n path: \"/whatsapp/webhook\",\n port: 8789,\n} as const;\nconst MAX_WAIT_CURSORS = 64;\nconst MAX_WHATSAPP_WEBHOOK_BODY_BYTES = 1024 * 1024;\nconst WHATSAPP_WEBHOOK_BODY_TIMEOUT_MS = 5_000;\n\nclass WhatsAppWebhookBodyError extends Error {\n constructor(\n message: string,\n readonly status: number,\n ) {\n super(message);\n }\n}\n\nasync function readWhatsAppWebhookBody(\n request: Request,\n lifecycleSignal: AbortSignal,\n): Promise<string> {\n if (!request.body) {\n return \"\";\n }\n\n const timeoutController = new AbortController();\n const timeout = setTimeout(() => {\n timeoutController.abort(new WhatsAppWebhookBodyError(\"webhook request body timed out\", 408));\n }, WHATSAPP_WEBHOOK_BODY_TIMEOUT_MS);\n timeout.unref();\n const signal = AbortSignal.any([lifecycleSignal, request.signal, timeoutController.signal]);\n const reader = request.body.getReader();\n const chunks: Buffer[] = [];\n let bodyBytes = 0;\n let completed = false;\n let failure: unknown;\n\n try {\n while (true) {\n const result = await new Promise<Awaited<ReturnType<typeof reader.read>>>(\n (resolve, reject) => {\n if (signal.aborted) {\n reject(signal.reason);\n return;\n }\n const abort = () => reject(signal.reason);\n signal.addEventListener(\"abort\", abort, { once: true });\n void reader.read().then(\n (value) => {\n signal.removeEventListener(\"abort\", abort);\n resolve(value);\n },\n (error) => {\n signal.removeEventListener(\"abort\", abort);\n reject(error);\n },\n );\n },\n );\n if (result.done) {\n completed = true;\n return Buffer.concat(chunks).toString(\"utf8\");\n }\n const chunk = Buffer.from(result.value);\n bodyBytes += chunk.length;\n if (bodyBytes > MAX_WHATSAPP_WEBHOOK_BODY_BYTES) {\n throw new WhatsAppWebhookBodyError(\"request body too large\", 413);\n }\n chunks.push(chunk);\n }\n } catch (error) {\n failure = error;\n throw error;\n } finally {\n clearTimeout(timeout);\n if (!completed) {\n void reader.cancel(failure ?? signal.reason).catch(() => undefined);\n } else {\n reader.releaseLock();\n }\n }\n}\n\nexport function resolveWhatsAppAdapterConfig(\n config: ProviderConfig,\n env: NodeJS.ProcessEnv = process.env,\n) {\n const appSecret = config.whatsapp?.appSecret ?? env.WHATSAPP_APP_SECRET;\n const verifyToken = config.whatsapp?.verifyToken ?? env.WHATSAPP_VERIFY_TOKEN;\n if (!appSecret || !verifyToken) {\n throw new CrablineError(\n \"WhatsApp webhook operation requires appSecret and verifyToken configuration.\",\n { kind: \"config\" },\n );\n }\n return {\n accessToken: config.whatsapp?.accessToken ?? env.WHATSAPP_ACCESS_TOKEN ?? \"local-mock-token\",\n appSecret,\n phoneNumberId:\n config.whatsapp?.phoneNumberId ?? env.WHATSAPP_PHONE_NUMBER_ID ?? \"local-mock-phone\",\n verifyToken,\n };\n}\n\ntype ResolvedWhatsAppAdapterConfig = ReturnType<typeof resolveWhatsAppAdapterConfig>;\ntype WaitCursorState = {\n active: number;\n cursor?: RecordedInboundCursor | undefined;\n};\n\nfunction pruneInactiveWaitCursors(cursors: Map<string, WaitCursorState>): void {\n for (const [key, state] of cursors) {\n if (cursors.size <= MAX_WAIT_CURSORS) {\n return;\n }\n if (state.active === 0) {\n cursors.delete(key);\n }\n }\n}\n\nexport class WhatsAppProviderAdapter extends LocalMockProviderAdapter implements ProviderAdapter {\n readonly #config: ProviderConfig;\n readonly #lifecycleAbort = new AbortController();\n readonly #publicUrl: string | undefined;\n readonly #recorderPath: string;\n readonly #webhook: LocalMockWebhookConfig | undefined;\n #cleanedUp = false;\n #cleanupBegun = false;\n #cleanupPromise: Promise<void> | null = null;\n readonly #inFlightSends = new Set<Promise<SendResult>>();\n readonly #inFlightWebhookRequests = new Set<Promise<Response>>();\n readonly #waitCursors = new Map<string, WaitCursorState>();\n #server: StartedWebhookServer | null = null;\n #serverClosing: Promise<void> | null = null;\n #serverStarting: Promise<StartedWebhookServer> | null = null;\n\n constructor(id: string, config: ProviderConfig, _userName: string, _runtime?: unknown) {\n super({\n codec: getBuiltinTargetCodec(\"whatsapp\"),\n config,\n id,\n options: {\n defaultWebhook: DEFAULT_WHATSAPP_WEBHOOK,\n endpointLabel: \"webhook endpoint\",\n normalizeWebhookPayload: normalizeWhatsAppWebhookPayload,\n platform: \"whatsapp\",\n publicUrl: config.whatsapp?.webhook.publicUrl,\n recorderPath: config.whatsapp?.recorder.path\n ? path.resolve(config.whatsapp.recorder.path)\n : undefined,\n webhook: config.whatsapp?.webhook,\n },\n });\n this.#config = config;\n this.#publicUrl = config.whatsapp?.webhook.publicUrl;\n this.#recorderPath = config.whatsapp?.recorder.path\n ? path.resolve(config.whatsapp.recorder.path)\n : path.resolve(\".crabline\", \"recorders\", `${id}.jsonl`);\n this.#webhook = config.whatsapp?.webhook;\n }\n\n override async probe(context: ProviderContext): Promise<ProbeResult> {\n context.signal?.throwIfAborted();\n const server = await this.#ensureWebhookServer();\n context.signal?.throwIfAborted();\n const target = this.normalizeTarget(context.fixture.target);\n const details = [\n \"whatsapp local mock ready\",\n `recorder path ${this.#recorderPath}`,\n `webhook endpoint ${server.endpointUrl}`,\n ];\n if (this.#publicUrl) {\n details.push(`public webhook ${this.#publicUrl}`);\n }\n if (target.threadId) {\n details.push(`thread reachable ${target.threadId}`);\n } else if (target.channelId) {\n details.push(`channel reachable ${target.channelId}`);\n } else {\n details.push(`dm reachable ${target.id}`);\n }\n return { details, healthy: true };\n }\n\n override async send(context: SendContext): Promise<SendResult> {\n if (this.#cleanupBegun || this.#cleanedUp) {\n throw this.#cleanedUpError();\n }\n const sending = super.send(context);\n this.#inFlightSends.add(sending);\n try {\n return await sending;\n } finally {\n this.#inFlightSends.delete(sending);\n }\n }\n\n override async waitForInbound(context: WaitContext): Promise<InboundEnvelope | null> {\n await this.#ensureWebhookServer();\n const target = this.normalizeTarget(context.fixture.target);\n const channelId = context.threadId ?? target.threadId ?? target.channelId ?? target.id;\n const cursorKey = JSON.stringify([\n context.nonce,\n context.since,\n channelId,\n context.fixture.inboundMatch,\n ]);\n const cursorState = this.#waitCursors.get(cursorKey) ?? { active: 0 };\n const cursor = cursorState.cursor\n ? cloneRecordedInboundCursor(cursorState.cursor)\n : createRecordedInboundCursor();\n cursorState.active++;\n this.#waitCursors.delete(cursorKey);\n this.#waitCursors.set(cursorKey, cursorState);\n pruneInactiveWaitCursors(this.#waitCursors);\n try {\n const event = await waitForRecordedInbound({\n cursor,\n filePath: this.#recorderPath,\n matches: (candidate) =>\n candidate.provider === this.id &&\n !isOutboundRecord(candidate) &&\n isAddressInChannel(candidate.threadId, channelId) &&\n matchesInbound(candidate, context.fixture.inboundMatch, context.nonce),\n since: context.since,\n signal: this.#operationSignal(context.signal),\n timeoutMs: context.timeoutMs,\n });\n if (event && this.#waitCursors.get(cursorKey) === cursorState) {\n cursorState.cursor = cursor;\n }\n return event;\n } finally {\n cursorState.active--;\n if (\n cursorState.active === 0 &&\n !cursorState.cursor &&\n this.#waitCursors.get(cursorKey) === cursorState\n ) {\n this.#waitCursors.delete(cursorKey);\n }\n }\n }\n\n override async *watch(context: WatchContext): AsyncIterable<InboundEnvelope> {\n await this.#ensureWebhookServer();\n const target = this.normalizeTarget(context.fixture.target);\n for await (const event of watchRecordedInbound({\n filePath: this.#recorderPath,\n matches: (entry) =>\n entry.provider === this.id &&\n !isOutboundRecord(entry) &&\n isAddressInChannel(entry.threadId, target.threadId ?? target.channelId ?? target.id),\n signal: this.#operationSignal(context.signal),\n since: context.since,\n })) {\n yield event;\n }\n }\n\n beginCleanup(): void {\n if (this.#cleanupBegun) {\n return;\n }\n this.#cleanupBegun = true;\n this.#lifecycleAbort.abort(this.#cleanedUpError());\n this.#serverClosing = this.#closeWebhookServer();\n void this.#serverClosing.catch(() => undefined);\n }\n\n override async cleanup(): Promise<void> {\n this.beginCleanup();\n this.#cleanedUp = true;\n this.#waitCursors.clear();\n this.#cleanupPromise ??= (async () => {\n await Promise.allSettled([...this.#inFlightSends, ...this.#inFlightWebhookRequests]);\n const errors: unknown[] = [];\n try {\n await this.#serverClosing;\n } catch (error) {\n errors.push(error);\n }\n try {\n await super.cleanup();\n } catch (error) {\n errors.push(error);\n }\n if (errors.length === 1) {\n throw errors[0];\n }\n if (errors.length > 1) {\n throw new AggregateError(errors, \"WhatsApp cleanup failed\");\n }\n })();\n await this.#cleanupPromise;\n }\n\n #handleWebhookRequest(\n request: Request,\n resolvedConfig: ResolvedWhatsAppAdapterConfig,\n ): Promise<Response> {\n if (this.#cleanupBegun) {\n return Promise.resolve(this.#cleanedUpResponse());\n }\n const handling = this.#handleWebhook(request, resolvedConfig);\n this.#inFlightWebhookRequests.add(handling);\n void handling.then(\n () => this.#inFlightWebhookRequests.delete(handling),\n () => this.#inFlightWebhookRequests.delete(handling),\n );\n return handling;\n }\n\n async #handleWebhook(\n request: Request,\n resolvedConfig: ResolvedWhatsAppAdapterConfig,\n ): Promise<Response> {\n if (request.method === \"GET\") {\n const url = new URL(request.url);\n const mode = url.searchParams.get(\"hub.mode\");\n const providedValue = url.searchParams.get(\"hub.verify_token\");\n const challenge = url.searchParams.get(\"hub.challenge\");\n if (\n mode === \"subscribe\" &&\n providedValue === resolvedConfig.verifyToken &&\n challenge !== null\n ) {\n return new Response(challenge, {\n headers: { \"content-type\": \"text/plain; charset=utf-8\" },\n status: 200,\n });\n }\n return new Response(\"forbidden\", { status: 403 });\n }\n\n let rawBody: string;\n try {\n rawBody = await readWhatsAppWebhookBody(request, this.#lifecycleAbort.signal);\n } catch (error) {\n if (this.#cleanupBegun) {\n return this.#cleanedUpResponse();\n }\n if (error instanceof WhatsAppWebhookBodyError) {\n return new Response(error.message, { status: error.status });\n }\n return new Response(\"invalid request body\", { status: 400 });\n }\n if (\n !hasValidWhatsAppSignature(\n rawBody,\n request.headers.get(\"x-hub-signature-256\"),\n resolvedConfig.appSecret,\n )\n ) {\n return new Response(\"invalid webhook signature\", { status: 401 });\n }\n const mediaType = request.headers.get(\"content-type\")?.split(\";\", 1)[0]?.trim().toLowerCase();\n if (mediaType !== \"application/json\") {\n return new Response(\"expected application/json\", { status: 415 });\n }\n\n let messages: NormalizedWhatsAppWebhookMessage[];\n try {\n messages = normalizeWhatsAppWebhookPayload(JSON.parse(rawBody), resolvedConfig.phoneNumberId);\n } catch (error) {\n return new Response(ensureErrorMessage(error), { status: 400 });\n }\n\n const ids: string[] = [];\n const records: InboundEnvelope[] = [];\n for (const message of messages) {\n const id = message.message?.id ?? message.id ?? createMessageId();\n const threadId = message.message?.threadId ?? message.threadId;\n const text = message.message?.text ?? message.text;\n if (!threadId || !text) {\n return new Response(\"payload requires message.threadId and message.text\", { status: 400 });\n }\n\n records.push({\n author: authorFromPayload(message),\n id,\n provider: this.id,\n raw: message.message?.raw ?? message.raw ?? message,\n sentAt: message.message?.sentAt ?? message.sentAt ?? new Date().toISOString(),\n text,\n threadId,\n });\n ids.push(id);\n }\n await appendRecordedInboundBatch(this.#recorderPath, records);\n\n return new Response(\n JSON.stringify(ids.length === 1 ? { id: ids[0], ok: true } : { ids, ok: true }),\n {\n headers: { \"content-type\": \"application/json\" },\n status: 200,\n },\n );\n }\n\n async #ensureWebhookServer(): Promise<StartedWebhookServer> {\n if (this.#cleanupBegun) {\n throw this.#cleanedUpError();\n }\n if (this.#server) {\n return this.#server;\n }\n if (this.#serverStarting) {\n return await this.#serverStarting;\n }\n\n const resolvedConfig = resolveWhatsAppAdapterConfig(this.#config);\n const host = this.#webhook?.host ?? DEFAULT_WHATSAPP_WEBHOOK.host;\n const port = this.#webhook?.port ?? DEFAULT_WHATSAPP_WEBHOOK.port;\n const webhookPath = this.#webhook?.path ?? DEFAULT_WHATSAPP_WEBHOOK.path;\n const starting = (async (): Promise<StartedWebhookServer> => {\n let server: StartedWebhookServer;\n try {\n server = await startWebhookServer({\n handle: (request) => this.#handleWebhookRequest(request, resolvedConfig),\n host,\n methods: [\"GET\", \"POST\"],\n path: webhookPath,\n port,\n });\n } catch (error) {\n throw new CrablineError(\n `whatsapp local mock webhook server failed: ${ensureErrorMessage(error)}`,\n { cause: error, kind: \"connectivity\" },\n );\n }\n\n this.#server = server;\n if (this.#cleanupBegun) {\n throw this.#cleanedUpError();\n }\n return server;\n })();\n this.#serverStarting = starting;\n\n try {\n return await starting;\n } finally {\n if (this.#serverStarting === starting) {\n this.#serverStarting = null;\n }\n }\n }\n\n async #closeWebhookServer(): Promise<void> {\n const starting = this.#serverStarting;\n if (starting) {\n try {\n await starting;\n } catch {\n // A failed startup has no listener; a cleanup race publishes one below.\n }\n }\n const server = this.#server;\n if (!server) {\n return;\n }\n\n if (this.#server === server) {\n this.#server = null;\n }\n await server.close();\n }\n\n #cleanedUpError(): CrablineError {\n return new CrablineError(`Provider \"${this.id}\" has been cleaned up.`, { kind: \"config\" });\n }\n\n #cleanedUpResponse(): Response {\n return new Response(`Provider \"${this.id}\" has been cleaned up.`, { status: 503 });\n }\n\n #operationSignal(signal: AbortSignal | undefined): AbortSignal {\n return signal\n ? AbortSignal.any([signal, this.#lifecycleAbort.signal])\n : this.#lifecycleAbort.signal;\n }\n}\n\nexport function normalizeWhatsAppWebhookPayload(\n payload: unknown,\n expectedPhoneNumberId?: string,\n): NormalizedWhatsAppWebhookMessage[] {\n if (!isRecord(payload)) {\n throw new CrablineError(\"WhatsApp webhook payload must be an object\", { kind: \"inbound\" });\n }\n\n const normalized: NormalizedWhatsAppWebhookMessage[] = [];\n if (Array.isArray(payload.entry)) {\n for (const entry of payload.entry) {\n if (!isRecord(entry) || !Array.isArray(entry.changes)) {\n continue;\n }\n for (const change of entry.changes) {\n if (!isRecord(change)) {\n continue;\n }\n const value = optionalRecord(change, \"value\");\n if (!value || !Array.isArray(value.messages)) {\n continue;\n }\n const metadata = optionalRecord(value, \"metadata\");\n if (\n expectedPhoneNumberId !== undefined &&\n optionalString(metadata ?? {}, \"phone_number_id\") !== expectedPhoneNumberId\n ) {\n continue;\n }\n for (const message of value.messages) {\n if (!isRecord(message)) {\n throw new CrablineError(\"WhatsApp webhook messages[] entries must be objects\", {\n kind: \"inbound\",\n });\n }\n const normalizedMessage = normalizeWhatsAppMessage(message);\n if (normalizedMessage) {\n normalized.push(normalizedMessage);\n }\n }\n }\n }\n return normalized;\n }\n\n const fallback = genericMockPayloadWithNativeThread({\n channelRule: WHATSAPP_WA_ID_RULE,\n payload,\n threadRule: WHATSAPP_WA_ID_RULE,\n }) as Record<string, unknown>;\n return [normalizeWhatsAppFallback(fallback, payload)];\n}\n\nfunction normalizeWhatsAppFallback(\n fallback: Record<string, unknown>,\n source: Record<string, unknown>,\n): NormalizedWhatsAppWebhookMessage {\n const normalized: NormalizedWhatsAppWebhookMessage = {\n raw: fallback.raw ?? fallback,\n };\n const author = normalizeAuthor(fallback.author);\n if (author) {\n normalized.author = author;\n }\n if (typeof fallback.authorIsBot === \"boolean\") {\n normalized.authorIsBot = fallback.authorIsBot;\n }\n const id = optionalString(fallback, \"id\");\n if (id) {\n normalized.id = id;\n }\n const text = optionalString(fallback, \"text\");\n if (text) {\n normalized.text = text;\n }\n const threadId = optionalString(fallback, \"threadId\");\n if (threadId) {\n normalized.threadId = threadId;\n }\n const sentAt = optionalString(source, \"sentAt\");\n if (sentAt) {\n normalized.sentAt = whatsAppFallbackTimestampToIso(sentAt, \"sentAt\");\n }\n\n const message = optionalRecord(fallback, \"message\");\n if (message) {\n const sourceMessage = optionalRecord(source, \"message\");\n const normalizedMessage: NonNullable<NormalizedWhatsAppWebhookMessage[\"message\"]> = {};\n const messageAuthor = normalizeAuthor(message.author);\n if (messageAuthor) {\n normalizedMessage.author = messageAuthor;\n }\n if (typeof message.authorIsBot === \"boolean\") {\n normalizedMessage.authorIsBot = message.authorIsBot;\n }\n const messageId = optionalString(message, \"id\");\n if (messageId) {\n normalizedMessage.id = messageId;\n }\n if (message.raw !== undefined) {\n normalizedMessage.raw = message.raw;\n }\n const messageSentAt = sourceMessage ? optionalString(sourceMessage, \"sentAt\") : undefined;\n if (messageSentAt) {\n normalizedMessage.sentAt = whatsAppFallbackTimestampToIso(messageSentAt, \"message.sentAt\");\n }\n const messageText = optionalString(message, \"text\");\n if (messageText) {\n normalizedMessage.text = messageText;\n }\n const messageThreadId = optionalString(message, \"threadId\");\n if (messageThreadId) {\n normalizedMessage.threadId = messageThreadId;\n }\n normalized.message = normalizedMessage;\n }\n\n return normalized;\n}\n\nfunction normalizeWhatsAppMessage(\n message: Record<string, unknown>,\n): NormalizedWhatsAppWebhookMessage | null {\n const messageType = optionalString(message, \"type\");\n if (messageType && messageType !== \"text\") {\n return null;\n }\n\n const text = optionalRecord(message, \"text\");\n const from = optionalString(message, \"from\");\n const body = text ? optionalString(text, \"body\") : undefined;\n if (!from || !body) {\n throw new CrablineError(\"WhatsApp webhook payload requires messages[].from and text.body\", {\n kind: \"inbound\",\n });\n }\n\n const messageId = optionalString(message, \"id\");\n if (!messageId) {\n throw new CrablineError(\"WhatsApp webhook payload requires messages[].id\", {\n kind: \"inbound\",\n });\n }\n const timestamp = optionalString(message, \"timestamp\");\n return {\n author: authorFromBotFlag(false),\n id: messageId,\n raw: message,\n ...(timestamp ? { sentAt: whatsAppTimestampToIso(timestamp) } : {}),\n text: body,\n threadId: requireNativeInboundId(from, WHATSAPP_WA_ID_RULE, \"WhatsApp messages[].from\"),\n };\n}\n\nfunction whatsAppTimestampToIso(timestamp: string): string {\n if (!/^\\d+$/u.test(timestamp)) {\n throw new CrablineError(\"WhatsApp messages[].timestamp must be Unix seconds\", {\n kind: \"inbound\",\n });\n }\n const milliseconds = Number(timestamp) * 1000;\n if (!Number.isSafeInteger(milliseconds)) {\n throw new CrablineError(\"WhatsApp messages[].timestamp is out of range\", { kind: \"inbound\" });\n }\n const date = new Date(milliseconds);\n if (Number.isNaN(date.getTime())) {\n throw new CrablineError(\"WhatsApp messages[].timestamp is invalid\", { kind: \"inbound\" });\n }\n return date.toISOString();\n}\n\nfunction whatsAppFallbackTimestampToIso(timestamp: string, field: string): string {\n const date = new Date(timestamp);\n if (Number.isNaN(date.getTime())) {\n throw new CrablineError(`WhatsApp fallback ${field} must be a valid timestamp`, {\n kind: \"inbound\",\n });\n }\n return date.toISOString();\n}\n\nfunction authorFromPayload(payload: NormalizedWhatsAppWebhookMessage): InboundEnvelope[\"author\"] {\n const explicit = payload.message?.author ?? payload.author;\n if (explicit) {\n return explicit;\n }\n return (payload.message?.authorIsBot ?? payload.authorIsBot ?? true) ? \"assistant\" : \"user\";\n}\n\nfunction createMessageId(): string {\n return `whatsapp-mock-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;\n}\n\nfunction hasValidWhatsAppSignature(\n rawBody: string,\n signatureHeader: string | null,\n signingKey: string,\n): boolean {\n if (!signatureHeader?.startsWith(\"sha256=\")) {\n return false;\n }\n const signature = signatureHeader.slice(\"sha256=\".length);\n if (!/^[a-f0-9]{64}$/iu.test(signature)) {\n return false;\n }\n const expected = createHmac(\"sha256\", signingKey).update(rawBody).digest();\n const actual = Buffer.from(signature, \"hex\");\n return actual.length === expected.length && timingSafeEqual(actual, expected);\n}\n\nfunction isAddressInChannel(threadId: string, channelId?: string): boolean {\n if (!channelId) {\n return true;\n }\n return threadId === channelId || threadId.startsWith(`${channelId}:`);\n}\n\nfunction isOutboundRecord(event: RecordedInboundEnvelope): boolean {\n if (event.recordedDirection !== undefined) {\n return event.recordedDirection === \"outbound\";\n }\n return (\n event.raw !== null &&\n typeof event.raw === \"object\" &&\n \"direction\" in event.raw &&\n event.raw.direction === \"outbound\"\n );\n}\n"]}
|
|
1
|
+
{"version":3,"file":"whatsapp.js","sourceRoot":"","sources":["../../../../src/providers/builtin/whatsapp.ts"],"names":[],"mappings":"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","sourcesContent":["import { createHmac, timingSafeEqual } from \"node:crypto\";\nimport path from \"node:path\";\nimport { CrablineError, ensureErrorMessage } from \"../../core/errors.js\";\nimport { matchesInbound } from \"../../core/matcher.js\";\nimport type { ProviderConfig } from \"../../config/schema.js\";\nimport { LocalMockProviderAdapter, type LocalMockWebhookConfig } from \"../local-mock.js\";\nimport {\n appendRecordedInboundBatch,\n cloneRecordedInboundCursor,\n createRecordedInboundCursor,\n waitForRecordedInbound,\n watchRecordedInbound,\n type RecordedInboundCursor,\n type RecordedInboundEnvelope,\n} from \"../recorder.js\";\nimport type {\n InboundEnvelope,\n ProbeResult,\n ProviderAdapter,\n ProviderContext,\n SendContext,\n SendResult,\n WaitContext,\n WatchContext,\n} from \"../types.js\";\nimport { getBuiltinTargetCodec, WHATSAPP_WA_ID_RULE } from \"../target-normalizers.js\";\nimport { startWebhookServer, type StartedWebhookServer } from \"../webhook-server.js\";\nimport {\n authorFromBotFlag,\n genericMockPayloadWithNativeThread,\n isRecord,\n normalizeAuthor,\n optionalRecord,\n optionalString,\n requireNativeInboundId,\n} from \"./native-local-mock.js\";\n\ntype NormalizedWhatsAppWebhookMessage = {\n author?: \"assistant\" | \"system\" | \"user\";\n authorIsBot?: boolean;\n id?: string;\n message?: {\n author?: \"assistant\" | \"system\" | \"user\";\n authorIsBot?: boolean;\n id?: string;\n raw?: unknown;\n sentAt?: string;\n text?: string;\n threadId?: string;\n };\n raw?: unknown;\n sentAt?: string;\n text?: string;\n threadId?: string;\n};\n\ntype WhatsAppEnvironment = Partial<\n Pick<\n NodeJS.ProcessEnv,\n | \"WHATSAPP_ACCESS_TOKEN\"\n | \"WHATSAPP_APP_SECRET\"\n | \"WHATSAPP_PHONE_NUMBER_ID\"\n | \"WHATSAPP_VERIFY_TOKEN\"\n >\n>;\n\nconst DEFAULT_WHATSAPP_WEBHOOK = {\n host: \"127.0.0.1\",\n path: \"/whatsapp/webhook\",\n port: 8789,\n} as const;\nconst MAX_WAIT_CURSORS = 64;\nconst MAX_WHATSAPP_WEBHOOK_BODY_BYTES = 1024 * 1024;\nconst WHATSAPP_WEBHOOK_BODY_TIMEOUT_MS = 5_000;\nconst WHATSAPP_WEBHOOK_CLEANUP_GRACE_MS = 250;\n\nfunction abortableOperation<T>(operation: Promise<T>, signal: AbortSignal): Promise<T> {\n if (signal.aborted) {\n return Promise.reject(signal.reason);\n }\n return new Promise<T>((resolve, reject) => {\n const onAbort = () => reject(signal.reason);\n signal.addEventListener(\"abort\", onAbort, { once: true });\n void operation.then(\n (value) => {\n signal.removeEventListener(\"abort\", onAbort);\n resolve(value);\n },\n (error: unknown) => {\n signal.removeEventListener(\"abort\", onAbort);\n reject(error);\n },\n );\n });\n}\n\nclass WhatsAppWebhookBodyError extends Error {\n constructor(\n message: string,\n readonly status: number,\n ) {\n super(message);\n }\n}\n\nasync function readWhatsAppWebhookBody(\n request: Request,\n lifecycleSignal: AbortSignal,\n): Promise<string> {\n if (!request.body) {\n return \"\";\n }\n\n const timeoutController = new AbortController();\n const timeout = setTimeout(() => {\n timeoutController.abort(new WhatsAppWebhookBodyError(\"webhook request body timed out\", 408));\n }, WHATSAPP_WEBHOOK_BODY_TIMEOUT_MS);\n timeout.unref();\n const signal = AbortSignal.any([lifecycleSignal, request.signal, timeoutController.signal]);\n const reader = request.body.getReader();\n const chunks: Buffer[] = [];\n let bodyBytes = 0;\n let completed = false;\n let failure: unknown;\n\n try {\n while (true) {\n const result = await new Promise<Awaited<ReturnType<typeof reader.read>>>(\n (resolve, reject) => {\n if (signal.aborted) {\n reject(signal.reason);\n return;\n }\n const abort = () => reject(signal.reason);\n signal.addEventListener(\"abort\", abort, { once: true });\n void reader.read().then(\n (value) => {\n signal.removeEventListener(\"abort\", abort);\n resolve(value);\n },\n (error) => {\n signal.removeEventListener(\"abort\", abort);\n reject(error);\n },\n );\n },\n );\n if (result.done) {\n completed = true;\n return Buffer.concat(chunks).toString(\"utf8\");\n }\n const chunk = Buffer.from(result.value);\n bodyBytes += chunk.length;\n if (bodyBytes > MAX_WHATSAPP_WEBHOOK_BODY_BYTES) {\n throw new WhatsAppWebhookBodyError(\"request body too large\", 413);\n }\n chunks.push(chunk);\n }\n } catch (error) {\n failure = error;\n throw error;\n } finally {\n clearTimeout(timeout);\n if (!completed) {\n void reader.cancel(failure ?? signal.reason).catch(() => undefined);\n } else {\n reader.releaseLock();\n }\n }\n}\n\nexport function resolveWhatsAppAdapterConfig(\n config: ProviderConfig,\n env: WhatsAppEnvironment = process.env,\n) {\n const appSecret = config.whatsapp?.appSecret ?? env.WHATSAPP_APP_SECRET;\n const verifyToken = config.whatsapp?.verifyToken ?? env.WHATSAPP_VERIFY_TOKEN;\n if (!appSecret?.trim() || !verifyToken?.trim()) {\n throw new CrablineError(\n \"WhatsApp webhook operation requires appSecret and verifyToken configuration.\",\n { kind: \"config\" },\n );\n }\n return {\n accessToken: config.whatsapp?.accessToken ?? env.WHATSAPP_ACCESS_TOKEN ?? \"local-mock-token\",\n appSecret,\n ...((config.whatsapp?.phoneNumberId ?? env.WHATSAPP_PHONE_NUMBER_ID)\n ? { phoneNumberId: config.whatsapp?.phoneNumberId ?? env.WHATSAPP_PHONE_NUMBER_ID! }\n : {}),\n verifyToken,\n };\n}\n\ntype ResolvedWhatsAppAdapterConfig = ReturnType<typeof resolveWhatsAppAdapterConfig>;\ntype WaitCursorState = {\n active: number;\n cursor?: RecordedInboundCursor | undefined;\n};\n\nfunction cursorHasAdvanced(\n candidate: RecordedInboundCursor,\n current: RecordedInboundCursor | undefined,\n): boolean {\n if (!current) {\n return true;\n }\n if (candidate.readState.generation !== current.readState.generation) {\n return candidate.readState.generation > current.readState.generation;\n }\n if (candidate.readState.offset !== current.readState.offset) {\n return candidate.readState.offset > current.readState.offset;\n }\n return candidate.buffered.length < current.buffered.length;\n}\n\nfunction pruneInactiveWaitCursors(cursors: Map<string, WaitCursorState>): void {\n let inactiveCount = 0;\n for (const state of cursors.values()) {\n if (state.active === 0) {\n inactiveCount++;\n }\n }\n if (inactiveCount <= MAX_WAIT_CURSORS) {\n return;\n }\n for (const [key, state] of cursors) {\n if (state.active === 0) {\n cursors.delete(key);\n inactiveCount--;\n if (inactiveCount <= MAX_WAIT_CURSORS) {\n return;\n }\n }\n }\n}\n\nexport class WhatsAppProviderAdapter extends LocalMockProviderAdapter implements ProviderAdapter {\n readonly #config: ProviderConfig;\n readonly #env: WhatsAppEnvironment;\n readonly #lifecycleAbort = new AbortController();\n readonly #publicUrl: string | undefined;\n readonly #recorderPath: string;\n readonly #webhook: LocalMockWebhookConfig | undefined;\n #cleanedUp = false;\n #cleanupBegun = false;\n #cleanupPromise: Promise<void> | null = null;\n readonly #inFlightSends = new Set<Promise<SendResult>>();\n readonly #inFlightWebhookRequests = new Set<Promise<Response>>();\n readonly #waitCursors = new Map<string, WaitCursorState>();\n #server: StartedWebhookServer | null = null;\n #serverClosePromise: Promise<void> | null = null;\n #serverClosing: Promise<void> | null = null;\n #serverStarting: Promise<StartedWebhookServer> | null = null;\n\n constructor(id: string, config: ProviderConfig, _userName: string, runtime?: unknown) {\n super({\n codec: getBuiltinTargetCodec(\"whatsapp\"),\n config,\n id,\n options: {\n defaultWebhook: DEFAULT_WHATSAPP_WEBHOOK,\n endpointLabel: \"webhook endpoint\",\n normalizeWebhookPayload: normalizeWhatsAppWebhookPayload,\n platform: \"whatsapp\",\n publicUrl: config.whatsapp?.webhook.publicUrl,\n recorderPath: config.whatsapp?.recorder.path\n ? path.resolve(config.whatsapp.recorder.path)\n : undefined,\n webhook: config.whatsapp?.webhook,\n },\n });\n this.#config = config;\n this.#env = (runtime as { env?: WhatsAppEnvironment } | undefined)?.env ?? process.env;\n this.#publicUrl = config.whatsapp?.webhook.publicUrl;\n this.#recorderPath = config.whatsapp?.recorder.path\n ? path.resolve(config.whatsapp.recorder.path)\n : path.resolve(\".crabline\", \"recorders\", `${id}.jsonl`);\n this.#webhook = config.whatsapp?.webhook;\n }\n\n override async probe(context: ProviderContext): Promise<ProbeResult> {\n const signal = this.#operationSignal(context.signal);\n signal.throwIfAborted();\n const server = await this.#ensureWebhookServer(signal);\n if (this.#cleanupBegun || this.#cleanedUp) {\n throw this.#cleanedUpError();\n }\n signal.throwIfAborted();\n const target = this.normalizeTarget(context.fixture.target);\n const details = [\n \"whatsapp local mock ready\",\n `recorder path ${this.#recorderPath}`,\n `webhook endpoint ${server.endpointUrl}`,\n ];\n if (this.#publicUrl) {\n details.push(`public webhook ${this.#publicUrl}`);\n }\n if (target.threadId) {\n details.push(`thread reachable ${target.threadId}`);\n } else if (target.channelId) {\n details.push(`channel reachable ${target.channelId}`);\n } else {\n details.push(`dm reachable ${target.id}`);\n }\n return { details, healthy: true };\n }\n\n override async send(context: SendContext): Promise<SendResult> {\n if (this.#cleanupBegun || this.#cleanedUp) {\n throw this.#cleanedUpError();\n }\n const sending = super.send(context);\n this.#inFlightSends.add(sending);\n try {\n return await sending;\n } finally {\n this.#inFlightSends.delete(sending);\n }\n }\n\n override async waitForInbound(context: WaitContext): Promise<InboundEnvelope | null> {\n if (context.signal?.aborted) {\n return null;\n }\n const signal = this.#operationSignal(context.signal);\n try {\n await this.#ensureWebhookServer(signal);\n } catch (error) {\n if (this.#cleanupBegun || signal.aborted) {\n return null;\n }\n throw error;\n }\n if (this.#cleanupBegun) {\n return null;\n }\n const target = this.normalizeTarget(context.fixture.target);\n const channelId = context.threadId ?? target.threadId ?? target.channelId ?? target.id;\n const excludedIds = new Set(context.excludeIds ?? []);\n const cursorKey = JSON.stringify([\n context.nonce,\n context.since,\n channelId,\n context.fixture.inboundMatch,\n ]);\n const cursorState = this.#waitCursors.get(cursorKey) ?? { active: 0 };\n const cursor = cursorState.cursor\n ? cloneRecordedInboundCursor(cursorState.cursor)\n : createRecordedInboundCursor();\n cursorState.active++;\n this.#waitCursors.delete(cursorKey);\n this.#waitCursors.set(cursorKey, cursorState);\n pruneInactiveWaitCursors(this.#waitCursors);\n try {\n const event = await waitForRecordedInbound({\n cursor,\n filePath: this.#recorderPath,\n matches: (candidate) =>\n candidate.provider === this.id &&\n !excludedIds.has(candidate.id) &&\n !isOutboundRecord(candidate) &&\n isAddressInChannel(candidate.threadId, channelId) &&\n matchesInbound(candidate, context.fixture.inboundMatch, context.nonce),\n since: context.since,\n signal,\n timeoutMs: context.timeoutMs,\n });\n if (\n this.#waitCursors.get(cursorKey) === cursorState &&\n cursorHasAdvanced(cursor, cursorState.cursor)\n ) {\n cursorState.cursor = cursor;\n }\n return event;\n } finally {\n cursorState.active--;\n if (\n cursorState.active === 0 &&\n !cursorState.cursor &&\n this.#waitCursors.get(cursorKey) === cursorState\n ) {\n this.#waitCursors.delete(cursorKey);\n }\n pruneInactiveWaitCursors(this.#waitCursors);\n }\n }\n\n override async *watch(context: WatchContext): AsyncIterable<InboundEnvelope> {\n if (context.signal?.aborted) {\n return;\n }\n const signal = this.#operationSignal(context.signal);\n try {\n await this.#ensureWebhookServer(signal);\n } catch (error) {\n if (this.#cleanupBegun || signal.aborted) {\n return;\n }\n throw error;\n }\n if (this.#cleanupBegun) {\n return;\n }\n const target = this.normalizeTarget(context.fixture.target);\n for await (const event of watchRecordedInbound({\n filePath: this.#recorderPath,\n matches: (entry) =>\n entry.provider === this.id &&\n !isOutboundRecord(entry) &&\n isAddressInChannel(entry.threadId, target.threadId ?? target.channelId ?? target.id),\n signal,\n since: context.since,\n })) {\n yield event;\n }\n }\n\n beginCleanup(): void {\n if (this.#cleanupBegun) {\n return;\n }\n this.#cleanupBegun = true;\n this.#lifecycleAbort.abort(this.#cleanedUpError());\n this.#serverClosing = this.#closeWebhookServer();\n void this.#serverClosing.catch(() => undefined);\n }\n\n override async cleanup(): Promise<void> {\n this.beginCleanup();\n this.#cleanedUp = true;\n this.#waitCursors.clear();\n this.#cleanupPromise ??= (async () => {\n const webhookRequests = [...this.#inFlightWebhookRequests];\n const settled = Promise.allSettled(webhookRequests).then(() => undefined);\n let webhookTimer: NodeJS.Timeout | undefined;\n const webhookDeadline =\n webhookRequests.length === 0\n ? settled\n : new Promise<never>((_, reject) => {\n webhookTimer = setTimeout(() => {\n reject(\n new CrablineError(\n `Provider \"${this.id}\" webhook handlers did not settle within ${WHATSAPP_WEBHOOK_CLEANUP_GRACE_MS}ms after cleanup.`,\n { kind: \"timeout\" },\n ),\n );\n }, WHATSAPP_WEBHOOK_CLEANUP_GRACE_MS);\n });\n const errors: unknown[] = [];\n const drainResults = await Promise.allSettled([\n ...this.#inFlightSends,\n Promise.race([settled, webhookDeadline]).finally(() => clearTimeout(webhookTimer)),\n ]);\n const webhookResult = drainResults.at(-1);\n if (webhookResult?.status === \"rejected\") {\n errors.push(webhookResult.reason);\n }\n try {\n await this.#serverClosing;\n } catch (error) {\n errors.push(error);\n }\n try {\n await super.cleanup();\n } catch (error) {\n errors.push(error);\n }\n if (errors.length === 1) {\n throw errors[0];\n }\n if (errors.length > 1) {\n throw new AggregateError(errors, \"WhatsApp cleanup failed\");\n }\n })();\n await this.#cleanupPromise;\n }\n\n #handleWebhookRequest(\n request: Request,\n resolvedConfig: ResolvedWhatsAppAdapterConfig,\n ): Promise<Response> {\n if (this.#cleanupBegun) {\n return Promise.resolve(this.#cleanedUpResponse());\n }\n const handling = this.#handleWebhook(request, resolvedConfig);\n this.#inFlightWebhookRequests.add(handling);\n void handling.then(\n () => this.#inFlightWebhookRequests.delete(handling),\n () => this.#inFlightWebhookRequests.delete(handling),\n );\n return handling;\n }\n\n async #handleWebhook(\n request: Request,\n resolvedConfig: ResolvedWhatsAppAdapterConfig,\n ): Promise<Response> {\n if (request.method === \"GET\") {\n const url = new URL(request.url);\n const mode = url.searchParams.get(\"hub.mode\");\n const providedValue = url.searchParams.get(\"hub.verify_token\");\n const challenge = url.searchParams.get(\"hub.challenge\");\n if (\n mode === \"subscribe\" &&\n providedValue === resolvedConfig.verifyToken &&\n challenge !== null\n ) {\n return new Response(challenge, {\n headers: { \"content-type\": \"text/plain; charset=utf-8\" },\n status: 200,\n });\n }\n return new Response(\"forbidden\", { status: 403 });\n }\n\n let rawBody: string;\n try {\n rawBody = await readWhatsAppWebhookBody(request, this.#lifecycleAbort.signal);\n } catch (error) {\n if (this.#cleanupBegun) {\n return this.#cleanedUpResponse();\n }\n if (error instanceof WhatsAppWebhookBodyError) {\n return new Response(error.message, { status: error.status });\n }\n return new Response(\"invalid request body\", { status: 400 });\n }\n if (\n !hasValidWhatsAppSignature(\n rawBody,\n request.headers.get(\"x-hub-signature-256\"),\n resolvedConfig.appSecret,\n )\n ) {\n return new Response(\"invalid webhook signature\", { status: 401 });\n }\n const mediaType = request.headers.get(\"content-type\")?.split(\";\", 1)[0]?.trim().toLowerCase();\n if (mediaType !== \"application/json\") {\n return new Response(\"expected application/json\", { status: 415 });\n }\n\n let messages: NormalizedWhatsAppWebhookMessage[];\n try {\n messages = normalizeWhatsAppWebhookPayload(JSON.parse(rawBody), resolvedConfig.phoneNumberId);\n } catch (error) {\n return new Response(ensureErrorMessage(error), { status: 400 });\n }\n\n const ids: string[] = [];\n const records: InboundEnvelope[] = [];\n for (const message of messages) {\n const id = message.message?.id ?? message.id ?? createMessageId();\n const threadId = message.message?.threadId ?? message.threadId;\n const text = message.message?.text ?? message.text;\n if (!threadId || !text) {\n return new Response(\"payload requires message.threadId and message.text\", { status: 400 });\n }\n\n records.push({\n author: authorFromPayload(message),\n id,\n provider: this.id,\n raw: message.message?.raw ?? message.raw ?? message,\n sentAt: message.message?.sentAt ?? message.sentAt ?? new Date().toISOString(),\n text,\n threadId,\n });\n ids.push(id);\n }\n await appendRecordedInboundBatch(this.#recorderPath, records);\n\n return new Response(\n JSON.stringify(ids.length === 1 ? { id: ids[0], ok: true } : { ids, ok: true }),\n {\n headers: { \"content-type\": \"application/json\" },\n status: 200,\n },\n );\n }\n\n async #ensureWebhookServer(signal: AbortSignal): Promise<StartedWebhookServer> {\n if (this.#cleanupBegun) {\n throw this.#cleanedUpError();\n }\n signal.throwIfAborted();\n if (this.#server) {\n return this.#server;\n }\n if (this.#serverStarting) {\n return await abortableOperation(this.#serverStarting, signal);\n }\n\n const resolvedConfig = resolveWhatsAppAdapterConfig(this.#config, this.#env);\n const host = this.#webhook?.host ?? DEFAULT_WHATSAPP_WEBHOOK.host;\n const port = this.#webhook?.port ?? DEFAULT_WHATSAPP_WEBHOOK.port;\n const webhookPath = this.#webhook?.path ?? DEFAULT_WHATSAPP_WEBHOOK.path;\n const starting = (async (): Promise<StartedWebhookServer> => {\n let server: StartedWebhookServer;\n try {\n server = await startWebhookServer({\n handle: (request) => this.#handleWebhookRequest(request, resolvedConfig),\n host,\n methods: [\"GET\", \"POST\"],\n path: webhookPath,\n port,\n signal: this.#lifecycleAbort.signal,\n });\n } catch (error) {\n if (this.#cleanupBegun) {\n throw error;\n }\n throw new CrablineError(\n `whatsapp local mock webhook server failed: ${ensureErrorMessage(error)}`,\n { cause: error, kind: \"connectivity\" },\n );\n }\n\n this.#server = server;\n if (this.#cleanupBegun) {\n await this.#closeStartedWebhookServer(server);\n }\n return server;\n })();\n this.#serverStarting = starting;\n void starting.then(\n () => {\n if (this.#serverStarting === starting) {\n this.#serverStarting = null;\n }\n },\n () => {\n if (this.#serverStarting === starting) {\n this.#serverStarting = null;\n }\n },\n );\n\n const server = await abortableOperation(starting, signal);\n if (this.#cleanupBegun) {\n throw this.#cleanedUpError();\n }\n return server;\n }\n\n async #closeStartedWebhookServer(server: StartedWebhookServer): Promise<void> {\n if (this.#server === server) {\n this.#server = null;\n }\n if (!this.#serverClosePromise) {\n this.#serverClosePromise = server.close();\n }\n await this.#serverClosePromise;\n }\n\n async #closeWebhookServer(): Promise<void> {\n const starting = this.#serverStarting;\n if (starting) {\n try {\n await starting;\n } catch (error) {\n if (error !== this.#lifecycleAbort.signal.reason) {\n throw error;\n }\n }\n }\n const server = this.#server;\n if (server) {\n await this.#closeStartedWebhookServer(server);\n return;\n }\n if (this.#serverClosePromise) {\n await this.#serverClosePromise;\n }\n }\n\n #cleanedUpError(): CrablineError {\n return new CrablineError(`Provider \"${this.id}\" has been cleaned up.`, { kind: \"config\" });\n }\n\n #cleanedUpResponse(): Response {\n return new Response(`Provider \"${this.id}\" has been cleaned up.`, { status: 503 });\n }\n\n #operationSignal(signal: AbortSignal | undefined): AbortSignal {\n return signal\n ? AbortSignal.any([signal, this.#lifecycleAbort.signal])\n : this.#lifecycleAbort.signal;\n }\n}\n\nexport function normalizeWhatsAppWebhookPayload(\n payload: unknown,\n expectedPhoneNumberId?: string,\n): NormalizedWhatsAppWebhookMessage[] {\n if (!isRecord(payload)) {\n throw new CrablineError(\"WhatsApp webhook payload must be an object\", { kind: \"inbound\" });\n }\n\n const normalized: NormalizedWhatsAppWebhookMessage[] = [];\n if (Array.isArray(payload.entry)) {\n if (optionalString(payload, \"object\") !== \"whatsapp_business_account\") {\n throw new CrablineError(\n 'WhatsApp webhook entry payloads require object=\"whatsapp_business_account\"',\n { kind: \"inbound\" },\n );\n }\n for (const entry of payload.entry) {\n if (!isRecord(entry) || !Array.isArray(entry.changes)) {\n continue;\n }\n for (const change of entry.changes) {\n if (!isRecord(change)) {\n continue;\n }\n const field = optionalString(change, \"field\");\n if (field !== undefined && field !== \"messages\") {\n continue;\n }\n const value = optionalRecord(change, \"value\");\n if (!value || !Array.isArray(value.messages)) {\n continue;\n }\n const metadata = optionalRecord(value, \"metadata\");\n if (\n expectedPhoneNumberId !== undefined &&\n optionalString(metadata ?? {}, \"phone_number_id\") !== expectedPhoneNumberId\n ) {\n continue;\n }\n for (const message of value.messages) {\n if (!isRecord(message)) {\n throw new CrablineError(\"WhatsApp webhook messages[] entries must be objects\", {\n kind: \"inbound\",\n });\n }\n const normalizedMessage = normalizeWhatsAppMessage(message);\n if (normalizedMessage) {\n normalized.push(normalizedMessage);\n }\n }\n }\n }\n return normalized;\n }\n\n const fallback = genericMockPayloadWithNativeThread({\n channelRule: WHATSAPP_WA_ID_RULE,\n payload,\n threadRule: WHATSAPP_WA_ID_RULE,\n }) as Record<string, unknown>;\n return [normalizeWhatsAppFallback(fallback, payload)];\n}\n\nfunction normalizeWhatsAppFallback(\n fallback: Record<string, unknown>,\n source: Record<string, unknown>,\n): NormalizedWhatsAppWebhookMessage {\n const normalized: NormalizedWhatsAppWebhookMessage = {\n raw: fallback.raw ?? fallback,\n };\n const author = normalizeAuthor(fallback.author);\n if (author) {\n normalized.author = author;\n }\n if (typeof fallback.authorIsBot === \"boolean\") {\n normalized.authorIsBot = fallback.authorIsBot;\n }\n const id = optionalString(fallback, \"id\");\n if (id) {\n normalized.id = id;\n }\n const text = optionalString(fallback, \"text\");\n if (text) {\n normalized.text = text;\n }\n const threadId = optionalString(fallback, \"threadId\");\n if (threadId) {\n normalized.threadId = threadId;\n }\n const sentAt = optionalString(source, \"sentAt\");\n if (sentAt) {\n normalized.sentAt = whatsAppFallbackTimestampToIso(sentAt, \"sentAt\");\n }\n\n const message = optionalRecord(fallback, \"message\");\n if (message) {\n const sourceMessage = optionalRecord(source, \"message\");\n const normalizedMessage: NonNullable<NormalizedWhatsAppWebhookMessage[\"message\"]> = {};\n const messageAuthor = normalizeAuthor(message.author);\n if (messageAuthor) {\n normalizedMessage.author = messageAuthor;\n }\n if (typeof message.authorIsBot === \"boolean\") {\n normalizedMessage.authorIsBot = message.authorIsBot;\n }\n const messageId = optionalString(message, \"id\");\n if (messageId) {\n normalizedMessage.id = messageId;\n }\n if (message.raw !== undefined) {\n normalizedMessage.raw = message.raw;\n }\n const messageSentAt = sourceMessage ? optionalString(sourceMessage, \"sentAt\") : undefined;\n if (messageSentAt) {\n normalizedMessage.sentAt = whatsAppFallbackTimestampToIso(messageSentAt, \"message.sentAt\");\n }\n const messageText = optionalString(message, \"text\");\n if (messageText) {\n normalizedMessage.text = messageText;\n }\n const messageThreadId = optionalString(message, \"threadId\");\n if (messageThreadId) {\n normalizedMessage.threadId = messageThreadId;\n }\n normalized.message = normalizedMessage;\n }\n\n return normalized;\n}\n\nfunction normalizeWhatsAppMessage(\n message: Record<string, unknown>,\n): NormalizedWhatsAppWebhookMessage | null {\n const messageType = optionalString(message, \"type\");\n if (messageType && messageType !== \"text\") {\n return null;\n }\n\n const text = optionalRecord(message, \"text\");\n const from = optionalString(message, \"from\");\n const body = text ? optionalString(text, \"body\") : undefined;\n if (!from || !body) {\n throw new CrablineError(\"WhatsApp webhook payload requires messages[].from and text.body\", {\n kind: \"inbound\",\n });\n }\n\n const messageId = optionalString(message, \"id\");\n if (!messageId) {\n throw new CrablineError(\"WhatsApp webhook payload requires messages[].id\", {\n kind: \"inbound\",\n });\n }\n const timestamp = optionalString(message, \"timestamp\");\n return {\n author: authorFromBotFlag(false),\n id: messageId,\n raw: message,\n ...(timestamp ? { sentAt: whatsAppTimestampToIso(timestamp) } : {}),\n text: body,\n threadId: requireNativeInboundId(from, WHATSAPP_WA_ID_RULE, \"WhatsApp messages[].from\"),\n };\n}\n\nfunction whatsAppTimestampToIso(timestamp: string): string {\n if (!/^\\d+$/u.test(timestamp)) {\n throw new CrablineError(\"WhatsApp messages[].timestamp must be Unix seconds\", {\n kind: \"inbound\",\n });\n }\n const milliseconds = Number(timestamp) * 1000;\n if (!Number.isSafeInteger(milliseconds)) {\n throw new CrablineError(\"WhatsApp messages[].timestamp is out of range\", { kind: \"inbound\" });\n }\n const date = new Date(milliseconds);\n if (Number.isNaN(date.getTime())) {\n throw new CrablineError(\"WhatsApp messages[].timestamp is invalid\", { kind: \"inbound\" });\n }\n return date.toISOString();\n}\n\nfunction whatsAppFallbackTimestampToIso(timestamp: string, field: string): string {\n const date = new Date(timestamp);\n if (Number.isNaN(date.getTime())) {\n throw new CrablineError(`WhatsApp fallback ${field} must be a valid timestamp`, {\n kind: \"inbound\",\n });\n }\n return date.toISOString();\n}\n\nfunction authorFromPayload(payload: NormalizedWhatsAppWebhookMessage): InboundEnvelope[\"author\"] {\n const explicit = payload.message?.author ?? payload.author;\n if (explicit) {\n return explicit;\n }\n return (payload.message?.authorIsBot ?? payload.authorIsBot ?? true) ? \"assistant\" : \"user\";\n}\n\nfunction createMessageId(): string {\n return `whatsapp-mock-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;\n}\n\nfunction hasValidWhatsAppSignature(\n rawBody: string,\n signatureHeader: string | null,\n signingKey: string,\n): boolean {\n if (!signatureHeader?.startsWith(\"sha256=\")) {\n return false;\n }\n const signature = signatureHeader.slice(\"sha256=\".length);\n if (!/^[a-f0-9]{64}$/iu.test(signature)) {\n return false;\n }\n const expected = createHmac(\"sha256\", signingKey).update(rawBody).digest();\n const actual = Buffer.from(signature, \"hex\");\n return actual.length === expected.length && timingSafeEqual(actual, expected);\n}\n\nfunction isAddressInChannel(threadId: string, channelId?: string): boolean {\n if (!channelId) {\n return true;\n }\n return threadId === channelId || threadId.startsWith(`${channelId}:`);\n}\n\nfunction isOutboundRecord(event: RecordedInboundEnvelope): boolean {\n if (event.recordedDirection !== undefined) {\n return event.recordedDirection === \"outbound\";\n }\n return (\n event.raw !== null &&\n typeof event.raw === \"object\" &&\n \"direction\" in event.raw &&\n event.raw.direction === \"outbound\"\n );\n}\n"]}
|
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
import type { ProviderConfig } from "../../config/schema.js";
|
|
2
2
|
import { LocalMockProviderAdapter } from "../local-mock.js";
|
|
3
3
|
import type { ProviderAdapter } from "../types.js";
|
|
4
|
-
|
|
4
|
+
type ZaloEnvironment = Partial<Pick<NodeJS.ProcessEnv, "ZALO_BOT_TOKEN" | "ZALO_WEBHOOK_SECRET">>;
|
|
5
|
+
export declare function resolveZaloAdapterConfig(config: ProviderConfig, env?: ZaloEnvironment): {
|
|
5
6
|
botToken: string;
|
|
6
7
|
webhookSecret: string | undefined;
|
|
7
8
|
};
|
|
8
9
|
export declare class ZaloProviderAdapter extends LocalMockProviderAdapter implements ProviderAdapter {
|
|
9
|
-
constructor(id: string, config: ProviderConfig, _userName: string,
|
|
10
|
+
constructor(id: string, config: ProviderConfig, _userName: string, runtime?: unknown);
|
|
10
11
|
}
|
|
12
|
+
export declare function matchesZaloTarget(candidateThreadId: string, expectedThreadId: string | undefined): boolean;
|
|
11
13
|
export declare function normalizeZaloWebhookPayload(payload: unknown): {
|
|
12
14
|
author?: "assistant" | "system" | "user" | undefined;
|
|
13
15
|
authorIsBot?: boolean;
|
|
@@ -15,3 +17,4 @@ export declare function normalizeZaloWebhookPayload(payload: unknown): {
|
|
|
15
17
|
raw: {};
|
|
16
18
|
text?: string | undefined;
|
|
17
19
|
};
|
|
20
|
+
export {};
|
|
@@ -4,14 +4,22 @@ import { LocalMockProviderAdapter } from "../local-mock.js";
|
|
|
4
4
|
import { getBuiltinTargetCodec, ZALO_ID_RULE } from "../target-normalizers.js";
|
|
5
5
|
import { authorFromBotFlag, createSecretVerifier, genericMockPayloadWithNativeThread, isRecord, optionalRecord, optionalString, requireNativeInboundId, } from "./native-local-mock.js";
|
|
6
6
|
export function resolveZaloAdapterConfig(config, env = process.env) {
|
|
7
|
+
const configuredWebhookSecret = config.zalo?.webhookSecret;
|
|
8
|
+
const webhookSecret = configuredWebhookSecret ?? env.ZALO_WEBHOOK_SECRET;
|
|
9
|
+
if (webhookSecret !== undefined && !webhookSecret.trim()) {
|
|
10
|
+
throw new CrablineError(configuredWebhookSecret === undefined
|
|
11
|
+
? "ZALO_WEBHOOK_SECRET must not be empty or whitespace-only."
|
|
12
|
+
: "Zalo webhookSecret must not be empty or whitespace-only.", { kind: "config" });
|
|
13
|
+
}
|
|
7
14
|
return {
|
|
8
15
|
botToken: config.zalo?.botToken ?? env.ZALO_BOT_TOKEN ?? "local-mock-zalo-token",
|
|
9
|
-
webhookSecret
|
|
16
|
+
webhookSecret,
|
|
10
17
|
};
|
|
11
18
|
}
|
|
12
19
|
export class ZaloProviderAdapter extends LocalMockProviderAdapter {
|
|
13
|
-
constructor(id, config, _userName,
|
|
14
|
-
const
|
|
20
|
+
constructor(id, config, _userName, runtime) {
|
|
21
|
+
const env = runtime?.env ?? process.env;
|
|
22
|
+
const resolvedConfig = resolveZaloAdapterConfig(config, env);
|
|
15
23
|
const authenticateWebhook = resolvedConfig.webhookSecret
|
|
16
24
|
? createSecretVerifier(resolvedConfig.webhookSecret)
|
|
17
25
|
: undefined;
|
|
@@ -31,6 +39,7 @@ export class ZaloProviderAdapter extends LocalMockProviderAdapter {
|
|
|
31
39
|
: {}),
|
|
32
40
|
defaultWebhook: { host: "127.0.0.1", path: "/zalo/webhook", port: 8794 },
|
|
33
41
|
endpointLabel: "webhook endpoint",
|
|
42
|
+
matchesThread: matchesZaloTarget,
|
|
34
43
|
normalizeWebhookPayload: normalizeZaloWebhookPayload,
|
|
35
44
|
platform: "zalo",
|
|
36
45
|
publicUrl: config.zalo?.webhook.publicUrl,
|
|
@@ -42,12 +51,16 @@ export class ZaloProviderAdapter extends LocalMockProviderAdapter {
|
|
|
42
51
|
});
|
|
43
52
|
}
|
|
44
53
|
}
|
|
54
|
+
export function matchesZaloTarget(candidateThreadId, expectedThreadId) {
|
|
55
|
+
return expectedThreadId === undefined || candidateThreadId === expectedThreadId;
|
|
56
|
+
}
|
|
45
57
|
export function normalizeZaloWebhookPayload(payload) {
|
|
46
58
|
if (!isRecord(payload)) {
|
|
47
59
|
throw new CrablineError("Zalo webhook payload must be an object", { kind: "inbound" });
|
|
48
60
|
}
|
|
49
|
-
|
|
50
|
-
|
|
61
|
+
const payloadMessage = optionalRecord(payload, "message");
|
|
62
|
+
if (optionalString(payload, "threadId") ||
|
|
63
|
+
(payloadMessage && optionalString(payloadMessage, "threadId"))) {
|
|
51
64
|
return genericMockPayloadWithNativeThread({
|
|
52
65
|
channelRule: ZALO_ID_RULE,
|
|
53
66
|
payload,
|
|
@@ -60,9 +73,20 @@ export function normalizeZaloWebhookPayload(payload) {
|
|
|
60
73
|
const chat = message ? optionalRecord(message, "chat") : undefined;
|
|
61
74
|
const senderId = sender ? optionalString(sender, "id") : undefined;
|
|
62
75
|
const chatId = chat ? optionalString(chat, "id") : senderId;
|
|
63
|
-
const
|
|
76
|
+
const eventName = optionalString(wrapped, "event_name");
|
|
77
|
+
// Live Zalo Bot image callbacks expose the media URL as photo_url, not photo.
|
|
78
|
+
const photoUrl = eventName === "message.image.received" && message
|
|
79
|
+
? optionalString(message, "photo_url")
|
|
80
|
+
: undefined;
|
|
81
|
+
const text = eventName === "message.image.received"
|
|
82
|
+
? photoUrl
|
|
83
|
+
? optionalString(message ?? {}, "caption") || photoUrl
|
|
84
|
+
: undefined
|
|
85
|
+
: message
|
|
86
|
+
? optionalString(message, "text")
|
|
87
|
+
: undefined;
|
|
64
88
|
if (!senderId || !chatId || !text) {
|
|
65
|
-
throw new CrablineError("Zalo webhook payload requires sender identity, chat identity, and
|
|
89
|
+
throw new CrablineError("Zalo webhook payload requires sender identity, chat identity, and message content", {
|
|
66
90
|
kind: "inbound",
|
|
67
91
|
});
|
|
68
92
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"zalo.js","sourceRoot":"","sources":["../../../../src/providers/builtin/zalo.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,EAAE,qBAAqB,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAC/E,OAAO,EACL,iBAAiB,EACjB,oBAAoB,EACpB,kCAAkC,EAClC,QAAQ,EACR,cAAc,EACd,cAAc,EACd,sBAAsB,GACvB,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"zalo.js","sourceRoot":"","sources":["../../../../src/providers/builtin/zalo.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,EAAE,qBAAqB,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAC/E,OAAO,EACL,iBAAiB,EACjB,oBAAoB,EACpB,kCAAkC,EAClC,QAAQ,EACR,cAAc,EACd,cAAc,EACd,sBAAsB,GACvB,MAAM,wBAAwB,CAAC;AAIhC,MAAM,UAAU,wBAAwB,CACtC,MAAsB,EACtB,GAAG,GAAoB,OAAO,CAAC,GAAG;IAElC,MAAM,uBAAuB,GAAG,MAAM,CAAC,IAAI,EAAE,aAAa,CAAC;IAC3D,MAAM,aAAa,GAAG,uBAAuB,IAAI,GAAG,CAAC,mBAAmB,CAAC;IACzE,IAAI,aAAa,KAAK,SAAS,IAAI,CAAC,aAAa,CAAC,IAAI,EAAE,EAAE,CAAC;QACzD,MAAM,IAAI,aAAa,CACrB,uBAAuB,KAAK,SAAS;YACnC,CAAC,CAAC,2DAA2D;YAC7D,CAAC,CAAC,0DAA0D,EAC9D,EAAE,IAAI,EAAE,QAAQ,EAAE,CACnB,CAAC;IACJ,CAAC;IACD,OAAO;QACL,QAAQ,EAAE,MAAM,CAAC,IAAI,EAAE,QAAQ,IAAI,GAAG,CAAC,cAAc,IAAI,uBAAuB;QAChF,aAAa;KACd,CAAC;AACJ,CAAC;AAED,MAAM,OAAO,mBAAoB,SAAQ,wBAAwB;IAC/D,YAAY,EAAU,EAAE,MAAsB,EAAE,SAAiB,EAAE,OAAiB;QAClF,MAAM,GAAG,GAAI,OAAiD,EAAE,GAAG,IAAI,OAAO,CAAC,GAAG,CAAC;QACnF,MAAM,cAAc,GAAG,wBAAwB,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;QAC7D,MAAM,mBAAmB,GAAG,cAAc,CAAC,aAAa;YACtD,CAAC,CAAC,oBAAoB,CAAC,cAAc,CAAC,aAAa,CAAC;YACpD,CAAC,CAAC,SAAS,CAAC;QACd,KAAK,CAAC;YACJ,KAAK,EAAE,qBAAqB,CAAC,MAAM,CAAC;YACpC,MAAM;YACN,EAAE;YACF,OAAO,EAAE;gBACP,GAAG,CAAC,mBAAmB;oBACrB,CAAC,CAAC;wBACE,0BAA0B,CAAC,OAAgB;4BACzC,OAAO,mBAAmB,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,wBAAwB,CAAC,CAAC;gCACvE,CAAC,CAAC,SAAS;gCACX,CAAC,CAAC,IAAI,QAAQ,CAAC,cAAc,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;wBACpD,CAAC;qBACF;oBACH,CAAC,CAAC,EAAE,CAAC;gBACP,cAAc,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,eAAe,EAAE,IAAI,EAAE,IAAI,EAAE;gBACxE,aAAa,EAAE,kBAAkB;gBACjC,aAAa,EAAE,iBAAiB;gBAChC,uBAAuB,EAAE,2BAA2B;gBACpD,QAAQ,EAAE,MAAM;gBAChB,SAAS,EAAE,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,SAAS;gBACzC,YAAY,EAAE,MAAM,CAAC,IAAI,EAAE,QAAQ,CAAC,IAAI;oBACtC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC;oBACzC,CAAC,CAAC,SAAS;gBACb,OAAO,EAAE,MAAM,CAAC,IAAI,EAAE,OAAO;aAC9B;SACF,CAAC,CAAC;IACL,CAAC;CACF;AAED,MAAM,UAAU,iBAAiB,CAC/B,iBAAyB,EACzB,gBAAoC;IAEpC,OAAO,gBAAgB,KAAK,SAAS,IAAI,iBAAiB,KAAK,gBAAgB,CAAC;AAClF,CAAC;AAED,MAAM,UAAU,2BAA2B,CAAC,OAAgB;IAC1D,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;QACvB,MAAM,IAAI,aAAa,CAAC,wCAAwC,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,CAAC;IACzF,CAAC;IAED,MAAM,cAAc,GAAG,cAAc,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;IAC1D,IACE,cAAc,CAAC,OAAO,EAAE,UAAU,CAAC;QACnC,CAAC,cAAc,IAAI,cAAc,CAAC,cAAc,EAAE,UAAU,CAAC,CAAC,EAC9D,CAAC;QACD,OAAO,kCAAkC,CAAC;YACxC,WAAW,EAAE,YAAY;YACzB,OAAO;YACP,UAAU,EAAE,YAAY;SACzB,CAAC,CAAC;IACL,CAAC;IAED,MAAM,OAAO,GAAG,cAAc,CAAC,OAAO,EAAE,QAAQ,CAAC,IAAI,OAAO,CAAC;IAC7D,MAAM,OAAO,GAAG,cAAc,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;IACnD,MAAM,MAAM,GAAG,cAAc,CAAC,OAAO,IAAI,EAAE,EAAE,MAAM,CAAC,IAAI,cAAc,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;IAC1F,MAAM,IAAI,GAAG,OAAO,CAAC,CAAC,CAAC,cAAc,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IACnE,MAAM,QAAQ,GAAG,MAAM,CAAC,CAAC,CAAC,cAAc,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IACnE,MAAM,MAAM,GAAG,IAAI,CAAC,CAAC,CAAC,cAAc,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;IAC5D,MAAM,SAAS,GAAG,cAAc,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC;IACxD,8EAA8E;IAC9E,MAAM,QAAQ,GACZ,SAAS,KAAK,wBAAwB,IAAI,OAAO;QAC/C,CAAC,CAAC,cAAc,CAAC,OAAO,EAAE,WAAW,CAAC;QACtC,CAAC,CAAC,SAAS,CAAC;IAChB,MAAM,IAAI,GACR,SAAS,KAAK,wBAAwB;QACpC,CAAC,CAAC,QAAQ;YACR,CAAC,CAAC,cAAc,CAAC,OAAO,IAAI,EAAE,EAAE,SAAS,CAAC,IAAI,QAAQ;YACtD,CAAC,CAAC,SAAS;QACb,CAAC,CAAC,OAAO;YACP,CAAC,CAAC,cAAc,CAAC,OAAO,EAAE,MAAM,CAAC;YACjC,CAAC,CAAC,SAAS,CAAC;IAClB,IAAI,CAAC,QAAQ,IAAI,CAAC,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC;QAClC,MAAM,IAAI,aAAa,CACrB,mFAAmF,EACnF;YACE,IAAI,EAAE,SAAS;SAChB,CACF,CAAC;IACJ,CAAC;IAED,OAAO;QACL,MAAM,EAAE,iBAAiB,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;QAClD,GAAG,CAAC,cAAc,CAAC,OAAO,IAAI,EAAE,EAAE,YAAY,CAAC;YAC7C,CAAC,CAAC,EAAE,EAAE,EAAE,cAAc,CAAC,OAAO,IAAI,EAAE,EAAE,YAAY,CAAC,EAAE;YACrD,CAAC,CAAC,cAAc,CAAC,OAAO,IAAI,EAAE,EAAE,QAAQ,CAAC;gBACvC,CAAC,CAAC,EAAE,EAAE,EAAE,cAAc,CAAC,OAAO,IAAI,EAAE,EAAE,QAAQ,CAAC,EAAE;gBACjD,CAAC,CAAC,EAAE,CAAC;QACT,GAAG,EAAE,OAAO;QACZ,IAAI;QACJ,QAAQ,EAAE,sBAAsB,CAAC,MAAM,EAAE,YAAY,EAAE,cAAc,CAAC;KACvE,CAAC;AACJ,CAAC","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, ZALO_ID_RULE } from \"../target-normalizers.js\";\nimport {\n authorFromBotFlag,\n createSecretVerifier,\n genericMockPayloadWithNativeThread,\n isRecord,\n optionalRecord,\n optionalString,\n requireNativeInboundId,\n} from \"./native-local-mock.js\";\n\ntype ZaloEnvironment = Partial<Pick<NodeJS.ProcessEnv, \"ZALO_BOT_TOKEN\" | \"ZALO_WEBHOOK_SECRET\">>;\n\nexport function resolveZaloAdapterConfig(\n config: ProviderConfig,\n env: ZaloEnvironment = process.env,\n) {\n const configuredWebhookSecret = config.zalo?.webhookSecret;\n const webhookSecret = configuredWebhookSecret ?? env.ZALO_WEBHOOK_SECRET;\n if (webhookSecret !== undefined && !webhookSecret.trim()) {\n throw new CrablineError(\n configuredWebhookSecret === undefined\n ? \"ZALO_WEBHOOK_SECRET must not be empty or whitespace-only.\"\n : \"Zalo webhookSecret must not be empty or whitespace-only.\",\n { kind: \"config\" },\n );\n }\n return {\n botToken: config.zalo?.botToken ?? env.ZALO_BOT_TOKEN ?? \"local-mock-zalo-token\",\n webhookSecret,\n };\n}\n\nexport class ZaloProviderAdapter extends LocalMockProviderAdapter implements ProviderAdapter {\n constructor(id: string, config: ProviderConfig, _userName: string, runtime?: unknown) {\n const env = (runtime as { env?: ZaloEnvironment } | undefined)?.env ?? process.env;\n const resolvedConfig = resolveZaloAdapterConfig(config, env);\n const authenticateWebhook = resolvedConfig.webhookSecret\n ? createSecretVerifier(resolvedConfig.webhookSecret)\n : undefined;\n super({\n codec: getBuiltinTargetCodec(\"zalo\"),\n config,\n id,\n options: {\n ...(authenticateWebhook\n ? {\n authenticateWebhookRequest(request: Request) {\n return authenticateWebhook(request.headers.get(\"x-bot-api-secret-token\"))\n ? undefined\n : new Response(\"unauthorized\", { status: 401 });\n },\n }\n : {}),\n defaultWebhook: { host: \"127.0.0.1\", path: \"/zalo/webhook\", port: 8794 },\n endpointLabel: \"webhook endpoint\",\n matchesThread: matchesZaloTarget,\n normalizeWebhookPayload: normalizeZaloWebhookPayload,\n platform: \"zalo\",\n publicUrl: config.zalo?.webhook.publicUrl,\n recorderPath: config.zalo?.recorder.path\n ? path.resolve(config.zalo.recorder.path)\n : undefined,\n webhook: config.zalo?.webhook,\n },\n });\n }\n}\n\nexport function matchesZaloTarget(\n candidateThreadId: string,\n expectedThreadId: string | undefined,\n): boolean {\n return expectedThreadId === undefined || candidateThreadId === expectedThreadId;\n}\n\nexport function normalizeZaloWebhookPayload(payload: unknown) {\n if (!isRecord(payload)) {\n throw new CrablineError(\"Zalo webhook payload must be an object\", { kind: \"inbound\" });\n }\n\n const payloadMessage = optionalRecord(payload, \"message\");\n if (\n optionalString(payload, \"threadId\") ||\n (payloadMessage && optionalString(payloadMessage, \"threadId\"))\n ) {\n return genericMockPayloadWithNativeThread({\n channelRule: ZALO_ID_RULE,\n payload,\n threadRule: ZALO_ID_RULE,\n });\n }\n\n const wrapped = optionalRecord(payload, \"result\") ?? payload;\n const message = optionalRecord(wrapped, \"message\");\n const sender = optionalRecord(message ?? {}, \"from\") ?? optionalRecord(wrapped, \"sender\");\n const chat = message ? optionalRecord(message, \"chat\") : undefined;\n const senderId = sender ? optionalString(sender, \"id\") : undefined;\n const chatId = chat ? optionalString(chat, \"id\") : senderId;\n const eventName = optionalString(wrapped, \"event_name\");\n // Live Zalo Bot image callbacks expose the media URL as photo_url, not photo.\n const photoUrl =\n eventName === \"message.image.received\" && message\n ? optionalString(message, \"photo_url\")\n : undefined;\n const text =\n eventName === \"message.image.received\"\n ? photoUrl\n ? optionalString(message ?? {}, \"caption\") || photoUrl\n : undefined\n : message\n ? optionalString(message, \"text\")\n : undefined;\n if (!senderId || !chatId || !text) {\n throw new CrablineError(\n \"Zalo webhook payload requires sender identity, chat identity, and message content\",\n {\n kind: \"inbound\",\n },\n );\n }\n\n return {\n author: authorFromBotFlag(sender?.is_bot === true),\n ...(optionalString(message ?? {}, \"message_id\")\n ? { id: optionalString(message ?? {}, \"message_id\") }\n : optionalString(message ?? {}, \"msg_id\")\n ? { id: optionalString(message ?? {}, \"msg_id\") }\n : {}),\n raw: payload,\n text,\n threadId: requireNativeInboundId(chatId, ZALO_ID_RULE, \"Zalo chat.id\"),\n };\n}\n"]}
|
|
@@ -37,7 +37,7 @@ export declare const OPENCLAW_SUPPORT_CATALOG: readonly [{
|
|
|
37
37
|
readonly status: "ready";
|
|
38
38
|
readonly supports: readonly ["probe", "send", "roundtrip", "agent"];
|
|
39
39
|
}, {
|
|
40
|
-
readonly notes: "Built-in local Mattermost mock.";
|
|
40
|
+
readonly notes: "Built-in local Mattermost mock with authenticated outgoing webhook ingress.";
|
|
41
41
|
readonly platform: "mattermost";
|
|
42
42
|
readonly status: "ready";
|
|
43
43
|
readonly supports: readonly ["probe", "send", "roundtrip", "agent"];
|
|
@@ -48,7 +48,7 @@ export const OPENCLAW_SUPPORT_CATALOG = [
|
|
|
48
48
|
supports: COMMON_BRIDGE_SUPPORT,
|
|
49
49
|
},
|
|
50
50
|
{
|
|
51
|
-
notes: "Built-in local Mattermost mock.",
|
|
51
|
+
notes: "Built-in local Mattermost mock with authenticated outgoing webhook ingress.",
|
|
52
52
|
platform: "mattermost",
|
|
53
53
|
status: "ready",
|
|
54
54
|
supports: COMMON_BRIDGE_SUPPORT,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"catalog.js","sourceRoot":"","sources":["../../../src/providers/catalog.ts"],"names":[],"mappings":"AAUA,MAAM,qBAAqB,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,OAAO,CAAU,CAAC;AAE/E,SAAS,iBAAiB,CAAC,QAA0B,EAAE,KAAa;IAClE,OAAO;QACL,KAAK;QACL,QAAQ;QACR,MAAM,EAAE,QAAQ;QAChB,QAAQ,EAAE,qBAAqB;KAChC,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,MAAM,wBAAwB,GAAG;IACtC;QACE,KAAK,EAAE,0DAA0D;QACjE,QAAQ,EAAE,UAAU;QACpB,MAAM,EAAE,OAAO;QACf,QAAQ,EAAE,qBAAqB;KAChC;IACD,iBAAiB,CACf,aAAa,EACb,gEAAgE,CACjE;IACD;QACE,KAAK,EAAE,8DAA8D;QACrE,QAAQ,EAAE,SAAS;QACnB,MAAM,EAAE,OAAO;QACf,QAAQ,EAAE,qBAAqB;KAChC;IACD;QACE,KAAK,EAAE,8EAA8E;QACrF,QAAQ,EAAE,QAAQ;QAClB,MAAM,EAAE,OAAO;QACf,QAAQ,EAAE,qBAAqB;KAChC;IACD;QACE,KAAK,EAAE,0EAA0E;QACjF,QAAQ,EAAE,YAAY;QACtB,MAAM,EAAE,OAAO;QACf,QAAQ,EAAE,qBAAqB;KAChC;IACD;QACE,KAAK,EAAE,+BAA+B;QACtC,QAAQ,EAAE,UAAU;QACpB,MAAM,EAAE,OAAO;QACf,QAAQ,EAAE,qBAAqB;KAChC;IACD,iBAAiB,CAAC,KAAK,EAAE,qCAAqC,CAAC;IAC/D,iBAAiB,CAAC,MAAM,EAAE,4CAA4C,CAAC;IACvE;QACE,KAAK,EAAE,6BAA6B;QACpC,QAAQ,EAAE,QAAQ;QAClB,MAAM,EAAE,OAAO;QACf,QAAQ,EAAE,qBAAqB;KAChC;IACD;QACE,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"catalog.js","sourceRoot":"","sources":["../../../src/providers/catalog.ts"],"names":[],"mappings":"AAUA,MAAM,qBAAqB,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,OAAO,CAAU,CAAC;AAE/E,SAAS,iBAAiB,CAAC,QAA0B,EAAE,KAAa;IAClE,OAAO;QACL,KAAK;QACL,QAAQ;QACR,MAAM,EAAE,QAAQ;QAChB,QAAQ,EAAE,qBAAqB;KAChC,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,MAAM,wBAAwB,GAAG;IACtC;QACE,KAAK,EAAE,0DAA0D;QACjE,QAAQ,EAAE,UAAU;QACpB,MAAM,EAAE,OAAO;QACf,QAAQ,EAAE,qBAAqB;KAChC;IACD,iBAAiB,CACf,aAAa,EACb,gEAAgE,CACjE;IACD;QACE,KAAK,EAAE,8DAA8D;QACrE,QAAQ,EAAE,SAAS;QACnB,MAAM,EAAE,OAAO;QACf,QAAQ,EAAE,qBAAqB;KAChC;IACD;QACE,KAAK,EAAE,8EAA8E;QACrF,QAAQ,EAAE,QAAQ;QAClB,MAAM,EAAE,OAAO;QACf,QAAQ,EAAE,qBAAqB;KAChC;IACD;QACE,KAAK,EAAE,0EAA0E;QACjF,QAAQ,EAAE,YAAY;QACtB,MAAM,EAAE,OAAO;QACf,QAAQ,EAAE,qBAAqB;KAChC;IACD;QACE,KAAK,EAAE,+BAA+B;QACtC,QAAQ,EAAE,UAAU;QACpB,MAAM,EAAE,OAAO;QACf,QAAQ,EAAE,qBAAqB;KAChC;IACD,iBAAiB,CAAC,KAAK,EAAE,qCAAqC,CAAC;IAC/D,iBAAiB,CAAC,MAAM,EAAE,4CAA4C,CAAC;IACvE;QACE,KAAK,EAAE,6BAA6B;QACpC,QAAQ,EAAE,QAAQ;QAClB,MAAM,EAAE,OAAO;QACf,QAAQ,EAAE,qBAAqB;KAChC;IACD;QACE,KAAK,EAAE,6EAA6E;QACpF,QAAQ,EAAE,YAAY;QACtB,MAAM,EAAE,OAAO;QACf,QAAQ,EAAE,qBAAqB;KAChC;IACD;QACE,KAAK,EAAE,wEAAwE;QAC/E,QAAQ,EAAE,SAAS;QACnB,MAAM,EAAE,OAAO;QACf,QAAQ,EAAE,qBAAqB;KAChC;IACD,iBAAiB,CAAC,eAAe,EAAE,4CAA4C,CAAC;IAChF,iBAAiB,CAAC,OAAO,EAAE,4CAA4C,CAAC;IACxE,iBAAiB,CACf,QAAQ,EACR,wFAAwF,CACzF;IACD;QACE,KAAK,EAAE,sDAAsD;QAC7D,QAAQ,EAAE,OAAO;QACjB,MAAM,EAAE,OAAO;QACf,QAAQ,EAAE,qBAAqB;KAChC;IACD,iBAAiB,CAAC,cAAc,EAAE,4CAA4C,CAAC;IAC/E;QACE,KAAK,EAAE,gEAAgE;QACvE,QAAQ,EAAE,UAAU;QACpB,MAAM,EAAE,OAAO;QACf,QAAQ,EAAE,qBAAqB;KAChC;IACD,iBAAiB,CAAC,MAAM,EAAE,4CAA4C,CAAC;IACvE,iBAAiB,CAAC,QAAQ,EAAE,4CAA4C,CAAC;IACzE,iBAAiB,CAAC,SAAS,EAAE,yCAAyC,CAAC;IACvE;QACE,KAAK,EAAE,kFAAkF;QACzF,QAAQ,EAAE,UAAU;QACpB,MAAM,EAAE,OAAO;QACf,QAAQ,EAAE,qBAAqB;KAChC;IACD;QACE,KAAK,EAAE,2BAA2B;QAClC,QAAQ,EAAE,MAAM;QAChB,MAAM,EAAE,OAAO;QACf,QAAQ,EAAE,qBAAqB;KAChC;IACD,iBAAiB,CAAC,UAAU,EAAE,6DAA6D,CAAC;CAClD,CAAC","sourcesContent":["import type { FixtureMode, ProviderPlatform } from \"../config/schema.js\";\nimport type { ProviderSupportStatus } from \"./types.js\";\n\nexport type CatalogEntry = {\n notes: string;\n platform: ProviderPlatform;\n status: ProviderSupportStatus;\n supports: readonly FixtureMode[];\n};\n\nconst COMMON_BRIDGE_SUPPORT = [\"probe\", \"send\", \"roundtrip\", \"agent\"] as const;\n\nfunction createBridgeEntry(platform: ProviderPlatform, notes: string): CatalogEntry {\n return {\n notes,\n platform,\n status: \"bridge\",\n supports: COMMON_BRIDGE_SUPPORT,\n };\n}\n\nexport const OPENCLAW_SUPPORT_CATALOG = [\n {\n notes: \"Built-in local reference mock for development and tests.\",\n platform: \"loopback\",\n status: \"ready\",\n supports: COMMON_BRIDGE_SUPPORT,\n },\n createBridgeEntry(\n \"bluebubbles\",\n \"OpenClaw channel via script bridge. Recommended iMessage path.\",\n ),\n {\n notes: \"Built-in local Discord mock with interactions webhook shape.\",\n platform: \"discord\",\n status: \"ready\",\n supports: COMMON_BRIDGE_SUPPORT,\n },\n {\n notes: \"Built-in local Feishu/Lark mock with verified and encrypted webhook ingress.\",\n platform: \"feishu\",\n status: \"ready\",\n supports: COMMON_BRIDGE_SUPPORT,\n },\n {\n notes: \"Built-in local Google Chat mock with direct and Pub/Sub webhook ingress.\",\n platform: \"googlechat\",\n status: \"ready\",\n supports: COMMON_BRIDGE_SUPPORT,\n },\n {\n notes: \"Built-in local iMessage mock.\",\n platform: \"imessage\",\n status: \"ready\",\n supports: COMMON_BRIDGE_SUPPORT,\n },\n createBridgeEntry(\"irc\", \"OpenClaw channel via script bridge.\"),\n createBridgeEntry(\"line\", \"OpenClaw plugin channel via script bridge.\"),\n {\n notes: \"Built-in local Matrix mock.\",\n platform: \"matrix\",\n status: \"ready\",\n supports: COMMON_BRIDGE_SUPPORT,\n },\n {\n notes: \"Built-in local Mattermost mock with authenticated outgoing webhook ingress.\",\n platform: \"mattermost\",\n status: \"ready\",\n supports: COMMON_BRIDGE_SUPPORT,\n },\n {\n notes: \"Built-in local Microsoft Teams mock with Bot Connector authentication.\",\n platform: \"msteams\",\n status: \"ready\",\n supports: COMMON_BRIDGE_SUPPORT,\n },\n createBridgeEntry(\"nextcloudtalk\", \"OpenClaw plugin channel via script bridge.\"),\n createBridgeEntry(\"nostr\", \"OpenClaw plugin channel via script bridge.\"),\n createBridgeEntry(\n \"signal\",\n \"OpenClaw channel via script bridge; signal-cli HTTP-compatible local server available.\",\n ),\n {\n notes: \"Built-in local Slack mock with events webhook shape.\",\n platform: \"slack\",\n status: \"ready\",\n supports: COMMON_BRIDGE_SUPPORT,\n },\n createBridgeEntry(\"synologychat\", \"OpenClaw plugin channel via script bridge.\"),\n {\n notes: \"Built-in local Telegram mock with Bot API-style webhook shape.\",\n platform: \"telegram\",\n status: \"ready\",\n supports: COMMON_BRIDGE_SUPPORT,\n },\n createBridgeEntry(\"tlon\", \"OpenClaw plugin channel via script bridge.\"),\n createBridgeEntry(\"twitch\", \"OpenClaw plugin channel via script bridge.\"),\n createBridgeEntry(\"webchat\", \"OpenClaw web channel via script bridge.\"),\n {\n notes: \"Built-in local WhatsApp mock with Business webhook and Baileys WebSocket shapes.\",\n platform: \"whatsapp\",\n status: \"ready\",\n supports: COMMON_BRIDGE_SUPPORT,\n },\n {\n notes: \"Built-in local Zalo mock.\",\n platform: \"zalo\",\n status: \"ready\",\n supports: COMMON_BRIDGE_SUPPORT,\n },\n createBridgeEntry(\"zalouser\", \"OpenClaw plugin personal-account channel via script bridge.\"),\n] as const satisfies readonly CatalogEntry[];\n"]}
|
|
@@ -16,6 +16,7 @@ export type LocalMockAdapterOptions = {
|
|
|
16
16
|
handleWebhookPayload?: (payload: unknown, request: Request, rawBody: string) => Promise<Response | undefined> | Response | undefined;
|
|
17
17
|
normalizeWebhookPayload?: (payload: unknown) => unknown;
|
|
18
18
|
platform: ProviderPlatform;
|
|
19
|
+
preflightWebhookRequest?: (request: Request) => Promise<Response | undefined> | Response | undefined;
|
|
19
20
|
publicUrl?: string | undefined;
|
|
20
21
|
recorderPath?: string | undefined;
|
|
21
22
|
settleWebhookRequest?: (params: {
|
|
@@ -24,11 +25,14 @@ export type LocalMockAdapterOptions = {
|
|
|
24
25
|
rawBody: string;
|
|
25
26
|
}) => void;
|
|
26
27
|
webhook?: LocalMockWebhookConfig | undefined;
|
|
28
|
+
webhookCleanupGraceMs?: number | undefined;
|
|
29
|
+
webhookMethods?: readonly string[] | undefined;
|
|
27
30
|
};
|
|
28
31
|
export type LocalMockTargetCodec = {
|
|
29
32
|
normalize(target: ProviderContext["fixture"]["target"]): NormalizedTarget;
|
|
30
33
|
resolveThreadId(target: ProviderContext["fixture"]["target"]): string;
|
|
31
34
|
};
|
|
35
|
+
export declare function resolveGeneratedLocalMockRecorderPath(providerId: string, suffix?: string): string;
|
|
32
36
|
export declare class LocalMockProviderAdapter implements ProviderAdapter {
|
|
33
37
|
#private;
|
|
34
38
|
readonly id: string;
|