@poolzin/pool-bot 2026.2.21 → 2026.2.22
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +17 -0
- package/dist/agents/api-key-rotation.js +47 -0
- package/dist/agents/apply-patch-update.js +19 -9
- package/dist/agents/apply-patch.js +72 -47
- package/dist/agents/bash-tools.exec.js +141 -559
- package/dist/agents/cli-backends.js +49 -6
- package/dist/agents/cli-runner/helpers.js +69 -152
- package/dist/agents/cli-runner.js +70 -19
- package/dist/agents/identity.js +20 -1
- package/dist/agents/image-sanitization.js +9 -0
- package/dist/agents/live-auth-keys.js +123 -26
- package/dist/agents/live-model-filter.js +13 -4
- package/dist/agents/model-catalog.js +40 -9
- package/dist/agents/model-forward-compat.js +60 -23
- package/dist/agents/model-selection.js +134 -41
- package/dist/agents/pi-auth-json.js +2 -2
- package/dist/agents/pi-embedded-helpers/bootstrap.js +65 -15
- package/dist/agents/pi-embedded-helpers/errors.js +140 -15
- package/dist/agents/pi-embedded-helpers/images.js +22 -12
- package/dist/agents/pi-embedded-helpers.js +2 -2
- package/dist/agents/pi-embedded-runner/abort.js +10 -3
- package/dist/agents/pi-embedded-runner/compact.js +230 -32
- package/dist/agents/pi-embedded-runner/extra-params.js +203 -12
- package/dist/agents/pi-embedded-runner/google.js +109 -19
- package/dist/agents/pi-embedded-runner/history.js +35 -17
- package/dist/agents/pi-embedded-runner/run/attempt.js +386 -95
- package/dist/agents/pi-embedded-runner/run/images.js +81 -55
- package/dist/agents/pi-embedded-runner/run/payloads.js +89 -39
- package/dist/agents/pi-embedded-runner/run.js +193 -25
- package/dist/agents/pi-embedded-runner/run.overflow-compaction.mocks.shared.js +2 -2
- package/dist/agents/pi-embedded-runner/runs.js +17 -8
- package/dist/agents/pi-embedded-runner/tool-result-context-guard.js +262 -0
- package/dist/agents/pi-embedded-runner.js +1 -1
- package/dist/agents/pi-embedded-subscribe.handlers.tools.js +180 -10
- package/dist/agents/pi-embedded-subscribe.js +37 -0
- package/dist/agents/pi-embedded-subscribe.tools.js +127 -30
- package/dist/agents/pi-model-discovery.js +9 -2
- package/dist/agents/pi-tool-definition-adapter.js +60 -8
- package/dist/agents/pi-tools.before-tool-call.js +1 -1
- package/dist/agents/pi-tools.js +113 -94
- package/dist/agents/pi-tools.read.js +337 -38
- package/dist/agents/poolbot-tools.js +14 -5
- package/dist/agents/sandbox/docker.js +10 -5
- package/dist/agents/sandbox/registry.js +96 -46
- package/dist/agents/sandbox/sanitize-env-vars.js +82 -0
- package/dist/agents/sandbox-paths.js +43 -10
- package/dist/agents/session-tool-result-guard-wrapper.js +23 -11
- package/dist/agents/session-tool-result-guard.js +39 -39
- package/dist/agents/session-transcript-repair.js +36 -33
- package/dist/agents/session-write-lock.js +62 -44
- package/dist/agents/skills/frontmatter.js +49 -88
- package/dist/agents/skills/workspace.js +335 -28
- package/dist/agents/subagent-announce.js +508 -174
- package/dist/agents/subagent-registry.js +45 -4
- package/dist/agents/subagent-spawn.js +16 -33
- package/dist/agents/system-prompt-report.js +27 -10
- package/dist/agents/system-prompt.js +26 -32
- package/dist/agents/tool-call-id.js +69 -17
- package/dist/agents/tool-display-common.js +1 -1
- package/dist/agents/tool-images.js +64 -31
- package/dist/agents/tools/canvas-tool.js +17 -11
- package/dist/agents/tools/common.js +37 -19
- package/dist/agents/tools/cron-tool.js +40 -38
- package/dist/agents/tools/gateway.js +70 -2
- package/dist/agents/tools/message-tool.js +181 -40
- package/dist/agents/tools/nodes-tool.js +128 -36
- package/dist/agents/tools/nodes-utils.js +12 -38
- package/dist/agents/tools/session-status-tool.js +24 -71
- package/dist/agents/tools/sessions-helpers.js +38 -210
- package/dist/agents/tools/sessions-spawn-tool.js +28 -198
- package/dist/agents/tools/telegram-actions.js +58 -7
- package/dist/agents/tools/web-fetch-utils.js +112 -7
- package/dist/agents/tools/web-fetch.js +279 -175
- package/dist/agents/tools/web-shared.js +71 -8
- package/dist/agents/usage.js +25 -16
- package/dist/auto-reply/commands-registry.data.js +85 -11
- package/dist/auto-reply/dispatch.js +40 -21
- package/dist/auto-reply/reply/abort.js +102 -33
- package/dist/auto-reply/reply/commands-core.js +82 -33
- package/dist/auto-reply/reply/commands-export-session.js +1 -1
- package/dist/auto-reply/reply/commands-info.js +41 -12
- package/dist/auto-reply/reply/commands-subagents.js +352 -100
- package/dist/auto-reply/reply/commands-system-prompt.js +2 -2
- package/dist/auto-reply/reply/dispatch-from-config.js +100 -29
- package/dist/auto-reply/reply/elevated-unavailable.js +1 -1
- package/dist/auto-reply/reply/inbound-meta.js +12 -1
- package/dist/auto-reply/reply/mentions.js +18 -11
- package/dist/auto-reply/reply/normalize-reply.js +17 -8
- package/dist/auto-reply/reply/reply-dispatcher.js +62 -10
- package/dist/auto-reply/reply/session.js +102 -21
- package/dist/auto-reply/reply/streaming-directives.js +16 -5
- package/dist/auto-reply/status.js +73 -50
- package/dist/browser/extension-relay.js +3 -3
- package/dist/browser/http-auth.js +1 -1
- package/dist/browser/paths.js +2 -2
- package/dist/build-info.json +3 -3
- package/dist/channels/allowlist-match.js +20 -0
- package/dist/channels/allowlists/resolve-utils.js +65 -2
- package/dist/channels/chat-type.js +8 -4
- package/dist/channels/dock.js +127 -35
- package/dist/channels/draft-stream-loop.js +6 -2
- package/dist/channels/plugins/actions/telegram.js +42 -18
- package/dist/channels/plugins/allowlist-match.js +1 -1
- package/dist/channels/plugins/group-mentions.js +51 -41
- package/dist/channels/plugins/message-action-names.js +2 -0
- package/dist/channels/plugins/message-actions.js +24 -5
- package/dist/channels/plugins/normalize/discord.js +26 -4
- package/dist/channels/plugins/normalize/signal.js +35 -22
- package/dist/channels/plugins/onboarding/helpers.js +8 -26
- package/dist/channels/plugins/outbound/imessage.js +15 -14
- package/dist/channels/registry.js +20 -7
- package/dist/cli/acp-cli.js +7 -5
- package/dist/cli/browser-cli-extension.js +25 -12
- package/dist/cli/browser-cli-state.cookies-storage.js +25 -6
- package/dist/cli/browser-cli-state.js +101 -145
- package/dist/cli/command-options.js +28 -0
- package/dist/cli/completion-cli.js +6 -6
- package/dist/cli/cron-cli/register.cron-add.js +25 -1
- package/dist/cli/cron-cli/register.cron-edit.js +44 -0
- package/dist/cli/cron-cli/shared.js +7 -1
- package/dist/cli/daemon-cli/lifecycle-core.js +23 -21
- package/dist/cli/daemon-cli/lifecycle.js +23 -247
- package/dist/cli/daemon-cli/register-service-commands.js +25 -4
- package/dist/cli/daemon-cli.js +1 -0
- package/dist/cli/devices-cli.js +33 -20
- package/dist/cli/gateway-cli/register.js +37 -105
- package/dist/cli/gateway-cli/run.js +49 -11
- package/dist/cli/nodes-camera.js +59 -4
- package/dist/cli/nodes-cli/register.camera.js +27 -24
- package/dist/cli/nodes-cli/rpc.js +21 -38
- package/dist/cli/qr-cli.js +2 -2
- package/dist/cli/skills-cli.format.js +2 -2
- package/dist/cli/update-cli/progress.js +2 -2
- package/dist/cli/update-cli/restart-helper.js +28 -7
- package/dist/cli/update-cli/shared.js +7 -7
- package/dist/cli/update-cli/status.js +1 -1
- package/dist/cli/update-cli/update-command.js +14 -8
- package/dist/cli/update-cli/wizard.js +2 -2
- package/dist/cli/update-cli.js +21 -1027
- package/dist/commands/auth-choice.apply.anthropic.js +10 -2
- package/dist/commands/channels/add-mutators.js +3 -35
- package/dist/commands/channels/add.js +39 -51
- package/dist/commands/config-validation.js +1 -1
- package/dist/commands/configure.gateway-auth.js +52 -15
- package/dist/commands/configure.gateway.js +84 -40
- package/dist/commands/doctor-completion.js +3 -3
- package/dist/commands/doctor-config-flow.js +536 -16
- package/dist/commands/doctor-gateway-services.js +103 -79
- package/dist/commands/doctor-memory-search.js +9 -9
- package/dist/commands/doctor-platform-notes.js +57 -30
- package/dist/commands/doctor-prompter.js +26 -15
- package/dist/commands/doctor-session-locks.js +1 -1
- package/dist/commands/doctor.js +21 -9
- package/dist/commands/model-picker.js +120 -95
- package/dist/commands/models/set.js +2 -21
- package/dist/commands/models/shared.js +65 -37
- package/dist/commands/onboard-helpers.js +81 -39
- package/dist/commands/openai-codex-oauth.js +1 -1
- package/dist/commands/sessions.js +52 -53
- package/dist/commands/status.summary.js +52 -34
- package/dist/commands/test-wizard-helpers.js +2 -2
- package/dist/config/defaults.js +79 -42
- package/dist/config/group-policy.js +50 -18
- package/dist/config/includes.js +37 -10
- package/dist/config/schema.help.js +5 -4
- package/dist/config/schema.hints.js +2 -2
- package/dist/config/schema.labels.js +1 -0
- package/dist/config/sessions/group.js +12 -11
- package/dist/config/sessions/paths.js +137 -11
- package/dist/config/sessions/store.js +185 -65
- package/dist/config/sessions/types.js +15 -1
- package/dist/config/sessions.js +1 -0
- package/dist/config/telegram-custom-commands.js +3 -2
- package/dist/config/types.js +2 -0
- package/dist/config/zod-schema.agent-defaults.js +6 -27
- package/dist/config/zod-schema.agent-runtime.js +171 -79
- package/dist/config/zod-schema.providers-core.js +138 -65
- package/dist/config/zod-schema.session.js +49 -22
- package/dist/control-ui/assets/index-HRr1grwl.js.map +1 -1
- package/dist/cron/isolated-agent/run.js +224 -57
- package/dist/cron/normalize.js +48 -45
- package/dist/cron/run-log.js +14 -0
- package/dist/cron/service/jobs.js +190 -28
- package/dist/cron/service/normalize.js +29 -11
- package/dist/cron/service/store.js +30 -44
- package/dist/cron/service/timer.js +182 -96
- package/dist/cron/service.js +3 -0
- package/dist/cron/stagger.js +37 -0
- package/dist/daemon/inspect.js +132 -92
- package/dist/daemon/runtime-paths.js +25 -4
- package/dist/daemon/service-audit.js +47 -16
- package/dist/discord/accounts.js +23 -20
- package/dist/discord/monitor/agent-components.js +1115 -219
- package/dist/discord/monitor/allow-list.js +114 -34
- package/dist/discord/monitor/listeners.js +204 -97
- package/dist/discord/monitor/message-handler.js +21 -10
- package/dist/discord/monitor/message-handler.preflight.js +195 -101
- package/dist/discord/monitor/message-handler.process.js +384 -123
- package/dist/discord/monitor/message-utils.js +86 -23
- package/dist/discord/monitor/native-command.js +77 -57
- package/dist/discord/monitor/provider.js +122 -117
- package/dist/discord/monitor/reply-context.js +20 -16
- package/dist/discord/monitor/reply-delivery.js +40 -8
- package/dist/discord/monitor/rest-fetch.js +22 -0
- package/dist/discord/monitor/threading.js +117 -24
- package/dist/discord/send.js +2 -1
- package/dist/discord/send.outbound.js +124 -11
- package/dist/discord/send.shared.js +112 -72
- package/dist/discord/voice-message.js +3 -3
- package/dist/gateway/auth.js +119 -44
- package/dist/gateway/call.js +76 -34
- package/dist/gateway/channel-health-monitor.js +57 -50
- package/dist/gateway/client.js +63 -29
- package/dist/gateway/control-ui-contract.js +1 -1
- package/dist/gateway/gateway-config-prompts.shared.js +2 -2
- package/dist/gateway/net.js +109 -1
- package/dist/gateway/protocol/index.js +5 -8
- package/dist/gateway/protocol/schema/agent.js +19 -1
- package/dist/gateway/protocol/schema/channels.js +21 -0
- package/dist/gateway/protocol/schema/cron.js +43 -30
- package/dist/gateway/protocol/schema/protocol-schemas.js +6 -11
- package/dist/gateway/protocol/schema/sessions.js +5 -1
- package/dist/gateway/protocol/schema.js +0 -1
- package/dist/gateway/server/presence-events.js +12 -0
- package/dist/gateway/server/ws-connection/message-handler.js +203 -212
- package/dist/gateway/server/ws-connection.js +58 -21
- package/dist/gateway/server-broadcast.js +18 -13
- package/dist/gateway/server-cron.js +177 -10
- package/dist/gateway/server-methods/agent-job.js +131 -38
- package/dist/gateway/server-methods/send.js +60 -14
- package/dist/gateway/server-methods/sessions.js +160 -96
- package/dist/gateway/server-methods/system.js +5 -7
- package/dist/gateway/server-methods-list.js +8 -0
- package/dist/gateway/server-methods.js +24 -8
- package/dist/gateway/server-node-events.js +278 -68
- package/dist/gateway/session-utils.fs.js +316 -75
- package/dist/gateway/session-utils.js +224 -70
- package/dist/gateway/sessions-patch.js +63 -20
- package/dist/gateway/test-temp-config.js +1 -1
- package/dist/gateway/tools-invoke-http.js +118 -70
- package/dist/gateway/ws-log.js +135 -107
- package/dist/hooks/frontmatter.js +36 -82
- package/dist/hooks/install.js +149 -139
- package/dist/hooks/internal-hooks.js +29 -4
- package/dist/hooks/plugin-hooks.js +2 -1
- package/dist/imessage/monitor/deliver.js +10 -4
- package/dist/imessage/monitor/monitor-provider.js +138 -375
- package/dist/imessage/monitor/runtime.js +4 -8
- package/dist/imessage/send.js +65 -19
- package/dist/infra/exec-approvals-allowlist.js +7 -0
- package/dist/infra/exec-approvals.js +35 -920
- package/dist/infra/exec-safe-bin-trust.js +64 -0
- package/dist/infra/heartbeat-runner.js +207 -134
- package/dist/infra/heartbeat-wake.js +183 -22
- package/dist/infra/install-source-utils.js +47 -0
- package/dist/infra/net/ssrf.js +170 -36
- package/dist/infra/outbound/deliver.js +224 -58
- package/dist/infra/outbound/message-action-spec.js +12 -5
- package/dist/infra/outbound/outbound-session.js +27 -25
- package/dist/infra/poolbot-root.js +32 -22
- package/dist/infra/ports.js +14 -11
- package/dist/infra/skills-remote.js +48 -37
- package/dist/infra/system-events.js +25 -11
- package/dist/infra/system-presence.js +26 -33
- package/dist/infra/tmp-poolbot-dir.js +81 -2
- package/dist/infra/wsl.js +37 -1
- package/dist/line/bot-message-context.js +163 -191
- package/dist/logging/subsystem.js +59 -22
- package/dist/markdown/ir.js +124 -50
- package/dist/media/store.js +1 -1
- package/dist/media-understanding/runner.entries.js +42 -25
- package/dist/media-understanding/runner.js +53 -488
- package/dist/memory/embeddings-gemini.js +53 -38
- package/dist/memory/manager-embedding-ops.js +48 -69
- package/dist/pairing/pairing-store.js +178 -119
- package/dist/plugin-sdk/index.js +34 -6
- package/dist/plugins/hooks.js +135 -14
- package/dist/plugins/install.js +190 -152
- package/dist/polls.js +11 -0
- package/dist/routing/resolve-route.js +190 -56
- package/dist/routing/session-key.js +38 -22
- package/dist/runtime.js +35 -9
- package/dist/security/audit-channel.js +1 -1
- package/dist/sessions/session-key-utils.js +29 -11
- package/dist/shared/frontmatter.js +5 -5
- package/dist/shared/node-list-types.js +1 -0
- package/dist/shared/string-normalization.js +15 -0
- package/dist/signal/monitor/event-handler.js +68 -36
- package/dist/signal/send.js +29 -37
- package/dist/slack/monitor/allow-list.js +10 -11
- package/dist/slack/monitor/commands.js +14 -3
- package/dist/slack/monitor/events/interactions.js +4 -4
- package/dist/slack/monitor/media.js +224 -16
- package/dist/slack/monitor/message-handler/dispatch.js +247 -13
- package/dist/slack/monitor/message-handler/prepare.js +128 -45
- package/dist/slack/monitor/slash.js +357 -144
- package/dist/slack/streaming.js +77 -0
- package/dist/telegram/accounts.js +40 -13
- package/dist/telegram/allowed-updates.js +3 -0
- package/dist/telegram/bot/delivery.js +129 -66
- package/dist/telegram/bot/helpers.js +136 -122
- package/dist/telegram/bot-handlers.js +600 -339
- package/dist/telegram/bot-message-context.js +115 -73
- package/dist/telegram/bot-message-dispatch.js +235 -104
- package/dist/telegram/bot-native-command-menu.js +3 -1
- package/dist/telegram/bot-native-commands.js +213 -193
- package/dist/telegram/bot.js +24 -132
- package/dist/telegram/draft-stream.js +84 -75
- package/dist/telegram/format.js +150 -6
- package/dist/telegram/send.js +415 -255
- package/dist/telegram/targets.js +21 -2
- package/dist/telegram/update-offset-store.js +19 -3
- package/dist/terminal/restore.js +5 -2
- package/dist/test-utils/fetch-mock.js +5 -0
- package/dist/version.js +18 -5
- package/dist/web/auto-reply/monitor/broadcast.js +7 -3
- package/dist/web/auto-reply/monitor/on-message.js +6 -3
- package/dist/web/inbound/media.js +34 -8
- package/dist/web/inbound/monitor.js +34 -17
- package/dist/web/inbound/send-api.js +18 -17
- package/dist/web/outbound.js +12 -5
- package/dist/wizard/clack-prompter.js +40 -7
- package/extensions/bluebubbles/package.json +1 -1
- package/extensions/copilot-proxy/package.json +1 -1
- package/extensions/diagnostics-otel/package.json +1 -1
- package/extensions/discord/package.json +1 -1
- package/extensions/feishu/package.json +1 -1
- package/extensions/google-antigravity-auth/package.json +1 -1
- package/extensions/google-gemini-cli-auth/package.json +1 -1
- package/extensions/googlechat/package.json +1 -1
- package/extensions/imessage/package.json +1 -1
- package/extensions/irc/package.json +1 -1
- package/extensions/line/package.json +1 -1
- package/extensions/llm-task/package.json +1 -1
- package/extensions/lobster/package.json +1 -1
- package/extensions/matrix/CHANGELOG.md +5 -0
- package/extensions/matrix/package.json +1 -1
- package/extensions/mattermost/package.json +1 -1
- package/extensions/memory-core/package.json +1 -1
- package/extensions/memory-lancedb/package.json +1 -1
- package/extensions/minimax-portal-auth/package.json +1 -1
- package/extensions/msteams/CHANGELOG.md +5 -0
- package/extensions/msteams/package.json +1 -1
- package/extensions/nextcloud-talk/package.json +1 -1
- package/extensions/nostr/CHANGELOG.md +5 -0
- package/extensions/nostr/package.json +1 -1
- package/extensions/open-prose/package.json +1 -1
- package/extensions/openai-codex-auth/package.json +1 -1
- package/extensions/signal/package.json +1 -1
- package/extensions/slack/package.json +1 -1
- package/extensions/telegram/package.json +1 -1
- package/extensions/tlon/package.json +1 -1
- package/extensions/twitch/CHANGELOG.md +5 -0
- package/extensions/twitch/package.json +1 -1
- package/extensions/voice-call/CHANGELOG.md +5 -0
- package/extensions/voice-call/package.json +1 -1
- package/extensions/whatsapp/package.json +1 -1
- package/extensions/zalo/CHANGELOG.md +5 -0
- package/extensions/zalo/package.json +1 -1
- package/extensions/zalouser/CHANGELOG.md +5 -0
- package/extensions/zalouser/package.json +1 -1
- package/package.json +1 -1
- package/skills/apple-reminders/SKILL.md +100 -49
- package/skills/coding-agent/SKILL.md +34 -28
- package/skills/github/SKILL.md +131 -16
- package/skills/imsg/SKILL.md +112 -15
- package/skills/openhue/SKILL.md +101 -19
- package/skills/tmux/SKILL.md +111 -79
- package/skills/weather/SKILL.md +88 -25
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
import { resolveDefaultAgentId } from "../agents/agent-scope.js";
|
|
2
|
+
import { normalizeChatType } from "../channels/chat-type.js";
|
|
3
|
+
import { shouldLogVerbose } from "../globals.js";
|
|
4
|
+
import { logDebug } from "../logger.js";
|
|
2
5
|
import { listBindings } from "./bindings.js";
|
|
3
6
|
import { buildAgentMainSessionKey, buildAgentPeerSessionKey, DEFAULT_ACCOUNT_ID, DEFAULT_MAIN_KEY, normalizeAgentId, sanitizeAgentId, } from "./session-key.js";
|
|
4
7
|
export { DEFAULT_ACCOUNT_ID, DEFAULT_AGENT_ID } from "./session-key.js";
|
|
@@ -6,7 +9,13 @@ function normalizeToken(value) {
|
|
|
6
9
|
return (value ?? "").trim().toLowerCase();
|
|
7
10
|
}
|
|
8
11
|
function normalizeId(value) {
|
|
9
|
-
|
|
12
|
+
if (typeof value === "string") {
|
|
13
|
+
return value.trim();
|
|
14
|
+
}
|
|
15
|
+
if (typeof value === "number" || typeof value === "bigint") {
|
|
16
|
+
return String(value).trim();
|
|
17
|
+
}
|
|
18
|
+
return "";
|
|
10
19
|
}
|
|
11
20
|
function normalizeAccountId(value) {
|
|
12
21
|
const trimmed = (value ?? "").trim();
|
|
@@ -14,10 +23,12 @@ function normalizeAccountId(value) {
|
|
|
14
23
|
}
|
|
15
24
|
function matchesAccountId(match, actual) {
|
|
16
25
|
const trimmed = (match ?? "").trim();
|
|
17
|
-
if (!trimmed)
|
|
26
|
+
if (!trimmed) {
|
|
18
27
|
return actual === DEFAULT_ACCOUNT_ID;
|
|
19
|
-
|
|
28
|
+
}
|
|
29
|
+
if (trimmed === "*") {
|
|
20
30
|
return true;
|
|
31
|
+
}
|
|
21
32
|
return trimmed === actual;
|
|
22
33
|
}
|
|
23
34
|
export function buildAgentSessionKey(params) {
|
|
@@ -28,7 +39,7 @@ export function buildAgentSessionKey(params) {
|
|
|
28
39
|
mainKey: DEFAULT_MAIN_KEY,
|
|
29
40
|
channel,
|
|
30
41
|
accountId: params.accountId,
|
|
31
|
-
peerKind: peer?.kind ?? "
|
|
42
|
+
peerKind: peer?.kind ?? "direct",
|
|
32
43
|
peerId: peer ? normalizeId(peer.id) || "unknown" : null,
|
|
33
44
|
dmScope: params.dmScope,
|
|
34
45
|
identityLinks: params.identityLinks,
|
|
@@ -40,44 +51,116 @@ function listAgents(cfg) {
|
|
|
40
51
|
}
|
|
41
52
|
function pickFirstExistingAgentId(cfg, agentId) {
|
|
42
53
|
const trimmed = (agentId ?? "").trim();
|
|
43
|
-
if (!trimmed)
|
|
54
|
+
if (!trimmed) {
|
|
44
55
|
return sanitizeAgentId(resolveDefaultAgentId(cfg));
|
|
56
|
+
}
|
|
45
57
|
const normalized = normalizeAgentId(trimmed);
|
|
46
58
|
const agents = listAgents(cfg);
|
|
47
|
-
if (agents.length === 0)
|
|
59
|
+
if (agents.length === 0) {
|
|
48
60
|
return sanitizeAgentId(trimmed);
|
|
61
|
+
}
|
|
49
62
|
const match = agents.find((agent) => normalizeAgentId(agent.id) === normalized);
|
|
50
|
-
if (match?.id?.trim())
|
|
63
|
+
if (match?.id?.trim()) {
|
|
51
64
|
return sanitizeAgentId(match.id.trim());
|
|
65
|
+
}
|
|
52
66
|
return sanitizeAgentId(resolveDefaultAgentId(cfg));
|
|
53
67
|
}
|
|
54
68
|
function matchesChannel(match, channel) {
|
|
55
69
|
const key = normalizeToken(match?.channel);
|
|
56
|
-
if (!key)
|
|
70
|
+
if (!key) {
|
|
57
71
|
return false;
|
|
72
|
+
}
|
|
58
73
|
return key === channel;
|
|
59
74
|
}
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
75
|
+
const evaluatedBindingsCacheByCfg = new WeakMap();
|
|
76
|
+
const MAX_EVALUATED_BINDINGS_CACHE_KEYS = 2000;
|
|
77
|
+
function getEvaluatedBindingsForChannelAccount(cfg, channel, accountId) {
|
|
78
|
+
const bindingsRef = cfg.bindings;
|
|
79
|
+
const existing = evaluatedBindingsCacheByCfg.get(cfg);
|
|
80
|
+
const cache = existing && existing.bindingsRef === bindingsRef
|
|
81
|
+
? existing
|
|
82
|
+
: { bindingsRef, byChannelAccount: new Map() };
|
|
83
|
+
if (cache !== existing) {
|
|
84
|
+
evaluatedBindingsCacheByCfg.set(cfg, cache);
|
|
85
|
+
}
|
|
86
|
+
const cacheKey = `${channel}\t${accountId}`;
|
|
87
|
+
const hit = cache.byChannelAccount.get(cacheKey);
|
|
88
|
+
if (hit) {
|
|
89
|
+
return hit;
|
|
90
|
+
}
|
|
91
|
+
const evaluated = listBindings(cfg).flatMap((binding) => {
|
|
92
|
+
if (!binding || typeof binding !== "object") {
|
|
93
|
+
return [];
|
|
94
|
+
}
|
|
95
|
+
if (!matchesChannel(binding.match, channel)) {
|
|
96
|
+
return [];
|
|
97
|
+
}
|
|
98
|
+
if (!matchesAccountId(binding.match?.accountId, accountId)) {
|
|
99
|
+
return [];
|
|
100
|
+
}
|
|
101
|
+
return [{ binding, match: normalizeBindingMatch(binding.match) }];
|
|
102
|
+
});
|
|
103
|
+
cache.byChannelAccount.set(cacheKey, evaluated);
|
|
104
|
+
if (cache.byChannelAccount.size > MAX_EVALUATED_BINDINGS_CACHE_KEYS) {
|
|
105
|
+
cache.byChannelAccount.clear();
|
|
106
|
+
cache.byChannelAccount.set(cacheKey, evaluated);
|
|
107
|
+
}
|
|
108
|
+
return evaluated;
|
|
109
|
+
}
|
|
110
|
+
function normalizePeerConstraint(peer) {
|
|
111
|
+
if (!peer) {
|
|
112
|
+
return { state: "none" };
|
|
113
|
+
}
|
|
114
|
+
const kind = normalizeChatType(peer.kind);
|
|
115
|
+
const id = normalizeId(peer.id);
|
|
116
|
+
if (!kind || !id) {
|
|
117
|
+
return { state: "invalid" };
|
|
118
|
+
}
|
|
119
|
+
return { state: "valid", kind, id };
|
|
120
|
+
}
|
|
121
|
+
function normalizeBindingMatch(match) {
|
|
122
|
+
const rawRoles = match?.roles;
|
|
123
|
+
return {
|
|
124
|
+
accountPattern: (match?.accountId ?? "").trim(),
|
|
125
|
+
peer: normalizePeerConstraint(match?.peer),
|
|
126
|
+
guildId: normalizeId(match?.guildId) || null,
|
|
127
|
+
teamId: normalizeId(match?.teamId) || null,
|
|
128
|
+
roles: Array.isArray(rawRoles) && rawRoles.length > 0 ? rawRoles : null,
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
function hasGuildConstraint(match) {
|
|
132
|
+
return Boolean(match.guildId);
|
|
133
|
+
}
|
|
134
|
+
function hasTeamConstraint(match) {
|
|
135
|
+
return Boolean(match.teamId);
|
|
136
|
+
}
|
|
137
|
+
function hasRolesConstraint(match) {
|
|
138
|
+
return Boolean(match.roles);
|
|
139
|
+
}
|
|
140
|
+
function matchesBindingScope(match, scope) {
|
|
141
|
+
if (match.peer.state === "invalid") {
|
|
63
142
|
return false;
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
143
|
+
}
|
|
144
|
+
if (match.peer.state === "valid") {
|
|
145
|
+
if (!scope.peer || scope.peer.kind !== match.peer.kind || scope.peer.id !== match.peer.id) {
|
|
146
|
+
return false;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
if (match.guildId && match.guildId !== scope.guildId) {
|
|
67
150
|
return false;
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
function matchesGuild(match, guildId) {
|
|
71
|
-
const id = normalizeId(match?.guildId);
|
|
72
|
-
if (!id)
|
|
151
|
+
}
|
|
152
|
+
if (match.teamId && match.teamId !== scope.teamId) {
|
|
73
153
|
return false;
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
154
|
+
}
|
|
155
|
+
if (match.roles) {
|
|
156
|
+
for (const role of match.roles) {
|
|
157
|
+
if (scope.memberRoleIds.has(role)) {
|
|
158
|
+
return true;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
79
161
|
return false;
|
|
80
|
-
|
|
162
|
+
}
|
|
163
|
+
return true;
|
|
81
164
|
}
|
|
82
165
|
export function resolveAgentRoute(input) {
|
|
83
166
|
const channel = normalizeToken(input.channel);
|
|
@@ -85,13 +168,9 @@ export function resolveAgentRoute(input) {
|
|
|
85
168
|
const peer = input.peer ? { kind: input.peer.kind, id: normalizeId(input.peer.id) } : null;
|
|
86
169
|
const guildId = normalizeId(input.guildId);
|
|
87
170
|
const teamId = normalizeId(input.teamId);
|
|
88
|
-
const
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
if (!matchesChannel(binding.match, channel))
|
|
92
|
-
return false;
|
|
93
|
-
return matchesAccountId(binding.match?.accountId, accountId);
|
|
94
|
-
});
|
|
171
|
+
const memberRoleIds = input.memberRoleIds ?? [];
|
|
172
|
+
const memberRoleIdSet = new Set(memberRoleIds);
|
|
173
|
+
const bindings = getEvaluatedBindingsForChannelAccount(input.cfg, channel, accountId);
|
|
95
174
|
const dmScope = input.cfg.session?.dmScope ?? "main";
|
|
96
175
|
const identityLinks = input.cfg.session?.identityLinks;
|
|
97
176
|
const choose = (agentId, matchedBy) => {
|
|
@@ -117,36 +196,91 @@ export function resolveAgentRoute(input) {
|
|
|
117
196
|
matchedBy,
|
|
118
197
|
};
|
|
119
198
|
};
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
199
|
+
const shouldLogDebug = shouldLogVerbose();
|
|
200
|
+
const formatPeer = (value) => value?.kind && value?.id ? `${value.kind}:${value.id}` : "none";
|
|
201
|
+
const formatNormalizedPeer = (value) => {
|
|
202
|
+
if (value.state === "none") {
|
|
203
|
+
return "none";
|
|
204
|
+
}
|
|
205
|
+
if (value.state === "invalid") {
|
|
206
|
+
return "invalid";
|
|
207
|
+
}
|
|
208
|
+
return `${value.kind}:${value.id}`;
|
|
209
|
+
};
|
|
210
|
+
if (shouldLogDebug) {
|
|
211
|
+
logDebug(`[routing] resolveAgentRoute: channel=${channel} accountId=${accountId} peer=${formatPeer(peer)} guildId=${guildId || "none"} teamId=${teamId || "none"} bindings=${bindings.length}`);
|
|
212
|
+
for (const entry of bindings) {
|
|
213
|
+
logDebug(`[routing] binding: agentId=${entry.binding.agentId} accountPattern=${entry.match.accountPattern || "default"} peer=${formatNormalizedPeer(entry.match.peer)} guildId=${entry.match.guildId ?? "none"} teamId=${entry.match.teamId ?? "none"} roles=${entry.match.roles?.length ?? 0}`);
|
|
214
|
+
}
|
|
124
215
|
}
|
|
125
216
|
// Thread parent inheritance: if peer (thread) didn't match, check parent peer binding
|
|
126
217
|
const parentPeer = input.parentPeer
|
|
127
218
|
? { kind: input.parentPeer.kind, id: normalizeId(input.parentPeer.id) }
|
|
128
219
|
: null;
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
220
|
+
const baseScope = {
|
|
221
|
+
guildId,
|
|
222
|
+
teamId,
|
|
223
|
+
memberRoleIds: memberRoleIdSet,
|
|
224
|
+
};
|
|
225
|
+
const tiers = [
|
|
226
|
+
{
|
|
227
|
+
matchedBy: "binding.peer",
|
|
228
|
+
enabled: Boolean(peer),
|
|
229
|
+
scopePeer: peer,
|
|
230
|
+
predicate: (candidate) => candidate.match.peer.state === "valid",
|
|
231
|
+
},
|
|
232
|
+
{
|
|
233
|
+
matchedBy: "binding.peer.parent",
|
|
234
|
+
enabled: Boolean(parentPeer && parentPeer.id),
|
|
235
|
+
scopePeer: parentPeer && parentPeer.id ? parentPeer : null,
|
|
236
|
+
predicate: (candidate) => candidate.match.peer.state === "valid",
|
|
237
|
+
},
|
|
238
|
+
{
|
|
239
|
+
matchedBy: "binding.guild+roles",
|
|
240
|
+
enabled: Boolean(guildId && memberRoleIds.length > 0),
|
|
241
|
+
scopePeer: peer,
|
|
242
|
+
predicate: (candidate) => hasGuildConstraint(candidate.match) && hasRolesConstraint(candidate.match),
|
|
243
|
+
},
|
|
244
|
+
{
|
|
245
|
+
matchedBy: "binding.guild",
|
|
246
|
+
enabled: Boolean(guildId),
|
|
247
|
+
scopePeer: peer,
|
|
248
|
+
predicate: (candidate) => hasGuildConstraint(candidate.match) && !hasRolesConstraint(candidate.match),
|
|
249
|
+
},
|
|
250
|
+
{
|
|
251
|
+
matchedBy: "binding.team",
|
|
252
|
+
enabled: Boolean(teamId),
|
|
253
|
+
scopePeer: peer,
|
|
254
|
+
predicate: (candidate) => hasTeamConstraint(candidate.match),
|
|
255
|
+
},
|
|
256
|
+
{
|
|
257
|
+
matchedBy: "binding.account",
|
|
258
|
+
enabled: true,
|
|
259
|
+
scopePeer: peer,
|
|
260
|
+
predicate: (candidate) => candidate.match.accountPattern !== "*",
|
|
261
|
+
},
|
|
262
|
+
{
|
|
263
|
+
matchedBy: "binding.channel",
|
|
264
|
+
enabled: true,
|
|
265
|
+
scopePeer: peer,
|
|
266
|
+
predicate: (candidate) => candidate.match.accountPattern === "*",
|
|
267
|
+
},
|
|
268
|
+
];
|
|
269
|
+
for (const tier of tiers) {
|
|
270
|
+
if (!tier.enabled) {
|
|
271
|
+
continue;
|
|
272
|
+
}
|
|
273
|
+
const matched = bindings.find((candidate) => tier.predicate(candidate) &&
|
|
274
|
+
matchesBindingScope(candidate.match, {
|
|
275
|
+
...baseScope,
|
|
276
|
+
peer: tier.scopePeer,
|
|
277
|
+
}));
|
|
278
|
+
if (matched) {
|
|
279
|
+
if (shouldLogDebug) {
|
|
280
|
+
logDebug(`[routing] match: matchedBy=${tier.matchedBy} agentId=${matched.binding.agentId}`);
|
|
281
|
+
}
|
|
282
|
+
return choose(matched.binding.agentId, tier.matchedBy);
|
|
133
283
|
}
|
|
134
284
|
}
|
|
135
|
-
if (guildId) {
|
|
136
|
-
const guildMatch = bindings.find((b) => matchesGuild(b.match, guildId));
|
|
137
|
-
if (guildMatch)
|
|
138
|
-
return choose(guildMatch.agentId, "binding.guild");
|
|
139
|
-
}
|
|
140
|
-
if (teamId) {
|
|
141
|
-
const teamMatch = bindings.find((b) => matchesTeam(b.match, teamId));
|
|
142
|
-
if (teamMatch)
|
|
143
|
-
return choose(teamMatch.agentId, "binding.team");
|
|
144
|
-
}
|
|
145
|
-
const accountMatch = bindings.find((b) => b.match?.accountId?.trim() !== "*" && !b.match?.peer && !b.match?.guildId && !b.match?.teamId);
|
|
146
|
-
if (accountMatch)
|
|
147
|
-
return choose(accountMatch.agentId, "binding.account");
|
|
148
|
-
const anyAccountMatch = bindings.find((b) => b.match?.accountId?.trim() === "*" && !b.match?.peer && !b.match?.guildId && !b.match?.teamId);
|
|
149
|
-
if (anyAccountMatch)
|
|
150
|
-
return choose(anyAccountMatch.agentId, "binding.channel");
|
|
151
285
|
return choose(resolveDefaultAgentId(input.cfg), "default");
|
|
152
286
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { parseAgentSessionKey } from "../sessions/session-key-utils.js";
|
|
2
|
-
export { isAcpSessionKey, isSubagentSessionKey, parseAgentSessionKey, } from "../sessions/session-key-utils.js";
|
|
2
|
+
export { getSubagentDepth, isCronSessionKey, isAcpSessionKey, isSubagentSessionKey, parseAgentSessionKey, } from "../sessions/session-key-utils.js";
|
|
3
3
|
export const DEFAULT_AGENT_ID = "main";
|
|
4
4
|
export const DEFAULT_MAIN_KEY = "main";
|
|
5
5
|
export const DEFAULT_ACCOUNT_ID = "default";
|
|
@@ -17,8 +17,9 @@ export function normalizeMainKey(value) {
|
|
|
17
17
|
}
|
|
18
18
|
export function toAgentRequestSessionKey(storeKey) {
|
|
19
19
|
const raw = (storeKey ?? "").trim();
|
|
20
|
-
if (!raw)
|
|
20
|
+
if (!raw) {
|
|
21
21
|
return undefined;
|
|
22
|
+
}
|
|
22
23
|
return parseAgentSessionKey(raw)?.rest ?? raw;
|
|
23
24
|
}
|
|
24
25
|
export function toAgentStoreSessionKey(params) {
|
|
@@ -27,8 +28,9 @@ export function toAgentStoreSessionKey(params) {
|
|
|
27
28
|
return buildAgentMainSessionKey({ agentId: params.agentId, mainKey: params.mainKey });
|
|
28
29
|
}
|
|
29
30
|
const lowered = raw.toLowerCase();
|
|
30
|
-
if (lowered.startsWith("agent:"))
|
|
31
|
+
if (lowered.startsWith("agent:")) {
|
|
31
32
|
return lowered;
|
|
33
|
+
}
|
|
32
34
|
if (lowered.startsWith("subagent:")) {
|
|
33
35
|
return `agent:${normalizeAgentId(params.agentId)}:${lowered}`;
|
|
34
36
|
}
|
|
@@ -50,11 +52,13 @@ export function classifySessionKeyShape(sessionKey) {
|
|
|
50
52
|
}
|
|
51
53
|
export function normalizeAgentId(value) {
|
|
52
54
|
const trimmed = (value ?? "").trim();
|
|
53
|
-
if (!trimmed)
|
|
55
|
+
if (!trimmed) {
|
|
54
56
|
return DEFAULT_AGENT_ID;
|
|
57
|
+
}
|
|
55
58
|
// Keep it path-safe + shell-friendly.
|
|
56
|
-
if (VALID_ID_RE.test(trimmed))
|
|
59
|
+
if (VALID_ID_RE.test(trimmed)) {
|
|
57
60
|
return trimmed.toLowerCase();
|
|
61
|
+
}
|
|
58
62
|
// Best-effort fallback: collapse invalid characters to "-"
|
|
59
63
|
return (trimmed
|
|
60
64
|
.toLowerCase()
|
|
@@ -65,10 +69,12 @@ export function normalizeAgentId(value) {
|
|
|
65
69
|
}
|
|
66
70
|
export function sanitizeAgentId(value) {
|
|
67
71
|
const trimmed = (value ?? "").trim();
|
|
68
|
-
if (!trimmed)
|
|
72
|
+
if (!trimmed) {
|
|
69
73
|
return DEFAULT_AGENT_ID;
|
|
70
|
-
|
|
74
|
+
}
|
|
75
|
+
if (VALID_ID_RE.test(trimmed)) {
|
|
71
76
|
return trimmed.toLowerCase();
|
|
77
|
+
}
|
|
72
78
|
return (trimmed
|
|
73
79
|
.toLowerCase()
|
|
74
80
|
.replace(INVALID_CHARS_RE, "-")
|
|
@@ -78,10 +84,12 @@ export function sanitizeAgentId(value) {
|
|
|
78
84
|
}
|
|
79
85
|
export function normalizeAccountId(value) {
|
|
80
86
|
const trimmed = (value ?? "").trim();
|
|
81
|
-
if (!trimmed)
|
|
87
|
+
if (!trimmed) {
|
|
82
88
|
return DEFAULT_ACCOUNT_ID;
|
|
83
|
-
|
|
89
|
+
}
|
|
90
|
+
if (VALID_ID_RE.test(trimmed)) {
|
|
84
91
|
return trimmed.toLowerCase();
|
|
92
|
+
}
|
|
85
93
|
return (trimmed
|
|
86
94
|
.toLowerCase()
|
|
87
95
|
.replace(INVALID_CHARS_RE, "-")
|
|
@@ -95,8 +103,8 @@ export function buildAgentMainSessionKey(params) {
|
|
|
95
103
|
return `agent:${agentId}:${mainKey}`;
|
|
96
104
|
}
|
|
97
105
|
export function buildAgentPeerSessionKey(params) {
|
|
98
|
-
const peerKind = params.peerKind ?? "
|
|
99
|
-
if (peerKind === "
|
|
106
|
+
const peerKind = params.peerKind ?? "direct";
|
|
107
|
+
if (peerKind === "direct") {
|
|
100
108
|
const dmScope = params.dmScope ?? "main";
|
|
101
109
|
let peerId = (params.peerId ?? "").trim();
|
|
102
110
|
const linkedPeerId = dmScope === "main"
|
|
@@ -106,20 +114,21 @@ export function buildAgentPeerSessionKey(params) {
|
|
|
106
114
|
channel: params.channel,
|
|
107
115
|
peerId,
|
|
108
116
|
});
|
|
109
|
-
if (linkedPeerId)
|
|
117
|
+
if (linkedPeerId) {
|
|
110
118
|
peerId = linkedPeerId;
|
|
119
|
+
}
|
|
111
120
|
peerId = peerId.toLowerCase();
|
|
112
121
|
if (dmScope === "per-account-channel-peer" && peerId) {
|
|
113
122
|
const channel = (params.channel ?? "").trim().toLowerCase() || "unknown";
|
|
114
123
|
const accountId = normalizeAccountId(params.accountId);
|
|
115
|
-
return `agent:${normalizeAgentId(params.agentId)}:${channel}:${accountId}:
|
|
124
|
+
return `agent:${normalizeAgentId(params.agentId)}:${channel}:${accountId}:direct:${peerId}`;
|
|
116
125
|
}
|
|
117
126
|
if (dmScope === "per-channel-peer" && peerId) {
|
|
118
127
|
const channel = (params.channel ?? "").trim().toLowerCase() || "unknown";
|
|
119
|
-
return `agent:${normalizeAgentId(params.agentId)}:${channel}:
|
|
128
|
+
return `agent:${normalizeAgentId(params.agentId)}:${channel}:direct:${peerId}`;
|
|
120
129
|
}
|
|
121
130
|
if (dmScope === "per-peer" && peerId) {
|
|
122
|
-
return `agent:${normalizeAgentId(params.agentId)}:
|
|
131
|
+
return `agent:${normalizeAgentId(params.agentId)}:direct:${peerId}`;
|
|
123
132
|
}
|
|
124
133
|
return buildAgentMainSessionKey({
|
|
125
134
|
agentId: params.agentId,
|
|
@@ -132,29 +141,36 @@ export function buildAgentPeerSessionKey(params) {
|
|
|
132
141
|
}
|
|
133
142
|
function resolveLinkedPeerId(params) {
|
|
134
143
|
const identityLinks = params.identityLinks;
|
|
135
|
-
if (!identityLinks)
|
|
144
|
+
if (!identityLinks) {
|
|
136
145
|
return null;
|
|
146
|
+
}
|
|
137
147
|
const peerId = params.peerId.trim();
|
|
138
|
-
if (!peerId)
|
|
148
|
+
if (!peerId) {
|
|
139
149
|
return null;
|
|
150
|
+
}
|
|
140
151
|
const candidates = new Set();
|
|
141
152
|
const rawCandidate = normalizeToken(peerId);
|
|
142
|
-
if (rawCandidate)
|
|
153
|
+
if (rawCandidate) {
|
|
143
154
|
candidates.add(rawCandidate);
|
|
155
|
+
}
|
|
144
156
|
const channel = normalizeToken(params.channel);
|
|
145
157
|
if (channel) {
|
|
146
158
|
const scopedCandidate = normalizeToken(`${channel}:${peerId}`);
|
|
147
|
-
if (scopedCandidate)
|
|
159
|
+
if (scopedCandidate) {
|
|
148
160
|
candidates.add(scopedCandidate);
|
|
161
|
+
}
|
|
149
162
|
}
|
|
150
|
-
if (candidates.size === 0)
|
|
163
|
+
if (candidates.size === 0) {
|
|
151
164
|
return null;
|
|
165
|
+
}
|
|
152
166
|
for (const [canonical, ids] of Object.entries(identityLinks)) {
|
|
153
167
|
const canonicalName = canonical.trim();
|
|
154
|
-
if (!canonicalName)
|
|
168
|
+
if (!canonicalName) {
|
|
155
169
|
continue;
|
|
156
|
-
|
|
170
|
+
}
|
|
171
|
+
if (!Array.isArray(ids)) {
|
|
157
172
|
continue;
|
|
173
|
+
}
|
|
158
174
|
for (const id of ids) {
|
|
159
175
|
const normalized = normalizeToken(id);
|
|
160
176
|
if (normalized && candidates.has(normalized)) {
|
package/dist/runtime.js
CHANGED
|
@@ -1,17 +1,43 @@
|
|
|
1
1
|
import { clearActiveProgressLine } from "./terminal/progress-line.js";
|
|
2
2
|
import { restoreTerminalState } from "./terminal/restore.js";
|
|
3
|
+
function shouldEmitRuntimeLog(env = process.env) {
|
|
4
|
+
if (env.VITEST !== "true") {
|
|
5
|
+
return true;
|
|
6
|
+
}
|
|
7
|
+
if (env.POOLBOT_TEST_RUNTIME_LOG === "1") {
|
|
8
|
+
return true;
|
|
9
|
+
}
|
|
10
|
+
const maybeMockedLog = console.log;
|
|
11
|
+
return typeof maybeMockedLog.mock === "object";
|
|
12
|
+
}
|
|
13
|
+
function createRuntimeIo() {
|
|
14
|
+
return {
|
|
15
|
+
log: (...args) => {
|
|
16
|
+
if (!shouldEmitRuntimeLog()) {
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
clearActiveProgressLine();
|
|
20
|
+
console.log(...args);
|
|
21
|
+
},
|
|
22
|
+
error: (...args) => {
|
|
23
|
+
clearActiveProgressLine();
|
|
24
|
+
console.error(...args);
|
|
25
|
+
},
|
|
26
|
+
};
|
|
27
|
+
}
|
|
3
28
|
export const defaultRuntime = {
|
|
4
|
-
|
|
5
|
-
clearActiveProgressLine();
|
|
6
|
-
console.log(...args);
|
|
7
|
-
},
|
|
8
|
-
error: (...args) => {
|
|
9
|
-
clearActiveProgressLine();
|
|
10
|
-
console.error(...args);
|
|
11
|
-
},
|
|
29
|
+
...createRuntimeIo(),
|
|
12
30
|
exit: (code) => {
|
|
13
|
-
restoreTerminalState("runtime exit");
|
|
31
|
+
restoreTerminalState("runtime exit", { resumeStdinIfPaused: false });
|
|
14
32
|
process.exit(code);
|
|
15
33
|
throw new Error("unreachable"); // satisfies tests when mocked
|
|
16
34
|
},
|
|
17
35
|
};
|
|
36
|
+
export function createNonExitingRuntime() {
|
|
37
|
+
return {
|
|
38
|
+
...createRuntimeIo(),
|
|
39
|
+
exit: (code) => {
|
|
40
|
+
throw new Error(`exit ${code}`);
|
|
41
|
+
},
|
|
42
|
+
};
|
|
43
|
+
}
|
|
@@ -90,7 +90,7 @@ export async function collectChannelSecurityFindings(params) {
|
|
|
90
90
|
title: `${input.label} DMs share the main session`,
|
|
91
91
|
detail: "Multiple DM senders currently share the main session, which can leak context across users.",
|
|
92
92
|
remediation: "Run: " +
|
|
93
|
-
formatCliCommand('
|
|
93
|
+
formatCliCommand('poolbot config set session.dmScope "per-channel-peer"') +
|
|
94
94
|
' (or "per-account-channel-peer" for multi-account channels) to isolate DM sessions per sender.',
|
|
95
95
|
});
|
|
96
96
|
}
|
|
@@ -1,16 +1,20 @@
|
|
|
1
1
|
export function parseAgentSessionKey(sessionKey) {
|
|
2
2
|
const raw = (sessionKey ?? "").trim();
|
|
3
|
-
if (!raw)
|
|
3
|
+
if (!raw) {
|
|
4
4
|
return null;
|
|
5
|
+
}
|
|
5
6
|
const parts = raw.split(":").filter(Boolean);
|
|
6
|
-
if (parts.length < 3)
|
|
7
|
+
if (parts.length < 3) {
|
|
7
8
|
return null;
|
|
8
|
-
|
|
9
|
+
}
|
|
10
|
+
if (parts[0] !== "agent") {
|
|
9
11
|
return null;
|
|
12
|
+
}
|
|
10
13
|
const agentId = parts[1]?.trim();
|
|
11
14
|
const rest = parts.slice(2).join(":");
|
|
12
|
-
if (!agentId || !rest)
|
|
15
|
+
if (!agentId || !rest) {
|
|
13
16
|
return null;
|
|
17
|
+
}
|
|
14
18
|
return { agentId, rest };
|
|
15
19
|
}
|
|
16
20
|
export function isCronRunSessionKey(sessionKey) {
|
|
@@ -20,12 +24,21 @@ export function isCronRunSessionKey(sessionKey) {
|
|
|
20
24
|
}
|
|
21
25
|
return /^cron:[^:]+:run:[^:]+$/.test(parsed.rest);
|
|
22
26
|
}
|
|
27
|
+
export function isCronSessionKey(sessionKey) {
|
|
28
|
+
const parsed = parseAgentSessionKey(sessionKey);
|
|
29
|
+
if (!parsed) {
|
|
30
|
+
return false;
|
|
31
|
+
}
|
|
32
|
+
return parsed.rest.toLowerCase().startsWith("cron:");
|
|
33
|
+
}
|
|
23
34
|
export function isSubagentSessionKey(sessionKey) {
|
|
24
35
|
const raw = (sessionKey ?? "").trim();
|
|
25
|
-
if (!raw)
|
|
36
|
+
if (!raw) {
|
|
26
37
|
return false;
|
|
27
|
-
|
|
38
|
+
}
|
|
39
|
+
if (raw.toLowerCase().startsWith("subagent:")) {
|
|
28
40
|
return true;
|
|
41
|
+
}
|
|
29
42
|
const parsed = parseAgentSessionKey(raw);
|
|
30
43
|
return Boolean((parsed?.rest ?? "").toLowerCase().startsWith("subagent:"));
|
|
31
44
|
}
|
|
@@ -38,28 +51,33 @@ export function getSubagentDepth(sessionKey) {
|
|
|
38
51
|
}
|
|
39
52
|
export function isAcpSessionKey(sessionKey) {
|
|
40
53
|
const raw = (sessionKey ?? "").trim();
|
|
41
|
-
if (!raw)
|
|
54
|
+
if (!raw) {
|
|
42
55
|
return false;
|
|
56
|
+
}
|
|
43
57
|
const normalized = raw.toLowerCase();
|
|
44
|
-
if (normalized.startsWith("acp:"))
|
|
58
|
+
if (normalized.startsWith("acp:")) {
|
|
45
59
|
return true;
|
|
60
|
+
}
|
|
46
61
|
const parsed = parseAgentSessionKey(raw);
|
|
47
62
|
return Boolean((parsed?.rest ?? "").toLowerCase().startsWith("acp:"));
|
|
48
63
|
}
|
|
49
64
|
const THREAD_SESSION_MARKERS = [":thread:", ":topic:"];
|
|
50
65
|
export function resolveThreadParentSessionKey(sessionKey) {
|
|
51
66
|
const raw = (sessionKey ?? "").trim();
|
|
52
|
-
if (!raw)
|
|
67
|
+
if (!raw) {
|
|
53
68
|
return null;
|
|
69
|
+
}
|
|
54
70
|
const normalized = raw.toLowerCase();
|
|
55
71
|
let idx = -1;
|
|
56
72
|
for (const marker of THREAD_SESSION_MARKERS) {
|
|
57
73
|
const candidate = normalized.lastIndexOf(marker);
|
|
58
|
-
if (candidate > idx)
|
|
74
|
+
if (candidate > idx) {
|
|
59
75
|
idx = candidate;
|
|
76
|
+
}
|
|
60
77
|
}
|
|
61
|
-
if (idx <= 0)
|
|
78
|
+
if (idx <= 0) {
|
|
62
79
|
return null;
|
|
80
|
+
}
|
|
63
81
|
const parent = raw.slice(0, idx).trim();
|
|
64
82
|
return parent ? parent : null;
|
|
65
83
|
}
|
|
@@ -24,7 +24,7 @@ export function parseFrontmatterBool(value, fallback) {
|
|
|
24
24
|
const parsed = parseBooleanValue(value);
|
|
25
25
|
return parsed === undefined ? fallback : parsed;
|
|
26
26
|
}
|
|
27
|
-
export function
|
|
27
|
+
export function resolvePoolbotManifestBlock(params) {
|
|
28
28
|
const raw = getFrontmatterString(params.frontmatter, params.key ?? "metadata");
|
|
29
29
|
if (!raw) {
|
|
30
30
|
return undefined;
|
|
@@ -47,7 +47,7 @@ export function resolveOpenClawManifestBlock(params) {
|
|
|
47
47
|
return undefined;
|
|
48
48
|
}
|
|
49
49
|
}
|
|
50
|
-
export function
|
|
50
|
+
export function resolvePoolbotManifestRequires(metadataObj) {
|
|
51
51
|
const requiresRaw = typeof metadataObj.requires === "object" && metadataObj.requires !== null
|
|
52
52
|
? metadataObj.requires
|
|
53
53
|
: undefined;
|
|
@@ -61,16 +61,16 @@ export function resolveOpenClawManifestRequires(metadataObj) {
|
|
|
61
61
|
config: normalizeStringList(requiresRaw.config),
|
|
62
62
|
};
|
|
63
63
|
}
|
|
64
|
-
export function
|
|
64
|
+
export function resolvePoolbotManifestInstall(metadataObj, parseInstallSpec) {
|
|
65
65
|
const installRaw = Array.isArray(metadataObj.install) ? metadataObj.install : [];
|
|
66
66
|
return installRaw
|
|
67
67
|
.map((entry) => parseInstallSpec(entry))
|
|
68
68
|
.filter((entry) => Boolean(entry));
|
|
69
69
|
}
|
|
70
|
-
export function
|
|
70
|
+
export function resolvePoolbotManifestOs(metadataObj) {
|
|
71
71
|
return normalizeStringList(metadataObj.os);
|
|
72
72
|
}
|
|
73
|
-
export function
|
|
73
|
+
export function parsePoolbotManifestInstallBase(input, allowedKinds) {
|
|
74
74
|
if (!input || typeof input !== "object") {
|
|
75
75
|
return undefined;
|
|
76
76
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export function normalizeStringEntries(list) {
|
|
2
|
+
return (list ?? []).map((entry) => String(entry).trim()).filter(Boolean);
|
|
3
|
+
}
|
|
4
|
+
export function normalizeStringEntriesLower(list) {
|
|
5
|
+
return normalizeStringEntries(list).map((entry) => entry.toLowerCase());
|
|
6
|
+
}
|
|
7
|
+
export function normalizeHyphenSlug(raw) {
|
|
8
|
+
const trimmed = raw?.trim().toLowerCase() ?? "";
|
|
9
|
+
if (!trimmed) {
|
|
10
|
+
return "";
|
|
11
|
+
}
|
|
12
|
+
const dashed = trimmed.replace(/\s+/g, "-");
|
|
13
|
+
const cleaned = dashed.replace(/[^a-z0-9#@._+-]+/g, "-");
|
|
14
|
+
return cleaned.replace(/-{2,}/g, "-").replace(/^[-.]+|[-.]+$/g, "");
|
|
15
|
+
}
|