@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,5 +1,5 @@
|
|
|
1
1
|
import { createSubsystemLogger } from "../logging/subsystem.js";
|
|
2
|
-
import { getImageMetadata, resizeToJpeg } from "../media/image-ops.js";
|
|
2
|
+
import { buildImageResizeSideGrid, getImageMetadata, IMAGE_REDUCE_QUALITY_STEPS, resizeToJpeg, } from "../media/image-ops.js";
|
|
3
3
|
import { DEFAULT_IMAGE_MAX_BYTES, DEFAULT_IMAGE_MAX_DIMENSION_PX, } from "./image-sanitization.js";
|
|
4
4
|
// Anthropic Messages API limitations (observed in Pool Bot sessions):
|
|
5
5
|
// - Images over ~2000px per side can fail in multi-image requests.
|
|
@@ -49,6 +49,68 @@ function formatBytesShort(bytes) {
|
|
|
49
49
|
}
|
|
50
50
|
return `${(bytes / (1024 * 1024)).toFixed(2)}MB`;
|
|
51
51
|
}
|
|
52
|
+
function parseMediaPathFromText(text) {
|
|
53
|
+
for (const line of text.split(/\r?\n/u)) {
|
|
54
|
+
const trimmed = line.trim();
|
|
55
|
+
if (!trimmed.startsWith("MEDIA:")) {
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
58
|
+
const raw = trimmed.slice("MEDIA:".length).trim();
|
|
59
|
+
if (!raw) {
|
|
60
|
+
continue;
|
|
61
|
+
}
|
|
62
|
+
const backtickWrapped = raw.match(/^`([^`]+)`$/u);
|
|
63
|
+
return (backtickWrapped?.[1] ?? raw).trim();
|
|
64
|
+
}
|
|
65
|
+
return undefined;
|
|
66
|
+
}
|
|
67
|
+
function fileNameFromPathLike(pathLike) {
|
|
68
|
+
const value = pathLike.trim();
|
|
69
|
+
if (!value) {
|
|
70
|
+
return undefined;
|
|
71
|
+
}
|
|
72
|
+
try {
|
|
73
|
+
const url = new URL(value);
|
|
74
|
+
const candidate = url.pathname.split("/").filter(Boolean).at(-1);
|
|
75
|
+
return candidate && candidate.length > 0 ? candidate : undefined;
|
|
76
|
+
}
|
|
77
|
+
catch {
|
|
78
|
+
// Not a URL; continue with path-like parsing.
|
|
79
|
+
}
|
|
80
|
+
const normalized = value.replaceAll("\\", "/");
|
|
81
|
+
const candidate = normalized.split("/").filter(Boolean).at(-1);
|
|
82
|
+
return candidate && candidate.length > 0 ? candidate : undefined;
|
|
83
|
+
}
|
|
84
|
+
function inferImageFileName(params) {
|
|
85
|
+
const rec = params.block;
|
|
86
|
+
const explicitKeys = ["fileName", "filename", "path", "url"];
|
|
87
|
+
for (const key of explicitKeys) {
|
|
88
|
+
const raw = rec[key];
|
|
89
|
+
if (typeof raw !== "string" || raw.trim().length === 0) {
|
|
90
|
+
continue;
|
|
91
|
+
}
|
|
92
|
+
const candidate = fileNameFromPathLike(raw);
|
|
93
|
+
if (candidate) {
|
|
94
|
+
return candidate;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
if (typeof rec.name === "string" && rec.name.trim().length > 0) {
|
|
98
|
+
return rec.name.trim();
|
|
99
|
+
}
|
|
100
|
+
if (params.mediaPathHint) {
|
|
101
|
+
const candidate = fileNameFromPathLike(params.mediaPathHint);
|
|
102
|
+
if (candidate) {
|
|
103
|
+
return candidate;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
if (typeof params.label === "string" && params.label.startsWith("read:")) {
|
|
107
|
+
const candidate = fileNameFromPathLike(params.label.slice("read:".length));
|
|
108
|
+
if (candidate) {
|
|
109
|
+
return candidate;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
return undefined;
|
|
113
|
+
}
|
|
52
114
|
async function resizeImageBase64IfNeeded(params) {
|
|
53
115
|
const buf = Buffer.from(params.base64, "base64");
|
|
54
116
|
const meta = await getImageMetadata(buf);
|
|
@@ -69,16 +131,12 @@ async function resizeImageBase64IfNeeded(params) {
|
|
|
69
131
|
height,
|
|
70
132
|
};
|
|
71
133
|
}
|
|
72
|
-
const qualities = [85, 75, 65, 55, 45, 35];
|
|
73
134
|
const maxDim = hasDimensions ? Math.max(width ?? 0, height ?? 0) : params.maxDimensionPx;
|
|
74
135
|
const sideStart = maxDim > 0 ? Math.min(params.maxDimensionPx, maxDim) : params.maxDimensionPx;
|
|
75
|
-
const sideGrid =
|
|
76
|
-
.filter((v) => v > 0 && v <= params.maxDimensionPx)
|
|
77
|
-
.filter((v, i, arr) => v > 0 && arr.indexOf(v) === i)
|
|
78
|
-
.toSorted((a, b) => b - a);
|
|
136
|
+
const sideGrid = buildImageResizeSideGrid(params.maxDimensionPx, sideStart);
|
|
79
137
|
let smallest = null;
|
|
80
138
|
for (const side of sideGrid) {
|
|
81
|
-
for (const quality of
|
|
139
|
+
for (const quality of IMAGE_REDUCE_QUALITY_STEPS) {
|
|
82
140
|
const out = await resizeToJpeg({
|
|
83
141
|
buffer: buf,
|
|
84
142
|
maxSide: side,
|
|
@@ -92,11 +150,15 @@ async function resizeImageBase64IfNeeded(params) {
|
|
|
92
150
|
const sourcePixels = typeof width === "number" && typeof height === "number"
|
|
93
151
|
? `${width}x${height}px`
|
|
94
152
|
: "unknown";
|
|
153
|
+
const sourceWithFile = params.fileName
|
|
154
|
+
? `${params.fileName} ${sourcePixels}`
|
|
155
|
+
: sourcePixels;
|
|
95
156
|
const byteReductionPct = buf.byteLength > 0
|
|
96
157
|
? Number((((buf.byteLength - out.byteLength) / buf.byteLength) * 100).toFixed(1))
|
|
97
158
|
: 0;
|
|
98
|
-
log.info(`Image resized to fit limits: ${
|
|
159
|
+
log.info(`Image resized to fit limits: ${sourceWithFile} ${formatBytesShort(buf.byteLength)} -> ${formatBytesShort(out.byteLength)} (-${byteReductionPct}%)`, {
|
|
99
160
|
label: params.label,
|
|
161
|
+
fileName: params.fileName,
|
|
100
162
|
sourceMimeType: params.mimeType,
|
|
101
163
|
sourceWidth: width,
|
|
102
164
|
sourceHeight: height,
|
|
@@ -125,8 +187,10 @@ async function resizeImageBase64IfNeeded(params) {
|
|
|
125
187
|
const maxMb = (params.maxBytes / (1024 * 1024)).toFixed(0);
|
|
126
188
|
const gotMb = (best.byteLength / (1024 * 1024)).toFixed(2);
|
|
127
189
|
const sourcePixels = typeof width === "number" && typeof height === "number" ? `${width}x${height}px` : "unknown";
|
|
128
|
-
|
|
190
|
+
const sourceWithFile = params.fileName ? `${params.fileName} ${sourcePixels}` : sourcePixels;
|
|
191
|
+
log.warn(`Image resize failed to fit limits: ${sourceWithFile} best=${formatBytesShort(best.byteLength)} limit=${formatBytesShort(params.maxBytes)}`, {
|
|
129
192
|
label: params.label,
|
|
193
|
+
fileName: params.fileName,
|
|
130
194
|
sourceMimeType: params.mimeType,
|
|
131
195
|
sourceWidth: width,
|
|
132
196
|
sourceHeight: height,
|
|
@@ -143,7 +207,14 @@ export async function sanitizeContentBlocksImages(blocks, label, opts = {}) {
|
|
|
143
207
|
const maxDimensionPx = Math.max(opts.maxDimensionPx ?? MAX_IMAGE_DIMENSION_PX, 1);
|
|
144
208
|
const maxBytes = Math.max(opts.maxBytes ?? MAX_IMAGE_BYTES, 1);
|
|
145
209
|
const out = [];
|
|
210
|
+
let mediaPathHint;
|
|
146
211
|
for (const block of blocks) {
|
|
212
|
+
if (isTextBlock(block)) {
|
|
213
|
+
const mediaPath = parseMediaPathFromText(block.text);
|
|
214
|
+
if (mediaPath) {
|
|
215
|
+
mediaPathHint = mediaPath;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
147
218
|
if (!isImageBlock(block)) {
|
|
148
219
|
out.push(block);
|
|
149
220
|
continue;
|
|
@@ -159,12 +230,14 @@ export async function sanitizeContentBlocksImages(blocks, label, opts = {}) {
|
|
|
159
230
|
try {
|
|
160
231
|
const inferredMimeType = inferMimeTypeFromBase64(data);
|
|
161
232
|
const mimeType = inferredMimeType ?? block.mimeType;
|
|
233
|
+
const fileName = inferImageFileName({ block, label, mediaPathHint });
|
|
162
234
|
const resized = await resizeImageBase64IfNeeded({
|
|
163
235
|
base64: data,
|
|
164
236
|
mimeType,
|
|
165
237
|
maxDimensionPx,
|
|
166
238
|
maxBytes,
|
|
167
239
|
label,
|
|
240
|
+
fileName,
|
|
168
241
|
});
|
|
169
242
|
out.push({
|
|
170
243
|
...block,
|
|
@@ -1,3 +1,15 @@
|
|
|
1
|
+
// Keep tool-policy browser-safe: do not import tools/common at runtime.
|
|
2
|
+
function wrapOwnerOnlyToolExecution(tool, senderIsOwner) {
|
|
3
|
+
if (tool.ownerOnly !== true || senderIsOwner || !tool.execute) {
|
|
4
|
+
return tool;
|
|
5
|
+
}
|
|
6
|
+
return {
|
|
7
|
+
...tool,
|
|
8
|
+
execute: async () => {
|
|
9
|
+
throw new Error("Tool restricted to owner senders.");
|
|
10
|
+
},
|
|
11
|
+
};
|
|
12
|
+
}
|
|
1
13
|
const TOOL_NAME_ALIASES = {
|
|
2
14
|
bash: "exec",
|
|
3
15
|
"apply-patch": "apply_patch",
|
|
@@ -16,6 +28,7 @@ export const TOOL_GROUPS = {
|
|
|
16
28
|
"sessions_history",
|
|
17
29
|
"sessions_send",
|
|
18
30
|
"sessions_spawn",
|
|
31
|
+
"subagents",
|
|
19
32
|
"session_status",
|
|
20
33
|
],
|
|
21
34
|
// UI helpers
|
|
@@ -26,7 +39,7 @@ export const TOOL_GROUPS = {
|
|
|
26
39
|
"group:messaging": ["message"],
|
|
27
40
|
// Nodes + device tools
|
|
28
41
|
"group:nodes": ["nodes"],
|
|
29
|
-
// All
|
|
42
|
+
// All Pool Bot native tools (excludes provider plugins).
|
|
30
43
|
"group:poolbot": [
|
|
31
44
|
"browser",
|
|
32
45
|
"canvas",
|
|
@@ -39,6 +52,7 @@ export const TOOL_GROUPS = {
|
|
|
39
52
|
"sessions_history",
|
|
40
53
|
"sessions_send",
|
|
41
54
|
"sessions_spawn",
|
|
55
|
+
"subagents",
|
|
42
56
|
"session_status",
|
|
43
57
|
"memory_search",
|
|
44
58
|
"memory_get",
|
|
@@ -47,7 +61,7 @@ export const TOOL_GROUPS = {
|
|
|
47
61
|
"image",
|
|
48
62
|
],
|
|
49
63
|
};
|
|
50
|
-
const
|
|
64
|
+
const OWNER_ONLY_TOOL_NAME_FALLBACKS = new Set(["whatsapp_login", "cron", "gateway"]);
|
|
51
65
|
const TOOL_PROFILES = {
|
|
52
66
|
minimal: {
|
|
53
67
|
allow: ["session_status"],
|
|
@@ -71,31 +85,27 @@ export function normalizeToolName(name) {
|
|
|
71
85
|
return TOOL_NAME_ALIASES[normalized] ?? normalized;
|
|
72
86
|
}
|
|
73
87
|
export function isOwnerOnlyToolName(name) {
|
|
74
|
-
return
|
|
88
|
+
return OWNER_ONLY_TOOL_NAME_FALLBACKS.has(normalizeToolName(name));
|
|
89
|
+
}
|
|
90
|
+
function isOwnerOnlyTool(tool) {
|
|
91
|
+
return tool.ownerOnly === true || isOwnerOnlyToolName(tool.name);
|
|
75
92
|
}
|
|
76
93
|
export function applyOwnerOnlyToolPolicy(tools, senderIsOwner) {
|
|
77
94
|
const withGuard = tools.map((tool) => {
|
|
78
|
-
if (!
|
|
95
|
+
if (!isOwnerOnlyTool(tool)) {
|
|
79
96
|
return tool;
|
|
80
97
|
}
|
|
81
|
-
|
|
82
|
-
return tool;
|
|
83
|
-
}
|
|
84
|
-
return {
|
|
85
|
-
...tool,
|
|
86
|
-
execute: async () => {
|
|
87
|
-
throw new Error("Tool restricted to owner senders.");
|
|
88
|
-
},
|
|
89
|
-
};
|
|
98
|
+
return wrapOwnerOnlyToolExecution(tool, senderIsOwner);
|
|
90
99
|
});
|
|
91
100
|
if (senderIsOwner) {
|
|
92
101
|
return withGuard;
|
|
93
102
|
}
|
|
94
|
-
return withGuard.filter((tool) => !
|
|
103
|
+
return withGuard.filter((tool) => !isOwnerOnlyTool(tool));
|
|
95
104
|
}
|
|
96
105
|
export function normalizeToolList(list) {
|
|
97
|
-
if (!list)
|
|
106
|
+
if (!list) {
|
|
98
107
|
return [];
|
|
108
|
+
}
|
|
99
109
|
return list.map(normalizeToolName).filter(Boolean);
|
|
100
110
|
}
|
|
101
111
|
export function expandToolGroups(list) {
|
|
@@ -114,14 +124,17 @@ export function expandToolGroups(list) {
|
|
|
114
124
|
export function collectExplicitAllowlist(policies) {
|
|
115
125
|
const entries = [];
|
|
116
126
|
for (const policy of policies) {
|
|
117
|
-
if (!policy?.allow)
|
|
127
|
+
if (!policy?.allow) {
|
|
118
128
|
continue;
|
|
129
|
+
}
|
|
119
130
|
for (const value of policy.allow) {
|
|
120
|
-
if (typeof value !== "string")
|
|
131
|
+
if (typeof value !== "string") {
|
|
121
132
|
continue;
|
|
133
|
+
}
|
|
122
134
|
const trimmed = value.trim();
|
|
123
|
-
if (trimmed)
|
|
135
|
+
if (trimmed) {
|
|
124
136
|
entries.push(trimmed);
|
|
137
|
+
}
|
|
125
138
|
}
|
|
126
139
|
}
|
|
127
140
|
return entries;
|
|
@@ -131,8 +144,9 @@ export function buildPluginToolGroups(params) {
|
|
|
131
144
|
const byPlugin = new Map();
|
|
132
145
|
for (const tool of params.tools) {
|
|
133
146
|
const meta = params.toolMeta(tool);
|
|
134
|
-
if (!meta)
|
|
147
|
+
if (!meta) {
|
|
135
148
|
continue;
|
|
149
|
+
}
|
|
136
150
|
const name = normalizeToolName(tool.name);
|
|
137
151
|
all.push(name);
|
|
138
152
|
const pluginId = meta.pluginId.toLowerCase();
|
|
@@ -143,8 +157,9 @@ export function buildPluginToolGroups(params) {
|
|
|
143
157
|
return { all, byPlugin };
|
|
144
158
|
}
|
|
145
159
|
export function expandPluginGroups(list, groups) {
|
|
146
|
-
if (!list || list.length === 0)
|
|
160
|
+
if (!list || list.length === 0) {
|
|
147
161
|
return list;
|
|
162
|
+
}
|
|
148
163
|
const expanded = [];
|
|
149
164
|
for (const entry of list) {
|
|
150
165
|
const normalized = normalizeToolName(entry);
|
|
@@ -167,8 +182,9 @@ export function expandPluginGroups(list, groups) {
|
|
|
167
182
|
return Array.from(new Set(expanded));
|
|
168
183
|
}
|
|
169
184
|
export function expandPolicyWithPluginGroups(policy, groups) {
|
|
170
|
-
if (!policy)
|
|
185
|
+
if (!policy) {
|
|
171
186
|
return undefined;
|
|
187
|
+
}
|
|
172
188
|
return {
|
|
173
189
|
allow: expandPluginGroups(policy.allow, groups),
|
|
174
190
|
deny: expandPluginGroups(policy.deny, groups),
|
|
@@ -187,13 +203,19 @@ export function stripPluginOnlyAllowlist(policy, groups, coreTools) {
|
|
|
187
203
|
const unknownAllowlist = [];
|
|
188
204
|
let hasCoreEntry = false;
|
|
189
205
|
for (const entry of normalized) {
|
|
206
|
+
if (entry === "*") {
|
|
207
|
+
hasCoreEntry = true;
|
|
208
|
+
continue;
|
|
209
|
+
}
|
|
190
210
|
const isPluginEntry = entry === "group:plugins" || pluginIds.has(entry) || pluginTools.has(entry);
|
|
191
211
|
const expanded = expandToolGroups([entry]);
|
|
192
212
|
const isCoreEntry = expanded.some((tool) => coreTools.has(tool));
|
|
193
|
-
if (isCoreEntry)
|
|
213
|
+
if (isCoreEntry) {
|
|
194
214
|
hasCoreEntry = true;
|
|
195
|
-
|
|
215
|
+
}
|
|
216
|
+
if (!isCoreEntry && !isPluginEntry) {
|
|
196
217
|
unknownAllowlist.push(entry);
|
|
218
|
+
}
|
|
197
219
|
}
|
|
198
220
|
const strippedAllowlist = !hasCoreEntry;
|
|
199
221
|
// When an allowlist contains only plugin tools, we strip it to avoid accidentally
|
|
@@ -209,13 +231,16 @@ export function stripPluginOnlyAllowlist(policy, groups, coreTools) {
|
|
|
209
231
|
};
|
|
210
232
|
}
|
|
211
233
|
export function resolveToolProfilePolicy(profile) {
|
|
212
|
-
if (!profile)
|
|
234
|
+
if (!profile) {
|
|
213
235
|
return undefined;
|
|
236
|
+
}
|
|
214
237
|
const resolved = TOOL_PROFILES[profile];
|
|
215
|
-
if (!resolved)
|
|
238
|
+
if (!resolved) {
|
|
216
239
|
return undefined;
|
|
217
|
-
|
|
240
|
+
}
|
|
241
|
+
if (!resolved.allow && !resolved.deny) {
|
|
218
242
|
return undefined;
|
|
243
|
+
}
|
|
219
244
|
return {
|
|
220
245
|
allow: resolved.allow ? [...resolved.allow] : undefined,
|
|
221
246
|
deny: resolved.deny ? [...resolved.deny] : undefined,
|
|
@@ -3,7 +3,7 @@ import { browserAct, browserArmDialog, browserArmFileChooser, browserConsoleMess
|
|
|
3
3
|
import { browserCloseTab, browserFocusTab, browserOpenTab, browserProfiles, browserSnapshot, browserStart, browserStatus, browserStop, browserTabs, } from "../../browser/client.js";
|
|
4
4
|
import { resolveBrowserConfig } from "../../browser/config.js";
|
|
5
5
|
import { DEFAULT_AI_SNAPSHOT_MAX_CHARS } from "../../browser/constants.js";
|
|
6
|
-
import { DEFAULT_UPLOAD_DIR,
|
|
6
|
+
import { DEFAULT_UPLOAD_DIR, resolveExistingPathsWithinRoot } from "../../browser/paths.js";
|
|
7
7
|
import { applyBrowserProxyPaths, persistBrowserProxyFiles } from "../../browser/proxy-files.js";
|
|
8
8
|
import { loadConfig } from "../../config/config.js";
|
|
9
9
|
import { wrapExternalContent } from "../../security/external-content.js";
|
|
@@ -587,7 +587,7 @@ export function createBrowserTool(opts) {
|
|
|
587
587
|
if (paths.length === 0) {
|
|
588
588
|
throw new Error("paths required");
|
|
589
589
|
}
|
|
590
|
-
const uploadPathsResult =
|
|
590
|
+
const uploadPathsResult = await resolveExistingPathsWithinRoot({
|
|
591
591
|
rootDir: DEFAULT_UPLOAD_DIR,
|
|
592
592
|
requestedPaths: paths,
|
|
593
593
|
scopeLabel: `uploads directory (${DEFAULT_UPLOAD_DIR})`,
|
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
import crypto from "node:crypto";
|
|
2
2
|
import fs from "node:fs/promises";
|
|
3
|
+
import path from "node:path";
|
|
3
4
|
import { Type } from "@sinclair/typebox";
|
|
4
5
|
import { writeBase64ToFile } from "../../cli/nodes-camera.js";
|
|
5
6
|
import { canvasSnapshotTempPath, parseCanvasSnapshotPayload } from "../../cli/nodes-canvas.js";
|
|
7
|
+
import { logVerbose, shouldLogVerbose } from "../../globals.js";
|
|
8
|
+
import { isInboundPathAllowed } from "../../media/inbound-path-policy.js";
|
|
9
|
+
import { getDefaultMediaLocalRoots } from "../../media/local-roots.js";
|
|
6
10
|
import { imageMimeFromFormat } from "../../media/mime.js";
|
|
7
11
|
import { resolveImageSanitizationLimits } from "../image-sanitization.js";
|
|
8
12
|
import { optionalStringEnum, stringEnum } from "../schema/typebox.js";
|
|
@@ -19,6 +23,28 @@ const CANVAS_ACTIONS = [
|
|
|
19
23
|
"a2ui_reset",
|
|
20
24
|
];
|
|
21
25
|
const CANVAS_SNAPSHOT_FORMATS = ["png", "jpg", "jpeg"];
|
|
26
|
+
async function readJsonlFromPath(jsonlPath) {
|
|
27
|
+
const trimmed = jsonlPath.trim();
|
|
28
|
+
if (!trimmed) {
|
|
29
|
+
return "";
|
|
30
|
+
}
|
|
31
|
+
const resolved = path.resolve(trimmed);
|
|
32
|
+
const roots = getDefaultMediaLocalRoots();
|
|
33
|
+
if (!isInboundPathAllowed({ filePath: resolved, roots })) {
|
|
34
|
+
if (shouldLogVerbose()) {
|
|
35
|
+
logVerbose(`Blocked canvas jsonlPath outside allowed roots: ${resolved}`);
|
|
36
|
+
}
|
|
37
|
+
throw new Error("jsonlPath outside allowed roots");
|
|
38
|
+
}
|
|
39
|
+
const canonical = await fs.realpath(resolved).catch(() => resolved);
|
|
40
|
+
if (!isInboundPathAllowed({ filePath: canonical, roots })) {
|
|
41
|
+
if (shouldLogVerbose()) {
|
|
42
|
+
logVerbose(`Blocked canvas jsonlPath outside allowed roots: ${canonical}`);
|
|
43
|
+
}
|
|
44
|
+
throw new Error("jsonlPath outside allowed roots");
|
|
45
|
+
}
|
|
46
|
+
return await fs.readFile(canonical, "utf8");
|
|
47
|
+
}
|
|
22
48
|
// Flattened schema: runtime validates per-action requirements.
|
|
23
49
|
const CanvasToolSchema = Type.Object({
|
|
24
50
|
action: stringEnum(CANVAS_ACTIONS),
|
|
@@ -145,7 +171,7 @@ export function createCanvasTool(options) {
|
|
|
145
171
|
const jsonl = typeof params.jsonl === "string" && params.jsonl.trim()
|
|
146
172
|
? params.jsonl
|
|
147
173
|
: typeof params.jsonlPath === "string" && params.jsonlPath.trim()
|
|
148
|
-
? await
|
|
174
|
+
? await readJsonlFromPath(params.jsonlPath)
|
|
149
175
|
: "";
|
|
150
176
|
if (!jsonl.trim()) {
|
|
151
177
|
throw new Error("jsonl or jsonlPath required");
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import fs from "node:fs/promises";
|
|
2
2
|
import { detectMime } from "../../media/mime.js";
|
|
3
3
|
import { sanitizeToolResultImages } from "../tool-images.js";
|
|
4
|
+
export const OWNER_ONLY_TOOL_ERROR = "Tool restricted to owner senders.";
|
|
4
5
|
export class ToolInputError extends Error {
|
|
5
6
|
status = 400;
|
|
6
7
|
constructor(message) {
|
|
@@ -8,6 +9,13 @@ export class ToolInputError extends Error {
|
|
|
8
9
|
this.name = "ToolInputError";
|
|
9
10
|
}
|
|
10
11
|
}
|
|
12
|
+
export class ToolAuthorizationError extends ToolInputError {
|
|
13
|
+
status = 403;
|
|
14
|
+
constructor(message) {
|
|
15
|
+
super(message);
|
|
16
|
+
this.name = "ToolAuthorizationError";
|
|
17
|
+
}
|
|
18
|
+
}
|
|
11
19
|
export function createActionGate(actions) {
|
|
12
20
|
return (key, defaultValue = true) => {
|
|
13
21
|
const value = actions?.[key];
|
|
@@ -131,6 +139,17 @@ export function jsonResult(payload) {
|
|
|
131
139
|
details: payload,
|
|
132
140
|
};
|
|
133
141
|
}
|
|
142
|
+
export function wrapOwnerOnlyToolExecution(tool, senderIsOwner) {
|
|
143
|
+
if (tool.ownerOnly !== true || senderIsOwner || !tool.execute) {
|
|
144
|
+
return tool;
|
|
145
|
+
}
|
|
146
|
+
return {
|
|
147
|
+
...tool,
|
|
148
|
+
execute: async () => {
|
|
149
|
+
throw new Error(OWNER_ONLY_TOOL_ERROR);
|
|
150
|
+
},
|
|
151
|
+
};
|
|
152
|
+
}
|
|
134
153
|
export async function imageResult(params) {
|
|
135
154
|
const content = [
|
|
136
155
|
{
|
|
@@ -162,3 +181,29 @@ export async function imageResultFromFile(params) {
|
|
|
162
181
|
imageSanitization: params.imageSanitization,
|
|
163
182
|
});
|
|
164
183
|
}
|
|
184
|
+
/**
|
|
185
|
+
* Validate and parse an `availableTags` parameter from untrusted input.
|
|
186
|
+
* Returns `undefined` when the value is missing or not an array.
|
|
187
|
+
* Entries that lack a string `name` are silently dropped.
|
|
188
|
+
*/
|
|
189
|
+
export function parseAvailableTags(raw) {
|
|
190
|
+
if (raw === undefined || raw === null) {
|
|
191
|
+
return undefined;
|
|
192
|
+
}
|
|
193
|
+
if (!Array.isArray(raw)) {
|
|
194
|
+
return undefined;
|
|
195
|
+
}
|
|
196
|
+
const result = raw
|
|
197
|
+
.filter((t) => typeof t === "object" && t !== null && typeof t.name === "string")
|
|
198
|
+
.map((t) => ({
|
|
199
|
+
...(t.id !== undefined && typeof t.id === "string" ? { id: t.id } : {}),
|
|
200
|
+
name: t.name,
|
|
201
|
+
...(typeof t.moderated === "boolean" ? { moderated: t.moderated } : {}),
|
|
202
|
+
...(t.emoji_id === null || typeof t.emoji_id === "string" ? { emoji_id: t.emoji_id } : {}),
|
|
203
|
+
...(t.emoji_name === null || typeof t.emoji_name === "string"
|
|
204
|
+
? { emoji_name: t.emoji_name }
|
|
205
|
+
: {}),
|
|
206
|
+
}));
|
|
207
|
+
// Return undefined instead of empty array to avoid accidentally clearing all tags
|
|
208
|
+
return result.length ? result : undefined;
|
|
209
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { getPresence } from "../../discord/monitor/presence-cache.js";
|
|
2
2
|
import { addRoleDiscord, createChannelDiscord, createScheduledEventDiscord, deleteChannelDiscord, editChannelDiscord, fetchChannelInfoDiscord, fetchMemberInfoDiscord, fetchRoleInfoDiscord, fetchVoiceStatusDiscord, listGuildChannelsDiscord, listGuildEmojisDiscord, listScheduledEventsDiscord, moveChannelDiscord, removeChannelPermissionDiscord, removeRoleDiscord, setChannelPermissionDiscord, uploadEmojiDiscord, uploadStickerDiscord, } from "../../discord/send.js";
|
|
3
|
-
import { jsonResult, readNumberParam, readStringArrayParam, readStringParam, } from "./common.js";
|
|
3
|
+
import { jsonResult, readNumberParam, parseAvailableTags, readStringArrayParam, readStringParam, } from "./common.js";
|
|
4
4
|
function readParentIdParam(params) {
|
|
5
5
|
if (params.clearParent === true)
|
|
6
6
|
return null;
|
|
@@ -280,6 +280,7 @@ export async function handleDiscordGuildAction(action, params, isActionEnabled)
|
|
|
280
280
|
const rateLimitPerUser = readNumberParam(params, "rateLimitPerUser", {
|
|
281
281
|
integer: true,
|
|
282
282
|
});
|
|
283
|
+
const availableTags = parseAvailableTags(params.availableTags);
|
|
283
284
|
const channel = accountId
|
|
284
285
|
? await editChannelDiscord({
|
|
285
286
|
channelId,
|
|
@@ -289,6 +290,7 @@ export async function handleDiscordGuildAction(action, params, isActionEnabled)
|
|
|
289
290
|
parentId,
|
|
290
291
|
nsfw,
|
|
291
292
|
rateLimitPerUser: rateLimitPerUser ?? undefined,
|
|
293
|
+
availableTags,
|
|
292
294
|
}, { accountId })
|
|
293
295
|
: await editChannelDiscord({
|
|
294
296
|
channelId,
|
|
@@ -298,6 +300,7 @@ export async function handleDiscordGuildAction(action, params, isActionEnabled)
|
|
|
298
300
|
parentId,
|
|
299
301
|
nsfw,
|
|
300
302
|
rateLimitPerUser: rateLimitPerUser ?? undefined,
|
|
303
|
+
availableTags,
|
|
301
304
|
});
|
|
302
305
|
return jsonResult({ ok: true, channel });
|
|
303
306
|
}
|
|
@@ -6,6 +6,8 @@ import { formatDoctorNonInteractiveHint, writeRestartSentinel, } from "../../inf
|
|
|
6
6
|
import { stringEnum } from "../schema/typebox.js";
|
|
7
7
|
import { jsonResult, readStringParam } from "./common.js";
|
|
8
8
|
import { callGatewayTool } from "./gateway.js";
|
|
9
|
+
import { createSubsystemLogger } from "../../logging/subsystem.js";
|
|
10
|
+
const log = createSubsystemLogger("gateway-tool");
|
|
9
11
|
function resolveBaseHashFromSnapshot(snapshot) {
|
|
10
12
|
if (!snapshot || typeof snapshot !== "object")
|
|
11
13
|
return undefined;
|
|
@@ -121,7 +123,7 @@ export function createGatewayTool(opts) {
|
|
|
121
123
|
catch {
|
|
122
124
|
// ignore: sentinel is best-effort
|
|
123
125
|
}
|
|
124
|
-
|
|
126
|
+
log.info(`gateway tool: restart requested (delayMs=${delayMs ?? "default"}, reason=${reason ?? "none"})`);
|
|
125
127
|
const scheduled = scheduleGatewaySigusr1Restart({
|
|
126
128
|
delayMs,
|
|
127
129
|
reason,
|
|
@@ -1,15 +1,6 @@
|
|
|
1
|
+
import { parseNodeList, parsePairingList } from "../../shared/node-list-parse.js";
|
|
1
2
|
import { resolveNodeIdFromCandidates } from "../../shared/node-match.js";
|
|
2
3
|
import { callGatewayTool } from "./gateway.js";
|
|
3
|
-
function parseNodeList(value) {
|
|
4
|
-
const obj = typeof value === "object" && value !== null ? value : {};
|
|
5
|
-
return Array.isArray(obj.nodes) ? obj.nodes : [];
|
|
6
|
-
}
|
|
7
|
-
function parsePairingList(value) {
|
|
8
|
-
const obj = typeof value === "object" && value !== null ? value : {};
|
|
9
|
-
const pending = Array.isArray(obj.pending) ? obj.pending : [];
|
|
10
|
-
const paired = Array.isArray(obj.paired) ? obj.paired : [];
|
|
11
|
-
return { pending, paired };
|
|
12
|
-
}
|
|
13
4
|
async function loadNodes(opts) {
|
|
14
5
|
try {
|
|
15
6
|
const res = await callGatewayTool("node.list", opts, {});
|
|
@@ -7,11 +7,13 @@ const MAX_PING_PONG_TURNS = 5;
|
|
|
7
7
|
export function resolveAnnounceTargetFromKey(sessionKey) {
|
|
8
8
|
const rawParts = sessionKey.split(":").filter(Boolean);
|
|
9
9
|
const parts = rawParts.length >= 3 && rawParts[0] === "agent" ? rawParts.slice(2) : rawParts;
|
|
10
|
-
if (parts.length < 3)
|
|
10
|
+
if (parts.length < 3) {
|
|
11
11
|
return null;
|
|
12
|
+
}
|
|
12
13
|
const [channelRaw, kind, ...rest] = parts;
|
|
13
|
-
if (kind !== "group" && kind !== "channel")
|
|
14
|
+
if (kind !== "group" && kind !== "channel") {
|
|
14
15
|
return null;
|
|
16
|
+
}
|
|
15
17
|
// Extract topic/thread ID from rest (supports both :topic: and :thread:)
|
|
16
18
|
// Telegram uses :topic:, other platforms use :thread:
|
|
17
19
|
let threadId;
|
|
@@ -24,15 +26,18 @@ export function resolveAnnounceTargetFromKey(sessionKey) {
|
|
|
24
26
|
}
|
|
25
27
|
// Remove :topic:N or :thread:N suffix from ID for target
|
|
26
28
|
const id = match ? restJoined.replace(/:(topic|thread):\d+$/, "") : restJoined.trim();
|
|
27
|
-
if (!id)
|
|
29
|
+
if (!id) {
|
|
28
30
|
return null;
|
|
29
|
-
|
|
31
|
+
}
|
|
32
|
+
if (!channelRaw) {
|
|
30
33
|
return null;
|
|
34
|
+
}
|
|
31
35
|
const normalizedChannel = normalizeAnyChannelId(channelRaw) ?? normalizeChatChannelId(channelRaw);
|
|
32
36
|
const channel = normalizedChannel ?? channelRaw.toLowerCase();
|
|
33
37
|
const kindTarget = (() => {
|
|
34
|
-
if (!normalizedChannel)
|
|
38
|
+
if (!normalizedChannel) {
|
|
35
39
|
return id;
|
|
40
|
+
}
|
|
36
41
|
if (normalizedChannel === "discord" || normalizedChannel === "slack") {
|
|
37
42
|
return `channel:${id}`;
|
|
38
43
|
}
|
|
@@ -109,8 +114,9 @@ export function isReplySkip(text) {
|
|
|
109
114
|
export function resolvePingPongTurns(cfg) {
|
|
110
115
|
const raw = cfg?.session?.agentToAgent?.maxPingPongTurns;
|
|
111
116
|
const fallback = DEFAULT_PING_PONG_TURNS;
|
|
112
|
-
if (typeof raw !== "number" || !Number.isFinite(raw))
|
|
117
|
+
if (typeof raw !== "number" || !Number.isFinite(raw)) {
|
|
113
118
|
return fallback;
|
|
119
|
+
}
|
|
114
120
|
const rounded = Math.floor(raw);
|
|
115
121
|
return Math.max(0, Math.min(MAX_PING_PONG_TURNS, rounded));
|
|
116
122
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Type } from "@sinclair/typebox";
|
|
2
2
|
import { optionalStringEnum } from "../schema/typebox.js";
|
|
3
|
-
import { spawnSubagentDirect } from "../subagent-spawn.js";
|
|
3
|
+
import { SUBAGENT_SPAWN_MODES, spawnSubagentDirect } from "../subagent-spawn.js";
|
|
4
4
|
import { jsonResult, readStringParam } from "./common.js";
|
|
5
5
|
const SessionsSpawnToolSchema = Type.Object({
|
|
6
6
|
task: Type.String(),
|
|
@@ -11,13 +11,15 @@ const SessionsSpawnToolSchema = Type.Object({
|
|
|
11
11
|
runTimeoutSeconds: Type.Optional(Type.Number({ minimum: 0 })),
|
|
12
12
|
// Back-compat: older callers used timeoutSeconds for this tool.
|
|
13
13
|
timeoutSeconds: Type.Optional(Type.Number({ minimum: 0 })),
|
|
14
|
+
thread: Type.Optional(Type.Boolean()),
|
|
15
|
+
mode: optionalStringEnum(SUBAGENT_SPAWN_MODES),
|
|
14
16
|
cleanup: optionalStringEnum(["delete", "keep"]),
|
|
15
17
|
});
|
|
16
18
|
export function createSessionsSpawnTool(opts) {
|
|
17
19
|
return {
|
|
18
20
|
label: "Sessions",
|
|
19
21
|
name: "sessions_spawn",
|
|
20
|
-
description:
|
|
22
|
+
description: 'Spawn a sub-agent in an isolated session (mode="run" one-shot or mode="session" persistent) and route results back to the requester chat/thread.',
|
|
21
23
|
parameters: SessionsSpawnToolSchema,
|
|
22
24
|
execute: async (_toolCallId, args) => {
|
|
23
25
|
const params = args;
|
|
@@ -26,6 +28,7 @@ export function createSessionsSpawnTool(opts) {
|
|
|
26
28
|
const requestedAgentId = readStringParam(params, "agentId");
|
|
27
29
|
const modelOverride = readStringParam(params, "model");
|
|
28
30
|
const thinkingOverrideRaw = readStringParam(params, "thinking");
|
|
31
|
+
const mode = params.mode === "run" || params.mode === "session" ? params.mode : undefined;
|
|
29
32
|
const cleanup = params.cleanup === "keep" || params.cleanup === "delete" ? params.cleanup : "keep";
|
|
30
33
|
// Back-compat: older callers used timeoutSeconds for this tool.
|
|
31
34
|
const timeoutSecondsCandidate = typeof params.runTimeoutSeconds === "number"
|
|
@@ -36,6 +39,7 @@ export function createSessionsSpawnTool(opts) {
|
|
|
36
39
|
const runTimeoutSeconds = typeof timeoutSecondsCandidate === "number" && Number.isFinite(timeoutSecondsCandidate)
|
|
37
40
|
? Math.max(0, Math.floor(timeoutSecondsCandidate))
|
|
38
41
|
: undefined;
|
|
42
|
+
const thread = params.thread === true;
|
|
39
43
|
const result = await spawnSubagentDirect({
|
|
40
44
|
task,
|
|
41
45
|
label: label || undefined,
|
|
@@ -43,6 +47,8 @@ export function createSessionsSpawnTool(opts) {
|
|
|
43
47
|
model: modelOverride,
|
|
44
48
|
thinking: thinkingOverrideRaw,
|
|
45
49
|
runTimeoutSeconds,
|
|
50
|
+
thread,
|
|
51
|
+
mode,
|
|
46
52
|
cleanup,
|
|
47
53
|
expectsCompletionMessage: true,
|
|
48
54
|
}, {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import crypto from "node:crypto";
|
|
2
2
|
import { Type } from "@sinclair/typebox";
|
|
3
3
|
import { clearSessionQueues } from "../../auto-reply/reply/queue.js";
|
|
4
|
+
import { DEFAULT_SUBAGENT_MAX_SPAWN_DEPTH } from "../../config/agent-limits.js";
|
|
4
5
|
import { loadConfig } from "../../config/config.js";
|
|
5
6
|
import { loadSessionStore, resolveStorePath, updateSessionStore } from "../../config/sessions.js";
|
|
6
7
|
import { callGateway } from "../../gateway/call.js";
|
|
@@ -181,7 +182,7 @@ function resolveRequesterKey(params) {
|
|
|
181
182
|
// Check if this sub-agent can spawn children (orchestrator).
|
|
182
183
|
// If so, it should see its own children, not its parent's children.
|
|
183
184
|
const callerDepth = getSubagentDepthFromSessionStore(callerSessionKey, { cfg: params.cfg });
|
|
184
|
-
const maxSpawnDepth = params.cfg.agents?.defaults?.subagents?.maxSpawnDepth ??
|
|
185
|
+
const maxSpawnDepth = params.cfg.agents?.defaults?.subagents?.maxSpawnDepth ?? DEFAULT_SUBAGENT_MAX_SPAWN_DEPTH;
|
|
185
186
|
if (callerDepth < maxSpawnDepth) {
|
|
186
187
|
// Orchestrator sub-agent: use its own session key as requester
|
|
187
188
|
// so it sees children it spawned.
|