@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
|
@@ -0,0 +1,651 @@
|
|
|
1
|
+
import { Button, Container, Row, Separator, StringSelectMenu, TextDisplay, } from "@buape/carbon";
|
|
2
|
+
import { ButtonStyle } from "discord-api-types/v10";
|
|
3
|
+
import { normalizeProviderId } from "../../agents/model-selection.js";
|
|
4
|
+
import { buildModelsProviderData, } from "../../auto-reply/reply/commands-models.js";
|
|
5
|
+
export const DISCORD_MODEL_PICKER_CUSTOM_ID_KEY = "mdlpk";
|
|
6
|
+
export const DISCORD_CUSTOM_ID_MAX_CHARS = 100;
|
|
7
|
+
// Discord component limits.
|
|
8
|
+
export const DISCORD_COMPONENT_MAX_ROWS = 5;
|
|
9
|
+
export const DISCORD_COMPONENT_MAX_BUTTONS_PER_ROW = 5;
|
|
10
|
+
export const DISCORD_COMPONENT_MAX_SELECT_OPTIONS = 25;
|
|
11
|
+
// Reserve one row for navigation/utility buttons when rendering providers.
|
|
12
|
+
export const DISCORD_MODEL_PICKER_PROVIDER_PAGE_SIZE = DISCORD_COMPONENT_MAX_BUTTONS_PER_ROW * (DISCORD_COMPONENT_MAX_ROWS - 1);
|
|
13
|
+
// When providers fit in one page, we can use all button rows and hide nav controls.
|
|
14
|
+
export const DISCORD_MODEL_PICKER_PROVIDER_SINGLE_PAGE_MAX = DISCORD_COMPONENT_MAX_BUTTONS_PER_ROW * DISCORD_COMPONENT_MAX_ROWS;
|
|
15
|
+
export const DISCORD_MODEL_PICKER_MODEL_PAGE_SIZE = DISCORD_COMPONENT_MAX_SELECT_OPTIONS;
|
|
16
|
+
const DISCORD_PROVIDER_BUTTON_LABEL_MAX_CHARS = 18;
|
|
17
|
+
const COMMAND_CONTEXTS = ["model", "models"];
|
|
18
|
+
const PICKER_ACTIONS = [
|
|
19
|
+
"open",
|
|
20
|
+
"provider",
|
|
21
|
+
"model",
|
|
22
|
+
"submit",
|
|
23
|
+
"quick",
|
|
24
|
+
"back",
|
|
25
|
+
"reset",
|
|
26
|
+
"cancel",
|
|
27
|
+
"recents",
|
|
28
|
+
];
|
|
29
|
+
const PICKER_VIEWS = ["providers", "models", "recents"];
|
|
30
|
+
function encodeCustomIdValue(value) {
|
|
31
|
+
return encodeURIComponent(value);
|
|
32
|
+
}
|
|
33
|
+
function decodeCustomIdValue(value) {
|
|
34
|
+
try {
|
|
35
|
+
return decodeURIComponent(value);
|
|
36
|
+
}
|
|
37
|
+
catch {
|
|
38
|
+
return value;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
function isValidCommandContext(value) {
|
|
42
|
+
return COMMAND_CONTEXTS.includes(value);
|
|
43
|
+
}
|
|
44
|
+
function isValidPickerAction(value) {
|
|
45
|
+
return PICKER_ACTIONS.includes(value);
|
|
46
|
+
}
|
|
47
|
+
function isValidPickerView(value) {
|
|
48
|
+
return PICKER_VIEWS.includes(value);
|
|
49
|
+
}
|
|
50
|
+
function normalizePage(value) {
|
|
51
|
+
const numeric = typeof value === "number" ? value : Number.NaN;
|
|
52
|
+
if (!Number.isFinite(numeric)) {
|
|
53
|
+
return 1;
|
|
54
|
+
}
|
|
55
|
+
return Math.max(1, Math.floor(numeric));
|
|
56
|
+
}
|
|
57
|
+
function parseRawPage(value) {
|
|
58
|
+
if (typeof value === "number") {
|
|
59
|
+
return normalizePage(value);
|
|
60
|
+
}
|
|
61
|
+
if (typeof value === "string" && value.trim()) {
|
|
62
|
+
const parsed = Number.parseInt(value, 10);
|
|
63
|
+
if (Number.isFinite(parsed)) {
|
|
64
|
+
return normalizePage(parsed);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return 1;
|
|
68
|
+
}
|
|
69
|
+
function parseRawPositiveInt(value) {
|
|
70
|
+
if (typeof value !== "string" && typeof value !== "number") {
|
|
71
|
+
return undefined;
|
|
72
|
+
}
|
|
73
|
+
const parsed = Number.parseInt(String(value), 10);
|
|
74
|
+
if (!Number.isFinite(parsed) || parsed < 1) {
|
|
75
|
+
return undefined;
|
|
76
|
+
}
|
|
77
|
+
return Math.floor(parsed);
|
|
78
|
+
}
|
|
79
|
+
function coerceString(value) {
|
|
80
|
+
return typeof value === "string" || typeof value === "number" ? String(value) : "";
|
|
81
|
+
}
|
|
82
|
+
function clampPageSize(rawPageSize, max, fallback) {
|
|
83
|
+
if (!Number.isFinite(rawPageSize)) {
|
|
84
|
+
return fallback;
|
|
85
|
+
}
|
|
86
|
+
return Math.min(max, Math.max(1, Math.floor(rawPageSize ?? fallback)));
|
|
87
|
+
}
|
|
88
|
+
function paginateItems(params) {
|
|
89
|
+
const totalItems = params.items.length;
|
|
90
|
+
const totalPages = Math.max(1, Math.ceil(totalItems / params.pageSize));
|
|
91
|
+
const page = Math.max(1, Math.min(params.page, totalPages));
|
|
92
|
+
const startIndex = (page - 1) * params.pageSize;
|
|
93
|
+
const endIndexExclusive = Math.min(totalItems, startIndex + params.pageSize);
|
|
94
|
+
return {
|
|
95
|
+
items: params.items.slice(startIndex, endIndexExclusive),
|
|
96
|
+
page,
|
|
97
|
+
pageSize: params.pageSize,
|
|
98
|
+
totalPages,
|
|
99
|
+
totalItems,
|
|
100
|
+
hasPrev: page > 1,
|
|
101
|
+
hasNext: page < totalPages,
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
function parseCurrentModelRef(raw) {
|
|
105
|
+
const trimmed = raw?.trim();
|
|
106
|
+
if (!trimmed) {
|
|
107
|
+
return null;
|
|
108
|
+
}
|
|
109
|
+
const slashIndex = trimmed.indexOf("/");
|
|
110
|
+
if (slashIndex <= 0 || slashIndex >= trimmed.length - 1) {
|
|
111
|
+
return null;
|
|
112
|
+
}
|
|
113
|
+
const provider = normalizeProviderId(trimmed.slice(0, slashIndex));
|
|
114
|
+
const model = trimmed.slice(slashIndex + 1);
|
|
115
|
+
if (!provider || !model) {
|
|
116
|
+
return null;
|
|
117
|
+
}
|
|
118
|
+
return { provider, model };
|
|
119
|
+
}
|
|
120
|
+
function formatCurrentModelLine(currentModel) {
|
|
121
|
+
const parsed = parseCurrentModelRef(currentModel);
|
|
122
|
+
if (!parsed) {
|
|
123
|
+
return "Current model: default";
|
|
124
|
+
}
|
|
125
|
+
return `Current model: ${parsed.provider}/${parsed.model}`;
|
|
126
|
+
}
|
|
127
|
+
function formatProviderButtonLabel(provider) {
|
|
128
|
+
if (provider.length <= DISCORD_PROVIDER_BUTTON_LABEL_MAX_CHARS) {
|
|
129
|
+
return provider;
|
|
130
|
+
}
|
|
131
|
+
return `${provider.slice(0, DISCORD_PROVIDER_BUTTON_LABEL_MAX_CHARS - 1)}…`;
|
|
132
|
+
}
|
|
133
|
+
function chunkProvidersForRows(items) {
|
|
134
|
+
if (items.length === 0) {
|
|
135
|
+
return [];
|
|
136
|
+
}
|
|
137
|
+
const rowCount = Math.max(1, Math.ceil(items.length / DISCORD_COMPONENT_MAX_BUTTONS_PER_ROW));
|
|
138
|
+
const minPerRow = Math.floor(items.length / rowCount);
|
|
139
|
+
const rowsWithExtraItem = items.length % rowCount;
|
|
140
|
+
const counts = Array.from({ length: rowCount }, (_, index) => index < rowCount - rowsWithExtraItem ? minPerRow : minPerRow + 1);
|
|
141
|
+
const rows = [];
|
|
142
|
+
let cursor = 0;
|
|
143
|
+
for (const count of counts) {
|
|
144
|
+
rows.push(items.slice(cursor, cursor + count));
|
|
145
|
+
cursor += count;
|
|
146
|
+
}
|
|
147
|
+
return rows;
|
|
148
|
+
}
|
|
149
|
+
function createModelPickerButton(params) {
|
|
150
|
+
class DiscordModelPickerButton extends Button {
|
|
151
|
+
label = params.label;
|
|
152
|
+
customId = params.customId;
|
|
153
|
+
style = params.style ?? ButtonStyle.Secondary;
|
|
154
|
+
disabled = params.disabled ?? false;
|
|
155
|
+
}
|
|
156
|
+
return new DiscordModelPickerButton();
|
|
157
|
+
}
|
|
158
|
+
function createModelSelect(params) {
|
|
159
|
+
class DiscordModelPickerSelect extends StringSelectMenu {
|
|
160
|
+
customId = params.customId;
|
|
161
|
+
options = params.options;
|
|
162
|
+
minValues = 1;
|
|
163
|
+
maxValues = 1;
|
|
164
|
+
placeholder = params.placeholder;
|
|
165
|
+
disabled = params.disabled ?? false;
|
|
166
|
+
}
|
|
167
|
+
return new DiscordModelPickerSelect();
|
|
168
|
+
}
|
|
169
|
+
function buildRenderedShell(params) {
|
|
170
|
+
if (params.layout === "classic") {
|
|
171
|
+
const lines = [params.title, ...params.detailLines, "", params.footer].filter(Boolean);
|
|
172
|
+
return {
|
|
173
|
+
layout: "classic",
|
|
174
|
+
content: lines.join("\n"),
|
|
175
|
+
components: params.rows,
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
const containerComponents = [
|
|
179
|
+
new TextDisplay(`## ${params.title}`),
|
|
180
|
+
];
|
|
181
|
+
if (params.detailLines.length > 0) {
|
|
182
|
+
containerComponents.push(new TextDisplay(params.detailLines.join("\n")));
|
|
183
|
+
}
|
|
184
|
+
containerComponents.push(new Separator({ divider: true, spacing: "small" }));
|
|
185
|
+
if (params.preRowText) {
|
|
186
|
+
containerComponents.push(new TextDisplay(params.preRowText));
|
|
187
|
+
}
|
|
188
|
+
containerComponents.push(...params.rows);
|
|
189
|
+
if (params.trailingRows && params.trailingRows.length > 0) {
|
|
190
|
+
containerComponents.push(new Separator({ divider: true, spacing: "small" }));
|
|
191
|
+
containerComponents.push(...params.trailingRows);
|
|
192
|
+
}
|
|
193
|
+
if (params.footer) {
|
|
194
|
+
containerComponents.push(new Separator({ divider: false, spacing: "small" }));
|
|
195
|
+
containerComponents.push(new TextDisplay(`-# ${params.footer}`));
|
|
196
|
+
}
|
|
197
|
+
const container = new Container(containerComponents);
|
|
198
|
+
return {
|
|
199
|
+
layout: "v2",
|
|
200
|
+
components: [container],
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
function buildProviderRows(params) {
|
|
204
|
+
const rows = chunkProvidersForRows(params.page.items).map((providers) => new Row(providers.map((provider) => {
|
|
205
|
+
const style = provider.id === params.currentProvider ? ButtonStyle.Primary : ButtonStyle.Secondary;
|
|
206
|
+
return createModelPickerButton({
|
|
207
|
+
label: formatProviderButtonLabel(provider.id),
|
|
208
|
+
style,
|
|
209
|
+
customId: buildDiscordModelPickerCustomId({
|
|
210
|
+
command: params.command,
|
|
211
|
+
action: "provider",
|
|
212
|
+
view: "models",
|
|
213
|
+
provider: provider.id,
|
|
214
|
+
page: params.page.page,
|
|
215
|
+
userId: params.userId,
|
|
216
|
+
}),
|
|
217
|
+
});
|
|
218
|
+
})));
|
|
219
|
+
return rows;
|
|
220
|
+
}
|
|
221
|
+
function buildModelRows(params) {
|
|
222
|
+
const parsedCurrentModel = parseCurrentModelRef(params.currentModel);
|
|
223
|
+
const parsedPendingModel = parseCurrentModelRef(params.pendingModel);
|
|
224
|
+
const rows = [];
|
|
225
|
+
const hasQuickModels = (params.quickModels ?? []).length > 0;
|
|
226
|
+
const providerPage = getDiscordModelPickerProviderPage({
|
|
227
|
+
data: params.data,
|
|
228
|
+
page: params.providerPage,
|
|
229
|
+
});
|
|
230
|
+
const providerOptions = providerPage.items.map((provider) => ({
|
|
231
|
+
label: provider.id,
|
|
232
|
+
value: provider.id,
|
|
233
|
+
default: provider.id === params.modelPage.provider,
|
|
234
|
+
}));
|
|
235
|
+
rows.push(new Row([
|
|
236
|
+
createModelSelect({
|
|
237
|
+
customId: buildDiscordModelPickerCustomId({
|
|
238
|
+
command: params.command,
|
|
239
|
+
action: "provider",
|
|
240
|
+
view: "models",
|
|
241
|
+
provider: params.modelPage.provider,
|
|
242
|
+
page: providerPage.page,
|
|
243
|
+
providerPage: providerPage.page,
|
|
244
|
+
userId: params.userId,
|
|
245
|
+
}),
|
|
246
|
+
options: providerOptions,
|
|
247
|
+
placeholder: "Select provider",
|
|
248
|
+
}),
|
|
249
|
+
]));
|
|
250
|
+
const selectedModelRef = parsedPendingModel ?? parsedCurrentModel;
|
|
251
|
+
const modelOptions = params.modelPage.items.map((model) => ({
|
|
252
|
+
label: model,
|
|
253
|
+
value: model,
|
|
254
|
+
default: selectedModelRef
|
|
255
|
+
? selectedModelRef.provider === params.modelPage.provider && selectedModelRef.model === model
|
|
256
|
+
: false,
|
|
257
|
+
}));
|
|
258
|
+
rows.push(new Row([
|
|
259
|
+
createModelSelect({
|
|
260
|
+
customId: buildDiscordModelPickerCustomId({
|
|
261
|
+
command: params.command,
|
|
262
|
+
action: "model",
|
|
263
|
+
view: "models",
|
|
264
|
+
provider: params.modelPage.provider,
|
|
265
|
+
page: params.modelPage.page,
|
|
266
|
+
providerPage: providerPage.page,
|
|
267
|
+
userId: params.userId,
|
|
268
|
+
}),
|
|
269
|
+
options: modelOptions,
|
|
270
|
+
placeholder: `Select ${params.modelPage.provider} model`,
|
|
271
|
+
}),
|
|
272
|
+
]));
|
|
273
|
+
const resolvedDefault = params.data.resolvedDefault;
|
|
274
|
+
const shouldDisableReset = Boolean(parsedCurrentModel) &&
|
|
275
|
+
parsedCurrentModel?.provider === resolvedDefault.provider &&
|
|
276
|
+
parsedCurrentModel?.model === resolvedDefault.model;
|
|
277
|
+
const hasPendingSelection = Boolean(parsedPendingModel) &&
|
|
278
|
+
parsedPendingModel?.provider === params.modelPage.provider &&
|
|
279
|
+
typeof params.pendingModelIndex === "number" &&
|
|
280
|
+
params.pendingModelIndex > 0;
|
|
281
|
+
const buttonRowItems = [
|
|
282
|
+
createModelPickerButton({
|
|
283
|
+
label: "Cancel",
|
|
284
|
+
style: ButtonStyle.Secondary,
|
|
285
|
+
customId: buildDiscordModelPickerCustomId({
|
|
286
|
+
command: params.command,
|
|
287
|
+
action: "cancel",
|
|
288
|
+
view: "models",
|
|
289
|
+
provider: params.modelPage.provider,
|
|
290
|
+
page: params.modelPage.page,
|
|
291
|
+
providerPage: providerPage.page,
|
|
292
|
+
userId: params.userId,
|
|
293
|
+
}),
|
|
294
|
+
}),
|
|
295
|
+
createModelPickerButton({
|
|
296
|
+
label: "Reset to default",
|
|
297
|
+
style: ButtonStyle.Secondary,
|
|
298
|
+
disabled: shouldDisableReset,
|
|
299
|
+
customId: buildDiscordModelPickerCustomId({
|
|
300
|
+
command: params.command,
|
|
301
|
+
action: "reset",
|
|
302
|
+
view: "models",
|
|
303
|
+
provider: params.modelPage.provider,
|
|
304
|
+
page: params.modelPage.page,
|
|
305
|
+
providerPage: providerPage.page,
|
|
306
|
+
userId: params.userId,
|
|
307
|
+
}),
|
|
308
|
+
}),
|
|
309
|
+
];
|
|
310
|
+
if (hasQuickModels) {
|
|
311
|
+
buttonRowItems.push(createModelPickerButton({
|
|
312
|
+
label: "Recents",
|
|
313
|
+
style: ButtonStyle.Secondary,
|
|
314
|
+
customId: buildDiscordModelPickerCustomId({
|
|
315
|
+
command: params.command,
|
|
316
|
+
action: "recents",
|
|
317
|
+
view: "recents",
|
|
318
|
+
provider: params.modelPage.provider,
|
|
319
|
+
page: params.modelPage.page,
|
|
320
|
+
providerPage: providerPage.page,
|
|
321
|
+
userId: params.userId,
|
|
322
|
+
}),
|
|
323
|
+
}));
|
|
324
|
+
}
|
|
325
|
+
buttonRowItems.push(createModelPickerButton({
|
|
326
|
+
label: "Submit",
|
|
327
|
+
style: ButtonStyle.Primary,
|
|
328
|
+
disabled: !hasPendingSelection,
|
|
329
|
+
customId: buildDiscordModelPickerCustomId({
|
|
330
|
+
command: params.command,
|
|
331
|
+
action: "submit",
|
|
332
|
+
view: "models",
|
|
333
|
+
provider: params.modelPage.provider,
|
|
334
|
+
page: params.modelPage.page,
|
|
335
|
+
providerPage: providerPage.page,
|
|
336
|
+
modelIndex: params.pendingModelIndex,
|
|
337
|
+
userId: params.userId,
|
|
338
|
+
}),
|
|
339
|
+
}));
|
|
340
|
+
return { rows, buttonRow: new Row(buttonRowItems) };
|
|
341
|
+
}
|
|
342
|
+
/**
|
|
343
|
+
* Source-of-truth data for Discord picker views. This intentionally reuses the
|
|
344
|
+
* same provider/model resolver used by text and Telegram model commands.
|
|
345
|
+
*/
|
|
346
|
+
export async function loadDiscordModelPickerData(cfg) {
|
|
347
|
+
return buildModelsProviderData(cfg);
|
|
348
|
+
}
|
|
349
|
+
export function buildDiscordModelPickerCustomId(params) {
|
|
350
|
+
const userId = params.userId.trim();
|
|
351
|
+
if (!userId) {
|
|
352
|
+
throw new Error("Discord model picker custom_id requires userId");
|
|
353
|
+
}
|
|
354
|
+
const page = normalizePage(params.page);
|
|
355
|
+
const providerPage = typeof params.providerPage === "number" && Number.isFinite(params.providerPage)
|
|
356
|
+
? Math.max(1, Math.floor(params.providerPage))
|
|
357
|
+
: undefined;
|
|
358
|
+
const normalizedProvider = params.provider ? normalizeProviderId(params.provider) : undefined;
|
|
359
|
+
const modelIndex = typeof params.modelIndex === "number" && Number.isFinite(params.modelIndex)
|
|
360
|
+
? Math.max(1, Math.floor(params.modelIndex))
|
|
361
|
+
: undefined;
|
|
362
|
+
const recentSlot = typeof params.recentSlot === "number" && Number.isFinite(params.recentSlot)
|
|
363
|
+
? Math.max(1, Math.floor(params.recentSlot))
|
|
364
|
+
: undefined;
|
|
365
|
+
const parts = [
|
|
366
|
+
`${DISCORD_MODEL_PICKER_CUSTOM_ID_KEY}:cmd=${encodeCustomIdValue(params.command)}`,
|
|
367
|
+
`act=${encodeCustomIdValue(params.action)}`,
|
|
368
|
+
`view=${encodeCustomIdValue(params.view)}`,
|
|
369
|
+
`u=${encodeCustomIdValue(userId)}`,
|
|
370
|
+
`pg=${String(page)}`,
|
|
371
|
+
];
|
|
372
|
+
if (normalizedProvider) {
|
|
373
|
+
parts.push(`p=${encodeCustomIdValue(normalizedProvider)}`);
|
|
374
|
+
}
|
|
375
|
+
if (providerPage) {
|
|
376
|
+
parts.push(`pp=${String(providerPage)}`);
|
|
377
|
+
}
|
|
378
|
+
if (modelIndex) {
|
|
379
|
+
parts.push(`mi=${String(modelIndex)}`);
|
|
380
|
+
}
|
|
381
|
+
if (recentSlot) {
|
|
382
|
+
parts.push(`rs=${String(recentSlot)}`);
|
|
383
|
+
}
|
|
384
|
+
const customId = parts.join(";");
|
|
385
|
+
if (customId.length > DISCORD_CUSTOM_ID_MAX_CHARS) {
|
|
386
|
+
throw new Error(`Discord model picker custom_id exceeds ${DISCORD_CUSTOM_ID_MAX_CHARS} chars (${customId.length})`);
|
|
387
|
+
}
|
|
388
|
+
return customId;
|
|
389
|
+
}
|
|
390
|
+
export function parseDiscordModelPickerCustomId(customId) {
|
|
391
|
+
const trimmed = customId.trim();
|
|
392
|
+
if (!trimmed.startsWith(`${DISCORD_MODEL_PICKER_CUSTOM_ID_KEY}:`)) {
|
|
393
|
+
return null;
|
|
394
|
+
}
|
|
395
|
+
const rawParts = trimmed.split(";");
|
|
396
|
+
const data = {};
|
|
397
|
+
for (const part of rawParts) {
|
|
398
|
+
const equalsIndex = part.indexOf("=");
|
|
399
|
+
if (equalsIndex <= 0) {
|
|
400
|
+
continue;
|
|
401
|
+
}
|
|
402
|
+
const rawKey = part.slice(0, equalsIndex);
|
|
403
|
+
const rawValue = part.slice(equalsIndex + 1);
|
|
404
|
+
const key = rawKey.includes(":") ? rawKey.split(":").slice(1).join(":") : rawKey;
|
|
405
|
+
if (!key) {
|
|
406
|
+
continue;
|
|
407
|
+
}
|
|
408
|
+
data[key] = rawValue;
|
|
409
|
+
}
|
|
410
|
+
return parseDiscordModelPickerData(data);
|
|
411
|
+
}
|
|
412
|
+
export function parseDiscordModelPickerData(data) {
|
|
413
|
+
if (!data || typeof data !== "object") {
|
|
414
|
+
return null;
|
|
415
|
+
}
|
|
416
|
+
const command = decodeCustomIdValue(coerceString(data.cmd));
|
|
417
|
+
const action = decodeCustomIdValue(coerceString(data.act));
|
|
418
|
+
const view = decodeCustomIdValue(coerceString(data.view));
|
|
419
|
+
const userId = decodeCustomIdValue(coerceString(data.u));
|
|
420
|
+
const providerRaw = decodeCustomIdValue(coerceString(data.p));
|
|
421
|
+
const page = parseRawPage(data.pg);
|
|
422
|
+
const providerPage = parseRawPositiveInt(data.pp);
|
|
423
|
+
const modelIndex = parseRawPositiveInt(data.mi);
|
|
424
|
+
const recentSlot = parseRawPositiveInt(data.rs);
|
|
425
|
+
if (!isValidCommandContext(command) || !isValidPickerAction(action) || !isValidPickerView(view)) {
|
|
426
|
+
return null;
|
|
427
|
+
}
|
|
428
|
+
const trimmedUserId = userId.trim();
|
|
429
|
+
if (!trimmedUserId) {
|
|
430
|
+
return null;
|
|
431
|
+
}
|
|
432
|
+
const provider = providerRaw ? normalizeProviderId(providerRaw) : undefined;
|
|
433
|
+
return {
|
|
434
|
+
command,
|
|
435
|
+
action,
|
|
436
|
+
view,
|
|
437
|
+
userId: trimmedUserId,
|
|
438
|
+
provider,
|
|
439
|
+
page,
|
|
440
|
+
...(typeof providerPage === "number" ? { providerPage } : {}),
|
|
441
|
+
...(typeof modelIndex === "number" ? { modelIndex } : {}),
|
|
442
|
+
...(typeof recentSlot === "number" ? { recentSlot } : {}),
|
|
443
|
+
};
|
|
444
|
+
}
|
|
445
|
+
export function buildDiscordModelPickerProviderItems(data) {
|
|
446
|
+
return data.providers.map((provider) => ({
|
|
447
|
+
id: provider,
|
|
448
|
+
count: data.byProvider.get(provider)?.size ?? 0,
|
|
449
|
+
}));
|
|
450
|
+
}
|
|
451
|
+
export function getDiscordModelPickerProviderPage(params) {
|
|
452
|
+
const items = buildDiscordModelPickerProviderItems(params.data);
|
|
453
|
+
const canFitSinglePage = items.length <= DISCORD_MODEL_PICKER_PROVIDER_SINGLE_PAGE_MAX;
|
|
454
|
+
const maxPageSize = canFitSinglePage
|
|
455
|
+
? DISCORD_MODEL_PICKER_PROVIDER_SINGLE_PAGE_MAX
|
|
456
|
+
: DISCORD_MODEL_PICKER_PROVIDER_PAGE_SIZE;
|
|
457
|
+
const pageSize = clampPageSize(params.pageSize, maxPageSize, maxPageSize);
|
|
458
|
+
return paginateItems({
|
|
459
|
+
items,
|
|
460
|
+
page: normalizePage(params.page),
|
|
461
|
+
pageSize,
|
|
462
|
+
});
|
|
463
|
+
}
|
|
464
|
+
export function getDiscordModelPickerModelPage(params) {
|
|
465
|
+
const provider = normalizeProviderId(params.provider);
|
|
466
|
+
const modelSet = params.data.byProvider.get(provider);
|
|
467
|
+
if (!modelSet) {
|
|
468
|
+
return null;
|
|
469
|
+
}
|
|
470
|
+
const pageSize = clampPageSize(params.pageSize, DISCORD_MODEL_PICKER_MODEL_PAGE_SIZE, DISCORD_MODEL_PICKER_MODEL_PAGE_SIZE);
|
|
471
|
+
const models = [...modelSet].toSorted();
|
|
472
|
+
const page = paginateItems({
|
|
473
|
+
items: models,
|
|
474
|
+
page: normalizePage(params.page),
|
|
475
|
+
pageSize,
|
|
476
|
+
});
|
|
477
|
+
return {
|
|
478
|
+
...page,
|
|
479
|
+
provider,
|
|
480
|
+
};
|
|
481
|
+
}
|
|
482
|
+
export function renderDiscordModelPickerProvidersView(params) {
|
|
483
|
+
const page = getDiscordModelPickerProviderPage({ data: params.data, page: params.page });
|
|
484
|
+
const parsedCurrent = parseCurrentModelRef(params.currentModel);
|
|
485
|
+
const rows = buildProviderRows({
|
|
486
|
+
command: params.command,
|
|
487
|
+
userId: params.userId,
|
|
488
|
+
page,
|
|
489
|
+
currentProvider: parsedCurrent?.provider,
|
|
490
|
+
});
|
|
491
|
+
const detailLines = [
|
|
492
|
+
formatCurrentModelLine(params.currentModel),
|
|
493
|
+
`Select a provider (${page.totalItems} available).`,
|
|
494
|
+
];
|
|
495
|
+
return buildRenderedShell({
|
|
496
|
+
layout: params.layout ?? "v2",
|
|
497
|
+
title: "Model Picker",
|
|
498
|
+
detailLines,
|
|
499
|
+
rows,
|
|
500
|
+
footer: `All ${page.totalItems} providers shown`,
|
|
501
|
+
});
|
|
502
|
+
}
|
|
503
|
+
export function renderDiscordModelPickerModelsView(params) {
|
|
504
|
+
const providerPage = normalizePage(params.providerPage);
|
|
505
|
+
const modelPage = getDiscordModelPickerModelPage({
|
|
506
|
+
data: params.data,
|
|
507
|
+
provider: params.provider,
|
|
508
|
+
page: params.page,
|
|
509
|
+
});
|
|
510
|
+
if (!modelPage) {
|
|
511
|
+
const rows = [
|
|
512
|
+
new Row([
|
|
513
|
+
createModelPickerButton({
|
|
514
|
+
label: "Back",
|
|
515
|
+
customId: buildDiscordModelPickerCustomId({
|
|
516
|
+
command: params.command,
|
|
517
|
+
action: "back",
|
|
518
|
+
view: "providers",
|
|
519
|
+
page: providerPage,
|
|
520
|
+
userId: params.userId,
|
|
521
|
+
}),
|
|
522
|
+
}),
|
|
523
|
+
]),
|
|
524
|
+
];
|
|
525
|
+
return buildRenderedShell({
|
|
526
|
+
layout: params.layout ?? "v2",
|
|
527
|
+
title: "Model Picker",
|
|
528
|
+
detailLines: [
|
|
529
|
+
formatCurrentModelLine(params.currentModel),
|
|
530
|
+
`Provider not found: ${normalizeProviderId(params.provider)}`,
|
|
531
|
+
],
|
|
532
|
+
rows,
|
|
533
|
+
footer: "Choose a different provider.",
|
|
534
|
+
});
|
|
535
|
+
}
|
|
536
|
+
const { rows, buttonRow } = buildModelRows({
|
|
537
|
+
command: params.command,
|
|
538
|
+
userId: params.userId,
|
|
539
|
+
data: params.data,
|
|
540
|
+
providerPage,
|
|
541
|
+
modelPage,
|
|
542
|
+
currentModel: params.currentModel,
|
|
543
|
+
pendingModel: params.pendingModel,
|
|
544
|
+
pendingModelIndex: params.pendingModelIndex,
|
|
545
|
+
quickModels: params.quickModels,
|
|
546
|
+
});
|
|
547
|
+
const defaultModel = `${params.data.resolvedDefault.provider}/${params.data.resolvedDefault.model}`;
|
|
548
|
+
const pendingLine = params.pendingModel
|
|
549
|
+
? `Selected: ${params.pendingModel} (press Submit)`
|
|
550
|
+
: "Select a model, then press Submit.";
|
|
551
|
+
return buildRenderedShell({
|
|
552
|
+
layout: params.layout ?? "v2",
|
|
553
|
+
title: "Model Picker",
|
|
554
|
+
detailLines: [formatCurrentModelLine(params.currentModel), `Default: ${defaultModel}`],
|
|
555
|
+
preRowText: pendingLine,
|
|
556
|
+
rows,
|
|
557
|
+
trailingRows: [buttonRow],
|
|
558
|
+
});
|
|
559
|
+
}
|
|
560
|
+
function formatRecentsButtonLabel(modelRef, suffix) {
|
|
561
|
+
const maxLen = 80;
|
|
562
|
+
const label = suffix ? `${modelRef} ${suffix}` : modelRef;
|
|
563
|
+
if (label.length <= maxLen) {
|
|
564
|
+
return label;
|
|
565
|
+
}
|
|
566
|
+
const trimmed = suffix
|
|
567
|
+
? `${modelRef.slice(0, maxLen - suffix.length - 2)}… ${suffix}`
|
|
568
|
+
: `${modelRef.slice(0, maxLen - 1)}…`;
|
|
569
|
+
return trimmed;
|
|
570
|
+
}
|
|
571
|
+
export function renderDiscordModelPickerRecentsView(params) {
|
|
572
|
+
const defaultModelRef = `${params.data.resolvedDefault.provider}/${params.data.resolvedDefault.model}`;
|
|
573
|
+
const rows = [];
|
|
574
|
+
// Dedupe: filter recents that match the default model.
|
|
575
|
+
const dedupedQuickModels = params.quickModels.filter((modelRef) => modelRef !== defaultModelRef);
|
|
576
|
+
// Default model button — slot 1.
|
|
577
|
+
rows.push(new Row([
|
|
578
|
+
createModelPickerButton({
|
|
579
|
+
label: formatRecentsButtonLabel(defaultModelRef, "(default)"),
|
|
580
|
+
style: ButtonStyle.Secondary,
|
|
581
|
+
customId: buildDiscordModelPickerCustomId({
|
|
582
|
+
command: params.command,
|
|
583
|
+
action: "submit",
|
|
584
|
+
view: "recents",
|
|
585
|
+
recentSlot: 1,
|
|
586
|
+
provider: params.provider,
|
|
587
|
+
page: params.page,
|
|
588
|
+
providerPage: params.providerPage,
|
|
589
|
+
userId: params.userId,
|
|
590
|
+
}),
|
|
591
|
+
}),
|
|
592
|
+
]));
|
|
593
|
+
// Recent model buttons — slot 2+.
|
|
594
|
+
for (let i = 0; i < dedupedQuickModels.length; i++) {
|
|
595
|
+
const modelRef = dedupedQuickModels[i];
|
|
596
|
+
rows.push(new Row([
|
|
597
|
+
createModelPickerButton({
|
|
598
|
+
label: formatRecentsButtonLabel(modelRef),
|
|
599
|
+
style: ButtonStyle.Secondary,
|
|
600
|
+
customId: buildDiscordModelPickerCustomId({
|
|
601
|
+
command: params.command,
|
|
602
|
+
action: "submit",
|
|
603
|
+
view: "recents",
|
|
604
|
+
recentSlot: i + 2,
|
|
605
|
+
provider: params.provider,
|
|
606
|
+
page: params.page,
|
|
607
|
+
providerPage: params.providerPage,
|
|
608
|
+
userId: params.userId,
|
|
609
|
+
}),
|
|
610
|
+
}),
|
|
611
|
+
]));
|
|
612
|
+
}
|
|
613
|
+
// Back button after a divider (via trailingRows).
|
|
614
|
+
const backRow = new Row([
|
|
615
|
+
createModelPickerButton({
|
|
616
|
+
label: "Back",
|
|
617
|
+
style: ButtonStyle.Secondary,
|
|
618
|
+
customId: buildDiscordModelPickerCustomId({
|
|
619
|
+
command: params.command,
|
|
620
|
+
action: "back",
|
|
621
|
+
view: "models",
|
|
622
|
+
provider: params.provider,
|
|
623
|
+
page: params.page,
|
|
624
|
+
providerPage: params.providerPage,
|
|
625
|
+
userId: params.userId,
|
|
626
|
+
}),
|
|
627
|
+
}),
|
|
628
|
+
]);
|
|
629
|
+
return buildRenderedShell({
|
|
630
|
+
layout: params.layout ?? "v2",
|
|
631
|
+
title: "Recents",
|
|
632
|
+
detailLines: [
|
|
633
|
+
"Models you've previously selected appear here.",
|
|
634
|
+
formatCurrentModelLine(params.currentModel),
|
|
635
|
+
],
|
|
636
|
+
preRowText: "Tap a model to switch.",
|
|
637
|
+
rows,
|
|
638
|
+
trailingRows: [backRow],
|
|
639
|
+
});
|
|
640
|
+
}
|
|
641
|
+
export function toDiscordModelPickerMessagePayload(view) {
|
|
642
|
+
if (view.layout === "classic") {
|
|
643
|
+
return {
|
|
644
|
+
content: view.content,
|
|
645
|
+
components: view.components,
|
|
646
|
+
};
|
|
647
|
+
}
|
|
648
|
+
return {
|
|
649
|
+
components: view.components,
|
|
650
|
+
};
|
|
651
|
+
}
|