@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
|
@@ -2,6 +2,7 @@ import { loadConfig } from "../config/config.js";
|
|
|
2
2
|
import { callGateway } from "../gateway/call.js";
|
|
3
3
|
import { onAgentEvent } from "../infra/agent-events.js";
|
|
4
4
|
import { normalizeDeliveryContext } from "../utils/delivery-context.js";
|
|
5
|
+
import { resetAnnounceQueuesForTests } from "./subagent-announce-queue.js";
|
|
5
6
|
import { runSubagentAnnounceFlow } from "./subagent-announce.js";
|
|
6
7
|
import { loadSubagentRegistryFromDisk, saveSubagentRegistryToDisk, } from "./subagent-registry.store.js";
|
|
7
8
|
import { resolveAgentTimeoutMs } from "./timeout.js";
|
|
@@ -11,6 +12,19 @@ let listenerStarted = false;
|
|
|
11
12
|
let listenerStop = null;
|
|
12
13
|
// Use var to avoid TDZ when init runs across circular imports during bootstrap.
|
|
13
14
|
var restoreAttempted = false;
|
|
15
|
+
const SUBAGENT_ANNOUNCE_TIMEOUT_MS = 120_000;
|
|
16
|
+
/**
|
|
17
|
+
* Maximum number of announce delivery attempts before giving up.
|
|
18
|
+
* Prevents infinite retry loops when `runSubagentAnnounceFlow` repeatedly
|
|
19
|
+
* returns `false` due to stale state or transient conditions (#18264).
|
|
20
|
+
*/
|
|
21
|
+
const MAX_ANNOUNCE_RETRY_COUNT = 3;
|
|
22
|
+
/**
|
|
23
|
+
* Announce entries older than this are force-expired even if delivery never
|
|
24
|
+
* succeeded. Guards against stale registry entries surviving gateway restarts.
|
|
25
|
+
*/
|
|
26
|
+
const ANNOUNCE_EXPIRY_MS = 5 * 60_000; // 5 minutes
|
|
27
|
+
// (Backoff constant removed — max-retry + expiry guards are sufficient.)
|
|
14
28
|
function persistSubagentRuns() {
|
|
15
29
|
try {
|
|
16
30
|
saveSubagentRegistryToDisk(subagentRuns);
|
|
@@ -20,55 +34,86 @@ function persistSubagentRuns() {
|
|
|
20
34
|
}
|
|
21
35
|
}
|
|
22
36
|
const resumedRuns = new Set();
|
|
37
|
+
function suppressAnnounceForSteerRestart(entry) {
|
|
38
|
+
return entry?.suppressAnnounceReason === "steer-restart";
|
|
39
|
+
}
|
|
40
|
+
function startSubagentAnnounceCleanupFlow(runId, entry) {
|
|
41
|
+
if (!beginSubagentCleanup(runId)) {
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
const requesterOrigin = normalizeDeliveryContext(entry.requesterOrigin);
|
|
45
|
+
void runSubagentAnnounceFlow({
|
|
46
|
+
childSessionKey: entry.childSessionKey,
|
|
47
|
+
childRunId: entry.runId,
|
|
48
|
+
requesterSessionKey: entry.requesterSessionKey,
|
|
49
|
+
requesterOrigin,
|
|
50
|
+
requesterDisplayKey: entry.requesterDisplayKey,
|
|
51
|
+
task: entry.task,
|
|
52
|
+
timeoutMs: SUBAGENT_ANNOUNCE_TIMEOUT_MS,
|
|
53
|
+
cleanup: entry.cleanup,
|
|
54
|
+
waitForCompletion: false,
|
|
55
|
+
startedAt: entry.startedAt,
|
|
56
|
+
endedAt: entry.endedAt,
|
|
57
|
+
label: entry.label,
|
|
58
|
+
outcome: entry.outcome,
|
|
59
|
+
}).then((didAnnounce) => {
|
|
60
|
+
finalizeSubagentCleanup(runId, entry.cleanup, didAnnounce);
|
|
61
|
+
});
|
|
62
|
+
return true;
|
|
63
|
+
}
|
|
23
64
|
function resumeSubagentRun(runId) {
|
|
24
|
-
if (!runId || resumedRuns.has(runId))
|
|
65
|
+
if (!runId || resumedRuns.has(runId)) {
|
|
25
66
|
return;
|
|
67
|
+
}
|
|
26
68
|
const entry = subagentRuns.get(runId);
|
|
27
|
-
if (!entry)
|
|
69
|
+
if (!entry) {
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
if (entry.cleanupCompletedAt) {
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
// Skip entries that have exhausted their retry budget or expired (#18264).
|
|
76
|
+
if ((entry.announceRetryCount ?? 0) >= MAX_ANNOUNCE_RETRY_COUNT) {
|
|
77
|
+
entry.cleanupCompletedAt = Date.now();
|
|
78
|
+
persistSubagentRuns();
|
|
28
79
|
return;
|
|
29
|
-
|
|
80
|
+
}
|
|
81
|
+
if (typeof entry.endedAt === "number" && Date.now() - entry.endedAt > ANNOUNCE_EXPIRY_MS) {
|
|
82
|
+
entry.cleanupCompletedAt = Date.now();
|
|
83
|
+
persistSubagentRuns();
|
|
30
84
|
return;
|
|
85
|
+
}
|
|
31
86
|
if (typeof entry.endedAt === "number" && entry.endedAt > 0) {
|
|
32
|
-
if (
|
|
87
|
+
if (suppressAnnounceForSteerRestart(entry)) {
|
|
88
|
+
resumedRuns.add(runId);
|
|
33
89
|
return;
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
requesterSessionKey: entry.requesterSessionKey,
|
|
39
|
-
requesterOrigin,
|
|
40
|
-
requesterDisplayKey: entry.requesterDisplayKey,
|
|
41
|
-
task: entry.task,
|
|
42
|
-
timeoutMs: 30_000,
|
|
43
|
-
cleanup: entry.cleanup,
|
|
44
|
-
waitForCompletion: false,
|
|
45
|
-
startedAt: entry.startedAt,
|
|
46
|
-
endedAt: entry.endedAt,
|
|
47
|
-
label: entry.label,
|
|
48
|
-
outcome: entry.outcome,
|
|
49
|
-
}).then((didAnnounce) => {
|
|
50
|
-
finalizeSubagentCleanup(runId, entry.cleanup, didAnnounce);
|
|
51
|
-
});
|
|
90
|
+
}
|
|
91
|
+
if (!startSubagentAnnounceCleanupFlow(runId, entry)) {
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
52
94
|
resumedRuns.add(runId);
|
|
53
95
|
return;
|
|
54
96
|
}
|
|
55
97
|
// Wait for completion again after restart.
|
|
56
98
|
const cfg = loadConfig();
|
|
57
|
-
const waitTimeoutMs = resolveSubagentWaitTimeoutMs(cfg,
|
|
99
|
+
const waitTimeoutMs = resolveSubagentWaitTimeoutMs(cfg, entry.runTimeoutSeconds);
|
|
58
100
|
void waitForSubagentCompletion(runId, waitTimeoutMs);
|
|
59
101
|
resumedRuns.add(runId);
|
|
60
102
|
}
|
|
61
103
|
function restoreSubagentRunsOnce() {
|
|
62
|
-
if (restoreAttempted)
|
|
104
|
+
if (restoreAttempted) {
|
|
63
105
|
return;
|
|
106
|
+
}
|
|
64
107
|
restoreAttempted = true;
|
|
65
108
|
try {
|
|
66
109
|
const restored = loadSubagentRegistryFromDisk();
|
|
67
|
-
if (restored.size === 0)
|
|
110
|
+
if (restored.size === 0) {
|
|
68
111
|
return;
|
|
112
|
+
}
|
|
69
113
|
for (const [runId, entry] of restored.entries()) {
|
|
70
|
-
if (!runId || !entry)
|
|
114
|
+
if (!runId || !entry) {
|
|
71
115
|
continue;
|
|
116
|
+
}
|
|
72
117
|
// Keep any newer in-memory entries.
|
|
73
118
|
if (!subagentRuns.has(runId)) {
|
|
74
119
|
subagentRuns.set(runId, entry);
|
|
@@ -90,24 +135,27 @@ function restoreSubagentRunsOnce() {
|
|
|
90
135
|
function resolveArchiveAfterMs(cfg) {
|
|
91
136
|
const config = cfg ?? loadConfig();
|
|
92
137
|
const minutes = config.agents?.defaults?.subagents?.archiveAfterMinutes ?? 60;
|
|
93
|
-
if (!Number.isFinite(minutes) || minutes <= 0)
|
|
138
|
+
if (!Number.isFinite(minutes) || minutes <= 0) {
|
|
94
139
|
return undefined;
|
|
140
|
+
}
|
|
95
141
|
return Math.max(1, Math.floor(minutes)) * 60_000;
|
|
96
142
|
}
|
|
97
143
|
function resolveSubagentWaitTimeoutMs(cfg, runTimeoutSeconds) {
|
|
98
|
-
return resolveAgentTimeoutMs({ cfg, overrideSeconds: runTimeoutSeconds });
|
|
144
|
+
return resolveAgentTimeoutMs({ cfg, overrideSeconds: runTimeoutSeconds ?? 0 });
|
|
99
145
|
}
|
|
100
146
|
function startSweeper() {
|
|
101
|
-
if (sweeper)
|
|
147
|
+
if (sweeper) {
|
|
102
148
|
return;
|
|
149
|
+
}
|
|
103
150
|
sweeper = setInterval(() => {
|
|
104
151
|
void sweepSubagentRuns();
|
|
105
152
|
}, 60_000);
|
|
106
153
|
sweeper.unref?.();
|
|
107
154
|
}
|
|
108
155
|
function stopSweeper() {
|
|
109
|
-
if (!sweeper)
|
|
156
|
+
if (!sweeper) {
|
|
110
157
|
return;
|
|
158
|
+
}
|
|
111
159
|
clearInterval(sweeper);
|
|
112
160
|
sweeper = null;
|
|
113
161
|
}
|
|
@@ -115,8 +163,9 @@ async function sweepSubagentRuns() {
|
|
|
115
163
|
const now = Date.now();
|
|
116
164
|
let mutated = false;
|
|
117
165
|
for (const [runId, entry] of subagentRuns.entries()) {
|
|
118
|
-
if (!entry.archiveAtMs || entry.archiveAtMs > now)
|
|
166
|
+
if (!entry.archiveAtMs || entry.archiveAtMs > now) {
|
|
119
167
|
continue;
|
|
168
|
+
}
|
|
120
169
|
subagentRuns.delete(runId);
|
|
121
170
|
mutated = true;
|
|
122
171
|
try {
|
|
@@ -130,10 +179,12 @@ async function sweepSubagentRuns() {
|
|
|
130
179
|
// ignore
|
|
131
180
|
}
|
|
132
181
|
}
|
|
133
|
-
if (mutated)
|
|
182
|
+
if (mutated) {
|
|
134
183
|
persistSubagentRuns();
|
|
135
|
-
|
|
184
|
+
}
|
|
185
|
+
if (subagentRuns.size === 0) {
|
|
136
186
|
stopSweeper();
|
|
187
|
+
}
|
|
137
188
|
}
|
|
138
189
|
function ensureListener() {
|
|
139
190
|
if (listenerStarted) {
|
|
@@ -141,8 +192,9 @@ function ensureListener() {
|
|
|
141
192
|
}
|
|
142
193
|
listenerStarted = true;
|
|
143
194
|
listenerStop = onAgentEvent((evt) => {
|
|
144
|
-
if (!evt || evt.stream !== "lifecycle")
|
|
195
|
+
if (!evt || evt.stream !== "lifecycle") {
|
|
145
196
|
return;
|
|
197
|
+
}
|
|
146
198
|
const entry = subagentRuns.get(evt.runId);
|
|
147
199
|
if (!entry) {
|
|
148
200
|
return;
|
|
@@ -156,77 +208,194 @@ function ensureListener() {
|
|
|
156
208
|
}
|
|
157
209
|
return;
|
|
158
210
|
}
|
|
159
|
-
if (phase !== "end" && phase !== "error")
|
|
211
|
+
if (phase !== "end" && phase !== "error") {
|
|
160
212
|
return;
|
|
213
|
+
}
|
|
161
214
|
const endedAt = typeof evt.data?.endedAt === "number" ? evt.data.endedAt : Date.now();
|
|
162
215
|
entry.endedAt = endedAt;
|
|
163
216
|
if (phase === "error") {
|
|
164
217
|
const error = typeof evt.data?.error === "string" ? evt.data.error : undefined;
|
|
165
218
|
entry.outcome = { status: "error", error };
|
|
166
219
|
}
|
|
220
|
+
else if (evt.data?.aborted) {
|
|
221
|
+
entry.outcome = { status: "timeout" };
|
|
222
|
+
}
|
|
167
223
|
else {
|
|
168
224
|
entry.outcome = { status: "ok" };
|
|
169
225
|
}
|
|
170
226
|
persistSubagentRuns();
|
|
171
|
-
if (
|
|
227
|
+
if (suppressAnnounceForSteerRestart(entry)) {
|
|
228
|
+
return;
|
|
229
|
+
}
|
|
230
|
+
if (!startSubagentAnnounceCleanupFlow(evt.runId, entry)) {
|
|
172
231
|
return;
|
|
173
232
|
}
|
|
174
|
-
const requesterOrigin = normalizeDeliveryContext(entry.requesterOrigin);
|
|
175
|
-
void runSubagentAnnounceFlow({
|
|
176
|
-
childSessionKey: entry.childSessionKey,
|
|
177
|
-
childRunId: entry.runId,
|
|
178
|
-
requesterSessionKey: entry.requesterSessionKey,
|
|
179
|
-
requesterOrigin,
|
|
180
|
-
requesterDisplayKey: entry.requesterDisplayKey,
|
|
181
|
-
task: entry.task,
|
|
182
|
-
timeoutMs: 30_000,
|
|
183
|
-
cleanup: entry.cleanup,
|
|
184
|
-
waitForCompletion: false,
|
|
185
|
-
startedAt: entry.startedAt,
|
|
186
|
-
endedAt: entry.endedAt,
|
|
187
|
-
label: entry.label,
|
|
188
|
-
outcome: entry.outcome,
|
|
189
|
-
}).then((didAnnounce) => {
|
|
190
|
-
finalizeSubagentCleanup(evt.runId, entry.cleanup, didAnnounce);
|
|
191
|
-
});
|
|
192
233
|
});
|
|
193
234
|
}
|
|
194
235
|
function finalizeSubagentCleanup(runId, cleanup, didAnnounce) {
|
|
195
236
|
const entry = subagentRuns.get(runId);
|
|
196
|
-
if (!entry)
|
|
197
|
-
return;
|
|
198
|
-
if (cleanup === "delete") {
|
|
199
|
-
subagentRuns.delete(runId);
|
|
200
|
-
persistSubagentRuns();
|
|
237
|
+
if (!entry) {
|
|
201
238
|
return;
|
|
202
239
|
}
|
|
203
240
|
if (!didAnnounce) {
|
|
204
|
-
|
|
241
|
+
const retryCount = (entry.announceRetryCount ?? 0) + 1;
|
|
242
|
+
entry.announceRetryCount = retryCount;
|
|
243
|
+
entry.lastAnnounceRetryAt = Date.now();
|
|
244
|
+
// Check if the announce has exceeded retry limits or expired (#18264).
|
|
245
|
+
const endedAgo = typeof entry.endedAt === "number" ? Date.now() - entry.endedAt : 0;
|
|
246
|
+
if (retryCount >= MAX_ANNOUNCE_RETRY_COUNT || endedAgo > ANNOUNCE_EXPIRY_MS) {
|
|
247
|
+
// Give up: mark as completed to break the infinite retry loop.
|
|
248
|
+
entry.cleanupCompletedAt = Date.now();
|
|
249
|
+
persistSubagentRuns();
|
|
250
|
+
retryDeferredCompletedAnnounces(runId);
|
|
251
|
+
return;
|
|
252
|
+
}
|
|
253
|
+
// Allow retry on the next wake if announce was deferred or failed.
|
|
205
254
|
entry.cleanupHandled = false;
|
|
255
|
+
resumedRuns.delete(runId);
|
|
206
256
|
persistSubagentRuns();
|
|
207
257
|
return;
|
|
208
258
|
}
|
|
259
|
+
if (cleanup === "delete") {
|
|
260
|
+
subagentRuns.delete(runId);
|
|
261
|
+
persistSubagentRuns();
|
|
262
|
+
retryDeferredCompletedAnnounces(runId);
|
|
263
|
+
return;
|
|
264
|
+
}
|
|
209
265
|
entry.cleanupCompletedAt = Date.now();
|
|
210
266
|
persistSubagentRuns();
|
|
267
|
+
retryDeferredCompletedAnnounces(runId);
|
|
268
|
+
}
|
|
269
|
+
function retryDeferredCompletedAnnounces(excludeRunId) {
|
|
270
|
+
const now = Date.now();
|
|
271
|
+
for (const [runId, entry] of subagentRuns.entries()) {
|
|
272
|
+
if (excludeRunId && runId === excludeRunId) {
|
|
273
|
+
continue;
|
|
274
|
+
}
|
|
275
|
+
if (typeof entry.endedAt !== "number") {
|
|
276
|
+
continue;
|
|
277
|
+
}
|
|
278
|
+
if (entry.cleanupCompletedAt || entry.cleanupHandled) {
|
|
279
|
+
continue;
|
|
280
|
+
}
|
|
281
|
+
if (suppressAnnounceForSteerRestart(entry)) {
|
|
282
|
+
continue;
|
|
283
|
+
}
|
|
284
|
+
// Force-expire announces that have been pending too long (#18264).
|
|
285
|
+
const endedAgo = now - (entry.endedAt ?? now);
|
|
286
|
+
if (endedAgo > ANNOUNCE_EXPIRY_MS) {
|
|
287
|
+
entry.cleanupCompletedAt = now;
|
|
288
|
+
persistSubagentRuns();
|
|
289
|
+
continue;
|
|
290
|
+
}
|
|
291
|
+
resumedRuns.delete(runId);
|
|
292
|
+
resumeSubagentRun(runId);
|
|
293
|
+
}
|
|
211
294
|
}
|
|
212
295
|
function beginSubagentCleanup(runId) {
|
|
213
296
|
const entry = subagentRuns.get(runId);
|
|
214
|
-
if (!entry)
|
|
297
|
+
if (!entry) {
|
|
215
298
|
return false;
|
|
216
|
-
|
|
299
|
+
}
|
|
300
|
+
if (entry.cleanupCompletedAt) {
|
|
217
301
|
return false;
|
|
218
|
-
|
|
302
|
+
}
|
|
303
|
+
if (entry.cleanupHandled) {
|
|
219
304
|
return false;
|
|
305
|
+
}
|
|
220
306
|
entry.cleanupHandled = true;
|
|
221
307
|
persistSubagentRuns();
|
|
222
308
|
return true;
|
|
223
309
|
}
|
|
310
|
+
export function markSubagentRunForSteerRestart(runId) {
|
|
311
|
+
const key = runId.trim();
|
|
312
|
+
if (!key) {
|
|
313
|
+
return false;
|
|
314
|
+
}
|
|
315
|
+
const entry = subagentRuns.get(key);
|
|
316
|
+
if (!entry) {
|
|
317
|
+
return false;
|
|
318
|
+
}
|
|
319
|
+
if (entry.suppressAnnounceReason === "steer-restart") {
|
|
320
|
+
return true;
|
|
321
|
+
}
|
|
322
|
+
entry.suppressAnnounceReason = "steer-restart";
|
|
323
|
+
persistSubagentRuns();
|
|
324
|
+
return true;
|
|
325
|
+
}
|
|
326
|
+
export function clearSubagentRunSteerRestart(runId) {
|
|
327
|
+
const key = runId.trim();
|
|
328
|
+
if (!key) {
|
|
329
|
+
return false;
|
|
330
|
+
}
|
|
331
|
+
const entry = subagentRuns.get(key);
|
|
332
|
+
if (!entry) {
|
|
333
|
+
return false;
|
|
334
|
+
}
|
|
335
|
+
if (entry.suppressAnnounceReason !== "steer-restart") {
|
|
336
|
+
return true;
|
|
337
|
+
}
|
|
338
|
+
entry.suppressAnnounceReason = undefined;
|
|
339
|
+
persistSubagentRuns();
|
|
340
|
+
// If the interrupted run already finished while suppression was active, retry
|
|
341
|
+
// cleanup now so completion output is not lost when restart dispatch fails.
|
|
342
|
+
resumedRuns.delete(key);
|
|
343
|
+
if (typeof entry.endedAt === "number" && !entry.cleanupCompletedAt) {
|
|
344
|
+
resumeSubagentRun(key);
|
|
345
|
+
}
|
|
346
|
+
return true;
|
|
347
|
+
}
|
|
348
|
+
export function replaceSubagentRunAfterSteer(params) {
|
|
349
|
+
const previousRunId = params.previousRunId.trim();
|
|
350
|
+
const nextRunId = params.nextRunId.trim();
|
|
351
|
+
if (!previousRunId || !nextRunId) {
|
|
352
|
+
return false;
|
|
353
|
+
}
|
|
354
|
+
const previous = subagentRuns.get(previousRunId);
|
|
355
|
+
const source = previous ?? params.fallback;
|
|
356
|
+
if (!source) {
|
|
357
|
+
return false;
|
|
358
|
+
}
|
|
359
|
+
if (previousRunId !== nextRunId) {
|
|
360
|
+
subagentRuns.delete(previousRunId);
|
|
361
|
+
resumedRuns.delete(previousRunId);
|
|
362
|
+
}
|
|
363
|
+
const now = Date.now();
|
|
364
|
+
const cfg = loadConfig();
|
|
365
|
+
const archiveAfterMs = resolveArchiveAfterMs(cfg);
|
|
366
|
+
const archiveAtMs = archiveAfterMs ? now + archiveAfterMs : undefined;
|
|
367
|
+
const runTimeoutSeconds = params.runTimeoutSeconds ?? source.runTimeoutSeconds ?? 0;
|
|
368
|
+
const waitTimeoutMs = resolveSubagentWaitTimeoutMs(cfg, runTimeoutSeconds);
|
|
369
|
+
const next = {
|
|
370
|
+
...source,
|
|
371
|
+
runId: nextRunId,
|
|
372
|
+
startedAt: now,
|
|
373
|
+
endedAt: undefined,
|
|
374
|
+
outcome: undefined,
|
|
375
|
+
cleanupCompletedAt: undefined,
|
|
376
|
+
cleanupHandled: false,
|
|
377
|
+
suppressAnnounceReason: undefined,
|
|
378
|
+
announceRetryCount: undefined,
|
|
379
|
+
lastAnnounceRetryAt: undefined,
|
|
380
|
+
archiveAtMs,
|
|
381
|
+
runTimeoutSeconds,
|
|
382
|
+
};
|
|
383
|
+
subagentRuns.set(nextRunId, next);
|
|
384
|
+
ensureListener();
|
|
385
|
+
persistSubagentRuns();
|
|
386
|
+
if (archiveAtMs) {
|
|
387
|
+
startSweeper();
|
|
388
|
+
}
|
|
389
|
+
void waitForSubagentCompletion(nextRunId, waitTimeoutMs);
|
|
390
|
+
return true;
|
|
391
|
+
}
|
|
224
392
|
export function registerSubagentRun(params) {
|
|
225
393
|
const now = Date.now();
|
|
226
394
|
const cfg = loadConfig();
|
|
227
395
|
const archiveAfterMs = resolveArchiveAfterMs(cfg);
|
|
228
396
|
const archiveAtMs = archiveAfterMs ? now + archiveAfterMs : undefined;
|
|
229
|
-
const
|
|
397
|
+
const runTimeoutSeconds = params.runTimeoutSeconds ?? 0;
|
|
398
|
+
const waitTimeoutMs = resolveSubagentWaitTimeoutMs(cfg, runTimeoutSeconds);
|
|
230
399
|
const requesterOrigin = normalizeDeliveryContext(params.requesterOrigin);
|
|
231
400
|
subagentRuns.set(params.runId, {
|
|
232
401
|
runId: params.runId,
|
|
@@ -237,6 +406,8 @@ export function registerSubagentRun(params) {
|
|
|
237
406
|
task: params.task,
|
|
238
407
|
cleanup: params.cleanup,
|
|
239
408
|
label: params.label,
|
|
409
|
+
model: params.model,
|
|
410
|
+
runTimeoutSeconds,
|
|
240
411
|
createdAt: now,
|
|
241
412
|
startedAt: now,
|
|
242
413
|
archiveAtMs,
|
|
@@ -244,8 +415,9 @@ export function registerSubagentRun(params) {
|
|
|
244
415
|
});
|
|
245
416
|
ensureListener();
|
|
246
417
|
persistSubagentRuns();
|
|
247
|
-
if (archiveAfterMs)
|
|
418
|
+
if (archiveAfterMs) {
|
|
248
419
|
startSweeper();
|
|
420
|
+
}
|
|
249
421
|
// Wait for subagent completion via gateway RPC (cross-process).
|
|
250
422
|
// The in-process lifecycle listener is a fallback for embedded runs.
|
|
251
423
|
void waitForSubagentCompletion(params.runId, waitTimeoutMs);
|
|
@@ -253,19 +425,21 @@ export function registerSubagentRun(params) {
|
|
|
253
425
|
async function waitForSubagentCompletion(runId, waitTimeoutMs) {
|
|
254
426
|
try {
|
|
255
427
|
const timeoutMs = Math.max(1, Math.floor(waitTimeoutMs));
|
|
256
|
-
const wait =
|
|
428
|
+
const wait = await callGateway({
|
|
257
429
|
method: "agent.wait",
|
|
258
430
|
params: {
|
|
259
431
|
runId,
|
|
260
432
|
timeoutMs,
|
|
261
433
|
},
|
|
262
434
|
timeoutMs: timeoutMs + 10_000,
|
|
263
|
-
})
|
|
264
|
-
if (wait?.status !== "ok" && wait?.status !== "error")
|
|
435
|
+
});
|
|
436
|
+
if (wait?.status !== "ok" && wait?.status !== "error" && wait?.status !== "timeout") {
|
|
265
437
|
return;
|
|
438
|
+
}
|
|
266
439
|
const entry = subagentRuns.get(runId);
|
|
267
|
-
if (!entry)
|
|
440
|
+
if (!entry) {
|
|
268
441
|
return;
|
|
442
|
+
}
|
|
269
443
|
let mutated = false;
|
|
270
444
|
if (typeof wait.startedAt === "number") {
|
|
271
445
|
entry.startedAt = wait.startedAt;
|
|
@@ -279,39 +453,32 @@ async function waitForSubagentCompletion(runId, waitTimeoutMs) {
|
|
|
279
453
|
entry.endedAt = Date.now();
|
|
280
454
|
mutated = true;
|
|
281
455
|
}
|
|
456
|
+
const waitError = typeof wait.error === "string" ? wait.error : undefined;
|
|
282
457
|
entry.outcome =
|
|
283
|
-
wait.status === "error"
|
|
458
|
+
wait.status === "error"
|
|
459
|
+
? { status: "error", error: waitError }
|
|
460
|
+
: wait.status === "timeout"
|
|
461
|
+
? { status: "timeout" }
|
|
462
|
+
: { status: "ok" };
|
|
284
463
|
mutated = true;
|
|
285
|
-
if (mutated)
|
|
464
|
+
if (mutated) {
|
|
286
465
|
persistSubagentRuns();
|
|
287
|
-
|
|
466
|
+
}
|
|
467
|
+
if (suppressAnnounceForSteerRestart(entry)) {
|
|
288
468
|
return;
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
requesterSessionKey: entry.requesterSessionKey,
|
|
294
|
-
requesterOrigin,
|
|
295
|
-
requesterDisplayKey: entry.requesterDisplayKey,
|
|
296
|
-
task: entry.task,
|
|
297
|
-
timeoutMs: 30_000,
|
|
298
|
-
cleanup: entry.cleanup,
|
|
299
|
-
waitForCompletion: false,
|
|
300
|
-
startedAt: entry.startedAt,
|
|
301
|
-
endedAt: entry.endedAt,
|
|
302
|
-
label: entry.label,
|
|
303
|
-
outcome: entry.outcome,
|
|
304
|
-
}).then((didAnnounce) => {
|
|
305
|
-
finalizeSubagentCleanup(runId, entry.cleanup, didAnnounce);
|
|
306
|
-
});
|
|
469
|
+
}
|
|
470
|
+
if (!startSubagentAnnounceCleanupFlow(runId, entry)) {
|
|
471
|
+
return;
|
|
472
|
+
}
|
|
307
473
|
}
|
|
308
474
|
catch {
|
|
309
475
|
// ignore
|
|
310
476
|
}
|
|
311
477
|
}
|
|
312
|
-
export function resetSubagentRegistryForTests() {
|
|
478
|
+
export function resetSubagentRegistryForTests(opts) {
|
|
313
479
|
subagentRuns.clear();
|
|
314
480
|
resumedRuns.clear();
|
|
481
|
+
resetAnnounceQueuesForTests();
|
|
315
482
|
stopSweeper();
|
|
316
483
|
restoreAttempted = false;
|
|
317
484
|
if (listenerStop) {
|
|
@@ -319,25 +486,210 @@ export function resetSubagentRegistryForTests() {
|
|
|
319
486
|
listenerStop = null;
|
|
320
487
|
}
|
|
321
488
|
listenerStarted = false;
|
|
322
|
-
|
|
489
|
+
if (opts?.persist !== false) {
|
|
490
|
+
persistSubagentRuns();
|
|
491
|
+
}
|
|
323
492
|
}
|
|
324
493
|
export function addSubagentRunForTests(entry) {
|
|
325
494
|
subagentRuns.set(entry.runId, entry);
|
|
326
|
-
persistSubagentRuns();
|
|
327
495
|
}
|
|
328
496
|
export function releaseSubagentRun(runId) {
|
|
329
497
|
const didDelete = subagentRuns.delete(runId);
|
|
330
|
-
if (didDelete)
|
|
498
|
+
if (didDelete) {
|
|
331
499
|
persistSubagentRuns();
|
|
332
|
-
|
|
500
|
+
}
|
|
501
|
+
if (subagentRuns.size === 0) {
|
|
333
502
|
stopSweeper();
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
function findRunIdsByChildSessionKey(childSessionKey) {
|
|
506
|
+
const key = childSessionKey.trim();
|
|
507
|
+
if (!key) {
|
|
508
|
+
return [];
|
|
509
|
+
}
|
|
510
|
+
const runIds = [];
|
|
511
|
+
for (const [runId, entry] of subagentRuns.entries()) {
|
|
512
|
+
if (entry.childSessionKey === key) {
|
|
513
|
+
runIds.push(runId);
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
return runIds;
|
|
517
|
+
}
|
|
518
|
+
function getRunsSnapshotForRead() {
|
|
519
|
+
const merged = new Map();
|
|
520
|
+
const shouldReadDisk = !(process.env.VITEST || process.env.NODE_ENV === "test");
|
|
521
|
+
if (shouldReadDisk) {
|
|
522
|
+
try {
|
|
523
|
+
// Registry state is persisted to disk so other worker processes (for
|
|
524
|
+
// example cron runners) can observe active children spawned elsewhere.
|
|
525
|
+
for (const [runId, entry] of loadSubagentRegistryFromDisk().entries()) {
|
|
526
|
+
merged.set(runId, entry);
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
catch {
|
|
530
|
+
// Ignore disk read failures and fall back to local memory state.
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
for (const [runId, entry] of subagentRuns.entries()) {
|
|
534
|
+
merged.set(runId, entry);
|
|
535
|
+
}
|
|
536
|
+
return merged;
|
|
537
|
+
}
|
|
538
|
+
export function resolveRequesterForChildSession(childSessionKey) {
|
|
539
|
+
const key = childSessionKey.trim();
|
|
540
|
+
if (!key) {
|
|
541
|
+
return null;
|
|
542
|
+
}
|
|
543
|
+
let best;
|
|
544
|
+
for (const entry of getRunsSnapshotForRead().values()) {
|
|
545
|
+
if (entry.childSessionKey !== key) {
|
|
546
|
+
continue;
|
|
547
|
+
}
|
|
548
|
+
if (!best || entry.createdAt > best.createdAt) {
|
|
549
|
+
best = entry;
|
|
550
|
+
}
|
|
551
|
+
}
|
|
552
|
+
if (!best) {
|
|
553
|
+
return null;
|
|
554
|
+
}
|
|
555
|
+
return {
|
|
556
|
+
requesterSessionKey: best.requesterSessionKey,
|
|
557
|
+
requesterOrigin: normalizeDeliveryContext(best.requesterOrigin),
|
|
558
|
+
};
|
|
559
|
+
}
|
|
560
|
+
export function isSubagentSessionRunActive(childSessionKey) {
|
|
561
|
+
const runIds = findRunIdsByChildSessionKey(childSessionKey);
|
|
562
|
+
for (const runId of runIds) {
|
|
563
|
+
const entry = subagentRuns.get(runId);
|
|
564
|
+
if (!entry) {
|
|
565
|
+
continue;
|
|
566
|
+
}
|
|
567
|
+
if (typeof entry.endedAt !== "number") {
|
|
568
|
+
return true;
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
return false;
|
|
572
|
+
}
|
|
573
|
+
export function markSubagentRunTerminated(params) {
|
|
574
|
+
const runIds = new Set();
|
|
575
|
+
if (typeof params.runId === "string" && params.runId.trim()) {
|
|
576
|
+
runIds.add(params.runId.trim());
|
|
577
|
+
}
|
|
578
|
+
if (typeof params.childSessionKey === "string" && params.childSessionKey.trim()) {
|
|
579
|
+
for (const runId of findRunIdsByChildSessionKey(params.childSessionKey)) {
|
|
580
|
+
runIds.add(runId);
|
|
581
|
+
}
|
|
582
|
+
}
|
|
583
|
+
if (runIds.size === 0) {
|
|
584
|
+
return 0;
|
|
585
|
+
}
|
|
586
|
+
const now = Date.now();
|
|
587
|
+
const reason = params.reason?.trim() || "killed";
|
|
588
|
+
let updated = 0;
|
|
589
|
+
for (const runId of runIds) {
|
|
590
|
+
const entry = subagentRuns.get(runId);
|
|
591
|
+
if (!entry) {
|
|
592
|
+
continue;
|
|
593
|
+
}
|
|
594
|
+
if (typeof entry.endedAt === "number") {
|
|
595
|
+
continue;
|
|
596
|
+
}
|
|
597
|
+
entry.endedAt = now;
|
|
598
|
+
entry.outcome = { status: "error", error: reason };
|
|
599
|
+
entry.cleanupHandled = true;
|
|
600
|
+
entry.cleanupCompletedAt = now;
|
|
601
|
+
entry.suppressAnnounceReason = "killed";
|
|
602
|
+
updated += 1;
|
|
603
|
+
}
|
|
604
|
+
if (updated > 0) {
|
|
605
|
+
persistSubagentRuns();
|
|
606
|
+
}
|
|
607
|
+
return updated;
|
|
334
608
|
}
|
|
335
609
|
export function listSubagentRunsForRequester(requesterSessionKey) {
|
|
336
610
|
const key = requesterSessionKey.trim();
|
|
337
|
-
if (!key)
|
|
611
|
+
if (!key) {
|
|
338
612
|
return [];
|
|
613
|
+
}
|
|
339
614
|
return [...subagentRuns.values()].filter((entry) => entry.requesterSessionKey === key);
|
|
340
615
|
}
|
|
616
|
+
export function countActiveRunsForSession(requesterSessionKey) {
|
|
617
|
+
const key = requesterSessionKey.trim();
|
|
618
|
+
if (!key) {
|
|
619
|
+
return 0;
|
|
620
|
+
}
|
|
621
|
+
let count = 0;
|
|
622
|
+
for (const entry of getRunsSnapshotForRead().values()) {
|
|
623
|
+
if (entry.requesterSessionKey !== key) {
|
|
624
|
+
continue;
|
|
625
|
+
}
|
|
626
|
+
if (typeof entry.endedAt === "number") {
|
|
627
|
+
continue;
|
|
628
|
+
}
|
|
629
|
+
count += 1;
|
|
630
|
+
}
|
|
631
|
+
return count;
|
|
632
|
+
}
|
|
633
|
+
export function countActiveDescendantRuns(rootSessionKey) {
|
|
634
|
+
const root = rootSessionKey.trim();
|
|
635
|
+
if (!root) {
|
|
636
|
+
return 0;
|
|
637
|
+
}
|
|
638
|
+
const runs = getRunsSnapshotForRead();
|
|
639
|
+
const pending = [root];
|
|
640
|
+
const visited = new Set([root]);
|
|
641
|
+
let count = 0;
|
|
642
|
+
while (pending.length > 0) {
|
|
643
|
+
const requester = pending.shift();
|
|
644
|
+
if (!requester) {
|
|
645
|
+
continue;
|
|
646
|
+
}
|
|
647
|
+
for (const entry of runs.values()) {
|
|
648
|
+
if (entry.requesterSessionKey !== requester) {
|
|
649
|
+
continue;
|
|
650
|
+
}
|
|
651
|
+
if (typeof entry.endedAt !== "number") {
|
|
652
|
+
count += 1;
|
|
653
|
+
}
|
|
654
|
+
const childKey = entry.childSessionKey.trim();
|
|
655
|
+
if (!childKey || visited.has(childKey)) {
|
|
656
|
+
continue;
|
|
657
|
+
}
|
|
658
|
+
visited.add(childKey);
|
|
659
|
+
pending.push(childKey);
|
|
660
|
+
}
|
|
661
|
+
}
|
|
662
|
+
return count;
|
|
663
|
+
}
|
|
664
|
+
export function listDescendantRunsForRequester(rootSessionKey) {
|
|
665
|
+
const root = rootSessionKey.trim();
|
|
666
|
+
if (!root) {
|
|
667
|
+
return [];
|
|
668
|
+
}
|
|
669
|
+
const runs = getRunsSnapshotForRead();
|
|
670
|
+
const pending = [root];
|
|
671
|
+
const visited = new Set([root]);
|
|
672
|
+
const descendants = [];
|
|
673
|
+
while (pending.length > 0) {
|
|
674
|
+
const requester = pending.shift();
|
|
675
|
+
if (!requester) {
|
|
676
|
+
continue;
|
|
677
|
+
}
|
|
678
|
+
for (const entry of runs.values()) {
|
|
679
|
+
if (entry.requesterSessionKey !== requester) {
|
|
680
|
+
continue;
|
|
681
|
+
}
|
|
682
|
+
descendants.push(entry);
|
|
683
|
+
const childKey = entry.childSessionKey.trim();
|
|
684
|
+
if (!childKey || visited.has(childKey)) {
|
|
685
|
+
continue;
|
|
686
|
+
}
|
|
687
|
+
visited.add(childKey);
|
|
688
|
+
pending.push(childKey);
|
|
689
|
+
}
|
|
690
|
+
}
|
|
691
|
+
return descendants;
|
|
692
|
+
}
|
|
341
693
|
export function initSubagentRegistry() {
|
|
342
694
|
restoreSubagentRunsOnce();
|
|
343
695
|
}
|