@spinabot/brigade 1.6.1 → 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/discord/account-config.d.ts +60 -0
- package/dist/agents/channels/discord/account-config.d.ts.map +1 -1
- package/dist/agents/channels/discord/account-config.js +89 -0
- package/dist/agents/channels/discord/account-config.js.map +1 -1
- package/dist/agents/channels/discord/adapter.d.ts +24 -1
- package/dist/agents/channels/discord/adapter.d.ts.map +1 -1
- package/dist/agents/channels/discord/adapter.js +208 -41
- package/dist/agents/channels/discord/adapter.js.map +1 -1
- package/dist/agents/channels/discord/component-blocks.d.ts +108 -0
- package/dist/agents/channels/discord/component-blocks.d.ts.map +1 -0
- package/dist/agents/channels/discord/component-blocks.js +113 -0
- package/dist/agents/channels/discord/component-blocks.js.map +1 -0
- package/dist/agents/channels/discord/components.d.ts +78 -0
- package/dist/agents/channels/discord/components.d.ts.map +1 -1
- package/dist/agents/channels/discord/components.js +89 -0
- package/dist/agents/channels/discord/components.js.map +1 -1
- package/dist/agents/channels/discord/connection.d.ts +195 -12
- package/dist/agents/channels/discord/connection.d.ts.map +1 -1
- package/dist/agents/channels/discord/connection.js +852 -38
- package/dist/agents/channels/discord/connection.js.map +1 -1
- package/dist/agents/channels/discord/directory-cache.d.ts +47 -0
- package/dist/agents/channels/discord/directory-cache.d.ts.map +1 -0
- package/dist/agents/channels/discord/directory-cache.js +131 -0
- package/dist/agents/channels/discord/directory-cache.js.map +1 -0
- package/dist/agents/channels/discord/directory-live.d.ts +61 -0
- package/dist/agents/channels/discord/directory-live.d.ts.map +1 -0
- package/dist/agents/channels/discord/directory-live.js +140 -0
- package/dist/agents/channels/discord/directory-live.js.map +1 -0
- package/dist/agents/channels/discord/format.d.ts +15 -0
- package/dist/agents/channels/discord/format.d.ts.map +1 -1
- package/dist/agents/channels/discord/format.js +56 -0
- package/dist/agents/channels/discord/format.js.map +1 -1
- package/dist/agents/channels/discord/guilds.d.ts +25 -0
- package/dist/agents/channels/discord/guilds.d.ts.map +1 -0
- package/dist/agents/channels/discord/guilds.js +46 -0
- package/dist/agents/channels/discord/guilds.js.map +1 -0
- package/dist/agents/channels/discord/inbound-extras.d.ts +166 -9
- package/dist/agents/channels/discord/inbound-extras.d.ts.map +1 -1
- package/dist/agents/channels/discord/inbound-extras.js +246 -8
- package/dist/agents/channels/discord/inbound-extras.js.map +1 -1
- package/dist/agents/channels/discord/index.d.ts +10 -3
- package/dist/agents/channels/discord/index.d.ts.map +1 -1
- package/dist/agents/channels/discord/index.js +10 -3
- package/dist/agents/channels/discord/index.js.map +1 -1
- package/dist/agents/channels/discord/modal-registry.d.ts +89 -0
- package/dist/agents/channels/discord/modal-registry.d.ts.map +1 -0
- package/dist/agents/channels/discord/modal-registry.js +104 -0
- package/dist/agents/channels/discord/modal-registry.js.map +1 -0
- package/dist/agents/channels/discord/modals.d.ts +100 -0
- package/dist/agents/channels/discord/modals.d.ts.map +1 -0
- package/dist/agents/channels/discord/modals.js +124 -0
- package/dist/agents/channels/discord/modals.js.map +1 -0
- package/dist/agents/channels/discord/permission-audit.d.ts +43 -0
- package/dist/agents/channels/discord/permission-audit.d.ts.map +1 -0
- package/dist/agents/channels/discord/permission-audit.js +192 -0
- package/dist/agents/channels/discord/permission-audit.js.map +1 -0
- package/dist/agents/channels/discord/plugin.d.ts +18 -2
- package/dist/agents/channels/discord/plugin.d.ts.map +1 -1
- package/dist/agents/channels/discord/plugin.js +73 -4
- package/dist/agents/channels/discord/plugin.js.map +1 -1
- package/dist/agents/channels/discord/probe.d.ts +23 -1
- package/dist/agents/channels/discord/probe.d.ts.map +1 -1
- package/dist/agents/channels/discord/probe.js +40 -5
- package/dist/agents/channels/discord/probe.js.map +1 -1
- package/dist/agents/channels/discord/rest-actions.d.ts +346 -0
- package/dist/agents/channels/discord/rest-actions.d.ts.map +1 -0
- package/dist/agents/channels/discord/rest-actions.js +559 -0
- package/dist/agents/channels/discord/rest-actions.js.map +1 -0
- package/dist/agents/channels/discord/rest-components.d.ts +122 -0
- package/dist/agents/channels/discord/rest-components.d.ts.map +1 -0
- package/dist/agents/channels/discord/rest-components.js +243 -0
- package/dist/agents/channels/discord/rest-components.js.map +1 -0
- package/dist/agents/channels/discord/security-audit.d.ts +29 -0
- package/dist/agents/channels/discord/security-audit.d.ts.map +1 -0
- package/dist/agents/channels/discord/security-audit.js +94 -0
- package/dist/agents/channels/discord/security-audit.js.map +1 -0
- package/dist/agents/channels/discord/security-doctor.d.ts +43 -0
- package/dist/agents/channels/discord/security-doctor.d.ts.map +1 -0
- package/dist/agents/channels/discord/security-doctor.js +83 -0
- package/dist/agents/channels/discord/security-doctor.js.map +1 -0
- package/dist/agents/channels/discord/status-issues.d.ts +37 -0
- package/dist/agents/channels/discord/status-issues.d.ts.map +1 -0
- package/dist/agents/channels/discord/status-issues.js +66 -0
- package/dist/agents/channels/discord/status-issues.js.map +1 -0
- package/dist/agents/channels/discord/subagent-thread-binding-store.d.ts +57 -0
- package/dist/agents/channels/discord/subagent-thread-binding-store.d.ts.map +1 -0
- package/dist/agents/channels/discord/subagent-thread-binding-store.js +98 -0
- package/dist/agents/channels/discord/subagent-thread-binding-store.js.map +1 -0
- package/dist/agents/channels/discord/subagent-thread-binding.d.ts +95 -0
- package/dist/agents/channels/discord/subagent-thread-binding.d.ts.map +1 -0
- package/dist/agents/channels/discord/subagent-thread-binding.js +208 -0
- package/dist/agents/channels/discord/subagent-thread-binding.js.map +1 -0
- package/dist/agents/channels/discord/system-events.d.ts +31 -0
- package/dist/agents/channels/discord/system-events.d.ts.map +1 -0
- package/dist/agents/channels/discord/system-events.js +74 -0
- package/dist/agents/channels/discord/system-events.js.map +1 -0
- package/dist/agents/channels/general-callback.d.ts +12 -0
- package/dist/agents/channels/general-callback.d.ts.map +1 -1
- package/dist/agents/channels/general-callback.js +18 -0
- package/dist/agents/channels/general-callback.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 +25 -4
- 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/extensions/types.d.ts +7 -0
- package/dist/agents/extensions/types.d.ts.map +1 -1
- package/dist/agents/extensions/types.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/subagent-announce-delivery.d.ts +10 -0
- package/dist/agents/subagent-announce-delivery.d.ts.map +1 -1
- package/dist/agents/subagent-announce-delivery.js +1 -0
- package/dist/agents/subagent-announce-delivery.js.map +1 -1
- package/dist/agents/subagent-completion-bridge.d.ts.map +1 -1
- package/dist/agents/subagent-completion-bridge.js +81 -0
- package/dist/agents/subagent-completion-bridge.js.map +1 -1
- package/dist/agents/subagent-spawn.d.ts.map +1 -1
- package/dist/agents/subagent-spawn.js +57 -4
- package/dist/agents/subagent-spawn.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/discord-action-tool.d.ts +224 -0
- package/dist/agents/tools/discord-action-tool.d.ts.map +1 -0
- package/dist/agents/tools/discord-action-tool.js +848 -0
- package/dist/agents/tools/discord-action-tool.js.map +1 -0
- package/dist/agents/tools/registry.d.ts.map +1 -1
- package/dist/agents/tools/registry.js +39 -0
- package/dist/agents/tools/registry.js.map +1 -1
- package/dist/agents/tools/sessions/index.d.ts +8 -0
- package/dist/agents/tools/sessions/index.d.ts.map +1 -1
- package/dist/agents/tools/sessions/index.js +15 -3
- package/dist/agents/tools/sessions/index.js.map +1 -1
- package/dist/buildstamp.json +1 -1
- package/dist/cli/commands/channels.d.ts +2 -0
- package/dist/cli/commands/channels.d.ts.map +1 -1
- package/dist/cli/commands/channels.js +58 -1
- package/dist/cli/commands/channels.js.map +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,504 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* iMessage inbound monitor — parse notifications, normalize, and guard against
|
|
3
|
+
* self-echo / reflection / runaway loops.
|
|
4
|
+
*
|
|
5
|
+
* The `imsg rpc` process emits a `message` notification for every new row in the
|
|
6
|
+
* chat database (including the agent's OWN outbound sends, which come back as
|
|
7
|
+
* `is_from_me` rows, AND self-chat reflections). This module condenses the
|
|
8
|
+
* upstream `monitor/` subsystem into the load-bearing pieces:
|
|
9
|
+
*
|
|
10
|
+
* 1. `parseIMessageNotification` — validate + shape the notification params,
|
|
11
|
+
* stripping the protobuf length-prefix some text rows carry.
|
|
12
|
+
* 2. `normalizeIMessageMessage` — turn the payload into a normalized inbound.
|
|
13
|
+
* 3. `SentMessageCache` — remember every outbound send; drop the
|
|
14
|
+
* inbound echo when it matches (text TTL 4s / id TTL 60s).
|
|
15
|
+
* 4. `SelfChatCache` — drop a self-chat message reflected back as a
|
|
16
|
+
* second `is_from_me=false` row (TTL 10s, keyed on text + timestamp).
|
|
17
|
+
* 5. `detectReflectedContent` — drop inbound carrying assistant-internal
|
|
18
|
+
* markers that leaked out and bounced back.
|
|
19
|
+
* 6. `LoopRateLimiter` — after 5 loop-drops in 60s, mute a
|
|
20
|
+
* conversation entirely (the runaway-loop safety net).
|
|
21
|
+
* 7. `decideInbound` — the gating brain that ties them together.
|
|
22
|
+
*
|
|
23
|
+
* Constants are kept byte-faithful to the upstream so the dedupe windows behave
|
|
24
|
+
* identically.
|
|
25
|
+
*/
|
|
26
|
+
import { createHash } from "node:crypto";
|
|
27
|
+
/** Read a protobuf varint at `offset`; returns the value + the next offset. */
|
|
28
|
+
function readVarint(buf, offset) {
|
|
29
|
+
let value = 0;
|
|
30
|
+
let shift = 0;
|
|
31
|
+
let pos = offset;
|
|
32
|
+
while (pos < buf.length && shift <= 28) {
|
|
33
|
+
const byte = buf[pos] ?? 0;
|
|
34
|
+
value |= (byte & 0x7f) << shift;
|
|
35
|
+
pos += 1;
|
|
36
|
+
if ((byte & 0x80) === 0)
|
|
37
|
+
return { value: value >>> 0, nextOffset: pos };
|
|
38
|
+
shift += 7;
|
|
39
|
+
}
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Strip a protobuf field-1 length-prefixed UTF-8 wrapper (tag `0x0a` + varint
|
|
44
|
+
* length + bytes) when the declared length consumes EXACTLY to the buffer end.
|
|
45
|
+
* Returns the inner string, or the original text unchanged.
|
|
46
|
+
*/
|
|
47
|
+
export function stripLengthPrefixedText(text) {
|
|
48
|
+
const src = text ?? "";
|
|
49
|
+
if (!src)
|
|
50
|
+
return src;
|
|
51
|
+
const buf = Buffer.from(src, "utf8");
|
|
52
|
+
if (buf.length < 2 || buf[0] !== 0x0a)
|
|
53
|
+
return src;
|
|
54
|
+
const len = readVarint(buf, 1);
|
|
55
|
+
if (!len || len.value === 0)
|
|
56
|
+
return src;
|
|
57
|
+
if (len.nextOffset + len.value !== buf.length)
|
|
58
|
+
return src;
|
|
59
|
+
const inner = buf.subarray(len.nextOffset).toString("utf8");
|
|
60
|
+
return inner.length > 0 ? inner : src;
|
|
61
|
+
}
|
|
62
|
+
function isRecord(v) {
|
|
63
|
+
return Boolean(v) && typeof v === "object";
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Parse an inbound notification's `params` (`{ message: {...} }`) into a typed
|
|
67
|
+
* payload. Returns null when the shape is malformed (the caller drops it).
|
|
68
|
+
*/
|
|
69
|
+
export function parseIMessageNotification(raw) {
|
|
70
|
+
if (!isRecord(raw))
|
|
71
|
+
return null;
|
|
72
|
+
const message = raw.message;
|
|
73
|
+
if (!isRecord(message))
|
|
74
|
+
return null;
|
|
75
|
+
const out = {};
|
|
76
|
+
const num = (v) => (typeof v === "number" && Number.isFinite(v) ? v : undefined);
|
|
77
|
+
const str = (v) => (typeof v === "string" ? v : undefined);
|
|
78
|
+
const bool = (v) => (typeof v === "boolean" ? v : undefined);
|
|
79
|
+
out.id = num(message.id);
|
|
80
|
+
out.guid = str(message.guid);
|
|
81
|
+
out.chat_id = num(message.chat_id);
|
|
82
|
+
out.sender = str(message.sender);
|
|
83
|
+
out.destination_caller_id = str(message.destination_caller_id);
|
|
84
|
+
out.is_from_me = bool(message.is_from_me);
|
|
85
|
+
const text = str(message.text);
|
|
86
|
+
out.text = text !== undefined ? stripLengthPrefixedText(text) : undefined;
|
|
87
|
+
if (typeof message.reply_to_id === "number" || typeof message.reply_to_id === "string") {
|
|
88
|
+
out.reply_to_id = message.reply_to_id;
|
|
89
|
+
}
|
|
90
|
+
const replyText = str(message.reply_to_text);
|
|
91
|
+
out.reply_to_text = replyText !== undefined ? stripLengthPrefixedText(replyText) : undefined;
|
|
92
|
+
out.reply_to_sender = str(message.reply_to_sender);
|
|
93
|
+
out.created_at = str(message.created_at);
|
|
94
|
+
out.chat_identifier = str(message.chat_identifier);
|
|
95
|
+
out.chat_guid = str(message.chat_guid);
|
|
96
|
+
out.chat_name = str(message.chat_name);
|
|
97
|
+
out.is_group = bool(message.is_group);
|
|
98
|
+
if (Array.isArray(message.attachments))
|
|
99
|
+
out.attachments = message.attachments;
|
|
100
|
+
if (Array.isArray(message.participants))
|
|
101
|
+
out.participants = message.participants.filter((p) => typeof p === "string");
|
|
102
|
+
return out;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Detect whether the bot's own `selfHandle` is named in `text`. iMessage carries
|
|
106
|
+
* no @-mention metadata, so "mention" = the handle appearing in the message body.
|
|
107
|
+
* A phone handle matches on its digit-run inside the text's digits; an email
|
|
108
|
+
* matches case-insensitively. `selfHandle` is expected pre-normalised (digits for
|
|
109
|
+
* a phone, lower-case for an email — see `normalizeIMessageSelfHandle`). Returns
|
|
110
|
+
* the matched self handle in an array, or undefined when there's no match (so the
|
|
111
|
+
* field stays unset). Mirrors BlueBubbles' `detectBlueBubblesMentions`.
|
|
112
|
+
*/
|
|
113
|
+
export function detectIMessageMentions(text, selfHandle) {
|
|
114
|
+
const handle = (selfHandle ?? "").trim();
|
|
115
|
+
if (!handle || !text)
|
|
116
|
+
return undefined;
|
|
117
|
+
if (handle.includes("@")) {
|
|
118
|
+
return text.toLowerCase().includes(handle.toLowerCase()) ? [handle] : undefined;
|
|
119
|
+
}
|
|
120
|
+
// Phone: compare digit-runs so "+1 (555) 123-4567" in text matches "15551234567".
|
|
121
|
+
const handleDigits = handle.replace(/[^0-9]/g, "");
|
|
122
|
+
if (handleDigits.length >= 5 && text.replace(/[^0-9]/g, "").includes(handleDigits))
|
|
123
|
+
return [handle];
|
|
124
|
+
return undefined;
|
|
125
|
+
}
|
|
126
|
+
/** Build the stable conversation id for a payload (group → chat scope, DM → sender). */
|
|
127
|
+
export function conversationIdFor(payload) {
|
|
128
|
+
if (typeof payload.chat_id === "number")
|
|
129
|
+
return `chat:${payload.chat_id}`;
|
|
130
|
+
if (payload.chat_guid)
|
|
131
|
+
return `chat_guid:${payload.chat_guid}`;
|
|
132
|
+
if (payload.chat_identifier)
|
|
133
|
+
return `chat_identifier:${payload.chat_identifier}`;
|
|
134
|
+
return (payload.sender ?? "").trim();
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Normalize a parsed payload into the inbound shape. When `selfHandle` is given
|
|
138
|
+
* and this is a GROUP message naming the bot, `mentions[]` is populated so the
|
|
139
|
+
* central group requireMention gate can fire.
|
|
140
|
+
*/
|
|
141
|
+
export function normalizeIMessageMessage(payload, selfHandle) {
|
|
142
|
+
const isGroup = Boolean(payload.is_group) || typeof payload.chat_id === "number";
|
|
143
|
+
const createdAtMs = payload.created_at ? Date.parse(payload.created_at) : NaN;
|
|
144
|
+
const messageId = payload.guid?.trim() || (typeof payload.id === "number" ? String(payload.id) : undefined);
|
|
145
|
+
const out = {
|
|
146
|
+
conversationId: conversationIdFor(payload),
|
|
147
|
+
from: (payload.sender ?? "").trim(),
|
|
148
|
+
text: payload.text ?? "",
|
|
149
|
+
isGroup,
|
|
150
|
+
raw: payload,
|
|
151
|
+
};
|
|
152
|
+
if (messageId)
|
|
153
|
+
out.messageId = messageId;
|
|
154
|
+
if (typeof payload.chat_id === "number")
|
|
155
|
+
out.chatId = payload.chat_id;
|
|
156
|
+
if (payload.chat_guid)
|
|
157
|
+
out.chatGuid = payload.chat_guid;
|
|
158
|
+
if (payload.chat_identifier)
|
|
159
|
+
out.chatIdentifier = payload.chat_identifier;
|
|
160
|
+
if (payload.chat_name)
|
|
161
|
+
out.fromName = payload.chat_name;
|
|
162
|
+
if (Number.isFinite(createdAtMs))
|
|
163
|
+
out.createdAtMs = createdAtMs;
|
|
164
|
+
if (Array.isArray(payload.attachments))
|
|
165
|
+
out.attachments = payload.attachments;
|
|
166
|
+
if (payload.reply_to_id !== undefined && payload.reply_to_id !== null) {
|
|
167
|
+
out.replyTo = {
|
|
168
|
+
messageId: String(payload.reply_to_id),
|
|
169
|
+
...(payload.reply_to_text ? { body: payload.reply_to_text } : {}),
|
|
170
|
+
...(payload.reply_to_sender ? { from: payload.reply_to_sender } : {}),
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
// Self-mention detection (group gating) — only meaningful in groups.
|
|
174
|
+
if (isGroup) {
|
|
175
|
+
const mentions = detectIMessageMentions(out.text, selfHandle);
|
|
176
|
+
if (mentions)
|
|
177
|
+
out.mentions = mentions;
|
|
178
|
+
}
|
|
179
|
+
return out;
|
|
180
|
+
}
|
|
181
|
+
/* ───────────────────────── echo cache (outbound → inbound) ───────────────────────── */
|
|
182
|
+
const SENT_MESSAGE_TEXT_TTL_MS = 4_000;
|
|
183
|
+
const SENT_MESSAGE_ID_TTL_MS = 60_000;
|
|
184
|
+
function normalizeCacheText(text) {
|
|
185
|
+
if (typeof text !== "string")
|
|
186
|
+
return null;
|
|
187
|
+
const v = text.replace(/\r\n?/g, "\n").trim();
|
|
188
|
+
return v ? v : null;
|
|
189
|
+
}
|
|
190
|
+
function normalizeCacheId(id) {
|
|
191
|
+
const v = (id ?? "").trim();
|
|
192
|
+
if (!v || v === "ok" || v === "unknown")
|
|
193
|
+
return null;
|
|
194
|
+
return v;
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Remembers every outbound send so the inbound poll can drop the echo. Keyed by
|
|
198
|
+
* a per-conversation `scope`; a text match (4s) or an id match (60s) suppresses
|
|
199
|
+
* the echo. Designed to degrade to a duplicate (noisy) rather than a dropped
|
|
200
|
+
* real message if an echo arrives after the TTL.
|
|
201
|
+
*/
|
|
202
|
+
export class SentMessageCache {
|
|
203
|
+
textCache = new Map();
|
|
204
|
+
idCache = new Map();
|
|
205
|
+
textBackedById = new Map();
|
|
206
|
+
/** Record an outbound send under `scope`. */
|
|
207
|
+
remember(scope, sent) {
|
|
208
|
+
const now = Date.now();
|
|
209
|
+
const text = normalizeCacheText(sent.text);
|
|
210
|
+
const id = normalizeCacheId(sent.messageId);
|
|
211
|
+
if (text)
|
|
212
|
+
this.textCache.set(`${scope}:${text}`, now);
|
|
213
|
+
if (id)
|
|
214
|
+
this.idCache.set(`${scope}:${id}`, now);
|
|
215
|
+
if (text && id)
|
|
216
|
+
this.textBackedById.set(`${scope}:${text}`, now);
|
|
217
|
+
this.cleanup(now);
|
|
218
|
+
}
|
|
219
|
+
/** True when an inbound matches a remembered outbound (an echo). */
|
|
220
|
+
has(scope, inbound, skipIdShortCircuit = false) {
|
|
221
|
+
const now = Date.now();
|
|
222
|
+
const text = normalizeCacheText(inbound.text);
|
|
223
|
+
const id = normalizeCacheId(inbound.messageId);
|
|
224
|
+
const textKey = text ? `${scope}:${text}` : null;
|
|
225
|
+
if (id) {
|
|
226
|
+
const idTs = this.idCache.get(`${scope}:${id}`);
|
|
227
|
+
if (idTs !== undefined && now - idTs <= SENT_MESSAGE_ID_TTL_MS)
|
|
228
|
+
return true;
|
|
229
|
+
// Is there a text-only match whose latest send was NOT id-backed?
|
|
230
|
+
let hasTextOnly = false;
|
|
231
|
+
if (textKey) {
|
|
232
|
+
const textTs = this.textCache.get(textKey);
|
|
233
|
+
if (textTs !== undefined && now - textTs <= SENT_MESSAGE_TEXT_TTL_MS) {
|
|
234
|
+
const backedTs = this.textBackedById.get(textKey);
|
|
235
|
+
hasTextOnly = backedTs === undefined || textTs > backedTs;
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
if (!skipIdShortCircuit && !hasTextOnly)
|
|
239
|
+
return false;
|
|
240
|
+
}
|
|
241
|
+
if (textKey) {
|
|
242
|
+
const textTs = this.textCache.get(textKey);
|
|
243
|
+
if (textTs !== undefined && now - textTs <= SENT_MESSAGE_TEXT_TTL_MS)
|
|
244
|
+
return true;
|
|
245
|
+
}
|
|
246
|
+
return false;
|
|
247
|
+
}
|
|
248
|
+
cleanup(now) {
|
|
249
|
+
for (const [k, ts] of this.textCache)
|
|
250
|
+
if (now - ts > SENT_MESSAGE_TEXT_TTL_MS)
|
|
251
|
+
this.textCache.delete(k);
|
|
252
|
+
for (const [k, ts] of this.textBackedById)
|
|
253
|
+
if (now - ts > SENT_MESSAGE_TEXT_TTL_MS)
|
|
254
|
+
this.textBackedById.delete(k);
|
|
255
|
+
for (const [k, ts] of this.idCache)
|
|
256
|
+
if (now - ts > SENT_MESSAGE_ID_TTL_MS)
|
|
257
|
+
this.idCache.delete(k);
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
/* ───────────────────────── self-chat cache ───────────────────────── */
|
|
261
|
+
const SELF_CHAT_TTL_MS = 10_000;
|
|
262
|
+
const MAX_SELF_CHAT_CACHE_ENTRIES = 512;
|
|
263
|
+
const CLEANUP_MIN_INTERVAL_MS = 1_000;
|
|
264
|
+
/**
|
|
265
|
+
* Catches a self-chat message that arrives once as `is_from_me=true` and is then
|
|
266
|
+
* reflected as a second `is_from_me=false` row. Keyed on `scope:createdAt:hash`
|
|
267
|
+
* so it only fires when BOTH text and a timestamp anchor the same message.
|
|
268
|
+
*/
|
|
269
|
+
export class SelfChatCache {
|
|
270
|
+
cache = new Map();
|
|
271
|
+
lastCleanup = 0;
|
|
272
|
+
buildKey(scope, text, createdAtMs) {
|
|
273
|
+
const t = normalizeCacheText(text);
|
|
274
|
+
if (!t || typeof createdAtMs !== "number" || !Number.isFinite(createdAtMs))
|
|
275
|
+
return null;
|
|
276
|
+
const hash = createHash("sha256").update(t).digest("hex");
|
|
277
|
+
return `${scope}:${createdAtMs}:${hash}`;
|
|
278
|
+
}
|
|
279
|
+
remember(scope, text, createdAtMs) {
|
|
280
|
+
const key = this.buildKey(scope, text, createdAtMs);
|
|
281
|
+
if (!key)
|
|
282
|
+
return;
|
|
283
|
+
this.cache.set(key, Date.now());
|
|
284
|
+
this.maybeCleanup();
|
|
285
|
+
}
|
|
286
|
+
has(scope, text, createdAtMs) {
|
|
287
|
+
const key = this.buildKey(scope, text, createdAtMs);
|
|
288
|
+
if (!key)
|
|
289
|
+
return false;
|
|
290
|
+
const ts = this.cache.get(key);
|
|
291
|
+
return ts !== undefined && Date.now() - ts <= SELF_CHAT_TTL_MS;
|
|
292
|
+
}
|
|
293
|
+
maybeCleanup() {
|
|
294
|
+
const now = Date.now();
|
|
295
|
+
if (now - this.lastCleanup < CLEANUP_MIN_INTERVAL_MS)
|
|
296
|
+
return;
|
|
297
|
+
this.lastCleanup = now;
|
|
298
|
+
for (const [k, ts] of this.cache)
|
|
299
|
+
if (now - ts > SELF_CHAT_TTL_MS)
|
|
300
|
+
this.cache.delete(k);
|
|
301
|
+
while (this.cache.size > MAX_SELF_CHAT_CACHE_ENTRIES) {
|
|
302
|
+
const oldest = this.cache.keys().next().value;
|
|
303
|
+
if (oldest === undefined)
|
|
304
|
+
break;
|
|
305
|
+
this.cache.delete(oldest);
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
/* ───────────────────────── reflection guard ───────────────────────── */
|
|
310
|
+
const REFLECTION_PATTERNS = [
|
|
311
|
+
{ label: "internal-separator", re: /(?:#\+){2,}#?/ },
|
|
312
|
+
{ label: "assistant-role-marker", re: /\bassistant\s+to\s*=\s*\w+/i },
|
|
313
|
+
{ label: "thinking-tag", re: /<\s*\/?\s*(?:think(?:ing)?|thought|antthinking)\b[^<>]*>/i },
|
|
314
|
+
{ label: "relevant-memories-tag", re: /<\s*\/?\s*relevant[-_]memories\b[^<>]*>/i },
|
|
315
|
+
{ label: "final-tag", re: /<\s*\/?\s*final\b[^<>]*>/i },
|
|
316
|
+
];
|
|
317
|
+
/**
|
|
318
|
+
* Find the code regions (fenced ``` / ~~~ blocks + inline backtick spans) in
|
|
319
|
+
* `text`. A reflection match that falls INSIDE one of these is a legit quoted
|
|
320
|
+
* sample, not a leaked assistant marker, so the guard ignores it. Ported byte-
|
|
321
|
+
* faithfully from the upstream `findCodeRegions`.
|
|
322
|
+
*/
|
|
323
|
+
export function findCodeRegions(text) {
|
|
324
|
+
const regions = [];
|
|
325
|
+
const fencedRe = /(^|\n)(```|~~~)[^\n]*\n[\s\S]*?(?:\n\2|$)/g;
|
|
326
|
+
for (const match of text.matchAll(fencedRe)) {
|
|
327
|
+
const start = (match.index ?? 0) + (match[1]?.length ?? 0);
|
|
328
|
+
regions.push({ start, end: start + match[0].length - (match[1]?.length ?? 0) });
|
|
329
|
+
}
|
|
330
|
+
const inlineRe = /`+[^`]+`+/g;
|
|
331
|
+
for (const match of text.matchAll(inlineRe)) {
|
|
332
|
+
const start = match.index ?? 0;
|
|
333
|
+
const end = start + match[0].length;
|
|
334
|
+
const insideFenced = regions.some((r) => start >= r.start && end <= r.end);
|
|
335
|
+
if (!insideFenced)
|
|
336
|
+
regions.push({ start, end });
|
|
337
|
+
}
|
|
338
|
+
regions.sort((a, b) => a.start - b.start);
|
|
339
|
+
return regions;
|
|
340
|
+
}
|
|
341
|
+
/** True when byte-index `pos` falls inside one of the code regions. */
|
|
342
|
+
export function isInsideCode(pos, regions) {
|
|
343
|
+
return regions.some((r) => pos >= r.start && pos < r.end);
|
|
344
|
+
}
|
|
345
|
+
/** True when `re` matches `text` at a position OUTSIDE every code region. */
|
|
346
|
+
function hasMatchOutsideCode(text, re) {
|
|
347
|
+
const codeRegions = findCodeRegions(text);
|
|
348
|
+
const globalRe = new RegExp(re.source, re.flags.includes("g") ? re.flags : `${re.flags}g`);
|
|
349
|
+
for (const match of text.matchAll(globalRe)) {
|
|
350
|
+
const start = match.index ?? -1;
|
|
351
|
+
if (start >= 0 && !isInsideCode(start, codeRegions))
|
|
352
|
+
return true;
|
|
353
|
+
}
|
|
354
|
+
return false;
|
|
355
|
+
}
|
|
356
|
+
/**
|
|
357
|
+
* Detect inbound text carrying assistant-internal markers (outbound metadata
|
|
358
|
+
* that leaked into the channel and bounced back). Returns the matched labels.
|
|
359
|
+
*
|
|
360
|
+
* A marker that appears INSIDE a fenced/inline code span is a legitimately
|
|
361
|
+
* quoted code sample (e.g. someone pasting `<final>` inside a ``` fence) and is
|
|
362
|
+
* NOT treated as a reflection — only matches OUTSIDE code count.
|
|
363
|
+
*/
|
|
364
|
+
export function detectReflectedContent(text) {
|
|
365
|
+
const src = text ?? "";
|
|
366
|
+
if (!src.trim())
|
|
367
|
+
return { isReflection: false, matchedLabels: [] };
|
|
368
|
+
const matchedLabels = [];
|
|
369
|
+
for (const { label, re } of REFLECTION_PATTERNS) {
|
|
370
|
+
if (hasMatchOutsideCode(src, re))
|
|
371
|
+
matchedLabels.push(label);
|
|
372
|
+
}
|
|
373
|
+
return { isReflection: matchedLabels.length > 0, matchedLabels };
|
|
374
|
+
}
|
|
375
|
+
/* ───────────────────────── loop rate limiter ───────────────────────── */
|
|
376
|
+
const LOOP_WINDOW_MS = 60_000;
|
|
377
|
+
const LOOP_MAX_HITS = 5;
|
|
378
|
+
const LOOP_CLEANUP_INTERVAL_MS = 120_000;
|
|
379
|
+
/**
|
|
380
|
+
* Per-conversation sliding-window counter. After {@link LOOP_MAX_HITS} loop
|
|
381
|
+
* drops within {@link LOOP_WINDOW_MS}, the conversation is rate-limited (muted)
|
|
382
|
+
* — the runaway-loop safety net.
|
|
383
|
+
*/
|
|
384
|
+
export class LoopRateLimiter {
|
|
385
|
+
hits = new Map();
|
|
386
|
+
lastCleanup = 0;
|
|
387
|
+
record(key) {
|
|
388
|
+
const arr = this.hits.get(key) ?? [];
|
|
389
|
+
arr.push(Date.now());
|
|
390
|
+
this.hits.set(key, arr);
|
|
391
|
+
this.cleanup();
|
|
392
|
+
}
|
|
393
|
+
isRateLimited(key) {
|
|
394
|
+
const now = Date.now();
|
|
395
|
+
const recent = (this.hits.get(key) ?? []).filter((ts) => now - ts <= LOOP_WINDOW_MS);
|
|
396
|
+
this.hits.set(key, recent);
|
|
397
|
+
return recent.length >= LOOP_MAX_HITS;
|
|
398
|
+
}
|
|
399
|
+
cleanup() {
|
|
400
|
+
const now = Date.now();
|
|
401
|
+
if (now - this.lastCleanup < LOOP_CLEANUP_INTERVAL_MS)
|
|
402
|
+
return;
|
|
403
|
+
this.lastCleanup = now;
|
|
404
|
+
for (const [k, arr] of this.hits) {
|
|
405
|
+
const recent = arr.filter((ts) => now - ts <= LOOP_WINDOW_MS);
|
|
406
|
+
if (recent.length === 0)
|
|
407
|
+
this.hits.delete(k);
|
|
408
|
+
else
|
|
409
|
+
this.hits.set(k, recent);
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
/** Build a fresh monitor state. */
|
|
414
|
+
export function createMonitorState() {
|
|
415
|
+
return {
|
|
416
|
+
sentMessageCache: new SentMessageCache(),
|
|
417
|
+
selfChatCache: new SelfChatCache(),
|
|
418
|
+
loopRateLimiter: new LoopRateLimiter(),
|
|
419
|
+
};
|
|
420
|
+
}
|
|
421
|
+
/** Build the echo/rate-limit scope for a payload. */
|
|
422
|
+
export function echoScope(accountId, payload) {
|
|
423
|
+
if (typeof payload.chat_id === "number")
|
|
424
|
+
return `${accountId}:chat_id:${payload.chat_id}`;
|
|
425
|
+
return `${accountId}:imessage:${(payload.sender ?? "").trim()}`;
|
|
426
|
+
}
|
|
427
|
+
/**
|
|
428
|
+
* The gating brain: parse → normalize → self-echo / self-chat / reflection
|
|
429
|
+
* dedupe → loop rate-limit. Pure given the (mutable) {@link MonitorState}.
|
|
430
|
+
* Loop-related drops feed the rate limiter; a rate-limited conversation drops a
|
|
431
|
+
* dispatch before it fires.
|
|
432
|
+
*/
|
|
433
|
+
export function decideInbound(state, accountId, payload, selfHandle) {
|
|
434
|
+
const sender = (payload.sender ?? "").trim();
|
|
435
|
+
if (!sender && typeof payload.chat_id !== "number")
|
|
436
|
+
return { kind: "drop", reason: "missing sender" };
|
|
437
|
+
const scope = echoScope(accountId, payload);
|
|
438
|
+
const rateKey = typeof payload.chat_id === "number" ? `${accountId}:group:${payload.chat_id}` : `${accountId}:dm:${sender}`;
|
|
439
|
+
const text = payload.text ?? "";
|
|
440
|
+
const inboundIds = [
|
|
441
|
+
...(typeof payload.id === "number" ? [String(payload.id)] : []),
|
|
442
|
+
...(payload.guid ? [payload.guid] : []),
|
|
443
|
+
];
|
|
444
|
+
const hasGuid = Boolean(payload.guid);
|
|
445
|
+
// Self-chat detection (DM only).
|
|
446
|
+
const senderNorm = sender.toLowerCase();
|
|
447
|
+
const chatIdentNorm = (payload.chat_identifier ?? "").trim().toLowerCase();
|
|
448
|
+
const destNorm = (payload.destination_caller_id ?? "").trim().toLowerCase();
|
|
449
|
+
const isSelfChat = !payload.is_group && senderNorm !== "" && senderNorm === chatIdentNorm && destNorm === senderNorm;
|
|
450
|
+
const isAmbiguousSelf = !payload.is_group && senderNorm !== "" && senderNorm === chatIdentNorm && destNorm === "";
|
|
451
|
+
let skipSelfChatHasCheck = false;
|
|
452
|
+
if (payload.is_from_me === true) {
|
|
453
|
+
if (isAmbiguousSelf) {
|
|
454
|
+
state.selfChatCache.remember(scope, text, payload.created_at ? Date.parse(payload.created_at) : undefined);
|
|
455
|
+
state.loopRateLimiter.record(rateKey);
|
|
456
|
+
return { kind: "drop", reason: "from me" };
|
|
457
|
+
}
|
|
458
|
+
if (isSelfChat) {
|
|
459
|
+
state.selfChatCache.remember(scope, text, payload.created_at ? Date.parse(payload.created_at) : undefined);
|
|
460
|
+
const echo = state.sentMessageCache.has(scope, { text, messageId: inboundIds[0] }, !hasGuid);
|
|
461
|
+
if (echo) {
|
|
462
|
+
state.loopRateLimiter.record(rateKey);
|
|
463
|
+
return { kind: "drop", reason: "agent echo in self-chat" };
|
|
464
|
+
}
|
|
465
|
+
skipSelfChatHasCheck = true;
|
|
466
|
+
}
|
|
467
|
+
else {
|
|
468
|
+
state.loopRateLimiter.record(rateKey);
|
|
469
|
+
return { kind: "drop", reason: "from me" };
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
if (payload.is_group && typeof payload.chat_id !== "number") {
|
|
473
|
+
return { kind: "drop", reason: "group without chat_id" };
|
|
474
|
+
}
|
|
475
|
+
if (!text.trim() && !(Array.isArray(payload.attachments) && payload.attachments.length > 0)) {
|
|
476
|
+
return { kind: "drop", reason: "empty body" };
|
|
477
|
+
}
|
|
478
|
+
// Self-chat reflection check.
|
|
479
|
+
if (!skipSelfChatHasCheck) {
|
|
480
|
+
const createdAtMs = payload.created_at ? Date.parse(payload.created_at) : undefined;
|
|
481
|
+
if (state.selfChatCache.has(scope, text, createdAtMs)) {
|
|
482
|
+
state.loopRateLimiter.record(rateKey);
|
|
483
|
+
return { kind: "drop", reason: "self-chat echo" };
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
// General echo check.
|
|
487
|
+
const echoMatch = inboundIds.some((id) => state.sentMessageCache.has(scope, { messageId: id })) ||
|
|
488
|
+
state.sentMessageCache.has(scope, { text, messageId: inboundIds[0] }, !hasGuid);
|
|
489
|
+
if (echoMatch) {
|
|
490
|
+
state.loopRateLimiter.record(rateKey);
|
|
491
|
+
return { kind: "drop", reason: "echo" };
|
|
492
|
+
}
|
|
493
|
+
// Reflection guard.
|
|
494
|
+
if (detectReflectedContent(text).isReflection) {
|
|
495
|
+
state.loopRateLimiter.record(rateKey);
|
|
496
|
+
return { kind: "drop", reason: "reflected assistant content" };
|
|
497
|
+
}
|
|
498
|
+
// Loop rate-limit safety net.
|
|
499
|
+
if (state.loopRateLimiter.isRateLimited(rateKey)) {
|
|
500
|
+
return { kind: "drop", reason: "loop rate-limited" };
|
|
501
|
+
}
|
|
502
|
+
return { kind: "dispatch", message: normalizeIMessageMessage(payload, selfHandle) };
|
|
503
|
+
}
|
|
504
|
+
//# sourceMappingURL=monitor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"monitor.js","sourceRoot":"","sources":["../../../../src/agents/channels/imessage/monitor.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* iMessage `ChannelPlugin` — the multi-ACCOUNT contract surface.
|
|
3
|
+
*
|
|
4
|
+
* Mirrors `discord/plugin.ts`: wraps `createIMessageAdapter()` (the
|
|
5
|
+
* per-connection implementation) with the lifecycle adapters the
|
|
6
|
+
* `ChannelPluginManager` consumes, so an operator can run MORE THAN ONE iMessage
|
|
7
|
+
* bridge at once (e.g. two Macs / two chat.db files) via:
|
|
8
|
+
*
|
|
9
|
+
* channels.imessage = {
|
|
10
|
+
* enabled: true,
|
|
11
|
+
* accounts: [
|
|
12
|
+
* { id: "personal", dbPath: "~/Library/Messages/chat.db" },
|
|
13
|
+
* { id: "work", cliPath: "/opt/imsg/bin/imsg" },
|
|
14
|
+
* ],
|
|
15
|
+
* }
|
|
16
|
+
*
|
|
17
|
+
* Per-account state lives in a `Map<accountId, AccountRuntime>` in this closure —
|
|
18
|
+
* one `imsg rpc` subprocess per account. Inbound dispatch reuses the shared
|
|
19
|
+
* `runChannelInboundPipeline` so the multi-account path carries the identical
|
|
20
|
+
* ACL + debounce + abort surface as the legacy single-adapter manager.
|
|
21
|
+
*
|
|
22
|
+
* The legacy single-account `createIMessageAdapter` STEPS ASIDE when >1 account
|
|
23
|
+
* is configured (its `isConfigured` returns false for the default account), so
|
|
24
|
+
* the two paths never double-start a subprocess. iMessage has no inbound HTTP
|
|
25
|
+
* route (the `imsg rpc` notification stream is the only inbound transport).
|
|
26
|
+
*/
|
|
27
|
+
import type { BrigadeConfig } from "../../../config/types.js";
|
|
28
|
+
import { type ChannelAdapter, type ChannelOutboundTarget, type ChannelPlugin, type StartChannelsArgs } from "../sdk.js";
|
|
29
|
+
import { type ResolvedIMessageAccount } from "./account-config.js";
|
|
30
|
+
import { type IMessageProbeResult } from "./probe.js";
|
|
31
|
+
/** Dependencies the gateway hands the plugin to drive turns + replies. */
|
|
32
|
+
export interface IMessagePluginDeps {
|
|
33
|
+
defaultAgentId: string;
|
|
34
|
+
loadConfig: () => BrigadeConfig;
|
|
35
|
+
runTurn: StartChannelsArgs["runTurn"];
|
|
36
|
+
/** Optional adapter factory — tests inject a fake; production uses `createIMessageAdapter`. */
|
|
37
|
+
adapterFactory?: (args: {
|
|
38
|
+
accountId: string;
|
|
39
|
+
}) => ChannelAdapter;
|
|
40
|
+
}
|
|
41
|
+
/** Operator-grade view of a per-account bridge — exposed via attached helpers. */
|
|
42
|
+
export interface IMessagePluginRuntimeView {
|
|
43
|
+
startedAccountIds(): string[];
|
|
44
|
+
getAdapter(accountId: string): ChannelAdapter | undefined;
|
|
45
|
+
probeAccount(accountId: string, cfg: BrigadeConfig): Promise<IMessageProbeResult>;
|
|
46
|
+
}
|
|
47
|
+
/** Plugin handle with the extra per-account introspection surface attached. */
|
|
48
|
+
export type IMessagePluginHandle = ChannelPlugin<ResolvedIMessageAccount> & IMessagePluginRuntimeView;
|
|
49
|
+
/** Construct the plugin instance, capturing per-account runtime state in closure. */
|
|
50
|
+
export declare function createIMessagePlugin(deps: IMessagePluginDeps): IMessagePluginHandle;
|
|
51
|
+
/** Outbound dispatch helper for callers reaching the plugin directly. */
|
|
52
|
+
export type IMessageOutboundTarget = ChannelOutboundTarget;
|
|
53
|
+
//# sourceMappingURL=plugin.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../../../../src/agents/channels/imessage/plugin.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAG9D,OAAO,EAKN,KAAK,cAAc,EAKnB,KAAK,qBAAqB,EAC1B,KAAK,aAAa,EAKlB,KAAK,iBAAiB,EAEtB,MAAM,WAAW,CAAC;AACnB,OAAO,EASN,KAAK,uBAAuB,EAC5B,MAAM,qBAAqB,CAAC;AAG7B,OAAO,EAAiB,KAAK,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAarE,0EAA0E;AAC1E,MAAM,WAAW,kBAAkB;IAClC,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,MAAM,aAAa,CAAC;IAChC,OAAO,EAAE,iBAAiB,CAAC,SAAS,CAAC,CAAC;IACtC,+FAA+F;IAC/F,cAAc,CAAC,EAAE,CAAC,IAAI,EAAE;QAAE,SAAS,EAAE,MAAM,CAAA;KAAE,KAAK,cAAc,CAAC;CACjE;AAED,kFAAkF;AAClF,MAAM,WAAW,yBAAyB;IACzC,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,mBAAmB,CAAC,CAAC;CAClF;AAED,+EAA+E;AAC/E,MAAM,MAAM,oBAAoB,GAAG,aAAa,CAAC,uBAAuB,CAAC,GAAG,yBAAyB,CAAC;AAEtG,qFAAqF;AACrF,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,kBAAkB,GAAG,oBAAoB,CAsKnF;AAOD,yEAAyE;AACzE,MAAM,MAAM,sBAAsB,GAAG,qBAAqB,CAAC"}
|