@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
|
@@ -1,33 +1,88 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { buildCommandTextFromArgs, findCommandByNativeName, listNativeCommandSpecsForConfig, parseCommandArgs, resolveCommandArgMenu, } from "../../auto-reply/commands-registry.js";
|
|
4
|
-
import { listSkillCommandsForAgents } from "../../auto-reply/skill-commands.js";
|
|
5
|
-
import { dispatchReplyWithDispatcher } from "../../auto-reply/reply/provider-dispatcher.js";
|
|
6
|
-
import { finalizeInboundContext } from "../../auto-reply/reply/inbound-context.js";
|
|
1
|
+
import { formatAllowlistMatchMeta } from "../../channels/allowlist-match.js";
|
|
2
|
+
import { resolveCommandAuthorizedFromAuthorizers } from "../../channels/command-gating.js";
|
|
7
3
|
import { resolveNativeCommandsEnabled, resolveNativeSkillsEnabled } from "../../config/commands.js";
|
|
8
|
-
import { resolveMarkdownTableMode } from "../../config/markdown-tables.js";
|
|
9
4
|
import { danger, logVerbose } from "../../globals.js";
|
|
10
5
|
import { buildPairingReply } from "../../pairing/pairing-messages.js";
|
|
11
6
|
import { readChannelAllowFromStore, upsertChannelPairingRequest, } from "../../pairing/pairing-store.js";
|
|
12
|
-
import {
|
|
13
|
-
import { resolveConversationLabel } from "../../channels/conversation-label.js";
|
|
14
|
-
import { resolveCommandAuthorizedFromAuthorizers } from "../../channels/command-gating.js";
|
|
15
|
-
import { formatAllowlistMatchMeta } from "../../channels/allowlist-match.js";
|
|
7
|
+
import { chunkItems } from "../../utils/chunk-items.js";
|
|
16
8
|
import { normalizeAllowList, normalizeAllowListLower, resolveSlackAllowListMatch, resolveSlackUserAllowed, } from "./allow-list.js";
|
|
17
9
|
import { resolveSlackChannelConfig } from "./channel-config.js";
|
|
18
10
|
import { buildSlackSlashCommandMatcher, resolveSlackSlashCommandConfig } from "./commands.js";
|
|
11
|
+
import { normalizeSlackChannelType } from "./context.js";
|
|
19
12
|
import { isSlackChannelAllowedByPolicy } from "./policy.js";
|
|
20
|
-
import {
|
|
13
|
+
import { resolveSlackRoomContextHints } from "./room-context.js";
|
|
21
14
|
const SLACK_COMMAND_ARG_ACTION_ID = "poolbot_cmdarg";
|
|
22
15
|
const SLACK_COMMAND_ARG_VALUE_PREFIX = "cmdarg";
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
16
|
+
const SLACK_COMMAND_ARG_BUTTON_ROW_SIZE = 5;
|
|
17
|
+
const SLACK_COMMAND_ARG_OVERFLOW_MIN = 3;
|
|
18
|
+
const SLACK_COMMAND_ARG_OVERFLOW_MAX = 5;
|
|
19
|
+
const SLACK_COMMAND_ARG_SELECT_OPTIONS_MAX = 100;
|
|
20
|
+
const SLACK_COMMAND_ARG_SELECT_OPTION_VALUE_MAX = 75;
|
|
21
|
+
const SLACK_COMMAND_ARG_EXTERNAL_PREFIX = "poolbot_cmdarg_ext:";
|
|
22
|
+
const SLACK_COMMAND_ARG_EXTERNAL_TTL_MS = 10 * 60 * 1000;
|
|
23
|
+
const SLACK_HEADER_TEXT_MAX = 150;
|
|
24
|
+
const slackExternalArgMenuStore = new Map();
|
|
25
|
+
function truncatePlainText(value, max) {
|
|
26
|
+
const trimmed = value.trim();
|
|
27
|
+
if (trimmed.length <= max) {
|
|
28
|
+
return trimmed;
|
|
29
|
+
}
|
|
30
|
+
if (max <= 1) {
|
|
31
|
+
return trimmed.slice(0, max);
|
|
32
|
+
}
|
|
33
|
+
return `${trimmed.slice(0, max - 1)}…`;
|
|
34
|
+
}
|
|
35
|
+
function escapeSlackMrkdwn(value) {
|
|
36
|
+
return value
|
|
37
|
+
.replaceAll("\\", "\\\\")
|
|
38
|
+
.replaceAll("&", "&")
|
|
39
|
+
.replaceAll("<", "<")
|
|
40
|
+
.replaceAll(">", ">")
|
|
41
|
+
.replace(/([*_`~])/g, "\\$1");
|
|
42
|
+
}
|
|
43
|
+
function buildSlackArgMenuConfirm(params) {
|
|
44
|
+
const command = escapeSlackMrkdwn(params.command);
|
|
45
|
+
const arg = escapeSlackMrkdwn(params.arg);
|
|
46
|
+
return {
|
|
47
|
+
title: { type: "plain_text", text: "Confirm selection" },
|
|
48
|
+
text: {
|
|
49
|
+
type: "mrkdwn",
|
|
50
|
+
text: `Run */${command}* with *${arg}* set to this value?`,
|
|
51
|
+
},
|
|
52
|
+
confirm: { type: "plain_text", text: "Run command" },
|
|
53
|
+
deny: { type: "plain_text", text: "Cancel" },
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
function pruneSlackExternalArgMenuStore(now = Date.now()) {
|
|
57
|
+
for (const [token, entry] of slackExternalArgMenuStore.entries()) {
|
|
58
|
+
if (entry.expiresAt <= now) {
|
|
59
|
+
slackExternalArgMenuStore.delete(token);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
function storeSlackExternalArgMenu(params) {
|
|
64
|
+
pruneSlackExternalArgMenuStore();
|
|
65
|
+
const token = `${Date.now().toString(36)}${Math.random().toString(36).slice(2, 10)}`;
|
|
66
|
+
slackExternalArgMenuStore.set(token, {
|
|
67
|
+
choices: params.choices,
|
|
68
|
+
userId: params.userId,
|
|
69
|
+
expiresAt: Date.now() + SLACK_COMMAND_ARG_EXTERNAL_TTL_MS,
|
|
70
|
+
});
|
|
71
|
+
return token;
|
|
72
|
+
}
|
|
73
|
+
function readSlackExternalArgMenuToken(raw) {
|
|
74
|
+
if (typeof raw !== "string" || !raw.startsWith(SLACK_COMMAND_ARG_EXTERNAL_PREFIX)) {
|
|
75
|
+
return undefined;
|
|
76
|
+
}
|
|
77
|
+
const token = raw.slice(SLACK_COMMAND_ARG_EXTERNAL_PREFIX.length).trim();
|
|
78
|
+
return token.length > 0 ? token : undefined;
|
|
79
|
+
}
|
|
80
|
+
let commandsRegistry;
|
|
81
|
+
async function getCommandsRegistry() {
|
|
82
|
+
if (!commandsRegistry) {
|
|
83
|
+
commandsRegistry = await import("../../auto-reply/commands-registry.js");
|
|
29
84
|
}
|
|
30
|
-
return
|
|
85
|
+
return commandsRegistry;
|
|
31
86
|
}
|
|
32
87
|
function encodeSlackCommandArgValue(parts) {
|
|
33
88
|
return [
|
|
@@ -39,14 +94,17 @@ function encodeSlackCommandArgValue(parts) {
|
|
|
39
94
|
].join("|");
|
|
40
95
|
}
|
|
41
96
|
function parseSlackCommandArgValue(raw) {
|
|
42
|
-
if (!raw)
|
|
97
|
+
if (!raw) {
|
|
43
98
|
return null;
|
|
99
|
+
}
|
|
44
100
|
const parts = raw.split("|");
|
|
45
|
-
if (parts.length !== 5 || parts[0] !== SLACK_COMMAND_ARG_VALUE_PREFIX)
|
|
101
|
+
if (parts.length !== 5 || parts[0] !== SLACK_COMMAND_ARG_VALUE_PREFIX) {
|
|
46
102
|
return null;
|
|
103
|
+
}
|
|
47
104
|
const [, command, arg, value, userId] = parts;
|
|
48
|
-
if (!command || !arg || !value || !userId)
|
|
105
|
+
if (!command || !arg || !value || !userId) {
|
|
49
106
|
return null;
|
|
107
|
+
}
|
|
50
108
|
const decode = (text) => {
|
|
51
109
|
try {
|
|
52
110
|
return decodeURIComponent(text);
|
|
@@ -59,8 +117,9 @@ function parseSlackCommandArgValue(raw) {
|
|
|
59
117
|
const decodedArg = decode(arg);
|
|
60
118
|
const decodedValue = decode(value);
|
|
61
119
|
const decodedUserId = decode(userId);
|
|
62
|
-
if (!decodedCommand || !decodedArg || !decodedValue || !decodedUserId)
|
|
120
|
+
if (!decodedCommand || !decodedArg || !decodedValue || !decodedUserId) {
|
|
63
121
|
return null;
|
|
122
|
+
}
|
|
64
123
|
return {
|
|
65
124
|
command: decodedCommand,
|
|
66
125
|
arg: decodedArg,
|
|
@@ -69,33 +128,112 @@ function parseSlackCommandArgValue(raw) {
|
|
|
69
128
|
};
|
|
70
129
|
}
|
|
71
130
|
function buildSlackCommandArgMenuBlocks(params) {
|
|
72
|
-
const
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
arg: params.arg,
|
|
81
|
-
value: choice.value,
|
|
82
|
-
userId: params.userId,
|
|
83
|
-
}),
|
|
84
|
-
})),
|
|
131
|
+
const encodedChoices = params.choices.map((choice) => ({
|
|
132
|
+
label: choice.label,
|
|
133
|
+
value: encodeSlackCommandArgValue({
|
|
134
|
+
command: params.command,
|
|
135
|
+
arg: params.arg,
|
|
136
|
+
value: choice.value,
|
|
137
|
+
userId: params.userId,
|
|
138
|
+
}),
|
|
85
139
|
}));
|
|
140
|
+
const canUseStaticSelect = encodedChoices.every((choice) => choice.value.length <= SLACK_COMMAND_ARG_SELECT_OPTION_VALUE_MAX);
|
|
141
|
+
const canUseOverflow = canUseStaticSelect &&
|
|
142
|
+
encodedChoices.length >= SLACK_COMMAND_ARG_OVERFLOW_MIN &&
|
|
143
|
+
encodedChoices.length <= SLACK_COMMAND_ARG_OVERFLOW_MAX;
|
|
144
|
+
const canUseExternalSelect = params.supportsExternalSelect &&
|
|
145
|
+
canUseStaticSelect &&
|
|
146
|
+
encodedChoices.length > SLACK_COMMAND_ARG_SELECT_OPTIONS_MAX;
|
|
147
|
+
const rows = canUseOverflow
|
|
148
|
+
? [
|
|
149
|
+
{
|
|
150
|
+
type: "actions",
|
|
151
|
+
elements: [
|
|
152
|
+
{
|
|
153
|
+
type: "overflow",
|
|
154
|
+
action_id: SLACK_COMMAND_ARG_ACTION_ID,
|
|
155
|
+
confirm: buildSlackArgMenuConfirm({ command: params.command, arg: params.arg }),
|
|
156
|
+
options: encodedChoices.map((choice) => ({
|
|
157
|
+
text: { type: "plain_text", text: choice.label.slice(0, 75) },
|
|
158
|
+
value: choice.value,
|
|
159
|
+
})),
|
|
160
|
+
},
|
|
161
|
+
],
|
|
162
|
+
},
|
|
163
|
+
]
|
|
164
|
+
: canUseExternalSelect
|
|
165
|
+
? [
|
|
166
|
+
{
|
|
167
|
+
type: "actions",
|
|
168
|
+
block_id: `${SLACK_COMMAND_ARG_EXTERNAL_PREFIX}${params.createExternalMenuToken(encodedChoices)}`,
|
|
169
|
+
elements: [
|
|
170
|
+
{
|
|
171
|
+
type: "external_select",
|
|
172
|
+
action_id: SLACK_COMMAND_ARG_ACTION_ID,
|
|
173
|
+
confirm: buildSlackArgMenuConfirm({ command: params.command, arg: params.arg }),
|
|
174
|
+
min_query_length: 0,
|
|
175
|
+
placeholder: {
|
|
176
|
+
type: "plain_text",
|
|
177
|
+
text: `Search ${params.arg}`,
|
|
178
|
+
},
|
|
179
|
+
},
|
|
180
|
+
],
|
|
181
|
+
},
|
|
182
|
+
]
|
|
183
|
+
: encodedChoices.length <= SLACK_COMMAND_ARG_BUTTON_ROW_SIZE || !canUseStaticSelect
|
|
184
|
+
? chunkItems(encodedChoices, SLACK_COMMAND_ARG_BUTTON_ROW_SIZE).map((choices) => ({
|
|
185
|
+
type: "actions",
|
|
186
|
+
elements: choices.map((choice) => ({
|
|
187
|
+
type: "button",
|
|
188
|
+
action_id: SLACK_COMMAND_ARG_ACTION_ID,
|
|
189
|
+
text: { type: "plain_text", text: choice.label },
|
|
190
|
+
value: choice.value,
|
|
191
|
+
confirm: buildSlackArgMenuConfirm({ command: params.command, arg: params.arg }),
|
|
192
|
+
})),
|
|
193
|
+
}))
|
|
194
|
+
: chunkItems(encodedChoices, SLACK_COMMAND_ARG_SELECT_OPTIONS_MAX).map((choices, index) => ({
|
|
195
|
+
type: "actions",
|
|
196
|
+
elements: [
|
|
197
|
+
{
|
|
198
|
+
type: "static_select",
|
|
199
|
+
action_id: SLACK_COMMAND_ARG_ACTION_ID,
|
|
200
|
+
confirm: buildSlackArgMenuConfirm({ command: params.command, arg: params.arg }),
|
|
201
|
+
placeholder: {
|
|
202
|
+
type: "plain_text",
|
|
203
|
+
text: index === 0 ? `Choose ${params.arg}` : `Choose ${params.arg} (${index + 1})`,
|
|
204
|
+
},
|
|
205
|
+
options: choices.map((choice) => ({
|
|
206
|
+
text: { type: "plain_text", text: choice.label.slice(0, 75) },
|
|
207
|
+
value: choice.value,
|
|
208
|
+
})),
|
|
209
|
+
},
|
|
210
|
+
],
|
|
211
|
+
}));
|
|
212
|
+
const headerText = truncatePlainText(`/${params.command}: choose ${params.arg}`, SLACK_HEADER_TEXT_MAX);
|
|
213
|
+
const sectionText = truncatePlainText(params.title, 3000);
|
|
214
|
+
const contextText = truncatePlainText(`Select one option to continue /${params.command} (${params.arg})`, 3000);
|
|
86
215
|
return [
|
|
216
|
+
{
|
|
217
|
+
type: "header",
|
|
218
|
+
text: { type: "plain_text", text: headerText },
|
|
219
|
+
},
|
|
87
220
|
{
|
|
88
221
|
type: "section",
|
|
89
|
-
text: { type: "mrkdwn", text:
|
|
222
|
+
text: { type: "mrkdwn", text: sectionText },
|
|
223
|
+
},
|
|
224
|
+
{
|
|
225
|
+
type: "context",
|
|
226
|
+
elements: [{ type: "mrkdwn", text: contextText }],
|
|
90
227
|
},
|
|
91
228
|
...rows,
|
|
92
229
|
];
|
|
93
230
|
}
|
|
94
|
-
export function registerSlackMonitorSlashCommands(params) {
|
|
231
|
+
export async function registerSlackMonitorSlashCommands(params) {
|
|
95
232
|
const { ctx, account } = params;
|
|
96
233
|
const cfg = ctx.cfg;
|
|
97
234
|
const runtime = ctx.runtime;
|
|
98
235
|
const supportsInteractiveArgMenus = typeof ctx.app.action === "function";
|
|
236
|
+
const supportsExternalArgMenus = typeof ctx.app.options === "function";
|
|
99
237
|
const slashCommand = resolveSlackSlashCommandConfig(ctx.slashCommand ?? account.config.slashCommand);
|
|
100
238
|
const handleSlashCommand = async (p) => {
|
|
101
239
|
const { command, ack, respond, prompt, commandArgs, commandDefinition } = p;
|
|
@@ -108,10 +246,12 @@ export function registerSlackMonitorSlashCommands(params) {
|
|
|
108
246
|
return;
|
|
109
247
|
}
|
|
110
248
|
await ack();
|
|
111
|
-
if (ctx.botUserId && command.user_id === ctx.botUserId)
|
|
249
|
+
if (ctx.botUserId && command.user_id === ctx.botUserId) {
|
|
112
250
|
return;
|
|
251
|
+
}
|
|
113
252
|
const channelInfo = await ctx.resolveChannelName(command.channel_id);
|
|
114
|
-
const
|
|
253
|
+
const rawChannelType = channelInfo?.type ?? (command.channel_name === "directmessage" ? "im" : undefined);
|
|
254
|
+
const channelType = normalizeSlackChannelType(rawChannelType, command.channel_id);
|
|
115
255
|
const isDirectMessage = channelType === "im";
|
|
116
256
|
const isGroupDm = channelType === "mpim";
|
|
117
257
|
const isRoom = channelType === "channel" || channelType === "group";
|
|
@@ -130,7 +270,9 @@ export function registerSlackMonitorSlashCommands(params) {
|
|
|
130
270
|
const storeAllowFrom = await readChannelAllowFromStore("slack").catch(() => []);
|
|
131
271
|
const effectiveAllowFrom = normalizeAllowList([...ctx.allowFrom, ...storeAllowFrom]);
|
|
132
272
|
const effectiveAllowFromLower = normalizeAllowListLower(effectiveAllowFrom);
|
|
133
|
-
|
|
273
|
+
// Privileged command surface: compute CommandAuthorized, don't assume true.
|
|
274
|
+
// Keep this aligned with the Slack message path (message-handler/prepare.ts).
|
|
275
|
+
let commandAuthorized = false;
|
|
134
276
|
let channelConfig = null;
|
|
135
277
|
if (isDirectMessage) {
|
|
136
278
|
if (!ctx.dmEnabled || ctx.dmPolicy === "disabled") {
|
|
@@ -177,7 +319,6 @@ export function registerSlackMonitorSlashCommands(params) {
|
|
|
177
319
|
}
|
|
178
320
|
return;
|
|
179
321
|
}
|
|
180
|
-
commandAuthorized = true;
|
|
181
322
|
}
|
|
182
323
|
}
|
|
183
324
|
if (isRoom) {
|
|
@@ -236,6 +377,13 @@ export function registerSlackMonitorSlashCommands(params) {
|
|
|
236
377
|
id: command.user_id,
|
|
237
378
|
name: senderName,
|
|
238
379
|
}).allowed;
|
|
380
|
+
// DMs: allow chatting in dmPolicy=open, but keep privileged command gating intact by setting
|
|
381
|
+
// CommandAuthorized based on allowlists/access-groups (downstream decides which commands need it).
|
|
382
|
+
commandAuthorized = resolveCommandAuthorizedFromAuthorizers({
|
|
383
|
+
useAccessGroups: ctx.useAccessGroups,
|
|
384
|
+
authorizers: [{ configured: effectiveAllowFromLower.length > 0, allowed: ownerAllowed }],
|
|
385
|
+
modeWhenAccessGroupsOff: "configured",
|
|
386
|
+
});
|
|
239
387
|
if (isRoomish) {
|
|
240
388
|
commandAuthorized = resolveCommandAuthorizedFromAuthorizers({
|
|
241
389
|
useAccessGroups: ctx.useAccessGroups,
|
|
@@ -243,6 +391,7 @@ export function registerSlackMonitorSlashCommands(params) {
|
|
|
243
391
|
{ configured: effectiveAllowFromLower.length > 0, allowed: ownerAllowed },
|
|
244
392
|
{ configured: channelUsersAllowlistConfigured, allowed: channelUserAllowed },
|
|
245
393
|
],
|
|
394
|
+
modeWhenAccessGroupsOff: "configured",
|
|
246
395
|
});
|
|
247
396
|
if (ctx.useAccessGroups && !commandAuthorized) {
|
|
248
397
|
await respond({
|
|
@@ -253,7 +402,8 @@ export function registerSlackMonitorSlashCommands(params) {
|
|
|
253
402
|
}
|
|
254
403
|
}
|
|
255
404
|
if (commandDefinition && supportsInteractiveArgMenus) {
|
|
256
|
-
const
|
|
405
|
+
const reg = await getCommandsRegistry();
|
|
406
|
+
const menu = reg.resolveCommandArgMenu({
|
|
257
407
|
command: commandDefinition,
|
|
258
408
|
args: commandArgs,
|
|
259
409
|
cfg,
|
|
@@ -267,6 +417,8 @@ export function registerSlackMonitorSlashCommands(params) {
|
|
|
267
417
|
arg: menu.arg.name,
|
|
268
418
|
choices: menu.choices,
|
|
269
419
|
userId: command.user_id,
|
|
420
|
+
supportsExternalSelect: supportsExternalArgMenus,
|
|
421
|
+
createExternalMenuToken: (choices) => storeSlackExternalArgMenu({ choices, userId: command.user_id }),
|
|
270
422
|
});
|
|
271
423
|
await respond({
|
|
272
424
|
text: title,
|
|
@@ -278,28 +430,33 @@ export function registerSlackMonitorSlashCommands(params) {
|
|
|
278
430
|
}
|
|
279
431
|
const channelName = channelInfo?.name;
|
|
280
432
|
const roomLabel = channelName ? `#${channelName}` : `#${command.channel_id}`;
|
|
433
|
+
const [{ resolveAgentRoute }, { finalizeInboundContext }, { dispatchReplyWithDispatcher }] = await Promise.all([
|
|
434
|
+
import("../../routing/resolve-route.js"),
|
|
435
|
+
import("../../auto-reply/reply/inbound-context.js"),
|
|
436
|
+
import("../../auto-reply/reply/provider-dispatcher.js"),
|
|
437
|
+
]);
|
|
438
|
+
const [{ resolveConversationLabel }, { createReplyPrefixOptions }] = await Promise.all([
|
|
439
|
+
import("../../channels/conversation-label.js"),
|
|
440
|
+
import("../../channels/reply-prefix.js"),
|
|
441
|
+
]);
|
|
281
442
|
const route = resolveAgentRoute({
|
|
282
443
|
cfg,
|
|
283
444
|
channel: "slack",
|
|
284
445
|
accountId: account.accountId,
|
|
285
446
|
teamId: ctx.teamId || undefined,
|
|
286
447
|
peer: {
|
|
287
|
-
kind: isDirectMessage ? "
|
|
448
|
+
kind: isDirectMessage ? "direct" : isRoom ? "channel" : "group",
|
|
288
449
|
id: isDirectMessage ? command.user_id : command.channel_id,
|
|
289
450
|
},
|
|
290
451
|
});
|
|
291
|
-
const
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
const systemPromptParts = [
|
|
297
|
-
channelDescription ? `Channel description: ${channelDescription}` : null,
|
|
298
|
-
channelConfig?.systemPrompt?.trim() || null,
|
|
299
|
-
].filter((entry) => Boolean(entry));
|
|
300
|
-
const groupSystemPrompt = systemPromptParts.length > 0 ? systemPromptParts.join("\n\n") : undefined;
|
|
452
|
+
const { untrustedChannelMetadata, groupSystemPrompt } = resolveSlackRoomContextHints({
|
|
453
|
+
isRoomish,
|
|
454
|
+
channelInfo,
|
|
455
|
+
channelConfig,
|
|
456
|
+
});
|
|
301
457
|
const ctxPayload = finalizeInboundContext({
|
|
302
458
|
Body: prompt,
|
|
459
|
+
BodyForAgent: prompt,
|
|
303
460
|
RawBody: prompt,
|
|
304
461
|
CommandBody: prompt,
|
|
305
462
|
CommandArgs: commandArgs,
|
|
@@ -322,6 +479,7 @@ export function registerSlackMonitorSlashCommands(params) {
|
|
|
322
479
|
}) ?? (isDirectMessage ? senderName : roomLabel),
|
|
323
480
|
GroupSubject: isRoomish ? roomLabel : undefined,
|
|
324
481
|
GroupSystemPrompt: isRoomish ? groupSystemPrompt : undefined,
|
|
482
|
+
UntrustedContext: untrustedChannelMetadata ? [untrustedChannelMetadata] : undefined,
|
|
325
483
|
SenderName: senderName,
|
|
326
484
|
SenderId: command.user_id,
|
|
327
485
|
Provider: "slack",
|
|
@@ -337,34 +495,20 @@ export function registerSlackMonitorSlashCommands(params) {
|
|
|
337
495
|
OriginatingChannel: "slack",
|
|
338
496
|
OriginatingTo: `user:${command.user_id}`,
|
|
339
497
|
});
|
|
340
|
-
const {
|
|
341
|
-
ctx: ctxPayload,
|
|
498
|
+
const { onModelSelected, ...prefixOptions } = createReplyPrefixOptions({
|
|
342
499
|
cfg,
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
await deliverSlackSlashReplies({
|
|
347
|
-
replies: [payload],
|
|
348
|
-
respond,
|
|
349
|
-
ephemeral: slashCommand.ephemeral,
|
|
350
|
-
textLimit: ctx.textLimit,
|
|
351
|
-
chunkMode: resolveChunkMode(cfg, "slack", route.accountId),
|
|
352
|
-
tableMode: resolveMarkdownTableMode({
|
|
353
|
-
cfg,
|
|
354
|
-
channel: "slack",
|
|
355
|
-
accountId: route.accountId,
|
|
356
|
-
}),
|
|
357
|
-
});
|
|
358
|
-
},
|
|
359
|
-
onError: (err, info) => {
|
|
360
|
-
runtime.error?.(danger(`slack slash ${info.kind} reply failed: ${String(err)}`));
|
|
361
|
-
},
|
|
362
|
-
},
|
|
363
|
-
replyOptions: { skillFilter: channelConfig?.skills },
|
|
500
|
+
agentId: route.agentId,
|
|
501
|
+
channel: "slack",
|
|
502
|
+
accountId: route.accountId,
|
|
364
503
|
});
|
|
365
|
-
|
|
504
|
+
const deliverSlashPayloads = async (replies) => {
|
|
505
|
+
const [{ deliverSlackSlashReplies }, { resolveChunkMode }, { resolveMarkdownTableMode }] = await Promise.all([
|
|
506
|
+
import("./replies.js"),
|
|
507
|
+
import("../../auto-reply/chunk.js"),
|
|
508
|
+
import("../../config/markdown-tables.js"),
|
|
509
|
+
]);
|
|
366
510
|
await deliverSlackSlashReplies({
|
|
367
|
-
replies
|
|
511
|
+
replies,
|
|
368
512
|
respond,
|
|
369
513
|
ephemeral: slashCommand.ephemeral,
|
|
370
514
|
textLimit: ctx.textLimit,
|
|
@@ -375,6 +519,24 @@ export function registerSlackMonitorSlashCommands(params) {
|
|
|
375
519
|
accountId: route.accountId,
|
|
376
520
|
}),
|
|
377
521
|
});
|
|
522
|
+
};
|
|
523
|
+
const { counts } = await dispatchReplyWithDispatcher({
|
|
524
|
+
ctx: ctxPayload,
|
|
525
|
+
cfg,
|
|
526
|
+
dispatcherOptions: {
|
|
527
|
+
...prefixOptions,
|
|
528
|
+
deliver: async (payload) => deliverSlashPayloads([payload]),
|
|
529
|
+
onError: (err, info) => {
|
|
530
|
+
runtime.error?.(danger(`slack slash ${info.kind} reply failed: ${String(err)}`));
|
|
531
|
+
},
|
|
532
|
+
},
|
|
533
|
+
replyOptions: {
|
|
534
|
+
skillFilter: channelConfig?.skills,
|
|
535
|
+
onModelSelected,
|
|
536
|
+
},
|
|
537
|
+
});
|
|
538
|
+
if (counts.final + counts.tool + counts.block === 0) {
|
|
539
|
+
await deliverSlashPayloads([]);
|
|
378
540
|
}
|
|
379
541
|
}
|
|
380
542
|
catch (err) {
|
|
@@ -395,22 +557,31 @@ export function registerSlackMonitorSlashCommands(params) {
|
|
|
395
557
|
providerSetting: account.config.commands?.nativeSkills,
|
|
396
558
|
globalSetting: cfg.commands?.nativeSkills,
|
|
397
559
|
});
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
560
|
+
let reg;
|
|
561
|
+
let nativeCommands = [];
|
|
562
|
+
if (nativeEnabled) {
|
|
563
|
+
reg = await getCommandsRegistry();
|
|
564
|
+
const skillCommands = nativeSkillsEnabled
|
|
565
|
+
? (await import("../../auto-reply/skill-commands.js")).listSkillCommandsForAgents({ cfg })
|
|
566
|
+
: [];
|
|
567
|
+
nativeCommands = reg.listNativeCommandSpecsForConfig(cfg, { skillCommands, provider: "slack" });
|
|
568
|
+
}
|
|
402
569
|
if (nativeCommands.length > 0) {
|
|
570
|
+
const registry = reg;
|
|
571
|
+
if (!registry) {
|
|
572
|
+
throw new Error("Missing commands registry for native Slack commands.");
|
|
573
|
+
}
|
|
403
574
|
for (const command of nativeCommands) {
|
|
404
575
|
ctx.app.command(`/${command.name}`, async ({ command: cmd, ack, respond }) => {
|
|
405
|
-
const commandDefinition = findCommandByNativeName(command.name, "slack");
|
|
576
|
+
const commandDefinition = registry.findCommandByNativeName(command.name, "slack");
|
|
406
577
|
const rawText = cmd.text?.trim() ?? "";
|
|
407
578
|
const commandArgs = commandDefinition
|
|
408
|
-
? parseCommandArgs(commandDefinition, rawText)
|
|
579
|
+
? registry.parseCommandArgs(commandDefinition, rawText)
|
|
409
580
|
: rawText
|
|
410
581
|
? { raw: rawText }
|
|
411
582
|
: undefined;
|
|
412
583
|
const prompt = commandDefinition
|
|
413
|
-
? buildCommandTextFromArgs(commandDefinition, commandArgs)
|
|
584
|
+
? registry.buildCommandTextFromArgs(commandDefinition, commandArgs)
|
|
414
585
|
: rawText
|
|
415
586
|
? `/${command.name} ${rawText}`
|
|
416
587
|
: `/${command.name}`;
|
|
@@ -438,67 +609,109 @@ export function registerSlackMonitorSlashCommands(params) {
|
|
|
438
609
|
else {
|
|
439
610
|
logVerbose("slack: slash commands disabled");
|
|
440
611
|
}
|
|
441
|
-
if (nativeCommands.length === 0 || !supportsInteractiveArgMenus)
|
|
612
|
+
if (nativeCommands.length === 0 || !supportsInteractiveArgMenus) {
|
|
442
613
|
return;
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
const
|
|
446
|
-
|
|
447
|
-
const respondFn = respond ??
|
|
448
|
-
(async (payload) => {
|
|
449
|
-
if (!body.channel?.id || !body.user?.id)
|
|
450
|
-
return;
|
|
451
|
-
await ctx.app.client.chat.postEphemeral({
|
|
452
|
-
token: ctx.botToken,
|
|
453
|
-
channel: body.channel.id,
|
|
454
|
-
user: body.user.id,
|
|
455
|
-
text: payload.text,
|
|
456
|
-
blocks: payload.blocks,
|
|
457
|
-
});
|
|
458
|
-
});
|
|
459
|
-
const parsed = parseSlackCommandArgValue(action?.value);
|
|
460
|
-
if (!parsed) {
|
|
461
|
-
await respondFn({
|
|
462
|
-
text: "Sorry, that button is no longer valid.",
|
|
463
|
-
response_type: "ephemeral",
|
|
464
|
-
});
|
|
614
|
+
}
|
|
615
|
+
const registerArgOptions = () => {
|
|
616
|
+
const optionsHandler = ctx.app.options;
|
|
617
|
+
if (typeof optionsHandler !== "function") {
|
|
465
618
|
return;
|
|
466
619
|
}
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
620
|
+
optionsHandler(SLACK_COMMAND_ARG_ACTION_ID, async ({ ack, body }) => {
|
|
621
|
+
const typedBody = body;
|
|
622
|
+
pruneSlackExternalArgMenuStore();
|
|
623
|
+
const blockId = typedBody.actions?.[0]?.block_id ?? typedBody.block_id;
|
|
624
|
+
const token = readSlackExternalArgMenuToken(blockId);
|
|
625
|
+
if (!token) {
|
|
626
|
+
await ack({ options: [] });
|
|
627
|
+
return;
|
|
628
|
+
}
|
|
629
|
+
const entry = slackExternalArgMenuStore.get(token);
|
|
630
|
+
if (!entry) {
|
|
631
|
+
await ack({ options: [] });
|
|
632
|
+
return;
|
|
633
|
+
}
|
|
634
|
+
if (typedBody.user?.id && typedBody.user.id !== entry.userId) {
|
|
635
|
+
await ack({ options: [] });
|
|
636
|
+
return;
|
|
637
|
+
}
|
|
638
|
+
const query = typedBody.value?.trim().toLowerCase() ?? "";
|
|
639
|
+
const options = entry.choices
|
|
640
|
+
.filter((choice) => !query || choice.label.toLowerCase().includes(query))
|
|
641
|
+
.slice(0, SLACK_COMMAND_ARG_SELECT_OPTIONS_MAX)
|
|
642
|
+
.map((choice) => ({
|
|
643
|
+
text: { type: "plain_text", text: choice.label.slice(0, 75) },
|
|
644
|
+
value: choice.value,
|
|
645
|
+
}));
|
|
646
|
+
await ack({ options });
|
|
647
|
+
});
|
|
648
|
+
};
|
|
649
|
+
registerArgOptions();
|
|
650
|
+
const registerArgAction = (actionId) => {
|
|
651
|
+
ctx.app.action(actionId, async (args) => {
|
|
652
|
+
const { ack, body, respond } = args;
|
|
653
|
+
const action = args.action;
|
|
654
|
+
await ack();
|
|
655
|
+
const respondFn = respond ??
|
|
656
|
+
(async (payload) => {
|
|
657
|
+
if (!body.channel?.id || !body.user?.id) {
|
|
658
|
+
return;
|
|
659
|
+
}
|
|
660
|
+
await ctx.app.client.chat.postEphemeral({
|
|
661
|
+
token: ctx.botToken,
|
|
662
|
+
channel: body.channel.id,
|
|
663
|
+
user: body.user.id,
|
|
664
|
+
text: payload.text,
|
|
665
|
+
blocks: payload.blocks,
|
|
666
|
+
});
|
|
667
|
+
});
|
|
668
|
+
const actionValue = action?.value ?? action?.selected_option?.value;
|
|
669
|
+
const parsed = parseSlackCommandArgValue(actionValue);
|
|
670
|
+
if (!parsed) {
|
|
671
|
+
await respondFn({
|
|
672
|
+
text: "Sorry, that button is no longer valid.",
|
|
673
|
+
response_type: "ephemeral",
|
|
674
|
+
});
|
|
675
|
+
return;
|
|
676
|
+
}
|
|
677
|
+
if (body.user?.id && parsed.userId !== body.user.id) {
|
|
678
|
+
await respondFn({
|
|
679
|
+
text: "That menu is for another user.",
|
|
680
|
+
response_type: "ephemeral",
|
|
681
|
+
});
|
|
682
|
+
return;
|
|
683
|
+
}
|
|
684
|
+
const reg = await getCommandsRegistry();
|
|
685
|
+
const commandDefinition = reg.findCommandByNativeName(parsed.command, "slack");
|
|
686
|
+
const commandArgs = {
|
|
687
|
+
values: { [parsed.arg]: parsed.value },
|
|
688
|
+
};
|
|
689
|
+
const prompt = commandDefinition
|
|
690
|
+
? reg.buildCommandTextFromArgs(commandDefinition, commandArgs)
|
|
691
|
+
: `/${parsed.command} ${parsed.value}`;
|
|
692
|
+
const user = body.user;
|
|
693
|
+
const userName = user && "name" in user && user.name
|
|
694
|
+
? user.name
|
|
695
|
+
: user && "username" in user && user.username
|
|
696
|
+
? user.username
|
|
697
|
+
: (user?.id ?? "");
|
|
698
|
+
const triggerId = "trigger_id" in body ? body.trigger_id : undefined;
|
|
699
|
+
const commandPayload = {
|
|
700
|
+
user_id: user?.id ?? "",
|
|
701
|
+
user_name: userName,
|
|
702
|
+
channel_id: body.channel?.id ?? "",
|
|
703
|
+
channel_name: body.channel?.name ?? body.channel?.id ?? "",
|
|
704
|
+
trigger_id: triggerId ?? String(Date.now()),
|
|
705
|
+
};
|
|
706
|
+
await handleSlashCommand({
|
|
707
|
+
command: commandPayload,
|
|
708
|
+
ack: async () => { },
|
|
709
|
+
respond: respondFn,
|
|
710
|
+
prompt,
|
|
711
|
+
commandArgs,
|
|
712
|
+
commandDefinition: commandDefinition ?? undefined,
|
|
471
713
|
});
|
|
472
|
-
return;
|
|
473
|
-
}
|
|
474
|
-
const commandDefinition = findCommandByNativeName(parsed.command, "slack");
|
|
475
|
-
const commandArgs = {
|
|
476
|
-
values: { [parsed.arg]: parsed.value },
|
|
477
|
-
};
|
|
478
|
-
const prompt = commandDefinition
|
|
479
|
-
? buildCommandTextFromArgs(commandDefinition, commandArgs)
|
|
480
|
-
: `/${parsed.command} ${parsed.value}`;
|
|
481
|
-
const user = body.user;
|
|
482
|
-
const userName = user && "name" in user && user.name
|
|
483
|
-
? user.name
|
|
484
|
-
: user && "username" in user && user.username
|
|
485
|
-
? user.username
|
|
486
|
-
: (user?.id ?? "");
|
|
487
|
-
const triggerId = "trigger_id" in body ? body.trigger_id : undefined;
|
|
488
|
-
const commandPayload = {
|
|
489
|
-
user_id: user?.id ?? "",
|
|
490
|
-
user_name: userName,
|
|
491
|
-
channel_id: body.channel?.id ?? "",
|
|
492
|
-
channel_name: body.channel?.name ?? body.channel?.id ?? "",
|
|
493
|
-
trigger_id: triggerId ?? String(Date.now()),
|
|
494
|
-
};
|
|
495
|
-
await handleSlashCommand({
|
|
496
|
-
command: commandPayload,
|
|
497
|
-
ack: async () => { },
|
|
498
|
-
respond: respondFn,
|
|
499
|
-
prompt,
|
|
500
|
-
commandArgs,
|
|
501
|
-
commandDefinition: commandDefinition ?? undefined,
|
|
502
714
|
});
|
|
503
|
-
}
|
|
715
|
+
};
|
|
716
|
+
registerArgAction(SLACK_COMMAND_ARG_ACTION_ID);
|
|
504
717
|
}
|