@poolzin/pool-bot 2026.2.24 → 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/CHANGELOG.md +21 -0
- package/dist/acp/client.js +207 -18
- package/dist/acp/event-mapper.js +87 -22
- package/dist/acp/meta.js +12 -6
- package/dist/acp/secret-file.js +22 -0
- package/dist/agents/agent-paths.js +8 -9
- package/dist/agents/agent-scope.js +17 -5
- package/dist/agents/auth-profiles/oauth.js +148 -64
- package/dist/agents/auth-profiles/session-override.js +13 -7
- package/dist/agents/bash-process-registry.test-helpers.js +29 -0
- package/dist/agents/bash-tools.exec-approval-request.js +20 -0
- package/dist/agents/bash-tools.exec-host-gateway.js +240 -0
- package/dist/agents/bash-tools.exec-host-node.js +235 -0
- package/dist/agents/bash-tools.exec-runtime.js +2 -25
- package/dist/agents/bash-tools.exec-types.js +1 -0
- package/dist/agents/bash-tools.process.js +224 -218
- 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/content-blocks.js +16 -0
- 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-fallback.js +96 -101
- package/dist/agents/model-selection.js +7 -1
- package/dist/agents/models-config.providers.js +364 -165
- 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-payloads.js +1 -0
- 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.fixture.js +34 -0
- 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/skills.test-helpers.js +13 -0
- package/dist/agents/stable-stringify.js +12 -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.mocks.shared.js +12 -0
- 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/assistant-message-fixtures.js +29 -0
- 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/test-helpers/pi-tools-sandbox-context.js +27 -0
- 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-shared.js +108 -0
- package/dist/agents/tool-policy.js +51 -26
- package/dist/agents/tools/browser-tool.js +160 -54
- package/dist/agents/tools/canvas-tool.js +27 -1
- package/dist/agents/tools/common.js +45 -0
- package/dist/agents/tools/cron-tool.test-helpers.js +12 -0
- package/dist/agents/tools/discord-actions-guild.js +4 -1
- package/dist/agents/tools/discord-actions-moderation-shared.js +27 -0
- package/dist/agents/tools/gateway-tool.js +3 -1
- package/dist/agents/tools/image-tool.js +214 -99
- package/dist/agents/tools/nodes-utils.js +1 -10
- package/dist/agents/tools/sessions-history-tool.js +140 -108
- 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/agents/workspace.js +222 -46
- package/dist/auto-reply/commands-registry.data.js +51 -0
- package/dist/auto-reply/commands-registry.js +19 -21
- package/dist/auto-reply/fallback-state.js +114 -0
- package/dist/auto-reply/group-activation.js +10 -5
- package/dist/auto-reply/inbound-debounce.js +10 -5
- package/dist/auto-reply/model-runtime.js +68 -0
- package/dist/auto-reply/reply/abort.js +1 -1
- package/dist/auto-reply/reply/agent-runner-execution.js +40 -5
- package/dist/auto-reply/reply/agent-runner.js +165 -39
- 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-standard.js +13 -0
- 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 +30 -0
- package/dist/browser/extension-relay-auth.js +55 -0
- package/dist/browser/extension-relay.js +74 -29
- package/dist/browser/navigation-guard.js +39 -0
- 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 +431 -424
- package/dist/browser/routes/agent.shared.js +47 -3
- package/dist/browser/routes/agent.snapshot.js +122 -116
- package/dist/browser/routes/agent.storage.js +303 -297
- package/dist/browser/routes/tabs.js +154 -100
- package/dist/browser/server-context.js +7 -0
- package/dist/browser/server-lifecycle.js +37 -0
- package/dist/build-info.json +3 -3
- package/dist/channels/allow-from.js +26 -0
- 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/account-action-gate.js +13 -0
- package/dist/channels/plugins/message-actions.js +10 -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/channels/telegram/api.js +18 -0
- package/dist/cli/argv.js +84 -21
- package/dist/cli/banner.js +3 -2
- 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/exec-approvals-cli.js +92 -124
- package/dist/cli/gateway-cli/run-loop.js +23 -5
- package/dist/cli/memory-cli.js +158 -61
- package/dist/cli/node-cli/register.js +14 -5
- package/dist/cli/nodes-cli/register.push.js +63 -0
- package/dist/cli/nodes-media-utils.js +26 -0
- 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 +250 -73
- package/dist/cli/ports.js +11 -10
- package/dist/cli/program/build-program.js +3 -1
- package/dist/cli/program/command-registry.js +214 -136
- package/dist/cli/program/command-tree.js +16 -0
- package/dist/cli/program/help.js +43 -12
- 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 +12 -8
- package/dist/cli/system-cli.js +36 -46
- package/dist/cli/test-runtime-capture.js +24 -0
- 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 +185 -89
- 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/channels.mock-harness.js +23 -0
- 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/daemon-install-runtime-warning.js +11 -0
- 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/sessions.test-helpers.js +61 -0
- 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 +32 -15
- package/dist/config/config-paths.js +9 -11
- package/dist/config/config.js +1 -1
- package/dist/config/defaults.js +22 -2
- package/dist/config/discord-preview-streaming.js +104 -0
- package/dist/config/env-substitution.js +62 -34
- package/dist/config/env-vars.js +45 -7
- package/dist/config/includes.js +4 -0
- package/dist/config/io.js +656 -171
- package/dist/config/legacy.migrations.part-1.js +189 -78
- package/dist/config/legacy.shared.js +3 -1
- package/dist/config/merge-patch.js +54 -4
- package/dist/config/prototype-keys.js +4 -0
- package/dist/config/redact-snapshot.js +404 -76
- package/dist/config/schema.help.js +44 -7
- package/dist/config/schema.js +58 -570
- 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/validation.js +140 -85
- package/dist/config/zod-schema.agent-runtime.js +11 -0
- package/dist/config/zod-schema.hooks.js +40 -11
- package/dist/config/zod-schema.installs.js +20 -0
- package/dist/config/zod-schema.js +156 -20
- 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/daemon/cmd-argv.js +21 -0
- package/dist/daemon/cmd-set.js +58 -0
- package/dist/daemon/service-types.js +1 -0
- 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/exec-approvals.js +357 -162
- 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 +72 -13
- package/dist/gateway/call.js +152 -83
- package/dist/gateway/canvas-capability.js +75 -0
- package/dist/gateway/client.js +28 -4
- package/dist/gateway/config-reload.js +3 -4
- package/dist/gateway/control-plane-audit.js +28 -0
- package/dist/gateway/control-plane-rate-limit.js +53 -0
- package/dist/gateway/control-ui.js +219 -96
- package/dist/gateway/events.js +1 -0
- package/dist/gateway/hooks-mapping.js +88 -38
- package/dist/gateway/hooks.js +109 -54
- package/dist/gateway/http-auth-helpers.js +3 -2
- package/dist/gateway/http-common.js +22 -0
- package/dist/gateway/http-endpoint-helpers.js +1 -0
- package/dist/gateway/method-scopes.js +169 -0
- package/dist/gateway/net.js +74 -9
- 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 +121 -110
- package/dist/gateway/origin-check.js +1 -18
- package/dist/gateway/probe-auth.js +2 -0
- package/dist/gateway/protocol/index.js +4 -2
- 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 +4 -1
- package/dist/gateway/protocol/schema/push.js +18 -0
- package/dist/gateway/protocol/schema/sessions.js +6 -0
- package/dist/gateway/protocol/schema.js +1 -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 +247 -54
- package/dist/gateway/server-maintenance.js +20 -5
- package/dist/gateway/server-methods/agent.js +162 -24
- package/dist/gateway/server-methods/chat.js +465 -130
- package/dist/gateway/server-methods/config.js +193 -152
- package/dist/gateway/server-methods/devices.js +17 -3
- package/dist/gateway/server-methods/models.js +11 -1
- package/dist/gateway/server-methods/nodes.helpers.js +12 -0
- package/dist/gateway/server-methods/nodes.js +251 -69
- package/dist/gateway/server-methods/push.js +53 -0
- 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-reload-handlers.js +2 -3
- package/dist/gateway/server-runtime-config.js +39 -13
- package/dist/gateway/server-runtime-state.js +2 -0
- package/dist/gateway/server-startup-memory.js +17 -11
- package/dist/gateway/server-ws-runtime.js +1 -0
- package/dist/gateway/server.impl.js +296 -139
- package/dist/gateway/session-preview.test-helpers.js +11 -0
- package/dist/gateway/session-utils.fs.js +32 -34
- package/dist/gateway/sessions-resolve.js +17 -5
- package/dist/gateway/startup-auth.js +126 -0
- package/dist/gateway/test-helpers.agent-results.js +15 -0
- package/dist/gateway/test-helpers.mocks.js +37 -14
- package/dist/gateway/test-helpers.openai-mock.js +14 -7
- package/dist/gateway/test-helpers.server.js +161 -77
- 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 +170 -38
- package/dist/hooks/frontmatter.js +6 -6
- package/dist/hooks/gmail-watcher-lifecycle.js +23 -0
- 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-path.js +49 -0
- package/dist/infra/archive.js +174 -73
- package/dist/infra/control-ui-assets.js +14 -6
- package/dist/infra/device-pairing.js +204 -144
- package/dist/infra/env.js +10 -5
- package/dist/infra/exec-approvals-allowlist.js +141 -70
- package/dist/infra/exec-approvals-analysis.js +78 -20
- package/dist/infra/exec-approvals.js +5 -17
- package/dist/infra/exec-safe-bin-policy.js +277 -0
- package/dist/infra/fixed-window-rate-limit.js +33 -0
- package/dist/infra/fs-safe.js +71 -39
- package/dist/infra/gateway-lock.js +6 -2
- package/dist/infra/git-root.js +61 -0
- package/dist/infra/heartbeat-active-hours.js +2 -2
- package/dist/infra/heartbeat-reason.js +40 -0
- package/dist/infra/heartbeat-runner.js +72 -32
- 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/install-source-utils.js +91 -7
- package/dist/infra/net/ssrf.js +131 -38
- package/dist/infra/node-pairing.js +50 -105
- package/dist/infra/npm-integrity.js +45 -0
- package/dist/infra/npm-pack-install.js +40 -0
- package/dist/infra/outbound/bound-delivery-router.js +88 -0
- package/dist/infra/outbound/channel-adapters.js +20 -7
- 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/message-action-runner.js +107 -327
- package/dist/infra/outbound/message.js +59 -36
- package/dist/infra/outbound/outbound-policy.js +52 -25
- package/dist/infra/outbound/outbound-send-service.js +58 -71
- package/dist/infra/outbound/payloads.js +14 -7
- package/dist/infra/outbound/session-binding-service.js +123 -0
- package/dist/infra/pairing-files.js +10 -0
- package/dist/infra/path-guards.js +25 -0
- package/dist/infra/plain-object.js +9 -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/push-apns.js +365 -0
- package/dist/infra/restart-sentinel.js +16 -1
- package/dist/infra/restart.js +229 -26
- package/dist/infra/retry-policy.js +4 -2
- package/dist/infra/retry.js +9 -5
- package/dist/infra/scp-host.js +54 -0
- 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/infra/update-startup.js +86 -9
- 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/inbound-path-policy.js +114 -0
- package/dist/media/input-files.js +16 -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/memory/test-manager.js +8 -0
- 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/temp-path.js +47 -0
- package/dist/plugin-sdk/webhook-targets.js +32 -0
- package/dist/plugins/bundled-dir.js +9 -6
- package/dist/plugins/discovery.js +217 -23
- package/dist/plugins/hook-runner-global.js +16 -0
- package/dist/plugins/hooks.js +50 -0
- package/dist/plugins/install.js +28 -16
- package/dist/plugins/loader.js +192 -26
- package/dist/plugins/logger.js +8 -0
- package/dist/plugins/manifest-registry.js +3 -0
- package/dist/plugins/path-safety.js +34 -0
- package/dist/plugins/registry.js +5 -2
- package/dist/plugins/runtime/index.js +271 -206
- 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-models.js +4 -1
- 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 +100 -20
- package/dist/security/audit-extra.async.js +505 -179
- package/dist/security/audit-extra.js +12 -2
- package/dist/security/audit-extra.sync.js +421 -35
- package/dist/security/audit-fs.js +31 -13
- package/dist/security/audit.js +180 -370
- package/dist/security/dm-policy-shared.js +68 -0
- package/dist/security/external-content.js +46 -14
- package/dist/security/fix.js +49 -85
- package/dist/security/scan-paths.js +20 -0
- package/dist/security/secret-equal.js +3 -7
- package/dist/security/windows-acl.js +30 -15
- package/dist/shared/entry-status.js +6 -0
- package/dist/shared/frontmatter.js +5 -5
- package/dist/shared/node-list-parse.js +13 -0
- package/dist/shared/node-match.js +11 -4
- package/dist/shared/operator-scope-compat.js +42 -0
- package/dist/shared/text-chunking.js +29 -0
- 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/blocks.test-helpers.js +31 -0
- package/dist/slack/monitor/auth.js +1 -1
- package/dist/slack/monitor/message-handler/dispatch.js +50 -29
- package/dist/slack/monitor/mrkdwn.js +8 -0
- 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 +477 -210
- package/dist/telegram/bot-native-commands.js +16 -0
- package/dist/telegram/draft-stream.js +44 -8
- 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/reasoning-lane-coordinator.js +128 -0
- 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/prompt-select-styled.js +9 -0
- package/dist/terminal/theme.js +12 -12
- package/dist/test-utils/command-runner.js +6 -0
- package/dist/test-utils/internal-hook-event-payload.js +10 -0
- package/dist/test-utils/model-auth-mock.js +12 -0
- package/dist/test-utils/provider-usage-fetch.js +14 -0
- package/dist/test-utils/temp-home.js +33 -0
- package/dist/tts/tts.js +80 -567
- package/dist/tui/components/chat-log.js +50 -8
- package/dist/tui/theme/theme.js +10 -12
- package/dist/tui/tui-command-handlers.js +36 -27
- package/dist/tui/tui-event-handlers.js +122 -32
- package/dist/tui/tui-local-shell.js +16 -6
- package/dist/tui/tui.js +236 -48
- 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/mask-api-key.js +10 -0
- package/dist/utils/queue-helpers.js +67 -12
- package/dist/utils/run-with-concurrency.js +39 -0
- 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 +126 -15
- package/docs/tools/slash-commands.md +5 -1
- package/extensions/bluebubbles/src/monitor-processing.ts +580 -139
- package/extensions/bluebubbles/src/monitor.ts +208 -1950
- package/extensions/feishu/src/external-keys.ts +19 -0
- package/extensions/lobster/src/windows-spawn.ts +193 -0
- package/extensions/matrix/src/matrix/actions/limits.ts +6 -0
- package/extensions/mattermost/src/mattermost/reactions.test-helpers.ts +83 -0
- package/package.json +1 -1
package/dist/browser/config.js
CHANGED
|
@@ -16,6 +16,30 @@ function normalizeTimeoutMs(raw, fallback) {
|
|
|
16
16
|
const value = typeof raw === "number" && Number.isFinite(raw) ? Math.floor(raw) : fallback;
|
|
17
17
|
return value < 0 ? fallback : value;
|
|
18
18
|
}
|
|
19
|
+
function normalizeStringList(raw) {
|
|
20
|
+
if (!Array.isArray(raw) || raw.length === 0) {
|
|
21
|
+
return undefined;
|
|
22
|
+
}
|
|
23
|
+
const values = raw
|
|
24
|
+
.map((value) => value.trim())
|
|
25
|
+
.filter((value) => value.length > 0);
|
|
26
|
+
return values.length > 0 ? values : undefined;
|
|
27
|
+
}
|
|
28
|
+
function resolveBrowserSsrFPolicy(cfg) {
|
|
29
|
+
const allowPrivateNetwork = cfg?.ssrfPolicy?.allowPrivateNetwork;
|
|
30
|
+
const allowedHostnames = normalizeStringList(cfg?.ssrfPolicy?.allowedHostnames);
|
|
31
|
+
const hostnameAllowlist = normalizeStringList(cfg?.ssrfPolicy?.hostnameAllowlist);
|
|
32
|
+
if (allowPrivateNetwork === undefined &&
|
|
33
|
+
allowedHostnames === undefined &&
|
|
34
|
+
hostnameAllowlist === undefined) {
|
|
35
|
+
return undefined;
|
|
36
|
+
}
|
|
37
|
+
return {
|
|
38
|
+
...(allowPrivateNetwork === true ? { allowPrivateNetwork: true } : {}),
|
|
39
|
+
...(allowedHostnames ? { allowedHostnames } : {}),
|
|
40
|
+
...(hostnameAllowlist ? { hostnameAllowlist } : {}),
|
|
41
|
+
};
|
|
42
|
+
}
|
|
19
43
|
export function parseHttpUrl(raw, label) {
|
|
20
44
|
const trimmed = raw.trim();
|
|
21
45
|
const parsed = new URL(trimmed);
|
|
@@ -113,6 +137,10 @@ export function resolveBrowserConfig(cfg, rootConfig) {
|
|
|
113
137
|
(profiles[DEFAULT_BROWSER_DEFAULT_PROFILE_NAME]
|
|
114
138
|
? DEFAULT_BROWSER_DEFAULT_PROFILE_NAME
|
|
115
139
|
: DEFAULT_CLAWD_BROWSER_PROFILE_NAME);
|
|
140
|
+
const ssrfPolicy = resolveBrowserSsrFPolicy(cfg);
|
|
141
|
+
const extraArgs = Array.isArray(cfg?.extraArgs)
|
|
142
|
+
? cfg.extraArgs.filter((a) => typeof a === "string" && a.trim().length > 0)
|
|
143
|
+
: [];
|
|
116
144
|
return {
|
|
117
145
|
enabled,
|
|
118
146
|
evaluateEnabled,
|
|
@@ -129,6 +157,8 @@ export function resolveBrowserConfig(cfg, rootConfig) {
|
|
|
129
157
|
attachOnly,
|
|
130
158
|
defaultProfile,
|
|
131
159
|
profiles,
|
|
160
|
+
ssrfPolicy,
|
|
161
|
+
extraArgs,
|
|
132
162
|
};
|
|
133
163
|
}
|
|
134
164
|
/**
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { createHmac } from "node:crypto";
|
|
2
|
+
import { loadConfig } from "../config/config.js";
|
|
3
|
+
const RELAY_TOKEN_CONTEXT = "poolbot-extension-relay-v1";
|
|
4
|
+
const DEFAULT_RELAY_PROBE_TIMEOUT_MS = 500;
|
|
5
|
+
const POOLBOT_RELAY_BROWSER = "PoolBot/extension-relay";
|
|
6
|
+
function resolveGatewayAuthToken() {
|
|
7
|
+
const envToken = process.env.POOLBOT_GATEWAY_TOKEN?.trim() ?? process.env.CLAWDBOT_GATEWAY_TOKEN?.trim();
|
|
8
|
+
if (envToken) {
|
|
9
|
+
return envToken;
|
|
10
|
+
}
|
|
11
|
+
try {
|
|
12
|
+
const cfg = loadConfig();
|
|
13
|
+
const configToken = cfg.gateway?.auth?.token?.trim();
|
|
14
|
+
if (configToken) {
|
|
15
|
+
return configToken;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
catch {
|
|
19
|
+
// ignore config read failures; caller can fallback to per-process random token
|
|
20
|
+
}
|
|
21
|
+
return null;
|
|
22
|
+
}
|
|
23
|
+
function deriveRelayAuthToken(gatewayToken, port) {
|
|
24
|
+
return createHmac("sha256", gatewayToken).update(`${RELAY_TOKEN_CONTEXT}:${port}`).digest("hex");
|
|
25
|
+
}
|
|
26
|
+
export function resolveRelayAuthTokenForPort(port) {
|
|
27
|
+
const gatewayToken = resolveGatewayAuthToken();
|
|
28
|
+
if (gatewayToken) {
|
|
29
|
+
return deriveRelayAuthToken(gatewayToken, port);
|
|
30
|
+
}
|
|
31
|
+
throw new Error("extension relay requires gateway auth token (set gateway.auth.token or POOLBOT_GATEWAY_TOKEN)");
|
|
32
|
+
}
|
|
33
|
+
export async function probeAuthenticatedPoolBotRelay(params) {
|
|
34
|
+
const ctrl = new AbortController();
|
|
35
|
+
const timer = setTimeout(() => ctrl.abort(), params.timeoutMs ?? DEFAULT_RELAY_PROBE_TIMEOUT_MS);
|
|
36
|
+
try {
|
|
37
|
+
const versionUrl = new URL("/json/version", `${params.baseUrl}/`).toString();
|
|
38
|
+
const res = await fetch(versionUrl, {
|
|
39
|
+
signal: ctrl.signal,
|
|
40
|
+
headers: { [params.relayAuthHeader]: params.relayAuthToken },
|
|
41
|
+
});
|
|
42
|
+
if (!res.ok) {
|
|
43
|
+
return false;
|
|
44
|
+
}
|
|
45
|
+
const body = (await res.json());
|
|
46
|
+
const browserName = typeof body?.Browser === "string" ? body.Browser.trim() : "";
|
|
47
|
+
return browserName === POOLBOT_RELAY_BROWSER;
|
|
48
|
+
}
|
|
49
|
+
catch {
|
|
50
|
+
return false;
|
|
51
|
+
}
|
|
52
|
+
finally {
|
|
53
|
+
clearTimeout(timer);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { randomBytes } from "node:crypto";
|
|
2
1
|
import { createServer } from "node:http";
|
|
3
2
|
import WebSocket, { WebSocketServer } from "ws";
|
|
4
3
|
import { isLoopbackAddress, isLoopbackHost } from "../gateway/net.js";
|
|
5
4
|
import { rawDataToString } from "../infra/ws.js";
|
|
5
|
+
import { probeAuthenticatedPoolBotRelay, resolveRelayAuthTokenForPort, } from "./extension-relay-auth.js";
|
|
6
6
|
const RELAY_AUTH_HEADER = "x-poolbot-relay-token";
|
|
7
7
|
function headerValue(value) {
|
|
8
8
|
if (!value) {
|
|
@@ -16,14 +16,32 @@ function headerValue(value) {
|
|
|
16
16
|
function getHeader(req, name) {
|
|
17
17
|
return headerValue(req.headers[name.toLowerCase()]);
|
|
18
18
|
}
|
|
19
|
+
function getRelayAuthTokenFromRequest(req, url) {
|
|
20
|
+
const headerToken = getHeader(req, RELAY_AUTH_HEADER)?.trim();
|
|
21
|
+
if (headerToken) {
|
|
22
|
+
return headerToken;
|
|
23
|
+
}
|
|
24
|
+
const queryToken = url?.searchParams.get("token")?.trim();
|
|
25
|
+
if (queryToken) {
|
|
26
|
+
return queryToken;
|
|
27
|
+
}
|
|
28
|
+
return undefined;
|
|
29
|
+
}
|
|
30
|
+
function parseUrlPort(parsed) {
|
|
31
|
+
const port = parsed.port?.trim() !== "" ? Number(parsed.port) : parsed.protocol === "https:" ? 443 : 80;
|
|
32
|
+
if (!Number.isFinite(port) || port <= 0 || port > 65535) {
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
return port;
|
|
36
|
+
}
|
|
19
37
|
function parseBaseUrl(raw) {
|
|
20
38
|
const parsed = new URL(raw.trim().replace(/\/$/, ""));
|
|
21
39
|
if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
|
|
22
40
|
throw new Error(`extension relay cdpUrl must be http(s), got ${parsed.protocol}`);
|
|
23
41
|
}
|
|
24
42
|
const host = parsed.hostname;
|
|
25
|
-
const port =
|
|
26
|
-
if (!
|
|
43
|
+
const port = parseUrlPort(parsed);
|
|
44
|
+
if (!port) {
|
|
27
45
|
throw new Error(`extension relay cdpUrl has invalid port: ${parsed.port || "(empty)"}`);
|
|
28
46
|
}
|
|
29
47
|
return { host, port, baseUrl: parsed.toString().replace(/\/$/, "") };
|
|
@@ -47,23 +65,24 @@ function rejectUpgrade(socket, status, bodyText) {
|
|
|
47
65
|
// ignore
|
|
48
66
|
}
|
|
49
67
|
}
|
|
50
|
-
const
|
|
51
|
-
|
|
68
|
+
const relayRuntimeByPort = new Map();
|
|
69
|
+
function isAddrInUseError(err) {
|
|
70
|
+
return (typeof err === "object" &&
|
|
71
|
+
err !== null &&
|
|
72
|
+
"code" in err &&
|
|
73
|
+
err.code === "EADDRINUSE");
|
|
74
|
+
}
|
|
52
75
|
function relayAuthTokenForUrl(url) {
|
|
53
76
|
try {
|
|
54
77
|
const parsed = new URL(url);
|
|
55
78
|
if (!isLoopbackHost(parsed.hostname)) {
|
|
56
79
|
return null;
|
|
57
80
|
}
|
|
58
|
-
const port = parsed
|
|
59
|
-
|
|
60
|
-
: parsed.protocol === "https:" || parsed.protocol === "wss:"
|
|
61
|
-
? 443
|
|
62
|
-
: 80;
|
|
63
|
-
if (!Number.isFinite(port)) {
|
|
81
|
+
const port = parseUrlPort(parsed);
|
|
82
|
+
if (!port) {
|
|
64
83
|
return null;
|
|
65
84
|
}
|
|
66
|
-
return
|
|
85
|
+
return relayRuntimeByPort.get(port)?.relayAuthToken ?? null;
|
|
67
86
|
}
|
|
68
87
|
catch {
|
|
69
88
|
return null;
|
|
@@ -81,10 +100,11 @@ export async function ensureChromeExtensionRelayServer(opts) {
|
|
|
81
100
|
if (!isLoopbackHost(info.host)) {
|
|
82
101
|
throw new Error(`extension relay requires loopback cdpUrl host (got ${info.host})`);
|
|
83
102
|
}
|
|
84
|
-
const existing =
|
|
103
|
+
const existing = relayRuntimeByPort.get(info.port);
|
|
85
104
|
if (existing) {
|
|
86
|
-
return existing;
|
|
105
|
+
return existing.server;
|
|
87
106
|
}
|
|
107
|
+
const relayAuthToken = resolveRelayAuthTokenForPort(info.port);
|
|
88
108
|
let extensionWs = null;
|
|
89
109
|
const cdpClients = new Set();
|
|
90
110
|
const connectedTargets = new Map();
|
|
@@ -144,9 +164,9 @@ export async function ensureChromeExtensionRelayServer(opts) {
|
|
|
144
164
|
case "Browser.getVersion":
|
|
145
165
|
return {
|
|
146
166
|
protocolVersion: "1.3",
|
|
147
|
-
product: "Chrome/
|
|
167
|
+
product: "Chrome/Pool Bot-Extension-Relay",
|
|
148
168
|
revision: "0",
|
|
149
|
-
userAgent: "
|
|
169
|
+
userAgent: "Pool Bot-Extension-Relay",
|
|
150
170
|
jsVersion: "V8",
|
|
151
171
|
};
|
|
152
172
|
case "Browser.setDownloadBehavior":
|
|
@@ -207,7 +227,6 @@ export async function ensureChromeExtensionRelayServer(opts) {
|
|
|
207
227
|
}
|
|
208
228
|
}
|
|
209
229
|
};
|
|
210
|
-
const relayAuthToken = randomBytes(32).toString("base64url");
|
|
211
230
|
const server = createServer((req, res) => {
|
|
212
231
|
const url = new URL(req.url ?? "/", info.baseUrl);
|
|
213
232
|
const path = url.pathname;
|
|
@@ -333,6 +352,11 @@ export async function ensureChromeExtensionRelayServer(opts) {
|
|
|
333
352
|
return;
|
|
334
353
|
}
|
|
335
354
|
if (pathname === "/extension") {
|
|
355
|
+
const token = getRelayAuthTokenFromRequest(req, url);
|
|
356
|
+
if (!token || token !== relayAuthToken) {
|
|
357
|
+
rejectUpgrade(socket, 401, "Unauthorized");
|
|
358
|
+
return;
|
|
359
|
+
}
|
|
336
360
|
if (extensionWs) {
|
|
337
361
|
rejectUpgrade(socket, 409, "Extension already connected");
|
|
338
362
|
return;
|
|
@@ -343,7 +367,7 @@ export async function ensureChromeExtensionRelayServer(opts) {
|
|
|
343
367
|
return;
|
|
344
368
|
}
|
|
345
369
|
if (pathname === "/cdp") {
|
|
346
|
-
const token =
|
|
370
|
+
const token = getRelayAuthTokenFromRequest(req, url);
|
|
347
371
|
if (!token || token !== relayAuthToken) {
|
|
348
372
|
rejectUpgrade(socket, 401, "Unauthorized");
|
|
349
373
|
return;
|
|
@@ -548,10 +572,34 @@ export async function ensureChromeExtensionRelayServer(opts) {
|
|
|
548
572
|
cdpClients.delete(ws);
|
|
549
573
|
});
|
|
550
574
|
});
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
575
|
+
try {
|
|
576
|
+
await new Promise((resolve, reject) => {
|
|
577
|
+
server.listen(info.port, info.host, () => resolve());
|
|
578
|
+
server.once("error", reject);
|
|
579
|
+
});
|
|
580
|
+
}
|
|
581
|
+
catch (err) {
|
|
582
|
+
if (isAddrInUseError(err) &&
|
|
583
|
+
(await probeAuthenticatedPoolBotRelay({
|
|
584
|
+
baseUrl: info.baseUrl,
|
|
585
|
+
relayAuthHeader: RELAY_AUTH_HEADER,
|
|
586
|
+
relayAuthToken,
|
|
587
|
+
}))) {
|
|
588
|
+
const existingRelay = {
|
|
589
|
+
host: info.host,
|
|
590
|
+
port: info.port,
|
|
591
|
+
baseUrl: info.baseUrl,
|
|
592
|
+
cdpWsUrl: `ws://${info.host}:${info.port}/cdp`,
|
|
593
|
+
extensionConnected: () => false,
|
|
594
|
+
stop: async () => {
|
|
595
|
+
relayRuntimeByPort.delete(info.port);
|
|
596
|
+
},
|
|
597
|
+
};
|
|
598
|
+
relayRuntimeByPort.set(info.port, { server: existingRelay, relayAuthToken });
|
|
599
|
+
return existingRelay;
|
|
600
|
+
}
|
|
601
|
+
throw err;
|
|
602
|
+
}
|
|
555
603
|
const addr = server.address();
|
|
556
604
|
const port = addr?.port ?? info.port;
|
|
557
605
|
const host = info.host;
|
|
@@ -563,8 +611,7 @@ export async function ensureChromeExtensionRelayServer(opts) {
|
|
|
563
611
|
cdpWsUrl: `ws://${host}:${port}/cdp`,
|
|
564
612
|
extensionConnected: () => Boolean(extensionWs),
|
|
565
613
|
stop: async () => {
|
|
566
|
-
|
|
567
|
-
relayAuthByPort.delete(port);
|
|
614
|
+
relayRuntimeByPort.delete(port);
|
|
568
615
|
try {
|
|
569
616
|
extensionWs?.close(1001, "server stopping");
|
|
570
617
|
}
|
|
@@ -586,17 +633,15 @@ export async function ensureChromeExtensionRelayServer(opts) {
|
|
|
586
633
|
wssCdp.close();
|
|
587
634
|
},
|
|
588
635
|
};
|
|
589
|
-
|
|
590
|
-
serversByPort.set(port, relay);
|
|
636
|
+
relayRuntimeByPort.set(port, { server: relay, relayAuthToken });
|
|
591
637
|
return relay;
|
|
592
638
|
}
|
|
593
639
|
export async function stopChromeExtensionRelayServer(opts) {
|
|
594
640
|
const info = parseBaseUrl(opts.cdpUrl);
|
|
595
|
-
const existing =
|
|
641
|
+
const existing = relayRuntimeByPort.get(info.port);
|
|
596
642
|
if (!existing) {
|
|
597
643
|
return false;
|
|
598
644
|
}
|
|
599
|
-
await existing.stop();
|
|
600
|
-
relayAuthByPort.delete(info.port);
|
|
645
|
+
await existing.server.stop();
|
|
601
646
|
return true;
|
|
602
647
|
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { resolvePinnedHostnameWithPolicy, } from "../infra/net/ssrf.js";
|
|
2
|
+
const NETWORK_NAVIGATION_PROTOCOLS = new Set(["http:", "https:"]);
|
|
3
|
+
const SAFE_NON_NETWORK_URLS = new Set(["about:blank"]);
|
|
4
|
+
function isAllowedNonNetworkNavigationUrl(parsed) {
|
|
5
|
+
// Keep non-network navigation explicit; about:blank is the only allowed bootstrap URL.
|
|
6
|
+
return SAFE_NON_NETWORK_URLS.has(parsed.href);
|
|
7
|
+
}
|
|
8
|
+
export class InvalidBrowserNavigationUrlError extends Error {
|
|
9
|
+
constructor(message) {
|
|
10
|
+
super(message);
|
|
11
|
+
this.name = "InvalidBrowserNavigationUrlError";
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
export function withBrowserNavigationPolicy(ssrfPolicy) {
|
|
15
|
+
return ssrfPolicy ? { ssrfPolicy } : {};
|
|
16
|
+
}
|
|
17
|
+
export async function assertBrowserNavigationAllowed(opts) {
|
|
18
|
+
const rawUrl = String(opts.url ?? "").trim();
|
|
19
|
+
if (!rawUrl) {
|
|
20
|
+
throw new InvalidBrowserNavigationUrlError("url is required");
|
|
21
|
+
}
|
|
22
|
+
let parsed;
|
|
23
|
+
try {
|
|
24
|
+
parsed = new URL(rawUrl);
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
throw new InvalidBrowserNavigationUrlError(`Invalid URL: ${rawUrl}`);
|
|
28
|
+
}
|
|
29
|
+
if (!NETWORK_NAVIGATION_PROTOCOLS.has(parsed.protocol)) {
|
|
30
|
+
if (isAllowedNonNetworkNavigationUrl(parsed)) {
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
throw new InvalidBrowserNavigationUrlError(`Navigation blocked: unsupported protocol "${parsed.protocol}"`);
|
|
34
|
+
}
|
|
35
|
+
await resolvePinnedHostnameWithPolicy(parsed.hostname, {
|
|
36
|
+
lookupFn: opts.lookupFn,
|
|
37
|
+
policy: opts.ssrfPolicy,
|
|
38
|
+
});
|
|
39
|
+
}
|
package/dist/browser/paths.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
+
import fs from "node:fs/promises";
|
|
1
2
|
import path from "node:path";
|
|
3
|
+
import { SafeOpenError, openFileWithinRoot } from "../infra/fs-safe.js";
|
|
2
4
|
import { resolvePreferredPoolbotTmpDir } from "../infra/tmp-poolbot-dir.js";
|
|
3
5
|
export const DEFAULT_BROWSER_TMP_DIR = resolvePreferredPoolbotTmpDir();
|
|
4
6
|
export const DEFAULT_TRACE_DIR = DEFAULT_BROWSER_TMP_DIR;
|
|
@@ -35,3 +37,78 @@ export function resolvePathsWithinRoot(params) {
|
|
|
35
37
|
}
|
|
36
38
|
return { ok: true, paths: resolvedPaths };
|
|
37
39
|
}
|
|
40
|
+
export async function resolveExistingPathsWithinRoot(params) {
|
|
41
|
+
const rootDir = path.resolve(params.rootDir);
|
|
42
|
+
let rootRealPath;
|
|
43
|
+
try {
|
|
44
|
+
rootRealPath = await fs.realpath(rootDir);
|
|
45
|
+
}
|
|
46
|
+
catch {
|
|
47
|
+
// Keep historical behavior for missing roots and rely on openFileWithinRoot for final checks.
|
|
48
|
+
rootRealPath = undefined;
|
|
49
|
+
}
|
|
50
|
+
const isInRoot = (relativePath) => Boolean(relativePath) && !relativePath.startsWith("..") && !path.isAbsolute(relativePath);
|
|
51
|
+
const resolveExistingRelativePath = async (requestedPath) => {
|
|
52
|
+
const raw = requestedPath.trim();
|
|
53
|
+
const lexicalPathResult = resolvePathWithinRoot({
|
|
54
|
+
rootDir,
|
|
55
|
+
requestedPath,
|
|
56
|
+
scopeLabel: params.scopeLabel,
|
|
57
|
+
});
|
|
58
|
+
if (lexicalPathResult.ok) {
|
|
59
|
+
return {
|
|
60
|
+
ok: true,
|
|
61
|
+
relativePath: path.relative(rootDir, lexicalPathResult.path),
|
|
62
|
+
fallbackPath: lexicalPathResult.path,
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
if (!rootRealPath || !raw || !path.isAbsolute(raw)) {
|
|
66
|
+
return lexicalPathResult;
|
|
67
|
+
}
|
|
68
|
+
try {
|
|
69
|
+
const resolvedExistingPath = await fs.realpath(raw);
|
|
70
|
+
const relativePath = path.relative(rootRealPath, resolvedExistingPath);
|
|
71
|
+
if (!isInRoot(relativePath)) {
|
|
72
|
+
return lexicalPathResult;
|
|
73
|
+
}
|
|
74
|
+
return {
|
|
75
|
+
ok: true,
|
|
76
|
+
relativePath,
|
|
77
|
+
fallbackPath: resolvedExistingPath,
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
catch {
|
|
81
|
+
return lexicalPathResult;
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
const resolvedPaths = [];
|
|
85
|
+
for (const raw of params.requestedPaths) {
|
|
86
|
+
const pathResult = await resolveExistingRelativePath(raw);
|
|
87
|
+
if (!pathResult.ok) {
|
|
88
|
+
return { ok: false, error: pathResult.error };
|
|
89
|
+
}
|
|
90
|
+
let opened;
|
|
91
|
+
try {
|
|
92
|
+
opened = await openFileWithinRoot({
|
|
93
|
+
rootDir,
|
|
94
|
+
relativePath: pathResult.relativePath,
|
|
95
|
+
});
|
|
96
|
+
resolvedPaths.push(opened.realPath);
|
|
97
|
+
}
|
|
98
|
+
catch (err) {
|
|
99
|
+
if (err instanceof SafeOpenError && err.code === "not-found") {
|
|
100
|
+
// Preserve historical behavior for paths that do not exist yet.
|
|
101
|
+
resolvedPaths.push(pathResult.fallbackPath);
|
|
102
|
+
continue;
|
|
103
|
+
}
|
|
104
|
+
return {
|
|
105
|
+
ok: false,
|
|
106
|
+
error: `Invalid path: must stay within ${params.scopeLabel} and be a regular non-symlink file`,
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
finally {
|
|
110
|
+
await opened?.handle.close().catch(() => { });
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
return { ok: true, paths: resolvedPaths };
|
|
114
|
+
}
|
package/dist/browser/profiles.js
CHANGED
|
@@ -15,8 +15,9 @@ export const CDP_PORT_RANGE_START = 18800;
|
|
|
15
15
|
export const CDP_PORT_RANGE_END = 18899;
|
|
16
16
|
export const PROFILE_NAME_REGEX = /^[a-z0-9][a-z0-9-]*$/;
|
|
17
17
|
export function isValidProfileName(name) {
|
|
18
|
-
if (!name || name.length > 64)
|
|
18
|
+
if (!name || name.length > 64) {
|
|
19
19
|
return false;
|
|
20
|
+
}
|
|
20
21
|
return PROFILE_NAME_REGEX.test(name);
|
|
21
22
|
}
|
|
22
23
|
export function allocateCdpPort(usedPorts, range) {
|
|
@@ -25,17 +26,20 @@ export function allocateCdpPort(usedPorts, range) {
|
|
|
25
26
|
if (!Number.isFinite(start) || !Number.isFinite(end) || start <= 0 || end <= 0) {
|
|
26
27
|
return null;
|
|
27
28
|
}
|
|
28
|
-
if (start > end)
|
|
29
|
+
if (start > end) {
|
|
29
30
|
return null;
|
|
31
|
+
}
|
|
30
32
|
for (let port = start; port <= end; port++) {
|
|
31
|
-
if (!usedPorts.has(port))
|
|
33
|
+
if (!usedPorts.has(port)) {
|
|
32
34
|
return port;
|
|
35
|
+
}
|
|
33
36
|
}
|
|
34
37
|
return null;
|
|
35
38
|
}
|
|
36
39
|
export function getUsedPorts(profiles) {
|
|
37
|
-
if (!profiles)
|
|
40
|
+
if (!profiles) {
|
|
38
41
|
return new Set();
|
|
42
|
+
}
|
|
39
43
|
const used = new Set();
|
|
40
44
|
for (const profile of Object.values(profiles)) {
|
|
41
45
|
if (typeof profile.cdpPort === "number") {
|
|
@@ -43,8 +47,9 @@ export function getUsedPorts(profiles) {
|
|
|
43
47
|
continue;
|
|
44
48
|
}
|
|
45
49
|
const rawUrl = profile.cdpUrl?.trim();
|
|
46
|
-
if (!rawUrl)
|
|
50
|
+
if (!rawUrl) {
|
|
47
51
|
continue;
|
|
52
|
+
}
|
|
48
53
|
try {
|
|
49
54
|
const parsed = new URL(rawUrl);
|
|
50
55
|
const port = parsed.port && Number.parseInt(parsed.port, 10) > 0
|
|
@@ -63,7 +68,7 @@ export function getUsedPorts(profiles) {
|
|
|
63
68
|
return used;
|
|
64
69
|
}
|
|
65
70
|
export const PROFILE_COLORS = [
|
|
66
|
-
"#
|
|
71
|
+
"#FF4500", // Orange-red (poolbot default)
|
|
67
72
|
"#0066CC", // Blue
|
|
68
73
|
"#00AA00", // Green
|
|
69
74
|
"#9933FF", // Purple
|
|
@@ -83,11 +88,11 @@ export function allocateColor(usedColors) {
|
|
|
83
88
|
}
|
|
84
89
|
// All colors used, cycle based on count
|
|
85
90
|
const index = usedColors.size % PROFILE_COLORS.length;
|
|
86
|
-
// biome-ignore lint/style/noNonNullAssertion: Array is non-empty constant
|
|
87
91
|
return PROFILE_COLORS[index] ?? PROFILE_COLORS[0];
|
|
88
92
|
}
|
|
89
93
|
export function getUsedColors(profiles) {
|
|
90
|
-
if (!profiles)
|
|
94
|
+
if (!profiles) {
|
|
91
95
|
return new Set();
|
|
96
|
+
}
|
|
92
97
|
return new Set(Object.values(profiles).map((p) => p.color.toUpperCase()));
|
|
93
98
|
}
|
|
@@ -3,8 +3,9 @@ let pwAiModuleSoft = null;
|
|
|
3
3
|
let pwAiModuleStrict = null;
|
|
4
4
|
function isModuleNotFoundError(err) {
|
|
5
5
|
const code = extractErrorCode(err);
|
|
6
|
-
if (code === "ERR_MODULE_NOT_FOUND")
|
|
6
|
+
if (code === "ERR_MODULE_NOT_FOUND") {
|
|
7
7
|
return true;
|
|
8
|
+
}
|
|
8
9
|
const msg = formatErrorMessage(err);
|
|
9
10
|
return (msg.includes("Cannot find module") ||
|
|
10
11
|
msg.includes("Cannot find package") ||
|
|
@@ -17,21 +18,25 @@ async function loadPwAiModule(mode) {
|
|
|
17
18
|
return await import("./pw-ai.js");
|
|
18
19
|
}
|
|
19
20
|
catch (err) {
|
|
20
|
-
if (mode === "soft")
|
|
21
|
+
if (mode === "soft") {
|
|
21
22
|
return null;
|
|
22
|
-
|
|
23
|
+
}
|
|
24
|
+
if (isModuleNotFoundError(err)) {
|
|
23
25
|
return null;
|
|
26
|
+
}
|
|
24
27
|
throw err;
|
|
25
28
|
}
|
|
26
29
|
}
|
|
27
30
|
export async function getPwAiModule(opts) {
|
|
28
31
|
const mode = opts?.mode ?? "soft";
|
|
29
32
|
if (mode === "soft") {
|
|
30
|
-
if (!pwAiModuleSoft)
|
|
33
|
+
if (!pwAiModuleSoft) {
|
|
31
34
|
pwAiModuleSoft = loadPwAiModule("soft");
|
|
35
|
+
}
|
|
32
36
|
return await pwAiModuleSoft;
|
|
33
37
|
}
|
|
34
|
-
if (!pwAiModuleStrict)
|
|
38
|
+
if (!pwAiModuleStrict) {
|
|
35
39
|
pwAiModuleStrict = loadPwAiModule("strict");
|
|
40
|
+
}
|
|
36
41
|
return await pwAiModuleStrict;
|
|
37
42
|
}
|