@poolzin/pool-bot 2026.2.11 → 2026.2.18
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 +34 -0
- package/dist/agents/agent-scope.js +4 -0
- package/dist/agents/announce-idempotency.js +14 -0
- package/dist/agents/auth-profiles/usage.js +22 -0
- package/dist/agents/auth-profiles.js +1 -1
- package/dist/agents/auth-profiles.resolve-auth-profile-order.fixtures.js +23 -0
- package/dist/agents/bash-tools.exec-runtime.js +438 -0
- package/dist/agents/bash-tools.shared.js +6 -0
- package/dist/agents/cli-runner/reliability.js +61 -0
- package/dist/agents/cli-watchdog-defaults.js +11 -0
- package/dist/agents/command-poll-backoff.js +63 -0
- package/dist/agents/current-time.js +16 -0
- package/dist/agents/glob-pattern.js +42 -0
- package/dist/agents/memory-search.js +33 -0
- package/dist/agents/model-alias-lines.js +18 -0
- package/dist/agents/model-auth-label.js +61 -0
- package/dist/agents/model-fallback.js +59 -8
- package/dist/agents/models-config.e2e-harness.js +115 -0
- package/dist/agents/ollama-stream.js +11 -3
- package/dist/agents/openclaw-tools.js +135 -0
- package/dist/agents/pi-auth-json.js +118 -0
- package/dist/agents/pi-embedded-runner/run.overflow-compaction.mocks.shared.js +147 -0
- package/dist/agents/pi-embedded-subscribe.e2e-harness.js +90 -0
- package/dist/agents/pi-embedded-subscribe.handlers.compaction.js +63 -0
- package/dist/agents/pi-embedded-subscribe.handlers.tools.media.test-helpers.js +30 -0
- package/dist/agents/pi-extensions/session-manager-runtime-registry.js +23 -0
- package/dist/agents/pi-tools.before-tool-call.js +145 -4
- package/dist/agents/pi-tools.js +29 -9
- package/dist/agents/pi-tools.policy.js +85 -92
- package/dist/agents/pi-tools.schema.js +54 -27
- package/dist/agents/queued-file-writer.js +22 -0
- package/dist/agents/sandbox/docker.js +133 -40
- package/dist/agents/sandbox/fs-bridge.js +146 -0
- package/dist/agents/sandbox/fs-paths.js +205 -0
- package/dist/agents/sandbox/hash.js +4 -0
- package/dist/agents/sandbox/validate-sandbox-security.js +157 -0
- package/dist/agents/sandbox-paths.js +3 -0
- package/dist/agents/sandbox-tool-policy.js +26 -0
- package/dist/agents/sanitize-for-prompt.js +18 -0
- package/dist/agents/session-dirs.js +20 -0
- package/dist/agents/session-write-lock.js +203 -39
- package/dist/agents/skills/filter.js +24 -0
- package/dist/agents/skills/tools-dir.js +9 -0
- package/dist/agents/skills-install-download.js +290 -0
- package/dist/agents/skills-install-output.js +30 -0
- package/dist/agents/skills-install.download-test-utils.js +36 -0
- package/dist/agents/skills.e2e-test-helpers.js +13 -0
- package/dist/agents/subagent-announce-queue.js +59 -15
- package/dist/agents/subagent-depth.js +137 -0
- package/dist/agents/subagent-registry.js +448 -96
- package/dist/agents/subagent-spawn.js +262 -0
- package/dist/agents/system-prompt.js +52 -10
- package/dist/agents/test-helpers/fast-tool-stubs.js +18 -0
- package/dist/agents/test-helpers/host-sandbox-fs-bridge.js +74 -0
- package/dist/agents/tool-display-common.js +782 -0
- package/dist/agents/tool-loop-detection.js +466 -0
- package/dist/agents/tool-policy.js +6 -0
- package/dist/agents/tools/image-tool.js +1 -1
- package/dist/agents/tools/sessions-access.js +178 -0
- package/dist/agents/tools/sessions-resolution.js +206 -0
- package/dist/agents/tools/subagents-tool.js +616 -0
- package/dist/agents/workspace-dir.js +18 -0
- package/dist/agents/workspace-dirs.js +14 -0
- package/dist/agents/workspace.js +70 -0
- package/dist/auto-reply/heartbeat-reply-payload.js +18 -0
- package/dist/auto-reply/reply/commands-export-session.js +163 -0
- package/dist/auto-reply/reply/commands-mesh.js +245 -0
- package/dist/auto-reply/reply/commands-setunset.js +28 -0
- package/dist/auto-reply/reply/commands-slash-parse.js +31 -0
- package/dist/auto-reply/reply/commands-system-prompt.js +117 -0
- package/dist/auto-reply/reply/directive-handling.levels.js +17 -0
- package/dist/auto-reply/reply/directive-handling.params.js +1 -0
- package/dist/auto-reply/reply/directive-parsing.js +36 -0
- package/dist/auto-reply/reply/dispatcher-registry.js +43 -0
- package/dist/auto-reply/reply/elevated-unavailable.js +20 -0
- package/dist/auto-reply/reply/post-compaction-audit.js +96 -0
- package/dist/auto-reply/reply/post-compaction-context.js +98 -0
- package/dist/auto-reply/reply/reply-delivery.js +92 -0
- package/dist/auto-reply/reply/session-reset-prompt.js +1 -0
- package/dist/auto-reply/reply/session-run-accounting.js +33 -0
- package/dist/auto-reply/reply.directive.directive-behavior.e2e-harness.js +115 -0
- package/dist/auto-reply/reply.directive.directive-behavior.e2e-mocks.js +12 -0
- package/dist/browser/bridge-auth-registry.js +26 -0
- package/dist/browser/client-actions-url.js +10 -0
- package/dist/browser/control-auth.js +73 -0
- package/dist/browser/csrf.js +64 -0
- package/dist/browser/http-auth.js +52 -0
- package/dist/browser/paths.js +37 -0
- package/dist/browser/proxy-files.js +32 -0
- package/dist/browser/pw-ai-state.js +7 -0
- package/dist/browser/resolved-config-refresh.js +42 -0
- package/dist/browser/routes/path-output.js +1 -0
- package/dist/browser/server-context.chrome-test-harness.js +20 -0
- package/dist/browser/server-middleware.js +31 -0
- package/dist/browser/test-port.js +16 -0
- package/dist/build-info.json +3 -3
- package/dist/canvas-host/file-resolver.js +43 -0
- package/dist/channels/account-summary.js +19 -0
- package/dist/channels/draft-stream-loop.js +77 -0
- package/dist/channels/plugins/account-helpers.js +26 -0
- package/dist/channels/telegram/allow-from.js +10 -0
- package/dist/cli/browser-cli-resize.js +22 -0
- package/dist/cli/browser-cli-shared.js +8 -0
- package/dist/cli/clawbot-cli.js +5 -0
- package/dist/cli/completion-cli.js +566 -0
- package/dist/cli/config-cli.js +63 -5
- package/dist/cli/daemon-cli/lifecycle-core.js +256 -0
- package/dist/cli/daemon-cli/register-service-commands.js +60 -0
- package/dist/cli/daemon-cli-compat.js +80 -0
- package/dist/cli/nodes-cli/pairing-render.js +26 -0
- package/dist/cli/program/action-reparse.js +17 -0
- package/dist/cli/program/command-registry.js +17 -0
- package/dist/cli/program/program-context.js +8 -0
- package/dist/cli/program/register.subclis.js +7 -0
- package/dist/cli/program/routes.js +233 -0
- package/dist/cli/qr-cli.js +132 -0
- package/dist/cli/requirements-test-fixtures.js +17 -0
- package/dist/cli/respawn-policy.js +4 -0
- package/dist/cli/shared/parse-port.js +18 -0
- package/dist/cli/skills-cli.format.js +241 -0
- package/dist/cli/update-cli/progress.js +121 -0
- package/dist/cli/update-cli/restart-helper.js +108 -0
- package/dist/cli/update-cli/shared.js +196 -0
- package/dist/cli/update-cli/status.js +97 -0
- package/dist/cli/update-cli/suppress-deprecations.js +17 -0
- package/dist/cli/update-cli/update-command.js +506 -0
- package/dist/cli/update-cli/wizard.js +130 -0
- package/dist/cli/update-cli.js +3 -9
- package/dist/cli/windows-argv.js +69 -0
- package/dist/commands/auth-choice-legacy.js +20 -0
- package/dist/commands/auth-choice.apply-helpers.js +8 -0
- package/dist/commands/channel-test-helpers.js +19 -0
- package/dist/commands/cleanup-plan.js +10 -0
- package/dist/commands/cleanup-utils.js +7 -0
- package/dist/commands/config-validation.js +15 -0
- package/dist/commands/doctor-completion.js +112 -0
- package/dist/commands/doctor-memory-search.js +119 -0
- package/dist/commands/doctor-session-locks.js +73 -0
- package/dist/commands/doctor.e2e-harness.js +364 -0
- package/dist/commands/gateway-presence.js +19 -0
- package/dist/commands/model-default.js +35 -0
- package/dist/commands/models/fallbacks-shared.js +102 -0
- package/dist/commands/models/shared.js +24 -0
- package/dist/commands/onboard-auth.config-gateways.js +64 -0
- package/dist/commands/onboard-auth.config-litellm.js +45 -0
- package/dist/commands/onboard-auth.config-shared.js +116 -0
- package/dist/commands/onboard-config.js +16 -0
- package/dist/commands/onboard-non-interactive.test-helpers.js +31 -0
- package/dist/commands/onboard-provider-auth-flags.js +136 -0
- package/dist/commands/openai-codex-oauth.js +40 -0
- package/dist/commands/test-runtime-config-helpers.js +21 -0
- package/dist/commands/test-wizard-helpers.js +68 -0
- package/dist/commands/vllm-setup.js +66 -0
- package/dist/compat/legacy-names.js +2 -0
- package/dist/config/backup-rotation.js +19 -0
- package/dist/config/env-preserve.js +122 -0
- package/dist/config/includes-scan.js +78 -0
- package/dist/config/plugins-allowlist.js +13 -0
- package/dist/config/schema.help.js +256 -0
- package/dist/config/schema.hints.js +189 -0
- package/dist/config/schema.irc.js +20 -0
- package/dist/config/schema.labels.js +317 -0
- package/dist/config/sessions/delivery-info.js +40 -0
- package/dist/config/types.irc.js +1 -0
- package/dist/config/zod-schema.agent-defaults.js +14 -0
- package/dist/config/zod-schema.agent-model.js +10 -0
- package/dist/config/zod-schema.agent-runtime.js +14 -0
- package/dist/config/zod-schema.allowdeny.js +35 -0
- package/dist/config/zod-schema.sensitive.js +4 -0
- package/dist/control-ui/assets/index-HRr1grwl.js.map +1 -1
- package/dist/cron/isolated-agent/skills-snapshot.js +26 -0
- package/dist/cron/isolated-agent/subagent-followup.js +127 -0
- package/dist/cron/isolated-agent.mocks.js +12 -0
- package/dist/cron/isolated-agent.test-setup.js +22 -0
- package/dist/cron/legacy-delivery.js +43 -0
- package/dist/cron/webhook-url.js +22 -0
- package/dist/daemon/arg-split.js +40 -0
- package/dist/daemon/exec-file.js +23 -0
- package/dist/daemon/output.js +6 -0
- package/dist/daemon/runtime-format.js +31 -0
- package/dist/daemon/schtasks-exec.js +4 -0
- package/dist/daemon/service-audit.js +22 -0
- package/dist/discord/client.js +41 -0
- package/dist/discord/components-registry.js +57 -0
- package/dist/discord/components.js +816 -0
- package/dist/discord/guilds.js +12 -0
- package/dist/discord/monitor/gateway-plugin.js +48 -0
- package/dist/discord/monitor/presence.js +30 -0
- package/dist/discord/send.components.js +115 -0
- package/dist/discord/send.shared.js +4 -0
- package/dist/discord/ui.js +26 -0
- package/dist/discord/voice-message.js +254 -0
- package/dist/gateway/agent-event-assistant-text.js +5 -0
- package/dist/gateway/agent-prompt.js +33 -0
- package/dist/gateway/auth-rate-limit.js +136 -0
- package/dist/gateway/channel-health-monitor.js +114 -0
- package/dist/gateway/control-ui-contract.js +1 -0
- package/dist/gateway/control-ui-csp.js +15 -0
- package/dist/gateway/gateway-config-prompts.shared.js +25 -0
- package/dist/gateway/http-auth-helpers.js +18 -0
- package/dist/gateway/http-common.js +18 -0
- package/dist/gateway/http-endpoint-helpers.js +27 -0
- package/dist/gateway/node-invoke-sanitize.js +11 -0
- package/dist/gateway/node-invoke-system-run-approval.js +205 -0
- package/dist/gateway/probe-auth.js +21 -0
- package/dist/gateway/protocol/index.js +7 -2
- package/dist/gateway/protocol/schema/mesh.js +54 -0
- package/dist/gateway/protocol/schema/protocol-schemas.js +7 -0
- package/dist/gateway/protocol/schema.js +1 -0
- package/dist/gateway/server/ws-connection/auth-messages.js +54 -0
- package/dist/gateway/server-channels.js +11 -0
- package/dist/gateway/server-methods/attachment-normalize.js +16 -0
- package/dist/gateway/server-methods/base-hash.js +8 -0
- package/dist/gateway/server-methods/mesh.js +700 -0
- package/dist/gateway/server-methods/nodes.handlers.invoke-result.js +55 -0
- package/dist/gateway/server-methods/restart-request.js +13 -0
- package/dist/gateway/server-methods/validation.js +8 -0
- package/dist/gateway/server.agent.gateway-server-agent.mocks.js +35 -0
- package/dist/gateway/server.e2e-registry-helpers.js +1 -0
- package/dist/gateway/server.e2e-ws-harness.js +20 -0
- package/dist/gateway/test-helpers.js +2 -0
- package/dist/gateway/test-helpers.server.js +3 -1
- package/dist/gateway/test-http-response.js +12 -0
- package/dist/gateway/test-openai-responses-model.js +20 -0
- package/dist/gateway/test-temp-config.js +30 -0
- package/dist/gateway/test-with-server.js +32 -0
- package/dist/hooks/bundled/bootstrap-extra-files/handler.js +46 -0
- package/dist/imessage/monitor/abort-handler.js +23 -0
- package/dist/imessage/monitor/inbound-processing.js +346 -0
- package/dist/imessage/monitor/parse-notification.js +64 -0
- package/dist/imessage/target-parsing-helpers.js +92 -0
- package/dist/infra/archive.js +244 -20
- package/dist/infra/detect-package-manager.js +26 -0
- package/dist/infra/exec-approvals-allowlist.js +257 -0
- package/dist/infra/exec-approvals-analysis.js +770 -0
- package/dist/infra/exec-approvals.js +13 -0
- package/dist/infra/file-lock.js +1 -0
- package/dist/infra/gemini-auth.js +39 -0
- package/dist/infra/heartbeat-active-hours.js +85 -0
- package/dist/infra/heartbeat-events-filter.js +50 -0
- package/dist/infra/heartbeat-runner.test-utils.js +39 -0
- package/dist/infra/http-body.js +265 -0
- package/dist/infra/install-package-dir.js +50 -0
- package/dist/infra/install-safe-path.js +49 -0
- package/dist/infra/json-files.js +49 -0
- package/dist/infra/jsonl-socket.js +52 -0
- package/dist/infra/map-size.js +14 -0
- package/dist/infra/net/hostname.js +7 -0
- package/dist/infra/npm-registry-spec.js +39 -0
- package/dist/infra/openclaw-root.js +109 -0
- package/dist/infra/outbound/delivery-queue.js +214 -0
- package/dist/infra/outbound/identity.js +23 -0
- package/dist/infra/outbound/message-action-params.js +307 -0
- package/dist/infra/outbound/tool-payload.js +21 -0
- package/dist/infra/package-json.js +23 -0
- package/dist/infra/pairing-files.js +19 -0
- package/dist/infra/pairing-token.js +9 -0
- package/dist/infra/path-prepend.js +51 -0
- package/dist/infra/path-safety.js +16 -0
- package/dist/infra/process-respawn.js +49 -0
- package/dist/infra/runtime-status.js +16 -0
- package/dist/infra/session-cost-usage.types.js +1 -0
- package/dist/infra/session-maintenance-warning.js +89 -0
- package/dist/infra/system-run-command.js +78 -0
- package/dist/infra/tmp-openclaw-dir.js +81 -0
- package/dist/infra/tmp-poolbot-dir.js +2 -0
- package/dist/infra/update-channels.js +19 -0
- package/dist/line/actions.js +45 -0
- package/dist/line/channel-access-token.js +9 -0
- package/dist/line/flex-templates/basic-cards.js +332 -0
- package/dist/line/flex-templates/common.js +18 -0
- package/dist/line/flex-templates/media-control-cards.js +453 -0
- package/dist/line/flex-templates/message.js +10 -0
- package/dist/line/flex-templates/schedule-cards.js +399 -0
- package/dist/line/flex-templates/types.js +1 -0
- package/dist/line/webhook-node.js +100 -0
- package/dist/line/webhook-utils.js +11 -0
- package/dist/logging/diagnostic-session-state.js +73 -0
- package/dist/logging/diagnostic.js +22 -0
- package/dist/logging/timestamps.js +14 -0
- package/dist/markdown/whatsapp.js +62 -0
- package/dist/media/base64.js +34 -0
- package/dist/media/local-roots.js +32 -0
- package/dist/media/outbound-attachment.js +10 -0
- package/dist/media/read-response-with-limit.js +41 -0
- package/dist/media/sniff-mime-from-base64.js +19 -0
- package/dist/media-understanding/audio-preflight.js +67 -0
- package/dist/media-understanding/fs.js +13 -0
- package/dist/media-understanding/output-extract.js +26 -0
- package/dist/media-understanding/providers/audio.test-helpers.js +34 -0
- package/dist/media-understanding/providers/google/inline-data.js +64 -0
- package/dist/media-understanding/providers/shared.js +7 -0
- package/dist/media-understanding/runner.entries.js +459 -0
- package/dist/memory/batch-error-utils.js +11 -0
- package/dist/memory/batch-http.js +27 -0
- package/dist/memory/batch-output.js +29 -0
- package/dist/memory/batch-runner.js +22 -0
- package/dist/memory/batch-upload.js +23 -0
- package/dist/memory/batch-utils.js +26 -0
- package/dist/memory/embeddings-debug.js +11 -0
- package/dist/memory/embeddings-remote-client.js +22 -0
- package/dist/memory/embeddings-remote-fetch.js +14 -0
- package/dist/memory/embeddings.js +36 -9
- package/dist/memory/hybrid.js +24 -5
- package/dist/memory/manager-embedding-ops.js +616 -0
- package/dist/memory/manager-sync-ops.js +953 -0
- package/dist/memory/manager.js +76 -28
- package/dist/memory/mmr.js +164 -0
- package/dist/memory/qmd-manager.js +1061 -0
- package/dist/memory/qmd-query-parser.js +107 -0
- package/dist/memory/qmd-scope.js +93 -0
- package/dist/memory/query-expansion.js +331 -0
- package/dist/memory/search-manager.js +0 -1
- package/dist/memory/sync-index.js +21 -0
- package/dist/memory/sync-progress.js +22 -0
- package/dist/memory/sync-stale.js +30 -0
- package/dist/memory/temporal-decay.js +119 -0
- package/dist/memory/test-embeddings-mock.js +16 -0
- package/dist/memory/test-manager-helpers.js +14 -0
- package/dist/memory/test-runtime-mocks.js +11 -0
- package/dist/node-host/invoke-browser.js +177 -0
- package/dist/node-host/invoke.js +685 -0
- package/dist/pairing/setup-code.js +285 -0
- package/dist/plugin-sdk/account-id.js +1 -0
- package/dist/plugin-sdk/agent-media-payload.js +13 -0
- package/dist/plugin-sdk/allow-from.js +47 -0
- package/dist/plugin-sdk/command-auth.js +23 -0
- package/dist/plugin-sdk/config-paths.js +9 -0
- package/dist/plugin-sdk/file-lock.js +116 -0
- package/dist/plugin-sdk/json-store.js +31 -0
- package/dist/plugin-sdk/onboarding.js +28 -0
- package/dist/plugin-sdk/provider-auth-result.js +29 -0
- package/dist/plugin-sdk/slack-message-actions.js +133 -0
- package/dist/plugin-sdk/status-helpers.js +35 -0
- package/dist/plugin-sdk/text-chunking.js +31 -0
- package/dist/plugin-sdk/tool-send.js +12 -0
- package/dist/plugin-sdk/webhook-path.js +27 -0
- package/dist/plugin-sdk/webhook-targets.js +34 -0
- package/dist/plugins/hooks.test-helpers.js +21 -0
- package/dist/plugins/uninstall.js +171 -0
- package/dist/process/kill-tree.js +98 -0
- package/dist/process/supervisor/adapters/child.js +143 -0
- package/dist/process/supervisor/adapters/env.js +13 -0
- package/dist/process/supervisor/adapters/pty.js +148 -0
- package/dist/process/supervisor/index.js +10 -0
- package/dist/process/supervisor/registry.js +117 -0
- package/dist/process/supervisor/supervisor.js +244 -0
- package/dist/process/supervisor/types.js +1 -0
- package/dist/providers/google-shared.test-helpers.js +75 -0
- package/dist/security/audit-channel.js +419 -0
- package/dist/security/audit-tool-policy.js +1 -0
- package/dist/security/scan-paths.js +12 -0
- package/dist/sessions/input-provenance.js +55 -0
- package/dist/sessions/session-key-utils.js +7 -0
- package/dist/shared/chat-content.js +31 -0
- package/dist/shared/chat-envelope.js +45 -0
- package/dist/shared/config-eval.js +117 -0
- package/dist/shared/device-auth.js +16 -0
- package/dist/shared/entry-metadata.js +9 -0
- package/dist/shared/entry-status.js +25 -0
- package/dist/shared/frontmatter.js +98 -0
- package/dist/shared/model-param-b.js +19 -0
- package/dist/shared/net/ipv4.js +17 -0
- package/dist/shared/node-match.js +53 -0
- package/dist/shared/pid-alive.js +12 -0
- package/dist/shared/process-scoped-map.js +10 -0
- package/dist/shared/requirements.js +128 -0
- package/dist/shared/subagents-format.js +84 -0
- package/dist/shared/usage-aggregates.js +28 -0
- package/dist/signal/monitor/mentions.js +45 -0
- package/dist/signal/rpc-context.js +19 -0
- package/dist/slack/blocks-fallback.js +76 -0
- package/dist/slack/blocks-input.js +40 -0
- package/dist/slack/draft-stream.js +106 -0
- package/dist/slack/message-actions.js +51 -0
- package/dist/slack/modal-metadata.js +32 -0
- package/dist/slack/monitor/events/interactions.js +462 -0
- package/dist/slack/monitor/room-context.js +17 -0
- package/dist/slack/stream-mode.js +41 -0
- package/dist/telegram/bot-native-command-menu.js +64 -0
- package/dist/telegram/bot.media.e2e-harness.js +81 -0
- package/dist/telegram/button-types.js +1 -0
- package/dist/telegram/group-access.js +65 -0
- package/dist/telegram/outbound-params.js +21 -0
- package/dist/telegram/poll-vote-cache.js +21 -0
- package/dist/terminal/health-style.js +36 -0
- package/dist/test-utils/chunk-test-helpers.js +21 -0
- package/dist/test-utils/env.js +72 -0
- package/dist/test-utils/exec-assertions.js +12 -0
- package/dist/test-utils/imessage-test-plugin.js +54 -0
- package/dist/test-utils/mock-http-response.js +17 -0
- package/dist/test-utils/vitest-mock-fn.js +1 -0
- package/dist/tts/tts-core.js +550 -0
- package/dist/utils/chunk-items.js +10 -0
- package/dist/utils/reaction-level.js +52 -0
- package/dist/utils/safe-json.js +22 -0
- package/dist/utils/with-timeout.js +14 -0
- package/dist/web/media.js +17 -5
- package/dist/whatsapp/resolve-outbound-target.js +42 -0
- package/dist/wizard/onboarding.completion.js +74 -0
- package/extensions/bluebubbles/package.json +1 -1
- package/extensions/bluebubbles/src/account-resolve.ts +29 -0
- package/extensions/bluebubbles/src/monitor-normalize.ts +796 -0
- package/extensions/bluebubbles/src/monitor-processing.ts +1007 -0
- package/extensions/bluebubbles/src/monitor-reply-cache.ts +185 -0
- package/extensions/bluebubbles/src/monitor-shared.ts +51 -0
- package/extensions/bluebubbles/src/multipart.ts +32 -0
- package/extensions/bluebubbles/src/send-helpers.ts +53 -0
- package/extensions/bluebubbles/src/test-harness.ts +50 -0
- package/extensions/bluebubbles/src/test-mocks.ts +11 -0
- package/extensions/copilot-proxy/package.json +1 -1
- package/extensions/device-pair/index.ts +554 -0
- package/extensions/diagnostics-otel/package.json +1 -1
- package/extensions/discord/package.json +1 -1
- package/extensions/discord/src/channel.js +366 -0
- package/extensions/discord/src/runtime.js +10 -0
- package/extensions/feishu/index.ts +63 -0
- package/extensions/feishu/src/accounts.ts +114 -0
- package/extensions/feishu/src/bitable.ts +739 -0
- package/extensions/feishu/src/bot.ts +965 -0
- package/extensions/feishu/src/channel.ts +351 -0
- package/extensions/feishu/src/client.ts +118 -0
- package/extensions/feishu/src/config-schema.ts +206 -0
- package/extensions/feishu/src/dedup.ts +33 -0
- package/extensions/feishu/src/directory.ts +177 -0
- package/extensions/feishu/src/doc-schema.ts +47 -0
- package/extensions/feishu/src/docx.ts +536 -0
- package/extensions/feishu/src/drive-schema.ts +46 -0
- package/extensions/feishu/src/drive.ts +227 -0
- package/extensions/feishu/src/dynamic-agent.ts +131 -0
- package/extensions/feishu/src/media.ts +449 -0
- package/extensions/feishu/src/mention.ts +126 -0
- package/extensions/feishu/src/monitor.ts +330 -0
- package/extensions/feishu/src/onboarding.ts +359 -0
- package/extensions/feishu/src/outbound.ts +55 -0
- package/extensions/feishu/src/perm-schema.ts +52 -0
- package/extensions/feishu/src/perm.ts +173 -0
- package/extensions/feishu/src/policy.ts +84 -0
- package/extensions/feishu/src/probe.ts +44 -0
- package/extensions/feishu/src/reactions.ts +160 -0
- package/extensions/feishu/src/reply-dispatcher.ts +239 -0
- package/extensions/feishu/src/runtime.ts +14 -0
- package/extensions/feishu/src/send-result.ts +29 -0
- package/extensions/feishu/src/send.ts +335 -0
- package/extensions/feishu/src/streaming-card.ts +223 -0
- package/extensions/feishu/src/targets.ts +78 -0
- package/extensions/feishu/src/tools-config.ts +21 -0
- package/extensions/feishu/src/types.ts +81 -0
- package/extensions/feishu/src/typing.ts +80 -0
- package/extensions/feishu/src/wiki-schema.ts +55 -0
- package/extensions/feishu/src/wiki.ts +232 -0
- package/extensions/google-antigravity-auth/package.json +1 -1
- package/extensions/google-gemini-cli-auth/package.json +1 -1
- package/extensions/googlechat/package.json +1 -1
- package/extensions/imessage/package.json +1 -1
- package/extensions/imessage/src/channel.js +253 -0
- package/extensions/imessage/src/runtime.js +10 -0
- package/extensions/irc/index.ts +17 -0
- package/extensions/irc/src/accounts.ts +268 -0
- package/extensions/irc/src/channel.ts +367 -0
- package/extensions/irc/src/client.ts +439 -0
- package/extensions/irc/src/config-schema.ts +97 -0
- package/extensions/irc/src/connect-options.ts +30 -0
- package/extensions/irc/src/control-chars.ts +22 -0
- package/extensions/irc/src/inbound.ts +334 -0
- package/extensions/irc/src/monitor.ts +147 -0
- package/extensions/irc/src/normalize.ts +117 -0
- package/extensions/irc/src/onboarding.ts +479 -0
- package/extensions/irc/src/policy.ts +157 -0
- package/extensions/irc/src/probe.ts +53 -0
- package/extensions/irc/src/protocol.ts +169 -0
- package/extensions/irc/src/runtime.ts +14 -0
- package/extensions/irc/src/send.ts +88 -0
- package/extensions/irc/src/types.ts +93 -0
- package/extensions/line/package.json +1 -1
- package/extensions/llm-task/package.json +1 -1
- package/extensions/lobster/package.json +1 -1
- package/extensions/matrix/CHANGELOG.md +5 -0
- package/extensions/matrix/package.json +1 -1
- package/extensions/matrix/src/matrix/client-bootstrap.ts +39 -0
- package/extensions/mattermost/package.json +1 -1
- package/extensions/mattermost/src/mattermost/monitor-onchar.ts +25 -0
- package/extensions/mattermost/src/mattermost/monitor-websocket.ts +221 -0
- package/extensions/mattermost/src/mattermost/reactions.ts +130 -0
- package/extensions/mattermost/src/mattermost/reconnect.ts +103 -0
- package/extensions/memory-core/package.json +1 -1
- package/extensions/memory-lancedb/package.json +1 -1
- package/extensions/minimax-portal-auth/index.ts +161 -0
- package/extensions/minimax-portal-auth/oauth.ts +247 -0
- package/extensions/msteams/CHANGELOG.md +5 -0
- package/extensions/msteams/package.json +1 -1
- package/extensions/msteams/src/file-lock.ts +1 -0
- package/extensions/msteams/src/graph.ts +92 -0
- package/extensions/msteams/src/mentions.ts +114 -0
- package/extensions/msteams/src/test-runtime.ts +16 -0
- package/extensions/nextcloud-talk/package.json +1 -1
- package/extensions/nostr/CHANGELOG.md +5 -0
- package/extensions/nostr/package.json +1 -1
- package/extensions/open-prose/package.json +1 -1
- package/extensions/openai-codex-auth/index.ts +177 -0
- package/extensions/phone-control/index.ts +421 -0
- package/extensions/shared/resolve-target-test-helpers.ts +66 -0
- package/extensions/signal/package.json +1 -1
- package/extensions/signal/src/channel.js +273 -0
- package/extensions/signal/src/runtime.js +10 -0
- package/extensions/slack/package.json +1 -1
- package/extensions/slack/src/channel.js +489 -0
- package/extensions/slack/src/runtime.js +10 -0
- package/extensions/talk-voice/index.ts +150 -0
- package/extensions/telegram/package.json +1 -1
- package/extensions/telegram/src/channel.js +424 -0
- package/extensions/telegram/src/runtime.js +10 -0
- package/extensions/thread-ownership/index.ts +133 -0
- package/extensions/tlon/package.json +1 -1
- package/extensions/tlon/src/account-fields.ts +25 -0
- package/extensions/tlon/src/urbit/base-url.ts +57 -0
- package/extensions/tlon/src/urbit/channel-client.ts +157 -0
- package/extensions/tlon/src/urbit/channel-ops.ts +164 -0
- package/extensions/tlon/src/urbit/context.ts +47 -0
- package/extensions/tlon/src/urbit/errors.ts +51 -0
- package/extensions/tlon/src/urbit/fetch.ts +39 -0
- package/extensions/twitch/CHANGELOG.md +5 -0
- package/extensions/twitch/package.json +1 -1
- package/extensions/twitch/src/test-fixtures.ts +30 -0
- package/extensions/voice-call/CHANGELOG.md +5 -0
- package/extensions/voice-call/package.json +1 -1
- package/extensions/voice-call/src/allowlist.ts +19 -0
- package/extensions/whatsapp/package.json +1 -1
- package/extensions/whatsapp/src/channel.js +429 -0
- package/extensions/whatsapp/src/runtime.js +10 -0
- package/extensions/zalo/CHANGELOG.md +5 -0
- package/extensions/zalo/package.json +1 -1
- package/extensions/zalouser/CHANGELOG.md +5 -0
- package/extensions/zalouser/package.json +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,37 @@
|
|
|
1
|
+
## v2026.2.18 (2026-02-17)
|
|
2
|
+
|
|
3
|
+
### Features
|
|
4
|
+
- Upstream bulk port — 394 new production files + 52 modified files aligned with upstream:
|
|
5
|
+
- **Archive security hardening:** path traversal guards, symlink/hardlink blocking, entry count + byte budget limits, `preservePaths: false` + `strict: true` for tar extraction
|
|
6
|
+
- **Agent workspace:** `loadExtraBootstrapFiles()` with full security (path traversal guards, symlink resolution, basename allowlist)
|
|
7
|
+
- **Gateway channels:** `ChannelManager` restart tracking with `restartAttempts` map, `manuallyStopped` set, exponential backoff
|
|
8
|
+
- **Config CLI:** `runConfigGet`/`runConfigUnset` now accept injectable `RuntimeEnv`; `runConfigUnset` uses `snapshot.resolved` with `structuredClone` to prevent runtime defaults leaking into config file
|
|
9
|
+
- **Gateway auth:** rate limiting support (`rateLimited`, `retryAfterMs`), `"none" | "trusted-proxy"` auth modes
|
|
10
|
+
- **Mesh networking:** protocol schemas, validators, and server methods for mesh gateway federation
|
|
11
|
+
- **Subagent registry:** complete rewrite with announcement queue
|
|
12
|
+
- **Memory:** QMD search mode fallback, hybrid search backend config
|
|
13
|
+
- **Exec approvals:** normalized path signature for approval checks
|
|
14
|
+
- Plus 375+ new source files covering agents, CLI, config, cron, daemon, gateway, hooks, infra, media, routing, and more
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## v2026.2.17 (2026-02-17)
|
|
19
|
+
|
|
20
|
+
### Features
|
|
21
|
+
- Upstream gap port — comprehensive security, memory, and agent tooling update:
|
|
22
|
+
- **Security:** path traversal guards, sandbox security validation, prompt literal sanitization, PID-based process liveness checks
|
|
23
|
+
- **Tool loop detection:** configurable detector with cooldown, warning injection, and diagnostic logging to prevent runaway tool-call loops
|
|
24
|
+
- **Memory search:** MMR (maximal marginal relevance) re-ranking, temporal decay scoring, query expansion — all configurable via `mmr` and `temporalDecay` search options
|
|
25
|
+
- **Hybrid search:** async merge with MMR diversity + temporal recency scoring
|
|
26
|
+
- **Embeddings:** graceful FTS-only fallback when all embedding providers are unavailable
|
|
27
|
+
- **Model fallback:** probe-during-cooldown logic — automatically tests primary model recovery without waiting for full cooldown expiry
|
|
28
|
+
- **Session write lock:** rewritten with PID liveness checks, watchdog timer, and stale lock cleanup
|
|
29
|
+
- **System prompt:** `llms.txt` context section, sanitized workspace variables, valid context file filtering
|
|
30
|
+
- **Tool policy:** extracted glob patterns to shared module, sandbox tool policy helpers, configurable subagent spawn depth/children limits
|
|
31
|
+
- **Post-compaction:** audit and context enrichment for compacted conversation summaries
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
1
35
|
## v2026.2.11 (2026-02-16)
|
|
2
36
|
|
|
3
37
|
### Fixes
|
|
@@ -2,6 +2,7 @@ import os from "node:os";
|
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { resolveStateDir } from "../config/paths.js";
|
|
4
4
|
import { DEFAULT_AGENT_ID, normalizeAgentId, parseAgentSessionKey, } from "../routing/session-key.js";
|
|
5
|
+
import { normalizeSkillFilter } from "./skills/filter.js";
|
|
5
6
|
import { resolveUserPath } from "../utils.js";
|
|
6
7
|
import { DEFAULT_AGENT_WORKSPACE_DIR } from "./workspace.js";
|
|
7
8
|
export { resolveAgentIdFromSessionKey } from "../routing/session-key.js";
|
|
@@ -76,6 +77,9 @@ export function resolveAgentConfig(cfg, agentId) {
|
|
|
76
77
|
tools: entry.tools,
|
|
77
78
|
};
|
|
78
79
|
}
|
|
80
|
+
export function resolveAgentSkillsFilter(cfg, agentId) {
|
|
81
|
+
return normalizeSkillFilter(resolveAgentConfig(cfg, agentId)?.skills);
|
|
82
|
+
}
|
|
79
83
|
export function resolveAgentModelPrimary(cfg, agentId) {
|
|
80
84
|
const raw = resolveAgentConfig(cfg, agentId)?.model;
|
|
81
85
|
if (!raw)
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export function buildAnnounceIdFromChildRun(params) {
|
|
2
|
+
return `v1:${params.childSessionKey}:${params.childRunId}`;
|
|
3
|
+
}
|
|
4
|
+
export function buildAnnounceIdempotencyKey(announceId) {
|
|
5
|
+
return `announce:${announceId}`;
|
|
6
|
+
}
|
|
7
|
+
export function resolveQueueAnnounceId(params) {
|
|
8
|
+
const announceId = params.announceId?.trim();
|
|
9
|
+
if (announceId) {
|
|
10
|
+
return announceId;
|
|
11
|
+
}
|
|
12
|
+
// Backward-compatible fallback for queue items that predate announceId.
|
|
13
|
+
return `legacy:${params.sessionKey}:${params.enqueuedAt}`;
|
|
14
|
+
}
|
|
@@ -8,6 +8,28 @@ function resolveProfileUnusableUntil(stats) {
|
|
|
8
8
|
return null;
|
|
9
9
|
return Math.max(...values);
|
|
10
10
|
}
|
|
11
|
+
/**
|
|
12
|
+
* Returns the soonest `cooldownUntil` / `disabledUntil` timestamp across the given
|
|
13
|
+
* profiles, or `null` when no profile has a recorded cooldown. Note: the
|
|
14
|
+
* returned timestamp may be in the past if the cooldown has already expired.
|
|
15
|
+
*/
|
|
16
|
+
export function getSoonestCooldownExpiry(store, profileIds) {
|
|
17
|
+
let soonest = null;
|
|
18
|
+
for (const id of profileIds) {
|
|
19
|
+
const stats = store.usageStats?.[id];
|
|
20
|
+
if (!stats) {
|
|
21
|
+
continue;
|
|
22
|
+
}
|
|
23
|
+
const until = resolveProfileUnusableUntil(stats);
|
|
24
|
+
if (typeof until !== "number" || !Number.isFinite(until) || until <= 0) {
|
|
25
|
+
continue;
|
|
26
|
+
}
|
|
27
|
+
if (soonest === null || until < soonest) {
|
|
28
|
+
soonest = until;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
return soonest;
|
|
32
|
+
}
|
|
11
33
|
/**
|
|
12
34
|
* Check if a profile is currently in cooldown (due to rate limiting or errors).
|
|
13
35
|
*/
|
|
@@ -7,4 +7,4 @@ export { resolveAuthStorePathForDisplay } from "./auth-profiles/paths.js";
|
|
|
7
7
|
export { listProfilesForProvider, markAuthProfileGood, setAuthProfileOrder, upsertAuthProfile, upsertAuthProfileWithLock, } from "./auth-profiles/profiles.js";
|
|
8
8
|
export { repairOAuthProfileIdMismatch, suggestOAuthProfileIdForLegacyDefault, } from "./auth-profiles/repair.js";
|
|
9
9
|
export { ensureAuthProfileStore, loadAuthProfileStore, saveAuthProfileStore, } from "./auth-profiles/store.js";
|
|
10
|
-
export { calculateAuthProfileCooldownMs, clearAuthProfileCooldown, isProfileInCooldown, markAuthProfileCooldown, markAuthProfileFailure, markAuthProfileUsed, resolveProfileUnusableUntilForDisplay, } from "./auth-profiles/usage.js";
|
|
10
|
+
export { calculateAuthProfileCooldownMs, clearAuthProfileCooldown, getSoonestCooldownExpiry, isProfileInCooldown, markAuthProfileCooldown, markAuthProfileFailure, markAuthProfileUsed, resolveProfileUnusableUntilForDisplay, } from "./auth-profiles/usage.js";
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export const ANTHROPIC_STORE = {
|
|
2
|
+
version: 1,
|
|
3
|
+
profiles: {
|
|
4
|
+
"anthropic:default": {
|
|
5
|
+
type: "api_key",
|
|
6
|
+
provider: "anthropic",
|
|
7
|
+
key: "sk-default",
|
|
8
|
+
},
|
|
9
|
+
"anthropic:work": {
|
|
10
|
+
type: "api_key",
|
|
11
|
+
provider: "anthropic",
|
|
12
|
+
key: "sk-work",
|
|
13
|
+
},
|
|
14
|
+
},
|
|
15
|
+
};
|
|
16
|
+
export const ANTHROPIC_CFG = {
|
|
17
|
+
auth: {
|
|
18
|
+
profiles: {
|
|
19
|
+
"anthropic:default": { provider: "anthropic", mode: "api_key" },
|
|
20
|
+
"anthropic:work": { provider: "anthropic", mode: "api_key" },
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
};
|
|
@@ -0,0 +1,438 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import { Type } from "@sinclair/typebox";
|
|
3
|
+
import { requestHeartbeatNow } from "../infra/heartbeat-wake.js";
|
|
4
|
+
import { mergePathPrepend } from "../infra/path-prepend.js";
|
|
5
|
+
import { enqueueSystemEvent } from "../infra/system-events.js";
|
|
6
|
+
export { applyPathPrepend, normalizePathPrepend } from "../infra/path-prepend.js";
|
|
7
|
+
import { logWarn } from "../logger.js";
|
|
8
|
+
import { getProcessSupervisor } from "../process/supervisor/index.js";
|
|
9
|
+
import { addSession, appendOutput, createSessionSlug, markExited, tail, } from "./bash-process-registry.js";
|
|
10
|
+
import { buildDockerExecArgs, chunkString, clampWithDefault, readEnvInt, } from "./bash-tools.shared.js";
|
|
11
|
+
import { buildCursorPositionResponse, stripDsrRequests } from "./pty-dsr.js";
|
|
12
|
+
import { getShellConfig, sanitizeBinaryOutput } from "./shell-utils.js";
|
|
13
|
+
// Security: Blocklist of environment variables that could alter execution flow
|
|
14
|
+
// or inject code when running on non-sandboxed hosts (Gateway/Node).
|
|
15
|
+
const DANGEROUS_HOST_ENV_VARS = new Set([
|
|
16
|
+
"LD_PRELOAD",
|
|
17
|
+
"LD_LIBRARY_PATH",
|
|
18
|
+
"LD_AUDIT",
|
|
19
|
+
"DYLD_INSERT_LIBRARIES",
|
|
20
|
+
"DYLD_LIBRARY_PATH",
|
|
21
|
+
"NODE_OPTIONS",
|
|
22
|
+
"NODE_PATH",
|
|
23
|
+
"PYTHONPATH",
|
|
24
|
+
"PYTHONHOME",
|
|
25
|
+
"RUBYLIB",
|
|
26
|
+
"PERL5LIB",
|
|
27
|
+
"BASH_ENV",
|
|
28
|
+
"ENV",
|
|
29
|
+
"GCONV_PATH",
|
|
30
|
+
"IFS",
|
|
31
|
+
"SSLKEYLOGFILE",
|
|
32
|
+
]);
|
|
33
|
+
const DANGEROUS_HOST_ENV_PREFIXES = ["DYLD_", "LD_"];
|
|
34
|
+
// Centralized sanitization helper.
|
|
35
|
+
// Throws an error if dangerous variables or PATH modifications are detected on the host.
|
|
36
|
+
export function validateHostEnv(env) {
|
|
37
|
+
for (const key of Object.keys(env)) {
|
|
38
|
+
const upperKey = key.toUpperCase();
|
|
39
|
+
// 1. Block known dangerous variables (Fail Closed)
|
|
40
|
+
if (DANGEROUS_HOST_ENV_PREFIXES.some((prefix) => upperKey.startsWith(prefix))) {
|
|
41
|
+
throw new Error(`Security Violation: Environment variable '${key}' is forbidden during host execution.`);
|
|
42
|
+
}
|
|
43
|
+
if (DANGEROUS_HOST_ENV_VARS.has(upperKey)) {
|
|
44
|
+
throw new Error(`Security Violation: Environment variable '${key}' is forbidden during host execution.`);
|
|
45
|
+
}
|
|
46
|
+
// 2. Strictly block PATH modification on host
|
|
47
|
+
// Allowing custom PATH on the gateway/node can lead to binary hijacking.
|
|
48
|
+
if (upperKey === "PATH") {
|
|
49
|
+
throw new Error("Security Violation: Custom 'PATH' variable is forbidden during host execution.");
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
export const DEFAULT_MAX_OUTPUT = clampWithDefault(readEnvInt("PI_BASH_MAX_OUTPUT_CHARS"), 200_000, 1_000, 200_000);
|
|
54
|
+
export const DEFAULT_PENDING_MAX_OUTPUT = clampWithDefault(readEnvInt("POOLBOT_BASH_PENDING_MAX_OUTPUT_CHARS"), 30_000, 1_000, 200_000);
|
|
55
|
+
export const DEFAULT_PATH = process.env.PATH ?? "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin";
|
|
56
|
+
export const DEFAULT_NOTIFY_TAIL_CHARS = 400;
|
|
57
|
+
const DEFAULT_NOTIFY_SNIPPET_CHARS = 180;
|
|
58
|
+
export const DEFAULT_APPROVAL_TIMEOUT_MS = 120_000;
|
|
59
|
+
export const DEFAULT_APPROVAL_REQUEST_TIMEOUT_MS = 130_000;
|
|
60
|
+
const DEFAULT_APPROVAL_RUNNING_NOTICE_MS = 10_000;
|
|
61
|
+
const APPROVAL_SLUG_LENGTH = 8;
|
|
62
|
+
export const execSchema = Type.Object({
|
|
63
|
+
command: Type.String({ description: "Shell command to execute" }),
|
|
64
|
+
workdir: Type.Optional(Type.String({ description: "Working directory (defaults to cwd)" })),
|
|
65
|
+
env: Type.Optional(Type.Record(Type.String(), Type.String())),
|
|
66
|
+
yieldMs: Type.Optional(Type.Number({
|
|
67
|
+
description: "Milliseconds to wait before backgrounding (default 10000)",
|
|
68
|
+
})),
|
|
69
|
+
background: Type.Optional(Type.Boolean({ description: "Run in background immediately" })),
|
|
70
|
+
timeout: Type.Optional(Type.Number({
|
|
71
|
+
description: "Timeout in seconds (optional, kills process on expiry)",
|
|
72
|
+
})),
|
|
73
|
+
pty: Type.Optional(Type.Boolean({
|
|
74
|
+
description: "Run in a pseudo-terminal (PTY) when available (TTY-required CLIs, coding agents)",
|
|
75
|
+
})),
|
|
76
|
+
elevated: Type.Optional(Type.Boolean({
|
|
77
|
+
description: "Run on the host with elevated permissions (if allowed)",
|
|
78
|
+
})),
|
|
79
|
+
host: Type.Optional(Type.String({
|
|
80
|
+
description: "Exec host (sandbox|gateway|node).",
|
|
81
|
+
})),
|
|
82
|
+
security: Type.Optional(Type.String({
|
|
83
|
+
description: "Exec security mode (deny|allowlist|full).",
|
|
84
|
+
})),
|
|
85
|
+
ask: Type.Optional(Type.String({
|
|
86
|
+
description: "Exec ask mode (off|on-miss|always).",
|
|
87
|
+
})),
|
|
88
|
+
node: Type.Optional(Type.String({
|
|
89
|
+
description: "Node id/name for host=node.",
|
|
90
|
+
})),
|
|
91
|
+
});
|
|
92
|
+
export function normalizeExecHost(value) {
|
|
93
|
+
const normalized = value?.trim().toLowerCase();
|
|
94
|
+
if (normalized === "sandbox" || normalized === "gateway" || normalized === "node") {
|
|
95
|
+
return normalized;
|
|
96
|
+
}
|
|
97
|
+
return null;
|
|
98
|
+
}
|
|
99
|
+
export function normalizeExecSecurity(value) {
|
|
100
|
+
const normalized = value?.trim().toLowerCase();
|
|
101
|
+
if (normalized === "deny" || normalized === "allowlist" || normalized === "full") {
|
|
102
|
+
return normalized;
|
|
103
|
+
}
|
|
104
|
+
return null;
|
|
105
|
+
}
|
|
106
|
+
export function normalizeExecAsk(value) {
|
|
107
|
+
const normalized = value?.trim().toLowerCase();
|
|
108
|
+
if (normalized === "off" || normalized === "on-miss" || normalized === "always") {
|
|
109
|
+
return normalized;
|
|
110
|
+
}
|
|
111
|
+
return null;
|
|
112
|
+
}
|
|
113
|
+
export function renderExecHostLabel(host) {
|
|
114
|
+
return host === "sandbox" ? "sandbox" : host === "gateway" ? "gateway" : "node";
|
|
115
|
+
}
|
|
116
|
+
export function normalizeNotifyOutput(value) {
|
|
117
|
+
return value.replace(/\s+/g, " ").trim();
|
|
118
|
+
}
|
|
119
|
+
function compactNotifyOutput(value, maxChars = DEFAULT_NOTIFY_SNIPPET_CHARS) {
|
|
120
|
+
const normalized = normalizeNotifyOutput(value);
|
|
121
|
+
if (!normalized) {
|
|
122
|
+
return "";
|
|
123
|
+
}
|
|
124
|
+
if (normalized.length <= maxChars) {
|
|
125
|
+
return normalized;
|
|
126
|
+
}
|
|
127
|
+
const safe = Math.max(1, maxChars - 1);
|
|
128
|
+
return `${normalized.slice(0, safe)}…`;
|
|
129
|
+
}
|
|
130
|
+
export function applyShellPath(env, shellPath) {
|
|
131
|
+
if (!shellPath) {
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
const entries = shellPath
|
|
135
|
+
.split(path.delimiter)
|
|
136
|
+
.map((part) => part.trim())
|
|
137
|
+
.filter(Boolean);
|
|
138
|
+
if (entries.length === 0) {
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
const merged = mergePathPrepend(env.PATH, entries);
|
|
142
|
+
if (merged) {
|
|
143
|
+
env.PATH = merged;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
function maybeNotifyOnExit(session, status) {
|
|
147
|
+
if (!session.backgrounded || !session.notifyOnExit || session.exitNotified) {
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
const sessionKey = session.sessionKey?.trim();
|
|
151
|
+
if (!sessionKey) {
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
session.exitNotified = true;
|
|
155
|
+
const exitLabel = session.exitSignal
|
|
156
|
+
? `signal ${session.exitSignal}`
|
|
157
|
+
: `code ${session.exitCode ?? 0}`;
|
|
158
|
+
const output = compactNotifyOutput(tail(session.tail || session.aggregated || "", DEFAULT_NOTIFY_TAIL_CHARS));
|
|
159
|
+
if (status === "completed" && !output && session.notifyOnExitEmptySuccess !== true) {
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
const summary = output
|
|
163
|
+
? `Exec ${status} (${session.id.slice(0, 8)}, ${exitLabel}) :: ${output}`
|
|
164
|
+
: `Exec ${status} (${session.id.slice(0, 8)}, ${exitLabel})`;
|
|
165
|
+
enqueueSystemEvent(summary, { sessionKey });
|
|
166
|
+
requestHeartbeatNow({ reason: `exec:${session.id}:exit` });
|
|
167
|
+
}
|
|
168
|
+
export function createApprovalSlug(id) {
|
|
169
|
+
return id.slice(0, APPROVAL_SLUG_LENGTH);
|
|
170
|
+
}
|
|
171
|
+
export function resolveApprovalRunningNoticeMs(value) {
|
|
172
|
+
if (typeof value !== "number" || !Number.isFinite(value)) {
|
|
173
|
+
return DEFAULT_APPROVAL_RUNNING_NOTICE_MS;
|
|
174
|
+
}
|
|
175
|
+
if (value <= 0) {
|
|
176
|
+
return 0;
|
|
177
|
+
}
|
|
178
|
+
return Math.floor(value);
|
|
179
|
+
}
|
|
180
|
+
export function emitExecSystemEvent(text, opts) {
|
|
181
|
+
const sessionKey = opts.sessionKey?.trim();
|
|
182
|
+
if (!sessionKey) {
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
enqueueSystemEvent(text, { sessionKey, contextKey: opts.contextKey });
|
|
186
|
+
requestHeartbeatNow({ reason: "exec-event" });
|
|
187
|
+
}
|
|
188
|
+
export async function runExecProcess(opts) {
|
|
189
|
+
const startedAt = Date.now();
|
|
190
|
+
const sessionId = createSessionSlug();
|
|
191
|
+
const execCommand = opts.execCommand ?? opts.command;
|
|
192
|
+
const supervisor = getProcessSupervisor();
|
|
193
|
+
const session = {
|
|
194
|
+
id: sessionId,
|
|
195
|
+
command: opts.command,
|
|
196
|
+
scopeKey: opts.scopeKey,
|
|
197
|
+
sessionKey: opts.sessionKey,
|
|
198
|
+
notifyOnExit: opts.notifyOnExit,
|
|
199
|
+
notifyOnExitEmptySuccess: opts.notifyOnExitEmptySuccess === true,
|
|
200
|
+
exitNotified: false,
|
|
201
|
+
child: undefined,
|
|
202
|
+
stdin: undefined,
|
|
203
|
+
pid: undefined,
|
|
204
|
+
startedAt,
|
|
205
|
+
cwd: opts.workdir,
|
|
206
|
+
maxOutputChars: opts.maxOutput,
|
|
207
|
+
pendingMaxOutputChars: opts.pendingMaxOutput,
|
|
208
|
+
totalOutputChars: 0,
|
|
209
|
+
pendingStdout: [],
|
|
210
|
+
pendingStderr: [],
|
|
211
|
+
pendingStdoutChars: 0,
|
|
212
|
+
pendingStderrChars: 0,
|
|
213
|
+
aggregated: "",
|
|
214
|
+
tail: "",
|
|
215
|
+
exited: false,
|
|
216
|
+
exitCode: undefined,
|
|
217
|
+
exitSignal: undefined,
|
|
218
|
+
truncated: false,
|
|
219
|
+
backgrounded: false,
|
|
220
|
+
};
|
|
221
|
+
addSession(session);
|
|
222
|
+
const emitUpdate = () => {
|
|
223
|
+
if (!opts.onUpdate) {
|
|
224
|
+
return;
|
|
225
|
+
}
|
|
226
|
+
const tailText = session.tail || session.aggregated;
|
|
227
|
+
const warningText = opts.warnings.length ? `${opts.warnings.join("\n")}\n\n` : "";
|
|
228
|
+
opts.onUpdate({
|
|
229
|
+
content: [{ type: "text", text: warningText + (tailText || "") }],
|
|
230
|
+
details: {
|
|
231
|
+
status: "running",
|
|
232
|
+
sessionId,
|
|
233
|
+
pid: session.pid ?? undefined,
|
|
234
|
+
startedAt,
|
|
235
|
+
cwd: session.cwd,
|
|
236
|
+
tail: session.tail,
|
|
237
|
+
},
|
|
238
|
+
});
|
|
239
|
+
};
|
|
240
|
+
const handleStdout = (data) => {
|
|
241
|
+
const str = sanitizeBinaryOutput(data.toString());
|
|
242
|
+
for (const chunk of chunkString(str)) {
|
|
243
|
+
appendOutput(session, "stdout", chunk);
|
|
244
|
+
emitUpdate();
|
|
245
|
+
}
|
|
246
|
+
};
|
|
247
|
+
const handleStderr = (data) => {
|
|
248
|
+
const str = sanitizeBinaryOutput(data.toString());
|
|
249
|
+
for (const chunk of chunkString(str)) {
|
|
250
|
+
appendOutput(session, "stderr", chunk);
|
|
251
|
+
emitUpdate();
|
|
252
|
+
}
|
|
253
|
+
};
|
|
254
|
+
const timeoutMs = typeof opts.timeoutSec === "number" && opts.timeoutSec > 0
|
|
255
|
+
? Math.floor(opts.timeoutSec * 1000)
|
|
256
|
+
: undefined;
|
|
257
|
+
const spawnSpec = (() => {
|
|
258
|
+
if (opts.sandbox) {
|
|
259
|
+
return {
|
|
260
|
+
mode: "child",
|
|
261
|
+
argv: [
|
|
262
|
+
"docker",
|
|
263
|
+
...buildDockerExecArgs({
|
|
264
|
+
containerName: opts.sandbox.containerName,
|
|
265
|
+
command: execCommand,
|
|
266
|
+
workdir: opts.containerWorkdir ?? opts.sandbox.containerWorkdir,
|
|
267
|
+
env: opts.env,
|
|
268
|
+
tty: opts.usePty,
|
|
269
|
+
}),
|
|
270
|
+
],
|
|
271
|
+
env: process.env,
|
|
272
|
+
stdinMode: opts.usePty ? "pipe-open" : "pipe-closed",
|
|
273
|
+
};
|
|
274
|
+
}
|
|
275
|
+
const { shell, args: shellArgs } = getShellConfig();
|
|
276
|
+
const childArgv = [shell, ...shellArgs, execCommand];
|
|
277
|
+
if (opts.usePty) {
|
|
278
|
+
return {
|
|
279
|
+
mode: "pty",
|
|
280
|
+
ptyCommand: execCommand,
|
|
281
|
+
childFallbackArgv: childArgv,
|
|
282
|
+
env: opts.env,
|
|
283
|
+
stdinMode: "pipe-open",
|
|
284
|
+
};
|
|
285
|
+
}
|
|
286
|
+
return {
|
|
287
|
+
mode: "child",
|
|
288
|
+
argv: childArgv,
|
|
289
|
+
env: opts.env,
|
|
290
|
+
stdinMode: "pipe-closed",
|
|
291
|
+
};
|
|
292
|
+
})();
|
|
293
|
+
let managedRun = null;
|
|
294
|
+
let usingPty = spawnSpec.mode === "pty";
|
|
295
|
+
const cursorResponse = buildCursorPositionResponse();
|
|
296
|
+
const onSupervisorStdout = (chunk) => {
|
|
297
|
+
if (usingPty) {
|
|
298
|
+
const { cleaned, requests } = stripDsrRequests(chunk);
|
|
299
|
+
if (requests > 0 && managedRun?.stdin) {
|
|
300
|
+
for (let i = 0; i < requests; i += 1) {
|
|
301
|
+
managedRun.stdin.write(cursorResponse);
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
handleStdout(cleaned);
|
|
305
|
+
return;
|
|
306
|
+
}
|
|
307
|
+
handleStdout(chunk);
|
|
308
|
+
};
|
|
309
|
+
try {
|
|
310
|
+
const spawnBase = {
|
|
311
|
+
runId: sessionId,
|
|
312
|
+
sessionId: opts.sessionKey?.trim() || sessionId,
|
|
313
|
+
backendId: opts.sandbox ? "exec-sandbox" : "exec-host",
|
|
314
|
+
scopeKey: opts.scopeKey,
|
|
315
|
+
cwd: opts.workdir,
|
|
316
|
+
env: spawnSpec.env,
|
|
317
|
+
timeoutMs,
|
|
318
|
+
captureOutput: false,
|
|
319
|
+
onStdout: onSupervisorStdout,
|
|
320
|
+
onStderr: handleStderr,
|
|
321
|
+
};
|
|
322
|
+
managedRun =
|
|
323
|
+
spawnSpec.mode === "pty"
|
|
324
|
+
? await supervisor.spawn({
|
|
325
|
+
...spawnBase,
|
|
326
|
+
mode: "pty",
|
|
327
|
+
ptyCommand: spawnSpec.ptyCommand,
|
|
328
|
+
})
|
|
329
|
+
: await supervisor.spawn({
|
|
330
|
+
...spawnBase,
|
|
331
|
+
mode: "child",
|
|
332
|
+
argv: spawnSpec.argv,
|
|
333
|
+
stdinMode: spawnSpec.stdinMode,
|
|
334
|
+
});
|
|
335
|
+
}
|
|
336
|
+
catch (err) {
|
|
337
|
+
if (spawnSpec.mode === "pty") {
|
|
338
|
+
const warning = `Warning: PTY spawn failed (${String(err)}); retrying without PTY for \`${opts.command}\`.`;
|
|
339
|
+
logWarn(`exec: PTY spawn failed (${String(err)}); retrying without PTY for "${opts.command}".`);
|
|
340
|
+
opts.warnings.push(warning);
|
|
341
|
+
usingPty = false;
|
|
342
|
+
try {
|
|
343
|
+
managedRun = await supervisor.spawn({
|
|
344
|
+
runId: sessionId,
|
|
345
|
+
sessionId: opts.sessionKey?.trim() || sessionId,
|
|
346
|
+
backendId: "exec-host",
|
|
347
|
+
scopeKey: opts.scopeKey,
|
|
348
|
+
mode: "child",
|
|
349
|
+
argv: spawnSpec.childFallbackArgv,
|
|
350
|
+
cwd: opts.workdir,
|
|
351
|
+
env: spawnSpec.env,
|
|
352
|
+
stdinMode: "pipe-open",
|
|
353
|
+
timeoutMs,
|
|
354
|
+
captureOutput: false,
|
|
355
|
+
onStdout: handleStdout,
|
|
356
|
+
onStderr: handleStderr,
|
|
357
|
+
});
|
|
358
|
+
}
|
|
359
|
+
catch (retryErr) {
|
|
360
|
+
markExited(session, null, null, "failed");
|
|
361
|
+
maybeNotifyOnExit(session, "failed");
|
|
362
|
+
throw retryErr;
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
else {
|
|
366
|
+
markExited(session, null, null, "failed");
|
|
367
|
+
maybeNotifyOnExit(session, "failed");
|
|
368
|
+
throw err;
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
session.stdin = managedRun.stdin;
|
|
372
|
+
session.pid = managedRun.pid;
|
|
373
|
+
const promise = managedRun
|
|
374
|
+
.wait()
|
|
375
|
+
.then((exit) => {
|
|
376
|
+
const durationMs = Date.now() - startedAt;
|
|
377
|
+
const isNormalExit = exit.reason === "exit";
|
|
378
|
+
const status = isNormalExit ? "completed" : "failed";
|
|
379
|
+
markExited(session, exit.exitCode, exit.exitSignal, status);
|
|
380
|
+
maybeNotifyOnExit(session, status);
|
|
381
|
+
if (!session.child && session.stdin) {
|
|
382
|
+
session.stdin.destroyed = true;
|
|
383
|
+
}
|
|
384
|
+
const aggregated = session.aggregated.trim();
|
|
385
|
+
if (status === "completed") {
|
|
386
|
+
const exitCode = exit.exitCode ?? 0;
|
|
387
|
+
const exitMsg = exitCode !== 0 ? `\n\n(Command exited with code ${exitCode})` : "";
|
|
388
|
+
return {
|
|
389
|
+
status: "completed",
|
|
390
|
+
exitCode,
|
|
391
|
+
exitSignal: exit.exitSignal,
|
|
392
|
+
durationMs,
|
|
393
|
+
aggregated: aggregated + exitMsg,
|
|
394
|
+
timedOut: false,
|
|
395
|
+
};
|
|
396
|
+
}
|
|
397
|
+
const reason = exit.reason === "overall-timeout"
|
|
398
|
+
? `Command timed out after ${opts.timeoutSec} seconds`
|
|
399
|
+
: exit.reason === "no-output-timeout"
|
|
400
|
+
? "Command timed out waiting for output"
|
|
401
|
+
: exit.exitSignal != null
|
|
402
|
+
? `Command aborted by signal ${exit.exitSignal}`
|
|
403
|
+
: "Command aborted before exit code was captured";
|
|
404
|
+
return {
|
|
405
|
+
status: "failed",
|
|
406
|
+
exitCode: exit.exitCode,
|
|
407
|
+
exitSignal: exit.exitSignal,
|
|
408
|
+
durationMs,
|
|
409
|
+
aggregated,
|
|
410
|
+
timedOut: exit.timedOut,
|
|
411
|
+
reason: aggregated ? `${aggregated}\n\n${reason}` : reason,
|
|
412
|
+
};
|
|
413
|
+
})
|
|
414
|
+
.catch((err) => {
|
|
415
|
+
markExited(session, null, null, "failed");
|
|
416
|
+
maybeNotifyOnExit(session, "failed");
|
|
417
|
+
const aggregated = session.aggregated.trim();
|
|
418
|
+
const message = aggregated ? `${aggregated}\n\n${String(err)}` : String(err);
|
|
419
|
+
return {
|
|
420
|
+
status: "failed",
|
|
421
|
+
exitCode: null,
|
|
422
|
+
exitSignal: null,
|
|
423
|
+
durationMs: Date.now() - startedAt,
|
|
424
|
+
aggregated,
|
|
425
|
+
timedOut: false,
|
|
426
|
+
reason: message,
|
|
427
|
+
};
|
|
428
|
+
});
|
|
429
|
+
return {
|
|
430
|
+
session,
|
|
431
|
+
startedAt,
|
|
432
|
+
pid: session.pid ?? undefined,
|
|
433
|
+
promise,
|
|
434
|
+
kill: () => {
|
|
435
|
+
managedRun?.cancel("manual-cancel");
|
|
436
|
+
},
|
|
437
|
+
};
|
|
438
|
+
}
|
|
@@ -197,3 +197,9 @@ export function pad(str, width) {
|
|
|
197
197
|
return str;
|
|
198
198
|
return str + " ".repeat(width - str.length);
|
|
199
199
|
}
|
|
200
|
+
export function clampWithDefault(value, defaultValue, min, max) {
|
|
201
|
+
if (value === undefined || Number.isNaN(value)) {
|
|
202
|
+
return defaultValue;
|
|
203
|
+
}
|
|
204
|
+
return Math.min(Math.max(value, min), max);
|
|
205
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import { CLI_FRESH_WATCHDOG_DEFAULTS, CLI_RESUME_WATCHDOG_DEFAULTS, CLI_WATCHDOG_MIN_TIMEOUT_MS, } from "../cli-watchdog-defaults.js";
|
|
3
|
+
function pickWatchdogProfile(backend, useResume) {
|
|
4
|
+
const defaults = useResume ? CLI_RESUME_WATCHDOG_DEFAULTS : CLI_FRESH_WATCHDOG_DEFAULTS;
|
|
5
|
+
const configured = useResume
|
|
6
|
+
? backend.reliability?.watchdog?.resume
|
|
7
|
+
: backend.reliability?.watchdog?.fresh;
|
|
8
|
+
const ratio = (() => {
|
|
9
|
+
const value = configured?.noOutputTimeoutRatio;
|
|
10
|
+
if (typeof value !== "number" || !Number.isFinite(value)) {
|
|
11
|
+
return defaults.noOutputTimeoutRatio;
|
|
12
|
+
}
|
|
13
|
+
return Math.max(0.05, Math.min(0.95, value));
|
|
14
|
+
})();
|
|
15
|
+
const minMs = (() => {
|
|
16
|
+
const value = configured?.minMs;
|
|
17
|
+
if (typeof value !== "number" || !Number.isFinite(value)) {
|
|
18
|
+
return defaults.minMs;
|
|
19
|
+
}
|
|
20
|
+
return Math.max(CLI_WATCHDOG_MIN_TIMEOUT_MS, Math.floor(value));
|
|
21
|
+
})();
|
|
22
|
+
const maxMs = (() => {
|
|
23
|
+
const value = configured?.maxMs;
|
|
24
|
+
if (typeof value !== "number" || !Number.isFinite(value)) {
|
|
25
|
+
return defaults.maxMs;
|
|
26
|
+
}
|
|
27
|
+
return Math.max(CLI_WATCHDOG_MIN_TIMEOUT_MS, Math.floor(value));
|
|
28
|
+
})();
|
|
29
|
+
return {
|
|
30
|
+
noOutputTimeoutMs: typeof configured?.noOutputTimeoutMs === "number" &&
|
|
31
|
+
Number.isFinite(configured.noOutputTimeoutMs)
|
|
32
|
+
? Math.max(CLI_WATCHDOG_MIN_TIMEOUT_MS, Math.floor(configured.noOutputTimeoutMs))
|
|
33
|
+
: undefined,
|
|
34
|
+
noOutputTimeoutRatio: ratio,
|
|
35
|
+
minMs: Math.min(minMs, maxMs),
|
|
36
|
+
maxMs: Math.max(minMs, maxMs),
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
export function resolveCliNoOutputTimeoutMs(params) {
|
|
40
|
+
const profile = pickWatchdogProfile(params.backend, params.useResume);
|
|
41
|
+
// Keep watchdog below global timeout in normal cases.
|
|
42
|
+
const cap = Math.max(CLI_WATCHDOG_MIN_TIMEOUT_MS, params.timeoutMs - 1_000);
|
|
43
|
+
if (profile.noOutputTimeoutMs !== undefined) {
|
|
44
|
+
return Math.min(profile.noOutputTimeoutMs, cap);
|
|
45
|
+
}
|
|
46
|
+
const computed = Math.floor(params.timeoutMs * profile.noOutputTimeoutRatio);
|
|
47
|
+
const bounded = Math.min(profile.maxMs, Math.max(profile.minMs, computed));
|
|
48
|
+
return Math.min(bounded, cap);
|
|
49
|
+
}
|
|
50
|
+
export function buildCliSupervisorScopeKey(params) {
|
|
51
|
+
const commandToken = path
|
|
52
|
+
.basename(params.backend.command ?? "")
|
|
53
|
+
.trim()
|
|
54
|
+
.toLowerCase();
|
|
55
|
+
const backendToken = params.backendId.trim().toLowerCase();
|
|
56
|
+
const sessionToken = params.cliSessionId?.trim();
|
|
57
|
+
if (!sessionToken) {
|
|
58
|
+
return undefined;
|
|
59
|
+
}
|
|
60
|
+
return `cli:${backendToken}:${commandToken}:${sessionToken}`;
|
|
61
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export const CLI_WATCHDOG_MIN_TIMEOUT_MS = 1_000;
|
|
2
|
+
export const CLI_FRESH_WATCHDOG_DEFAULTS = {
|
|
3
|
+
noOutputTimeoutRatio: 0.8,
|
|
4
|
+
minMs: 180_000,
|
|
5
|
+
maxMs: 600_000,
|
|
6
|
+
};
|
|
7
|
+
export const CLI_RESUME_WATCHDOG_DEFAULTS = {
|
|
8
|
+
noOutputTimeoutRatio: 0.3,
|
|
9
|
+
minMs: 60_000,
|
|
10
|
+
maxMs: 180_000,
|
|
11
|
+
};
|