@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
|
@@ -2,7 +2,9 @@ import fs from "node:fs";
|
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import readline from "node:readline";
|
|
4
4
|
import { normalizeUsage } from "../agents/usage.js";
|
|
5
|
+
import { stripInboundMetadata } from "../auto-reply/reply/strip-inbound-meta.js";
|
|
5
6
|
import { resolveSessionFilePath, resolveSessionTranscriptsDirForAgent, } from "../config/sessions/paths.js";
|
|
7
|
+
import { stripEnvelope, stripMessageIdHints } from "../shared/chat-envelope.js";
|
|
6
8
|
import { countToolResults, extractToolCallNames } from "../utils/transcript-tools.js";
|
|
7
9
|
import { estimateUsageCost, resolveModelCostConfig } from "../utils/usage-format.js";
|
|
8
10
|
const emptyTotals = () => ({
|
|
@@ -105,7 +107,7 @@ const computeLatencyStats = (values) => {
|
|
|
105
107
|
if (!values.length) {
|
|
106
108
|
return undefined;
|
|
107
109
|
}
|
|
108
|
-
const sorted =
|
|
110
|
+
const sorted = values.toSorted((a, b) => a - b);
|
|
109
111
|
const total = sorted.reduce((sum, v) => sum + v, 0);
|
|
110
112
|
const count = sorted.length;
|
|
111
113
|
const p95Index = Math.max(0, Math.ceil(count * 0.95) - 1);
|
|
@@ -144,33 +146,47 @@ const applyCostTotal = (totals, costTotal) => {
|
|
|
144
146
|
}
|
|
145
147
|
totals.totalCost += costTotal;
|
|
146
148
|
};
|
|
147
|
-
async function
|
|
148
|
-
const fileStream = fs.createReadStream(
|
|
149
|
+
async function* readJsonlRecords(filePath) {
|
|
150
|
+
const fileStream = fs.createReadStream(filePath, { encoding: "utf-8" });
|
|
149
151
|
const rl = readline.createInterface({ input: fileStream, crlfDelay: Infinity });
|
|
150
|
-
|
|
151
|
-
const
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
}
|
|
155
|
-
try {
|
|
156
|
-
const parsed = JSON.parse(trimmed);
|
|
157
|
-
const entry = parseTranscriptEntry(parsed);
|
|
158
|
-
if (!entry) {
|
|
152
|
+
try {
|
|
153
|
+
for await (const line of rl) {
|
|
154
|
+
const trimmed = line.trim();
|
|
155
|
+
if (!trimmed) {
|
|
159
156
|
continue;
|
|
160
157
|
}
|
|
161
|
-
|
|
162
|
-
const
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
158
|
+
try {
|
|
159
|
+
const parsed = JSON.parse(trimmed);
|
|
160
|
+
if (!parsed || typeof parsed !== "object") {
|
|
161
|
+
continue;
|
|
162
|
+
}
|
|
163
|
+
yield parsed;
|
|
164
|
+
}
|
|
165
|
+
catch {
|
|
166
|
+
// Ignore malformed lines
|
|
168
167
|
}
|
|
169
|
-
params.onEntry(entry);
|
|
170
168
|
}
|
|
171
|
-
|
|
172
|
-
|
|
169
|
+
}
|
|
170
|
+
finally {
|
|
171
|
+
rl.close();
|
|
172
|
+
fileStream.destroy();
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
async function scanTranscriptFile(params) {
|
|
176
|
+
for await (const parsed of readJsonlRecords(params.filePath)) {
|
|
177
|
+
const entry = parseTranscriptEntry(parsed);
|
|
178
|
+
if (!entry) {
|
|
179
|
+
continue;
|
|
173
180
|
}
|
|
181
|
+
if (entry.usage && entry.costTotal === undefined) {
|
|
182
|
+
const cost = resolveModelCostConfig({
|
|
183
|
+
provider: entry.provider,
|
|
184
|
+
model: entry.model,
|
|
185
|
+
config: params.config,
|
|
186
|
+
});
|
|
187
|
+
entry.costTotal = estimateUsageCost({ usage: entry.usage, cost });
|
|
188
|
+
}
|
|
189
|
+
params.onEntry(entry);
|
|
174
190
|
}
|
|
175
191
|
}
|
|
176
192
|
async function scanUsageFile(params) {
|
|
@@ -257,7 +273,7 @@ export async function loadCostUsageSummary(params) {
|
|
|
257
273
|
}
|
|
258
274
|
const daily = Array.from(dailyMap.entries())
|
|
259
275
|
.map(([date, bucket]) => Object.assign({ date }, bucket))
|
|
260
|
-
.
|
|
276
|
+
.toSorted((a, b) => a.date.localeCompare(b.date));
|
|
261
277
|
// Calculate days for backwards compatibility in response
|
|
262
278
|
const days = Math.ceil((untilTime - sinceTime) / (24 * 60 * 60 * 1000)) + 1;
|
|
263
279
|
return {
|
|
@@ -294,15 +310,8 @@ export async function discoverAllSessions(params) {
|
|
|
294
310
|
// Try to read first user message for label extraction
|
|
295
311
|
let firstUserMessage;
|
|
296
312
|
try {
|
|
297
|
-
const
|
|
298
|
-
const rl = readline.createInterface({ input: fileStream, crlfDelay: Infinity });
|
|
299
|
-
for await (const line of rl) {
|
|
300
|
-
const trimmed = line.trim();
|
|
301
|
-
if (!trimmed) {
|
|
302
|
-
continue;
|
|
303
|
-
}
|
|
313
|
+
for await (const parsed of readJsonlRecords(filePath)) {
|
|
304
314
|
try {
|
|
305
|
-
const parsed = JSON.parse(trimmed);
|
|
306
315
|
const message = parsed.message;
|
|
307
316
|
if (message?.role === "user") {
|
|
308
317
|
const content = message.content;
|
|
@@ -329,8 +338,6 @@ export async function discoverAllSessions(params) {
|
|
|
329
338
|
// Skip malformed lines
|
|
330
339
|
}
|
|
331
340
|
}
|
|
332
|
-
rl.close();
|
|
333
|
-
fileStream.destroy();
|
|
334
341
|
}
|
|
335
342
|
catch {
|
|
336
343
|
// Ignore read errors
|
|
@@ -343,11 +350,15 @@ export async function discoverAllSessions(params) {
|
|
|
343
350
|
});
|
|
344
351
|
}
|
|
345
352
|
// Sort by mtime descending (most recent first)
|
|
346
|
-
return discovered.
|
|
353
|
+
return discovered.toSorted((a, b) => b.mtime - a.mtime);
|
|
347
354
|
}
|
|
348
355
|
export async function loadSessionCostSummary(params) {
|
|
349
356
|
const sessionFile = params.sessionFile ??
|
|
350
|
-
(params.sessionId
|
|
357
|
+
(params.sessionId
|
|
358
|
+
? resolveSessionFilePath(params.sessionId, params.sessionEntry, {
|
|
359
|
+
agentId: params.agentId,
|
|
360
|
+
})
|
|
361
|
+
: undefined);
|
|
351
362
|
if (!sessionFile || !fs.existsSync(sessionFile)) {
|
|
352
363
|
return null;
|
|
353
364
|
}
|
|
@@ -527,8 +538,8 @@ export async function loadSessionCostSummary(params) {
|
|
|
527
538
|
// Convert daily map to sorted array
|
|
528
539
|
const dailyBreakdown = Array.from(dailyMap.entries())
|
|
529
540
|
.map(([date, data]) => ({ date, tokens: data.tokens, cost: data.cost }))
|
|
530
|
-
.
|
|
531
|
-
const dailyMessageCounts = Array.from(dailyMessageMap.values()).
|
|
541
|
+
.toSorted((a, b) => a.date.localeCompare(b.date));
|
|
542
|
+
const dailyMessageCounts = Array.from(dailyMessageMap.values()).toSorted((a, b) => a.date.localeCompare(b.date));
|
|
532
543
|
const dailyLatency = Array.from(dailyLatencyMap.entries())
|
|
533
544
|
.map(([date, values]) => {
|
|
534
545
|
const stats = computeLatencyStats(values);
|
|
@@ -538,19 +549,19 @@ export async function loadSessionCostSummary(params) {
|
|
|
538
549
|
return { date, ...stats };
|
|
539
550
|
})
|
|
540
551
|
.filter((entry) => Boolean(entry))
|
|
541
|
-
.
|
|
542
|
-
const dailyModelUsage = Array.from(dailyModelUsageMap.values()).
|
|
552
|
+
.toSorted((a, b) => a.date.localeCompare(b.date));
|
|
553
|
+
const dailyModelUsage = Array.from(dailyModelUsageMap.values()).toSorted((a, b) => a.date.localeCompare(b.date) || b.cost - a.cost);
|
|
543
554
|
const toolUsage = toolUsageMap.size
|
|
544
555
|
? {
|
|
545
556
|
totalCalls: Array.from(toolUsageMap.values()).reduce((sum, count) => sum + count, 0),
|
|
546
557
|
uniqueTools: toolUsageMap.size,
|
|
547
558
|
tools: Array.from(toolUsageMap.entries())
|
|
548
559
|
.map(([name, count]) => ({ name, count }))
|
|
549
|
-
.
|
|
560
|
+
.toSorted((a, b) => b.count - a.count),
|
|
550
561
|
}
|
|
551
562
|
: undefined;
|
|
552
563
|
const modelUsage = modelUsageMap.size
|
|
553
|
-
? Array.from(modelUsageMap.values()).
|
|
564
|
+
? Array.from(modelUsageMap.values()).toSorted((a, b) => {
|
|
554
565
|
const costDiff = b.totals.totalCost - a.totals.totalCost;
|
|
555
566
|
if (costDiff !== 0) {
|
|
556
567
|
return costDiff;
|
|
@@ -566,7 +577,7 @@ export async function loadSessionCostSummary(params) {
|
|
|
566
577
|
durationMs: firstActivity !== undefined && lastActivity !== undefined
|
|
567
578
|
? Math.max(0, lastActivity - firstActivity)
|
|
568
579
|
: undefined,
|
|
569
|
-
activityDates: Array.from(activityDatesSet).
|
|
580
|
+
activityDates: Array.from(activityDatesSet).toSorted(),
|
|
570
581
|
dailyBreakdown,
|
|
571
582
|
dailyMessageCounts,
|
|
572
583
|
dailyLatency: dailyLatency.length ? dailyLatency : undefined,
|
|
@@ -580,7 +591,11 @@ export async function loadSessionCostSummary(params) {
|
|
|
580
591
|
}
|
|
581
592
|
export async function loadSessionUsageTimeSeries(params) {
|
|
582
593
|
const sessionFile = params.sessionFile ??
|
|
583
|
-
(params.sessionId
|
|
594
|
+
(params.sessionId
|
|
595
|
+
? resolveSessionFilePath(params.sessionId, params.sessionEntry, {
|
|
596
|
+
agentId: params.agentId,
|
|
597
|
+
})
|
|
598
|
+
: undefined);
|
|
584
599
|
if (!sessionFile || !fs.existsSync(sessionFile)) {
|
|
585
600
|
return null;
|
|
586
601
|
}
|
|
@@ -617,18 +632,47 @@ export async function loadSessionUsageTimeSeries(params) {
|
|
|
617
632
|
},
|
|
618
633
|
});
|
|
619
634
|
// Sort by timestamp
|
|
620
|
-
const sortedPoints = points.
|
|
635
|
+
const sortedPoints = points.toSorted((a, b) => a.timestamp - b.timestamp);
|
|
621
636
|
// Optionally downsample if too many points
|
|
622
637
|
const maxPoints = params.maxPoints ?? 100;
|
|
623
638
|
if (sortedPoints.length > maxPoints) {
|
|
624
639
|
const step = Math.ceil(sortedPoints.length / maxPoints);
|
|
625
640
|
const downsampled = [];
|
|
641
|
+
let downsampledCumulativeTokens = 0;
|
|
642
|
+
let downsampledCumulativeCost = 0;
|
|
626
643
|
for (let i = 0; i < sortedPoints.length; i += step) {
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
644
|
+
const bucket = sortedPoints.slice(i, i + step);
|
|
645
|
+
const bucketLast = bucket[bucket.length - 1];
|
|
646
|
+
if (!bucketLast) {
|
|
647
|
+
continue;
|
|
648
|
+
}
|
|
649
|
+
let bucketInput = 0;
|
|
650
|
+
let bucketOutput = 0;
|
|
651
|
+
let bucketCacheRead = 0;
|
|
652
|
+
let bucketCacheWrite = 0;
|
|
653
|
+
let bucketTotalTokens = 0;
|
|
654
|
+
let bucketCost = 0;
|
|
655
|
+
for (const point of bucket) {
|
|
656
|
+
bucketInput += point.input;
|
|
657
|
+
bucketOutput += point.output;
|
|
658
|
+
bucketCacheRead += point.cacheRead;
|
|
659
|
+
bucketCacheWrite += point.cacheWrite;
|
|
660
|
+
bucketTotalTokens += point.totalTokens;
|
|
661
|
+
bucketCost += point.cost;
|
|
662
|
+
}
|
|
663
|
+
downsampledCumulativeTokens += bucketTotalTokens;
|
|
664
|
+
downsampledCumulativeCost += bucketCost;
|
|
665
|
+
downsampled.push({
|
|
666
|
+
timestamp: bucketLast.timestamp,
|
|
667
|
+
input: bucketInput,
|
|
668
|
+
output: bucketOutput,
|
|
669
|
+
cacheRead: bucketCacheRead,
|
|
670
|
+
cacheWrite: bucketCacheWrite,
|
|
671
|
+
totalTokens: bucketTotalTokens,
|
|
672
|
+
cost: bucketCost,
|
|
673
|
+
cumulativeTokens: downsampledCumulativeTokens,
|
|
674
|
+
cumulativeCost: downsampledCumulativeCost,
|
|
675
|
+
});
|
|
632
676
|
}
|
|
633
677
|
return { sessionId: params.sessionId, points: downsampled };
|
|
634
678
|
}
|
|
@@ -636,21 +680,18 @@ export async function loadSessionUsageTimeSeries(params) {
|
|
|
636
680
|
}
|
|
637
681
|
export async function loadSessionLogs(params) {
|
|
638
682
|
const sessionFile = params.sessionFile ??
|
|
639
|
-
(params.sessionId
|
|
683
|
+
(params.sessionId
|
|
684
|
+
? resolveSessionFilePath(params.sessionId, params.sessionEntry, {
|
|
685
|
+
agentId: params.agentId,
|
|
686
|
+
})
|
|
687
|
+
: undefined);
|
|
640
688
|
if (!sessionFile || !fs.existsSync(sessionFile)) {
|
|
641
689
|
return null;
|
|
642
690
|
}
|
|
643
691
|
const logs = [];
|
|
644
692
|
const limit = params.limit ?? 50;
|
|
645
|
-
const
|
|
646
|
-
const rl = readline.createInterface({ input: fileStream, crlfDelay: Infinity });
|
|
647
|
-
for await (const line of rl) {
|
|
648
|
-
const trimmed = line.trim();
|
|
649
|
-
if (!trimmed) {
|
|
650
|
-
continue;
|
|
651
|
-
}
|
|
693
|
+
for await (const parsed of readJsonlRecords(sessionFile)) {
|
|
652
694
|
try {
|
|
653
|
-
const parsed = JSON.parse(trimmed);
|
|
654
695
|
const message = parsed.message;
|
|
655
696
|
if (!message) {
|
|
656
697
|
continue;
|
|
@@ -718,6 +759,13 @@ export async function loadSessionLogs(params) {
|
|
|
718
759
|
if (!content) {
|
|
719
760
|
continue;
|
|
720
761
|
}
|
|
762
|
+
content = stripInboundMetadata(content);
|
|
763
|
+
if (role === "user") {
|
|
764
|
+
content = stripMessageIdHints(stripEnvelope(content)).trim();
|
|
765
|
+
}
|
|
766
|
+
if (!content) {
|
|
767
|
+
continue;
|
|
768
|
+
}
|
|
721
769
|
// Truncate very long content
|
|
722
770
|
const maxLen = 2000;
|
|
723
771
|
if (content.length > maxLen) {
|
|
@@ -771,7 +819,7 @@ export async function loadSessionLogs(params) {
|
|
|
771
819
|
}
|
|
772
820
|
}
|
|
773
821
|
// Sort by timestamp and limit
|
|
774
|
-
const sortedLogs = logs.
|
|
822
|
+
const sortedLogs = logs.toSorted((a, b) => a.timestamp - b.timestamp);
|
|
775
823
|
// Return most recent logs
|
|
776
824
|
if (sortedLogs.length > limit) {
|
|
777
825
|
return sortedLogs.slice(-limit);
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { resolveSessionAgentId } from "../agents/agent-scope.js";
|
|
2
|
+
import { createSubsystemLogger } from "../logging/subsystem.js";
|
|
2
3
|
import { isDeliverableMessageChannel, normalizeMessageChannel } from "../utils/message-channel.js";
|
|
3
4
|
import { resolveSessionDeliveryTarget } from "./outbound/targets.js";
|
|
4
5
|
import { enqueueSystemEvent } from "./system-events.js";
|
|
6
|
+
const log = createSubsystemLogger("session-maintenance");
|
|
5
7
|
const warnedContexts = new Map();
|
|
6
8
|
function shouldSendWarning() {
|
|
7
9
|
return !process.env.VITEST && process.env.NODE_ENV !== "test";
|
|
@@ -83,7 +85,7 @@ export async function deliverSessionMaintenanceWarning(params) {
|
|
|
83
85
|
});
|
|
84
86
|
}
|
|
85
87
|
catch (err) {
|
|
86
|
-
|
|
88
|
+
log.warn(`Failed to deliver session maintenance warning: ${String(err)}`);
|
|
87
89
|
enqueueSystemEvent(text, { sessionKey: params.sessionKey });
|
|
88
90
|
}
|
|
89
91
|
}
|
package/dist/infra/shell-env.js
CHANGED
|
@@ -1,26 +1,100 @@
|
|
|
1
1
|
import { execFileSync } from "node:child_process";
|
|
2
|
+
import fs from "node:fs";
|
|
3
|
+
import path from "node:path";
|
|
2
4
|
import { isTruthyEnvValue } from "./env.js";
|
|
3
5
|
const DEFAULT_TIMEOUT_MS = 15_000;
|
|
4
6
|
const DEFAULT_MAX_BUFFER_BYTES = 2 * 1024 * 1024;
|
|
7
|
+
const DEFAULT_SHELL = "/bin/sh";
|
|
8
|
+
const TRUSTED_SHELL_PREFIXES = [
|
|
9
|
+
"/bin/",
|
|
10
|
+
"/usr/bin/",
|
|
11
|
+
"/usr/local/bin/",
|
|
12
|
+
"/opt/homebrew/bin/",
|
|
13
|
+
"/run/current-system/sw/bin/",
|
|
14
|
+
];
|
|
5
15
|
let lastAppliedKeys = [];
|
|
6
16
|
let cachedShellPath;
|
|
17
|
+
let cachedEtcShells;
|
|
18
|
+
function resolveTimeoutMs(timeoutMs) {
|
|
19
|
+
if (typeof timeoutMs !== "number" || !Number.isFinite(timeoutMs)) {
|
|
20
|
+
return DEFAULT_TIMEOUT_MS;
|
|
21
|
+
}
|
|
22
|
+
return Math.max(0, timeoutMs);
|
|
23
|
+
}
|
|
24
|
+
function readEtcShells() {
|
|
25
|
+
if (cachedEtcShells !== undefined) {
|
|
26
|
+
return cachedEtcShells;
|
|
27
|
+
}
|
|
28
|
+
try {
|
|
29
|
+
const raw = fs.readFileSync("/etc/shells", "utf8");
|
|
30
|
+
const entries = raw
|
|
31
|
+
.split(/\r?\n/)
|
|
32
|
+
.map((line) => line.trim())
|
|
33
|
+
.filter((line) => line.length > 0 && !line.startsWith("#") && path.isAbsolute(line));
|
|
34
|
+
cachedEtcShells = new Set(entries);
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
cachedEtcShells = null;
|
|
38
|
+
}
|
|
39
|
+
return cachedEtcShells;
|
|
40
|
+
}
|
|
41
|
+
function isTrustedShellPath(shell) {
|
|
42
|
+
if (!path.isAbsolute(shell)) {
|
|
43
|
+
return false;
|
|
44
|
+
}
|
|
45
|
+
const normalized = path.normalize(shell);
|
|
46
|
+
if (normalized !== shell) {
|
|
47
|
+
return false;
|
|
48
|
+
}
|
|
49
|
+
// Primary trust anchor: shell registered in /etc/shells.
|
|
50
|
+
const registeredShells = readEtcShells();
|
|
51
|
+
if (registeredShells?.has(shell)) {
|
|
52
|
+
return true;
|
|
53
|
+
}
|
|
54
|
+
// Fallback for environments where /etc/shells is incomplete/unavailable.
|
|
55
|
+
if (!TRUSTED_SHELL_PREFIXES.some((prefix) => shell.startsWith(prefix))) {
|
|
56
|
+
return false;
|
|
57
|
+
}
|
|
58
|
+
try {
|
|
59
|
+
fs.accessSync(shell, fs.constants.X_OK);
|
|
60
|
+
return true;
|
|
61
|
+
}
|
|
62
|
+
catch {
|
|
63
|
+
return false;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
7
66
|
function resolveShell(env) {
|
|
8
67
|
const shell = env.SHELL?.trim();
|
|
9
|
-
|
|
68
|
+
if (shell && isTrustedShellPath(shell)) {
|
|
69
|
+
return shell;
|
|
70
|
+
}
|
|
71
|
+
return DEFAULT_SHELL;
|
|
72
|
+
}
|
|
73
|
+
function execLoginShellEnvZero(params) {
|
|
74
|
+
return params.exec(params.shell, ["-l", "-c", "env -0"], {
|
|
75
|
+
encoding: "buffer",
|
|
76
|
+
timeout: params.timeoutMs,
|
|
77
|
+
maxBuffer: DEFAULT_MAX_BUFFER_BYTES,
|
|
78
|
+
env: params.env,
|
|
79
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
80
|
+
});
|
|
10
81
|
}
|
|
11
82
|
function parseShellEnv(stdout) {
|
|
12
83
|
const shellEnv = new Map();
|
|
13
84
|
const parts = stdout.toString("utf8").split("\0");
|
|
14
85
|
for (const part of parts) {
|
|
15
|
-
if (!part)
|
|
86
|
+
if (!part) {
|
|
16
87
|
continue;
|
|
88
|
+
}
|
|
17
89
|
const eq = part.indexOf("=");
|
|
18
|
-
if (eq <= 0)
|
|
90
|
+
if (eq <= 0) {
|
|
19
91
|
continue;
|
|
92
|
+
}
|
|
20
93
|
const key = part.slice(0, eq);
|
|
21
94
|
const value = part.slice(eq + 1);
|
|
22
|
-
if (!key)
|
|
95
|
+
if (!key) {
|
|
23
96
|
continue;
|
|
97
|
+
}
|
|
24
98
|
shellEnv.set(key, value);
|
|
25
99
|
}
|
|
26
100
|
return shellEnv;
|
|
@@ -37,19 +111,11 @@ export function loadShellEnvFallback(opts) {
|
|
|
37
111
|
lastAppliedKeys = [];
|
|
38
112
|
return { ok: true, applied: [], skippedReason: "already-has-keys" };
|
|
39
113
|
}
|
|
40
|
-
const timeoutMs =
|
|
41
|
-
? Math.max(0, opts.timeoutMs)
|
|
42
|
-
: DEFAULT_TIMEOUT_MS;
|
|
114
|
+
const timeoutMs = resolveTimeoutMs(opts.timeoutMs);
|
|
43
115
|
const shell = resolveShell(opts.env);
|
|
44
116
|
let stdout;
|
|
45
117
|
try {
|
|
46
|
-
stdout =
|
|
47
|
-
encoding: "buffer",
|
|
48
|
-
timeout: timeoutMs,
|
|
49
|
-
maxBuffer: DEFAULT_MAX_BUFFER_BYTES,
|
|
50
|
-
env: opts.env,
|
|
51
|
-
stdio: ["ignore", "pipe", "pipe"],
|
|
52
|
-
});
|
|
118
|
+
stdout = execLoginShellEnvZero({ shell, env: opts.env, exec, timeoutMs });
|
|
53
119
|
}
|
|
54
120
|
catch (err) {
|
|
55
121
|
const msg = err instanceof Error ? err.message : String(err);
|
|
@@ -60,11 +126,13 @@ export function loadShellEnvFallback(opts) {
|
|
|
60
126
|
const shellEnv = parseShellEnv(stdout);
|
|
61
127
|
const applied = [];
|
|
62
128
|
for (const key of opts.expectedKeys) {
|
|
63
|
-
if (opts.env[key]?.trim())
|
|
129
|
+
if (opts.env[key]?.trim()) {
|
|
64
130
|
continue;
|
|
131
|
+
}
|
|
65
132
|
const value = shellEnv.get(key);
|
|
66
|
-
if (!value?.trim())
|
|
133
|
+
if (!value?.trim()) {
|
|
67
134
|
continue;
|
|
135
|
+
}
|
|
68
136
|
opts.env[key] = value;
|
|
69
137
|
applied.push(key);
|
|
70
138
|
}
|
|
@@ -72,42 +140,37 @@ export function loadShellEnvFallback(opts) {
|
|
|
72
140
|
return { ok: true, applied };
|
|
73
141
|
}
|
|
74
142
|
export function shouldEnableShellEnvFallback(env) {
|
|
75
|
-
return
|
|
143
|
+
return isTruthyEnvValue(env.POOLBOT_LOAD_SHELL_ENV);
|
|
76
144
|
}
|
|
77
145
|
export function shouldDeferShellEnvFallback(env) {
|
|
78
|
-
return
|
|
79
|
-
isTruthyEnvValue(env.CLAWDBOT_DEFER_SHELL_ENV_FALLBACK));
|
|
146
|
+
return isTruthyEnvValue(env.POOLBOT_DEFER_SHELL_ENV_FALLBACK);
|
|
80
147
|
}
|
|
81
148
|
export function resolveShellEnvFallbackTimeoutMs(env) {
|
|
82
|
-
const raw = env.POOLBOT_SHELL_ENV_TIMEOUT_MS?.trim()
|
|
83
|
-
if (!raw)
|
|
149
|
+
const raw = env.POOLBOT_SHELL_ENV_TIMEOUT_MS?.trim();
|
|
150
|
+
if (!raw) {
|
|
84
151
|
return DEFAULT_TIMEOUT_MS;
|
|
152
|
+
}
|
|
85
153
|
const parsed = Number.parseInt(raw, 10);
|
|
86
|
-
if (!Number.isFinite(parsed))
|
|
154
|
+
if (!Number.isFinite(parsed)) {
|
|
87
155
|
return DEFAULT_TIMEOUT_MS;
|
|
156
|
+
}
|
|
88
157
|
return Math.max(0, parsed);
|
|
89
158
|
}
|
|
90
159
|
export function getShellPathFromLoginShell(opts) {
|
|
91
|
-
if (cachedShellPath !== undefined)
|
|
160
|
+
if (cachedShellPath !== undefined) {
|
|
92
161
|
return cachedShellPath;
|
|
93
|
-
|
|
162
|
+
}
|
|
163
|
+
const platform = opts.platform ?? process.platform;
|
|
164
|
+
if (platform === "win32") {
|
|
94
165
|
cachedShellPath = null;
|
|
95
166
|
return cachedShellPath;
|
|
96
167
|
}
|
|
97
168
|
const exec = opts.exec ?? execFileSync;
|
|
98
|
-
const timeoutMs =
|
|
99
|
-
? Math.max(0, opts.timeoutMs)
|
|
100
|
-
: DEFAULT_TIMEOUT_MS;
|
|
169
|
+
const timeoutMs = resolveTimeoutMs(opts.timeoutMs);
|
|
101
170
|
const shell = resolveShell(opts.env);
|
|
102
171
|
let stdout;
|
|
103
172
|
try {
|
|
104
|
-
stdout =
|
|
105
|
-
encoding: "buffer",
|
|
106
|
-
timeout: timeoutMs,
|
|
107
|
-
maxBuffer: DEFAULT_MAX_BUFFER_BYTES,
|
|
108
|
-
env: opts.env,
|
|
109
|
-
stdio: ["ignore", "pipe", "pipe"],
|
|
110
|
-
});
|
|
173
|
+
stdout = execLoginShellEnvZero({ shell, env: opts.env, exec, timeoutMs });
|
|
111
174
|
}
|
|
112
175
|
catch {
|
|
113
176
|
cachedShellPath = null;
|
|
@@ -120,6 +183,7 @@ export function getShellPathFromLoginShell(opts) {
|
|
|
120
183
|
}
|
|
121
184
|
export function resetShellPathCacheForTests() {
|
|
122
185
|
cachedShellPath = undefined;
|
|
186
|
+
cachedEtcShells = undefined;
|
|
123
187
|
}
|
|
124
188
|
export function getShellEnvAppliedKeys() {
|
|
125
189
|
return [...lastAppliedKeys];
|
package/dist/infra/ssh-config.js
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { spawn } from "node:child_process";
|
|
2
2
|
function parsePort(value) {
|
|
3
|
-
if (!value)
|
|
3
|
+
if (!value) {
|
|
4
4
|
return undefined;
|
|
5
|
+
}
|
|
5
6
|
const parsed = Number.parseInt(value, 10);
|
|
6
|
-
if (!Number.isFinite(parsed) || parsed <= 0)
|
|
7
|
+
if (!Number.isFinite(parsed) || parsed <= 0) {
|
|
7
8
|
return undefined;
|
|
9
|
+
}
|
|
8
10
|
return parsed;
|
|
9
11
|
}
|
|
10
12
|
export function parseSshConfigOutput(output) {
|
|
@@ -12,12 +14,14 @@ export function parseSshConfigOutput(output) {
|
|
|
12
14
|
const lines = output.split("\n");
|
|
13
15
|
for (const raw of lines) {
|
|
14
16
|
const line = raw.trim();
|
|
15
|
-
if (!line)
|
|
17
|
+
if (!line) {
|
|
16
18
|
continue;
|
|
19
|
+
}
|
|
17
20
|
const [key, ...rest] = line.split(/\s+/);
|
|
18
21
|
const value = rest.join(" ").trim();
|
|
19
|
-
if (!key || !value)
|
|
22
|
+
if (!key || !value) {
|
|
20
23
|
continue;
|
|
24
|
+
}
|
|
21
25
|
switch (key) {
|
|
22
26
|
case "user":
|
|
23
27
|
result.user = value;
|
|
@@ -29,8 +33,9 @@ export function parseSshConfigOutput(output) {
|
|
|
29
33
|
result.port = parsePort(value);
|
|
30
34
|
break;
|
|
31
35
|
case "identityfile":
|
|
32
|
-
if (value !== "none")
|
|
36
|
+
if (value !== "none") {
|
|
33
37
|
result.identityFiles.push(value);
|
|
38
|
+
}
|
|
34
39
|
break;
|
|
35
40
|
default:
|
|
36
41
|
break;
|
|
@@ -48,7 +53,8 @@ export async function resolveSshConfig(target, opts = {}) {
|
|
|
48
53
|
args.push("-i", opts.identity.trim());
|
|
49
54
|
}
|
|
50
55
|
const userHost = target.user ? `${target.user}@${target.host}` : target.host;
|
|
51
|
-
|
|
56
|
+
// Use "--" so userHost can't be parsed as an ssh option.
|
|
57
|
+
args.push("--", userHost);
|
|
52
58
|
return await new Promise((resolve) => {
|
|
53
59
|
const child = spawn(sshPath, args, {
|
|
54
60
|
stdio: ["ignore", "pipe", "ignore"],
|
|
@@ -45,8 +45,12 @@ export function extractShellCommandFromArgv(argv) {
|
|
|
45
45
|
if (idx === -1) {
|
|
46
46
|
return null;
|
|
47
47
|
}
|
|
48
|
-
const
|
|
49
|
-
|
|
48
|
+
const tail = argv.slice(idx + 1).map((item) => String(item));
|
|
49
|
+
if (tail.length === 0) {
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
const cmd = tail.join(" ").trim();
|
|
53
|
+
return cmd.length > 0 ? cmd : null;
|
|
50
54
|
}
|
|
51
55
|
return null;
|
|
52
56
|
}
|
|
@@ -55,7 +59,7 @@ export function validateSystemRunCommandConsistency(params) {
|
|
|
55
59
|
? params.rawCommand.trim()
|
|
56
60
|
: null;
|
|
57
61
|
const shellCommand = extractShellCommandFromArgv(params.argv);
|
|
58
|
-
const inferred = shellCommand ? shellCommand.trim() : formatExecCommand(params.argv);
|
|
62
|
+
const inferred = shellCommand !== null ? shellCommand.trim() : formatExecCommand(params.argv);
|
|
59
63
|
if (raw && raw !== inferred) {
|
|
60
64
|
return {
|
|
61
65
|
ok: false,
|
|
@@ -72,7 +76,48 @@ export function validateSystemRunCommandConsistency(params) {
|
|
|
72
76
|
// Only treat this as a shell command when argv is a recognized shell wrapper.
|
|
73
77
|
// For direct argv execution, rawCommand is purely display/approval text and
|
|
74
78
|
// must match the formatted argv.
|
|
75
|
-
shellCommand: shellCommand ? (raw ?? shellCommand) : null,
|
|
79
|
+
shellCommand: shellCommand !== null ? (raw ?? shellCommand) : null,
|
|
76
80
|
cmdText: raw ?? shellCommand ?? inferred,
|
|
77
81
|
};
|
|
78
82
|
}
|
|
83
|
+
export function resolveSystemRunCommand(params) {
|
|
84
|
+
const raw = typeof params.rawCommand === "string" && params.rawCommand.trim().length > 0
|
|
85
|
+
? params.rawCommand.trim()
|
|
86
|
+
: null;
|
|
87
|
+
const command = Array.isArray(params.command) ? params.command : [];
|
|
88
|
+
if (command.length === 0) {
|
|
89
|
+
if (raw) {
|
|
90
|
+
return {
|
|
91
|
+
ok: false,
|
|
92
|
+
message: "rawCommand requires params.command",
|
|
93
|
+
details: { code: "MISSING_COMMAND" },
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
return {
|
|
97
|
+
ok: true,
|
|
98
|
+
argv: [],
|
|
99
|
+
rawCommand: null,
|
|
100
|
+
shellCommand: null,
|
|
101
|
+
cmdText: "",
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
const argv = command.map((v) => String(v));
|
|
105
|
+
const validation = validateSystemRunCommandConsistency({
|
|
106
|
+
argv,
|
|
107
|
+
rawCommand: raw,
|
|
108
|
+
});
|
|
109
|
+
if (!validation.ok) {
|
|
110
|
+
return {
|
|
111
|
+
ok: false,
|
|
112
|
+
message: validation.message,
|
|
113
|
+
details: validation.details ?? { code: "RAW_COMMAND_MISMATCH" },
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
return {
|
|
117
|
+
ok: true,
|
|
118
|
+
argv,
|
|
119
|
+
rawCommand: raw,
|
|
120
|
+
shellCommand: validation.shellCommand,
|
|
121
|
+
cmdText: validation.cmdText,
|
|
122
|
+
};
|
|
123
|
+
}
|