@poolzin/pool-bot 2026.2.21 → 2026.2.23
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/CHANGELOG.md +25 -0
- package/dist/agents/api-key-rotation.js +47 -0
- package/dist/agents/apply-patch-update.js +19 -9
- package/dist/agents/apply-patch.js +72 -47
- package/dist/agents/bash-tools.exec.js +141 -559
- package/dist/agents/cli-backends.js +49 -6
- package/dist/agents/cli-runner/helpers.js +69 -152
- package/dist/agents/cli-runner.js +70 -19
- package/dist/agents/identity.js +20 -1
- package/dist/agents/image-sanitization.js +9 -0
- package/dist/agents/live-auth-keys.js +123 -26
- package/dist/agents/live-model-filter.js +13 -4
- package/dist/agents/model-catalog.js +40 -9
- package/dist/agents/model-forward-compat.js +60 -23
- package/dist/agents/model-selection.js +134 -41
- package/dist/agents/pi-auth-json.js +2 -2
- package/dist/agents/pi-embedded-helpers/bootstrap.js +65 -15
- package/dist/agents/pi-embedded-helpers/errors.js +140 -15
- package/dist/agents/pi-embedded-helpers/images.js +22 -12
- package/dist/agents/pi-embedded-helpers.js +2 -2
- package/dist/agents/pi-embedded-runner/abort.js +10 -3
- package/dist/agents/pi-embedded-runner/compact.js +230 -32
- package/dist/agents/pi-embedded-runner/extra-params.js +203 -12
- package/dist/agents/pi-embedded-runner/google.js +109 -19
- package/dist/agents/pi-embedded-runner/history.js +35 -17
- package/dist/agents/pi-embedded-runner/run/attempt.js +386 -95
- package/dist/agents/pi-embedded-runner/run/images.js +81 -55
- package/dist/agents/pi-embedded-runner/run/payloads.js +89 -39
- package/dist/agents/pi-embedded-runner/run.js +193 -25
- package/dist/agents/pi-embedded-runner/run.overflow-compaction.mocks.shared.js +2 -2
- package/dist/agents/pi-embedded-runner/runs.js +17 -8
- package/dist/agents/pi-embedded-runner/tool-result-context-guard.js +262 -0
- package/dist/agents/pi-embedded-runner.js +1 -1
- package/dist/agents/pi-embedded-subscribe.handlers.tools.js +180 -10
- package/dist/agents/pi-embedded-subscribe.js +37 -0
- package/dist/agents/pi-embedded-subscribe.tools.js +127 -30
- package/dist/agents/pi-model-discovery.js +9 -2
- package/dist/agents/pi-tool-definition-adapter.js +60 -8
- package/dist/agents/pi-tools.before-tool-call.js +1 -1
- package/dist/agents/pi-tools.js +113 -94
- package/dist/agents/pi-tools.read.js +337 -38
- package/dist/agents/poolbot-tools.js +14 -5
- package/dist/agents/sandbox/docker.js +10 -5
- package/dist/agents/sandbox/registry.js +96 -46
- package/dist/agents/sandbox/sanitize-env-vars.js +82 -0
- package/dist/agents/sandbox-paths.js +43 -10
- package/dist/agents/session-tool-result-guard-wrapper.js +23 -11
- package/dist/agents/session-tool-result-guard.js +39 -39
- package/dist/agents/session-transcript-repair.js +36 -33
- package/dist/agents/session-write-lock.js +62 -44
- package/dist/agents/skills/frontmatter.js +49 -88
- package/dist/agents/skills/workspace.js +335 -28
- package/dist/agents/subagent-announce.js +508 -174
- package/dist/agents/subagent-registry.js +45 -4
- package/dist/agents/subagent-spawn.js +16 -33
- package/dist/agents/system-prompt-report.js +27 -10
- package/dist/agents/system-prompt.js +26 -32
- package/dist/agents/tool-call-id.js +69 -17
- package/dist/agents/tool-display-common.js +1 -1
- package/dist/agents/tool-images.js +64 -31
- package/dist/agents/tools/canvas-tool.js +17 -11
- package/dist/agents/tools/common.js +37 -19
- package/dist/agents/tools/cron-tool.js +40 -38
- package/dist/agents/tools/gateway.js +70 -2
- package/dist/agents/tools/message-tool.js +181 -40
- package/dist/agents/tools/nodes-tool.js +128 -36
- package/dist/agents/tools/nodes-utils.js +12 -38
- package/dist/agents/tools/session-status-tool.js +24 -71
- package/dist/agents/tools/sessions-helpers.js +38 -210
- package/dist/agents/tools/sessions-spawn-tool.js +28 -198
- package/dist/agents/tools/telegram-actions.js +58 -7
- package/dist/agents/tools/web-fetch-utils.js +112 -7
- package/dist/agents/tools/web-fetch.js +279 -175
- package/dist/agents/tools/web-shared.js +71 -8
- package/dist/agents/usage.js +25 -16
- package/dist/auto-reply/commands-registry.data.js +85 -11
- package/dist/auto-reply/dispatch.js +40 -21
- package/dist/auto-reply/reply/abort.js +102 -33
- package/dist/auto-reply/reply/commands-core.js +82 -33
- package/dist/auto-reply/reply/commands-export-session.js +1 -1
- package/dist/auto-reply/reply/commands-info.js +41 -12
- package/dist/auto-reply/reply/commands-subagents.js +352 -100
- package/dist/auto-reply/reply/commands-system-prompt.js +2 -2
- package/dist/auto-reply/reply/dispatch-from-config.js +100 -29
- package/dist/auto-reply/reply/elevated-unavailable.js +1 -1
- package/dist/auto-reply/reply/inbound-meta.js +12 -1
- package/dist/auto-reply/reply/mentions.js +18 -11
- package/dist/auto-reply/reply/normalize-reply.js +17 -8
- package/dist/auto-reply/reply/reply-dispatcher.js +62 -10
- package/dist/auto-reply/reply/session.js +102 -21
- package/dist/auto-reply/reply/streaming-directives.js +16 -5
- package/dist/auto-reply/status.js +73 -50
- package/dist/browser/extension-relay.js +3 -3
- package/dist/browser/http-auth.js +1 -1
- package/dist/browser/paths.js +2 -2
- package/dist/build-info.json +3 -3
- package/dist/channels/allowlist-match.js +20 -0
- package/dist/channels/allowlists/resolve-utils.js +65 -2
- package/dist/channels/chat-type.js +8 -4
- package/dist/channels/dock.js +127 -35
- package/dist/channels/draft-stream-loop.js +6 -2
- package/dist/channels/plugins/actions/telegram.js +42 -18
- package/dist/channels/plugins/allowlist-match.js +1 -1
- package/dist/channels/plugins/group-mentions.js +51 -41
- package/dist/channels/plugins/message-action-names.js +2 -0
- package/dist/channels/plugins/message-actions.js +24 -5
- package/dist/channels/plugins/normalize/discord.js +26 -4
- package/dist/channels/plugins/normalize/signal.js +35 -22
- package/dist/channels/plugins/onboarding/helpers.js +8 -26
- package/dist/channels/plugins/outbound/imessage.js +15 -14
- package/dist/channels/registry.js +20 -7
- package/dist/cli/acp-cli.js +7 -5
- package/dist/cli/browser-cli-extension.js +25 -12
- package/dist/cli/browser-cli-state.cookies-storage.js +25 -6
- package/dist/cli/browser-cli-state.js +101 -145
- package/dist/cli/command-options.js +28 -0
- package/dist/cli/completion-cli.js +6 -6
- package/dist/cli/cron-cli/register.cron-add.js +25 -1
- package/dist/cli/cron-cli/register.cron-edit.js +44 -0
- package/dist/cli/cron-cli/shared.js +7 -1
- package/dist/cli/daemon-cli/lifecycle-core.js +23 -21
- package/dist/cli/daemon-cli/lifecycle.js +23 -247
- package/dist/cli/daemon-cli/register-service-commands.js +25 -4
- package/dist/cli/daemon-cli.js +1 -0
- package/dist/cli/devices-cli.js +33 -20
- package/dist/cli/gateway-cli/register.js +37 -105
- package/dist/cli/gateway-cli/run.js +49 -11
- package/dist/cli/nodes-camera.js +59 -4
- package/dist/cli/nodes-cli/register.camera.js +27 -24
- package/dist/cli/nodes-cli/rpc.js +21 -38
- package/dist/cli/qr-cli.js +2 -2
- package/dist/cli/skills-cli.format.js +2 -2
- package/dist/cli/update-cli/progress.js +2 -2
- package/dist/cli/update-cli/restart-helper.js +28 -7
- package/dist/cli/update-cli/shared.js +7 -7
- package/dist/cli/update-cli/status.js +1 -1
- package/dist/cli/update-cli/update-command.js +14 -8
- package/dist/cli/update-cli/wizard.js +2 -2
- package/dist/cli/update-cli.js +21 -1027
- package/dist/commands/auth-choice.apply.anthropic.js +10 -2
- package/dist/commands/channels/add-mutators.js +3 -35
- package/dist/commands/channels/add.js +39 -51
- package/dist/commands/config-validation.js +1 -1
- package/dist/commands/configure.gateway-auth.js +52 -15
- package/dist/commands/configure.gateway.js +84 -40
- package/dist/commands/doctor-completion.js +3 -3
- package/dist/commands/doctor-config-flow.js +536 -16
- package/dist/commands/doctor-gateway-services.js +103 -79
- package/dist/commands/doctor-memory-search.js +9 -9
- package/dist/commands/doctor-platform-notes.js +57 -30
- package/dist/commands/doctor-prompter.js +26 -15
- package/dist/commands/doctor-session-locks.js +1 -1
- package/dist/commands/doctor.js +21 -9
- package/dist/commands/model-picker.js +120 -95
- package/dist/commands/models/set.js +2 -21
- package/dist/commands/models/shared.js +65 -37
- package/dist/commands/onboard-helpers.js +81 -39
- package/dist/commands/openai-codex-oauth.js +1 -1
- package/dist/commands/sessions.js +52 -53
- package/dist/commands/status.summary.js +52 -34
- package/dist/commands/test-wizard-helpers.js +2 -2
- package/dist/config/defaults.js +79 -42
- package/dist/config/group-policy.js +50 -18
- package/dist/config/includes.js +37 -10
- package/dist/config/schema.help.js +5 -4
- package/dist/config/schema.hints.js +2 -2
- package/dist/config/schema.labels.js +1 -0
- package/dist/config/sessions/group.js +12 -11
- package/dist/config/sessions/paths.js +137 -11
- package/dist/config/sessions/store.js +185 -65
- package/dist/config/sessions/types.js +15 -1
- package/dist/config/sessions.js +1 -0
- package/dist/config/telegram-custom-commands.js +3 -2
- package/dist/config/types.js +2 -0
- package/dist/config/zod-schema.agent-defaults.js +6 -27
- package/dist/config/zod-schema.agent-runtime.js +171 -79
- package/dist/config/zod-schema.providers-core.js +138 -65
- package/dist/config/zod-schema.session.js +49 -22
- package/dist/control-ui/assets/index-HRr1grwl.js.map +1 -1
- package/dist/cron/isolated-agent/run.js +224 -57
- package/dist/cron/normalize.js +48 -45
- package/dist/cron/run-log.js +14 -0
- package/dist/cron/service/jobs.js +190 -28
- package/dist/cron/service/normalize.js +29 -11
- package/dist/cron/service/store.js +30 -44
- package/dist/cron/service/timer.js +182 -96
- package/dist/cron/service.js +3 -0
- package/dist/cron/stagger.js +37 -0
- package/dist/daemon/inspect.js +132 -92
- package/dist/daemon/runtime-paths.js +25 -4
- package/dist/daemon/service-audit.js +47 -16
- package/dist/discord/accounts.js +23 -20
- package/dist/discord/monitor/agent-components.js +1115 -219
- package/dist/discord/monitor/allow-list.js +114 -34
- package/dist/discord/monitor/listeners.js +204 -97
- package/dist/discord/monitor/message-handler.js +21 -10
- package/dist/discord/monitor/message-handler.preflight.js +195 -101
- package/dist/discord/monitor/message-handler.process.js +384 -123
- package/dist/discord/monitor/message-utils.js +86 -23
- package/dist/discord/monitor/native-command.js +77 -57
- package/dist/discord/monitor/provider.js +122 -117
- package/dist/discord/monitor/reply-context.js +20 -16
- package/dist/discord/monitor/reply-delivery.js +40 -8
- package/dist/discord/monitor/rest-fetch.js +22 -0
- package/dist/discord/monitor/threading.js +117 -24
- package/dist/discord/send.js +2 -1
- package/dist/discord/send.outbound.js +124 -11
- package/dist/discord/send.shared.js +112 -72
- package/dist/discord/voice-message.js +3 -3
- package/dist/gateway/auth.js +119 -44
- package/dist/gateway/call.js +76 -34
- package/dist/gateway/channel-health-monitor.js +57 -50
- package/dist/gateway/client.js +63 -29
- package/dist/gateway/control-ui-contract.js +1 -1
- package/dist/gateway/gateway-config-prompts.shared.js +2 -2
- package/dist/gateway/net.js +109 -1
- package/dist/gateway/protocol/index.js +5 -8
- package/dist/gateway/protocol/schema/agent.js +19 -1
- package/dist/gateway/protocol/schema/channels.js +21 -0
- package/dist/gateway/protocol/schema/cron.js +43 -30
- package/dist/gateway/protocol/schema/protocol-schemas.js +6 -11
- package/dist/gateway/protocol/schema/sessions.js +5 -1
- package/dist/gateway/protocol/schema.js +0 -1
- package/dist/gateway/server/presence-events.js +12 -0
- package/dist/gateway/server/ws-connection/message-handler.js +203 -212
- package/dist/gateway/server/ws-connection.js +58 -21
- package/dist/gateway/server-broadcast.js +18 -13
- package/dist/gateway/server-cron.js +177 -10
- package/dist/gateway/server-methods/agent-job.js +131 -38
- package/dist/gateway/server-methods/send.js +60 -14
- package/dist/gateway/server-methods/sessions.js +160 -96
- package/dist/gateway/server-methods/system.js +5 -7
- package/dist/gateway/server-methods-list.js +8 -0
- package/dist/gateway/server-methods.js +24 -8
- package/dist/gateway/server-node-events.js +278 -68
- package/dist/gateway/session-utils.fs.js +316 -75
- package/dist/gateway/session-utils.js +224 -70
- package/dist/gateway/sessions-patch.js +63 -20
- package/dist/gateway/test-temp-config.js +1 -1
- package/dist/gateway/tools-invoke-http.js +118 -70
- package/dist/gateway/ws-log.js +135 -107
- package/dist/hooks/frontmatter.js +36 -82
- package/dist/hooks/install.js +149 -139
- package/dist/hooks/internal-hooks.js +29 -4
- package/dist/hooks/plugin-hooks.js +2 -1
- package/dist/imessage/monitor/deliver.js +10 -4
- package/dist/imessage/monitor/monitor-provider.js +138 -375
- package/dist/imessage/monitor/runtime.js +4 -8
- package/dist/imessage/send.js +65 -19
- package/dist/infra/exec-approvals-allowlist.js +7 -0
- package/dist/infra/exec-approvals.js +35 -920
- package/dist/infra/exec-safe-bin-trust.js +64 -0
- package/dist/infra/heartbeat-runner.js +207 -134
- package/dist/infra/heartbeat-wake.js +183 -22
- package/dist/infra/install-source-utils.js +47 -0
- package/dist/infra/net/ssrf.js +170 -36
- package/dist/infra/outbound/deliver.js +224 -58
- package/dist/infra/outbound/message-action-spec.js +12 -5
- package/dist/infra/outbound/outbound-session.js +27 -25
- package/dist/infra/poolbot-root.js +32 -22
- package/dist/infra/ports.js +14 -11
- package/dist/infra/skills-remote.js +48 -37
- package/dist/infra/system-events.js +25 -11
- package/dist/infra/system-presence.js +26 -33
- package/dist/infra/tmp-poolbot-dir.js +81 -2
- package/dist/infra/wsl.js +37 -1
- package/dist/line/bot-message-context.js +163 -191
- package/dist/logging/subsystem.js +59 -22
- package/dist/markdown/ir.js +124 -50
- package/dist/media/store.js +1 -1
- package/dist/media-understanding/runner.entries.js +42 -25
- package/dist/media-understanding/runner.js +53 -488
- package/dist/memory/embeddings-gemini.js +53 -38
- package/dist/memory/manager-embedding-ops.js +48 -69
- package/dist/pairing/pairing-store.js +178 -119
- package/dist/plugin-sdk/index.js +34 -6
- package/dist/plugins/hooks.js +135 -14
- package/dist/plugins/install.js +190 -152
- package/dist/polls.js +11 -0
- package/dist/routing/resolve-route.js +190 -56
- package/dist/routing/session-key.js +38 -22
- package/dist/runtime.js +35 -9
- package/dist/security/audit-channel.js +1 -1
- package/dist/sessions/session-key-utils.js +29 -11
- package/dist/shared/frontmatter.js +5 -5
- package/dist/shared/node-list-types.js +1 -0
- package/dist/shared/string-normalization.js +15 -0
- package/dist/signal/monitor/event-handler.js +68 -36
- package/dist/signal/send.js +29 -37
- package/dist/slack/monitor/allow-list.js +10 -11
- package/dist/slack/monitor/commands.js +14 -3
- package/dist/slack/monitor/events/interactions.js +4 -4
- package/dist/slack/monitor/media.js +224 -16
- package/dist/slack/monitor/message-handler/dispatch.js +247 -13
- package/dist/slack/monitor/message-handler/prepare.js +128 -45
- package/dist/slack/monitor/slash.js +357 -144
- package/dist/slack/streaming.js +77 -0
- package/dist/telegram/accounts.js +40 -13
- package/dist/telegram/allowed-updates.js +3 -0
- package/dist/telegram/bot/delivery.js +129 -66
- package/dist/telegram/bot/helpers.js +136 -122
- package/dist/telegram/bot-handlers.js +600 -339
- package/dist/telegram/bot-message-context.js +115 -73
- package/dist/telegram/bot-message-dispatch.js +235 -104
- package/dist/telegram/bot-native-command-menu.js +3 -1
- package/dist/telegram/bot-native-commands.js +213 -193
- package/dist/telegram/bot.js +24 -132
- package/dist/telegram/draft-stream.js +84 -75
- package/dist/telegram/format.js +150 -6
- package/dist/telegram/send.js +415 -255
- package/dist/telegram/targets.js +21 -2
- package/dist/telegram/update-offset-store.js +19 -3
- package/dist/terminal/restore.js +5 -2
- package/dist/test-utils/fetch-mock.js +5 -0
- package/dist/version.js +18 -5
- package/dist/web/auto-reply/monitor/broadcast.js +7 -3
- package/dist/web/auto-reply/monitor/on-message.js +6 -3
- package/dist/web/inbound/media.js +34 -8
- package/dist/web/inbound/monitor.js +34 -17
- package/dist/web/inbound/send-api.js +18 -17
- package/dist/web/outbound.js +12 -5
- package/dist/wizard/clack-prompter.js +40 -7
- package/extensions/bluebubbles/package.json +1 -1
- package/extensions/copilot-proxy/package.json +1 -1
- package/extensions/device-pair/index.ts +2 -2
- package/extensions/diagnostics-otel/package.json +1 -1
- package/extensions/discord/package.json +1 -1
- package/extensions/feishu/package.json +1 -1
- package/extensions/google-antigravity-auth/package.json +1 -1
- package/extensions/google-gemini-cli-auth/package.json +1 -1
- package/extensions/googlechat/package.json +1 -1
- package/extensions/imessage/package.json +1 -1
- package/extensions/irc/package.json +1 -1
- package/extensions/irc/src/accounts.ts +1 -1
- package/extensions/irc/src/onboarding.ts +4 -4
- package/extensions/line/package.json +1 -1
- package/extensions/llm-task/package.json +1 -1
- package/extensions/lobster/package.json +1 -1
- package/extensions/matrix/CHANGELOG.md +10 -0
- package/extensions/matrix/package.json +1 -1
- package/extensions/mattermost/package.json +1 -1
- package/extensions/memory-core/package.json +1 -1
- package/extensions/memory-lancedb/package.json +1 -1
- package/extensions/minimax-portal-auth/package.json +1 -1
- package/extensions/msteams/CHANGELOG.md +10 -0
- package/extensions/msteams/package.json +1 -1
- package/extensions/nextcloud-talk/package.json +1 -1
- package/extensions/nostr/CHANGELOG.md +10 -0
- package/extensions/nostr/package.json +1 -1
- package/extensions/open-prose/package.json +1 -1
- package/extensions/openai-codex-auth/package.json +1 -1
- package/extensions/signal/package.json +1 -1
- package/extensions/slack/package.json +1 -1
- package/extensions/telegram/package.json +1 -1
- package/extensions/tlon/package.json +1 -1
- package/extensions/twitch/CHANGELOG.md +10 -0
- package/extensions/twitch/package.json +1 -1
- package/extensions/voice-call/CHANGELOG.md +10 -0
- package/extensions/voice-call/package.json +1 -1
- package/extensions/whatsapp/package.json +1 -1
- package/extensions/zalo/CHANGELOG.md +10 -0
- package/extensions/zalo/package.json +1 -1
- package/extensions/zalouser/CHANGELOG.md +10 -0
- package/extensions/zalouser/package.json +1 -1
- package/package.json +1 -1
- package/skills/apple-reminders/SKILL.md +100 -49
- package/skills/coding-agent/SKILL.md +34 -28
- package/skills/github/SKILL.md +131 -16
- package/skills/imsg/SKILL.md +112 -15
- package/skills/openhue/SKILL.md +101 -19
- package/skills/tmux/SKILL.md +111 -79
- package/skills/weather/SKILL.md +88 -25
- package/dist/agents/openclaw-tools.js +0 -151
- package/dist/agents/tool-security.js +0 -96
- package/dist/gateway/url-validation.js +0 -94
- package/dist/infra/openclaw-root.js +0 -109
- package/dist/infra/tmp-openclaw-dir.js +0 -81
- package/dist/media/path-sanitization.js +0 -78
|
@@ -3,7 +3,7 @@ import { createInboundDebouncer, resolveInboundDebounceMs, } from "../../auto-re
|
|
|
3
3
|
import { danger } from "../../globals.js";
|
|
4
4
|
import { preflightDiscordMessage } from "./message-handler.preflight.js";
|
|
5
5
|
import { processDiscordMessage } from "./message-handler.process.js";
|
|
6
|
-
import { resolveDiscordMessageText } from "./message-utils.js";
|
|
6
|
+
import { resolveDiscordMessageChannelId, resolveDiscordMessageText } from "./message-utils.js";
|
|
7
7
|
export function createDiscordMessageHandler(params) {
|
|
8
8
|
const groupPolicy = params.discordConfig?.groupPolicy ?? "open";
|
|
9
9
|
const ackReactionScope = params.cfg.messages?.ackReactionScope ?? "group-mentions";
|
|
@@ -13,28 +13,37 @@ export function createDiscordMessageHandler(params) {
|
|
|
13
13
|
buildKey: (entry) => {
|
|
14
14
|
const message = entry.data.message;
|
|
15
15
|
const authorId = entry.data.author?.id;
|
|
16
|
-
if (!message || !authorId)
|
|
16
|
+
if (!message || !authorId) {
|
|
17
17
|
return null;
|
|
18
|
-
|
|
19
|
-
|
|
18
|
+
}
|
|
19
|
+
const channelId = resolveDiscordMessageChannelId({
|
|
20
|
+
message,
|
|
21
|
+
eventChannelId: entry.data.channel_id,
|
|
22
|
+
});
|
|
23
|
+
if (!channelId) {
|
|
20
24
|
return null;
|
|
25
|
+
}
|
|
21
26
|
return `discord:${params.accountId}:${channelId}:${authorId}`;
|
|
22
27
|
},
|
|
23
28
|
shouldDebounce: (entry) => {
|
|
24
29
|
const message = entry.data.message;
|
|
25
|
-
if (!message)
|
|
30
|
+
if (!message) {
|
|
26
31
|
return false;
|
|
27
|
-
|
|
32
|
+
}
|
|
33
|
+
if (message.attachments && message.attachments.length > 0) {
|
|
28
34
|
return false;
|
|
35
|
+
}
|
|
29
36
|
const baseText = resolveDiscordMessageText(message, { includeForwarded: false });
|
|
30
|
-
if (!baseText.trim())
|
|
37
|
+
if (!baseText.trim()) {
|
|
31
38
|
return false;
|
|
39
|
+
}
|
|
32
40
|
return !hasControlCommand(baseText, params.cfg);
|
|
33
41
|
},
|
|
34
42
|
onFlush: async (entries) => {
|
|
35
43
|
const last = entries.at(-1);
|
|
36
|
-
if (!last)
|
|
44
|
+
if (!last) {
|
|
37
45
|
return;
|
|
46
|
+
}
|
|
38
47
|
if (entries.length === 1) {
|
|
39
48
|
const ctx = await preflightDiscordMessage({
|
|
40
49
|
...params,
|
|
@@ -43,8 +52,9 @@ export function createDiscordMessageHandler(params) {
|
|
|
43
52
|
data: last.data,
|
|
44
53
|
client: last.client,
|
|
45
54
|
});
|
|
46
|
-
if (!ctx)
|
|
55
|
+
if (!ctx) {
|
|
47
56
|
return;
|
|
57
|
+
}
|
|
48
58
|
await processDiscordMessage(ctx);
|
|
49
59
|
return;
|
|
50
60
|
}
|
|
@@ -73,8 +83,9 @@ export function createDiscordMessageHandler(params) {
|
|
|
73
83
|
data: syntheticData,
|
|
74
84
|
client: last.client,
|
|
75
85
|
});
|
|
76
|
-
if (!ctx)
|
|
86
|
+
if (!ctx) {
|
|
77
87
|
return;
|
|
88
|
+
}
|
|
78
89
|
if (entries.length > 1) {
|
|
79
90
|
const ids = entries.map((entry) => entry.data.message?.id).filter(Boolean);
|
|
80
91
|
if (ids.length > 0) {
|
|
@@ -3,43 +3,78 @@ import { hasControlCommand } from "../../auto-reply/command-detection.js";
|
|
|
3
3
|
import { shouldHandleTextCommands } from "../../auto-reply/commands-registry.js";
|
|
4
4
|
import { recordPendingHistoryEntryIfEnabled, } from "../../auto-reply/reply/history.js";
|
|
5
5
|
import { buildMentionRegexes, matchesMentionWithExplicit, } from "../../auto-reply/reply/mentions.js";
|
|
6
|
+
import { formatAllowlistMatchMeta } from "../../channels/allowlist-match.js";
|
|
7
|
+
import { resolveControlCommandGate } from "../../channels/command-gating.js";
|
|
8
|
+
import { logInboundDrop } from "../../channels/logging.js";
|
|
9
|
+
import { resolveMentionGatingWithBypass } from "../../channels/mention-gating.js";
|
|
10
|
+
import { loadConfig } from "../../config/config.js";
|
|
6
11
|
import { logVerbose, shouldLogVerbose } from "../../globals.js";
|
|
7
12
|
import { recordChannelActivity } from "../../infra/channel-activity.js";
|
|
8
13
|
import { enqueueSystemEvent } from "../../infra/system-events.js";
|
|
14
|
+
import { logDebug } from "../../logger.js";
|
|
9
15
|
import { getChildLogger } from "../../logging.js";
|
|
10
16
|
import { buildPairingReply } from "../../pairing/pairing-messages.js";
|
|
11
17
|
import { readChannelAllowFromStore, upsertChannelPairingRequest, } from "../../pairing/pairing-store.js";
|
|
12
18
|
import { resolveAgentRoute } from "../../routing/resolve-route.js";
|
|
13
|
-
import {
|
|
14
|
-
import { formatAllowlistMatchMeta } from "../../channels/allowlist-match.js";
|
|
19
|
+
import { fetchPluralKitMessageInfo } from "../pluralkit.js";
|
|
15
20
|
import { sendMessageDiscord } from "../send.js";
|
|
16
|
-
import {
|
|
17
|
-
import { logInboundDrop } from "../../channels/logging.js";
|
|
18
|
-
import { allowListMatches, isDiscordGroupAllowedByPolicy, normalizeDiscordAllowList, normalizeDiscordSlug, resolveDiscordAllowListMatch, resolveDiscordChannelConfigWithFallback, resolveDiscordGuildEntry, resolveDiscordShouldRequireMention, resolveDiscordUserAllowed, resolveGroupDmAllow, } from "./allow-list.js";
|
|
21
|
+
import { allowListMatches, isDiscordGroupAllowedByPolicy, normalizeDiscordAllowList, normalizeDiscordSlug, resolveDiscordAllowListMatch, resolveDiscordChannelConfigWithFallback, resolveDiscordGuildEntry, resolveDiscordMemberAccessState, resolveDiscordShouldRequireMention, resolveGroupDmAllow, } from "./allow-list.js";
|
|
19
22
|
import { formatDiscordUserTag, resolveDiscordSystemLocation, resolveTimestampMs, } from "./format.js";
|
|
20
|
-
import { resolveDiscordChannelInfo, resolveDiscordMessageText } from "./message-utils.js";
|
|
23
|
+
import { resolveDiscordChannelInfo, resolveDiscordMessageChannelId, resolveDiscordMessageText, } from "./message-utils.js";
|
|
24
|
+
import { resolveDiscordSenderIdentity, resolveDiscordWebhookId } from "./sender-identity.js";
|
|
21
25
|
import { resolveDiscordSystemEvent } from "./system-events.js";
|
|
22
26
|
import { resolveDiscordThreadChannel, resolveDiscordThreadParentInfo } from "./threading.js";
|
|
23
27
|
export async function preflightDiscordMessage(params) {
|
|
24
28
|
const logger = getChildLogger({ module: "discord-auto-reply" });
|
|
25
29
|
const message = params.data.message;
|
|
26
30
|
const author = params.data.author;
|
|
27
|
-
if (!author)
|
|
31
|
+
if (!author) {
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
34
|
+
const messageChannelId = resolveDiscordMessageChannelId({
|
|
35
|
+
message,
|
|
36
|
+
eventChannelId: params.data.channel_id,
|
|
37
|
+
});
|
|
38
|
+
if (!messageChannelId) {
|
|
39
|
+
logVerbose(`discord: drop message ${message.id} (missing channel id)`);
|
|
28
40
|
return null;
|
|
41
|
+
}
|
|
29
42
|
const allowBots = params.discordConfig?.allowBots ?? false;
|
|
30
|
-
if (author.
|
|
43
|
+
if (params.botUserId && author.id === params.botUserId) {
|
|
31
44
|
// Always ignore own messages to prevent self-reply loops
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
45
|
+
return null;
|
|
46
|
+
}
|
|
47
|
+
const pluralkitConfig = params.discordConfig?.pluralkit;
|
|
48
|
+
const webhookId = resolveDiscordWebhookId(message);
|
|
49
|
+
const shouldCheckPluralKit = Boolean(pluralkitConfig?.enabled) && !webhookId;
|
|
50
|
+
let pluralkitInfo = null;
|
|
51
|
+
if (shouldCheckPluralKit) {
|
|
52
|
+
try {
|
|
53
|
+
pluralkitInfo = await fetchPluralKitMessageInfo({
|
|
54
|
+
messageId: message.id,
|
|
55
|
+
config: pluralkitConfig,
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
catch (err) {
|
|
59
|
+
logVerbose(`discord: pluralkit lookup failed for ${message.id}: ${String(err)}`);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
const sender = resolveDiscordSenderIdentity({
|
|
63
|
+
author,
|
|
64
|
+
member: params.data.member,
|
|
65
|
+
pluralkitInfo,
|
|
66
|
+
});
|
|
67
|
+
if (author.bot) {
|
|
68
|
+
if (!allowBots && !sender.isPluralKit) {
|
|
35
69
|
logVerbose("discord: drop bot message (allowBots=false)");
|
|
36
70
|
return null;
|
|
37
71
|
}
|
|
38
72
|
}
|
|
39
73
|
const isGuildMessage = Boolean(params.data.guild_id);
|
|
40
|
-
const channelInfo = await resolveDiscordChannelInfo(params.client,
|
|
74
|
+
const channelInfo = await resolveDiscordChannelInfo(params.client, messageChannelId);
|
|
41
75
|
const isDirectMessage = channelInfo?.type === ChannelType.DM;
|
|
42
76
|
const isGroupDm = channelInfo?.type === ChannelType.GroupDM;
|
|
77
|
+
logDebug(`[discord-preflight] channelId=${messageChannelId} guild_id=${params.data.guild_id} channelType=${channelInfo?.type} isGuild=${isGuildMessage} isDM=${isDirectMessage} isGroupDm=${isGroupDm}`);
|
|
43
78
|
if (isGroupDm && !params.groupDmEnabled) {
|
|
44
79
|
logVerbose("discord: drop group dm (group dms disabled)");
|
|
45
80
|
return null;
|
|
@@ -48,7 +83,7 @@ export async function preflightDiscordMessage(params) {
|
|
|
48
83
|
logVerbose("discord: drop dm (dms disabled)");
|
|
49
84
|
return null;
|
|
50
85
|
}
|
|
51
|
-
const dmPolicy = params.discordConfig?.dm?.policy ?? "pairing";
|
|
86
|
+
const dmPolicy = params.discordConfig?.dmPolicy ?? params.discordConfig?.dm?.policy ?? "pairing";
|
|
52
87
|
let commandAuthorized = true;
|
|
53
88
|
if (isDirectMessage) {
|
|
54
89
|
if (dmPolicy === "disabled") {
|
|
@@ -58,14 +93,14 @@ export async function preflightDiscordMessage(params) {
|
|
|
58
93
|
if (dmPolicy !== "open") {
|
|
59
94
|
const storeAllowFrom = await readChannelAllowFromStore("discord").catch(() => []);
|
|
60
95
|
const effectiveAllowFrom = [...(params.allowFrom ?? []), ...storeAllowFrom];
|
|
61
|
-
const allowList = normalizeDiscordAllowList(effectiveAllowFrom, ["discord:", "user:"]);
|
|
96
|
+
const allowList = normalizeDiscordAllowList(effectiveAllowFrom, ["discord:", "user:", "pk:"]);
|
|
62
97
|
const allowMatch = allowList
|
|
63
98
|
? resolveDiscordAllowListMatch({
|
|
64
99
|
allowList,
|
|
65
100
|
candidate: {
|
|
66
|
-
id:
|
|
67
|
-
name:
|
|
68
|
-
tag:
|
|
101
|
+
id: sender.id,
|
|
102
|
+
name: sender.name,
|
|
103
|
+
tag: sender.tag,
|
|
69
104
|
},
|
|
70
105
|
})
|
|
71
106
|
: { allowed: false };
|
|
@@ -101,7 +136,7 @@ export async function preflightDiscordMessage(params) {
|
|
|
101
136
|
}
|
|
102
137
|
}
|
|
103
138
|
else {
|
|
104
|
-
logVerbose(`Blocked unauthorized discord sender ${
|
|
139
|
+
logVerbose(`Blocked unauthorized discord sender ${sender.id} (dmPolicy=${dmPolicy}, ${allowMatchMeta})`);
|
|
105
140
|
}
|
|
106
141
|
return null;
|
|
107
142
|
}
|
|
@@ -120,15 +155,46 @@ export async function preflightDiscordMessage(params) {
|
|
|
120
155
|
accountId: params.accountId,
|
|
121
156
|
direction: "inbound",
|
|
122
157
|
});
|
|
158
|
+
// Resolve thread parent early for binding inheritance
|
|
159
|
+
const channelName = channelInfo?.name ??
|
|
160
|
+
((isGuildMessage || isGroupDm) && message.channel && "name" in message.channel
|
|
161
|
+
? message.channel.name
|
|
162
|
+
: undefined);
|
|
163
|
+
const earlyThreadChannel = resolveDiscordThreadChannel({
|
|
164
|
+
isGuildMessage,
|
|
165
|
+
message,
|
|
166
|
+
channelInfo,
|
|
167
|
+
messageChannelId,
|
|
168
|
+
});
|
|
169
|
+
let earlyThreadParentId;
|
|
170
|
+
let earlyThreadParentName;
|
|
171
|
+
let earlyThreadParentType;
|
|
172
|
+
if (earlyThreadChannel) {
|
|
173
|
+
const parentInfo = await resolveDiscordThreadParentInfo({
|
|
174
|
+
client: params.client,
|
|
175
|
+
threadChannel: earlyThreadChannel,
|
|
176
|
+
channelInfo,
|
|
177
|
+
});
|
|
178
|
+
earlyThreadParentId = parentInfo.id;
|
|
179
|
+
earlyThreadParentName = parentInfo.name;
|
|
180
|
+
earlyThreadParentType = parentInfo.type;
|
|
181
|
+
}
|
|
182
|
+
// Fresh config for bindings lookup; other routing inputs are payload-derived.
|
|
183
|
+
const memberRoleIds = Array.isArray(params.data.rawMember?.roles)
|
|
184
|
+
? params.data.rawMember.roles.map((roleId) => String(roleId))
|
|
185
|
+
: [];
|
|
123
186
|
const route = resolveAgentRoute({
|
|
124
|
-
cfg:
|
|
187
|
+
cfg: loadConfig(),
|
|
125
188
|
channel: "discord",
|
|
126
189
|
accountId: params.accountId,
|
|
127
190
|
guildId: params.data.guild_id ?? undefined,
|
|
191
|
+
memberRoleIds,
|
|
128
192
|
peer: {
|
|
129
|
-
kind: isDirectMessage ? "
|
|
130
|
-
id: isDirectMessage ? author.id :
|
|
193
|
+
kind: isDirectMessage ? "direct" : isGroupDm ? "group" : "channel",
|
|
194
|
+
id: isDirectMessage ? author.id : messageChannelId,
|
|
131
195
|
},
|
|
196
|
+
// Pass parent peer for thread binding inheritance
|
|
197
|
+
parentPeer: earlyThreadParentId ? { kind: "channel", id: earlyThreadParentId } : undefined,
|
|
132
198
|
});
|
|
133
199
|
const mentionRegexes = buildMentionRegexes(params.cfg, route.agentId);
|
|
134
200
|
const explicitlyMentioned = Boolean(botId && message.mentionedUsers?.some((user) => user.id === botId));
|
|
@@ -136,23 +202,6 @@ export async function preflightDiscordMessage(params) {
|
|
|
136
202
|
(message.mentionedEveryone ||
|
|
137
203
|
(message.mentionedUsers?.length ?? 0) > 0 ||
|
|
138
204
|
(message.mentionedRoles?.length ?? 0) > 0));
|
|
139
|
-
const wasMentioned = !isDirectMessage &&
|
|
140
|
-
matchesMentionWithExplicit({
|
|
141
|
-
text: baseText,
|
|
142
|
-
mentionRegexes,
|
|
143
|
-
explicit: {
|
|
144
|
-
hasAnyMention,
|
|
145
|
-
isExplicitlyMentioned: explicitlyMentioned,
|
|
146
|
-
canResolveExplicit: Boolean(botId),
|
|
147
|
-
},
|
|
148
|
-
});
|
|
149
|
-
const implicitMention = Boolean(!isDirectMessage &&
|
|
150
|
-
botId &&
|
|
151
|
-
message.referencedMessage?.author?.id &&
|
|
152
|
-
message.referencedMessage.author.id === botId);
|
|
153
|
-
if (shouldLogVerbose()) {
|
|
154
|
-
logVerbose(`discord: inbound id=${message.id} guild=${message.guild?.id ?? "dm"} channel=${message.channelId} mention=${wasMentioned ? "yes" : "no"} type=${isDirectMessage ? "dm" : isGroupDm ? "group-dm" : "guild"} content=${messageText ? "yes" : "no"}`);
|
|
155
|
-
}
|
|
156
205
|
if (isGuildMessage &&
|
|
157
206
|
(message.type === MessageType.ChatInputCommand ||
|
|
158
207
|
message.type === MessageType.ContextMenuCommand)) {
|
|
@@ -165,35 +214,20 @@ export async function preflightDiscordMessage(params) {
|
|
|
165
214
|
guildEntries: params.guildEntries,
|
|
166
215
|
})
|
|
167
216
|
: null;
|
|
217
|
+
logDebug(`[discord-preflight] guild_id=${params.data.guild_id} guild_obj=${!!params.data.guild} guild_obj_id=${params.data.guild?.id} guildInfo=${!!guildInfo} guildEntries=${params.guildEntries ? Object.keys(params.guildEntries).join(",") : "none"}`);
|
|
168
218
|
if (isGuildMessage &&
|
|
169
219
|
params.guildEntries &&
|
|
170
220
|
Object.keys(params.guildEntries).length > 0 &&
|
|
171
221
|
!guildInfo) {
|
|
222
|
+
logDebug(`[discord-preflight] guild blocked: guild_id=${params.data.guild_id} guildEntries keys=${Object.keys(params.guildEntries).join(",")}`);
|
|
172
223
|
logVerbose(`Blocked discord guild ${params.data.guild_id ?? "unknown"} (not in discord.guilds)`);
|
|
173
224
|
return null;
|
|
174
225
|
}
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
const
|
|
180
|
-
isGuildMessage,
|
|
181
|
-
message,
|
|
182
|
-
channelInfo,
|
|
183
|
-
});
|
|
184
|
-
let threadParentId;
|
|
185
|
-
let threadParentName;
|
|
186
|
-
let threadParentType;
|
|
187
|
-
if (threadChannel) {
|
|
188
|
-
const parentInfo = await resolveDiscordThreadParentInfo({
|
|
189
|
-
client: params.client,
|
|
190
|
-
threadChannel,
|
|
191
|
-
channelInfo,
|
|
192
|
-
});
|
|
193
|
-
threadParentId = parentInfo.id;
|
|
194
|
-
threadParentName = parentInfo.name;
|
|
195
|
-
threadParentType = parentInfo.type;
|
|
196
|
-
}
|
|
226
|
+
// Reuse early thread resolution from above (for binding inheritance)
|
|
227
|
+
const threadChannel = earlyThreadChannel;
|
|
228
|
+
const threadParentId = earlyThreadParentId;
|
|
229
|
+
const threadParentName = earlyThreadParentName;
|
|
230
|
+
const threadParentType = earlyThreadParentType;
|
|
197
231
|
const threadName = threadChannel?.name;
|
|
198
232
|
const configChannelName = threadParentName ?? channelName;
|
|
199
233
|
const configChannelSlug = configChannelName ? normalizeDiscordSlug(configChannelName) : "";
|
|
@@ -207,7 +241,7 @@ export async function preflightDiscordMessage(params) {
|
|
|
207
241
|
const channelConfig = isGuildMessage
|
|
208
242
|
? resolveDiscordChannelConfigWithFallback({
|
|
209
243
|
guildInfo,
|
|
210
|
-
channelId:
|
|
244
|
+
channelId: messageChannelId,
|
|
211
245
|
channelName,
|
|
212
246
|
channelSlug: threadChannelSlug,
|
|
213
247
|
parentId: threadParentId ?? undefined,
|
|
@@ -217,19 +251,27 @@ export async function preflightDiscordMessage(params) {
|
|
|
217
251
|
})
|
|
218
252
|
: null;
|
|
219
253
|
const channelMatchMeta = formatAllowlistMatchMeta(channelConfig);
|
|
254
|
+
if (shouldLogVerbose()) {
|
|
255
|
+
const channelConfigSummary = channelConfig
|
|
256
|
+
? `allowed=${channelConfig.allowed} enabled=${channelConfig.enabled ?? "unset"} requireMention=${channelConfig.requireMention ?? "unset"} matchKey=${channelConfig.matchKey ?? "none"} matchSource=${channelConfig.matchSource ?? "none"} users=${channelConfig.users?.length ?? 0} roles=${channelConfig.roles?.length ?? 0} skills=${channelConfig.skills?.length ?? 0}`
|
|
257
|
+
: "none";
|
|
258
|
+
logDebug(`[discord-preflight] channelConfig=${channelConfigSummary} channelMatchMeta=${channelMatchMeta} channelId=${messageChannelId}`);
|
|
259
|
+
}
|
|
220
260
|
if (isGuildMessage && channelConfig?.enabled === false) {
|
|
221
|
-
|
|
261
|
+
logDebug(`[discord-preflight] drop: channel disabled`);
|
|
262
|
+
logVerbose(`Blocked discord channel ${messageChannelId} (channel disabled, ${channelMatchMeta})`);
|
|
222
263
|
return null;
|
|
223
264
|
}
|
|
224
265
|
const groupDmAllowed = isGroupDm &&
|
|
225
266
|
resolveGroupDmAllow({
|
|
226
267
|
channels: params.groupDmChannels,
|
|
227
|
-
channelId:
|
|
268
|
+
channelId: messageChannelId,
|
|
228
269
|
channelName: displayChannelName,
|
|
229
270
|
channelSlug: displayChannelSlug,
|
|
230
271
|
});
|
|
231
|
-
if (isGroupDm && !groupDmAllowed)
|
|
272
|
+
if (isGroupDm && !groupDmAllowed) {
|
|
232
273
|
return null;
|
|
274
|
+
}
|
|
233
275
|
const channelAllowlistConfigured = Boolean(guildInfo?.channels) && Object.keys(guildInfo?.channels ?? {}).length > 0;
|
|
234
276
|
const channelAllowed = channelConfig?.allowed !== false;
|
|
235
277
|
if (isGuildMessage &&
|
|
@@ -246,23 +288,25 @@ export async function preflightDiscordMessage(params) {
|
|
|
246
288
|
logVerbose(`discord: drop guild message (groupPolicy: allowlist, no channel allowlist, ${channelMatchMeta})`);
|
|
247
289
|
}
|
|
248
290
|
else {
|
|
249
|
-
logVerbose(`Blocked discord channel ${
|
|
291
|
+
logVerbose(`Blocked discord channel ${messageChannelId} not in guild channel allowlist (groupPolicy: allowlist, ${channelMatchMeta})`);
|
|
250
292
|
}
|
|
251
293
|
return null;
|
|
252
294
|
}
|
|
253
295
|
if (isGuildMessage && channelConfig?.allowed === false) {
|
|
254
|
-
|
|
296
|
+
logDebug(`[discord-preflight] drop: channelConfig.allowed===false`);
|
|
297
|
+
logVerbose(`Blocked discord channel ${messageChannelId} not in guild channel allowlist (${channelMatchMeta})`);
|
|
255
298
|
return null;
|
|
256
299
|
}
|
|
257
300
|
if (isGuildMessage) {
|
|
258
|
-
|
|
301
|
+
logDebug(`[discord-preflight] pass: channel allowed`);
|
|
302
|
+
logVerbose(`discord: allow channel ${messageChannelId} (${channelMatchMeta})`);
|
|
259
303
|
}
|
|
260
304
|
const textForHistory = resolveDiscordMessageText(message, {
|
|
261
305
|
includeForwarded: true,
|
|
262
306
|
});
|
|
263
307
|
const historyEntry = isGuildMessage && params.historyLimit > 0 && textForHistory
|
|
264
308
|
? {
|
|
265
|
-
sender:
|
|
309
|
+
sender: sender.label,
|
|
266
310
|
body: textForHistory,
|
|
267
311
|
timestamp: resolveTimestampMs(message.timestamp),
|
|
268
312
|
messageId: message.id,
|
|
@@ -277,27 +321,80 @@ export async function preflightDiscordMessage(params) {
|
|
|
277
321
|
channelConfig,
|
|
278
322
|
guildInfo,
|
|
279
323
|
});
|
|
324
|
+
// Preflight audio transcription for mention detection in guilds
|
|
325
|
+
// This allows voice notes to be checked for mentions before being dropped
|
|
326
|
+
let preflightTranscript;
|
|
327
|
+
const hasAudioAttachment = message.attachments?.some((att) => att.contentType?.startsWith("audio/"));
|
|
328
|
+
const needsPreflightTranscription = !isDirectMessage &&
|
|
329
|
+
shouldRequireMention &&
|
|
330
|
+
hasAudioAttachment &&
|
|
331
|
+
!baseText &&
|
|
332
|
+
mentionRegexes.length > 0;
|
|
333
|
+
if (needsPreflightTranscription) {
|
|
334
|
+
try {
|
|
335
|
+
const { transcribeFirstAudio } = await import("../../media-understanding/audio-preflight.js");
|
|
336
|
+
const audioPaths = message.attachments
|
|
337
|
+
?.filter((att) => att.contentType?.startsWith("audio/"))
|
|
338
|
+
.map((att) => att.url) ?? [];
|
|
339
|
+
if (audioPaths.length > 0) {
|
|
340
|
+
const tempCtx = {
|
|
341
|
+
MediaUrls: audioPaths,
|
|
342
|
+
MediaTypes: message.attachments
|
|
343
|
+
?.filter((att) => att.contentType?.startsWith("audio/"))
|
|
344
|
+
.map((att) => att.contentType)
|
|
345
|
+
.filter(Boolean),
|
|
346
|
+
};
|
|
347
|
+
preflightTranscript = await transcribeFirstAudio({
|
|
348
|
+
ctx: tempCtx,
|
|
349
|
+
cfg: params.cfg,
|
|
350
|
+
agentDir: undefined,
|
|
351
|
+
});
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
catch (err) {
|
|
355
|
+
logVerbose(`discord: audio preflight transcription failed: ${String(err)}`);
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
const wasMentioned = !isDirectMessage &&
|
|
359
|
+
matchesMentionWithExplicit({
|
|
360
|
+
text: baseText,
|
|
361
|
+
mentionRegexes,
|
|
362
|
+
explicit: {
|
|
363
|
+
hasAnyMention,
|
|
364
|
+
isExplicitlyMentioned: explicitlyMentioned,
|
|
365
|
+
canResolveExplicit: Boolean(botId),
|
|
366
|
+
},
|
|
367
|
+
transcript: preflightTranscript,
|
|
368
|
+
});
|
|
369
|
+
const implicitMention = Boolean(!isDirectMessage &&
|
|
370
|
+
botId &&
|
|
371
|
+
message.referencedMessage?.author?.id &&
|
|
372
|
+
message.referencedMessage.author.id === botId);
|
|
373
|
+
if (shouldLogVerbose()) {
|
|
374
|
+
logVerbose(`discord: inbound id=${message.id} guild=${params.data.guild_id ?? "dm"} channel=${messageChannelId} mention=${wasMentioned ? "yes" : "no"} type=${isDirectMessage ? "dm" : isGroupDm ? "group-dm" : "guild"} content=${messageText ? "yes" : "no"}`);
|
|
375
|
+
}
|
|
280
376
|
const allowTextCommands = shouldHandleTextCommands({
|
|
281
377
|
cfg: params.cfg,
|
|
282
378
|
surface: "discord",
|
|
283
379
|
});
|
|
284
380
|
const hasControlCommandInMessage = hasControlCommand(baseText, params.cfg);
|
|
381
|
+
const { hasAccessRestrictions, memberAllowed } = resolveDiscordMemberAccessState({
|
|
382
|
+
channelConfig,
|
|
383
|
+
guildInfo,
|
|
384
|
+
memberRoleIds,
|
|
385
|
+
sender,
|
|
386
|
+
});
|
|
285
387
|
if (!isDirectMessage) {
|
|
286
|
-
const ownerAllowList = normalizeDiscordAllowList(params.allowFrom, [
|
|
388
|
+
const ownerAllowList = normalizeDiscordAllowList(params.allowFrom, [
|
|
389
|
+
"discord:",
|
|
390
|
+
"user:",
|
|
391
|
+
"pk:",
|
|
392
|
+
]);
|
|
287
393
|
const ownerOk = ownerAllowList
|
|
288
394
|
? allowListMatches(ownerAllowList, {
|
|
289
|
-
id:
|
|
290
|
-
name:
|
|
291
|
-
tag:
|
|
292
|
-
})
|
|
293
|
-
: false;
|
|
294
|
-
const channelUsers = channelConfig?.users ?? guildInfo?.users;
|
|
295
|
-
const usersOk = Array.isArray(channelUsers) && channelUsers.length > 0
|
|
296
|
-
? resolveDiscordUserAllowed({
|
|
297
|
-
allowList: channelUsers,
|
|
298
|
-
userId: author.id,
|
|
299
|
-
userName: author.username,
|
|
300
|
-
userTag: formatDiscordUserTag(author),
|
|
395
|
+
id: sender.id,
|
|
396
|
+
name: sender.name,
|
|
397
|
+
tag: sender.tag,
|
|
301
398
|
})
|
|
302
399
|
: false;
|
|
303
400
|
const useAccessGroups = params.cfg.commands?.useAccessGroups !== false;
|
|
@@ -305,7 +402,7 @@ export async function preflightDiscordMessage(params) {
|
|
|
305
402
|
useAccessGroups,
|
|
306
403
|
authorizers: [
|
|
307
404
|
{ configured: ownerAllowList != null, allowed: ownerOk },
|
|
308
|
-
{ configured:
|
|
405
|
+
{ configured: hasAccessRestrictions, allowed: memberAllowed },
|
|
309
406
|
],
|
|
310
407
|
modeWhenAccessGroupsOff: "configured",
|
|
311
408
|
allowTextCommands,
|
|
@@ -317,7 +414,7 @@ export async function preflightDiscordMessage(params) {
|
|
|
317
414
|
log: logVerbose,
|
|
318
415
|
channel: "discord",
|
|
319
416
|
reason: "control command (unauthorized)",
|
|
320
|
-
target:
|
|
417
|
+
target: sender.id,
|
|
321
418
|
});
|
|
322
419
|
return null;
|
|
323
420
|
}
|
|
@@ -335,55 +432,50 @@ export async function preflightDiscordMessage(params) {
|
|
|
335
432
|
commandAuthorized,
|
|
336
433
|
});
|
|
337
434
|
const effectiveWasMentioned = mentionGate.effectiveWasMentioned;
|
|
435
|
+
logDebug(`[discord-preflight] shouldRequireMention=${shouldRequireMention} mentionGate.shouldSkip=${mentionGate.shouldSkip} wasMentioned=${wasMentioned}`);
|
|
338
436
|
if (isGuildMessage && shouldRequireMention) {
|
|
339
437
|
if (botId && mentionGate.shouldSkip) {
|
|
438
|
+
logDebug(`[discord-preflight] drop: no-mention`);
|
|
340
439
|
logVerbose(`discord: drop guild message (mention required, botId=${botId})`);
|
|
341
440
|
logger.info({
|
|
342
|
-
channelId:
|
|
441
|
+
channelId: messageChannelId,
|
|
343
442
|
reason: "no-mention",
|
|
344
443
|
}, "discord: skipping guild message");
|
|
345
444
|
recordPendingHistoryEntryIfEnabled({
|
|
346
445
|
historyMap: params.guildHistories,
|
|
347
|
-
historyKey:
|
|
446
|
+
historyKey: messageChannelId,
|
|
348
447
|
limit: params.historyLimit,
|
|
349
448
|
entry: historyEntry ?? null,
|
|
350
449
|
});
|
|
351
450
|
return null;
|
|
352
451
|
}
|
|
353
452
|
}
|
|
354
|
-
if (isGuildMessage) {
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
allowList: channelUsers,
|
|
359
|
-
userId: author.id,
|
|
360
|
-
userName: author.username,
|
|
361
|
-
userTag: formatDiscordUserTag(author),
|
|
362
|
-
});
|
|
363
|
-
if (!userOk) {
|
|
364
|
-
logVerbose(`Blocked discord guild sender ${author.id} (not in channel users allowlist)`);
|
|
365
|
-
return null;
|
|
366
|
-
}
|
|
367
|
-
}
|
|
453
|
+
if (isGuildMessage && hasAccessRestrictions && !memberAllowed) {
|
|
454
|
+
logDebug(`[discord-preflight] drop: member not allowed`);
|
|
455
|
+
logVerbose(`Blocked discord guild sender ${sender.id} (not in users/roles allowlist)`);
|
|
456
|
+
return null;
|
|
368
457
|
}
|
|
369
458
|
const systemLocation = resolveDiscordSystemLocation({
|
|
370
459
|
isDirectMessage,
|
|
371
460
|
isGroupDm,
|
|
372
461
|
guild: params.data.guild ?? undefined,
|
|
373
|
-
channelName: channelName ??
|
|
462
|
+
channelName: channelName ?? messageChannelId,
|
|
374
463
|
});
|
|
375
464
|
const systemText = resolveDiscordSystemEvent(message, systemLocation);
|
|
376
465
|
if (systemText) {
|
|
466
|
+
logDebug(`[discord-preflight] drop: system event`);
|
|
377
467
|
enqueueSystemEvent(systemText, {
|
|
378
468
|
sessionKey: route.sessionKey,
|
|
379
|
-
contextKey: `discord:system:${
|
|
469
|
+
contextKey: `discord:system:${messageChannelId}:${message.id}`,
|
|
380
470
|
});
|
|
381
471
|
return null;
|
|
382
472
|
}
|
|
383
473
|
if (!messageText) {
|
|
474
|
+
logDebug(`[discord-preflight] drop: empty content`);
|
|
384
475
|
logVerbose(`discord: drop message ${message.id} (empty content)`);
|
|
385
476
|
return null;
|
|
386
477
|
}
|
|
478
|
+
logDebug(`[discord-preflight] success: route=${route.agentId} sessionKey=${route.sessionKey}`);
|
|
387
479
|
return {
|
|
388
480
|
cfg: params.cfg,
|
|
389
481
|
discordConfig: params.discordConfig,
|
|
@@ -401,7 +493,9 @@ export async function preflightDiscordMessage(params) {
|
|
|
401
493
|
data: params.data,
|
|
402
494
|
client: params.client,
|
|
403
495
|
message,
|
|
496
|
+
messageChannelId,
|
|
404
497
|
author,
|
|
498
|
+
sender,
|
|
405
499
|
channelInfo,
|
|
406
500
|
channelName,
|
|
407
501
|
isGuildMessage,
|