@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
|
@@ -31,8 +31,8 @@ function compileSafeBinProfile(fixture) {
|
|
|
31
31
|
return {
|
|
32
32
|
minPositional: fixture.minPositional,
|
|
33
33
|
maxPositional: fixture.maxPositional,
|
|
34
|
-
|
|
35
|
-
|
|
34
|
+
allowedValueFlags: toFlagSet(fixture.allowedValueFlags),
|
|
35
|
+
deniedFlags: toFlagSet(fixture.deniedFlags),
|
|
36
36
|
};
|
|
37
37
|
}
|
|
38
38
|
function compileSafeBinProfiles(fixtures) {
|
|
@@ -42,19 +42,8 @@ export const SAFE_BIN_GENERIC_PROFILE_FIXTURE = {};
|
|
|
42
42
|
export const SAFE_BIN_PROFILE_FIXTURES = {
|
|
43
43
|
jq: {
|
|
44
44
|
maxPositional: 1,
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
"--argjson",
|
|
48
|
-
"--argstr",
|
|
49
|
-
"--argfile",
|
|
50
|
-
"--rawfile",
|
|
51
|
-
"--slurpfile",
|
|
52
|
-
"--from-file",
|
|
53
|
-
"--library-path",
|
|
54
|
-
"-L",
|
|
55
|
-
"-f",
|
|
56
|
-
],
|
|
57
|
-
blockedFlags: [
|
|
45
|
+
allowedValueFlags: ["--arg", "--argjson", "--argstr"],
|
|
46
|
+
deniedFlags: [
|
|
58
47
|
"--argfile",
|
|
59
48
|
"--rawfile",
|
|
60
49
|
"--slurpfile",
|
|
@@ -65,31 +54,29 @@ export const SAFE_BIN_PROFILE_FIXTURES = {
|
|
|
65
54
|
],
|
|
66
55
|
},
|
|
67
56
|
grep: {
|
|
68
|
-
|
|
69
|
-
|
|
57
|
+
// Keep grep stdin-only: pattern must come from -e/--regexp.
|
|
58
|
+
// Allowing one positional is ambiguous because -e consumes the pattern and
|
|
59
|
+
// frees the positional slot for a filename.
|
|
60
|
+
maxPositional: 0,
|
|
61
|
+
allowedValueFlags: [
|
|
70
62
|
"--regexp",
|
|
71
|
-
"--file",
|
|
72
63
|
"--max-count",
|
|
73
64
|
"--after-context",
|
|
74
65
|
"--before-context",
|
|
75
66
|
"--context",
|
|
76
67
|
"--devices",
|
|
77
|
-
"--directories",
|
|
78
68
|
"--binary-files",
|
|
79
69
|
"--exclude",
|
|
80
|
-
"--exclude-from",
|
|
81
70
|
"--include",
|
|
82
71
|
"--label",
|
|
83
72
|
"-e",
|
|
84
|
-
"-f",
|
|
85
73
|
"-m",
|
|
86
74
|
"-A",
|
|
87
75
|
"-B",
|
|
88
76
|
"-C",
|
|
89
77
|
"-D",
|
|
90
|
-
"-d",
|
|
91
78
|
],
|
|
92
|
-
|
|
79
|
+
deniedFlags: [
|
|
93
80
|
"--file",
|
|
94
81
|
"--exclude-from",
|
|
95
82
|
"--dereference-recursive",
|
|
@@ -103,7 +90,7 @@ export const SAFE_BIN_PROFILE_FIXTURES = {
|
|
|
103
90
|
},
|
|
104
91
|
cut: {
|
|
105
92
|
maxPositional: 0,
|
|
106
|
-
|
|
93
|
+
allowedValueFlags: [
|
|
107
94
|
"--bytes",
|
|
108
95
|
"--characters",
|
|
109
96
|
"--fields",
|
|
@@ -117,36 +104,41 @@ export const SAFE_BIN_PROFILE_FIXTURES = {
|
|
|
117
104
|
},
|
|
118
105
|
sort: {
|
|
119
106
|
maxPositional: 0,
|
|
120
|
-
|
|
107
|
+
allowedValueFlags: [
|
|
121
108
|
"--key",
|
|
122
109
|
"--field-separator",
|
|
123
110
|
"--buffer-size",
|
|
124
111
|
"--temporary-directory",
|
|
125
|
-
"--compress-program",
|
|
126
112
|
"--parallel",
|
|
127
113
|
"--batch-size",
|
|
128
114
|
"--random-source",
|
|
129
|
-
"--files0-from",
|
|
130
|
-
"--output",
|
|
131
115
|
"-k",
|
|
132
116
|
"-t",
|
|
133
117
|
"-S",
|
|
134
118
|
"-T",
|
|
135
|
-
"-o",
|
|
136
119
|
],
|
|
137
|
-
|
|
120
|
+
// --compress-program can invoke an external executable and breaks stdin-only guarantees.
|
|
121
|
+
deniedFlags: ["--compress-program", "--files0-from", "--output", "-o"],
|
|
138
122
|
},
|
|
139
123
|
uniq: {
|
|
140
124
|
maxPositional: 0,
|
|
141
|
-
|
|
125
|
+
allowedValueFlags: [
|
|
126
|
+
"--skip-fields",
|
|
127
|
+
"--skip-chars",
|
|
128
|
+
"--check-chars",
|
|
129
|
+
"--group",
|
|
130
|
+
"-f",
|
|
131
|
+
"-s",
|
|
132
|
+
"-w",
|
|
133
|
+
],
|
|
142
134
|
},
|
|
143
135
|
head: {
|
|
144
136
|
maxPositional: 0,
|
|
145
|
-
|
|
137
|
+
allowedValueFlags: ["--lines", "--bytes", "-n", "-c"],
|
|
146
138
|
},
|
|
147
139
|
tail: {
|
|
148
140
|
maxPositional: 0,
|
|
149
|
-
|
|
141
|
+
allowedValueFlags: [
|
|
150
142
|
"--lines",
|
|
151
143
|
"--bytes",
|
|
152
144
|
"--sleep-interval",
|
|
@@ -162,12 +154,28 @@ export const SAFE_BIN_PROFILE_FIXTURES = {
|
|
|
162
154
|
},
|
|
163
155
|
wc: {
|
|
164
156
|
maxPositional: 0,
|
|
165
|
-
|
|
166
|
-
blockedFlags: ["--files0-from"],
|
|
157
|
+
deniedFlags: ["--files0-from"],
|
|
167
158
|
},
|
|
168
159
|
};
|
|
169
160
|
export const SAFE_BIN_GENERIC_PROFILE = compileSafeBinProfile(SAFE_BIN_GENERIC_PROFILE_FIXTURE);
|
|
170
161
|
export const SAFE_BIN_PROFILES = compileSafeBinProfiles(SAFE_BIN_PROFILE_FIXTURES);
|
|
162
|
+
export function resolveSafeBinDeniedFlags(fixtures = SAFE_BIN_PROFILE_FIXTURES) {
|
|
163
|
+
const out = {};
|
|
164
|
+
for (const [name, fixture] of Object.entries(fixtures)) {
|
|
165
|
+
const denied = Array.from(new Set(fixture.deniedFlags ?? [])).toSorted();
|
|
166
|
+
if (denied.length > 0) {
|
|
167
|
+
out[name] = denied;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
return out;
|
|
171
|
+
}
|
|
172
|
+
export function renderSafeBinDeniedFlagsDocBullets(fixtures = SAFE_BIN_PROFILE_FIXTURES) {
|
|
173
|
+
const deniedByBin = resolveSafeBinDeniedFlags(fixtures);
|
|
174
|
+
const bins = Object.keys(deniedByBin).toSorted();
|
|
175
|
+
return bins
|
|
176
|
+
.map((bin) => `- \`${bin}\`: ${deniedByBin[bin].map((flag) => `\`${flag}\``).join(", ")}`)
|
|
177
|
+
.join("\n");
|
|
178
|
+
}
|
|
171
179
|
function isSafeLiteralToken(value) {
|
|
172
180
|
if (!value || value === "-") {
|
|
173
181
|
return true;
|
|
@@ -177,25 +185,25 @@ function isSafeLiteralToken(value) {
|
|
|
177
185
|
function isInvalidValueToken(value) {
|
|
178
186
|
return !value || !isSafeLiteralToken(value);
|
|
179
187
|
}
|
|
180
|
-
function consumeLongOptionToken(args, index, flag, inlineValue,
|
|
181
|
-
if (
|
|
188
|
+
function consumeLongOptionToken(args, index, flag, inlineValue, allowedValueFlags, deniedFlags) {
|
|
189
|
+
if (deniedFlags.has(flag)) {
|
|
182
190
|
return -1;
|
|
183
191
|
}
|
|
184
192
|
if (inlineValue !== undefined) {
|
|
185
193
|
return isSafeLiteralToken(inlineValue) ? index + 1 : -1;
|
|
186
194
|
}
|
|
187
|
-
if (!
|
|
195
|
+
if (!allowedValueFlags.has(flag)) {
|
|
188
196
|
return index + 1;
|
|
189
197
|
}
|
|
190
198
|
return isInvalidValueToken(args[index + 1]) ? -1 : index + 2;
|
|
191
199
|
}
|
|
192
|
-
function consumeShortOptionClusterToken(args, index, raw, cluster, flags,
|
|
200
|
+
function consumeShortOptionClusterToken(args, index, raw, cluster, flags, allowedValueFlags, deniedFlags) {
|
|
193
201
|
for (let j = 0; j < flags.length; j += 1) {
|
|
194
202
|
const flag = flags[j];
|
|
195
|
-
if (
|
|
203
|
+
if (deniedFlags.has(flag)) {
|
|
196
204
|
return -1;
|
|
197
205
|
}
|
|
198
|
-
if (!
|
|
206
|
+
if (!allowedValueFlags.has(flag)) {
|
|
199
207
|
continue;
|
|
200
208
|
}
|
|
201
209
|
const inlineValue = cluster.slice(j + 1);
|
|
@@ -221,8 +229,8 @@ function validatePositionalCount(positional, profile) {
|
|
|
221
229
|
return typeof profile.maxPositional !== "number" || positional.length <= profile.maxPositional;
|
|
222
230
|
}
|
|
223
231
|
export function validateSafeBinArgv(args, profile) {
|
|
224
|
-
const
|
|
225
|
-
const
|
|
232
|
+
const allowedValueFlags = profile.allowedValueFlags ?? NO_FLAGS;
|
|
233
|
+
const deniedFlags = profile.deniedFlags ?? NO_FLAGS;
|
|
226
234
|
const positional = [];
|
|
227
235
|
let i = 0;
|
|
228
236
|
while (i < args.length) {
|
|
@@ -252,14 +260,14 @@ export function validateSafeBinArgv(args, profile) {
|
|
|
252
260
|
continue;
|
|
253
261
|
}
|
|
254
262
|
if (token.style === "long") {
|
|
255
|
-
const nextIndex = consumeLongOptionToken(args, i, token.flag, token.inlineValue,
|
|
263
|
+
const nextIndex = consumeLongOptionToken(args, i, token.flag, token.inlineValue, allowedValueFlags, deniedFlags);
|
|
256
264
|
if (nextIndex < 0) {
|
|
257
265
|
return false;
|
|
258
266
|
}
|
|
259
267
|
i = nextIndex;
|
|
260
268
|
continue;
|
|
261
269
|
}
|
|
262
|
-
const nextIndex = consumeShortOptionClusterToken(args, i, token.raw, token.cluster, token.flags,
|
|
270
|
+
const nextIndex = consumeShortOptionClusterToken(args, i, token.raw, token.cluster, token.flags, allowedValueFlags, deniedFlags);
|
|
263
271
|
if (nextIndex < 0) {
|
|
264
272
|
return false;
|
|
265
273
|
}
|
package/dist/infra/fs-safe.js
CHANGED
|
@@ -1,76 +1,108 @@
|
|
|
1
1
|
import { constants as fsConstants } from "node:fs";
|
|
2
2
|
import fs from "node:fs/promises";
|
|
3
3
|
import path from "node:path";
|
|
4
|
+
import { isNotFoundPathError, isPathInside, isSymlinkOpenError } from "./path-guards.js";
|
|
4
5
|
export class SafeOpenError extends Error {
|
|
5
6
|
code;
|
|
6
|
-
constructor(code, message) {
|
|
7
|
-
super(message);
|
|
7
|
+
constructor(code, message, options) {
|
|
8
|
+
super(message, options);
|
|
8
9
|
this.code = code;
|
|
9
10
|
this.name = "SafeOpenError";
|
|
10
11
|
}
|
|
11
12
|
}
|
|
12
|
-
const
|
|
13
|
+
const SUPPORTS_NOFOLLOW = process.platform !== "win32" && "O_NOFOLLOW" in fsConstants;
|
|
14
|
+
const OPEN_READ_FLAGS = fsConstants.O_RDONLY | (SUPPORTS_NOFOLLOW ? fsConstants.O_NOFOLLOW : 0);
|
|
13
15
|
const ensureTrailingSep = (value) => (value.endsWith(path.sep) ? value : value + path.sep);
|
|
14
|
-
|
|
15
|
-
const isNotFoundError = (err) => isNodeError(err) && typeof err.code === "string" && NOT_FOUND_CODES.has(err.code);
|
|
16
|
-
const isSymlinkOpenError = (err) => isNodeError(err) && (err.code === "ELOOP" || err.code === "EINVAL" || err.code === "ENOTSUP");
|
|
17
|
-
export async function openFileWithinRoot(params) {
|
|
18
|
-
let rootReal;
|
|
19
|
-
try {
|
|
20
|
-
rootReal = await fs.realpath(params.rootDir);
|
|
21
|
-
}
|
|
22
|
-
catch (err) {
|
|
23
|
-
if (isNotFoundError(err)) {
|
|
24
|
-
throw new SafeOpenError("not-found", "root dir not found");
|
|
25
|
-
}
|
|
26
|
-
throw err;
|
|
27
|
-
}
|
|
28
|
-
const rootWithSep = ensureTrailingSep(rootReal);
|
|
29
|
-
const resolved = path.resolve(rootWithSep, params.relativePath);
|
|
30
|
-
if (!resolved.startsWith(rootWithSep)) {
|
|
31
|
-
throw new SafeOpenError("invalid-path", "path escapes root");
|
|
32
|
-
}
|
|
33
|
-
const supportsNoFollow = process.platform !== "win32" && "O_NOFOLLOW" in fsConstants;
|
|
34
|
-
const flags = fsConstants.O_RDONLY | (supportsNoFollow ? fsConstants.O_NOFOLLOW : 0);
|
|
16
|
+
async function openVerifiedLocalFile(filePath) {
|
|
35
17
|
let handle;
|
|
36
18
|
try {
|
|
37
|
-
handle = await fs.open(
|
|
19
|
+
handle = await fs.open(filePath, OPEN_READ_FLAGS);
|
|
38
20
|
}
|
|
39
21
|
catch (err) {
|
|
40
|
-
if (
|
|
22
|
+
if (isNotFoundPathError(err)) {
|
|
41
23
|
throw new SafeOpenError("not-found", "file not found");
|
|
42
24
|
}
|
|
43
25
|
if (isSymlinkOpenError(err)) {
|
|
44
|
-
throw new SafeOpenError("
|
|
26
|
+
throw new SafeOpenError("symlink", "symlink open blocked", { cause: err });
|
|
45
27
|
}
|
|
46
28
|
throw err;
|
|
47
29
|
}
|
|
48
30
|
try {
|
|
49
|
-
const lstat = await
|
|
50
|
-
if (lstat
|
|
51
|
-
throw new SafeOpenError("
|
|
52
|
-
}
|
|
53
|
-
const realPath = await fs.realpath(resolved);
|
|
54
|
-
if (!realPath.startsWith(rootWithSep)) {
|
|
55
|
-
throw new SafeOpenError("invalid-path", "path escapes root");
|
|
31
|
+
const [stat, lstat] = await Promise.all([handle.stat(), fs.lstat(filePath)]);
|
|
32
|
+
if (lstat.isSymbolicLink()) {
|
|
33
|
+
throw new SafeOpenError("symlink", "symlink not allowed");
|
|
56
34
|
}
|
|
57
|
-
const stat = await handle.stat();
|
|
58
35
|
if (!stat.isFile()) {
|
|
59
|
-
throw new SafeOpenError("
|
|
36
|
+
throw new SafeOpenError("not-file", "not a file");
|
|
60
37
|
}
|
|
38
|
+
if (stat.ino !== lstat.ino || stat.dev !== lstat.dev) {
|
|
39
|
+
throw new SafeOpenError("path-mismatch", "path changed during read");
|
|
40
|
+
}
|
|
41
|
+
const realPath = await fs.realpath(filePath);
|
|
61
42
|
const realStat = await fs.stat(realPath);
|
|
62
43
|
if (stat.ino !== realStat.ino || stat.dev !== realStat.dev) {
|
|
63
|
-
throw new SafeOpenError("
|
|
44
|
+
throw new SafeOpenError("path-mismatch", "path mismatch");
|
|
64
45
|
}
|
|
65
46
|
return { handle, realPath, stat };
|
|
66
47
|
}
|
|
67
48
|
catch (err) {
|
|
68
49
|
await handle.close().catch(() => { });
|
|
69
|
-
if (err instanceof SafeOpenError)
|
|
50
|
+
if (err instanceof SafeOpenError) {
|
|
70
51
|
throw err;
|
|
71
|
-
|
|
52
|
+
}
|
|
53
|
+
if (isNotFoundPathError(err)) {
|
|
72
54
|
throw new SafeOpenError("not-found", "file not found");
|
|
73
55
|
}
|
|
74
56
|
throw err;
|
|
75
57
|
}
|
|
76
58
|
}
|
|
59
|
+
export async function openFileWithinRoot(params) {
|
|
60
|
+
let rootReal;
|
|
61
|
+
try {
|
|
62
|
+
rootReal = await fs.realpath(params.rootDir);
|
|
63
|
+
}
|
|
64
|
+
catch (err) {
|
|
65
|
+
if (isNotFoundPathError(err)) {
|
|
66
|
+
throw new SafeOpenError("not-found", "root dir not found");
|
|
67
|
+
}
|
|
68
|
+
throw err;
|
|
69
|
+
}
|
|
70
|
+
const rootWithSep = ensureTrailingSep(rootReal);
|
|
71
|
+
const resolved = path.resolve(rootWithSep, params.relativePath);
|
|
72
|
+
if (!isPathInside(rootWithSep, resolved)) {
|
|
73
|
+
throw new SafeOpenError("invalid-path", "path escapes root");
|
|
74
|
+
}
|
|
75
|
+
let opened;
|
|
76
|
+
try {
|
|
77
|
+
opened = await openVerifiedLocalFile(resolved);
|
|
78
|
+
}
|
|
79
|
+
catch (err) {
|
|
80
|
+
if (err instanceof SafeOpenError) {
|
|
81
|
+
if (err.code === "not-found") {
|
|
82
|
+
throw err;
|
|
83
|
+
}
|
|
84
|
+
throw new SafeOpenError("invalid-path", "path is not a regular file under root", {
|
|
85
|
+
cause: err,
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
throw err;
|
|
89
|
+
}
|
|
90
|
+
if (!isPathInside(rootWithSep, opened.realPath)) {
|
|
91
|
+
await opened.handle.close().catch(() => { });
|
|
92
|
+
throw new SafeOpenError("invalid-path", "path escapes root");
|
|
93
|
+
}
|
|
94
|
+
return opened;
|
|
95
|
+
}
|
|
96
|
+
export async function readLocalFileSafely(params) {
|
|
97
|
+
const opened = await openVerifiedLocalFile(params.filePath);
|
|
98
|
+
try {
|
|
99
|
+
if (params.maxBytes !== undefined && opened.stat.size > params.maxBytes) {
|
|
100
|
+
throw new SafeOpenError("too-large", `file exceeds limit of ${params.maxBytes} bytes (got ${opened.stat.size})`);
|
|
101
|
+
}
|
|
102
|
+
const buffer = await opened.handle.readFile();
|
|
103
|
+
return { buffer, realPath: opened.realPath, stat: opened.stat };
|
|
104
|
+
}
|
|
105
|
+
finally {
|
|
106
|
+
await opened.handle.close().catch(() => { });
|
|
107
|
+
}
|
|
108
|
+
}
|
|
@@ -118,7 +118,7 @@ async function readLockPayload(lockPath) {
|
|
|
118
118
|
function resolveGatewayLockPath(env) {
|
|
119
119
|
const stateDir = resolveStateDir(env);
|
|
120
120
|
const configPath = resolveConfigPath(env, stateDir);
|
|
121
|
-
const hash = createHash("
|
|
121
|
+
const hash = createHash("sha256").update(configPath).digest("hex").slice(0, 8);
|
|
122
122
|
const lockDir = resolveGatewayLockDir();
|
|
123
123
|
const lockPath = path.join(lockDir, `gateway.${hash}.lock`);
|
|
124
124
|
return { lockPath, configPath };
|
|
@@ -186,7 +186,11 @@ export async function acquireGatewayLock(opts = {}) {
|
|
|
186
186
|
stale = Date.now() - st.mtimeMs > staleMs;
|
|
187
187
|
}
|
|
188
188
|
catch {
|
|
189
|
-
|
|
189
|
+
// On Windows or locked filesystems we may be unable to stat the
|
|
190
|
+
// lock file even though the existing gateway is still healthy.
|
|
191
|
+
// Treat the lock as non-stale so we keep waiting instead of
|
|
192
|
+
// forcefully removing another gateway's lock.
|
|
193
|
+
stale = false;
|
|
190
194
|
}
|
|
191
195
|
}
|
|
192
196
|
if (stale) {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { isHeartbeatActionWakeReason, normalizeHeartbeatWakeReason, resolveHeartbeatReasonKind, } from "./heartbeat-reason.js";
|
|
1
2
|
let handler = null;
|
|
2
3
|
let handlerGeneration = 0;
|
|
3
4
|
const pendingWakes = new Map();
|
|
@@ -8,34 +9,27 @@ let timerDueAt = null;
|
|
|
8
9
|
let timerKind = null;
|
|
9
10
|
const DEFAULT_COALESCE_MS = 250;
|
|
10
11
|
const DEFAULT_RETRY_MS = 1_000;
|
|
11
|
-
const HOOK_REASON_PREFIX = "hook:";
|
|
12
12
|
const REASON_PRIORITY = {
|
|
13
13
|
RETRY: 0,
|
|
14
14
|
INTERVAL: 1,
|
|
15
15
|
DEFAULT: 2,
|
|
16
16
|
ACTION: 3,
|
|
17
17
|
};
|
|
18
|
-
function isActionWakeReason(reason) {
|
|
19
|
-
return reason === "manual" || reason === "exec-event" || reason.startsWith(HOOK_REASON_PREFIX);
|
|
20
|
-
}
|
|
21
18
|
function resolveReasonPriority(reason) {
|
|
22
|
-
|
|
19
|
+
const kind = resolveHeartbeatReasonKind(reason);
|
|
20
|
+
if (kind === "retry") {
|
|
23
21
|
return REASON_PRIORITY.RETRY;
|
|
24
22
|
}
|
|
25
|
-
if (
|
|
23
|
+
if (kind === "interval") {
|
|
26
24
|
return REASON_PRIORITY.INTERVAL;
|
|
27
25
|
}
|
|
28
|
-
if (
|
|
26
|
+
if (isHeartbeatActionWakeReason(reason)) {
|
|
29
27
|
return REASON_PRIORITY.ACTION;
|
|
30
28
|
}
|
|
31
29
|
return REASON_PRIORITY.DEFAULT;
|
|
32
30
|
}
|
|
33
31
|
function normalizeWakeReason(reason) {
|
|
34
|
-
|
|
35
|
-
return "requested";
|
|
36
|
-
}
|
|
37
|
-
const trimmed = reason.trim();
|
|
38
|
-
return trimmed.length > 0 ? trimmed : "requested";
|
|
32
|
+
return normalizeHeartbeatWakeReason(reason);
|
|
39
33
|
}
|
|
40
34
|
function normalizeWakeTarget(value) {
|
|
41
35
|
const trimmed = typeof value === "string" ? value.trim() : "";
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"blockedKeys": [
|
|
3
|
+
"NODE_OPTIONS",
|
|
4
|
+
"NODE_PATH",
|
|
5
|
+
"PYTHONHOME",
|
|
6
|
+
"PYTHONPATH",
|
|
7
|
+
"PERL5LIB",
|
|
8
|
+
"PERL5OPT",
|
|
9
|
+
"RUBYLIB",
|
|
10
|
+
"RUBYOPT",
|
|
11
|
+
"BASH_ENV",
|
|
12
|
+
"ENV",
|
|
13
|
+
"SHELL",
|
|
14
|
+
"GCONV_PATH",
|
|
15
|
+
"IFS",
|
|
16
|
+
"SSLKEYLOGFILE"
|
|
17
|
+
],
|
|
18
|
+
"blockedPrefixes": ["DYLD_", "LD_", "BASH_FUNC_"]
|
|
19
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import HOST_ENV_SECURITY_POLICY_JSON from "./host-env-security-policy.json" with { type: "json" };
|
|
2
|
+
const PORTABLE_ENV_VAR_KEY = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
3
|
+
const HOST_ENV_SECURITY_POLICY = HOST_ENV_SECURITY_POLICY_JSON;
|
|
4
|
+
export const HOST_DANGEROUS_ENV_KEY_VALUES = Object.freeze(HOST_ENV_SECURITY_POLICY.blockedKeys.map((key) => key.toUpperCase()));
|
|
5
|
+
export const HOST_DANGEROUS_ENV_PREFIXES = Object.freeze(HOST_ENV_SECURITY_POLICY.blockedPrefixes.map((prefix) => prefix.toUpperCase()));
|
|
6
|
+
export const HOST_DANGEROUS_ENV_KEYS = new Set(HOST_DANGEROUS_ENV_KEY_VALUES);
|
|
7
|
+
export function normalizeEnvVarKey(rawKey, options) {
|
|
8
|
+
const key = rawKey.trim();
|
|
9
|
+
if (!key) {
|
|
10
|
+
return null;
|
|
11
|
+
}
|
|
12
|
+
if (options?.portable && !PORTABLE_ENV_VAR_KEY.test(key)) {
|
|
13
|
+
return null;
|
|
14
|
+
}
|
|
15
|
+
return key;
|
|
16
|
+
}
|
|
17
|
+
export function isDangerousHostEnvVarName(rawKey) {
|
|
18
|
+
const key = normalizeEnvVarKey(rawKey);
|
|
19
|
+
if (!key) {
|
|
20
|
+
return false;
|
|
21
|
+
}
|
|
22
|
+
const upper = key.toUpperCase();
|
|
23
|
+
if (HOST_DANGEROUS_ENV_KEYS.has(upper)) {
|
|
24
|
+
return true;
|
|
25
|
+
}
|
|
26
|
+
return HOST_DANGEROUS_ENV_PREFIXES.some((prefix) => upper.startsWith(prefix));
|
|
27
|
+
}
|
|
28
|
+
export function sanitizeHostExecEnv(params) {
|
|
29
|
+
const baseEnv = params?.baseEnv ?? process.env;
|
|
30
|
+
const overrides = params?.overrides ?? undefined;
|
|
31
|
+
const blockPathOverrides = params?.blockPathOverrides ?? true;
|
|
32
|
+
const merged = {};
|
|
33
|
+
for (const [rawKey, value] of Object.entries(baseEnv)) {
|
|
34
|
+
if (typeof value !== "string") {
|
|
35
|
+
continue;
|
|
36
|
+
}
|
|
37
|
+
const key = normalizeEnvVarKey(rawKey, { portable: true });
|
|
38
|
+
if (!key || isDangerousHostEnvVarName(key)) {
|
|
39
|
+
continue;
|
|
40
|
+
}
|
|
41
|
+
merged[key] = value;
|
|
42
|
+
}
|
|
43
|
+
if (!overrides) {
|
|
44
|
+
return merged;
|
|
45
|
+
}
|
|
46
|
+
for (const [rawKey, value] of Object.entries(overrides)) {
|
|
47
|
+
if (typeof value !== "string") {
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
const key = normalizeEnvVarKey(rawKey, { portable: true });
|
|
51
|
+
if (!key) {
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
54
|
+
const upper = key.toUpperCase();
|
|
55
|
+
// PATH is part of the security boundary (command resolution + safe-bin checks). Never allow
|
|
56
|
+
// request-scoped PATH overrides from agents/gateways.
|
|
57
|
+
if (blockPathOverrides && upper === "PATH") {
|
|
58
|
+
continue;
|
|
59
|
+
}
|
|
60
|
+
if (isDangerousHostEnvVarName(upper)) {
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
63
|
+
merged[key] = value;
|
|
64
|
+
}
|
|
65
|
+
return merged;
|
|
66
|
+
}
|