@spinabot/brigade 1.7.0 → 1.8.0
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/dist/agents/agent-loop.d.ts +13 -0
- package/dist/agents/agent-loop.d.ts.map +1 -1
- package/dist/agents/agent-loop.js +5 -0
- package/dist/agents/agent-loop.js.map +1 -1
- package/dist/agents/channels/access-control/group-tool-policy.d.ts +73 -0
- package/dist/agents/channels/access-control/group-tool-policy.d.ts.map +1 -0
- package/dist/agents/channels/access-control/group-tool-policy.js +193 -0
- package/dist/agents/channels/access-control/group-tool-policy.js.map +1 -0
- package/dist/agents/channels/access-control/index.d.ts +1 -0
- package/dist/agents/channels/access-control/index.d.ts.map +1 -1
- package/dist/agents/channels/access-control/index.js +1 -0
- package/dist/agents/channels/access-control/index.js.map +1 -1
- package/dist/agents/channels/bluebubbles/account-config.d.ts +253 -0
- package/dist/agents/channels/bluebubbles/account-config.d.ts.map +1 -0
- package/dist/agents/channels/bluebubbles/account-config.js +486 -0
- package/dist/agents/channels/bluebubbles/account-config.js.map +1 -0
- package/dist/agents/channels/bluebubbles/account-registry.d.ts +33 -0
- package/dist/agents/channels/bluebubbles/account-registry.d.ts.map +1 -0
- package/dist/agents/channels/bluebubbles/account-registry.js +46 -0
- package/dist/agents/channels/bluebubbles/account-registry.js.map +1 -0
- package/dist/agents/channels/bluebubbles/adapter.d.ts +45 -0
- package/dist/agents/channels/bluebubbles/adapter.d.ts.map +1 -0
- package/dist/agents/channels/bluebubbles/adapter.js +366 -0
- package/dist/agents/channels/bluebubbles/adapter.js.map +1 -0
- package/dist/agents/channels/bluebubbles/catchup-cursor.d.ts +52 -0
- package/dist/agents/channels/bluebubbles/catchup-cursor.d.ts.map +1 -0
- package/dist/agents/channels/bluebubbles/catchup-cursor.js +118 -0
- package/dist/agents/channels/bluebubbles/catchup-cursor.js.map +1 -0
- package/dist/agents/channels/bluebubbles/catchup.d.ts +114 -0
- package/dist/agents/channels/bluebubbles/catchup.d.ts.map +1 -0
- package/dist/agents/channels/bluebubbles/catchup.js +220 -0
- package/dist/agents/channels/bluebubbles/catchup.js.map +1 -0
- package/dist/agents/channels/bluebubbles/chat.d.ts +75 -0
- package/dist/agents/channels/bluebubbles/chat.d.ts.map +1 -0
- package/dist/agents/channels/bluebubbles/chat.js +182 -0
- package/dist/agents/channels/bluebubbles/chat.js.map +1 -0
- package/dist/agents/channels/bluebubbles/connection.d.ts +95 -0
- package/dist/agents/channels/bluebubbles/connection.d.ts.map +1 -0
- package/dist/agents/channels/bluebubbles/connection.js +413 -0
- package/dist/agents/channels/bluebubbles/connection.js.map +1 -0
- package/dist/agents/channels/bluebubbles/contact-names.d.ts +79 -0
- package/dist/agents/channels/bluebubbles/contact-names.d.ts.map +1 -0
- package/dist/agents/channels/bluebubbles/contact-names.js +188 -0
- package/dist/agents/channels/bluebubbles/contact-names.js.map +1 -0
- package/dist/agents/channels/bluebubbles/debounce.d.ts +78 -0
- package/dist/agents/channels/bluebubbles/debounce.d.ts.map +1 -0
- package/dist/agents/channels/bluebubbles/debounce.js +173 -0
- package/dist/agents/channels/bluebubbles/debounce.js.map +1 -0
- package/dist/agents/channels/bluebubbles/dedupe.d.ts +25 -0
- package/dist/agents/channels/bluebubbles/dedupe.d.ts.map +1 -0
- package/dist/agents/channels/bluebubbles/dedupe.js +35 -0
- package/dist/agents/channels/bluebubbles/dedupe.js.map +1 -0
- package/dist/agents/channels/bluebubbles/effects.d.ts +17 -0
- package/dist/agents/channels/bluebubbles/effects.d.ts.map +1 -0
- package/dist/agents/channels/bluebubbles/effects.js +57 -0
- package/dist/agents/channels/bluebubbles/effects.js.map +1 -0
- package/dist/agents/channels/bluebubbles/history.d.ts +56 -0
- package/dist/agents/channels/bluebubbles/history.d.ts.map +1 -0
- package/dist/agents/channels/bluebubbles/history.js +140 -0
- package/dist/agents/channels/bluebubbles/history.js.map +1 -0
- package/dist/agents/channels/bluebubbles/index.d.ts +18 -0
- package/dist/agents/channels/bluebubbles/index.d.ts.map +1 -0
- package/dist/agents/channels/bluebubbles/index.js +18 -0
- package/dist/agents/channels/bluebubbles/index.js.map +1 -0
- package/dist/agents/channels/bluebubbles/media.d.ts +104 -0
- package/dist/agents/channels/bluebubbles/media.d.ts.map +1 -0
- package/dist/agents/channels/bluebubbles/media.js +222 -0
- package/dist/agents/channels/bluebubbles/media.js.map +1 -0
- package/dist/agents/channels/bluebubbles/messaging.d.ts +13 -0
- package/dist/agents/channels/bluebubbles/messaging.d.ts.map +1 -0
- package/dist/agents/channels/bluebubbles/messaging.js +36 -0
- package/dist/agents/channels/bluebubbles/messaging.js.map +1 -0
- package/dist/agents/channels/bluebubbles/module.d.ts +24 -0
- package/dist/agents/channels/bluebubbles/module.d.ts.map +1 -0
- package/dist/agents/channels/bluebubbles/module.js +52 -0
- package/dist/agents/channels/bluebubbles/module.js.map +1 -0
- package/dist/agents/channels/bluebubbles/normalize.d.ts +111 -0
- package/dist/agents/channels/bluebubbles/normalize.d.ts.map +1 -0
- package/dist/agents/channels/bluebubbles/normalize.js +239 -0
- package/dist/agents/channels/bluebubbles/normalize.js.map +1 -0
- package/dist/agents/channels/bluebubbles/plugin.d.ts +46 -0
- package/dist/agents/channels/bluebubbles/plugin.d.ts.map +1 -0
- package/dist/agents/channels/bluebubbles/plugin.js +242 -0
- package/dist/agents/channels/bluebubbles/plugin.js.map +1 -0
- package/dist/agents/channels/bluebubbles/probe.d.ts +79 -0
- package/dist/agents/channels/bluebubbles/probe.d.ts.map +1 -0
- package/dist/agents/channels/bluebubbles/probe.js +138 -0
- package/dist/agents/channels/bluebubbles/probe.js.map +1 -0
- package/dist/agents/channels/bluebubbles/reactions.d.ts +46 -0
- package/dist/agents/channels/bluebubbles/reactions.d.ts.map +1 -0
- package/dist/agents/channels/bluebubbles/reactions.js +207 -0
- package/dist/agents/channels/bluebubbles/reactions.js.map +1 -0
- package/dist/agents/channels/bluebubbles/send.d.ts +132 -0
- package/dist/agents/channels/bluebubbles/send.d.ts.map +1 -0
- package/dist/agents/channels/bluebubbles/send.js +327 -0
- package/dist/agents/channels/bluebubbles/send.js.map +1 -0
- package/dist/agents/channels/bluebubbles/status-issues.d.ts +57 -0
- package/dist/agents/channels/bluebubbles/status-issues.d.ts.map +1 -0
- package/dist/agents/channels/bluebubbles/status-issues.js +93 -0
- package/dist/agents/channels/bluebubbles/status-issues.js.map +1 -0
- package/dist/agents/channels/bluebubbles/types.d.ts +69 -0
- package/dist/agents/channels/bluebubbles/types.d.ts.map +1 -0
- package/dist/agents/channels/bluebubbles/types.js +118 -0
- package/dist/agents/channels/bluebubbles/types.js.map +1 -0
- package/dist/agents/channels/bluebubbles/webhook.d.ts +97 -0
- package/dist/agents/channels/bluebubbles/webhook.d.ts.map +1 -0
- package/dist/agents/channels/bluebubbles/webhook.js +249 -0
- package/dist/agents/channels/bluebubbles/webhook.js.map +1 -0
- package/dist/agents/channels/bundled-channel-metas.d.ts +13 -0
- package/dist/agents/channels/bundled-channel-metas.d.ts.map +1 -1
- package/dist/agents/channels/bundled-channel-metas.js +33 -0
- package/dist/agents/channels/bundled-channel-metas.js.map +1 -1
- package/dist/agents/channels/imessage/account-config.d.ts +178 -0
- package/dist/agents/channels/imessage/account-config.d.ts.map +1 -0
- package/dist/agents/channels/imessage/account-config.js +371 -0
- package/dist/agents/channels/imessage/account-config.js.map +1 -0
- package/dist/agents/channels/imessage/adapter.d.ts +36 -0
- package/dist/agents/channels/imessage/adapter.d.ts.map +1 -0
- package/dist/agents/channels/imessage/adapter.js +286 -0
- package/dist/agents/channels/imessage/adapter.js.map +1 -0
- package/dist/agents/channels/imessage/client.d.ts +99 -0
- package/dist/agents/channels/imessage/client.d.ts.map +1 -0
- package/dist/agents/channels/imessage/client.js +231 -0
- package/dist/agents/channels/imessage/client.js.map +1 -0
- package/dist/agents/channels/imessage/connection.d.ts +101 -0
- package/dist/agents/channels/imessage/connection.d.ts.map +1 -0
- package/dist/agents/channels/imessage/connection.js +367 -0
- package/dist/agents/channels/imessage/connection.js.map +1 -0
- package/dist/agents/channels/imessage/format.d.ts +45 -0
- package/dist/agents/channels/imessage/format.d.ts.map +1 -0
- package/dist/agents/channels/imessage/format.js +170 -0
- package/dist/agents/channels/imessage/format.js.map +1 -0
- package/dist/agents/channels/imessage/history.d.ts +49 -0
- package/dist/agents/channels/imessage/history.d.ts.map +1 -0
- package/dist/agents/channels/imessage/history.js +74 -0
- package/dist/agents/channels/imessage/history.js.map +1 -0
- package/dist/agents/channels/imessage/index.d.ts +25 -0
- package/dist/agents/channels/imessage/index.d.ts.map +1 -0
- package/dist/agents/channels/imessage/index.js +25 -0
- package/dist/agents/channels/imessage/index.js.map +1 -0
- package/dist/agents/channels/imessage/media.d.ts +92 -0
- package/dist/agents/channels/imessage/media.d.ts.map +1 -0
- package/dist/agents/channels/imessage/media.js +196 -0
- package/dist/agents/channels/imessage/media.js.map +1 -0
- package/dist/agents/channels/imessage/messaging.d.ts +14 -0
- package/dist/agents/channels/imessage/messaging.d.ts.map +1 -0
- package/dist/agents/channels/imessage/messaging.js +37 -0
- package/dist/agents/channels/imessage/messaging.js.map +1 -0
- package/dist/agents/channels/imessage/module.d.ts +16 -0
- package/dist/agents/channels/imessage/module.d.ts.map +1 -0
- package/dist/agents/channels/imessage/module.js +23 -0
- package/dist/agents/channels/imessage/module.js.map +1 -0
- package/dist/agents/channels/imessage/monitor.d.ts +207 -0
- package/dist/agents/channels/imessage/monitor.d.ts.map +1 -0
- package/dist/agents/channels/imessage/monitor.js +504 -0
- package/dist/agents/channels/imessage/monitor.js.map +1 -0
- package/dist/agents/channels/imessage/plugin.d.ts +53 -0
- package/dist/agents/channels/imessage/plugin.d.ts.map +1 -0
- package/dist/agents/channels/imessage/plugin.js +215 -0
- package/dist/agents/channels/imessage/plugin.js.map +1 -0
- package/dist/agents/channels/imessage/probe.d.ts +68 -0
- package/dist/agents/channels/imessage/probe.d.ts.map +1 -0
- package/dist/agents/channels/imessage/probe.js +134 -0
- package/dist/agents/channels/imessage/probe.js.map +1 -0
- package/dist/agents/channels/imessage/remote-attachments.d.ts +61 -0
- package/dist/agents/channels/imessage/remote-attachments.d.ts.map +1 -0
- package/dist/agents/channels/imessage/remote-attachments.js +131 -0
- package/dist/agents/channels/imessage/remote-attachments.js.map +1 -0
- package/dist/agents/channels/imessage/send.d.ts +61 -0
- package/dist/agents/channels/imessage/send.d.ts.map +1 -0
- package/dist/agents/channels/imessage/send.js +108 -0
- package/dist/agents/channels/imessage/send.js.map +1 -0
- package/dist/agents/channels/imessage/targets.d.ts +91 -0
- package/dist/agents/channels/imessage/targets.d.ts.map +1 -0
- package/dist/agents/channels/imessage/targets.js +245 -0
- package/dist/agents/channels/imessage/targets.js.map +1 -0
- package/dist/agents/channels/imessage/watch-error.d.ts +23 -0
- package/dist/agents/channels/imessage/watch-error.d.ts.map +1 -0
- package/dist/agents/channels/imessage/watch-error.js +69 -0
- package/dist/agents/channels/imessage/watch-error.js.map +1 -0
- package/dist/agents/channels/inbound-pipeline.d.ts +11 -0
- package/dist/agents/channels/inbound-pipeline.d.ts.map +1 -1
- package/dist/agents/channels/inbound-pipeline.js +20 -1
- package/dist/agents/channels/inbound-pipeline.js.map +1 -1
- package/dist/agents/channels/manager.d.ts +9 -0
- package/dist/agents/channels/manager.d.ts.map +1 -1
- package/dist/agents/channels/manager.js.map +1 -1
- package/dist/agents/channels/sdk.d.ts +4 -0
- package/dist/agents/channels/sdk.d.ts.map +1 -1
- package/dist/agents/channels/sdk.js +4 -0
- package/dist/agents/channels/sdk.js.map +1 -1
- package/dist/agents/extensions/modules/index.d.ts.map +1 -1
- package/dist/agents/extensions/modules/index.js +12 -0
- package/dist/agents/extensions/modules/index.js.map +1 -1
- package/dist/agents/session-wiring.d.ts +31 -0
- package/dist/agents/session-wiring.d.ts.map +1 -1
- package/dist/agents/session-wiring.js +45 -2
- package/dist/agents/session-wiring.js.map +1 -1
- package/dist/agents/tools/bluebubbles-action-tool.d.ts +66 -0
- package/dist/agents/tools/bluebubbles-action-tool.d.ts.map +1 -0
- package/dist/agents/tools/bluebubbles-action-tool.js +234 -0
- package/dist/agents/tools/bluebubbles-action-tool.js.map +1 -0
- package/dist/agents/tools/registry.d.ts.map +1 -1
- package/dist/agents/tools/registry.js +18 -0
- package/dist/agents/tools/registry.js.map +1 -1
- package/dist/buildstamp.json +1 -1
- package/dist/core/server.d.ts.map +1 -1
- package/dist/core/server.js +48 -2
- package/dist/core/server.js.map +1 -1
- package/dist/infra/net/fetch-guard.d.ts +24 -2
- package/dist/infra/net/fetch-guard.d.ts.map +1 -1
- package/dist/infra/net/fetch-guard.js +78 -31
- package/dist/infra/net/fetch-guard.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* BlueBubbles outbound-addressing adapter (the `ChannelPlugin.messaging` slot).
|
|
3
|
+
*
|
|
4
|
+
* Turns the loose `to` the agent hands `send_message` ("+1 555 123 4567",
|
|
5
|
+
* "bluebubbles:user@example.com", "chat_guid:…") into a concrete target the
|
|
6
|
+
* runtime `sendText` understands. BlueBubbles shares iMessage's target grammar,
|
|
7
|
+
* so this reuses the iMessage target primitives (chat_guid / chat_id / handle)
|
|
8
|
+
* and only swaps the channel-name prefix to `bluebubbles:`.
|
|
9
|
+
*/
|
|
10
|
+
import { inferIMessageTargetChatType, looksLikeIMessageTargetId, normalizeIMessageHandle, } from "../imessage/targets.js";
|
|
11
|
+
/** The BlueBubbles messaging adapter. */
|
|
12
|
+
export const bluebubblesMessagingAdapter = {
|
|
13
|
+
parseExplicitTarget(text) {
|
|
14
|
+
const trimmed = (text ?? "").trim();
|
|
15
|
+
if (!trimmed)
|
|
16
|
+
return null;
|
|
17
|
+
// An explicit `bluebubbles:<handle>` form names the channel.
|
|
18
|
+
const m = /^bluebubbles:(.+)$/i.exec(trimmed);
|
|
19
|
+
if (m && m[1])
|
|
20
|
+
return { channelId: "bluebubbles", target: m[1].trim() };
|
|
21
|
+
// A concrete chat/service/handle id (vs a bare name) is an explicit target.
|
|
22
|
+
if (looksLikeIMessageTargetId(trimmed))
|
|
23
|
+
return { target: trimmed };
|
|
24
|
+
return null;
|
|
25
|
+
},
|
|
26
|
+
normalizeTarget(raw) {
|
|
27
|
+
const trimmed = (raw ?? "").trim();
|
|
28
|
+
if (!trimmed)
|
|
29
|
+
return trimmed;
|
|
30
|
+
return normalizeIMessageHandle(trimmed);
|
|
31
|
+
},
|
|
32
|
+
inferTargetChatType(target) {
|
|
33
|
+
return inferIMessageTargetChatType(target);
|
|
34
|
+
},
|
|
35
|
+
};
|
|
36
|
+
//# sourceMappingURL=messaging.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"messaging.js","sourceRoot":"","sources":["../../../../src/agents/channels/bluebubbles/messaging.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,EACN,2BAA2B,EAC3B,yBAAyB,EACzB,uBAAuB,GACvB,MAAM,wBAAwB,CAAC;AAEhC,yCAAyC;AACzC,MAAM,CAAC,MAAM,2BAA2B,GAA4B;IACnE,mBAAmB,CAAC,IAAY;QAC/B,MAAM,OAAO,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;QACpC,IAAI,CAAC,OAAO;YAAE,OAAO,IAAI,CAAC;QAC1B,6DAA6D;QAC7D,MAAM,CAAC,GAAG,qBAAqB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAC9C,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAAE,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC;QACxE,4EAA4E;QAC5E,IAAI,yBAAyB,CAAC,OAAO,CAAC;YAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC;QACnE,OAAO,IAAI,CAAC;IACb,CAAC;IACD,eAAe,CAAC,GAAW;QAC1B,MAAM,OAAO,GAAG,CAAC,GAAG,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;QACnC,IAAI,CAAC,OAAO;YAAE,OAAO,OAAO,CAAC;QAC7B,OAAO,uBAAuB,CAAC,OAAO,CAAC,CAAC;IACzC,CAAC;IACD,mBAAmB,CAAC,MAAc;QACjC,OAAO,2BAA2B,CAAC,MAAM,CAAC,CAAC;IAC5C,CAAC;CACD,CAAC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* BlueBubbles extension module.
|
|
3
|
+
*
|
|
4
|
+
* Registers the BlueBubbles channel adapter through the seam, AND — because
|
|
5
|
+
* BlueBubbles is a WEBHOOK-in channel — registers a gateway HTTP route PER
|
|
6
|
+
* configured account that receives the server's webhook POSTs and feeds them into
|
|
7
|
+
* the started adapter for THAT account (after verifying the password embedded in
|
|
8
|
+
* the registered webhook URL query string).
|
|
9
|
+
*
|
|
10
|
+
* The loader gates the adapter by the usual extension config; the adapter itself
|
|
11
|
+
* only starts when `channels.bluebubbles.enabled` is true AND a serverUrl +
|
|
12
|
+
* password resolve — so bundling this module is inert until the operator opts in.
|
|
13
|
+
*
|
|
14
|
+
* - The default account keeps the base webhook path (`/bluebubbles/webhook`)
|
|
15
|
+
* and feeds the inline adapter directly.
|
|
16
|
+
* - Each NAMED account (only present when >1 account is configured) gets its own
|
|
17
|
+
* route on a distinct path, whose `resolveSink` looks up THAT account's
|
|
18
|
+
* STARTED adapter at request time via the per-account adapter registry
|
|
19
|
+
* (`account-registry.ts`) the plugin populates on `startAccount`.
|
|
20
|
+
* `b.httpRoute(...)` is only available at `register()` time (before the plugin
|
|
21
|
+
* starts accounts), so the late binding is essential. Mirrors `slack/module.ts`.
|
|
22
|
+
*/
|
|
23
|
+
export declare const bluebubblesModule: import("../sdk.js").BrigadeModule;
|
|
24
|
+
//# sourceMappingURL=module.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"module.d.ts","sourceRoot":"","sources":["../../../../src/agents/channels/bluebubbles/module.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAcH,eAAO,MAAM,iBAAiB,mCA2B5B,CAAC"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* BlueBubbles extension module.
|
|
3
|
+
*
|
|
4
|
+
* Registers the BlueBubbles channel adapter through the seam, AND — because
|
|
5
|
+
* BlueBubbles is a WEBHOOK-in channel — registers a gateway HTTP route PER
|
|
6
|
+
* configured account that receives the server's webhook POSTs and feeds them into
|
|
7
|
+
* the started adapter for THAT account (after verifying the password embedded in
|
|
8
|
+
* the registered webhook URL query string).
|
|
9
|
+
*
|
|
10
|
+
* The loader gates the adapter by the usual extension config; the adapter itself
|
|
11
|
+
* only starts when `channels.bluebubbles.enabled` is true AND a serverUrl +
|
|
12
|
+
* password resolve — so bundling this module is inert until the operator opts in.
|
|
13
|
+
*
|
|
14
|
+
* - The default account keeps the base webhook path (`/bluebubbles/webhook`)
|
|
15
|
+
* and feeds the inline adapter directly.
|
|
16
|
+
* - Each NAMED account (only present when >1 account is configured) gets its own
|
|
17
|
+
* route on a distinct path, whose `resolveSink` looks up THAT account's
|
|
18
|
+
* STARTED adapter at request time via the per-account adapter registry
|
|
19
|
+
* (`account-registry.ts`) the plugin populates on `startAccount`.
|
|
20
|
+
* `b.httpRoute(...)` is only available at `register()` time (before the plugin
|
|
21
|
+
* starts accounts), so the late binding is essential. Mirrors `slack/module.ts`.
|
|
22
|
+
*/
|
|
23
|
+
import { defineModule } from "../sdk.js";
|
|
24
|
+
import { bluebubblesChannelEnabled, listBlueBubblesAccountIds, resolveBlueBubblesPassword, resolveBlueBubblesWebhookPath, BLUEBUBBLES_DEFAULT_ACCOUNT_ID, } from "./account-config.js";
|
|
25
|
+
import { getBlueBubblesAccountSink } from "./account-registry.js";
|
|
26
|
+
import { createBlueBubblesAdapter } from "./adapter.js";
|
|
27
|
+
import { buildBlueBubblesWebhookRoute } from "./webhook.js";
|
|
28
|
+
export const bluebubblesModule = defineModule({
|
|
29
|
+
id: "bluebubbles",
|
|
30
|
+
register(b) {
|
|
31
|
+
const adapter = createBlueBubblesAdapter();
|
|
32
|
+
b.channel(adapter);
|
|
33
|
+
// Only register inbound routes when the channel is enabled (a disabled
|
|
34
|
+
// install exposes no inbound HTTP surface).
|
|
35
|
+
if (!bluebubblesChannelEnabled(b.config))
|
|
36
|
+
return;
|
|
37
|
+
const accountIds = listBlueBubblesAccountIds(b.config);
|
|
38
|
+
const isMultiAccount = accountIds.length > 1;
|
|
39
|
+
for (const accountId of accountIds) {
|
|
40
|
+
const isDefault = accountId === BLUEBUBBLES_DEFAULT_ACCOUNT_ID;
|
|
41
|
+
b.httpRoute(buildBlueBubblesWebhookRoute({
|
|
42
|
+
path: resolveBlueBubblesWebhookPath(b.config, accountId),
|
|
43
|
+
// Each route verifies with ITS OWN account's password.
|
|
44
|
+
password: resolveBlueBubblesPassword(b.config, accountId),
|
|
45
|
+
resolveSink: isDefault && !isMultiAccount
|
|
46
|
+
? () => adapter
|
|
47
|
+
: () => getBlueBubblesAccountSink(accountId) ?? null,
|
|
48
|
+
}));
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
});
|
|
52
|
+
//# sourceMappingURL=module.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"module.js","sourceRoot":"","sources":["../../../../src/agents/channels/bluebubbles/module.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,EACN,yBAAyB,EACzB,yBAAyB,EACzB,0BAA0B,EAC1B,6BAA6B,EAC7B,8BAA8B,GAC9B,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,yBAAyB,EAAE,MAAM,uBAAuB,CAAC;AAClE,OAAO,EAAE,wBAAwB,EAA2B,MAAM,cAAc,CAAC;AACjF,OAAO,EAAE,4BAA4B,EAAE,MAAM,cAAc,CAAC;AAE5D,MAAM,CAAC,MAAM,iBAAiB,GAAG,YAAY,CAAC;IAC7C,EAAE,EAAE,aAAa;IACjB,QAAQ,CAAC,CAAC;QACT,MAAM,OAAO,GAAG,wBAAwB,EAAwB,CAAC;QACjE,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QAEnB,uEAAuE;QACvE,4CAA4C;QAC5C,IAAI,CAAC,yBAAyB,CAAC,CAAC,CAAC,MAAe,CAAC;YAAE,OAAO;QAE1D,MAAM,UAAU,GAAG,yBAAyB,CAAC,CAAC,CAAC,MAAe,CAAC,CAAC;QAChE,MAAM,cAAc,GAAG,UAAU,CAAC,MAAM,GAAG,CAAC,CAAC;QAC7C,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;YACpC,MAAM,SAAS,GAAG,SAAS,KAAK,8BAA8B,CAAC;YAC/D,CAAC,CAAC,SAAS,CACV,4BAA4B,CAAC;gBAC5B,IAAI,EAAE,6BAA6B,CAAC,CAAC,CAAC,MAAe,EAAE,SAAS,CAAC;gBACjE,uDAAuD;gBACvD,QAAQ,EAAE,0BAA0B,CAAC,CAAC,CAAC,MAAe,EAAE,SAAS,CAAC;gBAClE,WAAW,EACV,SAAS,IAAI,CAAC,cAAc;oBAC3B,CAAC,CAAC,GAAG,EAAE,CAAC,OAAO;oBACf,CAAC,CAAC,GAAG,EAAE,CAAC,yBAAyB,CAAC,SAAS,CAAC,IAAI,IAAI;aACtD,CAAC,CACF,CAAC;QACH,CAAC;IACF,CAAC;CACD,CAAC,CAAC"}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* BlueBubbles webhook normalisation — DEFENSIVE.
|
|
3
|
+
*
|
|
4
|
+
* BlueBubbles fires `new-message` / `updated-message` webhook POSTs whose payload
|
|
5
|
+
* shape varies by server version: the chat GUID may sit at the TOP LEVEL
|
|
6
|
+
* (`chatGuid` / `chat_guid`), nested under `chat` / `conversation`, OR in the
|
|
7
|
+
* `chats[0]` array. The sender may be a `handle` object, a `handle` string, or a
|
|
8
|
+
* `sender`/`from` field. This module reads ALL those shapes into one stable
|
|
9
|
+
* `NormalizedBlueBubblesMessage`, and surfaces the load-bearing decisions:
|
|
10
|
+
*
|
|
11
|
+
* - `skip` reasons: `isFromMe` (we sent it) and tapback messages
|
|
12
|
+
* (`associatedMessageType` 2000-3999 — these are DROPPED so the agent never
|
|
13
|
+
* replies to a reaction as if it were text).
|
|
14
|
+
* - DM vs group: derived from the chat-guid separator (`;-;` = DM, `;+;` =
|
|
15
|
+
* group), then explicit flags, then participant count.
|
|
16
|
+
* - a decoded tapback note (for optional surfacing) when the message is a tapback.
|
|
17
|
+
*/
|
|
18
|
+
import { type DecodedTapback } from "./reactions.js";
|
|
19
|
+
import type { RawBlueBubblesAttachment } from "./media.js";
|
|
20
|
+
/** A normalised inbound BlueBubbles message (transport-neutral). */
|
|
21
|
+
export interface NormalizedBlueBubblesMessage {
|
|
22
|
+
/** The stable conversation id (a `chat_guid:` target the reply path understands). */
|
|
23
|
+
conversationId: string;
|
|
24
|
+
/** Raw chat GUID. */
|
|
25
|
+
chatGuid: string;
|
|
26
|
+
/** This message's GUID. */
|
|
27
|
+
messageGuid: string;
|
|
28
|
+
/** Sender handle (phone / email / `handle` string). */
|
|
29
|
+
from: string;
|
|
30
|
+
/** Optional display name of the sender. */
|
|
31
|
+
fromName?: string;
|
|
32
|
+
/** Message text (may be empty for a media-only message). */
|
|
33
|
+
text: string;
|
|
34
|
+
/** True when this is a group chat. */
|
|
35
|
+
isGroup: boolean;
|
|
36
|
+
/** When the platform stamped it (epoch ms), when known. */
|
|
37
|
+
timestampMs?: number;
|
|
38
|
+
/** A reply-to message GUID, when this message replies to another. */
|
|
39
|
+
replyToGuid?: string;
|
|
40
|
+
/**
|
|
41
|
+
* Handles mentioned in this message. iMessage has no @-mention metadata, so
|
|
42
|
+
* this is populated only when the bot's own `selfHandle` appears in the text —
|
|
43
|
+
* which is what lets the central pipeline's group requireMention gate fire.
|
|
44
|
+
*/
|
|
45
|
+
mentions?: string[];
|
|
46
|
+
/**
|
|
47
|
+
* The GUID of the parent message this one is ASSOCIATED with (a link-preview
|
|
48
|
+
* balloon, a sticker, …). Carried for inbound coalescing — a text + its
|
|
49
|
+
* link-preview balloon arrive as two `new-message` webhooks; the debouncer
|
|
50
|
+
* keys both on this so they collapse into ONE logical message. Distinct from a
|
|
51
|
+
* tapback association (those are dropped earlier in `normalize`).
|
|
52
|
+
*/
|
|
53
|
+
associatedMessageGuid?: string;
|
|
54
|
+
/**
|
|
55
|
+
* The balloon bundle id (`com.apple.messages.URLBalloonProvider`, sticker
|
|
56
|
+
* providers, …) when this message is a balloon rather than plain text. Present
|
|
57
|
+
* with `associatedMessageGuid` for a balloon; used as a coalescing signal.
|
|
58
|
+
*/
|
|
59
|
+
balloonBundleId?: string;
|
|
60
|
+
/** Raw attachment descriptors (downloaded later, post-access-gate). */
|
|
61
|
+
attachments: RawBlueBubblesAttachment[];
|
|
62
|
+
/** The raw webhook payload (for the pipeline's `raw` field). */
|
|
63
|
+
raw: unknown;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* A skip that MIGHT actually be a media message whose attachments indexed late
|
|
67
|
+
* (empty text + empty attachments + a real guid). The connection can use these
|
|
68
|
+
* fields to re-fetch the message's attachments and, only if media turns up,
|
|
69
|
+
* dispatch a synthetic inbound — without spamming the agent with truly-empty
|
|
70
|
+
* messages.
|
|
71
|
+
*/
|
|
72
|
+
export interface EmptyMediaCandidate {
|
|
73
|
+
messageGuid: string;
|
|
74
|
+
chatGuid: string;
|
|
75
|
+
from: string;
|
|
76
|
+
fromName?: string;
|
|
77
|
+
isGroup: boolean;
|
|
78
|
+
timestampMs?: number;
|
|
79
|
+
}
|
|
80
|
+
/** The result of normalising a webhook payload: a message, a skip, or a tapback note. */
|
|
81
|
+
export type NormalizeResult = {
|
|
82
|
+
kind: "message";
|
|
83
|
+
message: NormalizedBlueBubblesMessage;
|
|
84
|
+
} | {
|
|
85
|
+
kind: "skip";
|
|
86
|
+
reason: string;
|
|
87
|
+
mediaCandidate?: EmptyMediaCandidate;
|
|
88
|
+
} | {
|
|
89
|
+
kind: "tapback";
|
|
90
|
+
tapback: DecodedTapback;
|
|
91
|
+
chatGuid: string;
|
|
92
|
+
targetGuid?: string;
|
|
93
|
+
from: string;
|
|
94
|
+
isGroup: boolean;
|
|
95
|
+
};
|
|
96
|
+
/**
|
|
97
|
+
* Detect whether the bot's own `selfHandle` is mentioned in the text. iMessage
|
|
98
|
+
* has no @-mention metadata, so "mention" = the bot's handle appearing in the
|
|
99
|
+
* message body. A phone handle matches on its digit-run inside the text's
|
|
100
|
+
* digits; an email matches case-insensitively. Returns the matched self handle
|
|
101
|
+
* in an array, or undefined when there's no match (so the field stays unset).
|
|
102
|
+
*/
|
|
103
|
+
export declare function detectBlueBubblesMentions(text: string, selfHandle: string | undefined): string[] | undefined;
|
|
104
|
+
/**
|
|
105
|
+
* Normalise a BlueBubbles webhook payload. `eventType` is the webhook's declared
|
|
106
|
+
* type (`new-message` / `updated-message`). `selfHandle` (when set) lets group
|
|
107
|
+
* mention-gating fire by populating `mentions[]` when the bot is named in text.
|
|
108
|
+
* Returns a `message`, a `skip` (with a reason), or a `tapback` result.
|
|
109
|
+
*/
|
|
110
|
+
export declare function normalizeBlueBubblesWebhook(payload: unknown, eventType?: string, selfHandle?: string): NormalizeResult;
|
|
111
|
+
//# sourceMappingURL=normalize.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"normalize.d.ts","sourceRoot":"","sources":["../../../../src/agents/channels/bluebubbles/normalize.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EAA8C,KAAK,cAAc,EAAE,MAAM,gBAAgB,CAAC;AACjG,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,YAAY,CAAC;AAE3D,oEAAoE;AACpE,MAAM,WAAW,4BAA4B;IAC5C,qFAAqF;IACrF,cAAc,EAAE,MAAM,CAAC;IACvB,qBAAqB;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,2BAA2B;IAC3B,WAAW,EAAE,MAAM,CAAC;IACpB,uDAAuD;IACvD,IAAI,EAAE,MAAM,CAAC;IACb,2CAA2C;IAC3C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,4DAA4D;IAC5D,IAAI,EAAE,MAAM,CAAC;IACb,sCAAsC;IACtC,OAAO,EAAE,OAAO,CAAC;IACjB,2DAA2D;IAC3D,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,qEAAqE;IACrE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB;;;;;;OAMG;IACH,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B;;;;OAIG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,uEAAuE;IACvE,WAAW,EAAE,wBAAwB,EAAE,CAAC;IACxC,gEAAgE;IAChE,GAAG,EAAE,OAAO,CAAC;CACb;AAED;;;;;;GAMG;AACH,MAAM,WAAW,mBAAmB;IACnC,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,OAAO,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,yFAAyF;AACzF,MAAM,MAAM,eAAe,GACxB;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,OAAO,EAAE,4BAA4B,CAAA;CAAE,GAC1D;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,cAAc,CAAC,EAAE,mBAAmB,CAAA;CAAE,GACtE;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,OAAO,EAAE,cAAc,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,CAAC;AAgHvH;;;;;;GAMG;AACH,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,EAAE,GAAG,SAAS,CAU5G;AAED;;;;;GAKG;AACH,wBAAgB,2BAA2B,CAAC,OAAO,EAAE,OAAO,EAAE,SAAS,CAAC,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,eAAe,CAuFtH"}
|
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* BlueBubbles webhook normalisation — DEFENSIVE.
|
|
3
|
+
*
|
|
4
|
+
* BlueBubbles fires `new-message` / `updated-message` webhook POSTs whose payload
|
|
5
|
+
* shape varies by server version: the chat GUID may sit at the TOP LEVEL
|
|
6
|
+
* (`chatGuid` / `chat_guid`), nested under `chat` / `conversation`, OR in the
|
|
7
|
+
* `chats[0]` array. The sender may be a `handle` object, a `handle` string, or a
|
|
8
|
+
* `sender`/`from` field. This module reads ALL those shapes into one stable
|
|
9
|
+
* `NormalizedBlueBubblesMessage`, and surfaces the load-bearing decisions:
|
|
10
|
+
*
|
|
11
|
+
* - `skip` reasons: `isFromMe` (we sent it) and tapback messages
|
|
12
|
+
* (`associatedMessageType` 2000-3999 — these are DROPPED so the agent never
|
|
13
|
+
* replies to a reaction as if it were text).
|
|
14
|
+
* - DM vs group: derived from the chat-guid separator (`;-;` = DM, `;+;` =
|
|
15
|
+
* group), then explicit flags, then participant count.
|
|
16
|
+
* - a decoded tapback note (for optional surfacing) when the message is a tapback.
|
|
17
|
+
*/
|
|
18
|
+
import { decodeTapbackType, isTapbackAssociatedType } from "./reactions.js";
|
|
19
|
+
function asRecord(v) {
|
|
20
|
+
return v && typeof v === "object" && !Array.isArray(v) ? v : null;
|
|
21
|
+
}
|
|
22
|
+
function readString(rec, ...keys) {
|
|
23
|
+
if (!rec)
|
|
24
|
+
return undefined;
|
|
25
|
+
for (const key of keys) {
|
|
26
|
+
const v = rec[key];
|
|
27
|
+
if (typeof v === "string" && v.trim())
|
|
28
|
+
return v.trim();
|
|
29
|
+
}
|
|
30
|
+
return undefined;
|
|
31
|
+
}
|
|
32
|
+
function readBoolean(rec, ...keys) {
|
|
33
|
+
if (!rec)
|
|
34
|
+
return undefined;
|
|
35
|
+
for (const key of keys) {
|
|
36
|
+
const v = rec[key];
|
|
37
|
+
if (typeof v === "boolean")
|
|
38
|
+
return v;
|
|
39
|
+
}
|
|
40
|
+
return undefined;
|
|
41
|
+
}
|
|
42
|
+
function readNumber(rec, ...keys) {
|
|
43
|
+
if (!rec)
|
|
44
|
+
return undefined;
|
|
45
|
+
for (const key of keys) {
|
|
46
|
+
const v = rec[key];
|
|
47
|
+
if (typeof v === "number" && Number.isFinite(v))
|
|
48
|
+
return v;
|
|
49
|
+
}
|
|
50
|
+
return undefined;
|
|
51
|
+
}
|
|
52
|
+
/** The first `chats[]` record on a message, or null. */
|
|
53
|
+
function readFirstChatRecord(message) {
|
|
54
|
+
const chats = message.chats;
|
|
55
|
+
if (Array.isArray(chats) && chats.length > 0)
|
|
56
|
+
return asRecord(chats[0]);
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Unwrap the webhook envelope to the inner message record. BlueBubbles nests the
|
|
61
|
+
* message under `data` (and sometimes `payload` / `event`); the inner message may
|
|
62
|
+
* itself be under `message` or be the record directly.
|
|
63
|
+
*/
|
|
64
|
+
function extractMessageRecord(payload) {
|
|
65
|
+
const root = asRecord(payload);
|
|
66
|
+
if (!root)
|
|
67
|
+
return null;
|
|
68
|
+
const data = asRecord(root.data) ?? asRecord(root.payload) ?? asRecord(root.event) ?? root;
|
|
69
|
+
return asRecord(data.message) ?? data;
|
|
70
|
+
}
|
|
71
|
+
/** Resolve the chat GUID across the top-level / nested / `chats[0]` shapes. */
|
|
72
|
+
function resolveChatGuid(message) {
|
|
73
|
+
const chat = asRecord(message.chat) ?? asRecord(message.conversation);
|
|
74
|
+
const first = readFirstChatRecord(message);
|
|
75
|
+
return (readString(message, "chatGuid", "chat_guid") ??
|
|
76
|
+
readString(chat, "chatGuid", "chat_guid", "guid") ??
|
|
77
|
+
readString(first, "chatGuid", "chat_guid", "guid"));
|
|
78
|
+
}
|
|
79
|
+
/** Derive group-ness from the chat-guid separator (`;+;` group, `;-;` DM). */
|
|
80
|
+
function isGroupFromGuid(chatGuid) {
|
|
81
|
+
if (!chatGuid)
|
|
82
|
+
return undefined;
|
|
83
|
+
if (chatGuid.includes(";+;"))
|
|
84
|
+
return true;
|
|
85
|
+
if (chatGuid.includes(";-;"))
|
|
86
|
+
return false;
|
|
87
|
+
return undefined;
|
|
88
|
+
}
|
|
89
|
+
/** Extract the sender handle (object handle / string handle / sender / from). */
|
|
90
|
+
function resolveSender(message) {
|
|
91
|
+
const handle = asRecord(message.handle);
|
|
92
|
+
const fromHandle = readString(handle, "address", "handle", "id") ??
|
|
93
|
+
(typeof message.handle === "string" ? message.handle.trim() : undefined);
|
|
94
|
+
const from = fromHandle ?? readString(message, "sender", "from", "senderId") ?? "";
|
|
95
|
+
const fromName = readString(message, "displayName", "senderName") ?? readString(handle, "displayName");
|
|
96
|
+
return fromName ? { from, fromName } : { from };
|
|
97
|
+
}
|
|
98
|
+
/** Normalise a timestamp (s or ms) to epoch ms. */
|
|
99
|
+
function resolveTimestampMs(message) {
|
|
100
|
+
const raw = readNumber(message, "dateCreated", "date", "timestamp");
|
|
101
|
+
if (raw === undefined)
|
|
102
|
+
return undefined;
|
|
103
|
+
return raw > 1e12 ? raw : raw * 1000;
|
|
104
|
+
}
|
|
105
|
+
/** Read the raw attachment descriptors (camel + snake case). */
|
|
106
|
+
function resolveAttachments(message) {
|
|
107
|
+
const raw = message.attachments;
|
|
108
|
+
if (!Array.isArray(raw))
|
|
109
|
+
return [];
|
|
110
|
+
const out = [];
|
|
111
|
+
for (const a of raw) {
|
|
112
|
+
const rec = asRecord(a);
|
|
113
|
+
if (!rec)
|
|
114
|
+
continue;
|
|
115
|
+
const guid = readString(rec, "guid");
|
|
116
|
+
if (!guid)
|
|
117
|
+
continue;
|
|
118
|
+
const transferName = readString(rec, "transferName", "transfer_name");
|
|
119
|
+
const mimeType = readString(rec, "mimeType", "mime_type", "uti");
|
|
120
|
+
const totalBytes = readNumber(rec, "totalBytes", "total_bytes");
|
|
121
|
+
out.push({
|
|
122
|
+
guid,
|
|
123
|
+
...(transferName ? { transferName } : {}),
|
|
124
|
+
...(mimeType ? { mimeType } : {}),
|
|
125
|
+
...(totalBytes !== undefined ? { totalBytes } : {}),
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
return out;
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Detect whether the bot's own `selfHandle` is mentioned in the text. iMessage
|
|
132
|
+
* has no @-mention metadata, so "mention" = the bot's handle appearing in the
|
|
133
|
+
* message body. A phone handle matches on its digit-run inside the text's
|
|
134
|
+
* digits; an email matches case-insensitively. Returns the matched self handle
|
|
135
|
+
* in an array, or undefined when there's no match (so the field stays unset).
|
|
136
|
+
*/
|
|
137
|
+
export function detectBlueBubblesMentions(text, selfHandle) {
|
|
138
|
+
const handle = (selfHandle ?? "").trim();
|
|
139
|
+
if (!handle || !text)
|
|
140
|
+
return undefined;
|
|
141
|
+
if (handle.includes("@")) {
|
|
142
|
+
return text.toLowerCase().includes(handle.toLowerCase()) ? [handle] : undefined;
|
|
143
|
+
}
|
|
144
|
+
// Phone: compare digit-runs so "+1 (555) 123-4567" in text matches "15551234567".
|
|
145
|
+
const handleDigits = handle.replace(/[^0-9]/g, "");
|
|
146
|
+
if (handleDigits.length >= 5 && text.replace(/[^0-9]/g, "").includes(handleDigits))
|
|
147
|
+
return [handle];
|
|
148
|
+
return undefined;
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Normalise a BlueBubbles webhook payload. `eventType` is the webhook's declared
|
|
152
|
+
* type (`new-message` / `updated-message`). `selfHandle` (when set) lets group
|
|
153
|
+
* mention-gating fire by populating `mentions[]` when the bot is named in text.
|
|
154
|
+
* Returns a `message`, a `skip` (with a reason), or a `tapback` result.
|
|
155
|
+
*/
|
|
156
|
+
export function normalizeBlueBubblesWebhook(payload, eventType, selfHandle) {
|
|
157
|
+
const message = extractMessageRecord(payload);
|
|
158
|
+
if (!message)
|
|
159
|
+
return { kind: "skip", reason: "unparseable payload" };
|
|
160
|
+
// We sent it — never reply to our own message.
|
|
161
|
+
const fromMe = readBoolean(message, "isFromMe", "is_from_me");
|
|
162
|
+
if (fromMe)
|
|
163
|
+
return { kind: "skip", reason: "isFromMe" };
|
|
164
|
+
const chatGuid = resolveChatGuid(message);
|
|
165
|
+
const { from, fromName } = resolveSender(message);
|
|
166
|
+
const isGroup = isGroupFromGuid(chatGuid) ?? readBoolean(message, "isGroup", "is_group") ?? false;
|
|
167
|
+
// Tapback: an `associatedMessageType` in the 2000-3999 range. DROP it as a
|
|
168
|
+
// normal message; surface a decoded note when it's one of the six tapbacks.
|
|
169
|
+
const associatedType = readNumber(message, "associatedMessageType", "associated_message_type");
|
|
170
|
+
if (isTapbackAssociatedType(associatedType)) {
|
|
171
|
+
const decoded = decodeTapbackType(associatedType);
|
|
172
|
+
const targetGuid = readString(message, "associatedMessageGuid", "associated_message_guid");
|
|
173
|
+
if (decoded && chatGuid) {
|
|
174
|
+
return {
|
|
175
|
+
kind: "tapback",
|
|
176
|
+
tapback: decoded,
|
|
177
|
+
chatGuid,
|
|
178
|
+
...(targetGuid ? { targetGuid } : {}),
|
|
179
|
+
from,
|
|
180
|
+
isGroup,
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
return { kind: "skip", reason: "tapback" };
|
|
184
|
+
}
|
|
185
|
+
if (!chatGuid)
|
|
186
|
+
return { kind: "skip", reason: "no chat guid" };
|
|
187
|
+
const messageGuid = readString(message, "guid", "messageGuid") ?? "";
|
|
188
|
+
const text = readString(message, "text", "message") ?? "";
|
|
189
|
+
const attachments = resolveAttachments(message);
|
|
190
|
+
const timestampMs = resolveTimestampMs(message);
|
|
191
|
+
// Skip a truly empty message (no text, no media) — nothing to act on. BUT when
|
|
192
|
+
// it carries a real guid it MIGHT be a media message whose attachments indexed
|
|
193
|
+
// late (BlueBubbles fires the webhook before indexing finishes), so we hand the
|
|
194
|
+
// connection a `mediaCandidate` it can re-fetch + dispatch only if media exists.
|
|
195
|
+
if (!text && attachments.length === 0) {
|
|
196
|
+
const skip = { kind: "skip", reason: "empty message" };
|
|
197
|
+
if (messageGuid) {
|
|
198
|
+
skip.mediaCandidate = {
|
|
199
|
+
messageGuid,
|
|
200
|
+
chatGuid,
|
|
201
|
+
from,
|
|
202
|
+
...(fromName ? { fromName } : {}),
|
|
203
|
+
isGroup,
|
|
204
|
+
...(timestampMs !== undefined ? { timestampMs } : {}),
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
return skip;
|
|
208
|
+
}
|
|
209
|
+
// A reply target — but NOT a reaction association (that's handled above).
|
|
210
|
+
const replyToGuid = readString(message, "threadOriginatorGuid", "thread_originator_guid", "replyToGuid");
|
|
211
|
+
// Self-mention detection (group gating) — only meaningful in groups.
|
|
212
|
+
const mentions = isGroup ? detectBlueBubblesMentions(text, selfHandle) : undefined;
|
|
213
|
+
// Balloon-coalescing signals: a link-preview / sticker balloon carries an
|
|
214
|
+
// `associatedMessageGuid` pointing at its parent text + a `balloonBundleId`.
|
|
215
|
+
// These are NOT tapbacks (handled above) — they pass through as messages, and
|
|
216
|
+
// the debouncer keys them onto the parent so the two webhooks collapse.
|
|
217
|
+
const associatedMessageGuid = readString(message, "associatedMessageGuid", "associated_message_guid");
|
|
218
|
+
const balloonBundleId = readString(message, "balloonBundleId", "balloon_bundle_id");
|
|
219
|
+
return {
|
|
220
|
+
kind: "message",
|
|
221
|
+
message: {
|
|
222
|
+
conversationId: `chat_guid:${chatGuid}`,
|
|
223
|
+
chatGuid,
|
|
224
|
+
messageGuid,
|
|
225
|
+
from,
|
|
226
|
+
...(fromName ? { fromName } : {}),
|
|
227
|
+
text,
|
|
228
|
+
isGroup,
|
|
229
|
+
...(timestampMs !== undefined ? { timestampMs } : {}),
|
|
230
|
+
...(replyToGuid ? { replyToGuid } : {}),
|
|
231
|
+
...(mentions ? { mentions } : {}),
|
|
232
|
+
...(associatedMessageGuid ? { associatedMessageGuid } : {}),
|
|
233
|
+
...(balloonBundleId ? { balloonBundleId } : {}),
|
|
234
|
+
attachments,
|
|
235
|
+
raw: payload,
|
|
236
|
+
},
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
//# sourceMappingURL=normalize.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"normalize.js","sourceRoot":"","sources":["../../../../src/agents/channels/bluebubbles/normalize.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* BlueBubbles `ChannelPlugin` — the multi-ACCOUNT contract surface.
|
|
3
|
+
*
|
|
4
|
+
* Mirrors `slack/plugin.ts` (webhook-in + REST-out, multi-account): wraps
|
|
5
|
+
* `createBlueBubblesAdapter()` once per configured account, partitions per-account
|
|
6
|
+
* runtime in a `Map<accountId, AccountRuntime>`, and drives each account's inbound
|
|
7
|
+
* through the shared `runChannelInboundPipeline` so every account carries the
|
|
8
|
+
* identical ACL + debounce + abort surface.
|
|
9
|
+
*
|
|
10
|
+
* The webhook bridge: each module-registered route resolves its account's STARTED
|
|
11
|
+
* adapter via the per-account registry (`account-registry.ts`). This plugin
|
|
12
|
+
* populates that registry on `startAccount` (so a webhook POST for THIS account's
|
|
13
|
+
* path reaches THIS adapter) and clears it on `stopAccount` (so a torn-down
|
|
14
|
+
* account's route can't feed a dead adapter).
|
|
15
|
+
*
|
|
16
|
+
* The legacy single-account `createBlueBubblesAdapter` STEPS ASIDE when >1 account
|
|
17
|
+
* is configured (its `isConfigured` returns false for the default account).
|
|
18
|
+
*/
|
|
19
|
+
import type { BrigadeConfig } from "../../../config/types.js";
|
|
20
|
+
import { type ChannelAdapter, type ChannelOutboundTarget, type ChannelPlugin, type StartChannelsArgs } from "../sdk.js";
|
|
21
|
+
import { type ResolvedBlueBubblesAccount } from "./account-config.js";
|
|
22
|
+
import { type BlueBubblesAdapter } from "./adapter.js";
|
|
23
|
+
import { type BlueBubblesProbeResult } from "./probe.js";
|
|
24
|
+
/** Dependencies the gateway hands the plugin to drive turns + replies. */
|
|
25
|
+
export interface BlueBubblesPluginDeps {
|
|
26
|
+
defaultAgentId: string;
|
|
27
|
+
loadConfig: () => BrigadeConfig;
|
|
28
|
+
runTurn: StartChannelsArgs["runTurn"];
|
|
29
|
+
/** Optional adapter factory — tests inject a fake; production uses `createBlueBubblesAdapter`. */
|
|
30
|
+
adapterFactory?: (args: {
|
|
31
|
+
accountId: string;
|
|
32
|
+
}) => BlueBubblesAdapter;
|
|
33
|
+
}
|
|
34
|
+
/** Operator-grade view of a per-account bridge — exposed via attached helpers. */
|
|
35
|
+
export interface BlueBubblesPluginRuntimeView {
|
|
36
|
+
startedAccountIds(): string[];
|
|
37
|
+
getAdapter(accountId: string): ChannelAdapter | undefined;
|
|
38
|
+
probeAccount(accountId: string, cfg: BrigadeConfig): Promise<BlueBubblesProbeResult>;
|
|
39
|
+
}
|
|
40
|
+
/** Plugin handle with the extra per-account introspection surface attached. */
|
|
41
|
+
export type BlueBubblesPluginHandle = ChannelPlugin<ResolvedBlueBubblesAccount> & BlueBubblesPluginRuntimeView;
|
|
42
|
+
/** Construct the plugin instance, capturing per-account runtime state in closure. */
|
|
43
|
+
export declare function createBlueBubblesPlugin(deps: BlueBubblesPluginDeps): BlueBubblesPluginHandle;
|
|
44
|
+
/** Outbound dispatch helper for callers reaching the plugin directly. */
|
|
45
|
+
export type BlueBubblesOutboundTarget = ChannelOutboundTarget;
|
|
46
|
+
//# sourceMappingURL=plugin.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../../../../src/agents/channels/bluebubbles/plugin.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAC9D,OAAO,EAMN,KAAK,cAAc,EAKnB,KAAK,qBAAqB,EAC1B,KAAK,aAAa,EAKlB,KAAK,iBAAiB,EAEtB,MAAM,WAAW,CAAC;AACnB,OAAO,EAQN,KAAK,0BAA0B,EAC/B,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAA4B,KAAK,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAEjF,OAAO,EAAoB,KAAK,sBAAsB,EAAE,MAAM,YAAY,CAAC;AAwB3E,0EAA0E;AAC1E,MAAM,WAAW,qBAAqB;IACrC,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,MAAM,aAAa,CAAC;IAChC,OAAO,EAAE,iBAAiB,CAAC,SAAS,CAAC,CAAC;IACtC,kGAAkG;IAClG,cAAc,CAAC,EAAE,CAAC,IAAI,EAAE;QAAE,SAAS,EAAE,MAAM,CAAA;KAAE,KAAK,kBAAkB,CAAC;CACrE;AAED,kFAAkF;AAClF,MAAM,WAAW,4BAA4B;IAC5C,iBAAiB,IAAI,MAAM,EAAE,CAAC;IAC9B,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,cAAc,GAAG,SAAS,CAAC;IAC1D,YAAY,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,aAAa,GAAG,OAAO,CAAC,sBAAsB,CAAC,CAAC;CACrF;AAED,+EAA+E;AAC/E,MAAM,MAAM,uBAAuB,GAAG,aAAa,CAAC,0BAA0B,CAAC,GAAG,4BAA4B,CAAC;AAE/G,qFAAqF;AACrF,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,qBAAqB,GAAG,uBAAuB,CAkM5F;AAOD,yEAAyE;AACzE,MAAM,MAAM,yBAAyB,GAAG,qBAAqB,CAAC"}
|