@poolzin/pool-bot 2026.2.25 → 2026.2.26
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/acp/event-mapper.js +87 -22
- package/dist/acp/meta.js +12 -6
- package/dist/agents/agent-paths.js +8 -9
- package/dist/agents/agent-scope.js +7 -5
- package/dist/agents/auth-profiles/oauth.js +148 -64
- package/dist/agents/auth-profiles/session-override.js +13 -7
- package/dist/agents/bash-tools.exec-host-gateway.js +14 -4
- package/dist/agents/bash-tools.exec-runtime.js +2 -25
- package/dist/agents/bedrock-discovery.js +3 -1
- package/dist/agents/byteplus-models.js +97 -0
- package/dist/agents/chutes-oauth.js +1 -0
- package/dist/agents/cli-runner/helpers.js +4 -0
- package/dist/agents/compaction.js +41 -14
- package/dist/agents/doubao-models.js +121 -0
- package/dist/agents/failover-error.js +2 -0
- package/dist/agents/huggingface-models.js +5 -3
- package/dist/agents/live-model-filter.js +5 -0
- package/dist/agents/minimax-vlm.js +10 -8
- package/dist/agents/model-auth.js +6 -0
- package/dist/agents/model-catalog.js +3 -1
- package/dist/agents/model-selection.js +7 -1
- package/dist/agents/models-config.providers.js +93 -11
- package/dist/agents/ollama-stream.js +117 -4
- package/dist/agents/opencode-zen-models.js +22 -11
- package/dist/agents/pi-embedded-helpers/errors.js +55 -33
- package/dist/agents/pi-embedded-helpers/messaging-dedupe.js +10 -5
- package/dist/agents/pi-embedded-helpers/thinking.js +10 -5
- package/dist/agents/pi-embedded-helpers.js +1 -1
- package/dist/agents/pi-embedded-runner/compact.js +29 -7
- package/dist/agents/pi-embedded-runner/extensions.js +28 -26
- package/dist/agents/pi-embedded-runner/google.js +20 -8
- package/dist/agents/pi-embedded-runner/run/attempt.js +95 -36
- package/dist/agents/pi-embedded-runner/run.js +71 -12
- package/dist/agents/pi-embedded-runner/run.overflow-compaction.mocks.shared.js +11 -2
- package/dist/agents/pi-embedded-runner/session-manager-cache.js +11 -7
- package/dist/agents/pi-embedded-runner/system-prompt.js +2 -0
- package/dist/agents/pi-embedded-runner/thinking.js +42 -0
- package/dist/agents/pi-embedded-runner/tool-name-allowlist.js +19 -0
- package/dist/agents/pi-embedded-runner/utils.js +7 -10
- package/dist/agents/pi-embedded-subscribe.handlers.lifecycle.js +45 -56
- package/dist/agents/pi-embedded-subscribe.handlers.tools.js +2 -2
- package/dist/agents/pi-embedded-subscribe.js +9 -4
- package/dist/agents/pi-embedded-subscribe.tools.js +68 -14
- package/dist/agents/pi-embedded-utils.js +3 -0
- package/dist/agents/pi-extensions/compaction-safeguard-runtime.js +4 -20
- package/dist/agents/pi-extensions/compaction-safeguard.js +75 -33
- package/dist/agents/pi-settings.js +40 -0
- package/dist/agents/pi-tools.policy.js +2 -1
- package/dist/agents/provider/config-loader.js +1 -1
- package/dist/agents/sandbox/browser.js +170 -33
- package/dist/agents/sandbox/config-hash.js +14 -27
- package/dist/agents/sandbox/config.js +21 -2
- package/dist/agents/sandbox/constants.js +2 -0
- package/dist/agents/sandbox/docker.js +16 -2
- package/dist/agents/sandbox/novnc-auth.js +62 -0
- package/dist/agents/sandbox/sanitize-env-vars.js +1 -1
- package/dist/agents/sandbox/shared.js +10 -6
- package/dist/agents/sandbox-paths.js +24 -11
- package/dist/agents/schema/clean-for-gemini.js +132 -85
- package/dist/agents/session-slug.js +10 -5
- package/dist/agents/session-tool-result-guard-wrapper.js +1 -0
- package/dist/agents/session-tool-result-guard.js +3 -1
- package/dist/agents/session-transcript-repair.js +40 -6
- package/dist/agents/skills/bundled-dir.js +19 -5
- package/dist/agents/skills/env-overrides.js +124 -43
- package/dist/agents/skills/frontmatter.js +6 -6
- package/dist/agents/skills/plugin-skills.js +14 -7
- package/dist/agents/skills/workspace.js +1 -0
- package/dist/agents/subagent-announce.js +251 -49
- package/dist/agents/subagent-lifecycle-events.js +19 -0
- package/dist/agents/subagent-registry-cleanup.js +31 -0
- package/dist/agents/subagent-registry-completion.js +68 -0
- package/dist/agents/subagent-registry-queries.js +117 -0
- package/dist/agents/subagent-registry-state.js +46 -0
- package/dist/agents/subagent-registry.js +252 -221
- package/dist/agents/subagent-registry.store.js +1 -0
- package/dist/agents/subagent-registry.types.js +1 -0
- package/dist/agents/subagent-spawn.js +195 -7
- package/dist/agents/system-prompt.js +22 -6
- package/dist/agents/test-helpers/fast-coding-tools.js +1 -18
- package/dist/agents/test-helpers/fast-core-tools.js +1 -17
- package/dist/agents/timeout.js +18 -6
- package/dist/agents/tool-call-id.js +1 -1
- package/dist/agents/tool-display-common.js +162 -29
- package/dist/agents/tool-images.js +82 -9
- package/dist/agents/tool-policy.js +51 -26
- package/dist/agents/tools/browser-tool.js +2 -2
- package/dist/agents/tools/canvas-tool.js +27 -1
- package/dist/agents/tools/common.js +45 -0
- package/dist/agents/tools/discord-actions-guild.js +4 -1
- package/dist/agents/tools/gateway-tool.js +3 -1
- package/dist/agents/tools/nodes-utils.js +1 -10
- package/dist/agents/tools/sessions-send-helpers.js +12 -6
- package/dist/agents/tools/sessions-spawn-tool.js +8 -2
- package/dist/agents/tools/subagents-tool.js +2 -1
- package/dist/agents/tools/whatsapp-actions.js +10 -2
- package/dist/agents/tools/whatsapp-target-auth.js +18 -0
- package/dist/agents/transcript-policy.js +22 -8
- package/dist/agents/venice-models.js +11 -3
- package/dist/auto-reply/commands-registry.data.js +51 -0
- package/dist/auto-reply/commands-registry.js +4 -3
- package/dist/auto-reply/group-activation.js +10 -5
- package/dist/auto-reply/inbound-debounce.js +10 -5
- package/dist/auto-reply/reply/abort.js +1 -1
- package/dist/auto-reply/reply/agent-runner-execution.js +4 -1
- package/dist/auto-reply/reply/bash-command.js +41 -39
- package/dist/auto-reply/reply/command-gates.js +25 -0
- package/dist/auto-reply/reply/commands-allowlist.js +111 -72
- package/dist/auto-reply/reply/commands-bash.js +6 -5
- package/dist/auto-reply/reply/commands-config.js +30 -28
- package/dist/auto-reply/reply/commands-core.js +2 -1
- package/dist/auto-reply/reply/commands-info.js +1 -0
- package/dist/auto-reply/reply/commands-models.js +65 -14
- package/dist/auto-reply/reply/commands-session.js +237 -82
- package/dist/auto-reply/reply/commands-setunset.js +45 -0
- package/dist/auto-reply/reply/commands-subagents/action-agents.js +44 -0
- package/dist/auto-reply/reply/commands-subagents/action-focus.js +64 -0
- package/dist/auto-reply/reply/commands-subagents/action-help.js +4 -0
- package/dist/auto-reply/reply/commands-subagents/action-info.js +45 -0
- package/dist/auto-reply/reply/commands-subagents/action-kill.js +60 -0
- package/dist/auto-reply/reply/commands-subagents/action-list.js +44 -0
- package/dist/auto-reply/reply/commands-subagents/action-log.js +29 -0
- package/dist/auto-reply/reply/commands-subagents/action-send.js +119 -0
- package/dist/auto-reply/reply/commands-subagents/action-spawn.js +52 -0
- package/dist/auto-reply/reply/commands-subagents/action-unfocus.js +30 -0
- package/dist/auto-reply/reply/commands-subagents/shared.js +303 -0
- package/dist/auto-reply/reply/commands-subagents.js +51 -587
- package/dist/auto-reply/reply/commands-tts.js +10 -5
- package/dist/auto-reply/reply/config-value.js +10 -5
- package/dist/auto-reply/reply/directive-handling.model-picker.js +12 -6
- package/dist/auto-reply/reply/directive-handling.persist.js +9 -21
- package/dist/auto-reply/reply/directive-handling.shared.js +24 -4
- package/dist/auto-reply/reply/followup-runner.js +1 -0
- package/dist/auto-reply/reply/get-reply-directives-utils.js +23 -14
- package/dist/auto-reply/reply/get-reply-directives.js +17 -28
- package/dist/auto-reply/reply/get-reply-inline-actions.js +1 -0
- package/dist/auto-reply/reply/get-reply.js +71 -12
- package/dist/auto-reply/reply/model-selection.js +80 -39
- package/dist/auto-reply/reply/queue/enqueue.js +10 -5
- package/dist/auto-reply/reply/queue/state.js +13 -12
- package/dist/auto-reply/reply/reply-payloads.js +67 -36
- package/dist/auto-reply/reply/reply-reference.js +9 -8
- package/dist/auto-reply/reply/route-reply.js +15 -8
- package/dist/auto-reply/reply/session-reset-prompt.js +1 -1
- package/dist/auto-reply/reply/session.js +22 -6
- package/dist/auto-reply/reply/strip-inbound-meta.js +147 -0
- package/dist/auto-reply/reply/subagents-utils.js +56 -30
- package/dist/auto-reply/reply/typing.js +46 -21
- package/dist/auto-reply/send-policy.js +14 -7
- package/dist/auto-reply/status.js +140 -16
- package/dist/auto-reply/templating.js +10 -5
- package/dist/auto-reply/thinking.js +7 -16
- package/dist/auto-reply/tokens.js +21 -5
- package/dist/browser/bridge-server.js +36 -20
- package/dist/browser/cdp.helpers.js +7 -14
- package/dist/browser/cdp.js +35 -15
- package/dist/browser/chrome.profile-decoration.js +7 -4
- package/dist/browser/config.js +4 -0
- package/dist/browser/extension-relay-auth.js +55 -0
- package/dist/browser/extension-relay.js +74 -29
- package/dist/browser/navigation-guard.js +9 -1
- package/dist/browser/paths.js +77 -0
- package/dist/browser/profiles.js +13 -8
- package/dist/browser/pw-ai-module.js +10 -5
- package/dist/browser/pw-session.js +76 -39
- package/dist/browser/pw-tools-core.interactions.js +14 -7
- package/dist/browser/pw-tools-core.state.js +12 -6
- package/dist/browser/routes/agent.act.js +2 -2
- package/dist/browser/server-context.js +7 -0
- package/dist/build-info.json +3 -3
- package/dist/channels/allow-from.js +2 -1
- package/dist/channels/allowlists/resolve-utils.js +43 -19
- package/dist/channels/channel-config.js +14 -7
- package/dist/channels/draft-stream-loop.js +7 -0
- package/dist/channels/model-overrides.js +82 -0
- package/dist/channels/plugins/normalize/imessage.js +14 -7
- package/dist/channels/plugins/normalize/slack.js +10 -5
- package/dist/channels/plugins/normalize/telegram.js +14 -7
- package/dist/channels/plugins/outbound/discord.js +80 -8
- package/dist/channels/plugins/outbound/signal.js +11 -11
- package/dist/channels/plugins/setup-helpers.js +10 -5
- package/dist/channels/sender-label.js +14 -7
- package/dist/channels/session.js +4 -2
- package/dist/channels/status-reactions.js +297 -0
- package/dist/cli/banner.js +1 -1
- package/dist/cli/browser-cli-actions-input/register.files-downloads.js +65 -56
- package/dist/cli/cli-name.js +11 -11
- package/dist/cli/cli-utils.js +13 -3
- package/dist/cli/command-format.js +1 -1
- package/dist/cli/config-cli.js +1 -1
- package/dist/cli/daemon-cli/lifecycle-core.js +31 -19
- package/dist/cli/daemon-cli/lifecycle.js +64 -2
- package/dist/cli/daemon-cli/restart-health.js +126 -0
- package/dist/cli/daemon-cli/status.gather.js +9 -13
- package/dist/cli/daemon-cli/status.print.js +2 -10
- package/dist/cli/deps.js +27 -22
- package/dist/cli/gateway-cli/run-loop.js +23 -5
- package/dist/cli/node-cli/register.js +14 -5
- package/dist/cli/nodes-media-utils.js +7 -2
- package/dist/cli/outbound-send-deps.js +2 -9
- package/dist/cli/outbound-send-mapping.js +11 -0
- package/dist/cli/pairing-cli.js +40 -14
- package/dist/cli/plugins-cli.js +34 -41
- package/dist/cli/ports.js +11 -10
- package/dist/cli/program/command-registry.js +2 -11
- package/dist/cli/program/command-tree.js +16 -0
- package/dist/cli/program/preaction.js +13 -9
- package/dist/cli/program/register.configure.js +3 -18
- package/dist/cli/program/register.maintenance.js +2 -2
- package/dist/cli/program/register.onboard.js +2 -0
- package/dist/cli/program/register.status-health-sessions.js +16 -17
- package/dist/cli/program/register.subclis.js +93 -52
- package/dist/cli/route.js +11 -7
- package/dist/cli/system-cli.js +36 -46
- package/dist/cli/update-cli/shared.js +22 -9
- package/dist/cli/update-cli/update-command.js +89 -14
- package/dist/cli/update-cli/wizard.js +6 -12
- package/dist/commands/agent/run-context.js +18 -5
- package/dist/commands/agent/session-store.js +17 -4
- package/dist/commands/agent.js +22 -2
- package/dist/commands/agents.bindings.js +14 -7
- package/dist/commands/agents.commands.add.js +13 -9
- package/dist/commands/agents.commands.identity.js +12 -6
- package/dist/commands/agents.commands.list.js +11 -6
- package/dist/commands/agents.config.js +8 -10
- package/dist/commands/agents.providers.js +12 -6
- package/dist/commands/auth-choice-options.js +103 -75
- package/dist/commands/auth-choice.apply.byteplus.js +55 -0
- package/dist/commands/auth-choice.apply.js +4 -0
- package/dist/commands/auth-choice.apply.minimax.js +61 -13
- package/dist/commands/auth-choice.apply.openai.js +3 -1
- package/dist/commands/auth-choice.apply.volcengine.js +55 -0
- package/dist/commands/auth-choice.preferred-provider.js +2 -0
- package/dist/commands/channels/remove.js +13 -6
- package/dist/commands/channels/shared.js +4 -14
- package/dist/commands/configure.commands.js +14 -0
- package/dist/commands/configure.gateway.js +2 -4
- package/dist/commands/configure.js +1 -1
- package/dist/commands/configure.shared.js +11 -0
- package/dist/commands/daemon-install-helpers.js +2 -2
- package/dist/commands/dashboard.js +12 -10
- package/dist/commands/docs.js +14 -8
- package/dist/commands/doctor-config-flow.js +11 -9
- package/dist/commands/doctor-legacy-config.js +281 -0
- package/dist/commands/doctor-state-integrity.js +99 -23
- package/dist/commands/doctor-update.js +12 -9
- package/dist/commands/models/list.list-command.js +7 -5
- package/dist/commands/models/set-image.js +2 -21
- package/dist/commands/node-daemon-install-helpers.js +10 -8
- package/dist/commands/onboard-auth.config-minimax.js +54 -80
- package/dist/commands/onboard-auth.config-opencode.js +2 -18
- package/dist/commands/onboard-auth.credentials.js +90 -13
- package/dist/commands/onboard-auth.js +1 -1
- package/dist/commands/onboard-auth.models.js +6 -5
- package/dist/commands/onboard-hooks.js +1 -1
- package/dist/commands/onboard-non-interactive/api-keys.js +14 -7
- package/dist/commands/onboard-non-interactive/local/auth-choice.js +64 -49
- package/dist/commands/onboard-provider-auth-flags.js +14 -0
- package/dist/commands/onboard-remote.js +14 -7
- package/dist/commands/onboard.js +11 -13
- package/dist/commands/sandbox-display.js +6 -5
- package/dist/commands/status-all/diagnosis.js +14 -10
- package/dist/commands/status-all/format.js +1 -0
- package/dist/commands/status.gateway-probe.js +1 -16
- package/dist/commands/systemd-linger.js +12 -6
- package/dist/config/agent-limits.js +2 -0
- package/dist/config/commands.js +30 -16
- package/dist/config/config-paths.js +9 -11
- package/dist/config/defaults.js +22 -2
- package/dist/config/discord-preview-streaming.js +104 -0
- package/dist/config/env-vars.js +37 -8
- package/dist/config/includes.js +4 -0
- package/dist/config/io.js +97 -12
- package/dist/config/legacy.migrations.part-1.js +189 -78
- package/dist/config/legacy.shared.js +3 -1
- package/dist/config/merge-patch.js +4 -0
- package/dist/config/prototype-keys.js +4 -0
- package/dist/config/schema.help.js +44 -7
- package/dist/config/schema.labels.js +38 -6
- package/dist/config/sessions/delivery-info.js +10 -3
- package/dist/config/sessions/main-session.js +10 -5
- package/dist/config/sessions/session-file.js +33 -0
- package/dist/config/sessions/session-key.js +10 -5
- package/dist/config/sessions/store.js +1 -1
- package/dist/config/sessions.js +1 -0
- package/dist/config/zod-schema.agent-runtime.js +11 -0
- package/dist/config/zod-schema.js +148 -13
- package/dist/config/zod-schema.providers-core.js +78 -4
- package/dist/config/zod-schema.providers.js +6 -1
- package/dist/config/zod-schema.session.js +41 -2
- package/dist/cron/run-log.js +3 -0
- package/dist/cron/schedule.js +21 -10
- package/dist/cron/service/ops.js +35 -21
- package/dist/cron/service/timer.js +116 -16
- package/dist/cron/stagger.js +3 -1
- package/dist/discord/api.js +12 -6
- package/dist/discord/draft-chunking.js +22 -0
- package/dist/discord/draft-stream.js +124 -0
- package/dist/discord/monitor/agent-components.js +1 -1
- package/dist/discord/monitor/commands.js +5 -0
- package/dist/discord/monitor/gateway-plugin.js +2 -1
- package/dist/discord/monitor/listeners.js +37 -27
- package/dist/discord/monitor/message-handler.js +4 -1
- package/dist/discord/monitor/message-handler.preflight.js +65 -8
- package/dist/discord/monitor/message-handler.process.js +246 -217
- package/dist/discord/monitor/message-utils.js +143 -6
- package/dist/discord/monitor/model-picker-preferences.js +143 -0
- package/dist/discord/monitor/model-picker.js +651 -0
- package/dist/discord/monitor/native-command.js +573 -16
- package/dist/discord/monitor/provider.allowlist.js +223 -0
- package/dist/discord/monitor/provider.js +275 -347
- package/dist/discord/monitor/provider.lifecycle.js +100 -0
- package/dist/discord/monitor/reply-delivery.js +123 -16
- package/dist/discord/monitor/thread-bindings.discord-api.js +215 -0
- package/dist/discord/monitor/thread-bindings.js +4 -0
- package/dist/discord/monitor/thread-bindings.lifecycle.js +177 -0
- package/dist/discord/monitor/thread-bindings.manager.js +423 -0
- package/dist/discord/monitor/thread-bindings.messages.js +55 -0
- package/dist/discord/monitor/thread-bindings.state.js +358 -0
- package/dist/discord/monitor/thread-bindings.types.js +6 -0
- package/dist/discord/resolve-users.js +33 -21
- package/dist/discord/send.channels.js +15 -0
- package/dist/discord/send.js +3 -2
- package/dist/discord/send.outbound.js +82 -26
- package/dist/discord/send.permissions.js +83 -30
- package/dist/discord/send.reactions.js +8 -4
- package/dist/discord/token.js +10 -5
- package/dist/discord/voice/command.js +263 -0
- package/dist/discord/voice/manager.js +531 -0
- package/dist/gateway/auth.js +34 -10
- package/dist/gateway/call.js +4 -16
- package/dist/gateway/client.js +28 -4
- package/dist/gateway/config-reload.js +3 -4
- package/dist/gateway/control-ui.js +219 -96
- package/dist/gateway/hooks-mapping.js +88 -38
- package/dist/gateway/http-auth-helpers.js +3 -2
- package/dist/gateway/http-endpoint-helpers.js +1 -0
- package/dist/gateway/net.js +54 -12
- package/dist/gateway/node-invoke-system-run-approval.js +14 -35
- package/dist/gateway/node-registry.js +10 -5
- package/dist/gateway/openai-http.js +1 -0
- package/dist/gateway/openresponses-http.js +1 -0
- package/dist/gateway/origin-check.js +1 -18
- package/dist/gateway/protocol/index.js +4 -3
- package/dist/gateway/protocol/schema/cron.js +1 -0
- package/dist/gateway/protocol/schema/devices.js +1 -0
- package/dist/gateway/protocol/schema/protocol-schemas.js +2 -1
- package/dist/gateway/protocol/schema/sessions.js +6 -0
- package/dist/gateway/role-policy.js +17 -0
- package/dist/gateway/server/ws-connection/connect-policy.js +37 -0
- package/dist/gateway/server/ws-connection/message-handler.js +175 -148
- package/dist/gateway/server-chat.js +83 -25
- package/dist/gateway/server-constants.js +10 -9
- package/dist/gateway/server-cron.js +1 -0
- package/dist/gateway/server-http.js +16 -7
- package/dist/gateway/server-maintenance.js +20 -5
- package/dist/gateway/server-methods/chat.js +10 -6
- package/dist/gateway/server-methods/config.js +12 -14
- package/dist/gateway/server-methods/devices.js +17 -3
- package/dist/gateway/server-methods/models.js +11 -1
- package/dist/gateway/server-methods/sessions.js +64 -8
- package/dist/gateway/server-methods/usage.js +162 -75
- package/dist/gateway/server-node-events.js +29 -0
- package/dist/gateway/server-runtime-config.js +34 -13
- package/dist/gateway/server-startup-memory.js +17 -11
- package/dist/gateway/session-utils.fs.js +32 -34
- package/dist/gateway/sessions-resolve.js +17 -5
- package/dist/gateway/test-helpers.openai-mock.js +14 -7
- package/dist/gateway/tools-invoke-http.js +21 -10
- package/dist/hooks/bundled/bootstrap-extra-files/handler.js +3 -1
- package/dist/hooks/bundled/command-logger/handler.js +7 -2
- package/dist/hooks/bundled/session-memory/handler.js +6 -5
- package/dist/hooks/frontmatter.js +6 -6
- package/dist/hooks/gmail-watcher.js +11 -6
- package/dist/hooks/internal-hooks.js +11 -1
- package/dist/hooks/llm-slug-generator.js +4 -1
- package/dist/hooks/workspace.js +47 -17
- package/dist/imessage/accounts.js +9 -20
- package/dist/imessage/monitor/inbound-processing.js +2 -1
- package/dist/infra/archive.js +174 -73
- package/dist/infra/control-ui-assets.js +14 -6
- package/dist/infra/device-pairing.js +108 -29
- package/dist/infra/env.js +10 -5
- package/dist/infra/exec-approvals-allowlist.js +122 -0
- package/dist/infra/exec-approvals-analysis.js +34 -3
- package/dist/infra/exec-approvals.js +5 -17
- package/dist/infra/exec-safe-bin-policy.js +53 -45
- package/dist/infra/fs-safe.js +71 -39
- package/dist/infra/gateway-lock.js +6 -2
- package/dist/infra/heartbeat-wake.js +6 -12
- package/dist/infra/host-env-security-policy.json +19 -0
- package/dist/infra/host-env-security.js +66 -0
- package/dist/infra/net/ssrf.js +131 -38
- package/dist/infra/outbound/bound-delivery-router.js +88 -0
- package/dist/infra/outbound/channel-selection.js +12 -6
- package/dist/infra/outbound/envelope.js +1 -1
- package/dist/infra/outbound/format.js +12 -6
- package/dist/infra/outbound/payloads.js +14 -7
- package/dist/infra/outbound/session-binding-service.js +123 -0
- package/dist/infra/path-guards.js +25 -0
- package/dist/infra/provider-usage.fetch.codex.js +7 -15
- package/dist/infra/provider-usage.fetch.gemini.js +14 -11
- package/dist/infra/provider-usage.fetch.shared.js +30 -1
- package/dist/infra/provider-usage.fetch.zai.js +10 -9
- package/dist/infra/retry-policy.js +4 -2
- package/dist/infra/retry.js +9 -5
- package/dist/infra/session-cost-usage.js +107 -59
- package/dist/infra/session-maintenance-warning.js +3 -1
- package/dist/infra/shell-env.js +98 -34
- package/dist/infra/ssh-config.js +12 -6
- package/dist/infra/system-run-command.js +49 -4
- package/dist/infra/update-channels.js +10 -5
- package/dist/line/accounts.js +5 -7
- package/dist/line/bot-access.js +8 -20
- package/dist/line/bot-handlers.js +3 -1
- package/dist/link-understanding/detect.js +15 -7
- package/dist/media/constants.js +15 -6
- package/dist/media/image-ops.js +7 -0
- package/dist/media/local-roots.js +3 -2
- package/dist/media-understanding/apply.js +4 -1
- package/dist/media-understanding/concurrency.js +8 -20
- package/dist/memory/backend-config.js +45 -6
- package/dist/memory/embeddings.js +10 -4
- package/dist/memory/fs-utils.js +23 -0
- package/dist/memory/manager-search.js +12 -6
- package/dist/memory/manager-sync-ops.js +12 -2
- package/dist/memory/qmd-manager.js +466 -53
- package/dist/memory/query-expansion.js +167 -3
- package/dist/memory/status-format.js +10 -5
- package/dist/memory/sync-memory-files.js +1 -1
- package/dist/node-host/invoke-system-run.js +281 -0
- package/dist/node-host/invoke.js +55 -337
- package/dist/pairing/pairing-store.js +22 -0
- package/dist/plugin-sdk/allow-from.js +1 -1
- package/dist/plugin-sdk/command-auth.js +3 -1
- package/dist/plugin-sdk/index.js +6 -3
- package/dist/plugin-sdk/webhook-targets.js +32 -0
- package/dist/plugins/bundled-dir.js +9 -6
- package/dist/plugins/hooks.js +50 -0
- package/dist/plugins/install.js +28 -16
- package/dist/plugins/runtime.js +3 -17
- package/dist/plugins/update.js +78 -12
- package/dist/process/spawn-utils.js +14 -7
- package/dist/providers/github-copilot-token.js +11 -6
- package/dist/providers/qwen-portal-oauth.js +14 -6
- package/dist/routing/account-id.js +30 -0
- package/dist/routing/resolve-route.js +3 -7
- package/dist/routing/session-key.js +2 -16
- package/dist/security/audit-channel.js +93 -2
- package/dist/security/audit-extra.async.js +159 -5
- package/dist/security/audit-extra.js +1 -1
- package/dist/security/audit-extra.sync.js +85 -6
- package/dist/security/audit.js +40 -4
- package/dist/security/dm-policy-shared.js +44 -0
- package/dist/security/external-content.js +26 -6
- package/dist/shared/entry-status.js +6 -0
- package/dist/shared/frontmatter.js +5 -5
- package/dist/shared/node-match.js +11 -4
- package/dist/shared/operator-scope-compat.js +8 -3
- package/dist/signal/accounts.js +7 -20
- package/dist/signal/monitor/event-handler.js +3 -1
- package/dist/slack/accounts.js +6 -19
- package/dist/slack/actions.js +11 -3
- package/dist/slack/monitor/auth.js +1 -1
- package/dist/slack/monitor/message-handler/dispatch.js +50 -29
- package/dist/slack/monitor/replies.js +15 -7
- package/dist/slack/monitor/slash.js +22 -13
- package/dist/slack/resolve-channels.js +10 -5
- package/dist/slack/send.js +102 -12
- package/dist/slack/stream-mode.js +10 -0
- package/dist/slack/streaming.js +4 -2
- package/dist/telegram/accounts.js +19 -14
- package/dist/telegram/bot/helpers.js +3 -5
- package/dist/telegram/bot-access.js +35 -36
- package/dist/telegram/bot-handlers.js +120 -148
- package/dist/telegram/bot-message-context.js +68 -9
- package/dist/telegram/bot-message-dispatch.js +155 -90
- package/dist/telegram/bot-native-commands.js +16 -0
- package/dist/telegram/draft-stream.js +14 -1
- package/dist/telegram/inline-buttons.js +5 -15
- package/dist/telegram/monitor.js +11 -7
- package/dist/telegram/network-config.js +19 -7
- package/dist/telegram/send.js +3 -2
- package/dist/telegram/sent-message-cache.js +5 -6
- package/dist/telegram/status-reaction-variants.js +208 -0
- package/dist/telegram/sticker-cache.js +11 -9
- package/dist/terminal/theme.js +12 -12
- package/dist/tts/tts.js +80 -567
- package/dist/tui/components/chat-log.js +41 -8
- package/dist/tui/theme/theme.js +10 -12
- package/dist/tui/tui-local-shell.js +16 -6
- package/dist/tui/tui.js +58 -6
- package/dist/utils/account-id.js +2 -4
- package/dist/utils/boolean.js +10 -5
- package/dist/utils/directive-tags.js +11 -0
- package/dist/utils/queue-helpers.js +67 -12
- package/dist/web/auto-reply/deliver-reply.js +8 -4
- package/dist/web/auto-reply/mentions.js +10 -5
- package/dist/web/auto-reply/monitor/group-members.js +14 -7
- package/dist/web/auto-reply/monitor/process-message.js +45 -24
- package/dist/web/inbound/access-control.js +5 -2
- package/dist/web/login-qr.js +12 -6
- package/dist/web/media.js +123 -16
- package/extensions/bluebubbles/src/monitor-processing.ts +580 -139
- package/extensions/bluebubbles/src/monitor.ts +208 -1950
- package/package.json +1 -1
|
@@ -1,24 +1,33 @@
|
|
|
1
|
-
import { Button, ChannelType, Command, Row, } from "@buape/carbon";
|
|
1
|
+
import { Button, ChannelType, Command, Container, Row, StringSelectMenu, TextDisplay, } from "@buape/carbon";
|
|
2
2
|
import { ApplicationCommandOptionType, ButtonStyle } from "discord-api-types/v10";
|
|
3
3
|
import { resolveHumanDelayConfig } from "../../agents/identity.js";
|
|
4
4
|
import { resolveChunkMode, resolveTextChunkLimit } from "../../auto-reply/chunk.js";
|
|
5
5
|
import { buildCommandTextFromArgs, findCommandByNativeName, listChatCommands, parseCommandArgs, resolveCommandArgChoices, resolveCommandArgMenu, serializeCommandArgs, } from "../../auto-reply/commands-registry.js";
|
|
6
6
|
import { finalizeInboundContext } from "../../auto-reply/reply/inbound-context.js";
|
|
7
|
+
import { resolveStoredModelOverride } from "../../auto-reply/reply/model-selection.js";
|
|
7
8
|
import { dispatchReplyWithDispatcher } from "../../auto-reply/reply/provider-dispatcher.js";
|
|
8
9
|
import { resolveCommandAuthorizedFromAuthorizers } from "../../channels/command-gating.js";
|
|
9
10
|
import { createReplyPrefixOptions } from "../../channels/reply-prefix.js";
|
|
11
|
+
import { loadSessionStore, resolveStorePath } from "../../config/sessions.js";
|
|
12
|
+
import { logVerbose } from "../../globals.js";
|
|
13
|
+
import { createSubsystemLogger } from "../../logging/subsystem.js";
|
|
10
14
|
import { getAgentScopedMediaLocalRoots } from "../../media/local-roots.js";
|
|
11
15
|
import { buildPairingReply } from "../../pairing/pairing-messages.js";
|
|
12
16
|
import { readChannelAllowFromStore, upsertChannelPairingRequest, } from "../../pairing/pairing-store.js";
|
|
13
17
|
import { resolveAgentRoute } from "../../routing/resolve-route.js";
|
|
18
|
+
import { resolveAgentIdFromSessionKey } from "../../routing/session-key.js";
|
|
14
19
|
import { buildUntrustedChannelMetadata } from "../../security/channel-metadata.js";
|
|
15
20
|
import { chunkItems } from "../../utils/chunk-items.js";
|
|
21
|
+
import { withTimeout } from "../../utils/with-timeout.js";
|
|
16
22
|
import { loadWebMedia } from "../../web/media.js";
|
|
17
23
|
import { chunkDiscordTextWithMode } from "../chunk.js";
|
|
18
24
|
import { allowListMatches, isDiscordGroupAllowedByPolicy, normalizeDiscordAllowList, normalizeDiscordSlug, resolveDiscordChannelConfigWithFallback, resolveDiscordGuildEntry, resolveDiscordMemberAccessState, resolveDiscordOwnerAllowFrom, } from "./allow-list.js";
|
|
19
25
|
import { resolveDiscordChannelInfo } from "./message-utils.js";
|
|
26
|
+
import { readDiscordModelPickerRecentModels, recordDiscordModelPickerRecentModel, } from "./model-picker-preferences.js";
|
|
27
|
+
import { DISCORD_MODEL_PICKER_CUSTOM_ID_KEY, loadDiscordModelPickerData, parseDiscordModelPickerData, renderDiscordModelPickerModelsView, renderDiscordModelPickerProvidersView, renderDiscordModelPickerRecentsView, toDiscordModelPickerMessagePayload, } from "./model-picker.js";
|
|
20
28
|
import { resolveDiscordSenderIdentity } from "./sender-identity.js";
|
|
21
29
|
import { resolveDiscordThreadParentInfo } from "./threading.js";
|
|
30
|
+
const log = createSubsystemLogger("discord/native-command");
|
|
22
31
|
function buildDiscordCommandOptions(params) {
|
|
23
32
|
const { command, cfg } = params;
|
|
24
33
|
const args = command.args;
|
|
@@ -132,7 +141,7 @@ async function safeDiscordInteractionCall(label, fn) {
|
|
|
132
141
|
}
|
|
133
142
|
catch (error) {
|
|
134
143
|
if (isDiscordUnknownInteraction(error)) {
|
|
135
|
-
|
|
144
|
+
logVerbose(`discord: ${label} skipped (interaction expired)`);
|
|
136
145
|
return null;
|
|
137
146
|
}
|
|
138
147
|
throw error;
|
|
@@ -165,6 +174,486 @@ function parseDiscordCommandArgData(data) {
|
|
|
165
174
|
userId: decodeDiscordCommandArgValue(rawUser),
|
|
166
175
|
};
|
|
167
176
|
}
|
|
177
|
+
function resolveDiscordModelPickerCommandContext(command) {
|
|
178
|
+
const normalized = (command.nativeName ?? command.key).trim().toLowerCase();
|
|
179
|
+
if (normalized === "model" || normalized === "models") {
|
|
180
|
+
return normalized;
|
|
181
|
+
}
|
|
182
|
+
return null;
|
|
183
|
+
}
|
|
184
|
+
function resolveCommandArgStringValue(args, key) {
|
|
185
|
+
const value = args?.values?.[key];
|
|
186
|
+
if (typeof value !== "string") {
|
|
187
|
+
return "";
|
|
188
|
+
}
|
|
189
|
+
return value.trim();
|
|
190
|
+
}
|
|
191
|
+
function shouldOpenDiscordModelPickerFromCommand(params) {
|
|
192
|
+
const context = resolveDiscordModelPickerCommandContext(params.command);
|
|
193
|
+
if (!context) {
|
|
194
|
+
return null;
|
|
195
|
+
}
|
|
196
|
+
const serializedArgs = serializeCommandArgs(params.command, params.commandArgs)?.trim() ?? "";
|
|
197
|
+
if (context === "model") {
|
|
198
|
+
const modelValue = resolveCommandArgStringValue(params.commandArgs, "model");
|
|
199
|
+
return !modelValue && !serializedArgs ? context : null;
|
|
200
|
+
}
|
|
201
|
+
return serializedArgs ? null : context;
|
|
202
|
+
}
|
|
203
|
+
function buildDiscordModelPickerCurrentModel(defaultProvider, defaultModel) {
|
|
204
|
+
return `${defaultProvider}/${defaultModel}`;
|
|
205
|
+
}
|
|
206
|
+
function buildDiscordModelPickerAllowedModelRefs(data) {
|
|
207
|
+
const out = new Set();
|
|
208
|
+
for (const provider of data.providers) {
|
|
209
|
+
const models = data.byProvider.get(provider);
|
|
210
|
+
if (!models) {
|
|
211
|
+
continue;
|
|
212
|
+
}
|
|
213
|
+
for (const model of models) {
|
|
214
|
+
out.add(`${provider}/${model}`);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
return out;
|
|
218
|
+
}
|
|
219
|
+
function resolveDiscordModelPickerPreferenceScope(params) {
|
|
220
|
+
return {
|
|
221
|
+
accountId: params.accountId,
|
|
222
|
+
guildId: params.interaction.guild?.id ?? undefined,
|
|
223
|
+
userId: params.userId,
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
function buildDiscordModelPickerNoticePayload(message) {
|
|
227
|
+
return {
|
|
228
|
+
components: [new Container([new TextDisplay(message)])],
|
|
229
|
+
};
|
|
230
|
+
}
|
|
231
|
+
async function resolveDiscordModelPickerRoute(params) {
|
|
232
|
+
const { interaction, cfg, accountId } = params;
|
|
233
|
+
const channel = interaction.channel;
|
|
234
|
+
const channelType = channel?.type;
|
|
235
|
+
const isDirectMessage = channelType === ChannelType.DM;
|
|
236
|
+
const isGroupDm = channelType === ChannelType.GroupDM;
|
|
237
|
+
const isThreadChannel = channelType === ChannelType.PublicThread ||
|
|
238
|
+
channelType === ChannelType.PrivateThread ||
|
|
239
|
+
channelType === ChannelType.AnnouncementThread;
|
|
240
|
+
const rawChannelId = channel?.id ?? "unknown";
|
|
241
|
+
const memberRoleIds = Array.isArray(interaction.rawData.member?.roles)
|
|
242
|
+
? interaction.rawData.member.roles.map((roleId) => String(roleId))
|
|
243
|
+
: [];
|
|
244
|
+
let threadParentId;
|
|
245
|
+
if (interaction.guild && channel && isThreadChannel && rawChannelId) {
|
|
246
|
+
const channelInfo = await resolveDiscordChannelInfo(interaction.client, rawChannelId);
|
|
247
|
+
const parentInfo = await resolveDiscordThreadParentInfo({
|
|
248
|
+
client: interaction.client,
|
|
249
|
+
threadChannel: {
|
|
250
|
+
id: rawChannelId,
|
|
251
|
+
name: "name" in channel ? channel.name : undefined,
|
|
252
|
+
parentId: "parentId" in channel ? (channel.parentId ?? undefined) : undefined,
|
|
253
|
+
parent: undefined,
|
|
254
|
+
},
|
|
255
|
+
channelInfo,
|
|
256
|
+
});
|
|
257
|
+
threadParentId = parentInfo.id;
|
|
258
|
+
}
|
|
259
|
+
const route = resolveAgentRoute({
|
|
260
|
+
cfg,
|
|
261
|
+
channel: "discord",
|
|
262
|
+
accountId,
|
|
263
|
+
guildId: interaction.guild?.id ?? undefined,
|
|
264
|
+
memberRoleIds,
|
|
265
|
+
peer: {
|
|
266
|
+
kind: isDirectMessage ? "direct" : isGroupDm ? "group" : "channel",
|
|
267
|
+
id: isDirectMessage ? (interaction.user?.id ?? rawChannelId) : rawChannelId,
|
|
268
|
+
},
|
|
269
|
+
parentPeer: threadParentId ? { kind: "channel", id: threadParentId } : undefined,
|
|
270
|
+
});
|
|
271
|
+
const threadBinding = isThreadChannel
|
|
272
|
+
? params.threadBindings.getByThreadId(rawChannelId)
|
|
273
|
+
: undefined;
|
|
274
|
+
const boundSessionKey = threadBinding?.targetSessionKey?.trim();
|
|
275
|
+
const boundAgentId = boundSessionKey ? resolveAgentIdFromSessionKey(boundSessionKey) : undefined;
|
|
276
|
+
return boundSessionKey
|
|
277
|
+
? {
|
|
278
|
+
...route,
|
|
279
|
+
sessionKey: boundSessionKey,
|
|
280
|
+
agentId: boundAgentId ?? route.agentId,
|
|
281
|
+
}
|
|
282
|
+
: route;
|
|
283
|
+
}
|
|
284
|
+
function resolveDiscordModelPickerCurrentModel(params) {
|
|
285
|
+
const fallback = buildDiscordModelPickerCurrentModel(params.data.resolvedDefault.provider, params.data.resolvedDefault.model);
|
|
286
|
+
try {
|
|
287
|
+
const storePath = resolveStorePath(params.cfg.session?.store, {
|
|
288
|
+
agentId: params.route.agentId,
|
|
289
|
+
});
|
|
290
|
+
const sessionStore = loadSessionStore(storePath, { skipCache: true });
|
|
291
|
+
const sessionEntry = sessionStore[params.route.sessionKey];
|
|
292
|
+
const override = resolveStoredModelOverride({
|
|
293
|
+
sessionEntry,
|
|
294
|
+
sessionStore,
|
|
295
|
+
sessionKey: params.route.sessionKey,
|
|
296
|
+
});
|
|
297
|
+
if (!override?.model) {
|
|
298
|
+
return fallback;
|
|
299
|
+
}
|
|
300
|
+
const provider = (override.provider || params.data.resolvedDefault.provider).trim();
|
|
301
|
+
if (!provider) {
|
|
302
|
+
return fallback;
|
|
303
|
+
}
|
|
304
|
+
return `${provider}/${override.model}`;
|
|
305
|
+
}
|
|
306
|
+
catch {
|
|
307
|
+
return fallback;
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
async function replyWithDiscordModelPickerProviders(params) {
|
|
311
|
+
const data = await loadDiscordModelPickerData(params.cfg);
|
|
312
|
+
const route = await resolveDiscordModelPickerRoute({
|
|
313
|
+
interaction: params.interaction,
|
|
314
|
+
cfg: params.cfg,
|
|
315
|
+
accountId: params.accountId,
|
|
316
|
+
threadBindings: params.threadBindings,
|
|
317
|
+
});
|
|
318
|
+
const currentModel = resolveDiscordModelPickerCurrentModel({
|
|
319
|
+
cfg: params.cfg,
|
|
320
|
+
route,
|
|
321
|
+
data,
|
|
322
|
+
});
|
|
323
|
+
const quickModels = await readDiscordModelPickerRecentModels({
|
|
324
|
+
scope: resolveDiscordModelPickerPreferenceScope({
|
|
325
|
+
interaction: params.interaction,
|
|
326
|
+
accountId: params.accountId,
|
|
327
|
+
userId: params.userId,
|
|
328
|
+
}),
|
|
329
|
+
allowedModelRefs: buildDiscordModelPickerAllowedModelRefs(data),
|
|
330
|
+
limit: 5,
|
|
331
|
+
});
|
|
332
|
+
const rendered = renderDiscordModelPickerModelsView({
|
|
333
|
+
command: params.command,
|
|
334
|
+
userId: params.userId,
|
|
335
|
+
data,
|
|
336
|
+
provider: splitDiscordModelRef(currentModel ?? "")?.provider ?? data.resolvedDefault.provider,
|
|
337
|
+
page: 1,
|
|
338
|
+
providerPage: 1,
|
|
339
|
+
currentModel,
|
|
340
|
+
quickModels,
|
|
341
|
+
});
|
|
342
|
+
const payload = {
|
|
343
|
+
...toDiscordModelPickerMessagePayload(rendered),
|
|
344
|
+
ephemeral: true,
|
|
345
|
+
};
|
|
346
|
+
await safeDiscordInteractionCall("model picker reply", async () => {
|
|
347
|
+
if (params.preferFollowUp) {
|
|
348
|
+
await params.interaction.followUp(payload);
|
|
349
|
+
return;
|
|
350
|
+
}
|
|
351
|
+
await params.interaction.reply(payload);
|
|
352
|
+
});
|
|
353
|
+
}
|
|
354
|
+
function resolveModelPickerSelectionValue(interaction) {
|
|
355
|
+
const rawValues = interaction.values;
|
|
356
|
+
if (!Array.isArray(rawValues) || rawValues.length === 0) {
|
|
357
|
+
return null;
|
|
358
|
+
}
|
|
359
|
+
const first = rawValues[0];
|
|
360
|
+
if (typeof first !== "string") {
|
|
361
|
+
return null;
|
|
362
|
+
}
|
|
363
|
+
const trimmed = first.trim();
|
|
364
|
+
return trimmed || null;
|
|
365
|
+
}
|
|
366
|
+
function buildDiscordModelPickerSelectionCommand(params) {
|
|
367
|
+
const commandDefinition = findCommandByNativeName("model", "discord") ??
|
|
368
|
+
listChatCommands().find((entry) => entry.key === "model");
|
|
369
|
+
if (!commandDefinition) {
|
|
370
|
+
return null;
|
|
371
|
+
}
|
|
372
|
+
const commandArgs = {
|
|
373
|
+
values: {
|
|
374
|
+
model: params.modelRef,
|
|
375
|
+
},
|
|
376
|
+
raw: params.modelRef,
|
|
377
|
+
};
|
|
378
|
+
return {
|
|
379
|
+
command: commandDefinition,
|
|
380
|
+
args: commandArgs,
|
|
381
|
+
prompt: buildCommandTextFromArgs(commandDefinition, commandArgs),
|
|
382
|
+
};
|
|
383
|
+
}
|
|
384
|
+
function listDiscordModelPickerProviderModels(data, provider) {
|
|
385
|
+
const modelSet = data.byProvider.get(provider);
|
|
386
|
+
if (!modelSet) {
|
|
387
|
+
return [];
|
|
388
|
+
}
|
|
389
|
+
return [...modelSet].toSorted();
|
|
390
|
+
}
|
|
391
|
+
function resolveDiscordModelPickerModelIndex(params) {
|
|
392
|
+
const models = listDiscordModelPickerProviderModels(params.data, params.provider);
|
|
393
|
+
if (!models.length) {
|
|
394
|
+
return null;
|
|
395
|
+
}
|
|
396
|
+
const index = models.indexOf(params.model);
|
|
397
|
+
if (index < 0) {
|
|
398
|
+
return null;
|
|
399
|
+
}
|
|
400
|
+
return index + 1;
|
|
401
|
+
}
|
|
402
|
+
function resolveDiscordModelPickerModelByIndex(params) {
|
|
403
|
+
if (!params.modelIndex || params.modelIndex < 1) {
|
|
404
|
+
return null;
|
|
405
|
+
}
|
|
406
|
+
const models = listDiscordModelPickerProviderModels(params.data, params.provider);
|
|
407
|
+
if (!models.length) {
|
|
408
|
+
return null;
|
|
409
|
+
}
|
|
410
|
+
return models[params.modelIndex - 1] ?? null;
|
|
411
|
+
}
|
|
412
|
+
function splitDiscordModelRef(modelRef) {
|
|
413
|
+
const trimmed = modelRef.trim();
|
|
414
|
+
const slashIndex = trimmed.indexOf("/");
|
|
415
|
+
if (slashIndex <= 0 || slashIndex >= trimmed.length - 1) {
|
|
416
|
+
return null;
|
|
417
|
+
}
|
|
418
|
+
const provider = trimmed.slice(0, slashIndex).trim();
|
|
419
|
+
const model = trimmed.slice(slashIndex + 1).trim();
|
|
420
|
+
if (!provider || !model) {
|
|
421
|
+
return null;
|
|
422
|
+
}
|
|
423
|
+
return { provider, model };
|
|
424
|
+
}
|
|
425
|
+
async function handleDiscordModelPickerInteraction(interaction, data, ctx) {
|
|
426
|
+
const parsed = parseDiscordModelPickerData(data);
|
|
427
|
+
if (!parsed) {
|
|
428
|
+
await safeDiscordInteractionCall("model picker update", () => interaction.update(buildDiscordModelPickerNoticePayload("Sorry, that model picker interaction is no longer available.")));
|
|
429
|
+
return;
|
|
430
|
+
}
|
|
431
|
+
if (interaction.user?.id && interaction.user.id !== parsed.userId) {
|
|
432
|
+
await safeDiscordInteractionCall("model picker ack", () => interaction.acknowledge());
|
|
433
|
+
return;
|
|
434
|
+
}
|
|
435
|
+
const pickerData = await loadDiscordModelPickerData(ctx.cfg);
|
|
436
|
+
const route = await resolveDiscordModelPickerRoute({
|
|
437
|
+
interaction,
|
|
438
|
+
cfg: ctx.cfg,
|
|
439
|
+
accountId: ctx.accountId,
|
|
440
|
+
threadBindings: ctx.threadBindings,
|
|
441
|
+
});
|
|
442
|
+
const currentModelRef = resolveDiscordModelPickerCurrentModel({
|
|
443
|
+
cfg: ctx.cfg,
|
|
444
|
+
route,
|
|
445
|
+
data: pickerData,
|
|
446
|
+
});
|
|
447
|
+
const allowedModelRefs = buildDiscordModelPickerAllowedModelRefs(pickerData);
|
|
448
|
+
const preferenceScope = resolveDiscordModelPickerPreferenceScope({
|
|
449
|
+
interaction,
|
|
450
|
+
accountId: ctx.accountId,
|
|
451
|
+
userId: parsed.userId,
|
|
452
|
+
});
|
|
453
|
+
const quickModels = await readDiscordModelPickerRecentModels({
|
|
454
|
+
scope: preferenceScope,
|
|
455
|
+
allowedModelRefs,
|
|
456
|
+
limit: 5,
|
|
457
|
+
});
|
|
458
|
+
if (parsed.action === "recents") {
|
|
459
|
+
const rendered = renderDiscordModelPickerRecentsView({
|
|
460
|
+
command: parsed.command,
|
|
461
|
+
userId: parsed.userId,
|
|
462
|
+
data: pickerData,
|
|
463
|
+
quickModels,
|
|
464
|
+
currentModel: currentModelRef,
|
|
465
|
+
provider: parsed.provider,
|
|
466
|
+
page: parsed.page,
|
|
467
|
+
providerPage: parsed.providerPage,
|
|
468
|
+
});
|
|
469
|
+
await safeDiscordInteractionCall("model picker update", () => interaction.update(toDiscordModelPickerMessagePayload(rendered)));
|
|
470
|
+
return;
|
|
471
|
+
}
|
|
472
|
+
if (parsed.action === "back" && parsed.view === "providers") {
|
|
473
|
+
const rendered = renderDiscordModelPickerProvidersView({
|
|
474
|
+
command: parsed.command,
|
|
475
|
+
userId: parsed.userId,
|
|
476
|
+
data: pickerData,
|
|
477
|
+
page: parsed.page,
|
|
478
|
+
currentModel: currentModelRef,
|
|
479
|
+
});
|
|
480
|
+
await safeDiscordInteractionCall("model picker update", () => interaction.update(toDiscordModelPickerMessagePayload(rendered)));
|
|
481
|
+
return;
|
|
482
|
+
}
|
|
483
|
+
if (parsed.action === "back" && parsed.view === "models") {
|
|
484
|
+
const provider = parsed.provider ??
|
|
485
|
+
splitDiscordModelRef(currentModelRef ?? "")?.provider ??
|
|
486
|
+
pickerData.resolvedDefault.provider;
|
|
487
|
+
const rendered = renderDiscordModelPickerModelsView({
|
|
488
|
+
command: parsed.command,
|
|
489
|
+
userId: parsed.userId,
|
|
490
|
+
data: pickerData,
|
|
491
|
+
provider,
|
|
492
|
+
page: parsed.page ?? 1,
|
|
493
|
+
providerPage: parsed.providerPage ?? 1,
|
|
494
|
+
currentModel: currentModelRef,
|
|
495
|
+
quickModels,
|
|
496
|
+
});
|
|
497
|
+
await safeDiscordInteractionCall("model picker update", () => interaction.update(toDiscordModelPickerMessagePayload(rendered)));
|
|
498
|
+
return;
|
|
499
|
+
}
|
|
500
|
+
if (parsed.action === "provider") {
|
|
501
|
+
const selectedProvider = resolveModelPickerSelectionValue(interaction) ?? parsed.provider;
|
|
502
|
+
if (!selectedProvider || !pickerData.byProvider.has(selectedProvider)) {
|
|
503
|
+
await safeDiscordInteractionCall("model picker update", () => interaction.update(buildDiscordModelPickerNoticePayload("Sorry, that provider isn't available anymore.")));
|
|
504
|
+
return;
|
|
505
|
+
}
|
|
506
|
+
const rendered = renderDiscordModelPickerModelsView({
|
|
507
|
+
command: parsed.command,
|
|
508
|
+
userId: parsed.userId,
|
|
509
|
+
data: pickerData,
|
|
510
|
+
provider: selectedProvider,
|
|
511
|
+
page: 1,
|
|
512
|
+
providerPage: parsed.providerPage ?? parsed.page,
|
|
513
|
+
currentModel: currentModelRef,
|
|
514
|
+
quickModels,
|
|
515
|
+
});
|
|
516
|
+
await safeDiscordInteractionCall("model picker update", () => interaction.update(toDiscordModelPickerMessagePayload(rendered)));
|
|
517
|
+
return;
|
|
518
|
+
}
|
|
519
|
+
if (parsed.action === "model") {
|
|
520
|
+
const selectedModel = resolveModelPickerSelectionValue(interaction);
|
|
521
|
+
const provider = parsed.provider;
|
|
522
|
+
if (!provider || !selectedModel) {
|
|
523
|
+
await safeDiscordInteractionCall("model picker update", () => interaction.update(buildDiscordModelPickerNoticePayload("Sorry, I couldn't read that model selection.")));
|
|
524
|
+
return;
|
|
525
|
+
}
|
|
526
|
+
const modelIndex = resolveDiscordModelPickerModelIndex({
|
|
527
|
+
data: pickerData,
|
|
528
|
+
provider,
|
|
529
|
+
model: selectedModel,
|
|
530
|
+
});
|
|
531
|
+
if (!modelIndex) {
|
|
532
|
+
await safeDiscordInteractionCall("model picker update", () => interaction.update(buildDiscordModelPickerNoticePayload("Sorry, that model isn't available anymore.")));
|
|
533
|
+
return;
|
|
534
|
+
}
|
|
535
|
+
const modelRef = `${provider}/${selectedModel}`;
|
|
536
|
+
const rendered = renderDiscordModelPickerModelsView({
|
|
537
|
+
command: parsed.command,
|
|
538
|
+
userId: parsed.userId,
|
|
539
|
+
data: pickerData,
|
|
540
|
+
provider,
|
|
541
|
+
page: parsed.page,
|
|
542
|
+
providerPage: parsed.providerPage ?? 1,
|
|
543
|
+
currentModel: currentModelRef,
|
|
544
|
+
pendingModel: modelRef,
|
|
545
|
+
pendingModelIndex: modelIndex,
|
|
546
|
+
quickModels,
|
|
547
|
+
});
|
|
548
|
+
await safeDiscordInteractionCall("model picker update", () => interaction.update(toDiscordModelPickerMessagePayload(rendered)));
|
|
549
|
+
return;
|
|
550
|
+
}
|
|
551
|
+
if (parsed.action === "submit" || parsed.action === "reset" || parsed.action === "quick") {
|
|
552
|
+
let modelRef = null;
|
|
553
|
+
if (parsed.action === "reset") {
|
|
554
|
+
modelRef = `${pickerData.resolvedDefault.provider}/${pickerData.resolvedDefault.model}`;
|
|
555
|
+
}
|
|
556
|
+
else if (parsed.action === "quick") {
|
|
557
|
+
const slot = parsed.recentSlot ?? 0;
|
|
558
|
+
modelRef = slot >= 1 ? (quickModels[slot - 1] ?? null) : null;
|
|
559
|
+
}
|
|
560
|
+
else if (parsed.view === "recents") {
|
|
561
|
+
const defaultModelRef = `${pickerData.resolvedDefault.provider}/${pickerData.resolvedDefault.model}`;
|
|
562
|
+
const dedupedRecents = quickModels.filter((ref) => ref !== defaultModelRef);
|
|
563
|
+
const slot = parsed.recentSlot ?? 0;
|
|
564
|
+
if (slot === 1) {
|
|
565
|
+
modelRef = defaultModelRef;
|
|
566
|
+
}
|
|
567
|
+
else if (slot >= 2) {
|
|
568
|
+
modelRef = dedupedRecents[slot - 2] ?? null;
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
else {
|
|
572
|
+
const provider = parsed.provider;
|
|
573
|
+
const selectedModel = resolveDiscordModelPickerModelByIndex({
|
|
574
|
+
data: pickerData,
|
|
575
|
+
provider: provider ?? "",
|
|
576
|
+
modelIndex: parsed.modelIndex,
|
|
577
|
+
});
|
|
578
|
+
modelRef = provider && selectedModel ? `${provider}/${selectedModel}` : null;
|
|
579
|
+
}
|
|
580
|
+
const parsedModelRef = modelRef ? splitDiscordModelRef(modelRef) : null;
|
|
581
|
+
if (!parsedModelRef ||
|
|
582
|
+
!pickerData.byProvider.get(parsedModelRef.provider)?.has(parsedModelRef.model)) {
|
|
583
|
+
await safeDiscordInteractionCall("model picker update", () => interaction.update(buildDiscordModelPickerNoticePayload("That selection expired. Please choose a model again.")));
|
|
584
|
+
return;
|
|
585
|
+
}
|
|
586
|
+
const resolvedModelRef = `${parsedModelRef.provider}/${parsedModelRef.model}`;
|
|
587
|
+
const selectionCommand = buildDiscordModelPickerSelectionCommand({
|
|
588
|
+
modelRef: resolvedModelRef,
|
|
589
|
+
});
|
|
590
|
+
if (!selectionCommand) {
|
|
591
|
+
await safeDiscordInteractionCall("model picker update", () => interaction.update(buildDiscordModelPickerNoticePayload("Sorry, /model is unavailable right now.")));
|
|
592
|
+
return;
|
|
593
|
+
}
|
|
594
|
+
const updateResult = await safeDiscordInteractionCall("model picker update", () => interaction.update(buildDiscordModelPickerNoticePayload(`Applying model change to ${resolvedModelRef}...`)));
|
|
595
|
+
if (updateResult === null) {
|
|
596
|
+
return;
|
|
597
|
+
}
|
|
598
|
+
try {
|
|
599
|
+
await withTimeout(dispatchDiscordCommandInteraction({
|
|
600
|
+
interaction,
|
|
601
|
+
prompt: selectionCommand.prompt,
|
|
602
|
+
command: selectionCommand.command,
|
|
603
|
+
commandArgs: selectionCommand.args,
|
|
604
|
+
cfg: ctx.cfg,
|
|
605
|
+
discordConfig: ctx.discordConfig,
|
|
606
|
+
accountId: ctx.accountId,
|
|
607
|
+
sessionPrefix: ctx.sessionPrefix,
|
|
608
|
+
preferFollowUp: true,
|
|
609
|
+
threadBindings: ctx.threadBindings,
|
|
610
|
+
suppressReplies: true,
|
|
611
|
+
}), 12000);
|
|
612
|
+
}
|
|
613
|
+
catch (error) {
|
|
614
|
+
if (error instanceof Error && error.message === "timeout") {
|
|
615
|
+
await safeDiscordInteractionCall("model picker follow-up", () => interaction.followUp({
|
|
616
|
+
...buildDiscordModelPickerNoticePayload(`⏳ Model change to ${resolvedModelRef} is still processing. Check /status in a few seconds.`),
|
|
617
|
+
ephemeral: true,
|
|
618
|
+
}));
|
|
619
|
+
return;
|
|
620
|
+
}
|
|
621
|
+
await safeDiscordInteractionCall("model picker follow-up", () => interaction.followUp({
|
|
622
|
+
...buildDiscordModelPickerNoticePayload(`❌ Failed to apply ${resolvedModelRef}. Try /model ${resolvedModelRef} directly.`),
|
|
623
|
+
ephemeral: true,
|
|
624
|
+
}));
|
|
625
|
+
return;
|
|
626
|
+
}
|
|
627
|
+
const effectiveModelRef = resolveDiscordModelPickerCurrentModel({
|
|
628
|
+
cfg: ctx.cfg,
|
|
629
|
+
route,
|
|
630
|
+
data: pickerData,
|
|
631
|
+
});
|
|
632
|
+
const persisted = effectiveModelRef === resolvedModelRef;
|
|
633
|
+
if (!persisted) {
|
|
634
|
+
logVerbose(`discord: model picker override mismatch — expected ${resolvedModelRef} but read ${effectiveModelRef} from session key ${route.sessionKey}`);
|
|
635
|
+
}
|
|
636
|
+
if (persisted) {
|
|
637
|
+
await recordDiscordModelPickerRecentModel({
|
|
638
|
+
scope: preferenceScope,
|
|
639
|
+
modelRef: resolvedModelRef,
|
|
640
|
+
limit: 5,
|
|
641
|
+
}).catch(() => undefined);
|
|
642
|
+
}
|
|
643
|
+
await safeDiscordInteractionCall("model picker follow-up", () => interaction.followUp({
|
|
644
|
+
...buildDiscordModelPickerNoticePayload(persisted
|
|
645
|
+
? `✅ Model set to ${resolvedModelRef}.`
|
|
646
|
+
: `⚠️ Tried to set ${resolvedModelRef}, but current model is ${effectiveModelRef}.`),
|
|
647
|
+
ephemeral: true,
|
|
648
|
+
}));
|
|
649
|
+
return;
|
|
650
|
+
}
|
|
651
|
+
if (parsed.action === "cancel") {
|
|
652
|
+
const displayModel = currentModelRef ?? "default";
|
|
653
|
+
await safeDiscordInteractionCall("model picker update", () => interaction.update(buildDiscordModelPickerNoticePayload(`ℹ️ Model kept as ${displayModel}.`)));
|
|
654
|
+
return;
|
|
655
|
+
}
|
|
656
|
+
}
|
|
168
657
|
async function handleDiscordCommandArgInteraction(interaction, data, ctx) {
|
|
169
658
|
const parsed = parseDiscordCommandArgData(data);
|
|
170
659
|
if (!parsed) {
|
|
@@ -187,11 +676,11 @@ async function handleDiscordCommandArgInteraction(interaction, data, ctx) {
|
|
|
187
676
|
}));
|
|
188
677
|
return;
|
|
189
678
|
}
|
|
190
|
-
const
|
|
679
|
+
const argUpdateResult = await safeDiscordInteractionCall("command arg update", () => interaction.update({
|
|
191
680
|
content: `✅ Selected ${parsed.value}.`,
|
|
192
681
|
components: [],
|
|
193
682
|
}));
|
|
194
|
-
if (
|
|
683
|
+
if (argUpdateResult === null) {
|
|
195
684
|
return;
|
|
196
685
|
}
|
|
197
686
|
const commandArgs = createCommandArgsWithValue({
|
|
@@ -213,6 +702,7 @@ async function handleDiscordCommandArgInteraction(interaction, data, ctx) {
|
|
|
213
702
|
accountId: ctx.accountId,
|
|
214
703
|
sessionPrefix: ctx.sessionPrefix,
|
|
215
704
|
preferFollowUp: true,
|
|
705
|
+
threadBindings: ctx.threadBindings,
|
|
216
706
|
});
|
|
217
707
|
}
|
|
218
708
|
class DiscordCommandArgButton extends Button {
|
|
@@ -223,6 +713,7 @@ class DiscordCommandArgButton extends Button {
|
|
|
223
713
|
discordConfig;
|
|
224
714
|
accountId;
|
|
225
715
|
sessionPrefix;
|
|
716
|
+
threadBindings;
|
|
226
717
|
constructor(params) {
|
|
227
718
|
super();
|
|
228
719
|
this.label = params.label;
|
|
@@ -231,6 +722,7 @@ class DiscordCommandArgButton extends Button {
|
|
|
231
722
|
this.discordConfig = params.discordConfig;
|
|
232
723
|
this.accountId = params.accountId;
|
|
233
724
|
this.sessionPrefix = params.sessionPrefix;
|
|
725
|
+
this.threadBindings = params.threadBindings;
|
|
234
726
|
}
|
|
235
727
|
async run(interaction, data) {
|
|
236
728
|
await handleDiscordCommandArgInteraction(interaction, data, {
|
|
@@ -238,6 +730,7 @@ class DiscordCommandArgButton extends Button {
|
|
|
238
730
|
discordConfig: this.discordConfig,
|
|
239
731
|
accountId: this.accountId,
|
|
240
732
|
sessionPrefix: this.sessionPrefix,
|
|
733
|
+
threadBindings: this.threadBindings,
|
|
241
734
|
});
|
|
242
735
|
}
|
|
243
736
|
}
|
|
@@ -256,6 +749,36 @@ class DiscordCommandArgFallbackButton extends Button {
|
|
|
256
749
|
export function createDiscordCommandArgFallbackButton(params) {
|
|
257
750
|
return new DiscordCommandArgFallbackButton(params);
|
|
258
751
|
}
|
|
752
|
+
class DiscordModelPickerFallbackButton extends Button {
|
|
753
|
+
label = DISCORD_MODEL_PICKER_CUSTOM_ID_KEY;
|
|
754
|
+
customId = `${DISCORD_MODEL_PICKER_CUSTOM_ID_KEY}:seed=btn`;
|
|
755
|
+
ctx;
|
|
756
|
+
constructor(ctx) {
|
|
757
|
+
super();
|
|
758
|
+
this.ctx = ctx;
|
|
759
|
+
}
|
|
760
|
+
async run(interaction, data) {
|
|
761
|
+
await handleDiscordModelPickerInteraction(interaction, data, this.ctx);
|
|
762
|
+
}
|
|
763
|
+
}
|
|
764
|
+
class DiscordModelPickerFallbackSelect extends StringSelectMenu {
|
|
765
|
+
customId = `${DISCORD_MODEL_PICKER_CUSTOM_ID_KEY}:seed=sel`;
|
|
766
|
+
options = [];
|
|
767
|
+
ctx;
|
|
768
|
+
constructor(ctx) {
|
|
769
|
+
super();
|
|
770
|
+
this.ctx = ctx;
|
|
771
|
+
}
|
|
772
|
+
async run(interaction, data) {
|
|
773
|
+
await handleDiscordModelPickerInteraction(interaction, data, this.ctx);
|
|
774
|
+
}
|
|
775
|
+
}
|
|
776
|
+
export function createDiscordModelPickerFallbackButton(params) {
|
|
777
|
+
return new DiscordModelPickerFallbackButton(params);
|
|
778
|
+
}
|
|
779
|
+
export function createDiscordModelPickerFallbackSelect(params) {
|
|
780
|
+
return new DiscordModelPickerFallbackSelect(params);
|
|
781
|
+
}
|
|
259
782
|
function buildDiscordCommandArgMenu(params) {
|
|
260
783
|
const { command, menu, interaction } = params;
|
|
261
784
|
const commandLabel = command.nativeName ?? command.key;
|
|
@@ -273,6 +796,7 @@ function buildDiscordCommandArgMenu(params) {
|
|
|
273
796
|
discordConfig: params.discordConfig,
|
|
274
797
|
accountId: params.accountId,
|
|
275
798
|
sessionPrefix: params.sessionPrefix,
|
|
799
|
+
threadBindings: params.threadBindings,
|
|
276
800
|
}));
|
|
277
801
|
return new Row(buttons);
|
|
278
802
|
});
|
|
@@ -280,7 +804,7 @@ function buildDiscordCommandArgMenu(params) {
|
|
|
280
804
|
return { content, components: rows };
|
|
281
805
|
}
|
|
282
806
|
export function createDiscordNativeCommand(params) {
|
|
283
|
-
const { command, cfg, discordConfig, accountId, sessionPrefix, ephemeralDefault } = params;
|
|
807
|
+
const { command, cfg, discordConfig, accountId, sessionPrefix, ephemeralDefault, threadBindings, } = params;
|
|
284
808
|
const commandDefinition = findCommandByNativeName(command.name, "discord") ??
|
|
285
809
|
{
|
|
286
810
|
key: command.name,
|
|
@@ -338,12 +862,13 @@ export function createDiscordNativeCommand(params) {
|
|
|
338
862
|
accountId,
|
|
339
863
|
sessionPrefix,
|
|
340
864
|
preferFollowUp: false,
|
|
865
|
+
threadBindings,
|
|
341
866
|
});
|
|
342
867
|
}
|
|
343
868
|
})();
|
|
344
869
|
}
|
|
345
870
|
async function dispatchDiscordCommandInteraction(params) {
|
|
346
|
-
const { interaction, prompt, command, commandArgs, cfg, discordConfig, accountId, sessionPrefix, preferFollowUp, } = params;
|
|
871
|
+
const { interaction, prompt, command, commandArgs, cfg, discordConfig, accountId, sessionPrefix, preferFollowUp, threadBindings, suppressReplies, } = params;
|
|
347
872
|
const respond = async (content, options) => {
|
|
348
873
|
const payload = {
|
|
349
874
|
content,
|
|
@@ -451,7 +976,7 @@ async function dispatchDiscordCommandInteraction(params) {
|
|
|
451
976
|
return;
|
|
452
977
|
}
|
|
453
978
|
if (dmPolicy !== "open") {
|
|
454
|
-
const storeAllowFrom = await readChannelAllowFromStore("discord").catch(() => []);
|
|
979
|
+
const storeAllowFrom = dmPolicy === "allowlist" ? [] : await readChannelAllowFromStore("discord").catch(() => []);
|
|
455
980
|
const effectiveAllowFrom = [
|
|
456
981
|
...(discordConfig?.allowFrom ?? discordConfig?.dm?.allowFrom ?? []),
|
|
457
982
|
...storeAllowFrom,
|
|
@@ -532,6 +1057,7 @@ async function dispatchDiscordCommandInteraction(params) {
|
|
|
532
1057
|
discordConfig,
|
|
533
1058
|
accountId,
|
|
534
1059
|
sessionPrefix,
|
|
1060
|
+
threadBindings,
|
|
535
1061
|
});
|
|
536
1062
|
if (preferFollowUp) {
|
|
537
1063
|
await safeDiscordInteractionCall("interaction follow-up", () => interaction.followUp({
|
|
@@ -548,6 +1074,22 @@ async function dispatchDiscordCommandInteraction(params) {
|
|
|
548
1074
|
}));
|
|
549
1075
|
return;
|
|
550
1076
|
}
|
|
1077
|
+
const pickerCommandContext = shouldOpenDiscordModelPickerFromCommand({
|
|
1078
|
+
command,
|
|
1079
|
+
commandArgs,
|
|
1080
|
+
});
|
|
1081
|
+
if (pickerCommandContext) {
|
|
1082
|
+
await replyWithDiscordModelPickerProviders({
|
|
1083
|
+
interaction,
|
|
1084
|
+
cfg,
|
|
1085
|
+
command: pickerCommandContext,
|
|
1086
|
+
userId: user.id,
|
|
1087
|
+
accountId,
|
|
1088
|
+
threadBindings,
|
|
1089
|
+
preferFollowUp,
|
|
1090
|
+
});
|
|
1091
|
+
return;
|
|
1092
|
+
}
|
|
551
1093
|
const isGuild = Boolean(interaction.guild);
|
|
552
1094
|
const channelId = rawChannelId || "unknown";
|
|
553
1095
|
const interactionId = interaction.rawData.id;
|
|
@@ -563,6 +1105,16 @@ async function dispatchDiscordCommandInteraction(params) {
|
|
|
563
1105
|
},
|
|
564
1106
|
parentPeer: threadParentId ? { kind: "channel", id: threadParentId } : undefined,
|
|
565
1107
|
});
|
|
1108
|
+
const threadBinding = isThreadChannel ? threadBindings.getByThreadId(rawChannelId) : undefined;
|
|
1109
|
+
const boundSessionKey = threadBinding?.targetSessionKey?.trim();
|
|
1110
|
+
const boundAgentId = boundSessionKey ? resolveAgentIdFromSessionKey(boundSessionKey) : undefined;
|
|
1111
|
+
const effectiveRoute = boundSessionKey
|
|
1112
|
+
? {
|
|
1113
|
+
...route,
|
|
1114
|
+
sessionKey: boundSessionKey,
|
|
1115
|
+
agentId: boundAgentId ?? route.agentId,
|
|
1116
|
+
}
|
|
1117
|
+
: route;
|
|
566
1118
|
const conversationLabel = isDirectMessage ? (user.globalName ?? user.username) : channelId;
|
|
567
1119
|
const ownerAllowFrom = resolveDiscordOwnerAllowFrom({
|
|
568
1120
|
channelConfig,
|
|
@@ -581,9 +1133,9 @@ async function dispatchDiscordCommandInteraction(params) {
|
|
|
581
1133
|
? `discord:group:${channelId}`
|
|
582
1134
|
: `discord:channel:${channelId}`,
|
|
583
1135
|
To: `slash:${user.id}`,
|
|
584
|
-
SessionKey: `agent:${
|
|
585
|
-
CommandTargetSessionKey:
|
|
586
|
-
AccountId:
|
|
1136
|
+
SessionKey: boundSessionKey ?? `agent:${effectiveRoute.agentId}:${sessionPrefix}:${user.id}`,
|
|
1137
|
+
CommandTargetSessionKey: boundSessionKey ?? effectiveRoute.sessionKey,
|
|
1138
|
+
AccountId: effectiveRoute.accountId,
|
|
587
1139
|
ChatType: isDirectMessage ? "direct" : isGroupDm ? "group" : "channel",
|
|
588
1140
|
ConversationLabel: conversationLabel,
|
|
589
1141
|
GroupSubject: isGuild ? interaction.guild?.name : undefined,
|
|
@@ -613,6 +1165,7 @@ async function dispatchDiscordCommandInteraction(params) {
|
|
|
613
1165
|
Surface: "discord",
|
|
614
1166
|
WasMentioned: true,
|
|
615
1167
|
MessageSid: interactionId,
|
|
1168
|
+
MessageThreadId: isThreadChannel ? channelId : undefined,
|
|
616
1169
|
Timestamp: Date.now(),
|
|
617
1170
|
CommandAuthorized: commandAuthorized,
|
|
618
1171
|
CommandSource: "native",
|
|
@@ -624,19 +1177,22 @@ async function dispatchDiscordCommandInteraction(params) {
|
|
|
624
1177
|
});
|
|
625
1178
|
const { onModelSelected, ...prefixOptions } = createReplyPrefixOptions({
|
|
626
1179
|
cfg,
|
|
627
|
-
agentId:
|
|
1180
|
+
agentId: effectiveRoute.agentId,
|
|
628
1181
|
channel: "discord",
|
|
629
|
-
accountId:
|
|
1182
|
+
accountId: effectiveRoute.accountId,
|
|
630
1183
|
});
|
|
631
|
-
const mediaLocalRoots = getAgentScopedMediaLocalRoots(cfg,
|
|
1184
|
+
const mediaLocalRoots = getAgentScopedMediaLocalRoots(cfg, effectiveRoute.agentId);
|
|
632
1185
|
let didReply = false;
|
|
633
1186
|
await dispatchReplyWithDispatcher({
|
|
634
1187
|
ctx: ctxPayload,
|
|
635
1188
|
cfg,
|
|
636
1189
|
dispatcherOptions: {
|
|
637
1190
|
...prefixOptions,
|
|
638
|
-
humanDelay: resolveHumanDelayConfig(cfg,
|
|
1191
|
+
humanDelay: resolveHumanDelayConfig(cfg, effectiveRoute.agentId),
|
|
639
1192
|
deliver: async (payload) => {
|
|
1193
|
+
if (suppressReplies) {
|
|
1194
|
+
return;
|
|
1195
|
+
}
|
|
640
1196
|
try {
|
|
641
1197
|
await deliverDiscordInteractionReply({
|
|
642
1198
|
interaction,
|
|
@@ -652,7 +1208,7 @@ async function dispatchDiscordCommandInteraction(params) {
|
|
|
652
1208
|
}
|
|
653
1209
|
catch (error) {
|
|
654
1210
|
if (isDiscordUnknownInteraction(error)) {
|
|
655
|
-
|
|
1211
|
+
logVerbose("discord: interaction reply skipped (interaction expired)");
|
|
656
1212
|
return;
|
|
657
1213
|
}
|
|
658
1214
|
throw error;
|
|
@@ -660,7 +1216,8 @@ async function dispatchDiscordCommandInteraction(params) {
|
|
|
660
1216
|
didReply = true;
|
|
661
1217
|
},
|
|
662
1218
|
onError: (err, info) => {
|
|
663
|
-
|
|
1219
|
+
const message = err instanceof Error ? (err.stack ?? err.message) : String(err);
|
|
1220
|
+
log.error(`discord slash ${info.kind} reply failed: ${message}`);
|
|
664
1221
|
},
|
|
665
1222
|
},
|
|
666
1223
|
replyOptions: {
|