@poolzin/pool-bot 2026.2.0 → 2026.2.2
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 +118 -0
- package/README-header.png +0 -0
- package/dist/agents/bash-tools.exec.js +76 -25
- package/dist/agents/cli-runner/helpers.js +9 -11
- package/dist/agents/context.js +1 -1
- package/dist/agents/identity.js +47 -7
- package/dist/agents/memory-search.js +25 -8
- package/dist/agents/model-catalog.js +1 -1
- package/dist/agents/model-selection.js +21 -0
- 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.js +1 -1
- package/dist/agents/pi-embedded-runner/compact.js +8 -10
- package/dist/agents/pi-embedded-runner/model.js +62 -3
- package/dist/agents/pi-embedded-runner/run/attempt.js +21 -11
- package/dist/agents/pi-embedded-runner/run.js +199 -46
- package/dist/agents/pi-embedded-runner/system-prompt.js +10 -2
- package/dist/agents/pi-embedded-subscribe.js +118 -29
- package/dist/agents/pi-tools.js +10 -5
- package/dist/agents/poolbot-tools.js +15 -10
- package/dist/agents/sandbox-paths.js +31 -0
- package/dist/agents/session-tool-result-guard.js +94 -15
- 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-install.js +60 -23
- package/dist/agents/subagent-announce.js +79 -34
- package/dist/agents/tool-policy.conformance.js +14 -0
- package/dist/agents/tool-policy.js +24 -0
- 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 +1 -1
- 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/envelope.js +74 -82
- package/dist/auto-reply/reply/commands-compact.js +1 -0
- package/dist/auto-reply/reply/commands-context-report.js +1 -0
- 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/get-reply-run.js +2 -1
- package/dist/auto-reply/reply/inbound-context.js +5 -1
- package/dist/auto-reply/reply/mentions.js +1 -1
- package/dist/auto-reply/reply/model-selection.js +3 -3
- 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 +50 -7
- package/dist/browser/config.js +1 -10
- package/dist/browser/extension-relay.js +101 -40
- 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.js +13 -0
- package/dist/build-info.json +3 -3
- package/dist/canvas-host/a2ui/index.html +28 -28
- package/dist/channels/reply-prefix.js +8 -1
- 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/gateway-cli/register.js +37 -19
- package/dist/cli/memory-cli.js +5 -5
- package/dist/cli/parse-bytes.js +37 -0
- package/dist/cli/update-cli.js +173 -52
- package/dist/commands/agent.js +1 -0
- package/dist/commands/auth-choice.apply.oauth.js +1 -1
- package/dist/commands/doctor-config-flow.js +61 -5
- package/dist/commands/doctor-state-migrations.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.registry.js +1 -1
- package/dist/commands/models/list.status-command.js +43 -23
- package/dist/commands/models/shared.js +15 -0
- 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 +6 -3
- package/dist/commands/onboard-skills.js +63 -38
- package/dist/commands/openai-model-default.js +41 -0
- package/dist/compat/legacy-names.js +2 -0
- package/dist/config/defaults.js +3 -2
- 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 +2 -2
- package/dist/config/sessions/store.js +291 -23
- 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/control-ui/assets/{index-CIRDm-Lu.css → index-CSfXd2LO.css} +1 -1
- package/dist/control-ui/assets/{index-CmNMuoem.js → index-HRr1grwl.js} +446 -413
- package/dist/control-ui/assets/index-HRr1grwl.js.map +1 -0
- package/dist/control-ui/index.html +4 -4
- 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 +172 -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/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/net.js +96 -31
- package/dist/gateway/node-command-policy.js +50 -15
- 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-http.js +109 -11
- 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 +5 -1
- 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.mocks.js +11 -7
- package/dist/gateway/test-helpers.server.js +35 -2
- 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/infra/bonjour-discovery.js +131 -70
- 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/poolbot-root.js +43 -1
- package/dist/infra/session-cost-usage.js +631 -41
- package/dist/infra/state-migrations.js +317 -47
- 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/media/fetch.js +81 -58
- package/dist/media/store.js +2 -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 +3 -3
- 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/batch-voyage.js +277 -0
- package/dist/memory/embeddings-voyage.js +75 -0
- package/dist/memory/embeddings.js +28 -16
- package/dist/memory/internal.js +101 -18
- package/dist/memory/manager.js +154 -48
- package/dist/memory/search-manager.js +173 -0
- package/dist/memory/session-files.js +9 -3
- package/dist/node-host/runner.js +34 -24
- package/dist/node-host/with-timeout.js +27 -0
- package/dist/plugins/commands.js +5 -1
- package/dist/plugins/config-state.js +86 -7
- package/dist/plugins/source-display.js +51 -0
- 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/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/signal/monitor/event-handler.js +80 -1
- package/dist/slack/monitor/media.js +85 -15
- package/dist/tailscale/detect.js +1 -2
- package/dist/telegram/bot/helpers.js +109 -28
- package/dist/telegram/bot-handlers.js +144 -3
- package/dist/telegram/bot-message-context.js +37 -10
- package/dist/telegram/bot-message-dispatch.js +54 -17
- 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/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/transcript-tools.js +58 -0
- package/dist/utils.js +45 -14
- package/dist/version.js +42 -5
- package/dist/wizard/clack-prompter.js +9 -6
- package/extensions/googlechat/node_modules/.bin/poolbot +21 -0
- package/extensions/googlechat/package.json +2 -2
- package/extensions/line/node_modules/.bin/poolbot +21 -0
- package/extensions/line/package.json +1 -1
- package/extensions/matrix/node_modules/.bin/poolbot +21 -0
- package/extensions/matrix/package.json +1 -1
- package/extensions/memory-core/node_modules/.bin/poolbot +21 -0
- package/extensions/memory-core/package.json +4 -1
- package/extensions/twitch/node_modules/.bin/poolbot +21 -0
- package/extensions/twitch/package.json +1 -1
- package/package.json +183 -24
- package/dist/control-ui/assets/index-CmNMuoem.js.map +0 -1
|
@@ -4,10 +4,10 @@ import { parseDiscordTarget } from "../../discord/targets.js";
|
|
|
4
4
|
import { parseIMessageTarget, normalizeIMessageHandle } from "../../imessage/targets.js";
|
|
5
5
|
import { buildAgentSessionKey, } from "../../routing/resolve-route.js";
|
|
6
6
|
import { resolveThreadSessionKeys } from "../../routing/session-key.js";
|
|
7
|
+
import { resolveSignalPeerId, resolveSignalRecipient, resolveSignalSender, } from "../../signal/identity.js";
|
|
7
8
|
import { resolveSlackAccount } from "../../slack/accounts.js";
|
|
8
9
|
import { createSlackWebClient } from "../../slack/client.js";
|
|
9
10
|
import { normalizeAllowListLower } from "../../slack/monitor/allow-list.js";
|
|
10
|
-
import { resolveSignalPeerId, resolveSignalRecipient, resolveSignalSender, } from "../../signal/identity.js";
|
|
11
11
|
import { parseSlackTarget } from "../../slack/targets.js";
|
|
12
12
|
import { buildTelegramGroupPeerId } from "../../telegram/bot/helpers.js";
|
|
13
13
|
import { resolveTelegramTargetChatType } from "../../telegram/inline-buttons.js";
|
|
@@ -18,19 +18,23 @@ const UUID_COMPACT_RE = /^[0-9a-f]{32}$/i;
|
|
|
18
18
|
// Cache Slack channel type lookups to avoid repeated API calls.
|
|
19
19
|
const SLACK_CHANNEL_TYPE_CACHE = new Map();
|
|
20
20
|
function looksLikeUuid(value) {
|
|
21
|
-
if (UUID_RE.test(value) || UUID_COMPACT_RE.test(value))
|
|
21
|
+
if (UUID_RE.test(value) || UUID_COMPACT_RE.test(value)) {
|
|
22
22
|
return true;
|
|
23
|
+
}
|
|
23
24
|
const compact = value.replace(/-/g, "");
|
|
24
|
-
if (!/^[0-9a-f]+$/i.test(compact))
|
|
25
|
+
if (!/^[0-9a-f]+$/i.test(compact)) {
|
|
25
26
|
return false;
|
|
27
|
+
}
|
|
26
28
|
return /[a-f]/i.test(compact);
|
|
27
29
|
}
|
|
28
30
|
function normalizeThreadId(value) {
|
|
29
|
-
if (value == null)
|
|
31
|
+
if (value == null) {
|
|
30
32
|
return undefined;
|
|
33
|
+
}
|
|
31
34
|
if (typeof value === "number") {
|
|
32
|
-
if (!Number.isFinite(value))
|
|
35
|
+
if (!Number.isFinite(value)) {
|
|
33
36
|
return undefined;
|
|
37
|
+
}
|
|
34
38
|
return String(Math.trunc(value));
|
|
35
39
|
}
|
|
36
40
|
const trimmed = value.trim();
|
|
@@ -40,8 +44,9 @@ function stripProviderPrefix(raw, channel) {
|
|
|
40
44
|
const trimmed = raw.trim();
|
|
41
45
|
const lower = trimmed.toLowerCase();
|
|
42
46
|
const prefix = `${channel.toLowerCase()}:`;
|
|
43
|
-
if (lower.startsWith(prefix))
|
|
47
|
+
if (lower.startsWith(prefix)) {
|
|
44
48
|
return trimmed.slice(prefix.length).trim();
|
|
49
|
+
}
|
|
45
50
|
return trimmed;
|
|
46
51
|
}
|
|
47
52
|
function stripKindPrefix(raw) {
|
|
@@ -49,17 +54,20 @@ function stripKindPrefix(raw) {
|
|
|
49
54
|
}
|
|
50
55
|
function inferPeerKind(params) {
|
|
51
56
|
const resolvedKind = params.resolvedTarget?.kind;
|
|
52
|
-
if (resolvedKind === "user")
|
|
57
|
+
if (resolvedKind === "user") {
|
|
53
58
|
return "dm";
|
|
54
|
-
|
|
59
|
+
}
|
|
60
|
+
if (resolvedKind === "channel") {
|
|
55
61
|
return "channel";
|
|
62
|
+
}
|
|
56
63
|
if (resolvedKind === "group") {
|
|
57
64
|
const plugin = getChannelPlugin(params.channel);
|
|
58
65
|
const chatTypes = plugin?.capabilities?.chatTypes ?? [];
|
|
59
66
|
const supportsChannel = chatTypes.includes("channel");
|
|
60
67
|
const supportsGroup = chatTypes.includes("group");
|
|
61
|
-
if (supportsChannel && !supportsGroup)
|
|
68
|
+
if (supportsChannel && !supportsGroup) {
|
|
62
69
|
return "channel";
|
|
70
|
+
}
|
|
63
71
|
return "group";
|
|
64
72
|
}
|
|
65
73
|
return "dm";
|
|
@@ -68,6 +76,7 @@ function buildBaseSessionKey(params) {
|
|
|
68
76
|
return buildAgentSessionKey({
|
|
69
77
|
agentId: params.agentId,
|
|
70
78
|
channel: params.channel,
|
|
79
|
+
accountId: params.accountId,
|
|
71
80
|
peer: params.peer,
|
|
72
81
|
dmScope: params.cfg.session?.dmScope ?? "main",
|
|
73
82
|
identityLinks: params.cfg.session?.identityLinks,
|
|
@@ -76,11 +85,13 @@ function buildBaseSessionKey(params) {
|
|
|
76
85
|
// Best-effort mpim detection: allowlist/config, then Slack API (if token available).
|
|
77
86
|
async function resolveSlackChannelType(params) {
|
|
78
87
|
const channelId = params.channelId.trim();
|
|
79
|
-
if (!channelId)
|
|
88
|
+
if (!channelId) {
|
|
80
89
|
return "unknown";
|
|
90
|
+
}
|
|
81
91
|
const cached = SLACK_CHANNEL_TYPE_CACHE.get(`${params.accountId ?? "default"}:${channelId}`);
|
|
82
|
-
if (cached)
|
|
92
|
+
if (cached) {
|
|
83
93
|
return cached;
|
|
94
|
+
}
|
|
84
95
|
const account = resolveSlackAccount({ cfg: params.cfg, accountId: params.accountId });
|
|
85
96
|
const groupChannels = normalizeAllowListLower(account.dm?.groupChannels);
|
|
86
97
|
const channelIdLower = channelId.toLowerCase();
|
|
@@ -123,8 +134,9 @@ async function resolveSlackChannelType(params) {
|
|
|
123
134
|
}
|
|
124
135
|
async function resolveSlackSession(params) {
|
|
125
136
|
const parsed = parseSlackTarget(params.target, { defaultKind: "channel" });
|
|
126
|
-
if (!parsed)
|
|
137
|
+
if (!parsed) {
|
|
127
138
|
return null;
|
|
139
|
+
}
|
|
128
140
|
const isDm = parsed.kind === "user";
|
|
129
141
|
let peerKind = isDm ? "dm" : "channel";
|
|
130
142
|
if (!isDm && /^G/i.test(parsed.id)) {
|
|
@@ -134,10 +146,12 @@ async function resolveSlackSession(params) {
|
|
|
134
146
|
accountId: params.accountId,
|
|
135
147
|
channelId: parsed.id,
|
|
136
148
|
});
|
|
137
|
-
if (channelType === "group")
|
|
149
|
+
if (channelType === "group") {
|
|
138
150
|
peerKind = "group";
|
|
139
|
-
|
|
151
|
+
}
|
|
152
|
+
if (channelType === "dm") {
|
|
140
153
|
peerKind = "dm";
|
|
154
|
+
}
|
|
141
155
|
}
|
|
142
156
|
const peer = {
|
|
143
157
|
kind: peerKind,
|
|
@@ -147,6 +161,7 @@ async function resolveSlackSession(params) {
|
|
|
147
161
|
cfg: params.cfg,
|
|
148
162
|
agentId: params.agentId,
|
|
149
163
|
channel: "slack",
|
|
164
|
+
accountId: params.accountId,
|
|
150
165
|
peer,
|
|
151
166
|
});
|
|
152
167
|
const threadId = normalizeThreadId(params.threadId ?? params.replyToId);
|
|
@@ -170,8 +185,9 @@ async function resolveSlackSession(params) {
|
|
|
170
185
|
}
|
|
171
186
|
function resolveDiscordSession(params) {
|
|
172
187
|
const parsed = parseDiscordTarget(params.target, { defaultKind: "channel" });
|
|
173
|
-
if (!parsed)
|
|
188
|
+
if (!parsed) {
|
|
174
189
|
return null;
|
|
190
|
+
}
|
|
175
191
|
const isDm = parsed.kind === "user";
|
|
176
192
|
const peer = {
|
|
177
193
|
kind: isDm ? "dm" : "channel",
|
|
@@ -181,6 +197,7 @@ function resolveDiscordSession(params) {
|
|
|
181
197
|
cfg: params.cfg,
|
|
182
198
|
agentId: params.agentId,
|
|
183
199
|
channel: "discord",
|
|
200
|
+
accountId: params.accountId,
|
|
184
201
|
peer,
|
|
185
202
|
});
|
|
186
203
|
const explicitThreadId = normalizeThreadId(params.threadId);
|
|
@@ -204,8 +221,9 @@ function resolveDiscordSession(params) {
|
|
|
204
221
|
function resolveTelegramSession(params) {
|
|
205
222
|
const parsed = parseTelegramTarget(params.target);
|
|
206
223
|
const chatId = parsed.chatId.trim();
|
|
207
|
-
if (!chatId)
|
|
224
|
+
if (!chatId) {
|
|
208
225
|
return null;
|
|
226
|
+
}
|
|
209
227
|
const parsedThreadId = parsed.messageThreadId;
|
|
210
228
|
const fallbackThreadId = normalizeThreadId(params.threadId);
|
|
211
229
|
const resolvedThreadId = parsedThreadId ?? (fallbackThreadId ? Number.parseInt(fallbackThreadId, 10) : undefined);
|
|
@@ -225,6 +243,7 @@ function resolveTelegramSession(params) {
|
|
|
225
243
|
cfg: params.cfg,
|
|
226
244
|
agentId: params.agentId,
|
|
227
245
|
channel: "telegram",
|
|
246
|
+
accountId: params.accountId,
|
|
228
247
|
peer,
|
|
229
248
|
});
|
|
230
249
|
return {
|
|
@@ -239,8 +258,9 @@ function resolveTelegramSession(params) {
|
|
|
239
258
|
}
|
|
240
259
|
function resolveWhatsAppSession(params) {
|
|
241
260
|
const normalized = normalizeWhatsAppTarget(params.target);
|
|
242
|
-
if (!normalized)
|
|
261
|
+
if (!normalized) {
|
|
243
262
|
return null;
|
|
263
|
+
}
|
|
244
264
|
const isGroup = isWhatsAppGroupJid(normalized);
|
|
245
265
|
const peer = {
|
|
246
266
|
kind: isGroup ? "group" : "dm",
|
|
@@ -250,6 +270,7 @@ function resolveWhatsAppSession(params) {
|
|
|
250
270
|
cfg: params.cfg,
|
|
251
271
|
agentId: params.agentId,
|
|
252
272
|
channel: "whatsapp",
|
|
273
|
+
accountId: params.accountId,
|
|
253
274
|
peer,
|
|
254
275
|
});
|
|
255
276
|
return {
|
|
@@ -266,13 +287,15 @@ function resolveSignalSession(params) {
|
|
|
266
287
|
const lowered = stripped.toLowerCase();
|
|
267
288
|
if (lowered.startsWith("group:")) {
|
|
268
289
|
const groupId = stripped.slice("group:".length).trim();
|
|
269
|
-
if (!groupId)
|
|
290
|
+
if (!groupId) {
|
|
270
291
|
return null;
|
|
292
|
+
}
|
|
271
293
|
const peer = { kind: "group", id: groupId };
|
|
272
294
|
const baseSessionKey = buildBaseSessionKey({
|
|
273
295
|
cfg: params.cfg,
|
|
274
296
|
agentId: params.agentId,
|
|
275
297
|
channel: "signal",
|
|
298
|
+
accountId: params.accountId,
|
|
276
299
|
peer,
|
|
277
300
|
});
|
|
278
301
|
return {
|
|
@@ -291,8 +314,9 @@ function resolveSignalSession(params) {
|
|
|
291
314
|
else if (lowered.startsWith("u:")) {
|
|
292
315
|
recipient = stripped.slice("u:".length).trim();
|
|
293
316
|
}
|
|
294
|
-
if (!recipient)
|
|
317
|
+
if (!recipient) {
|
|
295
318
|
return null;
|
|
319
|
+
}
|
|
296
320
|
const uuidCandidate = recipient.toLowerCase().startsWith("uuid:")
|
|
297
321
|
? recipient.slice("uuid:".length)
|
|
298
322
|
: recipient;
|
|
@@ -307,6 +331,7 @@ function resolveSignalSession(params) {
|
|
|
307
331
|
cfg: params.cfg,
|
|
308
332
|
agentId: params.agentId,
|
|
309
333
|
channel: "signal",
|
|
334
|
+
accountId: params.accountId,
|
|
310
335
|
peer,
|
|
311
336
|
});
|
|
312
337
|
return {
|
|
@@ -322,13 +347,15 @@ function resolveIMessageSession(params) {
|
|
|
322
347
|
const parsed = parseIMessageTarget(params.target);
|
|
323
348
|
if (parsed.kind === "handle") {
|
|
324
349
|
const handle = normalizeIMessageHandle(parsed.to);
|
|
325
|
-
if (!handle)
|
|
350
|
+
if (!handle) {
|
|
326
351
|
return null;
|
|
352
|
+
}
|
|
327
353
|
const peer = { kind: "dm", id: handle };
|
|
328
354
|
const baseSessionKey = buildBaseSessionKey({
|
|
329
355
|
cfg: params.cfg,
|
|
330
356
|
agentId: params.agentId,
|
|
331
357
|
channel: "imessage",
|
|
358
|
+
accountId: params.accountId,
|
|
332
359
|
peer,
|
|
333
360
|
});
|
|
334
361
|
return {
|
|
@@ -345,13 +372,15 @@ function resolveIMessageSession(params) {
|
|
|
345
372
|
: parsed.kind === "chat_guid"
|
|
346
373
|
? parsed.chatGuid
|
|
347
374
|
: parsed.chatIdentifier;
|
|
348
|
-
if (!peerId)
|
|
375
|
+
if (!peerId) {
|
|
349
376
|
return null;
|
|
377
|
+
}
|
|
350
378
|
const peer = { kind: "group", id: peerId };
|
|
351
379
|
const baseSessionKey = buildBaseSessionKey({
|
|
352
380
|
cfg: params.cfg,
|
|
353
381
|
agentId: params.agentId,
|
|
354
382
|
channel: "imessage",
|
|
383
|
+
accountId: params.accountId,
|
|
355
384
|
peer,
|
|
356
385
|
});
|
|
357
386
|
const toPrefix = parsed.kind === "chat_id"
|
|
@@ -372,13 +401,15 @@ function resolveMatrixSession(params) {
|
|
|
372
401
|
const stripped = stripProviderPrefix(params.target, "matrix");
|
|
373
402
|
const isUser = params.resolvedTarget?.kind === "user" || stripped.startsWith("@") || /^user:/i.test(stripped);
|
|
374
403
|
const rawId = stripKindPrefix(stripped);
|
|
375
|
-
if (!rawId)
|
|
404
|
+
if (!rawId) {
|
|
376
405
|
return null;
|
|
406
|
+
}
|
|
377
407
|
const peer = { kind: isUser ? "dm" : "channel", id: rawId };
|
|
378
408
|
const baseSessionKey = buildBaseSessionKey({
|
|
379
409
|
cfg: params.cfg,
|
|
380
410
|
agentId: params.agentId,
|
|
381
411
|
channel: "matrix",
|
|
412
|
+
accountId: params.accountId,
|
|
382
413
|
peer,
|
|
383
414
|
});
|
|
384
415
|
return {
|
|
@@ -392,14 +423,16 @@ function resolveMatrixSession(params) {
|
|
|
392
423
|
}
|
|
393
424
|
function resolveMSTeamsSession(params) {
|
|
394
425
|
let trimmed = params.target.trim();
|
|
395
|
-
if (!trimmed)
|
|
426
|
+
if (!trimmed) {
|
|
396
427
|
return null;
|
|
428
|
+
}
|
|
397
429
|
trimmed = trimmed.replace(/^(msteams|teams):/i, "").trim();
|
|
398
430
|
const lower = trimmed.toLowerCase();
|
|
399
431
|
const isUser = lower.startsWith("user:");
|
|
400
432
|
const rawId = stripKindPrefix(trimmed);
|
|
401
|
-
if (!rawId)
|
|
433
|
+
if (!rawId) {
|
|
402
434
|
return null;
|
|
435
|
+
}
|
|
403
436
|
const conversationId = rawId.split(";")[0] ?? rawId;
|
|
404
437
|
const isChannel = !isUser && /@thread\.tacv2/i.test(conversationId);
|
|
405
438
|
const peer = {
|
|
@@ -410,6 +443,7 @@ function resolveMSTeamsSession(params) {
|
|
|
410
443
|
cfg: params.cfg,
|
|
411
444
|
agentId: params.agentId,
|
|
412
445
|
channel: "msteams",
|
|
446
|
+
accountId: params.accountId,
|
|
413
447
|
peer,
|
|
414
448
|
});
|
|
415
449
|
return {
|
|
@@ -427,8 +461,9 @@ function resolveMSTeamsSession(params) {
|
|
|
427
461
|
}
|
|
428
462
|
function resolveMattermostSession(params) {
|
|
429
463
|
let trimmed = params.target.trim();
|
|
430
|
-
if (!trimmed)
|
|
464
|
+
if (!trimmed) {
|
|
431
465
|
return null;
|
|
466
|
+
}
|
|
432
467
|
trimmed = trimmed.replace(/^mattermost:/i, "").trim();
|
|
433
468
|
const lower = trimmed.toLowerCase();
|
|
434
469
|
const isUser = lower.startsWith("user:") || trimmed.startsWith("@");
|
|
@@ -436,13 +471,15 @@ function resolveMattermostSession(params) {
|
|
|
436
471
|
trimmed = trimmed.slice(1).trim();
|
|
437
472
|
}
|
|
438
473
|
const rawId = stripKindPrefix(trimmed);
|
|
439
|
-
if (!rawId)
|
|
474
|
+
if (!rawId) {
|
|
440
475
|
return null;
|
|
476
|
+
}
|
|
441
477
|
const peer = { kind: isUser ? "dm" : "channel", id: rawId };
|
|
442
478
|
const baseSessionKey = buildBaseSessionKey({
|
|
443
479
|
cfg: params.cfg,
|
|
444
480
|
agentId: params.agentId,
|
|
445
481
|
channel: "mattermost",
|
|
482
|
+
accountId: params.accountId,
|
|
446
483
|
peer,
|
|
447
484
|
});
|
|
448
485
|
const threadId = normalizeThreadId(params.replyToId ?? params.threadId);
|
|
@@ -474,8 +511,9 @@ function resolveBlueBubblesSession(params) {
|
|
|
474
511
|
const peerId = isGroup
|
|
475
512
|
? rawPeerId.replace(/^(chat_id|chat_guid|chat_identifier):/i, "")
|
|
476
513
|
: rawPeerId;
|
|
477
|
-
if (!peerId)
|
|
514
|
+
if (!peerId) {
|
|
478
515
|
return null;
|
|
516
|
+
}
|
|
479
517
|
const peer = {
|
|
480
518
|
kind: isGroup ? "group" : "dm",
|
|
481
519
|
id: peerId,
|
|
@@ -484,6 +522,7 @@ function resolveBlueBubblesSession(params) {
|
|
|
484
522
|
cfg: params.cfg,
|
|
485
523
|
agentId: params.agentId,
|
|
486
524
|
channel: "bluebubbles",
|
|
525
|
+
accountId: params.accountId,
|
|
487
526
|
peer,
|
|
488
527
|
});
|
|
489
528
|
return {
|
|
@@ -497,17 +536,20 @@ function resolveBlueBubblesSession(params) {
|
|
|
497
536
|
}
|
|
498
537
|
function resolveNextcloudTalkSession(params) {
|
|
499
538
|
let trimmed = params.target.trim();
|
|
500
|
-
if (!trimmed)
|
|
539
|
+
if (!trimmed) {
|
|
501
540
|
return null;
|
|
541
|
+
}
|
|
502
542
|
trimmed = trimmed.replace(/^(nextcloud-talk|nc-talk|nc):/i, "").trim();
|
|
503
543
|
trimmed = trimmed.replace(/^room:/i, "").trim();
|
|
504
|
-
if (!trimmed)
|
|
544
|
+
if (!trimmed) {
|
|
505
545
|
return null;
|
|
546
|
+
}
|
|
506
547
|
const peer = { kind: "group", id: trimmed };
|
|
507
548
|
const baseSessionKey = buildBaseSessionKey({
|
|
508
549
|
cfg: params.cfg,
|
|
509
550
|
agentId: params.agentId,
|
|
510
551
|
channel: "nextcloud-talk",
|
|
552
|
+
accountId: params.accountId,
|
|
511
553
|
peer,
|
|
512
554
|
});
|
|
513
555
|
return {
|
|
@@ -523,8 +565,9 @@ function resolveZaloSession(params) {
|
|
|
523
565
|
const trimmed = stripProviderPrefix(params.target, "zalo")
|
|
524
566
|
.replace(/^(zl):/i, "")
|
|
525
567
|
.trim();
|
|
526
|
-
if (!trimmed)
|
|
568
|
+
if (!trimmed) {
|
|
527
569
|
return null;
|
|
570
|
+
}
|
|
528
571
|
const isGroup = trimmed.toLowerCase().startsWith("group:");
|
|
529
572
|
const peerId = stripKindPrefix(trimmed);
|
|
530
573
|
const peer = { kind: isGroup ? "group" : "dm", id: peerId };
|
|
@@ -532,6 +575,7 @@ function resolveZaloSession(params) {
|
|
|
532
575
|
cfg: params.cfg,
|
|
533
576
|
agentId: params.agentId,
|
|
534
577
|
channel: "zalo",
|
|
578
|
+
accountId: params.accountId,
|
|
535
579
|
peer,
|
|
536
580
|
});
|
|
537
581
|
return {
|
|
@@ -547,8 +591,9 @@ function resolveZalouserSession(params) {
|
|
|
547
591
|
const trimmed = stripProviderPrefix(params.target, "zalouser")
|
|
548
592
|
.replace(/^(zlu):/i, "")
|
|
549
593
|
.trim();
|
|
550
|
-
if (!trimmed)
|
|
594
|
+
if (!trimmed) {
|
|
551
595
|
return null;
|
|
596
|
+
}
|
|
552
597
|
const isGroup = trimmed.toLowerCase().startsWith("group:");
|
|
553
598
|
const peerId = stripKindPrefix(trimmed);
|
|
554
599
|
// Keep DM vs group aligned with inbound sessions for Zalo Personal.
|
|
@@ -557,6 +602,7 @@ function resolveZalouserSession(params) {
|
|
|
557
602
|
cfg: params.cfg,
|
|
558
603
|
agentId: params.agentId,
|
|
559
604
|
channel: "zalouser",
|
|
605
|
+
accountId: params.accountId,
|
|
560
606
|
peer,
|
|
561
607
|
});
|
|
562
608
|
return {
|
|
@@ -570,13 +616,15 @@ function resolveZalouserSession(params) {
|
|
|
570
616
|
}
|
|
571
617
|
function resolveNostrSession(params) {
|
|
572
618
|
const trimmed = stripProviderPrefix(params.target, "nostr").trim();
|
|
573
|
-
if (!trimmed)
|
|
619
|
+
if (!trimmed) {
|
|
574
620
|
return null;
|
|
621
|
+
}
|
|
575
622
|
const peer = { kind: "dm", id: trimmed };
|
|
576
623
|
const baseSessionKey = buildBaseSessionKey({
|
|
577
624
|
cfg: params.cfg,
|
|
578
625
|
agentId: params.agentId,
|
|
579
626
|
channel: "nostr",
|
|
627
|
+
accountId: params.accountId,
|
|
580
628
|
peer,
|
|
581
629
|
});
|
|
582
630
|
return {
|
|
@@ -590,15 +638,17 @@ function resolveNostrSession(params) {
|
|
|
590
638
|
}
|
|
591
639
|
function normalizeTlonShip(raw) {
|
|
592
640
|
const trimmed = raw.trim();
|
|
593
|
-
if (!trimmed)
|
|
641
|
+
if (!trimmed) {
|
|
594
642
|
return trimmed;
|
|
643
|
+
}
|
|
595
644
|
return trimmed.startsWith("~") ? trimmed : `~${trimmed}`;
|
|
596
645
|
}
|
|
597
646
|
function resolveTlonSession(params) {
|
|
598
647
|
let trimmed = stripProviderPrefix(params.target, "tlon");
|
|
599
648
|
trimmed = trimmed.trim();
|
|
600
|
-
if (!trimmed)
|
|
649
|
+
if (!trimmed) {
|
|
601
650
|
return null;
|
|
651
|
+
}
|
|
602
652
|
const lower = trimmed.toLowerCase();
|
|
603
653
|
let isGroup = lower.startsWith("group:") || lower.startsWith("room:") || lower.startsWith("chat/");
|
|
604
654
|
let peerId = trimmed;
|
|
@@ -635,6 +685,7 @@ function resolveTlonSession(params) {
|
|
|
635
685
|
cfg: params.cfg,
|
|
636
686
|
agentId: params.agentId,
|
|
637
687
|
channel: "tlon",
|
|
688
|
+
accountId: params.accountId,
|
|
638
689
|
peer,
|
|
639
690
|
});
|
|
640
691
|
return {
|
|
@@ -646,17 +697,69 @@ function resolveTlonSession(params) {
|
|
|
646
697
|
to: `tlon:${peerId}`,
|
|
647
698
|
};
|
|
648
699
|
}
|
|
700
|
+
/**
|
|
701
|
+
* Feishu ID formats:
|
|
702
|
+
* - oc_xxx: chat_id (group chat)
|
|
703
|
+
* - ou_xxx: user open_id (DM)
|
|
704
|
+
* - on_xxx: user union_id (DM)
|
|
705
|
+
* - cli_xxx: app_id (not a valid send target)
|
|
706
|
+
*/
|
|
707
|
+
function resolveFeishuSession(params) {
|
|
708
|
+
let trimmed = stripProviderPrefix(params.target, "feishu");
|
|
709
|
+
trimmed = stripProviderPrefix(trimmed, "lark").trim();
|
|
710
|
+
if (!trimmed) {
|
|
711
|
+
return null;
|
|
712
|
+
}
|
|
713
|
+
const lower = trimmed.toLowerCase();
|
|
714
|
+
let isGroup = false;
|
|
715
|
+
if (lower.startsWith("group:") || lower.startsWith("chat:")) {
|
|
716
|
+
trimmed = trimmed.replace(/^(group|chat):/i, "").trim();
|
|
717
|
+
isGroup = true;
|
|
718
|
+
}
|
|
719
|
+
else if (lower.startsWith("user:") || lower.startsWith("dm:")) {
|
|
720
|
+
trimmed = trimmed.replace(/^(user|dm):/i, "").trim();
|
|
721
|
+
isGroup = false;
|
|
722
|
+
}
|
|
723
|
+
const idLower = trimmed.toLowerCase();
|
|
724
|
+
if (idLower.startsWith("oc_")) {
|
|
725
|
+
isGroup = true;
|
|
726
|
+
}
|
|
727
|
+
else if (idLower.startsWith("ou_") || idLower.startsWith("on_")) {
|
|
728
|
+
isGroup = false;
|
|
729
|
+
}
|
|
730
|
+
const peer = {
|
|
731
|
+
kind: isGroup ? "group" : "dm",
|
|
732
|
+
id: trimmed,
|
|
733
|
+
};
|
|
734
|
+
const baseSessionKey = buildBaseSessionKey({
|
|
735
|
+
cfg: params.cfg,
|
|
736
|
+
agentId: params.agentId,
|
|
737
|
+
channel: "feishu",
|
|
738
|
+
accountId: params.accountId,
|
|
739
|
+
peer,
|
|
740
|
+
});
|
|
741
|
+
return {
|
|
742
|
+
sessionKey: baseSessionKey,
|
|
743
|
+
baseSessionKey,
|
|
744
|
+
peer,
|
|
745
|
+
chatType: isGroup ? "group" : "direct",
|
|
746
|
+
from: isGroup ? `feishu:group:${trimmed}` : `feishu:${trimmed}`,
|
|
747
|
+
to: trimmed,
|
|
748
|
+
};
|
|
749
|
+
}
|
|
649
750
|
function resolveFallbackSession(params) {
|
|
650
751
|
const trimmed = stripProviderPrefix(params.target, params.channel).trim();
|
|
651
|
-
if (!trimmed)
|
|
752
|
+
if (!trimmed) {
|
|
652
753
|
return null;
|
|
754
|
+
}
|
|
653
755
|
const peerKind = inferPeerKind({
|
|
654
756
|
channel: params.channel,
|
|
655
757
|
resolvedTarget: params.resolvedTarget,
|
|
656
758
|
});
|
|
657
759
|
const peerId = stripKindPrefix(trimmed);
|
|
658
|
-
if (!peerId)
|
|
760
|
+
if (!peerId) {
|
|
659
761
|
return null;
|
|
762
|
+
}
|
|
660
763
|
const peer = { kind: peerKind, id: peerId };
|
|
661
764
|
const baseSessionKey = buildBaseSessionKey({
|
|
662
765
|
cfg: params.cfg,
|
|
@@ -678,8 +781,9 @@ function resolveFallbackSession(params) {
|
|
|
678
781
|
}
|
|
679
782
|
export async function resolveOutboundSessionRoute(params) {
|
|
680
783
|
const target = params.target.trim();
|
|
681
|
-
if (!target)
|
|
784
|
+
if (!target) {
|
|
682
785
|
return null;
|
|
786
|
+
}
|
|
683
787
|
switch (params.channel) {
|
|
684
788
|
case "slack":
|
|
685
789
|
return await resolveSlackSession({ ...params, target });
|
|
@@ -711,6 +815,8 @@ export async function resolveOutboundSessionRoute(params) {
|
|
|
711
815
|
return resolveNostrSession({ ...params, target });
|
|
712
816
|
case "tlon":
|
|
713
817
|
return resolveTlonSession({ ...params, target });
|
|
818
|
+
case "feishu":
|
|
819
|
+
return resolveFeishuSession({ ...params, target });
|
|
714
820
|
default:
|
|
715
821
|
return resolveFallbackSession({ ...params, target });
|
|
716
822
|
}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
+
import fsSync from "node:fs";
|
|
1
2
|
import fs from "node:fs/promises";
|
|
2
3
|
import path from "node:path";
|
|
3
4
|
import { fileURLToPath } from "node:url";
|
|
4
|
-
const CORE_PACKAGE_NAMES = new Set(["poolbot"
|
|
5
|
+
const CORE_PACKAGE_NAMES = new Set(["poolbot"]);
|
|
5
6
|
async function readPackageName(dir) {
|
|
6
7
|
try {
|
|
7
8
|
const raw = await fs.readFile(path.join(dir, "package.json"), "utf-8");
|
|
@@ -12,6 +13,16 @@ async function readPackageName(dir) {
|
|
|
12
13
|
return null;
|
|
13
14
|
}
|
|
14
15
|
}
|
|
16
|
+
function readPackageNameSync(dir) {
|
|
17
|
+
try {
|
|
18
|
+
const raw = fsSync.readFileSync(path.join(dir, "package.json"), "utf-8");
|
|
19
|
+
const parsed = JSON.parse(raw);
|
|
20
|
+
return typeof parsed.name === "string" ? parsed.name : null;
|
|
21
|
+
}
|
|
22
|
+
catch {
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
15
26
|
async function findPackageRoot(startDir, maxDepth = 12) {
|
|
16
27
|
let current = path.resolve(startDir);
|
|
17
28
|
for (let i = 0; i < maxDepth; i += 1) {
|
|
@@ -25,6 +36,19 @@ async function findPackageRoot(startDir, maxDepth = 12) {
|
|
|
25
36
|
}
|
|
26
37
|
return null;
|
|
27
38
|
}
|
|
39
|
+
function findPackageRootSync(startDir, maxDepth = 12) {
|
|
40
|
+
let current = path.resolve(startDir);
|
|
41
|
+
for (let i = 0; i < maxDepth; i += 1) {
|
|
42
|
+
const name = readPackageNameSync(current);
|
|
43
|
+
if (name && CORE_PACKAGE_NAMES.has(name))
|
|
44
|
+
return current;
|
|
45
|
+
const parent = path.dirname(current);
|
|
46
|
+
if (parent === current)
|
|
47
|
+
break;
|
|
48
|
+
current = parent;
|
|
49
|
+
}
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
28
52
|
function candidateDirsFromArgv1(argv1) {
|
|
29
53
|
const normalized = path.resolve(argv1);
|
|
30
54
|
const candidates = [path.dirname(normalized)];
|
|
@@ -55,3 +79,21 @@ export async function resolvePoolBotPackageRoot(opts) {
|
|
|
55
79
|
}
|
|
56
80
|
return null;
|
|
57
81
|
}
|
|
82
|
+
export function resolvePoolBotPackageRootSync(opts) {
|
|
83
|
+
const candidates = [];
|
|
84
|
+
if (opts.moduleUrl) {
|
|
85
|
+
candidates.push(path.dirname(fileURLToPath(opts.moduleUrl)));
|
|
86
|
+
}
|
|
87
|
+
if (opts.argv1) {
|
|
88
|
+
candidates.push(...candidateDirsFromArgv1(opts.argv1));
|
|
89
|
+
}
|
|
90
|
+
if (opts.cwd) {
|
|
91
|
+
candidates.push(opts.cwd);
|
|
92
|
+
}
|
|
93
|
+
for (const candidate of candidates) {
|
|
94
|
+
const found = findPackageRootSync(candidate);
|
|
95
|
+
if (found)
|
|
96
|
+
return found;
|
|
97
|
+
}
|
|
98
|
+
return null;
|
|
99
|
+
}
|