@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":"whatsapp.js","sourceRoot":"","sources":["../../../../src/providers/builtin/whatsapp.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"whatsapp.js","sourceRoot":"","sources":["../../../../src/providers/builtin/whatsapp.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC1D,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AACzE,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAEvD,OAAO,EAAE,wBAAwB,EAA+B,MAAM,kBAAkB,CAAC;AACzF,OAAO,EACL,0BAA0B,EAC1B,0BAA0B,EAC1B,2BAA2B,EAC3B,sBAAsB,EACtB,oBAAoB,GAGrB,MAAM,gBAAgB,CAAC;AAWxB,OAAO,EAAE,qBAAqB,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AACtF,OAAO,EAAE,kBAAkB,EAA6B,MAAM,sBAAsB,CAAC;AACrF,OAAO,EACL,iBAAiB,EACjB,kCAAkC,EAClC,QAAQ,EACR,eAAe,EACf,cAAc,EACd,cAAc,EACd,sBAAsB,GACvB,MAAM,wBAAwB,CAAC;AAqBhC,MAAM,wBAAwB,GAAG;IAC/B,IAAI,EAAE,WAAW;IACjB,IAAI,EAAE,mBAAmB;IACzB,IAAI,EAAE,IAAI;CACF,CAAC;AACX,MAAM,gBAAgB,GAAG,EAAE,CAAC;AAC5B,MAAM,+BAA+B,GAAG,IAAI,GAAG,IAAI,CAAC;AACpD,MAAM,gCAAgC,GAAG,KAAK,CAAC;AAE/C,MAAM,wBAAyB,SAAQ,KAAK;IAG/B,MAAM;IAFjB,YACE,OAAe,EACN,MAAc;QAEvB,KAAK,CAAC,OAAO,CAAC,CAAC;sBAFN,MAAM;IAGjB,CAAC;CACF;AAED,KAAK,UAAU,uBAAuB,CACpC,OAAgB,EAChB,eAA4B;IAE5B,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;QAClB,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,MAAM,iBAAiB,GAAG,IAAI,eAAe,EAAE,CAAC;IAChD,MAAM,OAAO,GAAG,UAAU,CAAC,GAAG,EAAE;QAC9B,iBAAiB,CAAC,KAAK,CAAC,IAAI,wBAAwB,CAAC,gCAAgC,EAAE,GAAG,CAAC,CAAC,CAAC;IAC/F,CAAC,EAAE,gCAAgC,CAAC,CAAC;IACrC,OAAO,CAAC,KAAK,EAAE,CAAC;IAChB,MAAM,MAAM,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC,eAAe,EAAE,OAAO,CAAC,MAAM,EAAE,iBAAiB,CAAC,MAAM,CAAC,CAAC,CAAC;IAC5F,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC;IACxC,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,IAAI,SAAS,GAAG,CAAC,CAAC;IAClB,IAAI,SAAS,GAAG,KAAK,CAAC;IACtB,IAAI,OAAgB,CAAC;IAErB,IAAI,CAAC;QACH,OAAO,IAAI,EAAE,CAAC;YACZ,MAAM,MAAM,GAAG,MAAM,IAAI,OAAO,CAC9B,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;gBAClB,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;oBACnB,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;oBACtB,OAAO;gBACT,CAAC;gBACD,MAAM,KAAK,GAAG,GAAG,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;gBAC1C,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;gBACxD,KAAK,MAAM,CAAC,IAAI,EAAE,CAAC,IAAI,CACrB,CAAC,KAAK,EAAE,EAAE;oBACR,MAAM,CAAC,mBAAmB,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;oBAC3C,OAAO,CAAC,KAAK,CAAC,CAAC;gBACjB,CAAC,EACD,CAAC,KAAK,EAAE,EAAE;oBACR,MAAM,CAAC,mBAAmB,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;oBAC3C,MAAM,CAAC,KAAK,CAAC,CAAC;gBAChB,CAAC,CACF,CAAC;YACJ,CAAC,CACF,CAAC;YACF,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC;gBAChB,SAAS,GAAG,IAAI,CAAC;gBACjB,OAAO,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;YAChD,CAAC;YACD,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YACxC,SAAS,IAAI,KAAK,CAAC,MAAM,CAAC;YAC1B,IAAI,SAAS,GAAG,+BAA+B,EAAE,CAAC;gBAChD,MAAM,IAAI,wBAAwB,CAAC,wBAAwB,EAAE,GAAG,CAAC,CAAC;YACpE,CAAC;YACD,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACrB,CAAC;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,GAAG,KAAK,CAAC;QAChB,MAAM,KAAK,CAAC;IACd,CAAC;YAAS,CAAC;QACT,YAAY,CAAC,OAAO,CAAC,CAAC;QACtB,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,KAAK,MAAM,CAAC,MAAM,CAAC,OAAO,IAAI,MAAM,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;QACtE,CAAC;aAAM,CAAC;YACN,MAAM,CAAC,WAAW,EAAE,CAAC;QACvB,CAAC;IACH,CAAC;AACH,CAAC;AAED,MAAM,UAAU,4BAA4B,CAC1C,MAAsB,EACtB,GAAG,GAAsB,OAAO,CAAC,GAAG;IAEpC,MAAM,SAAS,GAAG,MAAM,CAAC,QAAQ,EAAE,SAAS,IAAI,GAAG,CAAC,mBAAmB,CAAC;IACxE,MAAM,WAAW,GAAG,MAAM,CAAC,QAAQ,EAAE,WAAW,IAAI,GAAG,CAAC,qBAAqB,CAAC;IAC9E,IAAI,CAAC,SAAS,IAAI,CAAC,WAAW,EAAE,CAAC;QAC/B,MAAM,IAAI,aAAa,CACrB,8EAA8E,EAC9E,EAAE,IAAI,EAAE,QAAQ,EAAE,CACnB,CAAC;IACJ,CAAC;IACD,OAAO;QACL,WAAW,EAAE,MAAM,CAAC,QAAQ,EAAE,WAAW,IAAI,GAAG,CAAC,qBAAqB,IAAI,kBAAkB;QAC5F,SAAS;QACT,aAAa,EACX,MAAM,CAAC,QAAQ,EAAE,aAAa,IAAI,GAAG,CAAC,wBAAwB,IAAI,kBAAkB;QACtF,WAAW;KACZ,CAAC;AACJ,CAAC;AAQD,SAAS,wBAAwB,CAAC,OAAqC;IACrE,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,OAAO,EAAE,CAAC;QACnC,IAAI,OAAO,CAAC,IAAI,IAAI,gBAAgB,EAAE,CAAC;YACrC,OAAO;QACT,CAAC;QACD,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACvB,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACtB,CAAC;IACH,CAAC;AACH,CAAC;AAED,MAAM,OAAO,uBAAwB,SAAQ,wBAAwB;IAC1D,OAAO,CAAiB;IACxB,eAAe,GAAG,IAAI,eAAe,EAAE,CAAC;IACxC,UAAU,CAAqB;IAC/B,aAAa,CAAS;IACtB,QAAQ,CAAqC;IACtD,UAAU,GAAG,KAAK,CAAC;IACnB,aAAa,GAAG,KAAK,CAAC;IACtB,eAAe,GAAyB,IAAI,CAAC;IACpC,cAAc,GAAG,IAAI,GAAG,EAAuB,CAAC;IAChD,wBAAwB,GAAG,IAAI,GAAG,EAAqB,CAAC;IACxD,YAAY,GAAG,IAAI,GAAG,EAA2B,CAAC;IAC3D,OAAO,GAAgC,IAAI,CAAC;IAC5C,cAAc,GAAyB,IAAI,CAAC;IAC5C,eAAe,GAAyC,IAAI,CAAC;IAE7D,YAAY,EAAU,EAAE,MAAsB,EAAE,SAAiB,EAAE,QAAkB;QACnF,KAAK,CAAC;YACJ,KAAK,EAAE,qBAAqB,CAAC,UAAU,CAAC;YACxC,MAAM;YACN,EAAE;YACF,OAAO,EAAE;gBACP,cAAc,EAAE,wBAAwB;gBACxC,aAAa,EAAE,kBAAkB;gBACjC,uBAAuB,EAAE,+BAA+B;gBACxD,QAAQ,EAAE,UAAU;gBACpB,SAAS,EAAE,MAAM,CAAC,QAAQ,EAAE,OAAO,CAAC,SAAS;gBAC7C,YAAY,EAAE,MAAM,CAAC,QAAQ,EAAE,QAAQ,CAAC,IAAI;oBAC1C,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC;oBAC7C,CAAC,CAAC,SAAS;gBACb,OAAO,EAAE,MAAM,CAAC,QAAQ,EAAE,OAAO;aAClC;SACF,CAAC,CAAC;QACH,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC;QACtB,IAAI,CAAC,UAAU,GAAG,MAAM,CAAC,QAAQ,EAAE,OAAO,CAAC,SAAS,CAAC;QACrD,IAAI,CAAC,aAAa,GAAG,MAAM,CAAC,QAAQ,EAAE,QAAQ,CAAC,IAAI;YACjD,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC;YAC7C,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,WAAW,EAAE,GAAG,EAAE,QAAQ,CAAC,CAAC;QAC1D,IAAI,CAAC,QAAQ,GAAG,MAAM,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3C,CAAC;IAEQ,KAAK,CAAC,KAAK,CAAC,OAAwB;QAC3C,OAAO,CAAC,MAAM,EAAE,cAAc,EAAE,CAAC;QACjC,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,oBAAoB,EAAE,CAAC;QACjD,OAAO,CAAC,MAAM,EAAE,cAAc,EAAE,CAAC;QACjC,MAAM,MAAM,GAAG,IAAI,CAAC,eAAe,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QAC5D,MAAM,OAAO,GAAG;YACd,2BAA2B;YAC3B,iBAAiB,IAAI,CAAC,aAAa,EAAE;YACrC,oBAAoB,MAAM,CAAC,WAAW,EAAE;SACzC,CAAC;QACF,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;YACpB,OAAO,CAAC,IAAI,CAAC,kBAAkB,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC;QACpD,CAAC;QACD,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC;YACpB,OAAO,CAAC,IAAI,CAAC,oBAAoB,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC;QACtD,CAAC;aAAM,IAAI,MAAM,CAAC,SAAS,EAAE,CAAC;YAC5B,OAAO,CAAC,IAAI,CAAC,qBAAqB,MAAM,CAAC,SAAS,EAAE,CAAC,CAAC;QACxD,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,IAAI,CAAC,gBAAgB,MAAM,CAAC,EAAE,EAAE,CAAC,CAAC;QAC5C,CAAC;QACD,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IACpC,CAAC;IAEQ,KAAK,CAAC,IAAI,CAAC,OAAoB;QACtC,IAAI,IAAI,CAAC,aAAa,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;YAC1C,MAAM,IAAI,CAAC,eAAe,EAAE,CAAC;QAC/B,CAAC;QACD,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACpC,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QACjC,IAAI,CAAC;YACH,OAAO,MAAM,OAAO,CAAC;QACvB,CAAC;gBAAS,CAAC;YACT,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QACtC,CAAC;IACH,CAAC;IAEQ,KAAK,CAAC,cAAc,CAAC,OAAoB;QAChD,MAAM,IAAI,CAAC,oBAAoB,EAAE,CAAC;QAClC,MAAM,MAAM,GAAG,IAAI,CAAC,eAAe,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QAC5D,MAAM,SAAS,GAAG,OAAO,CAAC,QAAQ,IAAI,MAAM,CAAC,QAAQ,IAAI,MAAM,CAAC,SAAS,IAAI,MAAM,CAAC,EAAE,CAAC;QACvF,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC;YAC/B,OAAO,CAAC,KAAK;YACb,OAAO,CAAC,KAAK;YACb,SAAS;YACT,OAAO,CAAC,OAAO,CAAC,YAAY;SAC7B,CAAC,CAAC;QACH,MAAM,WAAW,GAAG,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC;QACtE,MAAM,MAAM,GAAG,WAAW,CAAC,MAAM;YAC/B,CAAC,CAAC,0BAA0B,CAAC,WAAW,CAAC,MAAM,CAAC;YAChD,CAAC,CAAC,2BAA2B,EAAE,CAAC;QAClC,WAAW,CAAC,MAAM,EAAE,CAAC;QACrB,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;QACpC,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC;QAC9C,wBAAwB,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QAC5C,IAAI,CAAC;YACH,MAAM,KAAK,GAAG,MAAM,sBAAsB,CAAC;gBACzC,MAAM;gBACN,QAAQ,EAAE,IAAI,CAAC,aAAa;gBAC5B,OAAO,EAAE,CAAC,SAAS,EAAE,EAAE,CACrB,SAAS,CAAC,QAAQ,KAAK,IAAI,CAAC,EAAE;oBAC9B,CAAC,gBAAgB,CAAC,SAAS,CAAC;oBAC5B,kBAAkB,CAAC,SAAS,CAAC,QAAQ,EAAE,SAAS,CAAC;oBACjD,cAAc,CAAC,SAAS,EAAE,OAAO,CAAC,OAAO,CAAC,YAAY,EAAE,OAAO,CAAC,KAAK,CAAC;gBACxE,KAAK,EAAE,OAAO,CAAC,KAAK;gBACpB,MAAM,EAAE,IAAI,CAAC,gBAAgB,CAAC,OAAO,CAAC,MAAM,CAAC;gBAC7C,SAAS,EAAE,OAAO,CAAC,SAAS;aAC7B,CAAC,CAAC;YACH,IAAI,KAAK,IAAI,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,SAAS,CAAC,KAAK,WAAW,EAAE,CAAC;gBAC9D,WAAW,CAAC,MAAM,GAAG,MAAM,CAAC;YAC9B,CAAC;YACD,OAAO,KAAK,CAAC;QACf,CAAC;gBAAS,CAAC;YACT,WAAW,CAAC,MAAM,EAAE,CAAC;YACrB,IACE,WAAW,CAAC,MAAM,KAAK,CAAC;gBACxB,CAAC,WAAW,CAAC,MAAM;gBACnB,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,SAAS,CAAC,KAAK,WAAW,EAChD,CAAC;gBACD,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;YACtC,CAAC;QACH,CAAC;IACH,CAAC;IAEQ,KAAK,CAAC,CAAC,KAAK,CAAC,OAAqB;QACzC,MAAM,IAAI,CAAC,oBAAoB,EAAE,CAAC;QAClC,MAAM,MAAM,GAAG,IAAI,CAAC,eAAe,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QAC5D,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,oBAAoB,CAAC;YAC7C,QAAQ,EAAE,IAAI,CAAC,aAAa;YAC5B,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE,CACjB,KAAK,CAAC,QAAQ,KAAK,IAAI,CAAC,EAAE;gBAC1B,CAAC,gBAAgB,CAAC,KAAK,CAAC;gBACxB,kBAAkB,CAAC,KAAK,CAAC,QAAQ,EAAE,MAAM,CAAC,QAAQ,IAAI,MAAM,CAAC,SAAS,IAAI,MAAM,CAAC,EAAE,CAAC;YACtF,MAAM,EAAE,IAAI,CAAC,gBAAgB,CAAC,OAAO,CAAC,MAAM,CAAC;YAC7C,KAAK,EAAE,OAAO,CAAC,KAAK;SACrB,CAAC,EAAE,CAAC;YACH,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;IAED,YAAY;QACV,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;YACvB,OAAO;QACT,CAAC;QACD,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC;QAC1B,IAAI,CAAC,eAAe,CAAC,KAAK,CAAC,IAAI,CAAC,eAAe,EAAE,CAAC,CAAC;QACnD,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC,mBAAmB,EAAE,CAAC;QACjD,KAAK,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;IAClD,CAAC;IAEQ,KAAK,CAAC,OAAO;QACpB,IAAI,CAAC,YAAY,EAAE,CAAC;QACpB,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;QACvB,IAAI,CAAC,YAAY,CAAC,KAAK,EAAE,CAAC;QAC1B,IAAI,CAAC,eAAe,KAAK,CAAC,KAAK,IAAI,EAAE;YACnC,MAAM,OAAO,CAAC,UAAU,CAAC,CAAC,GAAG,IAAI,CAAC,cAAc,EAAE,GAAG,IAAI,CAAC,wBAAwB,CAAC,CAAC,CAAC;YACrF,MAAM,MAAM,GAAc,EAAE,CAAC;YAC7B,IAAI,CAAC;gBACH,MAAM,IAAI,CAAC,cAAc,CAAC;YAC5B,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACrB,CAAC;YACD,IAAI,CAAC;gBACH,MAAM,KAAK,CAAC,OAAO,EAAE,CAAC;YACxB,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACrB,CAAC;YACD,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACxB,MAAM,MAAM,CAAC,CAAC,CAAC,CAAC;YAClB,CAAC;YACD,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACtB,MAAM,IAAI,cAAc,CAAC,MAAM,EAAE,yBAAyB,CAAC,CAAC;YAC9D,CAAC;QACH,CAAC,CAAC,EAAE,CAAC;QACL,MAAM,IAAI,CAAC,eAAe,CAAC;IAC7B,CAAC;IAED,qBAAqB,CACnB,OAAgB,EAChB,cAA6C;QAE7C,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;YACvB,OAAO,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,kBAAkB,EAAE,CAAC,CAAC;QACpD,CAAC;QACD,MAAM,QAAQ,GAAG,IAAI,CAAC,cAAc,CAAC,OAAO,EAAE,cAAc,CAAC,CAAC;QAC9D,IAAI,CAAC,wBAAwB,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAC5C,KAAK,QAAQ,CAAC,IAAI,CAChB,GAAG,EAAE,CAAC,IAAI,CAAC,wBAAwB,CAAC,MAAM,CAAC,QAAQ,CAAC,EACpD,GAAG,EAAE,CAAC,IAAI,CAAC,wBAAwB,CAAC,MAAM,CAAC,QAAQ,CAAC,CACrD,CAAC;QACF,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,KAAK,CAAC,cAAc,CAClB,OAAgB,EAChB,cAA6C;QAE7C,IAAI,OAAO,CAAC,MAAM,KAAK,KAAK,EAAE,CAAC;YAC7B,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;YACjC,MAAM,IAAI,GAAG,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;YAC9C,MAAM,aAAa,GAAG,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC;YAC/D,MAAM,SAAS,GAAG,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;YACxD,IACE,IAAI,KAAK,WAAW;gBACpB,aAAa,KAAK,cAAc,CAAC,WAAW;gBAC5C,SAAS,KAAK,IAAI,EAClB,CAAC;gBACD,OAAO,IAAI,QAAQ,CAAC,SAAS,EAAE;oBAC7B,OAAO,EAAE,EAAE,cAAc,EAAE,2BAA2B,EAAE;oBACxD,MAAM,EAAE,GAAG;iBACZ,CAAC,CAAC;YACL,CAAC;YACD,OAAO,IAAI,QAAQ,CAAC,WAAW,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;QACpD,CAAC;QAED,IAAI,OAAe,CAAC;QACpB,IAAI,CAAC;YACH,OAAO,GAAG,MAAM,uBAAuB,CAAC,OAAO,EAAE,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC;QAChF,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;gBACvB,OAAO,IAAI,CAAC,kBAAkB,EAAE,CAAC;YACnC,CAAC;YACD,IAAI,KAAK,YAAY,wBAAwB,EAAE,CAAC;gBAC9C,OAAO,IAAI,QAAQ,CAAC,KAAK,CAAC,OAAO,EAAE,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC;YAC/D,CAAC;YACD,OAAO,IAAI,QAAQ,CAAC,sBAAsB,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;QAC/D,CAAC;QACD,IACE,CAAC,yBAAyB,CACxB,OAAO,EACP,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,qBAAqB,CAAC,EAC1C,cAAc,CAAC,SAAS,CACzB,EACD,CAAC;YACD,OAAO,IAAI,QAAQ,CAAC,2BAA2B,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;QACpE,CAAC;QACD,MAAM,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,EAAE,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QAC9F,IAAI,SAAS,KAAK,kBAAkB,EAAE,CAAC;YACrC,OAAO,IAAI,QAAQ,CAAC,2BAA2B,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;QACpE,CAAC;QAED,IAAI,QAA4C,CAAC;QACjD,IAAI,CAAC;YACH,QAAQ,GAAG,+BAA+B,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,cAAc,CAAC,aAAa,CAAC,CAAC;QAChG,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,IAAI,QAAQ,CAAC,kBAAkB,CAAC,KAAK,CAAC,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;QAClE,CAAC;QAED,MAAM,GAAG,GAAa,EAAE,CAAC;QACzB,MAAM,OAAO,GAAsB,EAAE,CAAC;QACtC,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;YAC/B,MAAM,EAAE,GAAG,OAAO,CAAC,OAAO,EAAE,EAAE,IAAI,OAAO,CAAC,EAAE,IAAI,eAAe,EAAE,CAAC;YAClE,MAAM,QAAQ,GAAG,OAAO,CAAC,OAAO,EAAE,QAAQ,IAAI,OAAO,CAAC,QAAQ,CAAC;YAC/D,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,EAAE,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;YACnD,IAAI,CAAC,QAAQ,IAAI,CAAC,IAAI,EAAE,CAAC;gBACvB,OAAO,IAAI,QAAQ,CAAC,oDAAoD,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;YAC7F,CAAC;YAED,OAAO,CAAC,IAAI,CAAC;gBACX,MAAM,EAAE,iBAAiB,CAAC,OAAO,CAAC;gBAClC,EAAE;gBACF,QAAQ,EAAE,IAAI,CAAC,EAAE;gBACjB,GAAG,EAAE,OAAO,CAAC,OAAO,EAAE,GAAG,IAAI,OAAO,CAAC,GAAG,IAAI,OAAO;gBACnD,MAAM,EAAE,OAAO,CAAC,OAAO,EAAE,MAAM,IAAI,OAAO,CAAC,MAAM,IAAI,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;gBAC7E,IAAI;gBACJ,QAAQ;aACT,CAAC,CAAC;YACH,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACf,CAAC;QACD,MAAM,0BAA0B,CAAC,IAAI,CAAC,aAAa,EAAE,OAAO,CAAC,CAAC;QAE9D,OAAO,IAAI,QAAQ,CACjB,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,EAC/E;YACE,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;YAC/C,MAAM,EAAE,GAAG;SACZ,CACF,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,oBAAoB;QACxB,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;YACvB,MAAM,IAAI,CAAC,eAAe,EAAE,CAAC;QAC/B,CAAC;QACD,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACjB,OAAO,IAAI,CAAC,OAAO,CAAC;QACtB,CAAC;QACD,IAAI,IAAI,CAAC,eAAe,EAAE,CAAC;YACzB,OAAO,MAAM,IAAI,CAAC,eAAe,CAAC;QACpC,CAAC;QAED,MAAM,cAAc,GAAG,4BAA4B,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAClE,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,EAAE,IAAI,IAAI,wBAAwB,CAAC,IAAI,CAAC;QAClE,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,EAAE,IAAI,IAAI,wBAAwB,CAAC,IAAI,CAAC;QAClE,MAAM,WAAW,GAAG,IAAI,CAAC,QAAQ,EAAE,IAAI,IAAI,wBAAwB,CAAC,IAAI,CAAC;QACzE,MAAM,QAAQ,GAAG,CAAC,KAAK,IAAmC,EAAE;YAC1D,IAAI,MAA4B,CAAC;YACjC,IAAI,CAAC;gBACH,MAAM,GAAG,MAAM,kBAAkB,CAAC;oBAChC,MAAM,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,IAAI,CAAC,qBAAqB,CAAC,OAAO,EAAE,cAAc,CAAC;oBACxE,IAAI;oBACJ,OAAO,EAAE,CAAC,KAAK,EAAE,MAAM,CAAC;oBACxB,IAAI,EAAE,WAAW;oBACjB,IAAI;iBACL,CAAC,CAAC;YACL,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,MAAM,IAAI,aAAa,CACrB,8CAA8C,kBAAkB,CAAC,KAAK,CAAC,EAAE,EACzE,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,cAAc,EAAE,CACvC,CAAC;YACJ,CAAC;YAED,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC;YACtB,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;gBACvB,MAAM,IAAI,CAAC,eAAe,EAAE,CAAC;YAC/B,CAAC;YACD,OAAO,MAAM,CAAC;QAChB,CAAC,CAAC,EAAE,CAAC;QACL,IAAI,CAAC,eAAe,GAAG,QAAQ,CAAC;QAEhC,IAAI,CAAC;YACH,OAAO,MAAM,QAAQ,CAAC;QACxB,CAAC;gBAAS,CAAC;YACT,IAAI,IAAI,CAAC,eAAe,KAAK,QAAQ,EAAE,CAAC;gBACtC,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC;YAC9B,CAAC;QACH,CAAC;IACH,CAAC;IAED,KAAK,CAAC,mBAAmB;QACvB,MAAM,QAAQ,GAAG,IAAI,CAAC,eAAe,CAAC;QACtC,IAAI,QAAQ,EAAE,CAAC;YACb,IAAI,CAAC;gBACH,MAAM,QAAQ,CAAC;YACjB,CAAC;YAAC,MAAM,CAAC;gBACP,wEAAwE;YAC1E,CAAC;QACH,CAAC;QACD,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC;QAC5B,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,OAAO;QACT,CAAC;QAED,IAAI,IAAI,CAAC,OAAO,KAAK,MAAM,EAAE,CAAC;YAC5B,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;QACtB,CAAC;QACD,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;IACvB,CAAC;IAED,eAAe;QACb,OAAO,IAAI,aAAa,CAAC,aAAa,IAAI,CAAC,EAAE,wBAAwB,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC;IAC7F,CAAC;IAED,kBAAkB;QAChB,OAAO,IAAI,QAAQ,CAAC,aAAa,IAAI,CAAC,EAAE,wBAAwB,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;IACrF,CAAC;IAED,gBAAgB,CAAC,MAA+B;QAC9C,OAAO,MAAM;YACX,CAAC,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC;YACxD,CAAC,CAAC,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC;IAClC,CAAC;CACF;AAED,MAAM,UAAU,+BAA+B,CAC7C,OAAgB,EAChB,qBAA8B;IAE9B,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;QACvB,MAAM,IAAI,aAAa,CAAC,4CAA4C,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,CAAC;IAC7F,CAAC;IAED,MAAM,UAAU,GAAuC,EAAE,CAAC;IAC1D,IAAI,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACjC,KAAK,MAAM,KAAK,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;YAClC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC;gBACtD,SAAS;YACX,CAAC;YACD,KAAK,MAAM,MAAM,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;gBACnC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;oBACtB,SAAS;gBACX,CAAC;gBACD,MAAM,KAAK,GAAG,cAAc,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;gBAC9C,IAAI,CAAC,KAAK,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC;oBAC7C,SAAS;gBACX,CAAC;gBACD,MAAM,QAAQ,GAAG,cAAc,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC;gBACnD,IACE,qBAAqB,KAAK,SAAS;oBACnC,cAAc,CAAC,QAAQ,IAAI,EAAE,EAAE,iBAAiB,CAAC,KAAK,qBAAqB,EAC3E,CAAC;oBACD,SAAS;gBACX,CAAC;gBACD,KAAK,MAAM,OAAO,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC;oBACrC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;wBACvB,MAAM,IAAI,aAAa,CAAC,qDAAqD,EAAE;4BAC7E,IAAI,EAAE,SAAS;yBAChB,CAAC,CAAC;oBACL,CAAC;oBACD,MAAM,iBAAiB,GAAG,wBAAwB,CAAC,OAAO,CAAC,CAAC;oBAC5D,IAAI,iBAAiB,EAAE,CAAC;wBACtB,UAAU,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;oBACrC,CAAC;gBACH,CAAC;YACH,CAAC;QACH,CAAC;QACD,OAAO,UAAU,CAAC;IACpB,CAAC;IAED,MAAM,QAAQ,GAAG,kCAAkC,CAAC;QAClD,WAAW,EAAE,mBAAmB;QAChC,OAAO;QACP,UAAU,EAAE,mBAAmB;KAChC,CAA4B,CAAC;IAC9B,OAAO,CAAC,yBAAyB,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAC;AACxD,CAAC;AAED,SAAS,yBAAyB,CAChC,QAAiC,EACjC,MAA+B;IAE/B,MAAM,UAAU,GAAqC;QACnD,GAAG,EAAE,QAAQ,CAAC,GAAG,IAAI,QAAQ;KAC9B,CAAC;IACF,MAAM,MAAM,GAAG,eAAe,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;IAChD,IAAI,MAAM,EAAE,CAAC;QACX,UAAU,CAAC,MAAM,GAAG,MAAM,CAAC;IAC7B,CAAC;IACD,IAAI,OAAO,QAAQ,CAAC,WAAW,KAAK,SAAS,EAAE,CAAC;QAC9C,UAAU,CAAC,WAAW,GAAG,QAAQ,CAAC,WAAW,CAAC;IAChD,CAAC;IACD,MAAM,EAAE,GAAG,cAAc,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;IAC1C,IAAI,EAAE,EAAE,CAAC;QACP,UAAU,CAAC,EAAE,GAAG,EAAE,CAAC;IACrB,CAAC;IACD,MAAM,IAAI,GAAG,cAAc,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IAC9C,IAAI,IAAI,EAAE,CAAC;QACT,UAAU,CAAC,IAAI,GAAG,IAAI,CAAC;IACzB,CAAC;IACD,MAAM,QAAQ,GAAG,cAAc,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;IACtD,IAAI,QAAQ,EAAE,CAAC;QACb,UAAU,CAAC,QAAQ,GAAG,QAAQ,CAAC;IACjC,CAAC;IACD,MAAM,MAAM,GAAG,cAAc,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IAChD,IAAI,MAAM,EAAE,CAAC;QACX,UAAU,CAAC,MAAM,GAAG,8BAA8B,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IACvE,CAAC;IAED,MAAM,OAAO,GAAG,cAAc,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;IACpD,IAAI,OAAO,EAAE,CAAC;QACZ,MAAM,aAAa,GAAG,cAAc,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;QACxD,MAAM,iBAAiB,GAA6D,EAAE,CAAC;QACvF,MAAM,aAAa,GAAG,eAAe,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QACtD,IAAI,aAAa,EAAE,CAAC;YAClB,iBAAiB,CAAC,MAAM,GAAG,aAAa,CAAC;QAC3C,CAAC;QACD,IAAI,OAAO,OAAO,CAAC,WAAW,KAAK,SAAS,EAAE,CAAC;YAC7C,iBAAiB,CAAC,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC;QACtD,CAAC;QACD,MAAM,SAAS,GAAG,cAAc,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;QAChD,IAAI,SAAS,EAAE,CAAC;YACd,iBAAiB,CAAC,EAAE,GAAG,SAAS,CAAC;QACnC,CAAC;QACD,IAAI,OAAO,CAAC,GAAG,KAAK,SAAS,EAAE,CAAC;YAC9B,iBAAiB,CAAC,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC;QACtC,CAAC;QACD,MAAM,aAAa,GAAG,aAAa,CAAC,CAAC,CAAC,cAAc,CAAC,aAAa,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QAC1F,IAAI,aAAa,EAAE,CAAC;YAClB,iBAAiB,CAAC,MAAM,GAAG,8BAA8B,CAAC,aAAa,EAAE,gBAAgB,CAAC,CAAC;QAC7F,CAAC;QACD,MAAM,WAAW,GAAG,cAAc,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QACpD,IAAI,WAAW,EAAE,CAAC;YAChB,iBAAiB,CAAC,IAAI,GAAG,WAAW,CAAC;QACvC,CAAC;QACD,MAAM,eAAe,GAAG,cAAc,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;QAC5D,IAAI,eAAe,EAAE,CAAC;YACpB,iBAAiB,CAAC,QAAQ,GAAG,eAAe,CAAC;QAC/C,CAAC;QACD,UAAU,CAAC,OAAO,GAAG,iBAAiB,CAAC;IACzC,CAAC;IAED,OAAO,UAAU,CAAC;AACpB,CAAC;AAED,SAAS,wBAAwB,CAC/B,OAAgC;IAEhC,MAAM,WAAW,GAAG,cAAc,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IACpD,IAAI,WAAW,IAAI,WAAW,KAAK,MAAM,EAAE,CAAC;QAC1C,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,IAAI,GAAG,cAAc,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IAC7C,MAAM,IAAI,GAAG,cAAc,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IAC7C,MAAM,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC,cAAc,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAC7D,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;QACnB,MAAM,IAAI,aAAa,CAAC,iEAAiE,EAAE;YACzF,IAAI,EAAE,SAAS;SAChB,CAAC,CAAC;IACL,CAAC;IAED,MAAM,SAAS,GAAG,cAAc,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IAChD,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,MAAM,IAAI,aAAa,CAAC,iDAAiD,EAAE;YACzE,IAAI,EAAE,SAAS;SAChB,CAAC,CAAC;IACL,CAAC;IACD,MAAM,SAAS,GAAG,cAAc,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC;IACvD,OAAO;QACL,MAAM,EAAE,iBAAiB,CAAC,KAAK,CAAC;QAChC,EAAE,EAAE,SAAS;QACb,GAAG,EAAE,OAAO;QACZ,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,sBAAsB,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACnE,IAAI,EAAE,IAAI;QACV,QAAQ,EAAE,sBAAsB,CAAC,IAAI,EAAE,mBAAmB,EAAE,0BAA0B,CAAC;KACxF,CAAC;AACJ,CAAC;AAED,SAAS,sBAAsB,CAAC,SAAiB;IAC/C,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;QAC9B,MAAM,IAAI,aAAa,CAAC,oDAAoD,EAAE;YAC5E,IAAI,EAAE,SAAS;SAChB,CAAC,CAAC;IACL,CAAC;IACD,MAAM,YAAY,GAAG,MAAM,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC;IAC9C,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,YAAY,CAAC,EAAE,CAAC;QACxC,MAAM,IAAI,aAAa,CAAC,+CAA+C,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,CAAC;IAChG,CAAC;IACD,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,YAAY,CAAC,CAAC;IACpC,IAAI,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,EAAE,CAAC;QACjC,MAAM,IAAI,aAAa,CAAC,0CAA0C,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,CAAC;IAC3F,CAAC;IACD,OAAO,IAAI,CAAC,WAAW,EAAE,CAAC;AAC5B,CAAC;AAED,SAAS,8BAA8B,CAAC,SAAiB,EAAE,KAAa;IACtE,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,SAAS,CAAC,CAAC;IACjC,IAAI,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,EAAE,CAAC;QACjC,MAAM,IAAI,aAAa,CAAC,qBAAqB,KAAK,4BAA4B,EAAE;YAC9E,IAAI,EAAE,SAAS;SAChB,CAAC,CAAC;IACL,CAAC;IACD,OAAO,IAAI,CAAC,WAAW,EAAE,CAAC;AAC5B,CAAC;AAED,SAAS,iBAAiB,CAAC,OAAyC;IAClE,MAAM,QAAQ,GAAG,OAAO,CAAC,OAAO,EAAE,MAAM,IAAI,OAAO,CAAC,MAAM,CAAC;IAC3D,IAAI,QAAQ,EAAE,CAAC;QACb,OAAO,QAAQ,CAAC;IAClB,CAAC;IACD,OAAO,CAAC,OAAO,CAAC,OAAO,EAAE,WAAW,IAAI,OAAO,CAAC,WAAW,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,MAAM,CAAC;AAC9F,CAAC;AAED,SAAS,eAAe;IACtB,OAAO,iBAAiB,IAAI,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;AAC9F,CAAC;AAED,SAAS,yBAAyB,CAChC,OAAe,EACf,eAA8B,EAC9B,UAAkB;IAElB,IAAI,CAAC,eAAe,EAAE,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;QAC5C,OAAO,KAAK,CAAC;IACf,CAAC;IACD,MAAM,SAAS,GAAG,eAAe,CAAC,KAAK,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;IAC1D,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;QACxC,OAAO,KAAK,CAAC;IACf,CAAC;IACD,MAAM,QAAQ,GAAG,UAAU,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,CAAC;IAC3E,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;IAC7C,OAAO,MAAM,CAAC,MAAM,KAAK,QAAQ,CAAC,MAAM,IAAI,eAAe,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;AAChF,CAAC;AAED,SAAS,kBAAkB,CAAC,QAAgB,EAAE,SAAkB;IAC9D,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO,QAAQ,KAAK,SAAS,IAAI,QAAQ,CAAC,UAAU,CAAC,GAAG,SAAS,GAAG,CAAC,CAAC;AACxE,CAAC;AAED,SAAS,gBAAgB,CAAC,KAA8B;IACtD,IAAI,KAAK,CAAC,iBAAiB,KAAK,SAAS,EAAE,CAAC;QAC1C,OAAO,KAAK,CAAC,iBAAiB,KAAK,UAAU,CAAC;IAChD,CAAC;IACD,OAAO,CACL,KAAK,CAAC,GAAG,KAAK,IAAI;QAClB,OAAO,KAAK,CAAC,GAAG,KAAK,QAAQ;QAC7B,WAAW,IAAI,KAAK,CAAC,GAAG;QACxB,KAAK,CAAC,GAAG,CAAC,SAAS,KAAK,UAAU,CACnC,CAAC;AACJ,CAAC","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,12 +1,8 @@
|
|
|
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
|
-
example: "123456789012345678",
|
|
7
|
-
name: "Zalo user or OA id",
|
|
8
|
-
pattern: /^\d{6,20}$/u,
|
|
9
|
-
};
|
|
4
|
+
import { getBuiltinTargetCodec, ZALO_ID_RULE } from "../target-normalizers.js";
|
|
5
|
+
import { authorFromBotFlag, createSecretVerifier, genericMockPayloadWithNativeThread, isRecord, optionalRecord, optionalString, requireNativeInboundId, } from "./native-local-mock.js";
|
|
10
6
|
export function resolveZaloAdapterConfig(config, env = process.env) {
|
|
11
7
|
return {
|
|
12
8
|
botToken: config.zalo?.botToken ?? env.ZALO_BOT_TOKEN ?? "local-mock-zalo-token",
|
|
@@ -15,14 +11,24 @@ export function resolveZaloAdapterConfig(config, env = process.env) {
|
|
|
15
11
|
}
|
|
16
12
|
export class ZaloProviderAdapter extends LocalMockProviderAdapter {
|
|
17
13
|
constructor(id, config, _userName, _runtime) {
|
|
14
|
+
const resolvedConfig = resolveZaloAdapterConfig(config);
|
|
15
|
+
const authenticateWebhook = resolvedConfig.webhookSecret
|
|
16
|
+
? createSecretVerifier(resolvedConfig.webhookSecret)
|
|
17
|
+
: undefined;
|
|
18
18
|
super({
|
|
19
|
-
codec:
|
|
20
|
-
channel: ZALO_ID_RULE,
|
|
21
|
-
channelLabel: "Zalo user_id or oa_id",
|
|
22
|
-
}),
|
|
19
|
+
codec: getBuiltinTargetCodec("zalo"),
|
|
23
20
|
config,
|
|
24
21
|
id,
|
|
25
22
|
options: {
|
|
23
|
+
...(authenticateWebhook
|
|
24
|
+
? {
|
|
25
|
+
authenticateWebhookRequest(request) {
|
|
26
|
+
return authenticateWebhook(request.headers.get("x-bot-api-secret-token"))
|
|
27
|
+
? undefined
|
|
28
|
+
: new Response("unauthorized", { status: 401 });
|
|
29
|
+
},
|
|
30
|
+
}
|
|
31
|
+
: {}),
|
|
26
32
|
defaultWebhook: { host: "127.0.0.1", path: "/zalo/webhook", port: 8794 },
|
|
27
33
|
endpointLabel: "webhook endpoint",
|
|
28
34
|
normalizeWebhookPayload: normalizeZaloWebhookPayload,
|
|
@@ -48,23 +54,28 @@ export function normalizeZaloWebhookPayload(payload) {
|
|
|
48
54
|
threadRule: ZALO_ID_RULE,
|
|
49
55
|
});
|
|
50
56
|
}
|
|
51
|
-
const
|
|
52
|
-
const message = optionalRecord(
|
|
57
|
+
const wrapped = optionalRecord(payload, "result") ?? payload;
|
|
58
|
+
const message = optionalRecord(wrapped, "message");
|
|
59
|
+
const sender = optionalRecord(message ?? {}, "from") ?? optionalRecord(wrapped, "sender");
|
|
60
|
+
const chat = message ? optionalRecord(message, "chat") : undefined;
|
|
53
61
|
const senderId = sender ? optionalString(sender, "id") : undefined;
|
|
62
|
+
const chatId = chat ? optionalString(chat, "id") : senderId;
|
|
54
63
|
const text = message ? optionalString(message, "text") : undefined;
|
|
55
|
-
if (!senderId || !text) {
|
|
56
|
-
throw new CrablineError("Zalo webhook payload requires sender
|
|
64
|
+
if (!senderId || !chatId || !text) {
|
|
65
|
+
throw new CrablineError("Zalo webhook payload requires sender identity, chat identity, and text", {
|
|
57
66
|
kind: "inbound",
|
|
58
67
|
});
|
|
59
68
|
}
|
|
60
69
|
return {
|
|
61
|
-
author: authorFromBotFlag(
|
|
62
|
-
...(message
|
|
63
|
-
? { id: optionalString(message, "
|
|
64
|
-
: {})
|
|
70
|
+
author: authorFromBotFlag(sender?.is_bot === true),
|
|
71
|
+
...(optionalString(message ?? {}, "message_id")
|
|
72
|
+
? { id: optionalString(message ?? {}, "message_id") }
|
|
73
|
+
: optionalString(message ?? {}, "msg_id")
|
|
74
|
+
? { id: optionalString(message ?? {}, "msg_id") }
|
|
75
|
+
: {}),
|
|
65
76
|
raw: payload,
|
|
66
77
|
text,
|
|
67
|
-
threadId: requireNativeInboundId(
|
|
78
|
+
threadId: requireNativeInboundId(chatId, ZALO_ID_RULE, "Zalo chat.id"),
|
|
68
79
|
};
|
|
69
80
|
}
|
|
70
81
|
//# sourceMappingURL=zalo.js.map
|
|
@@ -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,EACL,iBAAiB,EACjB,
|
|
1
|
+
{"version":3,"file":"zalo.js","sourceRoot":"","sources":["../../../../src/providers/builtin/zalo.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, 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\nexport function resolveZaloAdapterConfig(\n config: ProviderConfig,\n env: NodeJS.ProcessEnv = process.env,\n) {\n return {\n botToken: config.zalo?.botToken ?? env.ZALO_BOT_TOKEN ?? \"local-mock-zalo-token\",\n webhookSecret: config.zalo?.webhookSecret ?? env.ZALO_WEBHOOK_SECRET,\n };\n}\n\nexport class ZaloProviderAdapter extends LocalMockProviderAdapter implements ProviderAdapter {\n constructor(id: string, config: ProviderConfig, _userName: string, _runtime?: unknown) {\n const resolvedConfig = resolveZaloAdapterConfig(config);\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 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 normalizeZaloWebhookPayload(payload: unknown) {\n if (!isRecord(payload)) {\n throw new CrablineError(\"Zalo webhook payload must be an object\", { kind: \"inbound\" });\n }\n\n if (\n optionalRecord(payload, \"message\") &&\n optionalString(optionalRecord(payload, \"message\")!, \"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 text = message ? optionalString(message, \"text\") : undefined;\n if (!senderId || !chatId || !text) {\n throw new CrablineError(\n \"Zalo webhook payload requires sender identity, chat identity, and text\",\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"]}
|
|
@@ -17,12 +17,12 @@ export declare const OPENCLAW_SUPPORT_CATALOG: readonly [{
|
|
|
17
17
|
readonly status: "ready";
|
|
18
18
|
readonly supports: readonly ["probe", "send", "roundtrip", "agent"];
|
|
19
19
|
}, {
|
|
20
|
-
readonly notes: "Built-in local Feishu/Lark mock.";
|
|
20
|
+
readonly notes: "Built-in local Feishu/Lark mock with verified and encrypted webhook ingress.";
|
|
21
21
|
readonly platform: "feishu";
|
|
22
22
|
readonly status: "ready";
|
|
23
23
|
readonly supports: readonly ["probe", "send", "roundtrip", "agent"];
|
|
24
24
|
}, {
|
|
25
|
-
readonly notes: "Built-in local Google Chat mock.";
|
|
25
|
+
readonly notes: "Built-in local Google Chat mock with direct and Pub/Sub webhook ingress.";
|
|
26
26
|
readonly platform: "googlechat";
|
|
27
27
|
readonly status: "ready";
|
|
28
28
|
readonly supports: readonly ["probe", "send", "roundtrip", "agent"];
|
|
@@ -42,7 +42,7 @@ export declare const OPENCLAW_SUPPORT_CATALOG: readonly [{
|
|
|
42
42
|
readonly status: "ready";
|
|
43
43
|
readonly supports: readonly ["probe", "send", "roundtrip", "agent"];
|
|
44
44
|
}, {
|
|
45
|
-
readonly notes: "Built-in local Microsoft Teams mock.";
|
|
45
|
+
readonly notes: "Built-in local Microsoft Teams mock with Bot Connector authentication.";
|
|
46
46
|
readonly platform: "msteams";
|
|
47
47
|
readonly status: "ready";
|
|
48
48
|
readonly supports: readonly ["probe", "send", "roundtrip", "agent"];
|
|
@@ -22,13 +22,13 @@ export const OPENCLAW_SUPPORT_CATALOG = [
|
|
|
22
22
|
supports: COMMON_BRIDGE_SUPPORT,
|
|
23
23
|
},
|
|
24
24
|
{
|
|
25
|
-
notes: "Built-in local Feishu/Lark mock.",
|
|
25
|
+
notes: "Built-in local Feishu/Lark mock with verified and encrypted webhook ingress.",
|
|
26
26
|
platform: "feishu",
|
|
27
27
|
status: "ready",
|
|
28
28
|
supports: COMMON_BRIDGE_SUPPORT,
|
|
29
29
|
},
|
|
30
30
|
{
|
|
31
|
-
notes: "Built-in local Google Chat mock.",
|
|
31
|
+
notes: "Built-in local Google Chat mock with direct and Pub/Sub webhook ingress.",
|
|
32
32
|
platform: "googlechat",
|
|
33
33
|
status: "ready",
|
|
34
34
|
supports: COMMON_BRIDGE_SUPPORT,
|
|
@@ -54,7 +54,7 @@ export const OPENCLAW_SUPPORT_CATALOG = [
|
|
|
54
54
|
supports: COMMON_BRIDGE_SUPPORT,
|
|
55
55
|
},
|
|
56
56
|
{
|
|
57
|
-
notes: "Built-in local Microsoft Teams mock.",
|
|
57
|
+
notes: "Built-in local Microsoft Teams mock with Bot Connector authentication.",
|
|
58
58
|
platform: "msteams",
|
|
59
59
|
status: "ready",
|
|
60
60
|
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,
|
|
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,iCAAiC;QACxC,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.\",\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"]}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { ProviderConfig, ProviderPlatform } from "../config/schema.js";
|
|
2
2
|
import type { InboundEnvelope, NormalizedTarget, ProbeResult, ProviderAdapter, ProviderContext, SendContext, SendResult, WaitContext, WatchContext } from "./types.js";
|
|
3
|
+
export { createGenericLocalMockTargetCodec } from "./target-normalizers.js";
|
|
3
4
|
export type LocalMockWebhookConfig = {
|
|
4
5
|
host?: string;
|
|
5
6
|
path?: string;
|
|
@@ -7,25 +8,33 @@ export type LocalMockWebhookConfig = {
|
|
|
7
8
|
publicUrl?: string | undefined;
|
|
8
9
|
};
|
|
9
10
|
export type LocalMockAdapterOptions = {
|
|
11
|
+
authenticateWebhookRequest?: (request: Request, rawBody: string) => Promise<Response | undefined> | Response | undefined;
|
|
12
|
+
createWebhookSuccessResponse?: (payload: unknown, id: string) => Promise<Response> | Response;
|
|
10
13
|
defaultWebhook: Required<Pick<LocalMockWebhookConfig, "host" | "path" | "port">>;
|
|
11
14
|
endpointLabel: string;
|
|
15
|
+
matchesThread?: (candidateThreadId: string, expectedThreadId: string | undefined, target: NormalizedTarget, raw?: unknown) => boolean;
|
|
16
|
+
handleWebhookPayload?: (payload: unknown, request: Request, rawBody: string) => Promise<Response | undefined> | Response | undefined;
|
|
12
17
|
normalizeWebhookPayload?: (payload: unknown) => unknown;
|
|
13
18
|
platform: ProviderPlatform;
|
|
14
19
|
publicUrl?: string | undefined;
|
|
15
20
|
recorderPath?: string | undefined;
|
|
21
|
+
settleWebhookRequest?: (params: {
|
|
22
|
+
accepted: boolean;
|
|
23
|
+
payload: unknown;
|
|
24
|
+
rawBody: string;
|
|
25
|
+
}) => void;
|
|
16
26
|
webhook?: LocalMockWebhookConfig | undefined;
|
|
17
27
|
};
|
|
18
28
|
export type LocalMockTargetCodec = {
|
|
19
29
|
normalize(target: ProviderContext["fixture"]["target"]): NormalizedTarget;
|
|
20
30
|
resolveThreadId(target: ProviderContext["fixture"]["target"]): string;
|
|
21
31
|
};
|
|
22
|
-
export declare function createGenericLocalMockTargetCodec(platform: ProviderPlatform): LocalMockTargetCodec;
|
|
23
32
|
export declare class LocalMockProviderAdapter implements ProviderAdapter {
|
|
24
33
|
#private;
|
|
25
34
|
readonly id: string;
|
|
26
35
|
readonly platform: "bluebubbles" | "discord" | "feishu" | "googlechat" | "imessage" | "irc" | "line" | "loopback" | "matrix" | "mattermost" | "msteams" | "nextcloudtalk" | "nostr" | "signal" | "slack" | "synologychat" | "telegram" | "tlon" | "twitch" | "webchat" | "whatsapp" | "zalo" | "zalouser";
|
|
27
36
|
readonly status: "ready";
|
|
28
|
-
readonly supports:
|
|
37
|
+
readonly supports: ProviderAdapter["supports"];
|
|
29
38
|
constructor(params: {
|
|
30
39
|
codec: LocalMockTargetCodec;
|
|
31
40
|
config: ProviderConfig;
|