@poolzin/pool-bot 2026.2.24 → 2026.2.26
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +21 -0
- package/dist/acp/client.js +207 -18
- package/dist/acp/event-mapper.js +87 -22
- package/dist/acp/meta.js +12 -6
- package/dist/acp/secret-file.js +22 -0
- package/dist/agents/agent-paths.js +8 -9
- package/dist/agents/agent-scope.js +17 -5
- package/dist/agents/auth-profiles/oauth.js +148 -64
- package/dist/agents/auth-profiles/session-override.js +13 -7
- package/dist/agents/bash-process-registry.test-helpers.js +29 -0
- package/dist/agents/bash-tools.exec-approval-request.js +20 -0
- package/dist/agents/bash-tools.exec-host-gateway.js +240 -0
- package/dist/agents/bash-tools.exec-host-node.js +235 -0
- package/dist/agents/bash-tools.exec-runtime.js +2 -25
- package/dist/agents/bash-tools.exec-types.js +1 -0
- package/dist/agents/bash-tools.process.js +224 -218
- package/dist/agents/bedrock-discovery.js +3 -1
- package/dist/agents/byteplus-models.js +97 -0
- package/dist/agents/chutes-oauth.js +1 -0
- package/dist/agents/cli-runner/helpers.js +4 -0
- package/dist/agents/compaction.js +41 -14
- package/dist/agents/content-blocks.js +16 -0
- package/dist/agents/doubao-models.js +121 -0
- package/dist/agents/failover-error.js +2 -0
- package/dist/agents/huggingface-models.js +5 -3
- package/dist/agents/live-model-filter.js +5 -0
- package/dist/agents/minimax-vlm.js +10 -8
- package/dist/agents/model-auth.js +6 -0
- package/dist/agents/model-catalog.js +3 -1
- package/dist/agents/model-fallback.js +96 -101
- package/dist/agents/model-selection.js +7 -1
- package/dist/agents/models-config.providers.js +364 -165
- package/dist/agents/ollama-stream.js +117 -4
- package/dist/agents/opencode-zen-models.js +22 -11
- package/dist/agents/pi-embedded-helpers/errors.js +55 -33
- package/dist/agents/pi-embedded-helpers/messaging-dedupe.js +10 -5
- package/dist/agents/pi-embedded-helpers/thinking.js +10 -5
- package/dist/agents/pi-embedded-helpers.js +1 -1
- package/dist/agents/pi-embedded-payloads.js +1 -0
- package/dist/agents/pi-embedded-runner/compact.js +29 -7
- package/dist/agents/pi-embedded-runner/extensions.js +28 -26
- package/dist/agents/pi-embedded-runner/google.js +20 -8
- package/dist/agents/pi-embedded-runner/run/attempt.js +95 -36
- package/dist/agents/pi-embedded-runner/run.js +71 -12
- package/dist/agents/pi-embedded-runner/run.overflow-compaction.fixture.js +34 -0
- package/dist/agents/pi-embedded-runner/run.overflow-compaction.mocks.shared.js +11 -2
- package/dist/agents/pi-embedded-runner/session-manager-cache.js +11 -7
- package/dist/agents/pi-embedded-runner/system-prompt.js +2 -0
- package/dist/agents/pi-embedded-runner/thinking.js +42 -0
- package/dist/agents/pi-embedded-runner/tool-name-allowlist.js +19 -0
- package/dist/agents/pi-embedded-runner/utils.js +7 -10
- package/dist/agents/pi-embedded-subscribe.handlers.lifecycle.js +45 -56
- package/dist/agents/pi-embedded-subscribe.handlers.tools.js +2 -2
- package/dist/agents/pi-embedded-subscribe.js +9 -4
- package/dist/agents/pi-embedded-subscribe.tools.js +68 -14
- package/dist/agents/pi-embedded-utils.js +3 -0
- package/dist/agents/pi-extensions/compaction-safeguard-runtime.js +4 -20
- package/dist/agents/pi-extensions/compaction-safeguard.js +75 -33
- package/dist/agents/pi-settings.js +40 -0
- package/dist/agents/pi-tools.policy.js +2 -1
- package/dist/agents/provider/config-loader.js +1 -1
- package/dist/agents/sandbox/browser.js +170 -33
- package/dist/agents/sandbox/config-hash.js +14 -27
- package/dist/agents/sandbox/config.js +21 -2
- package/dist/agents/sandbox/constants.js +2 -0
- package/dist/agents/sandbox/docker.js +16 -2
- package/dist/agents/sandbox/novnc-auth.js +62 -0
- package/dist/agents/sandbox/sanitize-env-vars.js +1 -1
- package/dist/agents/sandbox/shared.js +10 -6
- package/dist/agents/sandbox-paths.js +24 -11
- package/dist/agents/schema/clean-for-gemini.js +132 -85
- package/dist/agents/session-slug.js +10 -5
- package/dist/agents/session-tool-result-guard-wrapper.js +1 -0
- package/dist/agents/session-tool-result-guard.js +3 -1
- package/dist/agents/session-transcript-repair.js +40 -6
- package/dist/agents/skills/bundled-dir.js +19 -5
- package/dist/agents/skills/env-overrides.js +124 -43
- package/dist/agents/skills/frontmatter.js +6 -6
- package/dist/agents/skills/plugin-skills.js +14 -7
- package/dist/agents/skills/workspace.js +1 -0
- package/dist/agents/skills.test-helpers.js +13 -0
- package/dist/agents/stable-stringify.js +12 -0
- package/dist/agents/subagent-announce.js +251 -49
- package/dist/agents/subagent-lifecycle-events.js +19 -0
- package/dist/agents/subagent-registry-cleanup.js +31 -0
- package/dist/agents/subagent-registry-completion.js +68 -0
- package/dist/agents/subagent-registry-queries.js +117 -0
- package/dist/agents/subagent-registry-state.js +46 -0
- package/dist/agents/subagent-registry.js +252 -221
- package/dist/agents/subagent-registry.mocks.shared.js +12 -0
- package/dist/agents/subagent-registry.store.js +1 -0
- package/dist/agents/subagent-registry.types.js +1 -0
- package/dist/agents/subagent-spawn.js +195 -7
- package/dist/agents/system-prompt.js +22 -6
- package/dist/agents/test-helpers/assistant-message-fixtures.js +29 -0
- package/dist/agents/test-helpers/fast-coding-tools.js +1 -18
- package/dist/agents/test-helpers/fast-core-tools.js +1 -17
- package/dist/agents/test-helpers/pi-tools-sandbox-context.js +27 -0
- package/dist/agents/timeout.js +18 -6
- package/dist/agents/tool-call-id.js +1 -1
- package/dist/agents/tool-display-common.js +162 -29
- package/dist/agents/tool-images.js +82 -9
- package/dist/agents/tool-policy-shared.js +108 -0
- package/dist/agents/tool-policy.js +51 -26
- package/dist/agents/tools/browser-tool.js +160 -54
- package/dist/agents/tools/canvas-tool.js +27 -1
- package/dist/agents/tools/common.js +45 -0
- package/dist/agents/tools/cron-tool.test-helpers.js +12 -0
- package/dist/agents/tools/discord-actions-guild.js +4 -1
- package/dist/agents/tools/discord-actions-moderation-shared.js +27 -0
- package/dist/agents/tools/gateway-tool.js +3 -1
- package/dist/agents/tools/image-tool.js +214 -99
- package/dist/agents/tools/nodes-utils.js +1 -10
- package/dist/agents/tools/sessions-history-tool.js +140 -108
- package/dist/agents/tools/sessions-send-helpers.js +12 -6
- package/dist/agents/tools/sessions-spawn-tool.js +8 -2
- package/dist/agents/tools/subagents-tool.js +2 -1
- package/dist/agents/tools/whatsapp-actions.js +10 -2
- package/dist/agents/tools/whatsapp-target-auth.js +18 -0
- package/dist/agents/transcript-policy.js +22 -8
- package/dist/agents/venice-models.js +11 -3
- package/dist/agents/workspace.js +222 -46
- package/dist/auto-reply/commands-registry.data.js +51 -0
- package/dist/auto-reply/commands-registry.js +19 -21
- package/dist/auto-reply/fallback-state.js +114 -0
- package/dist/auto-reply/group-activation.js +10 -5
- package/dist/auto-reply/inbound-debounce.js +10 -5
- package/dist/auto-reply/model-runtime.js +68 -0
- package/dist/auto-reply/reply/abort.js +1 -1
- package/dist/auto-reply/reply/agent-runner-execution.js +40 -5
- package/dist/auto-reply/reply/agent-runner.js +165 -39
- package/dist/auto-reply/reply/bash-command.js +41 -39
- package/dist/auto-reply/reply/command-gates.js +25 -0
- package/dist/auto-reply/reply/commands-allowlist.js +111 -72
- package/dist/auto-reply/reply/commands-bash.js +6 -5
- package/dist/auto-reply/reply/commands-config.js +30 -28
- package/dist/auto-reply/reply/commands-core.js +2 -1
- package/dist/auto-reply/reply/commands-info.js +1 -0
- package/dist/auto-reply/reply/commands-models.js +65 -14
- package/dist/auto-reply/reply/commands-session.js +237 -82
- package/dist/auto-reply/reply/commands-setunset-standard.js +13 -0
- package/dist/auto-reply/reply/commands-setunset.js +45 -0
- package/dist/auto-reply/reply/commands-subagents/action-agents.js +44 -0
- package/dist/auto-reply/reply/commands-subagents/action-focus.js +64 -0
- package/dist/auto-reply/reply/commands-subagents/action-help.js +4 -0
- package/dist/auto-reply/reply/commands-subagents/action-info.js +45 -0
- package/dist/auto-reply/reply/commands-subagents/action-kill.js +60 -0
- package/dist/auto-reply/reply/commands-subagents/action-list.js +44 -0
- package/dist/auto-reply/reply/commands-subagents/action-log.js +29 -0
- package/dist/auto-reply/reply/commands-subagents/action-send.js +119 -0
- package/dist/auto-reply/reply/commands-subagents/action-spawn.js +52 -0
- package/dist/auto-reply/reply/commands-subagents/action-unfocus.js +30 -0
- package/dist/auto-reply/reply/commands-subagents/shared.js +303 -0
- package/dist/auto-reply/reply/commands-subagents.js +51 -587
- package/dist/auto-reply/reply/commands-tts.js +10 -5
- package/dist/auto-reply/reply/config-value.js +10 -5
- package/dist/auto-reply/reply/directive-handling.model-picker.js +12 -6
- package/dist/auto-reply/reply/directive-handling.persist.js +9 -21
- package/dist/auto-reply/reply/directive-handling.shared.js +24 -4
- package/dist/auto-reply/reply/followup-runner.js +1 -0
- package/dist/auto-reply/reply/get-reply-directives-utils.js +23 -14
- package/dist/auto-reply/reply/get-reply-directives.js +17 -28
- package/dist/auto-reply/reply/get-reply-inline-actions.js +1 -0
- package/dist/auto-reply/reply/get-reply.js +71 -12
- package/dist/auto-reply/reply/model-selection.js +80 -39
- package/dist/auto-reply/reply/queue/enqueue.js +10 -5
- package/dist/auto-reply/reply/queue/state.js +13 -12
- package/dist/auto-reply/reply/reply-payloads.js +67 -36
- package/dist/auto-reply/reply/reply-reference.js +9 -8
- package/dist/auto-reply/reply/route-reply.js +15 -8
- package/dist/auto-reply/reply/session-reset-prompt.js +1 -1
- package/dist/auto-reply/reply/session.js +22 -6
- package/dist/auto-reply/reply/strip-inbound-meta.js +147 -0
- package/dist/auto-reply/reply/subagents-utils.js +56 -30
- package/dist/auto-reply/reply/typing.js +46 -21
- package/dist/auto-reply/send-policy.js +14 -7
- package/dist/auto-reply/status.js +140 -16
- package/dist/auto-reply/templating.js +10 -5
- package/dist/auto-reply/thinking.js +7 -16
- package/dist/auto-reply/tokens.js +21 -5
- package/dist/browser/bridge-server.js +36 -20
- package/dist/browser/cdp.helpers.js +7 -14
- package/dist/browser/cdp.js +35 -15
- package/dist/browser/chrome.profile-decoration.js +7 -4
- package/dist/browser/config.js +30 -0
- package/dist/browser/extension-relay-auth.js +55 -0
- package/dist/browser/extension-relay.js +74 -29
- package/dist/browser/navigation-guard.js +39 -0
- package/dist/browser/paths.js +77 -0
- package/dist/browser/profiles.js +13 -8
- package/dist/browser/pw-ai-module.js +10 -5
- package/dist/browser/pw-session.js +76 -39
- package/dist/browser/pw-tools-core.interactions.js +14 -7
- package/dist/browser/pw-tools-core.state.js +12 -6
- package/dist/browser/routes/agent.act.js +431 -424
- package/dist/browser/routes/agent.shared.js +47 -3
- package/dist/browser/routes/agent.snapshot.js +122 -116
- package/dist/browser/routes/agent.storage.js +303 -297
- package/dist/browser/routes/tabs.js +154 -100
- package/dist/browser/server-context.js +7 -0
- package/dist/browser/server-lifecycle.js +37 -0
- package/dist/build-info.json +3 -3
- package/dist/channels/allow-from.js +26 -0
- package/dist/channels/allowlists/resolve-utils.js +43 -19
- package/dist/channels/channel-config.js +14 -7
- package/dist/channels/draft-stream-loop.js +7 -0
- package/dist/channels/model-overrides.js +82 -0
- package/dist/channels/plugins/account-action-gate.js +13 -0
- package/dist/channels/plugins/message-actions.js +10 -0
- package/dist/channels/plugins/normalize/imessage.js +14 -7
- package/dist/channels/plugins/normalize/slack.js +10 -5
- package/dist/channels/plugins/normalize/telegram.js +14 -7
- package/dist/channels/plugins/outbound/discord.js +80 -8
- package/dist/channels/plugins/outbound/signal.js +11 -11
- package/dist/channels/plugins/setup-helpers.js +10 -5
- package/dist/channels/sender-label.js +14 -7
- package/dist/channels/session.js +4 -2
- package/dist/channels/status-reactions.js +297 -0
- package/dist/channels/telegram/api.js +18 -0
- package/dist/cli/argv.js +84 -21
- package/dist/cli/banner.js +3 -2
- package/dist/cli/browser-cli-actions-input/register.files-downloads.js +65 -56
- package/dist/cli/cli-name.js +11 -11
- package/dist/cli/cli-utils.js +13 -3
- package/dist/cli/command-format.js +1 -1
- package/dist/cli/config-cli.js +1 -1
- package/dist/cli/daemon-cli/lifecycle-core.js +31 -19
- package/dist/cli/daemon-cli/lifecycle.js +64 -2
- package/dist/cli/daemon-cli/restart-health.js +126 -0
- package/dist/cli/daemon-cli/status.gather.js +9 -13
- package/dist/cli/daemon-cli/status.print.js +2 -10
- package/dist/cli/deps.js +27 -22
- package/dist/cli/exec-approvals-cli.js +92 -124
- package/dist/cli/gateway-cli/run-loop.js +23 -5
- package/dist/cli/memory-cli.js +158 -61
- package/dist/cli/node-cli/register.js +14 -5
- package/dist/cli/nodes-cli/register.push.js +63 -0
- package/dist/cli/nodes-media-utils.js +26 -0
- package/dist/cli/outbound-send-deps.js +2 -9
- package/dist/cli/outbound-send-mapping.js +11 -0
- package/dist/cli/pairing-cli.js +40 -14
- package/dist/cli/plugins-cli.js +250 -73
- package/dist/cli/ports.js +11 -10
- package/dist/cli/program/build-program.js +3 -1
- package/dist/cli/program/command-registry.js +214 -136
- package/dist/cli/program/command-tree.js +16 -0
- package/dist/cli/program/help.js +43 -12
- package/dist/cli/program/preaction.js +13 -9
- package/dist/cli/program/register.configure.js +3 -18
- package/dist/cli/program/register.maintenance.js +2 -2
- package/dist/cli/program/register.onboard.js +2 -0
- package/dist/cli/program/register.status-health-sessions.js +16 -17
- package/dist/cli/program/register.subclis.js +93 -52
- package/dist/cli/route.js +12 -8
- package/dist/cli/system-cli.js +36 -46
- package/dist/cli/test-runtime-capture.js +24 -0
- package/dist/cli/update-cli/shared.js +22 -9
- package/dist/cli/update-cli/update-command.js +89 -14
- package/dist/cli/update-cli/wizard.js +6 -12
- package/dist/commands/agent/run-context.js +18 -5
- package/dist/commands/agent/session-store.js +17 -4
- package/dist/commands/agent.js +185 -89
- package/dist/commands/agents.bindings.js +14 -7
- package/dist/commands/agents.commands.add.js +13 -9
- package/dist/commands/agents.commands.identity.js +12 -6
- package/dist/commands/agents.commands.list.js +11 -6
- package/dist/commands/agents.config.js +8 -10
- package/dist/commands/agents.providers.js +12 -6
- package/dist/commands/auth-choice-options.js +103 -75
- package/dist/commands/auth-choice.apply.byteplus.js +55 -0
- package/dist/commands/auth-choice.apply.js +4 -0
- package/dist/commands/auth-choice.apply.minimax.js +61 -13
- package/dist/commands/auth-choice.apply.openai.js +3 -1
- package/dist/commands/auth-choice.apply.volcengine.js +55 -0
- package/dist/commands/auth-choice.preferred-provider.js +2 -0
- package/dist/commands/channels/remove.js +13 -6
- package/dist/commands/channels/shared.js +4 -14
- package/dist/commands/channels.mock-harness.js +23 -0
- package/dist/commands/configure.commands.js +14 -0
- package/dist/commands/configure.gateway.js +2 -4
- package/dist/commands/configure.js +1 -1
- package/dist/commands/configure.shared.js +11 -0
- package/dist/commands/daemon-install-helpers.js +2 -2
- package/dist/commands/daemon-install-runtime-warning.js +11 -0
- package/dist/commands/dashboard.js +12 -10
- package/dist/commands/docs.js +14 -8
- package/dist/commands/doctor-config-flow.js +11 -9
- package/dist/commands/doctor-legacy-config.js +281 -0
- package/dist/commands/doctor-state-integrity.js +99 -23
- package/dist/commands/doctor-update.js +12 -9
- package/dist/commands/models/list.list-command.js +7 -5
- package/dist/commands/models/set-image.js +2 -21
- package/dist/commands/node-daemon-install-helpers.js +10 -8
- package/dist/commands/onboard-auth.config-minimax.js +54 -80
- package/dist/commands/onboard-auth.config-opencode.js +2 -18
- package/dist/commands/onboard-auth.credentials.js +90 -13
- package/dist/commands/onboard-auth.js +1 -1
- package/dist/commands/onboard-auth.models.js +6 -5
- package/dist/commands/onboard-hooks.js +1 -1
- package/dist/commands/onboard-non-interactive/api-keys.js +14 -7
- package/dist/commands/onboard-non-interactive/local/auth-choice.js +64 -49
- package/dist/commands/onboard-provider-auth-flags.js +14 -0
- package/dist/commands/onboard-remote.js +14 -7
- package/dist/commands/onboard.js +11 -13
- package/dist/commands/sandbox-display.js +6 -5
- package/dist/commands/sessions.test-helpers.js +61 -0
- package/dist/commands/status-all/diagnosis.js +14 -10
- package/dist/commands/status-all/format.js +1 -0
- package/dist/commands/status.gateway-probe.js +1 -16
- package/dist/commands/systemd-linger.js +12 -6
- package/dist/config/agent-limits.js +2 -0
- package/dist/config/commands.js +32 -15
- package/dist/config/config-paths.js +9 -11
- package/dist/config/config.js +1 -1
- package/dist/config/defaults.js +22 -2
- package/dist/config/discord-preview-streaming.js +104 -0
- package/dist/config/env-substitution.js +62 -34
- package/dist/config/env-vars.js +45 -7
- package/dist/config/includes.js +4 -0
- package/dist/config/io.js +656 -171
- package/dist/config/legacy.migrations.part-1.js +189 -78
- package/dist/config/legacy.shared.js +3 -1
- package/dist/config/merge-patch.js +54 -4
- package/dist/config/prototype-keys.js +4 -0
- package/dist/config/redact-snapshot.js +404 -76
- package/dist/config/schema.help.js +44 -7
- package/dist/config/schema.js +58 -570
- package/dist/config/schema.labels.js +38 -6
- package/dist/config/sessions/delivery-info.js +10 -3
- package/dist/config/sessions/main-session.js +10 -5
- package/dist/config/sessions/session-file.js +33 -0
- package/dist/config/sessions/session-key.js +10 -5
- package/dist/config/sessions/store.js +1 -1
- package/dist/config/sessions.js +1 -0
- package/dist/config/validation.js +140 -85
- package/dist/config/zod-schema.agent-runtime.js +11 -0
- package/dist/config/zod-schema.hooks.js +40 -11
- package/dist/config/zod-schema.installs.js +20 -0
- package/dist/config/zod-schema.js +156 -20
- package/dist/config/zod-schema.providers-core.js +78 -4
- package/dist/config/zod-schema.providers.js +6 -1
- package/dist/config/zod-schema.session.js +41 -2
- package/dist/cron/run-log.js +3 -0
- package/dist/cron/schedule.js +21 -10
- package/dist/cron/service/ops.js +35 -21
- package/dist/cron/service/timer.js +116 -16
- package/dist/cron/stagger.js +3 -1
- package/dist/daemon/cmd-argv.js +21 -0
- package/dist/daemon/cmd-set.js +58 -0
- package/dist/daemon/service-types.js +1 -0
- package/dist/discord/api.js +12 -6
- package/dist/discord/draft-chunking.js +22 -0
- package/dist/discord/draft-stream.js +124 -0
- package/dist/discord/monitor/agent-components.js +1 -1
- package/dist/discord/monitor/commands.js +5 -0
- package/dist/discord/monitor/exec-approvals.js +357 -162
- package/dist/discord/monitor/gateway-plugin.js +2 -1
- package/dist/discord/monitor/listeners.js +37 -27
- package/dist/discord/monitor/message-handler.js +4 -1
- package/dist/discord/monitor/message-handler.preflight.js +65 -8
- package/dist/discord/monitor/message-handler.process.js +246 -217
- package/dist/discord/monitor/message-utils.js +143 -6
- package/dist/discord/monitor/model-picker-preferences.js +143 -0
- package/dist/discord/monitor/model-picker.js +651 -0
- package/dist/discord/monitor/native-command.js +573 -16
- package/dist/discord/monitor/provider.allowlist.js +223 -0
- package/dist/discord/monitor/provider.js +275 -347
- package/dist/discord/monitor/provider.lifecycle.js +100 -0
- package/dist/discord/monitor/reply-delivery.js +123 -16
- package/dist/discord/monitor/thread-bindings.discord-api.js +215 -0
- package/dist/discord/monitor/thread-bindings.js +4 -0
- package/dist/discord/monitor/thread-bindings.lifecycle.js +177 -0
- package/dist/discord/monitor/thread-bindings.manager.js +423 -0
- package/dist/discord/monitor/thread-bindings.messages.js +55 -0
- package/dist/discord/monitor/thread-bindings.state.js +358 -0
- package/dist/discord/monitor/thread-bindings.types.js +6 -0
- package/dist/discord/resolve-users.js +33 -21
- package/dist/discord/send.channels.js +15 -0
- package/dist/discord/send.js +3 -2
- package/dist/discord/send.outbound.js +82 -26
- package/dist/discord/send.permissions.js +83 -30
- package/dist/discord/send.reactions.js +8 -4
- package/dist/discord/token.js +10 -5
- package/dist/discord/voice/command.js +263 -0
- package/dist/discord/voice/manager.js +531 -0
- package/dist/gateway/auth.js +72 -13
- package/dist/gateway/call.js +152 -83
- package/dist/gateway/canvas-capability.js +75 -0
- package/dist/gateway/client.js +28 -4
- package/dist/gateway/config-reload.js +3 -4
- package/dist/gateway/control-plane-audit.js +28 -0
- package/dist/gateway/control-plane-rate-limit.js +53 -0
- package/dist/gateway/control-ui.js +219 -96
- package/dist/gateway/events.js +1 -0
- package/dist/gateway/hooks-mapping.js +88 -38
- package/dist/gateway/hooks.js +109 -54
- package/dist/gateway/http-auth-helpers.js +3 -2
- package/dist/gateway/http-common.js +22 -0
- package/dist/gateway/http-endpoint-helpers.js +1 -0
- package/dist/gateway/method-scopes.js +169 -0
- package/dist/gateway/net.js +74 -9
- package/dist/gateway/node-invoke-system-run-approval.js +14 -35
- package/dist/gateway/node-registry.js +10 -5
- package/dist/gateway/openai-http.js +1 -0
- package/dist/gateway/openresponses-http.js +121 -110
- package/dist/gateway/origin-check.js +1 -18
- package/dist/gateway/probe-auth.js +2 -0
- package/dist/gateway/protocol/index.js +4 -2
- package/dist/gateway/protocol/schema/cron.js +1 -0
- package/dist/gateway/protocol/schema/devices.js +1 -0
- package/dist/gateway/protocol/schema/protocol-schemas.js +4 -1
- package/dist/gateway/protocol/schema/push.js +18 -0
- package/dist/gateway/protocol/schema/sessions.js +6 -0
- package/dist/gateway/protocol/schema.js +1 -0
- package/dist/gateway/role-policy.js +17 -0
- package/dist/gateway/server/ws-connection/connect-policy.js +37 -0
- package/dist/gateway/server/ws-connection/message-handler.js +175 -148
- package/dist/gateway/server-chat.js +83 -25
- package/dist/gateway/server-constants.js +10 -9
- package/dist/gateway/server-cron.js +1 -0
- package/dist/gateway/server-http.js +247 -54
- package/dist/gateway/server-maintenance.js +20 -5
- package/dist/gateway/server-methods/agent.js +162 -24
- package/dist/gateway/server-methods/chat.js +465 -130
- package/dist/gateway/server-methods/config.js +193 -152
- package/dist/gateway/server-methods/devices.js +17 -3
- package/dist/gateway/server-methods/models.js +11 -1
- package/dist/gateway/server-methods/nodes.helpers.js +12 -0
- package/dist/gateway/server-methods/nodes.js +251 -69
- package/dist/gateway/server-methods/push.js +53 -0
- package/dist/gateway/server-methods/sessions.js +64 -8
- package/dist/gateway/server-methods/usage.js +162 -75
- package/dist/gateway/server-node-events.js +29 -0
- package/dist/gateway/server-reload-handlers.js +2 -3
- package/dist/gateway/server-runtime-config.js +39 -13
- package/dist/gateway/server-runtime-state.js +2 -0
- package/dist/gateway/server-startup-memory.js +17 -11
- package/dist/gateway/server-ws-runtime.js +1 -0
- package/dist/gateway/server.impl.js +296 -139
- package/dist/gateway/session-preview.test-helpers.js +11 -0
- package/dist/gateway/session-utils.fs.js +32 -34
- package/dist/gateway/sessions-resolve.js +17 -5
- package/dist/gateway/startup-auth.js +126 -0
- package/dist/gateway/test-helpers.agent-results.js +15 -0
- package/dist/gateway/test-helpers.mocks.js +37 -14
- package/dist/gateway/test-helpers.openai-mock.js +14 -7
- package/dist/gateway/test-helpers.server.js +161 -77
- package/dist/gateway/tools-invoke-http.js +21 -10
- package/dist/hooks/bundled/bootstrap-extra-files/handler.js +3 -1
- package/dist/hooks/bundled/command-logger/handler.js +7 -2
- package/dist/hooks/bundled/session-memory/handler.js +170 -38
- package/dist/hooks/frontmatter.js +6 -6
- package/dist/hooks/gmail-watcher-lifecycle.js +23 -0
- package/dist/hooks/gmail-watcher.js +11 -6
- package/dist/hooks/internal-hooks.js +11 -1
- package/dist/hooks/llm-slug-generator.js +4 -1
- package/dist/hooks/workspace.js +47 -17
- package/dist/imessage/accounts.js +9 -20
- package/dist/imessage/monitor/inbound-processing.js +2 -1
- package/dist/infra/archive-path.js +49 -0
- package/dist/infra/archive.js +174 -73
- package/dist/infra/control-ui-assets.js +14 -6
- package/dist/infra/device-pairing.js +204 -144
- package/dist/infra/env.js +10 -5
- package/dist/infra/exec-approvals-allowlist.js +141 -70
- package/dist/infra/exec-approvals-analysis.js +78 -20
- package/dist/infra/exec-approvals.js +5 -17
- package/dist/infra/exec-safe-bin-policy.js +277 -0
- package/dist/infra/fixed-window-rate-limit.js +33 -0
- package/dist/infra/fs-safe.js +71 -39
- package/dist/infra/gateway-lock.js +6 -2
- package/dist/infra/git-root.js +61 -0
- package/dist/infra/heartbeat-active-hours.js +2 -2
- package/dist/infra/heartbeat-reason.js +40 -0
- package/dist/infra/heartbeat-runner.js +72 -32
- package/dist/infra/heartbeat-wake.js +6 -12
- package/dist/infra/host-env-security-policy.json +19 -0
- package/dist/infra/host-env-security.js +66 -0
- package/dist/infra/install-source-utils.js +91 -7
- package/dist/infra/net/ssrf.js +131 -38
- package/dist/infra/node-pairing.js +50 -105
- package/dist/infra/npm-integrity.js +45 -0
- package/dist/infra/npm-pack-install.js +40 -0
- package/dist/infra/outbound/bound-delivery-router.js +88 -0
- package/dist/infra/outbound/channel-adapters.js +20 -7
- package/dist/infra/outbound/channel-selection.js +12 -6
- package/dist/infra/outbound/envelope.js +1 -1
- package/dist/infra/outbound/format.js +12 -6
- package/dist/infra/outbound/message-action-runner.js +107 -327
- package/dist/infra/outbound/message.js +59 -36
- package/dist/infra/outbound/outbound-policy.js +52 -25
- package/dist/infra/outbound/outbound-send-service.js +58 -71
- package/dist/infra/outbound/payloads.js +14 -7
- package/dist/infra/outbound/session-binding-service.js +123 -0
- package/dist/infra/pairing-files.js +10 -0
- package/dist/infra/path-guards.js +25 -0
- package/dist/infra/plain-object.js +9 -0
- package/dist/infra/provider-usage.fetch.codex.js +7 -15
- package/dist/infra/provider-usage.fetch.gemini.js +14 -11
- package/dist/infra/provider-usage.fetch.shared.js +30 -1
- package/dist/infra/provider-usage.fetch.zai.js +10 -9
- package/dist/infra/push-apns.js +365 -0
- package/dist/infra/restart-sentinel.js +16 -1
- package/dist/infra/restart.js +229 -26
- package/dist/infra/retry-policy.js +4 -2
- package/dist/infra/retry.js +9 -5
- package/dist/infra/scp-host.js +54 -0
- package/dist/infra/session-cost-usage.js +107 -59
- package/dist/infra/session-maintenance-warning.js +3 -1
- package/dist/infra/shell-env.js +98 -34
- package/dist/infra/ssh-config.js +12 -6
- package/dist/infra/system-run-command.js +49 -4
- package/dist/infra/update-channels.js +10 -5
- package/dist/infra/update-startup.js +86 -9
- package/dist/line/accounts.js +5 -7
- package/dist/line/bot-access.js +8 -20
- package/dist/line/bot-handlers.js +3 -1
- package/dist/link-understanding/detect.js +15 -7
- package/dist/media/constants.js +15 -6
- package/dist/media/image-ops.js +7 -0
- package/dist/media/inbound-path-policy.js +114 -0
- package/dist/media/input-files.js +16 -0
- package/dist/media/local-roots.js +3 -2
- package/dist/media-understanding/apply.js +4 -1
- package/dist/media-understanding/concurrency.js +8 -20
- package/dist/memory/backend-config.js +45 -6
- package/dist/memory/embeddings.js +10 -4
- package/dist/memory/fs-utils.js +23 -0
- package/dist/memory/manager-search.js +12 -6
- package/dist/memory/manager-sync-ops.js +12 -2
- package/dist/memory/qmd-manager.js +466 -53
- package/dist/memory/query-expansion.js +167 -3
- package/dist/memory/status-format.js +10 -5
- package/dist/memory/sync-memory-files.js +1 -1
- package/dist/memory/test-manager.js +8 -0
- package/dist/node-host/invoke-system-run.js +281 -0
- package/dist/node-host/invoke.js +55 -337
- package/dist/pairing/pairing-store.js +22 -0
- package/dist/plugin-sdk/allow-from.js +1 -1
- package/dist/plugin-sdk/command-auth.js +3 -1
- package/dist/plugin-sdk/index.js +6 -3
- package/dist/plugin-sdk/temp-path.js +47 -0
- package/dist/plugin-sdk/webhook-targets.js +32 -0
- package/dist/plugins/bundled-dir.js +9 -6
- package/dist/plugins/discovery.js +217 -23
- package/dist/plugins/hook-runner-global.js +16 -0
- package/dist/plugins/hooks.js +50 -0
- package/dist/plugins/install.js +28 -16
- package/dist/plugins/loader.js +192 -26
- package/dist/plugins/logger.js +8 -0
- package/dist/plugins/manifest-registry.js +3 -0
- package/dist/plugins/path-safety.js +34 -0
- package/dist/plugins/registry.js +5 -2
- package/dist/plugins/runtime/index.js +271 -206
- package/dist/plugins/runtime.js +3 -17
- package/dist/plugins/update.js +78 -12
- package/dist/process/spawn-utils.js +14 -7
- package/dist/providers/github-copilot-models.js +4 -1
- package/dist/providers/github-copilot-token.js +11 -6
- package/dist/providers/qwen-portal-oauth.js +14 -6
- package/dist/routing/account-id.js +30 -0
- package/dist/routing/resolve-route.js +3 -7
- package/dist/routing/session-key.js +2 -16
- package/dist/security/audit-channel.js +100 -20
- package/dist/security/audit-extra.async.js +505 -179
- package/dist/security/audit-extra.js +12 -2
- package/dist/security/audit-extra.sync.js +421 -35
- package/dist/security/audit-fs.js +31 -13
- package/dist/security/audit.js +180 -370
- package/dist/security/dm-policy-shared.js +68 -0
- package/dist/security/external-content.js +46 -14
- package/dist/security/fix.js +49 -85
- package/dist/security/scan-paths.js +20 -0
- package/dist/security/secret-equal.js +3 -7
- package/dist/security/windows-acl.js +30 -15
- package/dist/shared/entry-status.js +6 -0
- package/dist/shared/frontmatter.js +5 -5
- package/dist/shared/node-list-parse.js +13 -0
- package/dist/shared/node-match.js +11 -4
- package/dist/shared/operator-scope-compat.js +42 -0
- package/dist/shared/text-chunking.js +29 -0
- package/dist/signal/accounts.js +7 -20
- package/dist/signal/monitor/event-handler.js +3 -1
- package/dist/slack/accounts.js +6 -19
- package/dist/slack/actions.js +11 -3
- package/dist/slack/blocks.test-helpers.js +31 -0
- package/dist/slack/monitor/auth.js +1 -1
- package/dist/slack/monitor/message-handler/dispatch.js +50 -29
- package/dist/slack/monitor/mrkdwn.js +8 -0
- package/dist/slack/monitor/replies.js +15 -7
- package/dist/slack/monitor/slash.js +22 -13
- package/dist/slack/resolve-channels.js +10 -5
- package/dist/slack/send.js +102 -12
- package/dist/slack/stream-mode.js +10 -0
- package/dist/slack/streaming.js +4 -2
- package/dist/telegram/accounts.js +19 -14
- package/dist/telegram/bot/helpers.js +3 -5
- package/dist/telegram/bot-access.js +35 -36
- package/dist/telegram/bot-handlers.js +120 -148
- package/dist/telegram/bot-message-context.js +68 -9
- package/dist/telegram/bot-message-dispatch.js +477 -210
- package/dist/telegram/bot-native-commands.js +16 -0
- package/dist/telegram/draft-stream.js +44 -8
- package/dist/telegram/inline-buttons.js +5 -15
- package/dist/telegram/monitor.js +11 -7
- package/dist/telegram/network-config.js +19 -7
- package/dist/telegram/reasoning-lane-coordinator.js +128 -0
- package/dist/telegram/send.js +3 -2
- package/dist/telegram/sent-message-cache.js +5 -6
- package/dist/telegram/status-reaction-variants.js +208 -0
- package/dist/telegram/sticker-cache.js +11 -9
- package/dist/terminal/prompt-select-styled.js +9 -0
- package/dist/terminal/theme.js +12 -12
- package/dist/test-utils/command-runner.js +6 -0
- package/dist/test-utils/internal-hook-event-payload.js +10 -0
- package/dist/test-utils/model-auth-mock.js +12 -0
- package/dist/test-utils/provider-usage-fetch.js +14 -0
- package/dist/test-utils/temp-home.js +33 -0
- package/dist/tts/tts.js +80 -567
- package/dist/tui/components/chat-log.js +50 -8
- package/dist/tui/theme/theme.js +10 -12
- package/dist/tui/tui-command-handlers.js +36 -27
- package/dist/tui/tui-event-handlers.js +122 -32
- package/dist/tui/tui-local-shell.js +16 -6
- package/dist/tui/tui.js +236 -48
- package/dist/utils/account-id.js +2 -4
- package/dist/utils/boolean.js +10 -5
- package/dist/utils/directive-tags.js +11 -0
- package/dist/utils/mask-api-key.js +10 -0
- package/dist/utils/queue-helpers.js +67 -12
- package/dist/utils/run-with-concurrency.js +39 -0
- package/dist/web/auto-reply/deliver-reply.js +8 -4
- package/dist/web/auto-reply/mentions.js +10 -5
- package/dist/web/auto-reply/monitor/group-members.js +14 -7
- package/dist/web/auto-reply/monitor/process-message.js +45 -24
- package/dist/web/inbound/access-control.js +5 -2
- package/dist/web/login-qr.js +12 -6
- package/dist/web/media.js +126 -15
- package/docs/tools/slash-commands.md +5 -1
- package/extensions/bluebubbles/src/monitor-processing.ts +580 -139
- package/extensions/bluebubbles/src/monitor.ts +208 -1950
- package/extensions/feishu/src/external-keys.ts +19 -0
- package/extensions/lobster/src/windows-spawn.ts +193 -0
- package/extensions/matrix/src/matrix/actions/limits.ts +6 -0
- package/extensions/mattermost/src/mattermost/reactions.test-helpers.ts +83 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,24 @@
|
|
|
1
|
+
## v2026.2.25 (2026-02-22)
|
|
2
|
+
|
|
3
|
+
### Features
|
|
4
|
+
- **Upstream Port (OpenClaw):** ported 26 files from OpenClaw upstream covering agents, auto-reply, browser, gateway, hooks, plugins, config, and CLI
|
|
5
|
+
- **Agent tooling:** sandbox filesystem bridge, host sandbox bridge helpers, workspace sandbox integration, model fallback provider updates (openai/gpt-4.1-mini default)
|
|
6
|
+
- **Auto-reply:** commands registry extensions, templating updates, agent runner execution improvements, verbose-gated session notices
|
|
7
|
+
- **Browser:** config updates, agent act/snapshot/storage routes, tabs route enhancements, form layout contract tests
|
|
8
|
+
- **Gateway:** hook token extraction with query-string fallback, normalized agent payload with auto-generated session keys, HTTP server integration
|
|
9
|
+
- **Plugins:** plugin discovery and loading aligned with upstream patterns
|
|
10
|
+
- **Config:** browser config, CLI config, and schema updates
|
|
11
|
+
|
|
12
|
+
### Fixes
|
|
13
|
+
- **Tests:** fixed 9 pre-existing test failures across 6 test files (52 tests total)
|
|
14
|
+
- `model-fallback.test.ts`: updated expectations for openai/gpt-4.1-mini default
|
|
15
|
+
- `image-tool.test.ts`: aligned sandbox parameter structure with new bridge API
|
|
16
|
+
- `hooks.test.ts`: updated for new `extractHookToken` and `normalizeAgentPayload` signatures
|
|
17
|
+
- `poolbot-tools.sessions.test.ts`: added mock sessions.list handler for spawned sessions
|
|
18
|
+
- `reply.media-note.test.ts` / `reply.raw-body.test.ts`: verbose-gated session notice, rebranded env vars and paths
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
1
22
|
## v2026.2.24 (2026-02-19)
|
|
2
23
|
|
|
3
24
|
### Fixes
|
package/dist/acp/client.js
CHANGED
|
@@ -1,11 +1,187 @@
|
|
|
1
1
|
import { spawn } from "node:child_process";
|
|
2
|
+
import fs from "node:fs";
|
|
3
|
+
import path from "node:path";
|
|
2
4
|
import * as readline from "node:readline";
|
|
3
5
|
import { Readable, Writable } from "node:stream";
|
|
6
|
+
import { fileURLToPath } from "node:url";
|
|
4
7
|
import { ClientSideConnection, PROTOCOL_VERSION, ndJsonStream, } from "@agentclientprotocol/sdk";
|
|
5
8
|
import { ensurePoolbotCliOnPath } from "../infra/path-env.js";
|
|
9
|
+
import { DANGEROUS_ACP_TOOLS } from "../security/dangerous-tools.js";
|
|
10
|
+
const SAFE_AUTO_APPROVE_KINDS = new Set(["read", "search"]);
|
|
11
|
+
function asRecord(value) {
|
|
12
|
+
return value && typeof value === "object" && !Array.isArray(value)
|
|
13
|
+
? value
|
|
14
|
+
: undefined;
|
|
15
|
+
}
|
|
16
|
+
function readFirstStringValue(source, keys) {
|
|
17
|
+
if (!source) {
|
|
18
|
+
return undefined;
|
|
19
|
+
}
|
|
20
|
+
for (const key of keys) {
|
|
21
|
+
const value = source[key];
|
|
22
|
+
if (typeof value === "string" && value.trim()) {
|
|
23
|
+
return value.trim();
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
return undefined;
|
|
27
|
+
}
|
|
28
|
+
function normalizeToolName(value) {
|
|
29
|
+
const normalized = value.trim().toLowerCase();
|
|
30
|
+
if (!normalized) {
|
|
31
|
+
return undefined;
|
|
32
|
+
}
|
|
33
|
+
return normalized;
|
|
34
|
+
}
|
|
35
|
+
function parseToolNameFromTitle(title) {
|
|
36
|
+
if (!title) {
|
|
37
|
+
return undefined;
|
|
38
|
+
}
|
|
39
|
+
const head = title.split(":", 1)[0]?.trim();
|
|
40
|
+
if (!head || !/^[a-zA-Z0-9._-]+$/.test(head)) {
|
|
41
|
+
return undefined;
|
|
42
|
+
}
|
|
43
|
+
return normalizeToolName(head);
|
|
44
|
+
}
|
|
45
|
+
function resolveToolKindForPermission(params, toolName) {
|
|
46
|
+
const toolCall = params.toolCall;
|
|
47
|
+
const kindRaw = typeof toolCall?.kind === "string" ? toolCall.kind.trim().toLowerCase() : "";
|
|
48
|
+
if (kindRaw) {
|
|
49
|
+
return kindRaw;
|
|
50
|
+
}
|
|
51
|
+
const name = toolName ??
|
|
52
|
+
parseToolNameFromTitle(typeof toolCall?.title === "string" ? toolCall.title : undefined);
|
|
53
|
+
if (!name) {
|
|
54
|
+
return undefined;
|
|
55
|
+
}
|
|
56
|
+
const normalized = name.toLowerCase();
|
|
57
|
+
const hasToken = (token) => {
|
|
58
|
+
// Tool names tend to be snake_case. Avoid substring heuristics (ex: "thread" contains "read").
|
|
59
|
+
const re = new RegExp(`(?:^|[._-])${token}(?:$|[._-])`);
|
|
60
|
+
return re.test(normalized);
|
|
61
|
+
};
|
|
62
|
+
// Prefer a conservative classifier: only classify safe kinds when confident.
|
|
63
|
+
if (normalized === "read" || hasToken("read")) {
|
|
64
|
+
return "read";
|
|
65
|
+
}
|
|
66
|
+
if (normalized === "search" || hasToken("search") || hasToken("find")) {
|
|
67
|
+
return "search";
|
|
68
|
+
}
|
|
69
|
+
if (normalized.includes("fetch") || normalized.includes("http")) {
|
|
70
|
+
return "fetch";
|
|
71
|
+
}
|
|
72
|
+
if (normalized.includes("write") || normalized.includes("edit") || normalized.includes("patch")) {
|
|
73
|
+
return "edit";
|
|
74
|
+
}
|
|
75
|
+
if (normalized.includes("delete") || normalized.includes("remove")) {
|
|
76
|
+
return "delete";
|
|
77
|
+
}
|
|
78
|
+
if (normalized.includes("move") || normalized.includes("rename")) {
|
|
79
|
+
return "move";
|
|
80
|
+
}
|
|
81
|
+
if (normalized.includes("exec") || normalized.includes("run") || normalized.includes("bash")) {
|
|
82
|
+
return "execute";
|
|
83
|
+
}
|
|
84
|
+
return "other";
|
|
85
|
+
}
|
|
86
|
+
function resolveToolNameForPermission(params) {
|
|
87
|
+
const toolCall = params.toolCall;
|
|
88
|
+
const toolMeta = asRecord(toolCall?._meta);
|
|
89
|
+
const rawInput = asRecord(toolCall?.rawInput);
|
|
90
|
+
const fromMeta = readFirstStringValue(toolMeta, ["toolName", "tool_name", "name"]);
|
|
91
|
+
const fromRawInput = readFirstStringValue(rawInput, ["tool", "toolName", "tool_name", "name"]);
|
|
92
|
+
const fromTitle = parseToolNameFromTitle(toolCall?.title);
|
|
93
|
+
return normalizeToolName(fromMeta ?? fromRawInput ?? fromTitle ?? "");
|
|
94
|
+
}
|
|
95
|
+
function pickOption(options, kinds) {
|
|
96
|
+
for (const kind of kinds) {
|
|
97
|
+
const match = options.find((option) => option.kind === kind);
|
|
98
|
+
if (match) {
|
|
99
|
+
return match;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
return undefined;
|
|
103
|
+
}
|
|
104
|
+
function selectedPermission(optionId) {
|
|
105
|
+
return { outcome: { outcome: "selected", optionId } };
|
|
106
|
+
}
|
|
107
|
+
function cancelledPermission() {
|
|
108
|
+
return { outcome: { outcome: "cancelled" } };
|
|
109
|
+
}
|
|
110
|
+
function promptUserPermission(toolName, toolTitle) {
|
|
111
|
+
if (!process.stdin.isTTY || !process.stderr.isTTY) {
|
|
112
|
+
console.error(`[permission denied] ${toolName ?? "unknown"}: non-interactive terminal`);
|
|
113
|
+
return Promise.resolve(false);
|
|
114
|
+
}
|
|
115
|
+
return new Promise((resolve) => {
|
|
116
|
+
let settled = false;
|
|
117
|
+
const rl = readline.createInterface({
|
|
118
|
+
input: process.stdin,
|
|
119
|
+
output: process.stderr,
|
|
120
|
+
});
|
|
121
|
+
const finish = (approved) => {
|
|
122
|
+
if (settled) {
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
settled = true;
|
|
126
|
+
clearTimeout(timeout);
|
|
127
|
+
rl.close();
|
|
128
|
+
resolve(approved);
|
|
129
|
+
};
|
|
130
|
+
const timeout = setTimeout(() => {
|
|
131
|
+
console.error(`\n[permission timeout] denied: ${toolName ?? "unknown"}`);
|
|
132
|
+
finish(false);
|
|
133
|
+
}, 30_000);
|
|
134
|
+
const label = toolTitle
|
|
135
|
+
? toolName
|
|
136
|
+
? `${toolTitle} (${toolName})`
|
|
137
|
+
: toolTitle
|
|
138
|
+
: (toolName ?? "unknown tool");
|
|
139
|
+
rl.question(`\n[permission] Allow "${label}"? (y/N) `, (answer) => {
|
|
140
|
+
const approved = answer.trim().toLowerCase() === "y";
|
|
141
|
+
console.error(`[permission ${approved ? "approved" : "denied"}] ${toolName ?? "unknown"}`);
|
|
142
|
+
finish(approved);
|
|
143
|
+
});
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
export async function resolvePermissionRequest(params, deps = {}) {
|
|
147
|
+
const log = deps.log ?? ((line) => console.error(line));
|
|
148
|
+
const prompt = deps.prompt ?? promptUserPermission;
|
|
149
|
+
const options = params.options ?? [];
|
|
150
|
+
const toolTitle = params.toolCall?.title ?? "tool";
|
|
151
|
+
const toolName = resolveToolNameForPermission(params);
|
|
152
|
+
const toolKind = resolveToolKindForPermission(params, toolName);
|
|
153
|
+
if (options.length === 0) {
|
|
154
|
+
log(`[permission cancelled] ${toolName ?? "unknown"}: no options available`);
|
|
155
|
+
return cancelledPermission();
|
|
156
|
+
}
|
|
157
|
+
const allowOption = pickOption(options, ["allow_once", "allow_always"]);
|
|
158
|
+
const rejectOption = pickOption(options, ["reject_once", "reject_always"]);
|
|
159
|
+
const isSafeKind = Boolean(toolKind && SAFE_AUTO_APPROVE_KINDS.has(toolKind));
|
|
160
|
+
const promptRequired = !toolName || !isSafeKind || DANGEROUS_ACP_TOOLS.has(toolName);
|
|
161
|
+
if (!promptRequired) {
|
|
162
|
+
const option = allowOption ?? options[0];
|
|
163
|
+
if (!option) {
|
|
164
|
+
log(`[permission cancelled] ${toolName}: no selectable options`);
|
|
165
|
+
return cancelledPermission();
|
|
166
|
+
}
|
|
167
|
+
log(`[permission auto-approved] ${toolName} (${toolKind ?? "unknown"})`);
|
|
168
|
+
return selectedPermission(option.optionId);
|
|
169
|
+
}
|
|
170
|
+
log(`\n[permission requested] ${toolTitle}${toolName ? ` (${toolName})` : ""}${toolKind ? ` [${toolKind}]` : ""}`);
|
|
171
|
+
const approved = await prompt(toolName, toolTitle);
|
|
172
|
+
if (approved && allowOption) {
|
|
173
|
+
return selectedPermission(allowOption.optionId);
|
|
174
|
+
}
|
|
175
|
+
if (!approved && rejectOption) {
|
|
176
|
+
return selectedPermission(rejectOption.optionId);
|
|
177
|
+
}
|
|
178
|
+
log(`[permission cancelled] ${toolName ?? "unknown"}: missing ${approved ? "allow" : "reject"} option`);
|
|
179
|
+
return cancelledPermission();
|
|
180
|
+
}
|
|
6
181
|
function toArgs(value) {
|
|
7
|
-
if (!value)
|
|
182
|
+
if (!value) {
|
|
8
183
|
return [];
|
|
184
|
+
}
|
|
9
185
|
return Array.isArray(value) ? value : [value];
|
|
10
186
|
}
|
|
11
187
|
function buildServerArgs(opts) {
|
|
@@ -15,10 +191,29 @@ function buildServerArgs(opts) {
|
|
|
15
191
|
}
|
|
16
192
|
return args;
|
|
17
193
|
}
|
|
194
|
+
function resolveSelfEntryPath() {
|
|
195
|
+
// Prefer a path relative to the built module location (dist/acp/client.js -> dist/entry.js).
|
|
196
|
+
try {
|
|
197
|
+
const here = fileURLToPath(import.meta.url);
|
|
198
|
+
const candidate = path.resolve(path.dirname(here), "..", "entry.js");
|
|
199
|
+
if (fs.existsSync(candidate)) {
|
|
200
|
+
return candidate;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
catch {
|
|
204
|
+
// ignore
|
|
205
|
+
}
|
|
206
|
+
const argv1 = process.argv[1]?.trim();
|
|
207
|
+
if (argv1) {
|
|
208
|
+
return path.isAbsolute(argv1) ? argv1 : path.resolve(process.cwd(), argv1);
|
|
209
|
+
}
|
|
210
|
+
return null;
|
|
211
|
+
}
|
|
18
212
|
function printSessionUpdate(notification) {
|
|
19
213
|
const update = notification.update;
|
|
20
|
-
if (!("sessionUpdate" in update))
|
|
214
|
+
if (!("sessionUpdate" in update)) {
|
|
21
215
|
return;
|
|
216
|
+
}
|
|
22
217
|
switch (update.sessionUpdate) {
|
|
23
218
|
case "agent_message_chunk": {
|
|
24
219
|
if (update.content?.type === "text") {
|
|
@@ -38,8 +233,9 @@ function printSessionUpdate(notification) {
|
|
|
38
233
|
}
|
|
39
234
|
case "available_commands_update": {
|
|
40
235
|
const names = update.availableCommands?.map((cmd) => `/${cmd.name}`).join(" ");
|
|
41
|
-
if (names)
|
|
236
|
+
if (names) {
|
|
42
237
|
console.log(`\n[commands] ${names}`);
|
|
238
|
+
}
|
|
43
239
|
return;
|
|
44
240
|
}
|
|
45
241
|
default:
|
|
@@ -50,11 +246,13 @@ export async function createAcpClient(opts = {}) {
|
|
|
50
246
|
const cwd = opts.cwd ?? process.cwd();
|
|
51
247
|
const verbose = Boolean(opts.verbose);
|
|
52
248
|
const log = verbose ? (msg) => console.error(`[acp-client] ${msg}`) : () => { };
|
|
53
|
-
ensurePoolbotCliOnPath(
|
|
54
|
-
const serverCommand = opts.serverCommand ?? "poolbot";
|
|
249
|
+
ensurePoolbotCliOnPath();
|
|
55
250
|
const serverArgs = buildServerArgs(opts);
|
|
56
|
-
|
|
57
|
-
const
|
|
251
|
+
const entryPath = resolveSelfEntryPath();
|
|
252
|
+
const serverCommand = opts.serverCommand ?? (entryPath ? process.execPath : "poolbot");
|
|
253
|
+
const effectiveArgs = opts.serverCommand || !entryPath ? serverArgs : [entryPath, ...serverArgs];
|
|
254
|
+
log(`spawning: ${serverCommand} ${effectiveArgs.join(" ")}`);
|
|
255
|
+
const agent = spawn(serverCommand, effectiveArgs, {
|
|
58
256
|
stdio: ["pipe", "pipe", "inherit"],
|
|
59
257
|
cwd,
|
|
60
258
|
});
|
|
@@ -69,16 +267,7 @@ export async function createAcpClient(opts = {}) {
|
|
|
69
267
|
printSessionUpdate(params);
|
|
70
268
|
},
|
|
71
269
|
requestPermission: async (params) => {
|
|
72
|
-
|
|
73
|
-
const options = params.options ?? [];
|
|
74
|
-
const allowOnce = options.find((option) => option.kind === "allow_once");
|
|
75
|
-
const fallback = options[0];
|
|
76
|
-
return {
|
|
77
|
-
outcome: {
|
|
78
|
-
outcome: "selected",
|
|
79
|
-
optionId: allowOnce?.optionId ?? fallback?.optionId ?? "allow",
|
|
80
|
-
},
|
|
81
|
-
};
|
|
270
|
+
return resolvePermissionRequest(params);
|
|
82
271
|
},
|
|
83
272
|
}), stream);
|
|
84
273
|
log("initializing");
|
|
@@ -107,7 +296,7 @@ export async function runAcpClientInteractive(opts = {}) {
|
|
|
107
296
|
input: process.stdin,
|
|
108
297
|
output: process.stdout,
|
|
109
298
|
});
|
|
110
|
-
console.log("
|
|
299
|
+
console.log("Pool Bot ACP client");
|
|
111
300
|
console.log(`Session: ${sessionId}`);
|
|
112
301
|
console.log('Type a prompt, or "exit" to quit.\n');
|
|
113
302
|
const prompt = () => {
|
package/dist/acp/event-mapper.js
CHANGED
|
@@ -1,21 +1,76 @@
|
|
|
1
|
-
|
|
1
|
+
const INLINE_CONTROL_ESCAPE_MAP = {
|
|
2
|
+
"\0": "\\0",
|
|
3
|
+
"\r": "\\r",
|
|
4
|
+
"\n": "\\n",
|
|
5
|
+
"\t": "\\t",
|
|
6
|
+
"\v": "\\v",
|
|
7
|
+
"\f": "\\f",
|
|
8
|
+
"\u2028": "\\u2028",
|
|
9
|
+
"\u2029": "\\u2029",
|
|
10
|
+
};
|
|
11
|
+
function escapeInlineControlChars(value) {
|
|
12
|
+
let escaped = "";
|
|
13
|
+
for (const char of value) {
|
|
14
|
+
const codePoint = char.codePointAt(0);
|
|
15
|
+
if (codePoint === undefined) {
|
|
16
|
+
escaped += char;
|
|
17
|
+
continue;
|
|
18
|
+
}
|
|
19
|
+
const isInlineControl = codePoint <= 0x1f ||
|
|
20
|
+
(codePoint >= 0x7f && codePoint <= 0x9f) ||
|
|
21
|
+
codePoint === 0x2028 ||
|
|
22
|
+
codePoint === 0x2029;
|
|
23
|
+
if (!isInlineControl) {
|
|
24
|
+
escaped += char;
|
|
25
|
+
continue;
|
|
26
|
+
}
|
|
27
|
+
const mapped = INLINE_CONTROL_ESCAPE_MAP[char];
|
|
28
|
+
if (mapped) {
|
|
29
|
+
escaped += mapped;
|
|
30
|
+
continue;
|
|
31
|
+
}
|
|
32
|
+
// Keep escaped control bytes readable and stable in logs/prompts.
|
|
33
|
+
escaped +=
|
|
34
|
+
codePoint <= 0xff
|
|
35
|
+
? `\\x${codePoint.toString(16).padStart(2, "0")}`
|
|
36
|
+
: `\\u${codePoint.toString(16).padStart(4, "0")}`;
|
|
37
|
+
}
|
|
38
|
+
return escaped;
|
|
39
|
+
}
|
|
40
|
+
function escapeResourceTitle(value) {
|
|
41
|
+
// Keep title content, but escape characters that can break the resource-link annotation shape.
|
|
42
|
+
return escapeInlineControlChars(value).replace(/[()[\]]/g, (char) => `\\${char}`);
|
|
43
|
+
}
|
|
44
|
+
export function extractTextFromPrompt(prompt, maxBytes) {
|
|
2
45
|
const parts = [];
|
|
46
|
+
// Track accumulated byte count per block to catch oversized prompts before full concatenation
|
|
47
|
+
let totalBytes = 0;
|
|
3
48
|
for (const block of prompt) {
|
|
49
|
+
let blockText;
|
|
4
50
|
if (block.type === "text") {
|
|
5
|
-
|
|
6
|
-
continue;
|
|
51
|
+
blockText = block.text;
|
|
7
52
|
}
|
|
8
|
-
if (block.type === "resource") {
|
|
53
|
+
else if (block.type === "resource") {
|
|
9
54
|
const resource = block.resource;
|
|
10
|
-
if (resource?.text)
|
|
11
|
-
|
|
12
|
-
|
|
55
|
+
if (resource?.text) {
|
|
56
|
+
blockText = resource.text;
|
|
57
|
+
}
|
|
13
58
|
}
|
|
14
|
-
if (block.type === "resource_link") {
|
|
15
|
-
const title = block.title ? ` (${block.title})` : "";
|
|
16
|
-
const uri = block.uri
|
|
17
|
-
|
|
18
|
-
|
|
59
|
+
else if (block.type === "resource_link") {
|
|
60
|
+
const title = block.title ? ` (${escapeResourceTitle(block.title)})` : "";
|
|
61
|
+
const uri = block.uri ? escapeInlineControlChars(block.uri) : "";
|
|
62
|
+
blockText = uri ? `[Resource link${title}] ${uri}` : `[Resource link${title}]`;
|
|
63
|
+
}
|
|
64
|
+
if (blockText !== undefined) {
|
|
65
|
+
// Guard: reject before allocating the full concatenated string
|
|
66
|
+
if (maxBytes !== undefined) {
|
|
67
|
+
const separatorBytes = parts.length > 0 ? 1 : 0; // "\n" added by join() between blocks
|
|
68
|
+
totalBytes += separatorBytes + Buffer.byteLength(blockText, "utf-8");
|
|
69
|
+
if (totalBytes > maxBytes) {
|
|
70
|
+
throw new Error(`Prompt exceeds maximum allowed size of ${maxBytes} bytes`);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
parts.push(blockText);
|
|
19
74
|
}
|
|
20
75
|
}
|
|
21
76
|
return parts.join("\n");
|
|
@@ -23,11 +78,13 @@ export function extractTextFromPrompt(prompt) {
|
|
|
23
78
|
export function extractAttachmentsFromPrompt(prompt) {
|
|
24
79
|
const attachments = [];
|
|
25
80
|
for (const block of prompt) {
|
|
26
|
-
if (block.type !== "image")
|
|
81
|
+
if (block.type !== "image") {
|
|
27
82
|
continue;
|
|
83
|
+
}
|
|
28
84
|
const image = block;
|
|
29
|
-
if (!image.data || !image.mimeType)
|
|
85
|
+
if (!image.data || !image.mimeType) {
|
|
30
86
|
continue;
|
|
87
|
+
}
|
|
31
88
|
attachments.push({
|
|
32
89
|
type: "image",
|
|
33
90
|
mimeType: image.mimeType,
|
|
@@ -38,8 +95,9 @@ export function extractAttachmentsFromPrompt(prompt) {
|
|
|
38
95
|
}
|
|
39
96
|
export function formatToolTitle(name, args) {
|
|
40
97
|
const base = name ?? "tool";
|
|
41
|
-
if (!args || Object.keys(args).length === 0)
|
|
98
|
+
if (!args || Object.keys(args).length === 0) {
|
|
42
99
|
return base;
|
|
100
|
+
}
|
|
43
101
|
const parts = Object.entries(args).map(([key, value]) => {
|
|
44
102
|
const raw = typeof value === "string" ? value : JSON.stringify(value);
|
|
45
103
|
const safe = raw.length > 100 ? `${raw.slice(0, 100)}...` : raw;
|
|
@@ -48,23 +106,30 @@ export function formatToolTitle(name, args) {
|
|
|
48
106
|
return `${base}: ${parts.join(", ")}`;
|
|
49
107
|
}
|
|
50
108
|
export function inferToolKind(name) {
|
|
51
|
-
if (!name)
|
|
109
|
+
if (!name) {
|
|
52
110
|
return "other";
|
|
111
|
+
}
|
|
53
112
|
const normalized = name.toLowerCase();
|
|
54
|
-
if (normalized.includes("read"))
|
|
113
|
+
if (normalized.includes("read")) {
|
|
55
114
|
return "read";
|
|
56
|
-
|
|
115
|
+
}
|
|
116
|
+
if (normalized.includes("write") || normalized.includes("edit")) {
|
|
57
117
|
return "edit";
|
|
58
|
-
|
|
118
|
+
}
|
|
119
|
+
if (normalized.includes("delete") || normalized.includes("remove")) {
|
|
59
120
|
return "delete";
|
|
60
|
-
|
|
121
|
+
}
|
|
122
|
+
if (normalized.includes("move") || normalized.includes("rename")) {
|
|
61
123
|
return "move";
|
|
62
|
-
|
|
124
|
+
}
|
|
125
|
+
if (normalized.includes("search") || normalized.includes("find")) {
|
|
63
126
|
return "search";
|
|
127
|
+
}
|
|
64
128
|
if (normalized.includes("exec") || normalized.includes("run") || normalized.includes("bash")) {
|
|
65
129
|
return "execute";
|
|
66
130
|
}
|
|
67
|
-
if (normalized.includes("fetch") || normalized.includes("http"))
|
|
131
|
+
if (normalized.includes("fetch") || normalized.includes("http")) {
|
|
68
132
|
return "fetch";
|
|
133
|
+
}
|
|
69
134
|
return "other";
|
|
70
135
|
}
|
package/dist/acp/meta.js
CHANGED
|
@@ -1,30 +1,36 @@
|
|
|
1
1
|
export function readString(meta, keys) {
|
|
2
|
-
if (!meta)
|
|
2
|
+
if (!meta) {
|
|
3
3
|
return undefined;
|
|
4
|
+
}
|
|
4
5
|
for (const key of keys) {
|
|
5
6
|
const value = meta[key];
|
|
6
|
-
if (typeof value === "string" && value.trim())
|
|
7
|
+
if (typeof value === "string" && value.trim()) {
|
|
7
8
|
return value.trim();
|
|
9
|
+
}
|
|
8
10
|
}
|
|
9
11
|
return undefined;
|
|
10
12
|
}
|
|
11
13
|
export function readBool(meta, keys) {
|
|
12
|
-
if (!meta)
|
|
14
|
+
if (!meta) {
|
|
13
15
|
return undefined;
|
|
16
|
+
}
|
|
14
17
|
for (const key of keys) {
|
|
15
18
|
const value = meta[key];
|
|
16
|
-
if (typeof value === "boolean")
|
|
19
|
+
if (typeof value === "boolean") {
|
|
17
20
|
return value;
|
|
21
|
+
}
|
|
18
22
|
}
|
|
19
23
|
return undefined;
|
|
20
24
|
}
|
|
21
25
|
export function readNumber(meta, keys) {
|
|
22
|
-
if (!meta)
|
|
26
|
+
if (!meta) {
|
|
23
27
|
return undefined;
|
|
28
|
+
}
|
|
24
29
|
for (const key of keys) {
|
|
25
30
|
const value = meta[key];
|
|
26
|
-
if (typeof value === "number" && Number.isFinite(value))
|
|
31
|
+
if (typeof value === "number" && Number.isFinite(value)) {
|
|
27
32
|
return value;
|
|
33
|
+
}
|
|
28
34
|
}
|
|
29
35
|
return undefined;
|
|
30
36
|
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import { resolveUserPath } from "../utils.js";
|
|
3
|
+
export function readSecretFromFile(filePath, label) {
|
|
4
|
+
const resolvedPath = resolveUserPath(filePath.trim());
|
|
5
|
+
if (!resolvedPath) {
|
|
6
|
+
throw new Error(`${label} file path is empty.`);
|
|
7
|
+
}
|
|
8
|
+
let raw = "";
|
|
9
|
+
try {
|
|
10
|
+
raw = fs.readFileSync(resolvedPath, "utf8");
|
|
11
|
+
}
|
|
12
|
+
catch (err) {
|
|
13
|
+
throw new Error(`Failed to read ${label} file at ${resolvedPath}: ${String(err)}`, {
|
|
14
|
+
cause: err,
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
const secret = raw.trim();
|
|
18
|
+
if (!secret) {
|
|
19
|
+
throw new Error(`${label} file at ${resolvedPath} is empty.`);
|
|
20
|
+
}
|
|
21
|
+
return secret;
|
|
22
|
+
}
|
|
@@ -3,21 +3,20 @@ import { resolveStateDir } from "../config/paths.js";
|
|
|
3
3
|
import { DEFAULT_AGENT_ID } from "../routing/session-key.js";
|
|
4
4
|
import { resolveUserPath } from "../utils.js";
|
|
5
5
|
export function resolvePoolbotAgentDir() {
|
|
6
|
-
const override = process.env.POOLBOT_AGENT_DIR?.trim() ||
|
|
7
|
-
|
|
8
|
-
process.env.PI_CODING_AGENT_DIR?.trim();
|
|
9
|
-
if (override)
|
|
6
|
+
const override = process.env.POOLBOT_AGENT_DIR?.trim() || process.env.PI_CODING_AGENT_DIR?.trim();
|
|
7
|
+
if (override) {
|
|
10
8
|
return resolveUserPath(override);
|
|
9
|
+
}
|
|
11
10
|
const defaultAgentDir = path.join(resolveStateDir(), "agents", DEFAULT_AGENT_ID, "agent");
|
|
12
11
|
return resolveUserPath(defaultAgentDir);
|
|
13
12
|
}
|
|
14
|
-
export function
|
|
13
|
+
export function ensurePoolBotAgentEnv() {
|
|
15
14
|
const dir = resolvePoolbotAgentDir();
|
|
16
|
-
if (!process.env.POOLBOT_AGENT_DIR)
|
|
15
|
+
if (!process.env.POOLBOT_AGENT_DIR) {
|
|
17
16
|
process.env.POOLBOT_AGENT_DIR = dir;
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
if (!process.env.PI_CODING_AGENT_DIR)
|
|
17
|
+
}
|
|
18
|
+
if (!process.env.PI_CODING_AGENT_DIR) {
|
|
21
19
|
process.env.PI_CODING_AGENT_DIR = dir;
|
|
20
|
+
}
|
|
22
21
|
return dir;
|
|
23
22
|
}
|
|
@@ -4,17 +4,19 @@ import { resolveStateDir } from "../config/paths.js";
|
|
|
4
4
|
import { DEFAULT_AGENT_ID, normalizeAgentId, parseAgentSessionKey, } from "../routing/session-key.js";
|
|
5
5
|
import { normalizeSkillFilter } from "./skills/filter.js";
|
|
6
6
|
import { resolveUserPath } from "../utils.js";
|
|
7
|
+
import { createSubsystemLogger } from "../logging/subsystem.js";
|
|
7
8
|
import { DEFAULT_AGENT_WORKSPACE_DIR } from "./workspace.js";
|
|
9
|
+
const log = createSubsystemLogger("agent-scope");
|
|
8
10
|
export { resolveAgentIdFromSessionKey } from "../routing/session-key.js";
|
|
9
11
|
let defaultAgentWarned = false;
|
|
10
|
-
function
|
|
12
|
+
export function listAgentEntries(cfg) {
|
|
11
13
|
const list = cfg.agents?.list;
|
|
12
14
|
if (!Array.isArray(list))
|
|
13
15
|
return [];
|
|
14
16
|
return list.filter((entry) => Boolean(entry && typeof entry === "object"));
|
|
15
17
|
}
|
|
16
18
|
export function listAgentIds(cfg) {
|
|
17
|
-
const agents =
|
|
19
|
+
const agents = listAgentEntries(cfg);
|
|
18
20
|
if (agents.length === 0)
|
|
19
21
|
return [DEFAULT_AGENT_ID];
|
|
20
22
|
const seen = new Set();
|
|
@@ -29,13 +31,13 @@ export function listAgentIds(cfg) {
|
|
|
29
31
|
return ids.length > 0 ? ids : [DEFAULT_AGENT_ID];
|
|
30
32
|
}
|
|
31
33
|
export function resolveDefaultAgentId(cfg) {
|
|
32
|
-
const agents =
|
|
34
|
+
const agents = listAgentEntries(cfg);
|
|
33
35
|
if (agents.length === 0)
|
|
34
36
|
return DEFAULT_AGENT_ID;
|
|
35
37
|
const defaults = agents.filter((agent) => agent?.default);
|
|
36
38
|
if (defaults.length > 1 && !defaultAgentWarned) {
|
|
37
39
|
defaultAgentWarned = true;
|
|
38
|
-
|
|
40
|
+
log.warn("Multiple agents marked default=true; using the first entry as default.");
|
|
39
41
|
}
|
|
40
42
|
const chosen = (defaults[0] ?? agents[0])?.id?.trim();
|
|
41
43
|
return normalizeAgentId(chosen || DEFAULT_AGENT_ID);
|
|
@@ -53,7 +55,7 @@ export function resolveSessionAgentId(params) {
|
|
|
53
55
|
}
|
|
54
56
|
function resolveAgentEntry(cfg, agentId) {
|
|
55
57
|
const id = normalizeAgentId(agentId);
|
|
56
|
-
return
|
|
58
|
+
return listAgentEntries(cfg).find((entry) => normalizeAgentId(entry.id) === id);
|
|
57
59
|
}
|
|
58
60
|
export function resolveAgentConfig(cfg, agentId) {
|
|
59
61
|
const id = normalizeAgentId(agentId);
|
|
@@ -98,6 +100,16 @@ export function resolveAgentModelFallbacksOverride(cfg, agentId) {
|
|
|
98
100
|
return undefined;
|
|
99
101
|
return Array.isArray(raw.fallbacks) ? raw.fallbacks : undefined;
|
|
100
102
|
}
|
|
103
|
+
export function resolveEffectiveModelFallbacks(params) {
|
|
104
|
+
const agentFallbacksOverride = resolveAgentModelFallbacksOverride(params.cfg, params.agentId);
|
|
105
|
+
if (!params.hasSessionModelOverride) {
|
|
106
|
+
return agentFallbacksOverride;
|
|
107
|
+
}
|
|
108
|
+
const defaultFallbacks = typeof params.cfg.agents?.defaults?.model === "object"
|
|
109
|
+
? (params.cfg.agents.defaults.model.fallbacks ?? [])
|
|
110
|
+
: [];
|
|
111
|
+
return agentFallbacksOverride ?? defaultFallbacks;
|
|
112
|
+
}
|
|
101
113
|
export function resolveAgentWorkspaceDir(cfg, agentId) {
|
|
102
114
|
const id = normalizeAgentId(agentId);
|
|
103
115
|
const configured = resolveAgentConfig(cfg, id)?.workspace?.trim();
|