@poolzin/pool-bot 2026.2.21 → 2026.2.22
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 +17 -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/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/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 +5 -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 +5 -0
- package/extensions/msteams/package.json +1 -1
- package/extensions/nextcloud-talk/package.json +1 -1
- package/extensions/nostr/CHANGELOG.md +5 -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 +5 -0
- package/extensions/twitch/package.json +1 -1
- package/extensions/voice-call/CHANGELOG.md +5 -0
- package/extensions/voice-call/package.json +1 -1
- package/extensions/whatsapp/package.json +1 -1
- package/extensions/zalo/CHANGELOG.md +5 -0
- package/extensions/zalo/package.json +1 -1
- package/extensions/zalouser/CHANGELOG.md +5 -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
|
@@ -1,19 +1,21 @@
|
|
|
1
1
|
import { resolveHumanDelayConfig } from "../../agents/identity.js";
|
|
2
2
|
import { hasControlCommand } from "../../auto-reply/command-detection.js";
|
|
3
|
+
import { dispatchInboundMessage } from "../../auto-reply/dispatch.js";
|
|
3
4
|
import { formatInboundEnvelope, formatInboundFromLabel, resolveEnvelopeFormatOptions, } from "../../auto-reply/envelope.js";
|
|
4
5
|
import { createInboundDebouncer, resolveInboundDebounceMs, } from "../../auto-reply/inbound-debounce.js";
|
|
5
|
-
import { dispatchInboundMessage } from "../../auto-reply/dispatch.js";
|
|
6
6
|
import { buildPendingHistoryContextFromMap, clearHistoryEntriesIfEnabled, recordPendingHistoryEntryIfEnabled, } from "../../auto-reply/reply/history.js";
|
|
7
|
-
import { buildMentionRegexes, matchesMentionPatterns } from "../../auto-reply/reply/mentions.js";
|
|
8
7
|
import { finalizeInboundContext } from "../../auto-reply/reply/inbound-context.js";
|
|
8
|
+
import { buildMentionRegexes, matchesMentionPatterns } from "../../auto-reply/reply/mentions.js";
|
|
9
9
|
import { createReplyDispatcherWithTyping } from "../../auto-reply/reply/reply-dispatcher.js";
|
|
10
|
+
import { resolveControlCommandGate } from "../../channels/command-gating.js";
|
|
10
11
|
import { logInboundDrop, logTypingFailure } from "../../channels/logging.js";
|
|
11
12
|
import { resolveMentionGatingWithBypass } from "../../channels/mention-gating.js";
|
|
12
|
-
import {
|
|
13
|
+
import { normalizeSignalMessagingTarget } from "../../channels/plugins/normalize/signal.js";
|
|
14
|
+
import { createReplyPrefixOptions } from "../../channels/reply-prefix.js";
|
|
13
15
|
import { recordInboundSession } from "../../channels/session.js";
|
|
14
16
|
import { createTypingCallbacks } from "../../channels/typing.js";
|
|
15
|
-
import { readSessionUpdatedAt, resolveStorePath } from "../../config/sessions.js";
|
|
16
17
|
import { resolveChannelGroupRequireMention } from "../../config/group-policy.js";
|
|
18
|
+
import { readSessionUpdatedAt, resolveStorePath } from "../../config/sessions.js";
|
|
17
19
|
import { danger, logVerbose, shouldLogVerbose } from "../../globals.js";
|
|
18
20
|
import { enqueueSystemEvent } from "../../infra/system-events.js";
|
|
19
21
|
import { mediaKindFromMime } from "../../media/constants.js";
|
|
@@ -21,9 +23,9 @@ import { buildPairingReply } from "../../pairing/pairing-messages.js";
|
|
|
21
23
|
import { readChannelAllowFromStore, upsertChannelPairingRequest, } from "../../pairing/pairing-store.js";
|
|
22
24
|
import { resolveAgentRoute } from "../../routing/resolve-route.js";
|
|
23
25
|
import { normalizeE164 } from "../../utils.js";
|
|
24
|
-
import { resolveControlCommandGate } from "../../channels/command-gating.js";
|
|
25
26
|
import { formatSignalPairingIdLine, formatSignalSenderDisplay, formatSignalSenderId, isSignalSenderAllowed, resolveSignalPeerId, resolveSignalRecipient, resolveSignalSender, } from "../identity.js";
|
|
26
27
|
import { sendMessageSignal, sendReadReceiptSignal, sendTypingSignal } from "../send.js";
|
|
28
|
+
import { renderSignalMentions } from "./mentions.js";
|
|
27
29
|
export function createSignalEventHandler(deps) {
|
|
28
30
|
const inboundDebounceMs = resolveInboundDebounceMs({ cfg: deps.cfg, channel: "signal" });
|
|
29
31
|
async function handleSignalInboundMessage(entry) {
|
|
@@ -40,7 +42,7 @@ export function createSignalEventHandler(deps) {
|
|
|
40
42
|
channel: "signal",
|
|
41
43
|
accountId: deps.accountId,
|
|
42
44
|
peer: {
|
|
43
|
-
kind: entry.isGroup ? "group" : "
|
|
45
|
+
kind: entry.isGroup ? "group" : "direct",
|
|
44
46
|
id: entry.isGroup ? (entry.groupId ?? "unknown") : entry.senderPeerId,
|
|
45
47
|
},
|
|
46
48
|
});
|
|
@@ -81,7 +83,10 @@ export function createSignalEventHandler(deps) {
|
|
|
81
83
|
}),
|
|
82
84
|
});
|
|
83
85
|
}
|
|
84
|
-
const
|
|
86
|
+
const signalToRaw = entry.isGroup
|
|
87
|
+
? `group:${entry.groupId}`
|
|
88
|
+
: `signal:${entry.senderRecipient}`;
|
|
89
|
+
const signalTo = normalizeSignalMessagingTarget(signalToRaw) ?? signalToRaw;
|
|
85
90
|
const inboundHistory = entry.isGroup && historyKey && deps.historyLimit > 0
|
|
86
91
|
? (deps.groupHistories.get(historyKey) ?? []).map((historyEntry) => ({
|
|
87
92
|
sender: historyEntry.sender,
|
|
@@ -138,11 +143,17 @@ export function createSignalEventHandler(deps) {
|
|
|
138
143
|
const preview = body.slice(0, 200).replace(/\\n/g, "\\\\n");
|
|
139
144
|
logVerbose(`signal inbound: from=${ctxPayload.From} len=${body.length} preview="${preview}"`);
|
|
140
145
|
}
|
|
141
|
-
const
|
|
146
|
+
const { onModelSelected, ...prefixOptions } = createReplyPrefixOptions({
|
|
147
|
+
cfg: deps.cfg,
|
|
148
|
+
agentId: route.agentId,
|
|
149
|
+
channel: "signal",
|
|
150
|
+
accountId: route.accountId,
|
|
151
|
+
});
|
|
142
152
|
const typingCallbacks = createTypingCallbacks({
|
|
143
153
|
start: async () => {
|
|
144
|
-
if (!ctxPayload.To)
|
|
154
|
+
if (!ctxPayload.To) {
|
|
145
155
|
return;
|
|
156
|
+
}
|
|
146
157
|
await sendTypingSignal(ctxPayload.To, {
|
|
147
158
|
baseUrl: deps.baseUrl,
|
|
148
159
|
account: deps.account,
|
|
@@ -159,8 +170,7 @@ export function createSignalEventHandler(deps) {
|
|
|
159
170
|
},
|
|
160
171
|
});
|
|
161
172
|
const { dispatcher, replyOptions, markDispatchIdle } = createReplyDispatcherWithTyping({
|
|
162
|
-
|
|
163
|
-
responsePrefixContextProvider: prefixContext.responsePrefixContextProvider,
|
|
173
|
+
...prefixOptions,
|
|
164
174
|
humanDelay: resolveHumanDelayConfig(deps.cfg, route.agentId),
|
|
165
175
|
deliver: async (payload) => {
|
|
166
176
|
await deps.deliverReplies({
|
|
@@ -186,9 +196,7 @@ export function createSignalEventHandler(deps) {
|
|
|
186
196
|
replyOptions: {
|
|
187
197
|
...replyOptions,
|
|
188
198
|
disableBlockStreaming: typeof deps.blockStreaming === "boolean" ? !deps.blockStreaming : undefined,
|
|
189
|
-
onModelSelected
|
|
190
|
-
prefixContext.onModelSelected(ctx);
|
|
191
|
-
},
|
|
199
|
+
onModelSelected,
|
|
192
200
|
},
|
|
193
201
|
});
|
|
194
202
|
markDispatchIdle();
|
|
@@ -214,21 +222,25 @@ export function createSignalEventHandler(deps) {
|
|
|
214
222
|
debounceMs: inboundDebounceMs,
|
|
215
223
|
buildKey: (entry) => {
|
|
216
224
|
const conversationId = entry.isGroup ? (entry.groupId ?? "unknown") : entry.senderPeerId;
|
|
217
|
-
if (!conversationId || !entry.senderPeerId)
|
|
225
|
+
if (!conversationId || !entry.senderPeerId) {
|
|
218
226
|
return null;
|
|
227
|
+
}
|
|
219
228
|
return `signal:${deps.accountId}:${conversationId}:${entry.senderPeerId}`;
|
|
220
229
|
},
|
|
221
230
|
shouldDebounce: (entry) => {
|
|
222
|
-
if (!entry.bodyText.trim())
|
|
231
|
+
if (!entry.bodyText.trim()) {
|
|
223
232
|
return false;
|
|
224
|
-
|
|
233
|
+
}
|
|
234
|
+
if (entry.mediaPath || entry.mediaType) {
|
|
225
235
|
return false;
|
|
236
|
+
}
|
|
226
237
|
return !hasControlCommand(entry.bodyText, deps.cfg);
|
|
227
238
|
},
|
|
228
239
|
onFlush: async (entries) => {
|
|
229
240
|
const last = entries.at(-1);
|
|
230
|
-
if (!last)
|
|
241
|
+
if (!last) {
|
|
231
242
|
return;
|
|
243
|
+
}
|
|
232
244
|
if (entries.length === 1) {
|
|
233
245
|
await handleSignalInboundMessage(last);
|
|
234
246
|
return;
|
|
@@ -237,8 +249,9 @@ export function createSignalEventHandler(deps) {
|
|
|
237
249
|
.map((entry) => entry.bodyText)
|
|
238
250
|
.filter(Boolean)
|
|
239
251
|
.join("\\n");
|
|
240
|
-
if (!combinedText.trim())
|
|
252
|
+
if (!combinedText.trim()) {
|
|
241
253
|
return;
|
|
254
|
+
}
|
|
242
255
|
await handleSignalInboundMessage({
|
|
243
256
|
...last,
|
|
244
257
|
bodyText: combinedText,
|
|
@@ -251,8 +264,9 @@ export function createSignalEventHandler(deps) {
|
|
|
251
264
|
},
|
|
252
265
|
});
|
|
253
266
|
return async (event) => {
|
|
254
|
-
if (event.event !== "receive" || !event.data)
|
|
267
|
+
if (event.event !== "receive" || !event.data) {
|
|
255
268
|
return;
|
|
269
|
+
}
|
|
256
270
|
let payload = null;
|
|
257
271
|
try {
|
|
258
272
|
payload = JSON.parse(event.data);
|
|
@@ -265,16 +279,20 @@ export function createSignalEventHandler(deps) {
|
|
|
265
279
|
deps.runtime.error?.(`receive exception: ${payload.exception.message}`);
|
|
266
280
|
}
|
|
267
281
|
const envelope = payload?.envelope;
|
|
268
|
-
if (!envelope)
|
|
282
|
+
if (!envelope) {
|
|
269
283
|
return;
|
|
270
|
-
|
|
284
|
+
}
|
|
285
|
+
if (envelope.syncMessage) {
|
|
271
286
|
return;
|
|
287
|
+
}
|
|
272
288
|
const sender = resolveSignalSender(envelope);
|
|
273
|
-
if (!sender)
|
|
289
|
+
if (!sender) {
|
|
274
290
|
return;
|
|
291
|
+
}
|
|
275
292
|
if (deps.account && sender.kind === "phone") {
|
|
276
|
-
if (sender.e164 === normalizeE164(deps.account))
|
|
293
|
+
if (sender.e164 === normalizeE164(deps.account)) {
|
|
277
294
|
return;
|
|
295
|
+
}
|
|
278
296
|
}
|
|
279
297
|
const dataMessage = envelope.dataMessage ?? envelope.editMessage?.dataMessage;
|
|
280
298
|
const reaction = deps.isSignalReactionMessage(envelope.reactionMessage)
|
|
@@ -282,12 +300,17 @@ export function createSignalEventHandler(deps) {
|
|
|
282
300
|
: deps.isSignalReactionMessage(dataMessage?.reaction)
|
|
283
301
|
? dataMessage?.reaction
|
|
284
302
|
: null;
|
|
285
|
-
|
|
303
|
+
// Replace  (object replacement character) with @uuid or @phone from mentions
|
|
304
|
+
// Signal encodes mentions as the object replacement character; hydrate them from metadata first.
|
|
305
|
+
const rawMessage = dataMessage?.message ?? "";
|
|
306
|
+
const normalizedMessage = renderSignalMentions(rawMessage, dataMessage?.mentions);
|
|
307
|
+
const messageText = normalizedMessage.trim();
|
|
286
308
|
const quoteText = dataMessage?.quote?.text?.trim() ?? "";
|
|
287
309
|
const hasBodyContent = Boolean(messageText || quoteText) || Boolean(!reaction && dataMessage?.attachments?.length);
|
|
288
310
|
if (reaction && !hasBodyContent) {
|
|
289
|
-
if (reaction.isRemove)
|
|
290
|
-
return;
|
|
311
|
+
if (reaction.isRemove) {
|
|
312
|
+
return;
|
|
313
|
+
} // Ignore reaction removals
|
|
291
314
|
const emojiLabel = reaction.emoji?.trim() || "emoji";
|
|
292
315
|
const senderDisplay = formatSignalSenderDisplay(sender);
|
|
293
316
|
const senderName = envelope.sourceName ?? senderDisplay;
|
|
@@ -300,8 +323,9 @@ export function createSignalEventHandler(deps) {
|
|
|
300
323
|
sender,
|
|
301
324
|
allowlist: deps.reactionAllowlist,
|
|
302
325
|
});
|
|
303
|
-
if (!shouldNotify)
|
|
326
|
+
if (!shouldNotify) {
|
|
304
327
|
return;
|
|
328
|
+
}
|
|
305
329
|
const groupId = reaction.groupInfo?.groupId ?? undefined;
|
|
306
330
|
const groupName = reaction.groupInfo?.groupName ?? undefined;
|
|
307
331
|
const isGroup = Boolean(groupId);
|
|
@@ -311,7 +335,7 @@ export function createSignalEventHandler(deps) {
|
|
|
311
335
|
channel: "signal",
|
|
312
336
|
accountId: deps.accountId,
|
|
313
337
|
peer: {
|
|
314
|
-
kind: isGroup ? "group" : "
|
|
338
|
+
kind: isGroup ? "group" : "direct",
|
|
315
339
|
id: isGroup ? (groupId ?? "unknown") : senderPeerId,
|
|
316
340
|
},
|
|
317
341
|
});
|
|
@@ -341,14 +365,16 @@ export function createSignalEventHandler(deps) {
|
|
|
341
365
|
enqueueSystemEvent(text, { sessionKey: route.sessionKey, contextKey });
|
|
342
366
|
return;
|
|
343
367
|
}
|
|
344
|
-
if (!dataMessage)
|
|
368
|
+
if (!dataMessage) {
|
|
345
369
|
return;
|
|
370
|
+
}
|
|
346
371
|
const senderDisplay = formatSignalSenderDisplay(sender);
|
|
347
372
|
const senderRecipient = resolveSignalRecipient(sender);
|
|
348
373
|
const senderPeerId = resolveSignalPeerId(sender);
|
|
349
374
|
const senderAllowId = formatSignalSenderId(sender);
|
|
350
|
-
if (!senderRecipient)
|
|
375
|
+
if (!senderRecipient) {
|
|
351
376
|
return;
|
|
377
|
+
}
|
|
352
378
|
const senderIdLine = formatSignalPairingIdLine(sender);
|
|
353
379
|
const groupId = dataMessage.groupInfo?.groupId ?? undefined;
|
|
354
380
|
const groupName = dataMessage.groupInfo?.groupName ?? undefined;
|
|
@@ -358,8 +384,9 @@ export function createSignalEventHandler(deps) {
|
|
|
358
384
|
const effectiveGroupAllow = [...deps.groupAllowFrom, ...storeAllowFrom];
|
|
359
385
|
const dmAllowed = deps.dmPolicy === "open" ? true : isSignalSenderAllowed(sender, effectiveDmAllow);
|
|
360
386
|
if (!isGroup) {
|
|
361
|
-
if (deps.dmPolicy === "disabled")
|
|
387
|
+
if (deps.dmPolicy === "disabled") {
|
|
362
388
|
return;
|
|
389
|
+
}
|
|
363
390
|
if (!dmAllowed) {
|
|
364
391
|
if (deps.dmPolicy === "pairing") {
|
|
365
392
|
const senderId = senderAllowId;
|
|
@@ -435,7 +462,7 @@ export function createSignalEventHandler(deps) {
|
|
|
435
462
|
channel: "signal",
|
|
436
463
|
accountId: deps.accountId,
|
|
437
464
|
peer: {
|
|
438
|
-
kind: isGroup ? "group" : "
|
|
465
|
+
kind: isGroup ? "group" : "direct",
|
|
439
466
|
id: isGroup ? (groupId ?? "unknown") : senderPeerId,
|
|
440
467
|
},
|
|
441
468
|
});
|
|
@@ -473,6 +500,8 @@ export function createSignalEventHandler(deps) {
|
|
|
473
500
|
if (!dataMessage.attachments?.length) {
|
|
474
501
|
return "";
|
|
475
502
|
}
|
|
503
|
+
// When we're skipping a message we intentionally avoid downloading attachments.
|
|
504
|
+
// Still record a useful placeholder for pending-history context.
|
|
476
505
|
if (deps.ignoreAttachments) {
|
|
477
506
|
return "<media:attachment>";
|
|
478
507
|
}
|
|
@@ -519,13 +548,16 @@ export function createSignalEventHandler(deps) {
|
|
|
519
548
|
}
|
|
520
549
|
}
|
|
521
550
|
const kind = mediaKindFromMime(mediaType ?? undefined);
|
|
522
|
-
if (kind)
|
|
551
|
+
if (kind) {
|
|
523
552
|
placeholder = `<media:${kind}>`;
|
|
524
|
-
|
|
553
|
+
}
|
|
554
|
+
else if (dataMessage.attachments?.length) {
|
|
525
555
|
placeholder = "<media:attachment>";
|
|
556
|
+
}
|
|
526
557
|
const bodyText = messageText || placeholder || dataMessage.quote?.text?.trim() || "";
|
|
527
|
-
if (!bodyText)
|
|
558
|
+
if (!bodyText) {
|
|
528
559
|
return;
|
|
560
|
+
}
|
|
529
561
|
const receiptTimestamp = typeof envelope.timestamp === "number"
|
|
530
562
|
? envelope.timestamp
|
|
531
563
|
: typeof dataMessage.timestamp === "number"
|
package/dist/signal/send.js
CHANGED
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
import { loadConfig } from "../config/config.js";
|
|
2
2
|
import { resolveMarkdownTableMode } from "../config/markdown-tables.js";
|
|
3
3
|
import { mediaKindFromMime } from "../media/constants.js";
|
|
4
|
-
import {
|
|
5
|
-
import { loadWebMedia } from "../web/media.js";
|
|
4
|
+
import { resolveOutboundAttachmentFromUrl } from "../media/outbound-attachment.js";
|
|
6
5
|
import { resolveSignalAccount } from "./accounts.js";
|
|
7
6
|
import { signalRpcRequest } from "./client.js";
|
|
8
7
|
import { markdownToSignalText } from "./format.js";
|
|
8
|
+
import { resolveSignalRpcContext } from "./rpc-context.js";
|
|
9
9
|
function parseTarget(raw) {
|
|
10
10
|
let value = raw.trim();
|
|
11
|
-
if (!value)
|
|
11
|
+
if (!value) {
|
|
12
12
|
throw new Error("Signal recipient is required");
|
|
13
|
+
}
|
|
13
14
|
const lower = value.toLowerCase();
|
|
14
15
|
if (lower.startsWith("signal:")) {
|
|
15
16
|
value = value.slice("signal:".length).trim();
|
|
@@ -31,44 +32,25 @@ function parseTarget(raw) {
|
|
|
31
32
|
}
|
|
32
33
|
function buildTargetParams(target, allow) {
|
|
33
34
|
if (target.type === "recipient") {
|
|
34
|
-
if (!allow.recipient)
|
|
35
|
+
if (!allow.recipient) {
|
|
35
36
|
return null;
|
|
37
|
+
}
|
|
36
38
|
return { recipient: [target.recipient] };
|
|
37
39
|
}
|
|
38
40
|
if (target.type === "group") {
|
|
39
|
-
if (!allow.group)
|
|
41
|
+
if (!allow.group) {
|
|
40
42
|
return null;
|
|
43
|
+
}
|
|
41
44
|
return { groupId: target.groupId };
|
|
42
45
|
}
|
|
43
46
|
if (target.type === "username") {
|
|
44
|
-
if (!allow.username)
|
|
47
|
+
if (!allow.username) {
|
|
45
48
|
return null;
|
|
49
|
+
}
|
|
46
50
|
return { username: [target.username] };
|
|
47
51
|
}
|
|
48
52
|
return null;
|
|
49
53
|
}
|
|
50
|
-
function resolveSignalRpcContext(opts, accountInfo) {
|
|
51
|
-
const hasBaseUrl = Boolean(opts.baseUrl?.trim());
|
|
52
|
-
const hasAccount = Boolean(opts.account?.trim());
|
|
53
|
-
const resolvedAccount = accountInfo ||
|
|
54
|
-
(!hasBaseUrl || !hasAccount
|
|
55
|
-
? resolveSignalAccount({
|
|
56
|
-
cfg: loadConfig(),
|
|
57
|
-
accountId: opts.accountId,
|
|
58
|
-
})
|
|
59
|
-
: undefined);
|
|
60
|
-
const baseUrl = opts.baseUrl?.trim() || resolvedAccount?.baseUrl;
|
|
61
|
-
if (!baseUrl) {
|
|
62
|
-
throw new Error("Signal base URL is required");
|
|
63
|
-
}
|
|
64
|
-
const account = opts.account?.trim() || resolvedAccount?.config.account?.trim();
|
|
65
|
-
return { baseUrl, account };
|
|
66
|
-
}
|
|
67
|
-
async function resolveAttachment(mediaUrl, maxBytes) {
|
|
68
|
-
const media = await loadWebMedia(mediaUrl, maxBytes);
|
|
69
|
-
const saved = await saveMediaBuffer(media.buffer, media.contentType ?? undefined, "outbound", maxBytes);
|
|
70
|
-
return { path: saved.path, contentType: saved.contentType };
|
|
71
|
-
}
|
|
72
54
|
export async function sendMessageSignal(to, text, opts = {}) {
|
|
73
55
|
const cfg = loadConfig();
|
|
74
56
|
const accountInfo = resolveSignalAccount({
|
|
@@ -82,8 +64,9 @@ export async function sendMessageSignal(to, text, opts = {}) {
|
|
|
82
64
|
let textStyles = [];
|
|
83
65
|
const textMode = opts.textMode ?? "markdown";
|
|
84
66
|
const maxBytes = (() => {
|
|
85
|
-
if (typeof opts.maxBytes === "number")
|
|
67
|
+
if (typeof opts.maxBytes === "number") {
|
|
86
68
|
return opts.maxBytes;
|
|
69
|
+
}
|
|
87
70
|
if (typeof accountInfo.config.mediaMaxMb === "number") {
|
|
88
71
|
return accountInfo.config.mediaMaxMb * 1024 * 1024;
|
|
89
72
|
}
|
|
@@ -94,7 +77,9 @@ export async function sendMessageSignal(to, text, opts = {}) {
|
|
|
94
77
|
})();
|
|
95
78
|
let attachments;
|
|
96
79
|
if (opts.mediaUrl?.trim()) {
|
|
97
|
-
const resolved = await
|
|
80
|
+
const resolved = await resolveOutboundAttachmentFromUrl(opts.mediaUrl.trim(), maxBytes, {
|
|
81
|
+
localRoots: opts.mediaLocalRoots,
|
|
82
|
+
});
|
|
98
83
|
attachments = [resolved.path];
|
|
99
84
|
const kind = mediaKindFromMime(resolved.contentType ?? undefined);
|
|
100
85
|
if (!message && kind) {
|
|
@@ -125,8 +110,9 @@ export async function sendMessageSignal(to, text, opts = {}) {
|
|
|
125
110
|
if (textStyles.length > 0) {
|
|
126
111
|
params["text-style"] = textStyles.map((style) => `${style.start}:${style.length}:${style.style}`);
|
|
127
112
|
}
|
|
128
|
-
if (account)
|
|
113
|
+
if (account) {
|
|
129
114
|
params.account = account;
|
|
115
|
+
}
|
|
130
116
|
if (attachments && attachments.length > 0) {
|
|
131
117
|
params.attachments = attachments;
|
|
132
118
|
}
|
|
@@ -155,13 +141,16 @@ export async function sendTypingSignal(to, opts = {}) {
|
|
|
155
141
|
recipient: true,
|
|
156
142
|
group: true,
|
|
157
143
|
});
|
|
158
|
-
if (!targetParams)
|
|
144
|
+
if (!targetParams) {
|
|
159
145
|
return false;
|
|
146
|
+
}
|
|
160
147
|
const params = { ...targetParams };
|
|
161
|
-
if (account)
|
|
148
|
+
if (account) {
|
|
162
149
|
params.account = account;
|
|
163
|
-
|
|
150
|
+
}
|
|
151
|
+
if (opts.stop) {
|
|
164
152
|
params.stop = true;
|
|
153
|
+
}
|
|
165
154
|
await signalRpcRequest("sendTyping", params, {
|
|
166
155
|
baseUrl,
|
|
167
156
|
timeoutMs: opts.timeoutMs,
|
|
@@ -169,21 +158,24 @@ export async function sendTypingSignal(to, opts = {}) {
|
|
|
169
158
|
return true;
|
|
170
159
|
}
|
|
171
160
|
export async function sendReadReceiptSignal(to, targetTimestamp, opts = {}) {
|
|
172
|
-
if (!Number.isFinite(targetTimestamp) || targetTimestamp <= 0)
|
|
161
|
+
if (!Number.isFinite(targetTimestamp) || targetTimestamp <= 0) {
|
|
173
162
|
return false;
|
|
163
|
+
}
|
|
174
164
|
const { baseUrl, account } = resolveSignalRpcContext(opts);
|
|
175
165
|
const targetParams = buildTargetParams(parseTarget(to), {
|
|
176
166
|
recipient: true,
|
|
177
167
|
});
|
|
178
|
-
if (!targetParams)
|
|
168
|
+
if (!targetParams) {
|
|
179
169
|
return false;
|
|
170
|
+
}
|
|
180
171
|
const params = {
|
|
181
172
|
...targetParams,
|
|
182
173
|
targetTimestamp,
|
|
183
174
|
type: opts.type ?? "read",
|
|
184
175
|
};
|
|
185
|
-
if (account)
|
|
176
|
+
if (account) {
|
|
186
177
|
params.account = account;
|
|
178
|
+
}
|
|
187
179
|
await signalRpcRequest("sendReceipt", params, {
|
|
188
180
|
baseUrl,
|
|
189
181
|
timeoutMs: opts.timeoutMs,
|
|
@@ -1,21 +1,18 @@
|
|
|
1
|
+
import { normalizeHyphenSlug, normalizeStringEntries, normalizeStringEntriesLower, } from "../../shared/string-normalization.js";
|
|
1
2
|
export function normalizeSlackSlug(raw) {
|
|
2
|
-
|
|
3
|
-
if (!trimmed)
|
|
4
|
-
return "";
|
|
5
|
-
const dashed = trimmed.replace(/\s+/g, "-");
|
|
6
|
-
const cleaned = dashed.replace(/[^a-z0-9#@._+-]+/g, "-");
|
|
7
|
-
return cleaned.replace(/-{2,}/g, "-").replace(/^[-.]+|[-.]+$/g, "");
|
|
3
|
+
return normalizeHyphenSlug(raw);
|
|
8
4
|
}
|
|
9
5
|
export function normalizeAllowList(list) {
|
|
10
|
-
return (list
|
|
6
|
+
return normalizeStringEntries(list);
|
|
11
7
|
}
|
|
12
8
|
export function normalizeAllowListLower(list) {
|
|
13
|
-
return
|
|
9
|
+
return normalizeStringEntriesLower(list);
|
|
14
10
|
}
|
|
15
11
|
export function resolveSlackAllowListMatch(params) {
|
|
16
12
|
const allowList = params.allowList;
|
|
17
|
-
if (allowList.length === 0)
|
|
13
|
+
if (allowList.length === 0) {
|
|
18
14
|
return { allowed: false };
|
|
15
|
+
}
|
|
19
16
|
if (allowList.includes("*")) {
|
|
20
17
|
return { allowed: true, matchKey: "*", matchSource: "wildcard" };
|
|
21
18
|
}
|
|
@@ -31,8 +28,9 @@ export function resolveSlackAllowListMatch(params) {
|
|
|
31
28
|
{ value: slug, source: "slug" },
|
|
32
29
|
];
|
|
33
30
|
for (const candidate of candidates) {
|
|
34
|
-
if (!candidate.value)
|
|
31
|
+
if (!candidate.value) {
|
|
35
32
|
continue;
|
|
33
|
+
}
|
|
36
34
|
if (allowList.includes(candidate.value)) {
|
|
37
35
|
return {
|
|
38
36
|
allowed: true,
|
|
@@ -48,8 +46,9 @@ export function allowListMatches(params) {
|
|
|
48
46
|
}
|
|
49
47
|
export function resolveSlackUserAllowed(params) {
|
|
50
48
|
const allowList = normalizeAllowListLower(params.allowList);
|
|
51
|
-
if (allowList.length === 0)
|
|
49
|
+
if (allowList.length === 0) {
|
|
52
50
|
return true;
|
|
51
|
+
}
|
|
53
52
|
return allowListMatches({
|
|
54
53
|
allowList,
|
|
55
54
|
id: params.userId,
|
|
@@ -1,9 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Strip Slack mentions (<@U123>, <@U123|name>) so command detection works on
|
|
3
|
+
* normalized text. Use in both prepare and debounce gate for consistency.
|
|
4
|
+
*/
|
|
5
|
+
export function stripSlackMentionsForCommandDetection(text) {
|
|
6
|
+
return (text ?? "")
|
|
7
|
+
.replace(/<@[^>]+>/g, " ")
|
|
8
|
+
.replace(/\s+/g, " ")
|
|
9
|
+
.trim();
|
|
10
|
+
}
|
|
1
11
|
export function normalizeSlackSlashCommandName(raw) {
|
|
2
12
|
return raw.replace(/^\/+/, "");
|
|
3
13
|
}
|
|
4
14
|
export function resolveSlackSlashCommandConfig(raw) {
|
|
5
|
-
const normalizedName = normalizeSlackSlashCommandName(raw?.name?.trim() || "
|
|
6
|
-
const name = normalizedName || "
|
|
15
|
+
const normalizedName = normalizeSlackSlashCommandName(raw?.name?.trim() || "poolbot");
|
|
16
|
+
const name = normalizedName || "poolbot";
|
|
7
17
|
return {
|
|
8
18
|
enabled: raw?.enabled === true,
|
|
9
19
|
name,
|
|
@@ -12,6 +22,7 @@ export function resolveSlackSlashCommandConfig(raw) {
|
|
|
12
22
|
};
|
|
13
23
|
}
|
|
14
24
|
export function buildSlackSlashCommandMatcher(name) {
|
|
15
|
-
const
|
|
25
|
+
const normalized = normalizeSlackSlashCommandName(name);
|
|
26
|
+
const escaped = normalized.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
16
27
|
return new RegExp(`^/?${escaped}$`);
|
|
17
28
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { enqueueSystemEvent } from "../../../infra/system-events.js";
|
|
2
2
|
import { parseSlackModalPrivateMetadata } from "../../modal-metadata.js";
|
|
3
|
-
// Prefix for
|
|
4
|
-
const POOLBOT_ACTION_PREFIX = "
|
|
3
|
+
// Prefix for Pool Bot-generated action IDs to scope our handler
|
|
4
|
+
const POOLBOT_ACTION_PREFIX = "poolbot:";
|
|
5
5
|
function readOptionValues(options) {
|
|
6
6
|
if (!Array.isArray(options)) {
|
|
7
7
|
return undefined;
|
|
@@ -255,7 +255,7 @@ export function registerSlackInteractionEvents(params) {
|
|
|
255
255
|
if (typeof ctx.app.action !== "function") {
|
|
256
256
|
return;
|
|
257
257
|
}
|
|
258
|
-
// Handle Block Kit button clicks from
|
|
258
|
+
// Handle Block Kit button clicks from Pool Bot-generated messages
|
|
259
259
|
// Only matches action_ids that start with our prefix to avoid interfering
|
|
260
260
|
// with other Slack integrations or future features
|
|
261
261
|
ctx.app.action(new RegExp(`^${POOLBOT_ACTION_PREFIX}`), async (args) => {
|
|
@@ -378,7 +378,7 @@ export function registerSlackInteractionEvents(params) {
|
|
|
378
378
|
if (typeof ctx.app.view !== "function") {
|
|
379
379
|
return;
|
|
380
380
|
}
|
|
381
|
-
// Handle
|
|
381
|
+
// Handle Pool Bot modal submissions with callback_ids scoped by our prefix.
|
|
382
382
|
ctx.app.view(new RegExp(`^${POOLBOT_ACTION_PREFIX}`), async ({ ack, body }) => {
|
|
383
383
|
await ack();
|
|
384
384
|
const typedBody = body;
|