@poolzin/pool-bot 2026.2.25 → 2026.2.26
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/acp/event-mapper.js +87 -22
- package/dist/acp/meta.js +12 -6
- package/dist/agents/agent-paths.js +8 -9
- package/dist/agents/agent-scope.js +7 -5
- package/dist/agents/auth-profiles/oauth.js +148 -64
- package/dist/agents/auth-profiles/session-override.js +13 -7
- package/dist/agents/bash-tools.exec-host-gateway.js +14 -4
- package/dist/agents/bash-tools.exec-runtime.js +2 -25
- package/dist/agents/bedrock-discovery.js +3 -1
- package/dist/agents/byteplus-models.js +97 -0
- package/dist/agents/chutes-oauth.js +1 -0
- package/dist/agents/cli-runner/helpers.js +4 -0
- package/dist/agents/compaction.js +41 -14
- package/dist/agents/doubao-models.js +121 -0
- package/dist/agents/failover-error.js +2 -0
- package/dist/agents/huggingface-models.js +5 -3
- package/dist/agents/live-model-filter.js +5 -0
- package/dist/agents/minimax-vlm.js +10 -8
- package/dist/agents/model-auth.js +6 -0
- package/dist/agents/model-catalog.js +3 -1
- package/dist/agents/model-selection.js +7 -1
- package/dist/agents/models-config.providers.js +93 -11
- package/dist/agents/ollama-stream.js +117 -4
- package/dist/agents/opencode-zen-models.js +22 -11
- package/dist/agents/pi-embedded-helpers/errors.js +55 -33
- package/dist/agents/pi-embedded-helpers/messaging-dedupe.js +10 -5
- package/dist/agents/pi-embedded-helpers/thinking.js +10 -5
- package/dist/agents/pi-embedded-helpers.js +1 -1
- package/dist/agents/pi-embedded-runner/compact.js +29 -7
- package/dist/agents/pi-embedded-runner/extensions.js +28 -26
- package/dist/agents/pi-embedded-runner/google.js +20 -8
- package/dist/agents/pi-embedded-runner/run/attempt.js +95 -36
- package/dist/agents/pi-embedded-runner/run.js +71 -12
- package/dist/agents/pi-embedded-runner/run.overflow-compaction.mocks.shared.js +11 -2
- package/dist/agents/pi-embedded-runner/session-manager-cache.js +11 -7
- package/dist/agents/pi-embedded-runner/system-prompt.js +2 -0
- package/dist/agents/pi-embedded-runner/thinking.js +42 -0
- package/dist/agents/pi-embedded-runner/tool-name-allowlist.js +19 -0
- package/dist/agents/pi-embedded-runner/utils.js +7 -10
- package/dist/agents/pi-embedded-subscribe.handlers.lifecycle.js +45 -56
- package/dist/agents/pi-embedded-subscribe.handlers.tools.js +2 -2
- package/dist/agents/pi-embedded-subscribe.js +9 -4
- package/dist/agents/pi-embedded-subscribe.tools.js +68 -14
- package/dist/agents/pi-embedded-utils.js +3 -0
- package/dist/agents/pi-extensions/compaction-safeguard-runtime.js +4 -20
- package/dist/agents/pi-extensions/compaction-safeguard.js +75 -33
- package/dist/agents/pi-settings.js +40 -0
- package/dist/agents/pi-tools.policy.js +2 -1
- package/dist/agents/provider/config-loader.js +1 -1
- package/dist/agents/sandbox/browser.js +170 -33
- package/dist/agents/sandbox/config-hash.js +14 -27
- package/dist/agents/sandbox/config.js +21 -2
- package/dist/agents/sandbox/constants.js +2 -0
- package/dist/agents/sandbox/docker.js +16 -2
- package/dist/agents/sandbox/novnc-auth.js +62 -0
- package/dist/agents/sandbox/sanitize-env-vars.js +1 -1
- package/dist/agents/sandbox/shared.js +10 -6
- package/dist/agents/sandbox-paths.js +24 -11
- package/dist/agents/schema/clean-for-gemini.js +132 -85
- package/dist/agents/session-slug.js +10 -5
- package/dist/agents/session-tool-result-guard-wrapper.js +1 -0
- package/dist/agents/session-tool-result-guard.js +3 -1
- package/dist/agents/session-transcript-repair.js +40 -6
- package/dist/agents/skills/bundled-dir.js +19 -5
- package/dist/agents/skills/env-overrides.js +124 -43
- package/dist/agents/skills/frontmatter.js +6 -6
- package/dist/agents/skills/plugin-skills.js +14 -7
- package/dist/agents/skills/workspace.js +1 -0
- package/dist/agents/subagent-announce.js +251 -49
- package/dist/agents/subagent-lifecycle-events.js +19 -0
- package/dist/agents/subagent-registry-cleanup.js +31 -0
- package/dist/agents/subagent-registry-completion.js +68 -0
- package/dist/agents/subagent-registry-queries.js +117 -0
- package/dist/agents/subagent-registry-state.js +46 -0
- package/dist/agents/subagent-registry.js +252 -221
- package/dist/agents/subagent-registry.store.js +1 -0
- package/dist/agents/subagent-registry.types.js +1 -0
- package/dist/agents/subagent-spawn.js +195 -7
- package/dist/agents/system-prompt.js +22 -6
- package/dist/agents/test-helpers/fast-coding-tools.js +1 -18
- package/dist/agents/test-helpers/fast-core-tools.js +1 -17
- package/dist/agents/timeout.js +18 -6
- package/dist/agents/tool-call-id.js +1 -1
- package/dist/agents/tool-display-common.js +162 -29
- package/dist/agents/tool-images.js +82 -9
- package/dist/agents/tool-policy.js +51 -26
- package/dist/agents/tools/browser-tool.js +2 -2
- package/dist/agents/tools/canvas-tool.js +27 -1
- package/dist/agents/tools/common.js +45 -0
- package/dist/agents/tools/discord-actions-guild.js +4 -1
- package/dist/agents/tools/gateway-tool.js +3 -1
- package/dist/agents/tools/nodes-utils.js +1 -10
- package/dist/agents/tools/sessions-send-helpers.js +12 -6
- package/dist/agents/tools/sessions-spawn-tool.js +8 -2
- package/dist/agents/tools/subagents-tool.js +2 -1
- package/dist/agents/tools/whatsapp-actions.js +10 -2
- package/dist/agents/tools/whatsapp-target-auth.js +18 -0
- package/dist/agents/transcript-policy.js +22 -8
- package/dist/agents/venice-models.js +11 -3
- package/dist/auto-reply/commands-registry.data.js +51 -0
- package/dist/auto-reply/commands-registry.js +4 -3
- package/dist/auto-reply/group-activation.js +10 -5
- package/dist/auto-reply/inbound-debounce.js +10 -5
- package/dist/auto-reply/reply/abort.js +1 -1
- package/dist/auto-reply/reply/agent-runner-execution.js +4 -1
- package/dist/auto-reply/reply/bash-command.js +41 -39
- package/dist/auto-reply/reply/command-gates.js +25 -0
- package/dist/auto-reply/reply/commands-allowlist.js +111 -72
- package/dist/auto-reply/reply/commands-bash.js +6 -5
- package/dist/auto-reply/reply/commands-config.js +30 -28
- package/dist/auto-reply/reply/commands-core.js +2 -1
- package/dist/auto-reply/reply/commands-info.js +1 -0
- package/dist/auto-reply/reply/commands-models.js +65 -14
- package/dist/auto-reply/reply/commands-session.js +237 -82
- package/dist/auto-reply/reply/commands-setunset.js +45 -0
- package/dist/auto-reply/reply/commands-subagents/action-agents.js +44 -0
- package/dist/auto-reply/reply/commands-subagents/action-focus.js +64 -0
- package/dist/auto-reply/reply/commands-subagents/action-help.js +4 -0
- package/dist/auto-reply/reply/commands-subagents/action-info.js +45 -0
- package/dist/auto-reply/reply/commands-subagents/action-kill.js +60 -0
- package/dist/auto-reply/reply/commands-subagents/action-list.js +44 -0
- package/dist/auto-reply/reply/commands-subagents/action-log.js +29 -0
- package/dist/auto-reply/reply/commands-subagents/action-send.js +119 -0
- package/dist/auto-reply/reply/commands-subagents/action-spawn.js +52 -0
- package/dist/auto-reply/reply/commands-subagents/action-unfocus.js +30 -0
- package/dist/auto-reply/reply/commands-subagents/shared.js +303 -0
- package/dist/auto-reply/reply/commands-subagents.js +51 -587
- package/dist/auto-reply/reply/commands-tts.js +10 -5
- package/dist/auto-reply/reply/config-value.js +10 -5
- package/dist/auto-reply/reply/directive-handling.model-picker.js +12 -6
- package/dist/auto-reply/reply/directive-handling.persist.js +9 -21
- package/dist/auto-reply/reply/directive-handling.shared.js +24 -4
- package/dist/auto-reply/reply/followup-runner.js +1 -0
- package/dist/auto-reply/reply/get-reply-directives-utils.js +23 -14
- package/dist/auto-reply/reply/get-reply-directives.js +17 -28
- package/dist/auto-reply/reply/get-reply-inline-actions.js +1 -0
- package/dist/auto-reply/reply/get-reply.js +71 -12
- package/dist/auto-reply/reply/model-selection.js +80 -39
- package/dist/auto-reply/reply/queue/enqueue.js +10 -5
- package/dist/auto-reply/reply/queue/state.js +13 -12
- package/dist/auto-reply/reply/reply-payloads.js +67 -36
- package/dist/auto-reply/reply/reply-reference.js +9 -8
- package/dist/auto-reply/reply/route-reply.js +15 -8
- package/dist/auto-reply/reply/session-reset-prompt.js +1 -1
- package/dist/auto-reply/reply/session.js +22 -6
- package/dist/auto-reply/reply/strip-inbound-meta.js +147 -0
- package/dist/auto-reply/reply/subagents-utils.js +56 -30
- package/dist/auto-reply/reply/typing.js +46 -21
- package/dist/auto-reply/send-policy.js +14 -7
- package/dist/auto-reply/status.js +140 -16
- package/dist/auto-reply/templating.js +10 -5
- package/dist/auto-reply/thinking.js +7 -16
- package/dist/auto-reply/tokens.js +21 -5
- package/dist/browser/bridge-server.js +36 -20
- package/dist/browser/cdp.helpers.js +7 -14
- package/dist/browser/cdp.js +35 -15
- package/dist/browser/chrome.profile-decoration.js +7 -4
- package/dist/browser/config.js +4 -0
- package/dist/browser/extension-relay-auth.js +55 -0
- package/dist/browser/extension-relay.js +74 -29
- package/dist/browser/navigation-guard.js +9 -1
- package/dist/browser/paths.js +77 -0
- package/dist/browser/profiles.js +13 -8
- package/dist/browser/pw-ai-module.js +10 -5
- package/dist/browser/pw-session.js +76 -39
- package/dist/browser/pw-tools-core.interactions.js +14 -7
- package/dist/browser/pw-tools-core.state.js +12 -6
- package/dist/browser/routes/agent.act.js +2 -2
- package/dist/browser/server-context.js +7 -0
- package/dist/build-info.json +3 -3
- package/dist/channels/allow-from.js +2 -1
- package/dist/channels/allowlists/resolve-utils.js +43 -19
- package/dist/channels/channel-config.js +14 -7
- package/dist/channels/draft-stream-loop.js +7 -0
- package/dist/channels/model-overrides.js +82 -0
- package/dist/channels/plugins/normalize/imessage.js +14 -7
- package/dist/channels/plugins/normalize/slack.js +10 -5
- package/dist/channels/plugins/normalize/telegram.js +14 -7
- package/dist/channels/plugins/outbound/discord.js +80 -8
- package/dist/channels/plugins/outbound/signal.js +11 -11
- package/dist/channels/plugins/setup-helpers.js +10 -5
- package/dist/channels/sender-label.js +14 -7
- package/dist/channels/session.js +4 -2
- package/dist/channels/status-reactions.js +297 -0
- package/dist/cli/banner.js +1 -1
- package/dist/cli/browser-cli-actions-input/register.files-downloads.js +65 -56
- package/dist/cli/cli-name.js +11 -11
- package/dist/cli/cli-utils.js +13 -3
- package/dist/cli/command-format.js +1 -1
- package/dist/cli/config-cli.js +1 -1
- package/dist/cli/daemon-cli/lifecycle-core.js +31 -19
- package/dist/cli/daemon-cli/lifecycle.js +64 -2
- package/dist/cli/daemon-cli/restart-health.js +126 -0
- package/dist/cli/daemon-cli/status.gather.js +9 -13
- package/dist/cli/daemon-cli/status.print.js +2 -10
- package/dist/cli/deps.js +27 -22
- package/dist/cli/gateway-cli/run-loop.js +23 -5
- package/dist/cli/node-cli/register.js +14 -5
- package/dist/cli/nodes-media-utils.js +7 -2
- package/dist/cli/outbound-send-deps.js +2 -9
- package/dist/cli/outbound-send-mapping.js +11 -0
- package/dist/cli/pairing-cli.js +40 -14
- package/dist/cli/plugins-cli.js +34 -41
- package/dist/cli/ports.js +11 -10
- package/dist/cli/program/command-registry.js +2 -11
- package/dist/cli/program/command-tree.js +16 -0
- package/dist/cli/program/preaction.js +13 -9
- package/dist/cli/program/register.configure.js +3 -18
- package/dist/cli/program/register.maintenance.js +2 -2
- package/dist/cli/program/register.onboard.js +2 -0
- package/dist/cli/program/register.status-health-sessions.js +16 -17
- package/dist/cli/program/register.subclis.js +93 -52
- package/dist/cli/route.js +11 -7
- package/dist/cli/system-cli.js +36 -46
- package/dist/cli/update-cli/shared.js +22 -9
- package/dist/cli/update-cli/update-command.js +89 -14
- package/dist/cli/update-cli/wizard.js +6 -12
- package/dist/commands/agent/run-context.js +18 -5
- package/dist/commands/agent/session-store.js +17 -4
- package/dist/commands/agent.js +22 -2
- package/dist/commands/agents.bindings.js +14 -7
- package/dist/commands/agents.commands.add.js +13 -9
- package/dist/commands/agents.commands.identity.js +12 -6
- package/dist/commands/agents.commands.list.js +11 -6
- package/dist/commands/agents.config.js +8 -10
- package/dist/commands/agents.providers.js +12 -6
- package/dist/commands/auth-choice-options.js +103 -75
- package/dist/commands/auth-choice.apply.byteplus.js +55 -0
- package/dist/commands/auth-choice.apply.js +4 -0
- package/dist/commands/auth-choice.apply.minimax.js +61 -13
- package/dist/commands/auth-choice.apply.openai.js +3 -1
- package/dist/commands/auth-choice.apply.volcengine.js +55 -0
- package/dist/commands/auth-choice.preferred-provider.js +2 -0
- package/dist/commands/channels/remove.js +13 -6
- package/dist/commands/channels/shared.js +4 -14
- package/dist/commands/configure.commands.js +14 -0
- package/dist/commands/configure.gateway.js +2 -4
- package/dist/commands/configure.js +1 -1
- package/dist/commands/configure.shared.js +11 -0
- package/dist/commands/daemon-install-helpers.js +2 -2
- package/dist/commands/dashboard.js +12 -10
- package/dist/commands/docs.js +14 -8
- package/dist/commands/doctor-config-flow.js +11 -9
- package/dist/commands/doctor-legacy-config.js +281 -0
- package/dist/commands/doctor-state-integrity.js +99 -23
- package/dist/commands/doctor-update.js +12 -9
- package/dist/commands/models/list.list-command.js +7 -5
- package/dist/commands/models/set-image.js +2 -21
- package/dist/commands/node-daemon-install-helpers.js +10 -8
- package/dist/commands/onboard-auth.config-minimax.js +54 -80
- package/dist/commands/onboard-auth.config-opencode.js +2 -18
- package/dist/commands/onboard-auth.credentials.js +90 -13
- package/dist/commands/onboard-auth.js +1 -1
- package/dist/commands/onboard-auth.models.js +6 -5
- package/dist/commands/onboard-hooks.js +1 -1
- package/dist/commands/onboard-non-interactive/api-keys.js +14 -7
- package/dist/commands/onboard-non-interactive/local/auth-choice.js +64 -49
- package/dist/commands/onboard-provider-auth-flags.js +14 -0
- package/dist/commands/onboard-remote.js +14 -7
- package/dist/commands/onboard.js +11 -13
- package/dist/commands/sandbox-display.js +6 -5
- package/dist/commands/status-all/diagnosis.js +14 -10
- package/dist/commands/status-all/format.js +1 -0
- package/dist/commands/status.gateway-probe.js +1 -16
- package/dist/commands/systemd-linger.js +12 -6
- package/dist/config/agent-limits.js +2 -0
- package/dist/config/commands.js +30 -16
- package/dist/config/config-paths.js +9 -11
- package/dist/config/defaults.js +22 -2
- package/dist/config/discord-preview-streaming.js +104 -0
- package/dist/config/env-vars.js +37 -8
- package/dist/config/includes.js +4 -0
- package/dist/config/io.js +97 -12
- package/dist/config/legacy.migrations.part-1.js +189 -78
- package/dist/config/legacy.shared.js +3 -1
- package/dist/config/merge-patch.js +4 -0
- package/dist/config/prototype-keys.js +4 -0
- package/dist/config/schema.help.js +44 -7
- package/dist/config/schema.labels.js +38 -6
- package/dist/config/sessions/delivery-info.js +10 -3
- package/dist/config/sessions/main-session.js +10 -5
- package/dist/config/sessions/session-file.js +33 -0
- package/dist/config/sessions/session-key.js +10 -5
- package/dist/config/sessions/store.js +1 -1
- package/dist/config/sessions.js +1 -0
- package/dist/config/zod-schema.agent-runtime.js +11 -0
- package/dist/config/zod-schema.js +148 -13
- package/dist/config/zod-schema.providers-core.js +78 -4
- package/dist/config/zod-schema.providers.js +6 -1
- package/dist/config/zod-schema.session.js +41 -2
- package/dist/cron/run-log.js +3 -0
- package/dist/cron/schedule.js +21 -10
- package/dist/cron/service/ops.js +35 -21
- package/dist/cron/service/timer.js +116 -16
- package/dist/cron/stagger.js +3 -1
- package/dist/discord/api.js +12 -6
- package/dist/discord/draft-chunking.js +22 -0
- package/dist/discord/draft-stream.js +124 -0
- package/dist/discord/monitor/agent-components.js +1 -1
- package/dist/discord/monitor/commands.js +5 -0
- package/dist/discord/monitor/gateway-plugin.js +2 -1
- package/dist/discord/monitor/listeners.js +37 -27
- package/dist/discord/monitor/message-handler.js +4 -1
- package/dist/discord/monitor/message-handler.preflight.js +65 -8
- package/dist/discord/monitor/message-handler.process.js +246 -217
- package/dist/discord/monitor/message-utils.js +143 -6
- package/dist/discord/monitor/model-picker-preferences.js +143 -0
- package/dist/discord/monitor/model-picker.js +651 -0
- package/dist/discord/monitor/native-command.js +573 -16
- package/dist/discord/monitor/provider.allowlist.js +223 -0
- package/dist/discord/monitor/provider.js +275 -347
- package/dist/discord/monitor/provider.lifecycle.js +100 -0
- package/dist/discord/monitor/reply-delivery.js +123 -16
- package/dist/discord/monitor/thread-bindings.discord-api.js +215 -0
- package/dist/discord/monitor/thread-bindings.js +4 -0
- package/dist/discord/monitor/thread-bindings.lifecycle.js +177 -0
- package/dist/discord/monitor/thread-bindings.manager.js +423 -0
- package/dist/discord/monitor/thread-bindings.messages.js +55 -0
- package/dist/discord/monitor/thread-bindings.state.js +358 -0
- package/dist/discord/monitor/thread-bindings.types.js +6 -0
- package/dist/discord/resolve-users.js +33 -21
- package/dist/discord/send.channels.js +15 -0
- package/dist/discord/send.js +3 -2
- package/dist/discord/send.outbound.js +82 -26
- package/dist/discord/send.permissions.js +83 -30
- package/dist/discord/send.reactions.js +8 -4
- package/dist/discord/token.js +10 -5
- package/dist/discord/voice/command.js +263 -0
- package/dist/discord/voice/manager.js +531 -0
- package/dist/gateway/auth.js +34 -10
- package/dist/gateway/call.js +4 -16
- package/dist/gateway/client.js +28 -4
- package/dist/gateway/config-reload.js +3 -4
- package/dist/gateway/control-ui.js +219 -96
- package/dist/gateway/hooks-mapping.js +88 -38
- package/dist/gateway/http-auth-helpers.js +3 -2
- package/dist/gateway/http-endpoint-helpers.js +1 -0
- package/dist/gateway/net.js +54 -12
- package/dist/gateway/node-invoke-system-run-approval.js +14 -35
- package/dist/gateway/node-registry.js +10 -5
- package/dist/gateway/openai-http.js +1 -0
- package/dist/gateway/openresponses-http.js +1 -0
- package/dist/gateway/origin-check.js +1 -18
- package/dist/gateway/protocol/index.js +4 -3
- package/dist/gateway/protocol/schema/cron.js +1 -0
- package/dist/gateway/protocol/schema/devices.js +1 -0
- package/dist/gateway/protocol/schema/protocol-schemas.js +2 -1
- package/dist/gateway/protocol/schema/sessions.js +6 -0
- package/dist/gateway/role-policy.js +17 -0
- package/dist/gateway/server/ws-connection/connect-policy.js +37 -0
- package/dist/gateway/server/ws-connection/message-handler.js +175 -148
- package/dist/gateway/server-chat.js +83 -25
- package/dist/gateway/server-constants.js +10 -9
- package/dist/gateway/server-cron.js +1 -0
- package/dist/gateway/server-http.js +16 -7
- package/dist/gateway/server-maintenance.js +20 -5
- package/dist/gateway/server-methods/chat.js +10 -6
- package/dist/gateway/server-methods/config.js +12 -14
- package/dist/gateway/server-methods/devices.js +17 -3
- package/dist/gateway/server-methods/models.js +11 -1
- package/dist/gateway/server-methods/sessions.js +64 -8
- package/dist/gateway/server-methods/usage.js +162 -75
- package/dist/gateway/server-node-events.js +29 -0
- package/dist/gateway/server-runtime-config.js +34 -13
- package/dist/gateway/server-startup-memory.js +17 -11
- package/dist/gateway/session-utils.fs.js +32 -34
- package/dist/gateway/sessions-resolve.js +17 -5
- package/dist/gateway/test-helpers.openai-mock.js +14 -7
- package/dist/gateway/tools-invoke-http.js +21 -10
- package/dist/hooks/bundled/bootstrap-extra-files/handler.js +3 -1
- package/dist/hooks/bundled/command-logger/handler.js +7 -2
- package/dist/hooks/bundled/session-memory/handler.js +6 -5
- package/dist/hooks/frontmatter.js +6 -6
- package/dist/hooks/gmail-watcher.js +11 -6
- package/dist/hooks/internal-hooks.js +11 -1
- package/dist/hooks/llm-slug-generator.js +4 -1
- package/dist/hooks/workspace.js +47 -17
- package/dist/imessage/accounts.js +9 -20
- package/dist/imessage/monitor/inbound-processing.js +2 -1
- package/dist/infra/archive.js +174 -73
- package/dist/infra/control-ui-assets.js +14 -6
- package/dist/infra/device-pairing.js +108 -29
- package/dist/infra/env.js +10 -5
- package/dist/infra/exec-approvals-allowlist.js +122 -0
- package/dist/infra/exec-approvals-analysis.js +34 -3
- package/dist/infra/exec-approvals.js +5 -17
- package/dist/infra/exec-safe-bin-policy.js +53 -45
- package/dist/infra/fs-safe.js +71 -39
- package/dist/infra/gateway-lock.js +6 -2
- package/dist/infra/heartbeat-wake.js +6 -12
- package/dist/infra/host-env-security-policy.json +19 -0
- package/dist/infra/host-env-security.js +66 -0
- package/dist/infra/net/ssrf.js +131 -38
- package/dist/infra/outbound/bound-delivery-router.js +88 -0
- package/dist/infra/outbound/channel-selection.js +12 -6
- package/dist/infra/outbound/envelope.js +1 -1
- package/dist/infra/outbound/format.js +12 -6
- package/dist/infra/outbound/payloads.js +14 -7
- package/dist/infra/outbound/session-binding-service.js +123 -0
- package/dist/infra/path-guards.js +25 -0
- package/dist/infra/provider-usage.fetch.codex.js +7 -15
- package/dist/infra/provider-usage.fetch.gemini.js +14 -11
- package/dist/infra/provider-usage.fetch.shared.js +30 -1
- package/dist/infra/provider-usage.fetch.zai.js +10 -9
- package/dist/infra/retry-policy.js +4 -2
- package/dist/infra/retry.js +9 -5
- package/dist/infra/session-cost-usage.js +107 -59
- package/dist/infra/session-maintenance-warning.js +3 -1
- package/dist/infra/shell-env.js +98 -34
- package/dist/infra/ssh-config.js +12 -6
- package/dist/infra/system-run-command.js +49 -4
- package/dist/infra/update-channels.js +10 -5
- package/dist/line/accounts.js +5 -7
- package/dist/line/bot-access.js +8 -20
- package/dist/line/bot-handlers.js +3 -1
- package/dist/link-understanding/detect.js +15 -7
- package/dist/media/constants.js +15 -6
- package/dist/media/image-ops.js +7 -0
- package/dist/media/local-roots.js +3 -2
- package/dist/media-understanding/apply.js +4 -1
- package/dist/media-understanding/concurrency.js +8 -20
- package/dist/memory/backend-config.js +45 -6
- package/dist/memory/embeddings.js +10 -4
- package/dist/memory/fs-utils.js +23 -0
- package/dist/memory/manager-search.js +12 -6
- package/dist/memory/manager-sync-ops.js +12 -2
- package/dist/memory/qmd-manager.js +466 -53
- package/dist/memory/query-expansion.js +167 -3
- package/dist/memory/status-format.js +10 -5
- package/dist/memory/sync-memory-files.js +1 -1
- package/dist/node-host/invoke-system-run.js +281 -0
- package/dist/node-host/invoke.js +55 -337
- package/dist/pairing/pairing-store.js +22 -0
- package/dist/plugin-sdk/allow-from.js +1 -1
- package/dist/plugin-sdk/command-auth.js +3 -1
- package/dist/plugin-sdk/index.js +6 -3
- package/dist/plugin-sdk/webhook-targets.js +32 -0
- package/dist/plugins/bundled-dir.js +9 -6
- package/dist/plugins/hooks.js +50 -0
- package/dist/plugins/install.js +28 -16
- package/dist/plugins/runtime.js +3 -17
- package/dist/plugins/update.js +78 -12
- package/dist/process/spawn-utils.js +14 -7
- package/dist/providers/github-copilot-token.js +11 -6
- package/dist/providers/qwen-portal-oauth.js +14 -6
- package/dist/routing/account-id.js +30 -0
- package/dist/routing/resolve-route.js +3 -7
- package/dist/routing/session-key.js +2 -16
- package/dist/security/audit-channel.js +93 -2
- package/dist/security/audit-extra.async.js +159 -5
- package/dist/security/audit-extra.js +1 -1
- package/dist/security/audit-extra.sync.js +85 -6
- package/dist/security/audit.js +40 -4
- package/dist/security/dm-policy-shared.js +44 -0
- package/dist/security/external-content.js +26 -6
- package/dist/shared/entry-status.js +6 -0
- package/dist/shared/frontmatter.js +5 -5
- package/dist/shared/node-match.js +11 -4
- package/dist/shared/operator-scope-compat.js +8 -3
- package/dist/signal/accounts.js +7 -20
- package/dist/signal/monitor/event-handler.js +3 -1
- package/dist/slack/accounts.js +6 -19
- package/dist/slack/actions.js +11 -3
- package/dist/slack/monitor/auth.js +1 -1
- package/dist/slack/monitor/message-handler/dispatch.js +50 -29
- package/dist/slack/monitor/replies.js +15 -7
- package/dist/slack/monitor/slash.js +22 -13
- package/dist/slack/resolve-channels.js +10 -5
- package/dist/slack/send.js +102 -12
- package/dist/slack/stream-mode.js +10 -0
- package/dist/slack/streaming.js +4 -2
- package/dist/telegram/accounts.js +19 -14
- package/dist/telegram/bot/helpers.js +3 -5
- package/dist/telegram/bot-access.js +35 -36
- package/dist/telegram/bot-handlers.js +120 -148
- package/dist/telegram/bot-message-context.js +68 -9
- package/dist/telegram/bot-message-dispatch.js +155 -90
- package/dist/telegram/bot-native-commands.js +16 -0
- package/dist/telegram/draft-stream.js +14 -1
- package/dist/telegram/inline-buttons.js +5 -15
- package/dist/telegram/monitor.js +11 -7
- package/dist/telegram/network-config.js +19 -7
- package/dist/telegram/send.js +3 -2
- package/dist/telegram/sent-message-cache.js +5 -6
- package/dist/telegram/status-reaction-variants.js +208 -0
- package/dist/telegram/sticker-cache.js +11 -9
- package/dist/terminal/theme.js +12 -12
- package/dist/tts/tts.js +80 -567
- package/dist/tui/components/chat-log.js +41 -8
- package/dist/tui/theme/theme.js +10 -12
- package/dist/tui/tui-local-shell.js +16 -6
- package/dist/tui/tui.js +58 -6
- package/dist/utils/account-id.js +2 -4
- package/dist/utils/boolean.js +10 -5
- package/dist/utils/directive-tags.js +11 -0
- package/dist/utils/queue-helpers.js +67 -12
- package/dist/web/auto-reply/deliver-reply.js +8 -4
- package/dist/web/auto-reply/mentions.js +10 -5
- package/dist/web/auto-reply/monitor/group-members.js +14 -7
- package/dist/web/auto-reply/monitor/process-message.js +45 -24
- package/dist/web/inbound/access-control.js +5 -2
- package/dist/web/login-qr.js +12 -6
- package/dist/web/media.js +123 -16
- package/extensions/bluebubbles/src/monitor-processing.ts +580 -139
- package/extensions/bluebubbles/src/monitor.ts +208 -1950
- package/package.json +1 -1
package/dist/infra/net/ssrf.js
CHANGED
|
@@ -8,7 +8,11 @@ export class SsrFBlockedError extends Error {
|
|
|
8
8
|
this.name = "SsrFBlockedError";
|
|
9
9
|
}
|
|
10
10
|
}
|
|
11
|
-
const BLOCKED_HOSTNAMES = new Set([
|
|
11
|
+
const BLOCKED_HOSTNAMES = new Set([
|
|
12
|
+
"localhost",
|
|
13
|
+
"localhost.localdomain",
|
|
14
|
+
"metadata.google.internal",
|
|
15
|
+
]);
|
|
12
16
|
function normalizeHostnameSet(values) {
|
|
13
17
|
if (!values || values.length === 0) {
|
|
14
18
|
return new Set();
|
|
@@ -39,16 +43,72 @@ function matchesHostnameAllowlist(hostname, allowlist) {
|
|
|
39
43
|
}
|
|
40
44
|
return allowlist.some((pattern) => isHostnameAllowedByPattern(hostname, pattern));
|
|
41
45
|
}
|
|
46
|
+
function parseStrictIpv4Octet(part) {
|
|
47
|
+
if (!/^[0-9]+$/.test(part)) {
|
|
48
|
+
return null;
|
|
49
|
+
}
|
|
50
|
+
const value = Number.parseInt(part, 10);
|
|
51
|
+
if (Number.isNaN(value) || value < 0 || value > 255) {
|
|
52
|
+
return null;
|
|
53
|
+
}
|
|
54
|
+
// Accept only canonical decimal octets (no leading zeros, no alternate radices).
|
|
55
|
+
if (part !== String(value)) {
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
return value;
|
|
59
|
+
}
|
|
42
60
|
function parseIpv4(address) {
|
|
43
61
|
const parts = address.split(".");
|
|
44
62
|
if (parts.length !== 4) {
|
|
45
63
|
return null;
|
|
46
64
|
}
|
|
47
|
-
const
|
|
48
|
-
|
|
49
|
-
|
|
65
|
+
for (const part of parts) {
|
|
66
|
+
if (parseStrictIpv4Octet(part) === null) {
|
|
67
|
+
return null;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return parts.map((part) => Number.parseInt(part, 10));
|
|
71
|
+
}
|
|
72
|
+
function classifyIpv4Part(part) {
|
|
73
|
+
if (/^0x[0-9a-f]+$/i.test(part)) {
|
|
74
|
+
return "hex";
|
|
75
|
+
}
|
|
76
|
+
if (/^0x/i.test(part)) {
|
|
77
|
+
return "invalid-hex";
|
|
78
|
+
}
|
|
79
|
+
if (/^[0-9]+$/.test(part)) {
|
|
80
|
+
return "decimal";
|
|
81
|
+
}
|
|
82
|
+
return "non-numeric";
|
|
83
|
+
}
|
|
84
|
+
function isUnsupportedLegacyIpv4Literal(address) {
|
|
85
|
+
const parts = address.split(".");
|
|
86
|
+
if (parts.length === 0 || parts.length > 4) {
|
|
87
|
+
return false;
|
|
88
|
+
}
|
|
89
|
+
if (parts.some((part) => part.length === 0)) {
|
|
90
|
+
return true;
|
|
91
|
+
}
|
|
92
|
+
const partKinds = parts.map(classifyIpv4Part);
|
|
93
|
+
if (partKinds.some((kind) => kind === "non-numeric")) {
|
|
94
|
+
return false;
|
|
50
95
|
}
|
|
51
|
-
|
|
96
|
+
if (partKinds.some((kind) => kind === "invalid-hex")) {
|
|
97
|
+
return true;
|
|
98
|
+
}
|
|
99
|
+
if (parts.length !== 4) {
|
|
100
|
+
return true;
|
|
101
|
+
}
|
|
102
|
+
for (const part of parts) {
|
|
103
|
+
if (/^0x/i.test(part)) {
|
|
104
|
+
return true;
|
|
105
|
+
}
|
|
106
|
+
const value = Number.parseInt(part, 10);
|
|
107
|
+
if (Number.isNaN(value) || value > 255 || part !== String(value)) {
|
|
108
|
+
return true;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
return false;
|
|
52
112
|
}
|
|
53
113
|
function stripIpv6ZoneId(address) {
|
|
54
114
|
const index = address.indexOf("%");
|
|
@@ -148,6 +208,12 @@ const EMBEDDED_IPV4_RULES = [
|
|
|
148
208
|
matches: (hextets) => hextets[0] === 0x2001 && hextets[1] === 0x0000,
|
|
149
209
|
extract: (hextets) => [hextets[6] ^ 0xffff, hextets[7] ^ 0xffff],
|
|
150
210
|
},
|
|
211
|
+
{
|
|
212
|
+
// ISATAP IID format: 000000ug00000000:5efe:w.x.y.z (RFC 5214 section 6.1).
|
|
213
|
+
// Match only the IID marker bits to avoid over-broad :5efe: detection.
|
|
214
|
+
matches: (hextets) => (hextets[4] & 0xfcff) === 0 && hextets[5] === 0x5efe,
|
|
215
|
+
extract: (hextets) => [hextets[6], hextets[7]],
|
|
216
|
+
},
|
|
151
217
|
];
|
|
152
218
|
function extractIpv4FromEmbeddedIpv6(hextets) {
|
|
153
219
|
for (const rule of EMBEDDED_IPV4_RULES) {
|
|
@@ -159,31 +225,49 @@ function extractIpv4FromEmbeddedIpv6(hextets) {
|
|
|
159
225
|
}
|
|
160
226
|
return null;
|
|
161
227
|
}
|
|
162
|
-
function
|
|
163
|
-
const [
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
|
|
228
|
+
function ipv4ToUint(parts) {
|
|
229
|
+
const [a, b, c, d] = parts;
|
|
230
|
+
return (((a << 24) >>> 0) | (b << 16) | (c << 8) | d) >>> 0;
|
|
231
|
+
}
|
|
232
|
+
function ipv4RangeFromCidr(cidr) {
|
|
233
|
+
const base = ipv4ToUint(cidr.base);
|
|
234
|
+
const hostBits = 32 - cidr.prefixLength;
|
|
235
|
+
const mask = cidr.prefixLength === 0 ? 0 : (0xffffffff << hostBits) >>> 0;
|
|
236
|
+
const start = (base & mask) >>> 0;
|
|
237
|
+
const end = (start | (~mask >>> 0)) >>> 0;
|
|
238
|
+
return [start, end];
|
|
239
|
+
}
|
|
240
|
+
const BLOCKED_IPV4_SPECIAL_USE_CIDRS = [
|
|
241
|
+
{ base: [0, 0, 0, 0], prefixLength: 8 },
|
|
242
|
+
{ base: [10, 0, 0, 0], prefixLength: 8 },
|
|
243
|
+
{ base: [100, 64, 0, 0], prefixLength: 10 },
|
|
244
|
+
{ base: [127, 0, 0, 0], prefixLength: 8 },
|
|
245
|
+
{ base: [169, 254, 0, 0], prefixLength: 16 },
|
|
246
|
+
{ base: [172, 16, 0, 0], prefixLength: 12 },
|
|
247
|
+
{ base: [192, 0, 0, 0], prefixLength: 24 },
|
|
248
|
+
{ base: [192, 0, 2, 0], prefixLength: 24 },
|
|
249
|
+
{ base: [192, 88, 99, 0], prefixLength: 24 },
|
|
250
|
+
{ base: [192, 168, 0, 0], prefixLength: 16 },
|
|
251
|
+
{ base: [198, 18, 0, 0], prefixLength: 15 },
|
|
252
|
+
{ base: [198, 51, 100, 0], prefixLength: 24 },
|
|
253
|
+
{ base: [203, 0, 113, 0], prefixLength: 24 },
|
|
254
|
+
{ base: [224, 0, 0, 0], prefixLength: 4 },
|
|
255
|
+
{ base: [240, 0, 0, 0], prefixLength: 4 },
|
|
256
|
+
];
|
|
257
|
+
const BLOCKED_IPV4_SPECIAL_USE_RANGES = BLOCKED_IPV4_SPECIAL_USE_CIDRS.map(ipv4RangeFromCidr);
|
|
258
|
+
function isBlockedIpv4SpecialUse(parts) {
|
|
259
|
+
if (parts.length !== 4) {
|
|
260
|
+
return false;
|
|
181
261
|
}
|
|
182
|
-
|
|
183
|
-
|
|
262
|
+
const value = ipv4ToUint(parts);
|
|
263
|
+
for (const [start, end] of BLOCKED_IPV4_SPECIAL_USE_RANGES) {
|
|
264
|
+
if (value >= start && value <= end) {
|
|
265
|
+
return true;
|
|
266
|
+
}
|
|
184
267
|
}
|
|
185
268
|
return false;
|
|
186
269
|
}
|
|
270
|
+
// Returns true for private/internal and special-use non-global addresses.
|
|
187
271
|
export function isPrivateIpAddress(address) {
|
|
188
272
|
let normalized = address.trim().toLowerCase();
|
|
189
273
|
if (normalized.startsWith("[") && normalized.endsWith("]")) {
|
|
@@ -219,7 +303,7 @@ export function isPrivateIpAddress(address) {
|
|
|
219
303
|
}
|
|
220
304
|
const embeddedIpv4 = extractIpv4FromEmbeddedIpv6(hextets);
|
|
221
305
|
if (embeddedIpv4) {
|
|
222
|
-
return
|
|
306
|
+
return isBlockedIpv4SpecialUse(embeddedIpv4);
|
|
223
307
|
}
|
|
224
308
|
// IPv6 private/internal ranges
|
|
225
309
|
// - link-local: fe80::/10
|
|
@@ -238,16 +322,23 @@ export function isPrivateIpAddress(address) {
|
|
|
238
322
|
return false;
|
|
239
323
|
}
|
|
240
324
|
const ipv4 = parseIpv4(normalized);
|
|
241
|
-
if (
|
|
242
|
-
return
|
|
325
|
+
if (ipv4) {
|
|
326
|
+
return isBlockedIpv4SpecialUse(ipv4);
|
|
243
327
|
}
|
|
244
|
-
|
|
328
|
+
// Reject non-canonical IPv4 literal forms (octal/hex/short/packed) by default.
|
|
329
|
+
if (isUnsupportedLegacyIpv4Literal(normalized)) {
|
|
330
|
+
return true;
|
|
331
|
+
}
|
|
332
|
+
return false;
|
|
245
333
|
}
|
|
246
334
|
export function isBlockedHostname(hostname) {
|
|
247
335
|
const normalized = normalizeHostname(hostname);
|
|
248
336
|
if (!normalized) {
|
|
249
337
|
return false;
|
|
250
338
|
}
|
|
339
|
+
return isBlockedHostnameNormalized(normalized);
|
|
340
|
+
}
|
|
341
|
+
function isBlockedHostnameNormalized(normalized) {
|
|
251
342
|
if (BLOCKED_HOSTNAMES.has(normalized)) {
|
|
252
343
|
return true;
|
|
253
344
|
}
|
|
@@ -255,6 +346,13 @@ export function isBlockedHostname(hostname) {
|
|
|
255
346
|
normalized.endsWith(".local") ||
|
|
256
347
|
normalized.endsWith(".internal"));
|
|
257
348
|
}
|
|
349
|
+
export function isBlockedHostnameOrIp(hostname) {
|
|
350
|
+
const normalized = normalizeHostname(hostname);
|
|
351
|
+
if (!normalized) {
|
|
352
|
+
return false;
|
|
353
|
+
}
|
|
354
|
+
return isBlockedHostnameNormalized(normalized) || isPrivateIpAddress(normalized);
|
|
355
|
+
}
|
|
258
356
|
export function createPinnedLookup(params) {
|
|
259
357
|
const normalizedHost = normalizeHostname(params.hostname);
|
|
260
358
|
const fallback = params.fallback ?? dnsLookupCb;
|
|
@@ -306,13 +404,8 @@ export async function resolvePinnedHostnameWithPolicy(hostname, params = {}) {
|
|
|
306
404
|
if (!matchesHostnameAllowlist(normalized, hostnameAllowlist)) {
|
|
307
405
|
throw new SsrFBlockedError(`Blocked hostname (not in allowlist): ${hostname}`);
|
|
308
406
|
}
|
|
309
|
-
if (!allowPrivateNetwork && !isExplicitAllowed) {
|
|
310
|
-
|
|
311
|
-
throw new SsrFBlockedError(`Blocked hostname: ${hostname}`);
|
|
312
|
-
}
|
|
313
|
-
if (isPrivateIpAddress(normalized)) {
|
|
314
|
-
throw new SsrFBlockedError("Blocked: private/internal IP address");
|
|
315
|
-
}
|
|
407
|
+
if (!allowPrivateNetwork && !isExplicitAllowed && isBlockedHostnameOrIp(normalized)) {
|
|
408
|
+
throw new SsrFBlockedError("Blocked hostname or private/internal/special-use IP address");
|
|
316
409
|
}
|
|
317
410
|
const lookupFn = params.lookupFn ?? dnsLookup;
|
|
318
411
|
const results = await lookupFn(normalized, { all: true });
|
|
@@ -322,7 +415,7 @@ export async function resolvePinnedHostnameWithPolicy(hostname, params = {}) {
|
|
|
322
415
|
if (!allowPrivateNetwork && !isExplicitAllowed) {
|
|
323
416
|
for (const entry of results) {
|
|
324
417
|
if (isPrivateIpAddress(entry.address)) {
|
|
325
|
-
throw new SsrFBlockedError("Blocked: resolves to private/internal IP address");
|
|
418
|
+
throw new SsrFBlockedError("Blocked: resolves to private/internal/special-use IP address");
|
|
326
419
|
}
|
|
327
420
|
}
|
|
328
421
|
}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { getSessionBindingService, } from "./session-binding-service.js";
|
|
2
|
+
function isActiveBinding(record) {
|
|
3
|
+
return record.status === "active";
|
|
4
|
+
}
|
|
5
|
+
function resolveBindingForRequester(requester, bindings) {
|
|
6
|
+
const matchingChannelAccount = bindings.filter((entry) => entry.conversation.channel === requester.channel &&
|
|
7
|
+
entry.conversation.accountId === requester.accountId);
|
|
8
|
+
if (matchingChannelAccount.length === 0) {
|
|
9
|
+
return null;
|
|
10
|
+
}
|
|
11
|
+
const exactConversation = matchingChannelAccount.find((entry) => entry.conversation.conversationId === requester.conversationId);
|
|
12
|
+
if (exactConversation) {
|
|
13
|
+
return exactConversation;
|
|
14
|
+
}
|
|
15
|
+
if (matchingChannelAccount.length === 1) {
|
|
16
|
+
return matchingChannelAccount[0] ?? null;
|
|
17
|
+
}
|
|
18
|
+
return null;
|
|
19
|
+
}
|
|
20
|
+
export function createBoundDeliveryRouter(service = getSessionBindingService()) {
|
|
21
|
+
return {
|
|
22
|
+
resolveDestination: (input) => {
|
|
23
|
+
const targetSessionKey = input.targetSessionKey.trim();
|
|
24
|
+
if (!targetSessionKey) {
|
|
25
|
+
return {
|
|
26
|
+
binding: null,
|
|
27
|
+
mode: "fallback",
|
|
28
|
+
reason: "missing-target-session",
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
const activeBindings = service.listBySession(targetSessionKey).filter(isActiveBinding);
|
|
32
|
+
if (activeBindings.length === 0) {
|
|
33
|
+
return {
|
|
34
|
+
binding: null,
|
|
35
|
+
mode: "fallback",
|
|
36
|
+
reason: "no-active-binding",
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
if (!input.requester) {
|
|
40
|
+
if (activeBindings.length === 1) {
|
|
41
|
+
return {
|
|
42
|
+
binding: activeBindings[0] ?? null,
|
|
43
|
+
mode: "bound",
|
|
44
|
+
reason: "single-active-binding",
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
return {
|
|
48
|
+
binding: null,
|
|
49
|
+
mode: "fallback",
|
|
50
|
+
reason: "ambiguous-without-requester",
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
const requester = {
|
|
54
|
+
channel: input.requester.channel.trim().toLowerCase(),
|
|
55
|
+
accountId: input.requester.accountId.trim(),
|
|
56
|
+
conversationId: input.requester.conversationId.trim(),
|
|
57
|
+
parentConversationId: input.requester.parentConversationId?.trim() || undefined,
|
|
58
|
+
};
|
|
59
|
+
if (!requester.channel || !requester.conversationId) {
|
|
60
|
+
return {
|
|
61
|
+
binding: null,
|
|
62
|
+
mode: "fallback",
|
|
63
|
+
reason: "invalid-requester",
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
const fromRequester = resolveBindingForRequester(requester, activeBindings);
|
|
67
|
+
if (fromRequester) {
|
|
68
|
+
return {
|
|
69
|
+
binding: fromRequester,
|
|
70
|
+
mode: "bound",
|
|
71
|
+
reason: "requester-match",
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
if (activeBindings.length === 1 && !input.failClosed) {
|
|
75
|
+
return {
|
|
76
|
+
binding: activeBindings[0] ?? null,
|
|
77
|
+
mode: "bound",
|
|
78
|
+
reason: "single-active-binding-fallback",
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
return {
|
|
82
|
+
binding: null,
|
|
83
|
+
mode: "fallback",
|
|
84
|
+
reason: "no-requester-match",
|
|
85
|
+
};
|
|
86
|
+
},
|
|
87
|
+
};
|
|
88
|
+
}
|
|
@@ -5,35 +5,41 @@ function isKnownChannel(value) {
|
|
|
5
5
|
return getMessageChannels().includes(value);
|
|
6
6
|
}
|
|
7
7
|
function isAccountEnabled(account) {
|
|
8
|
-
if (!account || typeof account !== "object")
|
|
8
|
+
if (!account || typeof account !== "object") {
|
|
9
9
|
return true;
|
|
10
|
+
}
|
|
10
11
|
const enabled = account.enabled;
|
|
11
12
|
return enabled !== false;
|
|
12
13
|
}
|
|
13
14
|
async function isPluginConfigured(plugin, cfg) {
|
|
14
15
|
const accountIds = plugin.config.listAccountIds(cfg);
|
|
15
|
-
if (accountIds.length === 0)
|
|
16
|
+
if (accountIds.length === 0) {
|
|
16
17
|
return false;
|
|
18
|
+
}
|
|
17
19
|
for (const accountId of accountIds) {
|
|
18
20
|
const account = plugin.config.resolveAccount(cfg, accountId);
|
|
19
21
|
const enabled = plugin.config.isEnabled
|
|
20
22
|
? plugin.config.isEnabled(account, cfg)
|
|
21
23
|
: isAccountEnabled(account);
|
|
22
|
-
if (!enabled)
|
|
24
|
+
if (!enabled) {
|
|
23
25
|
continue;
|
|
24
|
-
|
|
26
|
+
}
|
|
27
|
+
if (!plugin.config.isConfigured) {
|
|
25
28
|
return true;
|
|
29
|
+
}
|
|
26
30
|
const configured = await plugin.config.isConfigured(account, cfg);
|
|
27
|
-
if (configured)
|
|
31
|
+
if (configured) {
|
|
28
32
|
return true;
|
|
33
|
+
}
|
|
29
34
|
}
|
|
30
35
|
return false;
|
|
31
36
|
}
|
|
32
37
|
export async function listConfiguredMessageChannels(cfg) {
|
|
33
38
|
const channels = [];
|
|
34
39
|
for (const plugin of listChannelPlugins()) {
|
|
35
|
-
if (!isKnownChannel(plugin.id))
|
|
40
|
+
if (!isKnownChannel(plugin.id)) {
|
|
36
41
|
continue;
|
|
42
|
+
}
|
|
37
43
|
if (await isPluginConfigured(plugin, cfg)) {
|
|
38
44
|
channels.push(plugin.id);
|
|
39
45
|
}
|
|
@@ -7,7 +7,7 @@ export function buildOutboundResultEnvelope(params) {
|
|
|
7
7
|
: params.payloads.length === 0
|
|
8
8
|
? []
|
|
9
9
|
: isOutboundPayloadJson(params.payloads[0])
|
|
10
|
-
? params.payloads
|
|
10
|
+
? [...params.payloads]
|
|
11
11
|
: normalizeOutboundPayloadsForJson(params.payloads);
|
|
12
12
|
if (params.flattenDelivery !== false && params.delivery && !params.meta && !hasPayloads) {
|
|
13
13
|
return params.delivery;
|
|
@@ -2,11 +2,13 @@ import { getChannelPlugin } from "../../channels/plugins/index.js";
|
|
|
2
2
|
import { getChatChannelMeta, normalizeChatChannelId } from "../../channels/registry.js";
|
|
3
3
|
const resolveChannelLabel = (channel) => {
|
|
4
4
|
const pluginLabel = getChannelPlugin(channel)?.meta.label;
|
|
5
|
-
if (pluginLabel)
|
|
5
|
+
if (pluginLabel) {
|
|
6
6
|
return pluginLabel;
|
|
7
|
+
}
|
|
7
8
|
const normalized = normalizeChatChannelId(channel);
|
|
8
|
-
if (normalized)
|
|
9
|
+
if (normalized) {
|
|
9
10
|
return getChatChannelMeta(normalized).label;
|
|
11
|
+
}
|
|
10
12
|
return channel;
|
|
11
13
|
};
|
|
12
14
|
export function formatOutboundDeliverySummary(channel, result) {
|
|
@@ -15,14 +17,18 @@ export function formatOutboundDeliverySummary(channel, result) {
|
|
|
15
17
|
}
|
|
16
18
|
const label = resolveChannelLabel(result.channel);
|
|
17
19
|
const base = `✅ Sent via ${label}. Message ID: ${result.messageId}`;
|
|
18
|
-
if ("chatId" in result)
|
|
20
|
+
if ("chatId" in result) {
|
|
19
21
|
return `${base} (chat ${result.chatId})`;
|
|
20
|
-
|
|
22
|
+
}
|
|
23
|
+
if ("channelId" in result) {
|
|
21
24
|
return `${base} (channel ${result.channelId})`;
|
|
22
|
-
|
|
25
|
+
}
|
|
26
|
+
if ("roomId" in result) {
|
|
23
27
|
return `${base} (room ${result.roomId})`;
|
|
24
|
-
|
|
28
|
+
}
|
|
29
|
+
if ("conversationId" in result) {
|
|
25
30
|
return `${base} (conversation ${result.conversationId})`;
|
|
31
|
+
}
|
|
26
32
|
return base;
|
|
27
33
|
}
|
|
28
34
|
export function buildOutboundDeliveryJson(params) {
|
|
@@ -4,14 +4,17 @@ function mergeMediaUrls(...lists) {
|
|
|
4
4
|
const seen = new Set();
|
|
5
5
|
const merged = [];
|
|
6
6
|
for (const list of lists) {
|
|
7
|
-
if (!list)
|
|
7
|
+
if (!list) {
|
|
8
8
|
continue;
|
|
9
|
+
}
|
|
9
10
|
for (const entry of list) {
|
|
10
11
|
const trimmed = entry?.trim();
|
|
11
|
-
if (!trimmed)
|
|
12
|
+
if (!trimmed) {
|
|
12
13
|
continue;
|
|
13
|
-
|
|
14
|
+
}
|
|
15
|
+
if (seen.has(trimmed)) {
|
|
14
16
|
continue;
|
|
17
|
+
}
|
|
15
18
|
seen.add(trimmed);
|
|
16
19
|
merged.push(trimmed);
|
|
17
20
|
}
|
|
@@ -36,10 +39,12 @@ export function normalizeReplyPayloadsForDelivery(payloads) {
|
|
|
36
39
|
replyToCurrent: payload.replyToCurrent || parsed.replyToCurrent,
|
|
37
40
|
audioAsVoice: Boolean(payload.audioAsVoice || parsed.audioAsVoice),
|
|
38
41
|
};
|
|
39
|
-
if (parsed.isSilent && mergedMedia.length === 0)
|
|
42
|
+
if (parsed.isSilent && mergedMedia.length === 0) {
|
|
40
43
|
return [];
|
|
41
|
-
|
|
44
|
+
}
|
|
45
|
+
if (!isRenderablePayload(next)) {
|
|
42
46
|
return [];
|
|
47
|
+
}
|
|
43
48
|
return [next];
|
|
44
49
|
});
|
|
45
50
|
}
|
|
@@ -70,9 +75,11 @@ export function normalizeOutboundPayloadsForJson(payloads) {
|
|
|
70
75
|
}
|
|
71
76
|
export function formatOutboundPayloadLog(payload) {
|
|
72
77
|
const lines = [];
|
|
73
|
-
if (payload.text)
|
|
78
|
+
if (payload.text) {
|
|
74
79
|
lines.push(payload.text.trimEnd());
|
|
75
|
-
|
|
80
|
+
}
|
|
81
|
+
for (const url of payload.mediaUrls) {
|
|
76
82
|
lines.push(`MEDIA:${url}`);
|
|
83
|
+
}
|
|
77
84
|
return lines.join("\n");
|
|
78
85
|
}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { normalizeAccountId } from "../../routing/session-key.js";
|
|
2
|
+
function normalizeConversationRef(ref) {
|
|
3
|
+
return {
|
|
4
|
+
channel: ref.channel.trim().toLowerCase(),
|
|
5
|
+
accountId: normalizeAccountId(ref.accountId),
|
|
6
|
+
conversationId: ref.conversationId.trim(),
|
|
7
|
+
parentConversationId: ref.parentConversationId?.trim() || undefined,
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
function toAdapterKey(params) {
|
|
11
|
+
return `${params.channel.trim().toLowerCase()}:${normalizeAccountId(params.accountId)}`;
|
|
12
|
+
}
|
|
13
|
+
const ADAPTERS_BY_CHANNEL_ACCOUNT = new Map();
|
|
14
|
+
export function registerSessionBindingAdapter(adapter) {
|
|
15
|
+
const key = toAdapterKey({
|
|
16
|
+
channel: adapter.channel,
|
|
17
|
+
accountId: adapter.accountId,
|
|
18
|
+
});
|
|
19
|
+
ADAPTERS_BY_CHANNEL_ACCOUNT.set(key, {
|
|
20
|
+
...adapter,
|
|
21
|
+
channel: adapter.channel.trim().toLowerCase(),
|
|
22
|
+
accountId: normalizeAccountId(adapter.accountId),
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
export function unregisterSessionBindingAdapter(params) {
|
|
26
|
+
ADAPTERS_BY_CHANNEL_ACCOUNT.delete(toAdapterKey(params));
|
|
27
|
+
}
|
|
28
|
+
function resolveAdapterForConversation(ref) {
|
|
29
|
+
const normalized = normalizeConversationRef(ref);
|
|
30
|
+
const key = toAdapterKey({
|
|
31
|
+
channel: normalized.channel,
|
|
32
|
+
accountId: normalized.accountId,
|
|
33
|
+
});
|
|
34
|
+
return ADAPTERS_BY_CHANNEL_ACCOUNT.get(key) ?? null;
|
|
35
|
+
}
|
|
36
|
+
function dedupeBindings(records) {
|
|
37
|
+
const byId = new Map();
|
|
38
|
+
for (const record of records) {
|
|
39
|
+
if (!record?.bindingId) {
|
|
40
|
+
continue;
|
|
41
|
+
}
|
|
42
|
+
byId.set(record.bindingId, record);
|
|
43
|
+
}
|
|
44
|
+
return [...byId.values()];
|
|
45
|
+
}
|
|
46
|
+
function createDefaultSessionBindingService() {
|
|
47
|
+
return {
|
|
48
|
+
bind: async (input) => {
|
|
49
|
+
const normalizedConversation = normalizeConversationRef(input.conversation);
|
|
50
|
+
const adapter = resolveAdapterForConversation(normalizedConversation);
|
|
51
|
+
if (!adapter?.bind) {
|
|
52
|
+
throw new Error(`Session binding adapter unavailable for ${normalizedConversation.channel}:${normalizedConversation.accountId}`);
|
|
53
|
+
}
|
|
54
|
+
const bound = await adapter.bind({
|
|
55
|
+
...input,
|
|
56
|
+
conversation: normalizedConversation,
|
|
57
|
+
});
|
|
58
|
+
if (!bound) {
|
|
59
|
+
throw new Error("Session binding adapter failed to bind target conversation");
|
|
60
|
+
}
|
|
61
|
+
return bound;
|
|
62
|
+
},
|
|
63
|
+
listBySession: (targetSessionKey) => {
|
|
64
|
+
const key = targetSessionKey.trim();
|
|
65
|
+
if (!key) {
|
|
66
|
+
return [];
|
|
67
|
+
}
|
|
68
|
+
const results = [];
|
|
69
|
+
for (const adapter of ADAPTERS_BY_CHANNEL_ACCOUNT.values()) {
|
|
70
|
+
const entries = adapter.listBySession(key);
|
|
71
|
+
if (entries.length > 0) {
|
|
72
|
+
results.push(...entries);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return dedupeBindings(results);
|
|
76
|
+
},
|
|
77
|
+
resolveByConversation: (ref) => {
|
|
78
|
+
const normalized = normalizeConversationRef(ref);
|
|
79
|
+
if (!normalized.channel || !normalized.conversationId) {
|
|
80
|
+
return null;
|
|
81
|
+
}
|
|
82
|
+
const adapter = resolveAdapterForConversation(normalized);
|
|
83
|
+
if (!adapter) {
|
|
84
|
+
return null;
|
|
85
|
+
}
|
|
86
|
+
return adapter.resolveByConversation(normalized);
|
|
87
|
+
},
|
|
88
|
+
touch: (bindingId, at) => {
|
|
89
|
+
const normalizedBindingId = bindingId.trim();
|
|
90
|
+
if (!normalizedBindingId) {
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
for (const adapter of ADAPTERS_BY_CHANNEL_ACCOUNT.values()) {
|
|
94
|
+
adapter.touch?.(normalizedBindingId, at);
|
|
95
|
+
}
|
|
96
|
+
},
|
|
97
|
+
unbind: async (input) => {
|
|
98
|
+
const removed = [];
|
|
99
|
+
for (const adapter of ADAPTERS_BY_CHANNEL_ACCOUNT.values()) {
|
|
100
|
+
if (!adapter.unbind) {
|
|
101
|
+
continue;
|
|
102
|
+
}
|
|
103
|
+
const entries = await adapter.unbind(input);
|
|
104
|
+
if (entries.length > 0) {
|
|
105
|
+
removed.push(...entries);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
return dedupeBindings(removed);
|
|
109
|
+
},
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
const DEFAULT_SESSION_BINDING_SERVICE = createDefaultSessionBindingService();
|
|
113
|
+
export function getSessionBindingService() {
|
|
114
|
+
return DEFAULT_SESSION_BINDING_SERVICE;
|
|
115
|
+
}
|
|
116
|
+
export const __testing = {
|
|
117
|
+
resetSessionBindingAdaptersForTests() {
|
|
118
|
+
ADAPTERS_BY_CHANNEL_ACCOUNT.clear();
|
|
119
|
+
},
|
|
120
|
+
getRegisteredAdapterKeys() {
|
|
121
|
+
return [...ADAPTERS_BY_CHANNEL_ACCOUNT.keys()];
|
|
122
|
+
},
|
|
123
|
+
};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
const NOT_FOUND_CODES = new Set(["ENOENT", "ENOTDIR"]);
|
|
3
|
+
const SYMLINK_OPEN_CODES = new Set(["ELOOP", "EINVAL", "ENOTSUP"]);
|
|
4
|
+
export function isNodeError(value) {
|
|
5
|
+
return Boolean(value && typeof value === "object" && "code" in value);
|
|
6
|
+
}
|
|
7
|
+
export function hasNodeErrorCode(value, code) {
|
|
8
|
+
return isNodeError(value) && value.code === code;
|
|
9
|
+
}
|
|
10
|
+
export function isNotFoundPathError(value) {
|
|
11
|
+
return isNodeError(value) && typeof value.code === "string" && NOT_FOUND_CODES.has(value.code);
|
|
12
|
+
}
|
|
13
|
+
export function isSymlinkOpenError(value) {
|
|
14
|
+
return isNodeError(value) && typeof value.code === "string" && SYMLINK_OPEN_CODES.has(value.code);
|
|
15
|
+
}
|
|
16
|
+
export function isPathInside(root, target) {
|
|
17
|
+
const resolvedRoot = path.resolve(root);
|
|
18
|
+
const resolvedTarget = path.resolve(target);
|
|
19
|
+
if (process.platform === "win32") {
|
|
20
|
+
const relative = path.win32.relative(resolvedRoot.toLowerCase(), resolvedTarget.toLowerCase());
|
|
21
|
+
return relative === "" || (!relative.startsWith("..") && !path.win32.isAbsolute(relative));
|
|
22
|
+
}
|
|
23
|
+
const relative = path.relative(resolvedRoot, resolvedTarget);
|
|
24
|
+
return relative === "" || (!relative.startsWith("..") && !path.isAbsolute(relative));
|
|
25
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { fetchJson } from "./provider-usage.fetch.shared.js";
|
|
1
|
+
import { buildUsageHttpErrorSnapshot, fetchJson } from "./provider-usage.fetch.shared.js";
|
|
2
2
|
import { clampPercent, PROVIDER_LABELS } from "./provider-usage.shared.js";
|
|
3
3
|
export async function fetchCodexUsage(token, accountId, timeoutMs, fetchFn) {
|
|
4
4
|
const headers = {
|
|
@@ -6,24 +6,16 @@ export async function fetchCodexUsage(token, accountId, timeoutMs, fetchFn) {
|
|
|
6
6
|
"User-Agent": "CodexBar",
|
|
7
7
|
Accept: "application/json",
|
|
8
8
|
};
|
|
9
|
-
if (accountId)
|
|
9
|
+
if (accountId) {
|
|
10
10
|
headers["ChatGPT-Account-Id"] = accountId;
|
|
11
|
-
const res = await fetchJson("https://chatgpt.com/backend-api/wham/usage", { method: "GET", headers }, timeoutMs, fetchFn);
|
|
12
|
-
if (res.status === 401 || res.status === 403) {
|
|
13
|
-
return {
|
|
14
|
-
provider: "openai-codex",
|
|
15
|
-
displayName: PROVIDER_LABELS["openai-codex"],
|
|
16
|
-
windows: [],
|
|
17
|
-
error: "Token expired",
|
|
18
|
-
};
|
|
19
11
|
}
|
|
12
|
+
const res = await fetchJson("https://chatgpt.com/backend-api/wham/usage", { method: "GET", headers }, timeoutMs, fetchFn);
|
|
20
13
|
if (!res.ok) {
|
|
21
|
-
return {
|
|
14
|
+
return buildUsageHttpErrorSnapshot({
|
|
22
15
|
provider: "openai-codex",
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
};
|
|
16
|
+
status: res.status,
|
|
17
|
+
tokenExpiredStatuses: [401, 403],
|
|
18
|
+
});
|
|
27
19
|
}
|
|
28
20
|
const data = (await res.json());
|
|
29
21
|
const windows = [];
|