@poolzin/pool-bot 2026.1.39 → 2026.2.1
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/assets/chrome-extension/README.md +3 -3
- package/assets/chrome-extension/background.js +5 -5
- package/assets/chrome-extension/manifest.json +3 -3
- package/assets/chrome-extension/options.html +4 -4
- package/assets/chrome-extension/options.js +1 -1
- package/dist/acp/client.js +3 -3
- package/dist/acp/types.js +1 -1
- package/dist/agents/agent-paths.js +3 -3
- package/dist/agents/auth-profiles/paths.js +3 -3
- package/dist/agents/bash-tools.exec.js +76 -25
- package/dist/agents/cli-runner/helpers.js +10 -12
- package/dist/agents/cli-runner.js +2 -2
- package/dist/agents/cloudflare-ai-gateway.js +31 -0
- package/dist/agents/compaction.js +16 -2
- package/dist/agents/context-window-guard.js +13 -10
- package/dist/agents/context.js +4 -4
- package/dist/agents/docs-path.js +1 -1
- package/dist/agents/identity.js +47 -7
- package/dist/agents/memory-search.js +25 -8
- package/dist/agents/minimax-vlm.js +1 -1
- package/dist/agents/model-auth.js +12 -1
- package/dist/agents/model-catalog.js +4 -4
- package/dist/agents/model-selection.js +31 -4
- package/dist/agents/models-config.js +3 -3
- package/dist/agents/models-config.providers.js +147 -39
- package/dist/agents/pi-embedded-block-chunker.js +117 -42
- package/dist/agents/pi-embedded-helpers/errors.js +183 -78
- package/dist/agents/pi-embedded-helpers/openai.js +1 -1
- package/dist/agents/pi-embedded-helpers.js +1 -1
- package/dist/agents/pi-embedded-runner/compact.js +9 -8
- package/dist/agents/pi-embedded-runner/model.js +63 -4
- package/dist/agents/pi-embedded-runner/run/attempt.js +27 -17
- package/dist/agents/pi-embedded-runner/run.js +203 -50
- package/dist/agents/pi-embedded-runner/system-prompt.js +10 -2
- package/dist/agents/pi-embedded-runner/tool-result-truncation.js +275 -0
- package/dist/agents/pi-embedded-runner/utils.js +1 -1
- package/dist/agents/pi-embedded-subscribe.js +118 -29
- package/dist/agents/pi-model-discovery.js +10 -0
- package/dist/agents/pi-tool-definition-adapter.js +50 -9
- package/dist/agents/pi-tools.before-tool-call.js +67 -0
- package/dist/agents/pi-tools.js +20 -10
- package/dist/agents/pi-tools.read.js +2 -2
- package/dist/agents/poolbot-tools.js +15 -10
- package/dist/agents/sandbox-paths.js +31 -0
- package/dist/agents/session-file-repair.js +83 -0
- package/dist/agents/session-tool-result-guard.js +94 -15
- package/dist/agents/session-transcript-repair.js +68 -0
- package/dist/agents/shell-utils.js +51 -0
- package/dist/agents/skills/bundled-context.js +23 -0
- package/dist/agents/skills/bundled-dir.js +41 -7
- package/dist/agents/skills/frontmatter.js +1 -1
- package/dist/agents/skills/workspace.js +2 -2
- package/dist/agents/skills-install.js +60 -23
- package/dist/agents/subagent-announce.js +79 -34
- package/dist/agents/system-prompt.js +28 -4
- package/dist/agents/together-models.js +127 -0
- package/dist/agents/tool-images.js +1 -1
- package/dist/agents/tool-policy.conformance.js +14 -0
- package/dist/agents/tool-policy.js +25 -1
- package/dist/agents/tools/browser-tool.js +3 -3
- package/dist/agents/tools/cron-tool.js +166 -19
- package/dist/agents/tools/discord-actions-presence.js +78 -0
- package/dist/agents/tools/image-tool.js +2 -2
- package/dist/agents/tools/memory-tool.js +93 -5
- package/dist/agents/tools/message-tool.js +56 -2
- package/dist/agents/tools/sessions-history-tool.js +69 -1
- package/dist/agents/tools/web-search.js +211 -42
- package/dist/agents/usage.js +23 -1
- package/dist/agents/workspace-run.js +67 -0
- package/dist/agents/workspace-templates.js +44 -0
- package/dist/auto-reply/command-auth.js +121 -6
- package/dist/auto-reply/commands-registry.data.js +1 -1
- package/dist/auto-reply/envelope.js +50 -72
- package/dist/auto-reply/reply/commands-compact.js +1 -0
- package/dist/auto-reply/reply/commands-context-report.js +3 -2
- package/dist/auto-reply/reply/commands-context.js +1 -0
- package/dist/auto-reply/reply/commands-models.js +107 -60
- package/dist/auto-reply/reply/commands-ptt.js +171 -0
- package/dist/auto-reply/reply/commands-session.js +2 -2
- package/dist/auto-reply/reply/get-reply-run.js +16 -5
- package/dist/auto-reply/reply/groups.js +1 -1
- package/dist/auto-reply/reply/inbound-context.js +9 -1
- package/dist/auto-reply/reply/inbound-meta.js +130 -0
- package/dist/auto-reply/reply/model-selection.js +3 -3
- package/dist/auto-reply/reply/untrusted-context.js +15 -0
- package/dist/auto-reply/status.js +1 -1
- package/dist/auto-reply/thinking.js +88 -43
- package/dist/browser/bridge-server.js +13 -0
- package/dist/browser/cdp.helpers.js +38 -24
- package/dist/browser/client-fetch.js +51 -8
- package/dist/browser/config.js +2 -11
- package/dist/browser/extension-relay.js +104 -43
- package/dist/browser/pw-ai.js +1 -1
- package/dist/browser/pw-session.js +143 -8
- package/dist/browser/pw-tools-core.interactions.js +125 -27
- package/dist/browser/pw-tools-core.responses.js +1 -1
- package/dist/browser/pw-tools-core.state.js +1 -1
- package/dist/browser/routes/agent.act.js +86 -41
- package/dist/browser/routes/dispatcher.js +4 -4
- package/dist/browser/screenshot.js +1 -1
- package/dist/browser/server-context.js +2 -2
- package/dist/browser/server.js +13 -0
- package/dist/build-info.json +3 -3
- package/dist/canvas-host/a2ui.js +3 -3
- package/dist/channels/plugins/catalog.js +2 -2
- package/dist/channels/plugins/onboarding/imessage.js +1 -1
- package/dist/channels/plugins/onboarding/signal.js +1 -1
- package/dist/channels/plugins/onboarding/slack.js +4 -4
- package/dist/channels/plugins/onboarding/whatsapp.js +3 -3
- package/dist/channels/plugins/pairing-message.js +1 -1
- package/dist/channels/reply-prefix.js +8 -1
- package/dist/cli/browser-cli-extension.js +2 -2
- package/dist/cli/cron-cli/register.cron-add.js +61 -40
- package/dist/cli/cron-cli/register.cron-edit.js +60 -34
- package/dist/cli/cron-cli/shared.js +56 -41
- package/dist/cli/dns-cli.js +26 -14
- package/dist/cli/docs-cli.js +1 -1
- package/dist/cli/gateway-cli/dev.js +1 -1
- package/dist/cli/gateway-cli/register.js +37 -19
- package/dist/cli/memory-cli.js +30 -20
- package/dist/cli/nodes-cli/register.canvas.js +1 -1
- package/dist/cli/parse-bytes.js +37 -0
- package/dist/cli/plugins-cli.js +1 -1
- package/dist/cli/run-main.js +2 -2
- package/dist/cli/security-cli.js +1 -1
- package/dist/cli/tagline.js +1 -1
- package/dist/cli/update-cli.js +173 -52
- package/dist/cli/webhooks-cli.js +5 -5
- package/dist/commands/agent.js +1 -0
- package/dist/commands/agents.commands.add.js +1 -1
- package/dist/commands/auth-choice.apply.api-providers.js +305 -17
- package/dist/commands/auth-choice.apply.js +4 -1
- package/dist/commands/auth-choice.apply.plugin-provider.js +2 -2
- package/dist/commands/auth-choice.apply.xai.js +63 -0
- package/dist/commands/auth-choice.preferred-provider.js +7 -1
- package/dist/commands/configure.wizard.js +1 -1
- package/dist/commands/dashboard.js +1 -1
- package/dist/commands/docs.js +1 -1
- package/dist/commands/doctor-config-flow.js +61 -5
- package/dist/commands/doctor-gateway-services.js +3 -3
- package/dist/commands/doctor-state-migrations.js +1 -1
- package/dist/commands/doctor-update.js +3 -3
- package/dist/commands/doctor.js +1 -1
- package/dist/commands/health.js +1 -1
- package/dist/commands/model-allowlist.js +29 -0
- package/dist/commands/model-picker.js +2 -1
- package/dist/commands/models/list.probe.js +2 -2
- package/dist/commands/models/list.registry.js +4 -4
- package/dist/commands/models/list.status-command.js +44 -24
- package/dist/commands/models/shared.js +15 -0
- package/dist/commands/onboard-auth.config-core.js +366 -28
- package/dist/commands/onboard-auth.credentials.js +71 -9
- package/dist/commands/onboard-auth.js +3 -3
- package/dist/commands/onboard-auth.models.js +26 -24
- package/dist/commands/onboard-custom.js +384 -0
- package/dist/commands/onboard-non-interactive/local/auth-choice-inference.js +35 -0
- package/dist/commands/onboard-non-interactive/local/auth-choice.js +146 -9
- package/dist/commands/onboard-skills.js +63 -38
- package/dist/commands/openai-model-default.js +41 -0
- package/dist/commands/status-all/report-lines.js +1 -1
- package/dist/commands/status.command.js +1 -1
- package/dist/commands/uninstall.js +3 -3
- package/dist/compat/legacy-names.js +1 -1
- package/dist/config/defaults.js +3 -2
- package/dist/config/io.js +3 -3
- package/dist/config/paths.js +136 -35
- package/dist/config/plugin-auto-enable.js +21 -5
- package/dist/config/redact-snapshot.js +153 -0
- package/dist/config/schema.field-metadata.js +590 -0
- package/dist/config/schema.js +3 -3
- package/dist/config/sessions/store.js +291 -23
- package/dist/config/types.memory.js +1 -0
- package/dist/config/version.js +4 -4
- package/dist/config/zod-schema.agent-defaults.js +3 -0
- package/dist/config/zod-schema.agent-runtime.js +13 -2
- package/dist/config/zod-schema.providers-core.js +142 -0
- package/dist/config/zod-schema.session.js +3 -0
- package/dist/cron/delivery.js +57 -0
- package/dist/cron/isolated-agent/delivery-target.js +18 -3
- package/dist/cron/isolated-agent/helpers.js +22 -5
- package/dist/cron/isolated-agent/run.js +171 -63
- package/dist/cron/isolated-agent/session.js +2 -0
- package/dist/cron/normalize.js +356 -28
- package/dist/cron/parse.js +10 -5
- package/dist/cron/run-log.js +35 -10
- package/dist/cron/schedule.js +41 -6
- package/dist/cron/service/jobs.js +208 -35
- package/dist/cron/service/ops.js +72 -16
- package/dist/cron/service/state.js +2 -0
- package/dist/cron/service/store.js +386 -14
- package/dist/cron/service/timer.js +390 -147
- package/dist/cron/session-reaper.js +86 -0
- package/dist/cron/store.js +23 -8
- package/dist/cron/validate-timestamp.js +43 -0
- package/dist/daemon/constants.js +7 -7
- package/dist/daemon/inspect.js +6 -6
- package/dist/daemon/systemd-unit.js +1 -1
- package/dist/discord/monitor/agent-components.js +438 -0
- package/dist/discord/monitor/allow-list.js +28 -5
- package/dist/discord/monitor/gateway-registry.js +29 -0
- package/dist/discord/monitor/native-command.js +44 -23
- package/dist/discord/monitor/sender-identity.js +45 -0
- package/dist/discord/pluralkit.js +27 -0
- package/dist/discord/send.outbound.js +92 -5
- package/dist/discord/send.shared.js +60 -23
- package/dist/discord/targets.js +84 -1
- package/dist/entry.js +15 -9
- package/dist/extensionAPI.js +8 -0
- package/dist/gateway/control-ui.js +8 -1
- package/dist/gateway/hooks-mapping.js +3 -0
- package/dist/gateway/hooks.js +65 -0
- package/dist/gateway/live-image-probe.js +1 -66
- package/dist/gateway/net.js +96 -31
- package/dist/gateway/node-command-policy.js +50 -15
- package/dist/gateway/openai-http.js +2 -2
- package/dist/gateway/openresponses-http.js +4 -4
- package/dist/gateway/origin-check.js +56 -0
- package/dist/gateway/protocol/client-info.js +9 -0
- package/dist/gateway/protocol/index.js +9 -2
- package/dist/gateway/protocol/schema/agents-models-skills.js +71 -1
- package/dist/gateway/protocol/schema/cron.js +22 -10
- package/dist/gateway/protocol/schema/protocol-schemas.js +16 -2
- package/dist/gateway/protocol/schema/sessions.js +12 -0
- package/dist/gateway/server/hooks.js +1 -1
- package/dist/gateway/server-broadcast.js +26 -9
- package/dist/gateway/server-chat.js +112 -23
- package/dist/gateway/server-discovery-runtime.js +10 -2
- package/dist/gateway/server-discovery.js +2 -2
- package/dist/gateway/server-http.js +110 -12
- package/dist/gateway/server-methods/agent-timestamp.js +60 -0
- package/dist/gateway/server-methods/agents.js +321 -2
- package/dist/gateway/server-methods/usage.js +559 -16
- package/dist/gateway/server-runtime-state.js +22 -8
- package/dist/gateway/server-startup-memory.js +16 -0
- package/dist/gateway/server.impl.js +7 -3
- package/dist/gateway/session-utils.fs.js +23 -25
- package/dist/gateway/session-utils.js +20 -10
- package/dist/gateway/sessions-patch.js +7 -22
- package/dist/gateway/test-helpers.server.js +35 -2
- package/dist/hooks/frontmatter.js +1 -1
- package/dist/hooks/hooks-status.js +1 -1
- package/dist/hooks/install.js +2 -2
- package/dist/hooks/loader.js +1 -1
- package/dist/hooks/workspace.js +3 -3
- package/dist/imessage/constants.js +2 -0
- package/dist/imessage/monitor/deliver.js +4 -1
- package/dist/imessage/monitor/monitor-provider.js +51 -1
- package/dist/index.js +2 -2
- package/dist/infra/bonjour-discovery.js +131 -70
- package/dist/infra/bonjour.js +3 -3
- package/dist/infra/control-ui-assets.js +134 -12
- package/dist/infra/errors.js +12 -0
- package/dist/infra/exec-approvals.js +266 -57
- package/dist/infra/format-time/format-datetime.js +79 -0
- package/dist/infra/format-time/format-duration.js +81 -0
- package/dist/infra/format-time/format-relative.js +80 -0
- package/dist/infra/heartbeat-runner.js +140 -49
- package/dist/infra/home-dir.js +54 -0
- package/dist/infra/net/fetch-guard.js +122 -0
- package/dist/infra/net/ssrf.js +65 -29
- package/dist/infra/outbound/abort.js +14 -0
- package/dist/infra/outbound/message-action-runner.js +77 -13
- package/dist/infra/outbound/outbound-session.js +143 -37
- package/dist/infra/path-env.js +3 -3
- package/dist/infra/poolbot-root.js +43 -1
- package/dist/infra/provider-usage.fetch.minimax.js +1 -1
- package/dist/infra/restart.js +1 -1
- package/dist/infra/session-cost-usage.js +631 -41
- package/dist/infra/state-migrations.js +317 -47
- package/dist/infra/tailscale.js +1 -1
- package/dist/infra/update-global.js +35 -0
- package/dist/infra/update-runner.js +149 -43
- package/dist/infra/warning-filter.js +65 -0
- package/dist/infra/widearea-dns.js +30 -9
- package/dist/logging/redact-identifier.js +12 -0
- package/dist/macos/relay.js +2 -2
- package/dist/media/fetch.js +81 -58
- package/dist/media/input-files.js +1 -1
- package/dist/media/mime.js +4 -0
- package/dist/media/png-encode.js +74 -0
- package/dist/media-understanding/apply.js +403 -3
- package/dist/media-understanding/attachments.js +38 -27
- package/dist/media-understanding/defaults.js +16 -0
- package/dist/media-understanding/providers/deepgram/audio.js +22 -14
- package/dist/media-understanding/providers/google/audio.js +24 -17
- package/dist/media-understanding/providers/google/video.js +24 -17
- package/dist/media-understanding/providers/image.js +4 -4
- package/dist/media-understanding/providers/index.js +4 -1
- package/dist/media-understanding/providers/openai/audio.js +22 -14
- package/dist/media-understanding/providers/shared.js +16 -11
- package/dist/media-understanding/providers/zai/index.js +6 -0
- package/dist/media-understanding/runner.js +158 -90
- package/dist/memory/backend-config.js +207 -0
- package/dist/memory/batch-voyage.js +277 -0
- package/dist/memory/embeddings-voyage.js +75 -0
- package/dist/memory/embeddings.js +29 -17
- package/dist/memory/internal.js +101 -18
- package/dist/memory/manager.js +155 -48
- package/dist/memory/search-manager.js +173 -0
- package/dist/memory/session-files.js +9 -3
- package/dist/memory/types.js +1 -0
- package/dist/node-host/runner.js +36 -26
- package/dist/node-host/with-timeout.js +27 -0
- package/dist/pairing/pairing-messages.js +1 -1
- package/dist/plugins/commands.js +5 -1
- package/dist/plugins/config-state.js +86 -7
- package/dist/plugins/discovery.js +1 -1
- package/dist/plugins/install.js +2 -2
- package/dist/plugins/source-display.js +51 -0
- package/dist/plugins/update.js +1 -1
- package/dist/process/exec.js +20 -2
- package/dist/routing/resolve-route.js +12 -0
- package/dist/routing/session-key.js +15 -0
- package/dist/runtime.js +2 -0
- package/dist/security/audit-extra.async.js +601 -0
- package/dist/security/audit-extra.js +2 -830
- package/dist/security/audit-extra.sync.js +505 -0
- package/dist/security/audit.js +2 -2
- package/dist/security/channel-metadata.js +34 -0
- package/dist/security/external-content.js +88 -6
- package/dist/security/skill-scanner.js +330 -0
- package/dist/sessions/session-key-utils.js +7 -0
- package/dist/shared/text/reasoning-tags.js +52 -7
- package/dist/signal/monitor/event-handler.js +80 -1
- package/dist/slack/monitor/media.js +85 -15
- package/dist/tailscale/detect.js +145 -0
- package/dist/telegram/bot/helpers.js +109 -28
- package/dist/telegram/bot-handlers.js +144 -3
- package/dist/telegram/bot-message-context.js +38 -11
- package/dist/telegram/bot-message-dispatch.js +48 -15
- package/dist/telegram/bot-native-commands.js +86 -29
- package/dist/telegram/bot.js +30 -29
- package/dist/telegram/model-buttons.js +163 -0
- package/dist/telegram/monitor.js +110 -85
- package/dist/telegram/send.js +129 -47
- package/dist/terminal/restore.js +45 -0
- package/dist/test-helpers/state-dir-env.js +16 -0
- package/dist/test-helpers/workspace.js +11 -0
- package/dist/test-utils/channel-plugins.js +82 -0
- package/dist/test-utils/ports.js +73 -0
- package/dist/tts/tts.js +12 -6
- package/dist/tui/tui-session-actions.js +166 -54
- package/dist/utils/fetch-timeout.js +20 -0
- package/dist/utils/normalize-secret-input.js +19 -0
- package/dist/utils/shell-argv.js +61 -0
- package/dist/utils/transcript-tools.js +58 -0
- package/dist/utils.js +55 -14
- package/dist/version.js +42 -5
- package/dist/web/qr-image.js +1 -61
- package/dist/wizard/onboarding.finalize.js +7 -7
- package/dist/wizard/onboarding.js +3 -3
- package/docs/RELEASE_WORKFOTS_COMPARISON.md +3 -3
- package/docs/_config.yml +2 -2
- package/docs/_layouts/default.html +9 -9
- package/docs/concepts/typebox.md +1 -1
- package/docs/docs.json +1 -1
- package/docs/northflank.mdx +7 -7
- package/docs/railway.mdx +3 -3
- package/docs/render.mdx +5 -5
- package/docs/start/lore.md +2 -2
- package/extensions/bluebubbles/index.ts +2 -2
- package/extensions/bluebubbles/package.json +1 -1
- package/extensions/bluebubbles/src/accounts.ts +8 -8
- package/extensions/bluebubbles/src/actions.test.ts +22 -22
- package/extensions/bluebubbles/src/actions.ts +5 -5
- package/extensions/bluebubbles/src/attachments.ts +2 -2
- package/extensions/bluebubbles/src/channel.ts +16 -16
- package/extensions/bluebubbles/src/chat.ts +2 -2
- package/extensions/bluebubbles/src/media-send.ts +2 -2
- package/extensions/bluebubbles/src/monitor.test.ts +46 -46
- package/extensions/bluebubbles/src/monitor.ts +5 -5
- package/extensions/bluebubbles/src/onboarding.ts +7 -7
- package/extensions/bluebubbles/src/reactions.ts +2 -2
- package/extensions/bluebubbles/src/send.ts +2 -2
- package/extensions/copilot-proxy/README.md +1 -1
- package/extensions/copilot-proxy/package.json +1 -1
- package/extensions/diagnostics-otel/index.ts +2 -2
- package/extensions/diagnostics-otel/package.json +1 -1
- package/extensions/diagnostics-otel/src/service.ts +3 -3
- package/extensions/discord/index.ts +2 -2
- package/extensions/discord/package.json +1 -1
- package/extensions/google-antigravity-auth/README.md +1 -1
- package/extensions/google-antigravity-auth/index.ts +1 -1
- package/extensions/google-antigravity-auth/package.json +1 -1
- package/extensions/google-gemini-cli-auth/README.md +1 -1
- package/extensions/google-gemini-cli-auth/oauth.ts +1 -1
- package/extensions/google-gemini-cli-auth/package.json +1 -1
- package/extensions/googlechat/index.ts +3 -3
- package/extensions/googlechat/package.json +1 -1
- package/extensions/googlechat/src/accounts.ts +8 -8
- package/extensions/googlechat/src/actions.ts +6 -6
- package/extensions/googlechat/src/channel.ts +21 -21
- package/extensions/googlechat/src/monitor.ts +8 -8
- package/extensions/googlechat/src/onboarding.ts +10 -10
- package/extensions/imessage/index.ts +2 -2
- package/extensions/imessage/package.json +1 -1
- package/extensions/line/index.ts +2 -2
- package/extensions/line/package.json +1 -1
- package/extensions/line/src/card-command.ts +2 -2
- package/extensions/line/src/channel.logout.test.ts +4 -4
- package/extensions/line/src/channel.sendPayload.test.ts +8 -8
- package/extensions/line/src/channel.ts +3 -3
- package/extensions/llm-task/README.md +3 -3
- package/extensions/llm-task/index.ts +2 -2
- package/extensions/llm-task/package.json +1 -1
- package/extensions/llm-task/src/llm-task-tool.ts +4 -4
- package/extensions/lobster/README.md +6 -6
- package/extensions/lobster/index.ts +2 -2
- package/extensions/lobster/src/lobster-tool.test.ts +4 -4
- package/extensions/lobster/src/lobster-tool.ts +2 -2
- package/extensions/matrix/index.ts +2 -2
- package/extensions/matrix/package.json +1 -1
- package/extensions/matrix/src/matrix/client/config.ts +1 -1
- package/extensions/matrix/src/matrix/monitor/handler.ts +1 -1
- package/extensions/matrix/src/onboarding.ts +1 -1
- package/extensions/mattermost/index.ts +2 -2
- package/extensions/mattermost/package.json +1 -1
- package/extensions/mattermost/src/mattermost/accounts.ts +8 -8
- package/extensions/mattermost/src/mattermost/monitor-helpers.ts +5 -5
- package/extensions/mattermost/src/mattermost/monitor.ts +2 -2
- package/extensions/mattermost/src/onboarding-helpers.ts +3 -3
- package/extensions/mattermost/src/onboarding.ts +2 -2
- package/extensions/memory-core/index.ts +2 -2
- package/extensions/memory-core/package.json +1 -1
- package/extensions/memory-lancedb/index.ts +3 -3
- package/extensions/memory-lancedb/package.json +1 -1
- package/extensions/msteams/index.ts +2 -2
- package/extensions/msteams/package.json +1 -1
- package/extensions/msteams/src/channel.directory.test.ts +2 -2
- package/extensions/msteams/src/channel.ts +2 -2
- package/extensions/msteams/src/graph-upload.ts +4 -4
- package/extensions/msteams/src/monitor-handler.ts +2 -2
- package/extensions/msteams/src/monitor.ts +2 -2
- package/extensions/msteams/src/onboarding.ts +9 -9
- package/extensions/msteams/src/reply-dispatcher.ts +2 -2
- package/extensions/msteams/src/send-context.ts +2 -2
- package/extensions/msteams/src/send.ts +4 -4
- package/extensions/nextcloud-talk/index.ts +2 -2
- package/extensions/nextcloud-talk/package.json +1 -1
- package/extensions/nextcloud-talk/src/channel.ts +7 -7
- package/extensions/nextcloud-talk/src/inbound.ts +7 -7
- package/extensions/nextcloud-talk/src/onboarding.ts +1 -1
- package/extensions/nostr/README.md +2 -2
- package/extensions/nostr/index.ts +5 -5
- package/extensions/nostr/package.json +1 -1
- package/extensions/nostr/src/types.ts +4 -4
- package/extensions/open-prose/index.ts +2 -2
- package/extensions/qwen-portal-auth/README.md +1 -1
- package/extensions/signal/index.ts +2 -2
- package/extensions/signal/package.json +1 -1
- package/extensions/slack/index.ts +2 -2
- package/extensions/slack/package.json +1 -1
- package/extensions/telegram/index.ts +2 -2
- package/extensions/telegram/package.json +1 -1
- package/extensions/telegram/src/channel.ts +2 -2
- package/extensions/tlon/README.md +2 -2
- package/extensions/tlon/index.ts +2 -2
- package/extensions/tlon/package.json +1 -1
- package/extensions/tlon/src/channel.ts +13 -13
- package/extensions/tlon/src/monitor/index.ts +3 -3
- package/extensions/tlon/src/onboarding.ts +3 -3
- package/extensions/tlon/src/types.ts +3 -3
- package/extensions/twitch/README.md +1 -1
- package/extensions/twitch/index.ts +2 -2
- package/extensions/twitch/package.json +1 -1
- package/extensions/twitch/src/config.ts +3 -3
- package/extensions/twitch/src/monitor.ts +3 -3
- package/extensions/twitch/src/onboarding.ts +9 -9
- package/extensions/twitch/src/outbound.test.ts +2 -2
- package/extensions/twitch/src/plugin.test.ts +2 -2
- package/extensions/twitch/src/plugin.ts +8 -8
- package/extensions/twitch/src/send.test.ts +2 -2
- package/extensions/twitch/src/send.ts +4 -4
- package/extensions/twitch/src/token.test.ts +8 -8
- package/extensions/twitch/src/token.ts +3 -3
- package/extensions/twitch/src/twitch-client.ts +3 -3
- package/extensions/twitch/src/types.ts +3 -3
- package/extensions/twitch/src/utils/markdown.ts +1 -1
- package/extensions/voice-call/README.md +3 -3
- package/extensions/voice-call/package.json +1 -1
- package/extensions/voice-call/src/core-bridge.ts +2 -2
- package/extensions/voice-call/src/response-generator.ts +1 -1
- package/extensions/whatsapp/index.ts +2 -2
- package/extensions/whatsapp/package.json +1 -1
- package/extensions/zalo/README.md +1 -1
- package/extensions/zalo/index.ts +2 -2
- package/extensions/zalo/package.json +1 -1
- package/extensions/zalo/src/accounts.ts +8 -8
- package/extensions/zalo/src/actions.ts +4 -4
- package/extensions/zalo/src/channel.directory.test.ts +2 -2
- package/extensions/zalo/src/channel.ts +18 -18
- package/extensions/zalo/src/monitor.ts +9 -9
- package/extensions/zalo/src/monitor.webhook.test.ts +2 -2
- package/extensions/zalo/src/onboarding.ts +24 -24
- package/extensions/zalo/src/send.ts +2 -2
- package/extensions/zalouser/README.md +2 -2
- package/extensions/zalouser/index.ts +2 -2
- package/extensions/zalouser/package.json +1 -1
- package/extensions/zalouser/src/accounts.ts +9 -9
- package/extensions/zalouser/src/channel.ts +24 -24
- package/extensions/zalouser/src/monitor.ts +4 -4
- package/extensions/zalouser/src/onboarding.ts +28 -28
- package/package.json +13 -251
- package/skills/nano-banana-pro/scripts/generate_image.py +1 -1
- package/skills/tmux/scripts/find-sessions.sh +1 -1
- package/CHANGELOG.md +0 -102
- package/README-header.png +0 -0
- package/git-hooks/pre-commit +0 -4
- package/scripts/format-staged.js +0 -148
- package/scripts/postinstall.js +0 -300
- package/scripts/setup-git-hooks.js +0 -96
|
@@ -10,8 +10,9 @@ import { formatForLog } from "./ws-log.js";
|
|
|
10
10
|
*/
|
|
11
11
|
function shouldSuppressHeartbeatBroadcast(runId) {
|
|
12
12
|
const runContext = getAgentRunContext(runId);
|
|
13
|
-
if (!runContext?.isHeartbeat)
|
|
13
|
+
if (!runContext?.isHeartbeat) {
|
|
14
14
|
return false;
|
|
15
|
+
}
|
|
15
16
|
try {
|
|
16
17
|
const cfg = loadConfig();
|
|
17
18
|
const visibility = resolveHeartbeatVisibility({ cfg, channel: "webchat" });
|
|
@@ -36,23 +37,28 @@ export function createChatRunRegistry() {
|
|
|
36
37
|
const peek = (sessionId) => chatRunSessions.get(sessionId)?.[0];
|
|
37
38
|
const shift = (sessionId) => {
|
|
38
39
|
const queue = chatRunSessions.get(sessionId);
|
|
39
|
-
if (!queue || queue.length === 0)
|
|
40
|
+
if (!queue || queue.length === 0) {
|
|
40
41
|
return undefined;
|
|
42
|
+
}
|
|
41
43
|
const entry = queue.shift();
|
|
42
|
-
if (!queue.length)
|
|
44
|
+
if (!queue.length) {
|
|
43
45
|
chatRunSessions.delete(sessionId);
|
|
46
|
+
}
|
|
44
47
|
return entry;
|
|
45
48
|
};
|
|
46
49
|
const remove = (sessionId, clientRunId, sessionKey) => {
|
|
47
50
|
const queue = chatRunSessions.get(sessionId);
|
|
48
|
-
if (!queue || queue.length === 0)
|
|
51
|
+
if (!queue || queue.length === 0) {
|
|
49
52
|
return undefined;
|
|
53
|
+
}
|
|
50
54
|
const idx = queue.findIndex((entry) => entry.clientRunId === clientRunId && (sessionKey ? entry.sessionKey === sessionKey : true));
|
|
51
|
-
if (idx < 0)
|
|
55
|
+
if (idx < 0) {
|
|
52
56
|
return undefined;
|
|
57
|
+
}
|
|
53
58
|
const [entry] = queue.splice(idx, 1);
|
|
54
|
-
if (!queue.length)
|
|
59
|
+
if (!queue.length) {
|
|
55
60
|
chatRunSessions.delete(sessionId);
|
|
61
|
+
}
|
|
56
62
|
return entry;
|
|
57
63
|
};
|
|
58
64
|
const clear = () => {
|
|
@@ -79,13 +85,69 @@ export function createChatRunState() {
|
|
|
79
85
|
clear,
|
|
80
86
|
};
|
|
81
87
|
}
|
|
82
|
-
|
|
88
|
+
const TOOL_EVENT_RECIPIENT_TTL_MS = 10 * 60 * 1000;
|
|
89
|
+
const TOOL_EVENT_RECIPIENT_FINAL_GRACE_MS = 30 * 1000;
|
|
90
|
+
export function createToolEventRecipientRegistry() {
|
|
91
|
+
const recipients = new Map();
|
|
92
|
+
const prune = () => {
|
|
93
|
+
if (recipients.size === 0) {
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
const now = Date.now();
|
|
97
|
+
for (const [runId, entry] of recipients) {
|
|
98
|
+
const cutoff = entry.finalizedAt
|
|
99
|
+
? entry.finalizedAt + TOOL_EVENT_RECIPIENT_FINAL_GRACE_MS
|
|
100
|
+
: entry.updatedAt + TOOL_EVENT_RECIPIENT_TTL_MS;
|
|
101
|
+
if (now >= cutoff) {
|
|
102
|
+
recipients.delete(runId);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
};
|
|
106
|
+
const add = (runId, connId) => {
|
|
107
|
+
if (!runId || !connId) {
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
const now = Date.now();
|
|
111
|
+
const existing = recipients.get(runId);
|
|
112
|
+
if (existing) {
|
|
113
|
+
existing.connIds.add(connId);
|
|
114
|
+
existing.updatedAt = now;
|
|
115
|
+
}
|
|
116
|
+
else {
|
|
117
|
+
recipients.set(runId, {
|
|
118
|
+
connIds: new Set([connId]),
|
|
119
|
+
updatedAt: now,
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
prune();
|
|
123
|
+
};
|
|
124
|
+
const get = (runId) => {
|
|
125
|
+
const entry = recipients.get(runId);
|
|
126
|
+
if (!entry) {
|
|
127
|
+
return undefined;
|
|
128
|
+
}
|
|
129
|
+
entry.updatedAt = Date.now();
|
|
130
|
+
prune();
|
|
131
|
+
return entry.connIds;
|
|
132
|
+
};
|
|
133
|
+
const markFinal = (runId) => {
|
|
134
|
+
const entry = recipients.get(runId);
|
|
135
|
+
if (!entry) {
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
entry.finalizedAt = Date.now();
|
|
139
|
+
prune();
|
|
140
|
+
};
|
|
141
|
+
return { add, get, markFinal };
|
|
142
|
+
}
|
|
143
|
+
export function createAgentEventHandler({ broadcast, broadcastToConnIds, nodeSendToSession, agentRunSeq, chatRunState, resolveSessionKeyForRun, clearAgentRunContext, toolEventRecipients, }) {
|
|
83
144
|
const emitChatDelta = (sessionKey, clientRunId, seq, text) => {
|
|
84
145
|
chatRunState.buffers.set(clientRunId, text);
|
|
85
146
|
const now = Date.now();
|
|
86
147
|
const last = chatRunState.deltaSentAt.get(clientRunId) ?? 0;
|
|
87
|
-
if (now - last < 150)
|
|
148
|
+
if (now - last < 150) {
|
|
88
149
|
return;
|
|
150
|
+
}
|
|
89
151
|
chatRunState.deltaSentAt.set(clientRunId, now);
|
|
90
152
|
const payload = {
|
|
91
153
|
runId: clientRunId,
|
|
@@ -139,23 +201,26 @@ export function createAgentEventHandler({ broadcast, nodeSendToSession, agentRun
|
|
|
139
201
|
broadcast("chat", payload);
|
|
140
202
|
nodeSendToSession(sessionKey, "chat", payload);
|
|
141
203
|
};
|
|
142
|
-
const
|
|
204
|
+
const resolveToolVerboseLevel = (runId, sessionKey) => {
|
|
143
205
|
const runContext = getAgentRunContext(runId);
|
|
144
206
|
const runVerbose = normalizeVerboseLevel(runContext?.verboseLevel);
|
|
145
|
-
if (runVerbose)
|
|
146
|
-
return runVerbose
|
|
147
|
-
|
|
148
|
-
|
|
207
|
+
if (runVerbose) {
|
|
208
|
+
return runVerbose;
|
|
209
|
+
}
|
|
210
|
+
if (!sessionKey) {
|
|
211
|
+
return "off";
|
|
212
|
+
}
|
|
149
213
|
try {
|
|
150
214
|
const { cfg, entry } = loadSessionEntry(sessionKey);
|
|
151
215
|
const sessionVerbose = normalizeVerboseLevel(entry?.verboseLevel);
|
|
152
|
-
if (sessionVerbose)
|
|
153
|
-
return sessionVerbose
|
|
216
|
+
if (sessionVerbose) {
|
|
217
|
+
return sessionVerbose;
|
|
218
|
+
}
|
|
154
219
|
const defaultVerbose = normalizeVerboseLevel(cfg.agents?.defaults?.verboseDefault);
|
|
155
|
-
return defaultVerbose
|
|
220
|
+
return defaultVerbose ?? "off";
|
|
156
221
|
}
|
|
157
222
|
catch {
|
|
158
|
-
return
|
|
223
|
+
return "off";
|
|
159
224
|
}
|
|
160
225
|
};
|
|
161
226
|
return (evt) => {
|
|
@@ -166,10 +231,17 @@ export function createAgentEventHandler({ broadcast, nodeSendToSession, agentRun
|
|
|
166
231
|
// Include sessionKey so Control UI can filter tool streams per session.
|
|
167
232
|
const agentPayload = sessionKey ? { ...evt, sessionKey } : evt;
|
|
168
233
|
const last = agentRunSeq.get(evt.runId) ?? 0;
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
234
|
+
const isToolEvent = evt.stream === "tool";
|
|
235
|
+
const toolVerbose = isToolEvent ? resolveToolVerboseLevel(evt.runId, sessionKey) : "off";
|
|
236
|
+
// Build tool payload: strip result/partialResult unless verbose=full
|
|
237
|
+
const toolPayload = isToolEvent && toolVerbose !== "full"
|
|
238
|
+
? (() => {
|
|
239
|
+
const data = evt.data ? { ...evt.data } : {};
|
|
240
|
+
delete data.result;
|
|
241
|
+
delete data.partialResult;
|
|
242
|
+
return sessionKey ? { ...evt, sessionKey, data } : { ...evt, data };
|
|
243
|
+
})()
|
|
244
|
+
: agentPayload;
|
|
173
245
|
if (evt.seq !== last + 1) {
|
|
174
246
|
broadcast("agent", {
|
|
175
247
|
runId: evt.runId,
|
|
@@ -184,10 +256,26 @@ export function createAgentEventHandler({ broadcast, nodeSendToSession, agentRun
|
|
|
184
256
|
});
|
|
185
257
|
}
|
|
186
258
|
agentRunSeq.set(evt.runId, evt.seq);
|
|
187
|
-
|
|
259
|
+
if (isToolEvent) {
|
|
260
|
+
// Always broadcast tool events to registered WS recipients with
|
|
261
|
+
// tool-events capability, regardless of verboseLevel. The verbose
|
|
262
|
+
// setting only controls whether tool details are sent as channel
|
|
263
|
+
// messages to messaging surfaces (Telegram, Discord, etc.).
|
|
264
|
+
const recipients = toolEventRecipients.get(evt.runId);
|
|
265
|
+
if (recipients && recipients.size > 0) {
|
|
266
|
+
broadcastToConnIds("agent", toolPayload, recipients);
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
else {
|
|
270
|
+
broadcast("agent", agentPayload);
|
|
271
|
+
}
|
|
188
272
|
const lifecyclePhase = evt.stream === "lifecycle" && typeof evt.data?.phase === "string" ? evt.data.phase : null;
|
|
189
273
|
if (sessionKey) {
|
|
190
|
-
|
|
274
|
+
// Send tool events to node/channel subscribers only when verbose is enabled;
|
|
275
|
+
// WS clients already received the event above via broadcastToConnIds.
|
|
276
|
+
if (!isToolEvent || toolVerbose !== "off") {
|
|
277
|
+
nodeSendToSession(sessionKey, "agent", isToolEvent ? toolPayload : agentPayload);
|
|
278
|
+
}
|
|
191
279
|
if (!isAborted && evt.stream === "assistant" && typeof evt.data?.text === "string") {
|
|
192
280
|
emitChatDelta(sessionKey, clientRunId, evt.seq, evt.data.text);
|
|
193
281
|
}
|
|
@@ -215,6 +303,7 @@ export function createAgentEventHandler({ broadcast, nodeSendToSession, agentRun
|
|
|
215
303
|
}
|
|
216
304
|
}
|
|
217
305
|
if (lifecyclePhase === "end" || lifecyclePhase === "error") {
|
|
306
|
+
toolEventRecipients.markFinal(evt.runId);
|
|
218
307
|
clearAgentRunContext(evt.runId);
|
|
219
308
|
}
|
|
220
309
|
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { startGatewayBonjourAdvertiser } from "../infra/bonjour.js";
|
|
2
2
|
import { pickPrimaryTailnetIPv4, pickPrimaryTailnetIPv6 } from "../infra/tailnet.js";
|
|
3
|
-
import {
|
|
3
|
+
import { resolveWideAreaDiscoveryDomain, writeWideAreaGatewayZone } from "../infra/widearea-dns.js";
|
|
4
4
|
import { formatBonjourInstanceName, resolveBonjourCliPath, resolveTailnetDnsHint, } from "./server-discovery.js";
|
|
5
5
|
export async function startGatewayDiscovery(params) {
|
|
6
6
|
let bonjourStop = null;
|
|
@@ -40,6 +40,13 @@ export async function startGatewayDiscovery(params) {
|
|
|
40
40
|
}
|
|
41
41
|
}
|
|
42
42
|
if (params.wideAreaDiscoveryEnabled) {
|
|
43
|
+
const wideAreaDomain = resolveWideAreaDiscoveryDomain({
|
|
44
|
+
configDomain: params.wideAreaDiscoveryDomain ?? undefined,
|
|
45
|
+
});
|
|
46
|
+
if (!wideAreaDomain) {
|
|
47
|
+
params.logDiscovery.warn("discovery.wideArea.enabled is true, but no domain was configured; set discovery.wideArea.domain to enable unicast DNS-SD");
|
|
48
|
+
return { bonjourStop };
|
|
49
|
+
}
|
|
43
50
|
const tailnetIPv4 = pickPrimaryTailnetIPv4();
|
|
44
51
|
if (!tailnetIPv4) {
|
|
45
52
|
params.logDiscovery.warn("discovery.wideArea.enabled is true, but no Tailscale IPv4 address was found; skipping unicast DNS-SD zone update");
|
|
@@ -48,6 +55,7 @@ export async function startGatewayDiscovery(params) {
|
|
|
48
55
|
try {
|
|
49
56
|
const tailnetIPv6 = pickPrimaryTailnetIPv6();
|
|
50
57
|
const result = await writeWideAreaGatewayZone({
|
|
58
|
+
domain: wideAreaDomain,
|
|
51
59
|
gatewayPort: params.port,
|
|
52
60
|
displayName: formatBonjourInstanceName(params.machineDisplayName),
|
|
53
61
|
tailnetIPv4,
|
|
@@ -58,7 +66,7 @@ export async function startGatewayDiscovery(params) {
|
|
|
58
66
|
sshPort,
|
|
59
67
|
cliPath: resolveBonjourCliPath(),
|
|
60
68
|
});
|
|
61
|
-
params.logDiscovery.info(`wide-area DNS-SD ${result.changed ? "updated" : "unchanged"} (${
|
|
69
|
+
params.logDiscovery.info(`wide-area DNS-SD ${result.changed ? "updated" : "unchanged"} (${wideAreaDomain} → ${result.zonePath})`);
|
|
62
70
|
}
|
|
63
71
|
catch (err) {
|
|
64
72
|
params.logDiscovery.warn(`wide-area discovery update failed: ${String(err)}`);
|
|
@@ -5,10 +5,10 @@ import { runExec } from "../process/exec.js";
|
|
|
5
5
|
export function formatBonjourInstanceName(displayName) {
|
|
6
6
|
const trimmed = displayName.trim();
|
|
7
7
|
if (!trimmed)
|
|
8
|
-
return "
|
|
8
|
+
return "Poolbot";
|
|
9
9
|
if (/poolbot/i.test(trimmed))
|
|
10
10
|
return trimmed;
|
|
11
|
-
return `${trimmed} (
|
|
11
|
+
return `${trimmed} (Poolbot)`;
|
|
12
12
|
}
|
|
13
13
|
export function resolveBonjourCliPath(opts = {}) {
|
|
14
14
|
const env = opts.env ?? process.env;
|
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
import { createServer as createHttpServer, } from "node:http";
|
|
2
2
|
import { createServer as createHttpsServer } from "node:https";
|
|
3
|
-
import { handleA2uiHttpRequest } from "../canvas-host/a2ui.js";
|
|
3
|
+
import { A2UI_PATH, CANVAS_HOST_PATH, CANVAS_WS_PATH, handleA2uiHttpRequest, } from "../canvas-host/a2ui.js";
|
|
4
4
|
import { loadConfig } from "../config/config.js";
|
|
5
|
-
import { handleSlackHttpRequest } from "../slack/http/index.js";
|
|
6
5
|
import { resolveAgentAvatar } from "../agents/identity-avatar.js";
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
6
|
+
import { handleSlackHttpRequest } from "../slack/http/index.js";
|
|
7
|
+
import { authorizeGatewayConnect, isLocalDirectRequest } from "./auth.js";
|
|
8
|
+
import { handleControlUiAvatarRequest, handleControlUiHttpRequest, } from "./control-ui.js";
|
|
9
|
+
import { extractHookToken, getHookAgentPolicyError, getHookChannelError, isHookAgentAllowed, normalizeAgentPayload, normalizeHookHeaders, normalizeWakePayload, readJsonBody, resolveHookTargetAgentId, resolveHookChannel, resolveHookDeliver, } from "./hooks.js";
|
|
9
10
|
import { applyHookMappings } from "./hooks-mapping.js";
|
|
11
|
+
import { sendUnauthorized } from "./http-common.js";
|
|
12
|
+
import { getBearerToken, getHeader } from "./http-utils.js";
|
|
13
|
+
import { resolveGatewayClientIp } from "./net.js";
|
|
10
14
|
import { handleOpenAiHttpRequest } from "./openai-http.js";
|
|
11
15
|
import { handleOpenResponsesHttpRequest } from "./openresponses-http.js";
|
|
12
16
|
import { handleToolsInvokeHttpRequest } from "./tools-invoke-http.js";
|
|
@@ -15,6 +19,49 @@ function sendJson(res, status, body) {
|
|
|
15
19
|
res.setHeader("Content-Type", "application/json; charset=utf-8");
|
|
16
20
|
res.end(JSON.stringify(body));
|
|
17
21
|
}
|
|
22
|
+
function isCanvasPath(pathname) {
|
|
23
|
+
return (pathname === A2UI_PATH ||
|
|
24
|
+
pathname.startsWith(`${A2UI_PATH}/`) ||
|
|
25
|
+
pathname === CANVAS_HOST_PATH ||
|
|
26
|
+
pathname.startsWith(`${CANVAS_HOST_PATH}/`) ||
|
|
27
|
+
pathname === CANVAS_WS_PATH);
|
|
28
|
+
}
|
|
29
|
+
function hasAuthorizedWsClientForIp(clients, clientIp) {
|
|
30
|
+
for (const client of clients) {
|
|
31
|
+
if (client.clientIp && client.clientIp === clientIp) {
|
|
32
|
+
return true;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
return false;
|
|
36
|
+
}
|
|
37
|
+
async function authorizeCanvasRequest(params) {
|
|
38
|
+
const { req, auth, trustedProxies, clients } = params;
|
|
39
|
+
if (isLocalDirectRequest(req, trustedProxies)) {
|
|
40
|
+
return true;
|
|
41
|
+
}
|
|
42
|
+
const token = getBearerToken(req);
|
|
43
|
+
if (token) {
|
|
44
|
+
const authResult = await authorizeGatewayConnect({
|
|
45
|
+
auth: { ...auth, allowTailscale: false },
|
|
46
|
+
connectAuth: { token, password: token },
|
|
47
|
+
req,
|
|
48
|
+
trustedProxies,
|
|
49
|
+
});
|
|
50
|
+
if (authResult.ok) {
|
|
51
|
+
return true;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
const clientIp = resolveGatewayClientIp({
|
|
55
|
+
remoteAddr: req.socket?.remoteAddress ?? "",
|
|
56
|
+
forwardedFor: getHeader(req, "x-forwarded-for"),
|
|
57
|
+
realIp: getHeader(req, "x-real-ip"),
|
|
58
|
+
trustedProxies,
|
|
59
|
+
});
|
|
60
|
+
if (!clientIp) {
|
|
61
|
+
return false;
|
|
62
|
+
}
|
|
63
|
+
return hasAuthorizedWsClientForIp(clients, clientIp);
|
|
64
|
+
}
|
|
18
65
|
export function createHooksRequestHandler(opts) {
|
|
19
66
|
const { getHooksConfig, bindHost, port, logHooks, dispatchAgentHook, dispatchWakeHook } = opts;
|
|
20
67
|
return async (req, res) => {
|
|
@@ -26,6 +73,8 @@ export function createHooksRequestHandler(opts) {
|
|
|
26
73
|
if (url.pathname !== basePath && !url.pathname.startsWith(`${basePath}/`)) {
|
|
27
74
|
return false;
|
|
28
75
|
}
|
|
76
|
+
// pool-bot keeps the deprecation-warning approach for query-param tokens
|
|
77
|
+
// (upstream hard-rejects; we warn and allow for now)
|
|
29
78
|
const { token, fromQuery } = extractHookToken(req, url);
|
|
30
79
|
if (!token || token !== hooksConfig.token) {
|
|
31
80
|
res.statusCode = 401;
|
|
@@ -36,7 +85,7 @@ export function createHooksRequestHandler(opts) {
|
|
|
36
85
|
if (fromQuery) {
|
|
37
86
|
logHooks.warn("Hook token provided via query parameter is deprecated for security reasons. " +
|
|
38
87
|
"Tokens in URLs appear in logs, browser history, and referrer headers. " +
|
|
39
|
-
"Use Authorization: Bearer <token> or X-
|
|
88
|
+
"Use Authorization: Bearer <token> or X-Poolbot-Token header instead.");
|
|
40
89
|
}
|
|
41
90
|
if (req.method !== "POST") {
|
|
42
91
|
res.statusCode = 405;
|
|
@@ -76,7 +125,14 @@ export function createHooksRequestHandler(opts) {
|
|
|
76
125
|
sendJson(res, 400, { ok: false, error: normalized.error });
|
|
77
126
|
return true;
|
|
78
127
|
}
|
|
79
|
-
|
|
128
|
+
if (!isHookAgentAllowed(hooksConfig, normalized.value.agentId)) {
|
|
129
|
+
sendJson(res, 400, { ok: false, error: getHookAgentPolicyError() });
|
|
130
|
+
return true;
|
|
131
|
+
}
|
|
132
|
+
const runId = dispatchAgentHook({
|
|
133
|
+
...normalized.value,
|
|
134
|
+
agentId: resolveHookTargetAgentId(hooksConfig, normalized.value.agentId),
|
|
135
|
+
});
|
|
80
136
|
sendJson(res, 202, { ok: true, runId });
|
|
81
137
|
return true;
|
|
82
138
|
}
|
|
@@ -111,9 +167,14 @@ export function createHooksRequestHandler(opts) {
|
|
|
111
167
|
sendJson(res, 400, { ok: false, error: getHookChannelError() });
|
|
112
168
|
return true;
|
|
113
169
|
}
|
|
170
|
+
if (!isHookAgentAllowed(hooksConfig, mapped.action.agentId)) {
|
|
171
|
+
sendJson(res, 400, { ok: false, error: getHookAgentPolicyError() });
|
|
172
|
+
return true;
|
|
173
|
+
}
|
|
114
174
|
const runId = dispatchAgentHook({
|
|
115
175
|
message: mapped.action.message,
|
|
116
176
|
name: mapped.action.name ?? "Hook",
|
|
177
|
+
agentId: resolveHookTargetAgentId(hooksConfig, mapped.action.agentId),
|
|
117
178
|
wakeMode: mapped.action.wakeMode,
|
|
118
179
|
sessionKey: mapped.action.sessionKey ?? "",
|
|
119
180
|
deliver: resolveHookDeliver(mapped.action.deliver),
|
|
@@ -141,7 +202,7 @@ export function createHooksRequestHandler(opts) {
|
|
|
141
202
|
};
|
|
142
203
|
}
|
|
143
204
|
export function createGatewayHttpServer(opts) {
|
|
144
|
-
const { canvasHost, controlUiEnabled, controlUiBasePath, openAiChatCompletionsEnabled, openResponsesEnabled, openResponsesConfig, handleHooksRequest, handlePluginRequest, resolvedAuth, } = opts;
|
|
205
|
+
const { canvasHost, clients, controlUiEnabled, controlUiBasePath, controlUiRoot, openAiChatCompletionsEnabled, openResponsesEnabled, openResponsesConfig, handleHooksRequest, handlePluginRequest, resolvedAuth, } = opts;
|
|
145
206
|
const httpServer = opts.tlsOptions
|
|
146
207
|
? createHttpsServer(opts.tlsOptions, (req, res) => {
|
|
147
208
|
void handleRequest(req, res);
|
|
@@ -183,6 +244,19 @@ export function createGatewayHttpServer(opts) {
|
|
|
183
244
|
return;
|
|
184
245
|
}
|
|
185
246
|
if (canvasHost) {
|
|
247
|
+
const url = new URL(req.url ?? "/", "http://localhost");
|
|
248
|
+
if (isCanvasPath(url.pathname)) {
|
|
249
|
+
const ok = await authorizeCanvasRequest({
|
|
250
|
+
req,
|
|
251
|
+
auth: resolvedAuth,
|
|
252
|
+
trustedProxies,
|
|
253
|
+
clients,
|
|
254
|
+
});
|
|
255
|
+
if (!ok) {
|
|
256
|
+
sendUnauthorized(res);
|
|
257
|
+
return;
|
|
258
|
+
}
|
|
259
|
+
}
|
|
186
260
|
if (await handleA2uiHttpRequest(req, res))
|
|
187
261
|
return;
|
|
188
262
|
if (await canvasHost.handleHttpRequest(req, res))
|
|
@@ -197,6 +271,7 @@ export function createGatewayHttpServer(opts) {
|
|
|
197
271
|
if (handleControlUiHttpRequest(req, res, {
|
|
198
272
|
basePath: controlUiBasePath,
|
|
199
273
|
config: configSnapshot,
|
|
274
|
+
root: controlUiRoot,
|
|
200
275
|
}))
|
|
201
276
|
return;
|
|
202
277
|
}
|
|
@@ -213,12 +288,35 @@ export function createGatewayHttpServer(opts) {
|
|
|
213
288
|
return httpServer;
|
|
214
289
|
}
|
|
215
290
|
export function attachGatewayUpgradeHandler(opts) {
|
|
216
|
-
const { httpServer, wss, canvasHost } = opts;
|
|
291
|
+
const { httpServer, wss, canvasHost, clients, resolvedAuth } = opts;
|
|
217
292
|
httpServer.on("upgrade", (req, socket, head) => {
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
293
|
+
void (async () => {
|
|
294
|
+
if (canvasHost) {
|
|
295
|
+
const url = new URL(req.url ?? "/", "http://localhost");
|
|
296
|
+
if (url.pathname === CANVAS_WS_PATH) {
|
|
297
|
+
const configSnapshot = loadConfig();
|
|
298
|
+
const trustedProxies = configSnapshot.gateway?.trustedProxies ?? [];
|
|
299
|
+
const ok = await authorizeCanvasRequest({
|
|
300
|
+
req,
|
|
301
|
+
auth: resolvedAuth,
|
|
302
|
+
trustedProxies,
|
|
303
|
+
clients,
|
|
304
|
+
});
|
|
305
|
+
if (!ok) {
|
|
306
|
+
socket.write("HTTP/1.1 401 Unauthorized\r\nConnection: close\r\n\r\n");
|
|
307
|
+
socket.destroy();
|
|
308
|
+
return;
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
if (canvasHost.handleUpgrade(req, socket, head)) {
|
|
312
|
+
return;
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
wss.handleUpgrade(req, socket, head, (ws) => {
|
|
316
|
+
wss.emit("connection", ws, req);
|
|
317
|
+
});
|
|
318
|
+
})().catch(() => {
|
|
319
|
+
socket.destroy();
|
|
222
320
|
});
|
|
223
321
|
});
|
|
224
322
|
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { resolveUserTimezone } from "../../agents/date-time.js";
|
|
2
|
+
import { formatZonedTimestamp } from "../../infra/format-time/format-datetime.js";
|
|
3
|
+
/**
|
|
4
|
+
* Cron jobs inject "Current time: ..." into their messages.
|
|
5
|
+
* Skip injection for those.
|
|
6
|
+
*/
|
|
7
|
+
const CRON_TIME_PATTERN = /Current time: /;
|
|
8
|
+
/**
|
|
9
|
+
* Matches a leading `[... YYYY-MM-DD HH:MM ...]` envelope -- either from
|
|
10
|
+
* channel plugins or from a previous injection. Uses the same YYYY-MM-DD
|
|
11
|
+
* HH:MM format as {@link formatZonedTimestamp}, so detection stays in sync
|
|
12
|
+
* with the formatting.
|
|
13
|
+
*/
|
|
14
|
+
const TIMESTAMP_ENVELOPE_PATTERN = /^\[.*\d{4}-\d{2}-\d{2} \d{2}:\d{2}/;
|
|
15
|
+
/**
|
|
16
|
+
* Injects a compact timestamp prefix into a message if one isn't already
|
|
17
|
+
* present. Uses the same `YYYY-MM-DD HH:MM TZ` format as channel envelope
|
|
18
|
+
* timestamps ({@link formatZonedTimestamp}), keeping token cost low (~7
|
|
19
|
+
* tokens) and format consistent across all agent contexts.
|
|
20
|
+
*
|
|
21
|
+
* Used by the gateway `agent` and `chat.send` handlers to give TUI, web,
|
|
22
|
+
* spawned subagents, `sessions_send`, and heartbeat wake events date/time
|
|
23
|
+
* awareness -- without modifying the system prompt (which is cached).
|
|
24
|
+
*
|
|
25
|
+
* Channel messages (Discord, Telegram, etc.) already have timestamps via
|
|
26
|
+
* envelope formatting and take a separate code path -- they never reach
|
|
27
|
+
* these handlers, so there is no double-stamping risk. The detection
|
|
28
|
+
* pattern is a safety net for edge cases.
|
|
29
|
+
*/
|
|
30
|
+
export function injectTimestamp(message, opts) {
|
|
31
|
+
if (!message.trim()) {
|
|
32
|
+
return message;
|
|
33
|
+
}
|
|
34
|
+
// Already has an envelope or injected timestamp
|
|
35
|
+
if (TIMESTAMP_ENVELOPE_PATTERN.test(message)) {
|
|
36
|
+
return message;
|
|
37
|
+
}
|
|
38
|
+
// Already has a cron-injected timestamp
|
|
39
|
+
if (CRON_TIME_PATTERN.test(message)) {
|
|
40
|
+
return message;
|
|
41
|
+
}
|
|
42
|
+
const now = opts?.now ?? new Date();
|
|
43
|
+
const timezone = opts?.timezone ?? "UTC";
|
|
44
|
+
const formatted = formatZonedTimestamp(now, { timeZone: timezone });
|
|
45
|
+
if (!formatted) {
|
|
46
|
+
return message;
|
|
47
|
+
}
|
|
48
|
+
// 3-letter DOW: small models (8B) can't reliably derive day-of-week from
|
|
49
|
+
// a date, and may treat a bare "Wed" as a typo. Costs ~1 token.
|
|
50
|
+
const dow = new Intl.DateTimeFormat("en-US", { timeZone: timezone, weekday: "short" }).format(now);
|
|
51
|
+
return `[${dow} ${formatted}] ${message}`;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Build TimestampInjectionOptions from a PoolBotConfig.
|
|
55
|
+
*/
|
|
56
|
+
export function timestampOptsFromConfig(cfg) {
|
|
57
|
+
return {
|
|
58
|
+
timezone: resolveUserTimezone(cfg.agents?.defaults?.userTimezone),
|
|
59
|
+
};
|
|
60
|
+
}
|